Floating DIVs built from JS Array with Knockout Binding and computed values
by nwinkler
HTML
<script src="https://github.com/downloads/SteveSanderson/knockout/knockout-2.1.0.debug.js"></script>
<script src="https://raw.github.com/SteveSanderson/knockout.mapping/master/knockout.mapping.js"></script>
<div class='container' id='fieldContainer' data-bind='foreach: labels'>
<div class='field' data-bind='attr: { id: "field_" + $parent.requestId() + "_" + id() }'>
<span class='label' data-bind='text: label'></span>: <span class='value' data-bind='text: value'></span>
</div>
</div>
<button id='update'>Update</button>
<button id='delete'>Delete</button>
<button id='reset'>Reset</button>
CSS
.container {
overflow: hidden;
width: 100%;
margin: -5px;
}
.field {
background-color: gray;
height: 20px;
width: 100px;
margin: 5px;
float: left;
text-align: left;
line-height: 20px;
}
.label {
margin: 2px;
float: left;
}
.value {
margin: 2px;
float: right;
}
JavaScript
var fields = [ { id: 1, text: 'Darkness' },
{ id: 5, text: 'Of' },
{ id: 2, text: 'On' },
{ id: 6, text: 'Town' },
{ id: 3, text: 'The' },
{ id: 4, text: 'Edge' }
];
var fields2 = [ { id: 1, text: 'We\'re' },
{ id: 2, text: 'Going' },
{ id: 3, text: 'Racing' },
{ id: 4, text: 'In' },
{ id: 5, text: 'The' },
{ id: 6, text: 'Streets' }
];
var labels = [ { id: 1, label: '1' },
{ id: 2, label: '2' },
{ id: 3, label: '3' },
{ id: 4, label: '4' },
{ id: 5, label: '5' },
{ id: 6, label: '6' }
];
var fieldMapping = {
key: function(item) {
return ko.utils.unwrapObservable(item.id);
}
};
var labelMapping = {
create: function(options) {
return (new (function() {
this.value = ko.computed(function() {
var index = viewModel.fields.mappedIndexOf( { id: options.data.id } );
if (index < 0) {
return "n/a";
}
else {
return viewModel.fields()[index].text();
}
}, this);
this.value.subscribe(function(data) {
$("#field_" + viewModel.requestId() + "_" + this.id()).effect('highlight');
}, this);
ko.mapping.fromJS(options.data, {}, this);
}) ());
}
};
var viewModel = {
labels: ko.mapping.fromJS([], labelMapping),
fields: ko.mapping.fromJS([], fieldMapping),
requestId: ko.observable("3")
};
ko.applyBindings(viewModel);
function updateFields(updatedFields) {
$.each(updatedFields, function(index, value) {
var indexInViewModel = viewModel.fields.mappedIndexOf( { id: value.id } );
if (indexInViewModel < 0) {
viewModel.fields.push(ko.mapping.fromJS(value));
}
else {
ko.mapping.fromJS(value, fieldMapping, viewModel.fields()[indexInViewModel]);
}
});
}
function...