Commit 6551cbbb authored by abhinav's avatar abhinav Committed by Pascal Hartig

Added Durandal framework

parent 94dc4b24
{
"name": "todomvc-durandal",
"version": "0.0.0",
"dependencies": {
"durandal": "~1.2.0",
"sammy": "~0.7.4",
"jquery": "~1.9.1",
"knockout": "~2.2.1",
"todomvc-common": "~0.1.4",
"requirejs": "~2.1.6"
}
}
/*
RequireJS 2.1.2 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved.
Available via the MIT or new BSD license.
see: http://github.com/jrburke/requirejs for details
*/
var requirejs,require,define;
(function(Y){function H(b){return"[object Function]"===L.call(b)}function I(b){return"[object Array]"===L.call(b)}function x(b,c){if(b){var d;for(d=0;d<b.length&&(!b[d]||!c(b[d],d,b));d+=1);}}function M(b,c){if(b){var d;for(d=b.length-1;-1<d&&(!b[d]||!c(b[d],d,b));d-=1);}}function r(b,c){return da.call(b,c)}function i(b,c){return r(b,c)&&b[c]}function E(b,c){for(var d in b)if(r(b,d)&&c(b[d],d))break}function Q(b,c,d,i){c&&E(c,function(c,h){if(d||!r(b,h))i&&"string"!==typeof c?(b[h]||(b[h]={}),Q(b[h],
c,d,i)):b[h]=c});return b}function t(b,c){return function(){return c.apply(b,arguments)}}function Z(b){if(!b)return b;var c=Y;x(b.split("."),function(b){c=c[b]});return c}function J(b,c,d,i){c=Error(c+"\nhttp://requirejs.org/docs/errors.html#"+b);c.requireType=b;c.requireModules=i;d&&(c.originalError=d);return c}function ea(b){function c(a,g,v){var e,n,b,c,d,j,f,h=g&&g.split("/");e=h;var l=m.map,k=l&&l["*"];if(a&&"."===a.charAt(0))if(g){e=i(m.pkgs,g)?h=[g]:h.slice(0,h.length-1);g=a=e.concat(a.split("/"));
for(e=0;g[e];e+=1)if(n=g[e],"."===n)g.splice(e,1),e-=1;else if(".."===n)if(1===e&&(".."===g[2]||".."===g[0]))break;else 0<e&&(g.splice(e-1,2),e-=2);e=i(m.pkgs,g=a[0]);a=a.join("/");e&&a===g+"/"+e.main&&(a=g)}else 0===a.indexOf("./")&&(a=a.substring(2));if(v&&(h||k)&&l){g=a.split("/");for(e=g.length;0<e;e-=1){b=g.slice(0,e).join("/");if(h)for(n=h.length;0<n;n-=1)if(v=i(l,h.slice(0,n).join("/")))if(v=i(v,b)){c=v;d=e;break}if(c)break;!j&&(k&&i(k,b))&&(j=i(k,b),f=e)}!c&&j&&(c=j,d=f);c&&(g.splice(0,d,
c),a=g.join("/"))}return a}function d(a){z&&x(document.getElementsByTagName("script"),function(g){if(g.getAttribute("data-requiremodule")===a&&g.getAttribute("data-requirecontext")===j.contextName)return g.parentNode.removeChild(g),!0})}function y(a){var g=i(m.paths,a);if(g&&I(g)&&1<g.length)return d(a),g.shift(),j.require.undef(a),j.require([a]),!0}function f(a){var g,b=a?a.indexOf("!"):-1;-1<b&&(g=a.substring(0,b),a=a.substring(b+1,a.length));return[g,a]}function h(a,g,b,e){var n,u,d=null,h=g?g.name:
null,l=a,m=!0,k="";a||(m=!1,a="_@r"+(L+=1));a=f(a);d=a[0];a=a[1];d&&(d=c(d,h,e),u=i(p,d));a&&(d?k=u&&u.normalize?u.normalize(a,function(a){return c(a,h,e)}):c(a,h,e):(k=c(a,h,e),a=f(k),d=a[0],k=a[1],b=!0,n=j.nameToUrl(k)));b=d&&!u&&!b?"_unnormalized"+(M+=1):"";return{prefix:d,name:k,parentMap:g,unnormalized:!!b,url:n,originalName:l,isDefine:m,id:(d?d+"!"+k:k)+b}}function q(a){var g=a.id,b=i(k,g);b||(b=k[g]=new j.Module(a));return b}function s(a,g,b){var e=a.id,n=i(k,e);if(r(p,e)&&(!n||n.defineEmitComplete))"defined"===
g&&b(p[e]);else q(a).on(g,b)}function C(a,g){var b=a.requireModules,e=!1;if(g)g(a);else if(x(b,function(g){if(g=i(k,g))g.error=a,g.events.error&&(e=!0,g.emit("error",a))}),!e)l.onError(a)}function w(){R.length&&(fa.apply(F,[F.length-1,0].concat(R)),R=[])}function A(a,g,b){var e=a.map.id;a.error?a.emit("error",a.error):(g[e]=!0,x(a.depMaps,function(e,c){var d=e.id,h=i(k,d);h&&(!a.depMatched[c]&&!b[d])&&(i(g,d)?(a.defineDep(c,p[d]),a.check()):A(h,g,b))}),b[e]=!0)}function B(){var a,g,b,e,n=(b=1E3*m.waitSeconds)&&
j.startTime+b<(new Date).getTime(),c=[],h=[],f=!1,l=!0;if(!T){T=!0;E(k,function(b){a=b.map;g=a.id;if(b.enabled&&(a.isDefine||h.push(b),!b.error))if(!b.inited&&n)y(g)?f=e=!0:(c.push(g),d(g));else if(!b.inited&&(b.fetched&&a.isDefine)&&(f=!0,!a.prefix))return l=!1});if(n&&c.length)return b=J("timeout","Load timeout for modules: "+c,null,c),b.contextName=j.contextName,C(b);l&&x(h,function(a){A(a,{},{})});if((!n||e)&&f)if((z||$)&&!U)U=setTimeout(function(){U=0;B()},50);T=!1}}function D(a){r(p,a[0])||
q(h(a[0],null,!0)).init(a[1],a[2])}function G(a){var a=a.currentTarget||a.srcElement,b=j.onScriptLoad;a.detachEvent&&!V?a.detachEvent("onreadystatechange",b):a.removeEventListener("load",b,!1);b=j.onScriptError;(!a.detachEvent||V)&&a.removeEventListener("error",b,!1);return{node:a,id:a&&a.getAttribute("data-requiremodule")}}function K(){var a;for(w();F.length;){a=F.shift();if(null===a[0])return C(J("mismatch","Mismatched anonymous define() module: "+a[a.length-1]));D(a)}}var T,W,j,N,U,m={waitSeconds:7,
baseUrl:"./",paths:{},pkgs:{},shim:{},map:{},config:{}},k={},X={},F=[],p={},S={},L=1,M=1;N={require:function(a){return a.require?a.require:a.require=j.makeRequire(a.map)},exports:function(a){a.usingExports=!0;if(a.map.isDefine)return a.exports?a.exports:a.exports=p[a.map.id]={}},module:function(a){return a.module?a.module:a.module={id:a.map.id,uri:a.map.url,config:function(){return m.config&&i(m.config,a.map.id)||{}},exports:p[a.map.id]}}};W=function(a){this.events=i(X,a.id)||{};this.map=a;this.shim=
i(m.shim,a.id);this.depExports=[];this.depMaps=[];this.depMatched=[];this.pluginMaps={};this.depCount=0};W.prototype={init:function(a,b,c,e){e=e||{};if(!this.inited){this.factory=b;if(c)this.on("error",c);else this.events.error&&(c=t(this,function(a){this.emit("error",a)}));this.depMaps=a&&a.slice(0);this.errback=c;this.inited=!0;this.ignore=e.ignore;e.enabled||this.enabled?this.enable():this.check()}},defineDep:function(a,b){this.depMatched[a]||(this.depMatched[a]=!0,this.depCount-=1,this.depExports[a]=
b)},fetch:function(){if(!this.fetched){this.fetched=!0;j.startTime=(new Date).getTime();var a=this.map;if(this.shim)j.makeRequire(this.map,{enableBuildCallback:!0})(this.shim.deps||[],t(this,function(){return a.prefix?this.callPlugin():this.load()}));else return a.prefix?this.callPlugin():this.load()}},load:function(){var a=this.map.url;S[a]||(S[a]=!0,j.load(this.map.id,a))},check:function(){if(this.enabled&&!this.enabling){var a,b,c=this.map.id;b=this.depExports;var e=this.exports,n=this.factory;
if(this.inited)if(this.error)this.emit("error",this.error);else{if(!this.defining){this.defining=!0;if(1>this.depCount&&!this.defined){if(H(n)){if(this.events.error)try{e=j.execCb(c,n,b,e)}catch(d){a=d}else e=j.execCb(c,n,b,e);this.map.isDefine&&((b=this.module)&&void 0!==b.exports&&b.exports!==this.exports?e=b.exports:void 0===e&&this.usingExports&&(e=this.exports));if(a)return a.requireMap=this.map,a.requireModules=[this.map.id],a.requireType="define",C(this.error=a)}else e=n;this.exports=e;if(this.map.isDefine&&
!this.ignore&&(p[c]=e,l.onResourceLoad))l.onResourceLoad(j,this.map,this.depMaps);delete k[c];this.defined=!0}this.defining=!1;this.defined&&!this.defineEmitted&&(this.defineEmitted=!0,this.emit("defined",this.exports),this.defineEmitComplete=!0)}}else this.fetch()}},callPlugin:function(){var a=this.map,b=a.id,d=h(a.prefix);this.depMaps.push(d);s(d,"defined",t(this,function(e){var n,d;d=this.map.name;var v=this.map.parentMap?this.map.parentMap.name:null,f=j.makeRequire(a.parentMap,{enableBuildCallback:!0,
skipMap:!0});if(this.map.unnormalized){if(e.normalize&&(d=e.normalize(d,function(a){return c(a,v,!0)})||""),e=h(a.prefix+"!"+d,this.map.parentMap),s(e,"defined",t(this,function(a){this.init([],function(){return a},null,{enabled:!0,ignore:!0})})),d=i(k,e.id)){this.depMaps.push(e);if(this.events.error)d.on("error",t(this,function(a){this.emit("error",a)}));d.enable()}}else n=t(this,function(a){this.init([],function(){return a},null,{enabled:!0})}),n.error=t(this,function(a){this.inited=!0;this.error=
a;a.requireModules=[b];E(k,function(a){0===a.map.id.indexOf(b+"_unnormalized")&&delete k[a.map.id]});C(a)}),n.fromText=t(this,function(e,c){var d=a.name,u=h(d),v=O;c&&(e=c);v&&(O=!1);q(u);r(m.config,b)&&(m.config[d]=m.config[b]);try{l.exec(e)}catch(k){throw Error("fromText eval for "+d+" failed: "+k);}v&&(O=!0);this.depMaps.push(u);j.completeLoad(d);f([d],n)}),e.load(a.name,f,n,m)}));j.enable(d,this);this.pluginMaps[d.id]=d},enable:function(){this.enabling=this.enabled=!0;x(this.depMaps,t(this,function(a,
b){var c,e;if("string"===typeof a){a=h(a,this.map.isDefine?this.map:this.map.parentMap,!1,!this.skipMap);this.depMaps[b]=a;if(c=i(N,a.id)){this.depExports[b]=c(this);return}this.depCount+=1;s(a,"defined",t(this,function(a){this.defineDep(b,a);this.check()}));this.errback&&s(a,"error",this.errback)}c=a.id;e=k[c];!r(N,c)&&(e&&!e.enabled)&&j.enable(a,this)}));E(this.pluginMaps,t(this,function(a){var b=i(k,a.id);b&&!b.enabled&&j.enable(a,this)}));this.enabling=!1;this.check()},on:function(a,b){var c=
this.events[a];c||(c=this.events[a]=[]);c.push(b)},emit:function(a,b){x(this.events[a],function(a){a(b)});"error"===a&&delete this.events[a]}};j={config:m,contextName:b,registry:k,defined:p,urlFetched:S,defQueue:F,Module:W,makeModuleMap:h,nextTick:l.nextTick,configure:function(a){a.baseUrl&&"/"!==a.baseUrl.charAt(a.baseUrl.length-1)&&(a.baseUrl+="/");var b=m.pkgs,c=m.shim,e={paths:!0,config:!0,map:!0};E(a,function(a,b){e[b]?"map"===b?Q(m[b],a,!0,!0):Q(m[b],a,!0):m[b]=a});a.shim&&(E(a.shim,function(a,
b){I(a)&&(a={deps:a});if((a.exports||a.init)&&!a.exportsFn)a.exportsFn=j.makeShimExports(a);c[b]=a}),m.shim=c);a.packages&&(x(a.packages,function(a){a="string"===typeof a?{name:a}:a;b[a.name]={name:a.name,location:a.location||a.name,main:(a.main||"main").replace(ga,"").replace(aa,"")}}),m.pkgs=b);E(k,function(a,b){!a.inited&&!a.map.unnormalized&&(a.map=h(b))});if(a.deps||a.callback)j.require(a.deps||[],a.callback)},makeShimExports:function(a){return function(){var b;a.init&&(b=a.init.apply(Y,arguments));
return b||a.exports&&Z(a.exports)}},makeRequire:function(a,d){function f(e,c,u){var i,m;d.enableBuildCallback&&(c&&H(c))&&(c.__requireJsBuild=!0);if("string"===typeof e){if(H(c))return C(J("requireargs","Invalid require call"),u);if(a&&r(N,e))return N[e](k[a.id]);if(l.get)return l.get(j,e,a);i=h(e,a,!1,!0);i=i.id;return!r(p,i)?C(J("notloaded",'Module name "'+i+'" has not been loaded yet for context: '+b+(a?"":". Use require([])"))):p[i]}K();j.nextTick(function(){K();m=q(h(null,a));m.skipMap=d.skipMap;
m.init(e,c,u,{enabled:!0});B()});return f}d=d||{};Q(f,{isBrowser:z,toUrl:function(b){var d=b.lastIndexOf("."),g=null;-1!==d&&(g=b.substring(d,b.length),b=b.substring(0,d));return j.nameToUrl(c(b,a&&a.id,!0),g)},defined:function(b){return r(p,h(b,a,!1,!0).id)},specified:function(b){b=h(b,a,!1,!0).id;return r(p,b)||r(k,b)}});a||(f.undef=function(b){w();var c=h(b,a,!0),d=i(k,b);delete p[b];delete S[c.url];delete X[b];d&&(d.events.defined&&(X[b]=d.events),delete k[b])});return f},enable:function(a){i(k,
a.id)&&q(a).enable()},completeLoad:function(a){var b,c,d=i(m.shim,a)||{},h=d.exports;for(w();F.length;){c=F.shift();if(null===c[0]){c[0]=a;if(b)break;b=!0}else c[0]===a&&(b=!0);D(c)}c=i(k,a);if(!b&&!r(p,a)&&c&&!c.inited){if(m.enforceDefine&&(!h||!Z(h)))return y(a)?void 0:C(J("nodefine","No define call for "+a,null,[a]));D([a,d.deps||[],d.exportsFn])}B()},nameToUrl:function(a,b){var c,d,h,f,j,k;if(l.jsExtRegExp.test(a))f=a+(b||"");else{c=m.paths;d=m.pkgs;f=a.split("/");for(j=f.length;0<j;j-=1)if(k=
f.slice(0,j).join("/"),h=i(d,k),k=i(c,k)){I(k)&&(k=k[0]);f.splice(0,j,k);break}else if(h){c=a===h.name?h.location+"/"+h.main:h.location;f.splice(0,j,c);break}f=f.join("/");f+=b||(/\?/.test(f)?"":".js");f=("/"===f.charAt(0)||f.match(/^[\w\+\.\-]+:/)?"":m.baseUrl)+f}return m.urlArgs?f+((-1===f.indexOf("?")?"?":"&")+m.urlArgs):f},load:function(a,b){l.load(j,a,b)},execCb:function(a,b,c,d){return b.apply(d,c)},onScriptLoad:function(a){if("load"===a.type||ha.test((a.currentTarget||a.srcElement).readyState))P=
null,a=G(a),j.completeLoad(a.id)},onScriptError:function(a){var b=G(a);if(!y(b.id))return C(J("scripterror","Script error",a,[b.id]))}};j.require=j.makeRequire();return j}var l,w,A,D,s,G,P,K,ba,ca,ia=/(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg,ja=/[^.]\s*require\s*\(\s*["']([^'"\s]+)["']\s*\)/g,aa=/\.js$/,ga=/^\.\//;w=Object.prototype;var L=w.toString,da=w.hasOwnProperty,fa=Array.prototype.splice,z=!!("undefined"!==typeof window&&navigator&&document),$=!z&&"undefined"!==typeof importScripts,ha=z&&
"PLAYSTATION 3"===navigator.platform?/^complete$/:/^(complete|loaded)$/,V="undefined"!==typeof opera&&"[object Opera]"===opera.toString(),B={},q={},R=[],O=!1;if("undefined"===typeof define){if("undefined"!==typeof requirejs){if(H(requirejs))return;q=requirejs;requirejs=void 0}"undefined"!==typeof require&&!H(require)&&(q=require,require=void 0);l=requirejs=function(b,c,d,y){var f,h="_";!I(b)&&"string"!==typeof b&&(f=b,I(c)?(b=c,c=d,d=y):b=[]);f&&f.context&&(h=f.context);(y=i(B,h))||(y=B[h]=l.s.newContext(h));
f&&y.configure(f);return y.require(b,c,d)};l.config=function(b){return l(b)};l.nextTick="undefined"!==typeof setTimeout?function(b){setTimeout(b,4)}:function(b){b()};require||(require=l);l.version="2.1.2";l.jsExtRegExp=/^\/|:|\?|\.js$/;l.isBrowser=z;w=l.s={contexts:B,newContext:ea};l({});x(["toUrl","undef","defined","specified"],function(b){l[b]=function(){var c=B._;return c.require[b].apply(c,arguments)}});if(z&&(A=w.head=document.getElementsByTagName("head")[0],D=document.getElementsByTagName("base")[0]))A=
w.head=D.parentNode;l.onError=function(b){throw b;};l.load=function(b,c,d){var i=b&&b.config||{},f;if(z)return f=i.xhtml?document.createElementNS("http://www.w3.org/1999/xhtml","html:script"):document.createElement("script"),f.type=i.scriptType||"text/javascript",f.charset="utf-8",f.async=!0,f.setAttribute("data-requirecontext",b.contextName),f.setAttribute("data-requiremodule",c),f.attachEvent&&!(f.attachEvent.toString&&0>f.attachEvent.toString().indexOf("[native code"))&&!V?(O=!0,f.attachEvent("onreadystatechange",
b.onScriptLoad)):(f.addEventListener("load",b.onScriptLoad,!1),f.addEventListener("error",b.onScriptError,!1)),f.src=d,K=f,D?A.insertBefore(f,D):A.appendChild(f),K=null,f;$&&(importScripts(d),b.completeLoad(c))};z&&M(document.getElementsByTagName("script"),function(b){A||(A=b.parentNode);if(s=b.getAttribute("data-main"))return q.baseUrl||(G=s.split("/"),ba=G.pop(),ca=G.length?G.join("/")+"/":"./",q.baseUrl=ca,s=ba),s=s.replace(aa,""),q.deps=q.deps?q.deps.concat(s):[s],!0});define=function(b,c,d){var i,
f;"string"!==typeof b&&(d=c,c=b,b=null);I(c)||(d=c,c=[]);!c.length&&H(d)&&d.length&&(d.toString().replace(ia,"").replace(ja,function(b,d){c.push(d)}),c=(1===d.length?["require"]:["require","exports","module"]).concat(c));if(O){if(!(i=K))P&&"interactive"===P.readyState||M(document.getElementsByTagName("script"),function(b){if("interactive"===b.readyState)return P=b}),i=P;i&&(b||(b=i.getAttribute("data-requiremodule")),f=B[i.getAttribute("data-requirecontext")])}(f?f.defQueue:R).push([b,c,d])};define.amd=
{jQuery:!0};l.exec=function(b){return eval(b)};l(q)}})(this);
/**
* @license RequireJS text 2.0.3 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved.
* Available via the MIT or new BSD license.
* see: http://github.com/requirejs/text for details
*/
/*jslint regexp: true */
/*global require: false, XMLHttpRequest: false, ActiveXObject: false,
define: false, window: false, process: false, Packages: false,
java: false, location: false */
define(['module'], function (module) {
'use strict';
var text, fs,
progIds = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0'],
xmlRegExp = /^\s*<\?xml(\s)+version=[\'\"](\d)*.(\d)*[\'\"](\s)*\?>/im,
bodyRegExp = /<body[^>]*>\s*([\s\S]+)\s*<\/body>/im,
hasLocation = typeof location !== 'undefined' && location.href,
defaultProtocol = hasLocation && location.protocol && location.protocol.replace(/\:/, ''),
defaultHostName = hasLocation && location.hostname,
defaultPort = hasLocation && (location.port || undefined),
buildMap = [],
masterConfig = (module.config && module.config()) || {};
text = {
version: '2.0.3',
strip: function (content) {
//Strips <?xml ...?> declarations so that external SVG and XML
//documents can be added to a document without worry. Also, if the string
//is an HTML document, only the part inside the body tag is returned.
if (content) {
content = content.replace(xmlRegExp, "");
var matches = content.match(bodyRegExp);
if (matches) {
content = matches[1];
}
} else {
content = "";
}
return content;
},
jsEscape: function (content) {
return content.replace(/(['\\])/g, '\\$1')
.replace(/[\f]/g, "\\f")
.replace(/[\b]/g, "\\b")
.replace(/[\n]/g, "\\n")
.replace(/[\t]/g, "\\t")
.replace(/[\r]/g, "\\r")
.replace(/[\u2028]/g, "\\u2028")
.replace(/[\u2029]/g, "\\u2029");
},
createXhr: masterConfig.createXhr || function () {
//Would love to dump the ActiveX crap in here. Need IE 6 to die first.
var xhr, i, progId;
if (typeof XMLHttpRequest !== "undefined") {
return new XMLHttpRequest();
} else if (typeof ActiveXObject !== "undefined") {
for (i = 0; i < 3; i += 1) {
progId = progIds[i];
try {
xhr = new ActiveXObject(progId);
} catch (e) {}
if (xhr) {
progIds = [progId]; // so faster next time
break;
}
}
}
return xhr;
},
/**
* Parses a resource name into its component parts. Resource names
* look like: module/name.ext!strip, where the !strip part is
* optional.
* @param {String} name the resource name
* @returns {Object} with properties "moduleName", "ext" and "strip"
* where strip is a boolean.
*/
parseName: function (name) {
var strip = false, index = name.indexOf("."),
modName = name.substring(0, index),
ext = name.substring(index + 1, name.length);
index = ext.indexOf("!");
if (index !== -1) {
//Pull off the strip arg.
strip = ext.substring(index + 1, ext.length);
strip = strip === "strip";
ext = ext.substring(0, index);
}
return {
moduleName: modName,
ext: ext,
strip: strip
};
},
xdRegExp: /^((\w+)\:)?\/\/([^\/\\]+)/,
/**
* Is an URL on another domain. Only works for browser use, returns
* false in non-browser environments. Only used to know if an
* optimized .js version of a text resource should be loaded
* instead.
* @param {String} url
* @returns Boolean
*/
useXhr: function (url, protocol, hostname, port) {
var uProtocol, uHostName, uPort,
match = text.xdRegExp.exec(url);
if (!match) {
return true;
}
uProtocol = match[2];
uHostName = match[3];
uHostName = uHostName.split(':');
uPort = uHostName[1];
uHostName = uHostName[0];
return (!uProtocol || uProtocol === protocol) &&
(!uHostName || uHostName.toLowerCase() === hostname.toLowerCase()) &&
((!uPort && !uHostName) || uPort === port);
},
finishLoad: function (name, strip, content, onLoad) {
content = strip ? text.strip(content) : content;
if (masterConfig.isBuild) {
buildMap[name] = content;
}
onLoad(content);
},
load: function (name, req, onLoad, config) {
//Name has format: some.module.filext!strip
//The strip part is optional.
//if strip is present, then that means only get the string contents
//inside a body tag in an HTML string. For XML/SVG content it means
//removing the <?xml ...?> declarations so the content can be inserted
//into the current doc without problems.
// Do not bother with the work if a build and text will
// not be inlined.
if (config.isBuild && !config.inlineText) {
onLoad();
return;
}
masterConfig.isBuild = config.isBuild;
var parsed = text.parseName(name),
nonStripName = parsed.moduleName + '.' + parsed.ext,
url = req.toUrl(nonStripName),
useXhr = (masterConfig.useXhr) ||
text.useXhr;
//Load the text. Use XHR if possible and in a browser.
if (!hasLocation || useXhr(url, defaultProtocol, defaultHostName, defaultPort)) {
text.get(url, function (content) {
text.finishLoad(name, parsed.strip, content, onLoad);
}, function (err) {
if (onLoad.error) {
onLoad.error(err);
}
});
} else {
//Need to fetch the resource across domains. Assume
//the resource has been optimized into a JS module. Fetch
//by the module name + extension, but do not include the
//!strip part to avoid file system issues.
req([nonStripName], function (content) {
text.finishLoad(parsed.moduleName + '.' + parsed.ext,
parsed.strip, content, onLoad);
});
}
},
write: function (pluginName, moduleName, write, config) {
if (buildMap.hasOwnProperty(moduleName)) {
var content = text.jsEscape(buildMap[moduleName]);
write.asModule(pluginName + "!" + moduleName,
"define(function () { return '" +
content +
"';});\n");
}
},
writeFile: function (pluginName, moduleName, req, write, config) {
var parsed = text.parseName(moduleName),
nonStripName = parsed.moduleName + '.' + parsed.ext,
//Use a '.js' file name so that it indicates it is a
//script that can be loaded across domains.
fileName = req.toUrl(parsed.moduleName + '.' +
parsed.ext) + '.js';
//Leverage own load() method to load plugin value, but only
//write out values that do not have the strip argument,
//to avoid any potential issues with ! in file names.
text.load(nonStripName, req, function (value) {
//Use own write() method to construct full module value.
//But need to create shell that translates writeFile's
//write() to the right interface.
var textWrite = function (contents) {
return write(fileName, contents);
};
textWrite.asModule = function (moduleName, contents) {
return write.asModule(moduleName, fileName, contents);
};
text.write(pluginName, nonStripName, textWrite, config);
}, config);
}
};
if (masterConfig.env === 'node' || (!masterConfig.env &&
typeof process !== "undefined" &&
process.versions &&
!!process.versions.node)) {
//Using special require.nodeRequire, something added by r.js.
fs = require.nodeRequire('fs');
text.get = function (url, callback) {
var file = fs.readFileSync(url, 'utf8');
//Remove BOM (Byte Mark Order) from utf8 files if it is there.
if (file.indexOf('\uFEFF') === 0) {
file = file.substring(1);
}
callback(file);
};
} else if (masterConfig.env === 'xhr' || (!masterConfig.env &&
text.createXhr())) {
text.get = function (url, callback, errback) {
var xhr = text.createXhr();
xhr.open('GET', url, true);
//Allow overrides specified in config
if (masterConfig.onXhr) {
masterConfig.onXhr(xhr, url);
}
xhr.onreadystatechange = function (evt) {
var status, err;
//Do not explicitly handle errors, those should be
//visible via console output in the browser.
if (xhr.readyState === 4) {
status = xhr.status;
if (status > 399 && status < 600) {
//An http 4xx or 5xx error. Signal an error.
err = new Error(url + ' HTTP status: ' + status);
err.xhr = xhr;
errback(err);
} else {
callback(xhr.responseText);
}
}
};
xhr.send(null);
};
} else if (masterConfig.env === 'rhino' || (!masterConfig.env &&
typeof Packages !== 'undefined' && typeof java !== 'undefined')) {
//Why Java, why is this so awkward?
text.get = function (url, callback) {
var stringBuffer, line,
encoding = "utf-8",
file = new java.io.File(url),
lineSeparator = java.lang.System.getProperty("line.separator"),
input = new java.io.BufferedReader(new java.io.InputStreamReader(new java.io.FileInputStream(file), encoding)),
content = '';
try {
stringBuffer = new java.lang.StringBuffer();
line = input.readLine();
// Byte Order Mark (BOM) - The Unicode Standard, version 3.0, page 324
// http://www.unicode.org/faq/utf_bom.html
// Note that when we use utf-8, the BOM should appear as "EF BB BF", but it doesn't due to this bug in the JDK:
// http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4508058
if (line && line.length() && line.charAt(0) === 0xfeff) {
// Eat the BOM, since we've already found the encoding on this file,
// and we plan to concatenating this buffer with others; the BOM should
// only appear at the top of a file.
line = line.substring(1);
}
stringBuffer.append(line);
while ((line = input.readLine()) !== null) {
stringBuffer.append(lineSeparator);
stringBuffer.append(line);
}
//Make sure we return a JavaScript string and not a Java string.
content = String(stringBuffer.toString()); //String
} finally {
input.close();
}
callback(content);
};
}
return text;
});
define(['./system', './viewEngine', './composition', './widget', './modalDialog', './events'],
function(system, viewEngine, composition, widget, modalDialog, Events) {
var app = {
title: 'Application',
showModal: function(obj, activationData, context) {
return modalDialog.show(obj, activationData, context);
},
showMessage: function(message, title, options) {
return modalDialog.show('./messageBox', {
message: message,
title: title || this.title,
options: options
});
},
start: function() {
var that = this;
if (that.title) {
document.title = that.title;
}
return system.defer(function (dfd) {
$(function() {
system.log('Starting Application');
dfd.resolve();
system.log('Started Application');
});
}).promise();
},
setRoot: function(root, transition, applicationHost) {
var hostElement, settings = { activate: true, transition: transition };
if (!applicationHost || typeof applicationHost == "string") {
hostElement = document.getElementById(applicationHost || 'applicationHost');
} else {
hostElement = applicationHost;
}
if (typeof root === 'string') {
if (viewEngine.isViewUrl(root)) {
settings.view = root;
} else {
settings.model = root;
}
} else {
settings.model = root;
}
composition.compose(hostElement, settings);
},
adaptToDevice: function() {
document.ontouchmove = function (event) {
event.preventDefault();
};
}
};
Events.includeIn(app);
return app;
});
\ No newline at end of file
define(['./viewLocator', './viewModelBinder', './viewEngine', './system', './viewModel'],
function (viewLocator, viewModelBinder, viewEngine, system, viewModel) {
var dummyModel = {},
activeViewAttributeName = 'data-active-view';
function shouldPerformActivation(settings) {
return settings.model && settings.model.activate
&& ((composition.activateDuringComposition && settings.activate == undefined) || settings.activate);
}
function tryActivate(settings, successCallback) {
if (shouldPerformActivation(settings)) {
viewModel.activator().activateItem(settings.model).then(function (success) {
if (success) {
successCallback();
}
});
} else {
successCallback();
}
}
function getHostState(parent) {
var elements = [];
var state = {
childElements: elements,
activeView: null
};
var child = ko.virtualElements.firstChild(parent);
while (child) {
if (child.nodeType == 1) {
elements.push(child);
if (child.getAttribute(activeViewAttributeName)) {
state.activeView = child;
}
}
child = ko.virtualElements.nextSibling(child);
}
return state;
}
function afterContentSwitch(parent, newChild, settings) {
if (settings.activeView) {
settings.activeView.removeAttribute(activeViewAttributeName);
}
if (newChild) {
if (settings.model && settings.model.viewAttached) {
if (settings.composingNewView || settings.alwaysAttachView) {
settings.model.viewAttached(newChild);
}
}
newChild.setAttribute(activeViewAttributeName, true);
}
if (settings.afterCompose) {
settings.afterCompose(parent, newChild, settings);
}
}
function shouldTransition(newChild, settings) {
if (typeof settings.transition == 'string') {
if (settings.activeView) {
if (settings.activeView == newChild) {
return false;
}
if (!newChild) {
return true;
}
if (settings.skipTransitionOnSameViewId) {
var currentViewId = settings.activeView.getAttribute('data-view');
var newViewId = newChild.getAttribute('data-view');
return currentViewId != newViewId;
}
}
return true;
}
return false;
}
var composition = {
activateDuringComposition: false,
convertTransitionToModuleId: function (name) {
return 'durandal/transitions/' + name;
},
switchContent: function (parent, newChild, settings) {
settings.transition = settings.transition || this.defaultTransitionName;
if (shouldTransition(newChild, settings)) {
var transitionModuleId = this.convertTransitionToModuleId(settings.transition);
system.acquire(transitionModuleId).then(function (transition) {
settings.transition = transition;
transition(parent, newChild, settings).then(function () {
afterContentSwitch(parent, newChild, settings);
});
});
} else {
if (newChild != settings.activeView) {
if (settings.cacheViews && settings.activeView) {
$(settings.activeView).css('display', 'none');
}
if (!newChild) {
if (!settings.cacheViews) {
ko.virtualElements.emptyNode(parent);
}
} else {
if (settings.cacheViews) {
if (settings.composingNewView) {
settings.viewElements.push(newChild);
ko.virtualElements.prepend(parent, newChild);
} else {
$(newChild).css('display', '');
}
} else {
ko.virtualElements.emptyNode(parent);
ko.virtualElements.prepend(parent, newChild);
}
}
}
afterContentSwitch(parent, newChild, settings);
}
},
bindAndShow: function (element, view, settings) {
if (settings.cacheViews) {
settings.composingNewView = (ko.utils.arrayIndexOf(settings.viewElements, view) == -1);
} else {
settings.composingNewView = true;
}
tryActivate(settings, function () {
if (settings.beforeBind) {
settings.beforeBind(element, view, settings);
}
if (settings.preserveContext && settings.bindingContext) {
if (settings.composingNewView) {
viewModelBinder.bindContext(settings.bindingContext, view, settings.model);
}
} else if (view) {
var modelToBind = settings.model || dummyModel;
var currentModel = ko.dataFor(view);
if (currentModel != modelToBind) {
if (!settings.composingNewView) {
$(view).remove();
viewEngine.createView(view.getAttribute('data-view')).then(function(recreatedView) {
composition.bindAndShow(element, recreatedView, settings);
});
return;
}
viewModelBinder.bind(modelToBind, view);
}
}
composition.switchContent(element, view, settings);
});
},
defaultStrategy: function (settings) {
return viewLocator.locateViewForObject(settings.model, settings.viewElements);
},
getSettings: function (valueAccessor, element) {
var value = ko.utils.unwrapObservable(valueAccessor()) || {};
if (typeof value == 'string') {
return value;
}
var moduleId = system.getModuleId(value);
if (moduleId) {
return {
model: value
};
}
for (var attrName in value) {
value[attrName] = ko.utils.unwrapObservable(value[attrName]);
}
return value;
},
executeStrategy: function (element, settings) {
settings.strategy(settings).then(function (view) {
composition.bindAndShow(element, view, settings);
});
},
inject: function (element, settings) {
if (!settings.model) {
this.bindAndShow(element, null, settings);
return;
}
if (settings.view) {
viewLocator.locateView(settings.view, settings.area, settings.viewElements).then(function (view) {
composition.bindAndShow(element, view, settings);
});
return;
}
if (settings.view !== undefined && !settings.view) {
return;
}
if (!settings.strategy) {
settings.strategy = this.defaultStrategy;
}
if (typeof settings.strategy == 'string') {
system.acquire(settings.strategy).then(function (strategy) {
settings.strategy = strategy;
composition.executeStrategy(element, settings);
});
} else {
this.executeStrategy(element, settings);
}
},
compose: function (element, settings, bindingContext) {
if (typeof settings == 'string') {
if (viewEngine.isViewUrl(settings)) {
settings = {
view: settings
};
} else {
settings = {
model: settings
};
}
}
var moduleId = system.getModuleId(settings);
if (moduleId) {
settings = {
model: settings
};
}
var hostState = getHostState(element);
settings.bindingContext = bindingContext;
settings.activeView = hostState.activeView;
if (settings.cacheViews && !settings.viewElements) {
settings.viewElements = hostState.childElements;
}
if (!settings.model) {
if (!settings.view) {
this.bindAndShow(element, null, settings);
} else {
settings.area = settings.area || 'partial';
settings.preserveContext = true;
viewLocator.locateView(settings.view, settings.area, settings.viewElements).then(function (view) {
composition.bindAndShow(element, view, settings);
});
}
} else if (typeof settings.model == 'string') {
system.acquire(settings.model).then(function (module) {
if (typeof (module) == 'function') {
settings.model = new module(element, settings);
} else {
settings.model = module;
}
composition.inject(element, settings);
});
} else {
composition.inject(element, settings);
}
}
};
ko.bindingHandlers.compose = {
update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
var settings = composition.getSettings(valueAccessor);
composition.compose(element, settings, bindingContext);
}
};
ko.virtualElements.allowedBindings.compose = true;
return composition;
});
\ No newline at end of file
//heavily borrowed from backbone events, augmented by signals.js, added a little of my own code, cleaned up for better readability
define(['./system'], function (system) {
var eventSplitter = /\s+/;
var Events = function() { };
var Subscription = function(owner, events) {
this.owner = owner;
this.events = events;
};
Subscription.prototype.then = function (callback, context) {
this.callback = callback || this.callback;
this.context = context || this.context;
if (!this.callback) {
return this;
}
this.owner.on(this.events, this.callback, this.context);
return this;
};
Subscription.prototype.on = Subscription.prototype.then;
Subscription.prototype.off = function () {
this.owner.off(this.events, this.callback, this.context);
return this;
};
Events.prototype.on = function(events, callback, context) {
var calls, event, list;
if (!callback) {
return new Subscription(this, events);
} else {
calls = this.callbacks || (this.callbacks = {});
events = events.split(eventSplitter);
while (event = events.shift()) {
list = calls[event] || (calls[event] = []);
list.push(callback, context);
}
return this;
}
};
Events.prototype.off = function(events, callback, context) {
var event, calls, list, i;
// No events
if (!(calls = this.callbacks)) {
return this;
}
//removing all
if (!(events || callback || context)) {
delete this.callbacks;
return this;
}
events = events ? events.split(eventSplitter) : system.keys(calls);
// Loop through the callback list, splicing where appropriate.
while (event = events.shift()) {
if (!(list = calls[event]) || !(callback || context)) {
delete calls[event];
continue;
}
for (i = list.length - 2; i >= 0; i -= 2) {
if (!(callback && list[i] !== callback || context && list[i + 1] !== context)) {
list.splice(i, 2);
}
}
}
return this;
};
Events.prototype.trigger = function(events) {
var event, calls, list, i, length, args, all, rest;
if (!(calls = this.callbacks)) {
return this;
}
rest = [];
events = events.split(eventSplitter);
for (i = 1, length = arguments.length; i < length; i++) {
rest[i - 1] = arguments[i];
}
// For each event, walk through the list of callbacks twice, first to
// trigger the event, then to trigger any `"all"` callbacks.
while (event = events.shift()) {
// Copy callback lists to prevent modification.
if (all = calls.all) {
all = all.slice();
}
if (list = calls[event]) {
list = list.slice();
}
// Execute event callbacks.
if (list) {
for (i = 0, length = list.length; i < length; i += 2) {
list[i].apply(list[i + 1] || this, rest);
}
}
// Execute "all" callbacks.
if (all) {
args = [event].concat(rest);
for (i = 0, length = all.length; i < length; i += 2) {
all[i].apply(all[i + 1] || this, args);
}
}
}
return this;
};
Events.prototype.proxy = function(events) {
var that = this;
return (function(arg) {
that.trigger(events, arg);
});
};
Events.includeIn = function(targetObject) {
targetObject.on = Events.prototype.on;
targetObject.off = Events.prototype.off;
targetObject.trigger = Events.prototype.trigger;
targetObject.proxy = Events.prototype.proxy;
};
return Events;
});
\ No newline at end of file
define(['./composition', './system', './viewModel'],
function (composition, system, viewModel) {
var contexts = {},
modalCount = 0;
function ensureModalInstance(objOrModuleId) {
return system.defer(function(dfd) {
if (typeof objOrModuleId == "string") {
system.acquire(objOrModuleId).then(function(module) {
if (typeof(module) == 'function') {
dfd.resolve(new module());
} else {
dfd.resolve(module);
}
});
} else {
dfd.resolve(objOrModuleId);
}
}).promise();
}
var modalDialog = {
currentZIndex: 1050,
getNextZIndex: function () {
return ++this.currentZIndex;
},
isModalOpen: function() {
return modalCount > 0;
},
getContext: function(name) {
return contexts[name || 'default'];
},
addContext: function(name, modalContext) {
modalContext.name = name;
contexts[name] = modalContext;
var helperName = 'show' + name.substr(0, 1).toUpperCase() + name.substr(1);
this[helperName] = function (obj, activationData) {
return this.show(obj, activationData, name);
};
},
createCompositionSettings: function(obj, modalContext) {
var settings = {
model:obj,
activate:false
};
if (modalContext.afterCompose) {
settings.afterCompose = modalContext.afterCompose;
}
return settings;
},
show: function(obj, activationData, context) {
var that = this;
var modalContext = contexts[context || 'default'];
return system.defer(function(dfd) {
ensureModalInstance(obj).then(function(instance) {
var activator = viewModel.activator();
activator.activateItem(instance, activationData).then(function (success) {
if (success) {
var modal = instance.modal = {
owner: instance,
context: modalContext,
activator: activator,
close: function () {
var args = arguments;
activator.deactivateItem(instance, true).then(function (closeSuccess) {
if (closeSuccess) {
modalCount--;
modalContext.removeHost(modal);
delete instance.modal;
dfd.resolve.apply(dfd, args);
}
});
}
};
modal.settings = that.createCompositionSettings(instance, modalContext);
modalContext.addHost(modal);
modalCount++;
composition.compose(modal.host, modal.settings);
} else {
dfd.resolve(false);
}
});
});
}).promise();
}
};
modalDialog.addContext('default', {
blockoutOpacity: .2,
removeDelay: 200,
addHost: function(modal) {
var body = $('body');
var blockout = $('<div class="modalBlockout"></div>')
.css({ 'z-index': modalDialog.getNextZIndex(), 'opacity': this.blockoutOpacity })
.appendTo(body);
var host = $('<div class="modalHost"></div>')
.css({ 'z-index': modalDialog.getNextZIndex() })
.appendTo(body);
modal.host = host.get(0);
modal.blockout = blockout.get(0);
if (!modalDialog.isModalOpen()) {
modal.oldBodyMarginRight = $("body").css("margin-right");
var html = $("html");
var oldBodyOuterWidth = body.outerWidth(true);
var oldScrollTop = html.scrollTop();
$("html").css("overflow-y", "hidden");
var newBodyOuterWidth = $("body").outerWidth(true);
body.css("margin-right", (newBodyOuterWidth - oldBodyOuterWidth + parseInt(modal.oldBodyMarginRight)) + "px");
html.scrollTop(oldScrollTop); // necessary for Firefox
$("#simplemodal-overlay").css("width", newBodyOuterWidth + "px");
}
},
removeHost: function(modal) {
$(modal.host).css('opacity', 0);
$(modal.blockout).css('opacity', 0);
setTimeout(function() {
$(modal.host).remove();
$(modal.blockout).remove();
}, this.removeDelay);
if (!modalDialog.isModalOpen()) {
var html = $("html");
var oldScrollTop = html.scrollTop(); // necessary for Firefox.
html.css("overflow-y", "").scrollTop(oldScrollTop);
$("body").css("margin-right", modal.oldBodyMarginRight);
}
},
afterCompose: function(parent, newChild, settings) {
var $child = $(newChild);
var width = $child.width();
var height = $child.height();
$child.css({
'margin-top': (-height / 2).toString() + 'px',
'margin-left': (-width / 2).toString() + 'px'
});
$(settings.model.modal.host).css('opacity', 1);
if ($(newChild).hasClass('autoclose')) {
$(settings.model.modal.blockout).click(function() {
settings.model.modal.close();
});
}
$('.autofocus', newChild).each(function() {
$(this).focus();
});
}
});
return modalDialog;
});
\ No newline at end of file
define(['../system', '../viewModel', '../app'], function (system, viewModel, app) {
//NOTE: Sammy.js is not required by the core of Durandal.
//However, this plugin leverages it to enable navigation.
var routesByPath = {},
allRoutes = ko.observableArray([]),
visibleRoutes = ko.observableArray([]),
ready = ko.observable(false),
isNavigating = ko.observable(false),
sammy,
router,
previousRoute,
previousModule,
cancelling = false,
activeItem = viewModel.activator(),
activeRoute = ko.observable(),
navigationDefaultRoute,
queue = [],
skipRouteUrl;
var tryActivateRouter = function () {
tryActivateRouter = system.noop;
ready(true);
router.dfd.resolve();
delete router.dfd;
};
activeItem.settings.areSameItem = function (currentItem, newItem, activationData) {
return false;
};
function redirect(url) {
isNavigating(false);
system.log('Redirecting');
router.navigateTo(url);
}
function cancelNavigation() {
cancelling = true;
system.log('Cancelling Navigation');
if (previousRoute) {
sammy.setLocation(previousRoute);
}
cancelling = false;
isNavigating(false);
var routeAttempted = sammy.last_location[1].split('#/')[1];
if (previousRoute || !routeAttempted) {
tryActivateRouter();
} else if (routeAttempted != navigationDefaultRoute) {
window.location.replace("#/" + navigationDefaultRoute);
} else {
tryActivateRouter();
}
}
function completeNavigation(routeInfo, params, module) {
activeRoute(routeInfo);
router.onNavigationComplete(routeInfo, params, module);
previousModule = module;
previousRoute = sammy.last_location[1].replace('/', '');
tryActivateRouter();
}
function activateRoute(routeInfo, params, module) {
system.log('Activating Route', routeInfo, module, params);
activeItem.activateItem(module, params).then(function (succeeded) {
if (succeeded) {
completeNavigation(routeInfo, params, module);
} else {
cancelNavigation();
}
});
}
function shouldStopNavigation() {
return cancelling || (sammy.last_location[1].replace('/', '') == previousRoute);
}
function handleGuardedRoute(routeInfo, params, instance) {
var resultOrPromise = router.guardRoute(routeInfo, params, instance);
if (resultOrPromise) {
if (resultOrPromise.then) {
resultOrPromise.then(function(result) {
if (result) {
if (typeof result == 'string') {
redirect(result);
} else {
activateRoute(routeInfo, params, instance);
}
} else {
cancelNavigation();
}
});
} else {
if (typeof resultOrPromise == 'string') {
redirect(resultOrPromise);
} else {
activateRoute(routeInfo, params, instance);
}
}
} else {
cancelNavigation();
}
}
function dequeueRoute() {
if (isNavigating()) {
return;
}
var next = queue.shift();
queue = [];
if (!next) {
return;
}
isNavigating(true);
system.acquire(next.routeInfo.moduleId).then(function(module) {
next.params.routeInfo = next.routeInfo;
next.params.router = router;
var instance = router.getActivatableInstance(next.routeInfo, next.params, module);
if (router.guardRoute) {
handleGuardedRoute(next.routeInfo, next.params, instance);
} else {
activateRoute(next.routeInfo, next.params, instance);
}
});
}
function queueRoute(routeInfo, params) {
queue.unshift({
routeInfo: routeInfo,
params: params
});
dequeueRoute();
}
function ensureRoute(route, params) {
var routeInfo = routesByPath[route];
if (shouldStopNavigation()) {
return;
}
if (!routeInfo) {
if (!router.autoConvertRouteToModuleId) {
router.handleInvalidRoute(route, params);
return;
}
routeInfo = {
moduleId: router.autoConvertRouteToModuleId(route, params),
name: router.convertRouteToName(route)
};
}
queueRoute(routeInfo, params);
}
function handleDefaultRoute() {
ensureRoute(navigationDefaultRoute, this.params || {});
}
function handleMappedRoute() {
ensureRoute(this.app.last_route.path.toString(), this.params || {});
}
function handleWildCardRoute() {
var params = this.params || {}, route;
if (router.autoConvertRouteToModuleId) {
var fragment = this.path.split('#/');
if (fragment.length == 2) {
var parts = fragment[1].split('/');
route = parts[0];
params.splat = parts.splice(1);
ensureRoute(route, params);
return;
}
}
router.handleInvalidRoute(this.app.last_location[1], params);
}
function configureRoute(routeInfo) {
router.prepareRouteInfo(routeInfo);
routesByPath[routeInfo.url.toString()] = routeInfo;
allRoutes.push(routeInfo);
if (routeInfo.visible) {
routeInfo.isActive = ko.computed(function () {
return ready() && activeItem() && activeItem().__moduleId__ == routeInfo.moduleId;
});
visibleRoutes.push(routeInfo);
}
return routeInfo;
}
return router = {
ready: ready,
allRoutes: allRoutes,
visibleRoutes: visibleRoutes,
isNavigating: isNavigating,
activeItem: activeItem,
activeRoute: activeRoute,
afterCompose: function () {
setTimeout(function () {
isNavigating(false);
dequeueRoute();
}, 10);
},
getActivatableInstance: function (routeInfo, params, module) {
if (typeof module == 'function') {
return new module();
} else {
return module;
}
},
useConvention: function (rootPath) {
rootPath = rootPath == null ? 'viewmodels' : rootPath;
if (rootPath) {
rootPath += '/';
}
router.convertRouteToModuleId = function (url) {
return rootPath + router.stripParameter(url);
};
},
stripParameter: function (val) {
var colonIndex = val.indexOf(':');
var length = colonIndex > 0 ? colonIndex - 1 : val.length;
return val.substring(0, length);
},
handleInvalidRoute: function (route, params) {
system.log('No Route Found', route, params);
},
onNavigationComplete: function (routeInfo, params, module) {
if (app.title) {
document.title = routeInfo.caption + " | " + app.title;
} else {
document.title = routeInfo.caption;
}
},
navigateBack: function () {
window.history.back();
},
navigateTo: function (url, option) {
option = option || 'trigger';
switch (option.toLowerCase()) {
case 'skip':
skipRouteUrl = url;
sammy.setLocation(url);
break;
case 'replace':
window.location.replace(url);
break;
default:
if (sammy.lookupRoute('get', url)) {
sammy.setLocation(url);
} else {
window.location.href = url;
}
break;
}
},
replaceLocation: function (url) {
this.navigateTo(url, 'replace');
},
convertRouteToName: function (route) {
var value = router.stripParameter(route);
return value.substring(0, 1).toUpperCase() + value.substring(1);
},
convertRouteToModuleId: function (route) {
return router.stripParameter(route);
},
prepareRouteInfo: function (info) {
if (!(info.url instanceof RegExp)) {
info.name = info.name || router.convertRouteToName(info.url);
info.moduleId = info.moduleId || router.convertRouteToModuleId(info.url);
info.hash = info.hash || '#/' + info.url;
}
info.caption = info.caption || info.name;
info.settings = info.settings || {};
},
mapAuto: function (path) {
path = path || 'viewmodels';
path += '/';
router.autoConvertRouteToModuleId = function (url, params) {
return path + router.stripParameter(url);
};
},
mapNav: function (urlOrConfig, moduleId, name) {
if (typeof urlOrConfig == "string") {
return this.mapRoute(urlOrConfig, moduleId, name, true);
}
urlOrConfig.visible = true;
return configureRoute(urlOrConfig);
},
mapRoute: function (urlOrConfig, moduleId, name, visible) {
if (typeof urlOrConfig == "string") {
return configureRoute({
url: urlOrConfig,
moduleId: moduleId,
name: name,
visible: visible
});
} else {
return configureRoute(urlOrConfig);
}
},
map: function (routeOrRouteArray) {
if (!system.isArray(routeOrRouteArray)) {
return configureRoute(routeOrRouteArray);
}
var configured = [];
for (var i = 0; i < routeOrRouteArray.length; i++) {
configured.push(configureRoute(routeOrRouteArray[i]));
}
return configured;
},
activate: function (defaultRoute) {
return system.defer(function (dfd) {
var processedRoute;
router.dfd = dfd;
navigationDefaultRoute = defaultRoute;
sammy = Sammy(function (route) {
var unwrapped = allRoutes();
for (var i = 0; i < unwrapped.length; i++) {
var current = unwrapped[i];
route.get(current.url, handleMappedRoute);
processedRoute = this.routes.get[i];
routesByPath[processedRoute.path.toString()] = current;
}
route.get('#/', handleDefaultRoute);
route.get(/\#\/(.*)/, handleWildCardRoute);
});
sammy._checkFormSubmission = function () {
return false;
};
sammy.before(null, function(context) {
if (!skipRouteUrl) {
return true;
} else if (context.path === "/" + skipRouteUrl) {
skipRouteUrl = null;
return false;
} else {
throw new Error("Expected to skip url '" + skipRouteUrl + "', but found url '" + context.path + "'");
}
});
sammy.log = function () {
var args = Array.prototype.slice.call(arguments, 0);
args.unshift('Sammy');
system.log.apply(system, args);
};
sammy.run('#/');
}).promise();
}
};
});
\ No newline at end of file
define(['require'], function (require) {
var isDebugging = false,
nativeKeys = Object.keys,
hasOwnProperty = Object.prototype.hasOwnProperty,
toString = Object.prototype.toString,
system,
treatAsIE8 = false;
//see http://patik.com/blog/complete-cross-browser-console-log/
// Tell IE9 to use its built-in console
if (Function.prototype.bind && (typeof console === 'object' || typeof console === 'function') && typeof console.log == 'object') {
try {
['log', 'info', 'warn', 'error', 'assert', 'dir', 'clear', 'profile', 'profileEnd']
.forEach(function(method) {
console[method] = this.call(console[method], console);
}, Function.prototype.bind);
} catch (ex) {
treatAsIE8 = true;
}
}
// callback for dojo's loader
// note: if you wish to use Durandal with dojo's AMD loader,
// currently you must fork the dojo source with the following
// dojo/dojo.js, line 1187, the last line of the finishExec() function:
// (add) signal("moduleLoaded", [module.result, module.mid]);
// an enhancement request has been submitted to dojo to make this
// a permanent change. To view the status of this request, visit:
// http://bugs.dojotoolkit.org/ticket/16727
if (require.on) {
require.on("moduleLoaded", function (module, mid) {
system.setModuleId(module, mid);
});
}
// callback for require.js loader
if (typeof requirejs !== 'undefined') {
requirejs.onResourceLoad = function (context, map, depArray) {
system.setModuleId(context.defined[map.id], map.id);
};
}
var noop = function() { };
var log = function() {
try {
// Modern browsers
if (typeof console != 'undefined' && typeof console.log == 'function') {
// Opera 11
if (window.opera) {
var i = 0;
while (i < arguments.length) {
console.log('Item ' + (i + 1) + ': ' + arguments[i]);
i++;
}
}
// All other modern browsers
else if ((Array.prototype.slice.call(arguments)).length == 1 && typeof Array.prototype.slice.call(arguments)[0] == 'string') {
console.log((Array.prototype.slice.call(arguments)).toString());
} else {
console.log(Array.prototype.slice.call(arguments));
}
}
// IE8
else if ((!Function.prototype.bind || treatAsIE8) && typeof console != 'undefined' && typeof console.log == 'object') {
Function.prototype.call.call(console.log, console, Array.prototype.slice.call(arguments));
}
// IE7 and lower, and other old browsers
} catch(ignore) {}
};
system = {
version:"1.2.0",
noop: noop,
getModuleId: function(obj) {
if (!obj) {
return null;
}
if (typeof obj == 'function') {
return obj.prototype.__moduleId__;
}
if (typeof obj == 'string') {
return null;
}
return obj.__moduleId__;
},
setModuleId: function (obj, id) {
if (!obj) {
return;
}
if (typeof obj == 'function') {
obj.prototype.__moduleId__ = id;
return;
}
if (typeof obj == 'string') {
return;
}
obj.__moduleId__ = id;
},
debug: function(enable) {
if (arguments.length == 1) {
isDebugging = enable;
if (isDebugging) {
this.log = log;
this.log('Debug mode enabled.');
} else {
this.log('Debug mode disabled.');
this.log = noop;
}
} else {
return isDebugging;
}
},
isArray: function(obj) {
return toString.call(obj) === '[object Array]';
},
log: noop,
defer: function(action) {
return $.Deferred(action);
},
guid: function() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
},
acquire: function() {
var modules = Array.prototype.slice.call(arguments, 0);
return this.defer(function(dfd) {
require(modules, function() {
var args = arguments;
setTimeout(function() {
dfd.resolve.apply(dfd, args);
}, 1);
});
}).promise();
}
};
system.keys = nativeKeys || function(obj) {
if (obj !== Object(obj)) {
throw new TypeError('Invalid object');
}
var keys = [];
for (var key in obj) {
if (hasOwnProperty.call(obj, key)) {
keys[keys.length] = key;
}
}
return keys;
};
return system;
});
\ No newline at end of file
define(['./system'], function (system) {
var parseMarkupCore;
if ($.parseHTML) {
parseMarkupCore = function(html) {
return $.parseHTML(html);
};
} else {
parseMarkupCore = function(html) {
return $(html).get();
};
}
return {
viewExtension: '.html',
viewPlugin: 'text',
isViewUrl: function (url) {
return url.indexOf(this.viewExtension, url.length - this.viewExtension.length) !== -1;
},
convertViewUrlToViewId: function (url) {
return url.substring(0, url.length - this.viewExtension.length);
},
convertViewIdToRequirePath: function (viewId) {
return this.viewPlugin + '!' + viewId + this.viewExtension;
},
parseMarkup: function (markup) {
var allElements = parseMarkupCore(markup);
if (allElements.length == 1) {
return allElements[0];
}
var withoutCommentsOrEmptyText = [];
for (var i = 0; i < allElements.length; i++) {
var current = allElements[i];
if (current.nodeType != 8) {
if (current.nodeType == 3) {
var result = /\S/.test(current.nodeValue);
if (!result) {
continue;
}
}
withoutCommentsOrEmptyText.push(current);
}
}
if (withoutCommentsOrEmptyText.length > 1) {
return $(withoutCommentsOrEmptyText).wrapAll('<div class="durandal-wrapper"></div>').parent().get(0);
}
return withoutCommentsOrEmptyText[0];
},
createView: function(viewId) {
var that = this;
var requirePath = this.convertViewIdToRequirePath(viewId);
return system.defer(function(dfd) {
system.acquire(requirePath).then(function(markup) {
var element = that.parseMarkup(markup);
element.setAttribute('data-view', viewId);
dfd.resolve(element);
});
}).promise();
}
};
});
\ No newline at end of file
define(['./system', './viewEngine'],
function (system, viewEngine) {
function findInElements(nodes, url) {
for (var i = 0; i < nodes.length; i++) {
var current = nodes[i];
var existingUrl = current.getAttribute('data-view');
if (existingUrl == url) {
return current;
}
}
}
function escape(str) {
return (str + '').replace(/([\\\.\+\*\?\[\^\]\$\(\)\{\}\=\!\<\>\|\:])/g, "\\$1");
}
return {
useConvention: function(modulesPath, viewsPath, areasPath) {
modulesPath = modulesPath || 'viewmodels';
viewsPath = viewsPath || 'views';
areasPath = areasPath || viewsPath;
var reg = new RegExp(escape(modulesPath), 'gi');
this.convertModuleIdToViewId = function (moduleId) {
return moduleId.replace(reg, viewsPath);
};
this.translateViewIdToArea = function (viewId, area) {
if (!area || area == 'partial') {
return areasPath + '/' + viewId;
}
return areasPath + '/' + area + '/' + viewId;
};
},
locateViewForObject: function(obj, elementsToSearch) {
var view;
if (obj.getView) {
view = obj.getView();
if (view) {
return this.locateView(view, null, elementsToSearch);
}
}
if (obj.viewUrl) {
return this.locateView(obj.viewUrl, null, elementsToSearch);
}
var id = system.getModuleId(obj);
if (id) {
return this.locateView(this.convertModuleIdToViewId(id), null, elementsToSearch);
}
return this.locateView(this.determineFallbackViewId(obj), null, elementsToSearch);
},
convertModuleIdToViewId: function(moduleId) {
return moduleId;
},
determineFallbackViewId: function (obj) {
var funcNameRegex = /function (.{1,})\(/;
var results = (funcNameRegex).exec((obj).constructor.toString());
var typeName = (results && results.length > 1) ? results[1] : "";
return 'views/' + typeName;
},
translateViewIdToArea: function (viewId, area) {
return viewId;
},
locateView: function(viewOrUrlOrId, area, elementsToSearch) {
if (typeof viewOrUrlOrId === 'string') {
var viewId;
if (viewEngine.isViewUrl(viewOrUrlOrId)) {
viewId = viewEngine.convertViewUrlToViewId(viewOrUrlOrId);
} else {
viewId = viewOrUrlOrId;
}
if (area) {
viewId = this.translateViewIdToArea(viewId, area);
}
if (elementsToSearch) {
var existing = findInElements(elementsToSearch, viewId);
if (existing) {
return system.defer(function(dfd) {
dfd.resolve(existing);
}).promise();
}
}
return viewEngine.createView(viewId);
}
return system.defer(function(dfd) {
dfd.resolve(viewOrUrlOrId);
}).promise();
}
};
});
\ No newline at end of file
define(['./system'], function (system) {
var viewModel;
function ensureSettings(settings) {
if (settings == undefined) {
settings = {};
}
if (!settings.closeOnDeactivate) {
settings.closeOnDeactivate = viewModel.defaults.closeOnDeactivate;
}
if (!settings.beforeActivate) {
settings.beforeActivate = viewModel.defaults.beforeActivate;
}
if (!settings.afterDeactivate) {
settings.afterDeactivate = viewModel.defaults.afterDeactivate;
}
if (!settings.interpretResponse) {
settings.interpretResponse = viewModel.defaults.interpretResponse;
}
if (!settings.areSameItem) {
settings.areSameItem = viewModel.defaults.areSameItem;
}
return settings;
}
function deactivate(item, close, settings, dfd, setter) {
if (item && item.deactivate) {
system.log('Deactivating', item);
var result;
try {
result = item.deactivate(close);
} catch(error) {
system.log(error);
dfd.resolve(false);
return;
}
if (result && result.then) {
result.then(function() {
settings.afterDeactivate(item, close, setter);
dfd.resolve(true);
}, function(reason) {
system.log(reason);
dfd.resolve(false);
});
} else {
settings.afterDeactivate(item, close, setter);
dfd.resolve(true);
}
} else {
if (item) {
settings.afterDeactivate(item, close, setter);
}
dfd.resolve(true);
}
}
function activate(newItem, activeItem, callback, activationData) {
if (newItem) {
if (newItem.activate) {
system.log('Activating', newItem);
var result;
try {
result = newItem.activate(activationData);
} catch (error) {
system.log(error);
callback(false);
return;
}
if (result && result.then) {
result.then(function() {
activeItem(newItem);
callback(true);
}, function(reason) {
system.log(reason);
callback(false);
});
} else {
activeItem(newItem);
callback(true);
}
} else {
activeItem(newItem);
callback(true);
}
} else {
callback(true);
}
}
function canDeactivateItem(item, close, settings) {
return system.defer(function (dfd) {
if (item && item.canDeactivate) {
var resultOrPromise;
try {
resultOrPromise = item.canDeactivate(close);
} catch(error) {
system.log(error);
dfd.resolve(false);
return;
}
if (resultOrPromise.then) {
resultOrPromise.then(function(result) {
dfd.resolve(settings.interpretResponse(result));
}, function(reason) {
system.log(reason);
dfd.resolve(false);
});
} else {
dfd.resolve(settings.interpretResponse(resultOrPromise));
}
} else {
dfd.resolve(true);
}
}).promise();
};
function canActivateItem(newItem, activeItem, settings, activationData) {
return system.defer(function (dfd) {
if (newItem == activeItem()) {
dfd.resolve(true);
return;
}
if (newItem && newItem.canActivate) {
var resultOrPromise;
try {
resultOrPromise = newItem.canActivate(activationData);
} catch (error) {
system.log(error);
dfd.resolve(false);
return;
}
if (resultOrPromise.then) {
resultOrPromise.then(function(result) {
dfd.resolve(settings.interpretResponse(result));
}, function(reason) {
system.log(reason);
dfd.resolve(false);
});
} else {
dfd.resolve(settings.interpretResponse(resultOrPromise));
}
} else {
dfd.resolve(true);
}
}).promise();
};
function createActivator(initialActiveItem, settings) {
var activeItem = ko.observable(null);
settings = ensureSettings(settings);
var computed = ko.computed({
read: function () {
return activeItem();
},
write: function (newValue) {
computed.viaSetter = true;
computed.activateItem(newValue);
}
});
computed.settings = settings;
settings.activator = computed;
computed.isActivating = ko.observable(false);
computed.canDeactivateItem = function (item, close) {
return canDeactivateItem(item, close, settings);
};
computed.deactivateItem = function (item, close) {
return system.defer(function(dfd) {
computed.canDeactivateItem(item, close).then(function(canDeactivate) {
if (canDeactivate) {
deactivate(item, close, settings, dfd, activeItem);
} else {
computed.notifySubscribers();
dfd.resolve(false);
}
});
}).promise();
};
computed.canActivateItem = function (newItem, activationData) {
return canActivateItem(newItem, activeItem, settings, activationData);
};
computed.activateItem = function (newItem, activationData) {
var viaSetter = computed.viaSetter;
computed.viaSetter = false;
return system.defer(function (dfd) {
if (computed.isActivating()) {
dfd.resolve(false);
return;
}
computed.isActivating(true);
var currentItem = activeItem();
if (settings.areSameItem(currentItem, newItem, activationData)) {
computed.isActivating(false);
dfd.resolve(true);
return;
}
computed.canDeactivateItem(currentItem, settings.closeOnDeactivate).then(function (canDeactivate) {
if (canDeactivate) {
computed.canActivateItem(newItem, activationData).then(function (canActivate) {
if (canActivate) {
system.defer(function (dfd2) {
deactivate(currentItem, settings.closeOnDeactivate, settings, dfd2);
}).promise().then(function () {
newItem = settings.beforeActivate(newItem, activationData);
activate(newItem, activeItem, function (result) {
computed.isActivating(false);
dfd.resolve(result);
}, activationData);
});
} else {
if (viaSetter) {
computed.notifySubscribers();
}
computed.isActivating(false);
dfd.resolve(false);
}
});
} else {
if (viaSetter) {
computed.notifySubscribers();
}
computed.isActivating(false);
dfd.resolve(false);
}
});
}).promise();
};
computed.canActivate = function () {
var toCheck;
if (initialActiveItem) {
toCheck = initialActiveItem;
initialActiveItem = false;
} else {
toCheck = computed();
}
return computed.canActivateItem(toCheck);
};
computed.activate = function () {
var toActivate;
if (initialActiveItem) {
toActivate = initialActiveItem;
initialActiveItem = false;
} else {
toActivate = computed();
}
return computed.activateItem(toActivate);
};
computed.canDeactivate = function (close) {
return computed.canDeactivateItem(computed(), close);
};
computed.deactivate = function (close) {
return computed.deactivateItem(computed(), close);
};
computed.includeIn = function (includeIn) {
includeIn.canActivate = function () {
return computed.canActivate();
};
includeIn.activate = function () {
return computed.activate();
};
includeIn.canDeactivate = function (close) {
return computed.canDeactivate(close);
};
includeIn.deactivate = function (close) {
return computed.deactivate(close);
};
};
if (settings.includeIn) {
computed.includeIn(settings.includeIn);
} else if (initialActiveItem) {
computed.activate();
}
computed.forItems = function (items) {
settings.closeOnDeactivate = false;
settings.determineNextItemToActivate = function (list, lastIndex) {
var toRemoveAt = lastIndex - 1;
if (toRemoveAt == -1 && list.length > 1) {
return list[1];
}
if (toRemoveAt > -1 && toRemoveAt < list.length - 1) {
return list[toRemoveAt];
}
return null;
};
settings.beforeActivate = function (newItem) {
var currentItem = computed();
if (!newItem) {
newItem = settings.determineNextItemToActivate(items, currentItem ? items.indexOf(currentItem) : 0);
} else {
var index = items.indexOf(newItem);
if (index == -1) {
items.push(newItem);
} else {
newItem = items()[index];
}
}
return newItem;
};
settings.afterDeactivate = function (oldItem, close) {
if (close) {
items.remove(oldItem);
}
};
var originalCanDeactivate = computed.canDeactivate;
computed.canDeactivate = function (close) {
if (close) {
return system.defer(function (dfd) {
var list = items();
var results = [];
function finish() {
for (var j = 0; j < results.length; j++) {
if (!results[j]) {
dfd.resolve(false);
return;
}
}
dfd.resolve(true);
}
for (var i = 0; i < list.length; i++) {
computed.canDeactivateItem(list[i], close).then(function (result) {
results.push(result);
if (results.length == list.length) {
finish();
}
});
}
}).promise();
} else {
return originalCanDeactivate();
}
};
var originalDeactivate = computed.deactivate;
computed.deactivate = function (close) {
if (close) {
return system.defer(function (dfd) {
var list = items();
var results = 0;
var listLength = list.length;
function doDeactivate(item) {
computed.deactivateItem(item, close).then(function () {
results++;
items.remove(item);
if (results == listLength) {
dfd.resolve();
}
});
}
for (var i = 0; i < listLength; i++) {
doDeactivate(list[i]);
}
}).promise();
} else {
return originalDeactivate();
}
};
return computed;
};
return computed;
}
return viewModel = {
defaults: {
closeOnDeactivate: true,
interpretResponse: function (value) {
if (typeof value == 'string') {
var lowered = value.toLowerCase();
return lowered == 'yes' || lowered == 'ok';
}
return value;
},
areSameItem: function (currentItem, newItem, activationData) {
return currentItem == newItem;
},
beforeActivate: function (newItem) {
return newItem;
},
afterDeactivate: function (item, close, setter) {
if (close && setter) {
setter(null);
}
}
},
activator: createActivator
};
});
\ No newline at end of file
define(['./system'], function (system) {
var viewModelBinder;
var insufficientInfoMessage = 'Insufficient Information to Bind';
var unexpectedViewMessage = 'Unexpected View Type';
function doBind(obj, view, action) {
if (!view || !obj) {
if (viewModelBinder.throwOnErrors) {
throw new Error(insufficientInfoMessage);
} else {
system.log(insufficientInfoMessage, view, obj);
}
return;
}
if (!view.getAttribute) {
if (viewModelBinder.throwOnErrors) {
throw new Error(unexpectedViewMessage);
} else {
system.log(unexpectedViewMessage, view, obj);
}
return;
}
var viewName = view.getAttribute('data-view');
try {
system.log('Binding', viewName, obj);
viewModelBinder.beforeBind(obj, view);
action();
viewModelBinder.afterBind(obj, view);
} catch (e) {
if (viewModelBinder.throwOnErrors) {
throw new Error(e.message + ';\nView: ' + viewName + ";\nModuleId: " + system.getModuleId(obj));
} else {
system.log(e.message, viewName, obj);
}
}
}
return viewModelBinder = {
beforeBind: system.noop,
afterBind:system.noop,
bindContext: function(bindingContext, view, obj) {
if (obj) {
bindingContext = bindingContext.createChildContext(obj);
}
doBind(bindingContext, view, function () {
if (obj && obj.beforeBind) {
obj.beforeBind(view);
}
ko.applyBindings(bindingContext, view);
if (obj && obj.afterBind) {
obj.afterBind(view);
}
});
},
bind: function(obj, view) {
doBind(obj, view, function () {
if (obj.beforeBind) {
obj.beforeBind(view);
}
ko.applyBindings(obj, view);
if (obj.afterBind) {
obj.afterBind(view);
}
});
}
};
});
\ No newline at end of file
define(['./system', './composition'], function (system, composition) {
var widgetPartAttribute = 'data-part',
widgetPartSelector = '[' + widgetPartAttribute + ']';
var kindModuleMaps = {},
kindViewMaps = {},
bindableSettings = ['model','view','kind'];
var widget = {
getParts: function(elements) {
var parts = {};
if (!system.isArray(elements)) {
elements = [elements];
}
for (var i = 0; i < elements.length; i++) {
var element = elements[i];
if (element.getAttribute) {
var id = element.getAttribute(widgetPartAttribute);
if (id) {
parts[id] = element;
}
var childParts = $(widgetPartSelector, element);
for (var j = 0; j < childParts.length; j++) {
var part = childParts.get(j);
parts[part.getAttribute(widgetPartAttribute)] = part;
}
}
}
return parts;
},
getSettings: function(valueAccessor) {
var value = ko.utils.unwrapObservable(valueAccessor()) || {};
if (typeof value == 'string') {
return value;
} else {
for (var attrName in value) {
if (ko.utils.arrayIndexOf(bindableSettings, attrName) != -1) {
value[attrName] = ko.utils.unwrapObservable(value[attrName]);
} else {
value[attrName] = value[attrName];
}
}
}
return value;
},
registerKind: function(kind) {
ko.bindingHandlers[kind] = {
init: function() {
return { controlsDescendantBindings: true };
},
update: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
var settings = widget.getSettings(valueAccessor);
settings.kind = kind;
widget.create(element, settings, bindingContext);
}
};
ko.virtualElements.allowedBindings[kind] = true;
},
mapKind: function(kind, viewId, moduleId) {
if (viewId) {
kindViewMaps[kind] = viewId;
}
if (moduleId) {
kindModuleMaps[kind] = moduleId;
}
},
convertKindToModuleId: function(kind) {
return kindModuleMaps[kind] || 'durandal/widgets/' + kind + '/controller';
},
convertKindToViewId: function (kind) {
return kindViewMaps[kind] || 'durandal/widgets/' + kind + '/view';
},
beforeBind: function(element, view, settings) {
var replacementParts = widget.getParts(element);
var standardParts = widget.getParts(view);
for (var partId in replacementParts) {
$(standardParts[partId]).replaceWith(replacementParts[partId]);
}
},
createCompositionSettings: function(settings) {
if (!settings.model) {
settings.model = this.convertKindToModuleId(settings.kind);
}
if (!settings.view) {
settings.view = this.convertKindToViewId(settings.kind);
}
settings.preserveContext = true;
settings.beforeBind = this.beforeBind;
return settings;
},
create: function (element, settings, bindingContext) {
if (typeof settings == 'string') {
settings = {
kind: settings
};
}
var compositionSettings = widget.createCompositionSettings(settings);
composition.compose(element, compositionSettings, bindingContext);
}
};
ko.bindingHandlers.widget = {
init: function() {
return { controlsDescendantBindings: true };
},
update: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
var settings = widget.getSettings(valueAccessor);
widget.create(element, settings, bindingContext);
}
};
ko.virtualElements.allowedBindings.widget = true;
return widget;
});
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
// Knockout JavaScript library v2.2.1
// (c) Steven Sanderson - http://knockoutjs.com/
// License: MIT (http://www.opensource.org/licenses/mit-license.php)
(function() {function j(w){throw w;}var m=!0,p=null,r=!1;function u(w){return function(){return w}};var x=window,y=document,ga=navigator,F=window.jQuery,I=void 0;
function L(w){function ha(a,d,c,e,f){var g=[];a=b.j(function(){var a=d(c,f)||[];0<g.length&&(b.a.Ya(M(g),a),e&&b.r.K(e,p,[c,a,f]));g.splice(0,g.length);b.a.P(g,a)},p,{W:a,Ka:function(){return 0==g.length||!b.a.X(g[0])}});return{M:g,j:a.pa()?a:I}}function M(a){for(;a.length&&!b.a.X(a[0]);)a.splice(0,1);if(1<a.length){for(var d=a[0],c=a[a.length-1],e=[d];d!==c;){d=d.nextSibling;if(!d)return;e.push(d)}Array.prototype.splice.apply(a,[0,a.length].concat(e))}return a}function S(a,b,c,e,f){var g=Math.min,
h=Math.max,k=[],l,n=a.length,q,s=b.length,v=s-n||1,G=n+s+1,J,A,z;for(l=0;l<=n;l++){A=J;k.push(J=[]);z=g(s,l+v);for(q=h(0,l-1);q<=z;q++)J[q]=q?l?a[l-1]===b[q-1]?A[q-1]:g(A[q]||G,J[q-1]||G)+1:q+1:l+1}g=[];h=[];v=[];l=n;for(q=s;l||q;)s=k[l][q]-1,q&&s===k[l][q-1]?h.push(g[g.length]={status:c,value:b[--q],index:q}):l&&s===k[l-1][q]?v.push(g[g.length]={status:e,value:a[--l],index:l}):(g.push({status:"retained",value:b[--q]}),--l);if(h.length&&v.length){a=10*n;var t;for(b=c=0;(f||b<a)&&(t=h[c]);c++){for(e=
0;k=v[e];e++)if(t.value===k.value){t.moved=k.index;k.moved=t.index;v.splice(e,1);b=e=0;break}b+=e}}return g.reverse()}function T(a,d,c,e,f){f=f||{};var g=a&&N(a),g=g&&g.ownerDocument,h=f.templateEngine||O;b.za.vb(c,h,g);c=h.renderTemplate(c,e,f,g);("number"!=typeof c.length||0<c.length&&"number"!=typeof c[0].nodeType)&&j(Error("Template engine must return an array of DOM nodes"));g=r;switch(d){case "replaceChildren":b.e.N(a,c);g=m;break;case "replaceNode":b.a.Ya(a,c);g=m;break;case "ignoreTargetNode":break;
default:j(Error("Unknown renderMode: "+d))}g&&(U(c,e),f.afterRender&&b.r.K(f.afterRender,p,[c,e.$data]));return c}function N(a){return a.nodeType?a:0<a.length?a[0]:p}function U(a,d){if(a.length){var c=a[0],e=a[a.length-1];V(c,e,function(a){b.Da(d,a)});V(c,e,function(a){b.s.ib(a,[d])})}}function V(a,d,c){var e;for(d=b.e.nextSibling(d);a&&(e=a)!==d;)a=b.e.nextSibling(e),(1===e.nodeType||8===e.nodeType)&&c(e)}function W(a,d,c){a=b.g.aa(a);for(var e=b.g.Q,f=0;f<a.length;f++){var g=a[f].key;if(e.hasOwnProperty(g)){var h=
e[g];"function"===typeof h?(g=h(a[f].value))&&j(Error(g)):h||j(Error("This template engine does not support the '"+g+"' binding within its templates"))}}a="ko.__tr_ambtns(function($context,$element){return(function(){return{ "+b.g.ba(a)+" } })()})";return c.createJavaScriptEvaluatorBlock(a)+d}function X(a,d,c,e){function f(a){return function(){return k[a]}}function g(){return k}var h=0,k,l;b.j(function(){var n=c&&c instanceof b.z?c:new b.z(b.a.d(c)),q=n.$data;e&&b.eb(a,n);if(k=("function"==typeof d?
d(n,a):d)||b.J.instance.getBindings(a,n)){if(0===h){h=1;for(var s in k){var v=b.c[s];v&&8===a.nodeType&&!b.e.I[s]&&j(Error("The binding '"+s+"' cannot be used with virtual elements"));if(v&&"function"==typeof v.init&&(v=(0,v.init)(a,f(s),g,q,n))&&v.controlsDescendantBindings)l!==I&&j(Error("Multiple bindings ("+l+" and "+s+") are trying to control descendant bindings of the same element. You cannot use these bindings together on the same element.")),l=s}h=2}if(2===h)for(s in k)(v=b.c[s])&&"function"==
typeof v.update&&(0,v.update)(a,f(s),g,q,n)}},p,{W:a});return{Nb:l===I}}function Y(a,d,c){var e=m,f=1===d.nodeType;f&&b.e.Ta(d);if(f&&c||b.J.instance.nodeHasBindings(d))e=X(d,p,a,c).Nb;e&&Z(a,d,!f)}function Z(a,d,c){for(var e=b.e.firstChild(d);d=e;)e=b.e.nextSibling(d),Y(a,d,c)}function $(a,b){var c=aa(a,b);return c?0<c.length?c[c.length-1].nextSibling:a.nextSibling:p}function aa(a,b){for(var c=a,e=1,f=[];c=c.nextSibling;){if(H(c)&&(e--,0===e))return f;f.push(c);B(c)&&e++}b||j(Error("Cannot find closing comment tag to match: "+
a.nodeValue));return p}function H(a){return 8==a.nodeType&&(K?a.text:a.nodeValue).match(ia)}function B(a){return 8==a.nodeType&&(K?a.text:a.nodeValue).match(ja)}function P(a,b){for(var c=p;a!=c;)c=a,a=a.replace(ka,function(a,c){return b[c]});return a}function la(){var a=[],d=[];this.save=function(c,e){var f=b.a.i(a,c);0<=f?d[f]=e:(a.push(c),d.push(e))};this.get=function(c){c=b.a.i(a,c);return 0<=c?d[c]:I}}function ba(a,b,c){function e(e){var g=b(a[e]);switch(typeof g){case "boolean":case "number":case "string":case "function":f[e]=
g;break;case "object":case "undefined":var h=c.get(g);f[e]=h!==I?h:ba(g,b,c)}}c=c||new la;a=b(a);if(!("object"==typeof a&&a!==p&&a!==I&&!(a instanceof Date)))return a;var f=a instanceof Array?[]:{};c.save(a,f);var g=a;if(g instanceof Array){for(var h=0;h<g.length;h++)e(h);"function"==typeof g.toJSON&&e("toJSON")}else for(h in g)e(h);return f}function ca(a,d){if(a)if(8==a.nodeType){var c=b.s.Ua(a.nodeValue);c!=p&&d.push({sb:a,Fb:c})}else if(1==a.nodeType)for(var c=0,e=a.childNodes,f=e.length;c<f;c++)ca(e[c],
d)}function Q(a,d,c,e){b.c[a]={init:function(a){b.a.f.set(a,da,{});return{controlsDescendantBindings:m}},update:function(a,g,h,k,l){h=b.a.f.get(a,da);g=b.a.d(g());k=!c!==!g;var n=!h.Za;if(n||d||k!==h.qb)n&&(h.Za=b.a.Ia(b.e.childNodes(a),m)),k?(n||b.e.N(a,b.a.Ia(h.Za)),b.Ea(e?e(l,g):l,a)):b.e.Y(a),h.qb=k}};b.g.Q[a]=r;b.e.I[a]=m}function ea(a,d,c){c&&d!==b.k.q(a)&&b.k.T(a,d);d!==b.k.q(a)&&b.r.K(b.a.Ba,p,[a,"change"])}var b="undefined"!==typeof w?w:{};b.b=function(a,d){for(var c=a.split("."),e=b,f=0;f<
c.length-1;f++)e=e[c[f]];e[c[c.length-1]]=d};b.p=function(a,b,c){a[b]=c};b.version="2.2.1";b.b("version",b.version);b.a=new function(){function a(a,d){if("input"!==b.a.u(a)||!a.type||"click"!=d.toLowerCase())return r;var c=a.type;return"checkbox"==c||"radio"==c}var d=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,c={},e={};c[/Firefox\/2/i.test(ga.userAgent)?"KeyboardEvent":"UIEvents"]=["keyup","keydown","keypress"];c.MouseEvents="click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave".split(" ");
for(var f in c){var g=c[f];if(g.length)for(var h=0,k=g.length;h<k;h++)e[g[h]]=f}var l={propertychange:m},n,c=3;f=y.createElement("div");for(g=f.getElementsByTagName("i");f.innerHTML="\x3c!--[if gt IE "+ ++c+"]><i></i><![endif]--\x3e",g[0];);n=4<c?c:I;return{Na:["authenticity_token",/^__RequestVerificationToken(_.*)?$/],o:function(a,b){for(var d=0,c=a.length;d<c;d++)b(a[d])},i:function(a,b){if("function"==typeof Array.prototype.indexOf)return Array.prototype.indexOf.call(a,b);for(var d=0,c=a.length;d<
c;d++)if(a[d]===b)return d;return-1},lb:function(a,b,d){for(var c=0,e=a.length;c<e;c++)if(b.call(d,a[c]))return a[c];return p},ga:function(a,d){var c=b.a.i(a,d);0<=c&&a.splice(c,1)},Ga:function(a){a=a||[];for(var d=[],c=0,e=a.length;c<e;c++)0>b.a.i(d,a[c])&&d.push(a[c]);return d},V:function(a,b){a=a||[];for(var d=[],c=0,e=a.length;c<e;c++)d.push(b(a[c]));return d},fa:function(a,b){a=a||[];for(var d=[],c=0,e=a.length;c<e;c++)b(a[c])&&d.push(a[c]);return d},P:function(a,b){if(b instanceof Array)a.push.apply(a,
b);else for(var d=0,c=b.length;d<c;d++)a.push(b[d]);return a},extend:function(a,b){if(b)for(var d in b)b.hasOwnProperty(d)&&(a[d]=b[d]);return a},ka:function(a){for(;a.firstChild;)b.removeNode(a.firstChild)},Hb:function(a){a=b.a.L(a);for(var d=y.createElement("div"),c=0,e=a.length;c<e;c++)d.appendChild(b.A(a[c]));return d},Ia:function(a,d){for(var c=0,e=a.length,g=[];c<e;c++){var f=a[c].cloneNode(m);g.push(d?b.A(f):f)}return g},N:function(a,d){b.a.ka(a);if(d)for(var c=0,e=d.length;c<e;c++)a.appendChild(d[c])},
Ya:function(a,d){var c=a.nodeType?[a]:a;if(0<c.length){for(var e=c[0],g=e.parentNode,f=0,h=d.length;f<h;f++)g.insertBefore(d[f],e);f=0;for(h=c.length;f<h;f++)b.removeNode(c[f])}},bb:function(a,b){7>n?a.setAttribute("selected",b):a.selected=b},D:function(a){return(a||"").replace(d,"")},Rb:function(a,d){for(var c=[],e=(a||"").split(d),f=0,g=e.length;f<g;f++){var h=b.a.D(e[f]);""!==h&&c.push(h)}return c},Ob:function(a,b){a=a||"";return b.length>a.length?r:a.substring(0,b.length)===b},tb:function(a,b){if(b.compareDocumentPosition)return 16==
(b.compareDocumentPosition(a)&16);for(;a!=p;){if(a==b)return m;a=a.parentNode}return r},X:function(a){return b.a.tb(a,a.ownerDocument)},u:function(a){return a&&a.tagName&&a.tagName.toLowerCase()},n:function(b,d,c){var e=n&&l[d];if(!e&&"undefined"!=typeof F){if(a(b,d)){var f=c;c=function(a,b){var d=this.checked;b&&(this.checked=b.nb!==m);f.call(this,a);this.checked=d}}F(b).bind(d,c)}else!e&&"function"==typeof b.addEventListener?b.addEventListener(d,c,r):"undefined"!=typeof b.attachEvent?b.attachEvent("on"+
d,function(a){c.call(b,a)}):j(Error("Browser doesn't support addEventListener or attachEvent"))},Ba:function(b,d){(!b||!b.nodeType)&&j(Error("element must be a DOM node when calling triggerEvent"));if("undefined"!=typeof F){var c=[];a(b,d)&&c.push({nb:b.checked});F(b).trigger(d,c)}else"function"==typeof y.createEvent?"function"==typeof b.dispatchEvent?(c=y.createEvent(e[d]||"HTMLEvents"),c.initEvent(d,m,m,x,0,0,0,0,0,r,r,r,r,0,b),b.dispatchEvent(c)):j(Error("The supplied element doesn't support dispatchEvent")):
"undefined"!=typeof b.fireEvent?(a(b,d)&&(b.checked=b.checked!==m),b.fireEvent("on"+d)):j(Error("Browser doesn't support triggering events"))},d:function(a){return b.$(a)?a():a},ua:function(a){return b.$(a)?a.t():a},da:function(a,d,c){if(d){var e=/[\w-]+/g,f=a.className.match(e)||[];b.a.o(d.match(e),function(a){var d=b.a.i(f,a);0<=d?c||f.splice(d,1):c&&f.push(a)});a.className=f.join(" ")}},cb:function(a,d){var c=b.a.d(d);if(c===p||c===I)c="";if(3===a.nodeType)a.data=c;else{var e=b.e.firstChild(a);
!e||3!=e.nodeType||b.e.nextSibling(e)?b.e.N(a,[y.createTextNode(c)]):e.data=c;b.a.wb(a)}},ab:function(a,b){a.name=b;if(7>=n)try{a.mergeAttributes(y.createElement("<input name='"+a.name+"'/>"),r)}catch(d){}},wb:function(a){9<=n&&(a=1==a.nodeType?a:a.parentNode,a.style&&(a.style.zoom=a.style.zoom))},ub:function(a){if(9<=n){var b=a.style.width;a.style.width=0;a.style.width=b}},Lb:function(a,d){a=b.a.d(a);d=b.a.d(d);for(var c=[],e=a;e<=d;e++)c.push(e);return c},L:function(a){for(var b=[],d=0,c=a.length;d<
c;d++)b.push(a[d]);return b},Pb:6===n,Qb:7===n,Z:n,Oa:function(a,d){for(var c=b.a.L(a.getElementsByTagName("input")).concat(b.a.L(a.getElementsByTagName("textarea"))),e="string"==typeof d?function(a){return a.name===d}:function(a){return d.test(a.name)},f=[],g=c.length-1;0<=g;g--)e(c[g])&&f.push(c[g]);return f},Ib:function(a){return"string"==typeof a&&(a=b.a.D(a))?x.JSON&&x.JSON.parse?x.JSON.parse(a):(new Function("return "+a))():p},xa:function(a,d,c){("undefined"==typeof JSON||"undefined"==typeof JSON.stringify)&&
j(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(b.a.d(a),d,c)},Jb:function(a,d,c){c=c||{};var e=c.params||{},f=c.includeFields||this.Na,g=a;if("object"==typeof a&&"form"===b.a.u(a))for(var g=a.action,h=f.length-1;0<=h;h--)for(var k=b.a.Oa(a,f[h]),l=k.length-1;0<=l;l--)e[k[l].name]=k[l].value;d=b.a.d(d);var n=y.createElement("form");
n.style.display="none";n.action=g;n.method="post";for(var w in d)a=y.createElement("input"),a.name=w,a.value=b.a.xa(b.a.d(d[w])),n.appendChild(a);for(w in e)a=y.createElement("input"),a.name=w,a.value=e[w],n.appendChild(a);y.body.appendChild(n);c.submitter?c.submitter(n):n.submit();setTimeout(function(){n.parentNode.removeChild(n)},0)}}};b.b("utils",b.a);b.b("utils.arrayForEach",b.a.o);b.b("utils.arrayFirst",b.a.lb);b.b("utils.arrayFilter",b.a.fa);b.b("utils.arrayGetDistinctValues",b.a.Ga);b.b("utils.arrayIndexOf",
b.a.i);b.b("utils.arrayMap",b.a.V);b.b("utils.arrayPushAll",b.a.P);b.b("utils.arrayRemoveItem",b.a.ga);b.b("utils.extend",b.a.extend);b.b("utils.fieldsIncludedWithJsonPost",b.a.Na);b.b("utils.getFormFields",b.a.Oa);b.b("utils.peekObservable",b.a.ua);b.b("utils.postJson",b.a.Jb);b.b("utils.parseJson",b.a.Ib);b.b("utils.registerEventHandler",b.a.n);b.b("utils.stringifyJson",b.a.xa);b.b("utils.range",b.a.Lb);b.b("utils.toggleDomNodeCssClass",b.a.da);b.b("utils.triggerEvent",b.a.Ba);b.b("utils.unwrapObservable",
b.a.d);Function.prototype.bind||(Function.prototype.bind=function(a){var b=this,c=Array.prototype.slice.call(arguments);a=c.shift();return function(){return b.apply(a,c.concat(Array.prototype.slice.call(arguments)))}});b.a.f=new function(){var a=0,d="__ko__"+(new Date).getTime(),c={};return{get:function(a,d){var c=b.a.f.la(a,r);return c===I?I:c[d]},set:function(a,d,c){c===I&&b.a.f.la(a,r)===I||(b.a.f.la(a,m)[d]=c)},la:function(b,f){var g=b[d];if(!g||!("null"!==g&&c[g])){if(!f)return I;g=b[d]="ko"+
a++;c[g]={}}return c[g]},clear:function(a){var b=a[d];return b?(delete c[b],a[d]=p,m):r}}};b.b("utils.domData",b.a.f);b.b("utils.domData.clear",b.a.f.clear);b.a.F=new function(){function a(a,d){var e=b.a.f.get(a,c);e===I&&d&&(e=[],b.a.f.set(a,c,e));return e}function d(c){var e=a(c,r);if(e)for(var e=e.slice(0),k=0;k<e.length;k++)e[k](c);b.a.f.clear(c);"function"==typeof F&&"function"==typeof F.cleanData&&F.cleanData([c]);if(f[c.nodeType])for(e=c.firstChild;c=e;)e=c.nextSibling,8===c.nodeType&&d(c)}
var c="__ko_domNodeDisposal__"+(new Date).getTime(),e={1:m,8:m,9:m},f={1:m,9:m};return{Ca:function(b,d){"function"!=typeof d&&j(Error("Callback must be a function"));a(b,m).push(d)},Xa:function(d,e){var f=a(d,r);f&&(b.a.ga(f,e),0==f.length&&b.a.f.set(d,c,I))},A:function(a){if(e[a.nodeType]&&(d(a),f[a.nodeType])){var c=[];b.a.P(c,a.getElementsByTagName("*"));for(var k=0,l=c.length;k<l;k++)d(c[k])}return a},removeNode:function(a){b.A(a);a.parentNode&&a.parentNode.removeChild(a)}}};b.A=b.a.F.A;b.removeNode=
b.a.F.removeNode;b.b("cleanNode",b.A);b.b("removeNode",b.removeNode);b.b("utils.domNodeDisposal",b.a.F);b.b("utils.domNodeDisposal.addDisposeCallback",b.a.F.Ca);b.b("utils.domNodeDisposal.removeDisposeCallback",b.a.F.Xa);b.a.ta=function(a){var d;if("undefined"!=typeof F)if(F.parseHTML)d=F.parseHTML(a);else{if((d=F.clean([a]))&&d[0]){for(a=d[0];a.parentNode&&11!==a.parentNode.nodeType;)a=a.parentNode;a.parentNode&&a.parentNode.removeChild(a)}}else{var c=b.a.D(a).toLowerCase();d=y.createElement("div");
c=c.match(/^<(thead|tbody|tfoot)/)&&[1,"<table>","</table>"]||!c.indexOf("<tr")&&[2,"<table><tbody>","</tbody></table>"]||(!c.indexOf("<td")||!c.indexOf("<th"))&&[3,"<table><tbody><tr>","</tr></tbody></table>"]||[0,"",""];a="ignored<div>"+c[1]+a+c[2]+"</div>";for("function"==typeof x.innerShiv?d.appendChild(x.innerShiv(a)):d.innerHTML=a;c[0]--;)d=d.lastChild;d=b.a.L(d.lastChild.childNodes)}return d};b.a.ca=function(a,d){b.a.ka(a);d=b.a.d(d);if(d!==p&&d!==I)if("string"!=typeof d&&(d=d.toString()),
"undefined"!=typeof F)F(a).html(d);else for(var c=b.a.ta(d),e=0;e<c.length;e++)a.appendChild(c[e])};b.b("utils.parseHtmlFragment",b.a.ta);b.b("utils.setHtml",b.a.ca);var R={};b.s={ra:function(a){"function"!=typeof a&&j(Error("You can only pass a function to ko.memoization.memoize()"));var b=(4294967296*(1+Math.random())|0).toString(16).substring(1)+(4294967296*(1+Math.random())|0).toString(16).substring(1);R[b]=a;return"\x3c!--[ko_memo:"+b+"]--\x3e"},hb:function(a,b){var c=R[a];c===I&&j(Error("Couldn't find any memo with ID "+
a+". Perhaps it's already been unmemoized."));try{return c.apply(p,b||[]),m}finally{delete R[a]}},ib:function(a,d){var c=[];ca(a,c);for(var e=0,f=c.length;e<f;e++){var g=c[e].sb,h=[g];d&&b.a.P(h,d);b.s.hb(c[e].Fb,h);g.nodeValue="";g.parentNode&&g.parentNode.removeChild(g)}},Ua:function(a){return(a=a.match(/^\[ko_memo\:(.*?)\]$/))?a[1]:p}};b.b("memoization",b.s);b.b("memoization.memoize",b.s.ra);b.b("memoization.unmemoize",b.s.hb);b.b("memoization.parseMemoText",b.s.Ua);b.b("memoization.unmemoizeDomNodeAndDescendants",
b.s.ib);b.Ma={throttle:function(a,d){a.throttleEvaluation=d;var c=p;return b.j({read:a,write:function(b){clearTimeout(c);c=setTimeout(function(){a(b)},d)}})},notify:function(a,d){a.equalityComparer="always"==d?u(r):b.m.fn.equalityComparer;return a}};b.b("extenders",b.Ma);b.fb=function(a,d,c){this.target=a;this.ha=d;this.rb=c;b.p(this,"dispose",this.B)};b.fb.prototype.B=function(){this.Cb=m;this.rb()};b.S=function(){this.w={};b.a.extend(this,b.S.fn);b.p(this,"subscribe",this.ya);b.p(this,"extend",
this.extend);b.p(this,"getSubscriptionsCount",this.yb)};b.S.fn={ya:function(a,d,c){c=c||"change";var e=new b.fb(this,d?a.bind(d):a,function(){b.a.ga(this.w[c],e)}.bind(this));this.w[c]||(this.w[c]=[]);this.w[c].push(e);return e},notifySubscribers:function(a,d){d=d||"change";this.w[d]&&b.r.K(function(){b.a.o(this.w[d].slice(0),function(b){b&&b.Cb!==m&&b.ha(a)})},this)},yb:function(){var a=0,b;for(b in this.w)this.w.hasOwnProperty(b)&&(a+=this.w[b].length);return a},extend:function(a){var d=this;if(a)for(var c in a){var e=
b.Ma[c];"function"==typeof e&&(d=e(d,a[c]))}return d}};b.Qa=function(a){return"function"==typeof a.ya&&"function"==typeof a.notifySubscribers};b.b("subscribable",b.S);b.b("isSubscribable",b.Qa);var C=[];b.r={mb:function(a){C.push({ha:a,La:[]})},end:function(){C.pop()},Wa:function(a){b.Qa(a)||j(Error("Only subscribable things can act as dependencies"));if(0<C.length){var d=C[C.length-1];d&&!(0<=b.a.i(d.La,a))&&(d.La.push(a),d.ha(a))}},K:function(a,b,c){try{return C.push(p),a.apply(b,c||[])}finally{C.pop()}}};
var ma={undefined:m,"boolean":m,number:m,string:m};b.m=function(a){function d(){if(0<arguments.length){if(!d.equalityComparer||!d.equalityComparer(c,arguments[0]))d.H(),c=arguments[0],d.G();return this}b.r.Wa(d);return c}var c=a;b.S.call(d);d.t=function(){return c};d.G=function(){d.notifySubscribers(c)};d.H=function(){d.notifySubscribers(c,"beforeChange")};b.a.extend(d,b.m.fn);b.p(d,"peek",d.t);b.p(d,"valueHasMutated",d.G);b.p(d,"valueWillMutate",d.H);return d};b.m.fn={equalityComparer:function(a,
b){return a===p||typeof a in ma?a===b:r}};var E=b.m.Kb="__ko_proto__";b.m.fn[E]=b.m;b.ma=function(a,d){return a===p||a===I||a[E]===I?r:a[E]===d?m:b.ma(a[E],d)};b.$=function(a){return b.ma(a,b.m)};b.Ra=function(a){return"function"==typeof a&&a[E]===b.m||"function"==typeof a&&a[E]===b.j&&a.zb?m:r};b.b("observable",b.m);b.b("isObservable",b.$);b.b("isWriteableObservable",b.Ra);b.R=function(a){0==arguments.length&&(a=[]);a!==p&&(a!==I&&!("length"in a))&&j(Error("The argument passed when initializing an observable array must be an array, or null, or undefined."));
var d=b.m(a);b.a.extend(d,b.R.fn);return d};b.R.fn={remove:function(a){for(var b=this.t(),c=[],e="function"==typeof a?a:function(b){return b===a},f=0;f<b.length;f++){var g=b[f];e(g)&&(0===c.length&&this.H(),c.push(g),b.splice(f,1),f--)}c.length&&this.G();return c},removeAll:function(a){if(a===I){var d=this.t(),c=d.slice(0);this.H();d.splice(0,d.length);this.G();return c}return!a?[]:this.remove(function(d){return 0<=b.a.i(a,d)})},destroy:function(a){var b=this.t(),c="function"==typeof a?a:function(b){return b===
a};this.H();for(var e=b.length-1;0<=e;e--)c(b[e])&&(b[e]._destroy=m);this.G()},destroyAll:function(a){return a===I?this.destroy(u(m)):!a?[]:this.destroy(function(d){return 0<=b.a.i(a,d)})},indexOf:function(a){var d=this();return b.a.i(d,a)},replace:function(a,b){var c=this.indexOf(a);0<=c&&(this.H(),this.t()[c]=b,this.G())}};b.a.o("pop push reverse shift sort splice unshift".split(" "),function(a){b.R.fn[a]=function(){var b=this.t();this.H();b=b[a].apply(b,arguments);this.G();return b}});b.a.o(["slice"],
function(a){b.R.fn[a]=function(){var b=this();return b[a].apply(b,arguments)}});b.b("observableArray",b.R);b.j=function(a,d,c){function e(){b.a.o(z,function(a){a.B()});z=[]}function f(){var a=h.throttleEvaluation;a&&0<=a?(clearTimeout(t),t=setTimeout(g,a)):g()}function g(){if(!q)if(n&&w())A();else{q=m;try{var a=b.a.V(z,function(a){return a.target});b.r.mb(function(c){var d;0<=(d=b.a.i(a,c))?a[d]=I:z.push(c.ya(f))});for(var c=s.call(d),e=a.length-1;0<=e;e--)a[e]&&z.splice(e,1)[0].B();n=m;h.notifySubscribers(l,
"beforeChange");l=c}finally{b.r.end()}h.notifySubscribers(l);q=r;z.length||A()}}function h(){if(0<arguments.length)return"function"===typeof v?v.apply(d,arguments):j(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.")),this;n||g();b.r.Wa(h);return l}function k(){return!n||0<z.length}var l,n=r,q=r,s=a;s&&"object"==typeof s?(c=s,s=c.read):(c=c||{},s||(s=c.read));"function"!=typeof s&&j(Error("Pass a function that returns the value of the ko.computed"));
var v=c.write,G=c.disposeWhenNodeIsRemoved||c.W||p,w=c.disposeWhen||c.Ka||u(r),A=e,z=[],t=p;d||(d=c.owner);h.t=function(){n||g();return l};h.xb=function(){return z.length};h.zb="function"===typeof c.write;h.B=function(){A()};h.pa=k;b.S.call(h);b.a.extend(h,b.j.fn);b.p(h,"peek",h.t);b.p(h,"dispose",h.B);b.p(h,"isActive",h.pa);b.p(h,"getDependenciesCount",h.xb);c.deferEvaluation!==m&&g();if(G&&k()){A=function(){b.a.F.Xa(G,arguments.callee);e()};b.a.F.Ca(G,A);var D=w,w=function(){return!b.a.X(G)||D()}}return h};
b.Bb=function(a){return b.ma(a,b.j)};w=b.m.Kb;b.j[w]=b.m;b.j.fn={};b.j.fn[w]=b.j;b.b("dependentObservable",b.j);b.b("computed",b.j);b.b("isComputed",b.Bb);b.gb=function(a){0==arguments.length&&j(Error("When calling ko.toJS, pass the object you want to convert."));return ba(a,function(a){for(var c=0;b.$(a)&&10>c;c++)a=a();return a})};b.toJSON=function(a,d,c){a=b.gb(a);return b.a.xa(a,d,c)};b.b("toJS",b.gb);b.b("toJSON",b.toJSON);b.k={q:function(a){switch(b.a.u(a)){case "option":return a.__ko__hasDomDataOptionValue__===
m?b.a.f.get(a,b.c.options.sa):7>=b.a.Z?a.getAttributeNode("value").specified?a.value:a.text:a.value;case "select":return 0<=a.selectedIndex?b.k.q(a.options[a.selectedIndex]):I;default:return a.value}},T:function(a,d){switch(b.a.u(a)){case "option":switch(typeof d){case "string":b.a.f.set(a,b.c.options.sa,I);"__ko__hasDomDataOptionValue__"in a&&delete a.__ko__hasDomDataOptionValue__;a.value=d;break;default:b.a.f.set(a,b.c.options.sa,d),a.__ko__hasDomDataOptionValue__=m,a.value="number"===typeof d?
d:""}break;case "select":for(var c=a.options.length-1;0<=c;c--)if(b.k.q(a.options[c])==d){a.selectedIndex=c;break}break;default:if(d===p||d===I)d="";a.value=d}}};b.b("selectExtensions",b.k);b.b("selectExtensions.readValue",b.k.q);b.b("selectExtensions.writeValue",b.k.T);var ka=/\@ko_token_(\d+)\@/g,na=["true","false"],oa=/^(?:[$_a-z][$\w]*|(.+)(\.\s*[$_a-z][$\w]*|\[.+\]))$/i;b.g={Q:[],aa:function(a){var d=b.a.D(a);if(3>d.length)return[];"{"===d.charAt(0)&&(d=d.substring(1,d.length-1));a=[];for(var c=
p,e,f=0;f<d.length;f++){var g=d.charAt(f);if(c===p)switch(g){case '"':case "'":case "/":c=f,e=g}else if(g==e&&"\\"!==d.charAt(f-1)){g=d.substring(c,f+1);a.push(g);var h="@ko_token_"+(a.length-1)+"@",d=d.substring(0,c)+h+d.substring(f+1),f=f-(g.length-h.length),c=p}}e=c=p;for(var k=0,l=p,f=0;f<d.length;f++){g=d.charAt(f);if(c===p)switch(g){case "{":c=f;l=g;e="}";break;case "(":c=f;l=g;e=")";break;case "[":c=f,l=g,e="]"}g===l?k++:g===e&&(k--,0===k&&(g=d.substring(c,f+1),a.push(g),h="@ko_token_"+(a.length-
1)+"@",d=d.substring(0,c)+h+d.substring(f+1),f-=g.length-h.length,c=p))}e=[];d=d.split(",");c=0;for(f=d.length;c<f;c++)k=d[c],l=k.indexOf(":"),0<l&&l<k.length-1?(g=k.substring(l+1),e.push({key:P(k.substring(0,l),a),value:P(g,a)})):e.push({unknown:P(k,a)});return e},ba:function(a){var d="string"===typeof a?b.g.aa(a):a,c=[];a=[];for(var e,f=0;e=d[f];f++)if(0<c.length&&c.push(","),e.key){var g;a:{g=e.key;var h=b.a.D(g);switch(h.length&&h.charAt(0)){case "'":case '"':break a;default:g="'"+h+"'"}}e=e.value;
c.push(g);c.push(":");c.push(e);e=b.a.D(e);0<=b.a.i(na,b.a.D(e).toLowerCase())?e=r:(h=e.match(oa),e=h===p?r:h[1]?"Object("+h[1]+")"+h[2]:e);e&&(0<a.length&&a.push(", "),a.push(g+" : function(__ko_value) { "+e+" = __ko_value; }"))}else e.unknown&&c.push(e.unknown);d=c.join("");0<a.length&&(d=d+", '_ko_property_writers' : { "+a.join("")+" } ");return d},Eb:function(a,d){for(var c=0;c<a.length;c++)if(b.a.D(a[c].key)==d)return m;return r},ea:function(a,d,c,e,f){if(!a||!b.Ra(a)){if((a=d()._ko_property_writers)&&
a[c])a[c](e)}else(!f||a.t()!==e)&&a(e)}};b.b("expressionRewriting",b.g);b.b("expressionRewriting.bindingRewriteValidators",b.g.Q);b.b("expressionRewriting.parseObjectLiteral",b.g.aa);b.b("expressionRewriting.preProcessBindings",b.g.ba);b.b("jsonExpressionRewriting",b.g);b.b("jsonExpressionRewriting.insertPropertyAccessorsIntoJson",b.g.ba);var K="\x3c!--test--\x3e"===y.createComment("test").text,ja=K?/^\x3c!--\s*ko(?:\s+(.+\s*\:[\s\S]*))?\s*--\x3e$/:/^\s*ko(?:\s+(.+\s*\:[\s\S]*))?\s*$/,ia=K?/^\x3c!--\s*\/ko\s*--\x3e$/:
/^\s*\/ko\s*$/,pa={ul:m,ol:m};b.e={I:{},childNodes:function(a){return B(a)?aa(a):a.childNodes},Y:function(a){if(B(a)){a=b.e.childNodes(a);for(var d=0,c=a.length;d<c;d++)b.removeNode(a[d])}else b.a.ka(a)},N:function(a,d){if(B(a)){b.e.Y(a);for(var c=a.nextSibling,e=0,f=d.length;e<f;e++)c.parentNode.insertBefore(d[e],c)}else b.a.N(a,d)},Va:function(a,b){B(a)?a.parentNode.insertBefore(b,a.nextSibling):a.firstChild?a.insertBefore(b,a.firstChild):a.appendChild(b)},Pa:function(a,d,c){c?B(a)?a.parentNode.insertBefore(d,
c.nextSibling):c.nextSibling?a.insertBefore(d,c.nextSibling):a.appendChild(d):b.e.Va(a,d)},firstChild:function(a){return!B(a)?a.firstChild:!a.nextSibling||H(a.nextSibling)?p:a.nextSibling},nextSibling:function(a){B(a)&&(a=$(a));return a.nextSibling&&H(a.nextSibling)?p:a.nextSibling},jb:function(a){return(a=B(a))?a[1]:p},Ta:function(a){if(pa[b.a.u(a)]){var d=a.firstChild;if(d){do if(1===d.nodeType){var c;c=d.firstChild;var e=p;if(c){do if(e)e.push(c);else if(B(c)){var f=$(c,m);f?c=f:e=[c]}else H(c)&&
(e=[c]);while(c=c.nextSibling)}if(c=e){e=d.nextSibling;for(f=0;f<c.length;f++)e?a.insertBefore(c[f],e):a.appendChild(c[f])}}while(d=d.nextSibling)}}}};b.b("virtualElements",b.e);b.b("virtualElements.allowedBindings",b.e.I);b.b("virtualElements.emptyNode",b.e.Y);b.b("virtualElements.insertAfter",b.e.Pa);b.b("virtualElements.prepend",b.e.Va);b.b("virtualElements.setDomNodeChildren",b.e.N);b.J=function(){this.Ha={}};b.a.extend(b.J.prototype,{nodeHasBindings:function(a){switch(a.nodeType){case 1:return a.getAttribute("data-bind")!=
p;case 8:return b.e.jb(a)!=p;default:return r}},getBindings:function(a,b){var c=this.getBindingsString(a,b);return c?this.parseBindingsString(c,b,a):p},getBindingsString:function(a){switch(a.nodeType){case 1:return a.getAttribute("data-bind");case 8:return b.e.jb(a);default:return p}},parseBindingsString:function(a,d,c){try{var e;if(!(e=this.Ha[a])){var f=this.Ha,g,h="with($context){with($data||{}){return{"+b.g.ba(a)+"}}}";g=new Function("$context","$element",h);e=f[a]=g}return e(d,c)}catch(k){j(Error("Unable to parse bindings.\nMessage: "+
k+";\nBindings value: "+a))}}});b.J.instance=new b.J;b.b("bindingProvider",b.J);b.c={};b.z=function(a,d,c){d?(b.a.extend(this,d),this.$parentContext=d,this.$parent=d.$data,this.$parents=(d.$parents||[]).slice(0),this.$parents.unshift(this.$parent)):(this.$parents=[],this.$root=a,this.ko=b);this.$data=a;c&&(this[c]=a)};b.z.prototype.createChildContext=function(a,d){return new b.z(a,this,d)};b.z.prototype.extend=function(a){var d=b.a.extend(new b.z,this);return b.a.extend(d,a)};b.eb=function(a,d){if(2==
arguments.length)b.a.f.set(a,"__ko_bindingContext__",d);else return b.a.f.get(a,"__ko_bindingContext__")};b.Fa=function(a,d,c){1===a.nodeType&&b.e.Ta(a);return X(a,d,c,m)};b.Ea=function(a,b){(1===b.nodeType||8===b.nodeType)&&Z(a,b,m)};b.Da=function(a,b){b&&(1!==b.nodeType&&8!==b.nodeType)&&j(Error("ko.applyBindings: first parameter should be your view model; second parameter should be a DOM node"));b=b||x.document.body;Y(a,b,m)};b.ja=function(a){switch(a.nodeType){case 1:case 8:var d=b.eb(a);if(d)return d;
if(a.parentNode)return b.ja(a.parentNode)}return I};b.pb=function(a){return(a=b.ja(a))?a.$data:I};b.b("bindingHandlers",b.c);b.b("applyBindings",b.Da);b.b("applyBindingsToDescendants",b.Ea);b.b("applyBindingsToNode",b.Fa);b.b("contextFor",b.ja);b.b("dataFor",b.pb);var fa={"class":"className","for":"htmlFor"};b.c.attr={update:function(a,d){var c=b.a.d(d())||{},e;for(e in c)if("string"==typeof e){var f=b.a.d(c[e]),g=f===r||f===p||f===I;g&&a.removeAttribute(e);8>=b.a.Z&&e in fa?(e=fa[e],g?a.removeAttribute(e):
a[e]=f):g||a.setAttribute(e,f.toString());"name"===e&&b.a.ab(a,g?"":f.toString())}}};b.c.checked={init:function(a,d,c){b.a.n(a,"click",function(){var e;if("checkbox"==a.type)e=a.checked;else if("radio"==a.type&&a.checked)e=a.value;else return;var f=d(),g=b.a.d(f);"checkbox"==a.type&&g instanceof Array?(e=b.a.i(g,a.value),a.checked&&0>e?f.push(a.value):!a.checked&&0<=e&&f.splice(e,1)):b.g.ea(f,c,"checked",e,m)});"radio"==a.type&&!a.name&&b.c.uniqueName.init(a,u(m))},update:function(a,d){var c=b.a.d(d());
"checkbox"==a.type?a.checked=c instanceof Array?0<=b.a.i(c,a.value):c:"radio"==a.type&&(a.checked=a.value==c)}};b.c.css={update:function(a,d){var c=b.a.d(d());if("object"==typeof c)for(var e in c){var f=b.a.d(c[e]);b.a.da(a,e,f)}else c=String(c||""),b.a.da(a,a.__ko__cssValue,r),a.__ko__cssValue=c,b.a.da(a,c,m)}};b.c.enable={update:function(a,d){var c=b.a.d(d());c&&a.disabled?a.removeAttribute("disabled"):!c&&!a.disabled&&(a.disabled=m)}};b.c.disable={update:function(a,d){b.c.enable.update(a,function(){return!b.a.d(d())})}};
b.c.event={init:function(a,d,c,e){var f=d()||{},g;for(g in f)(function(){var f=g;"string"==typeof f&&b.a.n(a,f,function(a){var g,n=d()[f];if(n){var q=c();try{var s=b.a.L(arguments);s.unshift(e);g=n.apply(e,s)}finally{g!==m&&(a.preventDefault?a.preventDefault():a.returnValue=r)}q[f+"Bubble"]===r&&(a.cancelBubble=m,a.stopPropagation&&a.stopPropagation())}})})()}};b.c.foreach={Sa:function(a){return function(){var d=a(),c=b.a.ua(d);if(!c||"number"==typeof c.length)return{foreach:d,templateEngine:b.C.oa};
b.a.d(d);return{foreach:c.data,as:c.as,includeDestroyed:c.includeDestroyed,afterAdd:c.afterAdd,beforeRemove:c.beforeRemove,afterRender:c.afterRender,beforeMove:c.beforeMove,afterMove:c.afterMove,templateEngine:b.C.oa}}},init:function(a,d){return b.c.template.init(a,b.c.foreach.Sa(d))},update:function(a,d,c,e,f){return b.c.template.update(a,b.c.foreach.Sa(d),c,e,f)}};b.g.Q.foreach=r;b.e.I.foreach=m;b.c.hasfocus={init:function(a,d,c){function e(e){a.__ko_hasfocusUpdating=m;var f=a.ownerDocument;"activeElement"in
f&&(e=f.activeElement===a);f=d();b.g.ea(f,c,"hasfocus",e,m);a.__ko_hasfocusUpdating=r}var f=e.bind(p,m),g=e.bind(p,r);b.a.n(a,"focus",f);b.a.n(a,"focusin",f);b.a.n(a,"blur",g);b.a.n(a,"focusout",g)},update:function(a,d){var c=b.a.d(d());a.__ko_hasfocusUpdating||(c?a.focus():a.blur(),b.r.K(b.a.Ba,p,[a,c?"focusin":"focusout"]))}};b.c.html={init:function(){return{controlsDescendantBindings:m}},update:function(a,d){b.a.ca(a,d())}};var da="__ko_withIfBindingData";Q("if");Q("ifnot",r,m);Q("with",m,r,function(a,
b){return a.createChildContext(b)});b.c.options={update:function(a,d,c){"select"!==b.a.u(a)&&j(Error("options binding applies only to SELECT elements"));for(var e=0==a.length,f=b.a.V(b.a.fa(a.childNodes,function(a){return a.tagName&&"option"===b.a.u(a)&&a.selected}),function(a){return b.k.q(a)||a.innerText||a.textContent}),g=a.scrollTop,h=b.a.d(d());0<a.length;)b.A(a.options[0]),a.remove(0);if(h){c=c();var k=c.optionsIncludeDestroyed;"number"!=typeof h.length&&(h=[h]);if(c.optionsCaption){var l=y.createElement("option");
b.a.ca(l,c.optionsCaption);b.k.T(l,I);a.appendChild(l)}d=0;for(var n=h.length;d<n;d++){var q=h[d];if(!q||!q._destroy||k){var l=y.createElement("option"),s=function(a,b,c){var d=typeof b;return"function"==d?b(a):"string"==d?a[b]:c},v=s(q,c.optionsValue,q);b.k.T(l,b.a.d(v));q=s(q,c.optionsText,v);b.a.cb(l,q);a.appendChild(l)}}h=a.getElementsByTagName("option");d=k=0;for(n=h.length;d<n;d++)0<=b.a.i(f,b.k.q(h[d]))&&(b.a.bb(h[d],m),k++);a.scrollTop=g;e&&"value"in c&&ea(a,b.a.ua(c.value),m);b.a.ub(a)}}};
b.c.options.sa="__ko.optionValueDomData__";b.c.selectedOptions={init:function(a,d,c){b.a.n(a,"change",function(){var e=d(),f=[];b.a.o(a.getElementsByTagName("option"),function(a){a.selected&&f.push(b.k.q(a))});b.g.ea(e,c,"value",f)})},update:function(a,d){"select"!=b.a.u(a)&&j(Error("values binding applies only to SELECT elements"));var c=b.a.d(d());c&&"number"==typeof c.length&&b.a.o(a.getElementsByTagName("option"),function(a){var d=0<=b.a.i(c,b.k.q(a));b.a.bb(a,d)})}};b.c.style={update:function(a,
d){var c=b.a.d(d()||{}),e;for(e in c)if("string"==typeof e){var f=b.a.d(c[e]);a.style[e]=f||""}}};b.c.submit={init:function(a,d,c,e){"function"!=typeof d()&&j(Error("The value for a submit binding must be a function"));b.a.n(a,"submit",function(b){var c,h=d();try{c=h.call(e,a)}finally{c!==m&&(b.preventDefault?b.preventDefault():b.returnValue=r)}})}};b.c.text={update:function(a,d){b.a.cb(a,d())}};b.e.I.text=m;b.c.uniqueName={init:function(a,d){if(d()){var c="ko_unique_"+ ++b.c.uniqueName.ob;b.a.ab(a,
c)}}};b.c.uniqueName.ob=0;b.c.value={init:function(a,d,c){function e(){h=r;var e=d(),f=b.k.q(a);b.g.ea(e,c,"value",f)}var f=["change"],g=c().valueUpdate,h=r;g&&("string"==typeof g&&(g=[g]),b.a.P(f,g),f=b.a.Ga(f));if(b.a.Z&&("input"==a.tagName.toLowerCase()&&"text"==a.type&&"off"!=a.autocomplete&&(!a.form||"off"!=a.form.autocomplete))&&-1==b.a.i(f,"propertychange"))b.a.n(a,"propertychange",function(){h=m}),b.a.n(a,"blur",function(){h&&e()});b.a.o(f,function(c){var d=e;b.a.Ob(c,"after")&&(d=function(){setTimeout(e,
0)},c=c.substring(5));b.a.n(a,c,d)})},update:function(a,d){var c="select"===b.a.u(a),e=b.a.d(d()),f=b.k.q(a),g=e!=f;0===e&&(0!==f&&"0"!==f)&&(g=m);g&&(f=function(){b.k.T(a,e)},f(),c&&setTimeout(f,0));c&&0<a.length&&ea(a,e,r)}};b.c.visible={update:function(a,d){var c=b.a.d(d()),e="none"!=a.style.display;c&&!e?a.style.display="":!c&&e&&(a.style.display="none")}};b.c.click={init:function(a,d,c,e){return b.c.event.init.call(this,a,function(){var a={};a.click=d();return a},c,e)}};b.v=function(){};b.v.prototype.renderTemplateSource=
function(){j(Error("Override renderTemplateSource"))};b.v.prototype.createJavaScriptEvaluatorBlock=function(){j(Error("Override createJavaScriptEvaluatorBlock"))};b.v.prototype.makeTemplateSource=function(a,d){if("string"==typeof a){d=d||y;var c=d.getElementById(a);c||j(Error("Cannot find template with ID "+a));return new b.l.h(c)}if(1==a.nodeType||8==a.nodeType)return new b.l.O(a);j(Error("Unknown template type: "+a))};b.v.prototype.renderTemplate=function(a,b,c,e){a=this.makeTemplateSource(a,e);
return this.renderTemplateSource(a,b,c)};b.v.prototype.isTemplateRewritten=function(a,b){return this.allowTemplateRewriting===r?m:this.makeTemplateSource(a,b).data("isRewritten")};b.v.prototype.rewriteTemplate=function(a,b,c){a=this.makeTemplateSource(a,c);b=b(a.text());a.text(b);a.data("isRewritten",m)};b.b("templateEngine",b.v);var qa=/(<[a-z]+\d*(\s+(?!data-bind=)[a-z0-9\-]+(=(\"[^\"]*\"|\'[^\']*\'))?)*\s+)data-bind=(["'])([\s\S]*?)\5/gi,ra=/\x3c!--\s*ko\b\s*([\s\S]*?)\s*--\x3e/g;b.za={vb:function(a,
d,c){d.isTemplateRewritten(a,c)||d.rewriteTemplate(a,function(a){return b.za.Gb(a,d)},c)},Gb:function(a,b){return a.replace(qa,function(a,e,f,g,h,k,l){return W(l,e,b)}).replace(ra,function(a,e){return W(e,"\x3c!-- ko --\x3e",b)})},kb:function(a){return b.s.ra(function(d,c){d.nextSibling&&b.Fa(d.nextSibling,a,c)})}};b.b("__tr_ambtns",b.za.kb);b.l={};b.l.h=function(a){this.h=a};b.l.h.prototype.text=function(){var a=b.a.u(this.h),a="script"===a?"text":"textarea"===a?"value":"innerHTML";if(0==arguments.length)return this.h[a];
var d=arguments[0];"innerHTML"===a?b.a.ca(this.h,d):this.h[a]=d};b.l.h.prototype.data=function(a){if(1===arguments.length)return b.a.f.get(this.h,"templateSourceData_"+a);b.a.f.set(this.h,"templateSourceData_"+a,arguments[1])};b.l.O=function(a){this.h=a};b.l.O.prototype=new b.l.h;b.l.O.prototype.text=function(){if(0==arguments.length){var a=b.a.f.get(this.h,"__ko_anon_template__")||{};a.Aa===I&&a.ia&&(a.Aa=a.ia.innerHTML);return a.Aa}b.a.f.set(this.h,"__ko_anon_template__",{Aa:arguments[0]})};b.l.h.prototype.nodes=
function(){if(0==arguments.length)return(b.a.f.get(this.h,"__ko_anon_template__")||{}).ia;b.a.f.set(this.h,"__ko_anon_template__",{ia:arguments[0]})};b.b("templateSources",b.l);b.b("templateSources.domElement",b.l.h);b.b("templateSources.anonymousTemplate",b.l.O);var O;b.wa=function(a){a!=I&&!(a instanceof b.v)&&j(Error("templateEngine must inherit from ko.templateEngine"));O=a};b.va=function(a,d,c,e,f){c=c||{};(c.templateEngine||O)==I&&j(Error("Set a template engine before calling renderTemplate"));
f=f||"replaceChildren";if(e){var g=N(e);return b.j(function(){var h=d&&d instanceof b.z?d:new b.z(b.a.d(d)),k="function"==typeof a?a(h.$data,h):a,h=T(e,f,k,h,c);"replaceNode"==f&&(e=h,g=N(e))},p,{Ka:function(){return!g||!b.a.X(g)},W:g&&"replaceNode"==f?g.parentNode:g})}return b.s.ra(function(e){b.va(a,d,c,e,"replaceNode")})};b.Mb=function(a,d,c,e,f){function g(a,b){U(b,k);c.afterRender&&c.afterRender(b,a)}function h(d,e){k=f.createChildContext(b.a.d(d),c.as);k.$index=e;var g="function"==typeof a?
a(d,k):a;return T(p,"ignoreTargetNode",g,k,c)}var k;return b.j(function(){var a=b.a.d(d)||[];"undefined"==typeof a.length&&(a=[a]);a=b.a.fa(a,function(a){return c.includeDestroyed||a===I||a===p||!b.a.d(a._destroy)});b.r.K(b.a.$a,p,[e,a,h,c,g])},p,{W:e})};b.c.template={init:function(a,d){var c=b.a.d(d());if("string"!=typeof c&&!c.name&&(1==a.nodeType||8==a.nodeType))c=1==a.nodeType?a.childNodes:b.e.childNodes(a),c=b.a.Hb(c),(new b.l.O(a)).nodes(c);return{controlsDescendantBindings:m}},update:function(a,
d,c,e,f){d=b.a.d(d());c={};e=m;var g,h=p;"string"!=typeof d&&(c=d,d=c.name,"if"in c&&(e=b.a.d(c["if"])),e&&"ifnot"in c&&(e=!b.a.d(c.ifnot)),g=b.a.d(c.data));"foreach"in c?h=b.Mb(d||a,e&&c.foreach||[],c,a,f):e?(f="data"in c?f.createChildContext(g,c.as):f,h=b.va(d||a,f,c,a)):b.e.Y(a);f=h;(g=b.a.f.get(a,"__ko__templateComputedDomDataKey__"))&&"function"==typeof g.B&&g.B();b.a.f.set(a,"__ko__templateComputedDomDataKey__",f&&f.pa()?f:I)}};b.g.Q.template=function(a){a=b.g.aa(a);return 1==a.length&&a[0].unknown||
b.g.Eb(a,"name")?p:"This template engine does not support anonymous templates nested within its templates"};b.e.I.template=m;b.b("setTemplateEngine",b.wa);b.b("renderTemplate",b.va);b.a.Ja=function(a,b,c){a=a||[];b=b||[];return a.length<=b.length?S(a,b,"added","deleted",c):S(b,a,"deleted","added",c)};b.b("utils.compareArrays",b.a.Ja);b.a.$a=function(a,d,c,e,f){function g(a,b){t=l[b];w!==b&&(z[a]=t);t.na(w++);M(t.M);s.push(t);A.push(t)}function h(a,c){if(a)for(var d=0,e=c.length;d<e;d++)c[d]&&b.a.o(c[d].M,
function(b){a(b,d,c[d].U)})}d=d||[];e=e||{};var k=b.a.f.get(a,"setDomNodeChildrenFromArrayMapping_lastMappingResult")===I,l=b.a.f.get(a,"setDomNodeChildrenFromArrayMapping_lastMappingResult")||[],n=b.a.V(l,function(a){return a.U}),q=b.a.Ja(n,d),s=[],v=0,w=0,B=[],A=[];d=[];for(var z=[],n=[],t,D=0,C,E;C=q[D];D++)switch(E=C.moved,C.status){case "deleted":E===I&&(t=l[v],t.j&&t.j.B(),B.push.apply(B,M(t.M)),e.beforeRemove&&(d[D]=t,A.push(t)));v++;break;case "retained":g(D,v++);break;case "added":E!==I?
g(D,E):(t={U:C.value,na:b.m(w++)},s.push(t),A.push(t),k||(n[D]=t))}h(e.beforeMove,z);b.a.o(B,e.beforeRemove?b.A:b.removeNode);for(var D=0,k=b.e.firstChild(a),H;t=A[D];D++){t.M||b.a.extend(t,ha(a,c,t.U,f,t.na));for(v=0;q=t.M[v];k=q.nextSibling,H=q,v++)q!==k&&b.e.Pa(a,q,H);!t.Ab&&f&&(f(t.U,t.M,t.na),t.Ab=m)}h(e.beforeRemove,d);h(e.afterMove,z);h(e.afterAdd,n);b.a.f.set(a,"setDomNodeChildrenFromArrayMapping_lastMappingResult",s)};b.b("utils.setDomNodeChildrenFromArrayMapping",b.a.$a);b.C=function(){this.allowTemplateRewriting=
r};b.C.prototype=new b.v;b.C.prototype.renderTemplateSource=function(a){var d=!(9>b.a.Z)&&a.nodes?a.nodes():p;if(d)return b.a.L(d.cloneNode(m).childNodes);a=a.text();return b.a.ta(a)};b.C.oa=new b.C;b.wa(b.C.oa);b.b("nativeTemplateEngine",b.C);b.qa=function(){var a=this.Db=function(){if("undefined"==typeof F||!F.tmpl)return 0;try{if(0<=F.tmpl.tag.tmpl.open.toString().indexOf("__"))return 2}catch(a){}return 1}();this.renderTemplateSource=function(b,c,e){e=e||{};2>a&&j(Error("Your version of jQuery.tmpl is too old. Please upgrade to jQuery.tmpl 1.0.0pre or later."));
var f=b.data("precompiled");f||(f=b.text()||"",f=F.template(p,"{{ko_with $item.koBindingContext}}"+f+"{{/ko_with}}"),b.data("precompiled",f));b=[c.$data];c=F.extend({koBindingContext:c},e.templateOptions);c=F.tmpl(f,b,c);c.appendTo(y.createElement("div"));F.fragments={};return c};this.createJavaScriptEvaluatorBlock=function(a){return"{{ko_code ((function() { return "+a+" })()) }}"};this.addTemplate=function(a,b){y.write("<script type='text/html' id='"+a+"'>"+b+"\x3c/script>")};0<a&&(F.tmpl.tag.ko_code=
{open:"__.push($1 || '');"},F.tmpl.tag.ko_with={open:"with($1) {",close:"} "})};b.qa.prototype=new b.v;w=new b.qa;0<w.Db&&b.wa(w);b.b("jqueryTmplTemplateEngine",b.qa)}"function"===typeof require&&"object"===typeof exports&&"object"===typeof module?L(module.exports||exports):"function"===typeof define&&define.amd?define(["exports"],L):L(x.ko={});m;
})();
/*
RequireJS 2.1.2 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved.
Available via the MIT or new BSD license.
see: http://github.com/jrburke/requirejs for details
*/
var requirejs,require,define;
(function(Y){function H(b){return"[object Function]"===L.call(b)}function I(b){return"[object Array]"===L.call(b)}function x(b,c){if(b){var d;for(d=0;d<b.length&&(!b[d]||!c(b[d],d,b));d+=1);}}function M(b,c){if(b){var d;for(d=b.length-1;-1<d&&(!b[d]||!c(b[d],d,b));d-=1);}}function r(b,c){return da.call(b,c)}function i(b,c){return r(b,c)&&b[c]}function E(b,c){for(var d in b)if(r(b,d)&&c(b[d],d))break}function Q(b,c,d,i){c&&E(c,function(c,h){if(d||!r(b,h))i&&"string"!==typeof c?(b[h]||(b[h]={}),Q(b[h],
c,d,i)):b[h]=c});return b}function t(b,c){return function(){return c.apply(b,arguments)}}function Z(b){if(!b)return b;var c=Y;x(b.split("."),function(b){c=c[b]});return c}function J(b,c,d,i){c=Error(c+"\nhttp://requirejs.org/docs/errors.html#"+b);c.requireType=b;c.requireModules=i;d&&(c.originalError=d);return c}function ea(b){function c(a,g,v){var e,n,b,c,d,j,f,h=g&&g.split("/");e=h;var l=m.map,k=l&&l["*"];if(a&&"."===a.charAt(0))if(g){e=i(m.pkgs,g)?h=[g]:h.slice(0,h.length-1);g=a=e.concat(a.split("/"));
for(e=0;g[e];e+=1)if(n=g[e],"."===n)g.splice(e,1),e-=1;else if(".."===n)if(1===e&&(".."===g[2]||".."===g[0]))break;else 0<e&&(g.splice(e-1,2),e-=2);e=i(m.pkgs,g=a[0]);a=a.join("/");e&&a===g+"/"+e.main&&(a=g)}else 0===a.indexOf("./")&&(a=a.substring(2));if(v&&(h||k)&&l){g=a.split("/");for(e=g.length;0<e;e-=1){b=g.slice(0,e).join("/");if(h)for(n=h.length;0<n;n-=1)if(v=i(l,h.slice(0,n).join("/")))if(v=i(v,b)){c=v;d=e;break}if(c)break;!j&&(k&&i(k,b))&&(j=i(k,b),f=e)}!c&&j&&(c=j,d=f);c&&(g.splice(0,d,
c),a=g.join("/"))}return a}function d(a){z&&x(document.getElementsByTagName("script"),function(g){if(g.getAttribute("data-requiremodule")===a&&g.getAttribute("data-requirecontext")===j.contextName)return g.parentNode.removeChild(g),!0})}function y(a){var g=i(m.paths,a);if(g&&I(g)&&1<g.length)return d(a),g.shift(),j.require.undef(a),j.require([a]),!0}function f(a){var g,b=a?a.indexOf("!"):-1;-1<b&&(g=a.substring(0,b),a=a.substring(b+1,a.length));return[g,a]}function h(a,g,b,e){var n,u,d=null,h=g?g.name:
null,l=a,m=!0,k="";a||(m=!1,a="_@r"+(L+=1));a=f(a);d=a[0];a=a[1];d&&(d=c(d,h,e),u=i(p,d));a&&(d?k=u&&u.normalize?u.normalize(a,function(a){return c(a,h,e)}):c(a,h,e):(k=c(a,h,e),a=f(k),d=a[0],k=a[1],b=!0,n=j.nameToUrl(k)));b=d&&!u&&!b?"_unnormalized"+(M+=1):"";return{prefix:d,name:k,parentMap:g,unnormalized:!!b,url:n,originalName:l,isDefine:m,id:(d?d+"!"+k:k)+b}}function q(a){var g=a.id,b=i(k,g);b||(b=k[g]=new j.Module(a));return b}function s(a,g,b){var e=a.id,n=i(k,e);if(r(p,e)&&(!n||n.defineEmitComplete))"defined"===
g&&b(p[e]);else q(a).on(g,b)}function C(a,g){var b=a.requireModules,e=!1;if(g)g(a);else if(x(b,function(g){if(g=i(k,g))g.error=a,g.events.error&&(e=!0,g.emit("error",a))}),!e)l.onError(a)}function w(){R.length&&(fa.apply(F,[F.length-1,0].concat(R)),R=[])}function A(a,g,b){var e=a.map.id;a.error?a.emit("error",a.error):(g[e]=!0,x(a.depMaps,function(e,c){var d=e.id,h=i(k,d);h&&(!a.depMatched[c]&&!b[d])&&(i(g,d)?(a.defineDep(c,p[d]),a.check()):A(h,g,b))}),b[e]=!0)}function B(){var a,g,b,e,n=(b=1E3*m.waitSeconds)&&
j.startTime+b<(new Date).getTime(),c=[],h=[],f=!1,l=!0;if(!T){T=!0;E(k,function(b){a=b.map;g=a.id;if(b.enabled&&(a.isDefine||h.push(b),!b.error))if(!b.inited&&n)y(g)?f=e=!0:(c.push(g),d(g));else if(!b.inited&&(b.fetched&&a.isDefine)&&(f=!0,!a.prefix))return l=!1});if(n&&c.length)return b=J("timeout","Load timeout for modules: "+c,null,c),b.contextName=j.contextName,C(b);l&&x(h,function(a){A(a,{},{})});if((!n||e)&&f)if((z||$)&&!U)U=setTimeout(function(){U=0;B()},50);T=!1}}function D(a){r(p,a[0])||
q(h(a[0],null,!0)).init(a[1],a[2])}function G(a){var a=a.currentTarget||a.srcElement,b=j.onScriptLoad;a.detachEvent&&!V?a.detachEvent("onreadystatechange",b):a.removeEventListener("load",b,!1);b=j.onScriptError;(!a.detachEvent||V)&&a.removeEventListener("error",b,!1);return{node:a,id:a&&a.getAttribute("data-requiremodule")}}function K(){var a;for(w();F.length;){a=F.shift();if(null===a[0])return C(J("mismatch","Mismatched anonymous define() module: "+a[a.length-1]));D(a)}}var T,W,j,N,U,m={waitSeconds:7,
baseUrl:"./",paths:{},pkgs:{},shim:{},map:{},config:{}},k={},X={},F=[],p={},S={},L=1,M=1;N={require:function(a){return a.require?a.require:a.require=j.makeRequire(a.map)},exports:function(a){a.usingExports=!0;if(a.map.isDefine)return a.exports?a.exports:a.exports=p[a.map.id]={}},module:function(a){return a.module?a.module:a.module={id:a.map.id,uri:a.map.url,config:function(){return m.config&&i(m.config,a.map.id)||{}},exports:p[a.map.id]}}};W=function(a){this.events=i(X,a.id)||{};this.map=a;this.shim=
i(m.shim,a.id);this.depExports=[];this.depMaps=[];this.depMatched=[];this.pluginMaps={};this.depCount=0};W.prototype={init:function(a,b,c,e){e=e||{};if(!this.inited){this.factory=b;if(c)this.on("error",c);else this.events.error&&(c=t(this,function(a){this.emit("error",a)}));this.depMaps=a&&a.slice(0);this.errback=c;this.inited=!0;this.ignore=e.ignore;e.enabled||this.enabled?this.enable():this.check()}},defineDep:function(a,b){this.depMatched[a]||(this.depMatched[a]=!0,this.depCount-=1,this.depExports[a]=
b)},fetch:function(){if(!this.fetched){this.fetched=!0;j.startTime=(new Date).getTime();var a=this.map;if(this.shim)j.makeRequire(this.map,{enableBuildCallback:!0})(this.shim.deps||[],t(this,function(){return a.prefix?this.callPlugin():this.load()}));else return a.prefix?this.callPlugin():this.load()}},load:function(){var a=this.map.url;S[a]||(S[a]=!0,j.load(this.map.id,a))},check:function(){if(this.enabled&&!this.enabling){var a,b,c=this.map.id;b=this.depExports;var e=this.exports,n=this.factory;
if(this.inited)if(this.error)this.emit("error",this.error);else{if(!this.defining){this.defining=!0;if(1>this.depCount&&!this.defined){if(H(n)){if(this.events.error)try{e=j.execCb(c,n,b,e)}catch(d){a=d}else e=j.execCb(c,n,b,e);this.map.isDefine&&((b=this.module)&&void 0!==b.exports&&b.exports!==this.exports?e=b.exports:void 0===e&&this.usingExports&&(e=this.exports));if(a)return a.requireMap=this.map,a.requireModules=[this.map.id],a.requireType="define",C(this.error=a)}else e=n;this.exports=e;if(this.map.isDefine&&
!this.ignore&&(p[c]=e,l.onResourceLoad))l.onResourceLoad(j,this.map,this.depMaps);delete k[c];this.defined=!0}this.defining=!1;this.defined&&!this.defineEmitted&&(this.defineEmitted=!0,this.emit("defined",this.exports),this.defineEmitComplete=!0)}}else this.fetch()}},callPlugin:function(){var a=this.map,b=a.id,d=h(a.prefix);this.depMaps.push(d);s(d,"defined",t(this,function(e){var n,d;d=this.map.name;var v=this.map.parentMap?this.map.parentMap.name:null,f=j.makeRequire(a.parentMap,{enableBuildCallback:!0,
skipMap:!0});if(this.map.unnormalized){if(e.normalize&&(d=e.normalize(d,function(a){return c(a,v,!0)})||""),e=h(a.prefix+"!"+d,this.map.parentMap),s(e,"defined",t(this,function(a){this.init([],function(){return a},null,{enabled:!0,ignore:!0})})),d=i(k,e.id)){this.depMaps.push(e);if(this.events.error)d.on("error",t(this,function(a){this.emit("error",a)}));d.enable()}}else n=t(this,function(a){this.init([],function(){return a},null,{enabled:!0})}),n.error=t(this,function(a){this.inited=!0;this.error=
a;a.requireModules=[b];E(k,function(a){0===a.map.id.indexOf(b+"_unnormalized")&&delete k[a.map.id]});C(a)}),n.fromText=t(this,function(e,c){var d=a.name,u=h(d),v=O;c&&(e=c);v&&(O=!1);q(u);r(m.config,b)&&(m.config[d]=m.config[b]);try{l.exec(e)}catch(k){throw Error("fromText eval for "+d+" failed: "+k);}v&&(O=!0);this.depMaps.push(u);j.completeLoad(d);f([d],n)}),e.load(a.name,f,n,m)}));j.enable(d,this);this.pluginMaps[d.id]=d},enable:function(){this.enabling=this.enabled=!0;x(this.depMaps,t(this,function(a,
b){var c,e;if("string"===typeof a){a=h(a,this.map.isDefine?this.map:this.map.parentMap,!1,!this.skipMap);this.depMaps[b]=a;if(c=i(N,a.id)){this.depExports[b]=c(this);return}this.depCount+=1;s(a,"defined",t(this,function(a){this.defineDep(b,a);this.check()}));this.errback&&s(a,"error",this.errback)}c=a.id;e=k[c];!r(N,c)&&(e&&!e.enabled)&&j.enable(a,this)}));E(this.pluginMaps,t(this,function(a){var b=i(k,a.id);b&&!b.enabled&&j.enable(a,this)}));this.enabling=!1;this.check()},on:function(a,b){var c=
this.events[a];c||(c=this.events[a]=[]);c.push(b)},emit:function(a,b){x(this.events[a],function(a){a(b)});"error"===a&&delete this.events[a]}};j={config:m,contextName:b,registry:k,defined:p,urlFetched:S,defQueue:F,Module:W,makeModuleMap:h,nextTick:l.nextTick,configure:function(a){a.baseUrl&&"/"!==a.baseUrl.charAt(a.baseUrl.length-1)&&(a.baseUrl+="/");var b=m.pkgs,c=m.shim,e={paths:!0,config:!0,map:!0};E(a,function(a,b){e[b]?"map"===b?Q(m[b],a,!0,!0):Q(m[b],a,!0):m[b]=a});a.shim&&(E(a.shim,function(a,
b){I(a)&&(a={deps:a});if((a.exports||a.init)&&!a.exportsFn)a.exportsFn=j.makeShimExports(a);c[b]=a}),m.shim=c);a.packages&&(x(a.packages,function(a){a="string"===typeof a?{name:a}:a;b[a.name]={name:a.name,location:a.location||a.name,main:(a.main||"main").replace(ga,"").replace(aa,"")}}),m.pkgs=b);E(k,function(a,b){!a.inited&&!a.map.unnormalized&&(a.map=h(b))});if(a.deps||a.callback)j.require(a.deps||[],a.callback)},makeShimExports:function(a){return function(){var b;a.init&&(b=a.init.apply(Y,arguments));
return b||a.exports&&Z(a.exports)}},makeRequire:function(a,d){function f(e,c,u){var i,m;d.enableBuildCallback&&(c&&H(c))&&(c.__requireJsBuild=!0);if("string"===typeof e){if(H(c))return C(J("requireargs","Invalid require call"),u);if(a&&r(N,e))return N[e](k[a.id]);if(l.get)return l.get(j,e,a);i=h(e,a,!1,!0);i=i.id;return!r(p,i)?C(J("notloaded",'Module name "'+i+'" has not been loaded yet for context: '+b+(a?"":". Use require([])"))):p[i]}K();j.nextTick(function(){K();m=q(h(null,a));m.skipMap=d.skipMap;
m.init(e,c,u,{enabled:!0});B()});return f}d=d||{};Q(f,{isBrowser:z,toUrl:function(b){var d=b.lastIndexOf("."),g=null;-1!==d&&(g=b.substring(d,b.length),b=b.substring(0,d));return j.nameToUrl(c(b,a&&a.id,!0),g)},defined:function(b){return r(p,h(b,a,!1,!0).id)},specified:function(b){b=h(b,a,!1,!0).id;return r(p,b)||r(k,b)}});a||(f.undef=function(b){w();var c=h(b,a,!0),d=i(k,b);delete p[b];delete S[c.url];delete X[b];d&&(d.events.defined&&(X[b]=d.events),delete k[b])});return f},enable:function(a){i(k,
a.id)&&q(a).enable()},completeLoad:function(a){var b,c,d=i(m.shim,a)||{},h=d.exports;for(w();F.length;){c=F.shift();if(null===c[0]){c[0]=a;if(b)break;b=!0}else c[0]===a&&(b=!0);D(c)}c=i(k,a);if(!b&&!r(p,a)&&c&&!c.inited){if(m.enforceDefine&&(!h||!Z(h)))return y(a)?void 0:C(J("nodefine","No define call for "+a,null,[a]));D([a,d.deps||[],d.exportsFn])}B()},nameToUrl:function(a,b){var c,d,h,f,j,k;if(l.jsExtRegExp.test(a))f=a+(b||"");else{c=m.paths;d=m.pkgs;f=a.split("/");for(j=f.length;0<j;j-=1)if(k=
f.slice(0,j).join("/"),h=i(d,k),k=i(c,k)){I(k)&&(k=k[0]);f.splice(0,j,k);break}else if(h){c=a===h.name?h.location+"/"+h.main:h.location;f.splice(0,j,c);break}f=f.join("/");f+=b||(/\?/.test(f)?"":".js");f=("/"===f.charAt(0)||f.match(/^[\w\+\.\-]+:/)?"":m.baseUrl)+f}return m.urlArgs?f+((-1===f.indexOf("?")?"?":"&")+m.urlArgs):f},load:function(a,b){l.load(j,a,b)},execCb:function(a,b,c,d){return b.apply(d,c)},onScriptLoad:function(a){if("load"===a.type||ha.test((a.currentTarget||a.srcElement).readyState))P=
null,a=G(a),j.completeLoad(a.id)},onScriptError:function(a){var b=G(a);if(!y(b.id))return C(J("scripterror","Script error",a,[b.id]))}};j.require=j.makeRequire();return j}var l,w,A,D,s,G,P,K,ba,ca,ia=/(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg,ja=/[^.]\s*require\s*\(\s*["']([^'"\s]+)["']\s*\)/g,aa=/\.js$/,ga=/^\.\//;w=Object.prototype;var L=w.toString,da=w.hasOwnProperty,fa=Array.prototype.splice,z=!!("undefined"!==typeof window&&navigator&&document),$=!z&&"undefined"!==typeof importScripts,ha=z&&
"PLAYSTATION 3"===navigator.platform?/^complete$/:/^(complete|loaded)$/,V="undefined"!==typeof opera&&"[object Opera]"===opera.toString(),B={},q={},R=[],O=!1;if("undefined"===typeof define){if("undefined"!==typeof requirejs){if(H(requirejs))return;q=requirejs;requirejs=void 0}"undefined"!==typeof require&&!H(require)&&(q=require,require=void 0);l=requirejs=function(b,c,d,y){var f,h="_";!I(b)&&"string"!==typeof b&&(f=b,I(c)?(b=c,c=d,d=y):b=[]);f&&f.context&&(h=f.context);(y=i(B,h))||(y=B[h]=l.s.newContext(h));
f&&y.configure(f);return y.require(b,c,d)};l.config=function(b){return l(b)};l.nextTick="undefined"!==typeof setTimeout?function(b){setTimeout(b,4)}:function(b){b()};require||(require=l);l.version="2.1.2";l.jsExtRegExp=/^\/|:|\?|\.js$/;l.isBrowser=z;w=l.s={contexts:B,newContext:ea};l({});x(["toUrl","undef","defined","specified"],function(b){l[b]=function(){var c=B._;return c.require[b].apply(c,arguments)}});if(z&&(A=w.head=document.getElementsByTagName("head")[0],D=document.getElementsByTagName("base")[0]))A=
w.head=D.parentNode;l.onError=function(b){throw b;};l.load=function(b,c,d){var i=b&&b.config||{},f;if(z)return f=i.xhtml?document.createElementNS("http://www.w3.org/1999/xhtml","html:script"):document.createElement("script"),f.type=i.scriptType||"text/javascript",f.charset="utf-8",f.async=!0,f.setAttribute("data-requirecontext",b.contextName),f.setAttribute("data-requiremodule",c),f.attachEvent&&!(f.attachEvent.toString&&0>f.attachEvent.toString().indexOf("[native code"))&&!V?(O=!0,f.attachEvent("onreadystatechange",
b.onScriptLoad)):(f.addEventListener("load",b.onScriptLoad,!1),f.addEventListener("error",b.onScriptError,!1)),f.src=d,K=f,D?A.insertBefore(f,D):A.appendChild(f),K=null,f;$&&(importScripts(d),b.completeLoad(c))};z&&M(document.getElementsByTagName("script"),function(b){A||(A=b.parentNode);if(s=b.getAttribute("data-main"))return q.baseUrl||(G=s.split("/"),ba=G.pop(),ca=G.length?G.join("/")+"/":"./",q.baseUrl=ca,s=ba),s=s.replace(aa,""),q.deps=q.deps?q.deps.concat(s):[s],!0});define=function(b,c,d){var i,
f;"string"!==typeof b&&(d=c,c=b,b=null);I(c)||(d=c,c=[]);!c.length&&H(d)&&d.length&&(d.toString().replace(ia,"").replace(ja,function(b,d){c.push(d)}),c=(1===d.length?["require"]:["require","exports","module"]).concat(c));if(O){if(!(i=K))P&&"interactive"===P.readyState||M(document.getElementsByTagName("script"),function(b){if("interactive"===b.readyState)return P=b}),i=P;i&&(b||(b=i.getAttribute("data-requiremodule")),f=B[i.getAttribute("data-requirecontext")])}(f?f.defQueue:R).push([b,c,d])};define.amd=
{jQuery:!0};l.exec=function(b){return eval(b)};l(q)}})(this);
// name: sammy
// version: 0.7.4
// Sammy.js / http://sammyjs.org
(function($, window) {
(function(factory){
// Support module loading scenarios
if (typeof define === 'function' && define.amd){
// AMD Anonymous Module
define(['jquery'], factory);
} else {
// No module loader (plain <script> tag) - put directly in global namespace
$.sammy = window.Sammy = factory($);
}
})(function($){
var Sammy,
PATH_REPLACER = "([^\/]+)",
PATH_NAME_MATCHER = /:([\w\d]+)/g,
QUERY_STRING_MATCHER = /\?([^#]*)?$/,
// mainly for making `arguments` an Array
_makeArray = function(nonarray) { return Array.prototype.slice.call(nonarray); },
// borrowed from jQuery
_isFunction = function( obj ) { return Object.prototype.toString.call(obj) === "[object Function]"; },
_isArray = function( obj ) { return Object.prototype.toString.call(obj) === "[object Array]"; },
_isRegExp = function( obj ) { return Object.prototype.toString.call(obj) === "[object RegExp]"; },
_decode = function( str ) { return decodeURIComponent((str || '').replace(/\+/g, ' ')); },
_encode = encodeURIComponent,
_escapeHTML = function(s) {
return String(s).replace(/&(?!\w+;)/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
},
_routeWrapper = function(verb) {
return function() {
return this.route.apply(this, [verb].concat(Array.prototype.slice.call(arguments)));
};
},
_template_cache = {},
_has_history = !!(window.history && history.pushState),
loggers = [];
// `Sammy` (also aliased as $.sammy) is not only the namespace for a
// number of prototypes, its also a top level method that allows for easy
// creation/management of `Sammy.Application` instances. There are a
// number of different forms for `Sammy()` but each returns an instance
// of `Sammy.Application`. When a new instance is created using
// `Sammy` it is added to an Object called `Sammy.apps`. This
// provides for an easy way to get at existing Sammy applications. Only one
// instance is allowed per `element_selector` so when calling
// `Sammy('selector')` multiple times, the first time will create
// the application and the following times will extend the application
// already added to that selector.
//
// ### Example
//
// // returns the app at #main or a new app
// Sammy('#main')
//
// // equivalent to "new Sammy.Application", except appends to apps
// Sammy();
// Sammy(function() { ... });
//
// // extends the app at '#main' with function.
// Sammy('#main', function() { ... });
//
Sammy = function() {
var args = _makeArray(arguments),
app, selector;
Sammy.apps = Sammy.apps || {};
if (args.length === 0 || args[0] && _isFunction(args[0])) { // Sammy()
return Sammy.apply(Sammy, ['body'].concat(args));
} else if (typeof (selector = args.shift()) == 'string') { // Sammy('#main')
app = Sammy.apps[selector] || new Sammy.Application();
app.element_selector = selector;
if (args.length > 0) {
$.each(args, function(i, plugin) {
app.use(plugin);
});
}
// if the selector changes make sure the reference in Sammy.apps changes
if (app.element_selector != selector) {
delete Sammy.apps[selector];
}
Sammy.apps[app.element_selector] = app;
return app;
}
};
Sammy.VERSION = '0.7.4';
// Add to the global logger pool. Takes a function that accepts an
// unknown number of arguments and should print them or send them somewhere
// The first argument is always a timestamp.
Sammy.addLogger = function(logger) {
loggers.push(logger);
};
// Sends a log message to each logger listed in the global
// loggers pool. Can take any number of arguments.
// Also prefixes the arguments with a timestamp.
Sammy.log = function() {
var args = _makeArray(arguments);
args.unshift("[" + Date() + "]");
$.each(loggers, function(i, logger) {
logger.apply(Sammy, args);
});
};
if (typeof window.console != 'undefined') {
if (_isFunction(window.console.log.apply)) {
Sammy.addLogger(function() {
window.console.log.apply(window.console, arguments);
});
} else {
Sammy.addLogger(function() {
window.console.log(arguments);
});
}
} else if (typeof console != 'undefined') {
Sammy.addLogger(function() {
console.log.apply(console, arguments);
});
}
$.extend(Sammy, {
makeArray: _makeArray,
isFunction: _isFunction,
isArray: _isArray
});
// Sammy.Object is the base for all other Sammy classes. It provides some useful
// functionality, including cloning, iterating, etc.
Sammy.Object = function(obj) { // constructor
return $.extend(this, obj || {});
};
$.extend(Sammy.Object.prototype, {
// Escape HTML in string, use in templates to prevent script injection.
// Also aliased as `h()`
escapeHTML: _escapeHTML,
h: _escapeHTML,
// Returns a copy of the object with Functions removed.
toHash: function() {
var json = {};
$.each(this, function(k,v) {
if (!_isFunction(v)) {
json[k] = v;
}
});
return json;
},
// Renders a simple HTML version of this Objects attributes.
// Does not render functions.
// For example. Given this Sammy.Object:
//
// var s = new Sammy.Object({first_name: 'Sammy', last_name: 'Davis Jr.'});
// s.toHTML()
// //=> '<strong>first_name</strong> Sammy<br /><strong>last_name</strong> Davis Jr.<br />'
//
toHTML: function() {
var display = "";
$.each(this, function(k, v) {
if (!_isFunction(v)) {
display += "<strong>" + k + "</strong> " + v + "<br />";
}
});
return display;
},
// Returns an array of keys for this object. If `attributes_only`
// is true will not return keys that map to a `function()`
keys: function(attributes_only) {
var keys = [];
for (var property in this) {
if (!_isFunction(this[property]) || !attributes_only) {
keys.push(property);
}
}
return keys;
},
// Checks if the object has a value at `key` and that the value is not empty
has: function(key) {
return this[key] && $.trim(this[key].toString()) !== '';
},
// convenience method to join as many arguments as you want
// by the first argument - useful for making paths
join: function() {
var args = _makeArray(arguments);
var delimiter = args.shift();
return args.join(delimiter);
},
// Shortcut to Sammy.log
log: function() {
Sammy.log.apply(Sammy, arguments);
},
// Returns a string representation of this object.
// if `include_functions` is true, it will also toString() the
// methods of this object. By default only prints the attributes.
toString: function(include_functions) {
var s = [];
$.each(this, function(k, v) {
if (!_isFunction(v) || include_functions) {
s.push('"' + k + '": ' + v.toString());
}
});
return "Sammy.Object: {" + s.join(',') + "}";
}
});
// Return whether the event targets this window.
Sammy.targetIsThisWindow = function targetIsThisWindow(event) {
var targetWindow = $(event.target).attr('target');
if ( !targetWindow || targetWindow === window.name || targetWindow === '_self' ) { return true; }
if ( targetWindow === '_blank' ) { return false; }
if ( targetWindow === 'top' && window === window.top ) { return true; }
return false;
};
// The DefaultLocationProxy is the default location proxy for all Sammy applications.
// A location proxy is a prototype that conforms to a simple interface. The purpose
// of a location proxy is to notify the Sammy.Application its bound to when the location
// or 'external state' changes.
//
// The `DefaultLocationProxy` watches for changes to the path of the current window and
// is also able to set the path based on changes in the application. It does this by
// using different methods depending on what is available in the current browser. In
// the latest and greatest browsers it used the HTML5 History API and the `pushState`
// `popState` events/methods. This allows you to use Sammy to serve a site behind normal
// URI paths as opposed to the older default of hash (#) based routing. Because the server
// can interpret the changed path on a refresh or re-entry, though, it requires additional
// support on the server side. If you'd like to force disable HTML5 history support, please
// use the `disable_push_state` setting on `Sammy.Application`. If pushState support
// is enabled, `DefaultLocationProxy` also binds to all links on the page. If a link is clicked
// that matches the current set of routes, the URL is changed using pushState instead of
// fully setting the location and the app is notified of the change.
//
// If the browser does not have support for HTML5 History, `DefaultLocationProxy` automatically
// falls back to the older hash based routing. The newest browsers (IE, Safari > 4, FF >= 3.6)
// support a 'onhashchange' DOM event, thats fired whenever the location.hash changes.
// In this situation the DefaultLocationProxy just binds to this event and delegates it to
// the application. In the case of older browsers a poller is set up to track changes to the
// hash.
Sammy.DefaultLocationProxy = function(app, run_interval_every) {
this.app = app;
// set is native to false and start the poller immediately
this.is_native = false;
this.has_history = _has_history;
this._startPolling(run_interval_every);
};
Sammy.DefaultLocationProxy.fullPath = function(location_obj) {
// Bypass the `window.location.hash` attribute. If a question mark
// appears in the hash IE6 will strip it and all of the following
// characters from `window.location.hash`.
var matches = location_obj.toString().match(/^[^#]*(#.+)$/);
var hash = matches ? matches[1] : '';
return [location_obj.pathname, location_obj.search, hash].join('');
};
$.extend(Sammy.DefaultLocationProxy.prototype , {
// bind the proxy events to the current app.
bind: function() {
var proxy = this, app = this.app, lp = Sammy.DefaultLocationProxy;
$(window).bind('hashchange.' + this.app.eventNamespace(), function(e, non_native) {
// if we receive a native hash change event, set the proxy accordingly
// and stop polling
if (proxy.is_native === false && !non_native) {
proxy.is_native = true;
window.clearInterval(lp._interval);
lp._interval = null;
}
app.trigger('location-changed');
});
if (_has_history && !app.disable_push_state) {
// bind to popstate
$(window).bind('popstate.' + this.app.eventNamespace(), function(e) {
app.trigger('location-changed');
});
// bind to link clicks that have routes
$(document).delegate('a', 'click.history-' + this.app.eventNamespace(), function (e) {
if (e.isDefaultPrevented() || e.metaKey || e.ctrlKey) {
return;
}
var full_path = lp.fullPath(this);
if (this.hostname == window.location.hostname &&
app.lookupRoute('get', full_path) &&
Sammy.targetIsThisWindow(e)) {
e.preventDefault();
proxy.setLocation(full_path);
return false;
}
});
}
if (!lp._bindings) {
lp._bindings = 0;
}
lp._bindings++;
},
// unbind the proxy events from the current app
unbind: function() {
$(window).unbind('hashchange.' + this.app.eventNamespace());
$(window).unbind('popstate.' + this.app.eventNamespace());
$(document).undelegate('a', 'click.history-' + this.app.eventNamespace());
Sammy.DefaultLocationProxy._bindings--;
if (Sammy.DefaultLocationProxy._bindings <= 0) {
window.clearInterval(Sammy.DefaultLocationProxy._interval);
Sammy.DefaultLocationProxy._interval = null;
}
},
// get the current location from the hash.
getLocation: function() {
return Sammy.DefaultLocationProxy.fullPath(window.location);
},
// set the current location to `new_location`
setLocation: function(new_location) {
if (/^([^#\/]|$)/.test(new_location)) { // non-prefixed url
if (_has_history && !this.app.disable_push_state) {
new_location = '/' + new_location;
} else {
new_location = '#!/' + new_location;
}
}
if (new_location != this.getLocation()) {
// HTML5 History exists and new_location is a full path
if (_has_history && !this.app.disable_push_state && /^\//.test(new_location)) {
history.pushState({ path: new_location }, window.title, new_location);
this.app.trigger('location-changed');
} else {
return (window.location = new_location);
}
}
},
_startPolling: function(every) {
// set up interval
var proxy = this;
if (!Sammy.DefaultLocationProxy._interval) {
if (!every) { every = 10; }
var hashCheck = function() {
var current_location = proxy.getLocation();
if (typeof Sammy.DefaultLocationProxy._last_location == 'undefined' ||
current_location != Sammy.DefaultLocationProxy._last_location) {
window.setTimeout(function() {
$(window).trigger('hashchange', [true]);
}, 0);
}
Sammy.DefaultLocationProxy._last_location = current_location;
};
hashCheck();
Sammy.DefaultLocationProxy._interval = window.setInterval(hashCheck, every);
}
}
});
// Sammy.Application is the Base prototype for defining 'applications'.
// An 'application' is a collection of 'routes' and bound events that is
// attached to an element when `run()` is called.
// The only argument an 'app_function' is evaluated within the context of the application.
Sammy.Application = function(app_function) {
var app = this;
this.routes = {};
this.listeners = new Sammy.Object({});
this.arounds = [];
this.befores = [];
// generate a unique namespace
this.namespace = (new Date()).getTime() + '-' + parseInt(Math.random() * 1000, 10);
this.context_prototype = function() { Sammy.EventContext.apply(this, arguments); };
this.context_prototype.prototype = new Sammy.EventContext();
if (_isFunction(app_function)) {
app_function.apply(this, [this]);
}
// set the location proxy if not defined to the default (DefaultLocationProxy)
if (!this._location_proxy) {
this.setLocationProxy(new Sammy.DefaultLocationProxy(this, this.run_interval_every));
}
if (this.debug) {
this.bindToAllEvents(function(e, data) {
app.log(app.toString(), e.cleaned_type, data || {});
});
}
};
Sammy.Application.prototype = $.extend({}, Sammy.Object.prototype, {
// the four route verbs
ROUTE_VERBS: ['get','post','put','delete'],
// An array of the default events triggered by the
// application during its lifecycle
APP_EVENTS: ['run', 'unload', 'lookup-route', 'run-route', 'route-found', 'event-context-before', 'event-context-after', 'changed', 'error', 'check-form-submission', 'redirect', 'location-changed'],
_last_route: null,
_location_proxy: null,
_running: false,
// Defines what element the application is bound to. Provide a selector
// (parseable by `jQuery()`) and this will be used by `$element()`
element_selector: 'body',
// When set to true, logs all of the default events using `log()`
debug: false,
// When set to true, and the error() handler is not overridden, will actually
// raise JS errors in routes (500) and when routes can't be found (404)
raise_errors: false,
// The time in milliseconds that the URL is queried for changes
run_interval_every: 50,
// if using the `DefaultLocationProxy` setting this to true will force the app to use
// traditional hash based routing as opposed to the new HTML5 PushState support
disable_push_state: false,
// The default template engine to use when using `partial()` in an
// `EventContext`. `template_engine` can either be a string that
// corresponds to the name of a method/helper on EventContext or it can be a function
// that takes two arguments, the content of the unrendered partial and an optional
// JS object that contains interpolation data. Template engine is only called/referred
// to if the extension of the partial is null or unknown. See `partial()`
// for more information
template_engine: null,
// //=> Sammy.Application: body
toString: function() {
return 'Sammy.Application:' + this.element_selector;
},
// returns a jQuery object of the Applications bound element.
$element: function(selector) {
return selector ? $(this.element_selector).find(selector) : $(this.element_selector);
},
// `use()` is the entry point for including Sammy plugins.
// The first argument to use should be a function() that is evaluated
// in the context of the current application, just like the `app_function`
// argument to the `Sammy.Application` constructor.
//
// Any additional arguments are passed to the app function sequentially.
//
// For much more detail about plugins, check out:
// [http://sammyjs.org/docs/plugins](http://sammyjs.org/docs/plugins)
//
// ### Example
//
// var MyPlugin = function(app, prepend) {
//
// this.helpers({
// myhelper: function(text) {
// alert(prepend + " " + text);
// }
// });
//
// };
//
// var app = $.sammy(function() {
//
// this.use(MyPlugin, 'This is my plugin');
//
// this.get('#/', function() {
// this.myhelper('and dont you forget it!');
// //=> Alerts: This is my plugin and dont you forget it!
// });
//
// });
//
// If plugin is passed as a string it assumes your are trying to load
// Sammy."Plugin". This is the preferred way of loading core Sammy plugins
// as it allows for better error-messaging.
//
// ### Example
//
// $.sammy(function() {
// this.use('Mustache'); //=> Sammy.Mustache
// this.use('Storage'); //=> Sammy.Storage
// });
//
use: function() {
// flatten the arguments
var args = _makeArray(arguments),
plugin = args.shift(),
plugin_name = plugin || '';
try {
args.unshift(this);
if (typeof plugin == 'string') {
plugin_name = 'Sammy.' + plugin;
plugin = Sammy[plugin];
}
plugin.apply(this, args);
} catch(e) {
if (typeof plugin === 'undefined') {
this.error("Plugin Error: called use() but plugin (" + plugin_name.toString() + ") is not defined", e);
} else if (!_isFunction(plugin)) {
this.error("Plugin Error: called use() but '" + plugin_name.toString() + "' is not a function", e);
} else {
this.error("Plugin Error", e);
}
}
return this;
},
// Sets the location proxy for the current app. By default this is set to
// a new `Sammy.DefaultLocationProxy` on initialization. However, you can set
// the location_proxy inside you're app function to give your app a custom
// location mechanism. See `Sammy.DefaultLocationProxy` and `Sammy.DataLocationProxy`
// for examples.
//
// `setLocationProxy()` takes an initialized location proxy.
//
// ### Example
//
// // to bind to data instead of the default hash;
// var app = $.sammy(function() {
// this.setLocationProxy(new Sammy.DataLocationProxy(this));
// });
//
setLocationProxy: function(new_proxy) {
var original_proxy = this._location_proxy;
this._location_proxy = new_proxy;
if (this.isRunning()) {
if (original_proxy) {
// if there is already a location proxy, unbind it.
original_proxy.unbind();
}
this._location_proxy.bind();
}
},
// provide log() override for inside an app that includes the relevant application element_selector
log: function() {
Sammy.log.apply(Sammy, Array.prototype.concat.apply([this.element_selector],arguments));
},
// `route()` is the main method for defining routes within an application.
// For great detail on routes, check out:
// [http://sammyjs.org/docs/routes](http://sammyjs.org/docs/routes)
//
// This method also has aliases for each of the different verbs (eg. `get()`, `post()`, etc.)
//
// ### Arguments
//
// * `verb` A String in the set of ROUTE_VERBS or 'any'. 'any' will add routes for each
// of the ROUTE_VERBS. If only two arguments are passed,
// the first argument is the path, the second is the callback and the verb
// is assumed to be 'any'.
// * `path` A Regexp or a String representing the path to match to invoke this verb.
// * `callback` A Function that is called/evaluated when the route is run see: `runRoute()`.
// It is also possible to pass a string as the callback, which is looked up as the name
// of a method on the application.
//
route: function(verb, path) {
var app = this, param_names = [], add_route, path_match, callback = Array.prototype.slice.call(arguments,2);
// if the method signature is just (path, callback)
// assume the verb is 'any'
if (callback.length === 0 && _isFunction(path)) {
path = verb;
callback = [path];
verb = 'any';
}
verb = verb.toLowerCase(); // ensure verb is lower case
// if path is a string turn it into a regex
if (path.constructor == String) {
// Needs to be explicitly set because IE will maintain the index unless NULL is returned,
// which means that with two consecutive routes that contain params, the second set of params will not be found and end up in splat instead of params
// https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/RegExp/lastIndex
PATH_NAME_MATCHER.lastIndex = 0;
// find the names
while ((path_match = PATH_NAME_MATCHER.exec(path)) !== null) {
param_names.push(path_match[1]);
}
// replace with the path replacement
path = new RegExp(path.replace(PATH_NAME_MATCHER, PATH_REPLACER) + "$");
}
// lookup callbacks
$.each(callback,function(i,cb){
if (typeof(cb) === 'string') {
callback[i] = app[cb];
}
});
add_route = function(with_verb) {
var r = {verb: with_verb, path: path, callback: callback, param_names: param_names};
// add route to routes array
app.routes[with_verb] = app.routes[with_verb] || [];
// place routes in order of definition
app.routes[with_verb].push(r);
};
if (verb === 'any') {
$.each(this.ROUTE_VERBS, function(i, v) { add_route(v); });
} else {
add_route(verb);
}
// return the app
return this;
},
// Alias for route('get', ...)
get: _routeWrapper('get'),
// Alias for route('post', ...)
post: _routeWrapper('post'),
// Alias for route('put', ...)
put: _routeWrapper('put'),
// Alias for route('delete', ...)
del: _routeWrapper('delete'),
// Alias for route('any', ...)
any: _routeWrapper('any'),
// `mapRoutes` takes an array of arrays, each array being passed to route()
// as arguments, this allows for mass definition of routes. Another benefit is
// this makes it possible/easier to load routes via remote JSON.
//
// ### Example
//
// var app = $.sammy(function() {
//
// this.mapRoutes([
// ['get', '#/', function() { this.log('index'); }],
// // strings in callbacks are looked up as methods on the app
// ['post', '#/create', 'addUser'],
// // No verb assumes 'any' as the verb
// [/dowhatever/, function() { this.log(this.verb, this.path)}];
// ]);
// });
//
mapRoutes: function(route_array) {
var app = this;
$.each(route_array, function(i, route_args) {
app.route.apply(app, route_args);
});
return this;
},
// A unique event namespace defined per application.
// All events bound with `bind()` are automatically bound within this space.
eventNamespace: function() {
return ['sammy-app', this.namespace].join('-');
},
// Works just like `jQuery.fn.bind()` with a couple notable differences.
//
// * It binds all events to the application element
// * All events are bound within the `eventNamespace()`
// * Events are not actually bound until the application is started with `run()`
// * callbacks are evaluated within the context of a Sammy.EventContext
//
bind: function(name, data, callback) {
var app = this;
// build the callback
// if the arity is 2, callback is the second argument
if (typeof callback == 'undefined') { callback = data; }
var listener_callback = function() {
// pull off the context from the arguments to the callback
var e, context, data;
e = arguments[0];
data = arguments[1];
if (data && data.context) {
context = data.context;
delete data.context;
} else {
context = new app.context_prototype(app, 'bind', e.type, data, e.target);
}
e.cleaned_type = e.type.replace(app.eventNamespace(), '');
callback.apply(context, [e, data]);
};
// it could be that the app element doesnt exist yet
// so attach to the listeners array and then run()
// will actually bind the event.
if (!this.listeners[name]) { this.listeners[name] = []; }
this.listeners[name].push(listener_callback);
if (this.isRunning()) {
// if the app is running
// *actually* bind the event to the app element
this._listen(name, listener_callback);
}
return this;
},
// Triggers custom events defined with `bind()`
//
// ### Arguments
//
// * `name` The name of the event. Automatically prefixed with the `eventNamespace()`
// * `data` An optional Object that can be passed to the bound callback.
// * `context` An optional context/Object in which to execute the bound callback.
// If no context is supplied a the context is a new `Sammy.EventContext`
//
trigger: function(name, data) {
this.$element().trigger([name, this.eventNamespace()].join('.'), [data]);
return this;
},
// Reruns the current route
refresh: function() {
this.last_location = null;
this.trigger('location-changed');
return this;
},
// Takes a single callback that is pushed on to a stack.
// Before any route is run, the callbacks are evaluated in order within
// the current `Sammy.EventContext`
//
// If any of the callbacks explicitly return false, execution of any
// further callbacks and the route itself is halted.
//
// You can also provide a set of options that will define when to run this
// before based on the route it proceeds.
//
// ### Example
//
// var app = $.sammy(function() {
//
// // will run at #/route but not at #/
// this.before('#/route', function() {
// //...
// });
//
// // will run at #/ but not at #/route
// this.before({except: {path: '#/route'}}, function() {
// this.log('not before #/route');
// });
//
// this.get('#/', function() {});
//
// this.get('#/route', function() {});
//
// });
//
// See `contextMatchesOptions()` for a full list of supported options
//
before: function(options, callback) {
if (_isFunction(options)) {
callback = options;
options = {};
}
this.befores.push([options, callback]);
return this;
},
// A shortcut for binding a callback to be run after a route is executed.
// After callbacks have no guarunteed order.
after: function(callback) {
return this.bind('event-context-after', callback);
},
// Adds an around filter to the application. around filters are functions
// that take a single argument `callback` which is the entire route
// execution path wrapped up in a closure. This means you can decide whether
// or not to proceed with execution by not invoking `callback` or,
// more usefully wrapping callback inside the result of an asynchronous execution.
//
// ### Example
//
// The most common use case for around() is calling a _possibly_ async function
// and executing the route within the functions callback:
//
// var app = $.sammy(function() {
//
// var current_user = false;
//
// function checkLoggedIn(callback) {
// // /session returns a JSON representation of the logged in user
// // or an empty object
// if (!current_user) {
// $.getJSON('/session', function(json) {
// if (json.login) {
// // show the user as logged in
// current_user = json;
// // execute the route path
// callback();
// } else {
// // show the user as not logged in
// current_user = false;
// // the context of aroundFilters is an EventContext
// this.redirect('#/login');
// }
// });
// } else {
// // execute the route path
// callback();
// }
// };
//
// this.around(checkLoggedIn);
//
// });
//
around: function(callback) {
this.arounds.push(callback);
return this;
},
// Adds a onComplete function to the application. onComplete functions are executed
// at the end of a chain of route callbacks, if they call next(). Unlike after,
// which is called as soon as the route is complete, onComplete is like a final next()
// for all routes, and is thus run asynchronously
//
// ### Example
//
// app.get('/chain',function(context,next){
// console.log('chain1');
// next();
// },function(context,next){
// console.log('chain2');
// next();
// });
// app.get('/link',function(context,next){
// console.log('link1');
// next();
// },function(context,next){
// console.log('link2');
// next();
// });
// app.onComplete(function(){
// console.log("Running finally")
// });
//
// If you go to '/chain', you will get the following messages:
// chain1
// chain2
// Running onComplete
//
//
// If you go to /link, you will get the following messages:
// link1
// link2
// Running onComplete
//
// It really comes to play when doing asynchronous:
// app.get('/chain',function(context,next){
// $.get('/my/url',function(){
// console.log('chain1');
// next();
// })
// },function(context,next){
// console.log('chain2');
// next();
// });
//
onComplete: function(callback) {
this._onComplete = callback;
return this;
},
// Returns `true` if the current application is running.
isRunning: function() {
return this._running;
},
// Helpers extends the EventContext prototype specific to this app.
// This allows you to define app specific helper functions that can be used
// whenever you're inside of an event context (templates, routes, bind).
//
// ### Example
//
// var app = $.sammy(function() {
//
// helpers({
// upcase: function(text) {
// return text.toString().toUpperCase();
// }
// });
//
// get('#/', function() { with(this) {
// // inside of this context I can use the helpers
// $('#main').html(upcase($('#main').text());
// }});
//
// });
//
//
// ### Arguments
//
// * `extensions` An object collection of functions to extend the context.
//
helpers: function(extensions) {
$.extend(this.context_prototype.prototype, extensions);
return this;
},
// Helper extends the event context just like `helpers()` but does it
// a single method at a time. This is especially useful for dynamically named
// helpers
//
// ### Example
//
// // Trivial example that adds 3 helper methods to the context dynamically
// var app = $.sammy(function(app) {
//
// $.each([1,2,3], function(i, num) {
// app.helper('helper' + num, function() {
// this.log("I'm helper number " + num);
// });
// });
//
// this.get('#/', function() {
// this.helper2(); //=> I'm helper number 2
// });
// });
//
// ### Arguments
//
// * `name` The name of the method
// * `method` The function to be added to the prototype at `name`
//
helper: function(name, method) {
this.context_prototype.prototype[name] = method;
return this;
},
// Actually starts the application's lifecycle. `run()` should be invoked
// within a document.ready block to ensure the DOM exists before binding events, etc.
//
// ### Example
//
// var app = $.sammy(function() { ... }); // your application
// $(function() { // document.ready
// app.run();
// });
//
// ### Arguments
//
// * `start_url` Optionally, a String can be passed which the App will redirect to
// after the events/routes have been bound.
run: function(start_url) {
if (this.isRunning()) { return false; }
var app = this;
// actually bind all the listeners
$.each(this.listeners.toHash(), function(name, callbacks) {
$.each(callbacks, function(i, listener_callback) {
app._listen(name, listener_callback);
});
});
this.trigger('run', {start_url: start_url});
this._running = true;
// set last location
this.last_location = null;
if (!(/\#(.+)/.test(this.getLocation())) && typeof start_url != 'undefined') {
this.setLocation(start_url);
}
// check url
this._checkLocation();
this._location_proxy.bind();
this.bind('location-changed', function() {
app._checkLocation();
});
// bind to submit to capture post/put/delete routes
this.bind('submit', function(e) {
if ( !Sammy.targetIsThisWindow(e) ) { return true; }
var returned = app._checkFormSubmission($(e.target).closest('form'));
return (returned === false) ? e.preventDefault() : false;
});
// bind unload to body unload
$(window).bind('unload', function() {
app.unload();
});
// trigger html changed
return this.trigger('changed');
},
// The opposite of `run()`, un-binds all event listeners and intervals
// `run()` Automatically binds a `onunload` event to run this when
// the document is closed.
unload: function() {
if (!this.isRunning()) { return false; }
var app = this;
this.trigger('unload');
// clear interval
this._location_proxy.unbind();
// unbind form submits
this.$element().unbind('submit').removeClass(app.eventNamespace());
// unbind all events
$.each(this.listeners.toHash() , function(name, listeners) {
$.each(listeners, function(i, listener_callback) {
app._unlisten(name, listener_callback);
});
});
this._running = false;
return this;
},
// Not only runs `unbind` but also destroys the app reference.
destroy: function() {
this.unload();
delete Sammy.apps[this.element_selector];
return this;
},
// Will bind a single callback function to every event that is already
// being listened to in the app. This includes all the `APP_EVENTS`
// as well as any custom events defined with `bind()`.
//
// Used internally for debug logging.
bindToAllEvents: function(callback) {
var app = this;
// bind to the APP_EVENTS first
$.each(this.APP_EVENTS, function(i, e) {
app.bind(e, callback);
});
// next, bind to listener names (only if they dont exist in APP_EVENTS)
$.each(this.listeners.keys(true), function(i, name) {
if ($.inArray(name, app.APP_EVENTS) == -1) {
app.bind(name, callback);
}
});
return this;
},
// Returns a copy of the given path with any query string after the hash
// removed.
routablePath: function(path) {
return path.replace(QUERY_STRING_MATCHER, '');
},
// Given a verb and a String path, will return either a route object or false
// if a matching route can be found within the current defined set.
lookupRoute: function(verb, path) {
var app = this, routed = false, i = 0, l, route;
if (typeof this.routes[verb] != 'undefined') {
l = this.routes[verb].length;
for (; i < l; i++) {
route = this.routes[verb][i];
if (app.routablePath(path).match(route.path)) {
routed = route;
break;
}
}
}
return routed;
},
// First, invokes `lookupRoute()` and if a route is found, parses the
// possible URL params and then invokes the route's callback within a new
// `Sammy.EventContext`. If the route can not be found, it calls
// `notFound()`. If `raise_errors` is set to `true` and
// the `error()` has not been overridden, it will throw an actual JS
// error.
//
// You probably will never have to call this directly.
//
// ### Arguments
//
// * `verb` A String for the verb.
// * `path` A String path to lookup.
// * `params` An Object of Params pulled from the URI or passed directly.
//
// ### Returns
//
// Either returns the value returned by the route callback or raises a 404 Not Found error.
//
runRoute: function(verb, path, params, target) {
var app = this,
route = this.lookupRoute(verb, path),
context,
wrapped_route,
arounds,
around,
befores,
before,
callback_args,
path_params,
final_returned;
if (this.debug) {
this.log('runRoute', [verb, path].join(' '));
}
this.trigger('run-route', {verb: verb, path: path, params: params});
if (typeof params == 'undefined') { params = {}; }
$.extend(params, this._parseQueryString(path));
if (route) {
this.trigger('route-found', {route: route});
// pull out the params from the path
if ((path_params = route.path.exec(this.routablePath(path))) !== null) {
// first match is the full path
path_params.shift();
// for each of the matches
$.each(path_params, function(i, param) {
// if theres a matching param name
if (route.param_names[i]) {
// set the name to the match
params[route.param_names[i]] = _decode(param);
} else {
// initialize 'splat'
if (!params.splat) { params.splat = []; }
params.splat.push(_decode(param));
}
});
}
// set event context
context = new this.context_prototype(this, verb, path, params, target);
// ensure arrays
arounds = this.arounds.slice(0);
befores = this.befores.slice(0);
// set the callback args to the context + contents of the splat
callback_args = [context];
if (params.splat) {
callback_args = callback_args.concat(params.splat);
}
// wrap the route up with the before filters
wrapped_route = function() {
var returned, i, nextRoute;
while (befores.length > 0) {
before = befores.shift();
// check the options
if (app.contextMatchesOptions(context, before[0])) {
returned = before[1].apply(context, [context]);
if (returned === false) { return false; }
}
}
app.last_route = route;
context.trigger('event-context-before', {context: context});
// run multiple callbacks
if (typeof(route.callback) === "function") {
route.callback = [route.callback];
}
if (route.callback && route.callback.length) {
i = -1;
nextRoute = function() {
i++;
if (route.callback[i]) {
returned = route.callback[i].apply(context,callback_args);
} else if (app._onComplete && typeof(app._onComplete === "function")) {
app._onComplete(context);
}
};
callback_args.push(nextRoute);
nextRoute();
}
context.trigger('event-context-after', {context: context});
return returned;
};
$.each(arounds.reverse(), function(i, around) {
var last_wrapped_route = wrapped_route;
wrapped_route = function() { return around.apply(context, [last_wrapped_route]); };
});
try {
final_returned = wrapped_route();
} catch(e) {
this.error(['500 Error', verb, path].join(' '), e);
}
return final_returned;
} else {
return this.notFound(verb, path);
}
},
// Matches an object of options against an `EventContext` like object that
// contains `path` and `verb` attributes. Internally Sammy uses this
// for matching `before()` filters against specific options. You can set the
// object to _only_ match certain paths or verbs, or match all paths or verbs _except_
// those that match the options.
//
// ### Example
//
// var app = $.sammy(),
// context = {verb: 'get', path: '#/mypath'};
//
// // match against a path string
// app.contextMatchesOptions(context, '#/mypath'); //=> true
// app.contextMatchesOptions(context, '#/otherpath'); //=> false
// // equivalent to
// app.contextMatchesOptions(context, {only: {path:'#/mypath'}}); //=> true
// app.contextMatchesOptions(context, {only: {path:'#/otherpath'}}); //=> false
// // match against a path regexp
// app.contextMatchesOptions(context, /path/); //=> true
// app.contextMatchesOptions(context, /^path/); //=> false
// // match only a verb
// app.contextMatchesOptions(context, {only: {verb:'get'}}); //=> true
// app.contextMatchesOptions(context, {only: {verb:'post'}}); //=> false
// // match all except a verb
// app.contextMatchesOptions(context, {except: {verb:'post'}}); //=> true
// app.contextMatchesOptions(context, {except: {verb:'get'}}); //=> false
// // match all except a path
// app.contextMatchesOptions(context, {except: {path:'#/otherpath'}}); //=> true
// app.contextMatchesOptions(context, {except: {path:'#/mypath'}}); //=> false
// // match multiple paths
// app.contextMatchesOptions(context, {path: ['#/mypath', '#/otherpath']}); //=> true
// app.contextMatchesOptions(context, {path: ['#/otherpath', '#/thirdpath']}); //=> false
// // equivalent to
// app.contextMatchesOptions(context, {only: {path: ['#/mypath', '#/otherpath']}}); //=> true
// app.contextMatchesOptions(context, {only: {path: ['#/otherpath', '#/thirdpath']}}); //=> false
// // match all except multiple paths
// app.contextMatchesOptions(context, {except: {path: ['#/mypath', '#/otherpath']}}); //=> false
// app.contextMatchesOptions(context, {except: {path: ['#/otherpath', '#/thirdpath']}}); //=> true
//
contextMatchesOptions: function(context, match_options, positive) {
var options = match_options;
// normalize options
if (typeof options === 'string' || _isRegExp(options)) {
options = {path: options};
}
if (typeof positive === 'undefined') {
positive = true;
}
// empty options always match
if ($.isEmptyObject(options)) {
return true;
}
// Do we have to match against multiple paths?
if (_isArray(options.path)){
var results, numopt, opts, len;
results = [];
for (numopt = 0, len = options.path.length; numopt < len; numopt += 1) {
opts = $.extend({}, options, {path: options.path[numopt]});
results.push(this.contextMatchesOptions(context, opts));
}
var matched = $.inArray(true, results) > -1 ? true : false;
return positive ? matched : !matched;
}
if (options.only) {
return this.contextMatchesOptions(context, options.only, true);
} else if (options.except) {
return this.contextMatchesOptions(context, options.except, false);
}
var path_matched = true, verb_matched = true;
if (options.path) {
if (!_isRegExp(options.path)) {
options.path = new RegExp(options.path.toString() + '$');
}
path_matched = options.path.test(context.path);
}
if (options.verb) {
if(typeof options.verb === 'string') {
verb_matched = options.verb === context.verb;
} else {
verb_matched = options.verb.indexOf(context.verb) > -1;
}
}
return positive ? (verb_matched && path_matched) : !(verb_matched && path_matched);
},
// Delegates to the `location_proxy` to get the current location.
// See `Sammy.DefaultLocationProxy` for more info on location proxies.
getLocation: function() {
return this._location_proxy.getLocation();
},
// Delegates to the `location_proxy` to set the current location.
// See `Sammy.DefaultLocationProxy` for more info on location proxies.
//
// ### Arguments
//
// * `new_location` A new location string (e.g. '#/')
//
setLocation: function(new_location) {
return this._location_proxy.setLocation(new_location);
},
// Swaps the content of `$element()` with `content`
// You can override this method to provide an alternate swap behavior
// for `EventContext.partial()`.
//
// ### Example
//
// var app = $.sammy(function() {
//
// // implements a 'fade out'/'fade in'
// this.swap = function(content, callback) {
// var context = this;
// context.$element().fadeOut('slow', function() {
// context.$element().html(content);
// context.$element().fadeIn('slow', function() {
// if (callback) {
// callback.apply();
// }
// });
// });
// };
//
// });
//
swap: function(content, callback) {
var $el = this.$element().html(content);
if (_isFunction(callback)) { callback(content); }
return $el;
},
// a simple global cache for templates. Uses the same semantics as
// `Sammy.Cache` and `Sammy.Storage` so can easily be replaced with
// a persistent storage that lasts beyond the current request.
templateCache: function(key, value) {
if (typeof value != 'undefined') {
return _template_cache[key] = value;
} else {
return _template_cache[key];
}
},
// clear the templateCache
clearTemplateCache: function() {
return (_template_cache = {});
},
// This throws a '404 Not Found' error by invoking `error()`.
// Override this method or `error()` to provide custom
// 404 behavior (i.e redirecting to / or showing a warning)
notFound: function(verb, path) {
var ret = this.error(['404 Not Found', verb, path].join(' '));
return (verb === 'get') ? ret : true;
},
// The base error handler takes a string `message` and an `Error`
// object. If `raise_errors` is set to `true` on the app level,
// this will re-throw the error to the browser. Otherwise it will send the error
// to `log()`. Override this method to provide custom error handling
// e.g logging to a server side component or displaying some feedback to the
// user.
error: function(message, original_error) {
if (!original_error) { original_error = new Error(); }
original_error.message = [message, original_error.message].join(' ');
this.trigger('error', {message: original_error.message, error: original_error});
if (this.raise_errors) {
throw(original_error);
} else {
this.log(original_error.message, original_error);
}
},
_checkLocation: function() {
var location, returned;
// get current location
location = this.getLocation();
// compare to see if hash has changed
if (!this.last_location || this.last_location[0] != 'get' || this.last_location[1] != location) {
// reset last location
this.last_location = ['get', location];
// lookup route for current hash
returned = this.runRoute('get', location);
}
return returned;
},
_getFormVerb: function(form) {
var $form = $(form), verb, $_method;
$_method = $form.find('input[name="_method"]');
if ($_method.length > 0) { verb = $_method.val(); }
if (!verb) { verb = $form[0].getAttribute('method'); }
if (!verb || verb === '') { verb = 'get'; }
return $.trim(verb.toString().toLowerCase());
},
_checkFormSubmission: function(form) {
var $form, path, verb, params, returned;
this.trigger('check-form-submission', {form: form});
$form = $(form);
path = $form.attr('action') || '';
verb = this._getFormVerb($form);
if (this.debug) {
this.log('_checkFormSubmission', $form, path, verb);
}
if (verb === 'get') {
params = this._serializeFormParams($form);
if (params !== '') { path += '?' + params; }
this.setLocation(path);
returned = false;
} else {
params = $.extend({}, this._parseFormParams($form));
returned = this.runRoute(verb, path, params, form.get(0));
}
return (typeof returned == 'undefined') ? false : returned;
},
_serializeFormParams: function($form) {
var queryString = "",
fields = $form.serializeArray(),
i;
if (fields.length > 0) {
queryString = this._encodeFormPair(fields[0].name, fields[0].value);
for (i = 1; i < fields.length; i++) {
queryString = queryString + "&" + this._encodeFormPair(fields[i].name, fields[i].value);
}
}
return queryString;
},
_encodeFormPair: function(name, value){
return _encode(name) + "=" + _encode(value);
},
_parseFormParams: function($form) {
var params = {},
form_fields = $form.serializeArray(),
i;
for (i = 0; i < form_fields.length; i++) {
params = this._parseParamPair(params, form_fields[i].name, form_fields[i].value);
}
return params;
},
_parseQueryString: function(path) {
var params = {}, parts, pairs, pair, i;
parts = path.match(QUERY_STRING_MATCHER);
if (parts && parts[1]) {
pairs = parts[1].split('&');
for (i = 0; i < pairs.length; i++) {
pair = pairs[i].split('=');
params = this._parseParamPair(params, _decode(pair[0]), _decode(pair[1] || ""));
}
}
return params;
},
_parseParamPair: function(params, key, value) {
if (typeof params[key] !== 'undefined') {
if (_isArray(params[key])) {
params[key].push(value);
} else {
params[key] = [params[key], value];
}
} else {
params[key] = value;
}
return params;
},
_listen: function(name, callback) {
return this.$element().bind([name, this.eventNamespace()].join('.'), callback);
},
_unlisten: function(name, callback) {
return this.$element().unbind([name, this.eventNamespace()].join('.'), callback);
}
});
// `Sammy.RenderContext` is an object that makes sequential template loading,
// rendering and interpolation seamless even when dealing with asynchronous
// operations.
//
// `RenderContext` objects are not usually created directly, rather they are
// instantiated from an `Sammy.EventContext` by using `render()`, `load()` or
// `partial()` which all return `RenderContext` objects.
//
// `RenderContext` methods always returns a modified `RenderContext`
// for chaining (like jQuery itself).
//
// The core magic is in the `then()` method which puts the callback passed as
// an argument into a queue to be executed once the previous callback is complete.
// All the methods of `RenderContext` are wrapped in `then()` which allows you
// to queue up methods by chaining, but maintaining a guaranteed execution order
// even with remote calls to fetch templates.
//
Sammy.RenderContext = function(event_context) {
this.event_context = event_context;
this.callbacks = [];
this.previous_content = null;
this.content = null;
this.next_engine = false;
this.waiting = false;
};
Sammy.RenderContext.prototype = $.extend({}, Sammy.Object.prototype, {
// The "core" of the `RenderContext` object, adds the `callback` to the
// queue. If the context is `waiting` (meaning an async operation is happening)
// then the callback will be executed in order, once the other operations are
// complete. If there is no currently executing operation, the `callback`
// is executed immediately.
//
// The value returned from the callback is stored in `content` for the
// subsequent operation. If you return `false`, the queue will pause, and
// the next callback in the queue will not be executed until `next()` is
// called. This allows for the guaranteed order of execution while working
// with async operations.
//
// If then() is passed a string instead of a function, the string is looked
// up as a helper method on the event context.
//
// ### Example
//
// this.get('#/', function() {
// // initialize the RenderContext
// // Even though `load()` executes async, the next `then()`
// // wont execute until the load finishes
// this.load('myfile.txt')
// .then(function(content) {
// // the first argument to then is the content of the
// // prev operation
// $('#main').html(content);
// });
// });
//
then: function(callback) {
if (!_isFunction(callback)) {
// if a string is passed to then, assume we want to call
// a helper on the event context in its context
if (typeof callback === 'string' && callback in this.event_context) {
var helper = this.event_context[callback];
callback = function(content) {
return helper.apply(this.event_context, [content]);
};
} else {
return this;
}
}
var context = this;
if (this.waiting) {
this.callbacks.push(callback);
} else {
this.wait();
window.setTimeout(function() {
var returned = callback.apply(context, [context.content, context.previous_content]);
if (returned !== false) {
context.next(returned);
}
}, 0);
}
return this;
},
// Pause the `RenderContext` queue. Combined with `next()` allows for async
// operations.
//
// ### Example
//
// this.get('#/', function() {
// this.load('mytext.json')
// .then(function(content) {
// var context = this,
// data = JSON.parse(content);
// // pause execution
// context.wait();
// // post to a url
// $.post(data.url, {}, function(response) {
// context.next(JSON.parse(response));
// });
// })
// .then(function(data) {
// // data is json from the previous post
// $('#message').text(data.status);
// });
// });
wait: function() {
this.waiting = true;
},
// Resume the queue, setting `content` to be used in the next operation.
// See `wait()` for an example.
next: function(content) {
this.waiting = false;
if (typeof content !== 'undefined') {
this.previous_content = this.content;
this.content = content;
}
if (this.callbacks.length > 0) {
this.then(this.callbacks.shift());
}
},
// Load a template into the context.
// The `location` can either be a string specifying the remote path to the
// file, a jQuery object, or a DOM element.
//
// No interpolation happens by default, the content is stored in
// `content`.
//
// In the case of a path, unless the option `{cache: false}` is passed the
// data is stored in the app's `templateCache()`.
//
// If a jQuery or DOM object is passed the `innerHTML` of the node is pulled in.
// This is useful for nesting templates as part of the initial page load wrapped
// in invisible elements or `<script>` tags. With template paths, the template
// engine is looked up by the extension. For DOM/jQuery embedded templates,
// this isnt possible, so there are a couple of options:
//
// * pass an `{engine:}` option.
// * define the engine in the `data-engine` attribute of the passed node.
// * just store the raw template data and use `interpolate()` manually
//
// If a `callback` is passed it is executed after the template load.
load: function(location, options, callback) {
var context = this;
return this.then(function() {
var should_cache, cached, is_json, location_array;
if (_isFunction(options)) {
callback = options;
options = {};
} else {
options = $.extend({}, options);
}
if (callback) { this.then(callback); }
if (typeof location === 'string') {
// it's a path
is_json = (location.match(/\.json$/) || options.json);
should_cache = is_json ? options.cache === true : options.cache !== false;
context.next_engine = context.event_context.engineFor(location);
delete options.cache;
delete options.json;
if (options.engine) {
context.next_engine = options.engine;
delete options.engine;
}
if (should_cache && (cached = this.event_context.app.templateCache(location))) {
return cached;
}
this.wait();
$.ajax($.extend({
url: location,
data: {},
dataType: is_json ? 'json' : 'text',
type: 'get',
success: function(data) {
if (should_cache) {
context.event_context.app.templateCache(location, data);
}
context.next(data);
}
}, options));
return false;
} else {
// it's a dom/jQuery
if (location.nodeType) {
return location.innerHTML;
}
if (location.selector) {
// it's a jQuery
context.next_engine = location.attr('data-engine');
if (options.clone === false) {
return location.remove()[0].innerHTML.toString();
} else {
return location[0].innerHTML.toString();
}
}
}
});
},
// Load partials
//
// ### Example
//
// this.loadPartials({mypartial: '/path/to/partial'});
//
loadPartials: function(partials) {
var name;
if(partials) {
this.partials = this.partials || {};
for(name in partials) {
(function(context, name) {
context.load(partials[name])
.then(function(template) {
this.partials[name] = template;
});
})(this, name);
}
}
return this;
},
// `load()` a template and then `interpolate()` it with data.
//
// can be called with multiple different signatures:
//
// this.render(callback);
// this.render('/location');
// this.render('/location', {some: data});
// this.render('/location', callback);
// this.render('/location', {some: data}, callback);
// this.render('/location', {some: data}, {my: partials});
// this.render('/location', callback, {my: partials});
// this.render('/location', {some: data}, callback, {my: partials});
//
// ### Example
//
// this.get('#/', function() {
// this.render('mytemplate.template', {name: 'test'});
// });
//
render: function(location, data, callback, partials) {
if (_isFunction(location) && !data) {
// invoked as render(callback)
return this.then(location);
} else {
if(_isFunction(data)) {
// invoked as render(location, callback, [partials])
partials = callback;
callback = data;
data = null;
} else if(callback && !_isFunction(callback)) {
// invoked as render(location, data, partials)
partials = callback;
callback = null;
}
return this.loadPartials(partials)
.load(location)
.interpolate(data, location)
.then(callback);
}
},
// `render()` the `location` with `data` and then `swap()` the
// app's `$element` with the rendered content.
partial: function(location, data, callback, partials) {
if (_isFunction(callback)) {
// invoked as partial(location, data, callback, [partials])
return this.render(location, data, partials).swap(callback);
} else if (_isFunction(data)) {
// invoked as partial(location, callback, [partials])
return this.render(location, {}, callback).swap(data);
} else {
// invoked as partial(location, data, [partials])
return this.render(location, data, callback).swap();
}
},
// defers the call of function to occur in order of the render queue.
// The function can accept any number of arguments as long as the last
// argument is a callback function. This is useful for putting arbitrary
// asynchronous functions into the queue. The content passed to the
// callback is passed as `content` to the next item in the queue.
//
// ### Example
//
// this.send($.getJSON, '/app.json')
// .then(function(json) {
// $('#message).text(json['message']);
// });
//
//
send: function() {
var context = this,
args = _makeArray(arguments),
fun = args.shift();
if (_isArray(args[0])) { args = args[0]; }
return this.then(function(content) {
args.push(function(response) { context.next(response); });
context.wait();
fun.apply(fun, args);
return false;
});
},
// iterates over an array, applying the callback for each item item. the
// callback takes the same style of arguments as `jQuery.each()` (index, item).
// The return value of each callback is collected as a single string and stored
// as `content` to be used in the next iteration of the `RenderContext`.
collect: function(array, callback, now) {
var context = this;
var coll = function() {
if (_isFunction(array)) {
callback = array;
array = this.content;
}
var contents = [], doms = false;
$.each(array, function(i, item) {
var returned = callback.apply(context, [i, item]);
if (returned.jquery && returned.length == 1) {
returned = returned[0];
doms = true;
}
contents.push(returned);
return returned;
});
return doms ? contents : contents.join('');
};
return now ? coll() : this.then(coll);
},
// loads a template, and then interpolates it for each item in the `data`
// array. If a callback is passed, it will call the callback with each
// item in the array _after_ interpolation
renderEach: function(location, name, data, callback) {
if (_isArray(name)) {
callback = data;
data = name;
name = null;
}
return this.load(location).then(function(content) {
var rctx = this;
if (!data) {
data = _isArray(this.previous_content) ? this.previous_content : [];
}
if (callback) {
$.each(data, function(i, value) {
var idata = {}, engine = this.next_engine || location;
if (name) {
idata[name] = value;
} else {
idata = value;
}
callback(value, rctx.event_context.interpolate(content, idata, engine));
});
} else {
return this.collect(data, function(i, value) {
var idata = {}, engine = this.next_engine || location;
if (name) {
idata[name] = value;
} else {
idata = value;
}
return this.event_context.interpolate(content, idata, engine);
}, true);
}
});
},
// uses the previous loaded `content` and the `data` object to interpolate
// a template. `engine` defines the templating/interpolation method/engine
// that should be used. If `engine` is not passed, the `next_engine` is
// used. If `retain` is `true`, the final interpolated data is appended to
// the `previous_content` instead of just replacing it.
interpolate: function(data, engine, retain) {
var context = this;
return this.then(function(content, prev) {
if (!data && prev) { data = prev; }
if (this.next_engine) {
engine = this.next_engine;
this.next_engine = false;
}
var rendered = context.event_context.interpolate(content, data, engine, this.partials);
return retain ? prev + rendered : rendered;
});
},
// Swap the return contents ensuring order. See `Application#swap`
swap: function(callback) {
return this.then(function(content) {
this.event_context.swap(content, callback);
return content;
}).trigger('changed', {});
},
// Same usage as `jQuery.fn.appendTo()` but uses `then()` to ensure order
appendTo: function(selector) {
return this.then(function(content) {
$(selector).append(content);
}).trigger('changed', {});
},
// Same usage as `jQuery.fn.prependTo()` but uses `then()` to ensure order
prependTo: function(selector) {
return this.then(function(content) {
$(selector).prepend(content);
}).trigger('changed', {});
},
// Replaces the `$(selector)` using `html()` with the previously loaded
// `content`
replace: function(selector) {
return this.then(function(content) {
$(selector).html(content);
}).trigger('changed', {});
},
// trigger the event in the order of the event context. Same semantics
// as `Sammy.EventContext#trigger()`. If data is omitted, `content`
// is sent as `{content: content}`
trigger: function(name, data) {
return this.then(function(content) {
if (typeof data == 'undefined') { data = {content: content}; }
this.event_context.trigger(name, data);
return content;
});
}
});
// `Sammy.EventContext` objects are created every time a route is run or a
// bound event is triggered. The callbacks for these events are evaluated within a `Sammy.EventContext`
// This within these callbacks the special methods of `EventContext` are available.
//
// ### Example
//
// $.sammy(function() {
// // The context here is this Sammy.Application
// this.get('#/:name', function() {
// // The context here is a new Sammy.EventContext
// if (this.params['name'] == 'sammy') {
// this.partial('name.html.erb', {name: 'Sammy'});
// } else {
// this.redirect('#/somewhere-else')
// }
// });
// });
//
// Initialize a new EventContext
//
// ### Arguments
//
// * `app` The `Sammy.Application` this event is called within.
// * `verb` The verb invoked to run this context/route.
// * `path` The string path invoked to run this context/route.
// * `params` An Object of optional params to pass to the context. Is converted
// to a `Sammy.Object`.
// * `target` a DOM element that the event that holds this context originates
// from. For post, put and del routes, this is the form element that triggered
// the route.
//
Sammy.EventContext = function(app, verb, path, params, target) {
this.app = app;
this.verb = verb;
this.path = path;
this.params = new Sammy.Object(params);
this.target = target;
};
Sammy.EventContext.prototype = $.extend({}, Sammy.Object.prototype, {
// A shortcut to the app's `$element()`
$element: function() {
return this.app.$element(_makeArray(arguments).shift());
},
// Look up a templating engine within the current app and context.
// `engine` can be one of the following:
//
// * a function: should conform to `function(content, data) { return interpolated; }`
// * a template path: 'template.ejs', looks up the extension to match to
// the `ejs()` helper
// * a string referring to the helper: "mustache" => `mustache()`
//
// If no engine is found, use the app's default `template_engine`
//
engineFor: function(engine) {
var context = this, engine_match;
// if path is actually an engine function just return it
if (_isFunction(engine)) { return engine; }
// lookup engine name by path extension
engine = (engine || context.app.template_engine).toString();
if ((engine_match = engine.match(/\.([^\.\?\#]+)$/))) {
engine = engine_match[1];
}
// set the engine to the default template engine if no match is found
if (engine && _isFunction(context[engine])) {
return context[engine];
}
if (context.app.template_engine) {
return this.engineFor(context.app.template_engine);
}
return function(content, data) { return content; };
},
// using the template `engine` found with `engineFor()`, interpolate the
// `data` into `content`
interpolate: function(content, data, engine, partials) {
return this.engineFor(engine).apply(this, [content, data, partials]);
},
// Create and return a `Sammy.RenderContext` calling `render()` on it.
// Loads the template and interpolate the data, however does not actual
// place it in the DOM.
//
// ### Example
//
// // mytemplate.mustache <div class="name">{{name}}</div>
// render('mytemplate.mustache', {name: 'quirkey'});
// // sets the `content` to <div class="name">quirkey</div>
// render('mytemplate.mustache', {name: 'quirkey'})
// .appendTo('ul');
// // appends the rendered content to $('ul')
//
render: function(location, data, callback, partials) {
return new Sammy.RenderContext(this).render(location, data, callback, partials);
},
// Create and return a `Sammy.RenderContext` calling `renderEach()` on it.
// Loads the template and interpolates the data for each item,
// however does not actual place it in the DOM.
//
// ### Example
//
// // mytemplate.mustache <div class="name">{{name}}</div>
// renderEach('mytemplate.mustache', [{name: 'quirkey'}, {name: 'endor'}])
// // sets the `content` to <div class="name">quirkey</div><div class="name">endor</div>
// renderEach('mytemplate.mustache', [{name: 'quirkey'}, {name: 'endor'}]).appendTo('ul');
// // appends the rendered content to $('ul')
//
renderEach: function(location, name, data, callback) {
return new Sammy.RenderContext(this).renderEach(location, name, data, callback);
},
// create a new `Sammy.RenderContext` calling `load()` with `location` and
// `options`. Called without interpolation or placement, this allows for
// preloading/caching the templates.
load: function(location, options, callback) {
return new Sammy.RenderContext(this).load(location, options, callback);
},
// create a new `Sammy.RenderContext` calling `loadPartials()` with `partials`.
loadPartials: function(partials) {
return new Sammy.RenderContext(this).loadPartials(partials);
},
// `render()` the `location` with `data` and then `swap()` the
// app's `$element` with the rendered content.
partial: function(location, data, callback, partials) {
return new Sammy.RenderContext(this).partial(location, data, callback, partials);
},
// create a new `Sammy.RenderContext` calling `send()` with an arbitrary
// function
send: function() {
var rctx = new Sammy.RenderContext(this);
return rctx.send.apply(rctx, arguments);
},
// Changes the location of the current window. If `to` begins with
// '#' it only changes the document's hash. If passed more than 1 argument
// redirect will join them together with forward slashes.
//
// ### Example
//
// redirect('#/other/route');
// // equivalent to
// redirect('#', 'other', 'route');
//
redirect: function() {
var to, args = _makeArray(arguments),
current_location = this.app.getLocation(),
l = args.length;
if (l > 1) {
var i = 0, paths = [], pairs = [], params = {}, has_params = false;
for (; i < l; i++) {
if (typeof args[i] == 'string') {
paths.push(args[i]);
} else {
$.extend(params, args[i]);
has_params = true;
}
}
to = paths.join('/');
if (has_params) {
for (var k in params) {
pairs.push(this.app._encodeFormPair(k, params[k]));
}
to += '?' + pairs.join('&');
}
} else {
to = args[0];
}
this.trigger('redirect', {to: to});
this.app.last_location = [this.verb, this.path];
this.app.setLocation(to);
if (new RegExp(to).test(current_location)) {
this.app.trigger('location-changed');
}
},
// Triggers events on `app` within the current context.
trigger: function(name, data) {
if (typeof data == 'undefined') { data = {}; }
if (!data.context) { data.context = this; }
return this.app.trigger(name, data);
},
// A shortcut to app's `eventNamespace()`
eventNamespace: function() {
return this.app.eventNamespace();
},
// A shortcut to app's `swap()`
swap: function(contents, callback) {
return this.app.swap(contents, callback);
},
// Raises a possible `notFound()` error for the current path.
notFound: function() {
return this.app.notFound(this.verb, this.path);
},
// Default JSON parsing uses jQuery's `parseJSON()`. Include `Sammy.JSON`
// plugin for the more conformant "crockford special".
json: function(string) {
return $.parseJSON(string);
},
// //=> Sammy.EventContext: get #/ {}
toString: function() {
return "Sammy.EventContext: " + [this.verb, this.path, this.params].join(' ');
}
});
return Sammy;
});
})(jQuery, window);
html,
body {
margin: 0;
padding: 0;
}
button {
margin: 0;
padding: 0;
border: 0;
background: none;
font-size: 100%;
vertical-align: baseline;
font-family: inherit;
color: inherit;
-webkit-appearance: none;
/*-moz-appearance: none;*/
-ms-appearance: none;
-o-appearance: none;
appearance: none;
}
body {
font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif;
line-height: 1.4em;
background: #eaeaea url('bg.png');
color: #4d4d4d;
width: 550px;
margin: 0 auto;
-webkit-font-smoothing: antialiased;
-moz-font-smoothing: antialiased;
-ms-font-smoothing: antialiased;
-o-font-smoothing: antialiased;
font-smoothing: antialiased;
}
#todoapp {
background: #fff;
background: rgba(255, 255, 255, 0.9);
margin: 130px 0 40px 0;
border: 1px solid #ccc;
position: relative;
border-top-left-radius: 2px;
border-top-right-radius: 2px;
box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.2),
0 25px 50px 0 rgba(0, 0, 0, 0.15);
}
#todoapp:before {
content: '';
border-left: 1px solid #f5d6d6;
border-right: 1px solid #f5d6d6;
width: 2px;
position: absolute;
top: 0;
left: 40px;
height: 100%;
}
#todoapp input::-webkit-input-placeholder {
font-style: italic;
}
#todoapp input::-moz-placeholder {
font-style: italic;
color: #a9a9a9;
}
#todoapp h1 {
position: absolute;
top: -120px;
width: 100%;
font-size: 70px;
font-weight: bold;
text-align: center;
color: #b3b3b3;
color: rgba(255, 255, 255, 0.3);
text-shadow: -1px -1px rgba(0, 0, 0, 0.2);
-webkit-text-rendering: optimizeLegibility;
-moz-text-rendering: optimizeLegibility;
-ms-text-rendering: optimizeLegibility;
-o-text-rendering: optimizeLegibility;
text-rendering: optimizeLegibility;
}
#header {
padding-top: 15px;
border-radius: inherit;
}
#header:before {
content: '';
position: absolute;
top: 0;
right: 0;
left: 0;
height: 15px;
z-index: 2;
border-bottom: 1px solid #6c615c;
background: #8d7d77;
background: -webkit-gradient(linear, left top, left bottom, from(rgba(132, 110, 100, 0.8)),to(rgba(101, 84, 76, 0.8)));
background: -webkit-linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8));
background: -moz-linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8));
background: -o-linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8));
background: -ms-linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8));
background: linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8));
filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0,StartColorStr='#9d8b83', EndColorStr='#847670');
border-top-left-radius: 1px;
border-top-right-radius: 1px;
}
#new-todo,
.edit {
position: relative;
margin: 0;
width: 100%;
font-size: 24px;
font-family: inherit;
line-height: 1.4em;
border: 0;
outline: none;
color: inherit;
padding: 6px;
border: 1px solid #999;
box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2);
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
-ms-box-sizing: border-box;
-o-box-sizing: border-box;
box-sizing: border-box;
-webkit-font-smoothing: antialiased;
-moz-font-smoothing: antialiased;
-ms-font-smoothing: antialiased;
-o-font-smoothing: antialiased;
font-smoothing: antialiased;
}
#new-todo {
padding: 16px 16px 16px 60px;
border: none;
background: rgba(0, 0, 0, 0.02);
z-index: 2;
box-shadow: none;
}
#main {
position: relative;
z-index: 2;
border-top: 1px dotted #adadad;
}
label[for='toggle-all'] {
display: none;
}
#toggle-all {
position: absolute;
top: -42px;
left: -4px;
width: 40px;
text-align: center;
border: none; /* Mobile Safari */
}
#toggle-all:before {
content: '»';
font-size: 28px;
color: #d9d9d9;
padding: 0 25px 7px;
}
#toggle-all:checked:before {
color: #737373;
}
#todo-list {
margin: 0;
padding: 0;
list-style: none;
}
#todo-list li {
position: relative;
font-size: 24px;
border-bottom: 1px dotted #ccc;
}
#todo-list li:last-child {
border-bottom: none;
}
#todo-list li.editing {
border-bottom: none;
padding: 0;
}
#todo-list li.editing .edit {
display: block;
width: 506px;
padding: 13px 17px 12px 17px;
margin: 0 0 0 43px;
}
#todo-list li.editing .view {
display: none;
}
#todo-list li .toggle {
text-align: center;
width: 40px;
/* auto, since non-WebKit browsers doesn't support input styling */
height: auto;
position: absolute;
top: 0;
bottom: 0;
margin: auto 0;
border: none; /* Mobile Safari */
-webkit-appearance: none;
/*-moz-appearance: none;*/
-ms-appearance: none;
-o-appearance: none;
appearance: none;
}
#todo-list li .toggle:after {
content: '✔';
line-height: 43px; /* 40 + a couple of pixels visual adjustment */
font-size: 20px;
color: #d9d9d9;
text-shadow: 0 -1px 0 #bfbfbf;
}
#todo-list li .toggle:checked:after {
color: #85ada7;
text-shadow: 0 1px 0 #669991;
bottom: 1px;
position: relative;
}
#todo-list li label {
word-break: break-word;
padding: 15px;
margin-left: 45px;
display: block;
line-height: 1.2;
-webkit-transition: color 0.4s;
-moz-transition: color 0.4s;
-ms-transition: color 0.4s;
-o-transition: color 0.4s;
transition: color 0.4s;
}
#todo-list li.completed label {
color: #a9a9a9;
text-decoration: line-through;
}
#todo-list li .destroy {
display: none;
position: absolute;
top: 0;
right: 10px;
bottom: 0;
width: 40px;
height: 40px;
margin: auto 0;
font-size: 22px;
color: #a88a8a;
-webkit-transition: all 0.2s;
-moz-transition: all 0.2s;
-ms-transition: all 0.2s;
-o-transition: all 0.2s;
transition: all 0.2s;
}
#todo-list li .destroy:hover {
text-shadow: 0 0 1px #000,
0 0 10px rgba(199, 107, 107, 0.8);
-webkit-transform: scale(1.3);
-moz-transform: scale(1.3);
-ms-transform: scale(1.3);
-o-transform: scale(1.3);
transform: scale(1.3);
}
#todo-list li .destroy:after {
content: '✖';
}
#todo-list li:hover .destroy {
display: block;
}
#todo-list li .edit {
display: none;
}
#todo-list li.editing:last-child {
margin-bottom: -1px;
}
#footer {
color: #777;
padding: 0 15px;
position: absolute;
right: 0;
bottom: -31px;
left: 0;
height: 20px;
z-index: 1;
text-align: center;
}
#footer:before {
content: '';
position: absolute;
right: 0;
bottom: 31px;
left: 0;
height: 50px;
z-index: -1;
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.3),
0 6px 0 -3px rgba(255, 255, 255, 0.8),
0 7px 1px -3px rgba(0, 0, 0, 0.3),
0 43px 0 -6px rgba(255, 255, 255, 0.8),
0 44px 2px -6px rgba(0, 0, 0, 0.2);
}
#todo-count {
float: left;
text-align: left;
}
#filters {
margin: 0;
padding: 0;
list-style: none;
position: absolute;
right: 0;
left: 0;
}
#filters li {
display: inline;
}
#filters li a {
color: #83756f;
margin: 2px;
text-decoration: none;
}
#filters li a.selected {
font-weight: bold;
}
#clear-completed {
float: right;
position: relative;
line-height: 20px;
text-decoration: none;
background: rgba(0, 0, 0, 0.1);
font-size: 11px;
padding: 0 10px;
border-radius: 3px;
box-shadow: 0 -1px 0 0 rgba(0, 0, 0, 0.2);
}
#clear-completed:hover {
background: rgba(0, 0, 0, 0.15);
box-shadow: 0 -1px 0 0 rgba(0, 0, 0, 0.3);
}
#info {
margin: 65px auto 0;
color: #a6a6a6;
font-size: 12px;
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.7);
text-align: center;
}
#info a {
color: inherit;
}
/*
Hack to remove background from Mobile Safari.
Can't use it globally since it destroys checkboxes in Firefox and Opera
*/
@media screen and (-webkit-min-device-pixel-ratio:0) {
#toggle-all,
#todo-list li .toggle {
background: none;
}
#todo-list li .toggle {
height: 40px;
}
#toggle-all {
top: -56px;
left: -15px;
width: 65px;
height: 41px;
-webkit-transform: rotate(90deg);
transform: rotate(90deg);
-webkit-appearance: none;
appearance: none;
}
}
.hidden{
display:none;
}
hr {
margin: 20px 0;
border: 0;
border-top: 1px dashed #C5C5C5;
border-bottom: 1px dashed #F7F7F7;
}
.learn a {
font-weight: normal;
text-decoration: none;
color: #b83f45;
}
.learn a:hover {
text-decoration: underline;
color: #787e7e;
}
.learn h3,
.learn h4,
.learn h5 {
margin: 10px 0;
font-weight: 500;
line-height: 1.2;
color: #000;
}
.learn h3 {
font-size: 24px;
}
.learn h4 {
font-size: 18px;
}
.learn h5 {
margin-bottom: 0;
font-size: 14px;
}
.learn ul {
padding: 0;
margin: 0 0 30px 25px;
}
.learn li {
line-height: 20px;
}
.learn p {
font-size: 15px;
font-weight: 300;
line-height: 1.3;
margin-top: 0;
margin-bottom: 0;
}
.quote {
border: none;
margin: 20px 0 60px 0;
}
.quote p {
font-style: italic;
}
.quote p:before {
content: '“';
font-size: 50px;
opacity: .15;
position: absolute;
top: -20px;
left: 3px;
}
.quote p:after {
content: '”';
font-size: 50px;
opacity: .15;
position: absolute;
bottom: -42px;
right: 3px;
}
.quote footer {
position: absolute;
bottom: -40px;
right: 0;
}
.quote footer img {
border-radius: 3px;
}
.quote footer a {
margin-left: 5px;
vertical-align: middle;
}
.speech-bubble {
position: relative;
padding: 10px;
background: rgba(0, 0, 0, .04);
border-radius: 5px;
}
.speech-bubble:after {
content: '';
position: absolute;
top: 100%;
right: 30px;
border: 13px solid transparent;
border-top-color: rgba(0, 0, 0, .04);
}
/**body*/.learn-bar > .learn {
position: absolute;
width: 272px;
top: 8px;
left: -300px;
padding: 10px;
border-radius: 5px;
background-color: rgba(255, 255, 255, .6);
transition-property: left;
transition-duration: 500ms;
}
@media (min-width: 899px) {
/**body*/.learn-bar {
width: auto;
margin: 0 0 0 300px;
}
/**body*/.learn-bar > .learn {
left: 8px;
}
/**body*/.learn-bar #todoapp {
width: 550px;
margin: 130px auto 40px auto;
}
}
(function () {
'use strict';
// Underscore's Template Module
// Courtesy of underscorejs.org
var _ = (function (_) {
_.defaults = function (object) {
if (!object) {
return object;
}
for (var argsIndex = 1, argsLength = arguments.length; argsIndex < argsLength; argsIndex++) {
var iterable = arguments[argsIndex];
if (iterable) {
for (var key in iterable) {
if (object[key] == null) {
object[key] = iterable[key];
}
}
}
}
return object;
}
// By default, Underscore uses ERB-style template delimiters, change the
// following template settings to use alternative delimiters.
_.templateSettings = {
evaluate : /<%([\s\S]+?)%>/g,
interpolate : /<%=([\s\S]+?)%>/g,
escape : /<%-([\s\S]+?)%>/g
};
// When customizing `templateSettings`, if you don't want to define an
// interpolation, evaluation or escaping regex, we need one that is
// guaranteed not to match.
var noMatch = /(.)^/;
// Certain characters need to be escaped so that they can be put into a
// string literal.
var escapes = {
"'": "'",
'\\': '\\',
'\r': 'r',
'\n': 'n',
'\t': 't',
'\u2028': 'u2028',
'\u2029': 'u2029'
};
var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g;
// JavaScript micro-templating, similar to John Resig's implementation.
// Underscore templating handles arbitrary delimiters, preserves whitespace,
// and correctly escapes quotes within interpolated code.
_.template = function(text, data, settings) {
var render;
settings = _.defaults({}, settings, _.templateSettings);
// Combine delimiters into one regular expression via alternation.
var matcher = new RegExp([
(settings.escape || noMatch).source,
(settings.interpolate || noMatch).source,
(settings.evaluate || noMatch).source
].join('|') + '|$', 'g');
// Compile the template source, escaping string literals appropriately.
var index = 0;
var source = "__p+='";
text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
source += text.slice(index, offset)
.replace(escaper, function(match) { return '\\' + escapes[match]; });
if (escape) {
source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
}
if (interpolate) {
source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
}
if (evaluate) {
source += "';\n" + evaluate + "\n__p+='";
}
index = offset + match.length;
return match;
});
source += "';\n";
// If a variable is not specified, place data values in local scope.
if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';
source = "var __t,__p='',__j=Array.prototype.join," +
"print=function(){__p+=__j.call(arguments,'');};\n" +
source + "return __p;\n";
try {
render = new Function(settings.variable || 'obj', '_', source);
} catch (e) {
e.source = source;
throw e;
}
if (data) return render(data, _);
var template = function(data) {
return render.call(this, data, _);
};
// Provide the compiled function source as a convenience for precompilation.
template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}';
return template;
};
return _;
})({});
if (location.hostname === 'todomvc.com') {
window._gaq = [['_setAccount','UA-31081062-1'],['_trackPageview']];(function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];g.src='//www.google-analytics.com/ga.js';s.parentNode.insertBefore(g,s)}(document,'script'));
}
function redirect() {
if (location.hostname === 'tastejs.github.io') {
location.href = location.href.replace('tastejs.github.io/todomvc', 'todomvc.com');
}
}
function findRoot() {
var base;
[/labs/, /\w*-examples/].forEach(function (href) {
var match = location.href.match(href);
if (!base && match) {
base = location.href.indexOf(match);
}
});
return location.href.substr(0, base);
}
function getFile(file, callback) {
if (!location.host) {
return console.info('Miss the info bar? Run TodoMVC from a server to avoid a cross-origin error.');
}
var xhr = new XMLHttpRequest();
xhr.open('GET', findRoot() + file, true);
xhr.send();
xhr.onload = function () {
if (xhr.status === 200 && callback) {
callback(xhr.responseText);
}
};
}
function Learn(learnJSON, config) {
if (!(this instanceof Learn)) {
return new Learn(learnJSON, config);
}
var template, framework;
if (typeof learnJSON !== 'object') {
try {
learnJSON = JSON.parse(learnJSON);
} catch (e) {
return;
}
}
if (config) {
template = config.template;
framework = config.framework;
}
if (!template && learnJSON.templates) {
template = learnJSON.templates.todomvc;
}
if (!framework && document.querySelector('[data-framework]')) {
framework = document.querySelector('[data-framework]').getAttribute('data-framework');
}
if (template && learnJSON[framework]) {
this.frameworkJSON = learnJSON[framework];
this.template = template;
this.append();
}
}
Learn.prototype.append = function () {
var aside = document.createElement('aside');
aside.innerHTML = _.template(this.template, this.frameworkJSON);
aside.className = 'learn';
// Localize demo links
var demoLinks = aside.querySelectorAll('.demo-link');
Array.prototype.forEach.call(demoLinks, function (demoLink) {
demoLink.setAttribute('href', findRoot() + demoLink.getAttribute('href'));
});
document.body.className = (document.body.className + ' learn-bar').trim();
document.body.insertAdjacentHTML('afterBegin', aside.outerHTML);
};
redirect();
getFile('learn.json', Learn);
})();
.splash {
text-align: center;
margin: 10% 0 0 0;
}
.splash .message {
font-size: 5em;
line-height: 1.5em;
-webkit-text-shadow: rgba(0, 0, 0, 0.5) 0px 0px 15px;
text-shadow: rgba(0, 0, 0, 0.5) 0px 0px 15px;
text-transform: uppercase;
}
.splash .icon-spinner {
text-align: center;
display: inline-block;
font-size: 5em;
margin-top: 50px;
}
.page-host {
position: relative;
top: 40px;
}
.navbar-fixed-top .navbar-inner {
padding-left: 1em;
padding-right: 1em;
}
.navbar-fixed-top .icon-home {
font-size: 18px
}
.loader {
margin: 6px 8px 4px 8px;
visibility: hidden;
}
.loader.active {
visibility: visible;
}
@media (max-width: 979px) {
.page-host {
top: 0;
}
.navbar-fixed-top {
margin-bottom: 0;
}
}
\ No newline at end of file
<!doctype html>
<html lang="en" data-framework="durandal">
<head>
<meta charset="utf-8">
<meta content="IE=edge" http-equiv="X-UA-Compatible">
<title>Durandal • TodoMVC</title>
<link rel="stylesheet" href="bower_components/todomvc-common/base.css">
<link rel="stylesheet" href="css/app.css">
</head>
<body>
<div id="applicationHost">
<!-- This is where the shell will be loaded into by idetifying as 'applicationHost' -->
</div>
<script src="bower_components/todomvc-common/base.js"></script>
<script src="bower_components/jquery/jquery.js"></script>
<script src="bower_components/knockout/knockout.js"></script>
<script src="bower_components/sammy/sammy.js"></script>
<script src="bower_components/requirejs/require.js" data-main="../durandal/js/main.js"></script>
</body>
</html>
/*global requirejs, define, ko */
(function () {
'use strict';
requirejs.config({
paths: {
'text': 'bower_components/durandal/amd/text'
},
baseUrl: './'
});
var ENTER_KEY = 13;
var ESCAPE_KEY = 27;
// a custom binding to handle the enter key (could go in a separate library)
ko.bindingHandlers.enterKey = {
init: function (element, valueAccessor, allBindingsAccessor, data) {
var wrappedHandler, newValueAccessor;
// wrap the handler with a check for the enter key
wrappedHandler = function (data, event) {
if (event.keyCode === ENTER_KEY) {
valueAccessor().call(this, data, event);
}
};
// create a valueAccessor with the options that we would want to pass to the event binding
newValueAccessor = function () {
return {
keyup: wrappedHandler
};
};
// call the real event binding's init function
ko.bindingHandlers.event.init(element, newValueAccessor, allBindingsAccessor, data);
}
};
// a custom binding to handle the enter key (could go in a separate library)
ko.bindingHandlers.escKey = {
init: function (element, valueAccessor, allBindingsAccessor, data) {
var wrappedHandler, newValueAccessor;
// wrap the handler with a check for the enter key
wrappedHandler = function (data, event) {
if (event.keyCode === ESCAPE_KEY) {
valueAccessor().call(this, data, event);
}
};
// create a valueAccessor with the options that we would want to pass to the event binding
newValueAccessor = function () {
return {
keyup: wrappedHandler
};
};
// call the real event binding's init function
ko.bindingHandlers.event.init(element, newValueAccessor, allBindingsAccessor, data);
}
};
// wrapper to hasfocus that also selects text and applies focus async
ko.bindingHandlers.selectAndFocus = {
init: function (element, valueAccessor, allBindingsAccessor) {
ko.bindingHandlers.hasfocus.init(element, valueAccessor, allBindingsAccessor);
ko.utils.registerEventHandler(element, 'focus', function () {
element.focus();
});
},
update: function (element, valueAccessor) {
ko.utils.unwrapObservable(valueAccessor()); // for dependency
// ensure that element is visible before trying to focus
setTimeout(function () {
ko.bindingHandlers.hasfocus.update(element, valueAccessor);
}, 0);
}
};
define(['bower_components/durandal/app',
'bower_components/durandal/viewLocator',
'bower_components/durandal/system',
'bower_components/durandal/plugins/router'],
function (app, viewLocator, system, router) {
//>>excludeStart("build", true);
system.debug(true);
//>>excludeEnd("build");
// this ensures that the title is simply the caption provided on the route
app.title = undefined;
app.start().then(function () {
// Replace 'viewmodels' in the moduleId with 'views' to locate the view.
// Look for partial views in a 'views' folder in the root.
viewLocator.useConvention();
// configure routing
router.useConvention('js/viewmodels');
router.mapNav({
url: '/',
moduleId: 'js/viewmodels/todoapp',
name: 'TodoMVC',
caption: 'Durandal • TodoMVC'
});
router.mapNav({
url: '#/:filter',
moduleId: 'js/viewmodels/todoapp',
name: 'TodoMVC',
hash: '#/filter',
caption: 'Durandal • TodoMVC'
});
app.adaptToDevice();
// Show the app by setting the root view model for our application with a transition.
app.setRoot('js/viewmodels/shell');
});
});
}());
\ No newline at end of file
/*global define, ko */
define([
'bower_components/durandal/app'
], function (app) {
'use strict';
var ViewModel = function () {
var self = this;
// store the new todo value being entered
self.current = ko.observable();
// add a new todo, when enter key is pressed
self.add = function () {
var current = self.current().trim();
if (current) {
app.trigger('todoitem', current);
self.current('');
}
};
};
return ViewModel;
});
\ No newline at end of file
/*global define, ko */
define([
'bower_components/durandal/app',
'js/viewmodels/shell'
], function (app, shell) {
'use strict';
// represent a single todo item
var Todo = function (title, completed) {
this.title = ko.observable(title);
this.completed = ko.observable(completed);
};
var ViewModel = function () {
var self = this;
self.activate = function () {
// initialize the show mode
var filter = shell.filter;
if (filter === undefined) {
filter = 'all';
}
self.showMode(filter);
// check local storage for todos
var todosFromlocalStorage = ko.utils.parseJson(localStorage.getItem('todos-durandal'));
todosFromlocalStorage = ko.utils.arrayMap(todosFromlocalStorage, function (todo) {
return new Todo(todo.title, todo.completed);
});
self.todos(todosFromlocalStorage);
// internal computed observable that fires whenever anything changes in our todos
ko.computed(function () {
// store a clean copy to local storage, which also creates a dependency on the observableArray and all observables in each item
localStorage.setItem('todos-durandal', ko.toJSON(self.todos()));
}).extend({
throttle: 500
}); // save at most twice per second
};
app.on('todoitem', function (item) {
self.todos.push(new Todo(item));
});
// map array of passed in todos to an observableArray of Todo objects
self.todos = ko.observableArray();
self.showMode = ko.observable('all');
self.filteredTodos = ko.computed(function () {
switch (self.showMode()) {
case 'active':
return self.todos().filter(function (todo) {
return !todo.completed();
});
case 'completed':
return self.todos().filter(function (todo) {
return todo.completed();
});
default:
return self.todos();
}
});
self.itemBeingEdited = ko.observable(undefined);
// remove a single todo
self.remove = function (todo) {
self.todos.remove(todo);
};
self.editTitle = ko.observable(''); // shadow variable so that the edit can be discarded on escape
self.cancelEdit = false;
// remove all completed todos
self.removeCompleted = function () {
self.todos.remove(function (todo) {
return todo.completed();
});
};
self.isThisItemBeingEdited = function (todo) {
return (todo === self.itemBeingEdited());
};
self.cancelEditing = function () {
self.itemBeingEdited(undefined);
self.cancelEdit = true;
};
// edit an item
self.editItem = function (item) {
self.itemBeingEdited(item);
self.editTitle(item.title());
self.cancelEdit = false;
};
// stop editing an item. Remove the item, if it is now empty
self.stopEditing = function (item) {
if (!self.cancelEdit) {
self.itemBeingEdited(undefined);
//trim and save back
var trimmed = self.editTitle().trim();
item.title(trimmed);
if (!trimmed) {
self.remove(item);
}
}
};
// count of all completed todos
self.completedCount = ko.computed(function () {
return ko.utils.arrayFilter(self.todos(), function (todo) {
return todo.completed();
}).length;
});
// count of todos that are not complete
self.remainingCount = ko.computed(function () {
return self.todos().length - self.completedCount();
});
// writeable computed observable to handle marking all complete/incomplete
self.allCompleted = ko.computed({
//always return true/false based on the done flag of all todos
read: function () {
return !self.remainingCount();
},
// set all todos to the written value (true/false)
write: function (newValue) {
ko.utils.arrayForEach(self.todos(), function (todo) {
// set even if value is the same, as subscribers are not notified in that case
todo.completed(newValue);
});
}
});
// helper function to keep expressions out of markup
self.getLabel = function (count) {
return ko.utils.unwrapObservable(count) === 1 ? 'item' : 'items';
};
};
return ViewModel;
});
\ No newline at end of file
/*global define*/
define([
'bower_components/durandal/plugins/router',
], function (router) {
'use strict';
return {
router: router,
filter: undefined, // this is used as the global cache to figure out the filter in effect.
activate: function () {
return router.activate('todoapp');
}
};
});
\ No newline at end of file
/*global define */
define([
'js/viewmodels/shell'
], function (shell) {
'use strict';
var ViewModel = function () {
var self = this;
self.activate = function (context) {
shell.filter = context.filter;
return true;
};
};
return ViewModel;
});
\ No newline at end of file
<header id="header">
<h1>todos</h1>
<input id="new-todo" data-bind="value: current, valueUpdate: 'afterkeydown', enterKey: add" placeholder="What needs to be done?" autofocus>
</header>
<section id="main" data-bind="visible: todos().length">
<div>
<input id="toggle-all" data-bind="checked: allCompleted" type="checkbox">
<label for="toggle-all">Mark all as complete</label>
</div>
<ul id="todo-list" data-bind="foreach: filteredTodos">
<li data-bind="css: { completed: completed, editing: $root.isThisItemBeingEdited($data) }">
<div class="view">
<input class="toggle" data-bind="checked: completed" type="checkbox">
<label data-bind="text: title, event: { dblclick: $root.editItem }"></label>
<button class="destroy" data-bind="click: $root.remove"></button>
</div>
<input class="edit" data-bind="value: $root.editTitle, valueUpdate: 'afterkeydown', escKey : $root.cancelEditing, enterKey: $root.stopEditing, selectAndFocus: $root.isThisItemBeingEdited($data), event: { blur: $root.stopEditing }">
</li>
</ul>
</section>
<footer id="footer" data-bind="visible: completedCount() || remainingCount()">
<span id="todo-count">
<strong data-bind="text: remainingCount">0</strong>
<span data-bind="text: getLabel( remainingCount )"></span> left
</span>
<ul id="filters">
<li>
<a data-bind="css: { selected: showMode() == 'all' }" href="#/all" >All</a>
</li>
<li>
<a data-bind="css: { selected: showMode() == 'active' }" href="#/active">Active</a>
</li>
<li>
<a data-bind="css: { selected: showMode() == 'completed' }" href="#/completed">Completed</a>
</li>
</ul>
<button id="clear-completed" data-bind="visible: completedCount, click: removeCompleted">
Clear completed (<span data-bind="text: completedCount"></span>)
</button>
</footer>
\ No newline at end of file
<div>
<div>
<!--ko compose: {
model: router.activeItem, // wiring the router
afterCompose: router.afterCompose, // wiring the router
cacheViews: true // telling composition to keep views in the dom, and reuse them (only a good idea with singleton view models)
}--><!--/ko-->
</div>
<footer id="info">
<p>Double-click to edit a todo</p>
<p>Original Knockout version from <a href="https://github.com/abhinavgujjar/durandal-todos">Abhinav Gujjar</a></p>
<p>Part of <a href="http://todomvc.com">TodoMVC</a></p>
</footer>
</div>
\ No newline at end of file
<section id="todoapp">
<!--ko compose: {
model: 'js/viewmodels/entry', activate: true
}--><!--/ko-->
<div>
<!--ko compose: {
model: 'js/viewmodels/list', activate: true
}--><!--/ko-->
</div>
</section>
\ No newline at end of file
# Durandal TodoMVC Example
> Single Page Apps Done Right.
> _[Durandal - durandaljs.com](http://durandaljs.com/)_
## Learning Durandal
The [Durandal website](http://durandaljs.com) is a great resource for getting started.
Here are some links you may find helpful:
* [Getting Started](http://durandaljs.com/pages/get-started/)
* [Documentation](http://durandaljs.com/pages/docs)
* [Videos](http://durandaljs.com/pages/videos/)
* [Durandal on GitHub](https://github.com/BlueSpire/Durandal)
Articles and guides from the community:
* [HotTowel Template - Durandal with ASP.Net MVC](http://www.johnpapa.net/hottowel/)
* [nuGet Download](http://www.nuget.org/packages/Durandal/)
Get help from other Durandal users:
* [Mailing list on Google Groups](https://groups.google.com/forum/#!forum/durandaljs)
* [Durandal on Twitter](http://twitter.com/durandaljs)
_If you have other helpful links to share, or find any of the links above no longer work, please [let us know](https://github.com/tastejs/todomvc/issues)._
## Credit
This Durandal TodoMVC application was created by [Abhinav Gujjar](https://github.com/abhinavgujjar).
......@@ -694,6 +694,56 @@
}]
}]
},
"durandal": {
"name": "Durandal",
"description": "Single Page Apps Done Right..",
"homepage": "http://durandaljs.com",
"examples": [{
"name": "Dependency Example",
"url": "labs/dependency-examples/durandal/index.html"
}],
"link_groups": [{
"heading": "Official Resources",
"links": [{
"name": "Getting Started",
"url": "http://durandaljs.com/pages/get-started/"
}, {
"name": "Documentation",
"url": "http://durandaljs.com/pages/docs"
}, {
"name": "Videos",
"url": "http://durandaljs.com/pages/videos/"
}, {
"name": "Durandal on GitHub",
"url": "https://github.com/BlueSpire/Durandal"
}]
}
, {
"heading": "Articles and Guides",
"links": [{
"name": "HotTowel Template - Durandal with ASP.Net MVC",
"url": "http://www.johnpapa.net/hottowel/"
}, {
"name": "Using Durandal to Create Single Page Apps",
"url": "http://stephenwalther.com/archive/2013/02/08/using-durandal-to-create-single-page-apps"
},{
"name": "nuGet Download",
"url": "http://www.nuget.org/packages/Durandal/"
}]
}, {
"heading": "Community",
"links": [{
"name": "Durandal on StackOverflow",
"url": "http://stackoverflow.com/questions/tagged/durandal"
}, {
"name": "Mailing list on Google Groups",
"url": "https://groups.google.com/forum/#!forum/durandaljs"
}, {
"name": "Durandal on Twitter",
"url": "http://twitter.com/durandaljs"
}]
}]
},
"emberjs": {
"name": "Ember.js",
"description": "A framework for creating ambitious web applications.",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment