JSFiddle - React, Tailwind, and code Playground
by Jan Föh
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>
SCSS
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('//placehold.it/640x640', '//lorempixel.com/640/640/cats') );
}
};
ko.applyBindings( new Viewmodel() );
var lazyInterval = setInterval(function () {
$('.lazy:in-viewport').each(function () {
if (ko.dataFor(this)) {
ko.dataFor(this).showPlaceholder(false);
}
});
}, 1000);