Image lazy loader
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

146 lines
3.8 KiB

11 years ago
/*! Echo v1.5.0 | (c) 2014 @toddmotto | MIT license | github.com/toddmotto/echo */
window.Echo = (function (global, document, undefined) {
11 years ago
'use strict';
11 years ago
/**
* callback - initialized to a no-op so that no validations on it's presence need to be made
* @type {Function}
*/
var callback = function(){};
/**
* offset, throttle, poll, unload vars
11 years ago
*/
var offset, throttle, poll, unload;
11 years ago
/**
* _inView
* @private
* @param {Element} element Image element
* @returns {Boolean} Is element in viewport
*/
var _inView = function (element, view) {
var box = element.getBoundingClientRect();
return (box.right >= view.l && box.bottom >= view.t && box.left <= view.r && box.top <= view.b);
11 years ago
};
11 years ago
/**
* _pollImages Loop through the images if present
* or remove all event listeners
* @private
*/
11 years ago
var _pollImages = function () {
11 years ago
var src,
length,
i,
11 years ago
elem,
view,
nodes = [].slice.call(document.querySelectorAll('img[data-echo]'));
view = {
l: 0 - offset.l,
t: 0 - offset.t,
b: (window.innerHeight || document.documentElement.clientHeight) + offset.b,
r: (window.innerWidth || document.documentElement.clientWidth) + offset.r
};
11 years ago
for(i=0; i<length; i++) {
elem = nodes[i];
if(_inView(elem, view)) {
if(unload) {
elem.setAttribute('data-echo-placeholder', elem.src);
11 years ago
}
11 years ago
elem.src = elem.getAttribute('data-echo');
if(!unload) {
elem.removeAttribute('data-echo');
}
11 years ago
callback(elem, 'load');
} else if(unload && !!(src = elem.getAttribute('data-echo-placeholder'))) {
elem.src = src;
elem.removeAttribute('data-echo-placeholder');
callback(elem, 'unload');
11 years ago
}
}
11 years ago
if(!length) {
detach();
11 years ago
}
};
11 years ago
/**
* _throttle Sensible event firing
* @private
*/
var _throttle = function () {
clearTimeout(poll);
poll = setTimeout(_pollImages, throttle);
};
11 years ago
/**
* init Module init function
* @param {Object} [opts] Passed in Object with options
* @param {Number|String} [opts.throttle]
* @param {Number|String} [opts.offset]
* @param {Number|String} [opts.offsetBottom]
* @param {Number|String} [opts.offsetTop]
* @param {Number|String} [opts.offsetLeft]
* @param {Number|String} [opts.offsetRight]
* @param {Boolean} [opts.unload]
* @param {Function} [opts.callback]
11 years ago
*/
var init = function (opts) {
opts = opts || {};
var offsetAll = opts.offset || 0;
var offsetVertical = opts.offsetVertical || offsetAll;
var offsetHorizontal = opts.offsetHorizontal || offsetAll;
11 years ago
function optionToInt(opt, fallback) {
return parseInt(opt || fallback, 10);
}
offset = {
t: optionToInt(opts.offsetTop, offsetVertical),
b: optionToInt(opts.offsetBottom, offsetVertical),
11 years ago
l: optionToInt(opts.offsetLeft, offsetHorizontal),
r: optionToInt(opts.offsetRight, offsetHorizontal)
};
11 years ago
throttle = optionToInt(opts.throttle, 250);
unload = !!opts.unload;
callback = opts.callback || callback;
11 years ago
_pollImages();
11 years ago
if (document.addEventListener) {
11 years ago
global.addEventListener('scroll', _throttle, false);
global.addEventListener('load', _throttle, false);
} else {
11 years ago
global.attachEvent('onscroll', _throttle);
global.attachEvent('onload', _throttle);
}
11 years ago
11 years ago
};
/**
* detach remove listeners
*/
var detach = function() {
if (document.removeEventListener) {
global.removeEventListener('scroll', _throttle);
} else {
global.detachEvent('onscroll', _throttle);
}
clearTimeout(poll);
};
11 years ago
/**
* return Public methods
* @returns {Object}
*/
11 years ago
return {
init: init,
detach: detach,
11 years ago
render: _pollImages
11 years ago
};
11 years ago
})(this, document);