最近需要用到预加载和延迟加载的东东,就参考写了一个。 支持跨页面,支持超时设置与依赖设置。
(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();*/