Relational data (with index)
Adding Ryan N's suggested index function
by spring1975
HTML
<script src="http://ajax.aspnetcdn.com/ajax/knockout/knockout-2.2.1.debug.js"></script>
<script src="https://raw.github.com/SteveSanderson/knockout.mapping/master/knockout.mapping.js"></script>
<script src="https://raw.github.com/timrwood/moment/master/moment.js"></script>
<div id="ViewModel">
<button class="getData">Get Data</button>
<button data-bind="click: updateAttachmentsProgress">Update Attachments Progress</button>
<ul class="worklist" data-bind="foreach: worklistRequests">
<li>
<div class="progress" data-bind="progressBar: IDRequest, root: $root"></div>
<div><span data-bind="text: IDRequest"></span> – <strong data-bind="text: name"></strong> <!--<span data-bind="text: '(' + attachmentsProgress.percentDone() + '%)'"></span>--></div>
</li>
</ul>
</div>
<pre id="ViewModelUnmapped" data-bind="text: unMappedVM()"></pre>
CSS
{
margin-left: 450px;
color: #00ff00;
width: 550px;
background-color: black;
overflow: auto;
height: 900px;
}
#ViewModel {
float: left;
}
.progress
{
background-color:#CC0000;
height: 2px;
}
.worklist li {
border: 1px solid #CCC;
}
JavaScript
var viewModel = {}, worklistRequestModel = {}, attachmentsProgressModel = {};
WorklistRequestModel = function(data) {
worklistRequestModel = ko.mapping.fromJS(data, {}, this);
},
AttachmentsProgressModel = function(data) {
ko.mapping.fromJS(data, {}, this);
},
RootModel = function(data, mappingOptions) {
var rootModel = ko.mapping.fromJS(data, mappingOptions);
return rootModel;
},
mappingOptions = {
'attachmentsProgress': {
key: function (data) {
return ko.utils.unwrapObservable(data.IDRequest);
},
create: function (options) {
return new AttachmentsProgressModel(options.data);
}
},
'worklistRequests': {
key: function (data) {
return ko.utils.unwrapObservable(data.IDRequest);
},
create: function (options) {
return new WorklistRequestModel(options.data);
}
}
},
rootMapping = {
create: function (options) {
return new RootModel(options.data, mappingOptions);
}
},
loadData = function (newData) {
if ($.isEmptyObject(viewModel)) {
viewModel = ko.mapping.fromJS(newData, rootMapping);
ko.applyBindings(viewModel);
} else {
ko.mapping.fromJS(newData, viewModel);
}
},
updateAttachmentsProgress = function () {
ko.mapping.fromJS({ "attachmentsProgress": myFauxAttachmentsProgress2 }, mappingOptions, viewModel);
},
unMappedVM = function () {
return ko.toJSON(ko.mapping.toJS(viewModel), null, 2);
};
ko.bindingHandlers.progressBar =
{
init: function (element, valueAccessor, allBindingsAccessor) {
var percentDone = ko.computed(function () {
var allBindings = allBindingsAccessor();
var progressItem = allBindings.root.attachmentsProgress.findByPropVal('IDRequest', valueAccessor());
return progressItem ? progressItem.PercentDone() : 0;
});
$(element).css('width', percentDone() + '%');
if (percentDone()...