<!DOCTYPE html>
<html>

  <head lang="en">
    <meta charset="utf-8">
    <title>Knockout string template engine</title>
    <script type='text/javascript' src="http://knockoutjs.com/downloads/knockout-2.2.1.js"></script>
  </head>
  
  <body>
    <ul data-bind="template: { name: getTemplate, foreach: items }"></ul>
    
    <script type="text/javascript" src="http://knockoutjs.com/downloads/knockout-2.2.1.js"></script>
    <script type="text/javascript" src="stringTemplateEngine.js"></script>
    <script type="text/javascript">
    
      ko.utils.extend(ko.templates, {
          typeA: "<li data-bind='text: name'></li>",
          typeB: "<li><input data-bind='value: name' /></li>"
      });
    
      var viewModel = {
         items: [
            { name: "One", type: "typeA" },
            { name: "Two", type: "typeB" },
            { name: "Three", type: "typeA" }
         ],
         getTemplate: function(item) {
           return item.type;
         }
      };
      
      ko.applyBindings(viewModel);
    </script>
  </body>
  
</html>
//string template engine
(function(ko) {
  //define a template source that tries to key into an object to find a template string
  var templates = {},
    data = {},
    engine = new ko.nativeTemplateEngine();

  ko.templateSources.stringTemplate = function(template) {
    this.templateName = template;
  };

  ko.utils.extend(ko.templateSources.stringTemplate.prototype, {
    data: function(key, value) {
      data[this.templateName] = data[this.templateName] || {};

      if (arguments.length === 1) {
        return data[this.templateName][key];
      }

      data[this.templateName][key] = value;
    },
    text: function(value) {
      if (arguments.length === 0) {
        return templates[this.templateName];
      }

      templates[this.templateName] = value;
    }
  });

  engine.makeTemplateSource = function(template, doc) {
    var elem;
    if (typeof template === "string") {
      elem = (doc || document).getElementById(template);

      if (elem) {
        return new ko.templateSources.domElement(elem);
      }

      return new ko.templateSources.stringTemplate(template);
    } else if (template && (template.nodeType == 1) || (template.nodeType == 8)) {
      return new ko.templateSources.anonymousTemplate(template);
    }
  };

  //make the templates accessible
  ko.templates = templates;

  //make this new template engine our default engine
  ko.setTemplateEngine(engine);
})(window.ko);