| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324 | (function($, window, document) {	var mid = 0;	$.Lazyload = $.Class.extend({		init: function(element, options) {			var self = this;			this.container = this.element = element;//			placeholder //默认图片			this.options = $.extend({				selector: '',//查询哪些元素需要lazyload				diff: false,//距离视窗底部多少像素出发lazyload				force: false,//强制加载(不论元素是否在是视窗内)				autoDestroy: true,//元素加载完后是否自动销毁当前插件对象				duration: 100//滑动停止多久后开始加载			}, options);			this._key = 0;			this._containerIsNotDocument = this.container.nodeType !== 9;			this._callbacks = {};			this._init();		},		_init: function() {			this._initLoadFn();			this.addElements();			this._loadFn();			$.ready(function() {				this._loadFn();			}.bind(this));			this.resume();		},		_initLoadFn: function() {			var self = this;			self._loadFn = this._buffer(function() { // 加载延迟项				if (self.options.autoDestroy && self._counter == 0 && $.isEmptyObject(self._callbacks)) {					self.destroy();				}				self._loadItems();			}, self.options.duration, self);		},		/**		 *根据加载函数实现加载器		 *@param {Function} load 加载函数		 *@returns {Function} 加载器		 */		_createLoader: function(load) {			var value, loading, handles = [],				h;			return function(handle) {				if (!loading) {					loading = true;					load(function(v) {						value = v;						while (h = handles.shift()) {							try {								h && h.apply(null, [value]);							} catch (e) {								setTimeout(function() {									throw e;								}, 0)							}						}					})				}				if (value) {					handle && handle.apply(null, [value]);					return value;				}				handle && handles.push(handle);				return value;			}		},		_buffer: function(fn, ms, context) {			var timer;			var lastStart = 0;			var lastEnd = 0;			var ms = ms || 150;			function run() {				if (timer) {					timer.cancel();					timer = 0;				}				lastStart = $.now();				fn.apply(context || this, arguments);				lastEnd = $.now();			}			return $.extend(function() {				if (					(!lastStart) || // 从未运行过					(lastEnd >= lastStart && $.now() - lastEnd > ms) || // 上次运行成功后已经超过ms毫秒					(lastEnd < lastStart && $.now() - lastStart > ms * 8) // 上次运行或未完成,后8*ms毫秒				) {					run();				} else {					if (timer) {						timer.cancel();					}					timer = $.later(run, ms, null, arguments);				}			}, {				stop: function() {					if (timer) {						timer.cancel();						timer = 0;					}				}			});		},		_getBoundingRect: function(c) {			var vh, vw, left, top;			if (c !== undefined) {				vh = c.offsetHeight;				vw = c.offsetWidth;				var offset = $.offset(c);				left = offset.left;				top = offset.top;			} else {				vh = window.innerHeight;				vw = window.innerWidth;				left = 0;				top = window.pageYOffset;			}			var diff = this.options.diff;			var diffX = diff === false ? vw : diff;			var diffX0 = 0;			var diffX1 = diffX;			var diffY = diff === false ? vh : diff;			var diffY0 = 0;			var diffY1 = diffY;			var right = left + vw;			var bottom = top + vh;			left -= diffX0;			right += diffX1;			top -= diffY0;			bottom += diffY1;			return {				left: left,				top: top,				right: right,				bottom: bottom			};		},		_cacheWidth: function(el) {			if (el._mui_lazy_width) {				return el._mui_lazy_width;			}			return el._mui_lazy_width = el.offsetWidth;		},		_cacheHeight: function(el) {			if (el._mui_lazy_height) {				return el._mui_lazy_height;			}			return el._mui_lazy_height = el.offsetHeight;		},		_isCross: function(r1, r2) {			var r = {};			r.top = Math.max(r1.top, r2.top);			r.bottom = Math.min(r1.bottom, r2.bottom);			r.left = Math.max(r1.left, r2.left);			r.right = Math.min(r1.right, r2.right);			return r.bottom >= r.top && r.right >= r.left;		},		_elementInViewport: function(elem, windowRegion, containerRegion) {			// display none or inside display none			if (!elem.offsetWidth) {				return false;			}			var elemOffset = $.offset(elem);			var inContainer = true;			var inWin;			var left = elemOffset.left;			var top = elemOffset.top;			var elemRegion = {				left: left,				top: top,				right: left + this._cacheWidth(elem),				bottom: top + this._cacheHeight(elem)			};			inWin = this._isCross(windowRegion, elemRegion);			if (inWin && containerRegion) {				inContainer = this._isCross(containerRegion, elemRegion);			}			// 确保在容器内出现			// 并且在视窗内也出现			return inContainer && inWin;		},		_loadItems: function() {			var self = this;			// container is display none			if (self._containerIsNotDocument && !self.container.offsetWidth) {				return;			}			self._windowRegion = self._getBoundingRect();			if (self._containerIsNotDocument) {				self._containerRegion = self._getBoundingRect(this.container);			}			$.each(self._callbacks, function(key, callback) {				callback && self._loadItem(key, callback);			});		},		_loadItem: function(key, callback) {			var self = this;			callback = callback || self._callbacks[key];			if (!callback) {				return true;			}			var el = callback.el;			var remove = false;			var fn = callback.fn;			if (self.options.force || self._elementInViewport(el, self._windowRegion, self._containerRegion)) {				try {					remove = fn.call(self, el, key);				} catch (e) {					setTimeout(function() {						throw e;					}, 0);				}			}			if (remove !== false) {				delete self._callbacks[key];			}			return remove;		},		addCallback: function(el, fn) {			var self = this;			var callbacks = self._callbacks;			var callback = {				el: el,				fn: fn || $.noop			};			var key = ++this._key;			callbacks[key] = callback;			// add 立即检测,防止首屏元素问题			if (self._windowRegion) {				self._loadItem(key, callback);			} else {				self.refresh();			}		},		addElements: function(elements) {			var self = this;			self._counter = self._counter || 0;			var lazyloads = [];			if (!elements && self.options.selector) {				lazyloads = self.container.querySelectorAll(self.options.selector);			} else {				$.each(elements, function(index, el) {					lazyloads = lazyloads.concat($.qsa(self.options.selector, el));				});			}			$.each(lazyloads, function(index, el) {				if (!el.getAttribute('data-lazyload-id')) {					if (self.addElement(el)) {						el.setAttribute('data-lazyload-id', mid++);						self.addCallback(el, self.handle);					}				}			});		},		addElement: function(el) {			return true;		},		handle: function() {			//throw new Error('需子类实现');		},		refresh: function(check) {			if (check) { //检查新的lazyload				this.addElements();			}			this._loadFn();		},		pause: function() {			var load = this._loadFn;			if (this._destroyed) {				return;			}			window.removeEventListener('scroll', load);			window.removeEventListener($.EVENT_MOVE, load);			window.removeEventListener('resize', load);			if (this._containerIsNotDocument) {				this.container.removeEventListener('scrollend', load);				this.container.removeEventListener('scroll', load);				this.container.removeEventListener($.EVENT_MOVE, load);			}		},		resume: function() {			var load = this._loadFn;			if (this._destroyed) {				return;			}			window.addEventListener('scroll', load, false);			window.addEventListener($.EVENT_MOVE, load, false);			window.addEventListener('resize', load, false);			if (this._containerIsNotDocument) {				this.container.addEventListener('scrollend', load, false);				this.container.addEventListener('scroll', load, false);				this.container.addEventListener($.EVENT_MOVE, load, false);			}		},		destroy: function() {			var self = this;			self.pause();			self._callbacks = {};			$.trigger(this.container, 'destroy', self);			self._destroyed = 1;		}	});})(mui, window, document);
 |