在我的网站的移动版本中,我有一个在特定情况下出现的JavaScript确认对话框。使用setTimeout
我触发确认对话框。 无论用户在哪个选项卡中,他都应该看到confirm dialog
但在iOS 10中会失去焦点。
在iOS版本8和9中,当我有两个选项卡并且我在第二个选项卡中时,确认对话框会像它应该的那样显示在前面。
是否有任何解决方案或解决方法?
var cf = confirm("Close?");
if (cf){ do that....} else { do this... }
SafariDriver 是用 JS 实现的,所以为了拦截对alert
、confirm
和prompt
的调用,必须在网页上下文中覆盖这些函数。
将注入的脚本更改为注入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 异步触发消息事件。为了保持同步性,我们可以手动触发一个消息事件:
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 响应时,扩展将完成链并将响应发送回注入的脚本。
您可以在此处找到更多信息。