javascript,css延迟加载器

/**
 * js/css LazyLoad
 * 
 * 变量hash记录已经加载过的资源,避免重复加载
 * 
 * Z.loadScript('a.js', function() { ... })
 *
 * Z.loadScript('a.js', option, function() { ... })
 * 
 * 加载多个js后才回调,如果某个js文件没有下载下来则会报错,且不会执行回调函数
 * Z.loadScript(['a.js','b.js','c.js'], function() { ... })
 * 
 * option
 *   charset: 'utf-8'
 *   scope: xx
 * 
 * 加载多个css后才回调,IE6/7/8/9和Opera中支持link的onreadystatechange事件
 * Firefox/Safari/Chrome既不支持onreadystatechange,也不支持onload。使用setTimeout延迟加载
 *
 * Z.loadLink('a.css', function() { ... })
 * 
 */

var Z = {
    error : function(msg) {
        throw new Error(msg)
    },
    ua : window.navigator.userAgent.toLowerCase(),
    ie : /msie/.test(this.ua) && !/opera/.test(this.ua)
};

(function(Z) {

var doc = window.document;
var hash = {};
var types = ['Array', 'Function', 'Object', 'String', 'Number', 'Boolean', 'Date'];
var nativeForEach = types.forEach;
var emptyFunc = function () {};
var head = doc.head || doc.getElementsByTagName('head')[0];

function forEach(obj, iterator, context) {
    if (obj == null) return;
    if (nativeForEach && obj.forEach === nativeForEach) {
        obj.forEach(iterator, context)
    } else if ( obj.length === +obj.length ) {
        for (var i = 0; i < obj.length; i++) {
            if (iterator.call(context||obj[i], obj[i], i, obj) === true) return
        }
    } else {
        for (var k in obj) {
            if (iterator.call(context||obj[k], obj[k], k, obj) === true) return
        }
    }
}

forEach(types, function(name) {
    Z['is' + name] = function(obj) {
        if (obj === undefined || obj === null) return false;
        return Object.prototype.toString.call(obj) === '[object ' + name + ']'
    }
});

function createEl(type, attrs) {
    var el = doc.createElement(type), attr;
    for (attr in attrs) {
        el.setAttribute(attr, attrs[attr])
    }
    return el
}
function done(list, obj) {
    hash[obj.url] = true;
    list.shift();
    if (!list.length) {
        obj.callback.call(obj.scope)
    }
}
function load(type, urls, option, callback) {

    if (Z.isString(urls)) {
        urls = [urls]
    }

    if (Z.isFunction(option)) {
        callback = option;
        option = {}
    }

    option = option || {};

    var obj = {
        scope: option.scope || window,
        callback: callback || emptyFunc
    };
    var list = [].concat(urls);
    var charset = option.charset || 'utf-8';

    forEach(urls, function(url, i) {
        var el = null;
            
        // 已经加载的不再加载
        if (hash[url]) {
            Z.error('warning: ' + url + ' has loaded.')
        }

        if (type === 'js') {
            el = createEl('script', {
                src: url,
                async: 'async',
                charset: charset
            })
        } else {
            el = createEl('link', {
                href: url,
                rel: 'stylesheet',
                type: 'text/css'
            })
        }

        (function(url) {
            if (Z.ie) {
                el.onreadystatechange = function() {
                    var readyState = this.readyState;
                    if(readyState === 'loaded' || readyState === 'complete') {
                        obj.url = url;
                        this.onreadystatechange = null;
                        done(list, obj)
                    }
                }
            } else {
                if (type == 'js') {
                    el.onload = function() {
                        obj.url = url;
                        done(list, obj)
                    };
                    el.onerror = function () {
                        Z.error(url + ' 不存在');
                    }
                } else {
                    setTimeout(function() {
                        obj.url = url;
                        done(list, obj)
                    }, 100)
                }
            }
        })(url);
        
        if (type === 'js') {
            head.insertBefore(el, head.firstChild)
        } else {
            head.appendChild(el)
        }
    })

}

Z.loadScript = function(urls, option, callback) {
    load('js', urls, option, callback)
};

Z.loadLink = function(urls, option, callback) {
    load('css', urls, option, callback)
}

})(Z);

 

posted @ 2014-06-14 20:13  breezefeng  阅读(1872)  评论(0编辑  收藏  举报