External Templates 1

https://groups.google.com/d/topic/knockoutjs/Xsj2xJrmnyM/discussion

by gurkavcu

HTML

<script src="http://rniemeyer.github.com/KnockMeOut/Scripts/jquery.tmpl.js"></script>
<script src="http://rniemeyer.github.com/KnockMeOut/Scripts/knockout-latest.debug.js"></script>
<table>
    <tr>
        <th>Name</th>
        <th></th>
        <th></th>
    </tr>            
    <tbody data-bind="template: { name: templateToUse, foreach: items}"></tbody>
</table>

<button data-bind="click: addItem">New Item</button>

CSS

input { width: 75px; }
td { width: 75px; }
th { color: #666; font-size: .8em; }
.buttons { width: 150px; }

JavaScript

$(function() {
    ensureTemplates(["itemTmpl", "editTmpl"]);
});

function ensureTemplates(list) {
    var loadedTemplates = [];
    ko.utils.arrayForEach(list, function(name) {
        $.get("/gh/get/response.html/rniemeyer/rniemeyer.github.com/tree/master/KnockMeOut/Templates/forJsFiddle/" + name + "/", function(template) {
            $("body").append("<script id=\"" + name + "\" type=\"text/html\">" + template + "<\/script>");
            loadedTemplates.push(name);
            if (list.length === loadedTemplates.length) {
                ko.applyBindings(viewModel);
            }
        });
    });
}

//wrapper for an observable that supports undo/redo
ko.undoableObservable = function(initialValue) {
    //private variables
    var _actual = ko.observable(initialValue);
    var _undos = ko.observableArray([]);
    var _redos = ko.observableArray([]);

    var result = ko.dependentObservable({
        read: function() {
            return _actual();
        },
        write: function(newValue) {
            _redos([]);
            _undos.push(_actual());
            _actual(newValue);
        }
    });

    //expose these flags to allow enabling/disabling buttons
    result.undoable = ko.dependentObservable(function() {
        return _undos().length > 0;
    });

    result.redoable = ko.dependentObservable(function() {
        return _redos().length > 0;
    });

    //go back to the latest undo value
    result.undo = function() {
        if (_undos().length > 0) {
            var last = _undos.pop();
            _redos.push(_actual());
            _actual(last);
        }
    };

    //redo the latest change
    result.redo = function() {
        if (_redos().length > 0) {
            var next = _redos.pop();
            _undos.push(_actual());
            _actual(next);
        }
    };

    return result;
};

var viewModel = {
    items: ko.observableArray([
        {
        name: ko.undoableObservable("one")},
    {
        name:...