JSFiddle - React, Tailwind, and code Playground
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-debug.js"></script>
<script src="https://githack.com/protonet/jquery.inview/master/jquery.inview.js"></script>
<table>
<tbody>
<tr>
<td style="width: 150px">
<h3>
Full List
</h3>
<ul data-bind="foreach:pages" style="position: fixed">
<li data-bind="text: page() + (inView() ? ': In View' : '' )"></li>
</ul>
</td>
<td class="smartlist">
<h3>
Smart List
</h3>
<ul data-bind="foreach: pages">
<li data-bind="if:inView, inview: $data, css: {inview: inView}">
<!-- if it's in the view, I want to render a complex UI -->
<p data-bind="text: page"></p>
<!-- if not, I just want to show a placeholder -->
</li>
</ul>
</td>
<td>
</td>
</tr>
</tbody>
</table>
CSS
table td {
vertical-align: top;
}
.smartlist ul {
width: 250px;
}
.smartlist li {
display: block;
background: #ccc;
height: 50px;
width: 100%;
margin: 0;
padding:0;
}
.smartlist li.inview {
background: #555;
}
JavaScript
ko.bindingHandlers.inview = {
update: function(element, valueAccessor, allBindings, viewModel) {
var $data = valueAccessor();
$(element).bind('inview', function(e, isInView, visiblePartX, visiblePartY) {
var elem = $(this);
if (isInView) {
$data.inView(true);
} else {
$data.inView(false);
}
});
}
};
$(function() {
ko.applyBindings(new ViewModel());
});
function ViewModel() {
var self = this;
var testPages = [];
for (var i = 0; i < 100; i++) {
testPages.push('Page ' + i);
}
this.pages = ko.observableArray();
this.pages(ko.utils.arrayMap(testPages, function(page) {
return new Page(page);
}));
}
function Page(page) {
var self = this;
this.page = ko.observable(page);
this.inView = ko.observable(false);
}
/**
* author Remy Sharp
* url http://remysharp.com/2009/01/26/element-in-view-event-plugin/
*/
(function($) {
function getViewportHeight() {
var height = window.innerHeight; // Safari, Opera
var mode = document.compatMode;
if ((mode || !$.support.boxModel)) { // IE, Gecko
height = (mode == 'CSS1Compat') ?
document.documentElement.clientHeight : // Standards
document.body.clientHeight; // Quirks
}
return height;
}
$(window).scroll(function() {
var vpH = getViewportHeight(),
scrolltop = (document.documentElement.scrollTop ?
document.documentElement.scrollTop :
document.body.scrollTop),
elems = [];
// naughty, but this is how it knows which elements to check for
$.each($.cache, function() {
if (this.events && this.events.inview) {
elems.push(this.handle.elem);
}
});
if (elems.length) {
$(elems).each(function() {
var $el = $(this),
top = $el.offset().top,
height = $el.height(),
inview = $el.data('inview') || false;
if (scrolltop > (top + height) || scrolltop + vpH < top) {
if...