KnockoutJS control subscription order

by Kevin Van Lierde

HTML

<p data-bind="text: 'The active row is: ' + activeRow()"></p>
<table>
    <tbody data-bind="foreach: data">
        <tr data-bind="css: {active: $parent.activeRow() === $data}">
            <td data-bind="text: $index"></td>
            <td data-bind="text: $data"></td>
            <td><button type="button" data-bind="click: $parent.setData">setData</button></td>
        </tr>
    </tbody>
</table>

CSS

tr.active td { background-color: #99AADD; }

JavaScript

ko.extenders.queueSubs = function(target, value) {
    var s = target.subscribe, //normal subscribe function
        sQueue = []; // subscription queue
    // set up a normal subscription and execute the queue subscriptions in order.
    target.subscribe(function(newValue) {
        sQueue.forEach(function(item, i) {
           sQueue[i](newValue);
        });
    });
    // overwrite the subscribe function of this observable into
    // a function that adds the subscription at a position in the queue
    target.subscribe = function(pos, fn) {
        sQueue.splice(pos, 0, fn);
    };
};

var app = {
  data: ['a','b','c'],
  activeRow: ko.observable(null).extend({queueSubs: true}),
  setData: function(data, e) {
     ko.contextFor(e.target).$parent.activeRow(data);
  }
};
app.activeRow.subscribe(2, function() { alert('This is the last popup'); });
app.activeRow.subscribe(0, function() { alert('Hello'); });
app.activeRow.subscribe(1, function() { alert('Don\'t worry'); });
ko.applyBindings(app);