rows binding
by jcreamer898
HTML
<div data-bind="rows: { columns: 3, items: things }">
<ul data-bind="foreach: $data">
<li data-bind="text: name"></li>
</ul>
</div>
CSS
li { display: inline-block; }
JavaScript
ko.bindingHandlers.rows = {
init: function (element, valueAccessor, allBindings, data, context) {
var rows = ko.computed({
read: function() {
var index = 0, length, row,
options = ko.unwrap(valueAccessor()),
data = ko.unwrap(options.items),
columnCount = ko.unwrap(options.columns)
result = [];
// we have a sorted array
// we want to produce rows where each column is sorted alpha
var countInAColumn = Math.ceil(data.length / columnCount);
var columns = [];
var originalLength = data.length;
while (index < originalLength) {
columns.push(data.splice(0, countInAColumn));
index += countInAColumn
}
var rows = [];
var cell;
for (var i = 0, length = columns[0].length; i < length; i++) {
var row = [];
rows.push(row);
for (var j = 0, colLength = columns.length; j < colLength; j++) {
cell = columns[j][i];
if (cell) {
row.push(cell);
}
}
}
return rows;
},
disposeWhenNodeIsRemoved: element
});
//apply the real foreach binding with our rows computed
ko.applyBindingsToNode(element, { foreach: rows }, context);
//tell KO that we will handle binding the children
return { controlsDescendantBindings: true };
}
};
var ViewModel = function () {
this.things = ko.observableArray();
for (var i = 0; i < 99; i++) {
this.things.push({ name: "item " + i });
...