Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
lazyload.js (c) Lorenzo Giuliani
/* lazyload.js (c) Lorenzo Giuliani
* MIT License (http://www.opensource.org/licenses/mit-license.html)
*
* expects a list of:
* `<img src="blank.gif" data-src="my_image.png" width="600" height="400" class="lazy">`
*/
!function(window){
var $q = function(q, res){
if (document.querySelectorAll) {
res = document.querySelectorAll(q);
} else {
var d=document
, a=d.styleSheets[0] || d.createStyleSheet();
a.addRule(q,'f:b');
for(var l=d.all,b=0,c=[],f=l.length;b<f;b++)
l[b].currentStyle.f && c.push(l[b]);
a.removeRule(0);
res = c;
}
return res;
}
, addEventListener = function(evt, fn){
window.addEventListener
? this.addEventListener(evt, fn, false)
: (window.attachEvent)
? this.attachEvent('on' + evt, fn)
: this['on' + evt] = fn;
}
, _has = function(obj, key) {
return Object.prototype.hasOwnProperty.call(obj, key);
}
;
function loadImage (el, fn) {
var img = new Image()
, src = el.getAttribute('data-src');
img.onload = function() {
if (!! el.parent)
el.parent.replaceChild(img, el)
else
el.src = src;
fn? fn() : null;
}
img.src = src;
}
function elementInViewport(el) {
var rect = el.getBoundingClientRect()
return (
rect.top >= 0
&& rect.left >= 0
&& rect.top <= (window.innerHeight || document.documentElement.clientHeight)
)
}
var images = new Array()
, query = $q('img.lazy')
, processScroll = function(){
for (var i = 0; i < images.length; i++) {
if (elementInViewport(images[i])) {
loadImage(images[i], function () {
images.splice(i, i);
});
}
};
}
;
// Array.prototype.slice.call is not callable under our lovely IE8
for (var i = 0; i < query.length; i++) {
images.push(query[i]);
};
processScroll();
addEventListener('scroll',processScroll);
}(this);

Hi, I know this code probably hasn't been touched in a while, but as I was going to use it today I realized these line are broken:

loadImage(images[i], function () {
    images.splice(i, i);
}

The second parameter of the splice call should be 1 and not i - because you only want to remove the i element from the array, right? Not i nr of elements.

By the time the splice call is made, via your loadImage callback function, your i will already be set to be the length of the whole images array - as the for loop controlling it will already have finished. You have to create another scope for your i, either by passing it in to loadImage, or perhaps just by wrapping these three line in an IIFE:

(function(i){
    loadImage(images[i], function () {
       images.splice(i, 1);
   }
}(i);
..

I did something else for my purpose, but I think something like this should work for a general case.

Much like pocketjoso before, I realize this code hasn't been touched in a few years, but here's a few lines I added so that images with "lazy" class but no "data-src" are ignored and de-classed. Not doing so could result in a bunch of www.domain.com/null unwanted calls.

This

function loadImage (el, fn) {
    var img = new Image()
      , src = el.getAttribute('data-src');
    img.onload = function() {
      if (!! el.parent)
        el.parent.replaceChild(img, el)
      else
        el.src = src;
      fn? fn() : null;
    }
    img.src = src;
}

Would become

function loadImage (el, fn) {
    var img = new Image()
      , src = el.getAttribute('data-src');
    if (!src) {
        el.className = el.className.replace(/(^|\s)lazy(\s|$)/i, ' ');
        return;
    }
    img.onload = function() {
      if (!! el.parent)
        el.parent.replaceChild(img, el)
      else
        el.src = src;
      fn? fn() : null;
    }
    img.src = src;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment