How to defer observable updating?
How can I defer evaluation of a view page until it is displayed?
by gene
HTML
<script src="https://github.com/downloads/SteveSanderson/knockout/knockout-2.0.0.js"></script>
<script src="https://raw.github.com/mbest/knockout-deferred-updates/master/knockout-deferred-updates.js"></script>
<table border="3" cellpadding="2">
<tr>
<th>Lists</th>
<th>Documents</th>
</tr>
<tr>
<td>
<div class="selections"><div class="fixed">
<ul class="lists" data-bind="foreach: views">
<li data-bind="text: label, click: $parent.selectedView"></li>
</ul>
<br />
<!-- ko with: selectedView --> <!-- ko with: view -->
<ul class="filters" data-bind="foreach: filters">
<li data-bind="text: label, click: $parent.selectedFilter, css: {selectedFilter: selected()}"></li>
</ul>
<!-- /ko --> <!-- /ko -->
</div></div>
</td>
<td data-bind="with: selectedView">
<div class="detail" >
<div class="fixed">
<div data-bind="foreach: pageList">
<div class="pageButton" data-bind="text: $data, click: $parent.goToPage"></div>
</div>
<button data-bind="click: sortById">By id</button>
<button data-bind="click: sortByTitle">By title</button>
<ul class="items" data-bind="foreach: rows">
<div><span data-bind="text: id"></span> <span data-bind="text: title"></span>
<span data-bind="text: price"></span></div>
</ul>
</div>
</div>
</td>
</tr>
</table>
<button data-bind="click: addDocument">Add doc</button>
<button data-bind="click: boostDocument">Boost doc</button>
CSS
.document {
display: inline;
margin-right: 10px;
text-decoration: none;
}
body {
font-family: sans-serif;
font-size: 10pt;
}
.lists > li {
cursor: pointer;
}
.filters > li {
cursor: pointer;
}
.selectedFilter {
font-weight: bold;
}
.pageButton {
border: 1px solid blue;
margin: 4px;
display: inline;
padding: 2px;
width: 10px;
height: 10px;
cursor: pointer;
}
.items {
position: relative;
padding: 6px;
border: 1px solid grey;
margin: 6px;
width: 100%;
}
td {
padding: 6px;
position: relative;
height: 200px;
}
.selections {
position: relative;
height: 200px;
width: 50px ! important;
}
.fixed {
position: absolute;
top: 4px;
left 4px;
}
.detail {
position: relative;
height: 200px;
width: 300px;
}
JavaScript
// data
function Document(id, title, price) {
var self = this;
this.id = ko.observable(id);
this.title = ko.observable(title);
this.price = ko.observable(price);
this.other = '';
}
var id = 1;
var docs = [
new Document(id++, 'first doc', 10),
new Document(id++, 'second doc', 10),
new Document(id++, 'third doc', 12),
new Document(id++, 'fourth doc', 12),
new Document(id++, 'fifth doc', 14),
new Document(id++, 'sixth doc', 14),
new Document(id++, 'seventh doc', 15),
new Document(id++, 'eighth doc', 15),
new Document(id++, 'ninth doc', 20),
new Document(id++, 'tenth doc', 20),
new Document(id++, 'eleventh doc', 20),
new Document(id++, 'twlevth doc', 20),
new Document(id++, 'thirteenth doc', 10),
new Document(id++, 'fourteenth doc', 9),
new Document(id++, 'fifteenth doc', 8),
new Document(id++, 'sixteenth doc', 7),
new Document(id++, 'seventeenth doc', 6),
new Document(id++, 'eighteenth doc', 8),
new Document(id++, 'nineteenth doc', 5),
new Document(id++, 'twentieth doc', 3)
];
// views
function Filter(label, range) {
var self = this;
this.label = ko.observable(label);
this.range = ko.observable(range);
this.matches = function(doc) {
var rnge = self.range();
var price = doc.price();
return price >= rnge[0] && price < rnge[1];
};
this.toString = function() { return "Filter(" + self.label() + ")"; }
this.selected = ko.observable(false);
this.selected.subscribe(function(sel) {
if (sel)
console.log(self, "selected");
});
}
function FilterView(filters, allItems) {
var self = this;
this.label = 'unassigned';
this.filters = filters;
this.selectedFilter = ko.observable();
this.selectedFilter.subscribe(function(f) {
for (var i=0; i<self.filters.length; i++)
self.filters[i].selected(false);
f.selected(true);
});
...