Opera 中的 JavaScript 范围问题?

发布于 2024-09-16 18:03:23 字数 1178 浏览 3 评论 0原文

我有一个类似小部件的 HTML+JavaScript 块,人们可以将其复制/粘贴到他们的 HTML 页面中一次或多次。该块检查 DOM 中是否已存在外部 JavaScript 文件,如果没有则加载它,如下所示:

(function(){
  d = document;
  if (!d.getElementById('ex-scr')) {
    scr = d.createElement('script');
    scr.async = true;
    scr.id = 'ex-scr';
    scr.src = 'external.js';
    d.getElementsByTagName('head')[0].appendChild(scr)
  }
})();

外部 JavaScript 文件检查 HTML 页面中是否有小部件的实例(使用 getElementsByClassName)并处理这些实例,有点像这样;

for (var i=0;i<document.getElementsByClassName('target').length;i++) {
 document.getElementsByClassName('target')[i].style.borderStyle="solid";
}

可以在 http://futtta.be/opera_enigma.html 上找到相关示例。

这在 Firefox (3.6 & 4b)、Chrome (5 & 6) 和 Safari 中完美运行,但在 Opera 中无法按预期运行(使用最新版本 10.61 进行测试):无论有多少“小部件”(带有class='target') 存在,Opera 仅对第一个起作用,因为显然 nodeList 仅包含 1 个条目(长度为 1 而不是 2 或 3 或...)。

如果在小部件的 javascript 中我调用函数来使用 window.onload 加载外部脚本,那么问题就会消失,但我希望我的小部件尽快激活(不干扰页面的其余部分,因此异步的东西) )。

所以我的问题是;我的代码中是否存在 Firefox、Safari 和 Chrome 忽略的错误?这是 Opera 中的错误吗?我怎样才能让 Opera 正常工作?

I have a widget-like block of HTML+JavaScript that people can copy/paste into their HTML-page one or multiple times. That block checks if an external JavaScript file is already in the DOM, and loads it if not, something like this:

(function(){
  d = document;
  if (!d.getElementById('ex-scr')) {
    scr = d.createElement('script');
    scr.async = true;
    scr.id = 'ex-scr';
    scr.src = 'external.js';
    d.getElementsByTagName('head')[0].appendChild(scr)
  }
})();

The external JavaScript-file checks the HTML-page for instances of the widget (using getElementsByClassName) and does stuff with those instances, kind of like this;

for (var i=0;i<document.getElementsByClassName('target').length;i++) {
 document.getElementsByClassName('target')[i].style.borderStyle="solid";
}

A working example of this can be found on http://futtta.be/opera_enigma.html.

This works perfectly in Firefox (3.6 & 4b), Chrome (5 & 6) and Safari, but does not work as expected in Opera (tested with most recent version, 10.61): no matter how many 'widgets' (divs with class='target') are present, Opera only acts on the first one because apparently the nodeList only contains 1 entry (length is 1 instead of 2 or 3 or ...).

The problem goes away if in the widget's javascript I call the function to load the external script with window.onload, but I'd like my widget to activate as soon as possible (without interfering with the rest of the page, hence the asynchronous stuff).

So my questions; is there a bug in my code which Firefox, Safari and Chrome ignore? Is this a bug in Opera? How can I get Opera to behave?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

陌生 2024-09-23 18:03:23

如果在小部件的 javascript 中我调用函数来使用 window.onload 加载外部脚本,问题就会消失

我认为这就是您的问题。当在脚本文件中执行 getElementsByClassName 时,尚不能保证 DOM 完全存在。如果不等到 DOMreadyloaded 事件,您将无法在此处创建可靠的行为。

The problem goes away if in the widget's javascript I call the function to load the external script with window.onload

I think that's your problem right there. When the getElementsByClassName is executed in your script file, the DOM is not yet guaranteed to be completely present. You won't be able to create reliable behaviour here without waiting until the DOMready or loaded event.

爱的故事 2024-09-23 18:03:23

您可能会遇到浏览器之间的微小时间差异:如果您通过 DOM 将 SCRIPT 添加到文档的头部,Opera 当前将等到脚本执行后再解析文档的其余部分。这是我在这里写的第三个问题:
http://my.opera.com/ Hallvors/blog/2009/03/07/websites-playing-timing-roulette

其他主流浏览器在等待外部脚本时会继续解析。当外部脚本进来时,它们会运行它,当你想要操作的所有元素都在时,它可能会随机(取决于缓存、文档大小、连接速度等)运行。 DOM。然而,我几乎可以保证,在知道解析完整标记之前尝试在 DOM 中查找某种类型的所有元素会给任何浏览器中的某些用户带来问题 - 你正在做什么对网络小问题、连接速度差异、CPU 功率以及影响加载和解析网页时的计时的所有其他细微差异过于敏感。

浏览器会向您发出两个页面已准备好编写脚本的信号:DOMContentLoaded 事件和 onload。如果您需要从文档或其元素读取尺寸,您可能需要等待所有图像和 CSS 加载完毕(即等待 onload 事件),如果没有,您可以使用 DOMContentLoaded。 jQuery 为您提供了 $(document).ready() 来抽象出浏览器支持的“DOM 已准备好”信号之间的差异,其他框架可能也有等效的。

You are probably running into a small timing difference between browsers: if you through DOM add a SCRIPT to the head of a document, Opera will currently wait until the script is executed before parsing the rest of the document. This is the third issue I wrote about here:
http://my.opera.com/hallvors/blog/2009/03/07/websites-playing-timing-roulette

The other major browsers will keep parsing while waiting for the external script. They will run the external script when it comes in, which randomly (depending on caching, size of document, speed of connection etc.) might make it run when all the elements you want to act on are in the DOM. However, I can pretty much promise that trying to look up all elements of a certain type in the DOM before you know the full markup is parsed will cause problems for some users in any browser - what you are doing is way too sensitive to small network hiccups, connection speed differences, CPU power and all the other minor differences that affect timing while loading and parsing a web page.

Browsers give you two signals the page is ready for scripting: DOMContentLoaded event and onload. If you need to read dimensions from the document or its elements, you probably need to wait until all images and CSS are loaded (i.e. wait for the onload event), if not you can use DOMContentLoaded. jQuery gives you $(document).ready() to abstract away the differences in what "DOM is ready now" signals browsers support, other frameworks probably have equivalents.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文