preload&lazy load

11678 단어 load
최근에 미리 불러오기와 지연 불러오기가 필요한 것은 참고로 하나 썼습니다.크로스 페이지 지원, 시간 초과 설정 및 의존 설정 지원.
 
(function($) {

(function($) {

    $.preload = function(data, cfg) {

        return new Loader(data, cfg);

    };

    var maps = {}, on = $.event.add, un = $.event.remove, head = document.getElementsByTagName('head')[0], body =

        document.body, bs = $.browser, ie = bs.msie, webkit = bs.webkit, gecko = bs.mozilla, space = 1000, ajax =

        $.ajax,

    loaders = $.preload.loaders = {

        'js'   : function(url, callback, timeout, defer) {

            var s, timer;

            if (defer) {

                if (ie) {

                    return loaders.img(url, callback, timeout);

                } else {

                    s = document.createElement('object');

                    s.data = url;

                    s.width = s.height = 0;

                }

            } else {

                s = document.createElement('script');

                s.setAttribute('type', 'text/javascript');

                s.setAttribute('src', url);

            }

            function f() {

                if (timer)

                    clearTimeout(timer);

                s.onreadystatechange = s.onload = s.onerror = null;

                callback(url, false);

            }

            if (ie) {

                s.onreadystatechange = function() {

                    if (this.readyState === 'loaded' || this.readyState === 'complete') {

                        if (timer)

                            clearTimeout(timer);

                        s.onreadystatechange = null;

                        callback(url, true);

                    }

                };

            } else {

                s.onload = function() {

                    if (timer)

                        clearTimeout(timer);

                    s.onload = s.onerror = null;

                    callback(url, true);

                };

                s.onerror = f;

            }

            timer = setTimeout(f, timeout);

            body.appendChild(s);

        },

        'css'  : function(url, callback, timeout, defer) {

            if (defer) {

                return loaders.js(url, callback, timeout, defer);

            }

            var s = document.createElement('link'), timer;

            s.setAttribute('rel', 'stylesheet');

            s.setAttribute('type', 'text/css');

            s.setAttribute('href', url);

            function f() {

                if (timer)

                    clearTimeout(timer);

                s.onreadystatechange = s.onload = s.onerror = null;

                callback(url, false);

            }

            if (ie) {

                s.onreadystatechange = function() {

                    if (this.readyState === 'loaded' || this.readyState === 'complete') {

                        if (timer)

                            clearTimeout(timer);

                        s.onreadystatechange = null;

                        callback(url, true);

                    }

                };

                timer = setTimeout(f, timeout);

            } else if (webkit || gecko) {

                timer = new Date();

                function f() {

                    if (('sheet' in s) && ('cssRules' in s.sheet)) {

                        try {

                            callback(url, !!s.sheet.cssRules[0]);

                        } catch (e) {

                            setTimeout(f, space);

                        }

                    } else if (new Date() - timer > timeout) {

                        callback(url, false);

                    } else {

                        setTimeout(f, space);

                    }

                }

                setTimeout(f, space * 2);

            } else {

                s.onload = function() {

                    if (timer)

                        clearTimeout(timer);

                    s.onload = s.onerror = null;

                    callback(url, true);

                };

                s.onerror = f;

                timer = setTimeout(f, timeout);

            }

            head.appendChild(s);

        },

        'img'  : function(url, callback, timeout) {

            var s = new Image(), timer;

            function f() {

                if (timer)

                    clearTimeout(timer);

                s.onload = s.onerror = null;

                callback(url, false);

            }

            s.onload = function() {

                if (timer)

                    clearTimeout(timer);

                s.onload = s.onerror = null;

                callback(url, true);

            };

            s.onerror = f;

            timer = setTimeout(f, timeout);

            s.src = url;

        },

        'ajax' : function(url, callback, cfg) {

            cfg = cfg || {};

            cfg.url = url;

            cfg.success = function(data) {

                callback(url, true, data);

            };

            cfg.error = function() {

                callback(url, false);

            };

            ajax(cfg);

        }

    };

    function Loader(data, cfg) {

        var self = this, cur = -1, items = [], pendings = [], done, i = 0, l = data.length, j, m, s, t, c, d, tt, item, doing =

            0, load;

        cfg = cfg || {};

        for (; i < l; ++i) {

            item = data[i];

            if (typeof item === 'string') {

                s = item.substr(item.lastIndexOf('.') + 1);

                items.push(maps[item] = {

                    type : loaders[s] ? s : 'img',

                    url  : item

                });

            } else if (item.urls) {

                for (j = 0, s = item.type, t = item.require, c = item.callback, d = item.defer, tt = item.timeout, item =

                    item.urls, m = item.length; j < m; ++j) {

                    s = s || item[j].substr(item[j].lastIndexOf('.') + 1);

                    items.push(maps[item[j]] = {

                        type     : loaders[s] ? s : 'img',

                        url      : item[j],

                        require  : t,

                        callback : c,

                        defer    : d,

                        timeout  : tt

                    });

                }

            } else {

                if (!item.type) {

                    s = item.url.substr(item.url.lastIndexOf('.') + 1);

                    item.type = loaders[s] ? s : 'img';

                }

                items.push(maps[item.url] = item);

            }

        }

        this.success = this.fail = this.progress = 0;

        if (cfg.onFinish)

            this.onFinish = cfg.onFinish;

        timeout = cfg.timeout || 2000;

        function callback(url, flag, data) {

            if (flag) {

                ++self.success;

            } else {

                ++self.fail;

            }

            self.progress = (self.success + self.fail) / items.length;

            console.info(url);

            console.warn(flag);

            item = maps[url];

            item.success = flag;

            if (self.progress === 1) {

                self.stop();

            }

            if (item.parent && !item.defer && !cfg.defer) {

                $(item.parent)[0].innerHTML = data || '';

            }

            if (item.callback) {

                item.callback(data);

            }

            item.done = true;

            --doing;

        }

        function runnable(item, pend) {

            var it;

            if (typeof item.require === 'string') {

                if (item.done)

                    return false;

                if (!item.require)

                    return true;

                it = maps[item.require];

                if (!it || it.done) {

                    if (pend)

                        pendings.shift();

                    if (it && it.success) {

                        return true;

                    } else {

                        callback(item.url, false);

                    }

                } else if (!pend) {

                    pendings.push(item);

                }

            } else {

                for (it = item.length; it--;) {

                    if (!runnable(item[it], pend))

                        return false;

                }

                return true;

            }

        }

        function run() {

            var item = pendings[0];

            if (!item || !runnable(item, true)) {

                while (item = items[++cur]) {

                    if (runnable(item)) {

                        break;

                    }

                }

            }

            if (item) {

                var fn = loaders[item.type || 'img'];

                if (fn) {

                    ++doing;

                    if (item.type === 'ajax') {

                        if (item.cfg && !item.cfg.timeout)

                            item.cfg.timeout = timeout;

                        fn(item.url, callback, item.cfg);

                    } else {

                        fn(item.url, callback, item.timeout || timeout, item.defer === undefined ? cfg.defer

                                : item.defer);

                    }

                };

                if (load) {

                    run();

                } else {

                    self.timer = setTimeout(run, space);

                }

            } else if (pendings.length) {

                self.timer = setTimeout(run, space);

            }

        }

        this.start = function(delay) {

            if (!done)

                this.timer = setTimeout(run, delay > space ? delay : space);

        };

        this.stop = function() {

            if (this.timer) {

                clearTimeout(this.timer);

                this.timer = null;

                done = true;

                if (this.onFinish) {

                    if (!doing)

                        this.onFinish();

                    else {

                        s = setInterval(function() {

                            if (!doing) {

                                clearInterval(s);

                                self.onFinish();

                            }

                        }, space);

                    }

                }

            }

        };

        this.pause = function() {

            clearTimeout(this.timer);

        };

        this.resume = function() {

            this.timer = setTimeout(run, space);

        };

        this.load = function() {

            clearTimeout(this.timer);

            load = true;

            run();

        };

    }

})(jQuery);

/**

 * @example

 * var loader = $.preload([

 //  , 

 '1.jpg', '1.js',

 //  , , type, require, timeout, defer, callback

 {

 type    : 'img',

 url     : 'http://foo.com/foo',

 timeout : 10

 }, {

 url      : '3.js',

 callback : fn,

 defer    : true,

 require  : '1.js'

 },

 //  , urls 

 {

 type : 'css',

 urls : ['4.css', '5.css']

 }], {

 //  

 onFinish : fn,

 //  

 timeout  : 50

 });

 //  

 loader.start();

 loader.stop();

 //  

 loader.pause();

 loader.resume();

 //  

 loader.load();

 */

좋은 웹페이지 즐겨찾기