在我的网站的移动版本中,我有一个在特定情况下出现的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异步触发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。