1

I'm trying out Ryan Fioravanti's neat-o technique for deferring JavaScript execution. It's described in slide 27 and slide 28 of his presentation at Google I/O.

In WebKit browsers, it works great, providing measurably better results than just putting the script tag at the bottom of the page or using the async attribute.

However, it does not work in Firefox or IE. I can see in Firebug that the script gets inserted into the DOM but I can also see in Firebug that the script itself is never executed.

The problem appears for both external scripts like <script src="..."></script> and inline scripts like <script>//inline code goes here</script>.

Has anyone gotten this technique to work in non-WebKit browsers?

Here's the relevant source code to replicate the issue:

<script type="text/notJs">
    alert('This alert will show in Chrome and Safari thanks to the DOM manipulation below! But it does not show in Firefox or IE.');
</script>
<script>
    window.onload = function () {
        var scripts = document.getElementsByTagName('script');
        var scriptIndex = 0;
        for (var i = 0, len = scripts.length; i < len; i++) {
            var scriptEl = scripts[scriptIndex];
            if (scriptEl.type === 'text/notJs') {
                scriptEl.type = 'text/javascript';
                scriptEl.parentNode.removeChild(scriptEl);
                document.body.appendChild(scriptEl);
            } else {
                scriptIndex++;
            }
        }
    };
</script>
Trott
  • 66,479
  • 23
  • 173
  • 212
  • So the type of the script gets changed but the script itself isn't downloaded? or it's downloaded and not executed? May be it only works in webkit, have you tried IE, Opera etc? – Andy Davies Jul 11 '12 at 07:13
  • @AndyDavies Looks like you nailed it. Webkit only. Shame on me for not testing more browsers. Ugh. I'll update the question. – Trott Jul 11 '12 at 18:15
  • Have you tried re-setting the content of that script after the type is changed to a known one? – Bergi Jul 11 '12 at 19:27
  • @Bergi Creating a new `script` element and setting it's `src` or `text` attribute appropriately seems to do the trick in IE, but Firefox still doesn't like it. Getting closer, though! – Trott Jul 11 '12 at 20:32
  • Actually, correction: Creating a new `script` element and setting its `text` attribute works in IE and Firefox. It's just scripts that aren't inline that aren't working in Firefox with this adjusted technique. Very close.... – Trott Jul 11 '12 at 20:37
  • Victory! It works in Firefox if I set the `type` attribute explicitly on the new `script` element. – Trott Jul 11 '12 at 20:47
  • Ugh! Not reliably, it doesn't. Bummer. Setting async=false doesn't seem to do the trick either. Weird because Firefox docs talk about order of execution of inserted script elements specifically under "Gecko-specific notes" at https://developer.mozilla.org/en/HTML/Element/script. Maybe I ought to file a bug... – Trott Jul 11 '12 at 21:18
  • Heh, it's weirdly erratic depending on the code that surrounds it. Odd. – Trott Jul 11 '12 at 21:40

1 Answers1

0

Here's code that seems to work in Firefox, IE, Safari, and Chrome. It works for both inline scripts and external scripts.

<script>
    window.onload = function () {
        var scripts = document.getElementsByTagName('script'),
            scriptIndex = 0,
            newScript,
            scriptEl;
        for (var i = 0, len = scripts.length; i < len; i++) {
            scriptEl = scripts[scriptIndex];
            if (scriptEl.type === 'text/notJs') {
                scriptEl.parentNode.removeChild(scriptEl);
                newScript = document.createElement('script');
                newScript.type = "text/javascript";
                if (scriptEl.text) {
                    newScript.text = scriptEl.text;
                } else {
                    newScript.src = scriptEl.src;
                }
                document.body.appendChild(newScript);
            } else {
                scriptIndex++;
            }
        }
    };
</script>
Trott
  • 66,479
  • 23
  • 173
  • 212