Inheriting Viewmodels

HTML

<script src="//cdnjs.cloudflare.com/ajax/libs/knockout/2.2.1/knockout-min.js"></script>
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.1/css/bootstrap-combined.min.css">
<script src="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.1/js/bootstrap.min.js"></script>
<div data-bind="foreach: items">
    <div data-bind="css: { 'label label-important' : dirtyFlag.isDirty }">
        <input data-bind="value: name, valueUpdate: 'afterkeydown'" />
        <button class="btn" data-bind="click: dirtyFlag.reset">Save</button>
    </div>
</div>
Dirty Items: <span data-bind="text: dirtyItems().length"></span>

JavaScript

ko.dirtyFlag = function(root, isInitiallyDirty) {
    var result = function() {},
        _initialState = ko.observable(ko.toJSON(root)),
        _isInitiallyDirty = ko.observable(isInitiallyDirty);

    result.isDirty = ko.computed(function() {
        return _isInitiallyDirty() || _initialState() !== ko.toJSON(root);
    });

    result.reset = function() {
        _initialState(ko.toJSON(root));
        _isInitiallyDirty(false);
    };

    return result;
};


function Item(data) {
    this.id = ko.observable(data.id);
    this.name = ko.observable(data.name);
    this.dirtyFlag = new ko.dirtyFlag(this);
}

var BaseViewModel = function () {
        var self = this;
        self.items = ko.observable([]);
        self.newItem = {};
        self.dirtyItems = ko.computed(function () {
            return self.items().filter(function (item) {
                return item.dirtyFlag.isDirty();
            });
        });
        self.isDirty = ko.computed(function () {
            return self.dirtyItems().length > 0;
        });
        self.load = function () { }
    };

var ViewModel = function(data) {
    var self = this;
    BaseViewModel.call(self);
    
    var items = ko.utils.arrayMap(data, function(i) { return new Item(i); });
    self.items(items);
};

ViewModel.prototype = new BaseViewModel();

var init = [
    { id: 1, name: "Guy" },
    { id: 2, name: "Dude" }
]

window.vm = new ViewModel(init);
ko.applyBindings(window.vm);