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