erdomester
erdomester

Reputation: 11829

How to defer javascript

I am using the fancybox jquery plugin and I am trying to defer the javascript to the end of page loading

    <html>
    <head>
    </head>
    <body> 
        content
/*bottom of body*/
        <script src="jquery-1.8.3.min.js" type="text/javascript"></script>
        <script type="text/javascript" src="jquery.fancybox-1.3.4/fancybox/jquery.fancybox-1.3.4.pack.js" ></script>
        <script type="text/javascript">
            $(document).ready(function() {
                $(".example3").fancybox({
                    'transitionIn'  : 'none',
                    'transitionOut' : 'none'    
                });
            });
        </script>
    </body>
    </html>

At this point the plugin works but the javascript is not deferred. Then I change the script to

<script defer="defer" type="text/javascript">
    window.onload=function(){
        var mycode;
        mycode=document.createElement("script");
        mycode.type="text/javascript";
        mycode.src="jquery.fancybox-1.3.4/fancybox/jquery.fancybox-1.3.4.pack.js";
        document.getElementsByTagName("head")[0].appendChild(mycode);
    }
</script>

like I read here, but then the plugin sometimes work, sometimes it doesn't work. According to google pagespeed I still need to defer the jquery-1.8.3.min.js script. If I defer it the same way, google pagespeed seems ok with it, but then the plugin doesn't work at all.

How am I supposed to do this?

Complete solution based on Jamed Donnelly's answer:

I removed all .js scripts from the head. Then I added this just before the tag:

<script>
(function() {
    function getScript(url,success){
        var script=document.createElement('script');
        script.src=url;
        var head=document.getElementsByTagName('head')[0],
        done=false;
        script.onload=script.onreadystatechange = function(){
        if ( !done && (!this.readyState || this.readyState == 'loaded' || this.readyState == 'complete') ) {
            done=true;
            success();
            script.onload = script.onreadystatechange = null;
            head.removeChild(script);
        }
        };
        head.appendChild(script);
    }

getScript("jquery-1.8.3.min.js",function(){
    getScript("jquery.fancybox-1.3.4/fancybox/jquery.fancybox-1.3.4.pack.js", function() {});
    getScript("myCustomScript.js", function() {});
});

})();
</script>

I created a file myCustomScript.js:

$(document).ready(function(){ 
    $(".example3").fancybox({
        'transitionIn'  : 'none',
        'transitionOut' : 'none'    
    });
});

And that's all.

Upvotes: 0

Views: 1129

Answers (2)

James Donnelly
James Donnelly

Reputation: 128791

What I've been using for a while now is:

(function() {
    function getScript(url,success){
        var script=document.createElement('script');
        script.src=url;
        var head=document.getElementsByTagName('head')[0],
        done=false;
        script.onload=script.onreadystatechange = function(){
        if ( !done && (!this.readyState || this.readyState == 'loaded' || this.readyState == 'complete') ) {
            done=true;
            success();
            script.onload = script.onreadystatechange = null;
            head.removeChild(script);
        }
        };
        head.appendChild(script);
    }
    getScript("whatever1.js",function(){
        getScript("whatever2.js", function() {});
    });
})();

I'll have a dig to try and find where I got this from.

Edit: No luck on finding the source of this, but it's very similar to this article on CSS Tricks.

In your case you'd do something like:

getScript("jquery-1.8.3.min.js",function(){
    getScript("jquery.fancybox-1.3.4/fancybox/jquery.fancybox-1.3.4.pack.js", function() {});
    getScript("myCustomScript.js", function() {});
});

Where myCustomScript.js is a file containing your document ready handler. This basically loads jQuery, then once that's loaded it then loads the plugin and your script.

Upvotes: 1

Joseph
Joseph

Reputation: 119847

Never rely on defer as it is not supported cross-browser. I suggest you load the scripts at the bottom, just before </body> with libraries loaded first (that would be what you did in the first place).

Upvotes: 0

Related Questions