diff --git a/README.md b/README.md index 9d60b1f..ed1c78c 100644 --- a/README.md +++ b/README.md @@ -30,12 +30,12 @@ Using Echo.js is simple, just add the image you wish to load to a `data-echo` a The `init()` API takes a few options #### offset -Type: `Integer` Default: `0` +Type: `Number|String` Default: `0` The `offset` option allows you to specify how far below the viewport you want Echo to _begin_ loading your images. If you specify `0`, Echo will load your image as soon as it is visible in the viewport, if you want to load _1000px_ below the viewport, use `1000`. #### throttle -Type: `Integer` Default: `250` +Type: `Number|String` Default: `250` The throttle is managed by an internal function that prevents performance issues from continuous firing of `window.onscroll` events. Using a throttle will set a small timeout when the user scrolls and will keep throttling until the user stops. The default is `250` milliseconds. @@ -53,7 +53,7 @@ Using `render()` is also throttled, which means you can bind it to a `window.onr Drop your files into your required folders, make sure you're using the file(s) from the `dist` folder, which is the compiled production-ready code. Ensure you place the script before the closing `` tag so the DOM tree is populated when the script runs. ## Configuring Echo -Add the image that needs to load when visible in a `data-echo` attribute: +Add the image that needs to load when it's visible inside the viewport in a `data-echo` attribute: ```html Photo diff --git a/dist/echo.js b/dist/echo.js index d33b5ed..ae82751 100644 --- a/dist/echo.js +++ b/dist/echo.js @@ -1,52 +1,102 @@ -/*! Echo v1.4.0 | (c) 2013 @toddmotto | MIT license | github.com/toddmotto/echo */ -window.Echo = (function (window, document, undefined) { +/*! Echo v1.5.0 | (c) 2014 @toddmotto | MIT license | github.com/toddmotto/echo */ +window.Echo = (function (global, document, undefined) { 'use strict'; - var store = [], offset, throttle, poll; + /** + * store + * @type {Array} + */ + var store = []; - var _inView = function (el) { - var coords = el.getBoundingClientRect(); - return ((coords.top >= 0 && coords.left >= 0 && coords.top) <= (window.innerHeight || document.documentElement.clientHeight) + parseInt(offset)); + /** + * offset, throttle, poll vars + */ + var offset, throttle, poll; + + /** + * _inView + * @private + * @param {Element} element Image element + * @returns {Boolean} Is element in viewport + */ + var _inView = function (element) { + var coords = element.getBoundingClientRect(); + return ((coords.top >= 0 && coords.left >= 0 && coords.top) <= (window.innerHeight || document.documentElement.clientHeight) + offset); }; + /** + * _pollImages Loop through the images if present + * or remove all event listeners + * @private + */ var _pollImages = function () { - for (var i = store.length; i--;) { - var self = store[i]; - if (_inView(self)) { - self.src = self.getAttribute('data-echo'); - store.splice(i, 1); + var length = store.length; + if (length > 0) { + for (var i = 0; i < length; i++) { + var self = store[i]; + if (self && _inView(self)) { + self.src = self.getAttribute('data-echo'); + store.splice(i, 1); + length = store.length; + i--; + } + } + } else { + if (document.removeEventListener) { + global.removeEventListener('scroll', _throttle); + } else { + global.detachEvent('onscroll', _throttle); } + clearTimeout(poll); } }; + /** + * _throttle Sensible event firing + * @private + */ var _throttle = function () { clearTimeout(poll); poll = setTimeout(_pollImages, throttle); }; + /** + * init Module init function + * @param {Object} [obj] Passed in Object with options + * @param {Number|String} [obj.throttle] + * @param {Number|String} [obj.offset] + */ var init = function (obj) { + var nodes = document.querySelectorAll('[data-echo]'); var opts = obj || {}; - offset = opts.offset || 0; - throttle = opts.throttle || 250; + offset = parseInt(opts.offset || 0); + throttle = parseInt(opts.throttle || 250); for (var i = 0; i < nodes.length; i++) { store.push(nodes[i]); } - _throttle(); + _pollImages(); if (document.addEventListener) { - window.addEventListener('scroll', _throttle, false); + global.addEventListener('scroll', _throttle, false); + global.addEventListener('load', _throttle, false); } else { - window.attachEvent('onscroll', _throttle); + global.attachEvent('onscroll', _throttle); + global.attachEvent('onload', _throttle); } + }; + /** + * return Public methods + * @returns {Object} + */ return { init: init, - render: _throttle + render: _pollImages }; -})(window, document); +})(this, document); diff --git a/dist/echo.min.js b/dist/echo.min.js index 4dfeda4..f736f12 100644 --- a/dist/echo.min.js +++ b/dist/echo.min.js @@ -1,2 +1,2 @@ -/*! Echo v1.4.0 | (c) 2013 @toddmotto | MIT license | github.com/toddmotto/echo */ -window.Echo=function(a,b){"use strict";var c,d,e,f=[],g=function(d){var e=d.getBoundingClientRect();return(e.top>=0&&e.left>=0&&e.top)<=(a.innerHeight||b.documentElement.clientHeight)+parseInt(c)},h=function(){for(var a=f.length;a--;){var b=f[a];g(b)&&(b.src=b.getAttribute("data-echo"),f.splice(a,1))}},i=function(){clearTimeout(e),e=setTimeout(h,d)},j=function(e){var g=b.querySelectorAll("[data-echo]"),h=e||{};c=h.offset||0,d=h.throttle||250;for(var j=0;j=0&&d.left>=0&&d.top)<=(window.innerHeight||b.documentElement.clientHeight)+c},h=function(){var c=f.length;if(c>0)for(var d=0;c>d;d++){var h=f[d];h&&g(h)&&(h.src=h.getAttribute("data-echo"),f.splice(d,1),c=f.length,d--)}else b.removeEventListener?a.removeEventListener("scroll",i):a.detachEvent("onscroll",i),clearTimeout(e)},i=function(){clearTimeout(e),e=setTimeout(h,d)},j=function(e){var g=b.querySelectorAll("[data-echo]"),j=e||{};c=parseInt(j.offset||0),d=parseInt(j.throttle||250);for(var k=0;k= 0 && coords.left >= 0 && coords.top) <= (window.innerHeight || document.documentElement.clientHeight) + parseInt(offset)); + /** + * offset, throttle, poll vars + */ + var offset, throttle, poll; + + /** + * _inView + * @private + * @param {Element} element Image element + * @returns {Boolean} Is element in viewport + */ + var _inView = function (element) { + var coords = element.getBoundingClientRect(); + return ((coords.top >= 0 && coords.left >= 0 && coords.top) <= (window.innerHeight || document.documentElement.clientHeight) + offset); }; + /** + * _pollImages Loop through the images if present + * or remove all event listeners + * @private + */ var _pollImages = function () { - for (var i = store.length; i--;) { - var self = store[i]; - if (_inView(self)) { - self.src = self.getAttribute('data-echo'); - store.splice(i, 1); + var length = store.length; + if (length > 0) { + for (var i = 0; i < length; i++) { + var self = store[i]; + if (self && _inView(self)) { + self.src = self.getAttribute('data-echo'); + store.splice(i, 1); + length = store.length; + i--; + } + } + } else { + if (document.removeEventListener) { + global.removeEventListener('scroll', _throttle); + } else { + global.detachEvent('onscroll', _throttle); } + clearTimeout(poll); } }; + /** + * _throttle Sensible event firing + * @private + */ var _throttle = function () { clearTimeout(poll); poll = setTimeout(_pollImages, throttle); }; + /** + * init Module init function + * @param {Object} [obj] Passed in Object with options + * @param {Number|String} [obj.throttle] + * @param {Number|String} [obj.offset] + */ var init = function (obj) { + var nodes = document.querySelectorAll('[data-echo]'); var opts = obj || {}; - offset = opts.offset || 0; - throttle = opts.throttle || 250; + offset = parseInt(opts.offset || 0); + throttle = parseInt(opts.throttle || 250); for (var i = 0; i < nodes.length; i++) { store.push(nodes[i]); } - _throttle(); + _pollImages(); if (document.addEventListener) { - window.addEventListener('scroll', _throttle, false); + global.addEventListener('scroll', _throttle, false); + global.addEventListener('load', _throttle, false); } else { - window.attachEvent('onscroll', _throttle); + global.attachEvent('onscroll', _throttle); + global.attachEvent('onload', _throttle); } + }; + /** + * return Public methods + * @returns {Object} + */ return { init: init, - render: _throttle + render: _pollImages }; -})(window, document); +})(this, document);