开发者

Javascript include function with callback when loaded

For my website I wanted to use conditional javascript loading when certain elements are detected. At first I only created a new script element and append it to the head. When I do this the commands following that statement would always fail because the browser is still loading the javascript file and the function is not ready yet. $("element").something is not a function

A second problem was when another part of my script wanted to include a script that was already requested before. I could not safely assume the script would always still be loading or was already loaded upon that point.

So I wrote a script that could execute callbacks when a script/scripts is/are loaded. This is how my function looks like now:

/* LOADING LIST */
var loading = new Array();

function include(script, callback) {
    if (script instanceof Array) {
        /* load an array of scripts */
        if (script.length > 1) {
            var top = script.shift();
            include(top, function() {
                include(script, callback);
            });
        } else
            include(script[0], callback);
    } else {
        var source = base_url + script;
        var type = /[^.]+$/.exec(script);

        if (type == "js") {
            if ($('script[src="' + source + '"]').length == 0) {
                /* first time script is requested */
                loading[script] = true;

                var e = document.createElement('script');
                e.src = source;
                e.type = "text/javascript";
                e.onload = function() {
                    delete loading[script];
                    if (callback !== undefined) {
                        callback();
                    }
                };
                document.getElementsByTagName("head")[0].appendChild(e);
            }
            else if(script in loading) {
                /* script is being loaded */
                var e = $('script[src="' + source + '"]')[0];
                var old = e.onload;
                e.onload = function() {
                    old();
                    callback();
                };
            }
            else {
                /* script is loaded */
                callback();
            }
        }
        else if (type == "css") {
            /* no need to wait for stylesheets */
            if ($('link[href="' + source + '"]').length == 0) {
                var e = document.createElement('link');
                e.rel = 'stylesheet';
                e.type = 'text/css';
                e.href = source;
                document.getElementsByTagName("head")[0].appendChild(e);
            }
            if (callback !== undefined) {
                callback();
            }
        }
    }
}

It supports things like this:

if($('.wysiwyg').length>0) {
    include(['javascript/ckeditor/ckeditor.js','javascript/ckeditor/adapters/jquery.js'], function() {
        $(".wysiwyg").ckeditor();
    }
}

This will only execute the callback when all the mentioned scripts are loaded.

I do not know very much about javascript and I was wondering if this script could become开发者_如何学JAVA shorter and/or more efficient.


you should use $.getScript() from jQuery. It does what you are doing. And you can also make it load synchronous with $.ajaxSetup({async: false});

for example

$.ajaxSetup({async: false});
$.getScript('myClass.js');
imFromMyClass();

I use a function like:

function require(module) {
    $.ajaxSetup({async: false, cache: true});

    if (window['matchExtension'] === undefined) {
        window['matchExtension'] = function(filename, extensions) {
            return (getFileExtension(filename).match(new RegExp("(" + extensions + ")", "ig")));
        }
    }

    if (typeof module == 'string') {
        var tmp = "";
        if (matchExtension(module, "htm*") || matchExtension(module, "txt")) {
            tmp = $.get(module).responseText;
            return tmp;
        } else if (matchExtension(module, "css")) {
            var obj = $.get(module);
            if (obj.status == 404) return '';

            tmp = obj.responseText;
            var el = document.createElement('style');
            el.type = 'text/css';
            el.media = 'screen';
            document.getElementsByTagName('head')[0].appendChild(el);
            if(el.styleSheet) el.styleSheet.cssText = tmp;// IE method
            else el.appendChild(document.createTextNode(tmp));// others
        } else if (module.EndsWith("/")) {
            return $.get(module).responseText; // directory listing
        } else {
            $.getScript(module);
        }
    } else {
        $.ajaxSetup({async: false, cache:true});
        for (var i =0, len = module.length; i < len; i++) $.getScript(module[i]);
    }
    return true;
}

var content = require('someFile.html');
require('someStyle.css');
require('someClass.js');
require(['class1.js', 'class2.js', 'class3.js']);

one other improvement you can do when loading an array of javascript files is to serve the list to a server script that concatenates them all in the same response

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜