javascript preload&lazy 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();

¡¡¡¡*/