Lazyload Images with Knockout & jQuery

Viewed 3688

I have an image intensive site built with knockout & includes jQuery.

These are in foreach loops:

<!-- ko foreach: {data: categories, as: 'categories'} -->
<!-- Category code -->
<!-- ko foreach: {data: visibleStations, as: 'stations'} -->
<!-- specific code -->
<img class="thumb lazy" data-bind="attr: { src: imageTmp,
                                           'data-src': imageThumb,
                                           alt: name,
                                           'data-original-title': name },
                                   css: {'now-playing-art': isPlaying}">
<!-- /ko -->
<!-- /ko -->

So basically when I create these elements, imageTmp is a computed observable that returns a temporary url, and imageThumb gets set to a real url from the CDN.

And I also have this chunk of code, call this the Lazy Sweeper:

var lazyInterval = setInterval(function () {
    $('.lazy:in-viewport').each(function () {
        $(this).attr('src', $(this).data('src')).bind('load', function(){
            $(this).removeClass('lazy')
        });
    });
}, 1000);

That code goes and looks for these images that are in the viewport (using a custom selector to only find images on the screen) and then sets the src to the data-src.

The behavior we want is to avoid the overhead of loading a jillion (er, actually, a few hundred) that the user won't see.

The behavior we are seeing is that on first load, it looks like after ko.applyBindings() is called somehow the Lazy Sweeper gets clobbered and we see the images revert to the default image. Then the sweeper re-runs and we see them display again.

It's not clear to us how best to implement this in a more knockout-ish way.

Thoughts? Insights? Ideas?


I got an answer on twitter mentioning a different lazyloading library. That did not solve the problem - the problem is not understanding how the DOM and the ko representations need to interact to set up lazyloading. I believe what I need is a better way to think about the problem of creating a knockout model that sets imageTmp, and responds to lazyloading based on whether it's in the viewport, and then updates the model once imageThumb (the real image) is loaded.

3 Answers
Related