确认对话框失去了对iOS10的关注

时间:2017-06-09 11:54:56

标签: javascript browser mobile-safari confirm-dialog safari10

在我的网站的移动版本中,我有一个在特定情况下出现的JavaScript确认对话框。使用setTimeout我触发确认对话框。 无论用户位于哪个标签页,他都应该看到confirm dialog但在iOS 10中失去焦点。

在iOS版本8&当我有两个标签并且我在第二个标签中时,9工作正常,确认对话框就像它应该显示在前面。

是否有任何解决方案或解决方法?

var cf = confirm("Close?"); 
if (cf){ do that....} else { do this... }

1 个答案:

答案 0 :(得分:2)

SafariDriver在JS中实现,因此为了拦截对alertconfirmprompt的调用,必须覆盖网页上下文中的函数。

将注入的脚本更改为注入Start脚本而不是End脚本 - 这意味着脚本在DOM加载后注入,但在解析之前(与之相反)在onload事件之后注入):

http://developer.apple.com/library/safari/#documentation/Tools/Conceptual/SafariExtensionGuide/InjectingScripts/InjectingScripts.html#//apple_ref/doc/uid/TP40009977-CH6-SW5

在被测页面的上下文中覆盖全局警报功能,注入的脚本。这类似于executeScript命令的要求。因此,我们注入的脚本应该做的第一件事是向DOM添加一个脚本标记来设置警报覆盖。应将此脚本标记添加为documentElement的第一个子项,以确保它在页面中的任何其他子项之前执行。这将确保我们在页面中的任何内容有机会发出警报之前设置我们的警报处理程序。

一旦警报触发,我们必须通知扩展程序有警报,同时阻止页面中的当前JS线程。通常,我们的页面脚本使用window.postMessage与注入的脚本进行通信。 postMessage异步触发MessageEvent。为了保持同步性,我们可以手动触发MessageEvent:

Use a MessageEvent instead of some other DOM event so we can include a JSON object describing the alert.

var event = document.createEvent('MessageEvent');
event.initMessageEvent('message', false, false, {
  type: "alert",  // confirm, or prompt
  text: "hello"
}, window.location.origin, '0', window, null);
window.dispatchEvent(event);

注入的脚本必须侦听对页面警报消息的响应。要同步将警报发送到扩展程序进行处理,我们可以(ab)使用Safari扩展程序来阻止加载内容:

http://developer.apple.com/library/safari/#documentation/Tools/Conceptual/SafariExtensionGuide/MessagesandProxies/MessagesandProxies.html#//apple_ref/doc/uid/TP40009977-CH14-SW9

window.addEventListener('message', function(e) {
  // Create a beforeload event, which is required by the canLoad method
  var e = document.createEvent('Events');
  e.initEvent('beforeload', false, false);

  // canLoad sends and waits for a response synchronously. It is the only
  // synchronous function in the Safari extension messaging API.
  var response = safari.self.tab.canLoad(e, e.data);

  // Send the response back to the page using another MessageEvent.
  var responseEvent = document.createEvent('MessageEvent');
  responseEvent.initMessageEvent('message', false, false, {
    accepted: response.accepted,
    response: response.value
  }, window.location.origin, '0', window, null);
  window.dispatchEvent(responseEvent);
}, true);

请注意,必须使用其他消息将扩展程序的警报响应传回页面,因为我们正在跨越上下文边界。唯一的另一种选择是将响应存储在要在另一端读取的DOM上。

最后一步,这是开放式问题,扩展应如何处理警报。由于我们正在维护警报的阻止行为,因此无法再执行命令(即使它们导致未处理的警报错误)。

一种可能性是让WebDriver客户端参与警报处理。除了提供WebSocket服务器之外,WebDriver客户端还应该提供XHR端点。检测到警报时,服务器将向此端点发送同步POST XHR。客户端应仅在用户接受或取消警报后响应(或者从另一个命令抛出未处理的警报错误)。收到XHR响应后,扩展完成链并将响应发送回注入的脚本。

您可以找到更多here