prototype inheritance and knockoutjs

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>
        <td>
            <div data-bind="template: {name: 'list', data: {list: docList, item: 'doctemplate'}}"></div>
        </td>
        <!-- ko foreach: postingSets -->
        <td>
            <div data-bind="template: {name: 'list', data: {list: $data, item: 'postingtemplate'}}"></div>
 
        </td>
        <!-- /ko -->
    </tr>
</table>
<button data-bind="click: runQuery">Query</button>

<script id="list" type="text/html">
    <div data-bind="foreach: list">
        <div class="item" data-bind="template: {data: $data, name: $parent.item}"></div>
    </div>
</script>

<script id="doctemplate" type="text/html">
    <div>
        <span data-bind="text: docid"></span>
        <span data-bind="text: title"></span>
    </div>
    <div>Retrieved <span data-bind="text: retrievedCount"></span> times</div>
</script>

<script id="postingtemplate" type="text/html">
    <div>
        #<span data-bind="text: rank"></span>
        <span data-bind="text: title"></span>
    </div>
    <div>Retrieved <span data-bind="text: retrievedCount"></span> times</div>
</script>

CSS

.document {
    display: inline;
    margin-right: 10px;
    text-decoration: none;
}

body {
    font-family: sans-serif;
    font-size: 10pt;
}

.lists > li {
    cursor: pointer;
}

.pageButton {
    border: 1px solid blue;
    margin: 4px;
    display: inline;
    padding: 2px;
    width: 10px;
    height: 10px;
    cursor: pointer;
}

.items {
    padding: 6px;
    border: 1px solid grey;
    margin: 6px;
}
.item {
    margin-bottom: 6px;
}

td {
    padding: 6px;
    width:150px;
}

JavaScript

function Document(id, title) {
    var self = this;
    this.docid = ko.observable(id);
    this.title = ko.observable(title);
    this.history = ko.observableArray([]);
    
    this.retrievedCount = ko.computed(function() {
        return self.history().length;
    });
}

var postingId = 1;
function Posting(rank) {
    var self = this;
    this.id = ko.observable(postingId++);
    this.rank = ko.observable(rank);
    this.__proto__.history.push(this);
  
    return this;
}


var id = 1;
var docs = [
    new Document(id++, 'first doc'),
    new Document(id++, 'second doc'),
    new Document(id++, 'third doc'),
    new Document(id++, 'fourth doc'),
    new Document(id++, 'fifth doc'),
    new Document(id++, 'sixth doc'),
    new Document(id++, 'seventh doc'),
    new Document(id++, 'eighth doc'),
    new Document(id++, 'ninth doc'),
    new Document(id++, 'tenth doc'),
/*    new Document(id++, 'eleventh doc'),
    new Document(id++, 'twlevth doc'),
    new Document(id++, 'thirteenth doc'),
    new Document(id++, 'fourteenth doc'),
    new Document(id++, 'fifteenth doc'),
    new Document(id++, 'sixteenth doc'),
    new Document(id++, 'seventeenth doc'),
    new Document(id++, 'eighteenth doc'),
    new Document(id++, 'nineteenth doc'),
    new Document(id++, 'twentieth doc') */
    ];

function PostingFactory(index, rank) {
    Posting.prototype = docs[index];
    return new Posting(rank);
}


function viewModel() {
    var self = this;
    
    this.docList = ko.observableArray(docs);
    this.postingSets = ko.observableArray([]);
    this.runQuery = function() {
        var n = Math.floor(Math.random()*10+1);
        var postings = ko.observableArray([]);       
        for (var i=0; i<n; i++) {
            var index = Math.floor(Math.random()*docs.length);
            postings.push( PostingFactory(index, i+1) );
        }
        self.postingSets.push(postings);
    }
    
};

ko.applyBindings(new viewModel());