【问题标题】:Confirm dialog loses focus on iOS10确认对话框失去了对 iOS 10 的关注
【发布时间】:2017-06-09 11:54:55
【问题描述】:

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

在 iOS 版本 8 和 9 中,当我有两个选项卡并且我在第二个选项卡中时,确认对话框会按应有的方式显示在前面。

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

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

【问题讨论】:

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


    【解决方案1】:

    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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-09-23
      • 1970-01-01
      • 2020-06-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-18
      相关资源
      最近更新 更多