Problem with JavaScript scope in Opera?

I have an HTML + JavaScript block widget that people can copy / paste into their HTML page one or more times. This block checks whether the 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) } })(); 

An external JavaScript file checks the HTML page for widget instances (using getElementsByClassName) and does things with these instances, sort of like:

 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 at http://futtta.be/opera_enigma.html .

This works fine in Firefox (3.6 and 4b), Chrome (5 and 6) and Safari, but it doesn’t work in Opera (tested with the latest version 10.61): no matter how many widgets (divs with class='target' ) , Opera only acts on the first, because, apparently, nodeList contains only 1 entry (the length is 1 instead of 2 or 3 or ...).

The problem disappears if in the javascript of the widget I call a function to load an external script using window.onload, but I would like my widget to be activated as soon as possible (without interfering with the rest of the page, therefore, asynchronous material).

So, my questions; Is there a bug in my code that Firefox, Safari and Chrome ignore? Is this a bug in Opera? How can I make Opera behave?

+4
javascript opera
source share
2 answers

The problem disappears if in the javascript of the widget I call a function to load an external script using window.onload

I think your problem is right there. When getElementsByClassName is executed in your script file, the DOM is not yet guaranteed to be fully present. Here you cannot create reliable behavior without waiting for a DOMready or loaded event.

+5
source share

You are probably faced with a small time difference between browsers: if you add SCRIPT to the document head via the DOM, Opera will wait until SCRIPT is executed before the rest of the document is parsed. This is the third question I wrote here: http://my.opera.com/hallvors/blog/2009/03/07/websites-playing-timing-roulette

Other major browsers will continue parsing, awaiting an external script. They will start an external SCRIPT when it comes in, which by chance (depending on caching, document size, connection speed, etc.) may make it work when all the elements you want to act on are in the DOM. However, I can pretty much promise that trying to find all elements of a certain type in the DOM before you know the full markup will be parsed will cause problems for some users in any browser - what you do is too sensitive to small network icons , differences in connection speeds, processor power, and all other minor differences that affect the time it takes to load and analyze a web page.

Browsers give you two signals, the page is ready for scripting: the DOMContentLoaded event and onload. If you need to read dimensions from a document or its elements, you will probably have to wait until all images and CSS have been loaded (for example, wait for the onload event) if you cannot use DOMContentLoaded. jQuery gives you $ (document) .ready () to distract from the differences in what supports the "DOM" now, supports browsers, other structures probably have equivalents.

+1
source share

All Articles