UNPKG

alazyload

Version:
140 lines (138 loc) 4.45 kB
var ALazyload = (function (win, doc, undefined) { /** opts = { element: '#wrapper', itemClass: '.lazy-img', dataSrc: 'data-img', offset: 100 } */ var slice = [].slice, WAIT_TIME = 200; var extend = function (target, source, isOverwrite) { isOverwrite = typeof isOverwrite == 'undefined' ? false : Boolean(isOverwrite); for (var key in source) { if (isOverwrite || !(key in target)) { target[key] = source[key]; } } return target; }; function _now() { return +new Date(); } var throttle = function (fn, wait) { var timer = null, previous = 0, context, args, ret; var later = function () { previous = _now(); timer = null; ret = fn.apply(context, args); args = null; }; return function (ctx) { var now = _now(); context = ctx, args = slice.call(arguments, 1); if (!previous) previous = now; var remaining = wait - (now - previous); if (remaining <= 0 || remaining > wait) { timer && clearTimeout(timer); timer = null; previous = now; ret = fn.apply(context, args); args = null; } else { timer = setTimeout(later, remaining); } }; }; var Lazyload = function (element, opts) { var len = slice.call(arguments, 1); var defaultOpts = { item: '.lazy-img', dataSrc: 'data-img', offset: 0 }; if (!len) { if (typeof element !== 'object' || element === null) { throw new Error('need opts arguments here.'); } opts = element; element = null; } this.opts = extend(opts, defaultOpts); this.element = typeof (element = element || opts.element) === 'string' ? doc.querySelector(element) : element; this.items = this.element.querySelectorAll(this.opts.itemClass); // initial & bind event this.init(); }; Lazyload.prototype = { constructor: Lazyload, init: function () { var self = this; // initial load images within viewport this._loadImgsWithinView(); var optimizedLoadImgsWithinView = throttle(this._loadImgsWithinView, WAIT_TIME); this._optimizedLoadImgsWithinView = function (e) { optimizedLoadImgsWithinView.call(this, self); }; // load images when scrolling into viewport this._addScrollHandler(); }, _loadImgsWithinView: function () { var offset = typeof (offset = this.opts.offset) !== 'number' ? parseInt(offset, 10) : offset; var W = window.innerWidth || doc.documentElement.clientWidth, H = window.innerHeight || doc.documentElement.clientHeight, viewport = { top: -offset, left: -offset, bottom: H + offset, right: W + offset }; this.items = slice.call(this.items); var i = 0, len = this.items.length, imgRect, imgItem, isInViewport; for (; i < len; i++) { imgItem = this.items[i]; imgRect = imgItem.getBoundingClientRect(); isInViewport = ( imgRect.top <= viewport.bottom && imgRect.bottom >= viewport.top && imgRect.left <= viewport.right && imgRect.right >= viewport.left ); console.log('isInViewport: ', isInViewport); // load img within viewport if (isInViewport) { console.log('load img: ', imgItem); this._loadImgItem(imgItem); this.items.splice(i, 1); i--; len--; } } if (len === 0) { // remove scroll event handler this._removeScrollHandler(); } }, _loadImgItem: function (img) { var dataSrc = this.opts.dataSrc, imgSrc = img.getAttribute(dataSrc); img.removeAttribute(dataSrc); if (imgSrc) { img.setAttribute('src', imgSrc); } }, _removeScrollHandler: function () { doc.removeEventListener('scroll', this._optimizedLoadImgsWithinView); }, _addScrollHandler: function () { doc.addEventListener('scroll', this._optimizedLoadImgsWithinView); } }; return Lazyload; })(window, window.document, void 0); // cmd/window output if (typeof module === 'object' && module.exports) { module.exports = ALazyload; } else { window.ALazyload = ALazyload; }