How can I use yepnope.js with $(document).ready() effectively?

守給你的承諾、 提交于 2019-11-29 21:53:52

If load jQuery without yepnope isn't a problem for you, there is a easier way to do.

<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>

<script>
    $.holdReady(true);

    yepnope.load({
        load: [
            'placeholder.js',
            'jquery-ui.min.js'
        ],
        complete: function (){
            $.holdReady(false);
        }
    });
</script>

This is the technique I use. It allows me to sprinkle $(document).ready() style calls wherever I like. Using this method, you can take a site that already uses jQuery and has existing $(document).ready() calls, and easily retrofit yepnope.

First, add this line of JS, preferably in the document head, before any javascript that calls $(document).ready():

<script>
    var docready=[],$=function(o){function r(fn){docready.push(fn);}if(typeof o === 'function') r(o);return{ready: r}};
</script>

Then, have your yepnope jQuery test object set similar to this:

yepnope({
    load: '//ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.min.js',
    complete: function() {
        $ = jQuery;         
        for(n in docready) $(document).ready(docready[n]);
    }
});

We create a fake $(document).ready() before jQuery loads. This stores every $(document).ready() call in an array, docready. Then, once jQuery has loaded, we overwrite our temporary $ object with the now loaded real jQuery object. Then, we iterate through all the stored $(document).ready() calls, and execute them for real.

UPDATED: improved version from Chris Jones that also covers $(function() {}) style invocations.

script tags are loading synchronously - so if you put your yepnope in a js file and load it via script tag:

   <script type="text/javascript" src="/my-yepnope-stuff.js"></script>
</body>

right before the closing body tag you can be quite sure to be at $(document).ready() state.

What you need to answer for yourself is whether it makes sense to force yepnope to load in a $(document).ready() fashion, as its main purpose is to break the synchronous loading order of script tags in the first place.

Using guidance from @ezmilhouse, I thought about the best way to achieve what I was after while still keeping compatibility with our older code.

My solution was to set up my yepnope scriptloader to load all necessary scripts in a hierarchical fashion, based on their individual dependencies. Once all scripts are loaded, you can use the complete property of my call to yepnope to call my ready function. This meant that the document was effectively ready and the code would work with no issues.

I also moved my js to the base of my pages (something that I should have done a long time ago, but we had a lot of legacy pages! :) )

Here is an example (using false libray/script names for illustration purposes only):

yepnope({
    test: baseLib.debug,
    yep: { "max": "/version2/res/jquery/jquery-1.5.2.js" },
    nope: { "min": "/version2/res/jquery/jquery-1.5.2.min.js" },
    callback: {
        "max": function (url, result, key) {
            baseLib.Log("jQuery full loaded.");
        },
        "min": function (url, result, key) {
            baseLib.Log("jQuery min loaded.");
        }
    },
    complete: function () {
        if (window.$) {
            yepnope({
                test: base.debug,
                yep: {
                   "anotherscript": "script/url/here.js",
                   "anotherscript2": "script/url/here2.js"
                },
                nope: {
                    "anotherscript": "script/url/here-min.js",
                    "anotherscript2": "script/url/here2-min.js"
                },
                both: {
                    "anotherscript3": "script/url/here3.js"
                },
                callback: {
                    "anotherscript": function (url, result, key) {
                        baseLib.Log("anotherscript " + (result ? "Max" : "Min") + " loaded.");

                    },
                    "anotherscript2": function (url, result, key) {
                        baseLib.Log("anotherscript2 " + (result ? "Max" : "Min") + " loaded.");
                    },
                    "anotherscript3": function (url, result, key) {
                        baseLib.Log("anotherscript3 loaded.");
                    }
                },
                complete: function () {
                    baseLib.Log("Scripts Loaded");
                    baseLib.Page.Ready();
                }
            });

        }
        else {
            baseLib.Log("Could not load jQuery. No further jQuery dependent files loaded.", "error");
        }
    }
});

In my page js I will assign a function to baseLib.Page.Ready that will then be called by yepnope on complete.

I think that Alex Sexton solution would be correct :

yepnope({
    load: '//ajax.googleapisOFFLINE.com/ajaxX/libs/jquery/1.7.1/jquery.min.js',
    callback: function () {
        if (!window.jQuery) {
            yepnope('/js/jquery-1.7.1.min.js');
        }
    },
    complete: function () {
      $(function(){
        $("div.whatever").css("color","red");
      });
    }
});
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!