vendor/assets/javascripts/knockout.js in knockoutjs-rails-1.1.2 vs vendor/assets/javascripts/knockout.js in knockoutjs-rails-1.02
- old
+ new
@@ -1,63 +1,1255 @@
-// Knockout JavaScript library v1.1.2
+// Knockout JavaScript library v1.02
// (c) 2010 Steven Sanderson - http://knockoutjs.com/
// License: Ms-Pl (http://www.opensource.org/licenses/ms-pl.html)
-function a(f){throw f;}var m=true,o=null,p=false,r=window.ko={};r.b=function(f,b){for(var c=f.split("."),d=window,e=0;e<c.length-1;e++)d=d[c[e]];d[c[c.length-1]]=b};r.g=function(f,b,c){f[b]=c};
-r.a=new function(){var f=/^(\s|\u00A0)+|(\s|\u00A0)+$/g;return{ba:["authenticity_token",/^__RequestVerificationToken(_.*)?$/],h:function(b,c){for(var d=0,e=b.length;d<e;d++)c(b[d])},i:function(b,c){if(typeof b.indexOf=="function")return b.indexOf(c);for(var d=0,e=b.length;d<e;d++)if(b[d]==c)return d;return-1},xa:function(b,c,d){for(var e=0,g=b.length;e<g;e++)if(c.call(d,b[e]))return b[e];return o},Z:function(b,c){var d=r.a.i(b,c);d>=0&&b.splice(d,1)},Y:function(b){b=b||[];for(var c=[],d=0,e=b.length;d<
-e;d++)r.a.i(c,b[d])<0&&c.push(b[d]);return c},K:function(b,c){b=b||[];for(var d=[],e=0,g=b.length;e<g;e++)d.push(c(b[e]));return d},J:function(b,c){b=b||[];for(var d=[],e=0,g=b.length;e<g;e++)c(b[e])&&d.push(b[e]);return d},L:function(b,c){for(var d=0,e=c.length;d<e;d++)b.push(c[d])},aa:function(b){for(;b.firstChild;){r.a.e.N(b.firstChild);b.removeChild(b.firstChild)}},Ua:function(b,c){r.a.aa(b);c&&r.a.h(c,function(d){b.appendChild(d)})},ka:function(b,c){var d=b.nodeType?[b]:b;if(d.length>0){for(var e=
-d[0],g=e.parentNode,h=0,i=c.length;h<i;h++)g.insertBefore(c[h],e);h=0;for(i=d.length;h<i;h++){r.a.e.N(d[h]);g.removeChild(d[h])}}},na:function(b,c){if(navigator.userAgent.indexOf("MSIE 6")>=0)b.setAttribute("selected",c);else b.selected=c},Ia:function(b,c){if(!b||b.nodeType!=1)return[];var d=[];b.getAttribute(c)!==o&&d.push(b);for(var e=b.getElementsByTagName("*"),g=0,h=e.length;g<h;g++)e[g].getAttribute(c)!==o&&d.push(e[g]);return d},l:function(b){return(b||"").replace(f,"")},$a:function(b,c){for(var d=
-[],e=(b||"").split(c),g=0,h=e.length;g<h;g++){var i=r.a.l(e[g]);i!==""&&d.push(i)}return d},Va:function(b,c){b=b||"";if(c.length>b.length)return p;return b.substring(0,c.length)===c},Ga:function(b,c){if(c===undefined)return(new Function("return "+b))();with(c)return eval("("+b+")")},Ea:function(b,c){if(c.compareDocumentPosition)return(c.compareDocumentPosition(b)&16)==16;for(;b!=o;){if(b==c)return m;b=b.parentNode}return p},A:function(b){return r.a.Ea(b,document)},q:function(b,c,d){if(typeof jQuery!=
-"undefined")jQuery(b).bind(c,d);else if(typeof b.addEventListener=="function")b.addEventListener(c,d,p);else if(typeof b.attachEvent!="undefined")b.attachEvent("on"+c,function(e){d.call(b,e)});else a(Error("Browser doesn't support addEventListener or attachEvent"))},qa:function(b,c){if(!(b&&b.nodeType))a(Error("element must be a DOM node when calling triggerEvent"));if(typeof document.createEvent=="function")if(typeof b.dispatchEvent=="function"){var d=document.createEvent(c=="click"?"MouseEvents":
-"HTMLEvents");d.initEvent(c,m,m,window,0,0,0,0,0,p,p,p,p,0,b);b.dispatchEvent(d)}else a(Error("The supplied element doesn't support dispatchEvent"));else if(typeof b.fireEvent!="undefined"){if(c=="click")if(b.tagName=="INPUT"&&(b.type.toLowerCase()=="checkbox"||b.type.toLowerCase()=="radio"))b.checked=b.checked!==m;b.fireEvent("on"+c)}else a(Error("Browser doesn't support triggering events"))},d:function(b){return r.C(b)?b():b},Da:function(b,c){return r.a.i((b.className||"").split(/\s+/),c)>=0},Xa:function(b,
-c,d){var e=r.a.Da(b,c);if(d&&!e)b.className=(b.className||"")+" "+c;else if(e&&!d){d=(b.className||"").split(/\s+/);e="";for(var g=0;g<d.length;g++)if(d[g]!=c)e+=d[g]+" ";b.className=r.a.l(e)}},Ra:function(b,c){b=r.a.d(b);c=r.a.d(c);for(var d=[],e=b;e<=c;e++)d.push(e);return d},ga:function(b){for(var c=[],d=b.length-1;d>=0;d--)c.push(b[d]);return c},P:/MSIE 6/i.test(navigator.userAgent),La:/MSIE 7/i.test(navigator.userAgent),da:function(b,c){for(var d=r.a.ga(b.getElementsByTagName("INPUT")).concat(r.a.ga(b.getElementsByTagName("TEXTAREA"))),
-e=typeof c=="string"?function(i){return i.name===c}:function(i){return c.test(i.name)},g=[],h=d.length-1;h>=0;h--)e(d[h])&&g.push(d[h]);return g},F:function(b){if(typeof b=="string")if(b=r.a.l(b)){if(window.JSON&&window.JSON.parse)return window.JSON.parse(b);return(new Function("return "+b))()}return o},T:function(b){if(typeof JSON=="undefined"||typeof JSON.stringify=="undefined")a(Error("Cannot find JSON.stringify(). Some browsers (e.g., IE < 8) don't support it natively, but you can overcome this by adding a script reference to json2.js, downloadable from http://www.json.org/json2.js"));
-return JSON.stringify(r.a.d(b))},Qa:function(b,c,d){d=d||{};var e=d.params||{},g=d.includeFields||this.ba,h=b;if(typeof b=="object"&&b.tagName=="FORM"){h=b.action;for(var i=g.length-1;i>=0;i--)for(var j=r.a.da(b,g[i]),l=j.length-1;l>=0;l--)e[j[l].name]=j[l].value}c=r.a.d(c);var k=document.createElement("FORM");k.style.display="none";k.action=h;k.method="post";for(var n in c){b=document.createElement("INPUT");b.name=n;b.value=r.a.T(r.a.d(c[n]));k.appendChild(b)}for(n in e){b=document.createElement("INPUT");
-b.name=n;b.value=e[n];k.appendChild(b)}document.body.appendChild(k);d.submitter?d.submitter(k):k.submit();setTimeout(function(){k.parentNode.removeChild(k)},0)},e:{Ya:0,w:"__ko__"+(new Date).getTime(),Za:{},t:function(b,c){var d=r.a.e.ca(b,p);return d===undefined?undefined:d[c]},la:function(b,c,d){r.a.e.ca(b,m)[c]=d},ca:function(b,c){var d=b[r.a.e.w];if(!d){if(!c)return;d=b[r.a.e.w]="ko"+r.a.e.Ya++;r.a.e[d]={}}return r.a.e[d]},M:function(b){var c=b[r.a.e.w];if(c){delete r.a.e[c];b[r.a.e.w]=o}},N:function(b){if(!(b.nodeType!=
-1&&b.nodeType!=9)){r.a.e.M(b);b=b.getElementsByTagName("*");for(var c=0,d=b.length;c<d;c++)r.a.e.M(b[c])}}}}};r.b("ko.utils",r.a);r.b("ko.utils.arrayForEach",r.a.h);r.b("ko.utils.arrayFirst",r.a.xa);r.b("ko.utils.arrayFilter",r.a.J);r.b("ko.utils.arrayGetDistinctValues",r.a.Y);r.b("ko.utils.arrayIndexOf",r.a.i);r.b("ko.utils.arrayMap",r.a.K);r.b("ko.utils.arrayPushAll",r.a.L);r.b("ko.utils.arrayRemoveItem",r.a.Z);r.b("ko.utils.fieldsIncludedWithJsonPost",r.a.ba);r.b("ko.utils.getFormFields",r.a.da);
-r.b("ko.utils.postJson",r.a.Qa);r.b("ko.utils.parseJson",r.a.F);r.b("ko.utils.stringifyJson",r.a.T);r.b("ko.utils.range",r.a.Ra);r.b("ko.utils.triggerEvent",r.a.qa);r.b("ko.utils.unwrapObservable",r.a.d);Function.prototype.bind||(Function.prototype.bind=function(f){var b=this,c=Array.prototype.slice.call(arguments);f=c.shift();return function(){return b.apply(f,c.concat(Array.prototype.slice.call(arguments)))}});
-r.j=function(){function f(){return((1+Math.random())*4294967296|0).toString(16).substring(1)}function b(d,e){if(d)if(d.nodeType==8){var g=r.j.ia(d.nodeValue);g!=o&&e.push({Ca:d,Na:g})}else if(d.nodeType==1){g=0;for(var h=d.childNodes,i=h.length;g<i;g++)b(h[g],e)}}var c={};return{R:function(d){if(typeof d!="function")a(Error("You can only pass a function to ko.memoization.memoize()"));var e=f()+f();c[e]=d;return"<!--[ko_memo:"+e+"]--\>"},ra:function(d,e){var g=c[d];if(g===undefined)a(Error("Couldn't find any memo with ID "+
-d+". Perhaps it's already been unmemoized."));try{g.apply(o,e||[]);return m}finally{delete c[d]}},sa:function(d,e){var g=[];b(d,g);for(var h=0,i=g.length;h<i;h++){var j=g[h].Ca,l=[j];e&&r.a.L(l,e);r.j.ra(g[h].Na,l);j.nodeValue="";j.parentNode&&j.parentNode.removeChild(j)}},ia:function(d){return(d=d.match(/^\[ko_memo\:(.*?)\]$/))?d[1]:o}}}();r.b("ko.memoization",r.j);r.b("ko.memoization.memoize",r.j.R);r.b("ko.memoization.unmemoize",r.j.ra);r.b("ko.memoization.parseMemoText",r.j.ia);
-r.b("ko.memoization.unmemoizeDomNodeAndDescendants",r.j.sa);r.Wa=function(f,b){this.za=f;this.s=b;r.g(this,"dispose",this.s)};r.U=function(){var f=[];this.V=function(b,c){var d=new r.Wa(c?function(){b.call(c)}:b,function(){r.a.Z(f,d)});f.push(d);return d};this.v=function(b){r.a.h(f.slice(0),function(c){c&&c.za(b)})};this.Ja=function(){return f.length};r.g(this,"subscribe",this.V);r.g(this,"notifySubscribers",this.v);r.g(this,"getSubscriptionsCount",this.Ja)};
-r.fa=function(f){return typeof f.V=="function"&&typeof f.v=="function"};r.b("ko.subscribable",r.U);r.b("ko.isSubscribable",r.fa);r.z=function(){var f=[];return{ya:function(){f.push([])},end:function(){return f.pop()},ja:function(b){if(!r.fa(b))a("Only subscribable things can act as dependencies");f.length>0&&f[f.length-1].push(b)}}}();
-r.p=function(f){function b(){if(arguments.length>0){c=arguments[0];b.v(c);return this}else{r.z.ja(b);return c}}var c=f;b.n=r.p;b.H=function(){b.v(c)};r.U.call(b);r.g(b,"valueHasMutated",b.H);return b};r.C=function(f){if(f===o||f===undefined||f.n===undefined)return p;if(f.n===r.p)return m;return r.C(f.n)};r.D=function(f){if(typeof f=="function"&&f.n===r.p)return m;if(typeof f=="function"&&f.n===r.m&&f.Ka)return m;return p};r.b("ko.observable",r.p);r.b("ko.isObservable",r.C);
-r.b("ko.isWriteableObservable",r.D);
-r.Pa=function(f){var b=new r.p(f);r.a.h(["pop","push","reverse","shift","sort","splice","unshift"],function(c){b[c]=function(){var d=b();d=d[c].apply(d,arguments);b.H();return d}});r.a.h(["slice"],function(c){b[c]=function(){var d=b();return d[c].apply(d,arguments)}});b.remove=function(c){for(var d=b(),e=[],g=[],h=typeof c=="function"?c:function(k){return k===c},i=0,j=d.length;i<j;i++){var l=d[i];h(l)?g.push(l):e.push(l)}b(e);return g};b.Sa=function(c){if(!c)return[];return b.remove(function(d){return r.a.i(c,
-d)>=0})};b.$=function(c){for(var d=b(),e=typeof c=="function"?c:function(h){return h===c},g=d.length-1;g>=0;g--)if(e(d[g]))d[g]._destroy=m;b.H()};b.Ba=function(c){if(!c)return[];return b.$(function(d){return r.a.i(c,d)>=0})};b.indexOf=function(c){var d=b();return r.a.i(d,c)};b.replace=function(c,d){var e=b.indexOf(c);if(e>=0){b()[e]=d;b.H()}};r.g(b,"remove",b.remove);r.g(b,"removeAll",b.Sa);r.g(b,"destroy",b.$);r.g(b,"destroyAll",b.Ba);r.g(b,"indexOf",b.indexOf);return b};
-r.b("ko.observableArray",r.Pa);
-r.m=function(f,b,c){function d(){r.a.h(i,function(k){k.s()});i=[]}function e(k){d();r.a.h(k,function(n){i.push(n.V(g))})}function g(){if(l&&typeof c.disposeWhen=="function")if(c.disposeWhen()){h.s();return}try{r.z.ya();j=c.owner?c.read.call(c.owner):c.read()}finally{var k=r.a.Y(r.z.end());e(k)}h.v(j);l=m}function h(){if(arguments.length>0)if(typeof c.write==="function"){var k=arguments[0];c.owner?c.write.call(c.owner,k):c.write(k)}else a("Cannot write a value to a dependentObservable unless you specify a 'write' option. If you wish to read the current value, don't pass any parameters.");else{l||
-g();r.z.ja(h);return j}}if(f&&typeof f=="object")c=f;else{c=c||{};c.read=f||c.read;c.owner=b||c.owner}if(typeof c.read!="function")a("Pass a function that returns the value of the dependentObservable");var i=[],j,l=p;h.n=r.m;h.Ha=function(){return i.length};h.Ka=typeof c.write==="function";h.s=function(){d()};r.U.call(h);c.deferEvaluation!==m&&g();r.g(h,"dispose",h.s);r.g(h,"getDependenciesCount",h.Ha);return h};r.m.n=r.p;r.b("ko.dependentObservable",r.m);
-(function(){function f(d,e,g){g=g||new c;d=e(d);if(!(typeof d=="object"&&d!==o&&d!==undefined))return d;var h=d instanceof Array?[]:{};g.save(d,h);b(d,function(i){var j=e(d[i]);switch(typeof j){case "boolean":case "number":case "string":case "function":h[i]=j;break;case "object":case "undefined":var l=g.t(j);h[i]=l!==undefined?l:f(j,e,g)}});return h}function b(d,e){if(d instanceof Array)for(var g=0;g<d.length;g++)e(g);else for(g in d)e(g)}function c(){var d=[],e=[];this.save=function(g,h){var i=r.a.i(d,
-g);if(i>=0)e[i]=h;else{d.push(g);e.push(h)}};this.t=function(g){g=r.a.i(d,g);return g>=0?e[g]:undefined}}r.pa=function(d){if(arguments.length==0)a(Error("When calling ko.toJS, pass the object you want to convert."));return f(d,function(e){for(var g=0;r.C(e)&&g<10;g++)e=e();return e})};r.toJSON=function(d){d=r.pa(d);return r.a.T(d)}})();r.b("ko.toJS",r.pa);r.b("ko.toJSON",r.toJSON);
-r.f={k:function(f){if(f.tagName=="OPTION"){if(f.__ko__hasDomDataOptionValue__===m)return r.a.e.t(f,r.c.options.ha);return f.getAttribute("value")}else return f.tagName=="SELECT"?f.selectedIndex>=0?r.f.k(f.options[f.selectedIndex]):undefined:f.value},I:function(f,b){if(f.tagName=="OPTION")switch(typeof b){case "string":case "number":r.a.e.M(f);"__ko__hasDomDataOptionValue__"in f&&delete f.__ko__hasDomDataOptionValue__;f.value=b;break;default:r.a.e.la(f,r.c.options.ha,b);f.__ko__hasDomDataOptionValue__=
-m;f.value=""}else if(f.tagName=="SELECT")for(var c=f.options.length-1;c>=0;c--){if(r.f.k(f.options[c])==b){f.selectedIndex=c;break}}else{if(b===o||b===undefined)b="";f.value=b}}};r.b("ko.selectExtensions",r.f);r.b("ko.selectExtensions.readValue",r.f.k);r.b("ko.selectExtensions.writeValue",r.f.I);
-r.o=function(){function f(e,g){return e.replace(b,function(h,i){return g[i]})}var b=/\[ko_token_(\d+)\]/g,c=/^[\_$a-z][\_$a-z0-9]*(\[.*?\])*(\.[\_$a-z][\_$a-z0-9]*(\[.*?\])*)*$/i,d=["true","false"];return{F:function(e){e=r.a.l(e);if(e.length<3)return{};for(var g=[],h=o,i,j=e.charAt(0)=="{"?1:0;j<e.length;j++){var l=e.charAt(j);if(h===o)switch(l){case '"':case "'":case "/":h=j;i=l;break;case "{":h=j;i="}";break;case "[":h=j;i="]"}else if(l==i){l=e.substring(h,j+1);g.push(l);var k="[ko_token_"+(g.length-
-1)+"]";e=e.substring(0,h)+k+e.substring(j+1);j-=l.length-k.length;h=o}}h={};e=e.split(",");i=0;for(j=e.length;i<j;i++){k=e[i];var n=k.indexOf(":");if(n>0&&n<k.length-1){l=r.a.l(k.substring(0,n));k=r.a.l(k.substring(n+1));if(l.charAt(0)=="{")l=l.substring(1);if(k.charAt(k.length-1)=="}")k=k.substring(0,k.length-1);l=r.a.l(f(l,g));k=r.a.l(f(k,g));h[l]=k}}return h},O:function(e){var g=r.o.F(e),h=[],i;for(i in g){var j=g[i],l;l=j;l=r.a.i(d,r.a.l(l).toLowerCase())>=0?p:l.match(c)!==o;if(l){h.length>0&&
-h.push(", ");h.push(i+" : function(__ko_value) { "+j+" = __ko_value; }")}}if(h.length>0)e=e+", '_ko_property_writers' : { "+h.join("")+" } ";return e}}}();r.b("ko.jsonExpressionRewriting",r.o);r.b("ko.jsonExpressionRewriting.parseJson",r.o.F);r.b("ko.jsonExpressionRewriting.insertPropertyAccessorsIntoJson",r.o.O);r.c={};
-r.X=function(f,b,c){function d(i){return function(){return h[i]}}function e(){return h}var g=m,h;new r.m(function(){var i;if(!(i=typeof b=="function"?b():b)){var j=f.getAttribute("data-bind");try{var l=" { "+r.o.O(j)+" } ";i=r.a.Ga(l,c===o?window:c)}catch(k){a(Error("Unable to parse binding attribute.\nMessage: "+k+";\nAttribute value: "+j))}}h=i;if(g)for(var n in h)r.c[n]&&typeof r.c[n].init=="function"&&(0,r.c[n].init)(f,d(n),e,c);for(n in h)r.c[n]&&typeof r.c[n].update=="function"&&(0,r.c[n].update)(f,
-d(n),e,c)},o,{disposeWhen:function(){return!r.a.A(f)}});g=p};r.ua=function(f,b){if(b&&b.nodeType==undefined)a(Error("ko.applyBindings: first parameter should be your view model; second parameter should be a DOM node (note: this is a breaking change since KO version 1.05)"));b=b||window.document.body;var c=r.a.Ia(b,"data-bind");r.a.h(c,function(d){r.X(d,o,f)})};r.b("ko.bindingHandlers",r.c);r.b("ko.applyBindings",r.ua);
-r.c.click={init:function(f,b,c,d){r.a.q(f,"click",function(e){var g,h=b();try{g=h.call(d)}finally{if(g!==m)if(e.preventDefault)e.preventDefault();else e.returnValue=p}})}};r.c.submit={init:function(f,b,c,d){if(typeof b()!="function")a(Error("The value for a submit binding must be a function to invoke on submit"));r.a.q(f,"submit",function(e){var g,h=b();try{g=h.call(d,f)}finally{if(g!==m)if(e.preventDefault)e.preventDefault();else e.returnValue=p}})}};
-r.c.visible={update:function(f,b){var c=r.a.d(b()),d=f.style.display!="none";if(c&&!d)f.style.display="";else if(!c&&d)f.style.display="none"}};r.c.enable={update:function(f,b){var c=r.a.d(b());if(c&&f.disabled)f.removeAttribute("disabled");else if(!c&&!f.disabled)f.disabled=m}};r.c.disable={update:function(f,b){r.c.enable.update(f,function(){return!r.a.d(b())})}};
-r.c.value={init:function(f,b,c){var d=c().valueUpdate||"change",e=p;if(r.a.Va(d,"after")){e=m;d=d.substring(5)}var g=e?function(h){setTimeout(h,0)}:function(h){h()};r.a.q(f,d,function(){g(function(){var h=b(),i=r.f.k(f);if(r.D(h))h(i);else{h=c();h._ko_property_writers&&h._ko_property_writers.value&&h._ko_property_writers.value(i)}})})},update:function(f,b){var c=r.a.d(b()),d=r.f.k(f),e=c!=d;if(c===0&&d!==0&&d!=="0")e=m;if(e){d=function(){r.f.I(f,c)};d();f.tagName=="SELECT"&&setTimeout(d,0)}if(f.tagName==
-"SELECT"){d=r.f.k(f);d!==c&&r.a.qa(f,"change")}}};
-r.c.options={update:function(f,b,c){if(f.tagName!="SELECT")a(Error("options binding applies only to SELECT elements"));var d=r.a.K(r.a.J(f.childNodes,function(k){return k.tagName&&k.tagName=="OPTION"&&k.selected}),function(k){return r.f.k(k)||k.innerText||k.textContent}),e=f.scrollTop,g=r.a.d(b());r.a.aa(f);if(g){var h=c();if(typeof g.length!="number")g=[g];if(h.optionsCaption){var i=document.createElement("OPTION");i.innerHTML=h.optionsCaption;r.f.I(i,undefined);f.appendChild(i)}c=0;for(b=g.length;c<
-b;c++){i=document.createElement("OPTION");var j=typeof h.optionsValue=="string"?g[c][h.optionsValue]:g[c],l=typeof h.optionsText=="string"?g[c][h.optionsText]:j;j=r.a.d(j);l=r.a.d(l);r.f.I(i,j);i.innerHTML=l.toString();f.appendChild(i)}g=f.getElementsByTagName("OPTION");c=h=0;for(b=g.length;c<b;c++)if(r.a.i(d,r.f.k(g[c]))>=0){r.a.na(g[c],m);h++}if(e)f.scrollTop=e}}};r.c.options.ha="__ko.bindingHandlers.options.optionValueDomData__";
-r.c.selectedOptions={ea:function(f){var b=[];f=f.childNodes;for(var c=0,d=f.length;c<d;c++){var e=f[c];e.tagName=="OPTION"&&e.selected&&b.push(r.f.k(e))}return b},init:function(f,b,c){r.a.q(f,"change",function(){var d=b();if(r.D(d))d(r.c.selectedOptions.ea(this));else{d=c();d._ko_property_writers&&d._ko_property_writers.value&&d._ko_property_writers.value(r.c.selectedOptions.ea(this))}})},update:function(f,b){if(f.tagName!="SELECT")a(Error("values binding applies only to SELECT elements"));var c=
-r.a.d(b());if(c&&typeof c.length=="number")for(var d=f.childNodes,e=0,g=d.length;e<g;e++){var h=d[e];h.tagName=="OPTION"&&r.a.na(h,r.a.i(c,r.f.k(h))>=0)}}};r.c.text={update:function(f,b){var c=r.a.d(b());if(c===o||c===undefined)c="";typeof f.innerText=="string"?f.innerText=c:f.textContent=c}};r.c.css={update:function(f,b){var c=r.a.d(b()||{}),d;for(d in c)if(typeof d=="string"){var e=r.a.d(c[d]);r.a.Xa(f,d,e)}}};
-r.c.style={update:function(f,b){var c=r.a.d(b()||{}),d;for(d in c)if(typeof d=="string"){var e=r.a.d(c[d]);f.style[d]=e||""}}};r.c.uniqueName={init:function(f,b){if(b()){f.name="ko_unique_"+ ++r.c.uniqueName.Aa;r.a.P&&f.mergeAttributes(document.createElement("<INPUT name='"+f.name+"'/>"),p)}}};r.c.uniqueName.Aa=0;
-r.c.checked={init:function(f,b,c){function d(){var e;if(f.type=="checkbox")e=f.checked;else if(f.type=="radio"&&f.checked)e=f.value;else return;var g=b();if(r.D(g))g()!==e&&g(e);else{g=c();g._ko_property_writers&&g._ko_property_writers.checked&&g._ko_property_writers.checked(e)}}r.a.q(f,"change",d);r.a.q(f,"click",d);f.type=="radio"&&!f.name&&r.c.uniqueName.init(f,function(){return m})},update:function(f,b){var c=r.a.d(b());if(f.type=="checkbox")(f.checked=c)&&r.a.P&&f.mergeAttributes(document.createElement("<INPUT type='checkbox' checked='checked' />"),
-p);else if(f.type=="radio"){f.checked=f.value==c;if(f.value==c&&(r.a.P||r.a.La))f.mergeAttributes(document.createElement("<INPUT type='radio' checked='checked' />"),p)}}};
-r.W=function(){this.renderTemplate=function(){a("Override renderTemplate in your ko.templateEngine subclass")};this.isTemplateRewritten=function(){a("Override isTemplateRewritten in your ko.templateEngine subclass")};this.rewriteTemplate=function(){a("Override rewriteTemplate in your ko.templateEngine subclass")};this.createJavaScriptEvaluatorBlock=function(){a("Override createJavaScriptEvaluatorBlock in your ko.templateEngine subclass")}};r.b("ko.templateEngine",r.W);
-r.G=function(){var f=/(<[a-z]+\d*(\s+(?!data-bind=)[a-z0-9]+(=(\"[^\"]*\"|\'[^\']*\'))?)*\s+)data-bind=(["'])([\s\S]*?)\5/g;return{Fa:function(b,c){c.isTemplateRewritten(b)||c.rewriteTemplate(b,function(d){return r.G.Oa(d,c)})},Oa:function(b,c){return b.replace(f,function(d,e,g,h,i,j,l){d=l;d=r.o.O(d);return c.createJavaScriptEvaluatorBlock("ko.templateRewriting.applyMemoizedBindingsToNextSibling(function() { return (function() { return { "+d+" } })() })")+e})},
-va:function(b){return r.j.R(function(c,d){c.nextSibling&&r.X(c.nextSibling,b,d)})}}}();r.b("ko.templateRewriting",r.G);r.b("ko.templateRewriting.applyMemoizedBindingsToNextSibling",r.G.va);
-(function(){function f(c,d,e,g,h){var i=r.a.d(g);h=h||{};var j=h.templateEngine||b;r.G.Fa(e,j);e=j.renderTemplate(e,i,h);if(typeof e.length!="number"||e.length>0&&typeof e[0].nodeType!="number")a("Template engine must return an array of DOM nodes");e&&r.a.h(e,function(l){r.j.sa(l,[g])});switch(d){case "replaceChildren":r.a.Ua(c,e);break;case "replaceNode":r.a.ka(c,e);break;case "ignoreTargetNode":break;default:a(Error("Unknown renderMode: "+d))}h.afterRender&&h.afterRender(e,g);return e}var b;r.oa=
-function(c){if(c!=undefined&&!(c instanceof r.W))a("templateEngine must inherit from ko.templateEngine");b=c};r.S=function(c,d,e,g,h){e=e||{};if((e.templateEngine||b)==undefined)a("Set a template engine before calling renderTemplate");h=h||"replaceChildren";if(g){var i=g.nodeType?g:g.length>0?g[0]:o;return new r.m(function(){var j=f(g,h,c,d,e);if(h=="replaceNode"){g=j;i=g.nodeType?g:g.length>0?g[0]:o}},o,{disposeWhen:function(){return!i||!r.a.A(i)}})}else return r.j.R(function(j){r.S(c,d,e,j,"replaceNode")})};
-r.Ta=function(c,d,e,g){new r.m(function(){var h=r.a.d(d)||[];if(typeof h.length=="undefined")h=[h];h=r.a.J(h,function(i){return e.includeDestroyed||!i._destroy});r.a.ma(g,h,function(i){return f(o,"ignoreTargetNode",c,i,e)},e)},o,{disposeWhen:function(){return!r.a.A(g)}})};r.c.template={update:function(c,d,e,g){d=r.a.d(d());e=typeof d=="string"?d:d.name;if(typeof d.foreach!="undefined")r.Ta(e,d.foreach||[],{afterAdd:d.afterAdd,beforeRemove:d.beforeRemove,includeDestroyed:d.includeDestroyed,afterRender:d.afterRender},
-c);else{var h=d.data;r.S(e,typeof h=="undefined"?g:h,{afterRender:d.afterRender},c)}}}})();r.b("ko.setTemplateEngine",r.oa);r.b("ko.renderTemplate",r.S);
-r.a.r=function(f,b,c){if(c===undefined)return r.a.r(f,b,1)||r.a.r(f,b,10)||r.a.r(f,b,Number.MAX_VALUE);else{f=f||[];b=b||[];for(var d=f,e=b,g=[],h=0;h<=e.length;h++)g[h]=[];h=0;for(var i=Math.min(d.length,c);h<=i;h++)g[0][h]=h;h=1;for(i=Math.min(e.length,c);h<=i;h++)g[h][0]=h;i=d.length;var j,l=e.length;for(h=1;h<=i;h++){var k=Math.min(l,h+c);for(j=Math.max(1,h-c);j<=k;j++)g[j][h]=d[h-1]===e[j-1]?g[j-1][h-1]:Math.min(g[j-1][h]===undefined?Number.MAX_VALUE:g[j-1][h]+1,g[j][h-1]===undefined?Number.MAX_VALUE:
-g[j][h-1]+1)}f=f;b=b;c=f.length;d=b.length;e=[];h=g[d][c];if(h===undefined)g=o;else{for(;c>0||d>0;){i=g[d][c];j=d>0?g[d-1][c]:h+1;l=c>0?g[d][c-1]:h+1;k=d>0&&c>0?g[d-1][c-1]:h+1;if(j===undefined||j<i-1)j=h+1;if(l===undefined||l<i-1)l=h+1;if(k<i-1)k=h+1;if(j<=l&&j<k){e.push({status:"added",value:b[d-1]});d--}else{if(l<j&&l<k)e.push({status:"deleted",value:f[c-1]});else{e.push({status:"retained",value:f[c-1]});d--}c--}}g=e.reverse()}return g}};r.b("ko.utils.compareArrays",r.a.r);
-(function(){function f(b,c){var d=[];r.m(function(){var e=b(c)||[];d.length>0&&r.a.ka(d,e);d.splice(0,d.length);r.a.L(d,e)},o,{disposeWhen:function(){return d.length==0||!r.a.A(d[0])}});return d}r.a.ma=function(b,c,d,e){c=c||[];e=e||{};var g=r.a.e.t(b,"setDomNodeChildrenFromArrayMapping_lastMappingResult")===undefined,h=r.a.e.t(b,"setDomNodeChildrenFromArrayMapping_lastMappingResult")||[],i=r.a.K(h,function(s){return s.wa}),j=r.a.r(i,c);c=[];var l=0,k=[];i=[];for(var n=o,q=0,w=j.length;q<w;q++)switch(j[q].status){case "retained":var t=
-h[l];c.push(t);if(t.B.length>0)n=t.B[t.B.length-1];l++;break;case "deleted":r.a.h(h[l].B,function(s){k.push({element:s,index:q,value:j[q].value});n=s});l++;break;case "added":t=f(d,j[q].value);c.push({wa:j[q].value,B:t});for(var v=0,x=t.length;v<x;v++){var u=t[v];i.push({element:u,index:q,value:j[q].value});if(n==o)b.firstChild?b.insertBefore(u,b.firstChild):b.appendChild(u);else n.nextSibling?b.insertBefore(u,n.nextSibling):b.appendChild(u);n=u}}r.a.h(k,function(s){r.a.e.N(s.element)});d=p;if(!g){if(e.afterAdd)for(q=
-0;q<i.length;q++)e.afterAdd(i[q].element,i[q].index,i[q].value);if(e.beforeRemove){for(q=0;q<k.length;q++)e.beforeRemove(k[q].element,k[q].index,k[q].value);d=m}}d||r.a.h(k,function(s){s.element.parentNode&&s.element.parentNode.removeChild(s.element)});r.a.e.la(b,"setDomNodeChildrenFromArrayMapping_lastMappingResult",c)}})();r.b("ko.utils.setDomNodeChildrenFromArrayMapping",r.a.ma);
-r.Q=function(){function f(c){var d=document.getElementById(c);if(d==o)a(Error("Cannot find template with ID="+c));return d}this.u=function(){if(typeof jQuery=="undefined"||!jQuery.tmpl)return 0;if(jQuery.tmpl.tag)return 2;return 1}();var b=RegExp("__ko_apos__","g");this.renderTemplate=function(c,d){if(this.u==0)a(Error("jquery.tmpl not detected.\nTo use KO's default template engine, reference jQuery and jquery.tmpl. See Knockout installation documentation for more details."));if(this.u==1){var e=
-'<script type="text/html">'+f(c).text+"<\/script>";e=jQuery.tmpl(e,d)[0].text.replace(b,"'");return jQuery.clean([e],document)}d=[d];e=f(c).text;return jQuery.tmpl(e,d)};this.isTemplateRewritten=function(c){return f(c).Ma===m};this.rewriteTemplate=function(c,d){var e=f(c),g=d(e.text);if(this.u==1){g=r.a.l(g);g=g.replace(/([\s\S]*?)(\${[\s\S]*?}|{{[\=a-z][\s\S]*?}}|$)/g,function(h,i,j){return i.replace(/\'/g,"__ko_apos__")+j})}e.text=g;e.Ma=m};this.createJavaScriptEvaluatorBlock=function(c){if(this.u==
-1)return"{{= "+c+"}}";return"{{ko_code ((function() { return "+c+" })()) }}"};this.ta=function(c,d){document.write("<script type='text/html' id='"+c+"'>"+d+"<\/script>")};r.g(this,"addTemplate",this.ta);if(this.u>1)jQuery.tmpl.tag.ko_code={open:"_.push($1 || '');"}};r.Q.prototype=new r.W;r.oa(new r.Q);r.b("ko.jqueryTmplTemplateEngine",r.Q);
+var ko = window.ko = {};
+/// <reference path="namespace.js" />
+
+ko.utils = new (function () {
+ var stringTrimRegex = /^(\s|\u00A0)+|(\s|\u00A0)+$/g;
+
+ return {
+ arrayForEach: function (array, action) {
+ for (var i = 0, j = array.length; i < j; i++)
+ action(array[i]);
+ },
+
+ arrayIndexOf: function (array, item) {
+ if (typeof array.indexOf == "function")
+ return array.indexOf(item);
+ for (var i = 0, j = array.length; i < j; i++)
+ if (array[i] == item)
+ return i;
+ return -1;
+ },
+
+ arrayFirst: function (array, predicate, predicateOwner) {
+ for (var i = 0, j = array.length; i < j; i++)
+ if (predicate.call(predicateOwner, array[i]))
+ return array[i];
+ return null;
+ },
+
+ arrayRemoveItem: function (array, itemToRemove) {
+ var index = ko.utils.arrayIndexOf(array, itemToRemove);
+ if (index >= 0)
+ array.splice(index, 1);
+ },
+
+ arrayGetDistinctValues: function (array) {
+ array = array || [];
+ var result = [];
+ for (var i = 0, j = array.length; i < j; i++) {
+ if (ko.utils.arrayIndexOf(result, array[i]) < 0)
+ result.push(array[i]);
+ }
+ return result;
+ },
+
+ arrayMap: function (array, mapping) {
+ array = array || [];
+ var result = [];
+ for (var i = 0, j = array.length; i < j; i++)
+ result.push(mapping(array[i]));
+ return result;
+ },
+
+ arrayFilter: function (array, predicate) {
+ array = array || [];
+ var result = [];
+ for (var i = 0, j = array.length; i < j; i++)
+ if (predicate(array[i]))
+ result.push(array[i]);
+ return result;
+ },
+
+ setDomNodeChildren: function (domNode, childNodes) {
+ while (domNode.firstChild) {
+ ko.utils.domData.cleanNodeAndDescendants(domNode.firstChild);
+ domNode.removeChild(domNode.firstChild);
+ }
+ if (childNodes) {
+ ko.utils.arrayForEach(childNodes, function (childNode) {
+ domNode.appendChild(childNode);
+ });
+ }
+ },
+
+ replaceDomNodes: function (nodeToReplaceOrNodeArray, newNodesArray) {
+ var nodesToReplaceArray = nodeToReplaceOrNodeArray.nodeType ? [nodeToReplaceOrNodeArray] : nodeToReplaceOrNodeArray;
+ if (nodesToReplaceArray.length > 0) {
+ var insertionPoint = nodesToReplaceArray[0];
+ var parent = insertionPoint.parentNode;
+ for (var i = 0, j = newNodesArray.length; i < j; i++)
+ parent.insertBefore(newNodesArray[i], insertionPoint);
+ for (var i = 0, j = nodesToReplaceArray.length; i < j; i++) {
+ ko.utils.domData.cleanNodeAndDescendants(nodesToReplaceArray[i]);
+ parent.removeChild(nodesToReplaceArray[i]);
+ }
+ }
+ },
+
+ getElementsHavingAttribute: function (rootNode, attributeName) {
+ if ((!rootNode) || (rootNode.nodeType != 1)) return [];
+ var results = [];
+ if (rootNode.getAttribute(attributeName) !== null)
+ results.push(rootNode);
+ var descendants = rootNode.getElementsByTagName("*");
+ for (var i = 0, j = descendants.length; i < j; i++)
+ if (descendants[i].getAttribute(attributeName) !== null)
+ results.push(descendants[i]);
+ return results;
+ },
+
+ stringTrim: function (string) {
+ return (string || "").replace(stringTrimRegex, "");
+ },
+
+ stringTokenize: function (string, delimiter) {
+ var result = [];
+ var tokens = (string || "").split(delimiter);
+ for (var i = 0, j = tokens.length; i < j; i++) {
+ var trimmed = ko.utils.stringTrim(tokens[i]);
+ if (trimmed !== "")
+ result.push(trimmed);
+ }
+ return result;
+ },
+
+ evalWithinScope: function (expression, scope) {
+ if (scope === undefined)
+ return (new Function("return " + expression))();
+ with (scope) { return eval("(" + expression + ")"); }
+ },
+
+ domNodeIsContainedBy: function (node, containedByNode) {
+ if (containedByNode.compareDocumentPosition)
+ return (containedByNode.compareDocumentPosition(node) & 16) == 16;
+ while (node != null) {
+ if (node == containedByNode)
+ return true;
+ node = node.parentNode;
+ }
+ return false;
+ },
+
+ domNodeIsAttachedToDocument: function (node) {
+ return ko.utils.domNodeIsContainedBy(node, document);
+ },
+
+ registerEventHandler: function (element, eventType, handler) {
+ if (typeof jQuery != "undefined")
+ jQuery(element).bind(eventType, handler);
+ else if (typeof element.addEventListener == "function")
+ element.addEventListener(eventType, handler, false);
+ else if (typeof element.attachEvent != "undefined")
+ element.attachEvent("on" + eventType, function (event) {
+ handler.call(element, event);
+ });
+ else
+ throw new Error("Browser doesn't support addEventListener or attachEvent");
+ },
+
+ triggerEvent: function (element, eventType) {
+ if (!(element && element.nodeType))
+ throw new Error("element must be a DOM node when calling triggerEvent");
+
+ if (typeof element.fireEvent != "undefined")
+ element.fireEvent("on" + eventType);
+ else if (typeof document.createEvent == "function") {
+ if (typeof element.dispatchEvent == "function") {
+ var eventCategory = (eventType == "click" ? "MouseEvents" : "HTMLEvents"); // Might need to account for other event names at some point
+ var event = document.createEvent(eventCategory);
+ event.initEvent(eventType, true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, element);
+ element.dispatchEvent(event);
+ }
+ else
+ throw new Error("The supplied element doesn't support dispatchEvent");
+ }
+ else
+ throw new Error("Browser doesn't support triggering events");
+ },
+
+ unwrapObservable: function (value) {
+ return ko.isObservable(value) ? value() : value;
+ },
+
+ domNodeHasCssClass: function (node, className) {
+ var currentClassNames = (node.className || "").split(/\s+/);
+ return ko.utils.arrayIndexOf(currentClassNames, className) >= 0;
+ },
+
+ toggleDomNodeCssClass: function (node, className, shouldHaveClass) {
+ var hasClass = ko.utils.domNodeHasCssClass(node, className);
+ if (shouldHaveClass && !hasClass) {
+ node.className = (node.className || "") + " " + className;
+ } else if (hasClass && !shouldHaveClass) {
+ var currentClassNames = (node.className || "").split(/\s+/);
+ var newClassName = "";
+ for (var i = 0; i < currentClassNames.length; i++)
+ if (currentClassNames[i] != className)
+ newClassName += currentClassNames[i] + " ";
+ node.className = ko.utils.stringTrim(newClassName);
+ }
+ },
+
+ range: function (min, max) {
+ min = ko.utils.unwrapObservable(min);
+ max = ko.utils.unwrapObservable(max);
+ var result = [];
+ for (var i = min; i <= max; i++)
+ result.push(i);
+ return result;
+ },
+
+ stringifyJson: function (data) {
+ if ((typeof JSON == "undefined") || (typeof JSON.stringify == "undefined"))
+ throw new Error("Cannot find JSON.stringify(). Some browsers (e.g., IE < 8) don't support it natively, but you can overcome this by adding a script reference to json2.js, downloadable from http://www.json.org/json2.js");
+ return JSON.stringify(ko.utils.unwrapObservable(data));
+ },
+
+ postJson: function (url, data) {
+ data = ko.utils.unwrapObservable(data);
+ var form = document.createElement("FORM");
+ form.style.display = "none";
+ form.action = url;
+ form.method = "post";
+ for (var key in data) {
+ var input = document.createElement("INPUT");
+ input.name = key;
+ input.value = ko.utils.stringifyJson(ko.utils.unwrapObservable(data[key]));
+ form.appendChild(input);
+ }
+ document.body.appendChild(form);
+ form.submit();
+ setTimeout(function () { form.parentNode.removeChild(form); }, 0);
+ },
+
+ domData: {
+ uniqueId: 0,
+ dataStoreKeyExpandoPropertyName: "__ko__" + (new Date).getTime(),
+ dataStore: {},
+ get: function (node, key) {
+ var allDataForNode = ko.utils.domData.getAll(node, false);
+ return allDataForNode === undefined ? undefined : allDataForNode[key];
+ },
+ set: function (node, key, value) {
+ var allDataForNode = ko.utils.domData.getAll(node, true);
+ allDataForNode[key] = value;
+ },
+ getAll: function (node, createIfNotFound) {
+ var dataStoreKey = node[ko.utils.domData.dataStoreKeyExpandoPropertyName];
+ if (!dataStoreKey) {
+ if (!createIfNotFound)
+ return undefined;
+ dataStoreKey = node[ko.utils.domData.dataStoreKeyExpandoPropertyName] = "ko" + ko.utils.domData.uniqueId++;
+ ko.utils.domData[dataStoreKey] = {};
+ }
+ return ko.utils.domData[dataStoreKey];
+ },
+ cleanNode: function (node) {
+ var dataStoreKey = node[ko.utils.domData.dataStoreKeyExpandoPropertyName];
+ if (dataStoreKey) {
+ delete ko.utils.domData[dataStoreKey];
+ node[ko.utils.domData.dataStoreKeyExpandoPropertyName] = null;
+ }
+ },
+ cleanNodeAndDescendants: function (node) {
+ if ((node.nodeType != 1) && (node.nodeType != 9))
+ return;
+ ko.utils.domData.cleanNode(node);
+ var descendants = node.getElementsByTagName("*");
+ for (var i = 0, j = descendants.length; i < j; i++)
+ ko.utils.domData.cleanNode(descendants[i]);
+ }
+ }
+ }
+})();
+
+if (!Function.prototype.bind) {
+ // Function.prototype.bind is a standard part of ECMAScript 5th Edition (December 2009, http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf)
+ // In case the browser doesn't implement it natively, provide a JavaScript implementation. This implementation is based on the one in prototype.js
+ Function.prototype.bind = function (object) {
+ var originalFunction = this, args = Array.prototype.slice.call(arguments), object = args.shift();
+ return function () {
+ return originalFunction.apply(object, args.concat(Array.prototype.slice.call(arguments)));
+ };
+ };
+}/// <reference path="utils.js" />
+
+ko.memoization = (function () {
+ var memos = {};
+
+ function randomMax8HexChars() {
+ return (((1 + Math.random()) * 0x100000000) | 0).toString(16).substring(1);
+ }
+ function generateRandomId() {
+ return randomMax8HexChars() + randomMax8HexChars();
+ }
+ function findMemoNodes(rootNode, appendToArray) {
+ if (!rootNode)
+ return;
+ if (rootNode.nodeType == 8) {
+ var memoId = ko.memoization.parseMemoText(rootNode.nodeValue);
+ if (memoId != null)
+ appendToArray.push({ domNode: rootNode, memoId: memoId });
+ } else if (rootNode.nodeType == 1) {
+ for (var i = 0, childNodes = rootNode.childNodes, j = childNodes.length; i < j; i++)
+ findMemoNodes(childNodes[i], appendToArray);
+ }
+ }
+
+ return {
+ memoize: function (callback) {
+ if (typeof callback != "function")
+ throw new Error("You can only pass a function to ko.memoization.memoize()");
+ var memoId = generateRandomId();
+ memos[memoId] = callback;
+ return "<!--[ko_memo:" + memoId + "]-->";
+ },
+
+ unmemoize: function (memoId, callbackParams) {
+ var callback = memos[memoId];
+ if (callback === undefined)
+ throw new Error("Couldn't find any memo with ID " + memoId + ". Perhaps it's already been unmemoized.");
+ try {
+ callback.apply(null, callbackParams || []);
+ return true;
+ }
+ finally { delete memos[memoId]; }
+ },
+
+ unmemoizeDomNodeAndDescendants: function (domNode) {
+ var memos = [];
+ findMemoNodes(domNode, memos);
+ for (var i = 0, j = memos.length; i < j; i++) {
+ var node = memos[i].domNode;
+ ko.memoization.unmemoize(memos[i].memoId, [node]);
+ node.nodeValue = ""; // Neuter this node so we don't try to unmemoize it again
+ if (node.parentNode)
+ node.parentNode.removeChild(node); // If possible, erase it totally (not always possible - someone else might just hold a reference to it then call unmemoizeDomNodeAndDescendants again)
+ }
+ },
+
+ parseMemoText: function (memoText) {
+ var match = memoText.match(/^\[ko_memo\:(.*?)\]$/);
+ return match ? match[1] : null;
+ }
+ };
+})();/// <reference path="../utils.js" />
+
+ko.subscription = function (callback, disposeCallback) {
+ this.callback = callback;
+ this.dispose = disposeCallback;
+};
+
+ko.subscribable = function () {
+ var _subscriptions = [];
+
+ this.subscribe = function (callback, callbackTarget) {
+ var boundCallback = callbackTarget ? function () { callback.call(callbackTarget) } : callback;
+
+ var subscription = new ko.subscription(boundCallback, function () {
+ ko.utils.arrayRemoveItem(_subscriptions, subscription);
+ });
+ _subscriptions.push(subscription);
+ return subscription;
+ };
+
+ this.notifySubscribers = function (valueToNotify) {
+ ko.utils.arrayForEach(_subscriptions.slice(0), function (subscription) {
+ if (subscription)
+ subscription.callback(valueToNotify);
+ });
+ };
+
+ this.getSubscriptionsCount = function () {
+ return _subscriptions.length;
+ };
+}
+
+ko.isSubscribable = function (instance) {
+ return typeof instance.subscribe == "function" && typeof instance.notifySubscribers == "function";
+};/// <reference path="subscribable.js" />
+
+ko.dependencyDetection = (function () {
+ var _detectedDependencies = [];
+
+ return {
+ begin: function () {
+ _detectedDependencies.push([]);
+ },
+
+ end: function () {
+ return _detectedDependencies.pop();
+ },
+
+ registerDependency: function (subscribable) {
+ if (!ko.isSubscribable(subscribable))
+ throw "Only subscribable things can act as dependencies";
+ if (_detectedDependencies.length > 0) {
+ _detectedDependencies[_detectedDependencies.length - 1].push(subscribable);
+ }
+ }
+ };
+})();/// <reference path="dependencyDetection.js" />
+
+ko.observable = function (initialValue) {
+ var _latestValue = initialValue;
+
+ function observable(newValue) {
+ if (arguments.length > 0) {
+ _latestValue = newValue;
+ observable.notifySubscribers(_latestValue);
+ }
+ else // The caller only needs to be notified of changes if they did a "read" operation
+ ko.dependencyDetection.registerDependency(observable);
+
+ return _latestValue;
+ }
+ observable.__ko_proto__ = ko.observable;
+ observable.valueHasMutated = function () { observable.notifySubscribers(_latestValue); }
+
+ ko.subscribable.call(observable);
+ return observable;
+}
+ko.isObservable = function (instance) {
+ if ((instance === null) || (instance === undefined) || (instance.__ko_proto__ === undefined)) return false;
+ if (instance.__ko_proto__ === ko.observable) return true;
+ return ko.isObservable(instance.__ko_proto__); // Walk the prototype chain
+}
+ko.isWriteableObservable = function (instance) {
+ return (typeof instance == "function") && instance.__ko_proto__ === ko.observable;
+}/// <reference path="observable.js" />
+
+ko.observableArray = function (initialValues) {
+ var result = new ko.observable(initialValues);
+
+ ko.utils.arrayForEach(["pop", "push", "reverse", "shift", "sort", "splice", "unshift"], function (methodName) {
+ result[methodName] = function () {
+ var underlyingArray = result();
+ var methodCallResult = underlyingArray[methodName].apply(underlyingArray, arguments);
+ result.valueHasMutated();
+ return methodCallResult;
+ };
+ });
+
+ ko.utils.arrayForEach(["slice"], function (methodName) {
+ result[methodName] = function () {
+ var underlyingArray = result();
+ return underlyingArray[methodName].apply(underlyingArray, arguments);
+ };
+ });
+
+ result.remove = function (valueOrPredicate) {
+ var underlyingArray = result();
+ var remainingValues = [];
+ var removedValues = [];
+ var predicate = typeof valueOrPredicate == "function" ? valueOrPredicate : function (value) { return value === valueOrPredicate; };
+ for (var i = 0, j = underlyingArray.length; i < j; i++) {
+ var value = underlyingArray[i];
+ if (!predicate(value))
+ remainingValues.push(value);
+ else
+ removedValues.push(value);
+ }
+ result(remainingValues);
+ return removedValues;
+ };
+
+ result.removeAll = function (arrayOfValues) {
+ if (!arrayOfValues)
+ return [];
+ return result.remove(function (value) {
+ return ko.utils.arrayIndexOf(arrayOfValues, value) >= 0;
+ });
+ };
+
+ result.indexOf = function (item) {
+ var underlyingArray = result();
+ return ko.utils.arrayIndexOf(underlyingArray, item);
+ };
+
+ return result;
+}/// <reference path="observable.js" />
+
+ko.dependentObservable = function (evaluatorFunction, evaluatorFunctionTarget, options) {
+ if (typeof evaluatorFunction != "function")
+ throw "Pass a function that returns the value of the dependentObservable";
+
+ var _subscriptionsToDependencies = [];
+ function disposeAllSubscriptionsToDependencies() {
+ ko.utils.arrayForEach(_subscriptionsToDependencies, function (subscription) {
+ subscription.dispose();
+ });
+ _subscriptionsToDependencies = [];
+ }
+
+ function replaceSubscriptionsToDependencies(newDependencies) {
+ disposeAllSubscriptionsToDependencies();
+ ko.utils.arrayForEach(newDependencies, function (dependency) {
+ _subscriptionsToDependencies.push(dependency.subscribe(evaluate));
+ });
+ };
+
+ var _latestValue, _isFirstEvaluation = true;
+ function evaluate() {
+ if ((!_isFirstEvaluation) && options && typeof options.disposeWhen == "function") {
+ if (options.disposeWhen()) {
+ dependentObservable.dispose();
+ return;
+ }
+ }
+
+ try {
+ ko.dependencyDetection.begin();
+ _latestValue = evaluatorFunctionTarget ? evaluatorFunction.call(evaluatorFunctionTarget) : evaluatorFunction();
+ } catch (ex) {
+ throw ex;
+ } finally {
+ var distinctDependencies = ko.utils.arrayGetDistinctValues(ko.dependencyDetection.end());
+ replaceSubscriptionsToDependencies(distinctDependencies);
+ }
+
+ dependentObservable.notifySubscribers(_latestValue);
+ _isFirstEvaluation = false;
+ }
+
+ function dependentObservable() {
+ if (arguments.length > 0)
+ throw "Cannot write a value to a dependentObservable. Do not pass any parameters to it";
+
+ ko.dependencyDetection.registerDependency(dependentObservable);
+ return _latestValue;
+ }
+ dependentObservable.__ko_proto__ = ko.dependentObservable;
+ dependentObservable.getDependenciesCount = function () { return _subscriptionsToDependencies.length; }
+ dependentObservable.dispose = function () {
+ disposeAllSubscriptionsToDependencies();
+ };
+
+ ko.subscribable.call(dependentObservable);
+ evaluate();
+ return dependentObservable;
+};
+ko.dependentObservable.__ko_proto__ = ko.observable;/// <reference path="../utils.js" />
+
+ko.jsonExpressionRewriting = (function () {
+ var restoreCapturedTokensRegex = /\[ko_token_(\d+)\]/g;
+ var javaScriptAssignmentTarget = /^[\_$a-z][\_$a-z]*(\[.*?\])*(\.[\_$a-z][\_$a-z]*(\[.*?\])*)*$/i;
+ var javaScriptReservedWords = ["true", "false"];
+
+ function restoreTokens(string, tokens) {
+ return string.replace(restoreCapturedTokensRegex, function (match, tokenIndex) {
+ return tokens[tokenIndex];
+ });
+ }
+
+ function isWriteableValue(expression) {
+ if (ko.utils.arrayIndexOf(javaScriptReservedWords, ko.utils.stringTrim(expression).toLowerCase()) >= 0)
+ return false;
+ return expression.match(javaScriptAssignmentTarget) !== null;
+ }
+
+ return {
+ parseJson: function (jsonString) {
+ jsonString = ko.utils.stringTrim(jsonString);
+ if (jsonString.length < 3)
+ return {};
+
+ // We're going to split on commas, so first extract any blocks that may contain commas other than those at the top level
+ var tokens = [];
+ var tokenStart = null, tokenEndChar;
+ for (var position = jsonString.charAt(0) == "{" ? 1 : 0; position < jsonString.length; position++) {
+ var c = jsonString.charAt(position);
+ if (tokenStart === null) {
+ switch (c) {
+ case '"':
+ case "'":
+ case "/":
+ tokenStart = position;
+ tokenEndChar = c;
+ break;
+ case "{":
+ tokenStart = position;
+ tokenEndChar = "}";
+ break;
+ case "[":
+ tokenStart = position;
+ tokenEndChar = "]";
+ break;
+ }
+ } else if (c == tokenEndChar) {
+ var token = jsonString.substring(tokenStart, position + 1);
+ tokens.push(token);
+ var replacement = "[ko_token_" + (tokens.length - 1) + "]";
+ jsonString = jsonString.substring(0, tokenStart) + replacement + jsonString.substring(position + 1);
+ position -= (token.length - replacement.length);
+ tokenStart = null;
+ }
+ }
+
+ // Now we can safely split on commas to get the key/value pairs
+ var result = {};
+ var keyValuePairs = jsonString.split(",");
+ for (var i = 0, j = keyValuePairs.length; i < j; i++) {
+ var pair = keyValuePairs[i];
+ var colonPos = pair.indexOf(":");
+ if ((colonPos > 0) && (colonPos < pair.length - 1)) {
+ var key = ko.utils.stringTrim(pair.substring(0, colonPos));
+ var value = ko.utils.stringTrim(pair.substring(colonPos + 1));
+ if (key.charAt(0) == "{")
+ key = key.substring(1);
+ if (value.charAt(value.length - 1) == "}")
+ value = value.substring(0, value.length - 1);
+ key = ko.utils.stringTrim(restoreTokens(key, tokens));
+ value = ko.utils.stringTrim(restoreTokens(value, tokens));
+ result[key] = value;
+ }
+ }
+ return result;
+ },
+
+ insertPropertyAccessorsIntoJson: function (jsonString) {
+ var parsed = ko.jsonExpressionRewriting.parseJson(jsonString);
+ var propertyAccessorTokens = [];
+ for (var key in parsed) {
+ var value = parsed[key];
+ if (isWriteableValue(value)) {
+ if (propertyAccessorTokens.length > 0)
+ propertyAccessorTokens.push(", ");
+ propertyAccessorTokens.push(key + " : function(__ko_value) { " + value + " = __ko_value; }");
+ }
+ }
+
+ if (propertyAccessorTokens.length > 0) {
+ var allPropertyAccessors = propertyAccessorTokens.join("");
+ jsonString = jsonString + ", '_ko_property_writers' : { " + allPropertyAccessors + " } ";
+ }
+
+ return jsonString;
+ }
+ };
+})();/// <reference path="../subscribables/dependentObservable.js" />
+
+(function () {
+ var bindingAttributeName = "data-bind";
+ ko.bindingHandlers = {};
+
+ function parseBindingAttribute(attributeText, viewModel) {
+ try {
+ var json = " { " + ko.jsonExpressionRewriting.insertPropertyAccessorsIntoJson(attributeText) + " } ";
+ return ko.utils.evalWithinScope(json, viewModel === null ? window : viewModel);
+ } catch (ex) {
+ throw new Error("Unable to parse binding attribute.\nMessage: " + ex + ";\nAttribute value: " + attributeText);
+ }
+ }
+
+ function invokeBindingHandler(handler, element, dataValue, allBindings, viewModel) {
+ handler(element, dataValue, allBindings, viewModel);
+ }
+
+ ko.applyBindingsToNode = function (node, bindings, viewModel) {
+ var isFirstEvaluation = true;
+ new ko.dependentObservable(
+ function () {
+ var evaluatedBindings = (typeof bindings == "function") ? bindings() : bindings;
+ var parsedBindings = evaluatedBindings || parseBindingAttribute(node.getAttribute(bindingAttributeName), viewModel);
+ for (var bindingKey in parsedBindings) {
+ if (ko.bindingHandlers[bindingKey]) {
+ if (isFirstEvaluation && typeof ko.bindingHandlers[bindingKey].init == "function")
+ invokeBindingHandler(ko.bindingHandlers[bindingKey].init, node, parsedBindings[bindingKey], parsedBindings, viewModel);
+ if (typeof ko.bindingHandlers[bindingKey].update == "function")
+ invokeBindingHandler(ko.bindingHandlers[bindingKey].update, node, parsedBindings[bindingKey], parsedBindings, viewModel);
+ }
+ }
+ },
+ null,
+ { disposeWhen: function () { return !ko.utils.domNodeIsAttachedToDocument(node); } }
+ );
+ isFirstEvaluation = false;
+ };
+
+ ko.applyBindings = function (rootNode, viewModel) {
+ var elemsWithBindingAttribute = ko.utils.getElementsHavingAttribute(rootNode, bindingAttributeName);
+ ko.utils.arrayForEach(elemsWithBindingAttribute, function (element) {
+ ko.applyBindingsToNode(element, null, viewModel);
+ });
+ };
+})();/// <reference path="bindingAttributeSyntax.js" />
+
+ko.bindingHandlers.click = {
+ init: function (element, value, allBindings, viewModel) {
+ ko.utils.registerEventHandler(element, "click", function (event) {
+ try { value.call(viewModel); }
+ finally {
+ if (event.preventDefault)
+ event.preventDefault();
+ else
+ event.returnValue = false;
+ }
+ });
+ }
+};
+
+ko.bindingHandlers.submit = {
+ init: function (element, value, allBindings, viewModel) {
+ if (typeof value != "function")
+ throw new Error("The value for a submit binding must be a function to invoke on submit");
+ ko.utils.registerEventHandler(element, "submit", function (event) {
+ try { value.call(viewModel); }
+ finally {
+ if (event.preventDefault)
+ event.preventDefault();
+ else
+ event.returnValue = false;
+ }
+ });
+ }
+};
+
+ko.bindingHandlers.visible = {
+ update: function (element, value) {
+ value = ko.utils.unwrapObservable(value);
+ var isCurrentlyVisible = !(element.style.display == "none");
+ if (value && !isCurrentlyVisible)
+ element.style.display = "";
+ else if ((!value) && isCurrentlyVisible)
+ element.style.display = "none";
+ }
+}
+
+ko.bindingHandlers.enable = {
+ update: function (element, value) {
+ value = ko.utils.unwrapObservable(value);
+ if (value && element.disabled)
+ element.removeAttribute("disabled");
+ else if ((!value) && (!element.disabled))
+ element.disabled = true;
+ }
+};
+
+ko.bindingHandlers.disable = { update: function (element, value) { ko.bindingHandlers.enable.update(element, !ko.utils.unwrapObservable(value)); } };
+
+ko.bindingHandlers.value = {
+ init: function (element, value, allBindings) {
+ var eventName = allBindings.valueUpdate || "change";
+ if (ko.isWriteableObservable(value))
+ ko.utils.registerEventHandler(element, eventName, function () { value(this.value); });
+ else if (allBindings._ko_property_writers && allBindings._ko_property_writers.value)
+ ko.utils.registerEventHandler(element, eventName, function () { allBindings._ko_property_writers.value(this.value); });
+ },
+ update: function (element, value) {
+ var newValue = ko.utils.unwrapObservable(value);
+
+ if (newValue != element.value) {
+ var applyValueAction = function () { element.value = newValue; };
+ applyValueAction();
+
+ // Workaround for IE6 bug: It won't reliably apply values to SELECT nodes during the same execution thread
+ // right after you've changed the set of OPTION nodes on it. So for that node type, we'll schedule a second thread
+ // to apply the value as well.
+ var alsoApplyAsynchronously = element.tagName == "SELECT";
+ if (alsoApplyAsynchronously)
+ setTimeout(applyValueAction, 0);
+ }
+ }
+};
+
+ko.bindingHandlers.options = {
+ update: function (element, value, allBindings) {
+ if (element.tagName != "SELECT")
+ throw new Error("values binding applies only to SELECT elements");
+
+ var previousSelectedValues = ko.utils.arrayMap(ko.utils.arrayFilter(element.childNodes, function (node) {
+ return node.tagName && node.tagName == "OPTION" && node.selected;
+ }), function (node) {
+ return node.value || node.innerText || node.textContent;
+ });
+
+ value = ko.utils.unwrapObservable(value);
+ var selectedValue = element.value;
+ element.innerHTML = "";
+ if (value) {
+ if (typeof value.length != "number")
+ value = [value];
+ for (var i = 0, j = value.length; i < j; i++) {
+ var option = document.createElement("OPTION");
+ var optionValue = typeof allBindings.options_value == "string" ? value[i][allBindings.options_value] : value[i];
+ option.value = optionValue.toString();
+ option.innerHTML = (typeof allBindings.options_text == "string" ? value[i][allBindings.options_text] : optionValue).toString();
+ element.appendChild(option);
+ }
+ // IE6 doesn't like us to assign selection to OPTION nodes before they're added to the document.
+ // That's why we first added them without selection. Now it's time to set the selection.
+ var newOptions = element.getElementsByTagName("OPTION");
+ for (var i = 0, j = newOptions.length; i < j; i++) {
+ if (ko.utils.arrayIndexOf(previousSelectedValues, newOptions[i].value) >= 0)
+ newOptions[i].selected = true;
+ }
+ }
+ }
+};
+
+ko.bindingHandlers.selectedOptions = {
+ getSelectedValuesFromSelectNode: function (selectNode) {
+ var result = [];
+ var nodes = selectNode.childNodes;
+ for (var i = 0, j = nodes.length; i < j; i++) {
+ var node = nodes[i];
+ if ((node.tagName == "OPTION") && node.selected)
+ result.push(node.value);
+ }
+ return result;
+ },
+ init: function (element, value, allBindings) {
+ if (ko.isWriteableObservable(value))
+ ko.utils.registerEventHandler(element, "change", function () { value(ko.bindingHandlers.selectedOptions.getSelectedValuesFromSelectNode(this)); });
+ else if (allBindings._ko_property_writers && allBindings._ko_property_writers.value)
+ ko.utils.registerEventHandler(element, "change", function () { allBindings._ko_property_writers.value(ko.bindingHandlers.selectedOptions.getSelectedValuesFromSelectNode(this)); });
+ },
+ update: function (element, value) {
+ if (element.tagName != "SELECT")
+ throw new Error("values binding applies only to SELECT elements");
+
+ var newValue = ko.utils.unwrapObservable(value);
+ if (newValue && typeof newValue.length == "number") {
+ var nodes = element.childNodes;
+ for (var i = 0, j = nodes.length; i < j; i++) {
+ var node = nodes[i];
+ if (node.tagName == "OPTION")
+ node.selected = ko.utils.arrayIndexOf(newValue, node.value) >= 0;
+ }
+ }
+ }
+};
+
+ko.bindingHandlers.text = {
+ update: function (element, value) {
+ value = ko.utils.unwrapObservable(value);
+ typeof element.innerText == "string" ? element.innerText = value
+ : element.textContent = value;
+ }
+};
+
+ko.bindingHandlers.css = {
+ update: function (element, value) {
+ value = value || {};
+ for (var className in value) {
+ if (typeof className == "string") {
+ var shouldHaveClass = ko.utils.unwrapObservable(value[className]);
+ ko.utils.toggleDomNodeCssClass(element, className, shouldHaveClass);
+ }
+ }
+ }
+};
+
+ko.bindingHandlers.uniqueName = {
+ init: function (element, value) {
+ if (value)
+ element.name = "ko_unique_" + (++ko.bindingHandlers.uniqueName.currentIndex);
+ }
+};
+ko.bindingHandlers.uniqueName.currentIndex = 0;
+
+ko.bindingHandlers.checked = {
+ init: function (element, value, allBindings) {
+ if (ko.isWriteableObservable(value)) {
+ var updateHandler;
+ if (element.type == "checkbox")
+ updateHandler = function () { value(this.checked) };
+ else if (element.type == "radio")
+ updateHandler = function () { if (this.checked) value(this.value) };
+ if (updateHandler) {
+ ko.utils.registerEventHandler(element, "change", updateHandler);
+ ko.utils.registerEventHandler(element, "click", updateHandler);
+ }
+ } else if (allBindings._ko_property_writers && allBindings._ko_property_writers.checked) {
+ var updateHandler;
+ if (element.type == "checkbox")
+ updateHandler = function () { allBindings._ko_property_writers.checked(this.checked) };
+ else if (element.type == "radio")
+ updateHandler = function () { if (this.checked) allBindings._ko_property_writers.checked(this.value) };
+ if (updateHandler) {
+ ko.utils.registerEventHandler(element, "change", updateHandler);
+ ko.utils.registerEventHandler(element, "click", updateHandler);
+ }
+ }
+ },
+ update: function (element, value) {
+ value = ko.utils.unwrapObservable(value);
+ if (element.type == "checkbox")
+ element.checked = value;
+ else if (element.type == "radio")
+ element.checked = (element.value == value);
+ }
+};/// <reference path="../utils.js" />
+
+ko.templateEngine = function () {
+ this.renderTemplate = function (templateName, data, options) {
+ throw "Override renderTemplate in your ko.templateEngine subclass";
+ },
+ this.isTemplateRewritten = function (templateName) {
+ throw "Override isTemplateRewritten in your ko.templateEngine subclass";
+ },
+ this.rewriteTemplate = function (templateName, rewriterCallback) {
+ throw "Override rewriteTemplate in your ko.templateEngine subclass";
+ },
+ this.createJavaScriptEvaluatorBlock = function (script) {
+ throw "Override createJavaScriptEvaluatorBlock in your ko.templateEngine subclass";
+ }
+};/// <reference path="templateEngine.js" />
+
+ko.templateRewriting = (function () {
+ var memoizeBindingAttributeSyntaxRegex = /(<[a-z]+(\s+(?!data-bind=)[a-z0-9]+(=(\"[^\"]*\"|\'[^\']*\'))?)*\s+)data-bind=(["'])(.*?)\5/g;
+
+ return {
+ ensureTemplateIsRewritten: function (template, templateEngine) {
+ if (!templateEngine.isTemplateRewritten(template))
+ templateEngine.rewriteTemplate(template, function (htmlString) {
+ return ko.templateRewriting.memoizeBindingAttributeSyntax(htmlString, templateEngine);
+ });
+ },
+
+ memoizeBindingAttributeSyntax: function (htmlString, templateEngine) {
+ return htmlString.replace(memoizeBindingAttributeSyntaxRegex, function () {
+ var tagToRetain = arguments[1];
+ var dataBindAttributeValue = arguments[6];
+
+ dataBindAttributeValue = ko.jsonExpressionRewriting.insertPropertyAccessorsIntoJson(dataBindAttributeValue);
+
+ // For no obvious reason, Opera fails to evaluate dataBindAttributeValue unless it's wrapped in an additional anonymous function,
+ // even though Opera's built-in debugger can evaluate it anyway. No other browser requires this extra indirection.
+ var applyBindingsToNextSiblingScript = "ko.templateRewriting.applyMemoizedBindingsToNextSibling(function() { \
+ return (function() { return { " + dataBindAttributeValue + " } })() \
+ })";
+ return templateEngine.createJavaScriptEvaluatorBlock(applyBindingsToNextSiblingScript) + tagToRetain;
+ });
+ },
+
+ applyMemoizedBindingsToNextSibling: function (bindings) {
+ return ko.memoization.memoize(function (domNode) {
+ if (domNode.nextSibling)
+ ko.applyBindingsToNode(domNode.nextSibling, bindings, null);
+ });
+ }
+ }
+})();/// <reference path="templating.js" />
+/// <reference path="../subscribables/dependentObservable.js" />
+
+(function () {
+ var _templateEngine;
+ ko.setTemplateEngine = function (templateEngine) {
+ if ((templateEngine != undefined) && !(templateEngine instanceof ko.templateEngine))
+ throw "templateEngine must inherit from ko.templateEngine";
+ _templateEngine = templateEngine;
+ }
+
+ function getFirstNodeFromPossibleArray(nodeOrNodeArray) {
+ return nodeOrNodeArray.nodeType ? nodeOrNodeArray
+ : nodeOrNodeArray.length > 0 ? nodeOrNodeArray[0]
+ : null;
+ }
+
+ function executeTemplate(targetNodeOrNodeArray, renderMode, template, data, options) {
+ var dataForTemplate = ko.utils.unwrapObservable(data);
+
+ options = options || {};
+ var templateEngineToUse = (options.templateEngine || _templateEngine);
+ ko.templateRewriting.ensureTemplateIsRewritten(template, templateEngineToUse);
+ var renderedNodesArray = templateEngineToUse.renderTemplate(template, dataForTemplate, options);
+
+ // Loosely check result is an array of DOM nodes
+ if ((typeof renderedNodesArray.length != "number") || (renderedNodesArray.length > 0 && typeof renderedNodesArray[0].nodeType != "number"))
+ throw "Template engine must return an array of DOM nodes";
+
+ if (renderedNodesArray)
+ ko.utils.arrayForEach(renderedNodesArray, function (renderedNode) {
+ ko.memoization.unmemoizeDomNodeAndDescendants(renderedNode);
+ });
+
+ switch (renderMode) {
+ case "replaceChildren": ko.utils.setDomNodeChildren(targetNodeOrNodeArray, renderedNodesArray); break;
+ case "replaceNode": ko.utils.replaceDomNodes(targetNodeOrNodeArray, renderedNodesArray); break;
+ case "ignoreTargetNode": break;
+ default: throw new Error("Unknown renderMode: " + renderMode);
+ }
+
+ return renderedNodesArray;
+ }
+
+ ko.renderTemplate = function (template, data, options, targetNodeOrNodeArray, renderMode) {
+ options = options || {};
+ if ((options.templateEngine || _templateEngine) == undefined)
+ throw "Set a template engine before calling renderTemplate";
+ renderMode = renderMode || "replaceChildren";
+
+ if (targetNodeOrNodeArray) {
+ var firstTargetNode = getFirstNodeFromPossibleArray(targetNodeOrNodeArray);
+ var whenToDispose = function () { return (!firstTargetNode) || !ko.utils.domNodeIsAttachedToDocument(firstTargetNode); };
+
+ return new ko.dependentObservable( // So the DOM is automatically updated when any dependency changes
+ function () {
+ var renderedNodesArray = executeTemplate(targetNodeOrNodeArray, renderMode, template, data, options);
+ if (renderMode == "replaceNode") {
+ targetNodeOrNodeArray = renderedNodesArray;
+ firstTargetNode = getFirstNodeFromPossibleArray(targetNodeOrNodeArray);
+ }
+ },
+ null,
+ { disposeWhen: whenToDispose }
+ );
+ } else {
+ // We don't yet have a DOM node to evaluate, so use a memo and render the template later when there is a DOM node
+ return ko.memoization.memoize(function (domNode) {
+ ko.renderTemplate(template, data, options, domNode, "replaceNode");
+ });
+ }
+ };
+
+ ko.renderTemplateForEach = function (template, arrayOrObservableArray, options, targetNode) {
+ var whenToDispose = function () { return !ko.utils.domNodeIsAttachedToDocument(targetNode); };
+
+ new ko.dependentObservable(function () {
+ var unwrappedArray = ko.utils.unwrapObservable(arrayOrObservableArray);
+ if (typeof unwrappedArray.length == "undefined") // Coerce single value into array
+ unwrappedArray = [unwrappedArray];
+
+ ko.utils.setDomNodeChildrenFromArrayMapping(targetNode, unwrappedArray, function (arrayValue) {
+ return executeTemplate(null, "ignoreTargetNode", template, arrayValue, options);
+ }, options);
+ }, null, { disposeWhen: whenToDispose });
+ };
+
+ ko.bindingHandlers.template = {
+ update: function (element, bindingValue, allBindings, viewModel) {
+ var templateName = typeof bindingValue == "string" ? bindingValue : bindingValue.name;
+
+ if (typeof bindingValue.foreach != "undefined") {
+ // Render once for each data point
+ ko.renderTemplateForEach(templateName, bindingValue.foreach || [], { afterAdd: bindingValue.afterAdd, beforeRemove: bindingValue.beforeRemove }, element);
+ }
+ else {
+ // Render once for this single data point (or use the viewModel if no data was provided)
+ var templateData = bindingValue.data;
+ ko.renderTemplate(templateName, typeof templateData == "undefined" ? viewModel : templateData, null, element);
+ }
+ }
+ };
+})();/// <reference path="../../utils.js" />
+
+// Simple calculation based on Levenshtein distance.
+(function () {
+
+ function calculateEditDistanceMatrix(oldArray, newArray, maxAllowedDistance) {
+ var distances = [];
+ for (var i = 0; i <= newArray.length; i++)
+ distances[i] = [];
+
+ // Top row - transform old array into empty array via deletions
+ for (var i = 0, j = Math.min(oldArray.length, maxAllowedDistance); i <= j; i++)
+ distances[0][i] = i;
+
+ // Left row - transform empty array into new array via additions
+ for (var i = 1, j = Math.min(newArray.length, maxAllowedDistance); i <= j; i++) {
+ distances[i][0] = i;
+ }
+
+ // Fill out the body of the array
+ var oldIndex, oldIndexMax = oldArray.length, newIndex, newIndexMax = newArray.length;
+ var distanceViaAddition, distanceViaDeletion;
+ for (oldIndex = 1; oldIndex <= oldIndexMax; oldIndex++) {
+ var newIndexMinForRow = Math.max(1, oldIndex - maxAllowedDistance);
+ var newIndexMaxForRow = Math.min(newIndexMax, oldIndex + maxAllowedDistance);
+ for (newIndex = newIndexMinForRow; newIndex <= newIndexMaxForRow; newIndex++) {
+ if (oldArray[oldIndex - 1] === newArray[newIndex - 1])
+ distances[newIndex][oldIndex] = distances[newIndex - 1][oldIndex - 1];
+ else {
+ var northDistance = distances[newIndex - 1][oldIndex] === undefined ? Number.MAX_VALUE : distances[newIndex - 1][oldIndex] + 1;
+ var westDistance = distances[newIndex][oldIndex - 1] === undefined ? Number.MAX_VALUE : distances[newIndex][oldIndex - 1] + 1;
+ distances[newIndex][oldIndex] = Math.min(northDistance, westDistance);
+ }
+ }
+ }
+
+ return distances;
+ }
+
+ function findEditScriptFromEditDistanceMatrix(editDistanceMatrix, oldArray, newArray) {
+ var oldIndex = oldArray.length;
+ var newIndex = newArray.length;
+ var editScript = [];
+ var maxDistance = editDistanceMatrix[newIndex][oldIndex];
+ if (maxDistance === undefined)
+ return null; // maxAllowedDistance must be too small
+ while ((oldIndex > 0) || (newIndex > 0)) {
+ var me = editDistanceMatrix[newIndex][oldIndex];
+ var distanceViaAdd = (newIndex > 0) ? editDistanceMatrix[newIndex - 1][oldIndex] : maxDistance + 1;
+ var distanceViaDelete = (oldIndex > 0) ? editDistanceMatrix[newIndex][oldIndex - 1] : maxDistance + 1;
+ var distanceViaRetain = (newIndex > 0) && (oldIndex > 0) ? editDistanceMatrix[newIndex - 1][oldIndex - 1] : maxDistance + 1;
+ if ((distanceViaAdd === undefined) || (distanceViaAdd < me - 1)) distanceViaAdd = maxDistance + 1;
+ if ((distanceViaDelete === undefined) || (distanceViaDelete < me - 1)) distanceViaDelete = maxDistance + 1;
+ if (distanceViaRetain < me - 1) distanceViaRetain = maxDistance + 1;
+
+ if ((distanceViaAdd <= distanceViaDelete) && (distanceViaAdd < distanceViaRetain)) {
+ editScript.push({ status: "added", value: newArray[newIndex - 1] });
+ newIndex--;
+ } else if ((distanceViaDelete < distanceViaAdd) && (distanceViaDelete < distanceViaRetain)) {
+ editScript.push({ status: "deleted", value: oldArray[oldIndex - 1] });
+ oldIndex--;
+ } else {
+ editScript.push({ status: "retained", value: oldArray[oldIndex - 1] });
+ newIndex--;
+ oldIndex--;
+ }
+ }
+ return editScript.reverse();
+ }
+
+ ko.utils.compareArrays = function (oldArray, newArray, maxEditsToConsider) {
+ if (maxEditsToConsider === undefined) {
+ return ko.utils.compareArrays(oldArray, newArray, 1) // First consider likely case where there is at most one edit (very fast)
+ || ko.utils.compareArrays(oldArray, newArray, 10) // If that fails, account for a fair number of changes while still being fast
+ || ko.utils.compareArrays(oldArray, newArray, Number.MAX_VALUE); // Ultimately give the right answer, even though it may take a long time
+ } else {
+ oldArray = oldArray || [];
+ newArray = newArray || [];
+ var editDistanceMatrix = calculateEditDistanceMatrix(oldArray, newArray, maxEditsToConsider);
+ return findEditScriptFromEditDistanceMatrix(editDistanceMatrix, oldArray, newArray);
+ }
+ };
+})();/// <reference path="compareArrays.js" />
+
+(function () {
+ // Objective:
+ // * Given an input array, a container DOM node, and a function from array elements to arrays of DOM nodes,
+ // map the array elements to arrays of DOM nodes, concatenate together all these arrays, and use them to populate the container DOM node
+ // * Next time we're given the same combination of things (with the array possibly having mutated), update the container DOM node
+ // so that its children is again the concatenation of the mappings of the array elements, but don't re-map any array elements that we
+ // previously mapped - retain those nodes, and just insert/delete other ones
+
+ ko.utils.setDomNodeChildrenFromArrayMapping = function (domNode, array, mapping, options) {
+ // Compare the provided array against the previous one
+ array = array || [];
+ options = options || {};
+ var isFirstExecution = ko.utils.domData.get(domNode, "setDomNodeChildrenFromArrayMapping_lastMappingResult") === undefined;
+ var lastMappingResult = ko.utils.domData.get(domNode, "setDomNodeChildrenFromArrayMapping_lastMappingResult") || [];
+ var lastArray = ko.utils.arrayMap(lastMappingResult, function (x) { return x.arrayEntry; });
+ var editScript = ko.utils.compareArrays(lastArray, array);
+
+ // Build the new mapping result
+ var newMappingResult = [];
+ var lastMappingResultIndex = 0;
+ var nodesToDelete = [];
+ var nodesAdded = [];
+ var insertAfterNode = null;
+ for (var i = 0, j = editScript.length; i < j; i++) {
+ switch (editScript[i].status) {
+ case "retained":
+ // Just keep the information - don't touch the nodes
+ var dataToRetain = lastMappingResult[lastMappingResultIndex];
+ newMappingResult.push(dataToRetain);
+ if (dataToRetain.domNodes.length > 0)
+ insertAfterNode = dataToRetain.domNodes[dataToRetain.domNodes.length - 1];
+ lastMappingResultIndex++;
+ break;
+
+ case "deleted":
+ // Queue these nodes for later removal
+ ko.utils.arrayForEach(lastMappingResult[lastMappingResultIndex].domNodes, function (node) {
+ nodesToDelete.push(node);
+ insertAfterNode = node;
+ });
+ lastMappingResultIndex++;
+ break;
+
+ case "added":
+ // Map this array value and insert the resulting nodes at the current insertion point
+ var mappedNodes = mapping(editScript[i].value) || [];
+ newMappingResult.push({ arrayEntry: editScript[i].value, domNodes: mappedNodes });
+ for (var nodeIndex = 0, nodeIndexMax = mappedNodes.length; nodeIndex < nodeIndexMax; nodeIndex++) {
+ var node = mappedNodes[nodeIndex];
+ nodesAdded.push(node);
+ if (insertAfterNode == null) {
+ // Insert at beginning
+ if (domNode.firstChild)
+ domNode.insertBefore(node, domNode.firstChild);
+ else
+ domNode.appendChild(node);
+ } else {
+ // Insert after insertion point
+ if (insertAfterNode.nextSibling)
+ domNode.insertBefore(node, insertAfterNode.nextSibling);
+ else
+ domNode.appendChild(node);
+ }
+ insertAfterNode = node;
+ }
+ break;
+ }
+ }
+
+ ko.utils.arrayForEach(nodesToDelete, function (node) { ko.utils.domData.cleanNodeAndDescendants(node); });
+
+ var invokedBeforeRemoveCallback = false;
+ if (!isFirstExecution) {
+ if (options.afterAdd)
+ options.afterAdd(nodesAdded);
+ if (options.beforeRemove) {
+ options.beforeRemove(nodesToDelete);
+ invokedBeforeRemoveCallback = true;
+ }
+ }
+ if (!invokedBeforeRemoveCallback)
+ ko.utils.arrayForEach(nodesToDelete, function (node) {
+ if (node.parentNode)
+ node.parentNode.removeChild(node);
+ });
+
+ // Store a copy of the array items we just considered so we can difference it next time
+ ko.utils.domData.set(domNode, "setDomNodeChildrenFromArrayMapping_lastMappingResult", newMappingResult);
+ }
+})();/// <reference path="../templating.js" />
+
+ko.jqueryTmplTemplateEngine = function () {
+ function getTemplateNode(template) {
+ var templateNode = document.getElementById(template);
+ if (templateNode == null)
+ throw new Error("Cannot find template with ID=" + template);
+ return templateNode;
+ }
+
+ this.renderTemplate = function (template, data, options) {
+ // jquery.tmpl doesn't like it if the template returns just text content or nothing - it only likes you to return DOM nodes.
+ // To make things more flexible, we can wrap the whole template in a <script> node so that jquery.tmpl just processes it as
+ // text and doesn't try to parse the output. Then, since jquery.tmpl has jQuery as a dependency anyway, we can use jQuery to
+ // parse that text into a document fragment using jQuery.clean().
+ var templateTextInWrapper = "<script type=\"text/html\">" + ko.utils.stringTrim(getTemplateNode(template).text) + "</script>";
+ var renderedMarkupInWrapper = $.tmpl(templateTextInWrapper, data);
+ return jQuery.clean([renderedMarkupInWrapper[0].text], document);
+ },
+
+ this.isTemplateRewritten = function (template) {
+ return getTemplateNode(template).isRewritten === true;
+ },
+
+ this.rewriteTemplate = function (template, rewriterCallback) {
+ var templateNode = getTemplateNode(template);
+ var rewritten = rewriterCallback(templateNode.text)
+ templateNode.text = rewritten;
+ templateNode.isRewritten = true;
+ },
+
+ this.createJavaScriptEvaluatorBlock = function (script) {
+ return "{{= " + script + "}}";
+ },
+
+ // Am considering making template registration a native part of the API (and storing added templates centrally), but for now it's specific to this template engine
+ this.addTemplate = function (templateName, templateMarkup) {
+ document.write("<script type='text/html' id='" + templateName + "'>" + templateMarkup + "</script>");
+ }
+};
+ko.jqueryTmplTemplateEngine.prototype = new ko.templateEngine();
+
+// Use this one by default
+ko.setTemplateEngine(new ko.jqueryTmplTemplateEngine());
\ No newline at end of file