quick_script 0.11.8 → 0.11.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,3 +1,3 @@
1
1
  module QuickScript
2
- VERSION = "0.11.8"
2
+ VERSION = "0.11.9"
3
3
  end
@@ -162,10 +162,11 @@ Overlay.add = (vm, tmp, opts) ->
162
162
  if opts.stretch == true
163
163
  $("#overlay-#{id} .modal-body").css({'max-height' : ($(window).height() - 200)})
164
164
  $('#overlay-' + id).css({'margin-top' : ($(window).height() - 100)/ -2})
165
- $('#overlay-' + id).modal('show')
166
165
  $('#overlay-' + id).on 'hidden', ->
167
166
  $('#overlay-' + id).koClean()
168
167
  $('#overlay-' + id).remove()
168
+ $('#overlay-' + id).on 'shown', opts.shown if opts.shown?
169
+ $('#overlay-' + id).modal('show')
169
170
  , 100
170
171
  #Overlay.instance.zindex = Overlay.instance.zindex + 10
171
172
 
@@ -207,10 +208,16 @@ Overlay.confirm = (msg, opts) ->
207
208
  $('#overlay-confirm').slideDown 'fast'
208
209
 
209
210
  Overlay.remove = (id) ->
210
- $('#overlay-' + id).modal('hide')
211
- $('#popover-' + id).koClean().remove()
212
- $('#backdrop-' + id).remove()
213
- $('#overlay-' + id).remove() if (id == 'confirm')
211
+ Overlay.removeModal(id)
212
+ Overlay.removePopover(id)
213
+
214
+ Overlay.removeModal = (id) ->
215
+ $('#overlay-' + id).modal('hide')
216
+ $('#backdrop-' + id).remove()
217
+ $('#overlay-' + id).remove() if (id == 'confirm')
218
+
219
+ Overlay.removePopover = (id) ->
220
+ $('#popover-' + id).koClean().remove()
214
221
 
215
222
  Overlay.removePopovers = ->
216
223
  $('.popover').remove()
@@ -221,7 +228,7 @@ Overlay.isVisible = (id) ->
221
228
  Overlay.popover = (el, vm, tmp, opts)->
222
229
  id = vm.name
223
230
  opts.placement = opts.placement || 'bottom'
224
- $po = $("<div id='popover-#{id}' class='popover fade'><div class='arrow'></div><div class='popover-inner'><h3 class='popover-title'>#{opts.title}</h3><div class='popover-content' data-bind=\"template : '#{tmp}'\"></div></div></div>")
231
+ $po = $("<div id='popover-#{id}' class='popover fade'><div class='arrow'></div><div class='popover-inner'><button class='close' data-bind='click : hidePopover'>x</button><h3 class='popover-title'>#{opts.title}</h3><div class='popover-content' data-bind=\"template : '#{tmp}'\"></div></div></div>")
225
232
 
226
233
  setTimeout ->
227
234
  $po.remove().css({ top: 0, left: 0, display: 'block', width: 'auto' }).prependTo(document.body)
@@ -555,6 +555,7 @@ class @Model
555
555
  error : =>
556
556
  console.log("Delete error encountered")
557
557
  @model_state(ko.modelStates.READY)
558
+ callback({meta : 500, data : {errors : ['An error occurred']}}) if callback?
558
559
  @model_state(ko.modelStates.SAVING)
559
560
  removeFromCollection : =>
560
561
  @collection.removeItemById(@id()) if @collection?
@@ -947,6 +948,8 @@ class @View
947
948
  Overlay.popover(el, this, tmp, opts)
948
949
  hideOverlay : =>
949
950
  Overlay.remove(@name)
951
+ hidePopover : =>
952
+ Overlay.removePopover(@name)
950
953
  overlayVisible : =>
951
954
  Overlay.isVisible(@name)
952
955
 
@@ -981,12 +984,9 @@ class @ModelAdapter
981
984
  send : (opts)->
982
985
  ModelAdapter.send(@host, opts)
983
986
  delete : (opts)->
984
- $.ajax
985
- type : 'DELETE'
986
- url : @host + @save_url
987
- data : opts.data
988
- success : opts.success
989
- error : opts.error
987
+ opts.type = 'DELETE'
988
+ opts.url = @save_url
989
+ @send opts
990
990
  add_method : (fn_name, fn)->
991
991
  @[fn_name] = fn.bind(this)
992
992
  ModelAdapter.send = (host, opts)->
@@ -1056,13 +1056,9 @@ class @AccountAdapter
1056
1056
  send : (opts)->
1057
1057
  ModelAdapter.send(@host, opts)
1058
1058
  delete : (opts)->
1059
- $.ajax_qs
1060
- type : 'DELETE'
1061
- url : @host + opts.url
1062
- data : opts.data
1063
- progress : opts.progress
1064
- success : opts.success
1065
- error : opts.error
1059
+ opts.type = 'DELETE'
1060
+ opts.url = @save_url
1061
+ @send opts
1066
1062
  add_method : (fn_name, fn)->
1067
1063
  @[fn_name] = fn.bind(this)
1068
1064
 
@@ -1,86 +1,3577 @@
1
- // Knockout JavaScript library v2.1.0
1
+ // Knockout JavaScript library v2.2.0
2
2
  // (c) Steven Sanderson - http://knockoutjs.com/
3
3
  // License: MIT (http://www.opensource.org/licenses/mit-license.php)
4
4
 
5
- (function(window,document,navigator,undefined){
6
- function m(w){throw w;}var n=void 0,p=!0,s=null,t=!1;function A(w){return function(){return w}};function E(w){function B(b,c,d){d&&c!==a.k.r(b)&&a.k.S(b,c);c!==a.k.r(b)&&a.a.va(b,"change")}var a="undefined"!==typeof w?w:{};a.b=function(b,c){for(var d=b.split("."),f=a,g=0;g<d.length-1;g++)f=f[d[g]];f[d[d.length-1]]=c};a.B=function(a,c,d){a[c]=d};a.version="2.1.0";a.b("version",a.version);a.a=new function(){function b(b,c){if("input"!==a.a.o(b)||!b.type||"click"!=c.toLowerCase())return t;var e=b.type;return"checkbox"==e||"radio"==e}var c=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,d={},f={};d[/Firefox\/2/i.test(navigator.userAgent)?
7
- "KeyboardEvent":"UIEvents"]=["keyup","keydown","keypress"];d.MouseEvents="click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave".split(" ");for(var g in d){var e=d[g];if(e.length)for(var h=0,j=e.length;h<j;h++)f[e[h]]=g}var k={propertychange:p},i=function(){for(var a=3,b=document.createElement("div"),c=b.getElementsByTagName("i");b.innerHTML="<\!--[if gt IE "+ ++a+"]><i></i><![endif]--\>",c[0];);return 4<a?a:n}();return{Ca:["authenticity_token",/^__RequestVerificationToken(_.*)?$/],
8
- v:function(a,b){for(var c=0,e=a.length;c<e;c++)b(a[c])},j:function(a,b){if("function"==typeof Array.prototype.indexOf)return Array.prototype.indexOf.call(a,b);for(var c=0,e=a.length;c<e;c++)if(a[c]===b)return c;return-1},ab:function(a,b,c){for(var e=0,f=a.length;e<f;e++)if(b.call(c,a[e]))return a[e];return s},ba:function(b,c){var e=a.a.j(b,c);0<=e&&b.splice(e,1)},za:function(b){for(var b=b||[],c=[],e=0,f=b.length;e<f;e++)0>a.a.j(c,b[e])&&c.push(b[e]);return c},T:function(a,b){for(var a=a||[],c=[],
9
- e=0,f=a.length;e<f;e++)c.push(b(a[e]));return c},aa:function(a,b){for(var a=a||[],c=[],e=0,f=a.length;e<f;e++)b(a[e])&&c.push(a[e]);return c},N:function(a,b){if(b instanceof Array)a.push.apply(a,b);else for(var c=0,e=b.length;c<e;c++)a.push(b[c]);return a},extend:function(a,b){if(b)for(var c in b)b.hasOwnProperty(c)&&(a[c]=b[c]);return a},ga:function(b){for(;b.firstChild;)a.removeNode(b.firstChild)},Ab:function(b){for(var b=a.a.L(b),c=document.createElement("div"),e=0,f=b.length;e<f;e++)a.F(b[e]),
10
- c.appendChild(b[e]);return c},X:function(b,c){a.a.ga(b);if(c)for(var e=0,f=c.length;e<f;e++)b.appendChild(c[e])},Na:function(b,c){var e=b.nodeType?[b]:b;if(0<e.length){for(var f=e[0],d=f.parentNode,g=0,h=c.length;g<h;g++)d.insertBefore(c[g],f);g=0;for(h=e.length;g<h;g++)a.removeNode(e[g])}},Pa:function(a,b){0<=navigator.userAgent.indexOf("MSIE 6")?a.setAttribute("selected",b):a.selected=b},w:function(a){return(a||"").replace(c,"")},Ib:function(b,c){for(var e=[],f=(b||"").split(c),g=0,d=f.length;g<
11
- d;g++){var h=a.a.w(f[g]);""!==h&&e.push(h)}return e},Hb:function(a,b){a=a||"";return b.length>a.length?t:a.substring(0,b.length)===b},eb:function(a,b){for(var c="return ("+a+")",e=0;e<b;e++)c="with(sc["+e+"]) { "+c+" } ";return new Function("sc",c)},kb:function(a,b){if(b.compareDocumentPosition)return 16==(b.compareDocumentPosition(a)&16);for(;a!=s;){if(a==b)return p;a=a.parentNode}return t},fa:function(b){return a.a.kb(b,b.ownerDocument)},o:function(a){return a&&a.tagName&&a.tagName.toLowerCase()},
12
- n:function(a,c,e){var f=i&&k[c];if(!f&&"undefined"!=typeof jQuery){if(b(a,c))var g=e,e=function(a,b){var c=this.checked;b&&(this.checked=b.fb!==p);g.call(this,a);this.checked=c};jQuery(a).bind(c,e)}else!f&&"function"==typeof a.addEventListener?a.addEventListener(c,e,t):"undefined"!=typeof a.attachEvent?a.attachEvent("on"+c,function(b){e.call(a,b)}):m(Error("Browser doesn't support addEventListener or attachEvent"))},va:function(a,c){(!a||!a.nodeType)&&m(Error("element must be a DOM node when calling triggerEvent"));
13
- if("undefined"!=typeof jQuery){var e=[];b(a,c)&&e.push({fb:a.checked});jQuery(a).trigger(c,e)}else"function"==typeof document.createEvent?"function"==typeof a.dispatchEvent?(e=document.createEvent(f[c]||"HTMLEvents"),e.initEvent(c,p,p,window,0,0,0,0,0,t,t,t,t,0,a),a.dispatchEvent(e)):m(Error("The supplied element doesn't support dispatchEvent")):"undefined"!=typeof a.fireEvent?(b(a,c)&&(a.checked=a.checked!==p),a.fireEvent("on"+c)):m(Error("Browser doesn't support triggering events"))},d:function(b){return a.la(b)?
14
- b():b},Ua:function(b,c,e){var f=(b.className||"").split(/\s+/),g=0<=a.a.j(f,c);if(e&&!g)b.className+=(f[0]?" ":"")+c;else if(g&&!e){e="";for(g=0;g<f.length;g++)f[g]!=c&&(e+=f[g]+" ");b.className=a.a.w(e)}},Qa:function(b,c){var e=a.a.d(c);if(e===s||e===n)e="";"innerText"in b?b.innerText=e:b.textContent=e;9<=i&&(b.style.display=b.style.display)},lb:function(a){if(9<=i){var b=a.style.width;a.style.width=0;a.style.width=b}},Eb:function(b,e){for(var b=a.a.d(b),e=a.a.d(e),c=[],f=b;f<=e;f++)c.push(f);return c},
15
- L:function(a){for(var b=[],e=0,c=a.length;e<c;e++)b.push(a[e]);return b},tb:6===i,ub:7===i,ja:i,Da:function(b,e){for(var c=a.a.L(b.getElementsByTagName("input")).concat(a.a.L(b.getElementsByTagName("textarea"))),f="string"==typeof e?function(a){return a.name===e}:function(a){return e.test(a.name)},g=[],d=c.length-1;0<=d;d--)f(c[d])&&g.push(c[d]);return g},Bb:function(b){return"string"==typeof b&&(b=a.a.w(b))?window.JSON&&window.JSON.parse?window.JSON.parse(b):(new Function("return "+b))():s},sa:function(b,
16
- e,c){("undefined"==typeof JSON||"undefined"==typeof JSON.stringify)&&m(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(a.a.d(b),e,c)},Cb:function(b,e,c){var c=c||{},f=c.params||{},g=c.includeFields||this.Ca,d=b;if("object"==typeof b&&"form"===a.a.o(b))for(var d=b.action,h=g.length-1;0<=h;h--)for(var k=a.a.Da(b,g[h]),
17
- j=k.length-1;0<=j;j--)f[k[j].name]=k[j].value;var e=a.a.d(e),i=document.createElement("form");i.style.display="none";i.action=d;i.method="post";for(var z in e)b=document.createElement("input"),b.name=z,b.value=a.a.sa(a.a.d(e[z])),i.appendChild(b);for(z in f)b=document.createElement("input"),b.name=z,b.value=f[z],i.appendChild(b);document.body.appendChild(i);c.submitter?c.submitter(i):i.submit();setTimeout(function(){i.parentNode.removeChild(i)},0)}}};a.b("utils",a.a);a.b("utils.arrayForEach",a.a.v);
18
- a.b("utils.arrayFirst",a.a.ab);a.b("utils.arrayFilter",a.a.aa);a.b("utils.arrayGetDistinctValues",a.a.za);a.b("utils.arrayIndexOf",a.a.j);a.b("utils.arrayMap",a.a.T);a.b("utils.arrayPushAll",a.a.N);a.b("utils.arrayRemoveItem",a.a.ba);a.b("utils.extend",a.a.extend);a.b("utils.fieldsIncludedWithJsonPost",a.a.Ca);a.b("utils.getFormFields",a.a.Da);a.b("utils.postJson",a.a.Cb);a.b("utils.parseJson",a.a.Bb);a.b("utils.registerEventHandler",a.a.n);a.b("utils.stringifyJson",a.a.sa);a.b("utils.range",a.a.Eb);
19
- a.b("utils.toggleDomNodeCssClass",a.a.Ua);a.b("utils.triggerEvent",a.a.va);a.b("utils.unwrapObservable",a.a.d);Function.prototype.bind||(Function.prototype.bind=function(a){var c=this,d=Array.prototype.slice.call(arguments),a=d.shift();return function(){return c.apply(a,d.concat(Array.prototype.slice.call(arguments)))}});a.a.f=new function(){var b=0,c="__ko__"+(new Date).getTime(),d={};return{get:function(b,c){var e=a.a.f.getAll(b,t);return e===n?n:e[c]},set:function(b,c,e){e===n&&a.a.f.getAll(b,
20
- t)===n||(a.a.f.getAll(b,p)[c]=e)},getAll:function(a,g){var e=a[c];if(!(e&&"null"!==e)){if(!g)return;e=a[c]="ko"+b++;d[e]={}}return d[e]},clear:function(a){var b=a[c];b&&(delete d[b],a[c]=s)}}};a.b("utils.domData",a.a.f);a.b("utils.domData.clear",a.a.f.clear);a.a.G=new function(){function b(b,c){var f=a.a.f.get(b,d);f===n&&c&&(f=[],a.a.f.set(b,d,f));return f}function c(e){var f=b(e,t);if(f)for(var f=f.slice(0),d=0;d<f.length;d++)f[d](e);a.a.f.clear(e);"function"==typeof jQuery&&"function"==typeof jQuery.cleanData&&
21
- jQuery.cleanData([e]);if(g[e.nodeType])for(f=e.firstChild;e=f;)f=e.nextSibling,8===e.nodeType&&c(e)}var d="__ko_domNodeDisposal__"+(new Date).getTime(),f={1:p,8:p,9:p},g={1:p,9:p};return{wa:function(a,c){"function"!=typeof c&&m(Error("Callback must be a function"));b(a,p).push(c)},Ma:function(c,f){var g=b(c,t);g&&(a.a.ba(g,f),0==g.length&&a.a.f.set(c,d,n))},F:function(b){if(f[b.nodeType]&&(c(b),g[b.nodeType])){var d=[];a.a.N(d,b.getElementsByTagName("*"));for(var b=0,j=d.length;b<j;b++)c(d[b])}},
22
- removeNode:function(b){a.F(b);b.parentNode&&b.parentNode.removeChild(b)}}};a.F=a.a.G.F;a.removeNode=a.a.G.removeNode;a.b("cleanNode",a.F);a.b("removeNode",a.removeNode);a.b("utils.domNodeDisposal",a.a.G);a.b("utils.domNodeDisposal.addDisposeCallback",a.a.G.wa);a.b("utils.domNodeDisposal.removeDisposeCallback",a.a.G.Ma);(function(){a.a.pa=function(b){var c;if("undefined"!=typeof jQuery){if((c=jQuery.clean([b]))&&c[0]){for(b=c[0];b.parentNode&&11!==b.parentNode.nodeType;)b=b.parentNode;b.parentNode&&
23
- b.parentNode.removeChild(b)}}else{var d=a.a.w(b).toLowerCase();c=document.createElement("div");d=d.match(/^<(thead|tbody|tfoot)/)&&[1,"<table>","</table>"]||!d.indexOf("<tr")&&[2,"<table><tbody>","</tbody></table>"]||(!d.indexOf("<td")||!d.indexOf("<th"))&&[3,"<table><tbody><tr>","</tr></tbody></table>"]||[0,"",""];b="ignored<div>"+d[1]+b+d[2]+"</div>";for("function"==typeof window.innerShiv?c.appendChild(window.innerShiv(b)):c.innerHTML=b;d[0]--;)c=c.lastChild;c=a.a.L(c.lastChild.childNodes)}return c};
24
- a.a.Y=function(b,c){a.a.ga(b);if(c!==s&&c!==n)if("string"!=typeof c&&(c=c.toString()),"undefined"!=typeof jQuery)jQuery(b).html(c);else for(var d=a.a.pa(c),f=0;f<d.length;f++)b.appendChild(d[f])}})();a.b("utils.parseHtmlFragment",a.a.pa);a.b("utils.setHtml",a.a.Y);a.s=function(){function b(){return(4294967296*(1+Math.random())|0).toString(16).substring(1)}function c(b,g){if(b)if(8==b.nodeType){var e=a.s.Ja(b.nodeValue);e!=s&&g.push({jb:b,yb:e})}else if(1==b.nodeType)for(var e=0,d=b.childNodes,j=d.length;e<
25
- j;e++)c(d[e],g)}var d={};return{na:function(a){"function"!=typeof a&&m(Error("You can only pass a function to ko.memoization.memoize()"));var c=b()+b();d[c]=a;return"<\!--[ko_memo:"+c+"]--\>"},Va:function(a,b){var c=d[a];c===n&&m(Error("Couldn't find any memo with ID "+a+". Perhaps it's already been unmemoized."));try{return c.apply(s,b||[]),p}finally{delete d[a]}},Wa:function(b,d){var e=[];c(b,e);for(var h=0,j=e.length;h<j;h++){var k=e[h].jb,i=[k];d&&a.a.N(i,d);a.s.Va(e[h].yb,i);k.nodeValue="";k.parentNode&&
26
- k.parentNode.removeChild(k)}},Ja:function(a){return(a=a.match(/^\[ko_memo\:(.*?)\]$/))?a[1]:s}}}();a.b("memoization",a.s);a.b("memoization.memoize",a.s.na);a.b("memoization.unmemoize",a.s.Va);a.b("memoization.parseMemoText",a.s.Ja);a.b("memoization.unmemoizeDomNodeAndDescendants",a.s.Wa);a.Ba={throttle:function(b,c){b.throttleEvaluation=c;var d=s;return a.h({read:b,write:function(a){clearTimeout(d);d=setTimeout(function(){b(a)},c)}})},notify:function(b,c){b.equalityComparer="always"==c?A(t):a.m.fn.equalityComparer;
27
- return b}};a.b("extenders",a.Ba);a.Sa=function(b,c,d){this.target=b;this.ca=c;this.ib=d;a.B(this,"dispose",this.A)};a.Sa.prototype.A=function(){this.sb=p;this.ib()};a.R=function(){this.u={};a.a.extend(this,a.R.fn);a.B(this,"subscribe",this.ta);a.B(this,"extend",this.extend);a.B(this,"getSubscriptionsCount",this.ob)};a.R.fn={ta:function(b,c,d){var d=d||"change",b=c?b.bind(c):b,f=new a.Sa(this,b,function(){a.a.ba(this.u[d],f)}.bind(this));this.u[d]||(this.u[d]=[]);this.u[d].push(f);return f},notifySubscribers:function(b,
28
- c){c=c||"change";this.u[c]&&a.a.v(this.u[c].slice(0),function(a){a&&a.sb!==p&&a.ca(b)})},ob:function(){var a=0,c;for(c in this.u)this.u.hasOwnProperty(c)&&(a+=this.u[c].length);return a},extend:function(b){var c=this;if(b)for(var d in b){var f=a.Ba[d];"function"==typeof f&&(c=f(c,b[d]))}return c}};a.Ga=function(a){return"function"==typeof a.ta&&"function"==typeof a.notifySubscribers};a.b("subscribable",a.R);a.b("isSubscribable",a.Ga);a.U=function(){var b=[];return{bb:function(a){b.push({ca:a,Aa:[]})},
29
- end:function(){b.pop()},La:function(c){a.Ga(c)||m(Error("Only subscribable things can act as dependencies"));if(0<b.length){var d=b[b.length-1];0<=a.a.j(d.Aa,c)||(d.Aa.push(c),d.ca(c))}}}}();var G={undefined:p,"boolean":p,number:p,string:p};a.m=function(b){function c(){if(0<arguments.length){if(!c.equalityComparer||!c.equalityComparer(d,arguments[0]))c.I(),d=arguments[0],c.H();return this}a.U.La(c);return d}var d=b;a.R.call(c);c.H=function(){c.notifySubscribers(d)};c.I=function(){c.notifySubscribers(d,
30
- "beforeChange")};a.a.extend(c,a.m.fn);a.B(c,"valueHasMutated",c.H);a.B(c,"valueWillMutate",c.I);return c};a.m.fn={equalityComparer:function(a,c){return a===s||typeof a in G?a===c:t}};var x=a.m.Db="__ko_proto__";a.m.fn[x]=a.m;a.ia=function(b,c){return b===s||b===n||b[x]===n?t:b[x]===c?p:a.ia(b[x],c)};a.la=function(b){return a.ia(b,a.m)};a.Ha=function(b){return"function"==typeof b&&b[x]===a.m||"function"==typeof b&&b[x]===a.h&&b.pb?p:t};a.b("observable",a.m);a.b("isObservable",a.la);a.b("isWriteableObservable",
31
- a.Ha);a.Q=function(b){0==arguments.length&&(b=[]);b!==s&&(b!==n&&!("length"in b))&&m(Error("The argument passed when initializing an observable array must be an array, or null, or undefined."));var c=a.m(b);a.a.extend(c,a.Q.fn);return c};a.Q.fn={remove:function(a){for(var c=this(),d=[],f="function"==typeof a?a:function(c){return c===a},g=0;g<c.length;g++){var e=c[g];f(e)&&(0===d.length&&this.I(),d.push(e),c.splice(g,1),g--)}d.length&&this.H();return d},removeAll:function(b){if(b===n){var c=this(),
32
- d=c.slice(0);this.I();c.splice(0,c.length);this.H();return d}return!b?[]:this.remove(function(c){return 0<=a.a.j(b,c)})},destroy:function(a){var c=this(),d="function"==typeof a?a:function(c){return c===a};this.I();for(var f=c.length-1;0<=f;f--)d(c[f])&&(c[f]._destroy=p);this.H()},destroyAll:function(b){return b===n?this.destroy(A(p)):!b?[]:this.destroy(function(c){return 0<=a.a.j(b,c)})},indexOf:function(b){var c=this();return a.a.j(c,b)},replace:function(a,c){var d=this.indexOf(a);0<=d&&(this.I(),
33
- this()[d]=c,this.H())}};a.a.v("pop push reverse shift sort splice unshift".split(" "),function(b){a.Q.fn[b]=function(){var a=this();this.I();a=a[b].apply(a,arguments);this.H();return a}});a.a.v(["slice"],function(b){a.Q.fn[b]=function(){var a=this();return a[b].apply(a,arguments)}});a.b("observableArray",a.Q);a.h=function(b,c,d){function f(){a.a.v(v,function(a){a.A()});v=[]}function g(){var a=h.throttleEvaluation;a&&0<=a?(clearTimeout(x),x=setTimeout(e,a)):e()}function e(){if(!l)if(i&&w())u();else{l=
34
- p;try{var b=a.a.T(v,function(a){return a.target});a.U.bb(function(c){var e;0<=(e=a.a.j(b,c))?b[e]=n:v.push(c.ta(g))});for(var e=q.call(c),f=b.length-1;0<=f;f--)b[f]&&v.splice(f,1)[0].A();i=p;h.notifySubscribers(k,"beforeChange");k=e}finally{a.U.end()}h.notifySubscribers(k);l=t}}function h(){if(0<arguments.length)j.apply(h,arguments);else return i||e(),a.U.La(h),k}function j(){"function"===typeof o?o.apply(c,arguments):m(Error("Cannot write a value to a ko.computed unless you specify a 'write' option. If you wish to read the current value, don't pass any parameters."))}
35
- var k,i=t,l=t,q=b;q&&"object"==typeof q?(d=q,q=d.read):(d=d||{},q||(q=d.read));"function"!=typeof q&&m(Error("Pass a function that returns the value of the ko.computed"));var o=d.write;c||(c=d.owner);var v=[],u=f,r="object"==typeof d.disposeWhenNodeIsRemoved?d.disposeWhenNodeIsRemoved:s,w=d.disposeWhen||A(t);if(r){u=function(){a.a.G.Ma(r,arguments.callee);f()};a.a.G.wa(r,u);var y=w,w=function(){return!a.a.fa(r)||y()}}var x=s;h.nb=function(){return v.length};h.pb="function"===typeof d.write;h.A=function(){u()};
36
- a.R.call(h);a.a.extend(h,a.h.fn);d.deferEvaluation!==p&&e();a.B(h,"dispose",h.A);a.B(h,"getDependenciesCount",h.nb);return h};a.rb=function(b){return a.ia(b,a.h)};w=a.m.Db;a.h[w]=a.m;a.h.fn={};a.h.fn[w]=a.h;a.b("dependentObservable",a.h);a.b("computed",a.h);a.b("isComputed",a.rb);(function(){function b(a,g,e){e=e||new d;a=g(a);if(!("object"==typeof a&&a!==s&&a!==n&&!(a instanceof Date)))return a;var h=a instanceof Array?[]:{};e.save(a,h);c(a,function(c){var d=g(a[c]);switch(typeof d){case "boolean":case "number":case "string":case "function":h[c]=
37
- d;break;case "object":case "undefined":var i=e.get(d);h[c]=i!==n?i:b(d,g,e)}});return h}function c(a,b){if(a instanceof Array){for(var c=0;c<a.length;c++)b(c);"function"==typeof a.toJSON&&b("toJSON")}else for(c in a)b(c)}function d(){var b=[],c=[];this.save=function(e,d){var j=a.a.j(b,e);0<=j?c[j]=d:(b.push(e),c.push(d))};this.get=function(e){e=a.a.j(b,e);return 0<=e?c[e]:n}}a.Ta=function(c){0==arguments.length&&m(Error("When calling ko.toJS, pass the object you want to convert."));return b(c,function(b){for(var c=
38
- 0;a.la(b)&&10>c;c++)b=b();return b})};a.toJSON=function(b,c,e){b=a.Ta(b);return a.a.sa(b,c,e)}})();a.b("toJS",a.Ta);a.b("toJSON",a.toJSON);(function(){a.k={r:function(b){switch(a.a.o(b)){case "option":return b.__ko__hasDomDataOptionValue__===p?a.a.f.get(b,a.c.options.oa):b.getAttribute("value");case "select":return 0<=b.selectedIndex?a.k.r(b.options[b.selectedIndex]):n;default:return b.value}},S:function(b,c){switch(a.a.o(b)){case "option":switch(typeof c){case "string":a.a.f.set(b,a.c.options.oa,
39
- n);"__ko__hasDomDataOptionValue__"in b&&delete b.__ko__hasDomDataOptionValue__;b.value=c;break;default:a.a.f.set(b,a.c.options.oa,c),b.__ko__hasDomDataOptionValue__=p,b.value="number"===typeof c?c:""}break;case "select":for(var d=b.options.length-1;0<=d;d--)if(a.k.r(b.options[d])==c){b.selectedIndex=d;break}break;default:if(c===s||c===n)c="";b.value=c}}}})();a.b("selectExtensions",a.k);a.b("selectExtensions.readValue",a.k.r);a.b("selectExtensions.writeValue",a.k.S);a.g=function(){function b(a,b){for(var d=
40
- s;a!=d;)d=a,a=a.replace(c,function(a,c){return b[c]});return a}var c=/\@ko_token_(\d+)\@/g,d=/^[\_$a-z][\_$a-z0-9]*(\[.*?\])*(\.[\_$a-z][\_$a-z0-9]*(\[.*?\])*)*$/i,f=["true","false"];return{D:[],W:function(c){var e=a.a.w(c);if(3>e.length)return[];"{"===e.charAt(0)&&(e=e.substring(1,e.length-1));for(var c=[],d=s,f,k=0;k<e.length;k++){var i=e.charAt(k);if(d===s)switch(i){case '"':case "'":case "/":d=k,f=i}else if(i==f&&"\\"!==e.charAt(k-1)){i=e.substring(d,k+1);c.push(i);var l="@ko_token_"+(c.length-
41
- 1)+"@",e=e.substring(0,d)+l+e.substring(k+1),k=k-(i.length-l.length),d=s}}f=d=s;for(var q=0,o=s,k=0;k<e.length;k++){i=e.charAt(k);if(d===s)switch(i){case "{":d=k;o=i;f="}";break;case "(":d=k;o=i;f=")";break;case "[":d=k,o=i,f="]"}i===o?q++:i===f&&(q--,0===q&&(i=e.substring(d,k+1),c.push(i),l="@ko_token_"+(c.length-1)+"@",e=e.substring(0,d)+l+e.substring(k+1),k-=i.length-l.length,d=s))}f=[];e=e.split(",");d=0;for(k=e.length;d<k;d++)q=e[d],o=q.indexOf(":"),0<o&&o<q.length-1?(i=q.substring(o+1),f.push({key:b(q.substring(0,
42
- o),c),value:b(i,c)})):f.push({unknown:b(q,c)});return f},ka:function(b){for(var c="string"===typeof b?a.g.W(b):b,h=[],b=[],j,k=0;j=c[k];k++)if(0<h.length&&h.push(","),j.key){var i;a:{i=j.key;var l=a.a.w(i);switch(l.length&&l.charAt(0)){case "'":case '"':break a;default:i="'"+l+"'"}}j=j.value;h.push(i);h.push(":");h.push(j);l=a.a.w(j);if(0<=a.a.j(f,a.a.w(l).toLowerCase())?0:l.match(d)!==s)0<b.length&&b.push(", "),b.push(i+" : function(__ko_value) { "+j+" = __ko_value; }")}else j.unknown&&h.push(j.unknown);
43
- c=h.join("");0<b.length&&(c=c+", '_ko_property_writers' : { "+b.join("")+" } ");return c},wb:function(b,c){for(var d=0;d<b.length;d++)if(a.a.w(b[d].key)==c)return p;return t},$:function(b,c,d,f,k){if(!b||!a.Ha(b)){if((b=c()._ko_property_writers)&&b[d])b[d](f)}else(!k||b()!==f)&&b(f)}}}();a.b("jsonExpressionRewriting",a.g);a.b("jsonExpressionRewriting.bindingRewriteValidators",a.g.D);a.b("jsonExpressionRewriting.parseObjectLiteral",a.g.W);a.b("jsonExpressionRewriting.insertPropertyAccessorsIntoJson",
44
- a.g.ka);(function(){function b(a){return 8==a.nodeType&&(g?a.text:a.nodeValue).match(e)}function c(a){return 8==a.nodeType&&(g?a.text:a.nodeValue).match(h)}function d(a,e){for(var d=a,f=1,g=[];d=d.nextSibling;){if(c(d)&&(f--,0===f))return g;g.push(d);b(d)&&f++}e||m(Error("Cannot find closing comment tag to match: "+a.nodeValue));return s}function f(a,b){var c=d(a,b);return c?0<c.length?c[c.length-1].nextSibling:a.nextSibling:s}var g="<\!--test--\>"===document.createComment("test").text,e=g?/^<\!--\s*ko\s+(.*\:.*)\s*--\>$/:
45
- /^\s*ko\s+(.*\:.*)\s*$/,h=g?/^<\!--\s*\/ko\s*--\>$/:/^\s*\/ko\s*$/,j={ul:p,ol:p};a.e={C:{},childNodes:function(a){return b(a)?d(a):a.childNodes},ha:function(c){if(b(c))for(var c=a.e.childNodes(c),e=0,d=c.length;e<d;e++)a.removeNode(c[e]);else a.a.ga(c)},X:function(c,e){if(b(c)){a.e.ha(c);for(var d=c.nextSibling,f=0,g=e.length;f<g;f++)d.parentNode.insertBefore(e[f],d)}else a.a.X(c,e)},Ka:function(a,c){b(a)?a.parentNode.insertBefore(c,a.nextSibling):a.firstChild?a.insertBefore(c,a.firstChild):a.appendChild(c)},
46
- Fa:function(a,c,e){b(a)?a.parentNode.insertBefore(c,e.nextSibling):e.nextSibling?a.insertBefore(c,e.nextSibling):a.appendChild(c)},firstChild:function(a){return!b(a)?a.firstChild:!a.nextSibling||c(a.nextSibling)?s:a.nextSibling},nextSibling:function(a){b(a)&&(a=f(a));return a.nextSibling&&c(a.nextSibling)?s:a.nextSibling},Xa:function(a){return(a=b(a))?a[1]:s},Ia:function(e){if(j[a.a.o(e)]){var d=e.firstChild;if(d){do if(1===d.nodeType){var g;g=d.firstChild;var h=s;if(g){do if(h)h.push(g);else if(b(g)){var o=
47
- f(g,p);o?g=o:h=[g]}else c(g)&&(h=[g]);while(g=g.nextSibling)}if(g=h){h=d.nextSibling;for(o=0;o<g.length;o++)h?e.insertBefore(g[o],h):e.appendChild(g[o])}}while(d=d.nextSibling)}}}}})();a.b("virtualElements",a.e);a.b("virtualElements.allowedBindings",a.e.C);a.b("virtualElements.emptyNode",a.e.ha);a.b("virtualElements.insertAfter",a.e.Fa);a.b("virtualElements.prepend",a.e.Ka);a.b("virtualElements.setDomNodeChildren",a.e.X);(function(){a.J=function(){this.cb={}};a.a.extend(a.J.prototype,{nodeHasBindings:function(b){switch(b.nodeType){case 1:return b.getAttribute("data-bind")!=
48
- s;case 8:return a.e.Xa(b)!=s;default:return t}},getBindings:function(a,c){var d=this.getBindingsString(a,c);return d?this.parseBindingsString(d,c):s},getBindingsString:function(b){switch(b.nodeType){case 1:return b.getAttribute("data-bind");case 8:return a.e.Xa(b);default:return s}},parseBindingsString:function(b,c){try{var d=c.$data,d="object"==typeof d&&d!=s?[d,c]:[c],f=d.length,g=this.cb,e=f+"_"+b,h;if(!(h=g[e])){var j=" { "+a.g.ka(b)+" } ";h=g[e]=a.a.eb(j,f)}return h(d)}catch(k){m(Error("Unable to parse bindings.\nMessage: "+
49
- k+";\nBindings value: "+b))}}});a.J.instance=new a.J})();a.b("bindingProvider",a.J);(function(){function b(b,d,e){for(var h=a.e.firstChild(d);d=h;)h=a.e.nextSibling(d),c(b,d,e)}function c(c,g,e){var h=p,j=1===g.nodeType;j&&a.e.Ia(g);if(j&&e||a.J.instance.nodeHasBindings(g))h=d(g,s,c,e).Gb;h&&b(c,g,!j)}function d(b,c,e,d){function j(a){return function(){return l[a]}}function k(){return l}var i=0,l,q;a.h(function(){var o=e&&e instanceof a.z?e:new a.z(a.a.d(e)),v=o.$data;d&&a.Ra(b,o);if(l=("function"==
50
- typeof c?c():c)||a.J.instance.getBindings(b,o)){if(0===i){i=1;for(var u in l){var r=a.c[u];r&&8===b.nodeType&&!a.e.C[u]&&m(Error("The binding '"+u+"' cannot be used with virtual elements"));if(r&&"function"==typeof r.init&&(r=(0,r.init)(b,j(u),k,v,o))&&r.controlsDescendantBindings)q!==n&&m(Error("Multiple bindings ("+q+" and "+u+") are trying to control descendant bindings of the same element. You cannot use these bindings together on the same element.")),q=u}i=2}if(2===i)for(u in l)(r=a.c[u])&&"function"==
51
- typeof r.update&&(0,r.update)(b,j(u),k,v,o)}},s,{disposeWhenNodeIsRemoved:b});return{Gb:q===n}}a.c={};a.z=function(b,c){c?(a.a.extend(this,c),this.$parentContext=c,this.$parent=c.$data,this.$parents=(c.$parents||[]).slice(0),this.$parents.unshift(this.$parent)):(this.$parents=[],this.$root=b);this.$data=b};a.z.prototype.createChildContext=function(b){return new a.z(b,this)};a.z.prototype.extend=function(b){var c=a.a.extend(new a.z,this);return a.a.extend(c,b)};a.Ra=function(b,c){if(2==arguments.length)a.a.f.set(b,
52
- "__ko_bindingContext__",c);else return a.a.f.get(b,"__ko_bindingContext__")};a.ya=function(b,c,e){1===b.nodeType&&a.e.Ia(b);return d(b,c,e,p)};a.Ya=function(a,c){(1===c.nodeType||8===c.nodeType)&&b(a,c,p)};a.xa=function(a,b){b&&(1!==b.nodeType&&8!==b.nodeType)&&m(Error("ko.applyBindings: first parameter should be your view model; second parameter should be a DOM node"));b=b||window.document.body;c(a,b,p)};a.ea=function(b){switch(b.nodeType){case 1:case 8:var c=a.Ra(b);if(c)return c;if(b.parentNode)return a.ea(b.parentNode)}};
53
- a.hb=function(b){return(b=a.ea(b))?b.$data:n};a.b("bindingHandlers",a.c);a.b("applyBindings",a.xa);a.b("applyBindingsToDescendants",a.Ya);a.b("applyBindingsToNode",a.ya);a.b("contextFor",a.ea);a.b("dataFor",a.hb)})();a.a.v(["click"],function(b){a.c[b]={init:function(c,d,f,g){return a.c.event.init.call(this,c,function(){var a={};a[b]=d();return a},f,g)}}});a.c.event={init:function(b,c,d,f){var g=c()||{},e;for(e in g)(function(){var g=e;"string"==typeof g&&a.a.n(b,g,function(b){var e,i=c()[g];if(i){var l=
54
- d();try{var q=a.a.L(arguments);q.unshift(f);e=i.apply(f,q)}finally{e!==p&&(b.preventDefault?b.preventDefault():b.returnValue=t)}l[g+"Bubble"]===t&&(b.cancelBubble=p,b.stopPropagation&&b.stopPropagation())}})})()}};a.c.submit={init:function(b,c,d,f){"function"!=typeof c()&&m(Error("The value for a submit binding must be a function"));a.a.n(b,"submit",function(a){var e,d=c();try{e=d.call(f,b)}finally{e!==p&&(a.preventDefault?a.preventDefault():a.returnValue=t)}})}};a.c.visible={update:function(b,c){var d=
55
- a.a.d(c()),f="none"!=b.style.display;d&&!f?b.style.display="":!d&&f&&(b.style.display="none")}};a.c.enable={update:function(b,c){var d=a.a.d(c());d&&b.disabled?b.removeAttribute("disabled"):!d&&!b.disabled&&(b.disabled=p)}};a.c.disable={update:function(b,c){a.c.enable.update(b,function(){return!a.a.d(c())})}};a.c.value={init:function(b,c,d){function f(){var e=c(),f=a.k.r(b);a.g.$(e,d,"value",f,p)}var g=["change"],e=d().valueUpdate;e&&("string"==typeof e&&(e=[e]),a.a.N(g,e),g=a.a.za(g));if(a.a.ja&&
56
- ("input"==b.tagName.toLowerCase()&&"text"==b.type&&"off"!=b.autocomplete&&(!b.form||"off"!=b.form.autocomplete))&&-1==a.a.j(g,"propertychange")){var h=t;a.a.n(b,"propertychange",function(){h=p});a.a.n(b,"blur",function(){if(h){h=t;f()}})}a.a.v(g,function(c){var e=f;if(a.a.Hb(c,"after")){e=function(){setTimeout(f,0)};c=c.substring(5)}a.a.n(b,c,e)})},update:function(b,c){var d="select"===a.a.o(b),f=a.a.d(c()),g=a.k.r(b),e=f!=g;0===f&&(0!==g&&"0"!==g)&&(e=p);e&&(g=function(){a.k.S(b,f)},g(),d&&setTimeout(g,
57
- 0));d&&0<b.length&&B(b,f,t)}};a.c.options={update:function(b,c,d){"select"!==a.a.o(b)&&m(Error("options binding applies only to SELECT elements"));for(var f=0==b.length,g=a.a.T(a.a.aa(b.childNodes,function(b){return b.tagName&&"option"===a.a.o(b)&&b.selected}),function(b){return a.k.r(b)||b.innerText||b.textContent}),e=b.scrollTop,h=a.a.d(c());0<b.length;)a.F(b.options[0]),b.remove(0);if(h){d=d();"number"!=typeof h.length&&(h=[h]);if(d.optionsCaption){var j=document.createElement("option");a.a.Y(j,
58
- d.optionsCaption);a.k.S(j,n);b.appendChild(j)}for(var c=0,k=h.length;c<k;c++){var j=document.createElement("option"),i="string"==typeof d.optionsValue?h[c][d.optionsValue]:h[c],i=a.a.d(i);a.k.S(j,i);var l=d.optionsText,i="function"==typeof l?l(h[c]):"string"==typeof l?h[c][l]:i;if(i===s||i===n)i="";a.a.Qa(j,i);b.appendChild(j)}h=b.getElementsByTagName("option");c=j=0;for(k=h.length;c<k;c++)0<=a.a.j(g,a.k.r(h[c]))&&(a.a.Pa(h[c],p),j++);b.scrollTop=e;f&&"value"in d&&B(b,a.a.d(d.value),p);a.a.lb(b)}}};
59
- a.c.options.oa="__ko.optionValueDomData__";a.c.selectedOptions={Ea:function(b){for(var c=[],b=b.childNodes,d=0,f=b.length;d<f;d++){var g=b[d],e=a.a.o(g);"option"==e&&g.selected?c.push(a.k.r(g)):"optgroup"==e&&(g=a.c.selectedOptions.Ea(g),Array.prototype.splice.apply(c,[c.length,0].concat(g)))}return c},init:function(b,c,d){a.a.n(b,"change",function(){var b=c(),g=a.c.selectedOptions.Ea(this);a.g.$(b,d,"value",g)})},update:function(b,c){"select"!=a.a.o(b)&&m(Error("values binding applies only to SELECT elements"));
60
- var d=a.a.d(c());if(d&&"number"==typeof d.length)for(var f=b.childNodes,g=0,e=f.length;g<e;g++){var h=f[g];"option"===a.a.o(h)&&a.a.Pa(h,0<=a.a.j(d,a.k.r(h)))}}};a.c.text={update:function(b,c){a.a.Qa(b,c())}};a.c.html={init:function(){return{controlsDescendantBindings:p}},update:function(b,c){var d=a.a.d(c());a.a.Y(b,d)}};a.c.css={update:function(b,c){var d=a.a.d(c()||{}),f;for(f in d)if("string"==typeof f){var g=a.a.d(d[f]);a.a.Ua(b,f,g)}}};a.c.style={update:function(b,c){var d=a.a.d(c()||{}),f;
61
- for(f in d)if("string"==typeof f){var g=a.a.d(d[f]);b.style[f]=g||""}}};a.c.uniqueName={init:function(b,c){c()&&(b.name="ko_unique_"+ ++a.c.uniqueName.gb,(a.a.tb||a.a.ub)&&b.mergeAttributes(document.createElement("<input name='"+b.name+"'/>"),t))}};a.c.uniqueName.gb=0;a.c.checked={init:function(b,c,d){a.a.n(b,"click",function(){var f;if("checkbox"==b.type)f=b.checked;else if("radio"==b.type&&b.checked)f=b.value;else return;var g=c();"checkbox"==b.type&&a.a.d(g)instanceof Array?(f=a.a.j(a.a.d(g),b.value),
62
- b.checked&&0>f?g.push(b.value):!b.checked&&0<=f&&g.splice(f,1)):a.g.$(g,d,"checked",f,p)});"radio"==b.type&&!b.name&&a.c.uniqueName.init(b,A(p))},update:function(b,c){var d=a.a.d(c());"checkbox"==b.type?b.checked=d instanceof Array?0<=a.a.j(d,b.value):d:"radio"==b.type&&(b.checked=b.value==d)}};var F={"class":"className","for":"htmlFor"};a.c.attr={update:function(b,c){var d=a.a.d(c())||{},f;for(f in d)if("string"==typeof f){var g=a.a.d(d[f]),e=g===t||g===s||g===n;e&&b.removeAttribute(f);8>=a.a.ja&&
63
- f in F?(f=F[f],e?b.removeAttribute(f):b[f]=g):e||b.setAttribute(f,g.toString())}}};a.c.hasfocus={init:function(b,c,d){function f(b){var e=c();a.g.$(e,d,"hasfocus",b,p)}a.a.n(b,"focus",function(){f(p)});a.a.n(b,"focusin",function(){f(p)});a.a.n(b,"blur",function(){f(t)});a.a.n(b,"focusout",function(){f(t)})},update:function(b,c){var d=a.a.d(c());d?b.focus():b.blur();a.a.va(b,d?"focusin":"focusout")}};a.c["with"]={p:function(b){return function(){var c=b();return{"if":c,data:c,templateEngine:a.q.K}}},
64
- init:function(b,c){return a.c.template.init(b,a.c["with"].p(c))},update:function(b,c,d,f,g){return a.c.template.update(b,a.c["with"].p(c),d,f,g)}};a.g.D["with"]=t;a.e.C["with"]=p;a.c["if"]={p:function(b){return function(){return{"if":b(),templateEngine:a.q.K}}},init:function(b,c){return a.c.template.init(b,a.c["if"].p(c))},update:function(b,c,d,f,g){return a.c.template.update(b,a.c["if"].p(c),d,f,g)}};a.g.D["if"]=t;a.e.C["if"]=p;a.c.ifnot={p:function(b){return function(){return{ifnot:b(),templateEngine:a.q.K}}},
65
- init:function(b,c){return a.c.template.init(b,a.c.ifnot.p(c))},update:function(b,c,d,f,g){return a.c.template.update(b,a.c.ifnot.p(c),d,f,g)}};a.g.D.ifnot=t;a.e.C.ifnot=p;a.c.foreach={p:function(b){return function(){var c=a.a.d(b());return!c||"number"==typeof c.length?{foreach:c,templateEngine:a.q.K}:{foreach:c.data,includeDestroyed:c.includeDestroyed,afterAdd:c.afterAdd,beforeRemove:c.beforeRemove,afterRender:c.afterRender,templateEngine:a.q.K}}},init:function(b,c){return a.c.template.init(b,a.c.foreach.p(c))},
66
- update:function(b,c,d,f,g){return a.c.template.update(b,a.c.foreach.p(c),d,f,g)}};a.g.D.foreach=t;a.e.C.foreach=p;a.t=function(){};a.t.prototype.renderTemplateSource=function(){m(Error("Override renderTemplateSource"))};a.t.prototype.createJavaScriptEvaluatorBlock=function(){m(Error("Override createJavaScriptEvaluatorBlock"))};a.t.prototype.makeTemplateSource=function(b,c){if("string"==typeof b){var c=c||document,d=c.getElementById(b);d||m(Error("Cannot find template with ID "+b));return new a.l.i(d)}if(1==
67
- b.nodeType||8==b.nodeType)return new a.l.M(b);m(Error("Unknown template type: "+b))};a.t.prototype.renderTemplate=function(a,c,d,f){return this.renderTemplateSource(this.makeTemplateSource(a,f),c,d)};a.t.prototype.isTemplateRewritten=function(a,c){return this.allowTemplateRewriting===t||!(c&&c!=document)&&this.V&&this.V[a]?p:this.makeTemplateSource(a,c).data("isRewritten")};a.t.prototype.rewriteTemplate=function(a,c,d){var f=this.makeTemplateSource(a,d),c=c(f.text());f.text(c);f.data("isRewritten",
68
- p);!(d&&d!=document)&&"string"==typeof a&&(this.V=this.V||{},this.V[a]=p)};a.b("templateEngine",a.t);a.Z=function(){function b(b,c,e){for(var b=a.g.W(b),d=a.g.D,j=0;j<b.length;j++){var k=b[j].key;if(d.hasOwnProperty(k)){var i=d[k];"function"===typeof i?(k=i(b[j].value))&&m(Error(k)):i||m(Error("This template engine does not support the '"+k+"' binding within its templates"))}}b="ko.templateRewriting.applyMemoizedBindingsToNextSibling(function() { return (function() { return { "+a.g.ka(b)+
69
- " } })() })";return e.createJavaScriptEvaluatorBlock(b)+c}var c=/(<[a-z]+\d*(\s+(?!data-bind=)[a-z0-9\-]+(=(\"[^\"]*\"|\'[^\']*\'))?)*\s+)data-bind=(["'])([\s\S]*?)\5/gi,d=/<\!--\s*ko\b\s*([\s\S]*?)\s*--\>/g;return{mb:function(b,c,e){c.isTemplateRewritten(b,e)||c.rewriteTemplate(b,function(b){return a.Z.zb(b,c)},e)},zb:function(a,g){return a.replace(c,function(a,c,d,f,i,l,q){return b(q,c,g)}).replace(d,function(a,c){return b(c,"<\!-- ko --\>",g)})},Za:function(b){return a.s.na(function(c,
70
- e){c.nextSibling&&a.ya(c.nextSibling,b,e)})}}}();a.b("templateRewriting",a.Z);a.b("templateRewriting.applyMemoizedBindingsToNextSibling",a.Z.Za);(function(){a.l={};a.l.i=function(a){this.i=a};a.l.i.prototype.text=function(){var b=a.a.o(this.i),b="script"===b?"text":"textarea"===b?"value":"innerHTML";if(0==arguments.length)return this.i[b];var c=arguments[0];"innerHTML"===b?a.a.Y(this.i,c):this.i[b]=c};a.l.i.prototype.data=function(b){if(1===arguments.length)return a.a.f.get(this.i,"templateSourceData_"+
71
- b);a.a.f.set(this.i,"templateSourceData_"+b,arguments[1])};a.l.M=function(a){this.i=a};a.l.M.prototype=new a.l.i;a.l.M.prototype.text=function(){if(0==arguments.length){var b=a.a.f.get(this.i,"__ko_anon_template__")||{};b.ua===n&&b.da&&(b.ua=b.da.innerHTML);return b.ua}a.a.f.set(this.i,"__ko_anon_template__",{ua:arguments[0]})};a.l.i.prototype.nodes=function(){if(0==arguments.length)return(a.a.f.get(this.i,"__ko_anon_template__")||{}).da;a.a.f.set(this.i,"__ko_anon_template__",{da:arguments[0]})};
72
- a.b("templateSources",a.l);a.b("templateSources.domElement",a.l.i);a.b("templateSources.anonymousTemplate",a.l.M)})();(function(){function b(b,c,d){for(var f,c=a.e.nextSibling(c);b&&(f=b)!==c;)b=a.e.nextSibling(f),(1===f.nodeType||8===f.nodeType)&&d(f)}function c(c,d){if(c.length){var f=c[0],g=c[c.length-1];b(f,g,function(b){a.xa(d,b)});b(f,g,function(b){a.s.Wa(b,[d])})}}function d(a){return a.nodeType?a:0<a.length?a[0]:s}function f(b,f,j,k,i){var i=i||{},l=b&&d(b),l=l&&l.ownerDocument,q=i.templateEngine||
73
- g;a.Z.mb(j,q,l);j=q.renderTemplate(j,k,i,l);("number"!=typeof j.length||0<j.length&&"number"!=typeof j[0].nodeType)&&m(Error("Template engine must return an array of DOM nodes"));l=t;switch(f){case "replaceChildren":a.e.X(b,j);l=p;break;case "replaceNode":a.a.Na(b,j);l=p;break;case "ignoreTargetNode":break;default:m(Error("Unknown renderMode: "+f))}l&&(c(j,k),i.afterRender&&i.afterRender(j,k.$data));return j}var g;a.ra=function(b){b!=n&&!(b instanceof a.t)&&m(Error("templateEngine must inherit from ko.templateEngine"));
74
- g=b};a.qa=function(b,c,j,k,i){j=j||{};(j.templateEngine||g)==n&&m(Error("Set a template engine before calling renderTemplate"));i=i||"replaceChildren";if(k){var l=d(k);return a.h(function(){var g=c&&c instanceof a.z?c:new a.z(a.a.d(c)),o="function"==typeof b?b(g.$data):b,g=f(k,i,o,g,j);"replaceNode"==i&&(k=g,l=d(k))},s,{disposeWhen:function(){return!l||!a.a.fa(l)},disposeWhenNodeIsRemoved:l&&"replaceNode"==i?l.parentNode:l})}return a.s.na(function(d){a.qa(b,c,j,d,"replaceNode")})};a.Fb=function(b,
75
- d,g,k,i){function l(a,b){c(b,o);g.afterRender&&g.afterRender(b,a)}function q(c,d){var h="function"==typeof b?b(c):b;o=i.createChildContext(a.a.d(c));o.$index=d;return f(s,"ignoreTargetNode",h,o,g)}var o;return a.h(function(){var b=a.a.d(d)||[];"undefined"==typeof b.length&&(b=[b]);b=a.a.aa(b,function(b){return g.includeDestroyed||b===n||b===s||!a.a.d(b._destroy)});a.a.Oa(k,b,q,g,l)},s,{disposeWhenNodeIsRemoved:k})};a.c.template={init:function(b,c){var d=a.a.d(c());if("string"!=typeof d&&!d.name&&
76
- (1==b.nodeType||8==b.nodeType))d=1==b.nodeType?b.childNodes:a.e.childNodes(b),d=a.a.Ab(d),(new a.l.M(b)).nodes(d);return{controlsDescendantBindings:p}},update:function(b,c,d,f,g){c=a.a.d(c());f=p;"string"==typeof c?d=c:(d=c.name,"if"in c&&(f=f&&a.a.d(c["if"])),"ifnot"in c&&(f=f&&!a.a.d(c.ifnot)));var l=s;"object"===typeof c&&"foreach"in c?l=a.Fb(d||b,f&&c.foreach||[],c,b,g):f?(g="object"==typeof c&&"data"in c?g.createChildContext(a.a.d(c.data)):g,l=a.qa(d||b,g,c,b)):a.e.ha(b);g=l;(c=a.a.f.get(b,"__ko__templateSubscriptionDomDataKey__"))&&
77
- "function"==typeof c.A&&c.A();a.a.f.set(b,"__ko__templateSubscriptionDomDataKey__",g)}};a.g.D.template=function(b){b=a.g.W(b);return 1==b.length&&b[0].unknown||a.g.wb(b,"name")?s:"This template engine does not support anonymous templates nested within its templates"};a.e.C.template=p})();a.b("setTemplateEngine",a.ra);a.b("renderTemplate",a.qa);(function(){a.a.O=function(b,c,d){if(d===n)return a.a.O(b,c,1)||a.a.O(b,c,10)||a.a.O(b,c,Number.MAX_VALUE);for(var b=b||[],c=c||[],f=b,g=c,e=[],h=0;h<=g.length;h++)e[h]=
78
- [];for(var h=0,j=Math.min(f.length,d);h<=j;h++)e[0][h]=h;h=1;for(j=Math.min(g.length,d);h<=j;h++)e[h][0]=h;for(var j=f.length,k,i=g.length,h=1;h<=j;h++){k=Math.max(1,h-d);for(var l=Math.min(i,h+d);k<=l;k++)e[k][h]=f[h-1]===g[k-1]?e[k-1][h-1]:Math.min(e[k-1][h]===n?Number.MAX_VALUE:e[k-1][h]+1,e[k][h-1]===n?Number.MAX_VALUE:e[k][h-1]+1)}d=b.length;f=c.length;g=[];h=e[f][d];if(h===n)e=s;else{for(;0<d||0<f;){j=e[f][d];i=0<f?e[f-1][d]:h+1;l=0<d?e[f][d-1]:h+1;k=0<f&&0<d?e[f-1][d-1]:h+1;if(i===n||i<j-1)i=
79
- h+1;if(l===n||l<j-1)l=h+1;k<j-1&&(k=h+1);i<=l&&i<k?(g.push({status:"added",value:c[f-1]}),f--):(l<i&&l<k?g.push({status:"deleted",value:b[d-1]}):(g.push({status:"retained",value:b[d-1]}),f--),d--)}e=g.reverse()}return e}})();a.b("utils.compareArrays",a.a.O);(function(){function b(a){if(2<a.length){for(var b=a[0],c=a[a.length-1],e=[b];b!==c;){b=b.nextSibling;if(!b)return;e.push(b)}Array.prototype.splice.apply(a,[0,a.length].concat(e))}}function c(c,f,g,e,h){var j=[],c=a.h(function(){var c=f(g,h)||
80
- [];0<j.length&&(b(j),a.a.Na(j,c),e&&e(g,c));j.splice(0,j.length);a.a.N(j,c)},s,{disposeWhenNodeIsRemoved:c,disposeWhen:function(){return 0==j.length||!a.a.fa(j[0])}});return{xb:j,h:c}}a.a.Oa=function(d,f,g,e,h){for(var f=f||[],e=e||{},j=a.a.f.get(d,"setDomNodeChildrenFromArrayMapping_lastMappingResult")===n,k=a.a.f.get(d,"setDomNodeChildrenFromArrayMapping_lastMappingResult")||[],i=a.a.T(k,function(a){return a.$a}),l=a.a.O(i,f),f=[],q=0,o=[],v=0,i=[],u=s,r=0,w=l.length;r<w;r++)switch(l[r].status){case "retained":var y=
81
- k[q];y.qb(v);v=f.push(y);0<y.P.length&&(u=y.P[y.P.length-1]);q++;break;case "deleted":k[q].h.A();b(k[q].P);a.a.v(k[q].P,function(a){o.push({element:a,index:r,value:l[r].value});u=a});q++;break;case "added":for(var y=l[r].value,x=a.m(v),v=c(d,g,y,h,x),C=v.xb,v=f.push({$a:l[r].value,P:C,h:v.h,qb:x}),z=0,B=C.length;z<B;z++){var D=C[z];i.push({element:D,index:r,value:l[r].value});u==s?a.e.Ka(d,D):a.e.Fa(d,D,u);u=D}h&&h(y,C,x)}a.a.v(o,function(b){a.F(b.element)});g=t;if(!j){if(e.afterAdd)for(r=0;r<i.length;r++)e.afterAdd(i[r].element,
82
- i[r].index,i[r].value);if(e.beforeRemove){for(r=0;r<o.length;r++)e.beforeRemove(o[r].element,o[r].index,o[r].value);g=p}}if(!g&&o.length)for(r=0;r<o.length;r++)e=o[r].element,e.parentNode&&e.parentNode.removeChild(e);a.a.f.set(d,"setDomNodeChildrenFromArrayMapping_lastMappingResult",f)}})();a.b("utils.setDomNodeChildrenFromArrayMapping",a.a.Oa);a.q=function(){this.allowTemplateRewriting=t};a.q.prototype=new a.t;a.q.prototype.renderTemplateSource=function(b){var c=!(9>a.a.ja)&&b.nodes?b.nodes():s;
83
- if(c)return a.a.L(c.cloneNode(p).childNodes);b=b.text();return a.a.pa(b)};a.q.K=new a.q;a.ra(a.q.K);a.b("nativeTemplateEngine",a.q);(function(){a.ma=function(){var a=this.vb=function(){if("undefined"==typeof jQuery||!jQuery.tmpl)return 0;try{if(0<=jQuery.tmpl.tag.tmpl.open.toString().indexOf("__"))return 2}catch(a){}return 1}();this.renderTemplateSource=function(b,f,g){g=g||{};2>a&&m(Error("Your version of jQuery.tmpl is too old. Please upgrade to jQuery.tmpl 1.0.0pre or later."));var e=b.data("precompiled");
84
- e||(e=b.text()||"",e=jQuery.template(s,"{{ko_with $item.koBindingContext}}"+e+"{{/ko_with}}"),b.data("precompiled",e));b=[f.$data];f=jQuery.extend({koBindingContext:f},g.templateOptions);f=jQuery.tmpl(e,b,f);f.appendTo(document.createElement("div"));jQuery.fragments={};return f};this.createJavaScriptEvaluatorBlock=function(a){return"{{ko_code ((function() { return "+a+" })()) }}"};this.addTemplate=function(a,b){document.write("<script type='text/html' id='"+a+"'>"+b+"<\/script>")};0<a&&(jQuery.tmpl.tag.ko_code=
85
- {open:"__.push($1 || '');"},jQuery.tmpl.tag.ko_with={open:"with($1) {",close:"} "})};a.ma.prototype=new a.t;var b=new a.ma;0<b.vb&&a.ra(b);a.b("jqueryTmplTemplateEngine",a.ma)})()}"function"===typeof require&&"object"===typeof exports&&"object"===typeof module?E(module.exports||exports):"function"===typeof define&&define.amd?define(["exports"],E):E(window.ko={});p;
86
- })(window,document,navigator);
5
+ (function(){
6
+ var DEBUG=true;
7
+ (function(window,document,navigator,jQuery,undefined){
8
+ !function(factory) {
9
+ // Support three module loading scenarios
10
+ if (typeof require === 'function' && typeof exports === 'object' && typeof module === 'object') {
11
+ // [1] CommonJS/Node.js
12
+ var target = module['exports'] || exports; // module.exports is for Node.js
13
+ factory(target);
14
+ } else if (typeof define === 'function' && define['amd']) {
15
+ // [2] AMD anonymous module
16
+ define(['exports'], factory);
17
+ } else {
18
+ // [3] No module loader (plain <script> tag) - put directly in global namespace
19
+ factory(window['ko'] = {});
20
+ }
21
+ }(function(koExports){
22
+ // Internally, all KO objects are attached to koExports (even the non-exported ones whose names will be minified by the closure compiler).
23
+ // In the future, the following "ko" variable may be made distinct from "koExports" so that private objects are not externally reachable.
24
+ var ko = typeof koExports !== 'undefined' ? koExports : {};
25
+ // Google Closure Compiler helpers (used only to make the minified file smaller)
26
+ ko.exportSymbol = function(koPath, object) {
27
+ var tokens = koPath.split(".");
28
+
29
+ // In the future, "ko" may become distinct from "koExports" (so that non-exported objects are not reachable)
30
+ // At that point, "target" would be set to: (typeof koExports !== "undefined" ? koExports : ko)
31
+ var target = ko;
32
+
33
+ for (var i = 0; i < tokens.length - 1; i++)
34
+ target = target[tokens[i]];
35
+ target[tokens[tokens.length - 1]] = object;
36
+ };
37
+ ko.exportProperty = function(owner, publicName, object) {
38
+ owner[publicName] = object;
39
+ };
40
+ ko.version = "2.2.0";
41
+
42
+ ko.exportSymbol('version', ko.version);
43
+ ko.utils = new (function () {
44
+ var stringTrimRegex = /^(\s|\u00A0)+|(\s|\u00A0)+$/g;
45
+
46
+ // Represent the known event types in a compact way, then at runtime transform it into a hash with event name as key (for fast lookup)
47
+ var knownEvents = {}, knownEventTypesByEventName = {};
48
+ var keyEventTypeName = /Firefox\/2/i.test(navigator.userAgent) ? 'KeyboardEvent' : 'UIEvents';
49
+ knownEvents[keyEventTypeName] = ['keyup', 'keydown', 'keypress'];
50
+ knownEvents['MouseEvents'] = ['click', 'dblclick', 'mousedown', 'mouseup', 'mousemove', 'mouseover', 'mouseout', 'mouseenter', 'mouseleave'];
51
+ for (var eventType in knownEvents) {
52
+ var knownEventsForType = knownEvents[eventType];
53
+ if (knownEventsForType.length) {
54
+ for (var i = 0, j = knownEventsForType.length; i < j; i++)
55
+ knownEventTypesByEventName[knownEventsForType[i]] = eventType;
56
+ }
57
+ }
58
+ var eventsThatMustBeRegisteredUsingAttachEvent = { 'propertychange': true }; // Workaround for an IE9 issue - https://github.com/SteveSanderson/knockout/issues/406
59
+
60
+ // Detect IE versions for bug workarounds (uses IE conditionals, not UA string, for robustness)
61
+ // Note that, since IE 10 does not support conditional comments, the following logic only detects IE < 10.
62
+ // Currently this is by design, since IE 10+ behaves correctly when treated as a standard browser.
63
+ // If there is a future need to detect specific versions of IE10+, we will amend this.
64
+ var ieVersion = (function() {
65
+ var version = 3, div = document.createElement('div'), iElems = div.getElementsByTagName('i');
66
+
67
+ // Keep constructing conditional HTML blocks until we hit one that resolves to an empty fragment
68
+ while (
69
+ div.innerHTML = '<!--[if gt IE ' + (++version) + ']><i></i><![endif]-->',
70
+ iElems[0]
71
+ );
72
+ return version > 4 ? version : undefined;
73
+ }());
74
+ var isIe6 = ieVersion === 6,
75
+ isIe7 = ieVersion === 7;
76
+
77
+ function isClickOnCheckableElement(element, eventType) {
78
+ if ((ko.utils.tagNameLower(element) !== "input") || !element.type) return false;
79
+ if (eventType.toLowerCase() != "click") return false;
80
+ var inputType = element.type;
81
+ return (inputType == "checkbox") || (inputType == "radio");
82
+ }
83
+
84
+ return {
85
+ fieldsIncludedWithJsonPost: ['authenticity_token', /^__RequestVerificationToken(_.*)?$/],
86
+
87
+ arrayForEach: function (array, action) {
88
+ for (var i = 0, j = array.length; i < j; i++)
89
+ action(array[i]);
90
+ },
91
+
92
+ arrayIndexOf: function (array, item) {
93
+ if (typeof Array.prototype.indexOf == "function")
94
+ return Array.prototype.indexOf.call(array, item);
95
+ for (var i = 0, j = array.length; i < j; i++)
96
+ if (array[i] === item)
97
+ return i;
98
+ return -1;
99
+ },
100
+
101
+ arrayFirst: function (array, predicate, predicateOwner) {
102
+ for (var i = 0, j = array.length; i < j; i++)
103
+ if (predicate.call(predicateOwner, array[i]))
104
+ return array[i];
105
+ return null;
106
+ },
107
+
108
+ arrayRemoveItem: function (array, itemToRemove) {
109
+ var index = ko.utils.arrayIndexOf(array, itemToRemove);
110
+ if (index >= 0)
111
+ array.splice(index, 1);
112
+ },
113
+
114
+ arrayGetDistinctValues: function (array) {
115
+ array = array || [];
116
+ var result = [];
117
+ for (var i = 0, j = array.length; i < j; i++) {
118
+ if (ko.utils.arrayIndexOf(result, array[i]) < 0)
119
+ result.push(array[i]);
120
+ }
121
+ return result;
122
+ },
123
+
124
+ arrayMap: function (array, mapping) {
125
+ array = array || [];
126
+ var result = [];
127
+ for (var i = 0, j = array.length; i < j; i++)
128
+ result.push(mapping(array[i]));
129
+ return result;
130
+ },
131
+
132
+ arrayFilter: function (array, predicate) {
133
+ array = array || [];
134
+ var result = [];
135
+ for (var i = 0, j = array.length; i < j; i++)
136
+ if (predicate(array[i]))
137
+ result.push(array[i]);
138
+ return result;
139
+ },
140
+
141
+ arrayPushAll: function (array, valuesToPush) {
142
+ if (valuesToPush instanceof Array)
143
+ array.push.apply(array, valuesToPush);
144
+ else
145
+ for (var i = 0, j = valuesToPush.length; i < j; i++)
146
+ array.push(valuesToPush[i]);
147
+ return array;
148
+ },
149
+
150
+ extend: function (target, source) {
151
+ if (source) {
152
+ for(var prop in source) {
153
+ if(source.hasOwnProperty(prop)) {
154
+ target[prop] = source[prop];
155
+ }
156
+ }
157
+ }
158
+ return target;
159
+ },
160
+
161
+ emptyDomNode: function (domNode) {
162
+ while (domNode.firstChild) {
163
+ ko.removeNode(domNode.firstChild);
164
+ }
165
+ },
166
+
167
+ moveCleanedNodesToContainerElement: function(nodes) {
168
+ // Ensure it's a real array, as we're about to reparent the nodes and
169
+ // we don't want the underlying collection to change while we're doing that.
170
+ var nodesArray = ko.utils.makeArray(nodes);
171
+
172
+ var container = document.createElement('div');
173
+ for (var i = 0, j = nodesArray.length; i < j; i++) {
174
+ container.appendChild(ko.cleanNode(nodesArray[i]));
175
+ }
176
+ return container;
177
+ },
178
+
179
+ cloneNodes: function (nodesArray, shouldCleanNodes) {
180
+ for (var i = 0, j = nodesArray.length, newNodesArray = []; i < j; i++) {
181
+ var clonedNode = nodesArray[i].cloneNode(true);
182
+ newNodesArray.push(shouldCleanNodes ? ko.cleanNode(clonedNode) : clonedNode);
183
+ }
184
+ return newNodesArray;
185
+ },
186
+
187
+ setDomNodeChildren: function (domNode, childNodes) {
188
+ ko.utils.emptyDomNode(domNode);
189
+ if (childNodes) {
190
+ for (var i = 0, j = childNodes.length; i < j; i++)
191
+ domNode.appendChild(childNodes[i]);
192
+ }
193
+ },
194
+
195
+ replaceDomNodes: function (nodeToReplaceOrNodeArray, newNodesArray) {
196
+ var nodesToReplaceArray = nodeToReplaceOrNodeArray.nodeType ? [nodeToReplaceOrNodeArray] : nodeToReplaceOrNodeArray;
197
+ if (nodesToReplaceArray.length > 0) {
198
+ var insertionPoint = nodesToReplaceArray[0];
199
+ var parent = insertionPoint.parentNode;
200
+ for (var i = 0, j = newNodesArray.length; i < j; i++)
201
+ parent.insertBefore(newNodesArray[i], insertionPoint);
202
+ for (var i = 0, j = nodesToReplaceArray.length; i < j; i++) {
203
+ ko.removeNode(nodesToReplaceArray[i]);
204
+ }
205
+ }
206
+ },
207
+
208
+ setOptionNodeSelectionState: function (optionNode, isSelected) {
209
+ // IE6 sometimes throws "unknown error" if you try to write to .selected directly, whereas Firefox struggles with setAttribute. Pick one based on browser.
210
+ if (ieVersion < 7)
211
+ optionNode.setAttribute("selected", isSelected);
212
+ else
213
+ optionNode.selected = isSelected;
214
+ },
215
+
216
+ stringTrim: function (string) {
217
+ return (string || "").replace(stringTrimRegex, "");
218
+ },
219
+
220
+ stringTokenize: function (string, delimiter) {
221
+ var result = [];
222
+ var tokens = (string || "").split(delimiter);
223
+ for (var i = 0, j = tokens.length; i < j; i++) {
224
+ var trimmed = ko.utils.stringTrim(tokens[i]);
225
+ if (trimmed !== "")
226
+ result.push(trimmed);
227
+ }
228
+ return result;
229
+ },
230
+
231
+ stringStartsWith: function (string, startsWith) {
232
+ string = string || "";
233
+ if (startsWith.length > string.length)
234
+ return false;
235
+ return string.substring(0, startsWith.length) === startsWith;
236
+ },
237
+
238
+ domNodeIsContainedBy: function (node, containedByNode) {
239
+ if (containedByNode.compareDocumentPosition)
240
+ return (containedByNode.compareDocumentPosition(node) & 16) == 16;
241
+ while (node != null) {
242
+ if (node == containedByNode)
243
+ return true;
244
+ node = node.parentNode;
245
+ }
246
+ return false;
247
+ },
248
+
249
+ domNodeIsAttachedToDocument: function (node) {
250
+ return ko.utils.domNodeIsContainedBy(node, node.ownerDocument);
251
+ },
252
+
253
+ tagNameLower: function(element) {
254
+ // For HTML elements, tagName will always be upper case; for XHTML elements, it'll be lower case.
255
+ // Possible future optimization: If we know it's an element from an XHTML document (not HTML),
256
+ // we don't need to do the .toLowerCase() as it will always be lower case anyway.
257
+ return element && element.tagName && element.tagName.toLowerCase();
258
+ },
259
+
260
+ registerEventHandler: function (element, eventType, handler) {
261
+ var mustUseAttachEvent = ieVersion && eventsThatMustBeRegisteredUsingAttachEvent[eventType];
262
+ if (!mustUseAttachEvent && typeof jQuery != "undefined") {
263
+ if (isClickOnCheckableElement(element, eventType)) {
264
+ // For click events on checkboxes, jQuery interferes with the event handling in an awkward way:
265
+ // it toggles the element checked state *after* the click event handlers run, whereas native
266
+ // click events toggle the checked state *before* the event handler.
267
+ // Fix this by intecepting the handler and applying the correct checkedness before it runs.
268
+ var originalHandler = handler;
269
+ handler = function(event, eventData) {
270
+ var jQuerySuppliedCheckedState = this.checked;
271
+ if (eventData)
272
+ this.checked = eventData.checkedStateBeforeEvent !== true;
273
+ originalHandler.call(this, event);
274
+ this.checked = jQuerySuppliedCheckedState; // Restore the state jQuery applied
275
+ };
276
+ }
277
+ jQuery(element)['bind'](eventType, handler);
278
+ } else if (!mustUseAttachEvent && typeof element.addEventListener == "function")
279
+ element.addEventListener(eventType, handler, false);
280
+ else if (typeof element.attachEvent != "undefined")
281
+ element.attachEvent("on" + eventType, function (event) {
282
+ handler.call(element, event);
283
+ });
284
+ else
285
+ throw new Error("Browser doesn't support addEventListener or attachEvent");
286
+ },
287
+
288
+ triggerEvent: function (element, eventType) {
289
+ if (!(element && element.nodeType))
290
+ throw new Error("element must be a DOM node when calling triggerEvent");
291
+
292
+ if (typeof jQuery != "undefined") {
293
+ var eventData = [];
294
+ if (isClickOnCheckableElement(element, eventType)) {
295
+ // Work around the jQuery "click events on checkboxes" issue described above by storing the original checked state before triggering the handler
296
+ eventData.push({ checkedStateBeforeEvent: element.checked });
297
+ }
298
+ jQuery(element)['trigger'](eventType, eventData);
299
+ } else if (typeof document.createEvent == "function") {
300
+ if (typeof element.dispatchEvent == "function") {
301
+ var eventCategory = knownEventTypesByEventName[eventType] || "HTMLEvents";
302
+ var event = document.createEvent(eventCategory);
303
+ event.initEvent(eventType, true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, element);
304
+ element.dispatchEvent(event);
305
+ }
306
+ else
307
+ throw new Error("The supplied element doesn't support dispatchEvent");
308
+ } else if (typeof element.fireEvent != "undefined") {
309
+ // Unlike other browsers, IE doesn't change the checked state of checkboxes/radiobuttons when you trigger their "click" event
310
+ // so to make it consistent, we'll do it manually here
311
+ if (isClickOnCheckableElement(element, eventType))
312
+ element.checked = element.checked !== true;
313
+ element.fireEvent("on" + eventType);
314
+ }
315
+ else
316
+ throw new Error("Browser doesn't support triggering events");
317
+ },
318
+
319
+ unwrapObservable: function (value) {
320
+ return ko.isObservable(value) ? value() : value;
321
+ },
322
+
323
+ peekObservable: function (value) {
324
+ return ko.isObservable(value) ? value.peek() : value;
325
+ },
326
+
327
+ toggleDomNodeCssClass: function (node, classNames, shouldHaveClass) {
328
+ if (classNames) {
329
+ var cssClassNameRegex = /[\w-]+/g,
330
+ currentClassNames = node.className.match(cssClassNameRegex) || [];
331
+ ko.utils.arrayForEach(classNames.match(cssClassNameRegex), function(className) {
332
+ var indexOfClass = ko.utils.arrayIndexOf(currentClassNames, className);
333
+ if (indexOfClass >= 0) {
334
+ if (!shouldHaveClass)
335
+ currentClassNames.splice(indexOfClass, 1);
336
+ } else {
337
+ if (shouldHaveClass)
338
+ currentClassNames.push(className);
339
+ }
340
+ });
341
+ node.className = currentClassNames.join(" ");
342
+ }
343
+ },
344
+
345
+ setTextContent: function(element, textContent) {
346
+ var value = ko.utils.unwrapObservable(textContent);
347
+ if ((value === null) || (value === undefined))
348
+ value = "";
349
+
350
+ if (element.nodeType === 3) {
351
+ element.data = value;
352
+ } else {
353
+ // We need there to be exactly one child: a text node.
354
+ // If there are no children, more than one, or if it's not a text node,
355
+ // we'll clear everything and create a single text node.
356
+ var innerTextNode = ko.virtualElements.firstChild(element);
357
+ if (!innerTextNode || innerTextNode.nodeType != 3 || ko.virtualElements.nextSibling(innerTextNode)) {
358
+ ko.virtualElements.setDomNodeChildren(element, [document.createTextNode(value)]);
359
+ } else {
360
+ innerTextNode.data = value;
361
+ }
362
+
363
+ ko.utils.forceRefresh(element);
364
+ }
365
+ },
366
+
367
+ setElementName: function(element, name) {
368
+ element.name = name;
369
+
370
+ // Workaround IE 6/7 issue
371
+ // - https://github.com/SteveSanderson/knockout/issues/197
372
+ // - http://www.matts411.com/post/setting_the_name_attribute_in_ie_dom/
373
+ if (ieVersion <= 7) {
374
+ try {
375
+ element.mergeAttributes(document.createElement("<input name='" + element.name + "'/>"), false);
376
+ }
377
+ catch(e) {} // For IE9 with doc mode "IE9 Standards" and browser mode "IE9 Compatibility View"
378
+ }
379
+ },
380
+
381
+ forceRefresh: function(node) {
382
+ // Workaround for an IE9 rendering bug - https://github.com/SteveSanderson/knockout/issues/209
383
+ if (ieVersion >= 9) {
384
+ // For text nodes and comment nodes (most likely virtual elements), we will have to refresh the container
385
+ var elem = node.nodeType == 1 ? node : node.parentNode;
386
+ if (elem.style)
387
+ elem.style.zoom = elem.style.zoom;
388
+ }
389
+ },
390
+
391
+ ensureSelectElementIsRenderedCorrectly: function(selectElement) {
392
+ // Workaround for IE9 rendering bug - it doesn't reliably display all the text in dynamically-added select boxes unless you force it to re-render by updating the width.
393
+ // (See https://github.com/SteveSanderson/knockout/issues/312, http://stackoverflow.com/questions/5908494/select-only-shows-first-char-of-selected-option)
394
+ if (ieVersion >= 9) {
395
+ var originalWidth = selectElement.style.width;
396
+ selectElement.style.width = 0;
397
+ selectElement.style.width = originalWidth;
398
+ }
399
+ },
400
+
401
+ range: function (min, max) {
402
+ min = ko.utils.unwrapObservable(min);
403
+ max = ko.utils.unwrapObservable(max);
404
+ var result = [];
405
+ for (var i = min; i <= max; i++)
406
+ result.push(i);
407
+ return result;
408
+ },
409
+
410
+ makeArray: function(arrayLikeObject) {
411
+ var result = [];
412
+ for (var i = 0, j = arrayLikeObject.length; i < j; i++) {
413
+ result.push(arrayLikeObject[i]);
414
+ };
415
+ return result;
416
+ },
417
+
418
+ isIe6 : isIe6,
419
+ isIe7 : isIe7,
420
+ ieVersion : ieVersion,
421
+
422
+ getFormFields: function(form, fieldName) {
423
+ var fields = ko.utils.makeArray(form.getElementsByTagName("input")).concat(ko.utils.makeArray(form.getElementsByTagName("textarea")));
424
+ var isMatchingField = (typeof fieldName == 'string')
425
+ ? function(field) { return field.name === fieldName }
426
+ : function(field) { return fieldName.test(field.name) }; // Treat fieldName as regex or object containing predicate
427
+ var matches = [];
428
+ for (var i = fields.length - 1; i >= 0; i--) {
429
+ if (isMatchingField(fields[i]))
430
+ matches.push(fields[i]);
431
+ };
432
+ return matches;
433
+ },
434
+
435
+ parseJson: function (jsonString) {
436
+ if (typeof jsonString == "string") {
437
+ jsonString = ko.utils.stringTrim(jsonString);
438
+ if (jsonString) {
439
+ if (window.JSON && window.JSON.parse) // Use native parsing where available
440
+ return window.JSON.parse(jsonString);
441
+ return (new Function("return " + jsonString))(); // Fallback on less safe parsing for older browsers
442
+ }
443
+ }
444
+ return null;
445
+ },
446
+
447
+ stringifyJson: function (data, replacer, space) { // replacer and space are optional
448
+ if ((typeof JSON == "undefined") || (typeof JSON.stringify == "undefined"))
449
+ 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");
450
+ return JSON.stringify(ko.utils.unwrapObservable(data), replacer, space);
451
+ },
452
+
453
+ postJson: function (urlOrForm, data, options) {
454
+ options = options || {};
455
+ var params = options['params'] || {};
456
+ var includeFields = options['includeFields'] || this.fieldsIncludedWithJsonPost;
457
+ var url = urlOrForm;
458
+
459
+ // If we were given a form, use its 'action' URL and pick out any requested field values
460
+ if((typeof urlOrForm == 'object') && (ko.utils.tagNameLower(urlOrForm) === "form")) {
461
+ var originalForm = urlOrForm;
462
+ url = originalForm.action;
463
+ for (var i = includeFields.length - 1; i >= 0; i--) {
464
+ var fields = ko.utils.getFormFields(originalForm, includeFields[i]);
465
+ for (var j = fields.length - 1; j >= 0; j--)
466
+ params[fields[j].name] = fields[j].value;
467
+ }
468
+ }
469
+
470
+ data = ko.utils.unwrapObservable(data);
471
+ var form = document.createElement("form");
472
+ form.style.display = "none";
473
+ form.action = url;
474
+ form.method = "post";
475
+ for (var key in data) {
476
+ var input = document.createElement("input");
477
+ input.name = key;
478
+ input.value = ko.utils.stringifyJson(ko.utils.unwrapObservable(data[key]));
479
+ form.appendChild(input);
480
+ }
481
+ for (var key in params) {
482
+ var input = document.createElement("input");
483
+ input.name = key;
484
+ input.value = params[key];
485
+ form.appendChild(input);
486
+ }
487
+ document.body.appendChild(form);
488
+ options['submitter'] ? options['submitter'](form) : form.submit();
489
+ setTimeout(function () { form.parentNode.removeChild(form); }, 0);
490
+ }
491
+ }
492
+ })();
493
+
494
+ ko.exportSymbol('utils', ko.utils);
495
+ ko.exportSymbol('utils.arrayForEach', ko.utils.arrayForEach);
496
+ ko.exportSymbol('utils.arrayFirst', ko.utils.arrayFirst);
497
+ ko.exportSymbol('utils.arrayFilter', ko.utils.arrayFilter);
498
+ ko.exportSymbol('utils.arrayGetDistinctValues', ko.utils.arrayGetDistinctValues);
499
+ ko.exportSymbol('utils.arrayIndexOf', ko.utils.arrayIndexOf);
500
+ ko.exportSymbol('utils.arrayMap', ko.utils.arrayMap);
501
+ ko.exportSymbol('utils.arrayPushAll', ko.utils.arrayPushAll);
502
+ ko.exportSymbol('utils.arrayRemoveItem', ko.utils.arrayRemoveItem);
503
+ ko.exportSymbol('utils.extend', ko.utils.extend);
504
+ ko.exportSymbol('utils.fieldsIncludedWithJsonPost', ko.utils.fieldsIncludedWithJsonPost);
505
+ ko.exportSymbol('utils.getFormFields', ko.utils.getFormFields);
506
+ ko.exportSymbol('utils.peekObservable', ko.utils.peekObservable);
507
+ ko.exportSymbol('utils.postJson', ko.utils.postJson);
508
+ ko.exportSymbol('utils.parseJson', ko.utils.parseJson);
509
+ ko.exportSymbol('utils.registerEventHandler', ko.utils.registerEventHandler);
510
+ ko.exportSymbol('utils.stringifyJson', ko.utils.stringifyJson);
511
+ ko.exportSymbol('utils.range', ko.utils.range);
512
+ ko.exportSymbol('utils.toggleDomNodeCssClass', ko.utils.toggleDomNodeCssClass);
513
+ ko.exportSymbol('utils.triggerEvent', ko.utils.triggerEvent);
514
+ ko.exportSymbol('utils.unwrapObservable', ko.utils.unwrapObservable);
515
+
516
+ if (!Function.prototype['bind']) {
517
+ // 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)
518
+ // In case the browser doesn't implement it natively, provide a JavaScript implementation. This implementation is based on the one in prototype.js
519
+ Function.prototype['bind'] = function (object) {
520
+ var originalFunction = this, args = Array.prototype.slice.call(arguments), object = args.shift();
521
+ return function () {
522
+ return originalFunction.apply(object, args.concat(Array.prototype.slice.call(arguments)));
523
+ };
524
+ };
525
+ }
526
+
527
+ ko.utils.domData = new (function () {
528
+ var uniqueId = 0;
529
+ var dataStoreKeyExpandoPropertyName = "__ko__" + (new Date).getTime();
530
+ var dataStore = {};
531
+ return {
532
+ get: function (node, key) {
533
+ var allDataForNode = ko.utils.domData.getAll(node, false);
534
+ return allDataForNode === undefined ? undefined : allDataForNode[key];
535
+ },
536
+ set: function (node, key, value) {
537
+ if (value === undefined) {
538
+ // Make sure we don't actually create a new domData key if we are actually deleting a value
539
+ if (ko.utils.domData.getAll(node, false) === undefined)
540
+ return;
541
+ }
542
+ var allDataForNode = ko.utils.domData.getAll(node, true);
543
+ allDataForNode[key] = value;
544
+ },
545
+ getAll: function (node, createIfNotFound) {
546
+ var dataStoreKey = node[dataStoreKeyExpandoPropertyName];
547
+ var hasExistingDataStore = dataStoreKey && (dataStoreKey !== "null") && dataStore[dataStoreKey];
548
+ if (!hasExistingDataStore) {
549
+ if (!createIfNotFound)
550
+ return undefined;
551
+ dataStoreKey = node[dataStoreKeyExpandoPropertyName] = "ko" + uniqueId++;
552
+ dataStore[dataStoreKey] = {};
553
+ }
554
+ return dataStore[dataStoreKey];
555
+ },
556
+ clear: function (node) {
557
+ var dataStoreKey = node[dataStoreKeyExpandoPropertyName];
558
+ if (dataStoreKey) {
559
+ delete dataStore[dataStoreKey];
560
+ node[dataStoreKeyExpandoPropertyName] = null;
561
+ return true; // Exposing "did clean" flag purely so specs can infer whether things have been cleaned up as intended
562
+ }
563
+ return false;
564
+ }
565
+ }
566
+ })();
567
+
568
+ ko.exportSymbol('utils.domData', ko.utils.domData);
569
+ ko.exportSymbol('utils.domData.clear', ko.utils.domData.clear); // Exporting only so specs can clear up after themselves fully
570
+
571
+ ko.utils.domNodeDisposal = new (function () {
572
+ var domDataKey = "__ko_domNodeDisposal__" + (new Date).getTime();
573
+ var cleanableNodeTypes = { 1: true, 8: true, 9: true }; // Element, Comment, Document
574
+ var cleanableNodeTypesWithDescendants = { 1: true, 9: true }; // Element, Document
575
+
576
+ function getDisposeCallbacksCollection(node, createIfNotFound) {
577
+ var allDisposeCallbacks = ko.utils.domData.get(node, domDataKey);
578
+ if ((allDisposeCallbacks === undefined) && createIfNotFound) {
579
+ allDisposeCallbacks = [];
580
+ ko.utils.domData.set(node, domDataKey, allDisposeCallbacks);
581
+ }
582
+ return allDisposeCallbacks;
583
+ }
584
+ function destroyCallbacksCollection(node) {
585
+ ko.utils.domData.set(node, domDataKey, undefined);
586
+ }
587
+
588
+ function cleanSingleNode(node) {
589
+ // Run all the dispose callbacks
590
+ var callbacks = getDisposeCallbacksCollection(node, false);
591
+ if (callbacks) {
592
+ callbacks = callbacks.slice(0); // Clone, as the array may be modified during iteration (typically, callbacks will remove themselves)
593
+ for (var i = 0; i < callbacks.length; i++)
594
+ callbacks[i](node);
595
+ }
596
+
597
+ // Also erase the DOM data
598
+ ko.utils.domData.clear(node);
599
+
600
+ // Special support for jQuery here because it's so commonly used.
601
+ // Many jQuery plugins (including jquery.tmpl) store data using jQuery's equivalent of domData
602
+ // so notify it to tear down any resources associated with the node & descendants here.
603
+ if ((typeof jQuery == "function") && (typeof jQuery['cleanData'] == "function"))
604
+ jQuery['cleanData']([node]);
605
+
606
+ // Also clear any immediate-child comment nodes, as these wouldn't have been found by
607
+ // node.getElementsByTagName("*") in cleanNode() (comment nodes aren't elements)
608
+ if (cleanableNodeTypesWithDescendants[node.nodeType])
609
+ cleanImmediateCommentTypeChildren(node);
610
+ }
611
+
612
+ function cleanImmediateCommentTypeChildren(nodeWithChildren) {
613
+ var child, nextChild = nodeWithChildren.firstChild;
614
+ while (child = nextChild) {
615
+ nextChild = child.nextSibling;
616
+ if (child.nodeType === 8)
617
+ cleanSingleNode(child);
618
+ }
619
+ }
620
+
621
+ return {
622
+ addDisposeCallback : function(node, callback) {
623
+ if (typeof callback != "function")
624
+ throw new Error("Callback must be a function");
625
+ getDisposeCallbacksCollection(node, true).push(callback);
626
+ },
627
+
628
+ removeDisposeCallback : function(node, callback) {
629
+ var callbacksCollection = getDisposeCallbacksCollection(node, false);
630
+ if (callbacksCollection) {
631
+ ko.utils.arrayRemoveItem(callbacksCollection, callback);
632
+ if (callbacksCollection.length == 0)
633
+ destroyCallbacksCollection(node);
634
+ }
635
+ },
636
+
637
+ cleanNode : function(node) {
638
+ // First clean this node, where applicable
639
+ if (cleanableNodeTypes[node.nodeType]) {
640
+ cleanSingleNode(node);
641
+
642
+ // ... then its descendants, where applicable
643
+ if (cleanableNodeTypesWithDescendants[node.nodeType]) {
644
+ // Clone the descendants list in case it changes during iteration
645
+ var descendants = [];
646
+ ko.utils.arrayPushAll(descendants, node.getElementsByTagName("*"));
647
+ for (var i = 0, j = descendants.length; i < j; i++)
648
+ cleanSingleNode(descendants[i]);
649
+ }
650
+ }
651
+ return node;
652
+ },
653
+
654
+ removeNode : function(node) {
655
+ ko.cleanNode(node);
656
+ if (node.parentNode)
657
+ node.parentNode.removeChild(node);
658
+ }
659
+ }
660
+ })();
661
+ ko.cleanNode = ko.utils.domNodeDisposal.cleanNode; // Shorthand name for convenience
662
+ ko.removeNode = ko.utils.domNodeDisposal.removeNode; // Shorthand name for convenience
663
+ ko.exportSymbol('cleanNode', ko.cleanNode);
664
+ ko.exportSymbol('removeNode', ko.removeNode);
665
+ ko.exportSymbol('utils.domNodeDisposal', ko.utils.domNodeDisposal);
666
+ ko.exportSymbol('utils.domNodeDisposal.addDisposeCallback', ko.utils.domNodeDisposal.addDisposeCallback);
667
+ ko.exportSymbol('utils.domNodeDisposal.removeDisposeCallback', ko.utils.domNodeDisposal.removeDisposeCallback);
668
+ (function () {
669
+ var leadingCommentRegex = /^(\s*)<!--(.*?)-->/;
670
+
671
+ function simpleHtmlParse(html) {
672
+ // Based on jQuery's "clean" function, but only accounting for table-related elements.
673
+ // If you have referenced jQuery, this won't be used anyway - KO will use jQuery's "clean" function directly
674
+
675
+ // Note that there's still an issue in IE < 9 whereby it will discard comment nodes that are the first child of
676
+ // a descendant node. For example: "<div><!-- mycomment -->abc</div>" will get parsed as "<div>abc</div>"
677
+ // This won't affect anyone who has referenced jQuery, and there's always the workaround of inserting a dummy node
678
+ // (possibly a text node) in front of the comment. So, KO does not attempt to workaround this IE issue automatically at present.
679
+
680
+ // Trim whitespace, otherwise indexOf won't work as expected
681
+ var tags = ko.utils.stringTrim(html).toLowerCase(), div = document.createElement("div");
682
+
683
+ // Finds the first match from the left column, and returns the corresponding "wrap" data from the right column
684
+ var wrap = tags.match(/^<(thead|tbody|tfoot)/) && [1, "<table>", "</table>"] ||
685
+ !tags.indexOf("<tr") && [2, "<table><tbody>", "</tbody></table>"] ||
686
+ (!tags.indexOf("<td") || !tags.indexOf("<th")) && [3, "<table><tbody><tr>", "</tr></tbody></table>"] ||
687
+ /* anything else */ [0, "", ""];
688
+
689
+ // Go to html and back, then peel off extra wrappers
690
+ // Note that we always prefix with some dummy text, because otherwise, IE<9 will strip out leading comment nodes in descendants. Total madness.
691
+ var markup = "ignored<div>" + wrap[1] + html + wrap[2] + "</div>";
692
+ if (typeof window['innerShiv'] == "function") {
693
+ div.appendChild(window['innerShiv'](markup));
694
+ } else {
695
+ div.innerHTML = markup;
696
+ }
697
+
698
+ // Move to the right depth
699
+ while (wrap[0]--)
700
+ div = div.lastChild;
701
+
702
+ return ko.utils.makeArray(div.lastChild.childNodes);
703
+ }
704
+
705
+ function jQueryHtmlParse(html) {
706
+ var elems = jQuery['clean']([html]);
707
+
708
+ // As of jQuery 1.7.1, jQuery parses the HTML by appending it to some dummy parent nodes held in an in-memory document fragment.
709
+ // Unfortunately, it never clears the dummy parent nodes from the document fragment, so it leaks memory over time.
710
+ // Fix this by finding the top-most dummy parent element, and detaching it from its owner fragment.
711
+ if (elems && elems[0]) {
712
+ // Find the top-most parent element that's a direct child of a document fragment
713
+ var elem = elems[0];
714
+ while (elem.parentNode && elem.parentNode.nodeType !== 11 /* i.e., DocumentFragment */)
715
+ elem = elem.parentNode;
716
+ // ... then detach it
717
+ if (elem.parentNode)
718
+ elem.parentNode.removeChild(elem);
719
+ }
720
+
721
+ return elems;
722
+ }
723
+
724
+ ko.utils.parseHtmlFragment = function(html) {
725
+ return typeof jQuery != 'undefined' ? jQueryHtmlParse(html) // As below, benefit from jQuery's optimisations where possible
726
+ : simpleHtmlParse(html); // ... otherwise, this simple logic will do in most common cases.
727
+ };
728
+
729
+ ko.utils.setHtml = function(node, html) {
730
+ ko.utils.emptyDomNode(node);
731
+
732
+ // There's no legitimate reason to display a stringified observable without unwrapping it, so we'll unwrap it
733
+ html = ko.utils.unwrapObservable(html);
734
+
735
+ if ((html !== null) && (html !== undefined)) {
736
+ if (typeof html != 'string')
737
+ html = html.toString();
738
+
739
+ // jQuery contains a lot of sophisticated code to parse arbitrary HTML fragments,
740
+ // for example <tr> elements which are not normally allowed to exist on their own.
741
+ // If you've referenced jQuery we'll use that rather than duplicating its code.
742
+ if (typeof jQuery != 'undefined') {
743
+ jQuery(node)['html'](html);
744
+ } else {
745
+ // ... otherwise, use KO's own parsing logic.
746
+ var parsedNodes = ko.utils.parseHtmlFragment(html);
747
+ for (var i = 0; i < parsedNodes.length; i++)
748
+ node.appendChild(parsedNodes[i]);
749
+ }
750
+ }
751
+ };
752
+ })();
753
+
754
+ ko.exportSymbol('utils.parseHtmlFragment', ko.utils.parseHtmlFragment);
755
+ ko.exportSymbol('utils.setHtml', ko.utils.setHtml);
756
+
757
+ ko.memoization = (function () {
758
+ var memos = {};
759
+
760
+ function randomMax8HexChars() {
761
+ return (((1 + Math.random()) * 0x100000000) | 0).toString(16).substring(1);
762
+ }
763
+ function generateRandomId() {
764
+ return randomMax8HexChars() + randomMax8HexChars();
765
+ }
766
+ function findMemoNodes(rootNode, appendToArray) {
767
+ if (!rootNode)
768
+ return;
769
+ if (rootNode.nodeType == 8) {
770
+ var memoId = ko.memoization.parseMemoText(rootNode.nodeValue);
771
+ if (memoId != null)
772
+ appendToArray.push({ domNode: rootNode, memoId: memoId });
773
+ } else if (rootNode.nodeType == 1) {
774
+ for (var i = 0, childNodes = rootNode.childNodes, j = childNodes.length; i < j; i++)
775
+ findMemoNodes(childNodes[i], appendToArray);
776
+ }
777
+ }
778
+
779
+ return {
780
+ memoize: function (callback) {
781
+ if (typeof callback != "function")
782
+ throw new Error("You can only pass a function to ko.memoization.memoize()");
783
+ var memoId = generateRandomId();
784
+ memos[memoId] = callback;
785
+ return "<!--[ko_memo:" + memoId + "]-->";
786
+ },
787
+
788
+ unmemoize: function (memoId, callbackParams) {
789
+ var callback = memos[memoId];
790
+ if (callback === undefined)
791
+ throw new Error("Couldn't find any memo with ID " + memoId + ". Perhaps it's already been unmemoized.");
792
+ try {
793
+ callback.apply(null, callbackParams || []);
794
+ return true;
795
+ }
796
+ finally { delete memos[memoId]; }
797
+ },
798
+
799
+ unmemoizeDomNodeAndDescendants: function (domNode, extraCallbackParamsArray) {
800
+ var memos = [];
801
+ findMemoNodes(domNode, memos);
802
+ for (var i = 0, j = memos.length; i < j; i++) {
803
+ var node = memos[i].domNode;
804
+ var combinedParams = [node];
805
+ if (extraCallbackParamsArray)
806
+ ko.utils.arrayPushAll(combinedParams, extraCallbackParamsArray);
807
+ ko.memoization.unmemoize(memos[i].memoId, combinedParams);
808
+ node.nodeValue = ""; // Neuter this node so we don't try to unmemoize it again
809
+ if (node.parentNode)
810
+ 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)
811
+ }
812
+ },
813
+
814
+ parseMemoText: function (memoText) {
815
+ var match = memoText.match(/^\[ko_memo\:(.*?)\]$/);
816
+ return match ? match[1] : null;
817
+ }
818
+ };
819
+ })();
820
+
821
+ ko.exportSymbol('memoization', ko.memoization);
822
+ ko.exportSymbol('memoization.memoize', ko.memoization.memoize);
823
+ ko.exportSymbol('memoization.unmemoize', ko.memoization.unmemoize);
824
+ ko.exportSymbol('memoization.parseMemoText', ko.memoization.parseMemoText);
825
+ ko.exportSymbol('memoization.unmemoizeDomNodeAndDescendants', ko.memoization.unmemoizeDomNodeAndDescendants);
826
+ ko.extenders = {
827
+ 'throttle': function(target, timeout) {
828
+ // Throttling means two things:
829
+
830
+ // (1) For dependent observables, we throttle *evaluations* so that, no matter how fast its dependencies
831
+ // notify updates, the target doesn't re-evaluate (and hence doesn't notify) faster than a certain rate
832
+ target['throttleEvaluation'] = timeout;
833
+
834
+ // (2) For writable targets (observables, or writable dependent observables), we throttle *writes*
835
+ // so the target cannot change value synchronously or faster than a certain rate
836
+ var writeTimeoutInstance = null;
837
+ return ko.dependentObservable({
838
+ 'read': target,
839
+ 'write': function(value) {
840
+ clearTimeout(writeTimeoutInstance);
841
+ writeTimeoutInstance = setTimeout(function() {
842
+ target(value);
843
+ }, timeout);
844
+ }
845
+ });
846
+ },
847
+
848
+ 'notify': function(target, notifyWhen) {
849
+ target["equalityComparer"] = notifyWhen == "always"
850
+ ? function() { return false } // Treat all values as not equal
851
+ : ko.observable["fn"]["equalityComparer"];
852
+ return target;
853
+ }
854
+ };
855
+
856
+ function applyExtenders(requestedExtenders) {
857
+ var target = this;
858
+ if (requestedExtenders) {
859
+ for (var key in requestedExtenders) {
860
+ var extenderHandler = ko.extenders[key];
861
+ if (typeof extenderHandler == 'function') {
862
+ target = extenderHandler(target, requestedExtenders[key]);
863
+ }
864
+ }
865
+ }
866
+ return target;
867
+ }
868
+
869
+ ko.exportSymbol('extenders', ko.extenders);
870
+
871
+ ko.subscription = function (target, callback, disposeCallback) {
872
+ this.target = target;
873
+ this.callback = callback;
874
+ this.disposeCallback = disposeCallback;
875
+ ko.exportProperty(this, 'dispose', this.dispose);
876
+ };
877
+ ko.subscription.prototype.dispose = function () {
878
+ this.isDisposed = true;
879
+ this.disposeCallback();
880
+ };
881
+
882
+ ko.subscribable = function () {
883
+ this._subscriptions = {};
884
+
885
+ ko.utils.extend(this, ko.subscribable['fn']);
886
+ ko.exportProperty(this, 'subscribe', this.subscribe);
887
+ ko.exportProperty(this, 'extend', this.extend);
888
+ ko.exportProperty(this, 'getSubscriptionsCount', this.getSubscriptionsCount);
889
+ }
890
+
891
+ var defaultEvent = "change";
892
+
893
+ ko.subscribable['fn'] = {
894
+ subscribe: function (callback, callbackTarget, event) {
895
+ event = event || defaultEvent;
896
+ var boundCallback = callbackTarget ? callback.bind(callbackTarget) : callback;
897
+
898
+ var subscription = new ko.subscription(this, boundCallback, function () {
899
+ ko.utils.arrayRemoveItem(this._subscriptions[event], subscription);
900
+ }.bind(this));
901
+
902
+ if (!this._subscriptions[event])
903
+ this._subscriptions[event] = [];
904
+ this._subscriptions[event].push(subscription);
905
+ return subscription;
906
+ },
907
+
908
+ "notifySubscribers": function (valueToNotify, event) {
909
+ event = event || defaultEvent;
910
+ if (this._subscriptions[event]) {
911
+ ko.dependencyDetection.ignore(function() {
912
+ ko.utils.arrayForEach(this._subscriptions[event].slice(0), function (subscription) {
913
+ // In case a subscription was disposed during the arrayForEach cycle, check
914
+ // for isDisposed on each subscription before invoking its callback
915
+ if (subscription && (subscription.isDisposed !== true))
916
+ subscription.callback(valueToNotify);
917
+ });
918
+ }, this);
919
+ }
920
+ },
921
+
922
+ getSubscriptionsCount: function () {
923
+ var total = 0;
924
+ for (var eventName in this._subscriptions) {
925
+ if (this._subscriptions.hasOwnProperty(eventName))
926
+ total += this._subscriptions[eventName].length;
927
+ }
928
+ return total;
929
+ },
930
+
931
+ extend: applyExtenders
932
+ };
933
+
934
+
935
+ ko.isSubscribable = function (instance) {
936
+ return typeof instance.subscribe == "function" && typeof instance["notifySubscribers"] == "function";
937
+ };
938
+
939
+ ko.exportSymbol('subscribable', ko.subscribable);
940
+ ko.exportSymbol('isSubscribable', ko.isSubscribable);
941
+
942
+ ko.dependencyDetection = (function () {
943
+ var _frames = [];
944
+
945
+ return {
946
+ begin: function (callback) {
947
+ _frames.push({ callback: callback, distinctDependencies:[] });
948
+ },
949
+
950
+ end: function () {
951
+ _frames.pop();
952
+ },
953
+
954
+ registerDependency: function (subscribable) {
955
+ if (!ko.isSubscribable(subscribable))
956
+ throw new Error("Only subscribable things can act as dependencies");
957
+ if (_frames.length > 0) {
958
+ var topFrame = _frames[_frames.length - 1];
959
+ if (!topFrame || ko.utils.arrayIndexOf(topFrame.distinctDependencies, subscribable) >= 0)
960
+ return;
961
+ topFrame.distinctDependencies.push(subscribable);
962
+ topFrame.callback(subscribable);
963
+ }
964
+ },
965
+
966
+ ignore: function(callback, callbackTarget, callbackArgs) {
967
+ try {
968
+ _frames.push(null);
969
+ return callback.apply(callbackTarget, callbackArgs || []);
970
+ } finally {
971
+ _frames.pop();
972
+ }
973
+ }
974
+ };
975
+ })();
976
+ var primitiveTypes = { 'undefined':true, 'boolean':true, 'number':true, 'string':true };
977
+
978
+ ko.observable = function (initialValue) {
979
+ var _latestValue = initialValue;
980
+
981
+ function observable() {
982
+ if (arguments.length > 0) {
983
+ // Write
984
+
985
+ // Ignore writes if the value hasn't changed
986
+ if ((!observable['equalityComparer']) || !observable['equalityComparer'](_latestValue, arguments[0])) {
987
+ observable.valueWillMutate();
988
+ _latestValue = arguments[0];
989
+ if (DEBUG) observable._latestValue = _latestValue;
990
+ observable.valueHasMutated();
991
+ }
992
+ return this; // Permits chained assignments
993
+ }
994
+ else {
995
+ // Read
996
+ ko.dependencyDetection.registerDependency(observable); // The caller only needs to be notified of changes if they did a "read" operation
997
+ return _latestValue;
998
+ }
999
+ }
1000
+ if (DEBUG) observable._latestValue = _latestValue;
1001
+ ko.subscribable.call(observable);
1002
+ observable.peek = function() { return _latestValue };
1003
+ observable.valueHasMutated = function () { observable["notifySubscribers"](_latestValue); }
1004
+ observable.valueWillMutate = function () { observable["notifySubscribers"](_latestValue, "beforeChange"); }
1005
+ ko.utils.extend(observable, ko.observable['fn']);
1006
+
1007
+ ko.exportProperty(observable, 'peek', observable.peek);
1008
+ ko.exportProperty(observable, "valueHasMutated", observable.valueHasMutated);
1009
+ ko.exportProperty(observable, "valueWillMutate", observable.valueWillMutate);
1010
+
1011
+ return observable;
1012
+ }
1013
+
1014
+ ko.observable['fn'] = {
1015
+ "equalityComparer": function valuesArePrimitiveAndEqual(a, b) {
1016
+ var oldValueIsPrimitive = (a === null) || (typeof(a) in primitiveTypes);
1017
+ return oldValueIsPrimitive ? (a === b) : false;
1018
+ }
1019
+ };
1020
+
1021
+ var protoProperty = ko.observable.protoProperty = "__ko_proto__";
1022
+ ko.observable['fn'][protoProperty] = ko.observable;
1023
+
1024
+ ko.hasPrototype = function(instance, prototype) {
1025
+ if ((instance === null) || (instance === undefined) || (instance[protoProperty] === undefined)) return false;
1026
+ if (instance[protoProperty] === prototype) return true;
1027
+ return ko.hasPrototype(instance[protoProperty], prototype); // Walk the prototype chain
1028
+ };
1029
+
1030
+ ko.isObservable = function (instance) {
1031
+ return ko.hasPrototype(instance, ko.observable);
1032
+ }
1033
+ ko.isWriteableObservable = function (instance) {
1034
+ // Observable
1035
+ if ((typeof instance == "function") && instance[protoProperty] === ko.observable)
1036
+ return true;
1037
+ // Writeable dependent observable
1038
+ if ((typeof instance == "function") && (instance[protoProperty] === ko.dependentObservable) && (instance.hasWriteFunction))
1039
+ return true;
1040
+ // Anything else
1041
+ return false;
1042
+ }
1043
+
1044
+
1045
+ ko.exportSymbol('observable', ko.observable);
1046
+ ko.exportSymbol('isObservable', ko.isObservable);
1047
+ ko.exportSymbol('isWriteableObservable', ko.isWriteableObservable);
1048
+ ko.observableArray = function (initialValues) {
1049
+ if (arguments.length == 0) {
1050
+ // Zero-parameter constructor initializes to empty array
1051
+ initialValues = [];
1052
+ }
1053
+ if ((initialValues !== null) && (initialValues !== undefined) && !('length' in initialValues))
1054
+ throw new Error("The argument passed when initializing an observable array must be an array, or null, or undefined.");
1055
+
1056
+ var result = ko.observable(initialValues);
1057
+ ko.utils.extend(result, ko.observableArray['fn']);
1058
+ return result;
1059
+ }
1060
+
1061
+ ko.observableArray['fn'] = {
1062
+ 'remove': function (valueOrPredicate) {
1063
+ var underlyingArray = this.peek();
1064
+ var removedValues = [];
1065
+ var predicate = typeof valueOrPredicate == "function" ? valueOrPredicate : function (value) { return value === valueOrPredicate; };
1066
+ for (var i = 0; i < underlyingArray.length; i++) {
1067
+ var value = underlyingArray[i];
1068
+ if (predicate(value)) {
1069
+ if (removedValues.length === 0) {
1070
+ this.valueWillMutate();
1071
+ }
1072
+ removedValues.push(value);
1073
+ underlyingArray.splice(i, 1);
1074
+ i--;
1075
+ }
1076
+ }
1077
+ if (removedValues.length) {
1078
+ this.valueHasMutated();
1079
+ }
1080
+ return removedValues;
1081
+ },
1082
+
1083
+ 'removeAll': function (arrayOfValues) {
1084
+ // If you passed zero args, we remove everything
1085
+ if (arrayOfValues === undefined) {
1086
+ var underlyingArray = this.peek();
1087
+ var allValues = underlyingArray.slice(0);
1088
+ this.valueWillMutate();
1089
+ underlyingArray.splice(0, underlyingArray.length);
1090
+ this.valueHasMutated();
1091
+ return allValues;
1092
+ }
1093
+ // If you passed an arg, we interpret it as an array of entries to remove
1094
+ if (!arrayOfValues)
1095
+ return [];
1096
+ return this['remove'](function (value) {
1097
+ return ko.utils.arrayIndexOf(arrayOfValues, value) >= 0;
1098
+ });
1099
+ },
1100
+
1101
+ 'destroy': function (valueOrPredicate) {
1102
+ var underlyingArray = this.peek();
1103
+ var predicate = typeof valueOrPredicate == "function" ? valueOrPredicate : function (value) { return value === valueOrPredicate; };
1104
+ this.valueWillMutate();
1105
+ for (var i = underlyingArray.length - 1; i >= 0; i--) {
1106
+ var value = underlyingArray[i];
1107
+ if (predicate(value))
1108
+ underlyingArray[i]["_destroy"] = true;
1109
+ }
1110
+ this.valueHasMutated();
1111
+ },
1112
+
1113
+ 'destroyAll': function (arrayOfValues) {
1114
+ // If you passed zero args, we destroy everything
1115
+ if (arrayOfValues === undefined)
1116
+ return this['destroy'](function() { return true });
1117
+
1118
+ // If you passed an arg, we interpret it as an array of entries to destroy
1119
+ if (!arrayOfValues)
1120
+ return [];
1121
+ return this['destroy'](function (value) {
1122
+ return ko.utils.arrayIndexOf(arrayOfValues, value) >= 0;
1123
+ });
1124
+ },
1125
+
1126
+ 'indexOf': function (item) {
1127
+ var underlyingArray = this();
1128
+ return ko.utils.arrayIndexOf(underlyingArray, item);
1129
+ },
1130
+
1131
+ 'replace': function(oldItem, newItem) {
1132
+ var index = this['indexOf'](oldItem);
1133
+ if (index >= 0) {
1134
+ this.valueWillMutate();
1135
+ this.peek()[index] = newItem;
1136
+ this.valueHasMutated();
1137
+ }
1138
+ }
1139
+ }
1140
+
1141
+ // Populate ko.observableArray.fn with read/write functions from native arrays
1142
+ // Important: Do not add any additional functions here that may reasonably be used to *read* data from the array
1143
+ // because we'll eval them without causing subscriptions, so ko.computed output could end up getting stale
1144
+ ko.utils.arrayForEach(["pop", "push", "reverse", "shift", "sort", "splice", "unshift"], function (methodName) {
1145
+ ko.observableArray['fn'][methodName] = function () {
1146
+ // Use "peek" to avoid creating a subscription in any computed that we're executing in the context of
1147
+ // (for consistency with mutating regular observables)
1148
+ var underlyingArray = this.peek();
1149
+ this.valueWillMutate();
1150
+ var methodCallResult = underlyingArray[methodName].apply(underlyingArray, arguments);
1151
+ this.valueHasMutated();
1152
+ return methodCallResult;
1153
+ };
1154
+ });
1155
+
1156
+ // Populate ko.observableArray.fn with read-only functions from native arrays
1157
+ ko.utils.arrayForEach(["slice"], function (methodName) {
1158
+ ko.observableArray['fn'][methodName] = function () {
1159
+ var underlyingArray = this();
1160
+ return underlyingArray[methodName].apply(underlyingArray, arguments);
1161
+ };
1162
+ });
1163
+
1164
+ ko.exportSymbol('observableArray', ko.observableArray);
1165
+ ko.dependentObservable = function (evaluatorFunctionOrOptions, evaluatorFunctionTarget, options) {
1166
+ var _latestValue,
1167
+ _hasBeenEvaluated = false,
1168
+ _isBeingEvaluated = false,
1169
+ readFunction = evaluatorFunctionOrOptions;
1170
+
1171
+ if (readFunction && typeof readFunction == "object") {
1172
+ // Single-parameter syntax - everything is on this "options" param
1173
+ options = readFunction;
1174
+ readFunction = options["read"];
1175
+ } else {
1176
+ // Multi-parameter syntax - construct the options according to the params passed
1177
+ options = options || {};
1178
+ if (!readFunction)
1179
+ readFunction = options["read"];
1180
+ }
1181
+ if (typeof readFunction != "function")
1182
+ throw new Error("Pass a function that returns the value of the ko.computed");
1183
+
1184
+ function addSubscriptionToDependency(subscribable) {
1185
+ _subscriptionsToDependencies.push(subscribable.subscribe(evaluatePossiblyAsync));
1186
+ }
1187
+
1188
+ function disposeAllSubscriptionsToDependencies() {
1189
+ ko.utils.arrayForEach(_subscriptionsToDependencies, function (subscription) {
1190
+ subscription.dispose();
1191
+ });
1192
+ _subscriptionsToDependencies = [];
1193
+ }
1194
+
1195
+ function evaluatePossiblyAsync() {
1196
+ var throttleEvaluationTimeout = dependentObservable['throttleEvaluation'];
1197
+ if (throttleEvaluationTimeout && throttleEvaluationTimeout >= 0) {
1198
+ clearTimeout(evaluationTimeoutInstance);
1199
+ evaluationTimeoutInstance = setTimeout(evaluateImmediate, throttleEvaluationTimeout);
1200
+ } else
1201
+ evaluateImmediate();
1202
+ }
1203
+
1204
+ function evaluateImmediate() {
1205
+ if (_isBeingEvaluated) {
1206
+ // If the evaluation of a ko.computed causes side effects, it's possible that it will trigger its own re-evaluation.
1207
+ // This is not desirable (it's hard for a developer to realise a chain of dependencies might cause this, and they almost
1208
+ // certainly didn't intend infinite re-evaluations). So, for predictability, we simply prevent ko.computeds from causing
1209
+ // their own re-evaluation. Further discussion at https://github.com/SteveSanderson/knockout/pull/387
1210
+ return;
1211
+ }
1212
+
1213
+ // Don't dispose on first evaluation, because the "disposeWhen" callback might
1214
+ // e.g., dispose when the associated DOM element isn't in the doc, and it's not
1215
+ // going to be in the doc until *after* the first evaluation
1216
+ if (_hasBeenEvaluated && disposeWhen()) {
1217
+ dispose();
1218
+ return;
1219
+ }
1220
+
1221
+ _isBeingEvaluated = true;
1222
+ try {
1223
+ // Initially, we assume that none of the subscriptions are still being used (i.e., all are candidates for disposal).
1224
+ // Then, during evaluation, we cross off any that are in fact still being used.
1225
+ var disposalCandidates = ko.utils.arrayMap(_subscriptionsToDependencies, function(item) {return item.target;});
1226
+
1227
+ ko.dependencyDetection.begin(function(subscribable) {
1228
+ var inOld;
1229
+ if ((inOld = ko.utils.arrayIndexOf(disposalCandidates, subscribable)) >= 0)
1230
+ disposalCandidates[inOld] = undefined; // Don't want to dispose this subscription, as it's still being used
1231
+ else
1232
+ addSubscriptionToDependency(subscribable); // Brand new subscription - add it
1233
+ });
1234
+
1235
+ var newValue = readFunction.call(evaluatorFunctionTarget);
1236
+
1237
+ // For each subscription no longer being used, remove it from the active subscriptions list and dispose it
1238
+ for (var i = disposalCandidates.length - 1; i >= 0; i--) {
1239
+ if (disposalCandidates[i])
1240
+ _subscriptionsToDependencies.splice(i, 1)[0].dispose();
1241
+ }
1242
+ _hasBeenEvaluated = true;
1243
+
1244
+ dependentObservable["notifySubscribers"](_latestValue, "beforeChange");
1245
+ _latestValue = newValue;
1246
+ if (DEBUG) dependentObservable._latestValue = _latestValue;
1247
+ } finally {
1248
+ ko.dependencyDetection.end();
1249
+ }
1250
+
1251
+ dependentObservable["notifySubscribers"](_latestValue);
1252
+ _isBeingEvaluated = false;
1253
+ if (!_subscriptionsToDependencies.length)
1254
+ dispose();
1255
+ }
1256
+
1257
+ function dependentObservable() {
1258
+ if (arguments.length > 0) {
1259
+ if (typeof writeFunction === "function") {
1260
+ // Writing a value
1261
+ writeFunction.apply(evaluatorFunctionTarget, arguments);
1262
+ } else {
1263
+ throw new Error("Cannot write a value to a ko.computed unless you specify a 'write' option. If you wish to read the current value, don't pass any parameters.");
1264
+ }
1265
+ return this; // Permits chained assignments
1266
+ } else {
1267
+ // Reading the value
1268
+ if (!_hasBeenEvaluated)
1269
+ evaluateImmediate();
1270
+ ko.dependencyDetection.registerDependency(dependentObservable);
1271
+ return _latestValue;
1272
+ }
1273
+ }
1274
+
1275
+ function peek() {
1276
+ if (!_hasBeenEvaluated)
1277
+ evaluateImmediate();
1278
+ return _latestValue;
1279
+ }
1280
+
1281
+ function isActive() {
1282
+ return !_hasBeenEvaluated || _subscriptionsToDependencies.length > 0;
1283
+ }
1284
+
1285
+ // By here, "options" is always non-null
1286
+ var writeFunction = options["write"],
1287
+ disposeWhenNodeIsRemoved = options["disposeWhenNodeIsRemoved"] || options.disposeWhenNodeIsRemoved || null,
1288
+ disposeWhen = options["disposeWhen"] || options.disposeWhen || function() { return false; },
1289
+ dispose = disposeAllSubscriptionsToDependencies,
1290
+ _subscriptionsToDependencies = [],
1291
+ evaluationTimeoutInstance = null;
1292
+
1293
+ if (!evaluatorFunctionTarget)
1294
+ evaluatorFunctionTarget = options["owner"];
1295
+
1296
+ dependentObservable.peek = peek;
1297
+ dependentObservable.getDependenciesCount = function () { return _subscriptionsToDependencies.length; };
1298
+ dependentObservable.hasWriteFunction = typeof options["write"] === "function";
1299
+ dependentObservable.dispose = function () { dispose(); };
1300
+ dependentObservable.isActive = isActive;
1301
+
1302
+ ko.subscribable.call(dependentObservable);
1303
+ ko.utils.extend(dependentObservable, ko.dependentObservable['fn']);
1304
+
1305
+ ko.exportProperty(dependentObservable, 'peek', dependentObservable.peek);
1306
+ ko.exportProperty(dependentObservable, 'dispose', dependentObservable.dispose);
1307
+ ko.exportProperty(dependentObservable, 'isActive', dependentObservable.isActive);
1308
+ ko.exportProperty(dependentObservable, 'getDependenciesCount', dependentObservable.getDependenciesCount);
1309
+
1310
+ // Evaluate, unless deferEvaluation is true
1311
+ if (options['deferEvaluation'] !== true)
1312
+ evaluateImmediate();
1313
+
1314
+ // Build "disposeWhenNodeIsRemoved" and "disposeWhenNodeIsRemovedCallback" option values.
1315
+ // But skip if isActive is false (there will never be any dependencies to dispose).
1316
+ // (Note: "disposeWhenNodeIsRemoved" option both proactively disposes as soon as the node is removed using ko.removeNode(),
1317
+ // plus adds a "disposeWhen" callback that, on each evaluation, disposes if the node was removed by some other means.)
1318
+ if (disposeWhenNodeIsRemoved && isActive()) {
1319
+ dispose = function() {
1320
+ ko.utils.domNodeDisposal.removeDisposeCallback(disposeWhenNodeIsRemoved, arguments.callee);
1321
+ disposeAllSubscriptionsToDependencies();
1322
+ };
1323
+ ko.utils.domNodeDisposal.addDisposeCallback(disposeWhenNodeIsRemoved, dispose);
1324
+ var existingDisposeWhenFunction = disposeWhen;
1325
+ disposeWhen = function () {
1326
+ return !ko.utils.domNodeIsAttachedToDocument(disposeWhenNodeIsRemoved) || existingDisposeWhenFunction();
1327
+ }
1328
+ }
1329
+
1330
+ return dependentObservable;
1331
+ };
1332
+
1333
+ ko.isComputed = function(instance) {
1334
+ return ko.hasPrototype(instance, ko.dependentObservable);
1335
+ };
1336
+
1337
+ var protoProp = ko.observable.protoProperty; // == "__ko_proto__"
1338
+ ko.dependentObservable[protoProp] = ko.observable;
1339
+
1340
+ ko.dependentObservable['fn'] = {};
1341
+ ko.dependentObservable['fn'][protoProp] = ko.dependentObservable;
1342
+
1343
+ ko.exportSymbol('dependentObservable', ko.dependentObservable);
1344
+ ko.exportSymbol('computed', ko.dependentObservable); // Make "ko.computed" an alias for "ko.dependentObservable"
1345
+ ko.exportSymbol('isComputed', ko.isComputed);
1346
+
1347
+ (function() {
1348
+ var maxNestedObservableDepth = 10; // Escape the (unlikely) pathalogical case where an observable's current value is itself (or similar reference cycle)
1349
+
1350
+ ko.toJS = function(rootObject) {
1351
+ if (arguments.length == 0)
1352
+ throw new Error("When calling ko.toJS, pass the object you want to convert.");
1353
+
1354
+ // We just unwrap everything at every level in the object graph
1355
+ return mapJsObjectGraph(rootObject, function(valueToMap) {
1356
+ // Loop because an observable's value might in turn be another observable wrapper
1357
+ for (var i = 0; ko.isObservable(valueToMap) && (i < maxNestedObservableDepth); i++)
1358
+ valueToMap = valueToMap();
1359
+ return valueToMap;
1360
+ });
1361
+ };
1362
+
1363
+ ko.toJSON = function(rootObject, replacer, space) { // replacer and space are optional
1364
+ var plainJavaScriptObject = ko.toJS(rootObject);
1365
+ return ko.utils.stringifyJson(plainJavaScriptObject, replacer, space);
1366
+ };
1367
+
1368
+ function mapJsObjectGraph(rootObject, mapInputCallback, visitedObjects) {
1369
+ visitedObjects = visitedObjects || new objectLookup();
1370
+
1371
+ rootObject = mapInputCallback(rootObject);
1372
+ var canHaveProperties = (typeof rootObject == "object") && (rootObject !== null) && (rootObject !== undefined) && (!(rootObject instanceof Date));
1373
+ if (!canHaveProperties)
1374
+ return rootObject;
1375
+
1376
+ var outputProperties = rootObject instanceof Array ? [] : {};
1377
+ visitedObjects.save(rootObject, outputProperties);
1378
+
1379
+ visitPropertiesOrArrayEntries(rootObject, function(indexer) {
1380
+ var propertyValue = mapInputCallback(rootObject[indexer]);
1381
+
1382
+ switch (typeof propertyValue) {
1383
+ case "boolean":
1384
+ case "number":
1385
+ case "string":
1386
+ case "function":
1387
+ outputProperties[indexer] = propertyValue;
1388
+ break;
1389
+ case "object":
1390
+ case "undefined":
1391
+ var previouslyMappedValue = visitedObjects.get(propertyValue);
1392
+ outputProperties[indexer] = (previouslyMappedValue !== undefined)
1393
+ ? previouslyMappedValue
1394
+ : mapJsObjectGraph(propertyValue, mapInputCallback, visitedObjects);
1395
+ break;
1396
+ }
1397
+ });
1398
+
1399
+ return outputProperties;
1400
+ }
1401
+
1402
+ function visitPropertiesOrArrayEntries(rootObject, visitorCallback) {
1403
+ if (rootObject instanceof Array) {
1404
+ for (var i = 0; i < rootObject.length; i++)
1405
+ visitorCallback(i);
1406
+
1407
+ // For arrays, also respect toJSON property for custom mappings (fixes #278)
1408
+ if (typeof rootObject['toJSON'] == 'function')
1409
+ visitorCallback('toJSON');
1410
+ } else {
1411
+ for (var propertyName in rootObject)
1412
+ visitorCallback(propertyName);
1413
+ }
1414
+ };
1415
+
1416
+ function objectLookup() {
1417
+ var keys = [];
1418
+ var values = [];
1419
+ this.save = function(key, value) {
1420
+ var existingIndex = ko.utils.arrayIndexOf(keys, key);
1421
+ if (existingIndex >= 0)
1422
+ values[existingIndex] = value;
1423
+ else {
1424
+ keys.push(key);
1425
+ values.push(value);
1426
+ }
1427
+ };
1428
+ this.get = function(key) {
1429
+ var existingIndex = ko.utils.arrayIndexOf(keys, key);
1430
+ return (existingIndex >= 0) ? values[existingIndex] : undefined;
1431
+ };
1432
+ };
1433
+ })();
1434
+
1435
+ ko.exportSymbol('toJS', ko.toJS);
1436
+ ko.exportSymbol('toJSON', ko.toJSON);
1437
+ (function () {
1438
+ var hasDomDataExpandoProperty = '__ko__hasDomDataOptionValue__';
1439
+
1440
+ // Normally, SELECT elements and their OPTIONs can only take value of type 'string' (because the values
1441
+ // are stored on DOM attributes). ko.selectExtensions provides a way for SELECTs/OPTIONs to have values
1442
+ // that are arbitrary objects. This is very convenient when implementing things like cascading dropdowns.
1443
+ ko.selectExtensions = {
1444
+ readValue : function(element) {
1445
+ switch (ko.utils.tagNameLower(element)) {
1446
+ case 'option':
1447
+ if (element[hasDomDataExpandoProperty] === true)
1448
+ return ko.utils.domData.get(element, ko.bindingHandlers.options.optionValueDomDataKey);
1449
+ return ko.utils.ieVersion <= 7
1450
+ ? (element.getAttributeNode('value').specified ? element.value : element.text)
1451
+ : element.value;
1452
+ case 'select':
1453
+ return element.selectedIndex >= 0 ? ko.selectExtensions.readValue(element.options[element.selectedIndex]) : undefined;
1454
+ default:
1455
+ return element.value;
1456
+ }
1457
+ },
1458
+
1459
+ writeValue: function(element, value) {
1460
+ switch (ko.utils.tagNameLower(element)) {
1461
+ case 'option':
1462
+ switch(typeof value) {
1463
+ case "string":
1464
+ ko.utils.domData.set(element, ko.bindingHandlers.options.optionValueDomDataKey, undefined);
1465
+ if (hasDomDataExpandoProperty in element) { // IE <= 8 throws errors if you delete non-existent properties from a DOM node
1466
+ delete element[hasDomDataExpandoProperty];
1467
+ }
1468
+ element.value = value;
1469
+ break;
1470
+ default:
1471
+ // Store arbitrary object using DomData
1472
+ ko.utils.domData.set(element, ko.bindingHandlers.options.optionValueDomDataKey, value);
1473
+ element[hasDomDataExpandoProperty] = true;
1474
+
1475
+ // Special treatment of numbers is just for backward compatibility. KO 1.2.1 wrote numerical values to element.value.
1476
+ element.value = typeof value === "number" ? value : "";
1477
+ break;
1478
+ }
1479
+ break;
1480
+ case 'select':
1481
+ for (var i = element.options.length - 1; i >= 0; i--) {
1482
+ if (ko.selectExtensions.readValue(element.options[i]) == value) {
1483
+ element.selectedIndex = i;
1484
+ break;
1485
+ }
1486
+ }
1487
+ break;
1488
+ default:
1489
+ if ((value === null) || (value === undefined))
1490
+ value = "";
1491
+ element.value = value;
1492
+ break;
1493
+ }
1494
+ }
1495
+ };
1496
+ })();
1497
+
1498
+ ko.exportSymbol('selectExtensions', ko.selectExtensions);
1499
+ ko.exportSymbol('selectExtensions.readValue', ko.selectExtensions.readValue);
1500
+ ko.exportSymbol('selectExtensions.writeValue', ko.selectExtensions.writeValue);
1501
+ ko.expressionRewriting = (function () {
1502
+ var restoreCapturedTokensRegex = /\@ko_token_(\d+)\@/g;
1503
+ var javaScriptReservedWords = ["true", "false"];
1504
+
1505
+ // Matches something that can be assigned to--either an isolated identifier or something ending with a property accessor
1506
+ // This is designed to be simple and avoid false negatives, but could produce false positives (e.g., a+b.c).
1507
+ var javaScriptAssignmentTarget = /^(?:[$_a-z][$\w]*|(.+)(\.\s*[$_a-z][$\w]*|\[.+\]))$/i;
1508
+
1509
+ function restoreTokens(string, tokens) {
1510
+ var prevValue = null;
1511
+ while (string != prevValue) { // Keep restoring tokens until it no longer makes a difference (they may be nested)
1512
+ prevValue = string;
1513
+ string = string.replace(restoreCapturedTokensRegex, function (match, tokenIndex) {
1514
+ return tokens[tokenIndex];
1515
+ });
1516
+ }
1517
+ return string;
1518
+ }
1519
+
1520
+ function getWriteableValue(expression) {
1521
+ if (ko.utils.arrayIndexOf(javaScriptReservedWords, ko.utils.stringTrim(expression).toLowerCase()) >= 0)
1522
+ return false;
1523
+ var match = expression.match(javaScriptAssignmentTarget);
1524
+ return match === null ? false : match[1] ? ('Object(' + match[1] + ')' + match[2]) : expression;
1525
+ }
1526
+
1527
+ function ensureQuoted(key) {
1528
+ var trimmedKey = ko.utils.stringTrim(key);
1529
+ switch (trimmedKey.length && trimmedKey.charAt(0)) {
1530
+ case "'":
1531
+ case '"':
1532
+ return key;
1533
+ default:
1534
+ return "'" + trimmedKey + "'";
1535
+ }
1536
+ }
1537
+
1538
+ return {
1539
+ bindingRewriteValidators: [],
1540
+
1541
+ parseObjectLiteral: function(objectLiteralString) {
1542
+ // A full tokeniser+lexer would add too much weight to this library, so here's a simple parser
1543
+ // that is sufficient just to split an object literal string into a set of top-level key-value pairs
1544
+
1545
+ var str = ko.utils.stringTrim(objectLiteralString);
1546
+ if (str.length < 3)
1547
+ return [];
1548
+ if (str.charAt(0) === "{")// Ignore any braces surrounding the whole object literal
1549
+ str = str.substring(1, str.length - 1);
1550
+
1551
+ // Pull out any string literals and regex literals
1552
+ var tokens = [];
1553
+ var tokenStart = null, tokenEndChar;
1554
+ for (var position = 0; position < str.length; position++) {
1555
+ var c = str.charAt(position);
1556
+ if (tokenStart === null) {
1557
+ switch (c) {
1558
+ case '"':
1559
+ case "'":
1560
+ case "/":
1561
+ tokenStart = position;
1562
+ tokenEndChar = c;
1563
+ break;
1564
+ }
1565
+ } else if ((c == tokenEndChar) && (str.charAt(position - 1) !== "\\")) {
1566
+ var token = str.substring(tokenStart, position + 1);
1567
+ tokens.push(token);
1568
+ var replacement = "@ko_token_" + (tokens.length - 1) + "@";
1569
+ str = str.substring(0, tokenStart) + replacement + str.substring(position + 1);
1570
+ position -= (token.length - replacement.length);
1571
+ tokenStart = null;
1572
+ }
1573
+ }
1574
+
1575
+ // Next pull out balanced paren, brace, and bracket blocks
1576
+ tokenStart = null;
1577
+ tokenEndChar = null;
1578
+ var tokenDepth = 0, tokenStartChar = null;
1579
+ for (var position = 0; position < str.length; position++) {
1580
+ var c = str.charAt(position);
1581
+ if (tokenStart === null) {
1582
+ switch (c) {
1583
+ case "{": tokenStart = position; tokenStartChar = c;
1584
+ tokenEndChar = "}";
1585
+ break;
1586
+ case "(": tokenStart = position; tokenStartChar = c;
1587
+ tokenEndChar = ")";
1588
+ break;
1589
+ case "[": tokenStart = position; tokenStartChar = c;
1590
+ tokenEndChar = "]";
1591
+ break;
1592
+ }
1593
+ }
1594
+
1595
+ if (c === tokenStartChar)
1596
+ tokenDepth++;
1597
+ else if (c === tokenEndChar) {
1598
+ tokenDepth--;
1599
+ if (tokenDepth === 0) {
1600
+ var token = str.substring(tokenStart, position + 1);
1601
+ tokens.push(token);
1602
+ var replacement = "@ko_token_" + (tokens.length - 1) + "@";
1603
+ str = str.substring(0, tokenStart) + replacement + str.substring(position + 1);
1604
+ position -= (token.length - replacement.length);
1605
+ tokenStart = null;
1606
+ }
1607
+ }
1608
+ }
1609
+
1610
+ // Now we can safely split on commas to get the key/value pairs
1611
+ var result = [];
1612
+ var keyValuePairs = str.split(",");
1613
+ for (var i = 0, j = keyValuePairs.length; i < j; i++) {
1614
+ var pair = keyValuePairs[i];
1615
+ var colonPos = pair.indexOf(":");
1616
+ if ((colonPos > 0) && (colonPos < pair.length - 1)) {
1617
+ var key = pair.substring(0, colonPos);
1618
+ var value = pair.substring(colonPos + 1);
1619
+ result.push({ 'key': restoreTokens(key, tokens), 'value': restoreTokens(value, tokens) });
1620
+ } else {
1621
+ result.push({ 'unknown': restoreTokens(pair, tokens) });
1622
+ }
1623
+ }
1624
+ return result;
1625
+ },
1626
+
1627
+ preProcessBindings: function (objectLiteralStringOrKeyValueArray) {
1628
+ var keyValueArray = typeof objectLiteralStringOrKeyValueArray === "string"
1629
+ ? ko.expressionRewriting.parseObjectLiteral(objectLiteralStringOrKeyValueArray)
1630
+ : objectLiteralStringOrKeyValueArray;
1631
+ var resultStrings = [], propertyAccessorResultStrings = [];
1632
+
1633
+ var keyValueEntry;
1634
+ for (var i = 0; keyValueEntry = keyValueArray[i]; i++) {
1635
+ if (resultStrings.length > 0)
1636
+ resultStrings.push(",");
1637
+
1638
+ if (keyValueEntry['key']) {
1639
+ var quotedKey = ensureQuoted(keyValueEntry['key']), val = keyValueEntry['value'];
1640
+ resultStrings.push(quotedKey);
1641
+ resultStrings.push(":");
1642
+ resultStrings.push(val);
1643
+
1644
+ if (val = getWriteableValue(ko.utils.stringTrim(val))) {
1645
+ if (propertyAccessorResultStrings.length > 0)
1646
+ propertyAccessorResultStrings.push(", ");
1647
+ propertyAccessorResultStrings.push(quotedKey + " : function(__ko_value) { " + val + " = __ko_value; }");
1648
+ }
1649
+ } else if (keyValueEntry['unknown']) {
1650
+ resultStrings.push(keyValueEntry['unknown']);
1651
+ }
1652
+ }
1653
+
1654
+ var combinedResult = resultStrings.join("");
1655
+ if (propertyAccessorResultStrings.length > 0) {
1656
+ var allPropertyAccessors = propertyAccessorResultStrings.join("");
1657
+ combinedResult = combinedResult + ", '_ko_property_writers' : { " + allPropertyAccessors + " } ";
1658
+ }
1659
+
1660
+ return combinedResult;
1661
+ },
1662
+
1663
+ keyValueArrayContainsKey: function(keyValueArray, key) {
1664
+ for (var i = 0; i < keyValueArray.length; i++)
1665
+ if (ko.utils.stringTrim(keyValueArray[i]['key']) == key)
1666
+ return true;
1667
+ return false;
1668
+ },
1669
+
1670
+ // Internal, private KO utility for updating model properties from within bindings
1671
+ // property: If the property being updated is (or might be) an observable, pass it here
1672
+ // If it turns out to be a writable observable, it will be written to directly
1673
+ // allBindingsAccessor: All bindings in the current execution context.
1674
+ // This will be searched for a '_ko_property_writers' property in case you're writing to a non-observable
1675
+ // key: The key identifying the property to be written. Example: for { hasFocus: myValue }, write to 'myValue' by specifying the key 'hasFocus'
1676
+ // value: The value to be written
1677
+ // checkIfDifferent: If true, and if the property being written is a writable observable, the value will only be written if
1678
+ // it is !== existing value on that writable observable
1679
+ writeValueToProperty: function(property, allBindingsAccessor, key, value, checkIfDifferent) {
1680
+ if (!property || !ko.isWriteableObservable(property)) {
1681
+ var propWriters = allBindingsAccessor()['_ko_property_writers'];
1682
+ if (propWriters && propWriters[key])
1683
+ propWriters[key](value);
1684
+ } else if (!checkIfDifferent || property.peek() !== value) {
1685
+ property(value);
1686
+ }
1687
+ }
1688
+ };
1689
+ })();
1690
+
1691
+ ko.exportSymbol('expressionRewriting', ko.expressionRewriting);
1692
+ ko.exportSymbol('expressionRewriting.bindingRewriteValidators', ko.expressionRewriting.bindingRewriteValidators);
1693
+ ko.exportSymbol('expressionRewriting.parseObjectLiteral', ko.expressionRewriting.parseObjectLiteral);
1694
+ ko.exportSymbol('expressionRewriting.preProcessBindings', ko.expressionRewriting.preProcessBindings);
1695
+
1696
+ // For backward compatibility, define the following aliases. (Previously, these function names were misleading because
1697
+ // they referred to JSON specifically, even though they actually work with arbitrary JavaScript object literal expressions.)
1698
+ ko.exportSymbol('jsonExpressionRewriting', ko.expressionRewriting);
1699
+ ko.exportSymbol('jsonExpressionRewriting.insertPropertyAccessorsIntoJson', ko.expressionRewriting.preProcessBindings);(function() {
1700
+ // "Virtual elements" is an abstraction on top of the usual DOM API which understands the notion that comment nodes
1701
+ // may be used to represent hierarchy (in addition to the DOM's natural hierarchy).
1702
+ // If you call the DOM-manipulating functions on ko.virtualElements, you will be able to read and write the state
1703
+ // of that virtual hierarchy
1704
+ //
1705
+ // The point of all this is to support containerless templates (e.g., <!-- ko foreach:someCollection -->blah<!-- /ko -->)
1706
+ // without having to scatter special cases all over the binding and templating code.
1707
+
1708
+ // IE 9 cannot reliably read the "nodeValue" property of a comment node (see https://github.com/SteveSanderson/knockout/issues/186)
1709
+ // but it does give them a nonstandard alternative property called "text" that it can read reliably. Other browsers don't have that property.
1710
+ // So, use node.text where available, and node.nodeValue elsewhere
1711
+ var commentNodesHaveTextProperty = document.createComment("test").text === "<!--test-->";
1712
+
1713
+ var startCommentRegex = commentNodesHaveTextProperty ? /^<!--\s*ko(?:\s+(.+\s*\:[\s\S]*))?\s*-->$/ : /^\s*ko(?:\s+(.+\s*\:[\s\S]*))?\s*$/;
1714
+ var endCommentRegex = commentNodesHaveTextProperty ? /^<!--\s*\/ko\s*-->$/ : /^\s*\/ko\s*$/;
1715
+ var htmlTagsWithOptionallyClosingChildren = { 'ul': true, 'ol': true };
1716
+
1717
+ function isStartComment(node) {
1718
+ return (node.nodeType == 8) && (commentNodesHaveTextProperty ? node.text : node.nodeValue).match(startCommentRegex);
1719
+ }
1720
+
1721
+ function isEndComment(node) {
1722
+ return (node.nodeType == 8) && (commentNodesHaveTextProperty ? node.text : node.nodeValue).match(endCommentRegex);
1723
+ }
1724
+
1725
+ function getVirtualChildren(startComment, allowUnbalanced) {
1726
+ var currentNode = startComment;
1727
+ var depth = 1;
1728
+ var children = [];
1729
+ while (currentNode = currentNode.nextSibling) {
1730
+ if (isEndComment(currentNode)) {
1731
+ depth--;
1732
+ if (depth === 0)
1733
+ return children;
1734
+ }
1735
+
1736
+ children.push(currentNode);
1737
+
1738
+ if (isStartComment(currentNode))
1739
+ depth++;
1740
+ }
1741
+ if (!allowUnbalanced)
1742
+ throw new Error("Cannot find closing comment tag to match: " + startComment.nodeValue);
1743
+ return null;
1744
+ }
1745
+
1746
+ function getMatchingEndComment(startComment, allowUnbalanced) {
1747
+ var allVirtualChildren = getVirtualChildren(startComment, allowUnbalanced);
1748
+ if (allVirtualChildren) {
1749
+ if (allVirtualChildren.length > 0)
1750
+ return allVirtualChildren[allVirtualChildren.length - 1].nextSibling;
1751
+ return startComment.nextSibling;
1752
+ } else
1753
+ return null; // Must have no matching end comment, and allowUnbalanced is true
1754
+ }
1755
+
1756
+ function getUnbalancedChildTags(node) {
1757
+ // e.g., from <div>OK</div><!-- ko blah --><span>Another</span>, returns: <!-- ko blah --><span>Another</span>
1758
+ // from <div>OK</div><!-- /ko --><!-- /ko -->, returns: <!-- /ko --><!-- /ko -->
1759
+ var childNode = node.firstChild, captureRemaining = null;
1760
+ if (childNode) {
1761
+ do {
1762
+ if (captureRemaining) // We already hit an unbalanced node and are now just scooping up all subsequent nodes
1763
+ captureRemaining.push(childNode);
1764
+ else if (isStartComment(childNode)) {
1765
+ var matchingEndComment = getMatchingEndComment(childNode, /* allowUnbalanced: */ true);
1766
+ if (matchingEndComment) // It's a balanced tag, so skip immediately to the end of this virtual set
1767
+ childNode = matchingEndComment;
1768
+ else
1769
+ captureRemaining = [childNode]; // It's unbalanced, so start capturing from this point
1770
+ } else if (isEndComment(childNode)) {
1771
+ captureRemaining = [childNode]; // It's unbalanced (if it wasn't, we'd have skipped over it already), so start capturing
1772
+ }
1773
+ } while (childNode = childNode.nextSibling);
1774
+ }
1775
+ return captureRemaining;
1776
+ }
1777
+
1778
+ ko.virtualElements = {
1779
+ allowedBindings: {},
1780
+
1781
+ childNodes: function(node) {
1782
+ return isStartComment(node) ? getVirtualChildren(node) : node.childNodes;
1783
+ },
1784
+
1785
+ emptyNode: function(node) {
1786
+ if (!isStartComment(node))
1787
+ ko.utils.emptyDomNode(node);
1788
+ else {
1789
+ var virtualChildren = ko.virtualElements.childNodes(node);
1790
+ for (var i = 0, j = virtualChildren.length; i < j; i++)
1791
+ ko.removeNode(virtualChildren[i]);
1792
+ }
1793
+ },
1794
+
1795
+ setDomNodeChildren: function(node, childNodes) {
1796
+ if (!isStartComment(node))
1797
+ ko.utils.setDomNodeChildren(node, childNodes);
1798
+ else {
1799
+ ko.virtualElements.emptyNode(node);
1800
+ var endCommentNode = node.nextSibling; // Must be the next sibling, as we just emptied the children
1801
+ for (var i = 0, j = childNodes.length; i < j; i++)
1802
+ endCommentNode.parentNode.insertBefore(childNodes[i], endCommentNode);
1803
+ }
1804
+ },
1805
+
1806
+ prepend: function(containerNode, nodeToPrepend) {
1807
+ if (!isStartComment(containerNode)) {
1808
+ if (containerNode.firstChild)
1809
+ containerNode.insertBefore(nodeToPrepend, containerNode.firstChild);
1810
+ else
1811
+ containerNode.appendChild(nodeToPrepend);
1812
+ } else {
1813
+ // Start comments must always have a parent and at least one following sibling (the end comment)
1814
+ containerNode.parentNode.insertBefore(nodeToPrepend, containerNode.nextSibling);
1815
+ }
1816
+ },
1817
+
1818
+ insertAfter: function(containerNode, nodeToInsert, insertAfterNode) {
1819
+ if (!insertAfterNode) {
1820
+ ko.virtualElements.prepend(containerNode, nodeToInsert);
1821
+ } else if (!isStartComment(containerNode)) {
1822
+ // Insert after insertion point
1823
+ if (insertAfterNode.nextSibling)
1824
+ containerNode.insertBefore(nodeToInsert, insertAfterNode.nextSibling);
1825
+ else
1826
+ containerNode.appendChild(nodeToInsert);
1827
+ } else {
1828
+ // Children of start comments must always have a parent and at least one following sibling (the end comment)
1829
+ containerNode.parentNode.insertBefore(nodeToInsert, insertAfterNode.nextSibling);
1830
+ }
1831
+ },
1832
+
1833
+ firstChild: function(node) {
1834
+ if (!isStartComment(node))
1835
+ return node.firstChild;
1836
+ if (!node.nextSibling || isEndComment(node.nextSibling))
1837
+ return null;
1838
+ return node.nextSibling;
1839
+ },
1840
+
1841
+ nextSibling: function(node) {
1842
+ if (isStartComment(node))
1843
+ node = getMatchingEndComment(node);
1844
+ if (node.nextSibling && isEndComment(node.nextSibling))
1845
+ return null;
1846
+ return node.nextSibling;
1847
+ },
1848
+
1849
+ virtualNodeBindingValue: function(node) {
1850
+ var regexMatch = isStartComment(node);
1851
+ return regexMatch ? regexMatch[1] : null;
1852
+ },
1853
+
1854
+ normaliseVirtualElementDomStructure: function(elementVerified) {
1855
+ // Workaround for https://github.com/SteveSanderson/knockout/issues/155
1856
+ // (IE <= 8 or IE 9 quirks mode parses your HTML weirdly, treating closing </li> tags as if they don't exist, thereby moving comment nodes
1857
+ // that are direct descendants of <ul> into the preceding <li>)
1858
+ if (!htmlTagsWithOptionallyClosingChildren[ko.utils.tagNameLower(elementVerified)])
1859
+ return;
1860
+
1861
+ // Scan immediate children to see if they contain unbalanced comment tags. If they do, those comment tags
1862
+ // must be intended to appear *after* that child, so move them there.
1863
+ var childNode = elementVerified.firstChild;
1864
+ if (childNode) {
1865
+ do {
1866
+ if (childNode.nodeType === 1) {
1867
+ var unbalancedTags = getUnbalancedChildTags(childNode);
1868
+ if (unbalancedTags) {
1869
+ // Fix up the DOM by moving the unbalanced tags to where they most likely were intended to be placed - *after* the child
1870
+ var nodeToInsertBefore = childNode.nextSibling;
1871
+ for (var i = 0; i < unbalancedTags.length; i++) {
1872
+ if (nodeToInsertBefore)
1873
+ elementVerified.insertBefore(unbalancedTags[i], nodeToInsertBefore);
1874
+ else
1875
+ elementVerified.appendChild(unbalancedTags[i]);
1876
+ }
1877
+ }
1878
+ }
1879
+ } while (childNode = childNode.nextSibling);
1880
+ }
1881
+ }
1882
+ };
1883
+ })();
1884
+ ko.exportSymbol('virtualElements', ko.virtualElements);
1885
+ ko.exportSymbol('virtualElements.allowedBindings', ko.virtualElements.allowedBindings);
1886
+ ko.exportSymbol('virtualElements.emptyNode', ko.virtualElements.emptyNode);
1887
+ //ko.exportSymbol('virtualElements.firstChild', ko.virtualElements.firstChild); // firstChild is not minified
1888
+ ko.exportSymbol('virtualElements.insertAfter', ko.virtualElements.insertAfter);
1889
+ //ko.exportSymbol('virtualElements.nextSibling', ko.virtualElements.nextSibling); // nextSibling is not minified
1890
+ ko.exportSymbol('virtualElements.prepend', ko.virtualElements.prepend);
1891
+ ko.exportSymbol('virtualElements.setDomNodeChildren', ko.virtualElements.setDomNodeChildren);
1892
+ (function() {
1893
+ var defaultBindingAttributeName = "data-bind";
1894
+
1895
+ ko.bindingProvider = function() {
1896
+ this.bindingCache = {};
1897
+ };
1898
+
1899
+ ko.utils.extend(ko.bindingProvider.prototype, {
1900
+ 'nodeHasBindings': function(node) {
1901
+ switch (node.nodeType) {
1902
+ case 1: return node.getAttribute(defaultBindingAttributeName) != null; // Element
1903
+ case 8: return ko.virtualElements.virtualNodeBindingValue(node) != null; // Comment node
1904
+ default: return false;
1905
+ }
1906
+ },
1907
+
1908
+ 'getBindings': function(node, bindingContext) {
1909
+ var bindingsString = this['getBindingsString'](node, bindingContext);
1910
+ return bindingsString ? this['parseBindingsString'](bindingsString, bindingContext, node) : null;
1911
+ },
1912
+
1913
+ // The following function is only used internally by this default provider.
1914
+ // It's not part of the interface definition for a general binding provider.
1915
+ 'getBindingsString': function(node, bindingContext) {
1916
+ switch (node.nodeType) {
1917
+ case 1: return node.getAttribute(defaultBindingAttributeName); // Element
1918
+ case 8: return ko.virtualElements.virtualNodeBindingValue(node); // Comment node
1919
+ default: return null;
1920
+ }
1921
+ },
1922
+
1923
+ // The following function is only used internally by this default provider.
1924
+ // It's not part of the interface definition for a general binding provider.
1925
+ 'parseBindingsString': function(bindingsString, bindingContext, node) {
1926
+ try {
1927
+ var bindingFunction = createBindingsStringEvaluatorViaCache(bindingsString, this.bindingCache);
1928
+ return bindingFunction(bindingContext, node);
1929
+ } catch (ex) {
1930
+ throw new Error("Unable to parse bindings.\nMessage: " + ex + ";\nBindings value: " + bindingsString);
1931
+ }
1932
+ }
1933
+ });
1934
+
1935
+ ko.bindingProvider['instance'] = new ko.bindingProvider();
1936
+
1937
+ function createBindingsStringEvaluatorViaCache(bindingsString, cache) {
1938
+ var cacheKey = bindingsString;
1939
+ return cache[cacheKey]
1940
+ || (cache[cacheKey] = createBindingsStringEvaluator(bindingsString));
1941
+ }
1942
+
1943
+ function createBindingsStringEvaluator(bindingsString) {
1944
+ // Build the source for a function that evaluates "expression"
1945
+ // For each scope variable, add an extra level of "with" nesting
1946
+ // Example result: with(sc1) { with(sc0) { return (expression) } }
1947
+ var rewrittenBindings = ko.expressionRewriting.preProcessBindings(bindingsString),
1948
+ functionBody = "with($context){with($data||{}){return{" + rewrittenBindings + "}}}";
1949
+ return new Function("$context", "$element", functionBody);
1950
+ }
1951
+ })();
1952
+
1953
+ ko.exportSymbol('bindingProvider', ko.bindingProvider);
1954
+ (function () {
1955
+ ko.bindingHandlers = {};
1956
+
1957
+ ko.bindingContext = function(dataItem, parentBindingContext, dataItemAlias) {
1958
+ if (parentBindingContext) {
1959
+ ko.utils.extend(this, parentBindingContext); // Inherit $root and any custom properties
1960
+ this['$parentContext'] = parentBindingContext;
1961
+ this['$parent'] = parentBindingContext['$data'];
1962
+ this['$parents'] = (parentBindingContext['$parents'] || []).slice(0);
1963
+ this['$parents'].unshift(this['$parent']);
1964
+ } else {
1965
+ this['$parents'] = [];
1966
+ this['$root'] = dataItem;
1967
+ // Export 'ko' in the binding context so it will be available in bindings and templates
1968
+ // even if 'ko' isn't exported as a global, such as when using an AMD loader.
1969
+ // See https://github.com/SteveSanderson/knockout/issues/490
1970
+ this['ko'] = ko;
1971
+ }
1972
+ this['$data'] = dataItem;
1973
+ if (dataItemAlias)
1974
+ this[dataItemAlias] = dataItem;
1975
+ }
1976
+ ko.bindingContext.prototype['createChildContext'] = function (dataItem, dataItemAlias) {
1977
+ return new ko.bindingContext(dataItem, this, dataItemAlias);
1978
+ };
1979
+ ko.bindingContext.prototype['extend'] = function(properties) {
1980
+ var clone = ko.utils.extend(new ko.bindingContext(), this);
1981
+ return ko.utils.extend(clone, properties);
1982
+ };
1983
+
1984
+ function validateThatBindingIsAllowedForVirtualElements(bindingName) {
1985
+ var validator = ko.virtualElements.allowedBindings[bindingName];
1986
+ if (!validator)
1987
+ throw new Error("The binding '" + bindingName + "' cannot be used with virtual elements")
1988
+ }
1989
+
1990
+ function applyBindingsToDescendantsInternal (viewModel, elementOrVirtualElement, bindingContextsMayDifferFromDomParentElement) {
1991
+ var currentChild, nextInQueue = ko.virtualElements.firstChild(elementOrVirtualElement);
1992
+ while (currentChild = nextInQueue) {
1993
+ // Keep a record of the next child *before* applying bindings, in case the binding removes the current child from its position
1994
+ nextInQueue = ko.virtualElements.nextSibling(currentChild);
1995
+ applyBindingsToNodeAndDescendantsInternal(viewModel, currentChild, bindingContextsMayDifferFromDomParentElement);
1996
+ }
1997
+ }
1998
+
1999
+ function applyBindingsToNodeAndDescendantsInternal (viewModel, nodeVerified, bindingContextMayDifferFromDomParentElement) {
2000
+ var shouldBindDescendants = true;
2001
+
2002
+ // Perf optimisation: Apply bindings only if...
2003
+ // (1) We need to store the binding context on this node (because it may differ from the DOM parent node's binding context)
2004
+ // Note that we can't store binding contexts on non-elements (e.g., text nodes), as IE doesn't allow expando properties for those
2005
+ // (2) It might have bindings (e.g., it has a data-bind attribute, or it's a marker for a containerless template)
2006
+ var isElement = (nodeVerified.nodeType === 1);
2007
+ if (isElement) // Workaround IE <= 8 HTML parsing weirdness
2008
+ ko.virtualElements.normaliseVirtualElementDomStructure(nodeVerified);
2009
+
2010
+ var shouldApplyBindings = (isElement && bindingContextMayDifferFromDomParentElement) // Case (1)
2011
+ || ko.bindingProvider['instance']['nodeHasBindings'](nodeVerified); // Case (2)
2012
+ if (shouldApplyBindings)
2013
+ shouldBindDescendants = applyBindingsToNodeInternal(nodeVerified, null, viewModel, bindingContextMayDifferFromDomParentElement).shouldBindDescendants;
2014
+
2015
+ if (shouldBindDescendants) {
2016
+ // We're recursing automatically into (real or virtual) child nodes without changing binding contexts. So,
2017
+ // * For children of a *real* element, the binding context is certainly the same as on their DOM .parentNode,
2018
+ // hence bindingContextsMayDifferFromDomParentElement is false
2019
+ // * For children of a *virtual* element, we can't be sure. Evaluating .parentNode on those children may
2020
+ // skip over any number of intermediate virtual elements, any of which might define a custom binding context,
2021
+ // hence bindingContextsMayDifferFromDomParentElement is true
2022
+ applyBindingsToDescendantsInternal(viewModel, nodeVerified, /* bindingContextsMayDifferFromDomParentElement: */ !isElement);
2023
+ }
2024
+ }
2025
+
2026
+ function applyBindingsToNodeInternal (node, bindings, viewModelOrBindingContext, bindingContextMayDifferFromDomParentElement) {
2027
+ // Need to be sure that inits are only run once, and updates never run until all the inits have been run
2028
+ var initPhase = 0; // 0 = before all inits, 1 = during inits, 2 = after all inits
2029
+
2030
+ // Each time the dependentObservable is evaluated (after data changes),
2031
+ // the binding attribute is reparsed so that it can pick out the correct
2032
+ // model properties in the context of the changed data.
2033
+ // DOM event callbacks need to be able to access this changed data,
2034
+ // so we need a single parsedBindings variable (shared by all callbacks
2035
+ // associated with this node's bindings) that all the closures can access.
2036
+ var parsedBindings;
2037
+ function makeValueAccessor(bindingKey) {
2038
+ return function () { return parsedBindings[bindingKey] }
2039
+ }
2040
+ function parsedBindingsAccessor() {
2041
+ return parsedBindings;
2042
+ }
2043
+
2044
+ var bindingHandlerThatControlsDescendantBindings;
2045
+ ko.dependentObservable(
2046
+ function () {
2047
+ // Ensure we have a nonnull binding context to work with
2048
+ var bindingContextInstance = viewModelOrBindingContext && (viewModelOrBindingContext instanceof ko.bindingContext)
2049
+ ? viewModelOrBindingContext
2050
+ : new ko.bindingContext(ko.utils.unwrapObservable(viewModelOrBindingContext));
2051
+ var viewModel = bindingContextInstance['$data'];
2052
+
2053
+ // Optimization: Don't store the binding context on this node if it's definitely the same as on node.parentNode, because
2054
+ // we can easily recover it just by scanning up the node's ancestors in the DOM
2055
+ // (note: here, parent node means "real DOM parent" not "virtual parent", as there's no O(1) way to find the virtual parent)
2056
+ if (bindingContextMayDifferFromDomParentElement)
2057
+ ko.storedBindingContextForNode(node, bindingContextInstance);
2058
+
2059
+ // Use evaluatedBindings if given, otherwise fall back on asking the bindings provider to give us some bindings
2060
+ var evaluatedBindings = (typeof bindings == "function") ? bindings(bindingContextInstance, node) : bindings;
2061
+ parsedBindings = evaluatedBindings || ko.bindingProvider['instance']['getBindings'](node, bindingContextInstance);
2062
+
2063
+ if (parsedBindings) {
2064
+ // First run all the inits, so bindings can register for notification on changes
2065
+ if (initPhase === 0) {
2066
+ initPhase = 1;
2067
+ for (var bindingKey in parsedBindings) {
2068
+ var binding = ko.bindingHandlers[bindingKey];
2069
+ if (binding && node.nodeType === 8)
2070
+ validateThatBindingIsAllowedForVirtualElements(bindingKey);
2071
+
2072
+ if (binding && typeof binding["init"] == "function") {
2073
+ var handlerInitFn = binding["init"];
2074
+ var initResult = handlerInitFn(node, makeValueAccessor(bindingKey), parsedBindingsAccessor, viewModel, bindingContextInstance);
2075
+
2076
+ // If this binding handler claims to control descendant bindings, make a note of this
2077
+ if (initResult && initResult['controlsDescendantBindings']) {
2078
+ if (bindingHandlerThatControlsDescendantBindings !== undefined)
2079
+ throw new Error("Multiple bindings (" + bindingHandlerThatControlsDescendantBindings + " and " + bindingKey + ") are trying to control descendant bindings of the same element. You cannot use these bindings together on the same element.");
2080
+ bindingHandlerThatControlsDescendantBindings = bindingKey;
2081
+ }
2082
+ }
2083
+ }
2084
+ initPhase = 2;
2085
+ }
2086
+
2087
+ // ... then run all the updates, which might trigger changes even on the first evaluation
2088
+ if (initPhase === 2) {
2089
+ for (var bindingKey in parsedBindings) {
2090
+ var binding = ko.bindingHandlers[bindingKey];
2091
+ if (binding && typeof binding["update"] == "function") {
2092
+ var handlerUpdateFn = binding["update"];
2093
+ handlerUpdateFn(node, makeValueAccessor(bindingKey), parsedBindingsAccessor, viewModel, bindingContextInstance);
2094
+ }
2095
+ }
2096
+ }
2097
+ }
2098
+ },
2099
+ null,
2100
+ { disposeWhenNodeIsRemoved : node }
2101
+ );
2102
+
2103
+ return {
2104
+ shouldBindDescendants: bindingHandlerThatControlsDescendantBindings === undefined
2105
+ };
2106
+ };
2107
+
2108
+ var storedBindingContextDomDataKey = "__ko_bindingContext__";
2109
+ ko.storedBindingContextForNode = function (node, bindingContext) {
2110
+ if (arguments.length == 2)
2111
+ ko.utils.domData.set(node, storedBindingContextDomDataKey, bindingContext);
2112
+ else
2113
+ return ko.utils.domData.get(node, storedBindingContextDomDataKey);
2114
+ }
2115
+
2116
+ ko.applyBindingsToNode = function (node, bindings, viewModel) {
2117
+ if (node.nodeType === 1) // If it's an element, workaround IE <= 8 HTML parsing weirdness
2118
+ ko.virtualElements.normaliseVirtualElementDomStructure(node);
2119
+ return applyBindingsToNodeInternal(node, bindings, viewModel, true);
2120
+ };
2121
+
2122
+ ko.applyBindingsToDescendants = function(viewModel, rootNode) {
2123
+ if (rootNode.nodeType === 1 || rootNode.nodeType === 8)
2124
+ applyBindingsToDescendantsInternal(viewModel, rootNode, true);
2125
+ };
2126
+
2127
+ ko.applyBindings = function (viewModel, rootNode) {
2128
+ if (rootNode && (rootNode.nodeType !== 1) && (rootNode.nodeType !== 8))
2129
+ throw new Error("ko.applyBindings: first parameter should be your view model; second parameter should be a DOM node");
2130
+ rootNode = rootNode || window.document.body; // Make "rootNode" parameter optional
2131
+
2132
+ applyBindingsToNodeAndDescendantsInternal(viewModel, rootNode, true);
2133
+ };
2134
+
2135
+ // Retrieving binding context from arbitrary nodes
2136
+ ko.contextFor = function(node) {
2137
+ // We can only do something meaningful for elements and comment nodes (in particular, not text nodes, as IE can't store domdata for them)
2138
+ switch (node.nodeType) {
2139
+ case 1:
2140
+ case 8:
2141
+ var context = ko.storedBindingContextForNode(node);
2142
+ if (context) return context;
2143
+ if (node.parentNode) return ko.contextFor(node.parentNode);
2144
+ break;
2145
+ }
2146
+ return undefined;
2147
+ };
2148
+ ko.dataFor = function(node) {
2149
+ var context = ko.contextFor(node);
2150
+ return context ? context['$data'] : undefined;
2151
+ };
2152
+
2153
+ ko.exportSymbol('bindingHandlers', ko.bindingHandlers);
2154
+ ko.exportSymbol('applyBindings', ko.applyBindings);
2155
+ ko.exportSymbol('applyBindingsToDescendants', ko.applyBindingsToDescendants);
2156
+ ko.exportSymbol('applyBindingsToNode', ko.applyBindingsToNode);
2157
+ ko.exportSymbol('contextFor', ko.contextFor);
2158
+ ko.exportSymbol('dataFor', ko.dataFor);
2159
+ })();
2160
+ var attrHtmlToJavascriptMap = { 'class': 'className', 'for': 'htmlFor' };
2161
+ ko.bindingHandlers['attr'] = {
2162
+ 'update': function(element, valueAccessor, allBindingsAccessor) {
2163
+ var value = ko.utils.unwrapObservable(valueAccessor()) || {};
2164
+ for (var attrName in value) {
2165
+ if (typeof attrName == "string") {
2166
+ var attrValue = ko.utils.unwrapObservable(value[attrName]);
2167
+
2168
+ // To cover cases like "attr: { checked:someProp }", we want to remove the attribute entirely
2169
+ // when someProp is a "no value"-like value (strictly null, false, or undefined)
2170
+ // (because the absence of the "checked" attr is how to mark an element as not checked, etc.)
2171
+ var toRemove = (attrValue === false) || (attrValue === null) || (attrValue === undefined);
2172
+ if (toRemove)
2173
+ element.removeAttribute(attrName);
2174
+
2175
+ // In IE <= 7 and IE8 Quirks Mode, you have to use the Javascript property name instead of the
2176
+ // HTML attribute name for certain attributes. IE8 Standards Mode supports the correct behavior,
2177
+ // but instead of figuring out the mode, we'll just set the attribute through the Javascript
2178
+ // property for IE <= 8.
2179
+ if (ko.utils.ieVersion <= 8 && attrName in attrHtmlToJavascriptMap) {
2180
+ attrName = attrHtmlToJavascriptMap[attrName];
2181
+ if (toRemove)
2182
+ element.removeAttribute(attrName);
2183
+ else
2184
+ element[attrName] = attrValue;
2185
+ } else if (!toRemove) {
2186
+ element.setAttribute(attrName, attrValue.toString());
2187
+ }
2188
+
2189
+ // Treat "name" specially - although you can think of it as an attribute, it also needs
2190
+ // special handling on older versions of IE (https://github.com/SteveSanderson/knockout/pull/333)
2191
+ // Deliberately being case-sensitive here because XHTML would regard "Name" as a different thing
2192
+ // entirely, and there's no strong reason to allow for such casing in HTML.
2193
+ if (attrName === "name") {
2194
+ ko.utils.setElementName(element, toRemove ? "" : attrValue.toString());
2195
+ }
2196
+ }
2197
+ }
2198
+ }
2199
+ };
2200
+ ko.bindingHandlers['checked'] = {
2201
+ 'init': function (element, valueAccessor, allBindingsAccessor) {
2202
+ var updateHandler = function() {
2203
+ var valueToWrite;
2204
+ if (element.type == "checkbox") {
2205
+ valueToWrite = element.checked;
2206
+ } else if ((element.type == "radio") && (element.checked)) {
2207
+ valueToWrite = element.value;
2208
+ } else {
2209
+ return; // "checked" binding only responds to checkboxes and selected radio buttons
2210
+ }
2211
+
2212
+ var modelValue = valueAccessor(), unwrappedValue = ko.utils.unwrapObservable(modelValue);
2213
+ if ((element.type == "checkbox") && (unwrappedValue instanceof Array)) {
2214
+ // For checkboxes bound to an array, we add/remove the checkbox value to that array
2215
+ // This works for both observable and non-observable arrays
2216
+ var existingEntryIndex = ko.utils.arrayIndexOf(unwrappedValue, element.value);
2217
+ if (element.checked && (existingEntryIndex < 0))
2218
+ modelValue.push(element.value);
2219
+ else if ((!element.checked) && (existingEntryIndex >= 0))
2220
+ modelValue.splice(existingEntryIndex, 1);
2221
+ } else {
2222
+ ko.expressionRewriting.writeValueToProperty(modelValue, allBindingsAccessor, 'checked', valueToWrite, true);
2223
+ }
2224
+ };
2225
+ ko.utils.registerEventHandler(element, "click", updateHandler);
2226
+
2227
+ // IE 6 won't allow radio buttons to be selected unless they have a name
2228
+ if ((element.type == "radio") && !element.name)
2229
+ ko.bindingHandlers['uniqueName']['init'](element, function() { return true });
2230
+ },
2231
+ 'update': function (element, valueAccessor) {
2232
+ var value = ko.utils.unwrapObservable(valueAccessor());
2233
+
2234
+ if (element.type == "checkbox") {
2235
+ if (value instanceof Array) {
2236
+ // When bound to an array, the checkbox being checked represents its value being present in that array
2237
+ element.checked = ko.utils.arrayIndexOf(value, element.value) >= 0;
2238
+ } else {
2239
+ // When bound to anything other value (not an array), the checkbox being checked represents the value being trueish
2240
+ element.checked = value;
2241
+ }
2242
+ } else if (element.type == "radio") {
2243
+ element.checked = (element.value == value);
2244
+ }
2245
+ }
2246
+ };
2247
+ var classesWrittenByBindingKey = '__ko__cssValue';
2248
+ ko.bindingHandlers['css'] = {
2249
+ 'update': function (element, valueAccessor) {
2250
+ var value = ko.utils.unwrapObservable(valueAccessor());
2251
+ if (typeof value == "object") {
2252
+ for (var className in value) {
2253
+ var shouldHaveClass = ko.utils.unwrapObservable(value[className]);
2254
+ ko.utils.toggleDomNodeCssClass(element, className, shouldHaveClass);
2255
+ }
2256
+ } else {
2257
+ value = String(value || ''); // Make sure we don't try to store or set a non-string value
2258
+ ko.utils.toggleDomNodeCssClass(element, element[classesWrittenByBindingKey], false);
2259
+ element[classesWrittenByBindingKey] = value;
2260
+ ko.utils.toggleDomNodeCssClass(element, value, true);
2261
+ }
2262
+ }
2263
+ };
2264
+ ko.bindingHandlers['enable'] = {
2265
+ 'update': function (element, valueAccessor) {
2266
+ var value = ko.utils.unwrapObservable(valueAccessor());
2267
+ if (value && element.disabled)
2268
+ element.removeAttribute("disabled");
2269
+ else if ((!value) && (!element.disabled))
2270
+ element.disabled = true;
2271
+ }
2272
+ };
2273
+
2274
+ ko.bindingHandlers['disable'] = {
2275
+ 'update': function (element, valueAccessor) {
2276
+ ko.bindingHandlers['enable']['update'](element, function() { return !ko.utils.unwrapObservable(valueAccessor()) });
2277
+ }
2278
+ };
2279
+ // For certain common events (currently just 'click'), allow a simplified data-binding syntax
2280
+ // e.g. click:handler instead of the usual full-length event:{click:handler}
2281
+ function makeEventHandlerShortcut(eventName) {
2282
+ ko.bindingHandlers[eventName] = {
2283
+ 'init': function(element, valueAccessor, allBindingsAccessor, viewModel) {
2284
+ var newValueAccessor = function () {
2285
+ var result = {};
2286
+ result[eventName] = valueAccessor();
2287
+ return result;
2288
+ };
2289
+ return ko.bindingHandlers['event']['init'].call(this, element, newValueAccessor, allBindingsAccessor, viewModel);
2290
+ }
2291
+ }
2292
+ }
2293
+
2294
+ ko.bindingHandlers['event'] = {
2295
+ 'init' : function (element, valueAccessor, allBindingsAccessor, viewModel) {
2296
+ var eventsToHandle = valueAccessor() || {};
2297
+ for(var eventNameOutsideClosure in eventsToHandle) {
2298
+ (function() {
2299
+ var eventName = eventNameOutsideClosure; // Separate variable to be captured by event handler closure
2300
+ if (typeof eventName == "string") {
2301
+ ko.utils.registerEventHandler(element, eventName, function (event) {
2302
+ var handlerReturnValue;
2303
+ var handlerFunction = valueAccessor()[eventName];
2304
+ if (!handlerFunction)
2305
+ return;
2306
+ var allBindings = allBindingsAccessor();
2307
+
2308
+ try {
2309
+ // Take all the event args, and prefix with the viewmodel
2310
+ var argsForHandler = ko.utils.makeArray(arguments);
2311
+ argsForHandler.unshift(viewModel);
2312
+ handlerReturnValue = handlerFunction.apply(viewModel, argsForHandler);
2313
+ } finally {
2314
+ if (handlerReturnValue !== true) { // Normally we want to prevent default action. Developer can override this be explicitly returning true.
2315
+ if (event.preventDefault)
2316
+ event.preventDefault();
2317
+ else
2318
+ event.returnValue = false;
2319
+ }
2320
+ }
2321
+
2322
+ var bubble = allBindings[eventName + 'Bubble'] !== false;
2323
+ if (!bubble) {
2324
+ event.cancelBubble = true;
2325
+ if (event.stopPropagation)
2326
+ event.stopPropagation();
2327
+ }
2328
+ });
2329
+ }
2330
+ })();
2331
+ }
2332
+ }
2333
+ };
2334
+ // "foreach: someExpression" is equivalent to "template: { foreach: someExpression }"
2335
+ // "foreach: { data: someExpression, afterAdd: myfn }" is equivalent to "template: { foreach: someExpression, afterAdd: myfn }"
2336
+ ko.bindingHandlers['foreach'] = {
2337
+ makeTemplateValueAccessor: function(valueAccessor) {
2338
+ return function() {
2339
+ var modelValue = valueAccessor(),
2340
+ unwrappedValue = ko.utils.peekObservable(modelValue); // Unwrap without setting a dependency here
2341
+
2342
+ // If unwrappedValue is the array, pass in the wrapped value on its own
2343
+ // The value will be unwrapped and tracked within the template binding
2344
+ // (See https://github.com/SteveSanderson/knockout/issues/523)
2345
+ if ((!unwrappedValue) || typeof unwrappedValue.length == "number")
2346
+ return { 'foreach': modelValue, 'templateEngine': ko.nativeTemplateEngine.instance };
2347
+
2348
+ // If unwrappedValue.data is the array, preserve all relevant options and unwrap again value so we get updates
2349
+ ko.utils.unwrapObservable(modelValue);
2350
+ return {
2351
+ 'foreach': unwrappedValue['data'],
2352
+ 'as': unwrappedValue['as'],
2353
+ 'includeDestroyed': unwrappedValue['includeDestroyed'],
2354
+ 'afterAdd': unwrappedValue['afterAdd'],
2355
+ 'beforeRemove': unwrappedValue['beforeRemove'],
2356
+ 'afterRender': unwrappedValue['afterRender'],
2357
+ 'beforeMove': unwrappedValue['beforeMove'],
2358
+ 'afterMove': unwrappedValue['afterMove'],
2359
+ 'templateEngine': ko.nativeTemplateEngine.instance
2360
+ };
2361
+ };
2362
+ },
2363
+ 'init': function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
2364
+ return ko.bindingHandlers['template']['init'](element, ko.bindingHandlers['foreach'].makeTemplateValueAccessor(valueAccessor));
2365
+ },
2366
+ 'update': function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
2367
+ return ko.bindingHandlers['template']['update'](element, ko.bindingHandlers['foreach'].makeTemplateValueAccessor(valueAccessor), allBindingsAccessor, viewModel, bindingContext);
2368
+ }
2369
+ };
2370
+ ko.expressionRewriting.bindingRewriteValidators['foreach'] = false; // Can't rewrite control flow bindings
2371
+ ko.virtualElements.allowedBindings['foreach'] = true;
2372
+ var hasfocusUpdatingProperty = '__ko_hasfocusUpdating';
2373
+ ko.bindingHandlers['hasfocus'] = {
2374
+ 'init': function(element, valueAccessor, allBindingsAccessor) {
2375
+ var handleElementFocusChange = function(isFocused) {
2376
+ // Where possible, ignore which event was raised and determine focus state using activeElement,
2377
+ // as this avoids phantom focus/blur events raised when changing tabs in modern browsers.
2378
+ // However, not all KO-targeted browsers (Firefox 2) support activeElement. For those browsers,
2379
+ // prevent a loss of focus when changing tabs/windows by setting a flag that prevents hasfocus
2380
+ // from calling 'blur()' on the element when it loses focus.
2381
+ // Discussion at https://github.com/SteveSanderson/knockout/pull/352
2382
+ element[hasfocusUpdatingProperty] = true;
2383
+ var ownerDoc = element.ownerDocument;
2384
+ if ("activeElement" in ownerDoc) {
2385
+ isFocused = (ownerDoc.activeElement === element);
2386
+ }
2387
+ var modelValue = valueAccessor();
2388
+ ko.expressionRewriting.writeValueToProperty(modelValue, allBindingsAccessor, 'hasfocus', isFocused, true);
2389
+ element[hasfocusUpdatingProperty] = false;
2390
+ };
2391
+ var handleElementFocusIn = handleElementFocusChange.bind(null, true);
2392
+ var handleElementFocusOut = handleElementFocusChange.bind(null, false);
2393
+
2394
+ ko.utils.registerEventHandler(element, "focus", handleElementFocusIn);
2395
+ ko.utils.registerEventHandler(element, "focusin", handleElementFocusIn); // For IE
2396
+ ko.utils.registerEventHandler(element, "blur", handleElementFocusOut);
2397
+ ko.utils.registerEventHandler(element, "focusout", handleElementFocusOut); // For IE
2398
+ },
2399
+ 'update': function(element, valueAccessor) {
2400
+ var value = ko.utils.unwrapObservable(valueAccessor());
2401
+ if (!element[hasfocusUpdatingProperty]) {
2402
+ value ? element.focus() : element.blur();
2403
+ ko.dependencyDetection.ignore(ko.utils.triggerEvent, null, [element, value ? "focusin" : "focusout"]); // For IE, which doesn't reliably fire "focus" or "blur" events synchronously
2404
+ }
2405
+ }
2406
+ };
2407
+ ko.bindingHandlers['html'] = {
2408
+ 'init': function() {
2409
+ // Prevent binding on the dynamically-injected HTML (as developers are unlikely to expect that, and it has security implications)
2410
+ return { 'controlsDescendantBindings': true };
2411
+ },
2412
+ 'update': function (element, valueAccessor) {
2413
+ // setHtml will unwrap the value if needed
2414
+ ko.utils.setHtml(element, valueAccessor());
2415
+ }
2416
+ };
2417
+ var withIfDomDataKey = '__ko_withIfBindingData';
2418
+ // Makes a binding like with or if
2419
+ function makeWithIfBinding(bindingKey, isWith, isNot, makeContextCallback) {
2420
+ ko.bindingHandlers[bindingKey] = {
2421
+ 'init': function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
2422
+ ko.utils.domData.set(element, withIfDomDataKey, {});
2423
+ return { 'controlsDescendantBindings': true };
2424
+ },
2425
+ 'update': function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
2426
+ var withIfData = ko.utils.domData.get(element, withIfDomDataKey),
2427
+ dataValue = ko.utils.unwrapObservable(valueAccessor()),
2428
+ shouldDisplay = !isNot !== !dataValue, // equivalent to isNot ? !dataValue : !!dataValue
2429
+ isFirstRender = !withIfData.savedNodes,
2430
+ needsRefresh = isFirstRender || isWith || (shouldDisplay !== withIfData.didDisplayOnLastUpdate);
2431
+
2432
+ if (needsRefresh) {
2433
+ if (isFirstRender) {
2434
+ withIfData.savedNodes = ko.utils.cloneNodes(ko.virtualElements.childNodes(element), true /* shouldCleanNodes */);
2435
+ }
2436
+
2437
+ if (shouldDisplay) {
2438
+ if (!isFirstRender) {
2439
+ ko.virtualElements.setDomNodeChildren(element, ko.utils.cloneNodes(withIfData.savedNodes));
2440
+ }
2441
+ ko.applyBindingsToDescendants(makeContextCallback ? makeContextCallback(bindingContext, dataValue) : bindingContext, element);
2442
+ } else {
2443
+ ko.virtualElements.emptyNode(element);
2444
+ }
2445
+
2446
+ withIfData.didDisplayOnLastUpdate = shouldDisplay;
2447
+ }
2448
+ }
2449
+ };
2450
+ ko.expressionRewriting.bindingRewriteValidators[bindingKey] = false; // Can't rewrite control flow bindings
2451
+ ko.virtualElements.allowedBindings[bindingKey] = true;
2452
+ }
2453
+
2454
+ // Construct the actual binding handlers
2455
+ makeWithIfBinding('if');
2456
+ makeWithIfBinding('ifnot', false /* isWith */, true /* isNot */);
2457
+ makeWithIfBinding('with', true /* isWith */, false /* isNot */,
2458
+ function(bindingContext, dataValue) {
2459
+ return bindingContext['createChildContext'](dataValue);
2460
+ }
2461
+ );
2462
+ function ensureDropdownSelectionIsConsistentWithModelValue(element, modelValue, preferModelValue) {
2463
+ if (preferModelValue) {
2464
+ if (modelValue !== ko.selectExtensions.readValue(element))
2465
+ ko.selectExtensions.writeValue(element, modelValue);
2466
+ }
2467
+
2468
+ // No matter which direction we're syncing in, we want the end result to be equality between dropdown value and model value.
2469
+ // If they aren't equal, either we prefer the dropdown value, or the model value couldn't be represented, so either way,
2470
+ // change the model value to match the dropdown.
2471
+ if (modelValue !== ko.selectExtensions.readValue(element))
2472
+ ko.dependencyDetection.ignore(ko.utils.triggerEvent, null, [element, "change"]);
2473
+ };
2474
+
2475
+ ko.bindingHandlers['options'] = {
2476
+ 'update': function (element, valueAccessor, allBindingsAccessor) {
2477
+ if (ko.utils.tagNameLower(element) !== "select")
2478
+ throw new Error("options binding applies only to SELECT elements");
2479
+
2480
+ var selectWasPreviouslyEmpty = element.length == 0;
2481
+ var previousSelectedValues = ko.utils.arrayMap(ko.utils.arrayFilter(element.childNodes, function (node) {
2482
+ return node.tagName && (ko.utils.tagNameLower(node) === "option") && node.selected;
2483
+ }), function (node) {
2484
+ return ko.selectExtensions.readValue(node) || node.innerText || node.textContent;
2485
+ });
2486
+ var previousScrollTop = element.scrollTop;
2487
+
2488
+ var value = ko.utils.unwrapObservable(valueAccessor());
2489
+ var selectedValue = element.value;
2490
+
2491
+ // Remove all existing <option>s.
2492
+ // Need to use .remove() rather than .removeChild() for <option>s otherwise IE behaves oddly (https://github.com/SteveSanderson/knockout/issues/134)
2493
+ while (element.length > 0) {
2494
+ ko.cleanNode(element.options[0]);
2495
+ element.remove(0);
2496
+ }
2497
+
2498
+ if (value) {
2499
+ var allBindings = allBindingsAccessor(),
2500
+ includeDestroyed = allBindings['optionsIncludeDestroyed'];
2501
+
2502
+ if (typeof value.length != "number")
2503
+ value = [value];
2504
+ if (allBindings['optionsCaption']) {
2505
+ var option = document.createElement("option");
2506
+ ko.utils.setHtml(option, allBindings['optionsCaption']);
2507
+ ko.selectExtensions.writeValue(option, undefined);
2508
+ element.appendChild(option);
2509
+ }
2510
+
2511
+ for (var i = 0, j = value.length; i < j; i++) {
2512
+ // Skip destroyed items
2513
+ var arrayEntry = value[i];
2514
+ if (arrayEntry && arrayEntry['_destroy'] && !includeDestroyed)
2515
+ continue;
2516
+
2517
+ var option = document.createElement("option");
2518
+
2519
+ function applyToObject(object, predicate, defaultValue) {
2520
+ var predicateType = typeof predicate;
2521
+ if (predicateType == "function") // Given a function; run it against the data value
2522
+ return predicate(object);
2523
+ else if (predicateType == "string") // Given a string; treat it as a property name on the data value
2524
+ return object[predicate];
2525
+ else // Given no optionsText arg; use the data value itself
2526
+ return defaultValue;
2527
+ }
2528
+
2529
+ // Apply a value to the option element
2530
+ var optionValue = applyToObject(arrayEntry, allBindings['optionsValue'], arrayEntry);
2531
+ ko.selectExtensions.writeValue(option, ko.utils.unwrapObservable(optionValue));
2532
+
2533
+ // Apply some text to the option element
2534
+ var optionText = applyToObject(arrayEntry, allBindings['optionsText'], optionValue);
2535
+ ko.utils.setTextContent(option, optionText);
2536
+
2537
+ element.appendChild(option);
2538
+ }
2539
+
2540
+ // IE6 doesn't like us to assign selection to OPTION nodes before they're added to the document.
2541
+ // That's why we first added them without selection. Now it's time to set the selection.
2542
+ var newOptions = element.getElementsByTagName("option");
2543
+ var countSelectionsRetained = 0;
2544
+ for (var i = 0, j = newOptions.length; i < j; i++) {
2545
+ if (ko.utils.arrayIndexOf(previousSelectedValues, ko.selectExtensions.readValue(newOptions[i])) >= 0) {
2546
+ ko.utils.setOptionNodeSelectionState(newOptions[i], true);
2547
+ countSelectionsRetained++;
2548
+ }
2549
+ }
2550
+
2551
+ element.scrollTop = previousScrollTop;
2552
+
2553
+ if (selectWasPreviouslyEmpty && ('value' in allBindings)) {
2554
+ // Ensure consistency between model value and selected option.
2555
+ // If the dropdown is being populated for the first time here (or was otherwise previously empty),
2556
+ // the dropdown selection state is meaningless, so we preserve the model value.
2557
+ ensureDropdownSelectionIsConsistentWithModelValue(element, ko.utils.peekObservable(allBindings['value']), /* preferModelValue */ true);
2558
+ }
2559
+
2560
+ // Workaround for IE9 bug
2561
+ ko.utils.ensureSelectElementIsRenderedCorrectly(element);
2562
+ }
2563
+ }
2564
+ };
2565
+ ko.bindingHandlers['options'].optionValueDomDataKey = '__ko.optionValueDomData__';
2566
+ ko.bindingHandlers['selectedOptions'] = {
2567
+ 'init': function (element, valueAccessor, allBindingsAccessor) {
2568
+ ko.utils.registerEventHandler(element, "change", function () {
2569
+ var value = valueAccessor(), valueToWrite = [];
2570
+ ko.utils.arrayForEach(element.getElementsByTagName("option"), function(node) {
2571
+ if (node.selected)
2572
+ valueToWrite.push(ko.selectExtensions.readValue(node));
2573
+ });
2574
+ ko.expressionRewriting.writeValueToProperty(value, allBindingsAccessor, 'value', valueToWrite);
2575
+ });
2576
+ },
2577
+ 'update': function (element, valueAccessor) {
2578
+ if (ko.utils.tagNameLower(element) != "select")
2579
+ throw new Error("values binding applies only to SELECT elements");
2580
+
2581
+ var newValue = ko.utils.unwrapObservable(valueAccessor());
2582
+ if (newValue && typeof newValue.length == "number") {
2583
+ ko.utils.arrayForEach(element.getElementsByTagName("option"), function(node) {
2584
+ var isSelected = ko.utils.arrayIndexOf(newValue, ko.selectExtensions.readValue(node)) >= 0;
2585
+ ko.utils.setOptionNodeSelectionState(node, isSelected);
2586
+ });
2587
+ }
2588
+ }
2589
+ };
2590
+ ko.bindingHandlers['style'] = {
2591
+ 'update': function (element, valueAccessor) {
2592
+ var value = ko.utils.unwrapObservable(valueAccessor() || {});
2593
+ for (var styleName in value) {
2594
+ if (typeof styleName == "string") {
2595
+ var styleValue = ko.utils.unwrapObservable(value[styleName]);
2596
+ element.style[styleName] = styleValue || ""; // Empty string removes the value, whereas null/undefined have no effect
2597
+ }
2598
+ }
2599
+ }
2600
+ };
2601
+ ko.bindingHandlers['submit'] = {
2602
+ 'init': function (element, valueAccessor, allBindingsAccessor, viewModel) {
2603
+ if (typeof valueAccessor() != "function")
2604
+ throw new Error("The value for a submit binding must be a function");
2605
+ ko.utils.registerEventHandler(element, "submit", function (event) {
2606
+ var handlerReturnValue;
2607
+ var value = valueAccessor();
2608
+ try { handlerReturnValue = value.call(viewModel, element); }
2609
+ finally {
2610
+ if (handlerReturnValue !== true) { // Normally we want to prevent default action. Developer can override this be explicitly returning true.
2611
+ if (event.preventDefault)
2612
+ event.preventDefault();
2613
+ else
2614
+ event.returnValue = false;
2615
+ }
2616
+ }
2617
+ });
2618
+ }
2619
+ };
2620
+ ko.bindingHandlers['text'] = {
2621
+ 'update': function (element, valueAccessor) {
2622
+ ko.utils.setTextContent(element, valueAccessor());
2623
+ }
2624
+ };
2625
+ ko.virtualElements.allowedBindings['text'] = true;
2626
+ ko.bindingHandlers['uniqueName'] = {
2627
+ 'init': function (element, valueAccessor) {
2628
+ if (valueAccessor()) {
2629
+ var name = "ko_unique_" + (++ko.bindingHandlers['uniqueName'].currentIndex);
2630
+ ko.utils.setElementName(element, name);
2631
+ }
2632
+ }
2633
+ };
2634
+ ko.bindingHandlers['uniqueName'].currentIndex = 0;
2635
+ ko.bindingHandlers['value'] = {
2636
+ 'init': function (element, valueAccessor, allBindingsAccessor) {
2637
+ // Always catch "change" event; possibly other events too if asked
2638
+ var eventsToCatch = ["change"];
2639
+ var requestedEventsToCatch = allBindingsAccessor()["valueUpdate"];
2640
+ var propertyChangedFired = false;
2641
+ if (requestedEventsToCatch) {
2642
+ if (typeof requestedEventsToCatch == "string") // Allow both individual event names, and arrays of event names
2643
+ requestedEventsToCatch = [requestedEventsToCatch];
2644
+ ko.utils.arrayPushAll(eventsToCatch, requestedEventsToCatch);
2645
+ eventsToCatch = ko.utils.arrayGetDistinctValues(eventsToCatch);
2646
+ }
2647
+
2648
+ var valueUpdateHandler = function() {
2649
+ propertyChangedFired = false;
2650
+ var modelValue = valueAccessor();
2651
+ var elementValue = ko.selectExtensions.readValue(element);
2652
+ ko.expressionRewriting.writeValueToProperty(modelValue, allBindingsAccessor, 'value', elementValue);
2653
+ }
2654
+
2655
+ // Workaround for https://github.com/SteveSanderson/knockout/issues/122
2656
+ // IE doesn't fire "change" events on textboxes if the user selects a value from its autocomplete list
2657
+ var ieAutoCompleteHackNeeded = ko.utils.ieVersion && element.tagName.toLowerCase() == "input" && element.type == "text"
2658
+ && element.autocomplete != "off" && (!element.form || element.form.autocomplete != "off");
2659
+ if (ieAutoCompleteHackNeeded && ko.utils.arrayIndexOf(eventsToCatch, "propertychange") == -1) {
2660
+ ko.utils.registerEventHandler(element, "propertychange", function () { propertyChangedFired = true });
2661
+ ko.utils.registerEventHandler(element, "blur", function() {
2662
+ if (propertyChangedFired) {
2663
+ valueUpdateHandler();
2664
+ }
2665
+ });
2666
+ }
2667
+
2668
+ ko.utils.arrayForEach(eventsToCatch, function(eventName) {
2669
+ // The syntax "after<eventname>" means "run the handler asynchronously after the event"
2670
+ // This is useful, for example, to catch "keydown" events after the browser has updated the control
2671
+ // (otherwise, ko.selectExtensions.readValue(this) will receive the control's value *before* the key event)
2672
+ var handler = valueUpdateHandler;
2673
+ if (ko.utils.stringStartsWith(eventName, "after")) {
2674
+ handler = function() { setTimeout(valueUpdateHandler, 0) };
2675
+ eventName = eventName.substring("after".length);
2676
+ }
2677
+ ko.utils.registerEventHandler(element, eventName, handler);
2678
+ });
2679
+ },
2680
+ 'update': function (element, valueAccessor) {
2681
+ var valueIsSelectOption = ko.utils.tagNameLower(element) === "select";
2682
+ var newValue = ko.utils.unwrapObservable(valueAccessor());
2683
+ var elementValue = ko.selectExtensions.readValue(element);
2684
+ var valueHasChanged = (newValue != elementValue);
2685
+
2686
+ // JavaScript's 0 == "" behavious is unfortunate here as it prevents writing 0 to an empty text box (loose equality suggests the values are the same).
2687
+ // We don't want to do a strict equality comparison as that is more confusing for developers in certain cases, so we specifically special case 0 != "" here.
2688
+ if ((newValue === 0) && (elementValue !== 0) && (elementValue !== "0"))
2689
+ valueHasChanged = true;
2690
+
2691
+ if (valueHasChanged) {
2692
+ var applyValueAction = function () { ko.selectExtensions.writeValue(element, newValue); };
2693
+ applyValueAction();
2694
+
2695
+ // Workaround for IE6 bug: It won't reliably apply values to SELECT nodes during the same execution thread
2696
+ // right after you've changed the set of OPTION nodes on it. So for that node type, we'll schedule a second thread
2697
+ // to apply the value as well.
2698
+ var alsoApplyAsynchronously = valueIsSelectOption;
2699
+ if (alsoApplyAsynchronously)
2700
+ setTimeout(applyValueAction, 0);
2701
+ }
2702
+
2703
+ // If you try to set a model value that can't be represented in an already-populated dropdown, reject that change,
2704
+ // because you're not allowed to have a model value that disagrees with a visible UI selection.
2705
+ if (valueIsSelectOption && (element.length > 0))
2706
+ ensureDropdownSelectionIsConsistentWithModelValue(element, newValue, /* preferModelValue */ false);
2707
+ }
2708
+ };
2709
+ ko.bindingHandlers['visible'] = {
2710
+ 'update': function (element, valueAccessor) {
2711
+ var value = ko.utils.unwrapObservable(valueAccessor());
2712
+ var isCurrentlyVisible = !(element.style.display == "none");
2713
+ if (value && !isCurrentlyVisible)
2714
+ element.style.display = "";
2715
+ else if ((!value) && isCurrentlyVisible)
2716
+ element.style.display = "none";
2717
+ }
2718
+ };
2719
+ // 'click' is just a shorthand for the usual full-length event:{click:handler}
2720
+ makeEventHandlerShortcut('click');
2721
+ // If you want to make a custom template engine,
2722
+ //
2723
+ // [1] Inherit from this class (like ko.nativeTemplateEngine does)
2724
+ // [2] Override 'renderTemplateSource', supplying a function with this signature:
2725
+ //
2726
+ // function (templateSource, bindingContext, options) {
2727
+ // // - templateSource.text() is the text of the template you should render
2728
+ // // - bindingContext.$data is the data you should pass into the template
2729
+ // // - you might also want to make bindingContext.$parent, bindingContext.$parents,
2730
+ // // and bindingContext.$root available in the template too
2731
+ // // - options gives you access to any other properties set on "data-bind: { template: options }"
2732
+ // //
2733
+ // // Return value: an array of DOM nodes
2734
+ // }
2735
+ //
2736
+ // [3] Override 'createJavaScriptEvaluatorBlock', supplying a function with this signature:
2737
+ //
2738
+ // function (script) {
2739
+ // // Return value: Whatever syntax means "Evaluate the JavaScript statement 'script' and output the result"
2740
+ // // For example, the jquery.tmpl template engine converts 'someScript' to '${ someScript }'
2741
+ // }
2742
+ //
2743
+ // This is only necessary if you want to allow data-bind attributes to reference arbitrary template variables.
2744
+ // If you don't want to allow that, you can set the property 'allowTemplateRewriting' to false (like ko.nativeTemplateEngine does)
2745
+ // and then you don't need to override 'createJavaScriptEvaluatorBlock'.
2746
+
2747
+ ko.templateEngine = function () { };
2748
+
2749
+ ko.templateEngine.prototype['renderTemplateSource'] = function (templateSource, bindingContext, options) {
2750
+ throw new Error("Override renderTemplateSource");
2751
+ };
2752
+
2753
+ ko.templateEngine.prototype['createJavaScriptEvaluatorBlock'] = function (script) {
2754
+ throw new Error("Override createJavaScriptEvaluatorBlock");
2755
+ };
2756
+
2757
+ ko.templateEngine.prototype['makeTemplateSource'] = function(template, templateDocument) {
2758
+ // Named template
2759
+ if (typeof template == "string") {
2760
+ templateDocument = templateDocument || document;
2761
+ var elem = templateDocument.getElementById(template);
2762
+ if (!elem)
2763
+ throw new Error("Cannot find template with ID " + template);
2764
+ return new ko.templateSources.domElement(elem);
2765
+ } else if ((template.nodeType == 1) || (template.nodeType == 8)) {
2766
+ // Anonymous template
2767
+ return new ko.templateSources.anonymousTemplate(template);
2768
+ } else
2769
+ throw new Error("Unknown template type: " + template);
2770
+ };
2771
+
2772
+ ko.templateEngine.prototype['renderTemplate'] = function (template, bindingContext, options, templateDocument) {
2773
+ var templateSource = this['makeTemplateSource'](template, templateDocument);
2774
+ return this['renderTemplateSource'](templateSource, bindingContext, options);
2775
+ };
2776
+
2777
+ ko.templateEngine.prototype['isTemplateRewritten'] = function (template, templateDocument) {
2778
+ // Skip rewriting if requested
2779
+ if (this['allowTemplateRewriting'] === false)
2780
+ return true;
2781
+ return this['makeTemplateSource'](template, templateDocument)['data']("isRewritten");
2782
+ };
2783
+
2784
+ ko.templateEngine.prototype['rewriteTemplate'] = function (template, rewriterCallback, templateDocument) {
2785
+ var templateSource = this['makeTemplateSource'](template, templateDocument);
2786
+ var rewritten = rewriterCallback(templateSource['text']());
2787
+ templateSource['text'](rewritten);
2788
+ templateSource['data']("isRewritten", true);
2789
+ };
2790
+
2791
+ ko.exportSymbol('templateEngine', ko.templateEngine);
2792
+
2793
+ ko.templateRewriting = (function () {
2794
+ var memoizeDataBindingAttributeSyntaxRegex = /(<[a-z]+\d*(\s+(?!data-bind=)[a-z0-9\-]+(=(\"[^\"]*\"|\'[^\']*\'))?)*\s+)data-bind=(["'])([\s\S]*?)\5/gi;
2795
+ var memoizeVirtualContainerBindingSyntaxRegex = /<!--\s*ko\b\s*([\s\S]*?)\s*-->/g;
2796
+
2797
+ function validateDataBindValuesForRewriting(keyValueArray) {
2798
+ var allValidators = ko.expressionRewriting.bindingRewriteValidators;
2799
+ for (var i = 0; i < keyValueArray.length; i++) {
2800
+ var key = keyValueArray[i]['key'];
2801
+ if (allValidators.hasOwnProperty(key)) {
2802
+ var validator = allValidators[key];
2803
+
2804
+ if (typeof validator === "function") {
2805
+ var possibleErrorMessage = validator(keyValueArray[i]['value']);
2806
+ if (possibleErrorMessage)
2807
+ throw new Error(possibleErrorMessage);
2808
+ } else if (!validator) {
2809
+ throw new Error("This template engine does not support the '" + key + "' binding within its templates");
2810
+ }
2811
+ }
2812
+ }
2813
+ }
2814
+
2815
+ function constructMemoizedTagReplacement(dataBindAttributeValue, tagToRetain, templateEngine) {
2816
+ var dataBindKeyValueArray = ko.expressionRewriting.parseObjectLiteral(dataBindAttributeValue);
2817
+ validateDataBindValuesForRewriting(dataBindKeyValueArray);
2818
+ var rewrittenDataBindAttributeValue = ko.expressionRewriting.preProcessBindings(dataBindKeyValueArray);
2819
+
2820
+ // For no obvious reason, Opera fails to evaluate rewrittenDataBindAttributeValue unless it's wrapped in an additional
2821
+ // anonymous function, even though Opera's built-in debugger can evaluate it anyway. No other browser requires this
2822
+ // extra indirection.
2823
+ var applyBindingsToNextSiblingScript =
2824
+ "ko.__tr_ambtns(function($context,$element){return(function(){return{ " + rewrittenDataBindAttributeValue + " } })()})";
2825
+ return templateEngine['createJavaScriptEvaluatorBlock'](applyBindingsToNextSiblingScript) + tagToRetain;
2826
+ }
2827
+
2828
+ return {
2829
+ ensureTemplateIsRewritten: function (template, templateEngine, templateDocument) {
2830
+ if (!templateEngine['isTemplateRewritten'](template, templateDocument))
2831
+ templateEngine['rewriteTemplate'](template, function (htmlString) {
2832
+ return ko.templateRewriting.memoizeBindingAttributeSyntax(htmlString, templateEngine);
2833
+ }, templateDocument);
2834
+ },
2835
+
2836
+ memoizeBindingAttributeSyntax: function (htmlString, templateEngine) {
2837
+ return htmlString.replace(memoizeDataBindingAttributeSyntaxRegex, function () {
2838
+ return constructMemoizedTagReplacement(/* dataBindAttributeValue: */ arguments[6], /* tagToRetain: */ arguments[1], templateEngine);
2839
+ }).replace(memoizeVirtualContainerBindingSyntaxRegex, function() {
2840
+ return constructMemoizedTagReplacement(/* dataBindAttributeValue: */ arguments[1], /* tagToRetain: */ "<!-- ko -->", templateEngine);
2841
+ });
2842
+ },
2843
+
2844
+ applyMemoizedBindingsToNextSibling: function (bindings) {
2845
+ return ko.memoization.memoize(function (domNode, bindingContext) {
2846
+ if (domNode.nextSibling)
2847
+ ko.applyBindingsToNode(domNode.nextSibling, bindings, bindingContext);
2848
+ });
2849
+ }
2850
+ }
2851
+ })();
2852
+
2853
+
2854
+ // Exported only because it has to be referenced by string lookup from within rewritten template
2855
+ ko.exportSymbol('__tr_ambtns', ko.templateRewriting.applyMemoizedBindingsToNextSibling);
2856
+ (function() {
2857
+ // A template source represents a read/write way of accessing a template. This is to eliminate the need for template loading/saving
2858
+ // logic to be duplicated in every template engine (and means they can all work with anonymous templates, etc.)
2859
+ //
2860
+ // Two are provided by default:
2861
+ // 1. ko.templateSources.domElement - reads/writes the text content of an arbitrary DOM element
2862
+ // 2. ko.templateSources.anonymousElement - uses ko.utils.domData to read/write text *associated* with the DOM element, but
2863
+ // without reading/writing the actual element text content, since it will be overwritten
2864
+ // with the rendered template output.
2865
+ // You can implement your own template source if you want to fetch/store templates somewhere other than in DOM elements.
2866
+ // Template sources need to have the following functions:
2867
+ // text() - returns the template text from your storage location
2868
+ // text(value) - writes the supplied template text to your storage location
2869
+ // data(key) - reads values stored using data(key, value) - see below
2870
+ // data(key, value) - associates "value" with this template and the key "key". Is used to store information like "isRewritten".
2871
+ //
2872
+ // Optionally, template sources can also have the following functions:
2873
+ // nodes() - returns a DOM element containing the nodes of this template, where available
2874
+ // nodes(value) - writes the given DOM element to your storage location
2875
+ // If a DOM element is available for a given template source, template engines are encouraged to use it in preference over text()
2876
+ // for improved speed. However, all templateSources must supply text() even if they don't supply nodes().
2877
+ //
2878
+ // Once you've implemented a templateSource, make your template engine use it by subclassing whatever template engine you were
2879
+ // using and overriding "makeTemplateSource" to return an instance of your custom template source.
2880
+
2881
+ ko.templateSources = {};
2882
+
2883
+ // ---- ko.templateSources.domElement -----
2884
+
2885
+ ko.templateSources.domElement = function(element) {
2886
+ this.domElement = element;
2887
+ }
2888
+
2889
+ ko.templateSources.domElement.prototype['text'] = function(/* valueToWrite */) {
2890
+ var tagNameLower = ko.utils.tagNameLower(this.domElement),
2891
+ elemContentsProperty = tagNameLower === "script" ? "text"
2892
+ : tagNameLower === "textarea" ? "value"
2893
+ : "innerHTML";
2894
+
2895
+ if (arguments.length == 0) {
2896
+ return this.domElement[elemContentsProperty];
2897
+ } else {
2898
+ var valueToWrite = arguments[0];
2899
+ if (elemContentsProperty === "innerHTML")
2900
+ ko.utils.setHtml(this.domElement, valueToWrite);
2901
+ else
2902
+ this.domElement[elemContentsProperty] = valueToWrite;
2903
+ }
2904
+ };
2905
+
2906
+ ko.templateSources.domElement.prototype['data'] = function(key /*, valueToWrite */) {
2907
+ if (arguments.length === 1) {
2908
+ return ko.utils.domData.get(this.domElement, "templateSourceData_" + key);
2909
+ } else {
2910
+ ko.utils.domData.set(this.domElement, "templateSourceData_" + key, arguments[1]);
2911
+ }
2912
+ };
2913
+
2914
+ // ---- ko.templateSources.anonymousTemplate -----
2915
+ // Anonymous templates are normally saved/retrieved as DOM nodes through "nodes".
2916
+ // For compatibility, you can also read "text"; it will be serialized from the nodes on demand.
2917
+ // Writing to "text" is still supported, but then the template data will not be available as DOM nodes.
2918
+
2919
+ var anonymousTemplatesDomDataKey = "__ko_anon_template__";
2920
+ ko.templateSources.anonymousTemplate = function(element) {
2921
+ this.domElement = element;
2922
+ }
2923
+ ko.templateSources.anonymousTemplate.prototype = new ko.templateSources.domElement();
2924
+ ko.templateSources.anonymousTemplate.prototype['text'] = function(/* valueToWrite */) {
2925
+ if (arguments.length == 0) {
2926
+ var templateData = ko.utils.domData.get(this.domElement, anonymousTemplatesDomDataKey) || {};
2927
+ if (templateData.textData === undefined && templateData.containerData)
2928
+ templateData.textData = templateData.containerData.innerHTML;
2929
+ return templateData.textData;
2930
+ } else {
2931
+ var valueToWrite = arguments[0];
2932
+ ko.utils.domData.set(this.domElement, anonymousTemplatesDomDataKey, {textData: valueToWrite});
2933
+ }
2934
+ };
2935
+ ko.templateSources.domElement.prototype['nodes'] = function(/* valueToWrite */) {
2936
+ if (arguments.length == 0) {
2937
+ var templateData = ko.utils.domData.get(this.domElement, anonymousTemplatesDomDataKey) || {};
2938
+ return templateData.containerData;
2939
+ } else {
2940
+ var valueToWrite = arguments[0];
2941
+ ko.utils.domData.set(this.domElement, anonymousTemplatesDomDataKey, {containerData: valueToWrite});
2942
+ }
2943
+ };
2944
+
2945
+ ko.exportSymbol('templateSources', ko.templateSources);
2946
+ ko.exportSymbol('templateSources.domElement', ko.templateSources.domElement);
2947
+ ko.exportSymbol('templateSources.anonymousTemplate', ko.templateSources.anonymousTemplate);
2948
+ })();
2949
+ (function () {
2950
+ var _templateEngine;
2951
+ ko.setTemplateEngine = function (templateEngine) {
2952
+ if ((templateEngine != undefined) && !(templateEngine instanceof ko.templateEngine))
2953
+ throw new Error("templateEngine must inherit from ko.templateEngine");
2954
+ _templateEngine = templateEngine;
2955
+ }
2956
+
2957
+ function invokeForEachNodeOrCommentInContinuousRange(firstNode, lastNode, action) {
2958
+ var node, nextInQueue = firstNode, firstOutOfRangeNode = ko.virtualElements.nextSibling(lastNode);
2959
+ while (nextInQueue && ((node = nextInQueue) !== firstOutOfRangeNode)) {
2960
+ nextInQueue = ko.virtualElements.nextSibling(node);
2961
+ if (node.nodeType === 1 || node.nodeType === 8)
2962
+ action(node);
2963
+ }
2964
+ }
2965
+
2966
+ function activateBindingsOnContinuousNodeArray(continuousNodeArray, bindingContext) {
2967
+ // To be used on any nodes that have been rendered by a template and have been inserted into some parent element
2968
+ // Walks through continuousNodeArray (which *must* be continuous, i.e., an uninterrupted sequence of sibling nodes, because
2969
+ // the algorithm for walking them relies on this), and for each top-level item in the virtual-element sense,
2970
+ // (1) Does a regular "applyBindings" to associate bindingContext with this node and to activate any non-memoized bindings
2971
+ // (2) Unmemoizes any memos in the DOM subtree (e.g., to activate bindings that had been memoized during template rewriting)
2972
+
2973
+ if (continuousNodeArray.length) {
2974
+ var firstNode = continuousNodeArray[0], lastNode = continuousNodeArray[continuousNodeArray.length - 1];
2975
+
2976
+ // Need to applyBindings *before* unmemoziation, because unmemoization might introduce extra nodes (that we don't want to re-bind)
2977
+ // whereas a regular applyBindings won't introduce new memoized nodes
2978
+ invokeForEachNodeOrCommentInContinuousRange(firstNode, lastNode, function(node) {
2979
+ ko.applyBindings(bindingContext, node);
2980
+ });
2981
+ invokeForEachNodeOrCommentInContinuousRange(firstNode, lastNode, function(node) {
2982
+ ko.memoization.unmemoizeDomNodeAndDescendants(node, [bindingContext]);
2983
+ });
2984
+ }
2985
+ }
2986
+
2987
+ function getFirstNodeFromPossibleArray(nodeOrNodeArray) {
2988
+ return nodeOrNodeArray.nodeType ? nodeOrNodeArray
2989
+ : nodeOrNodeArray.length > 0 ? nodeOrNodeArray[0]
2990
+ : null;
2991
+ }
2992
+
2993
+ function executeTemplate(targetNodeOrNodeArray, renderMode, template, bindingContext, options) {
2994
+ options = options || {};
2995
+ var firstTargetNode = targetNodeOrNodeArray && getFirstNodeFromPossibleArray(targetNodeOrNodeArray);
2996
+ var templateDocument = firstTargetNode && firstTargetNode.ownerDocument;
2997
+ var templateEngineToUse = (options['templateEngine'] || _templateEngine);
2998
+ ko.templateRewriting.ensureTemplateIsRewritten(template, templateEngineToUse, templateDocument);
2999
+ var renderedNodesArray = templateEngineToUse['renderTemplate'](template, bindingContext, options, templateDocument);
3000
+
3001
+ // Loosely check result is an array of DOM nodes
3002
+ if ((typeof renderedNodesArray.length != "number") || (renderedNodesArray.length > 0 && typeof renderedNodesArray[0].nodeType != "number"))
3003
+ throw new Error("Template engine must return an array of DOM nodes");
3004
+
3005
+ var haveAddedNodesToParent = false;
3006
+ switch (renderMode) {
3007
+ case "replaceChildren":
3008
+ ko.virtualElements.setDomNodeChildren(targetNodeOrNodeArray, renderedNodesArray);
3009
+ haveAddedNodesToParent = true;
3010
+ break;
3011
+ case "replaceNode":
3012
+ ko.utils.replaceDomNodes(targetNodeOrNodeArray, renderedNodesArray);
3013
+ haveAddedNodesToParent = true;
3014
+ break;
3015
+ case "ignoreTargetNode": break;
3016
+ default:
3017
+ throw new Error("Unknown renderMode: " + renderMode);
3018
+ }
3019
+
3020
+ if (haveAddedNodesToParent) {
3021
+ activateBindingsOnContinuousNodeArray(renderedNodesArray, bindingContext);
3022
+ if (options['afterRender'])
3023
+ ko.dependencyDetection.ignore(options['afterRender'], null, [renderedNodesArray, bindingContext['$data']]);
3024
+ }
3025
+
3026
+ return renderedNodesArray;
3027
+ }
3028
+
3029
+ ko.renderTemplate = function (template, dataOrBindingContext, options, targetNodeOrNodeArray, renderMode) {
3030
+ options = options || {};
3031
+ if ((options['templateEngine'] || _templateEngine) == undefined)
3032
+ throw new Error("Set a template engine before calling renderTemplate");
3033
+ renderMode = renderMode || "replaceChildren";
3034
+
3035
+ if (targetNodeOrNodeArray) {
3036
+ var firstTargetNode = getFirstNodeFromPossibleArray(targetNodeOrNodeArray);
3037
+
3038
+ var whenToDispose = function () { return (!firstTargetNode) || !ko.utils.domNodeIsAttachedToDocument(firstTargetNode); }; // Passive disposal (on next evaluation)
3039
+ var activelyDisposeWhenNodeIsRemoved = (firstTargetNode && renderMode == "replaceNode") ? firstTargetNode.parentNode : firstTargetNode;
3040
+
3041
+ return ko.dependentObservable( // So the DOM is automatically updated when any dependency changes
3042
+ function () {
3043
+ // Ensure we've got a proper binding context to work with
3044
+ var bindingContext = (dataOrBindingContext && (dataOrBindingContext instanceof ko.bindingContext))
3045
+ ? dataOrBindingContext
3046
+ : new ko.bindingContext(ko.utils.unwrapObservable(dataOrBindingContext));
3047
+
3048
+ // Support selecting template as a function of the data being rendered
3049
+ var templateName = typeof(template) == 'function' ? template(bindingContext['$data'], bindingContext) : template;
3050
+
3051
+ var renderedNodesArray = executeTemplate(targetNodeOrNodeArray, renderMode, templateName, bindingContext, options);
3052
+ if (renderMode == "replaceNode") {
3053
+ targetNodeOrNodeArray = renderedNodesArray;
3054
+ firstTargetNode = getFirstNodeFromPossibleArray(targetNodeOrNodeArray);
3055
+ }
3056
+ },
3057
+ null,
3058
+ { disposeWhen: whenToDispose, disposeWhenNodeIsRemoved: activelyDisposeWhenNodeIsRemoved }
3059
+ );
3060
+ } else {
3061
+ // 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
3062
+ return ko.memoization.memoize(function (domNode) {
3063
+ ko.renderTemplate(template, dataOrBindingContext, options, domNode, "replaceNode");
3064
+ });
3065
+ }
3066
+ };
3067
+
3068
+ ko.renderTemplateForEach = function (template, arrayOrObservableArray, options, targetNode, parentBindingContext) {
3069
+ // Since setDomNodeChildrenFromArrayMapping always calls executeTemplateForArrayItem and then
3070
+ // activateBindingsCallback for added items, we can store the binding context in the former to use in the latter.
3071
+ var arrayItemContext;
3072
+
3073
+ // This will be called by setDomNodeChildrenFromArrayMapping to get the nodes to add to targetNode
3074
+ var executeTemplateForArrayItem = function (arrayValue, index) {
3075
+ // Support selecting template as a function of the data being rendered
3076
+ arrayItemContext = parentBindingContext['createChildContext'](ko.utils.unwrapObservable(arrayValue), options['as']);
3077
+ arrayItemContext['$index'] = index;
3078
+ var templateName = typeof(template) == 'function' ? template(arrayValue, arrayItemContext) : template;
3079
+ return executeTemplate(null, "ignoreTargetNode", templateName, arrayItemContext, options);
3080
+ }
3081
+
3082
+ // This will be called whenever setDomNodeChildrenFromArrayMapping has added nodes to targetNode
3083
+ var activateBindingsCallback = function(arrayValue, addedNodesArray, index) {
3084
+ activateBindingsOnContinuousNodeArray(addedNodesArray, arrayItemContext);
3085
+ if (options['afterRender'])
3086
+ options['afterRender'](addedNodesArray, arrayValue);
3087
+ };
3088
+
3089
+ return ko.dependentObservable(function () {
3090
+ var unwrappedArray = ko.utils.unwrapObservable(arrayOrObservableArray) || [];
3091
+ if (typeof unwrappedArray.length == "undefined") // Coerce single value into array
3092
+ unwrappedArray = [unwrappedArray];
3093
+
3094
+ // Filter out any entries marked as destroyed
3095
+ var filteredArray = ko.utils.arrayFilter(unwrappedArray, function(item) {
3096
+ return options['includeDestroyed'] || item === undefined || item === null || !ko.utils.unwrapObservable(item['_destroy']);
3097
+ });
3098
+
3099
+ // Call setDomNodeChildrenFromArrayMapping, ignoring any observables unwrapped within (most likely from a callback function).
3100
+ // If the array items are observables, though, they will be unwrapped in executeTemplateForArrayItem and managed within setDomNodeChildrenFromArrayMapping.
3101
+ ko.dependencyDetection.ignore(ko.utils.setDomNodeChildrenFromArrayMapping, null, [targetNode, filteredArray, executeTemplateForArrayItem, options, activateBindingsCallback]);
3102
+
3103
+ }, null, { disposeWhenNodeIsRemoved: targetNode });
3104
+ };
3105
+
3106
+ var templateComputedDomDataKey = '__ko__templateComputedDomDataKey__';
3107
+ function disposeOldComputedAndStoreNewOne(element, newComputed) {
3108
+ var oldComputed = ko.utils.domData.get(element, templateComputedDomDataKey);
3109
+ if (oldComputed && (typeof(oldComputed.dispose) == 'function'))
3110
+ oldComputed.dispose();
3111
+ ko.utils.domData.set(element, templateComputedDomDataKey, (newComputed && newComputed.isActive()) ? newComputed : undefined);
3112
+ }
3113
+
3114
+ ko.bindingHandlers['template'] = {
3115
+ 'init': function(element, valueAccessor) {
3116
+ // Support anonymous templates
3117
+ var bindingValue = ko.utils.unwrapObservable(valueAccessor());
3118
+ if ((typeof bindingValue != "string") && (!bindingValue['name']) && (element.nodeType == 1 || element.nodeType == 8)) {
3119
+ // It's an anonymous template - store the element contents, then clear the element
3120
+ var templateNodes = element.nodeType == 1 ? element.childNodes : ko.virtualElements.childNodes(element),
3121
+ container = ko.utils.moveCleanedNodesToContainerElement(templateNodes); // This also removes the nodes from their current parent
3122
+ new ko.templateSources.anonymousTemplate(element)['nodes'](container);
3123
+ }
3124
+ return { 'controlsDescendantBindings': true };
3125
+ },
3126
+ 'update': function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
3127
+ var templateName = ko.utils.unwrapObservable(valueAccessor()),
3128
+ options = {},
3129
+ shouldDisplay = true,
3130
+ dataValue,
3131
+ templateComputed = null;
3132
+
3133
+ if (typeof templateName != "string") {
3134
+ options = templateName;
3135
+ templateName = options['name'];
3136
+
3137
+ // Support "if"/"ifnot" conditions
3138
+ if ('if' in options)
3139
+ shouldDisplay = ko.utils.unwrapObservable(options['if']);
3140
+ if (shouldDisplay && 'ifnot' in options)
3141
+ shouldDisplay = !ko.utils.unwrapObservable(options['ifnot']);
3142
+
3143
+ dataValue = ko.utils.unwrapObservable(options['data']);
3144
+ }
3145
+
3146
+ if ('foreach' in options) {
3147
+ // Render once for each data point (treating data set as empty if shouldDisplay==false)
3148
+ var dataArray = (shouldDisplay && options['foreach']) || [];
3149
+ templateComputed = ko.renderTemplateForEach(templateName || element, dataArray, options, element, bindingContext);
3150
+ } else if (!shouldDisplay) {
3151
+ ko.virtualElements.emptyNode(element);
3152
+ } else {
3153
+ // Render once for this single data point (or use the viewModel if no data was provided)
3154
+ var innerBindingContext = ('data' in options) ?
3155
+ bindingContext['createChildContext'](dataValue, options['as']) : // Given an explitit 'data' value, we create a child binding context for it
3156
+ bindingContext; // Given no explicit 'data' value, we retain the same binding context
3157
+ templateComputed = ko.renderTemplate(templateName || element, innerBindingContext, options, element);
3158
+ }
3159
+
3160
+ // It only makes sense to have a single template computed per element (otherwise which one should have its output displayed?)
3161
+ disposeOldComputedAndStoreNewOne(element, templateComputed);
3162
+ }
3163
+ };
3164
+
3165
+ // Anonymous templates can't be rewritten. Give a nice error message if you try to do it.
3166
+ ko.expressionRewriting.bindingRewriteValidators['template'] = function(bindingValue) {
3167
+ var parsedBindingValue = ko.expressionRewriting.parseObjectLiteral(bindingValue);
3168
+
3169
+ if ((parsedBindingValue.length == 1) && parsedBindingValue[0]['unknown'])
3170
+ return null; // It looks like a string literal, not an object literal, so treat it as a named template (which is allowed for rewriting)
3171
+
3172
+ if (ko.expressionRewriting.keyValueArrayContainsKey(parsedBindingValue, "name"))
3173
+ return null; // Named templates can be rewritten, so return "no error"
3174
+ return "This template engine does not support anonymous templates nested within its templates";
3175
+ };
3176
+
3177
+ ko.virtualElements.allowedBindings['template'] = true;
3178
+ })();
3179
+
3180
+ ko.exportSymbol('setTemplateEngine', ko.setTemplateEngine);
3181
+ ko.exportSymbol('renderTemplate', ko.renderTemplate);
3182
+
3183
+ ko.utils.compareArrays = (function () {
3184
+ var statusNotInOld = 'added', statusNotInNew = 'deleted';
3185
+
3186
+ // Simple calculation based on Levenshtein distance.
3187
+ function compareArrays(oldArray, newArray, dontLimitMoves) {
3188
+ oldArray = oldArray || [];
3189
+ newArray = newArray || [];
3190
+
3191
+ if (oldArray.length <= newArray.length)
3192
+ return compareSmallArrayToBigArray(oldArray, newArray, statusNotInOld, statusNotInNew, dontLimitMoves);
3193
+ else
3194
+ return compareSmallArrayToBigArray(newArray, oldArray, statusNotInNew, statusNotInOld, dontLimitMoves);
3195
+ }
3196
+
3197
+ function compareSmallArrayToBigArray(smlArray, bigArray, statusNotInSml, statusNotInBig, dontLimitMoves) {
3198
+ var myMin = Math.min,
3199
+ myMax = Math.max,
3200
+ editDistanceMatrix = [],
3201
+ smlIndex, smlIndexMax = smlArray.length,
3202
+ bigIndex, bigIndexMax = bigArray.length,
3203
+ compareRange = (bigIndexMax - smlIndexMax) || 1,
3204
+ maxDistance = smlIndexMax + bigIndexMax + 1,
3205
+ thisRow, lastRow,
3206
+ bigIndexMaxForRow, bigIndexMinForRow;
3207
+
3208
+ for (smlIndex = 0; smlIndex <= smlIndexMax; smlIndex++) {
3209
+ lastRow = thisRow;
3210
+ editDistanceMatrix.push(thisRow = []);
3211
+ bigIndexMaxForRow = myMin(bigIndexMax, smlIndex + compareRange);
3212
+ bigIndexMinForRow = myMax(0, smlIndex - 1);
3213
+ for (bigIndex = bigIndexMinForRow; bigIndex <= bigIndexMaxForRow; bigIndex++) {
3214
+ if (!bigIndex)
3215
+ thisRow[bigIndex] = smlIndex + 1;
3216
+ else if (!smlIndex) // Top row - transform empty array into new array via additions
3217
+ thisRow[bigIndex] = bigIndex + 1;
3218
+ else if (smlArray[smlIndex - 1] === bigArray[bigIndex - 1])
3219
+ thisRow[bigIndex] = lastRow[bigIndex - 1]; // copy value (no edit)
3220
+ else {
3221
+ var northDistance = lastRow[bigIndex] || maxDistance; // not in big (deletion)
3222
+ var westDistance = thisRow[bigIndex - 1] || maxDistance; // not in small (addition)
3223
+ thisRow[bigIndex] = myMin(northDistance, westDistance) + 1;
3224
+ }
3225
+ }
3226
+ }
3227
+
3228
+ var editScript = [], meMinusOne, notInSml = [], notInBig = [];
3229
+ for (smlIndex = smlIndexMax, bigIndex = bigIndexMax; smlIndex || bigIndex;) {
3230
+ meMinusOne = editDistanceMatrix[smlIndex][bigIndex] - 1;
3231
+ if (bigIndex && meMinusOne === editDistanceMatrix[smlIndex][bigIndex-1]) {
3232
+ notInSml.push(editScript[editScript.length] = { // added
3233
+ 'status': statusNotInSml,
3234
+ 'value': bigArray[--bigIndex],
3235
+ 'index': bigIndex });
3236
+ } else if (smlIndex && meMinusOne === editDistanceMatrix[smlIndex - 1][bigIndex]) {
3237
+ notInBig.push(editScript[editScript.length] = { // deleted
3238
+ 'status': statusNotInBig,
3239
+ 'value': smlArray[--smlIndex],
3240
+ 'index': smlIndex });
3241
+ } else {
3242
+ editScript.push({
3243
+ 'status': "retained",
3244
+ 'value': bigArray[--bigIndex] });
3245
+ --smlIndex;
3246
+ }
3247
+ }
3248
+
3249
+ if (notInSml.length && notInBig.length) {
3250
+ // Set a limit on the number of consecutive non-matching comparisons; having it a multiple of
3251
+ // smlIndexMax keeps the time complexity of this algorithm linear.
3252
+ var limitFailedCompares = smlIndexMax * 10, failedCompares,
3253
+ a, d, notInSmlItem, notInBigItem;
3254
+ // Go through the items that have been added and deleted and try to find matches between them.
3255
+ for (failedCompares = a = 0; (dontLimitMoves || failedCompares < limitFailedCompares) && (notInSmlItem = notInSml[a]); a++) {
3256
+ for (d = 0; notInBigItem = notInBig[d]; d++) {
3257
+ if (notInSmlItem['value'] === notInBigItem['value']) {
3258
+ notInSmlItem['moved'] = notInBigItem['index'];
3259
+ notInBigItem['moved'] = notInSmlItem['index'];
3260
+ notInBig.splice(d,1); // This item is marked as moved; so remove it from notInBig list
3261
+ failedCompares = d = 0; // Reset failed compares count because we're checking for consecutive failures
3262
+ break;
3263
+ }
3264
+ }
3265
+ failedCompares += d;
3266
+ }
3267
+ }
3268
+ return editScript.reverse();
3269
+ }
3270
+
3271
+ return compareArrays;
3272
+ })();
3273
+
3274
+ ko.exportSymbol('utils.compareArrays', ko.utils.compareArrays);
3275
+
3276
+ (function () {
3277
+ // Objective:
3278
+ // * Given an input array, a container DOM node, and a function from array elements to arrays of DOM nodes,
3279
+ // map the array elements to arrays of DOM nodes, concatenate together all these arrays, and use them to populate the container DOM node
3280
+ // * Next time we're given the same combination of things (with the array possibly having mutated), update the container DOM node
3281
+ // 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
3282
+ // previously mapped - retain those nodes, and just insert/delete other ones
3283
+
3284
+ // "callbackAfterAddingNodes" will be invoked after any "mapping"-generated nodes are inserted into the container node
3285
+ // You can use this, for example, to activate bindings on those nodes.
3286
+
3287
+ function fixUpNodesToBeMovedOrRemoved(contiguousNodeArray) {
3288
+ // Before moving, deleting, or replacing a set of nodes that were previously outputted by the "map" function, we have to reconcile
3289
+ // them against what is in the DOM right now. It may be that some of the nodes have already been removed from the document,
3290
+ // or that new nodes might have been inserted in the middle, for example by a binding. Also, there may previously have been
3291
+ // leading comment nodes (created by rewritten string-based templates) that have since been removed during binding.
3292
+ // So, this function translates the old "map" output array into its best guess of what set of current DOM nodes should be removed.
3293
+ //
3294
+ // Rules:
3295
+ // [A] Any leading nodes that aren't in the document any more should be ignored
3296
+ // These most likely correspond to memoization nodes that were already removed during binding
3297
+ // See https://github.com/SteveSanderson/knockout/pull/440
3298
+ // [B] We want to output a contiguous series of nodes that are still in the document. So, ignore any nodes that
3299
+ // have already been removed, and include any nodes that have been inserted among the previous collection
3300
+
3301
+ // Rule [A]
3302
+ while (contiguousNodeArray.length && !ko.utils.domNodeIsAttachedToDocument(contiguousNodeArray[0]))
3303
+ contiguousNodeArray.splice(0, 1);
3304
+
3305
+ // Rule [B]
3306
+ if (contiguousNodeArray.length > 1) {
3307
+ // Build up the actual new contiguous node set
3308
+ var current = contiguousNodeArray[0], last = contiguousNodeArray[contiguousNodeArray.length - 1], newContiguousSet = [current];
3309
+ while (current !== last) {
3310
+ current = current.nextSibling;
3311
+ if (!current) // Won't happen, except if the developer has manually removed some DOM elements (then we're in an undefined scenario)
3312
+ return;
3313
+ newContiguousSet.push(current);
3314
+ }
3315
+
3316
+ // ... then mutate the input array to match this.
3317
+ // (The following line replaces the contents of contiguousNodeArray with newContiguousSet)
3318
+ Array.prototype.splice.apply(contiguousNodeArray, [0, contiguousNodeArray.length].concat(newContiguousSet));
3319
+ }
3320
+ return contiguousNodeArray;
3321
+ }
3322
+
3323
+ function mapNodeAndRefreshWhenChanged(containerNode, mapping, valueToMap, callbackAfterAddingNodes, index) {
3324
+ // Map this array value inside a dependentObservable so we re-map when any dependency changes
3325
+ var mappedNodes = [];
3326
+ var dependentObservable = ko.dependentObservable(function() {
3327
+ var newMappedNodes = mapping(valueToMap, index) || [];
3328
+
3329
+ // On subsequent evaluations, just replace the previously-inserted DOM nodes
3330
+ if (mappedNodes.length > 0) {
3331
+ ko.utils.replaceDomNodes(fixUpNodesToBeMovedOrRemoved(mappedNodes), newMappedNodes);
3332
+ if (callbackAfterAddingNodes)
3333
+ ko.dependencyDetection.ignore(callbackAfterAddingNodes, null, [valueToMap, newMappedNodes, index]);
3334
+ }
3335
+
3336
+ // Replace the contents of the mappedNodes array, thereby updating the record
3337
+ // of which nodes would be deleted if valueToMap was itself later removed
3338
+ mappedNodes.splice(0, mappedNodes.length);
3339
+ ko.utils.arrayPushAll(mappedNodes, newMappedNodes);
3340
+ }, null, { disposeWhenNodeIsRemoved: containerNode, disposeWhen: function() { return (mappedNodes.length == 0) || !ko.utils.domNodeIsAttachedToDocument(mappedNodes[0]) } });
3341
+ return { mappedNodes : mappedNodes, dependentObservable : (dependentObservable.isActive() ? dependentObservable : undefined) };
3342
+ }
3343
+
3344
+ var lastMappingResultDomDataKey = "setDomNodeChildrenFromArrayMapping_lastMappingResult";
3345
+
3346
+ ko.utils.setDomNodeChildrenFromArrayMapping = function (domNode, array, mapping, options, callbackAfterAddingNodes) {
3347
+ // Compare the provided array against the previous one
3348
+ array = array || [];
3349
+ options = options || {};
3350
+ var isFirstExecution = ko.utils.domData.get(domNode, lastMappingResultDomDataKey) === undefined;
3351
+ var lastMappingResult = ko.utils.domData.get(domNode, lastMappingResultDomDataKey) || [];
3352
+ var lastArray = ko.utils.arrayMap(lastMappingResult, function (x) { return x.arrayEntry; });
3353
+ var editScript = ko.utils.compareArrays(lastArray, array);
3354
+
3355
+ // Build the new mapping result
3356
+ var newMappingResult = [];
3357
+ var lastMappingResultIndex = 0;
3358
+ var newMappingResultIndex = 0;
3359
+
3360
+ var nodesToDelete = [];
3361
+ var itemsToProcess = [];
3362
+ var itemsForBeforeRemoveCallbacks = [];
3363
+ var itemsForMoveCallbacks = [];
3364
+ var itemsForAfterAddCallbacks = [];
3365
+ var mapData;
3366
+
3367
+ function itemMovedOrRetained(editScriptIndex, oldPosition) {
3368
+ mapData = lastMappingResult[oldPosition];
3369
+ if (newMappingResultIndex !== oldPosition)
3370
+ itemsForMoveCallbacks[editScriptIndex] = mapData;
3371
+ // Since updating the index might change the nodes, do so before calling fixUpNodesToBeMovedOrRemoved
3372
+ mapData.indexObservable(newMappingResultIndex++);
3373
+ fixUpNodesToBeMovedOrRemoved(mapData.mappedNodes);
3374
+ newMappingResult.push(mapData);
3375
+ itemsToProcess.push(mapData);
3376
+ }
3377
+
3378
+ function callCallback(callback, items) {
3379
+ if (callback) {
3380
+ for (var i = 0, n = items.length; i < n; i++) {
3381
+ if (items[i]) {
3382
+ ko.utils.arrayForEach(items[i].mappedNodes, function(node) {
3383
+ callback(node, i, items[i].arrayEntry);
3384
+ });
3385
+ }
3386
+ }
3387
+ }
3388
+ }
3389
+
3390
+ for (var i = 0, editScriptItem, movedIndex; editScriptItem = editScript[i]; i++) {
3391
+ movedIndex = editScriptItem['moved'];
3392
+ switch (editScriptItem['status']) {
3393
+ case "deleted":
3394
+ if (movedIndex === undefined) {
3395
+ mapData = lastMappingResult[lastMappingResultIndex];
3396
+
3397
+ // Stop tracking changes to the mapping for these nodes
3398
+ if (mapData.dependentObservable)
3399
+ mapData.dependentObservable.dispose();
3400
+
3401
+ // Queue these nodes for later removal
3402
+ nodesToDelete.push.apply(nodesToDelete, fixUpNodesToBeMovedOrRemoved(mapData.mappedNodes));
3403
+ if (options['beforeRemove']) {
3404
+ itemsForBeforeRemoveCallbacks[i] = mapData;
3405
+ itemsToProcess.push(mapData);
3406
+ }
3407
+ }
3408
+ lastMappingResultIndex++;
3409
+ break;
3410
+
3411
+ case "retained":
3412
+ itemMovedOrRetained(i, lastMappingResultIndex++);
3413
+ break;
3414
+
3415
+ case "added":
3416
+ if (movedIndex !== undefined) {
3417
+ itemMovedOrRetained(i, movedIndex);
3418
+ } else {
3419
+ mapData = { arrayEntry: editScriptItem['value'], indexObservable: ko.observable(newMappingResultIndex++) };
3420
+ newMappingResult.push(mapData);
3421
+ itemsToProcess.push(mapData);
3422
+ if (!isFirstExecution)
3423
+ itemsForAfterAddCallbacks[i] = mapData;
3424
+ }
3425
+ break;
3426
+ }
3427
+ }
3428
+
3429
+ // Call beforeMove first before any changes have been made to the DOM
3430
+ callCallback(options['beforeMove'], itemsForMoveCallbacks);
3431
+
3432
+ // Next remove nodes for deleted items (or just clean if there's a beforeRemove callback)
3433
+ ko.utils.arrayForEach(nodesToDelete, options['beforeRemove'] ? ko.cleanNode : ko.removeNode);
3434
+
3435
+ // Next add/reorder the remaining items (will include deleted items if there's a beforeRemove callback)
3436
+ for (var i = 0, nextNode = ko.virtualElements.firstChild(domNode), lastNode, node; mapData = itemsToProcess[i]; i++) {
3437
+ // Get nodes for newly added items
3438
+ if (!mapData.mappedNodes)
3439
+ ko.utils.extend(mapData, mapNodeAndRefreshWhenChanged(domNode, mapping, mapData.arrayEntry, callbackAfterAddingNodes, mapData.indexObservable));
3440
+
3441
+ // Put nodes in the right place if they aren't there already
3442
+ for (var j = 0; node = mapData.mappedNodes[j]; nextNode = node.nextSibling, lastNode = node, j++) {
3443
+ if (node !== nextNode)
3444
+ ko.virtualElements.insertAfter(domNode, node, lastNode);
3445
+ }
3446
+
3447
+ // Run the callbacks for newly added nodes (for example, to apply bindings, etc.)
3448
+ if (!mapData.initialized && callbackAfterAddingNodes) {
3449
+ callbackAfterAddingNodes(mapData.arrayEntry, mapData.mappedNodes, mapData.indexObservable);
3450
+ mapData.initialized = true;
3451
+ }
3452
+ }
3453
+
3454
+ // If there's a beforeRemove callback, call it after reordering.
3455
+ // Note that we assume that the beforeRemove callback will usually be used to remove the nodes using
3456
+ // some sort of animation, which is why we first reorder the nodes that will be removed. If the
3457
+ // callback instead removes the nodes right away, it would be more efficient to skip reordering them.
3458
+ // Perhaps we'll make that change in the future if this scenario becomes more common.
3459
+ callCallback(options['beforeRemove'], itemsForBeforeRemoveCallbacks);
3460
+
3461
+ // Finally call afterMove and afterAdd callbacks
3462
+ callCallback(options['afterMove'], itemsForMoveCallbacks);
3463
+ callCallback(options['afterAdd'], itemsForAfterAddCallbacks);
3464
+
3465
+ // Store a copy of the array items we just considered so we can difference it next time
3466
+ ko.utils.domData.set(domNode, lastMappingResultDomDataKey, newMappingResult);
3467
+ }
3468
+ })();
3469
+
3470
+ ko.exportSymbol('utils.setDomNodeChildrenFromArrayMapping', ko.utils.setDomNodeChildrenFromArrayMapping);
3471
+ ko.nativeTemplateEngine = function () {
3472
+ this['allowTemplateRewriting'] = false;
3473
+ }
3474
+
3475
+ ko.nativeTemplateEngine.prototype = new ko.templateEngine();
3476
+ ko.nativeTemplateEngine.prototype['renderTemplateSource'] = function (templateSource, bindingContext, options) {
3477
+ var useNodesIfAvailable = !(ko.utils.ieVersion < 9), // IE<9 cloneNode doesn't work properly
3478
+ templateNodesFunc = useNodesIfAvailable ? templateSource['nodes'] : null,
3479
+ templateNodes = templateNodesFunc ? templateSource['nodes']() : null;
3480
+
3481
+ if (templateNodes) {
3482
+ return ko.utils.makeArray(templateNodes.cloneNode(true).childNodes);
3483
+ } else {
3484
+ var templateText = templateSource['text']();
3485
+ return ko.utils.parseHtmlFragment(templateText);
3486
+ }
3487
+ };
3488
+
3489
+ ko.nativeTemplateEngine.instance = new ko.nativeTemplateEngine();
3490
+ ko.setTemplateEngine(ko.nativeTemplateEngine.instance);
3491
+
3492
+ ko.exportSymbol('nativeTemplateEngine', ko.nativeTemplateEngine);
3493
+ (function() {
3494
+ ko.jqueryTmplTemplateEngine = function () {
3495
+ // Detect which version of jquery-tmpl you're using. Unfortunately jquery-tmpl
3496
+ // doesn't expose a version number, so we have to infer it.
3497
+ // Note that as of Knockout 1.3, we only support jQuery.tmpl 1.0.0pre and later,
3498
+ // which KO internally refers to as version "2", so older versions are no longer detected.
3499
+ var jQueryTmplVersion = this.jQueryTmplVersion = (function() {
3500
+ if ((typeof(jQuery) == "undefined") || !(jQuery['tmpl']))
3501
+ return 0;
3502
+ // Since it exposes no official version number, we use our own numbering system. To be updated as jquery-tmpl evolves.
3503
+ try {
3504
+ if (jQuery['tmpl']['tag']['tmpl']['open'].toString().indexOf('__') >= 0) {
3505
+ // Since 1.0.0pre, custom tags should append markup to an array called "__"
3506
+ return 2; // Final version of jquery.tmpl
3507
+ }
3508
+ } catch(ex) { /* Apparently not the version we were looking for */ }
3509
+
3510
+ return 1; // Any older version that we don't support
3511
+ })();
3512
+
3513
+ function ensureHasReferencedJQueryTemplates() {
3514
+ if (jQueryTmplVersion < 2)
3515
+ throw new Error("Your version of jQuery.tmpl is too old. Please upgrade to jQuery.tmpl 1.0.0pre or later.");
3516
+ }
3517
+
3518
+ function executeTemplate(compiledTemplate, data, jQueryTemplateOptions) {
3519
+ return jQuery['tmpl'](compiledTemplate, data, jQueryTemplateOptions);
3520
+ }
3521
+
3522
+ this['renderTemplateSource'] = function(templateSource, bindingContext, options) {
3523
+ options = options || {};
3524
+ ensureHasReferencedJQueryTemplates();
3525
+
3526
+ // Ensure we have stored a precompiled version of this template (don't want to reparse on every render)
3527
+ var precompiled = templateSource['data']('precompiled');
3528
+ if (!precompiled) {
3529
+ var templateText = templateSource['text']() || "";
3530
+ // Wrap in "with($whatever.koBindingContext) { ... }"
3531
+ templateText = "{{ko_with $item.koBindingContext}}" + templateText + "{{/ko_with}}";
3532
+
3533
+ precompiled = jQuery['template'](null, templateText);
3534
+ templateSource['data']('precompiled', precompiled);
3535
+ }
3536
+
3537
+ var data = [bindingContext['$data']]; // Prewrap the data in an array to stop jquery.tmpl from trying to unwrap any arrays
3538
+ var jQueryTemplateOptions = jQuery['extend']({ 'koBindingContext': bindingContext }, options['templateOptions']);
3539
+
3540
+ var resultNodes = executeTemplate(precompiled, data, jQueryTemplateOptions);
3541
+ resultNodes['appendTo'](document.createElement("div")); // Using "appendTo" forces jQuery/jQuery.tmpl to perform necessary cleanup work
3542
+
3543
+ jQuery['fragments'] = {}; // Clear jQuery's fragment cache to avoid a memory leak after a large number of template renders
3544
+ return resultNodes;
3545
+ };
3546
+
3547
+ this['createJavaScriptEvaluatorBlock'] = function(script) {
3548
+ return "{{ko_code ((function() { return " + script + " })()) }}";
3549
+ };
3550
+
3551
+ this['addTemplate'] = function(templateName, templateMarkup) {
3552
+ document.write("<script type='text/html' id='" + templateName + "'>" + templateMarkup + "</script>");
3553
+ };
3554
+
3555
+ if (jQueryTmplVersion > 0) {
3556
+ jQuery['tmpl']['tag']['ko_code'] = {
3557
+ open: "__.push($1 || '');"
3558
+ };
3559
+ jQuery['tmpl']['tag']['ko_with'] = {
3560
+ open: "with($1) {",
3561
+ close: "} "
3562
+ };
3563
+ }
3564
+ };
3565
+
3566
+ ko.jqueryTmplTemplateEngine.prototype = new ko.templateEngine();
3567
+
3568
+ // Use this one by default *only if jquery.tmpl is referenced*
3569
+ var jqueryTmplTemplateEngineInstance = new ko.jqueryTmplTemplateEngine();
3570
+ if (jqueryTmplTemplateEngineInstance.jQueryTmplVersion > 0)
3571
+ ko.setTemplateEngine(jqueryTmplTemplateEngineInstance);
3572
+
3573
+ ko.exportSymbol('jqueryTmplTemplateEngine', ko.jqueryTmplTemplateEngine);
3574
+ })();
3575
+ });
3576
+ })(window,document,navigator,window["jQuery"]);
3577
+ })();