JSFiddle - React, Tailwind, and code Playground
HTML
<script src="//cdnjs.cloudflare.com/ajax/libs/knockout/2.3.0/knockout-debug.js"></script>
<script src="http://www.appelsiini.net/download/jquery.viewport.js"></script>
<ul data-bind="foreach: stations">
<li>
<img class="lazy" data-bind="lazyImage: imageUrl" />
</li>
</ul>
CSS
ul {
position: relative;
width: 100%;
padding: 0;
list-style-type: none;
}
li img {
width: 100%;
}
JavaScript
var Station,
Viewmodel;
ko.bindingHandlers.lazyImage = {
update: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
var $element = $(element),
// we unwrap our imageUrl to get a subscription to it,
// so we're called when it changes.
// Use ko.utils.unwrapObservable for older versions of Knockout
imageSource = ko.unwrap(valueAccessor());
$element.attr('src', imageSource);
// we don't want to remove the lazy class after the temp image
// has loaded. Set placehold.it to something that identifies
// your real placeholder image
if (imageSource.indexOf('placehold.it') === -1) {
$element.one('load', function() {
$(this).removeClass('lazy');
});
}
}
};
Station = function Station(tempUrl, thumbUrl) {
var that = this;
this.showPlaceholder = ko.observable(true);
this.imageTemp = ko.observable(tempUrl);
this.imageThumb = ko.observable(thumbUrl);
this.imageUrl = ko.computed(function() {
return that.showPlaceholder() ? that.imageTemp() : that.imageThumb();
});
};
Viewmodel = function Viewmodel() {
this.stations = ko.observableArray([]);
for (var i=0; i < 10; i++) {
this.stations.push( new Station('https://cdn.sstatic.net/Sites/stackoverflow/img/apple-touch-icon.png?v=c78bd457575a', 'https://cdn.sstatic.net/Sites/stackoverflow/img/apple-touch-icon.png?v=c78bd457575a') );
}
};
ko.applyBindings( new Viewmodel() );
var lazyInterval = setInterval(function () {
$('.lazy:in-viewport').each(function () {
if (ko.dataFor(this)) {
ko.dataFor(this).showPlaceholder(false);
}
});
}, 1000);