【问题标题】:Iframe steals focus even another browser is opened即使打开另一个浏览器,iframe 也会窃取焦点
【发布时间】:2012-01-04 21:21:53
【问题描述】:

我们有一个网站,我们使用 iframe 加载一些数据(iframe 长轮询)。该数据可以自动加载,例如每 2 分钟。当这个网站在 IE 中打开时(在最新的 9 版本中尝试过),它将每 2 分钟发送一次请求。没关系。

但是当我们打开另一个浏览器(或程序)并且 IE 不在焦点上时 - 在每次请求期间,IE 都会自己获取焦点...

也许有人知道如何解决这个问题(防止 IE 窃取焦点)? 据我了解,Ajax 请求可以解决此问题,但这可能很难更新...

更新:

从服务器(在 Iframe 中)我们返回如下内容:

<html><body>
<script>parent.MailChecker.updateStatus({"s":"Connecting to xxx@gmail.com...","p":0,"c":null,"e":false})</script>
<script>parent.MailChecker.updateStatus({"s":"Preparing to fetch emails...","p":0,"c":null,"e":false})</script>
<script>parent.MailChecker.updateStatus({"s":"Downloading 1 email from 35...","p":2.8571428571429,"c":null,"e":"784"})</script>
<script>parent.MailChecker.updateStatus({"s":"Downloading 2 emails from 35...","p":5.7142857142857,"c":null,"e":"784"})</script>
...
<script>parent.MailChecker.updateStatus({"s":"Done!","p":100,"c":"0","e":false})</script>
</body></html>

【问题讨论】:

  • IFRAME(永久帧或长轮询)是解决此问题的旧方法。最常见的解决方案是给我们XMLHttpRequest 对象来实现您想要做的事情。如果您采用这种方法,您将不会看到同样的焦点问题。
  • 在我的情况下,我将 js(将被自动调用)返回到框架中,所以我认为我不能使用 Ajax 来做类似的事情......
  • Forever 框架确实按照您描述的方式工作(它们执行脚本,通常是从 IFRAME 对页面的一次调用),因此您需要重新编写代码,以便仅发送连接的数据.也许指示应该执行什么功能的指令?
  • 我们使用 iframe 来检查电子邮件列表,在这个请求中,我们通过 js 代码(自动更新进度条)返回电子邮件检查的当前状态(百分比、总数等)。
  • 太棒了!您可以从 XHR 请求中返回类似于以下 JSON 的内容:{ "percent" :55, "totalCount": 355, "otherValue": "I'm another value" } 作为字符串并使用 JSON.parse 将其解析为 JavaScript 对象(在大多数/所有现代浏览器中原生可用)。然后像现在一样进行 UI 更新。这听起来不像是一项大工作,它会解决你的注意力问题。

标签: javascript internet-explorer iframe comet


【解决方案1】:

从 IFRAME 技术更改为使用 XMLHttpRequest 解决方案(被数千个站点/网络应用程序使用)将消除您的焦点问题。许多 Comet 服务器都使用了这种技术,其中一些服务器在 here 中列出。

正如 cmets 中所讨论的,您应该使用 XHR 请求(长轮询或流式传输),以便您可以将更新从服务器推送到仅包含数据的客户端。您可以使用 XMLHttpRequest (XHR) 对象来使用 HTTP 长轮询或 HTTP 流。从上面你可以看到数据如下:

{"s":"正在连接到 xxx@gmail.com...","p":0,"c":null,"e":false}

然后,当状态发生变化时,沿着连接推送另一个更新,例如

{"s":"正在准备提取电子邮件...","p":0,"c":null,"e":false}

XHR 的处理程序然后可以检查XHR.responseText 并解析出更新值。如果您使用长轮询,这很简单:

var update = JSON.parse(xhr.responseText);
MailChecker.updateStatus(update);

如果您使用 XHR 流,那么您还需要从 XHR.responseText 解析出以前的更新,因为它的大小一直在增长。更多关于 HTTP 流的信息:http://ajaxpatterns.org/HTTP_Streaming

【讨论】:

  • 所以例如在邮件服务器上有 100 封电子邮件。结果 - 我们将发送 100 个或更多 Ajax 请求来查看进度?现在只有一个请求...这就是 iframe 用于此的原因。
  • @Andron - 创建一个持久连接。然后,随着新数据可用(电子邮件处理的进度发生变化),您的服务器可以将更新推送到 Web 浏览器。如果需要,您可以一次推送多个更新(可能是更新数组)。关键是,您的iframe 解决方案引起了问题,它可能不是正确的解决方案,使用XMLHttpRequest 对象可能是您的最佳解决方案。我建议您阅读Push TechnologyComet
  • 感谢您的回答,但项目的要求是我们不能安装任何特殊的东西(例如彗星)。那么你认为这可以通过“XMLHttpRequest”响应来完成吗?也许你有一个例子...... :)
  • Comet 不需要任何特殊安装。这是一个范式,一个总称,它还涵盖了您通过 IFRAME 所做的事情。如果您愿意,当然可以使用专用的 Comet/实时服务器 - 这可能是一种很好的做法。您可以看到一个相关的问题here 和一个示例here(查看 JavaScript 源代码),但您需要使用代码来解决缓冲问题。
猜你喜欢
  • 2011-11-04
  • 1970-01-01
  • 2023-04-02
  • 2018-02-13
  • 1970-01-01
  • 2015-05-27
  • 1970-01-01
  • 2015-06-22
相关资源
最近更新 更多