diff --git a/ui/index.html b/ui/index.html index 2261f8258e..0a28305f22 100644 --- a/ui/index.html +++ b/ui/index.html @@ -58,7 +58,7 @@
- {{view Ember.Select content=statuses value=filterStatus class="form-control form-control-mini"}} + {{view Ember.Select content=statuses value=status class="form-control form-control-mini"}}
@@ -114,7 +114,7 @@ - + diff --git a/ui/javascripts/app/models.js b/ui/javascripts/app/models.js index 9c90572f77..4ecf38bbf3 100644 --- a/ui/javascripts/app/models.js +++ b/ui/javascripts/app/models.js @@ -46,6 +46,10 @@ App.Service = Ember.Object.extend({ } }.property('Checks'), + nodes: function() { + return (this.get('Nodes')) + }.property('Nodes'), + // // Boolean of whether or not there are failing checks in the service. // This is used to set color backgrounds and so on. @@ -110,6 +114,12 @@ App.Node = Ember.Object.extend({ numServices: function() { return (this.get('Services').length) }.property('Services'), + // The number of services on the node + // + + services: function() { + return (this.get('Services')) + }.property('Services'), filterKey: function() { return this.get('Node') diff --git a/ui/javascripts/libs/ember-1.5.1.min.js b/ui/javascripts/libs/ember-1.5.1.min.js deleted file mode 100644 index a9383a689e..0000000000 --- a/ui/javascripts/libs/ember-1.5.1.min.js +++ /dev/null @@ -1,29 +0,0 @@ -/*! - * @overview Ember - JavaScript Application Framework - * @copyright Copyright 2011-2014 Tilde Inc. and contributors - * Portions Copyright 2006-2011 Strobe Inc. - * Portions Copyright 2008-2011 Apple Inc. All rights reserved. - * @license Licensed under MIT license - * See https://raw.github.com/emberjs/ember.js/master/LICENSE - * @version 1.5.1 - */ -!function(){if("undefined"==typeof Ember&&(Ember={},"undefined"!=typeof window&&(window.Em=window.Ember=Em=Ember)),Ember.ENV||(Ember.ENV="undefined"!=typeof EmberENV?EmberENV:"undefined"!=typeof ENV?ENV:{}),"MANDATORY_SETTER"in Ember.ENV||(Ember.ENV.MANDATORY_SETTER=!0),Ember.assert=function(e,t){if(!t)throw new Ember.Error("Assertion Failed: "+e)},Ember.warn=function(e,t){t||(Ember.Logger.warn("WARNING: "+e),"trace"in Ember.Logger&&Ember.Logger.trace())},Ember.debug=function(e){Ember.Logger.debug("DEBUG: "+e)},Ember.deprecate=function(e,t){if(!t){if(Ember.ENV.RAISE_ON_DEPRECATION)throw new Ember.Error(e);var r;try{__fail__.fail()}catch(n){r=n}if(Ember.LOG_STACKTRACE_ON_DEPRECATION&&r.stack){var i,o="";r.arguments?(i=r.stack.replace(/^\s+at\s+/gm,"").replace(/^([^\(]+?)([\n$])/gm,"{anonymous}($1)$2").replace(/^Object.\s*\(([^\)]+)\)/gm,"{anonymous}($1)").split("\n"),i.shift()):i=r.stack.replace(/(?:\n@:0)?\s+$/m,"").replace(/^\(/gm,"{anonymous}(").split("\n"),o="\n "+i.slice(2).join("\n "),e+=o}Ember.Logger.warn("DEPRECATION: "+e)}},Ember.deprecateFunc=function(e,t){return function(){return Ember.deprecate(e),t.apply(this,arguments)}},Ember.runInDebug=function(e){e()},!Ember.testing){var e="undefined"!=typeof InstallTrigger,t=!!window.chrome&&!window.opera;"undefined"!=typeof window&&(e||t)&&window.addEventListener&&window.addEventListener("load",function(){if(document.documentElement&&document.documentElement.dataset&&!document.documentElement.dataset.emberExtension){var r;t?r="https://chrome.google.com/webstore/detail/ember-inspector/bmdblncegkenkacieihfhpjfppoconhi":e&&(r="https://addons.mozilla.org/en-US/firefox/addon/ember-inspector/"),Ember.debug("For more advanced debugging, install the Ember Inspector from "+r)}},!1)}}(),/*! - * @overview Ember - JavaScript Application Framework - * @copyright Copyright 2011-2014 Tilde Inc. and contributors - * Portions Copyright 2006-2011 Strobe Inc. - * Portions Copyright 2008-2011 Apple Inc. All rights reserved. - * @license Licensed under MIT license - * See https://raw.github.com/emberjs/ember.js/master/LICENSE - * @version 1.5.1 - */ -function(){var e,t,r,n;!function(){var i={},o={};e=function(e,t,r){i[e]={deps:t,callback:r}},n=r=t=function(e){function r(t){if("."!==t.charAt(0))return t;for(var r=t.split("/"),n=e.split("/").slice(0,-1),i=0,o=r.length;o>i;i++){var a=r[i];if(".."===a)n.pop();else{if("."===a)continue;n.push(a)}}return n.join("/")}if(n._eak_seen=i,o[e])return o[e];if(o[e]={},!i[e])throw new Error("Could not find module "+e);for(var a,s=i[e],u=s.deps,l=s.callback,c=[],h=0,m=u.length;m>h;h++)c.push("exports"===u[h]?a={}:t(r(u[h])));var p=l.apply(this,c);return o[e]=a||p}}(),function(){"undefined"==typeof Ember&&(Ember={});{var e=(Ember.imports=Ember.imports||this,Ember.exports=Ember.exports||this);Ember.lookup=Ember.lookup||this}e.Em=e.Ember=Em=Ember,Ember.isNamespace=!0,Ember.toString=function(){return"Ember"},Ember.VERSION="1.5.1",Ember.ENV||(Ember.ENV="undefined"!=typeof EmberENV?EmberENV:"undefined"!=typeof ENV?ENV:{}),Ember.config=Ember.config||{},"undefined"==typeof Ember.ENV.DISABLE_RANGE_API&&(Ember.ENV.DISABLE_RANGE_API=!0),"undefined"==typeof MetamorphENV&&(e.MetamorphENV={}),MetamorphENV.DISABLE_RANGE_API=Ember.ENV.DISABLE_RANGE_API,Ember.FEATURES=Ember.ENV.FEATURES||{},Ember.FEATURES.isEnabled=function(e){var t=Ember.FEATURES[e];return Ember.ENV.ENABLE_ALL_FEATURES?!0:t===!0||t===!1||void 0===t?t:Ember.ENV.ENABLE_OPTIONAL_FEATURES?!0:!1},Ember.EXTEND_PROTOTYPES=Ember.ENV.EXTEND_PROTOTYPES,"undefined"==typeof Ember.EXTEND_PROTOTYPES&&(Ember.EXTEND_PROTOTYPES=!0),Ember.LOG_STACKTRACE_ON_DEPRECATION=Ember.ENV.LOG_STACKTRACE_ON_DEPRECATION!==!1,Ember.SHIM_ES5=Ember.ENV.SHIM_ES5===!1?!1:Ember.EXTEND_PROTOTYPES,Ember.LOG_VERSION=Ember.ENV.LOG_VERSION===!1?!1:!0,Ember.K=function(){return this},"undefined"==typeof Ember.assert&&(Ember.assert=Ember.K),"undefined"==typeof Ember.warn&&(Ember.warn=Ember.K),"undefined"==typeof Ember.debug&&(Ember.debug=Ember.K),"undefined"==typeof Ember.runInDebug&&(Ember.runInDebug=Ember.K),"undefined"==typeof Ember.deprecate&&(Ember.deprecate=Ember.K),"undefined"==typeof Ember.deprecateFunc&&(Ember.deprecateFunc=function(e,t){return t}),Ember.uuid=0,Ember.merge=function(e,t){for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r]);return e},Ember.isNone=function(e){return null===e||void 0===e},Ember.none=Ember.deprecateFunc("Ember.none is deprecated. Please use Ember.isNone instead.",Ember.isNone),Ember.isEmpty=function(e){return Ember.isNone(e)||0===e.length&&"function"!=typeof e||"object"==typeof e&&0===Ember.get(e,"length")},Ember.empty=Ember.deprecateFunc("Ember.empty is deprecated. Please use Ember.isEmpty instead.",Ember.isEmpty),Ember.isBlank=function(e){return Ember.isEmpty(e)||"string"==typeof e&&null===e.match(/\S/)}}(),function(){var e=Ember.platform={};if(Ember.create=Object.create,Ember.create&&2!==Ember.create({a:1},{a:{value:2}}).a&&(Ember.create=null),!Ember.create||Ember.ENV.STUB_OBJECT_CREATE){var t=function(){};Ember.create=function(e,r){if(t.prototype=e,e=new t,r){t.prototype=e;for(var n in r)t.prototype[n]=r[n].value;e=new t}return t.prototype=null,e},Ember.create.isSimulated=!0}var r,n,i=Object.defineProperty;if(i)try{i({},"a",{get:function(){}})}catch(o){i=null}i&&(r=function(){var e={};return i(e,"a",{configurable:!0,enumerable:!0,get:function(){},set:function(){}}),i(e,"a",{configurable:!0,enumerable:!0,writable:!0,value:!0}),e.a===!0}(),n=function(){try{return i(document.createElement("div"),"definePropertyOnDOM",{}),!0}catch(e){}return!1}(),r?n||(i=function(e,t,r){var n;return n="object"==typeof Node?e instanceof Node:"object"==typeof e&&"number"==typeof e.nodeType&&"string"==typeof e.nodeName,n?e[t]=r.value:Object.defineProperty(e,t,r)}):i=null),e.defineProperty=i,e.hasPropertyAccessors=!0,e.defineProperty||(e.hasPropertyAccessors=!1,e.defineProperty=function(e,t,r){r.get||(e[t]=r.value)},e.defineProperty.isSimulated=!0),Ember.ENV.MANDATORY_SETTER&&!e.hasPropertyAccessors&&(Ember.ENV.MANDATORY_SETTER=!1)}(),function(){var e=function(e){return e&&Function.prototype.toString.call(e).indexOf("[native code]")>-1},t=e(Array.prototype.map)?Array.prototype.map:function(e){if(void 0===this||null===this)throw new TypeError;var t=Object(this),r=t.length>>>0;if("function"!=typeof e)throw new TypeError;for(var n=new Array(r),i=arguments[1],o=0;r>o;o++)o in t&&(n[o]=e.call(i,t[o],o,t));return n},r=e(Array.prototype.forEach)?Array.prototype.forEach:function(e){if(void 0===this||null===this)throw new TypeError;var t=Object(this),r=t.length>>>0;if("function"!=typeof e)throw new TypeError;for(var n=arguments[1],i=0;r>i;i++)i in t&&e.call(n,t[i],i,t)},n=e(Array.prototype.indexOf)?Array.prototype.indexOf:function(e,t){null===t||void 0===t?t=0:0>t&&(t=Math.max(0,this.length+t));for(var r=t,n=this.length;n>r;r++)if(this[r]===e)return r;return-1},i=e(Array.prototype.filter)?Array.prototype.filter:function(e,t){var r,n,i=[],o=this.length;for(r=0;o>r;r++)this.hasOwnProperty(r)&&(n=this[r],e.call(t,n,r,this)&&i.push(n));return i};Ember.ArrayPolyfills={map:t,forEach:r,filter:i,indexOf:n},Ember.SHIM_ES5&&(Array.prototype.map||(Array.prototype.map=t),Array.prototype.forEach||(Array.prototype.forEach=r),Array.prototype.filter||(Array.prototype.filter=i),Array.prototype.indexOf||(Array.prototype.indexOf=n))}(),function(){var e=["description","fileName","lineNumber","message","name","number","stack"];Ember.Error=function(){var t=Error.apply(this,arguments);Error.captureStackTrace&&Error.captureStackTrace(this,Ember.Error);for(var r=0;rs;s++){if(i=t[s],o=a[i]){if(o.__ember_source__!==e){if(!r)return void 0;o=a[i]=n(o),o.__ember_source__=e}}else{if(!r)return void 0;o=a[i]={__ember_source__:e}}a=o}return o},Ember.wrap=function(e,t){function r(){var r,n=this.__nextSuper;return this.__nextSuper=t,r=e.apply(this,arguments),this.__nextSuper=n,r}return r.wrappedFunction=e,r.__ember_observes__=e.__ember_observes__,r.__ember_observesBefore__=e.__ember_observesBefore__,r.__ember_listens__=e.__ember_listens__,r},Ember.isArray=function(e){return!e||e.setInterval?!1:Array.isArray&&Array.isArray(e)?!0:Ember.Array&&Ember.Array.detect(e)?!0:void 0!==e.length&&"object"==typeof e?!0:!1},Ember.makeArray=function(e){return null===e||void 0===e?[]:Ember.isArray(e)?e:[e]},Ember.canInvoke=t,Ember.tryInvoke=function(e,r,n){return t(e,r)?e[r].apply(e,n||[]):void 0};var d=function(){var e=0;try{try{}finally{throw e++,new Error("needsFinallyFixTest")}}catch(t){}return 1!==e}();Ember.tryFinally=d?function(e,t,r){var n,i,o;r=r||this;try{n=e.call(r)}finally{try{i=t.call(r)}catch(a){o=a}}if(o)throw o;return void 0===i?n:i}:function(e,t,r){var n,i;r=r||this;try{n=e.call(r)}finally{i=t.call(r)}return void 0===i?n:i},Ember.tryCatchFinally=d?function(e,t,r,n){var i,o,a;n=n||this;try{i=e.call(n)}catch(s){i=t.call(n,s)}finally{try{o=r.call(n)}catch(u){a=u}}if(a)throw a;return void 0===o?i:o}:function(e,t,r,n){var i,o;n=n||this;try{i=e.call(n)}catch(a){i=t.call(n,a)}finally{o=r.call(n)}return void 0===o?i:o};var f={},b="Boolean Number String Function Array Date RegExp Object".split(" ");Ember.ArrayPolyfills.forEach.call(b,function(e){f["[object "+e+"]"]=e.toLowerCase()});var E=Object.prototype.toString;Ember.typeOf=function(e){var t;return t=null===e||void 0===e?String(e):f[E.call(e)]||"object","function"===t?Ember.Object&&Ember.Object.detect(e)&&(t="class"):"object"===t&&(e instanceof Error?t="error":Ember.Object&&e instanceof Ember.Object?t="instance":e instanceof Date&&(t="date")),t},Ember.inspect=function(e){var t=Ember.typeOf(e);if("array"===t)return"["+e+"]";if("object"!==t)return e+"";var r,n=[];for(var i in e)if(e.hasOwnProperty(i)){if(r=e[i],"toString"===r)continue;"function"===Ember.typeOf(r)&&(r="function() { ... }"),n.push(i+": "+r)}return"{"+n.join(", ")+"}"}}(),function(){Ember.Instrumentation={};var e=[],t={},r=function(r){for(var n,i=[],o=0,a=e.length;a>o;o++)n=e[o],n.regex.test(r)&&i.push(n.object);return t[r]=i,i},n=function(){var e="undefined"!=typeof window?window.performance||{}:{},t=e.now||e.mozNow||e.webkitNow||e.msNow||e.oNow;return t?t.bind(e):function(){return+new Date}}();Ember.Instrumentation.instrument=function(e,i,o,a){function s(){for(d=0,f=m.length;f>d;d++)p=m[d],b[d]=p.before(e,n(),i);return o.call(a)}function u(e){i=i||{},i.exception=e}function l(){for(d=0,f=m.length;f>d;d++)p=m[d],p.after(e,n(),i,b[d]);Ember.STRUCTURED_PROFILE&&console.timeEnd(c)}var c,h,m=t[e];if(Ember.STRUCTURED_PROFILE&&(c=e+": "+i.object,console.time(c)),m||(m=r(e)),0===m.length)return h=o.call(a),Ember.STRUCTURED_PROFILE&&console.timeEnd(c),h;var p,d,f,b=[];return Ember.tryCatchFinally(s,u,l)},Ember.Instrumentation.subscribe=function(r,n){for(var i,o=r.split("."),a=[],s=0,u=o.length;u>s;s++)i=o[s],a.push("*"===i?"[^\\.]*":i);a=a.join("\\."),a+="(\\..*)?";var l={pattern:r,regex:new RegExp("^"+a+"$"),object:n};return e.push(l),t={},l},Ember.Instrumentation.unsubscribe=function(r){for(var n,i=0,o=e.length;o>i;i++)e[i]===r&&(n=i);e.splice(n,1),t={}},Ember.Instrumentation.reset=function(){e=[],t={}},Ember.instrument=Ember.Instrumentation.instrument,Ember.subscribe=Ember.Instrumentation.subscribe}(),function(){var e,t,r,n,i;e=Array.prototype.map||Ember.ArrayPolyfills.map,t=Array.prototype.forEach||Ember.ArrayPolyfills.forEach,r=Array.prototype.indexOf||Ember.ArrayPolyfills.indexOf,i=Array.prototype.filter||Ember.ArrayPolyfills.filter,n=Array.prototype.splice;var o=Ember.EnumerableUtils={map:function(t,r,n){return t.map?t.map.call(t,r,n):e.call(t,r,n)},forEach:function(e,r,n){return e.forEach?e.forEach.call(e,r,n):t.call(e,r,n)},filter:function(e,t,r){return e.filter?e.filter.call(e,t,r):i.call(e,t,r)},indexOf:function(e,t,n){return e.indexOf?e.indexOf.call(e,t,n):r.call(e,t,n)},indexesOf:function(e,t){return void 0===t?[]:o.map(t,function(t){return o.indexOf(e,t)})},addObject:function(e,t){var r=o.indexOf(e,t);-1===r&&e.push(t)},removeObject:function(e,t){var r=o.indexOf(e,t);-1!==r&&e.splice(r,1)},_replace:function(e,t,r,i){for(var o,a,s=[].concat(i),u=[],l=6e4,c=t,h=r;s.length;)a=h>l?l:h,0>=a&&(a=0),o=s.splice(0,l),o=[c,a].concat(o),c+=l,h-=a,u=u.concat(n.apply(e,o));return u},replace:function(e,t,r,n){return e.replace?e.replace(t,r,n):o._replace(e,t,r,n)},intersection:function(e,t){var r=[];return o.forEach(e,function(e){o.indexOf(t,e)>=0&&r.push(e)}),r}}}(),function(){var e,t=Ember.META_KEY,r=Ember.ENV.MANDATORY_SETTER,n=/^([A-Z$]|([0-9][A-Z$])).*[\.\*]/,i=/^this[\.\*]/,o=/^([^\.\*]+)/;e=function(e,n){if(""===n)return e;if(n||"string"!=typeof e||(n=e,e=null),Ember.assert("Cannot call get with "+n+" key.",!!n),Ember.assert("Cannot call get with '"+n+"' on an undefined object.",void 0!==e),null===e||-1!==n.indexOf("."))return s(e,n);var i,o=e[t],a=o&&o.descs[n];return a?a.get(e,n):(i=r&&o&&o.watching[n]>0?o.values[n]:e[n],void 0!==i||"object"!=typeof e||n in e||"function"!=typeof e.unknownProperty?i:e.unknownProperty(n))},Ember.config.overrideAccessors&&(Ember.get=e,Ember.config.overrideAccessors(),e=Ember.get);var a=Ember.normalizeTuple=function(t,r){var a,s=i.test(r),u=!s&&n.test(r);if((!t||u)&&(t=Ember.lookup),s&&(r=r.slice(5)),t===Ember.lookup&&(a=r.match(o)[0],t=e(t,a),r=r.slice(a.length+1)),!r||0===r.length)throw new Ember.Error("Path cannot be empty");return[t,r]},s=Ember._getPath=function(t,r){var n,o,s,u,l;if(null===t&&-1===r.indexOf("."))return e(Ember.lookup,r);for(n=i.test(r),(!t||n)&&(s=a(t,r),t=s[0],r=s[1],s.length=0),o=r.split("."),l=o.length,u=0;null!=t&&l>u;u++)if(t=e(t,o[u],!0),t&&t.isDestroyed)return void 0;return t};Ember.getWithDefault=function(t,r,n){var i=e(t,r);return void 0===i?n:i},Ember.get=e}(),function(){function e(e,t,r){for(var n=-1,i=e.length-3;i>=0;i-=3)if(t===e[i]&&r===e[i+1]){n=i;break}return n}function t(e,t){var r,n=p(e,!0);return n.listeners||(n.listeners={}),n.hasOwnProperty("listeners")||(n.listeners=m(n.listeners)),r=n.listeners[t],r&&!n.listeners.hasOwnProperty(t)?r=n.listeners[t]=n.listeners[t].slice():r||(r=n.listeners[t]=[]),r}function r(t,r,n){var i=t[d],o=i&&i.listeners&&i.listeners[r];if(o)for(var a=o.length-3;a>=0;a-=3){var s=o[a],u=o[a+1],l=o[a+2],c=e(n,s,u);-1===c&&n.push(s,u,l)}}function n(t,r,n){var i=t[d],o=i&&i.listeners&&i.listeners[r],a=[];if(o){for(var s=o.length-3;s>=0;s-=3){var u=o[s],l=o[s+1],c=o[s+2],h=e(n,u,l);-1===h&&(n.push(u,l,c),a.push(u,l,c))}return a}}function i(r,n,i,o,a){Ember.assert("You must pass at least an object and event name to Ember.addListener",!!r&&!!n),o||"function"!=typeof i||(o=i,i=null);var s=t(r,n),u=e(s,i,o),l=0;a&&(l|=b),-1===u&&(s.push(i,o,l),"function"==typeof r.didAddListener&&r.didAddListener(n,i,o))}function o(r,n,i,o){function a(i,o){var a=t(r,n),s=e(a,i,o);-1!==s&&(a.splice(s,3),"function"==typeof r.didRemoveListener&&r.didRemoveListener(n,i,o))}if(Ember.assert("You must pass at least an object and event name to Ember.removeListener",!!r&&!!n),o||"function"!=typeof i||(o=i,i=null),o)a(i,o);else{var s=r[d],u=s&&s.listeners&&s.listeners[n];if(!u)return;for(var l=u.length-3;l>=0;l-=3)a(u[l],u[l+1])}}function a(r,n,i,o,a){function s(){return a.call(i)}function u(){-1!==c&&(l[c+2]&=~E)}o||"function"!=typeof i||(o=i,i=null);var l=t(r,n),c=e(l,i,o);return-1!==c&&(l[c+2]|=E),Ember.tryFinally(s,u)}function s(r,n,i,o,a){function s(){return a.call(i)}function u(){for(var e=0,t=p.length;t>e;e++){var r=p[e];d[e][r+2]&=~E}}o||"function"!=typeof i||(o=i,i=null);var l,c,h,m,p=[],d=[];for(h=0,m=n.length;m>h;h++){l=n[h],c=t(r,l);var f=e(c,i,o);-1!==f&&(c[f+2]|=E,p.push(f),d.push(c))}return Ember.tryFinally(s,u)}function u(e){var t=e[d].listeners,r=[];if(t)for(var n in t)t[n]&&r.push(n);return r}function l(e,t,r,n){if(e!==Ember&&"function"==typeof e.sendEvent&&e.sendEvent(t,r),!n){var i=e[d];n=i&&i.listeners&&i.listeners[t]}if(n){for(var a=n.length-3;a>=0;a-=3){var s=n[a],u=n[a+1],l=n[a+2];u&&(l&E||(l&b&&o(e,t,s,u),s||(s=e),"string"==typeof u&&(u=s[u]),r?u.apply(s,r):u.call(s)))}return!0}}function c(e,t){var r=e[d],n=r&&r.listeners&&r.listeners[t];return!(!n||!n.length)}function h(e,t){var r=[],n=e[d],i=n&&n.listeners&&n.listeners[t];if(!i)return r;for(var o=0,a=i.length;a>o;o+=3){var s=i[o],u=i[o+1];r.push([s,u])}return r}var m=Ember.create,p=Ember.meta,d=Ember.META_KEY,f=[].slice,b=1,E=2;Ember.on=function(){var e=f.call(arguments,-1)[0],t=f.call(arguments,0,-1);return e.__ember_listens__=t,e},Ember.addListener=i,Ember.removeListener=o,Ember._suspendListener=a,Ember._suspendListeners=s,Ember.sendEvent=l,Ember.hasListeners=c,Ember.watchedEvents=u,Ember.listenersFor=h,Ember.listenersDiff=n,Ember.listenersUnion=r}(),function(){var e=Ember.guidFor,t=Ember.sendEvent,r=Ember._ObserverSet=function(){this.clear()};r.prototype.add=function(t,r,n){var i,o=this.observerSet,a=this.observers,s=e(t),u=o[s];return u||(o[s]=u={}),i=u[r],void 0===i&&(i=a.push({sender:t,keyName:r,eventName:n,listeners:[]})-1,u[r]=i),a[i].listeners},r.prototype.flush=function(){var e,r,n,i,o=this.observers;for(this.clear(),e=0,r=o.length;r>e;++e)n=o[e],i=n.sender,i.isDestroying||i.isDestroyed||t(i,n.eventName,[i,n.keyName],n.listeners)},r.prototype.clear=function(){this.observerSet={},this.observers=[]}}(),function(){function e(e,t){var n=e[h],i=n&&n.watching[t]>0||"length"===t,a=n&&n.proto,s=n&&n.descs[t];i&&a!==e&&(s&&s.willChange&&s.willChange(e,t),r(e,t,n),o(e,t,n),l(e,t))}function t(e,t){var r=e[h],i=r&&r.watching[t]>0||"length"===t,o=r&&r.proto,s=r&&r.descs[t];o!==e&&(s&&s.didChange&&s.didChange(e,t),(i||"length"===t)&&(n(e,t,r),a(e,t,r,!1),c(e,t)))}function r(t,r,n){if(!t.isDestroying){var o=w,a=!o;a&&(o=w={}),i(e,t,r,o,n),a&&(w=null)}}function n(e,r,n){if(!e.isDestroying){var o=_,a=!o;a&&(o=_={}),i(t,e,r,o,n),a&&(_=null)}}function i(e,t,r,n,i){var o=m(t);if(n[o]||(n[o]={}),!n[o][r]){n[o][r]=!0;var a=i.deps;if(a=a&&a[r])for(var s in a){var u=i.descs[s];u&&u._suspended===t||e(t,s)}}}function o(t,r,n){if(n.hasOwnProperty("chainWatchers")&&n.chainWatchers[r]){var i,o,a=n.chainWatchers[r],s=[];for(i=0,o=a.length;o>i;i++)a[i].willChange(s);for(i=0,o=s.length;o>i;i+=2)e(s[i],s[i+1])}}function a(e,r,n,i){if(n&&n.hasOwnProperty("chainWatchers")&&n.chainWatchers[r]){var o,a,s=n.chainWatchers[r],u=i?null:[];for(o=0,a=s.length;a>o;o++)s[o].didChange(u);if(!i)for(o=0,a=u.length;a>o;o+=2)t(u[o],u[o+1])}}function s(){y++}function u(){y--,0>=y&&(v.clear(),g.flush())}function l(e,t){if(!e.isDestroying){var r,n,i=t+":before";y?(r=v.add(e,t,i),n=b(e,i,r),d(e,i,[e,t],n)):d(e,i,[e,t])}}function c(e,t){if(!e.isDestroying){var r,n=t+":change";y?(r=g.add(e,t,n),f(e,n,r)):d(e,n,[e,t])}}var h=Ember.META_KEY,m=Ember.guidFor,p=Ember.tryFinally,d=Ember.sendEvent,f=Ember.listenersUnion,b=Ember.listenersDiff,E=Ember._ObserverSet,v=new E,g=new E,y=0;Ember.propertyWillChange=e,Ember.propertyDidChange=t;var w,_;Ember.overrideChains=function(e,t,r){a(e,t,r,!0)},Ember.beginPropertyChanges=s,Ember.endPropertyChanges=u,Ember.changeProperties=function(e,t){s(),p(e,u,t)}}(),function(){function e(e,t,r,n){var a;if(a=t.slice(t.lastIndexOf(".")+1),t=t===a?a:t.slice(0,t.length-(a.length+1)),"this"!==t&&(e=i(e,t)),!a||0===a.length)throw new Ember.Error("Property set failed: You passed an empty path");if(!e){if(n)return;throw new Ember.Error('Property set failed: object in path "'+t+'" could not be found or was destroyed.')}return o(e,a,r)}var t=Ember.META_KEY,r=Ember.ENV.MANDATORY_SETTER,n=/^([A-Z$]|([0-9][A-Z$]))/,i=Ember._getPath,o=function(i,o,a,s){if("string"==typeof i&&(Ember.assert("Path '"+i+"' must be global if no obj is given.",n.test(i)),a=o,o=i,i=null),Ember.assert("Cannot call set with "+o+" key.",!!o),!i||-1!==o.indexOf("."))return e(i,o,a,s);Ember.assert("You need to provide an object and key to `set`.",!!i&&void 0!==o),Ember.assert("calling set on destroyed object",!i.isDestroyed);var u,l,c=i[t],h=c&&c.descs[o];return h?h.set(i,o,a):(u="object"==typeof i&&!(o in i),u&&"function"==typeof i.setUnknownProperty?i.setUnknownProperty(o,a):c&&c.watching[o]>0?(l=r?c.values[o]:i[o],a!==l&&(Ember.propertyWillChange(i,o),r?(void 0!==l||o in i)&&i.propertyIsEnumerable(o)?c.values[o]=a:Ember.defineProperty(i,o,null,a):i[o]=a,Ember.propertyDidChange(i,o))):i[o]=a),a};Ember.config.overrideAccessors&&(Ember.set=o,Ember.config.overrideAccessors(),o=Ember.set),Ember.set=o,Ember.trySet=function(e,t,r){return o(e,t,r,!0)}}(),function(){var e=Ember.set,t=Ember.guidFor,r=Ember.ArrayPolyfills.indexOf,n=function(e){var t={};for(var r in e)e.hasOwnProperty(r)&&(t[r]=e[r]);return t},i=function(e,t){var r=e.keys.copy(),i=n(e.values);return t.keys=r,t.values=i,t.length=e.length,t},o=Ember.OrderedSet=function(){this.clear()};o.create=function(){return new o},o.prototype={clear:function(){this.presenceSet={},this.list=[]},add:function(e){var r=t(e),n=this.presenceSet,i=this.list;r in n||(n[r]=!0,i.push(e))},remove:function(e){var n=t(e),i=this.presenceSet,o=this.list;delete i[n];var a=r.call(o,e);a>-1&&o.splice(a,1)},isEmpty:function(){return 0===this.list.length},has:function(e){var r=t(e),n=this.presenceSet;return r in n},forEach:function(e,t){for(var r=this.toArray(),n=0,i=r.length;i>n;n++)e.call(t,r[n])},toArray:function(){return this.list.slice()},copy:function(){var e=new o;return e.presenceSet=n(this.presenceSet),e.list=this.toArray(),e}};var a=Ember.Map=function(){this.keys=Ember.OrderedSet.create(),this.values={}};a.create=function(){return new a},a.prototype={length:0,get:function(e){var r=this.values,n=t(e);return r[n]},set:function(r,n){var i=this.keys,o=this.values,a=t(r);i.add(r),o[a]=n,e(this,"length",i.list.length)},remove:function(r){var n=this.keys,i=this.values,o=t(r);return i.hasOwnProperty(o)?(n.remove(r),delete i[o],e(this,"length",n.list.length),!0):!1},has:function(e){var r=this.values,n=t(e);return r.hasOwnProperty(n)},forEach:function(e,r){var n=this.keys,i=this.values;n.forEach(function(n){var o=t(n);e.call(r,n,i[o])})},copy:function(){return i(this,new a)}};var s=Ember.MapWithDefault=function(e){a.call(this),this.defaultValue=e.defaultValue};s.create=function(e){return e?new s(e):new a},s.prototype=Ember.create(a.prototype),s.prototype.get=function(e){var t=this.has(e);if(t)return a.prototype.get.call(this,e);var r=this.defaultValue(e);return this.set(e,r),r},s.prototype.copy=function(){return i(this,new s({defaultValue:this.defaultValue}))}}(),function(){function e(e){var t,r;Ember.imports.console?t=Ember.imports.console:"undefined"!=typeof console&&(t=console);var n="object"==typeof t?t[e]:null;return n?"function"==typeof n.apply?(r=function(){n.apply(t,arguments)},r.displayName="console."+e,r):function(){var e=Array.prototype.join.call(arguments,", ");n(e)}:void 0}function t(e,t){if(!e)try{throw new Ember.Error("assertion failed: "+t)}catch(r){setTimeout(function(){throw r},0)}}Ember.Logger={log:e("log")||Ember.K,warn:e("warn")||Ember.K,error:e("error")||Ember.K,info:e("info")||Ember.K,debug:e("debug")||e("info")||Ember.K,assert:e("assert")||t}}(),function(){var e=Ember.META_KEY,t=Ember.meta,r=Ember.platform.defineProperty,n=Ember.ENV.MANDATORY_SETTER;Ember.Descriptor=function(){};var i=Ember.MANDATORY_SETTER_FUNCTION=function(){Ember.assert("You must use Ember.set() to access this property (of "+this+")",!1)},o=Ember.DEFAULT_GETTER_FUNCTION=function(t){return function(){var r=this[e];return r&&r.values[t]}};if(Ember.defineProperty=function(e,s,u,l,c){var h,m,p,d;return c||(c=t(e)),h=c.descs,m=c.descs[s],p=c.watching[s]>0,m instanceof Ember.Descriptor&&m.teardown(e,s),u instanceof Ember.Descriptor?(d=u,h[s]=u,n&&p?r(e,s,{configurable:!0,enumerable:!0,writable:!0,value:void 0}):e[s]=void 0,Ember.FEATURES.isEnabled("composable-computed-properties")&&u.func&&u._dependentCPs&&a(e,u._dependentCPs,c)):(h[s]=void 0,null==u?(d=l,n&&p?(c.values[s]=l,r(e,s,{configurable:!0,enumerable:!0,set:i,get:o(s)})):e[s]=l):(d=u,r(e,s,u))),p&&Ember.overrideChains(e,s,c),e.didDefineProperty&&e.didDefineProperty(e,s,d),this},Ember.FEATURES.isEnabled("composable-computed-properties"))var a=function(e,t,r){for(var n,i,o=t.length,s=0;o>s;++s)n=t[s],i=n.implicitCPKey,Ember.defineProperty(e,i,n,void 0,r),n._dependentCPs&&a(e,n._dependentCPs,r)}}(),function(){var e=Ember.get;Ember.getProperties=function(t){var r={},n=arguments,i=1;2===arguments.length&&"array"===Ember.typeOf(arguments[1])&&(i=0,n=arguments[1]);for(var o=n.length;o>i;i++)r[n[i]]=e(t,n[i]);return r}}(),function(){var e=Ember.changeProperties,t=Ember.set;Ember.setProperties=function(r,n){return e(function(){for(var e in n)n.hasOwnProperty(e)&&t(r,e,n[e])}),r}}(),function(){var e=Ember.meta,t=Ember.typeOf,r=Ember.ENV.MANDATORY_SETTER,n=Ember.platform.defineProperty;Ember.watchKey=function(i,o,a){if("length"!==o||"array"!==t(i)){var s=a||e(i),u=s.watching;u[o]?u[o]=(u[o]||0)+1:(u[o]=1,"function"==typeof i.willWatchProperty&&i.willWatchProperty(o),r&&o in i&&(s.values[o]=i[o],n(i,o,{configurable:!0,enumerable:i.propertyIsEnumerable(o),set:Ember.MANDATORY_SETTER_FUNCTION,get:Ember.DEFAULT_GETTER_FUNCTION(o)})))}},Ember.unwatchKey=function(t,i,o){var a=o||e(t),s=a.watching;1===s[i]?(s[i]=0,"function"==typeof t.didUnwatchProperty&&t.didUnwatchProperty(i),r&&i in t&&n(t,i,{configurable:!0,enumerable:t.propertyIsEnumerable(i),set:function(e){n(t,i,{configurable:!0,writable:!0,enumerable:!0,value:e}),delete a.values[i]},get:Ember.DEFAULT_GETTER_FUNCTION(i)})):s[i]>1&&s[i]--}}(),function(){function e(e){return e.match(c)[0]}function t(e,t,r){if(e&&"object"==typeof e){var i=n(e),o=i.chainWatchers;i.hasOwnProperty("chainWatchers")||(o=i.chainWatchers={}),o[t]||(o[t]=[]),o[t].push(r),u(e,t,i)}}function r(e,t){if(!e)return void 0;var r=e[h];if(r&&r.proto===e)return void 0;if("@each"===t)return i(e,t);var n=r&&r.descs[t];return n&&n._cacheable?t in r.cache?r.cache[t]:void 0:i(e,t)}var n=Ember.meta,i=Ember.get,o=Ember.normalizeTuple,a=Ember.ArrayPolyfills.forEach,s=Ember.warn,u=Ember.watchKey,l=Ember.unwatchKey,c=/^([^\.\*]+)/,h=Ember.META_KEY,m=[];Ember.flushPendingChains=function(){if(0!==m.length){var e=m;m=[],a.call(e,function(e){e[0].add(e[1])}),s("Watching an undefined global, Ember expects watched globals to be setup by the time the run loop is flushed, check for typos",0===m.length)}};var p=Ember.removeChainWatcher=function(e,t,r){if(e&&"object"==typeof e){var n=e[h];if(!n||n.hasOwnProperty("chainWatchers")){var i=n&&n.chainWatchers;if(i&&i[t]){i=i[t];for(var o=0,a=i.length;a>o;o++)i[o]===r&&i.splice(o,1)}l(e,t,n)}}},d=Ember._ChainNode=function(e,r,n){this._parent=e,this._key=r,this._watching=void 0===n,this._value=n,this._paths={},this._watching&&(this._object=e.value(),this._object&&t(this._object,this._key,this)),this._parent&&"@each"===this._parent._key&&this.value()},f=d.prototype;f.value=function(){if(void 0===this._value&&this._watching){var e=this._parent.value();this._value=r(e,this._key)}return this._value},f.destroy=function(){if(this._watching){var e=this._object;e&&p(e,this._key,this),this._watching=!1}},f.copy=function(e){var t,r=new d(null,null,e),n=this._paths;for(t in n)n[t]<=0||r.add(t);return r},f.add=function(t){var r,n,i,a,s;if(s=this._paths,s[t]=(s[t]||0)+1,r=this.value(),n=o(r,t),n[0]&&n[0]===r)t=n[1],i=e(t),t=t.slice(i.length+1);else{if(!n[0])return m.push([this,t]),void(n.length=0);a=n[0],i=t.slice(0,0-(n[1].length+1)),t=n[1]}n.length=0,this.chain(i,t,a)},f.remove=function(t){var r,n,i,a,s;s=this._paths,s[t]>0&&s[t]--,r=this.value(),n=o(r,t),n[0]===r?(t=n[1],i=e(t),t=t.slice(i.length+1)):(a=n[0],i=t.slice(0,0-(n[1].length+1)),t=n[1]),n.length=0,this.unchain(i,t)},f.count=0,f.chain=function(t,r,n){var i,o=this._chains;o||(o=this._chains={}),i=o[t],i||(i=o[t]=new d(this,t,n)),i.count++,r&&r.length>0&&(t=e(r),r=r.slice(t.length+1),i.chain(t,r))},f.unchain=function(t,r){var n=this._chains,i=n[t];r&&r.length>1&&(t=e(r),r=r.slice(t.length+1),i.unchain(t,r)),i.count--,i.count<=0&&(delete n[i._key],i.destroy())},f.willChange=function(e){var t=this._chains;if(t)for(var r in t)t.hasOwnProperty(r)&&t[r].willChange(e);this._parent&&this._parent.chainWillChange(this,this._key,1,e)},f.chainWillChange=function(e,t,r,n){this._key&&(t=this._key+"."+t),this._parent?this._parent.chainWillChange(this,t,r+1,n):(r>1&&n.push(this.value(),t),t="this."+t,this._paths[t]>0&&n.push(this.value(),t))},f.chainDidChange=function(e,t,r,n){this._key&&(t=this._key+"."+t),this._parent?this._parent.chainDidChange(this,t,r+1,n):(r>1&&n.push(this.value(),t),t="this."+t,this._paths[t]>0&&n.push(this.value(),t))},f.didChange=function(e){if(this._watching){var r=this._parent.value();r!==this._object&&(p(this._object,this._key,this),this._object=r,t(r,this._key,this)),this._value=void 0,this._parent&&"@each"===this._parent._key&&this.value()}var n=this._chains;if(n)for(var i in n)n.hasOwnProperty(i)&&n[i].didChange(e);null!==e&&this._parent&&this._parent.chainDidChange(this,this._key,1,e)},Ember.finishChains=function(e){var t=e[h],r=t&&t.chains;r&&(r.value()!==e?n(e).chains=r=r.copy(e):r.didChange(null))}}(),function(){var e=Ember.EnumerableUtils.forEach,t=/^((?:[^\.]*\.)*)\{(.*)\}$/;Ember.expandProperties=function(r,n){var i,o,a;(i=t.exec(r))?(o=i[1],a=i[2],e(a.split(","),function(e){n(o+e)})):n(r)}}(),function(){function e(e,r){var i=r||t(e),o=i.chains;return o?o.value()!==e&&(o=i.chains=o.copy(e)):o=i.chains=new n(null,null,e),o}var t=Ember.meta,r=Ember.typeOf,n=Ember._ChainNode;Ember.watchPath=function(n,i,o){if("length"!==i||"array"!==r(n)){var a=o||t(n),s=a.watching;s[i]?s[i]=(s[i]||0)+1:(s[i]=1,e(n,a).add(i))}},Ember.unwatchPath=function(r,n,i){var o=i||t(r),a=o.watching;1===a[n]?(a[n]=0,e(r,o).remove(n)):a[n]>1&&a[n]--}}(),function(){function e(e){return"*"===e||!c.test(e)}var t=(Ember.meta,Ember.GUID_KEY),r=Ember.META_KEY,n=Ember.removeChainWatcher,i=Ember.watchKey,o=Ember.unwatchKey,a=Ember.watchPath,s=Ember.unwatchPath,u=Ember.typeOf,l=Ember.generateGuid,c=/[\.\*]/;Ember.watch=function(t,r,n){("length"!==r||"array"!==u(t))&&(e(r)?i(t,r,n):a(t,r,n))},Ember.isWatching=function(e,t){var n=e[r];return(n&&n.watching[t])>0},Ember.watch.flushPending=Ember.flushPendingChains,Ember.unwatch=function(t,r,n){("length"!==r||"array"!==u(t))&&(e(r)?o(t,r,n):s(t,r,n))},Ember.rewatch=function(e){var n=e[r],i=n&&n.chains;t in e&&!e.hasOwnProperty(t)&&l(e),i&&i.value()!==e&&(n.chains=i.copy(e))};var h=[];Ember.destroy=function(e){var t,i,o,a,s=e[r];if(s&&(e[r]=null,t=s.chains))for(h.push(t);h.length>0;){if(t=h.pop(),i=t._chains)for(o in i)i.hasOwnProperty(o)&&h.push(i[o]);t._watching&&(a=t._object,a&&n(a,t._key,t))}}}(),function(){function e(e,t){var r=e[t];return r?e.hasOwnProperty(t)||(r=e[t]=h(r)):r=e[t]={},r}function t(t){return e(t,"deps")}function r(r,n,i,o){var a,s,u,l,c,h=r._dependentKeys;if(h)for(a=t(o),s=0,u=h.length;u>s;s++)l=h[s],c=e(a,l),c[i]=(c[i]||0)+1,p(n,l,o)}function n(r,n,i,o){var a,s,u,l,c,h=r._dependentKeys;if(h)for(a=t(o),s=0,u=h.length;u>s;s++)l=h[s],c=e(a,l),c[i]=(c[i]||0)-1,d(n,l,o)}function i(e,t){this.func=e,Ember.FEATURES.isEnabled("composable-computed-properties")?P(this,t&&t.dependentKeys):this._dependentKeys=t&&t.dependentKeys,this._cacheable=t&&void 0!==t.cacheable?t.cacheable:!0,this._readOnly=t&&(void 0!==t.readOnly||!!t.readOnly)}function o(e){for(var t=0,r=e.length;r>t;t++)e[t].didChange(null)}function a(e,t){for(var r={},n=0;nr;r++)f(arguments[r],t);return Ember.FEATURES.isEnabled("composable-computed-properties")?P(this,e):this._dependentKeys=e,this},b.meta=function(e){return 0===arguments.length?this._meta||{}:(this._meta=e,this)},b.didChange=function(e,t){if(this._cacheable&&this._suspended!==e){var r=l(e);t in r.cache&&(delete r.cache[t],n(this,e,t,r))}},b.get=function(e,t){var n,i,a,s;if(this._cacheable){if(a=l(e),i=a.cache,t in i)return i[t];n=i[t]=this.func.call(e,t),s=a.chainWatchers&&a.chainWatchers[t],s&&o(s),r(this,e,t,a)}else n=this.func.call(e,t);return n},b.set=function(e,t,n){var i,o,a,s=this._cacheable,u=this.func,c=l(e,s),h=c.watching[t],m=this._suspended,p=!1,d=c.cache;if(this._readOnly)throw new Ember.Error('Cannot set read-only property "'+t+'" on object: '+Ember.inspect(e)); -this._suspended=e;try{if(s&&d.hasOwnProperty(t)&&(o=d[t],p=!0),i=u.wrappedFunction?u.wrappedFunction.length:u.length,3===i)a=u.call(e,t,n,o);else{if(2!==i)return Ember.defineProperty(e,t,null,o),void Ember.set(e,t,n);a=u.call(e,t,n)}if(p&&o===a)return;h&&Ember.propertyWillChange(e,t),p&&delete d[t],s&&(p||r(this,e,t,c),d[t]=a),h&&Ember.propertyDidChange(e,t)}finally{this._suspended=m}return a},b.teardown=function(e,t){var r=l(e);return t in r.cache&&n(this,e,t,r),this._cacheable&&delete r.cache[t],null},Ember.computed=function(e){var t;if(arguments.length>1&&(t=c.call(arguments,0,-1),e=c.call(arguments,-1)[0]),"function"!=typeof e)throw new Ember.Error("Computed Property declared without a property function");var r=new i(e);return t&&r.property.apply(r,t),r},Ember.cacheFor=function(e,t){var r=e[m],n=r&&r.cache;return n&&t in n?n[t]:void 0};var E,v;if(Ember.FEATURES.isEnabled("composable-computed-properties")){var g=Ember.guidFor,y=Ember.EnumerableUtils.map,w=Ember.EnumerableUtils.filter,_=(Ember.typeOf,function(e){return[g(e)].concat(e._dependentKeys).join("_").replace(/\./g,"_DOT_")}),C=function(e){return e instanceof Ember.ComputedProperty?_(e):e},O=function(e){return y(e,function(e){return C(e)})},A=function(e){return w(e,function(e){return e instanceof Ember.ComputedProperty})},P=function(e,t){t?(e._dependentKeys=O(t),e._dependentCPs=A(t)):e._dependentKeys=e._dependentCPs=[],e.implicitCPKey=_(e)};Ember.computed.normalizeDependentKey=C,Ember.computed.normalizeDependentKeys=O,E=function(e,t){Ember.computed[e]=function(e){var r=O(c.call(arguments));return Ember.computed(e,function(){return t.apply(this,r)})}}}Ember.FEATURES.isEnabled("composable-computed-properties")?v=function(e,t){Ember.computed[e]=function(){var e=c.call(arguments),r=O(e),n=Ember.computed(function(){return t.apply(this,[a(this,r)])});return n.property.apply(n,e)}}:(E=function(e,t){Ember.computed[e]=function(e){var r=c.call(arguments);return Ember.computed(e,function(){return t.apply(this,r)})}},v=function(e,t){Ember.computed[e]=function(){var e=c.call(arguments),r=Ember.computed(function(){return t.apply(this,[a(this,e)])});return r.property.apply(r,e)}}),Ember.FEATURES.isEnabled("composable-computed-properties")&&(Ember.computed.literal=function(e){return Ember.computed(function(){return e})}),E("empty",function(e){return Ember.isEmpty(s(this,e))}),E("notEmpty",function(e){return!Ember.isEmpty(s(this,e))}),E("none",function(e){return Ember.isNone(s(this,e))}),E("not",function(e){return!s(this,e)}),E("bool",function(e){return!!s(this,e)}),E("match",function(e,t){var r=s(this,e);return"string"==typeof r?t.test(r):!1}),E("equal",function(e,t){return s(this,e)===t}),E("gt",function(e,t){return s(this,e)>t}),E("gte",function(e,t){return s(this,e)>=t}),E("lt",function(e,t){return s(this,e)1?(u(this,e,r),r):s(this,e)})},Ember.computed.oneWay=function(e){return Ember.computed(e,function(){return s(this,e)})},Ember.computed.readOnly=function(e){return Ember.computed(e,function(){return s(this,e)}).readOnly()},Ember.computed.defaultTo=function(e){return Ember.computed(function(t,r,n){return 1===arguments.length?null!=n?n:s(this,e):null!=r?r:s(this,e)})}}(),function(){function e(e){return e+r}function t(e){return e+n}var r=":change",n=":before";Ember.addObserver=function(t,r,n,i){return Ember.addListener(t,e(r),n,i),Ember.watch(t,r),this},Ember.observersFor=function(t,r){return Ember.listenersFor(t,e(r))},Ember.removeObserver=function(t,r,n,i){return Ember.unwatch(t,r),Ember.removeListener(t,e(r),n,i),this},Ember.addBeforeObserver=function(e,r,n,i){return Ember.addListener(e,t(r),n,i),Ember.watch(e,r),this},Ember._suspendBeforeObserver=function(e,r,n,i,o){return Ember._suspendListener(e,t(r),n,i,o)},Ember._suspendObserver=function(t,r,n,i,o){return Ember._suspendListener(t,e(r),n,i,o)};var i=Ember.ArrayPolyfills.map;Ember._suspendBeforeObservers=function(e,r,n,o,a){var s=i.call(r,t);return Ember._suspendListeners(e,s,n,o,a)},Ember._suspendObservers=function(t,r,n,o,a){var s=i.call(r,e);return Ember._suspendListeners(t,s,n,o,a)},Ember.beforeObserversFor=function(e,r){return Ember.listenersFor(e,t(r))},Ember.removeBeforeObserver=function(e,r,n,i){return Ember.unwatch(e,r),Ember.removeListener(e,t(r),n,i),this}}(),function(){e("backburner/queue",["exports"],function(e){"use strict";function t(e,t,r){this.daq=e,this.name=t,this.options=r,this._queue=[]}t.prototype={daq:null,name:null,options:null,_queue:null,push:function(e,t,r,n){var i=this._queue;return i.push(e,t,r,n),{queue:this,target:e,method:t}},pushUnique:function(e,t,r,n){var i,o,a,s,u=this._queue;for(a=0,s=u.length;s>a;a+=4)if(i=u[a],o=u[a+1],i===e&&o===t)return u[a+2]=r,u[a+3]=n,{queue:this,target:e,method:t};return this._queue.push(e,t,r,n),{queue:this,target:e,method:t}},flush:function(){var e,t,r,n,i,o=this._queue,a=this.options,s=a&&a.before,u=a&&a.after,l=o.length;for(l&&s&&s(),i=0;l>i;i+=4)e=o[i],t=o[i+1],r=o[i+2],n=o[i+3],r&&r.length>0?t.apply(e,r):t.call(e);l&&u&&u(),o.length>l?(this._queue=o.slice(l),this.flush()):this._queue.length=0},cancel:function(e){var t,r,n,i,o=this._queue;for(n=0,i=o.length;i>n;n+=4)if(t=o[n],r=o[n+1],t===e.target&&r===e.method)return o.splice(n,4),!0;if(o=this._queueBeingFlushed)for(n=0,i=o.length;i>n;n+=4)if(t=o[n],r=o[n+1],t===e.target&&r===e.method)return o[n+1]=null,!0}},e.Queue=t}),e("backburner/deferred_action_queues",["backburner/queue","exports"],function(e,t){"use strict";function r(e,t){var r=this.queues={};this.queueNames=e=e||[];for(var n,o=0,a=e.length;a>o;o++)n=e[o],r[n]=new i(this,n,t[n])}function n(e,t){for(var r,n,i=0,o=t;o>=i;i++)if(r=e.queueNames[i],n=e.queues[r],n._queue.length)return i;return-1}var i=e.Queue;r.prototype={queueNames:null,queues:null,schedule:function(e,t,r,n,i,o){var a=this.queues,s=a[e];if(!s)throw new Error("You attempted to schedule an action in a queue ("+e+") that doesn't exist");return i?s.pushUnique(t,r,n,o):s.push(t,r,n,o)},flush:function(){for(var e,t,r,i,o=this.queues,a=this.queueNames,s=0,u=a.length;u>s;){e=a[s],t=o[e],r=t._queueBeingFlushed=t._queue.slice(),t._queue=[];var l,c,h,m,p=t.options,d=p&&p.before,f=p&&p.after,b=0,E=r.length;for(E&&d&&d();E>b;)l=r[b],c=r[b+1],h=r[b+2],m=r[b+3],"string"==typeof c&&(c=l[c]),c&&(h&&h.length>0?c.apply(l,h):c.call(l)),b+=4;t._queueBeingFlushed=null,E&&f&&f(),-1===(i=n(this,s))?s++:s=i}}},t.DeferredActionQueues=r}),e("backburner",["backburner/deferred_action_queues","exports"],function(e,t){"use strict";function r(e){return"number"==typeof e||g.test(e)}function n(e,t){this.queueNames=e,this.options=t||{},this.options.defaultQueue||(this.options.defaultQueue=e[0]),this.instanceStack=[]}function i(e){e.begin(),l=v.setTimeout(function(){l=null,e.end()})}function o(e,t,r){(!c||h>t)&&(c&&clearTimeout(c),c=v.setTimeout(function(){c=null,h=null,a(e)},r),h=t)}function a(e){var t,r,n,i,a=+new Date;e.run(function(){for(n=0,i=E.length;i>n&&(t=E[n],!(t>a));n+=2);for(r=E.splice(0,n),n=1,i=r.length;i>n;n+=2)e.schedule(e.options.defaultQueue,null,r[n])}),E.length&&o(e,E[0],E[0]-a)}function s(e,t){for(var r,n=-1,i=0,o=b.length;o>i;i++)if(r=b[i],r[0]===e&&r[1]===t){n=i;break}return n}function u(e,t){for(var r,n=-1,i=0,o=f.length;o>i;i++)if(r=f[i],r[0]===e&&r[1]===t){n=i;break}return n}var l,c,h,m=e.DeferredActionQueues,p=[].slice,d=[].pop,f=[],b=[],E=[],v=this,g=/\d+/;n.prototype={queueNames:null,options:null,currentInstance:null,instanceStack:null,begin:function(){var e=this.options&&this.options.onBegin,t=this.currentInstance;t&&this.instanceStack.push(t),this.currentInstance=new m(this.queueNames,this.options),e&&e(this.currentInstance,t)},end:function(){var e=this.options&&this.options.onEnd,t=this.currentInstance,r=null;try{t.flush()}finally{this.currentInstance=null,this.instanceStack.length&&(r=this.instanceStack.pop(),this.currentInstance=r),e&&e(t,r)}},run:function(e,t){var r;this.begin(),t||(t=e,e=null),"string"==typeof t&&(t=e[t]);var n=!1;try{r=arguments.length>2?t.apply(e,p.call(arguments,2)):t.call(e)}finally{n||(n=!0,this.end())}return r},defer:function(e,t,r){r||(r=t,t=null),"string"==typeof r&&(r=t[r]);var n=this.DEBUG?new Error:void 0,o=arguments.length>3?p.call(arguments,3):void 0;return this.currentInstance||i(this),this.currentInstance.schedule(e,t,r,o,!1,n)},deferOnce:function(e,t,r){r||(r=t,t=null),"string"==typeof r&&(r=t[r]);var n=this.DEBUG?new Error:void 0,o=arguments.length>3?p.call(arguments,3):void 0;return this.currentInstance||i(this),this.currentInstance.schedule(e,t,r,o,!0,n)},setTimeout:function(){function e(){t.apply(i,l)}var t,n,i,a,s,u,l=p.call(arguments),c=l.length,h=this;if(0!==c){if(1===c)t=l.shift(),n=0;else if(2===c)a=l[0],s=l[1],"function"==typeof s||"function"==typeof a[s]?(i=l.shift(),t=l.shift(),n=0):r(s)?(t=l.shift(),n=l.shift()):(t=l.shift(),n=0);else{var m=l[l.length-1];r(m)&&(n=l.pop()),a=l[0],u=l[1],"function"==typeof u||"string"==typeof u&&null!==a&&u in a?(i=l.shift(),t=l.shift()):t=l.shift()}var d=+new Date+parseInt(n,10);"string"==typeof t&&(t=i[t]);var f,b;for(f=0,b=E.length;b>f&&!(d-1?f[i]:(o=v.setTimeout(function(){l||a.run.apply(a,s);var r=u(e,t);r>-1&&f.splice(r,1)},r),l&&a.run.apply(a,s),n=[e,t,o],f.push(n),n)},debounce:function(e,t){var r,n,i,o,a=this,u=arguments,l=d.call(u);return"number"==typeof l||"string"==typeof l?(r=l,l=!1):r=d.call(u),r=parseInt(r,10),n=s(e,t),n>-1&&(i=b[n],b.splice(n,1),clearTimeout(i[2])),o=v.setTimeout(function(){l||a.run.apply(a,u);var r=s(e,t);r>-1&&b.splice(r,1)},r),l&&-1===n&&a.run.apply(a,u),i=[e,t,o],b.push(i),i},cancelTimers:function(){var e,t;for(e=0,t=f.length;t>e;e++)clearTimeout(f[e][2]);for(f=[],e=0,t=b.length;t>e;e++)clearTimeout(b[e][2]);b=[],c&&(clearTimeout(c),c=null),E=[],l&&(clearTimeout(l),l=null)},hasTimers:function(){return!!E.length||l},cancel:function(e){var t=typeof e;if(e&&"object"===t&&e.queue&&e.method)return e.queue.cancel(e);if("function"!==t)return"[object Array]"===Object.prototype.toString.call(e)?this._cancelItem(u,f,e)||this._cancelItem(s,b,e):void 0;for(var r=0,n=E.length;n>r;r+=2)if(E[r+1]===e)return E.splice(r,2),!0},_cancelItem:function(e,t,r){var n,i;return r.length<3?!1:(i=e(r[0],r[1]),i>-1&&(n=t[i],n[2]===r[2])?(t.splice(i,1),clearTimeout(r[2]),!0):!1)}},n.prototype.schedule=n.prototype.defer,n.prototype.scheduleOnce=n.prototype.deferOnce,n.prototype.later=n.prototype.setTimeout,t.Backburner=n})}(),function(){function e(e){try{return a.run.apply(a,e)}catch(t){Ember.onerror(t)}}function r(){Ember.run.currentRunLoop||Ember.assert("You have turned on testing mode, which disabled the run-loop's autorun. You will need to wrap any code with asynchronous side-effects in an Ember.run",!Ember.testing)}{var n=function(e){Ember.run.currentRunLoop=e},i=function(e,t){Ember.run.currentRunLoop=t},o=t("backburner").Backburner,a=new o(["sync","actions","destroy"],{sync:{before:Ember.beginPropertyChanges,after:Ember.endPropertyChanges},defaultQueue:"actions",onBegin:n,onEnd:i}),s=[].slice;[].concat}Ember.run=function(){return Ember.onerror?e(arguments):a.run.apply(a,arguments)},Ember.run.join=function(){if(!Ember.run.currentRunLoop)return Ember.run.apply(Ember.run,arguments);var e=s.call(arguments);e.unshift("actions"),Ember.run.schedule.apply(Ember.run,e)},Ember.run.bind=function(){var e=s.call(arguments);return function(){return Ember.run.join.apply(Ember.run,e.concat(s.call(arguments)))}},Ember.run.backburner=a;Ember.run;Ember.run.currentRunLoop=null,Ember.run.queues=a.queueNames,Ember.run.begin=function(){a.begin()},Ember.run.end=function(){a.end()},Ember.run.schedule=function(){r(),a.schedule.apply(a,arguments)},Ember.run.hasScheduledTimers=function(){return a.hasTimers()},Ember.run.cancelTimers=function(){a.cancelTimers()},Ember.run.sync=function(){a.currentInstance&&a.currentInstance.queues.sync.flush()},Ember.run.later=function(){return a.later.apply(a,arguments)},Ember.run.once=function(){r();var e=s.call(arguments);return e.unshift("actions"),a.scheduleOnce.apply(a,e)},Ember.run.scheduleOnce=function(){return r(),a.scheduleOnce.apply(a,arguments)},Ember.run.next=function(){var e=s.call(arguments);return e.push(1),a.later.apply(a,e)},Ember.run.cancel=function(e){return a.cancel(e)},Ember.run.debounce=function(){return a.debounce.apply(a,arguments)},Ember.run.throttle=function(){return a.throttle.apply(a,arguments)}}(),function(){function e(e,t){return r(o(t)?Ember.lookup:e,t)}function t(e,t){for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r])}Ember.LOG_BINDINGS=!1||!!Ember.ENV.LOG_BINDINGS;var r=Ember.get,n=(Ember.set,Ember.guidFor),i=/^([A-Z$]|([0-9][A-Z$]))/,o=Ember.isGlobalPath=function(e){return i.test(e)},a=function(e,t){this._direction="fwd",this._from=t,this._to=e,this._directionMap=Ember.Map.create()};a.prototype={copy:function(){var e=new a(this._to,this._from);return this._oneWay&&(e._oneWay=!0),e},from:function(e){return this._from=e,this},to:function(e){return this._to=e,this},oneWay:function(){return this._oneWay=!0,this},toString:function(){var e=this._oneWay?"[oneWay]":"";return"Ember.Binding<"+n(this)+">("+this._from+" -> "+this._to+")"+e},connect:function(t){Ember.assert("Must pass a valid object to Ember.Binding.connect()",!!t);var r=this._from,n=this._to;return Ember.trySet(t,n,e(t,r)),Ember.addObserver(t,r,this,this.fromDidChange),this._oneWay||Ember.addObserver(t,n,this,this.toDidChange),this._readyToSync=!0,this},disconnect:function(e){Ember.assert("Must pass a valid object to Ember.Binding.disconnect()",!!e);var t=!this._oneWay;return Ember.removeObserver(e,this._from,this,this.fromDidChange),t&&Ember.removeObserver(e,this._to,this,this.toDidChange),this._readyToSync=!1,this},fromDidChange:function(e){this._scheduleSync(e,"fwd")},toDidChange:function(e){this._scheduleSync(e,"back")},_scheduleSync:function(e,t){var r=this._directionMap,n=r.get(e);n||(Ember.run.schedule("sync",this,this._sync,e),r.set(e,t)),"back"===n&&"fwd"===t&&r.set(e,"fwd")},_sync:function(t){var n=Ember.LOG_BINDINGS;if(!t.isDestroyed&&this._readyToSync){var i=this._directionMap,o=i.get(t),a=this._from,s=this._to;if(i.remove(t),"fwd"===o){var u=e(t,this._from);n&&Ember.Logger.log(" ",this.toString(),"->",u,t),this._oneWay?Ember.trySet(t,s,u):Ember._suspendObserver(t,s,this,this.toDidChange,function(){Ember.trySet(t,s,u)})}else if("back"===o){var l=r(t,this._to);n&&Ember.Logger.log(" ",this.toString(),"<-",l,t),Ember._suspendObserver(t,a,this,this.fromDidChange,function(){Ember.trySet(Ember.isGlobalPath(a)?Ember.lookup:t,a,l)})}}}},t(a,{from:function(){var e=this,t=new e;return t.from.apply(t,arguments)},to:function(){var e=this,t=new e;return t.to.apply(t,arguments)},oneWay:function(e,t){var r=this,n=new r(null,e);return n.oneWay(t)}}),Ember.Binding=a,Ember.bind=function(e,t,r){return new Ember.Binding(t,r).connect(e)},Ember.oneWay=function(e,t,r){return new Ember.Binding(t,r).oneWay().connect(e)}}(),function(){function e(){var e,t=this.__nextSuper;return t&&(this.__nextSuper=null,e=t.apply(this,arguments),this.__nextSuper=t),e}function t(e){var t=N(e,!0),r=t.mixins;return r?t.hasOwnProperty("mixins")||(r=t.mixins=x(r)):r=t.mixins={},r}function r(e,t){return t&&t.length>0&&(e.mixins=O.call(t,function(e){if(e instanceof w)return e;var t=new w;return t.properties=e,t})),e}function n(e){return"function"==typeof e&&e.isMethod!==!1&&e!==Boolean&&e!==Object&&e!==Number&&e!==Array&&e!==Date&&e!==String}function i(e,t){var r;return t instanceof w?(r=V(t),e[r]?k:(e[r]=t,t.properties)):t}function o(e,t,r,n){var i;return i=r[e]||n[e],t[e]&&(i=i?i.concat(t[e]):t[e]),i}function a(e,t,r,n,i){var o;return void 0===n[t]&&(o=i[t]),o=o||e.descs[t],o&&o instanceof Ember.ComputedProperty?(r=x(r),r.func=Ember.wrap(r.func,o.func),r):r}function s(e,t,r,n,i){var o;return void 0===i[t]&&(o=n[t]),o=o||e[t],"function"!=typeof o?r:Ember.wrap(r,o)}function u(e,t,r,n){var i=n[t]||e[t];return i?"function"==typeof i.concat?i.concat(r):Ember.makeArray(i).concat(r):Ember.makeArray(r)}function l(t,r,i,o){var a=o[r]||t[r];if(!a)return i;var u=Ember.merge({},a),l=!1;for(var c in i)if(i.hasOwnProperty(c)){var h=i[c];n(h)?(l=!0,u[c]=s(t,c,h,a,{})):u[c]=h}return l&&(u._super=e),u}function c(e,t,r,i,o,c,h,m){if(r instanceof Ember.Descriptor){if(r===_&&o[t])return k;r.func&&(r=a(i,t,r,c,o)),o[t]=r,c[t]=void 0}else h&&A.call(h,t)>=0||"concatenatedProperties"===t||"mergedProperties"===t?r=u(e,t,r,c):m&&A.call(m,t)>=0?r=l(e,t,r,c):n(r)&&(r=s(e,t,r,c,o)),o[t]=void 0,c[t]=r}function h(e,t,r,n,a,s){function u(e){delete r[e],delete n[e]}for(var l,m,p,d,f,b,E=0,v=e.length;v>E;E++)if(l=e[E],Ember.assert("Expected hash or Mixin instance, got "+Object.prototype.toString.call(l),"object"==typeof l&&null!==l&&"[object Array]"!==Object.prototype.toString.call(l)),m=i(t,l),m!==k)if(m){b=N(a),a.willMergeMixin&&a.willMergeMixin(m),d=o("concatenatedProperties",m,n,a),f=o("mergedProperties",m,n,a);for(p in m)m.hasOwnProperty(p)&&(s.push(p),c(a,p,m[p],b,r,n,d,f));m.hasOwnProperty("toString")&&(a.toString=m.toString)}else l.mixins&&(h(l.mixins,t,r,n,a,s),l._without&&P.call(l._without,u))}function m(e,t,r,n){if(D.test(t)){var i=n.bindings;i?n.hasOwnProperty("bindings")||(i=n.bindings=x(n.bindings)):i=n.bindings={},i[t]=r}}function p(e,t){var r,n,i,o=t.bindings;if(o){for(r in o)n=o[r],n&&(i=r.slice(0,-7),n instanceof Ember.Binding?(n=n.copy(),n.to(i)):n=new Ember.Binding(i,n),n.connect(e),e[r]=n);t.bindings={}}}function d(e,t){return p(e,t||N(e)),e}function f(e,t,r,n,i){var o,a=t.methodName;return n[a]||i[a]?(o=i[a],t=n[a]):r.descs[a]?(t=r.descs[a],o=void 0):(t=void 0,o=e[a]),{desc:t,value:o}}function b(e,t,r,n,i){var o=r[n];if(o)for(var a=0,s=o.length;s>a;a++)Ember[i](e,o[a],null,t)}function E(e,t,r){var n=e[t];"function"==typeof n&&(b(e,t,n,"__ember_observesBefore__","removeBeforeObserver"),b(e,t,n,"__ember_observes__","removeObserver"),b(e,t,n,"__ember_listens__","removeListener")),"function"==typeof r&&(b(e,t,r,"__ember_observesBefore__","addBeforeObserver"),b(e,t,r,"__ember_observes__","addObserver"),b(e,t,r,"__ember_listens__","addListener"))}function v(r,n,i){var o,a,s,u={},l={},c=N(r),p=[];r._super=e,h(n,t(r),u,l,r,p);for(var b=0,v=p.length;v>b;b++)if(o=p[b],"constructor"!==o&&l.hasOwnProperty(o)&&(s=u[o],a=l[o],s!==_)){for(;s&&s instanceof C;){var g=f(r,s,c,u,l);s=g.desc,a=g.value}(void 0!==s||void 0!==a)&&(E(r,o,a),m(r,o,a,c),S(r,o,s,a,c))}return i||d(r,c),r}function g(e,t,r){var n=V(e);if(r[n])return!1;if(r[n]=!0,e===t)return!0;for(var i=e.mixins,o=i?i.length:0;--o>=0;)if(g(i[o],t,r))return!0;return!1}function y(e,t,r){if(!r[V(t)])if(r[V(t)]=!0,t.properties){var n=t.properties;for(var i in n)n.hasOwnProperty(i)&&(e[i]=!0)}else t.mixins&&P.call(t.mixins,function(t){y(e,t,r)})}var w,_,C,O=Ember.ArrayPolyfills.map,A=Ember.ArrayPolyfills.indexOf,P=Ember.ArrayPolyfills.forEach,T=[].slice,x=Ember.create,S=Ember.defineProperty,V=Ember.guidFor,N=Ember.meta,I=Ember.META_KEY,R=Ember.expandProperties,k={},D=Ember.IS_BINDING=/^.+Binding$/;Ember.mixin=function(e){var t=T.call(arguments,1);return v(e,t,!1),e},Ember.Mixin=function(){return r(this,arguments)},w=Ember.Mixin,w.prototype={properties:null,mixins:null,ownerConstructor:null},w._apply=v,w.applyPartial=function(e){var t=T.call(arguments,1);return v(e,t,!0)},w.finishPartial=d,Ember.anyUnprocessedMixins=!1,w.create=function(){Ember.anyUnprocessedMixins=!0;var e=this;return r(new e,arguments)};var j=w.prototype;j.reopen=function(){var e,t;this.properties?(e=w.create(),e.properties=this.properties,delete this.properties,this.mixins=[e]):this.mixins||(this.mixins=[]);var r,n=arguments.length,i=this.mixins;for(r=0;n>r;r++)e=arguments[r],Ember.assert("Expected hash or Mixin instance, got "+Object.prototype.toString.call(e),"object"==typeof e&&null!==e&&"[object Array]"!==Object.prototype.toString.call(e)),e instanceof w?i.push(e):(t=w.create(),t.properties=e,i.push(t));return this},j.apply=function(e){return v(e,[this],!1)},j.applyPartial=function(e){return v(e,[this],!0)},j.detect=function(e){if(!e)return!1;if(e instanceof w)return g(e,this,{});var t=e[I],r=t&&t.mixins;return r?!!r[V(this)]:!1},j.without=function(){var e=new w(this);return e._without=T.call(arguments),e},j.keys=function(){var e={},t={},r=[];y(e,this,t);for(var n in e)e.hasOwnProperty(n)&&r.push(n);return r},w.mixins=function(e){var t=e[I],r=t&&t.mixins,n=[];if(!r)return n;for(var i in r){var o=r[i];o.properties||n.push(o)}return n},_=new Ember.Descriptor,_.toString=function(){return"(Required Property)"},Ember.required=function(){return _},C=function(e){this.methodName=e},C.prototype=new Ember.Descriptor,Ember.aliasMethod=function(e){return new C(e)},Ember.observer=function(){var e,t=T.call(arguments,-1)[0],r=function(t){e.push(t)},n=T.call(arguments,0,-1);"function"!=typeof t&&(t=arguments[0],n=T.call(arguments,1)),e=[];for(var i=0;ie;e++){var r=arguments[e];Ember.assert("Immediate observers must observe internal properties only, not properties on other objects.","string"!=typeof r||-1===r.indexOf("."))}return Ember.observer.apply(this,arguments)},Ember.beforeObserver=function(){var e,t=T.call(arguments,-1)[0],r=function(t){e.push(t)},n=T.call(arguments,0,-1);"function"!=typeof t&&(t=arguments[0],n=T.call(arguments,1)),e=[];for(var i=0;ir;r++)if(e[r]===t)return r;return-1},r=function(e){var t=e._promiseCallbacks;return t||(t=e._promiseCallbacks={}),t};e["default"]={mixin:function(e){return e.on=this.on,e.off=this.off,e.trigger=this.trigger,e._promiseCallbacks=void 0,e},on:function(e,n){var i,o=r(this);i=o[e],i||(i=o[e]=[]),-1===t(i,n)&&i.push(n)},off:function(e,n){var i,o,a=r(this);return n?(i=a[e],o=t(i,n),void(-1!==o&&i.splice(o,1))):void(a[e]=[])},trigger:function(e,t){var n,i,o=r(this);if(n=o[e])for(var a=0;at;t++)e[t]&&i.push(n[t]);return i})})}var o=e["default"],a=t["default"],s=r.isFunction,u=r.isArray;n["default"]=i}),e("rsvp/hash",["./promise","./utils","exports"],function(e,t,r){"use strict";var n=e["default"],i=t.isNonThenable,o=t.keysOf;r["default"]=function(e){return new n(function(t,r){function a(e){return function(r){c[e]=r,0===--m&&t(c)}}function s(e){m=0,r(e)}var u,l,c={},h=o(e),m=h.length;if(0===m)return void t(c);for(var p=0;ps;s++)l.push(t(n[s]));return i(l,r)})}}),e("rsvp/node",["./promise","exports"],function(e,t){"use strict";function r(e,t){return function(r,n){r?t(r):e(arguments.length>2?i.call(arguments,1):n)}}var n=e["default"],i=Array.prototype.slice;t["default"]=function(e,t){return function(){var o=i.call(arguments),a=this||t;return new n(function(t,i){n.all(o).then(function(n){try{n.push(r(t,i)),e.apply(a,n)}catch(o){i(o)}})})}}}),e("rsvp/promise",["./config","./events","./instrument","./utils","./promise/cast","./promise/all","./promise/race","./promise/resolve","./promise/reject","exports"],function(e,t,r,n,i,o,a,s,u,l){"use strict";function c(){}function h(e,t){if(!A(e))throw new TypeError("You must pass a resolver function as the first argument to the promise constructor");if(!(this instanceof h))throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.");this._id=R++,this._label=t,this._subscribers=[],_.instrument&&C("created",this),c!==e&&m(e,this)}function m(e,t){function r(e){E(t,e)}function n(e){g(t,e)}try{e(r,n)}catch(i){n(i)}}function p(e,t,r,n){var i=e._subscribers,o=i.length;i[o]=t,i[o+j]=r,i[o+M]=n}function d(e,t){var r,n,i=e._subscribers,o=e._detail;_.instrument&&C(t===j?"fulfilled":"rejected",e);for(var a=0;aa;a++){if(n=t[a],o=i(e,n.fullName),void 0===o)throw new Error("Attempting to inject an unknown injection: `"+n.fullName+"`");r[n.property]=o}return r}function u(e,t,r){var n=e._options.get(t);if(n&&void 0!==n[r])return n[r];var i=t.split(":")[0];return n=e._typeOptions.get(i),n?n[r]:void 0}function l(e,t){var r,n=t,i=e.resolve(n),o=e.factoryCache,a=t.split(":")[0];if(void 0!==i){if(o.has(t))return o.get(t);if(!i||"function"!=typeof i.extend||!Ember.MODEL_FACTORY_INJECTIONS&&"model"===a)return i;var s=c(e,t),u=h(e,t);return u._toString=e.makeToString(i,t),r=i.extend(s),r.reopenClass(u),o.set(t,r),r}}function c(e,t){var r=t.split(":"),n=r[0],i=[];return i=i.concat(e.typeInjections.get(n)||[]),i=i.concat(e.injections[t]||[]),i=s(e,i),i._debugContainerKey=t,i.container=e,i}function h(e,t){var r=t.split(":"),n=r[0],i=[];return i=i.concat(e.factoryTypeInjections.get(n)||[]),i=i.concat(e.factoryInjections[t]||[]),i=s(e,i),i._debugContainerKey=t,i}function m(e,t){var r=l(e,t);return u(e,t,"instantiate")===!1?r:r?"function"==typeof r.extend?r.create():r.create(c(e,t)):void 0}function p(e,t){e.cache.eachLocal(function(r,n){u(e,r,"instantiate")!==!1&&t(n)})}function d(e){e.cache.eachLocal(function(t,r){u(e,t,"instantiate")!==!1&&r.destroy()}),e.cache.dict={}}function f(e,t,r,n){var i=e.get(t);i||(i=[],e.set(t,i)),i.push({property:r,fullName:n})}function b(e){if(!g.test(e))throw new TypeError("Invalid Fullname, expected: `type:name` got: "+e)}function E(e,t,r,n){var i=e[t]=e[t]||[];i.push({property:r,fullName:n})}var v=e["default"];r.prototype={parent:null,children:null,resolver:null,registry:null,cache:null,typeInjections:null,injections:null,_options:null,_typeOptions:null,child:function(){var e=new r(this);return this.children.push(e),e},set:function(e,t,r){e[t]=r},register:function(e,t,r){if(b(e),void 0===t)throw new TypeError("Attempting to register an unknown factory: `"+e+"`");var n=this.normalize(e);if(this.cache.has(n))throw new Error("Cannot re-register: `"+e+"`, as it has already been looked up.");this.registry.set(n,t),this._options.set(n,r||{})},unregister:function(e){b(e);var t=this.normalize(e);this.registry.remove(t),this.cache.remove(t),this.factoryCache.remove(t),this.resolveCache.remove(t),this._options.remove(t)},resolve:function(e){b(e);var t=this.normalize(e),r=this.resolveCache.get(t);if(r)return r;var n=this.resolver(t)||this.registry.get(t);return this.resolveCache.set(t,n),n},describe:function(e){return e},normalize:function(e){return e},makeToString:function(e){return e.toString()},lookup:function(e,t){return b(e),i(this,this.normalize(e),t)},lookupFactory:function(e){return b(e),l(this,this.normalize(e))},has:function(e){return b(e),n(this,this.normalize(e))},optionsForType:function(e,t){this.parent&&o("optionsForType"),this._typeOptions.set(e,t)},options:function(e,t){this.optionsForType(e,t)},typeInjection:function(e,t,r){b(r),this.parent&&o("typeInjection"),f(this.typeInjections,e,t,r)},injection:function(e,t,r){this.parent&&o("injection"),b(r);var n=this.normalize(r);if(-1===e.indexOf(":"))return this.typeInjection(e,t,n);b(e);var i=this.normalize(e);E(this.injections,i,t,n)},factoryTypeInjection:function(e,t,r){this.parent&&o("factoryTypeInjection"),f(this.factoryTypeInjections,e,t,this.normalize(r))},factoryInjection:function(e,t,r){this.parent&&o("injection");var n=this.normalize(e),i=this.normalize(r);return b(r),-1===e.indexOf(":")?this.factoryTypeInjection(n,t,i):(b(e),void E(this.factoryInjections,n,t,i))},destroy:function(){for(var e=0,t=this.children.length;t>e;e++)this.children[e].destroy();this.children=[],p(this,function(e){e.destroy()}),this.parent=void 0,this.isDestroyed=!0},reset:function(){for(var e=0,t=this.children.length;t>e;e++)d(this.children[e]);d(this)}};var g=/^[^:]+.+:[^:]+$/;t["default"]=r}),e("container/inheriting_dict",["exports"],function(e){"use strict";function t(e){this.parent=e,this.dict={}}t.prototype={parent:null,dict:null,get:function(e){var t=this.dict;return t.hasOwnProperty(e)?t[e]:this.parent?this.parent.get(e):void 0},set:function(e,t){this.dict[e]=t},remove:function(e){delete this.dict[e]},has:function(e){var t=this.dict;return t.hasOwnProperty(e)?!0:this.parent?this.parent.has(e):!1},eachLocal:function(e,t){var r=this.dict;for(var n in r)r.hasOwnProperty(n)&&e.call(t,n,r[n])}},e["default"]=t}),e("container",["container/container","exports"],function(e,t){"use strict";Ember.MODEL_FACTORY_INJECTIONS=!1||!!Ember.ENV.MODEL_FACTORY_INJECTIONS;var r=e["default"];t["default"]=r})}(),function(){function e(r,n,i,o){var a,s,u;if("object"!=typeof r||null===r)return r;if(n&&(s=t(i,r))>=0)return o[s];if(Ember.assert("Cannot clone an Ember.Object that does not implement Ember.Copyable",!(r instanceof Ember.Object)||Ember.Copyable&&Ember.Copyable.detect(r)),"array"===Ember.typeOf(r)){if(a=r.slice(),n)for(s=a.length;--s>=0;)a[s]=e(a[s],n,i,o)}else if(Ember.Copyable&&Ember.Copyable.detect(r))a=r.copy(n,i,o);else if(r instanceof Date)a=new Date(r.getTime());else{a={};for(u in r)r.hasOwnProperty(u)&&"__"!==u.substring(0,2)&&(a[u]=n?e(r[u],n,i,o):r[u])}return n&&(i.push(r),o.push(a)),a}var t=Ember.EnumerableUtils.indexOf;if(Ember.compare=function i(e,t){if(e===t)return 0;var r=Ember.typeOf(e),n=Ember.typeOf(t),o=Ember.Comparable;if(o){if("instance"===r&&o.detect(e.constructor))return e.constructor.compare(e,t);if("instance"===n&&o.detect(t.constructor))return 1-t.constructor.compare(t,e)}var a=Ember.ORDER_DEFINITION_MAPPING;if(!a){var s=Ember.ORDER_DEFINITION;a=Ember.ORDER_DEFINITION_MAPPING={};var u,l;for(u=0,l=s.length;l>u;++u)a[s[u]]=u;delete Ember.ORDER_DEFINITION}var c=a[r],h=a[n];if(h>c)return-1;if(c>h)return 1;switch(r){case"boolean":case"number":return t>e?-1:e>t?1:0;case"string":var m=e.localeCompare(t);return 0>m?-1:m>0?1:0;case"array":for(var p=e.length,d=t.length,f=Math.min(p,d),b=0,E=0;0===b&&f>E;)b=i(e[E],t[E]),E++;return 0!==b?b:d>p?-1:p>d?1:0;case"instance":return Ember.Comparable&&Ember.Comparable.detect(e)?e.compare(e,t):0;case"date":var v=e.getTime(),g=t.getTime();return g>v?-1:v>g?1:0;default:return 0}},Ember.copy=function(t,r){return"object"!=typeof t||null===t?t:Ember.Copyable&&Ember.Copyable.detect(t)?t.copy(r):e(t,r,r?[]:null,r?[]:null)},Ember.isEqual=function(e,t){return e&&"function"==typeof e.isEqual?e.isEqual(t):e===t},Ember.ORDER_DEFINITION=Ember.ENV.ORDER_DEFINITION||["undefined","null","boolean","number","string","array","object","instance","function","class","date"],Ember.keys=Object.keys,!Ember.keys||Ember.create.isSimulated){var r=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","valueOf","toLocaleString","toString"],n=function(e,r,n){"__"!==n.substring(0,2)&&"_super"!==n&&(t(r,n)>=0||e.hasOwnProperty(n)&&r.push(n))};Ember.keys=function(e){var t,i=[];for(t in e)n(e,i,t);for(var o=0,a=r.length;a>o;o++)t=r[o],n(e,i,t);return i}}}(),function(){var e=/[ _]/g,t={},r=/([a-z\d])([A-Z])/g,n=/(\-|_|\.|\s)+(.)?/g,i=/([a-z\d])([A-Z]+)/g,o=/\-|\s+/g;Ember.STRINGS={},Ember.String={fmt:function(e,t){var r=0;return e.replace(/%@([0-9]+)?/g,function(e,n){return n=n?parseInt(n,10)-1:r++,e=t[n],null===e?"(null)":void 0===e?"":Ember.inspect(e)})},loc:function(e,t){return e=Ember.STRINGS[e]||e,Ember.String.fmt(e,t)},w:function(e){return e.split(/\s+/)},decamelize:function(e){return e.replace(r,"$1_$2").toLowerCase()},dasherize:function(r){var n,i=t,o=i.hasOwnProperty(r);return o?i[r]:(n=Ember.String.decamelize(r).replace(e,"-"),i[r]=n,n)},camelize:function(e){return e.replace(n,function(e,t,r){return r?r.toUpperCase():""}).replace(/^([A-Z])/,function(e){return e.toLowerCase()})},classify:function(e){for(var t=e.split("."),r=[],n=0,i=t.length;i>n;n++){var o=Ember.String.camelize(t[n]);r.push(o.charAt(0).toUpperCase()+o.substr(1))}return r.join(".")},underscore:function(e){return e.replace(i,"$1_$2").replace(o,"_").toLowerCase()},capitalize:function(e){return e.charAt(0).toUpperCase()+e.substr(1)}}}(),function(){var e=Ember.String.fmt,t=Ember.String.w,r=Ember.String.loc,n=Ember.String.camelize,i=Ember.String.decamelize,o=Ember.String.dasherize,a=Ember.String.underscore,s=Ember.String.capitalize,u=Ember.String.classify;(Ember.EXTEND_PROTOTYPES===!0||Ember.EXTEND_PROTOTYPES.String)&&(String.prototype.fmt=function(){return e(this,arguments)},String.prototype.w=function(){return t(this)},String.prototype.loc=function(){return r(this,arguments)},String.prototype.camelize=function(){return n(this)},String.prototype.decamelize=function(){return i(this)},String.prototype.dasherize=function(){return o(this)},String.prototype.underscore=function(){return a(this)},String.prototype.classify=function(){return u(this)},String.prototype.capitalize=function(){return s(this)})}(),function(){var e=Ember.get,t=Ember.set,r=Array.prototype.slice,n=Ember.getProperties;Ember.Observable=Ember.Mixin.create({get:function(t){return e(this,t)},getProperties:function(){return n.apply(null,[this].concat(r.call(arguments)))},set:function(e,r){return t(this,e,r),this},setProperties:function(e){return Ember.setProperties(this,e)},beginPropertyChanges:function(){return Ember.beginPropertyChanges(),this},endPropertyChanges:function(){return Ember.endPropertyChanges(),this},propertyWillChange:function(e){return Ember.propertyWillChange(this,e),this},propertyDidChange:function(e){return Ember.propertyDidChange(this,e),this},notifyPropertyChange:function(e){return this.propertyWillChange(e),this.propertyDidChange(e),this},addBeforeObserver:function(e,t,r){Ember.addBeforeObserver(this,e,t,r)},addObserver:function(e,t,r){Ember.addObserver(this,e,t,r)},removeObserver:function(e,t,r){Ember.removeObserver(this,e,t,r)},hasObserverFor:function(e){return Ember.hasListeners(this,e+":change")},getWithDefault:function(e,t){return Ember.getWithDefault(this,e,t)},incrementProperty:function(r,n){return Ember.isNone(n)&&(n=1),Ember.assert("Must pass a numeric value to incrementProperty",!isNaN(parseFloat(n))&&isFinite(n)),t(this,r,(e(this,r)||0)+n),e(this,r)},decrementProperty:function(r,n){return Ember.isNone(n)&&(n=1),Ember.assert("Must pass a numeric value to decrementProperty",!isNaN(parseFloat(n))&&isFinite(n)),t(this,r,(e(this,r)||0)-n),e(this,r)},toggleProperty:function(r){return t(this,r,!e(this,r)),e(this,r)},cacheFor:function(e){return Ember.cacheFor(this,e)},observersForKey:function(e){return Ember.observersFor(this,e)}})}(),function(){function e(){var e,t,o=!1,a=function(){o||a.proto(),n(this,i,w),n(this,"__nextSuper",y);var u=s(this),l=u.proto;if(u.proto=this,e){var m=e;e=null,this.reopen.apply(this,m)}if(t){var p=t;t=null;for(var d=this.concatenatedProperties,f=0,E=p.length;E>f;f++){var _=p[f];if(Ember.assert("Ember.Object.create no longer supports mixing in other definitions, use createWithMixins instead.",!(_ instanceof Ember.Mixin)),"object"!=typeof _&&void 0!==_)throw new Ember.Error("Ember.Object.create only accepts objects.");if(_)for(var C=Ember.keys(_),O=0,A=C.length;A>O;O++){var P=C[O];if(_.hasOwnProperty(P)){var T=_[P],x=Ember.IS_BINDING;if(x.test(P)){var S=u.bindings;S?u.hasOwnProperty("bindings")||(S=u.bindings=r(u.bindings)):S=u.bindings={},S[P]=T}var V=u.descs[P];if(Ember.assert("Ember.Object.create no longer supports defining computed properties. Define computed properties using extend() or reopen() before calling create().",!(T instanceof Ember.ComputedProperty)),Ember.assert("Ember.Object.create no longer supports defining methods that call _super.",!("function"==typeof T&&-1!==T.toString().indexOf("._super"))),Ember.assert("`actions` must be provided at extend time, not at create time, when Ember.ActionHandler is used (i.e. views, controllers & routes).",!("actions"===P&&Ember.ActionHandler.detect(this))),d&&g(d,P)>=0){var N=this[P];T=N?"function"==typeof N.concat?N.concat(T):Ember.makeArray(N).concat(T):Ember.makeArray(T)}V?V.set(this,P,T):"function"!=typeof this.setUnknownProperty||P in this?v?Ember.defineProperty(this,P,null,T):this[P]=T:this.setUnknownProperty(P,T)}}}}b(this,u),this.init.apply(this,arguments),u.proto=l,c(this),h(this,"init")};return a.toString=d.prototype.toString,a.willReopen=function(){o&&(a.PrototypeMixin=d.create(a.PrototypeMixin)),o=!1},a._initMixins=function(t){e=t},a._initProperties=function(e){t=e},a.proto=function(){var e=a.superclass;return e&&e.proto(),o||(o=!0,a.PrototypeMixin.applyPartial(a.prototype),l(a.prototype)),this.prototype},a}function t(e){return function(){return e}}var r=(Ember.set,Ember.get,Ember.create),n=Ember.platform.defineProperty,i=Ember.GUID_KEY,o=Ember.guidFor,a=Ember.generateGuid,s=Ember.meta,u=Ember.META_KEY,l=Ember.rewatch,c=Ember.finishChains,h=Ember.sendEvent,m=Ember.destroy,p=Ember.run.schedule,d=Ember.Mixin,f=d._apply,b=d.finishPartial,E=d.prototype.reopen,v=Ember.ENV.MANDATORY_SETTER,g=Ember.EnumerableUtils.indexOf,y={configurable:!0,writable:!0,enumerable:!1,value:void 0},w={configurable:!0,writable:!0,enumerable:!1,value:null},_=e();_.toString=function(){return"Ember.CoreObject"},_.PrototypeMixin=d.create({reopen:function(){return f(this,arguments,!0),this},init:function(){},concatenatedProperties:null,isDestroyed:!1,isDestroying:!1,destroy:function(){return this.isDestroying?void 0:(this.isDestroying=!0,p("actions",this,this.willDestroy),p("destroy",this,this._scheduledDestroy),this)},willDestroy:Ember.K,_scheduledDestroy:function(){this.isDestroyed||(m(this),this.isDestroyed=!0)},bind:function(e,t){return t instanceof Ember.Binding||(t=Ember.Binding.from(t)),t.to(e).connect(this),t},toString:function(){var e="function"==typeof this.toStringExtension,r=e?":"+this.toStringExtension():"",n="<"+this.constructor.toString()+":"+o(this)+r+">";return this.toString=t(n),n}}),_.PrototypeMixin.ownerConstructor=_,Ember.config.overridePrototypeMixin&&Ember.config.overridePrototypeMixin(_.PrototypeMixin),_.__super__=null;var C=d.create({ClassMixin:Ember.required(),PrototypeMixin:Ember.required(),isClass:!0,isMethod:!1,extend:function(){var t,n=e();return n.ClassMixin=d.create(this.ClassMixin),n.PrototypeMixin=d.create(this.PrototypeMixin),n.ClassMixin.ownerConstructor=n,n.PrototypeMixin.ownerConstructor=n,E.apply(n.PrototypeMixin,arguments),n.superclass=this,n.__super__=this.prototype,t=n.prototype=r(this.prototype),t.constructor=n,a(t),s(t).proto=t,n.ClassMixin.apply(n),n},createWithMixins:function(){var e=this;return arguments.length>0&&this._initMixins(arguments),new e},create:function(){var e=this;return arguments.length>0&&this._initProperties(arguments),new e},reopen:function(){return this.willReopen(),E.apply(this.PrototypeMixin,arguments),this},reopenClass:function(){return E.apply(this.ClassMixin,arguments),f(this,arguments,!1),this},detect:function(e){if("function"!=typeof e)return!1;for(;e;){if(e===this)return!0;e=e.superclass}return!1},detectInstance:function(e){return e instanceof this},metaForProperty:function(e){var t=this.proto()[u],r=t&&t.descs[e];return Ember.assert("metaForProperty() could not find a computed property with key '"+e+"'.",!!r&&r instanceof Ember.ComputedProperty),r._meta||{}},eachComputedProperty:function(e,t){var r,n=this.proto(),i=s(n).descs,o={};for(var a in i)r=i[a],r instanceof Ember.ComputedProperty&&e.call(t||this,a,r._meta||o)}});C.ownerConstructor=_,Ember.config.overrideClassMixin&&Ember.config.overrideClassMixin(C),_.ClassMixin=C,C.apply(_),Ember.CoreObject=_}(),function(){Ember.Object=Ember.CoreObject.extend(Ember.Observable),Ember.Object.toString=function(){return"Ember.Object"}}(),function(){function e(t,r,i){var a=t.length;l[t.join(".")]=r;for(var s in r)if(c.call(r,s)){var u=r[s];if(t[a]=s,u&&u.toString===n)u.toString=o(t.join(".")),u[m]=t.join(".");else if(u&&u.isNamespace){if(i[h(u)])continue;i[h(u)]=!0,e(t,u,i)}}t.length=a}function t(){var e,t,r=Ember.Namespace,n=Ember.lookup;if(!r.PROCESSED)for(var i in n)if("parent"!==i&&"top"!==i&&"frameElement"!==i&&"webkitStorageInfo"!==i&&!("globalStorage"===i&&n.StorageList&&n.globalStorage instanceof n.StorageList||n.hasOwnProperty&&!n.hasOwnProperty(i))){try{e=Ember.lookup[i],t=e&&e.isNamespace}catch(o){continue}t&&(Ember.deprecate("Namespaces should not begin with lowercase.",/^[A-Z]/.test(i)),e[m]=i)}}function r(e){var t=e.superclass;return t?t[m]?t[m]:r(t):void 0}function n(){Ember.BOOTED||this[m]||i();var e;if(this[m])e=this[m];else if(this._toString)e=this._toString;else{var t=r(this);e=t?"(subclass of "+t+")":"(unknown mixin)",this.toString=o(e)}return e}function i(){var r=!u.PROCESSED,n=Ember.anyUnprocessedMixins;if(r&&(t(),u.PROCESSED=!0),r||n){for(var i,o=u.NAMESPACES,a=0,s=o.length;s>a;a++)i=o[a],e([i.toString()],i,{});Ember.anyUnprocessedMixins=!1}}function o(e){return function(){return e}}var a=Ember.get,s=Ember.ArrayPolyfills.indexOf,u=Ember.Namespace=Ember.Object.extend({isNamespace:!0,init:function(){Ember.Namespace.NAMESPACES.push(this),Ember.Namespace.PROCESSED=!1},toString:function(){var e=a(this,"name");return e?e:(t(),this[Ember.GUID_KEY+"_name"])},nameClasses:function(){e([this.toString()],this,{})},destroy:function(){var e=Ember.Namespace.NAMESPACES;Ember.lookup[this.toString()]=void 0,delete Ember.Namespace.NAMESPACES_BY_ID[this.toString()],e.splice(s.call(e,this),1),this._super()}});u.reopenClass({NAMESPACES:[Ember],NAMESPACES_BY_ID:{},PROCESSED:!1,processAll:i,byName:function(e){return Ember.BOOTED||i(),l[e]}});var l=u.NAMESPACES_BY_ID,c={}.hasOwnProperty,h=Ember.guidFor,m=Ember.NAME_KEY=Ember.GUID_KEY+"_name";Ember.Mixin.prototype.toString=n}(),function(){function e(e,t){var r=t.slice(8);r in this||l(this,r)}function t(e,t){var r=t.slice(8);r in this||c(this,r)}var r=Ember.get,n=Ember.set,i=Ember.String.fmt,o=Ember.addBeforeObserver,a=Ember.addObserver,s=Ember.removeBeforeObserver,u=Ember.removeObserver,l=Ember.propertyWillChange,c=Ember.propertyDidChange,h=Ember.meta,m=Ember.defineProperty;Ember.ObjectProxy=Ember.Object.extend({content:null,_contentDidChange:Ember.observer("content",function(){Ember.assert("Can't set ObjectProxy's content to itself",this.get("content")!==this)}),isTruthy:Ember.computed.bool("content"),_debugContainerKey:null,willWatchProperty:function(r){var n="content."+r;o(this,n,null,e),a(this,n,null,t)},didUnwatchProperty:function(r){var n="content."+r;s(this,n,null,e),u(this,n,null,t)},unknownProperty:function(e){var t=r(this,"content");return t?r(t,e):void 0},setUnknownProperty:function(e,t){var o=h(this);if(o.proto===this)return m(this,e,null,t),t;var a=r(this,"content");return Ember.assert(i("Cannot delegate set('%@', %@) to the 'content' property of object proxy %@: its 'content' is undefined.",[e,t,this]),a),n(a,e,t)}})}(),function(){function e(){return 0===s.length?{}:s.pop()}function t(e){return s.push(e),null}function r(e,t){function r(r){var o=n(r,e);return i?t===o:!!o}var i=2===arguments.length;return r}var n=Ember.get,i=Ember.set,o=Array.prototype.slice,a=Ember.EnumerableUtils.indexOf,s=[];Ember.Enumerable=Ember.Mixin.create({nextObject:Ember.required(Function),firstObject:Ember.computed(function(){if(0===n(this,"length"))return void 0;var r,i=e();return r=this.nextObject(0,null,i),t(i),r}).property("[]"),lastObject:Ember.computed(function(){var r=n(this,"length");if(0===r)return void 0;var i,o=e(),a=0,s=null;do s=i,i=this.nextObject(a++,s,o);while(void 0!==i);return t(o),s}).property("[]"),contains:function(e){return void 0!==this.find(function(t){return t===e})},forEach:function(r,i){if("function"!=typeof r)throw new TypeError;var o=n(this,"length"),a=null,s=e();void 0===i&&(i=null);for(var u=0;o>u;u++){var l=this.nextObject(u,a,s);r.call(i,l,u,this),a=l}return a=null,s=t(s),this},getEach:function(e){return this.mapBy(e)},setEach:function(e,t){return this.forEach(function(r){i(r,e,t)})},map:function(e,t){var r=Ember.A();return this.forEach(function(n,i,o){r[i]=e.call(t,n,i,o)}),r},mapBy:function(e){return this.map(function(t){return n(t,e)})},mapProperty:Ember.aliasMethod("mapBy"),filter:function(e,t){var r=Ember.A();return this.forEach(function(n,i,o){e.call(t,n,i,o)&&r.push(n)}),r},reject:function(e,t){return this.filter(function(){return!e.apply(t,arguments)})},filterBy:function(){return this.filter(r.apply(this,arguments))},filterProperty:Ember.aliasMethod("filterBy"),rejectBy:function(e,t){var r=function(r){return n(r,e)===t},i=function(t){return!!n(t,e)},o=2===arguments.length?r:i;return this.reject(o)},rejectProperty:Ember.aliasMethod("rejectBy"),find:function(r,i){var o=n(this,"length");void 0===i&&(i=null);for(var a,s,u=null,l=!1,c=e(),h=0;o>h&&!l;h++)a=this.nextObject(h,u,c),(l=r.call(i,a,h,this))&&(s=a),u=a;return a=u=null,c=t(c),s},findBy:function(){return this.find(r.apply(this,arguments))},findProperty:Ember.aliasMethod("findBy"),every:function(e,t){return!this.find(function(r,n,i){return!e.call(t,r,n,i)})},everyBy:Ember.aliasMethod("isEvery"),everyProperty:Ember.aliasMethod("isEvery"),isEvery:function(){return this.every(r.apply(this,arguments))},any:function(r,i){var o,a,s=n(this,"length"),u=e(),l=!1,c=null;for(void 0===i&&(i=null),a=0;s>a&&!l;a++)o=this.nextObject(a,c,u),l=r.call(i,o,a,this),c=o;return o=c=null,u=t(u),l},some:Ember.aliasMethod("any"),isAny:function(){return this.any(r.apply(this,arguments))},anyBy:Ember.aliasMethod("isAny"),someProperty:Ember.aliasMethod("isAny"),reduce:function(e,t,r){if("function"!=typeof e)throw new TypeError;var n=t;return this.forEach(function(t,i){n=e(n,t,i,this,r)},this),n},invoke:function(e){var t,r=Ember.A();return arguments.length>1&&(t=o.call(arguments,1)),this.forEach(function(n,i){var o=n&&n[e];"function"==typeof o&&(r[i]=t?o.apply(n,t):n[e]())},this),r},toArray:function(){var e=Ember.A();return this.forEach(function(t,r){e[r]=t}),e},compact:function(){return this.filter(function(e){return null!=e})},without:function(e){if(!this.contains(e))return this;var t=Ember.A();return this.forEach(function(r){r!==e&&(t[t.length]=r)}),t},uniq:function(){var e=Ember.A();return this.forEach(function(t){a(e,t)<0&&e.push(t)}),e},"[]":Ember.computed(function(){return this}),addEnumerableObserver:function(e,t){var r=t&&t.willChange||"enumerableWillChange",i=t&&t.didChange||"enumerableDidChange",o=n(this,"hasEnumerableObservers");return o||Ember.propertyWillChange(this,"hasEnumerableObservers"),Ember.addListener(this,"@enumerable:before",e,r),Ember.addListener(this,"@enumerable:change",e,i),o||Ember.propertyDidChange(this,"hasEnumerableObservers"),this},removeEnumerableObserver:function(e,t){var r=t&&t.willChange||"enumerableWillChange",i=t&&t.didChange||"enumerableDidChange",o=n(this,"hasEnumerableObservers");return o&&Ember.propertyWillChange(this,"hasEnumerableObservers"),Ember.removeListener(this,"@enumerable:before",e,r),Ember.removeListener(this,"@enumerable:change",e,i),o&&Ember.propertyDidChange(this,"hasEnumerableObservers"),this},hasEnumerableObservers:Ember.computed(function(){return Ember.hasListeners(this,"@enumerable:change")||Ember.hasListeners(this,"@enumerable:before")}),enumerableContentWillChange:function(e,t){var r,i,o;return r="number"==typeof e?e:e?n(e,"length"):e=-1,i="number"==typeof t?t:t?n(t,"length"):t=-1,o=0>i||0>r||i-r!==0,-1===e&&(e=null),-1===t&&(t=null),Ember.propertyWillChange(this,"[]"),o&&Ember.propertyWillChange(this,"length"),Ember.sendEvent(this,"@enumerable:before",[this,e,t]),this},enumerableContentDidChange:function(e,t){var r,i,o;return r="number"==typeof e?e:e?n(e,"length"):e=-1,i="number"==typeof t?t:t?n(t,"length"):t=-1,o=0>i||0>r||i-r!==0,-1===e&&(e=null),-1===t&&(t=null),Ember.sendEvent(this,"@enumerable:change",[this,e,t]),o&&Ember.propertyDidChange(this,"length"),Ember.propertyDidChange(this,"[]"),this},sortBy:function(){var e=arguments;return this.toArray().sort(function(t,r){for(var i=0;it||t>=e(this,"length")?void 0:e(this,t)},objectsAt:function(e){var t=this;return r(e,function(e){return t.objectAt(e)})},nextObject:function(e){return this.objectAt(e)},"[]":Ember.computed(function(t,r){return void 0!==r&&this.replace(0,e(this,"length"),r),this}),firstObject:Ember.computed(function(){return this.objectAt(0)}),lastObject:Ember.computed(function(){return this.objectAt(e(this,"length")-1)}),contains:function(e){return this.indexOf(e)>=0},slice:function(r,n){var i=Ember.A(),o=e(this,"length");for(t(r)&&(r=0),(t(n)||n>o)&&(n=o),0>r&&(r=o+r),0>n&&(n=o+n);n>r;)i[i.length]=this.objectAt(r++);return i},indexOf:function(t,r){var n,i=e(this,"length");for(void 0===r&&(r=0),0>r&&(r+=i),n=r;i>n;n++)if(this.objectAt(n)===t)return n;return-1},lastIndexOf:function(t,r){var n,i=e(this,"length");for((void 0===r||r>=i)&&(r=i-1),0>r&&(r+=i),n=r;n>=0;n--)if(this.objectAt(n)===t)return n;return-1},addArrayObserver:function(t,r){var n=r&&r.willChange||"arrayWillChange",i=r&&r.didChange||"arrayDidChange",o=e(this,"hasArrayObservers");return o||Ember.propertyWillChange(this,"hasArrayObservers"),Ember.addListener(this,"@array:before",t,n),Ember.addListener(this,"@array:change",t,i),o||Ember.propertyDidChange(this,"hasArrayObservers"),this},removeArrayObserver:function(t,r){var n=r&&r.willChange||"arrayWillChange",i=r&&r.didChange||"arrayDidChange",o=e(this,"hasArrayObservers");return o&&Ember.propertyWillChange(this,"hasArrayObservers"),Ember.removeListener(this,"@array:before",t,n),Ember.removeListener(this,"@array:change",t,i),o&&Ember.propertyDidChange(this,"hasArrayObservers"),this},hasArrayObservers:Ember.computed(function(){return Ember.hasListeners(this,"@array:change")||Ember.hasListeners(this,"@array:before")}),arrayContentWillChange:function(t,r,n){void 0===t?(t=0,r=n=-1):(void 0===r&&(r=-1),void 0===n&&(n=-1)),Ember.isWatching(this,"@each")&&e(this,"@each"),Ember.sendEvent(this,"@array:before",[this,t,r,n]);var i,o;if(t>=0&&r>=0&&e(this,"hasEnumerableObservers")){i=[],o=t+r;for(var a=t;o>a;a++)i.push(this.objectAt(a))}else i=r;return this.enumerableContentWillChange(i,n),this},arrayContentDidChange:function(t,r,i){void 0===t?(t=0,r=i=-1):(void 0===r&&(r=-1),void 0===i&&(i=-1));var o,a;if(t>=0&&i>=0&&e(this,"hasEnumerableObservers")){o=[],a=t+i;for(var s=t;a>s;s++)o.push(this.objectAt(s))}else o=i;this.enumerableContentDidChange(r,o),Ember.sendEvent(this,"@array:change",[this,t,r,i]);var u=e(this,"length"),l=n(this,"firstObject"),c=n(this,"lastObject");return this.objectAt(0)!==l&&(Ember.propertyWillChange(this,"firstObject"),Ember.propertyDidChange(this,"firstObject")),this.objectAt(u-1)!==c&&(Ember.propertyWillChange(this,"lastObject"),Ember.propertyDidChange(this,"lastObject")),this},"@each":Ember.computed(function(){return this.__each||(this.__each=new Ember.EachProxy(this)),this.__each})})}(),function(){function e(e,t){return"@this"===t?e:m(e,t)}function t(e,t,r){this.callbacks=e,this.cp=t,this.instanceMeta=r,this.dependentKeysByGuid={},this.trackedArraysByGuid={},this.suspended=!1,this.changedItems={}}function r(e,t,r){Ember.assert("Internal error: trackedArray is null or undefined",r),this.dependentArray=e,this.index=t,this.item=e.objectAt(t),this.trackedArray=r,this.beforeObserver=null,this.observer=null,this.destroyed=!1}function n(e,t,r){return 0>e?Math.max(0,t+e):t>e?e:Math.min(t-r,e)}function i(e,t,r){return Math.min(r,t-e)}function o(e,t,r,n,i,o){var a={arrayChanged:e,index:r,item:t,propertyName:n,property:i};return o&&(a.previousValues=o),a}function a(e,t,r,n,i){O(e,function(a,s){i.setValue(t.addedItem.call(this,i.getValue(),a,o(e,a,s,n,r),i.sugarMeta))},this)}function s(e,t){{var r;e._callbacks()}e._hasInstanceMeta(this,t)?(r=e._instanceMeta(this,t),r.setValue(e.resetValue(r.getValue()))):r=e._instanceMeta(this,t),e.options.initialize&&e.options.initialize.call(this,r.getValue(),{property:e,propertyName:t},r.sugarMeta)}function u(t,r){if(T.test(r))return!1;var n=e(t,r);return Ember.Array.detect(n)}function l(e,t,r){this.context=e,this.propertyName=t,this.cache=d(e).cache,this.dependentArrays={},this.sugarMeta={},this.initialValue=r}function c(t){var r=this;this.options=t,this._dependentKeys=null,this._itemPropertyKeys={},this._previousItemPropertyKeys={},this.readOnly(),this.cacheable(),this.recomputeOnce=function(e){Ember.run.once(this,n,e)};var n=function(t){var n=(r._dependentKeys,r._instanceMeta(this,t)),i=r._callbacks();s.call(this,r,t),n.dependentArraysObserver.suspendArrayObservers(function(){O(r._dependentKeys,function(t){if(Ember.assert("dependent array "+t+" must be an `Ember.Array`. If you are not extending arrays, you will need to wrap native arrays with `Ember.A`",!(Ember.isArray(e(this,t))&&!Ember.Array.detect(e(this,t)))),u(this,t)){var i=e(this,t),o=n.dependentArrays[t];i===o?r._previousItemPropertyKeys[t]&&(delete r._previousItemPropertyKeys[t],n.dependentArraysObserver.setupPropertyObservers(t,r._itemPropertyKeys[t])):(n.dependentArrays[t]=i,o&&n.dependentArraysObserver.teardownObservers(o,t),i&&n.dependentArraysObserver.setupObservers(i,t))}},this)},this),O(r._dependentKeys,function(o){if(u(this,o)){var s=e(this,o);s&&a.call(this,s,i,r,t,n)}},this)};this.func=function(e){return Ember.assert("Computed reduce values require at least one dependent key",r._dependentKeys),n.call(this,e),r._instanceMeta(this,e).getValue()}}function h(e){return e}var m=Ember.get,p=(Ember.set,Ember.guidFor),d=Ember.meta,f=Ember.propertyWillChange,b=Ember.propertyDidChange,E=Ember.addBeforeObserver,v=Ember.removeBeforeObserver,g=Ember.addObserver,y=Ember.removeObserver,w=Ember.ComputedProperty,_=[].slice,C=Ember.create,O=Ember.EnumerableUtils.forEach,A=(Ember.cacheFor.set,Ember.cacheFor.get,Ember.cacheFor.remove,/^(.*)\.@each\.(.*)/),P=/(.*\.@each){2,}/,T=/\.\[\]$/,x=Ember.expandProperties;t.prototype={setValue:function(e){this.instanceMeta.setValue(e,!0)},getValue:function(){return this.instanceMeta.getValue()},setupObservers:function(e,t){this.dependentKeysByGuid[p(e)]=t,e.addArrayObserver(this,{willChange:"dependentArrayWillChange",didChange:"dependentArrayDidChange"}),this.cp._itemPropertyKeys[t]&&this.setupPropertyObservers(t,this.cp._itemPropertyKeys[t])},teardownObservers:function(e,t){var r=this.cp._itemPropertyKeys[t]||[];delete this.dependentKeysByGuid[p(e)],this.teardownPropertyObservers(t,r),e.removeArrayObserver(this,{willChange:"dependentArrayWillChange",didChange:"dependentArrayDidChange"})},suspendArrayObservers:function(e,t){var r=this.suspended;this.suspended=!0,e.call(t),this.suspended=r},setupPropertyObservers:function(t,r){var n=e(this.instanceMeta.context,t),i=e(n,"length"),o=new Array(i);this.resetTransformations(t,o),O(n,function(e,i){var a=this.createPropertyObserverContext(n,i,this.trackedArraysByGuid[t]);o[i]=a,O(r,function(t){E(e,t,this,a.beforeObserver),g(e,t,this,a.observer)},this)},this)},teardownPropertyObservers:function(e,t){var r,n,i,o=this,a=this.trackedArraysByGuid[e];a&&a.apply(function(e,a,s){s!==Ember.TrackedArray.DELETE&&O(e,function(e){e.destroyed=!0,r=e.beforeObserver,n=e.observer,i=e.item,O(t,function(e){v(i,e,o,r),y(i,e,o,n)})})})},createPropertyObserverContext:function(e,t,n){var i=new r(e,t,n);return this.createPropertyObserver(i),i},createPropertyObserver:function(e){var t=this;e.beforeObserver=function(r,n){return t.itemPropertyWillChange(r,n,e.dependentArray,e)},e.observer=function(r,n){return t.itemPropertyDidChange(r,n,e.dependentArray,e)}},resetTransformations:function(e,t){this.trackedArraysByGuid[e]=new Ember.TrackedArray(t)},trackAdd:function(e,t,r){var n=this.trackedArraysByGuid[e];n&&n.addItems(t,r)},trackRemove:function(e,t,r){var n=this.trackedArraysByGuid[e];return n?n.removeItems(t,r):[]},updateIndexes:function(t,r){var n=e(r,"length");t.apply(function(e,t,r){r!==Ember.TrackedArray.DELETE&&(r!==Ember.TrackedArray.RETAIN||e.length!==n||0!==t)&&O(e,function(e,r){e.index=r+t})})},dependentArrayWillChange:function(t,r,a){function s(e){m[h].destroyed=!0,v(l,e,this,m[h].beforeObserver),y(l,e,this,m[h].observer)}if(!this.suspended){var u,l,c,h,m,d=this.callbacks.removedItem,f=p(t),b=this.dependentKeysByGuid[f],E=this.cp._itemPropertyKeys[b]||[],g=e(t,"length"),w=n(r,g,0),_=i(w,g,a);for(m=this.trackRemove(b,w,_),h=_-1;h>=0&&(c=w+h,!(c>=g));--h)l=t.objectAt(c),O(E,s,this),u=o(t,l,c,this.instanceMeta.propertyName,this.cp),this.setValue(d.call(this.instanceMeta.context,this.getValue(),l,u,this.instanceMeta.sugarMeta)) -}},dependentArrayDidChange:function(t,r,i,a){if(!this.suspended){var s,u,l=this.callbacks.addedItem,c=p(t),h=this.dependentKeysByGuid[c],m=new Array(a),d=this.cp._itemPropertyKeys[h],f=e(t,"length"),b=n(r,f,a);O(t.slice(b,b+a),function(e,r){d&&(u=m[r]=this.createPropertyObserverContext(t,b+r,this.trackedArraysByGuid[h]),O(d,function(t){E(e,t,this,u.beforeObserver),g(e,t,this,u.observer)},this)),s=o(t,e,b+r,this.instanceMeta.propertyName,this.cp),this.setValue(l.call(this.instanceMeta.context,this.getValue(),e,s,this.instanceMeta.sugarMeta))},this),this.trackAdd(h,b,m)}},itemPropertyWillChange:function(t,r,n,i){var o=p(t);this.changedItems[o]||(this.changedItems[o]={array:n,observerContext:i,obj:t,previousValues:{}}),this.changedItems[o].previousValues[r]=e(t,r)},itemPropertyDidChange:function(){this.flushChanges()},flushChanges:function(){var e,t,r,n=this.changedItems;for(e in n)t=n[e],t.observerContext.destroyed||(this.updateIndexes(t.observerContext.trackedArray,t.observerContext.dependentArray),r=o(t.array,t.obj,t.observerContext.index,this.instanceMeta.propertyName,this.cp,t.previousValues),this.setValue(this.callbacks.removedItem.call(this.instanceMeta.context,this.getValue(),t.obj,r,this.instanceMeta.sugarMeta)),this.setValue(this.callbacks.addedItem.call(this.instanceMeta.context,this.getValue(),t.obj,r,this.instanceMeta.sugarMeta)));this.changedItems={}}},l.prototype={getValue:function(){return this.propertyName in this.cache?this.cache[this.propertyName]:this.initialValue},setValue:function(e,t){e!==this.cache[this.propertyName]&&(t&&f(this.context,this.propertyName),void 0===e?delete this.cache[this.propertyName]:this.cache[this.propertyName]=e,t&&b(this.context,this.propertyName))}},Ember.ReduceComputedProperty=c,c.prototype=C(w.prototype),c.prototype._callbacks=function(){if(!this.callbacks){var e=this.options;this.callbacks={removedItem:e.removedItem||h,addedItem:e.addedItem||h}}return this.callbacks},c.prototype._hasInstanceMeta=function(e,t){return!!d(e).cacheMeta[t]},c.prototype._instanceMeta=function(e,r){var n=d(e).cacheMeta,i=n[r];return i||(i=n[r]=new l(e,r,this.initialValue()),i.dependentArraysObserver=new t(this._callbacks(),this,i,e,r,i.sugarMeta)),i},c.prototype.initialValue=function(){return"function"==typeof this.options.initialValue?this.options.initialValue():this.options.initialValue},c.prototype.resetValue=function(){return this.initialValue()},c.prototype.itemPropertyKey=function(e,t){this._itemPropertyKeys[e]=this._itemPropertyKeys[e]||[],this._itemPropertyKeys[e].push(t)},c.prototype.clearItemPropertyKeys=function(e){this._itemPropertyKeys[e]&&(this._previousItemPropertyKeys[e]=this._itemPropertyKeys[e],this._itemPropertyKeys[e]=[])},c.prototype.property=function(){var e,t,r=this,n=_.call(arguments),i=new Ember.Set;return O(n,function(n){if(P.test(n))throw new Ember.Error("Nested @each properties not supported: "+n);if(e=A.exec(n)){t=e[1];var o=e[2],a=function(e){r.itemPropertyKey(t,e)};x(o,a),i.add(t)}else i.add(n)}),w.prototype.property.apply(this,i.toArray())},Ember.reduceComputed=function(e){var t;if(arguments.length>1&&(t=_.call(arguments,0,-1),e=_.call(arguments,-1)[0]),"object"!=typeof e)throw new Ember.Error("Reduce Computed Property declared without an options hash");if(!("initialValue"in e))throw new Ember.Error("Reduce Computed Property declared without an initial value");var r=new c(e);return t&&r.property.apply(r,t),r}}(),function(){function e(){var e=this;return t.apply(this,arguments),this.func=function(t){return function(r){return e._hasInstanceMeta(this,r)||i(e._dependentKeys,function(t){Ember.addObserver(this,t,function(){e.recomputeOnce.call(this,r)})},this),t.apply(this,arguments)}}(this.func),this}var t=Ember.ReduceComputedProperty,r=[].slice,n=Ember.create,i=Ember.EnumerableUtils.forEach;Ember.ArrayComputedProperty=e,e.prototype=n(t.prototype),e.prototype.initialValue=function(){return Ember.A()},e.prototype.resetValue=function(e){return e.clear(),e},e.prototype.didChange=function(){},Ember.arrayComputed=function(t){var n;if(arguments.length>1&&(n=r.call(arguments,0,-1),t=r.call(arguments,-1)[0]),"object"!=typeof t)throw new Ember.Error("Array Computed Property declared without an options hash");var i=new e(t);return n&&i.property.apply(i,n),i}}(),function(){function e(e,i,o,a){function s(e){return n(t.detectInstance(e)?r(e,"content"):e)}var u,l,c,h,m;return arguments.length<4&&(a=r(e,"length")),arguments.length<3&&(o=0),o===a?o:(u=o+Math.floor((a-o)/2),l=e.objectAt(u),h=s(l),m=s(i),h===m?u:(c=this.order(l,i),0===c&&(c=m>h?-1:1),0>c?this.binarySearch(e,i,u+1,a):c>0?this.binarySearch(e,i,o,u):u))}var t,r=Ember.get,n=(Ember.set,Ember.guidFor),i=Ember.merge,o=[].slice,a=Ember.EnumerableUtils.forEach,s=Ember.EnumerableUtils.map;Ember.computed.sum=function(e){return Ember.reduceComputed(e,{initialValue:0,addedItem:function(e,t){return e+t},removedItem:function(e,t){return e-t}})},Ember.computed.max=function(e){return Ember.reduceComputed(e,{initialValue:-1/0,addedItem:function(e,t){return Math.max(e,t)},removedItem:function(e,t){return e>t?e:void 0}})},Ember.computed.min=function(e){return Ember.reduceComputed(e,{initialValue:1/0,addedItem:function(e,t){return Math.min(e,t)},removedItem:function(e,t){return t>e?e:void 0}})},Ember.computed.map=function(e,t){var r={addedItem:function(e,r,n){var i=t.call(this,r);return e.insertAt(n.index,i),e},removedItem:function(e,t,r){return e.removeAt(r.index,1),e}};return Ember.arrayComputed(e,r)},Ember.computed.mapBy=function(e,t){var n=function(e){return r(e,t)};return Ember.computed.map(e+".@each."+t,n)},Ember.computed.mapProperty=Ember.computed.mapBy,Ember.computed.filter=function(e,t){var r={initialize:function(e,t,r){r.filteredArrayIndexes=new Ember.SubArray},addedItem:function(e,r,n,i){var o=!!t.call(this,r),a=i.filteredArrayIndexes.addItem(n.index,o);return o&&e.insertAt(a,r),e},removedItem:function(e,t,r,n){var i=n.filteredArrayIndexes.removeItem(r.index);return i>-1&&e.removeAt(i),e}};return Ember.arrayComputed(e,r)},Ember.computed.filterBy=function(e,t,n){var i;return i=2===arguments.length?function(e){return r(e,t)}:function(e){return r(e,t)===n},Ember.computed.filter(e+".@each."+t,i)},Ember.computed.filterProperty=Ember.computed.filterBy,Ember.computed.uniq=function(){var e=o.call(arguments);return e.push({initialize:function(e,t,r){r.itemCounts={}},addedItem:function(e,t,r,i){var o=n(t);return i.itemCounts[o]?++i.itemCounts[o]:i.itemCounts[o]=1,e.addObject(t),e},removedItem:function(e,t,r,i){var o=n(t),a=i.itemCounts;return 0===--a[o]&&e.removeObject(t),e}}),Ember.arrayComputed.apply(null,e)},Ember.computed.union=Ember.computed.uniq,Ember.computed.intersect=function(){var e=function(e){return s(e.property._dependentKeys,function(e){return n(e)})},t=o.call(arguments);return t.push({initialize:function(e,t,r){r.itemCounts={}},addedItem:function(t,r,i,o){var a=n(r),s=(e(i),n(i.arrayChanged)),u=i.property._dependentKeys.length,l=o.itemCounts;return l[a]||(l[a]={}),void 0===l[a][s]&&(l[a][s]=0),1===++l[a][s]&&u===Ember.keys(l[a]).length&&t.addObject(r),t},removedItem:function(t,r,i,o){var a,s=n(r),u=(e(i),n(i.arrayChanged)),l=(i.property._dependentKeys.length,o.itemCounts);return void 0===l[s][u]&&(l[s][u]=0),0===--l[s][u]&&(delete l[s][u],a=Ember.keys(l[s]).length,0===a&&delete l[s],t.removeObject(r)),t}}),Ember.arrayComputed.apply(null,t)},Ember.computed.setDiff=function(e,t){if(2!==arguments.length)throw new Ember.Error("setDiff requires exactly two dependent arrays.");return Ember.arrayComputed(e,t,{addedItem:function(n,i,o){var a=r(this,e),s=r(this,t);return o.arrayChanged===a?s.contains(i)||n.addObject(i):n.removeObject(i),n},removedItem:function(n,i,o){var a=r(this,e),s=r(this,t);return o.arrayChanged===s?a.contains(i)&&n.addObject(i):n.removeObject(i),n}})},t=Ember.ObjectProxy.extend(),Ember.computed.sort=function(n,o){Ember.assert("Ember.computed.sort requires two arguments: an array key to sort and either a sort properties key or sort function",2===arguments.length);var s,u;return"function"==typeof o?s=function(t,r,n){n.order=o,n.binarySearch=e}:(u=o,s=function(i,o,s){function l(){var e,t,i,l=r(this,u),h=s.sortProperties=[],m=s.sortPropertyAscending={};Ember.assert("Cannot sort: '"+u+"' is not an array.",Ember.isArray(l)),o.property.clearItemPropertyKeys(n),a(l,function(r){-1!==(t=r.indexOf(":"))?(e=r.substring(0,t),i="desc"!==r.substring(t+1).toLowerCase()):(e=r,i=!0),h.push(e),m[e]=i,o.property.itemPropertyKey(n,e)}),l.addObserver("@each",this,c)}function c(){Ember.run.once(this,h,o.propertyName)}function h(e){l.call(this),o.property.recomputeOnce.call(this,e)}Ember.addObserver(this,u,c),l.call(this),s.order=function(e,n){for(var i,o,a,s=n instanceof t,u=0;ue;e++){var r=arguments[e];Ember.assert("Immediate observers must observe internal properties only, not properties on other objects.",-1===r.indexOf("."))}return this.observes.apply(this,arguments)},Function.prototype.observesBefore=function(){for(var e=function(e){r.push(e)},r=[],n=0;nr(this,"length"))throw new Ember.Error(e);return this.replace(t,0,[n]),this},removeAt:function(n,i){if("number"==typeof n){if(0>n||n>=r(this,"length"))throw new Ember.Error(e);void 0===i&&(i=1),this.replace(n,i,t)}return this},pushObject:function(e){return this.insertAt(r(this,"length"),e),e},pushObjects:function(e){if(!Ember.Enumerable.detect(e)&&!Ember.isArray(e))throw new TypeError("Must pass Ember.Enumerable to Ember.MutableArray#pushObjects");return this.replace(r(this,"length"),0,e),this},popObject:function(){var e=r(this,"length");if(0===e)return null;var t=this.objectAt(e-1);return this.removeAt(e-1,1),t},shiftObject:function(){if(0===r(this,"length"))return null;var e=this.objectAt(0);return this.removeAt(0),e},unshiftObject:function(e){return this.insertAt(0,e),e},unshiftObjects:function(e){return this.replace(0,0,e),this},reverseObjects:function(){var e=r(this,"length");if(0===e)return this;var t=this.toArray().reverse();return this.replace(0,e,t),this},setObjects:function(e){if(0===e.length)return this.clear();var t=r(this,"length");return this.replace(0,t,e),this},removeObject:function(e){for(var t=r(this,"length")||0;--t>=0;){var n=this.objectAt(t);n===e&&this.removeAt(t)}return this},addObject:function(e){return this.contains(e)||this.pushObject(e),this}})}(),function(){{var e=Ember.get;Ember.set}Ember.TargetActionSupport=Ember.Mixin.create({target:null,action:null,actionContext:null,targetObject:Ember.computed(function(){var t=e(this,"target");if("string"===Ember.typeOf(t)){var r=e(this,t);return void 0===r&&(r=e(Ember.lookup,t)),r}return t}).property("target"),actionContextObject:Ember.computed(function(){var t=e(this,"actionContext");if("string"===Ember.typeOf(t)){var r=e(this,t);return void 0===r&&(r=e(Ember.lookup,t)),r}return t}).property("actionContext"),triggerAction:function(t){function r(e,t){var r=[];return t&&r.push(t),r.concat(e)}t=t||{};var n=t.action||e(this,"action"),i=t.target||e(this,"targetObject"),o=t.actionContext;if("undefined"==typeof o&&(o=e(this,"actionContextObject")||this),i&&n){var a;return i.send?a=i.send.apply(i,r(o,n)):(Ember.assert("The action '"+n+"' did not exist on "+i,"function"==typeof i[n]),a=i[n].apply(i,r(o))),a!==!1&&(a=!0),a}return!1}})}(),function(){Ember.Evented=Ember.Mixin.create({on:function(e,t,r){return Ember.addListener(this,e,t,r),this},one:function(e,t,r){return r||(r=t,t=null),Ember.addListener(this,e,t,r,!0),this},trigger:function(e){var t,r,n=[];for(t=1,r=arguments.length;r>t;t++)n.push(arguments[t]);Ember.sendEvent(this,e,n)},off:function(e,t,r){return Ember.removeListener(this,e,t,r),this},has:function(e){return Ember.hasListeners(this,e)}})}(),function(){var e=t("rsvp");if(Ember.FEATURES["ember-runtime-test-friendly-promises"]){var r=function(){Ember.Test&&Ember.Test.adapter&&Ember.Test.adapter.asyncStart()},n=function(){Ember.Test&&Ember.Test.adapter&&Ember.Test.adapter.asyncEnd()};e.configure("async",function(e,t){var i=!Ember.run.currentRunLoop;Ember.testing&&i&&r(),Ember.run.backburner.schedule("actions",function(){Ember.testing&&i&&n(),e(t)})})}else e.configure("async",function(e,t){Ember.run.backburner.schedule("actions",function(){e(t)})});e.Promise.prototype.fail=function(e,t){return Ember.deprecate("RSVP.Promise.fail has been renamed as RSVP.Promise.catch"),this["catch"](e,t)};var i=Ember.get;Ember.DeferredMixin=Ember.Mixin.create({then:function(e,t,r){function n(t){return e(t===a?s:t)}var o,a,s;return s=this,o=i(this,"_deferred"),a=o.promise,a.then(e&&n,t,r)},resolve:function(e){var t,r;t=i(this,"_deferred"),r=t.promise,t.resolve(e===this?r:e)},reject:function(e){i(this,"_deferred").reject(e)},_deferred:Ember.computed(function(){return e.defer("Ember: DeferredMixin - "+this)})})}(),function(){var e=Ember.get,t=Ember.typeOf;Ember.ActionHandler=Ember.Mixin.create({mergedProperties:["_actions"],willMergeMixin:function(e){var r;e._actions||(Ember.assert("'actions' should not be a function","function"!=typeof e.actions),"object"===t(e.actions)?r="actions":"object"===t(e.events)&&(Ember.deprecate("Action handlers contained in an `events` object are deprecated in favor of putting them in an `actions` object",!1),r="events"),r&&(e._actions=Ember.merge(e._actions||{},e[r])),delete e[r])},send:function(t){var r,n=[].slice.call(arguments,1);if(this._actions&&this._actions[t]){if(this._actions[t].apply(this,n)!==!0)return}else if(!Ember.FEATURES.isEnabled("ember-routing-drop-deprecated-action-style")&&this.deprecatedSend&&this.deprecatedSendHandles&&this.deprecatedSendHandles(t)&&(Ember.warn("The current default is deprecated but will prefer to handle actions directly on the controller instead of a similarly named action in the actions hash. To turn off this deprecated feature set: Ember.FEATURES['ember-routing-drop-deprecated-action-style'] = true"),this.deprecatedSend.apply(this,[].slice.call(arguments))!==!0))return;(r=e(this,"target"))&&(Ember.assert("The `target` for "+this+" ("+r+") does not have a `send` method","function"==typeof r.send),r.send.apply(r,arguments))}})}(),function(){function e(e,t){return r(e,"isFulfilled",!1),r(e,"isRejected",!1),t.then(function(t){return r(e,"isFulfilled",!0),r(e,"content",t),t},function(t){throw r(e,"isRejected",!0),r(e,"reason",t),t},"Ember: PromiseProxy")}function t(e){return function(){var t=n(this,"promise");return t[e].apply(t,arguments)}}var r=Ember.set,n=Ember.get,i=Ember.computed.not,o=Ember.computed.or;Ember.PromiseProxyMixin=Ember.Mixin.create({reason:null,isPending:i("isSettled").readOnly(),isSettled:o("isRejected","isFulfilled").readOnly(),isRejected:!1,isFulfilled:!1,promise:Ember.computed(function(t,r){if(2===arguments.length)return e(this,r);throw new Ember.Error("PromiseProxy's promise must be set")}),then:t("then"),"catch":t("catch"),"finally":t("finally")})}(),function(){function e(e,t,r){this.type=e,this.count=t,this.items=r}function t(e,t,r,n){this.operation=e,this.index=t,this.split=r,this.rangeStart=n}var r=Ember.get,n=Ember.EnumerableUtils.forEach,i="r",o="i",a="d";Ember.TrackedArray=function(t){arguments.length<1&&(t=[]);var n=r(t,"length");this._operations=n?[new e(i,n,t)]:[]},Ember.TrackedArray.RETAIN=i,Ember.TrackedArray.INSERT=o,Ember.TrackedArray.DELETE=a,Ember.TrackedArray.prototype={addItems:function(t,n){var i=r(n,"length");if(!(1>i)){var a,s,u=this._findArrayOperation(t),l=u.operation,c=u.index,h=u.rangeStart;s=new e(o,i,n),l?u.split?(this._split(c,t-h,s),a=c+1):(this._operations.splice(c,0,s),a=c):(this._operations.push(s),a=c),this._composeInsert(a)}},removeItems:function(t,r){if(!(1>r)){var n,i,o=this._findArrayOperation(t),s=(o.operation,o.index),u=o.rangeStart;return n=new e(a,r),o.split?(this._split(s,t-u,n),i=s+1):(this._operations.splice(s,0,n),i=s),this._composeDelete(i)}},apply:function(t){var r=[],o=0;n(this._operations,function(e){t(e.items,o,e.type),e.type!==a&&(o+=e.count,r=r.concat(e.items))}),this._operations=[new e(i,r.length,r)]},_findArrayOperation:function(e){var r,n,i,o,s,u=!1;for(r=o=0,n=this._operations.length;n>r;++r)if(i=this._operations[r],i.type!==a){if(s=o+i.count-1,e===o)break;if(e>o&&s>=e){u=!0;break}o=s+1}return new t(i,r,u,o)},_split:function(t,r,n){var i=this._operations[t],o=i.items.slice(r),a=new e(i.type,o.length,o);i.count=r,i.items=i.items.slice(0,r),this._operations.splice(t+1,0,n,a)},_composeInsert:function(e){var t=this._operations[e],r=this._operations[e-1],n=this._operations[e+1],i=r&&r.type,a=n&&n.type;i===o?(r.count+=t.count,r.items=r.items.concat(t.items),a===o?(r.count+=n.count,r.items=r.items.concat(n.items),this._operations.splice(e,2)):this._operations.splice(e,1)):a===o&&(t.count+=n.count,t.items=t.items.concat(n.items),this._operations.splice(e+1,1))},_composeDelete:function(e){var t,r,n,i=this._operations[e],s=i.count,u=this._operations[e-1],l=u&&u.type,c=!1,h=[];l===a&&(i=u,e-=1);for(var m=e+1;s>0;++m)t=this._operations[m],r=t.type,n=t.count,r!==a?(n>s?(h=h.concat(t.items.splice(0,s)),t.count-=s,m-=1,n=s,s=0):(n===s&&(c=!0),h=h.concat(t.items),s-=n),r===o&&(i.count-=n)):i.count+=n;return i.count>0?this._operations.splice(e+1,m-1-e):this._operations.splice(e,c?2:1),h},toString:function(){var e="";return n(this._operations,function(t){e+=" "+t.type+":"+t.count}),e.substring(1)}}}(),function(){function e(e,t){this.type=e,this.count=t}var t=(Ember.get,Ember.EnumerableUtils.forEach),r="r",n="f";Ember.SubArray=function(t){arguments.length<1&&(t=0),this._operations=t>0?[new e(r,t)]:[]},Ember.SubArray.prototype={addItem:function(t,i){var o=-1,a=i?r:n,s=this;return this._findOperation(t,function(n,u,l,c,h){var m,p;a===n.type?++n.count:t===l?s._operations.splice(u,0,new e(a,1)):(m=new e(a,1),p=new e(n.type,c-t+1),n.count=t-l,s._operations.splice(u+1,0,m,p)),i&&(o=n.type===r?h+(t-l):h),s._composeAt(u)},function(t){s._operations.push(new e(a,1)),i&&(o=t),s._composeAt(s._operations.length-1)}),o},removeItem:function(e){var t=-1,n=this;return this._findOperation(e,function(i,o,a,s,u){i.type===r&&(t=u+(e-a)),i.count>1?--i.count:(n._operations.splice(o,1),n._composeAt(o))},function(){throw new Ember.Error("Can't remove an item that has never been added.")}),t},_findOperation:function(e,t,n){var i,o,a,s,u,l=0;for(i=s=0,o=this._operations.length;o>i;s=u+1,++i){if(a=this._operations[i],u=s+a.count-1,e>=s&&u>=e)return void t(a,i,s,u,l);a.type===r&&(l+=a.count)}n(l)},_composeAt:function(e){var t,r=this._operations[e];r&&(e>0&&(t=this._operations[e-1],t.type===r.type&&(r.count+=t.count,this._operations.splice(e-1,1),--e)),er(this,"content.length"))throw new Ember.Error(e);return this._replace(t,0,[n]),this},insertAt:function(e,t){if(r(this,"arrangedContent")===r(this,"content"))return this._insertAt(e,t);throw new Ember.Error("Using insertAt on an arranged ArrayProxy is not allowed.")},removeAt:function(n,i){if("number"==typeof n){var o,a=r(this,"content"),s=r(this,"arrangedContent"),u=[];if(0>n||n>=r(this,"length"))throw new Ember.Error(e);for(void 0===i&&(i=1),o=n;n+i>o;o++)u.push(a.indexOf(s.objectAt(o)));for(u.sort(function(e,t){return t-e}),Ember.beginPropertyChanges(),o=0;o=i;){var u=e.objectAt(o);u&&(Ember.assert("When using @each to observe the array "+e+", the array must return an object","instance"===Ember.typeOf(u)||"object"===Ember.typeOf(u)),Ember.addBeforeObserver(u,t,r,"contentKeyWillChange"),Ember.addObserver(u,t,r,"contentKeyDidChange"),a=n(u),s[a]||(s[a]=[]),s[a].push(o))}}function t(e,t,r,i,a){var s=r._objects;s||(s=r._objects={});for(var u,l;--a>=i;){var c=e.objectAt(a);c&&(Ember.removeBeforeObserver(c,t,r,"contentKeyWillChange"),Ember.removeObserver(c,t,r,"contentKeyDidChange"),l=n(c),u=s[l],u[o.call(u,a)]=null)}}var r=(Ember.set,Ember.get),n=Ember.guidFor,i=Ember.EnumerableUtils.forEach,o=Ember.ArrayPolyfills.indexOf,a=Ember.Object.extend(Ember.Array,{init:function(e,t,r){this._super(),this._keyName=t,this._owner=r,this._content=e},objectAt:function(e){var t=this._content.objectAt(e);return t&&r(t,this._keyName)},length:Ember.computed(function(){var e=this._content;return e?r(e,"length"):0})}),s=/^.+:(before|change)$/;Ember.EachProxy=Ember.Object.extend({init:function(e){this._super(),this._content=e,e.addArrayObserver(this),i(Ember.watchedEvents(this),function(e){this.didAddListener(e)},this)},unknownProperty:function(e){var t;return t=new a(this._content,e,this),Ember.defineProperty(this,e,null,t),this.beginObservingContentKey(e),t},arrayWillChange:function(e,r,n){var i,o,a=this._keys;o=n>0?r+n:-1,Ember.beginPropertyChanges(this);for(i in a)a.hasOwnProperty(i)&&(o>0&&t(e,i,this,r,o),Ember.propertyWillChange(this,i));Ember.propertyWillChange(this._content,"@each"),Ember.endPropertyChanges(this)},arrayDidChange:function(t,r,n,i){var o,a=this._keys;o=i>0?r+i:-1,Ember.changeProperties(function(){for(var n in a)a.hasOwnProperty(n)&&(o>0&&e(t,n,this,r,o),Ember.propertyDidChange(this,n));Ember.propertyDidChange(this._content,"@each")},this)},didAddListener:function(e){s.test(e)&&this.beginObservingContentKey(e.slice(0,-7))},didRemoveListener:function(e){s.test(e)&&this.stopObservingContentKey(e.slice(0,-7))},beginObservingContentKey:function(t){var n=this._keys;if(n||(n=this._keys={}),n[t])n[t]++;else{n[t]=1;var i=this._content,o=r(i,"length");e(i,t,this,0,o)}},stopObservingContentKey:function(e){var n=this._keys;if(n&&n[e]>0&&--n[e]<=0){var i=this._content,o=r(i,"length");t(i,e,this,0,o)}},contentKeyWillChange:function(e,t){Ember.propertyWillChange(this,t)},contentKeyDidChange:function(e,t){Ember.propertyDidChange(this,t)}})}(),function(){var e=Ember.get,t=(Ember.set,Ember.EnumerableUtils._replace),r=Ember.Mixin.create(Ember.MutableArray,Ember.Observable,Ember.Copyable,{get:function(e){return"length"===e?this.length:"number"==typeof e?this[e]:this._super(e)},objectAt:function(e){return this[e]},replace:function(r,n,i){if(this.isFrozen)throw Ember.FROZEN_ERROR;var o=i?e(i,"length"):0;return this.arrayContentWillChange(r,n,o),0===o?this.splice(r,n):t(this,r,n,i),this.arrayContentDidChange(r,n,o),this},unknownProperty:function(e,t){var r;return void 0!==t&&void 0===r&&(r=this[e]=t),r},indexOf:function(e,t){var r,n=this.length;for(t=void 0===t?0:0>t?Math.ceil(t):Math.floor(t),0>t&&(t+=n),r=t;n>r;r++)if(this[r]===e)return r;return-1},lastIndexOf:function(e,t){var r,n=this.length;for(t=void 0===t?n-1:0>t?Math.ceil(t):Math.floor(t),0>t&&(t+=n),r=t;r>=0;r--)if(this[r]===e)return r;return-1},copy:function(e){return e?this.map(function(e){return Ember.copy(e,!0)}):this.slice()}}),n=["length"];Ember.EnumerableUtils.forEach(r.keys(),function(e){Array.prototype[e]&&n.push(e)}),n.length>0&&(r=r.without.apply(r,n)),Ember.NativeArray=r,Ember.A=function(e){return void 0===e&&(e=[]),Ember.Array.detect(e)?e:Ember.NativeArray.apply(e)},Ember.NativeArray.activate=function(){r.apply(Array.prototype),Ember.A=function(e){return e||[]}},(Ember.EXTEND_PROTOTYPES===!0||Ember.EXTEND_PROTOTYPES.Array)&&Ember.NativeArray.activate()}(),function(){var e=Ember.get,t=Ember.set,r=Ember.guidFor,n=Ember.isNone,i=Ember.String.fmt;Ember.Set=Ember.CoreObject.extend(Ember.MutableEnumerable,Ember.Copyable,Ember.Freezable,{length:0,clear:function(){if(this.isFrozen)throw new Ember.Error(Ember.FROZEN_ERROR);var n=e(this,"length");if(0===n)return this;var i;this.enumerableContentWillChange(n,0),Ember.propertyWillChange(this,"firstObject"),Ember.propertyWillChange(this,"lastObject");for(var o=0;n>o;o++)i=r(this[o]),delete this[i],delete this[o];return t(this,"length",0),Ember.propertyDidChange(this,"firstObject"),Ember.propertyDidChange(this,"lastObject"),this.enumerableContentDidChange(n,0),this},isEqual:function(t){if(!Ember.Enumerable.detect(t))return!1;var r=e(this,"length");if(e(t,"length")!==r)return!1;for(;--r>=0;)if(!t.contains(this[r]))return!1;return!0},add:Ember.aliasMethod("addObject"),remove:Ember.aliasMethod("removeObject"),pop:function(){if(e(this,"isFrozen"))throw new Ember.Error(Ember.FROZEN_ERROR);var t=this.length>0?this[this.length-1]:null;return this.remove(t),t},push:Ember.aliasMethod("addObject"),shift:Ember.aliasMethod("pop"),unshift:Ember.aliasMethod("push"),addEach:Ember.aliasMethod("addObjects"),removeEach:Ember.aliasMethod("removeObjects"),init:function(e){this._super(),e&&this.addObjects(e)},nextObject:function(e){return this[e]},firstObject:Ember.computed(function(){return this.length>0?this[0]:void 0}),lastObject:Ember.computed(function(){return this.length>0?this[this.length-1]:void 0}),addObject:function(i){if(e(this,"isFrozen"))throw new Ember.Error(Ember.FROZEN_ERROR);if(n(i))return this;var o,a=r(i),s=this[a],u=e(this,"length");return s>=0&&u>s&&this[s]===i?this:(o=[i],this.enumerableContentWillChange(null,o),Ember.propertyWillChange(this,"lastObject"),u=e(this,"length"),this[a]=u,this[u]=i,t(this,"length",u+1),Ember.propertyDidChange(this,"lastObject"),this.enumerableContentDidChange(null,o),this)},removeObject:function(i){if(e(this,"isFrozen"))throw new Ember.Error(Ember.FROZEN_ERROR);if(n(i))return this;var o,a,s=r(i),u=this[s],l=e(this,"length"),c=0===u,h=u===l-1;return u>=0&&l>u&&this[u]===i&&(a=[i],this.enumerableContentWillChange(a,null),c&&Ember.propertyWillChange(this,"firstObject"),h&&Ember.propertyWillChange(this,"lastObject"),l-1>u&&(o=this[l-1],this[u]=o,this[r(o)]=u),delete this[s],delete this[l-1],t(this,"length",l-1),c&&Ember.propertyDidChange(this,"firstObject"),h&&Ember.propertyDidChange(this,"lastObject"),this.enumerableContentDidChange(a,null)),this},contains:function(e){return this[r(e)]>=0},copy:function(){var n=this.constructor,i=new n,o=e(this,"length");for(t(i,"length",o);--o>=0;)i[o]=this[o],i[r(this[o])]=o;return i},toString:function(){var e,t=this.length,r=[];for(e=0;t>e;e++)r[e]=this[e];return i("Ember.Set<%@>",[r.join(",")])}})}(),function(){var e=Ember.DeferredMixin,t=(Ember.get,Ember.Object.extend(e)); -t.reopenClass({promise:function(e,r){var n=t.create();return e.call(r,n),n}}),Ember.Deferred=t}(),function(){var e=Ember.ArrayPolyfills.forEach,t=Ember.ENV.EMBER_LOAD_HOOKS||{},r={};Ember.onLoad=function(e,n){var i;t[e]=t[e]||Ember.A(),t[e].pushObject(n),(i=r[e])&&n(i)},Ember.runLoadHooks=function(n,i){if(r[n]=i,"object"==typeof window&&"function"==typeof window.dispatchEvent&&"function"==typeof CustomEvent){var o=new CustomEvent(n,{detail:i,name:n});window.dispatchEvent(o)}t[n]&&e.call(t[n],function(e){e(i)})}}(),function(){Ember.get;Ember.ControllerMixin=Ember.Mixin.create(Ember.ActionHandler,{isController:!0,target:null,container:null,parentController:null,store:null,model:Ember.computed.alias("content"),deprecatedSendHandles:function(e){return!!this[e]},deprecatedSend:function(e){var t=[].slice.call(arguments,1);Ember.assert(""+this+" has the action "+e+" but it is not a function","function"==typeof this[e]),Ember.deprecate("Action handlers implemented directly on controllers are deprecated in favor of action handlers on an `actions` object ( action: `"+e+"` on "+this+")",!1),this[e].apply(this,t)}}),Ember.Controller=Ember.Object.extend(Ember.ControllerMixin)}(),function(){var e=Ember.get,t=(Ember.set,Ember.EnumerableUtils.forEach);Ember.SortableMixin=Ember.Mixin.create(Ember.MutableEnumerable,{sortProperties:null,sortAscending:!0,sortFunction:Ember.compare,orderBy:function(r,n){var i=0,o=e(this,"sortProperties"),a=e(this,"sortAscending"),s=e(this,"sortFunction");return Ember.assert("you need to define `sortProperties`",!!o),t(o,function(t){0===i&&(i=s(e(r,t),e(n,t)),0===i||a||(i=-1*i))}),i},destroy:function(){var r=e(this,"content"),n=e(this,"sortProperties");return r&&n&&t(r,function(e){t(n,function(t){Ember.removeObserver(e,t,this,"contentItemSortPropertyDidChange")},this)},this),this._super()},isSorted:Ember.computed.bool("sortProperties"),arrangedContent:Ember.computed("content","sortProperties.@each",function(){var r=e(this,"content"),n=e(this,"isSorted"),i=e(this,"sortProperties"),o=this;return r&&n?(r=r.slice(),r.sort(function(e,t){return o.orderBy(e,t)}),t(r,function(e){t(i,function(t){Ember.addObserver(e,t,this,"contentItemSortPropertyDidChange")},this)},this),Ember.A(r)):r}),_contentWillChange:Ember.beforeObserver("content",function(){var r=e(this,"content"),n=e(this,"sortProperties");r&&n&&t(r,function(e){t(n,function(t){Ember.removeObserver(e,t,this,"contentItemSortPropertyDidChange")},this)},this),this._super()}),sortAscendingWillChange:Ember.beforeObserver("sortAscending",function(){this._lastSortAscending=e(this,"sortAscending")}),sortAscendingDidChange:Ember.observer("sortAscending",function(){if(e(this,"sortAscending")!==this._lastSortAscending){var t=e(this,"arrangedContent");t.reverseObjects()}}),contentArrayWillChange:function(r,n,i,o){var a=e(this,"isSorted");if(a){var s=e(this,"arrangedContent"),u=r.slice(n,n+i),l=e(this,"sortProperties");t(u,function(e){s.removeObject(e),t(l,function(t){Ember.removeObserver(e,t,this,"contentItemSortPropertyDidChange")},this)},this)}return this._super(r,n,i,o)},contentArrayDidChange:function(r,n,i,o){var a=e(this,"isSorted"),s=e(this,"sortProperties");if(a){var u=r.slice(n,n+o);t(u,function(e){this.insertItemSorted(e),t(s,function(t){Ember.addObserver(e,t,this,"contentItemSortPropertyDidChange")},this)},this)}return this._super(r,n,i,o)},insertItemSorted:function(t){var r=e(this,"arrangedContent"),n=e(r,"length"),i=this._binarySearch(t,0,n);r.insertAt(i,t)},contentItemSortPropertyDidChange:function(t){var r=e(this,"arrangedContent"),n=r.indexOf(t),i=r.objectAt(n-1),o=r.objectAt(n+1),a=i&&this.orderBy(t,i),s=o&&this.orderBy(t,o);(0>a||s>0)&&(r.removeObject(t),this.insertItemSorted(t))},_binarySearch:function(t,r,n){var i,o,a,s;return r===n?r:(s=e(this,"arrangedContent"),i=r+Math.floor((n-r)/2),o=s.objectAt(i),a=this.orderBy(o,t),0>a?this._binarySearch(t,i+1,n):a>0?this._binarySearch(t,r,i):i)}})}(),function(){var e=Ember.get,t=(Ember.set,Ember.EnumerableUtils.forEach),r=Ember.EnumerableUtils.replace;Ember.ArrayController=Ember.ArrayProxy.extend(Ember.ControllerMixin,Ember.SortableMixin,{itemController:null,lookupItemController:function(){return e(this,"itemController")},objectAtContent:function(t){var r=e(this,"length"),n=e(this,"arrangedContent"),i=n&&n.objectAt(t);if(t>=0&&r>t){var o=this.lookupItemController(i);if(o)return this.controllerAt(t,i,o)}return i},arrangedContentDidChange:function(){this._super(),this._resetSubControllers()},arrayContentDidChange:function(n,i,o){var a=e(this,"_subControllers"),s=a.slice(n,n+i);t(s,function(e){e&&e.destroy()}),r(a,n,i,new Array(o)),this._super(n,i,o)},init:function(){this._super(),this.set("_subControllers",Ember.A())},content:Ember.computed(function(){return Ember.A()}),_isVirtual:!1,controllerAt:function(t,r,n){var i,o=e(this,"container"),a=e(this,"_subControllers"),s=a[t];if(s)return s;if(i="controller:"+n,!o.has(i))throw new Ember.Error('Could not resolve itemController: "'+n+'"');var u;return this._isVirtual&&(u=e(this,"parentController")),u=u||this,s=o.lookupFactory(i).create({target:this,parentController:u,content:r}),a[t]=s,s},_subControllers:null,_resetSubControllers:function(){var r=e(this,"_subControllers");r&&t(r,function(e){e&&e.destroy()}),this.set("_subControllers",Ember.A())}})}(),function(){Ember.ObjectController=Ember.ObjectProxy.extend(Ember.ControllerMixin)}(),function(){var e=Ember.imports&&Ember.imports.jQuery||this&&this.jQuery;e||"function"!=typeof r||(e=r("jquery")),Ember.assert("Ember Views require jQuery between 1.7 and 2.1",e&&(e().jquery.match(/^((1\.(7|8|9|10|11))|(2\.(0|1)))(\.\d+)?(pre|rc\d?)?/)||Ember.ENV.FORCE_JQUERY)),Ember.$=e}(),function(){if(Ember.$){var e=Ember.String.w("dragstart drag dragenter dragleave dragover drop dragend");Ember.EnumerableUtils.forEach(e,function(e){Ember.$.event.fixHooks[e]={props:["dataTransfer"]}})}}(),function(){function e(e){var t=e.shiftKey||e.metaKey||e.altKey||e.ctrlKey,r=e.which>1;return!t&&!r}var t="undefined"!=typeof document&&function(){var e=document.createElement("div");return e.innerHTML="
",e.firstChild.innerHTML="",""===e.firstChild.innerHTML}(),r="undefined"!=typeof document&&function(){var e=document.createElement("div");return e.innerHTML="Test: Value","Test:"===e.childNodes[0].nodeValue&&" Value"===e.childNodes[2].nodeValue}(),n=function(e,t){if(e.getAttribute("id")===t)return e;var r,i,o,a=e.childNodes.length;for(r=0;a>r;r++)if(i=e.childNodes[r],o=1===i.nodeType&&n(i,t))return o},i=function(e,i){t&&(i="­"+i);var o=[];if(r&&(i=i.replace(/(\s+)(",""===e.firstChild.innerHTML}(),o=document&&function(){var e=document.createElement("div");return e.innerHTML="Test: Value","Test:"===e.childNodes[0].nodeValue&&" Value"===e.childNodes[2].nodeValue}(),a=function(r){var n;n=this instanceof a?this:new e,n.innerHTML=r;var i="metamorph-"+t++;return n.start=i+"-start",n.end=i+"-end",n};e.prototype=a.prototype;var s,u,l,c,h,m,p,d,f;if(c=function(){return this.startTag()+this.innerHTML+this.endTag()},d=function(){return""},f=function(){return""},n)s=function(e,t){var r=document.createRange(),n=document.getElementById(e.start),i=document.getElementById(e.end);return t?(r.setStartBefore(n),r.setEndAfter(i)):(r.setStartAfter(n),r.setEndBefore(i)),r},u=function(e,t){var r=s(this,t);r.deleteContents();var n=r.createContextualFragment(e);r.insertNode(n)},l=function(){var e=s(this,!0);e.deleteContents()},h=function(e){var t=document.createRange();t.setStart(e),t.collapse(!1);var r=t.createContextualFragment(this.outerHTML());e.appendChild(r)},m=function(e){var t=document.createRange(),r=document.getElementById(this.end);t.setStartAfter(r),t.setEndAfter(r);var n=t.createContextualFragment(e);t.insertNode(n)},p=function(e){var t=document.createRange(),r=document.getElementById(this.start);t.setStartAfter(r),t.setEndAfter(r);var n=t.createContextualFragment(e);t.insertNode(n)};else{var b={select:[1,""],fieldset:[1,"
","
"],table:[1,"","
"],tbody:[2,"","
"],tr:[3,"","
"],colgroup:[2,"","
"],map:[1,"",""],_default:[0,"",""]},E=function(e,t){if(e.getAttribute("id")===t)return e;var r,n,i,o=e.childNodes.length;for(r=0;o>r;r++)if(n=e.childNodes[r],i=1===n.nodeType&&E(n,t))return i},v=function(e,t){var r=[];if(o&&(t=t.replace(/(\s+)("; - return testEl.firstChild.innerHTML === ''; - })(); - - // IE 8 (and likely earlier) likes to move whitespace preceeding - // a script tag to appear after it. This means that we can - // accidentally remove whitespace when updating a morph. - var movesWhitespace = typeof document !== 'undefined' && (function() { - var testEl = document.createElement('div'); - testEl.innerHTML = "Test: Value"; - return testEl.childNodes[0].nodeValue === 'Test:' && - testEl.childNodes[2].nodeValue === ' Value'; - })(); - - // Use this to find children by ID instead of using jQuery - var findChildById = function(element, id) { - if (element.getAttribute('id') === id) { return element; } - - var len = element.childNodes.length, idx, node, found; - for (idx=0; idx 0) { - var len = matches.length, idx; - for (idx=0; idxTest'); - canSet = el.options.length === 1; - } - - innerHTMLTags[tagName] = canSet; - - return canSet; - }; - - var setInnerHTML = function(element, html) { - var tagName = element.tagName; - - if (canSetInnerHTML(tagName)) { - setInnerHTMLWithoutFix(element, html); - } else { - // Firefox versions < 11 do not have support for element.outerHTML. - var outerHTML = element.outerHTML || new XMLSerializer().serializeToString(element); - Ember.assert("Can't set innerHTML on "+element.tagName+" in this browser", outerHTML); - - var startTag = outerHTML.match(new RegExp("<"+tagName+"([^>]*)>", 'i'))[0], - endTag = ''; - - var wrapper = document.createElement('div'); - setInnerHTMLWithoutFix(wrapper, startTag + html + endTag); - element = wrapper.firstChild; - while (element.tagName !== tagName) { - element = element.nextSibling; - } - } - - return element; - }; - - function isSimpleClick(event) { - var modifier = event.shiftKey || event.metaKey || event.altKey || event.ctrlKey, - secondaryClick = event.which > 1; // IE9 may return undefined - - return !modifier && !secondaryClick; - } - - __exports__.setInnerHTML = setInnerHTML; - __exports__.isSimpleClick = isSimpleClick; - }); -define("ember-views/views/collection_view", - ["ember-metal/core","ember-metal/platform","ember-metal/binding","ember-metal/merge","ember-metal/property_get","ember-metal/property_set","ember-runtime/system/string","ember-views/views/container_view","ember-views/views/view","ember-metal/mixin","ember-runtime/mixins/array","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __exports__) { - "use strict"; - - /** - @module ember - @submodule ember-views - */ - - var Ember = __dependency1__["default"]; - // Ember.assert - var create = __dependency2__.create; - var isGlobalPath = __dependency3__.isGlobalPath; - var merge = __dependency4__["default"]; - var get = __dependency5__.get; - var set = __dependency6__.set; - var fmt = __dependency7__.fmt; - var ContainerView = __dependency8__["default"]; - var CoreView = __dependency9__.CoreView; - var View = __dependency9__.View; - var observer = __dependency10__.observer; - var beforeObserver = __dependency10__.beforeObserver; - var EmberArray = __dependency11__["default"]; - - /** - `Ember.CollectionView` is an `Ember.View` descendent responsible for managing - a collection (an array or array-like object) by maintaining a child view object - and associated DOM representation for each item in the array and ensuring - that child views and their associated rendered HTML are updated when items in - the array are added, removed, or replaced. - - ## Setting content - - The managed collection of objects is referenced as the `Ember.CollectionView` - instance's `content` property. - - ```javascript - someItemsView = Ember.CollectionView.create({ - content: ['A', 'B','C'] - }) - ``` - - The view for each item in the collection will have its `content` property set - to the item. - - ## Specifying itemViewClass - - By default the view class for each item in the managed collection will be an - instance of `Ember.View`. You can supply a different class by setting the - `CollectionView`'s `itemViewClass` property. - - Given an empty `` and the following code: - - ```javascript - someItemsView = Ember.CollectionView.create({ - classNames: ['a-collection'], - content: ['A','B','C'], - itemViewClass: Ember.View.extend({ - template: Ember.Handlebars.compile("the letter: {{view.content}}") - }) - }); - - someItemsView.appendTo('body'); - ``` - - Will result in the following HTML structure - - ```html -
-
the letter: A
-
the letter: B
-
the letter: C
-
- ``` - - ## Automatic matching of parent/child tagNames - - Setting the `tagName` property of a `CollectionView` to any of - "ul", "ol", "table", "thead", "tbody", "tfoot", "tr", or "select" will result - in the item views receiving an appropriately matched `tagName` property. - - Given an empty `` and the following code: - - ```javascript - anUnorderedListView = Ember.CollectionView.create({ - tagName: 'ul', - content: ['A','B','C'], - itemViewClass: Ember.View.extend({ - template: Ember.Handlebars.compile("the letter: {{view.content}}") - }) - }); - - anUnorderedListView.appendTo('body'); - ``` - - Will result in the following HTML structure - - ```html -
    -
  • the letter: A
  • -
  • the letter: B
  • -
  • the letter: C
  • -
- ``` - - Additional `tagName` pairs can be provided by adding to - `Ember.CollectionView.CONTAINER_MAP ` - - ```javascript - Ember.CollectionView.CONTAINER_MAP['article'] = 'section' - ``` - - ## Programmatic creation of child views - - For cases where additional customization beyond the use of a single - `itemViewClass` or `tagName` matching is required CollectionView's - `createChildView` method can be overidden: - - ```javascript - CustomCollectionView = Ember.CollectionView.extend({ - createChildView: function(viewClass, attrs) { - if (attrs.content.kind == 'album') { - viewClass = App.AlbumView; - } else { - viewClass = App.SongView; - } - return this._super(viewClass, attrs); - } - }); - ``` - - ## Empty View - - You can provide an `Ember.View` subclass to the `Ember.CollectionView` - instance as its `emptyView` property. If the `content` property of a - `CollectionView` is set to `null` or an empty array, an instance of this view - will be the `CollectionView`s only child. - - ```javascript - aListWithNothing = Ember.CollectionView.create({ - classNames: ['nothing'] - content: null, - emptyView: Ember.View.extend({ - template: Ember.Handlebars.compile("The collection is empty") - }) - }); - - aListWithNothing.appendTo('body'); - ``` - - Will result in the following HTML structure - - ```html -
-
- The collection is empty -
-
- ``` - - ## Adding and Removing items - - The `childViews` property of a `CollectionView` should not be directly - manipulated. Instead, add, remove, replace items from its `content` property. - This will trigger appropriate changes to its rendered HTML. - - - @class CollectionView - @namespace Ember - @extends Ember.ContainerView - @since Ember 0.9 - */ - var CollectionView = ContainerView.extend({ - - /** - A list of items to be displayed by the `Ember.CollectionView`. - - @property content - @type Ember.Array - @default null - */ - content: null, - - /** - This provides metadata about what kind of empty view class this - collection would like if it is being instantiated from another - system (like Handlebars) - - @private - @property emptyViewClass - */ - emptyViewClass: View, - - /** - An optional view to display if content is set to an empty array. - - @property emptyView - @type Ember.View - @default null - */ - emptyView: null, - - /** - @property itemViewClass - @type Ember.View - @default Ember.View - */ - itemViewClass: View, - - /** - Setup a CollectionView - - @method init - */ - init: function() { - var ret = this._super(); - this._contentDidChange(); - return ret; - }, - - /** - Invoked when the content property is about to change. Notifies observers that the - entire array content will change. - - @private - @method _contentWillChange - */ - _contentWillChange: beforeObserver('content', function() { - var content = this.get('content'); - - if (content) { content.removeArrayObserver(this); } - var len = content ? get(content, 'length') : 0; - this.arrayWillChange(content, 0, len); - }), - - /** - Check to make sure that the content has changed, and if so, - update the children directly. This is always scheduled - asynchronously, to allow the element to be created before - bindings have synchronized and vice versa. - - @private - @method _contentDidChange - */ - _contentDidChange: observer('content', function() { - var content = get(this, 'content'); - - if (content) { - this._assertArrayLike(content); - content.addArrayObserver(this); - } - - var len = content ? get(content, 'length') : 0; - this.arrayDidChange(content, 0, null, len); - }), - - /** - Ensure that the content implements Ember.Array - - @private - @method _assertArrayLike - */ - _assertArrayLike: function(content) { - Ember.assert(fmt("an Ember.CollectionView's content must implement Ember.Array. You passed %@", [content]), EmberArray.detect(content)); - }, - - /** - Removes the content and content observers. - - @method destroy - */ - destroy: function() { - if (!this._super()) { return; } - - var content = get(this, 'content'); - if (content) { content.removeArrayObserver(this); } - - if (this._createdEmptyView) { - this._createdEmptyView.destroy(); - } - - return this; - }, - - /** - Called when a mutation to the underlying content array will occur. - - This method will remove any views that are no longer in the underlying - content array. - - Invokes whenever the content array itself will change. - - @method arrayWillChange - @param {Array} content the managed collection of objects - @param {Number} start the index at which the changes will occurr - @param {Number} removed number of object to be removed from content - */ - arrayWillChange: function(content, start, removedCount) { - // If the contents were empty before and this template collection has an - // empty view remove it now. - var emptyView = get(this, 'emptyView'); - if (emptyView && emptyView instanceof View) { - emptyView.removeFromParent(); - } - - // Loop through child views that correspond with the removed items. - // Note that we loop from the end of the array to the beginning because - // we are mutating it as we go. - var childViews = this._childViews, childView, idx, len; - - len = this._childViews.length; - - var removingAll = removedCount === len; - - if (removingAll) { - this.currentState.empty(this); - this.invokeRecursively(function(view) { - view.removedFromDOM = true; - }, false); - } - - for (idx = start + removedCount - 1; idx >= start; idx--) { - childView = childViews[idx]; - childView.destroy(); - } - }, - - /** - Called when a mutation to the underlying content array occurs. - - This method will replay that mutation against the views that compose the - `Ember.CollectionView`, ensuring that the view reflects the model. - - This array observer is added in `contentDidChange`. - - @method arrayDidChange - @param {Array} content the managed collection of objects - @param {Number} start the index at which the changes occurred - @param {Number} removed number of object removed from content - @param {Number} added number of object added to content - */ - arrayDidChange: function(content, start, removed, added) { - var addedViews = [], view, item, idx, len, itemViewClass, - emptyView; - - len = content ? get(content, 'length') : 0; - - if (len) { - itemViewClass = get(this, 'itemViewClass'); - - if ('string' === typeof itemViewClass && isGlobalPath(itemViewClass)) { - itemViewClass = get(itemViewClass) || itemViewClass; - } - - Ember.assert(fmt("itemViewClass must be a subclass of Ember.View, not %@", - [itemViewClass]), - 'string' === typeof itemViewClass || View.detect(itemViewClass)); - - for (idx = start; idx < start+added; idx++) { - item = content.objectAt(idx); - - view = this.createChildView(itemViewClass, { - content: item, - contentIndex: idx - }); - - addedViews.push(view); - } - } else { - emptyView = get(this, 'emptyView'); - - if (!emptyView) { return; } - - if ('string' === typeof emptyView && isGlobalPath(emptyView)) { - emptyView = get(emptyView) || emptyView; - } - - emptyView = this.createChildView(emptyView); - addedViews.push(emptyView); - set(this, 'emptyView', emptyView); - - if (CoreView.detect(emptyView)) { - this._createdEmptyView = emptyView; - } - } - - this.replace(start, 0, addedViews); - }, - - /** - Instantiates a view to be added to the childViews array during view - initialization. You generally will not call this method directly unless - you are overriding `createChildViews()`. Note that this method will - automatically configure the correct settings on the new view instance to - act as a child of the parent. - - The tag name for the view will be set to the tagName of the viewClass - passed in. - - @method createChildView - @param {Class} viewClass - @param {Hash} [attrs] Attributes to add - @return {Ember.View} new instance - */ - createChildView: function(view, attrs) { - view = this._super(view, attrs); - - var itemTagName = get(view, 'tagName'); - - if (itemTagName === null || itemTagName === undefined) { - itemTagName = CollectionView.CONTAINER_MAP[get(this, 'tagName')]; - set(view, 'tagName', itemTagName); - } - - return view; - } - }); - - /** - A map of parent tags to their default child tags. You can add - additional parent tags if you want collection views that use - a particular parent tag to default to a child tag. - - @property CONTAINER_MAP - @type Hash - @static - @final - */ - CollectionView.CONTAINER_MAP = { - ul: 'li', - ol: 'li', - table: 'tr', - thead: 'tr', - tbody: 'tr', - tfoot: 'tr', - tr: 'td', - select: 'option' - }; - - __exports__["default"] = CollectionView; - }); -define("ember-views/views/component", - ["ember-metal/core","ember-views/mixins/component_template_deprecation","ember-runtime/mixins/target_action_support","ember-views/views/view","ember-metal/property_get","ember-metal/property_set","ember-metal/is_none","ember-metal/computed","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __exports__) { - "use strict"; - var Ember = __dependency1__["default"]; - // Ember.assert, Ember.Handlebars - - var ComponentTemplateDeprecation = __dependency2__["default"]; - var TargetActionSupport = __dependency3__["default"]; - var View = __dependency4__.View;var get = __dependency5__.get; - var set = __dependency6__.set; - var isNone = __dependency7__.isNone; - - var computed = __dependency8__.computed; - - var a_slice = Array.prototype.slice; - - /** - @module ember - @submodule ember-views - */ - - /** - An `Ember.Component` is a view that is completely - isolated. Property access in its templates go - to the view object and actions are targeted at - the view object. There is no access to the - surrounding context or outer controller; all - contextual information must be passed in. - - The easiest way to create an `Ember.Component` is via - a template. If you name a template - `components/my-foo`, you will be able to use - `{{my-foo}}` in other templates, which will make - an instance of the isolated component. - - ```handlebars - {{app-profile person=currentUser}} - ``` - - ```handlebars - -

{{person.title}}

- -

{{person.signature}}

- ``` - - You can use `yield` inside a template to - include the **contents** of any block attached to - the component. The block will be executed in the - context of the surrounding context or outer controller: - - ```handlebars - {{#app-profile person=currentUser}} -

Admin mode

- {{! Executed in the controller's context. }} - {{/app-profile}} - ``` - - ```handlebars - -

{{person.title}}

- {{! Executed in the components context. }} - {{yield}} {{! block contents }} - ``` - - If you want to customize the component, in order to - handle events or actions, you implement a subclass - of `Ember.Component` named after the name of the - component. Note that `Component` needs to be appended to the name of - your subclass like `AppProfileComponent`. - - For example, you could implement the action - `hello` for the `app-profile` component: - - ```javascript - App.AppProfileComponent = Ember.Component.extend({ - actions: { - hello: function(name) { - console.log("Hello", name); - } - } - }); - ``` - - And then use it in the component's template: - - ```handlebars - - -

{{person.title}}

- {{yield}} - - - ``` - - Components must have a `-` in their name to avoid - conflicts with built-in controls that wrap HTML - elements. This is consistent with the same - requirement in web components. - - @class Component - @namespace Ember - @extends Ember.View - */ - var Component = View.extend(TargetActionSupport, ComponentTemplateDeprecation, { - instrumentName: 'component', - instrumentDisplay: computed(function() { - if (this._debugContainerKey) { - return '{{' + this._debugContainerKey.split(':')[1] + '}}'; - } - }), - - init: function() { - this._super(); - set(this, 'context', this); - set(this, 'controller', this); - }, - - defaultLayout: function(context, options){ - Ember.Handlebars.helpers['yield'].call(context, options); - }, - - /** - A components template property is set by passing a block - during its invocation. It is executed within the parent context. - - Example: - - ```handlebars - {{#my-component}} - // something that is run in the context - // of the parent context - {{/my-component}} - ``` - - Specifying a template directly to a component is deprecated without - also specifying the layout property. - - @deprecated - @property template - */ - template: computed(function(key, value) { - if (value !== undefined) { return value; } - - var templateName = get(this, 'templateName'), - template = this.templateForName(templateName, 'template'); - - Ember.assert("You specified the templateName " + templateName + " for " + this + ", but it did not exist.", !templateName || template); - - return template || get(this, 'defaultTemplate'); - }).property('templateName'), - - /** - Specifying a components `templateName` is deprecated without also - providing the `layout` or `layoutName` properties. - - @deprecated - @property templateName - */ - templateName: null, - - // during render, isolate keywords - cloneKeywords: function() { - return { - view: this, - controller: this - }; - }, - - _yield: function(context, options) { - var view = options.data.view, - parentView = this._parentView, - template = get(this, 'template'); - - if (template) { - Ember.assert("A Component must have a parent view in order to yield.", parentView); - - view.appendChild(View, { - isVirtual: true, - tagName: '', - _contextView: parentView, - template: template, - context: get(parentView, 'context'), - controller: get(parentView, 'controller'), - templateData: { keywords: parentView.cloneKeywords() } - }); - } - }, - - /** - If the component is currently inserted into the DOM of a parent view, this - property will point to the controller of the parent view. - - @property targetObject - @type Ember.Controller - @default null - */ - targetObject: computed(function(key) { - var parentView = get(this, '_parentView'); - return parentView ? get(parentView, 'controller') : null; - }).property('_parentView'), - - /** - Triggers a named action on the controller context where the component is used if - this controller has registered for notifications of the action. - - For example a component for playing or pausing music may translate click events - into action notifications of "play" or "stop" depending on some internal state - of the component: - - - ```javascript - App.PlayButtonComponent = Ember.Component.extend({ - click: function(){ - if (this.get('isPlaying')) { - this.sendAction('play'); - } else { - this.sendAction('stop'); - } - } - }); - ``` - - When used inside a template these component actions are configured to - trigger actions in the outer application context: - - ```handlebars - {{! application.hbs }} - {{play-button play="musicStarted" stop="musicStopped"}} - ``` - - When the component receives a browser `click` event it translate this - interaction into application-specific semantics ("play" or "stop") and - triggers the specified action name on the controller for the template - where the component is used: - - - ```javascript - App.ApplicationController = Ember.Controller.extend({ - actions: { - musicStarted: function(){ - // called when the play button is clicked - // and the music started playing - }, - musicStopped: function(){ - // called when the play button is clicked - // and the music stopped playing - } - } - }); - ``` - - If no action name is passed to `sendAction` a default name of "action" - is assumed. - - ```javascript - App.NextButtonComponent = Ember.Component.extend({ - click: function(){ - this.sendAction(); - } - }); - ``` - - ```handlebars - {{! application.hbs }} - {{next-button action="playNextSongInAlbum"}} - ``` - - ```javascript - App.ApplicationController = Ember.Controller.extend({ - actions: { - playNextSongInAlbum: function(){ - ... - } - } - }); - ``` - - @method sendAction - @param [action] {String} the action to trigger - @param [context] {*} a context to send with the action - */ - sendAction: function(action) { - var actionName, - contexts = a_slice.call(arguments, 1); - - // Send the default action - if (action === undefined) { - actionName = get(this, 'action'); - Ember.assert("The default action was triggered on the component " + this.toString() + - ", but the action name (" + actionName + ") was not a string.", - isNone(actionName) || typeof actionName === 'string'); - } else { - actionName = get(this, action); - Ember.assert("The " + action + " action was triggered on the component " + - this.toString() + ", but the action name (" + actionName + - ") was not a string.", - isNone(actionName) || typeof actionName === 'string'); - } - - // If no action name for that action could be found, just abort. - if (actionName === undefined) { return; } - - this.triggerAction({ - action: actionName, - actionContext: contexts - }); - } - }); - - __exports__["default"] = Component; - }); -define("ember-views/views/container_view", - ["ember-metal/core","ember-metal/merge","ember-runtime/mixins/mutable_array","ember-metal/property_get","ember-metal/property_set","ember-views/views/view","ember-views/views/states","ember-metal/error","ember-metal/enumerable_utils","ember-metal/computed","ember-metal/run_loop","ember-metal/properties","ember-views/system/render_buffer","ember-metal/mixin","ember-runtime/system/native_array","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __dependency15__, __exports__) { - "use strict"; - var Ember = __dependency1__["default"]; - // Ember.assert, Ember.K - - var merge = __dependency2__["default"]; - var MutableArray = __dependency3__["default"]; - var get = __dependency4__.get; - var set = __dependency5__.set; - - var View = __dependency6__.View; - var ViewCollection = __dependency6__.ViewCollection; - var cloneStates = __dependency7__.cloneStates; - var EmberViewStates = __dependency7__.states; - - var EmberError = __dependency8__["default"]; - - // ES6TODO: functions on EnumerableUtils should get their own export - var EnumerableUtils = __dependency9__["default"]; - var forEach = EnumerableUtils.forEach; - - var computed = __dependency10__.computed; - var run = __dependency11__["default"]; - var defineProperty = __dependency12__.defineProperty; - var RenderBuffer = __dependency13__["default"]; - var observer = __dependency14__.observer; - var beforeObserver = __dependency14__.beforeObserver; - var A = __dependency15__.A; - - /** - @module ember - @submodule ember-views - */ - - var states = cloneStates(EmberViewStates); - - /** - A `ContainerView` is an `Ember.View` subclass that implements `Ember.MutableArray` - allowing programmatic management of its child views. - - ## Setting Initial Child Views - - The initial array of child views can be set in one of two ways. You can - provide a `childViews` property at creation time that contains instance of - `Ember.View`: - - ```javascript - aContainer = Ember.ContainerView.create({ - childViews: [Ember.View.create(), Ember.View.create()] - }); - ``` - - You can also provide a list of property names whose values are instances of - `Ember.View`: - - ```javascript - aContainer = Ember.ContainerView.create({ - childViews: ['aView', 'bView', 'cView'], - aView: Ember.View.create(), - bView: Ember.View.create(), - cView: Ember.View.create() - }); - ``` - - The two strategies can be combined: - - ```javascript - aContainer = Ember.ContainerView.create({ - childViews: ['aView', Ember.View.create()], - aView: Ember.View.create() - }); - ``` - - Each child view's rendering will be inserted into the container's rendered - HTML in the same order as its position in the `childViews` property. - - ## Adding and Removing Child Views - - The container view implements `Ember.MutableArray` allowing programmatic management of its child views. - - To remove a view, pass that view into a `removeObject` call on the container view. - - Given an empty `` the following code - - ```javascript - aContainer = Ember.ContainerView.create({ - classNames: ['the-container'], - childViews: ['aView', 'bView'], - aView: Ember.View.create({ - template: Ember.Handlebars.compile("A") - }), - bView: Ember.View.create({ - template: Ember.Handlebars.compile("B") - }) - }); - - aContainer.appendTo('body'); - ``` - - Results in the HTML - - ```html -
-
A
-
B
-
- ``` - - Removing a view - - ```javascript - aContainer.toArray(); // [aContainer.aView, aContainer.bView] - aContainer.removeObject(aContainer.get('bView')); - aContainer.toArray(); // [aContainer.aView] - ``` - - Will result in the following HTML - - ```html -
-
A
-
- ``` - - Similarly, adding a child view is accomplished by adding `Ember.View` instances to the - container view. - - Given an empty `` the following code - - ```javascript - aContainer = Ember.ContainerView.create({ - classNames: ['the-container'], - childViews: ['aView', 'bView'], - aView: Ember.View.create({ - template: Ember.Handlebars.compile("A") - }), - bView: Ember.View.create({ - template: Ember.Handlebars.compile("B") - }) - }); - - aContainer.appendTo('body'); - ``` - - Results in the HTML - - ```html -
-
A
-
B
-
- ``` - - Adding a view - - ```javascript - AnotherViewClass = Ember.View.extend({ - template: Ember.Handlebars.compile("Another view") - }); - - aContainer.toArray(); // [aContainer.aView, aContainer.bView] - aContainer.pushObject(AnotherViewClass.create()); - aContainer.toArray(); // [aContainer.aView, aContainer.bView, ] - ``` - - Will result in the following HTML - - ```html -
-
A
-
B
-
Another view
-
- ``` - - ## Templates and Layout - - A `template`, `templateName`, `defaultTemplate`, `layout`, `layoutName` or - `defaultLayout` property on a container view will not result in the template - or layout being rendered. The HTML contents of a `Ember.ContainerView`'s DOM - representation will only be the rendered HTML of its child views. - - @class ContainerView - @namespace Ember - @extends Ember.View - */ - var ContainerView = View.extend(MutableArray, { - states: states, - - init: function() { - this._super(); - - var childViews = get(this, 'childViews'); - - // redefine view's childViews property that was obliterated - defineProperty(this, 'childViews', View.childViewsProperty); - - var _childViews = this._childViews; - - forEach(childViews, function(viewName, idx) { - var view; - - if ('string' === typeof viewName) { - view = get(this, viewName); - view = this.createChildView(view); - set(this, viewName, view); - } else { - view = this.createChildView(viewName); - } - - _childViews[idx] = view; - }, this); - - var currentView = get(this, 'currentView'); - if (currentView) { - if (!_childViews.length) { _childViews = this._childViews = this._childViews.slice(); } - _childViews.push(this.createChildView(currentView)); - } - }, - - replace: function(idx, removedCount, addedViews) { - var addedCount = addedViews ? get(addedViews, 'length') : 0; - var self = this; - Ember.assert("You can't add a child to a container - the child is already a child of another view", A(addedViews).every(function(item) { return !get(item, '_parentView') || get(item, '_parentView') === self; })); - - this.arrayContentWillChange(idx, removedCount, addedCount); - this.childViewsWillChange(this._childViews, idx, removedCount); - - if (addedCount === 0) { - this._childViews.splice(idx, removedCount) ; - } else { - var args = [idx, removedCount].concat(addedViews); - if (addedViews.length && !this._childViews.length) { this._childViews = this._childViews.slice(); } - this._childViews.splice.apply(this._childViews, args); - } - - this.arrayContentDidChange(idx, removedCount, addedCount); - this.childViewsDidChange(this._childViews, idx, removedCount, addedCount); - - return this; - }, - - objectAt: function(idx) { - return this._childViews[idx]; - }, - - length: computed(function () { - return this._childViews.length; - }).volatile(), - - /** - Instructs each child view to render to the passed render buffer. - - @private - @method render - @param {Ember.RenderBuffer} buffer the buffer to render to - */ - render: function(buffer) { - this.forEachChildView(function(view) { - view.renderToBuffer(buffer); - }); - }, - - instrumentName: 'container', - - /** - When a child view is removed, destroy its element so that - it is removed from the DOM. - - The array observer that triggers this action is set up in the - `renderToBuffer` method. - - @private - @method childViewsWillChange - @param {Ember.Array} views the child views array before mutation - @param {Number} start the start position of the mutation - @param {Number} removed the number of child views removed - **/ - childViewsWillChange: function(views, start, removed) { - this.propertyWillChange('childViews'); - - if (removed > 0) { - var changedViews = views.slice(start, start+removed); - // transition to preRender before clearing parentView - this.currentState.childViewsWillChange(this, views, start, removed); - this.initializeViews(changedViews, null, null); - } - }, - - removeChild: function(child) { - this.removeObject(child); - return this; - }, - - /** - When a child view is added, make sure the DOM gets updated appropriately. - - If the view has already rendered an element, we tell the child view to - create an element and insert it into the DOM. If the enclosing container - view has already written to a buffer, but not yet converted that buffer - into an element, we insert the string representation of the child into the - appropriate place in the buffer. - - @private - @method childViewsDidChange - @param {Ember.Array} views the array of child views after the mutation has occurred - @param {Number} start the start position of the mutation - @param {Number} removed the number of child views removed - @param {Number} added the number of child views added - */ - childViewsDidChange: function(views, start, removed, added) { - if (added > 0) { - var changedViews = views.slice(start, start+added); - this.initializeViews(changedViews, this, get(this, 'templateData')); - this.currentState.childViewsDidChange(this, views, start, added); - } - this.propertyDidChange('childViews'); - }, - - initializeViews: function(views, parentView, templateData) { - forEach(views, function(view) { - set(view, '_parentView', parentView); - - if (!view.container && parentView) { - set(view, 'container', parentView.container); - } - - if (!get(view, 'templateData')) { - set(view, 'templateData', templateData); - } - }); - }, - - currentView: null, - - _currentViewWillChange: beforeObserver('currentView', function() { - var currentView = get(this, 'currentView'); - if (currentView) { - currentView.destroy(); - } - }), - - _currentViewDidChange: observer('currentView', function() { - var currentView = get(this, 'currentView'); - if (currentView) { - Ember.assert("You tried to set a current view that already has a parent. Make sure you don't have multiple outlets in the same view.", !get(currentView, '_parentView')); - this.pushObject(currentView); - } - }), - - _ensureChildrenAreInDOM: function () { - this.currentState.ensureChildrenAreInDOM(this); - } - }); - - merge(states._default, { - childViewsWillChange: Ember.K, - childViewsDidChange: Ember.K, - ensureChildrenAreInDOM: Ember.K - }); - - merge(states.inBuffer, { - childViewsDidChange: function(parentView, views, start, added) { - throw new EmberError('You cannot modify child views while in the inBuffer state'); - } - }); - - merge(states.hasElement, { - childViewsWillChange: function(view, views, start, removed) { - for (var i=start; i - ``` - - ## HTML `class` Attribute - - The HTML `class` attribute of a view's tag can be set by providing a - `classNames` property that is set to an array of strings: - - ```javascript - MyView = Ember.View.extend({ - classNames: ['my-class', 'my-other-class'] - }); - ``` - - Will result in view instances with an HTML representation of: - - ```html -
- ``` - - `class` attribute values can also be set by providing a `classNameBindings` - property set to an array of properties names for the view. The return value - of these properties will be added as part of the value for the view's `class` - attribute. These properties can be computed properties: - - ```javascript - MyView = Ember.View.extend({ - classNameBindings: ['propertyA', 'propertyB'], - propertyA: 'from-a', - propertyB: function() { - if (someLogic) { return 'from-b'; } - }.property() - }); - ``` - - Will result in view instances with an HTML representation of: - - ```html -
- ``` - - If the value of a class name binding returns a boolean the property name - itself will be used as the class name if the property is true. The class name - will not be added if the value is `false` or `undefined`. - - ```javascript - MyView = Ember.View.extend({ - classNameBindings: ['hovered'], - hovered: true - }); - ``` - - Will result in view instances with an HTML representation of: - - ```html -
- ``` - - When using boolean class name bindings you can supply a string value other - than the property name for use as the `class` HTML attribute by appending the - preferred value after a ":" character when defining the binding: - - ```javascript - MyView = Ember.View.extend({ - classNameBindings: ['awesome:so-very-cool'], - awesome: true - }); - ``` - - Will result in view instances with an HTML representation of: - - ```html -
- ``` - - Boolean value class name bindings whose property names are in a - camelCase-style format will be converted to a dasherized format: - - ```javascript - MyView = Ember.View.extend({ - classNameBindings: ['isUrgent'], - isUrgent: true - }); - ``` - - Will result in view instances with an HTML representation of: - - ```html -
- ``` - - Class name bindings can also refer to object values that are found by - traversing a path relative to the view itself: - - ```javascript - MyView = Ember.View.extend({ - classNameBindings: ['messages.empty'] - messages: Ember.Object.create({ - empty: true - }) - }); - ``` - - Will result in view instances with an HTML representation of: - - ```html -
- ``` - - If you want to add a class name for a property which evaluates to true and - and a different class name if it evaluates to false, you can pass a binding - like this: - - ```javascript - // Applies 'enabled' class when isEnabled is true and 'disabled' when isEnabled is false - Ember.View.extend({ - classNameBindings: ['isEnabled:enabled:disabled'] - isEnabled: true - }); - ``` - - Will result in view instances with an HTML representation of: - - ```html -
- ``` - - When isEnabled is `false`, the resulting HTML reprensentation looks like - this: - - ```html -
- ``` - - This syntax offers the convenience to add a class if a property is `false`: - - ```javascript - // Applies no class when isEnabled is true and class 'disabled' when isEnabled is false - Ember.View.extend({ - classNameBindings: ['isEnabled::disabled'] - isEnabled: true - }); - ``` - - Will result in view instances with an HTML representation of: - - ```html -
- ``` - - When the `isEnabled` property on the view is set to `false`, it will result - in view instances with an HTML representation of: - - ```html -
- ``` - - Updates to the the value of a class name binding will result in automatic - update of the HTML `class` attribute in the view's rendered HTML - representation. If the value becomes `false` or `undefined` the class name - will be removed. - - Both `classNames` and `classNameBindings` are concatenated properties. See - [Ember.Object](/api/classes/Ember.Object.html) documentation for more - information about concatenated properties. - - ## HTML Attributes - - The HTML attribute section of a view's tag can be set by providing an - `attributeBindings` property set to an array of property names on the view. - The return value of these properties will be used as the value of the view's - HTML associated attribute: - - ```javascript - AnchorView = Ember.View.extend({ - tagName: 'a', - attributeBindings: ['href'], - href: 'http://google.com' - }); - ``` - - Will result in view instances with an HTML representation of: - - ```html - - ``` - - One property can be mapped on to another by placing a ":" between - the source property and the destination property: - - ```javascript - AnchorView = Ember.View.extend({ - tagName: 'a', - attributeBindings: ['url:href'], - url: 'http://google.com' - }); - ``` - - Will result in view instances with an HTML representation of: - - ```html - - ``` - - If the return value of an `attributeBindings` monitored property is a boolean - the property will follow HTML's pattern of repeating the attribute's name as - its value: - - ```javascript - MyTextInput = Ember.View.extend({ - tagName: 'input', - attributeBindings: ['disabled'], - disabled: true - }); - ``` - - Will result in view instances with an HTML representation of: - - ```html - - ``` - - `attributeBindings` can refer to computed properties: - - ```javascript - MyTextInput = Ember.View.extend({ - tagName: 'input', - attributeBindings: ['disabled'], - disabled: function() { - if (someLogic) { - return true; - } else { - return false; - } - }.property() - }); - ``` - - Updates to the the property of an attribute binding will result in automatic - update of the HTML attribute in the view's rendered HTML representation. - - `attributeBindings` is a concatenated property. See [Ember.Object](/api/classes/Ember.Object.html) - documentation for more information about concatenated properties. - - ## Templates - - The HTML contents of a view's rendered representation are determined by its - template. Templates can be any function that accepts an optional context - parameter and returns a string of HTML that will be inserted within the - view's tag. Most typically in Ember this function will be a compiled - `Ember.Handlebars` template. - - ```javascript - AView = Ember.View.extend({ - template: Ember.Handlebars.compile('I am the template') - }); - ``` - - Will result in view instances with an HTML representation of: - - ```html -
I am the template
- ``` - - Within an Ember application is more common to define a Handlebars templates as - part of a page: - - ```html - - ``` - - And associate it by name using a view's `templateName` property: - - ```javascript - AView = Ember.View.extend({ - templateName: 'some-template' - }); - ``` - - If you have nested resources, your Handlebars template will look like this: - - ```html - - ``` - - And `templateName` property: - - ```javascript - AView = Ember.View.extend({ - templateName: 'posts/new' - }); - ``` - - Using a value for `templateName` that does not have a Handlebars template - with a matching `data-template-name` attribute will throw an error. - - For views classes that may have a template later defined (e.g. as the block - portion of a `{{view}}` Handlebars helper call in another template or in - a subclass), you can provide a `defaultTemplate` property set to compiled - template function. If a template is not later provided for the view instance - the `defaultTemplate` value will be used: - - ```javascript - AView = Ember.View.extend({ - defaultTemplate: Ember.Handlebars.compile('I was the default'), - template: null, - templateName: null - }); - ``` - - Will result in instances with an HTML representation of: - - ```html -
I was the default
- ``` - - If a `template` or `templateName` is provided it will take precedence over - `defaultTemplate`: - - ```javascript - AView = Ember.View.extend({ - defaultTemplate: Ember.Handlebars.compile('I was the default') - }); - - aView = AView.create({ - template: Ember.Handlebars.compile('I was the template, not default') - }); - ``` - - Will result in the following HTML representation when rendered: - - ```html -
I was the template, not default
- ``` - - ## View Context - - The default context of the compiled template is the view's controller: - - ```javascript - AView = Ember.View.extend({ - template: Ember.Handlebars.compile('Hello {{excitedGreeting}}') - }); - - aController = Ember.Object.create({ - firstName: 'Barry', - excitedGreeting: function() { - return this.get("content.firstName") + "!!!" - }.property() - }); - - aView = AView.create({ - controller: aController, - }); - ``` - - Will result in an HTML representation of: - - ```html -
Hello Barry!!!
- ``` - - A context can also be explicitly supplied through the view's `context` - property. If the view has neither `context` nor `controller` properties, the - `parentView`'s context will be used. - - ## Layouts - - Views can have a secondary template that wraps their main template. Like - primary templates, layouts can be any function that accepts an optional - context parameter and returns a string of HTML that will be inserted inside - view's tag. Views whose HTML element is self closing (e.g. ``) - cannot have a layout and this property will be ignored. - - Most typically in Ember a layout will be a compiled `Ember.Handlebars` - template. - - A view's layout can be set directly with the `layout` property or reference - an existing Handlebars template by name with the `layoutName` property. - - A template used as a layout must contain a single use of the Handlebars - `{{yield}}` helper. The HTML contents of a view's rendered `template` will be - inserted at this location: - - ```javascript - AViewWithLayout = Ember.View.extend({ - layout: Ember.Handlebars.compile("
{{yield}}
") - template: Ember.Handlebars.compile("I got wrapped"), - }); - ``` - - Will result in view instances with an HTML representation of: - - ```html -
-
- I got wrapped -
-
- ``` - - See [Ember.Handlebars.helpers.yield](/api/classes/Ember.Handlebars.helpers.html#method_yield) - for more information. - - ## Responding to Browser Events - - Views can respond to user-initiated events in one of three ways: method - implementation, through an event manager, and through `{{action}}` helper use - in their template or layout. - - ### Method Implementation - - Views can respond to user-initiated events by implementing a method that - matches the event name. A `jQuery.Event` object will be passed as the - argument to this method. - - ```javascript - AView = Ember.View.extend({ - click: function(event) { - // will be called when when an instance's - // rendered element is clicked - } - }); - ``` - - ### Event Managers - - Views can define an object as their `eventManager` property. This object can - then implement methods that match the desired event names. Matching events - that occur on the view's rendered HTML or the rendered HTML of any of its DOM - descendants will trigger this method. A `jQuery.Event` object will be passed - as the first argument to the method and an `Ember.View` object as the - second. The `Ember.View` will be the view whose rendered HTML was interacted - with. This may be the view with the `eventManager` property or one of its - descendent views. - - ```javascript - AView = Ember.View.extend({ - eventManager: Ember.Object.create({ - doubleClick: function(event, view) { - // will be called when when an instance's - // rendered element or any rendering - // of this views's descendent - // elements is clicked - } - }) - }); - ``` - - An event defined for an event manager takes precedence over events of the - same name handled through methods on the view. - - ```javascript - AView = Ember.View.extend({ - mouseEnter: function(event) { - // will never trigger. - }, - eventManager: Ember.Object.create({ - mouseEnter: function(event, view) { - // takes precedence over AView#mouseEnter - } - }) - }); - ``` - - Similarly a view's event manager will take precedence for events of any views - rendered as a descendent. A method name that matches an event name will not - be called if the view instance was rendered inside the HTML representation of - a view that has an `eventManager` property defined that handles events of the - name. Events not handled by the event manager will still trigger method calls - on the descendent. - - ```javascript - OuterView = Ember.View.extend({ - template: Ember.Handlebars.compile("outer {{#view InnerView}}inner{{/view}} outer"), - eventManager: Ember.Object.create({ - mouseEnter: function(event, view) { - // view might be instance of either - // OuterView or InnerView depending on - // where on the page the user interaction occured - } - }) - }); - - InnerView = Ember.View.extend({ - click: function(event) { - // will be called if rendered inside - // an OuterView because OuterView's - // eventManager doesn't handle click events - }, - mouseEnter: function(event) { - // will never be called if rendered inside - // an OuterView. - } - }); - ``` - - ### Handlebars `{{action}}` Helper - - See [Handlebars.helpers.action](/api/classes/Ember.Handlebars.helpers.html#method_action). - - ### Event Names - - All of the event handling approaches described above respond to the same set - of events. The names of the built-in events are listed below. (The hash of - built-in events exists in `Ember.EventDispatcher`.) Additional, custom events - can be registered by using `Ember.Application.customEvents`. - - Touch events: - - * `touchStart` - * `touchMove` - * `touchEnd` - * `touchCancel` - - Keyboard events - - * `keyDown` - * `keyUp` - * `keyPress` - - Mouse events - - * `mouseDown` - * `mouseUp` - * `contextMenu` - * `click` - * `doubleClick` - * `mouseMove` - * `focusIn` - * `focusOut` - * `mouseEnter` - * `mouseLeave` - - Form events: - - * `submit` - * `change` - * `focusIn` - * `focusOut` - * `input` - - HTML5 drag and drop events: - - * `dragStart` - * `drag` - * `dragEnter` - * `dragLeave` - * `dragOver` - * `dragEnd` - * `drop` - - ## Handlebars `{{view}}` Helper - - Other `Ember.View` instances can be included as part of a view's template by - using the `{{view}}` Handlebars helper. See [Ember.Handlebars.helpers.view](/api/classes/Ember.Handlebars.helpers.html#method_view) - for additional information. - - @class View - @namespace Ember - @extends Ember.CoreView - */ - var View = CoreView.extend({ - - concatenatedProperties: ['classNames', 'classNameBindings', 'attributeBindings'], - - /** - @property isView - @type Boolean - @default true - @static - */ - isView: true, - - // .......................................................... - // TEMPLATE SUPPORT - // - - /** - The name of the template to lookup if no template is provided. - - By default `Ember.View` will lookup a template with this name in - `Ember.TEMPLATES` (a shared global object). - - @property templateName - @type String - @default null - */ - templateName: null, - - /** - The name of the layout to lookup if no layout is provided. - - By default `Ember.View` will lookup a template with this name in - `Ember.TEMPLATES` (a shared global object). - - @property layoutName - @type String - @default null - */ - layoutName: null, - - /** - Used to identify this view during debugging - - @property instrumentDisplay - @type String - */ - instrumentDisplay: computed(function() { - if (this.helperName) { - return '{{' + this.helperName + '}}'; - } - }), - - /** - The template used to render the view. This should be a function that - accepts an optional context parameter and returns a string of HTML that - will be inserted into the DOM relative to its parent view. - - In general, you should set the `templateName` property instead of setting - the template yourself. - - @property template - @type Function - */ - template: computed('templateName', function(key, value) { - if (value !== undefined) { return value; } - - var templateName = get(this, 'templateName'), - template = this.templateForName(templateName, 'template'); - - Ember.assert("You specified the templateName " + templateName + " for " + this + ", but it did not exist.", !templateName || template); - - return template || get(this, 'defaultTemplate'); - }), - - /** - The controller managing this view. If this property is set, it will be - made available for use by the template. - - @property controller - @type Object - */ - controller: computed('_parentView', function(key) { - var parentView = get(this, '_parentView'); - return parentView ? get(parentView, 'controller') : null; - }), - - /** - A view may contain a layout. A layout is a regular template but - supersedes the `template` property during rendering. It is the - responsibility of the layout template to retrieve the `template` - property from the view (or alternatively, call `Handlebars.helpers.yield`, - `{{yield}}`) to render it in the correct location. - - This is useful for a view that has a shared wrapper, but which delegates - the rendering of the contents of the wrapper to the `template` property - on a subclass. - - @property layout - @type Function - */ - layout: computed(function(key) { - var layoutName = get(this, 'layoutName'), - layout = this.templateForName(layoutName, 'layout'); - - Ember.assert("You specified the layoutName " + layoutName + " for " + this + ", but it did not exist.", !layoutName || layout); - - return layout || get(this, 'defaultLayout'); - }).property('layoutName'), - - _yield: function(context, options) { - var template = get(this, 'template'); - if (template) { template(context, options); } - }, - - templateForName: function(name, type) { - if (!name) { return; } - Ember.assert("templateNames are not allowed to contain periods: "+name, name.indexOf('.') === -1); - - // the defaultContainer is deprecated - var container = this.container || (Container && Container.defaultContainer); - return container && container.lookup('template:' + name); - }, - - /** - The object from which templates should access properties. - - This object will be passed to the template function each time the render - method is called, but it is up to the individual function to decide what - to do with it. - - By default, this will be the view's controller. - - @property context - @type Object - */ - context: computed(function(key, value) { - if (arguments.length === 2) { - set(this, '_context', value); - return value; - } else { - return get(this, '_context'); - } - }).volatile(), - - /** - Private copy of the view's template context. This can be set directly - by Handlebars without triggering the observer that causes the view - to be re-rendered. - - The context of a view is looked up as follows: - - 1. Supplied context (usually by Handlebars) - 2. Specified controller - 3. `parentView`'s context (for a child of a ContainerView) - - The code in Handlebars that overrides the `_context` property first - checks to see whether the view has a specified controller. This is - something of a hack and should be revisited. - - @property _context - @private - */ - _context: computed(function(key) { - var parentView, controller; - - if (controller = get(this, 'controller')) { - return controller; - } - - parentView = this._parentView; - if (parentView) { - return get(parentView, '_context'); - } - - return null; - }), - - /** - If a value that affects template rendering changes, the view should be - re-rendered to reflect the new value. - - @method _contextDidChange - @private - */ - _contextDidChange: observer('context', function() { - this.rerender(); - }), - - /** - If `false`, the view will appear hidden in DOM. - - @property isVisible - @type Boolean - @default null - */ - isVisible: true, - - /** - Array of child views. You should never edit this array directly. - Instead, use `appendChild` and `removeFromParent`. - - @property childViews - @type Array - @default [] - @private - */ - childViews: childViewsProperty, - - _childViews: EMPTY_ARRAY, - - // When it's a virtual view, we need to notify the parent that their - // childViews will change. - _childViewsWillChange: beforeObserver('childViews', function() { - if (this.isVirtual) { - var parentView = get(this, 'parentView'); - if (parentView) { propertyWillChange(parentView, 'childViews'); } - } - }), - - // When it's a virtual view, we need to notify the parent that their - // childViews did change. - _childViewsDidChange: observer('childViews', function() { - if (this.isVirtual) { - var parentView = get(this, 'parentView'); - if (parentView) { propertyDidChange(parentView, 'childViews'); } - } - }), - - /** - Return the nearest ancestor that is an instance of the provided - class. - - @method nearestInstanceOf - @param {Class} klass Subclass of Ember.View (or Ember.View itself) - @return Ember.View - @deprecated - */ - nearestInstanceOf: function(klass) { - Ember.deprecate("nearestInstanceOf is deprecated and will be removed from future releases. Use nearestOfType."); - var view = get(this, 'parentView'); - - while (view) { - if (view instanceof klass) { return view; } - view = get(view, 'parentView'); - } - }, - - /** - Return the nearest ancestor that is an instance of the provided - class or mixin. - - @method nearestOfType - @param {Class,Mixin} klass Subclass of Ember.View (or Ember.View itself), - or an instance of Ember.Mixin. - @return Ember.View - */ - nearestOfType: function(klass) { - var view = get(this, 'parentView'), - isOfType = klass instanceof Mixin ? - function(view) { return klass.detect(view); } : - function(view) { return klass.detect(view.constructor); }; - - while (view) { - if (isOfType(view)) { return view; } - view = get(view, 'parentView'); - } - }, - - /** - Return the nearest ancestor that has a given property. - - @method nearestWithProperty - @param {String} property A property name - @return Ember.View - */ - nearestWithProperty: function(property) { - var view = get(this, 'parentView'); - - while (view) { - if (property in view) { return view; } - view = get(view, 'parentView'); - } - }, - - /** - Return the nearest ancestor whose parent is an instance of - `klass`. - - @method nearestChildOf - @param {Class} klass Subclass of Ember.View (or Ember.View itself) - @return Ember.View - */ - nearestChildOf: function(klass) { - var view = get(this, 'parentView'); - - while (view) { - if (get(view, 'parentView') instanceof klass) { return view; } - view = get(view, 'parentView'); - } - }, - - /** - When the parent view changes, recursively invalidate `controller` - - @method _parentViewDidChange - @private - */ - _parentViewDidChange: observer('_parentView', function() { - if (this.isDestroying) { return; } - - this.trigger('parentViewDidChange'); - - if (get(this, 'parentView.controller') && !get(this, 'controller')) { - this.notifyPropertyChange('controller'); - } - }), - - _controllerDidChange: observer('controller', function() { - if (this.isDestroying) { return; } - - this.rerender(); - - this.forEachChildView(function(view) { - view.propertyDidChange('controller'); - }); - }), - - cloneKeywords: function() { - var templateData = get(this, 'templateData'); - - var keywords = templateData ? copy(templateData.keywords) : {}; - set(keywords, 'view', get(this, 'concreteView')); - set(keywords, '_view', this); - set(keywords, 'controller', get(this, 'controller')); - - return keywords; - }, - - /** - Called on your view when it should push strings of HTML into a - `Ember.RenderBuffer`. Most users will want to override the `template` - or `templateName` properties instead of this method. - - By default, `Ember.View` will look for a function in the `template` - property and invoke it with the value of `context`. The value of - `context` will be the view's controller unless you override it. - - @method render - @param {Ember.RenderBuffer} buffer The render buffer - */ - render: function(buffer) { - // If this view has a layout, it is the responsibility of the - // the layout to render the view's template. Otherwise, render the template - // directly. - var template = get(this, 'layout') || get(this, 'template'); - - if (template) { - var context = get(this, 'context'); - var keywords = this.cloneKeywords(); - var output; - - var data = { - view: this, - buffer: buffer, - isRenderData: true, - keywords: keywords, - insideGroup: get(this, 'templateData.insideGroup') - }; - - // Invoke the template with the provided template context, which - // is the view's controller by default. A hash of data is also passed that provides - // the template with access to the view and render buffer. - - Ember.assert('template must be a function. Did you mean to call Ember.Handlebars.compile("...") or specify templateName instead?', typeof template === 'function'); - // The template should write directly to the render buffer instead - // of returning a string. - output = template(context, { data: data }); - - // If the template returned a string instead of writing to the buffer, - // push the string onto the buffer. - if (output !== undefined) { buffer.push(output); } - } - }, - - /** - Renders the view again. This will work regardless of whether the - view is already in the DOM or not. If the view is in the DOM, the - rendering process will be deferred to give bindings a chance - to synchronize. - - If children were added during the rendering process using `appendChild`, - `rerender` will remove them, because they will be added again - if needed by the next `render`. - - In general, if the display of your view changes, you should modify - the DOM element directly instead of manually calling `rerender`, which can - be slow. - - @method rerender - */ - rerender: function() { - return this.currentState.rerender(this); - }, - - clearRenderedChildren: function() { - var lengthBefore = this.lengthBeforeRender, - lengthAfter = this.lengthAfterRender; - - // If there were child views created during the last call to render(), - // remove them under the assumption that they will be re-created when - // we re-render. - - // VIEW-TODO: Unit test this path. - var childViews = this._childViews; - for (var i=lengthAfter-1; i>=lengthBefore; i--) { - if (childViews[i]) { childViews[i].destroy(); } - } - }, - - /** - Iterates over the view's `classNameBindings` array, inserts the value - of the specified property into the `classNames` array, then creates an - observer to update the view's element if the bound property ever changes - in the future. - - @method _applyClassNameBindings - @private - */ - _applyClassNameBindings: function(classBindings) { - var classNames = this.classNames, - elem, newClass, dasherizedClass; - - // Loop through all of the configured bindings. These will be either - // property names ('isUrgent') or property paths relative to the view - // ('content.isUrgent') - a_forEach(classBindings, function(binding) { - - Ember.assert("classNameBindings must not have spaces in them. Multiple class name bindings can be provided as elements of an array, e.g. ['foo', ':bar']", binding.indexOf(' ') === -1); - - // Variable in which the old class value is saved. The observer function - // closes over this variable, so it knows which string to remove when - // the property changes. - var oldClass; - // Extract just the property name from bindings like 'foo:bar' - var parsedPath = View._parsePropertyPath(binding); - - // Set up an observer on the context. If the property changes, toggle the - // class name. - var observer = function() { - // Get the current value of the property - newClass = this._classStringForProperty(binding); - elem = this.$(); - - // If we had previously added a class to the element, remove it. - if (oldClass) { - elem.removeClass(oldClass); - // Also remove from classNames so that if the view gets rerendered, - // the class doesn't get added back to the DOM. - classNames.removeObject(oldClass); - } - - // If necessary, add a new class. Make sure we keep track of it so - // it can be removed in the future. - if (newClass) { - elem.addClass(newClass); - oldClass = newClass; - } else { - oldClass = null; - } - }; - - // Get the class name for the property at its current value - dasherizedClass = this._classStringForProperty(binding); - - if (dasherizedClass) { - // Ensure that it gets into the classNames array - // so it is displayed when we render. - a_addObject(classNames, dasherizedClass); - - // Save a reference to the class name so we can remove it - // if the observer fires. Remember that this variable has - // been closed over by the observer. - oldClass = dasherizedClass; - } - - this.registerObserver(this, parsedPath.path, observer); - // Remove className so when the view is rerendered, - // the className is added based on binding reevaluation - this.one('willClearRender', function() { - if (oldClass) { - classNames.removeObject(oldClass); - oldClass = null; - } - }); - - }, this); - }, - - _unspecifiedAttributeBindings: null, - - /** - Iterates through the view's attribute bindings, sets up observers for each, - then applies the current value of the attributes to the passed render buffer. - - @method _applyAttributeBindings - @param {Ember.RenderBuffer} buffer - @private - */ - _applyAttributeBindings: function(buffer, attributeBindings) { - var attributeValue, - unspecifiedAttributeBindings = this._unspecifiedAttributeBindings = this._unspecifiedAttributeBindings || {}; - - a_forEach(attributeBindings, function(binding) { - var split = binding.split(':'), - property = split[0], - attributeName = split[1] || property; - - if (property in this) { - this._setupAttributeBindingObservation(property, attributeName); - - // Determine the current value and add it to the render buffer - // if necessary. - attributeValue = get(this, property); - View.applyAttributeBindings(buffer, attributeName, attributeValue); - } else { - unspecifiedAttributeBindings[property] = attributeName; - } - }, this); - - // Lazily setup setUnknownProperty after attributeBindings are initially applied - this.setUnknownProperty = this._setUnknownProperty; - }, - - _setupAttributeBindingObservation: function(property, attributeName) { - var attributeValue, elem; - - // Create an observer to add/remove/change the attribute if the - // JavaScript property changes. - var observer = function() { - elem = this.$(); - - attributeValue = get(this, property); - - View.applyAttributeBindings(elem, attributeName, attributeValue); - }; - - this.registerObserver(this, property, observer); - }, - - /** - We're using setUnknownProperty as a hook to setup attributeBinding observers for - properties that aren't defined on a view at initialization time. - - Note: setUnknownProperty will only be called once for each property. - - @method setUnknownProperty - @param key - @param value - @private - */ - setUnknownProperty: null, // Gets defined after initialization by _applyAttributeBindings - - _setUnknownProperty: function(key, value) { - var attributeName = this._unspecifiedAttributeBindings && this._unspecifiedAttributeBindings[key]; - if (attributeName) { - this._setupAttributeBindingObservation(key, attributeName); - } - - defineProperty(this, key); - return set(this, key, value); - }, - - /** - Given a property name, returns a dasherized version of that - property name if the property evaluates to a non-falsy value. - - For example, if the view has property `isUrgent` that evaluates to true, - passing `isUrgent` to this method will return `"is-urgent"`. - - @method _classStringForProperty - @param property - @private - */ - _classStringForProperty: function(property) { - var parsedPath = View._parsePropertyPath(property); - var path = parsedPath.path; - - var val = get(this, path); - if (val === undefined && isGlobalPath(path)) { - val = get(Ember.lookup, path); - } - - return View._classStringForValue(path, val, parsedPath.className, parsedPath.falsyClassName); - }, - - // .......................................................... - // ELEMENT SUPPORT - // - - /** - Returns the current DOM element for the view. - - @property element - @type DOMElement - */ - element: computed('_parentView', function(key, value) { - if (value !== undefined) { - return this.currentState.setElement(this, value); - } else { - return this.currentState.getElement(this); - } - }), - - /** - Returns a jQuery object for this view's element. If you pass in a selector - string, this method will return a jQuery object, using the current element - as its buffer. - - For example, calling `view.$('li')` will return a jQuery object containing - all of the `li` elements inside the DOM element of this view. - - @method $ - @param {String} [selector] a jQuery-compatible selector string - @return {jQuery} the jQuery object for the DOM node - */ - $: function(sel) { - return this.currentState.$(this, sel); - }, - - mutateChildViews: function(callback) { - var childViews = this._childViews, - idx = childViews.length, - view; - - while(--idx >= 0) { - view = childViews[idx]; - callback(this, view, idx); - } - - return this; - }, - - forEachChildView: function(callback) { - var childViews = this._childViews; - - if (!childViews) { return this; } - - var len = childViews.length, - view, idx; - - for (idx = 0; idx < len; idx++) { - view = childViews[idx]; - callback(view); - } - - return this; - }, - - /** - Appends the view's element to the specified parent element. - - If the view does not have an HTML representation yet, `createElement()` - will be called automatically. - - Note that this method just schedules the view to be appended; the DOM - element will not be appended to the given element until all bindings have - finished synchronizing. - - This is not typically a function that you will need to call directly when - building your application. You might consider using `Ember.ContainerView` - instead. If you do need to use `appendTo`, be sure that the target element - you are providing is associated with an `Ember.Application` and does not - have an ancestor element that is associated with an Ember view. - - @method appendTo - @param {String|DOMElement|jQuery} A selector, element, HTML string, or jQuery object - @return {Ember.View} receiver - */ - appendTo: function(target) { - // Schedule the DOM element to be created and appended to the given - // element after bindings have synchronized. - this._insertElementLater(function() { - Ember.assert("You tried to append to (" + target + ") but that isn't in the DOM", jQuery(target).length > 0); - Ember.assert("You cannot append to an existing Ember.View. Consider using Ember.ContainerView instead.", !jQuery(target).is('.ember-view') && !jQuery(target).parents().is('.ember-view')); - this.$().appendTo(target); - }); - - return this; - }, - - /** - Replaces the content of the specified parent element with this view's - element. If the view does not have an HTML representation yet, - `createElement()` will be called automatically. - - Note that this method just schedules the view to be appended; the DOM - element will not be appended to the given element until all bindings have - finished synchronizing - - @method replaceIn - @param {String|DOMElement|jQuery} target A selector, element, HTML string, or jQuery object - @return {Ember.View} received - */ - replaceIn: function(target) { - Ember.assert("You tried to replace in (" + target + ") but that isn't in the DOM", jQuery(target).length > 0); - Ember.assert("You cannot replace an existing Ember.View. Consider using Ember.ContainerView instead.", !jQuery(target).is('.ember-view') && !jQuery(target).parents().is('.ember-view')); - - this._insertElementLater(function() { - jQuery(target).empty(); - this.$().appendTo(target); - }); - - return this; - }, - - /** - Schedules a DOM operation to occur during the next render phase. This - ensures that all bindings have finished synchronizing before the view is - rendered. - - To use, pass a function that performs a DOM operation. - - Before your function is called, this view and all child views will receive - the `willInsertElement` event. After your function is invoked, this view - and all of its child views will receive the `didInsertElement` event. - - ```javascript - view._insertElementLater(function() { - this.createElement(); - this.$().appendTo('body'); - }); - ``` - - @method _insertElementLater - @param {Function} fn the function that inserts the element into the DOM - @private - */ - _insertElementLater: function(fn) { - this._scheduledInsert = run.scheduleOnce('render', this, '_insertElement', fn); - }, - - _insertElement: function (fn) { - this._scheduledInsert = null; - this.currentState.insertElement(this, fn); - }, - - /** - Appends the view's element to the document body. If the view does - not have an HTML representation yet, `createElement()` will be called - automatically. - - If your application uses the `rootElement` property, you must append - the view within that element. Rendering views outside of the `rootElement` - is not supported. - - Note that this method just schedules the view to be appended; the DOM - element will not be appended to the document body until all bindings have - finished synchronizing. - - @method append - @return {Ember.View} receiver - */ - append: function() { - return this.appendTo(document.body); - }, - - /** - Removes the view's element from the element to which it is attached. - - @method remove - @return {Ember.View} receiver - */ - remove: function() { - // What we should really do here is wait until the end of the run loop - // to determine if the element has been re-appended to a different - // element. - // In the interim, we will just re-render if that happens. It is more - // important than elements get garbage collected. - if (!this.removedFromDOM) { this.destroyElement(); } - this.invokeRecursively(function(view) { - if (view.clearRenderedChildren) { view.clearRenderedChildren(); } - }); - }, - - elementId: null, - - /** - Attempts to discover the element in the parent element. The default - implementation looks for an element with an ID of `elementId` (or the - view's guid if `elementId` is null). You can override this method to - provide your own form of lookup. For example, if you want to discover your - element using a CSS class name instead of an ID. - - @method findElementInParentElement - @param {DOMElement} parentElement The parent's DOM element - @return {DOMElement} The discovered element - */ - findElementInParentElement: function(parentElem) { - var id = "#" + this.elementId; - return jQuery(id)[0] || jQuery(id, parentElem)[0]; - }, - - /** - Creates a DOM representation of the view and all of its - child views by recursively calling the `render()` method. - - After the element has been created, `didInsertElement` will - be called on this view and all of its child views. - - @method createElement - @return {Ember.View} receiver - */ - createElement: function() { - if (get(this, 'element')) { return this; } - - var buffer = this.renderToBuffer(); - set(this, 'element', buffer.element()); - - return this; - }, - - /** - Called when a view is going to insert an element into the DOM. - - @event willInsertElement - */ - willInsertElement: Ember.K, - - /** - Called when the element of the view has been inserted into the DOM - or after the view was re-rendered. Override this function to do any - set up that requires an element in the document body. - - @event didInsertElement - */ - didInsertElement: Ember.K, - - /** - Called when the view is about to rerender, but before anything has - been torn down. This is a good opportunity to tear down any manual - observers you have installed based on the DOM state - - @event willClearRender - */ - willClearRender: Ember.K, - - /** - Run this callback on the current view (unless includeSelf is false) and recursively on child views. - - @method invokeRecursively - @param fn {Function} - @param includeSelf {Boolean} Includes itself if true. - @private - */ - invokeRecursively: function(fn, includeSelf) { - var childViews = (includeSelf === false) ? this._childViews : [this]; - var currentViews, view, currentChildViews; - - while (childViews.length) { - currentViews = childViews.slice(); - childViews = []; - - for (var i=0, l=currentViews.length; i` tag for views. - - @property tagName - @type String - @default null - */ - - // We leave this null by default so we can tell the difference between - // the default case and a user-specified tag. - tagName: null, - - /** - The WAI-ARIA role of the control represented by this view. For example, a - button may have a role of type 'button', or a pane may have a role of - type 'alertdialog'. This property is used by assistive software to help - visually challenged users navigate rich web applications. - - The full list of valid WAI-ARIA roles is available at: - [http://www.w3.org/TR/wai-aria/roles#roles_categorization](http://www.w3.org/TR/wai-aria/roles#roles_categorization) - - @property ariaRole - @type String - @default null - */ - ariaRole: null, - - /** - Standard CSS class names to apply to the view's outer element. This - property automatically inherits any class names defined by the view's - superclasses as well. - - @property classNames - @type Array - @default ['ember-view'] - */ - classNames: ['ember-view'], - - /** - A list of properties of the view to apply as class names. If the property - is a string value, the value of that string will be applied as a class - name. - - ```javascript - // Applies the 'high' class to the view element - Ember.View.extend({ - classNameBindings: ['priority'] - priority: 'high' - }); - ``` - - If the value of the property is a Boolean, the name of that property is - added as a dasherized class name. - - ```javascript - // Applies the 'is-urgent' class to the view element - Ember.View.extend({ - classNameBindings: ['isUrgent'] - isUrgent: true - }); - ``` - - If you would prefer to use a custom value instead of the dasherized - property name, you can pass a binding like this: - - ```javascript - // Applies the 'urgent' class to the view element - Ember.View.extend({ - classNameBindings: ['isUrgent:urgent'] - isUrgent: true - }); - ``` - - This list of properties is inherited from the view's superclasses as well. - - @property classNameBindings - @type Array - @default [] - */ - classNameBindings: EMPTY_ARRAY, - - /** - A list of properties of the view to apply as attributes. If the property is - a string value, the value of that string will be applied as the attribute. - - ```javascript - // Applies the type attribute to the element - // with the value "button", like
- Ember.View.extend({ - attributeBindings: ['type'], - type: 'button' - }); - ``` - - If the value of the property is a Boolean, the name of that property is - added as an attribute. - - ```javascript - // Renders something like
- Ember.View.extend({ - attributeBindings: ['enabled'], - enabled: true - }); - ``` - - @property attributeBindings - */ - attributeBindings: EMPTY_ARRAY, - - // ....................................................... - // CORE DISPLAY METHODS - // - - /** - Setup a view, but do not finish waking it up. - - * configure `childViews` - * register the view with the global views hash, which is used for event - dispatch - - @method init - @private - */ - init: function() { - this.elementId = this.elementId || guidFor(this); - - this._super(); - - // setup child views. be sure to clone the child views array first - this._childViews = this._childViews.slice(); - - Ember.assert("Only arrays are allowed for 'classNameBindings'", typeOf(this.classNameBindings) === 'array'); - this.classNameBindings = A(this.classNameBindings.slice()); - - Ember.assert("Only arrays are allowed for 'classNames'", typeOf(this.classNames) === 'array'); - this.classNames = A(this.classNames.slice()); - }, - - appendChild: function(view, options) { - return this.currentState.appendChild(this, view, options); - }, - - /** - Removes the child view from the parent view. - - @method removeChild - @param {Ember.View} view - @return {Ember.View} receiver - */ - removeChild: function(view) { - // If we're destroying, the entire subtree will be - // freed, and the DOM will be handled separately, - // so no need to mess with childViews. - if (this.isDestroying) { return; } - - // update parent node - set(view, '_parentView', null); - - // remove view from childViews array. - var childViews = this._childViews; - - a_removeObject(childViews, view); - - this.propertyDidChange('childViews'); // HUH?! what happened to will change? - - return this; - }, - - /** - Removes all children from the `parentView`. - - @method removeAllChildren - @return {Ember.View} receiver - */ - removeAllChildren: function() { - return this.mutateChildViews(function(parentView, view) { - parentView.removeChild(view); - }); - }, - - destroyAllChildren: function() { - return this.mutateChildViews(function(parentView, view) { - view.destroy(); - }); - }, - - /** - Removes the view from its `parentView`, if one is found. Otherwise - does nothing. - - @method removeFromParent - @return {Ember.View} receiver - */ - removeFromParent: function() { - var parent = this._parentView; - - // Remove DOM element from parent - this.remove(); - - if (parent) { parent.removeChild(this); } - return this; - }, - - /** - You must call `destroy` on a view to destroy the view (and all of its - child views). This will remove the view from any parent node, then make - sure that the DOM element managed by the view can be released by the - memory manager. - - @method destroy - */ - destroy: function() { - var childViews = this._childViews, - // get parentView before calling super because it'll be destroyed - nonVirtualParentView = get(this, 'parentView'), - viewName = this.viewName, - childLen, i; - - if (!this._super()) { return; } - - childLen = childViews.length; - for (i=childLen-1; i>=0; i--) { - childViews[i].removedFromDOM = true; - } - - // remove from non-virtual parent view if viewName was specified - if (viewName && nonVirtualParentView) { - nonVirtualParentView.set(viewName, null); - } - - childLen = childViews.length; - for (i=childLen-1; i>=0; i--) { - childViews[i].destroy(); - } - - return this; - }, - - /** - Instantiates a view to be added to the childViews array during view - initialization. You generally will not call this method directly unless - you are overriding `createChildViews()`. Note that this method will - automatically configure the correct settings on the new view instance to - act as a child of the parent. - - @method createChildView - @param {Class|String} viewClass - @param {Hash} [attrs] Attributes to add - @return {Ember.View} new instance - */ - createChildView: function(view, attrs) { - if (!view) { - throw new TypeError("createChildViews first argument must exist"); - } - - if (view.isView && view._parentView === this && view.container === this.container) { - return view; - } - - attrs = attrs || {}; - attrs._parentView = this; - - if (CoreView.detect(view)) { - attrs.templateData = attrs.templateData || get(this, 'templateData'); - - attrs.container = this.container; - view = view.create(attrs); - - // don't set the property on a virtual view, as they are invisible to - // consumers of the view API - if (view.viewName) { - set(get(this, 'concreteView'), view.viewName, view); - } - } else if ('string' === typeof view) { - var fullName = 'view:' + view; - var ViewKlass = this.container.lookupFactory(fullName); - - Ember.assert("Could not find view: '" + fullName + "'", !!ViewKlass); - - attrs.templateData = get(this, 'templateData'); - view = ViewKlass.create(attrs); - } else { - Ember.assert('You must pass instance or subclass of View', view.isView); - attrs.container = this.container; - - if (!get(view, 'templateData')) { - attrs.templateData = get(this, 'templateData'); - } - - setProperties(view, attrs); - - } - - return view; - }, - - becameVisible: Ember.K, - becameHidden: Ember.K, - - /** - When the view's `isVisible` property changes, toggle the visibility - element of the actual DOM element. - - @method _isVisibleDidChange - @private - */ - _isVisibleDidChange: observer('isVisible', function() { - if (this._isVisible === get(this, 'isVisible')) { return ; } - run.scheduleOnce('render', this, this._toggleVisibility); - }), - - _toggleVisibility: function() { - var $el = this.$(); - if (!$el) { return; } - - var isVisible = get(this, 'isVisible'); - - if (this._isVisible === isVisible) { return ; } - - $el.toggle(isVisible); - - this._isVisible = isVisible; - - if (this._isAncestorHidden()) { return; } - - if (isVisible) { - this._notifyBecameVisible(); - } else { - this._notifyBecameHidden(); - } - }, - - _notifyBecameVisible: function() { - this.trigger('becameVisible'); - - this.forEachChildView(function(view) { - var isVisible = get(view, 'isVisible'); - - if (isVisible || isVisible === null) { - view._notifyBecameVisible(); - } - }); - }, - - _notifyBecameHidden: function() { - this.trigger('becameHidden'); - this.forEachChildView(function(view) { - var isVisible = get(view, 'isVisible'); - - if (isVisible || isVisible === null) { - view._notifyBecameHidden(); - } - }); - }, - - _isAncestorHidden: function() { - var parent = get(this, 'parentView'); - - while (parent) { - if (get(parent, 'isVisible') === false) { return true; } - - parent = get(parent, 'parentView'); - } - - return false; - }, - - clearBuffer: function() { - this.invokeRecursively(nullViewsBuffer); - }, - - transitionTo: function(state, children) { - var priorState = this.currentState, - currentState = this.currentState = this.states[state]; - this.state = state; - - if (priorState && priorState.exit) { priorState.exit(this); } - if (currentState.enter) { currentState.enter(this); } - if (state === 'inDOM') { meta(this).cache.element = undefined; } - - if (children !== false) { - this.forEachChildView(function(view) { - view.transitionTo(state); - }); - } - }, - - // ....................................................... - // EVENT HANDLING - // - - /** - Handle events from `Ember.EventDispatcher` - - @method handleEvent - @param eventName {String} - @param evt {Event} - @private - */ - handleEvent: function(eventName, evt) { - return this.currentState.handleEvent(this, eventName, evt); - }, - - registerObserver: function(root, path, target, observer) { - if (!observer && 'function' === typeof target) { - observer = target; - target = null; - } - - if (!root || typeof root !== 'object') { - return; - } - - var view = this, - stateCheckedObserver = function() { - view.currentState.invokeObserver(this, observer); - }, - scheduledObserver = function() { - run.scheduleOnce('render', this, stateCheckedObserver); - }; - - addObserver(root, path, target, scheduledObserver); - - this.one('willClearRender', function() { - removeObserver(root, path, target, scheduledObserver); - }); - } - - }); - - /* - Describe how the specified actions should behave in the various - states that a view can exist in. Possible states: - - * preRender: when a view is first instantiated, and after its - element was destroyed, it is in the preRender state - * inBuffer: once a view has been rendered, but before it has - been inserted into the DOM, it is in the inBuffer state - * hasElement: the DOM representation of the view is created, - and is ready to be inserted - * inDOM: once a view has been inserted into the DOM it is in - the inDOM state. A view spends the vast majority of its - existence in this state. - * destroyed: once a view has been destroyed (using the destroy - method), it is in this state. No further actions can be invoked - on a destroyed view. - */ - - // in the destroyed state, everything is illegal - - // before rendering has begun, all legal manipulations are noops. - - // inside the buffer, legal manipulations are done on the buffer - - // once the view has been inserted into the DOM, legal manipulations - // are done on the DOM element. - - function notifyMutationListeners() { - run.once(View, 'notifyMutationListeners'); - } - - var DOMManager = { - prepend: function(view, html) { - view.$().prepend(html); - notifyMutationListeners(); - }, - - after: function(view, html) { - view.$().after(html); - notifyMutationListeners(); - }, - - html: function(view, html) { - view.$().html(html); - notifyMutationListeners(); - }, - - replace: function(view) { - var element = get(view, 'element'); - - set(view, 'element', null); - - view._insertElementLater(function() { - jQuery(element).replaceWith(get(view, 'element')); - notifyMutationListeners(); - }); - }, - - remove: function(view) { - view.$().remove(); - notifyMutationListeners(); - }, - - empty: function(view) { - view.$().empty(); - notifyMutationListeners(); - } - }; - - View.reopen({ - domManager: DOMManager - }); - - View.reopenClass({ - - /** - Parse a path and return an object which holds the parsed properties. - - For example a path like "content.isEnabled:enabled:disabled" will return the - following object: - - ```javascript - { - path: "content.isEnabled", - className: "enabled", - falsyClassName: "disabled", - classNames: ":enabled:disabled" - } - ``` - - @method _parsePropertyPath - @static - @private - */ - _parsePropertyPath: function(path) { - var split = path.split(':'), - propertyPath = split[0], - classNames = "", - className, - falsyClassName; - - // check if the property is defined as prop:class or prop:trueClass:falseClass - if (split.length > 1) { - className = split[1]; - if (split.length === 3) { falsyClassName = split[2]; } - - classNames = ':' + className; - if (falsyClassName) { classNames += ":" + falsyClassName; } - } - - return { - path: propertyPath, - classNames: classNames, - className: (className === '') ? undefined : className, - falsyClassName: falsyClassName - }; - }, - - /** - Get the class name for a given value, based on the path, optional - `className` and optional `falsyClassName`. - - - if a `className` or `falsyClassName` has been specified: - - if the value is truthy and `className` has been specified, - `className` is returned - - if the value is falsy and `falsyClassName` has been specified, - `falsyClassName` is returned - - otherwise `null` is returned - - if the value is `true`, the dasherized last part of the supplied path - is returned - - if the value is not `false`, `undefined` or `null`, the `value` - is returned - - if none of the above rules apply, `null` is returned - - @method _classStringForValue - @param path - @param val - @param className - @param falsyClassName - @static - @private - */ - _classStringForValue: function(path, val, className, falsyClassName) { - if(isArray(val)) { - val = get(val, 'length') !== 0; - } - - // When using the colon syntax, evaluate the truthiness or falsiness - // of the value to determine which className to return - if (className || falsyClassName) { - if (className && !!val) { - return className; - - } else if (falsyClassName && !val) { - return falsyClassName; - - } else { - return null; - } - - // If value is a Boolean and true, return the dasherized property - // name. - } else if (val === true) { - // Normalize property path to be suitable for use - // as a class name. For exaple, content.foo.barBaz - // becomes bar-baz. - var parts = path.split('.'); - return dasherize(parts[parts.length-1]); - - // If the value is not false, undefined, or null, return the current - // value of the property. - } else if (val !== false && val != null) { - return val; - - // Nothing to display. Return null so that the old class is removed - // but no new class is added. - } else { - return null; - } - } - }); - - var mutation = EmberObject.extend(Evented).create(); - - View.addMutationListener = function(callback) { - mutation.on('change', callback); - }; - - View.removeMutationListener = function(callback) { - mutation.off('change', callback); - }; - - View.notifyMutationListeners = function() { - mutation.trigger('change'); - }; - - /** - Global views hash - - @property views - @static - @type Hash - */ - View.views = {}; - - // If someone overrides the child views computed property when - // defining their class, we want to be able to process the user's - // supplied childViews and then restore the original computed property - // at view initialization time. This happens in Ember.ContainerView's init - // method. - View.childViewsProperty = childViewsProperty; - - View.applyAttributeBindings = function(elem, name, value) { - var type = typeOf(value); - - // if this changes, also change the logic in ember-handlebars/lib/helpers/binding.js - if (name !== 'value' && (type === 'string' || (type === 'number' && !isNaN(value)))) { - if (value !== elem.attr(name)) { - elem.attr(name, value); - } - } else if (name === 'value' || type === 'boolean') { - if (isNone(value) || value === false) { - // `null`, `undefined` or `false` should remove attribute - elem.removeAttr(name); - elem.prop(name, ''); - } else if (value !== elem.prop(name)) { - // value should always be properties - elem.prop(name, value); - } - } else if (!value) { - elem.removeAttr(name); - } - }; - - __exports__.CoreView = CoreView; - __exports__.View = View; - __exports__.ViewCollection = ViewCollection; - }); -})(); - -(function() { -define("metamorph", - [], - function() { - "use strict"; - // ========================================================================== - // Project: metamorph - // Copyright: ©2014 Tilde, Inc. All rights reserved. - // ========================================================================== - - var K = function() {}, - guid = 0, - disableRange = (function(){ - if ('undefined' !== typeof MetamorphENV) { - return MetamorphENV.DISABLE_RANGE_API; - } else if ('undefined' !== ENV) { - return ENV.DISABLE_RANGE_API; - } else { - return false; - } - })(), - - // Feature-detect the W3C range API, the extended check is for IE9 which only partially supports ranges - supportsRange = (!disableRange) && typeof document !== 'undefined' && ('createRange' in document) && (typeof Range !== 'undefined') && Range.prototype.createContextualFragment, - - // Internet Explorer prior to 9 does not allow setting innerHTML if the first element - // is a "zero-scope" element. This problem can be worked around by making - // the first node an invisible text node. We, like Modernizr, use ­ - needsShy = typeof document !== 'undefined' && (function() { - var testEl = document.createElement('div'); - testEl.innerHTML = "
"; - testEl.firstChild.innerHTML = ""; - return testEl.firstChild.innerHTML === ''; - })(), - - - // IE 8 (and likely earlier) likes to move whitespace preceeding - // a script tag to appear after it. This means that we can - // accidentally remove whitespace when updating a morph. - movesWhitespace = document && (function() { - var testEl = document.createElement('div'); - testEl.innerHTML = "Test: Value"; - return testEl.childNodes[0].nodeValue === 'Test:' && - testEl.childNodes[2].nodeValue === ' Value'; - })(); - - // Constructor that supports either Metamorph('foo') or new - // Metamorph('foo'); - // - // Takes a string of HTML as the argument. - - var Metamorph = function(html) { - var self; - - if (this instanceof Metamorph) { - self = this; - } else { - self = new K(); - } - - self.innerHTML = html; - var myGuid = 'metamorph-'+(guid++); - self.start = myGuid + '-start'; - self.end = myGuid + '-end'; - - return self; - }; - - K.prototype = Metamorph.prototype; - - var rangeFor, htmlFunc, removeFunc, outerHTMLFunc, appendToFunc, afterFunc, prependFunc, startTagFunc, endTagFunc; - - outerHTMLFunc = function() { - return this.startTag() + this.innerHTML + this.endTag(); - }; - - startTagFunc = function() { - /* - * We replace chevron by its hex code in order to prevent escaping problems. - * Check this thread for more explaination: - * http://stackoverflow.com/questions/8231048/why-use-x3c-instead-of-when-generating-html-from-javascript - */ - return "hi"; - * div.firstChild.firstChild.tagName //=> "" - * - * If our script markers are inside such a node, we need to find that - * node and use *it* as the marker. - */ - var realNode = function(start) { - while (start.parentNode.tagName === "") { - start = start.parentNode; - } - - return start; - }; - - /* - * When automatically adding a tbody, Internet Explorer inserts the - * tbody immediately before the first . Other browsers create it - * before the first node, no matter what. - * - * This means the the following code: - * - * div = document.createElement("div"); - * div.innerHTML = "
hi
- * - * Generates the following DOM in IE: - * - * + div - * + table - * - script id='first' - * + tbody - * + tr - * + td - * - "hi" - * - script id='last' - * - * Which means that the two script tags, even though they were - * inserted at the same point in the hierarchy in the original - * HTML, now have different parents. - * - * This code reparents the first script tag by making it the tbody's - * first child. - * - */ - var fixParentage = function(start, end) { - if (start.parentNode !== end.parentNode) { - end.parentNode.insertBefore(start, end.parentNode.firstChild); - } - }; - - htmlFunc = function(html, outerToo) { - // get the real starting node. see realNode for details. - var start = realNode(document.getElementById(this.start)); - var end = document.getElementById(this.end); - var parentNode = end.parentNode; - var node, nextSibling, last; - - // make sure that the start and end nodes share the same - // parent. If not, fix it. - fixParentage(start, end); - - // remove all of the nodes after the starting placeholder and - // before the ending placeholder. - node = start.nextSibling; - while (node) { - nextSibling = node.nextSibling; - last = node === end; - - // if this is the last node, and we want to remove it as well, - // set the `end` node to the next sibling. This is because - // for the rest of the function, we insert the new nodes - // before the end (note that insertBefore(node, null) is - // the same as appendChild(node)). - // - // if we do not want to remove it, just break. - if (last) { - if (outerToo) { end = node.nextSibling; } else { break; } - } - - node.parentNode.removeChild(node); - - // if this is the last node and we didn't break before - // (because we wanted to remove the outer nodes), break - // now. - if (last) { break; } - - node = nextSibling; - } - - // get the first node for the HTML string, even in cases like - // tables and lists where a simple innerHTML on a div would - // swallow some of the content. - node = firstNodeFor(start.parentNode, html); - - if (outerToo) { - start.parentNode.removeChild(start); - } - - // copy the nodes for the HTML between the starting and ending - // placeholder. - while (node) { - nextSibling = node.nextSibling; - parentNode.insertBefore(node, end); - node = nextSibling; - } - }; - - // remove the nodes in the DOM representing this metamorph. - // - // this includes the starting and ending placeholders. - removeFunc = function() { - var start = realNode(document.getElementById(this.start)); - var end = document.getElementById(this.end); - - this.html(''); - start.parentNode.removeChild(start); - end.parentNode.removeChild(end); - }; - - appendToFunc = function(parentNode) { - var node = firstNodeFor(parentNode, this.outerHTML()); - var nextSibling; - - while (node) { - nextSibling = node.nextSibling; - parentNode.appendChild(node); - node = nextSibling; - } - }; - - afterFunc = function(html) { - // get the real starting node. see realNode for details. - var end = document.getElementById(this.end); - var insertBefore = end.nextSibling; - var parentNode = end.parentNode; - var nextSibling; - var node; - - // get the first node for the HTML string, even in cases like - // tables and lists where a simple innerHTML on a div would - // swallow some of the content. - node = firstNodeFor(parentNode, html); - - // copy the nodes for the HTML between the starting and ending - // placeholder. - while (node) { - nextSibling = node.nextSibling; - parentNode.insertBefore(node, insertBefore); - node = nextSibling; - } - }; - - prependFunc = function(html) { - var start = document.getElementById(this.start); - var parentNode = start.parentNode; - var nextSibling; - var node; - - node = firstNodeFor(parentNode, html); - var insertBefore = start.nextSibling; - - while (node) { - nextSibling = node.nextSibling; - parentNode.insertBefore(node, insertBefore); - node = nextSibling; - } - }; - } - - Metamorph.prototype.html = function(html) { - this.checkRemoved(); - if (html === undefined) { return this.innerHTML; } - - htmlFunc.call(this, html); - - this.innerHTML = html; - }; - - Metamorph.prototype.replaceWith = function(html) { - this.checkRemoved(); - htmlFunc.call(this, html, true); - }; - - Metamorph.prototype.remove = removeFunc; - Metamorph.prototype.outerHTML = outerHTMLFunc; - Metamorph.prototype.appendTo = appendToFunc; - Metamorph.prototype.after = afterFunc; - Metamorph.prototype.prepend = prependFunc; - Metamorph.prototype.startTag = startTagFunc; - Metamorph.prototype.endTag = endTagFunc; - - Metamorph.prototype.isRemoved = function() { - var before = document.getElementById(this.start); - var after = document.getElementById(this.end); - - return !before || !after; - }; - - Metamorph.prototype.checkRemoved = function() { - if (this.isRemoved()) { - throw new Error("Cannot perform operations on a Metamorph that is not in the DOM."); - } - }; - - return Metamorph; - }); - -})(); - -(function() { -define("ember-handlebars-compiler", - ["ember-metal/core","exports"], - function(__dependency1__, __exports__) { - "use strict"; - /** - @module ember - @submodule ember-handlebars-compiler - */ - - var Ember = __dependency1__["default"]; - - // ES6Todo: you'll need to import debugger once debugger is es6'd. - if (typeof Ember.assert === 'undefined') { Ember.assert = function(){}; }; - if (typeof Ember.FEATURES === 'undefined') { Ember.FEATURES = { isEnabled: function(){} }; }; - - var objectCreate = Object.create || function(parent) { - function F() {} - F.prototype = parent; - return new F(); - }; - - // set up for circular references later - var View, Component; - - // ES6Todo: when ember-debug is es6'ed import this. - // var emberAssert = Ember.assert; - var Handlebars = (Ember.imports && Ember.imports.Handlebars) || (this && this.Handlebars); - if (!Handlebars && typeof require === 'function') { - Handlebars = require('handlebars'); - } - - Ember.assert("Ember Handlebars requires Handlebars version 1.0 or 1.1. Include " + - "a SCRIPT tag in the HTML HEAD linking to the Handlebars file " + - "before you link to Ember.", Handlebars); - - Ember.assert("Ember Handlebars requires Handlebars version 1.0 or 1.1, " + - "COMPILER_REVISION expected: 4, got: " + Handlebars.COMPILER_REVISION + - " - Please note: Builds of master may have other COMPILER_REVISION values.", - Handlebars.COMPILER_REVISION === 4); - - /** - Prepares the Handlebars templating library for use inside Ember's view - system. - - The `Ember.Handlebars` object is the standard Handlebars library, extended to - use Ember's `get()` method instead of direct property access, which allows - computed properties to be used inside templates. - - To create an `Ember.Handlebars` template, call `Ember.Handlebars.compile()`. - This will return a function that can be used by `Ember.View` for rendering. - - @class Handlebars - @namespace Ember - */ - var EmberHandlebars = Ember.Handlebars = objectCreate(Handlebars); - - /** - Register a bound helper or custom view helper. - - ## Simple bound helper example - - ```javascript - Ember.Handlebars.helper('capitalize', function(value) { - return value.toUpperCase(); - }); - ``` - - The above bound helper can be used inside of templates as follows: - - ```handlebars - {{capitalize name}} - ``` - - In this case, when the `name` property of the template's context changes, - the rendered value of the helper will update to reflect this change. - - For more examples of bound helpers, see documentation for - `Ember.Handlebars.registerBoundHelper`. - - ## Custom view helper example - - Assuming a view subclass named `App.CalendarView` were defined, a helper - for rendering instances of this view could be registered as follows: - - ```javascript - Ember.Handlebars.helper('calendar', App.CalendarView): - ``` - - The above bound helper can be used inside of templates as follows: - - ```handlebars - {{calendar}} - ``` - - Which is functionally equivalent to: - - ```handlebars - {{view App.CalendarView}} - ``` - - Options in the helper will be passed to the view in exactly the same - manner as with the `view` helper. - - @method helper - @for Ember.Handlebars - @param {String} name - @param {Function|Ember.View} function or view class constructor - @param {String} dependentKeys* - */ - EmberHandlebars.helper = function(name, value) { - if (!View) { View = requireModule('ember-views/views/view')['View']; } // ES6TODO: stupid circular dep - if (!Component) { Component = requireModule('ember-views/views/component')['default']; } // ES6TODO: stupid circular dep - - Ember.assert("You tried to register a component named '" + name + "', but component names must include a '-'", !Component.detect(value) || name.match(/-/)); - - if (View.detect(value)) { - EmberHandlebars.registerHelper(name, EmberHandlebars.makeViewHelper(value)); - } else { - EmberHandlebars.registerBoundHelper.apply(null, arguments); - } - }; - - /** - Returns a helper function that renders the provided ViewClass. - - Used internally by Ember.Handlebars.helper and other methods - involving helper/component registration. - - @private - @method makeViewHelper - @for Ember.Handlebars - @param {Function} ViewClass view class constructor - @since 1.2.0 - */ - EmberHandlebars.makeViewHelper = function(ViewClass) { - return function(options) { - Ember.assert("You can only pass attributes (such as name=value) not bare values to a helper for a View found in '" + ViewClass.toString() + "'", arguments.length < 2); - return EmberHandlebars.helpers.view.call(this, ViewClass, options); - }; - }; - - /** - @class helpers - @namespace Ember.Handlebars - */ - EmberHandlebars.helpers = objectCreate(Handlebars.helpers); - - /** - Override the the opcode compiler and JavaScript compiler for Handlebars. - - @class Compiler - @namespace Ember.Handlebars - @private - @constructor - */ - EmberHandlebars.Compiler = function() {}; - - // Handlebars.Compiler doesn't exist in runtime-only - if (Handlebars.Compiler) { - EmberHandlebars.Compiler.prototype = objectCreate(Handlebars.Compiler.prototype); - } - - EmberHandlebars.Compiler.prototype.compiler = EmberHandlebars.Compiler; - - /** - @class JavaScriptCompiler - @namespace Ember.Handlebars - @private - @constructor - */ - EmberHandlebars.JavaScriptCompiler = function() {}; - - // Handlebars.JavaScriptCompiler doesn't exist in runtime-only - if (Handlebars.JavaScriptCompiler) { - EmberHandlebars.JavaScriptCompiler.prototype = objectCreate(Handlebars.JavaScriptCompiler.prototype); - EmberHandlebars.JavaScriptCompiler.prototype.compiler = EmberHandlebars.JavaScriptCompiler; - } - - - EmberHandlebars.JavaScriptCompiler.prototype.namespace = "Ember.Handlebars"; - - EmberHandlebars.JavaScriptCompiler.prototype.initializeBuffer = function() { - return "''"; - }; - - /** - Override the default buffer for Ember Handlebars. By default, Handlebars - creates an empty String at the beginning of each invocation and appends to - it. Ember's Handlebars overrides this to append to a single shared buffer. - - @private - @method appendToBuffer - @param string {String} - */ - EmberHandlebars.JavaScriptCompiler.prototype.appendToBuffer = function(string) { - return "data.buffer.push("+string+");"; - }; - - // Hacks ahead: - // Handlebars presently has a bug where the `blockHelperMissing` hook - // doesn't get passed the name of the missing helper name, but rather - // gets passed the value of that missing helper evaluated on the current - // context, which is most likely `undefined` and totally useless. - // - // So we alter the compiled template function to pass the name of the helper - // instead, as expected. - // - // This can go away once the following is closed: - // https://github.com/wycats/handlebars.js/issues/634 - - var DOT_LOOKUP_REGEX = /helpers\.(.*?)\)/, - BRACKET_STRING_LOOKUP_REGEX = /helpers\['(.*?)'/, - INVOCATION_SPLITTING_REGEX = /(.*blockHelperMissing\.call\(.*)(stack[0-9]+)(,.*)/; - - EmberHandlebars.JavaScriptCompiler.stringifyLastBlockHelperMissingInvocation = function(source) { - var helperInvocation = source[source.length - 1], - helperName = (DOT_LOOKUP_REGEX.exec(helperInvocation) || BRACKET_STRING_LOOKUP_REGEX.exec(helperInvocation))[1], - matches = INVOCATION_SPLITTING_REGEX.exec(helperInvocation); - - source[source.length - 1] = matches[1] + "'" + helperName + "'" + matches[3]; - }; - - var stringifyBlockHelperMissing = EmberHandlebars.JavaScriptCompiler.stringifyLastBlockHelperMissingInvocation; - - var originalBlockValue = EmberHandlebars.JavaScriptCompiler.prototype.blockValue; - EmberHandlebars.JavaScriptCompiler.prototype.blockValue = function() { - originalBlockValue.apply(this, arguments); - stringifyBlockHelperMissing(this.source); - }; - - var originalAmbiguousBlockValue = EmberHandlebars.JavaScriptCompiler.prototype.ambiguousBlockValue; - EmberHandlebars.JavaScriptCompiler.prototype.ambiguousBlockValue = function() { - originalAmbiguousBlockValue.apply(this, arguments); - stringifyBlockHelperMissing(this.source); - }; - - /** - Rewrite simple mustaches from `{{foo}}` to `{{bind "foo"}}`. This means that - all simple mustaches in Ember's Handlebars will also set up an observer to - keep the DOM up to date when the underlying property changes. - - @private - @method mustache - @for Ember.Handlebars.Compiler - @param mustache - */ - EmberHandlebars.Compiler.prototype.mustache = function(mustache) { - if (!(mustache.params.length || mustache.hash)) { - var id = new Handlebars.AST.IdNode([{ part: '_triageMustache' }]); - - // Update the mustache node to include a hash value indicating whether the original node - // was escaped. This will allow us to properly escape values when the underlying value - // changes and we need to re-render the value. - if (!mustache.escaped) { - mustache.hash = mustache.hash || new Handlebars.AST.HashNode([]); - mustache.hash.pairs.push(["unescaped", new Handlebars.AST.StringNode("true")]); - } - mustache = new Handlebars.AST.MustacheNode([id].concat([mustache.id]), mustache.hash, !mustache.escaped); - } - - return Handlebars.Compiler.prototype.mustache.call(this, mustache); - }; - - /** - Used for precompilation of Ember Handlebars templates. This will not be used - during normal app execution. - - @method precompile - @for Ember.Handlebars - @static - @param {String} string The template to precompile - @param {Boolean} asObject optional parameter, defaulting to true, of whether or not the - compiled template should be returned as an Object or a String - */ - EmberHandlebars.precompile = function(string, asObject) { - var ast = Handlebars.parse(string); - - var options = { - knownHelpers: { - action: true, - unbound: true, - 'bind-attr': true, - template: true, - view: true, - _triageMustache: true - }, - data: true, - stringParams: true - }; - - asObject = asObject === undefined ? true : asObject; - - var environment = new EmberHandlebars.Compiler().compile(ast, options); - return new EmberHandlebars.JavaScriptCompiler().compile(environment, options, undefined, asObject); - }; - - // We don't support this for Handlebars runtime-only - if (Handlebars.compile) { - /** - The entry point for Ember Handlebars. This replaces the default - `Handlebars.compile` and turns on template-local data and String - parameters. - - @method compile - @for Ember.Handlebars - @static - @param {String} string The template to compile - @return {Function} - */ - EmberHandlebars.compile = function(string) { - var ast = Handlebars.parse(string); - var options = { data: true, stringParams: true }; - var environment = new EmberHandlebars.Compiler().compile(ast, options); - var templateSpec = new EmberHandlebars.JavaScriptCompiler().compile(environment, options, undefined, true); - - var template = EmberHandlebars.template(templateSpec); - template.isMethod = false; //Make sure we don't wrap templates with ._super - - return template; - }; - } - - __exports__["default"] = EmberHandlebars; - }); -})(); - -(function() { -define("ember-handlebars/component_lookup", - ["ember-runtime/system/object","exports"], - function(__dependency1__, __exports__) { - "use strict"; - var EmberObject = __dependency1__["default"]; - - var ComponentLookup = EmberObject.extend({ - lookupFactory: function(name, container) { - - container = container || this.container; - - var fullName = 'component:' + name, - templateFullName = 'template:components/' + name, - templateRegistered = container && container.has(templateFullName); - - if (templateRegistered) { - container.injection(fullName, 'layout', templateFullName); - } - - var Component = container.lookupFactory(fullName); - - // Only treat as a component if either the component - // or a template has been registered. - if (templateRegistered || Component) { - if (!Component) { - container.register(fullName, Ember.Component); - Component = container.lookupFactory(fullName); - } - return Component; - } - } - }); - - __exports__["default"] = ComponentLookup; - }); -define("ember-handlebars/controls", - ["ember-handlebars/controls/checkbox","ember-handlebars/controls/text_field","ember-handlebars/controls/text_area","ember-metal/core","ember-handlebars-compiler","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) { - "use strict"; - var Checkbox = __dependency1__["default"]; - var TextField = __dependency2__["default"]; - var TextArea = __dependency3__["default"]; - - var Ember = __dependency4__["default"]; - // Ember.assert - // var emberAssert = Ember.assert; - - var EmberHandlebars = __dependency5__["default"]; - var helpers = EmberHandlebars.helpers; - /** - @module ember - @submodule ember-handlebars-compiler - */ - - /** - - The `{{input}}` helper inserts an HTML `` tag into the template, - with a `type` value of either `text` or `checkbox`. If no `type` is provided, - `text` will be the default value applied. The attributes of `{{input}}` - match those of the native HTML tag as closely as possible for these two types. - - ## Use as text field - An `{{input}}` with no `type` or a `type` of `text` will render an HTML text input. - The following HTML attributes can be set via the helper: - - - - - - - - - - - - -
`readonly``required``autofocus`
`value``placeholder``disabled`
`size``tabindex``maxlength`
`name``min``max`
`pattern``accept``autocomplete`
`autosave``formaction``formenctype`
`formmethod``formnovalidate``formtarget`
`height``inputmode``multiple`
`step``width``form`
`selectionDirection``spellcheck` 
- - - When set to a quoted string, these values will be directly applied to the HTML - element. When left unquoted, these values will be bound to a property on the - template's current rendering context (most typically a controller instance). - - ## Unbound: - - ```handlebars - {{input value="http://www.facebook.com"}} - ``` - - - ```html - - ``` - - ## Bound: - - ```javascript - App.ApplicationController = Ember.Controller.extend({ - firstName: "Stanley", - entryNotAllowed: true - }); - ``` - - - ```handlebars - {{input type="text" value=firstName disabled=entryNotAllowed size="50"}} - ``` - - - ```html - - ``` - - ## Extension - - Internally, `{{input type="text"}}` creates an instance of `Ember.TextField`, passing - arguments from the helper to `Ember.TextField`'s `create` method. You can extend the - capabilities of text inputs in your applications by reopening this class. For example, - if you are building a Bootstrap project where `data-*` attributes are used, you - can add one to the `TextField`'s `attributeBindings` property: - - - ```javascript - Ember.TextField.reopen({ - attributeBindings: ['data-error'] - }); - ``` - - Keep in mind when writing `Ember.TextField` subclasses that `Ember.TextField` - itself extends `Ember.Component`, meaning that it does NOT inherit - the `controller` of the parent view. - - See more about [Ember components](api/classes/Ember.Component.html) - - - ## Use as checkbox - - An `{{input}}` with a `type` of `checkbox` will render an HTML checkbox input. - The following HTML attributes can be set via the helper: - - * `checked` - * `disabled` - * `tabindex` - * `indeterminate` - * `name` - * `autofocus` - * `form` - - - When set to a quoted string, these values will be directly applied to the HTML - element. When left unquoted, these values will be bound to a property on the - template's current rendering context (most typically a controller instance). - - ## Unbound: - - ```handlebars - {{input type="checkbox" name="isAdmin"}} - ``` - - ```html - - ``` - - ## Bound: - - ```javascript - App.ApplicationController = Ember.Controller.extend({ - isAdmin: true - }); - ``` - - - ```handlebars - {{input type="checkbox" checked=isAdmin }} - ``` - - - ```html - - ``` - - ## Extension - - Internally, `{{input type="checkbox"}}` creates an instance of `Ember.Checkbox`, passing - arguments from the helper to `Ember.Checkbox`'s `create` method. You can extend the - capablilties of checkbox inputs in your applications by reopening this class. For example, - if you wanted to add a css class to all checkboxes in your application: - - - ```javascript - Ember.Checkbox.reopen({ - classNames: ['my-app-checkbox'] - }); - ``` - - - @method input - @for Ember.Handlebars.helpers - @param {Hash} options - */ - function inputHelper(options) { - Ember.assert('You can only pass attributes to the `input` helper, not arguments', arguments.length < 2); - - var hash = options.hash, - types = options.hashTypes, - inputType = hash.type, - onEvent = hash.on; - - delete hash.type; - delete hash.on; - - if (inputType === 'checkbox') { - Ember.assert("{{input type='checkbox'}} does not support setting `value=someBooleanValue`; you must use `checked=someBooleanValue` instead.", options.hashTypes.value !== 'ID'); - return helpers.view.call(this, Checkbox, options); - } else { - if (inputType) { hash.type = inputType; } - hash.onEvent = onEvent || 'enter'; - return helpers.view.call(this, TextField, options); - } - } - - /** - `{{textarea}}` inserts a new instance of ` - ``` - - Bound: - - In the following example, the `writtenWords` property on `App.ApplicationController` - will be updated live as the user types 'Lots of text that IS bound' into - the text area of their browser's window. - - ```javascript - App.ApplicationController = Ember.Controller.extend({ - writtenWords: "Lots of text that IS bound" - }); - ``` - - ```handlebars - {{textarea value=writtenWords}} - ``` - - Would result in the following HTML: - - ```html - - ``` - - If you wanted a one way binding between the text area and a div tag - somewhere else on your screen, you could use `Ember.computed.oneWay`: - - ```javascript - App.ApplicationController = Ember.Controller.extend({ - writtenWords: "Lots of text that IS bound", - outputWrittenWords: Ember.computed.oneWay("writtenWords") - }); - ``` - - ```handlebars - {{textarea value=writtenWords}} - -
- {{outputWrittenWords}} -
- ``` - - Would result in the following HTML: - - ```html - - - <-- the following div will be updated in real time as you type --> - -
- Lots of text that IS bound -
- ``` - - Finally, this example really shows the power and ease of Ember when two - properties are bound to eachother via `Ember.computed.alias`. Type into - either text area box and they'll both stay in sync. Note that - `Ember.computed.alias` costs more in terms of performance, so only use it when - your really binding in both directions: - - ```javascript - App.ApplicationController = Ember.Controller.extend({ - writtenWords: "Lots of text that IS bound", - twoWayWrittenWords: Ember.computed.alias("writtenWords") - }); - ``` - - ```handlebars - {{textarea value=writtenWords}} - {{textarea value=twoWayWrittenWords}} - ``` - - ```html - - - <-- both updated in real time --> - - - ``` - - ## Extension - - Internally, `{{textarea}}` creates an instance of `Ember.TextArea`, passing - arguments from the helper to `Ember.TextArea`'s `create` method. You can - extend the capabilities of text areas in your application by reopening this - class. For example, if you are building a Bootstrap project where `data-*` - attributes are used, you can globally add support for a `data-*` attribute - on all `{{textarea}}`s' in your app by reopening `Ember.TextArea` or - `Ember.TextSupport` and adding it to the `attributeBindings` concatenated - property: - - ```javascript - Ember.TextArea.reopen({ - attributeBindings: ['data-error'] - }); - ``` - - Keep in mind when writing `Ember.TextArea` subclasses that `Ember.TextArea` - itself extends `Ember.Component`, meaning that it does NOT inherit - the `controller` of the parent view. - - See more about [Ember components](api/classes/Ember.Component.html) - - @method textarea - @for Ember.Handlebars.helpers - @param {Hash} options - */ - function textareaHelper(options) { - Ember.assert('You can only pass attributes to the `textarea` helper, not arguments', arguments.length < 2); - - var hash = options.hash, - types = options.hashTypes; - - return helpers.view.call(this, TextArea, options); - } - - __exports__.inputHelper = inputHelper; - __exports__.textareaHelper = textareaHelper; - }); -define("ember-handlebars/controls/checkbox", - ["ember-metal/property_get","ember-metal/property_set","ember-views/views/view","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __exports__) { - "use strict"; - var get = __dependency1__.get; - var set = __dependency2__.set; - var View = __dependency3__.View; - - /** - @module ember - @submodule ember-handlebars - */ - - /** - The internal class used to create text inputs when the `{{input}}` - helper is used with `type` of `checkbox`. - - See [handlebars.helpers.input](/api/classes/Ember.Handlebars.helpers.html#method_input) for usage details. - - ## Direct manipulation of `checked` - - The `checked` attribute of an `Ember.Checkbox` object should always be set - through the Ember object or by interacting with its rendered element - representation via the mouse, keyboard, or touch. Updating the value of the - checkbox via jQuery will result in the checked value of the object and its - element losing synchronization. - - ## Layout and LayoutName properties - - Because HTML `input` elements are self closing `layout` and `layoutName` - properties will not be applied. See [Ember.View](/api/classes/Ember.View.html)'s - layout section for more information. - - @class Checkbox - @namespace Ember - @extends Ember.View - */ - var Checkbox = View.extend({ - instrumentDisplay: '{{input type="checkbox"}}', - - classNames: ['ember-checkbox'], - - tagName: 'input', - - attributeBindings: ['type', 'checked', 'indeterminate', 'disabled', 'tabindex', 'name', - 'autofocus', 'required', 'form'], - - type: "checkbox", - checked: false, - disabled: false, - indeterminate: false, - - init: function() { - this._super(); - this.on("change", this, this._updateElementValue); - }, - - didInsertElement: function() { - this._super(); - get(this, 'element').indeterminate = !!get(this, 'indeterminate'); - }, - - _updateElementValue: function() { - set(this, 'checked', this.$().prop('checked')); - } - }); - - __exports__["default"] = Checkbox; - }); -define("ember-handlebars/controls/select", - ["ember-handlebars-compiler","ember-metal/enumerable_utils","ember-metal/property_get","ember-metal/property_set","ember-views/views/view","ember-views/views/collection_view","ember-metal/utils","ember-metal/is_none","ember-metal/computed","ember-runtime/system/native_array","ember-metal/mixin","ember-metal/properties","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __exports__) { - "use strict"; - /*jshint eqeqeq:false newcap:false */ - - /** - @module ember - @submodule ember-handlebars - */ - - var EmberHandlebars = __dependency1__["default"]; - var EnumerableUtils = __dependency2__["default"]; - var get = __dependency3__.get; - var set = __dependency4__.set; - var View = __dependency5__.View; - var CollectionView = __dependency6__["default"]; - var isArray = __dependency7__.isArray; - var isNone = __dependency8__["default"]; - var computed = __dependency9__.computed; - var A = __dependency10__.A; - var observer = __dependency11__.observer; - var defineProperty = __dependency12__.defineProperty; - - var indexOf = EnumerableUtils.indexOf, - indexesOf = EnumerableUtils.indexesOf, - forEach = EnumerableUtils.forEach, - replace = EnumerableUtils.replace, - precompileTemplate = EmberHandlebars.compile; - - var SelectOption = View.extend({ - instrumentDisplay: 'Ember.SelectOption', - - tagName: 'option', - attributeBindings: ['value', 'selected'], - - defaultTemplate: function(context, options) { - options = { data: options.data, hash: {} }; - EmberHandlebars.helpers.bind.call(context, "view.label", options); - }, - - init: function() { - this.labelPathDidChange(); - this.valuePathDidChange(); - - this._super(); - }, - - selected: computed(function() { - var content = get(this, 'content'), - selection = get(this, 'parentView.selection'); - if (get(this, 'parentView.multiple')) { - return selection && indexOf(selection, content.valueOf()) > -1; - } else { - // Primitives get passed through bindings as objects... since - // `new Number(4) !== 4`, we use `==` below - return content == selection; - } - }).property('content', 'parentView.selection'), - - labelPathDidChange: observer('parentView.optionLabelPath', function() { - var labelPath = get(this, 'parentView.optionLabelPath'); - - if (!labelPath) { return; } - - defineProperty(this, 'label', computed(function() { - return get(this, labelPath); - }).property(labelPath)); - }), - - valuePathDidChange: observer('parentView.optionValuePath', function() { - var valuePath = get(this, 'parentView.optionValuePath'); - - if (!valuePath) { return; } - - defineProperty(this, 'value', computed(function() { - return get(this, valuePath); - }).property(valuePath)); - }) - }); - - var SelectOptgroup = CollectionView.extend({ - instrumentDisplay: 'Ember.SelectOptgroup', - - tagName: 'optgroup', - attributeBindings: ['label'], - - selectionBinding: 'parentView.selection', - multipleBinding: 'parentView.multiple', - optionLabelPathBinding: 'parentView.optionLabelPath', - optionValuePathBinding: 'parentView.optionValuePath', - - itemViewClassBinding: 'parentView.optionView' - }); - - /** - The `Ember.Select` view class renders a - [select](https://developer.mozilla.org/en/HTML/Element/select) HTML element, - allowing the user to choose from a list of options. - - The text and `value` property of each ` - - - ``` - - The `value` attribute of the selected `"); - return buffer; - } - -function program3(depth0,data) { - - var stack1; - stack1 = helpers.each.call(depth0, "view.groupedContent", {hash:{},hashTypes:{},hashContexts:{},inverse:self.noop,fn:self.program(4, program4, data),contexts:[depth0],types:["ID"],data:data}); - if(stack1 || stack1 === 0) { data.buffer.push(stack1); } - else { data.buffer.push(''); } - } -function program4(depth0,data) { - - - data.buffer.push(escapeExpression(helpers.view.call(depth0, "view.groupView", {hash:{ - 'content': ("content"), - 'label': ("label") - },hashTypes:{'content': "ID",'label': "ID"},hashContexts:{'content': depth0,'label': depth0},contexts:[depth0],types:["ID"],data:data}))); - } - -function program6(depth0,data) { - - var stack1; - stack1 = helpers.each.call(depth0, "view.content", {hash:{},hashTypes:{},hashContexts:{},inverse:self.noop,fn:self.program(7, program7, data),contexts:[depth0],types:["ID"],data:data}); - if(stack1 || stack1 === 0) { data.buffer.push(stack1); } - else { data.buffer.push(''); } - } -function program7(depth0,data) { - - - data.buffer.push(escapeExpression(helpers.view.call(depth0, "view.optionView", {hash:{ - 'content': ("") - },hashTypes:{'content': "ID"},hashContexts:{'content': depth0},contexts:[depth0],types:["ID"],data:data}))); - } - - stack1 = helpers['if'].call(depth0, "view.prompt", {hash:{},hashTypes:{},hashContexts:{},inverse:self.noop,fn:self.program(1, program1, data),contexts:[depth0],types:["ID"],data:data}); - if(stack1 || stack1 === 0) { data.buffer.push(stack1); } - stack1 = helpers['if'].call(depth0, "view.optionGroupPath", {hash:{},hashTypes:{},hashContexts:{},inverse:self.program(6, program6, data),fn:self.program(3, program3, data),contexts:[depth0],types:["ID"],data:data}); - if(stack1 || stack1 === 0) { data.buffer.push(stack1); } - return buffer; - -}), - attributeBindings: ['multiple', 'disabled', 'tabindex', 'name', 'required', 'autofocus', - 'form', 'size'], - - /** - The `multiple` attribute of the select element. Indicates whether multiple - options can be selected. - - @property multiple - @type Boolean - @default false - */ - multiple: false, - - /** - The `disabled` attribute of the select element. Indicates whether - the element is disabled from interactions. - - @property disabled - @type Boolean - @default false - */ - disabled: false, - - /** - The `required` attribute of the select element. Indicates whether - a selected option is required for form validation. - - @property required - @type Boolean - @default false - @since 1.5.0 - */ - required: false, - - /** - The list of options. - - If `optionLabelPath` and `optionValuePath` are not overridden, this should - be a list of strings, which will serve simultaneously as labels and values. - - Otherwise, this should be a list of objects. For instance: - - ```javascript - Ember.Select.create({ - content: A([ - { id: 1, firstName: 'Yehuda' }, - { id: 2, firstName: 'Tom' } - ]), - optionLabelPath: 'content.firstName', - optionValuePath: 'content.id' - }); - ``` - - @property content - @type Array - @default null - */ - content: null, - - /** - When `multiple` is `false`, the element of `content` that is currently - selected, if any. - - When `multiple` is `true`, an array of such elements. - - @property selection - @type Object or Array - @default null - */ - selection: null, - - /** - In single selection mode (when `multiple` is `false`), value can be used to - get the current selection's value or set the selection by it's value. - - It is not currently supported in multiple selection mode. - - @property value - @type String - @default null - */ - value: computed(function(key, value) { - if (arguments.length === 2) { return value; } - var valuePath = get(this, 'optionValuePath').replace(/^content\.?/, ''); - return valuePath ? get(this, 'selection.' + valuePath) : get(this, 'selection'); - }).property('selection'), - - /** - If given, a top-most dummy option will be rendered to serve as a user - prompt. - - @property prompt - @type String - @default null - */ - prompt: null, - - /** - The path of the option labels. See [content](/api/classes/Ember.Select.html#property_content). - - @property optionLabelPath - @type String - @default 'content' - */ - optionLabelPath: 'content', - - /** - The path of the option values. See [content](/api/classes/Ember.Select.html#property_content). - - @property optionValuePath - @type String - @default 'content' - */ - optionValuePath: 'content', - - /** - The path of the option group. - When this property is used, `content` should be sorted by `optionGroupPath`. - - @property optionGroupPath - @type String - @default null - */ - optionGroupPath: null, - - /** - The view class for optgroup. - - @property groupView - @type Ember.View - @default Ember.SelectOptgroup - */ - groupView: SelectOptgroup, - - groupedContent: computed(function() { - var groupPath = get(this, 'optionGroupPath'); - var groupedContent = A(); - var content = get(this, 'content') || []; - - forEach(content, function(item) { - var label = get(item, groupPath); - - if (get(groupedContent, 'lastObject.label') !== label) { - groupedContent.pushObject({ - label: label, - content: A() - }); - } - - get(groupedContent, 'lastObject.content').push(item); - }); - - return groupedContent; - }).property('optionGroupPath', 'content.@each'), - - /** - The view class for option. - - @property optionView - @type Ember.View - @default Ember.SelectOption - */ - optionView: SelectOption, - - _change: function() { - if (get(this, 'multiple')) { - this._changeMultiple(); - } else { - this._changeSingle(); - } - }, - - selectionDidChange: observer('selection.@each', function() { - var selection = get(this, 'selection'); - if (get(this, 'multiple')) { - if (!isArray(selection)) { - set(this, 'selection', A([selection])); - return; - } - this._selectionDidChangeMultiple(); - } else { - this._selectionDidChangeSingle(); - } - }), - - valueDidChange: observer('value', function() { - var content = get(this, 'content'), - value = get(this, 'value'), - valuePath = get(this, 'optionValuePath').replace(/^content\.?/, ''), - selectedValue = (valuePath ? get(this, 'selection.' + valuePath) : get(this, 'selection')), - selection; - - if (value !== selectedValue) { - selection = content ? content.find(function(obj) { - return value === (valuePath ? get(obj, valuePath) : obj); - }) : null; - - this.set('selection', selection); - } - }), - - - _triggerChange: function() { - var selection = get(this, 'selection'); - var value = get(this, 'value'); - - if (!isNone(selection)) { this.selectionDidChange(); } - if (!isNone(value)) { this.valueDidChange(); } - - this._change(); - }, - - _changeSingle: function() { - var selectedIndex = this.$()[0].selectedIndex, - content = get(this, 'content'), - prompt = get(this, 'prompt'); - - if (!content || !get(content, 'length')) { return; } - if (prompt && selectedIndex === 0) { set(this, 'selection', null); return; } - - if (prompt) { selectedIndex -= 1; } - set(this, 'selection', content.objectAt(selectedIndex)); - }, - - - _changeMultiple: function() { - var options = this.$('option:selected'), - prompt = get(this, 'prompt'), - offset = prompt ? 1 : 0, - content = get(this, 'content'), - selection = get(this, 'selection'); - - if (!content) { return; } - if (options) { - var selectedIndexes = options.map(function() { - return this.index - offset; - }).toArray(); - var newSelection = content.objectsAt(selectedIndexes); - - if (isArray(selection)) { - replace(selection, 0, get(selection, 'length'), newSelection); - } else { - set(this, 'selection', newSelection); - } - } - }, - - _selectionDidChangeSingle: function() { - var el = this.get('element'); - if (!el) { return; } - - var content = get(this, 'content'), - selection = get(this, 'selection'), - selectionIndex = content ? indexOf(content, selection) : -1, - prompt = get(this, 'prompt'); - - if (prompt) { selectionIndex += 1; } - if (el) { el.selectedIndex = selectionIndex; } - }, - - _selectionDidChangeMultiple: function() { - var content = get(this, 'content'), - selection = get(this, 'selection'), - selectedIndexes = content ? indexesOf(content, selection) : [-1], - prompt = get(this, 'prompt'), - offset = prompt ? 1 : 0, - options = this.$('option'), - adjusted; - - if (options) { - options.each(function() { - adjusted = this.index > -1 ? this.index - offset : -1; - this.selected = indexOf(selectedIndexes, adjusted) > -1; - }); - } - }, - - init: function() { - this._super(); - this.on("didInsertElement", this, this._triggerChange); - this.on("change", this, this._change); - } - }); - - __exports__["default"] = Select - __exports__.Select = Select; - __exports__.SelectOption = SelectOption; - __exports__.SelectOptgroup = SelectOptgroup; - }); -define("ember-handlebars/controls/text_area", - ["ember-metal/property_get","ember-views/views/component","ember-handlebars/controls/text_support","ember-metal/mixin","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) { - "use strict"; - - /** - @module ember - @submodule ember-handlebars - */ - var get = __dependency1__.get; - var Component = __dependency2__["default"]; - var TextSupport = __dependency3__["default"]; - var observer = __dependency4__.observer; - - /** - The internal class used to create textarea element when the `{{textarea}}` - helper is used. - - See [handlebars.helpers.textarea](/api/classes/Ember.Handlebars.helpers.html#method_textarea) for usage details. - - ## Layout and LayoutName properties - - Because HTML `textarea` elements do not contain inner HTML the `layout` and - `layoutName` properties will not be applied. See [Ember.View](/api/classes/Ember.View.html)'s - layout section for more information. - - @class TextArea - @namespace Ember - @extends Ember.Component - @uses Ember.TextSupport - */ - var TextArea = Component.extend(TextSupport, { - instrumentDisplay: '{{textarea}}', - - classNames: ['ember-text-area'], - - tagName: "textarea", - attributeBindings: ['rows', 'cols', 'name', 'selectionEnd', 'selectionStart', 'wrap'], - rows: null, - cols: null, - - _updateElementValue: observer('value', function() { - // We do this check so cursor position doesn't get affected in IE - var value = get(this, 'value'), - $el = this.$(); - if ($el && value !== $el.val()) { - $el.val(value); - } - }), - - init: function() { - this._super(); - this.on("didInsertElement", this, this._updateElementValue); - } - - }); - - __exports__["default"] = TextArea; - }); -define("ember-handlebars/controls/text_field", - ["ember-metal/property_get","ember-metal/property_set","ember-views/views/component","ember-handlebars/controls/text_support","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) { - "use strict"; - /** - @module ember - @submodule ember-handlebars - */ - - var get = __dependency1__.get; - var set = __dependency2__.set; - var Component = __dependency3__["default"]; - var TextSupport = __dependency4__["default"]; - - /** - - The internal class used to create text inputs when the `{{input}}` - helper is used with `type` of `text`. - - See [Handlebars.helpers.input](/api/classes/Ember.Handlebars.helpers.html#method_input) for usage details. - - ## Layout and LayoutName properties - - Because HTML `input` elements are self closing `layout` and `layoutName` - properties will not be applied. See [Ember.View](/api/classes/Ember.View.html)'s - layout section for more information. - - @class TextField - @namespace Ember - @extends Ember.Component - @uses Ember.TextSupport - */ - var TextField = Component.extend(TextSupport, { - instrumentDisplay: '{{input type="text"}}', - - classNames: ['ember-text-field'], - tagName: "input", - attributeBindings: ['type', 'value', 'size', 'pattern', 'name', 'min', 'max', - 'accept', 'autocomplete', 'autosave', 'formaction', - 'formenctype', 'formmethod', 'formnovalidate', 'formtarget', - 'height', 'inputmode', 'list', 'multiple', 'pattern', 'step', - 'width'], - - /** - The `value` attribute of the input element. As the user inputs text, this - property is updated live. - - @property value - @type String - @default "" - */ - value: "", - - /** - The `type` attribute of the input element. - - @property type - @type String - @default "text" - */ - type: "text", - - /** - The `size` of the text field in characters. - - @property size - @type String - @default null - */ - size: null, - - /** - The `pattern` attribute of input element. - - @property pattern - @type String - @default null - */ - pattern: null, - - /** - The `min` attribute of input element used with `type="number"` or `type="range"`. - - @property min - @type String - @default null - @since 1.4.0 - */ - min: null, - - /** - The `max` attribute of input element used with `type="number"` or `type="range"`. - - @property max - @type String - @default null - @since 1.4.0 - */ - max: null - }); - - __exports__["default"] = TextField; - }); -define("ember-handlebars/controls/text_support", - ["ember-metal/property_get","ember-metal/property_set","ember-metal/mixin","ember-runtime/mixins/target_action_support","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) { - "use strict"; - /** - @module ember - @submodule ember-handlebars - */ - - var get = __dependency1__.get; - var set = __dependency2__.set; - var Mixin = __dependency3__.Mixin; - var TargetActionSupport = __dependency4__["default"]; - - /** - Shared mixin used by `Ember.TextField` and `Ember.TextArea`. - - @class TextSupport - @namespace Ember - @uses Ember.TargetActionSupport - @extends Ember.Mixin - @private - */ - var TextSupport = Mixin.create(TargetActionSupport, { - value: "", - - attributeBindings: ['placeholder', 'disabled', 'maxlength', 'tabindex', 'readonly', - 'autofocus', 'form', 'selectionDirection', 'spellcheck', 'required', - 'title', 'autocapitalize', 'autocorrect'], - placeholder: null, - disabled: false, - maxlength: null, - - init: function() { - this._super(); - this.on("focusOut", this, this._elementValueDidChange); - this.on("change", this, this._elementValueDidChange); - this.on("paste", this, this._elementValueDidChange); - this.on("cut", this, this._elementValueDidChange); - this.on("input", this, this._elementValueDidChange); - this.on("keyUp", this, this.interpretKeyEvents); - }, - - /** - The action to be sent when the user presses the return key. - - This is similar to the `{{action}}` helper, but is fired when - the user presses the return key when editing a text field, and sends - the value of the field as the context. - - @property action - @type String - @default null - */ - action: null, - - /** - The event that should send the action. - - Options are: - - * `enter`: the user pressed enter - * `keyPress`: the user pressed a key - - @property onEvent - @type String - @default enter - */ - onEvent: 'enter', - - /** - Whether they `keyUp` event that triggers an `action` to be sent continues - propagating to other views. - - By default, when the user presses the return key on their keyboard and - the text field has an `action` set, the action will be sent to the view's - controller and the key event will stop propagating. - - If you would like parent views to receive the `keyUp` event even after an - action has been dispatched, set `bubbles` to true. - - @property bubbles - @type Boolean - @default false - */ - bubbles: false, - - interpretKeyEvents: function(event) { - var map = TextSupport.KEY_EVENTS; - var method = map[event.keyCode]; - - this._elementValueDidChange(); - if (method) { return this[method](event); } - }, - - _elementValueDidChange: function() { - set(this, 'value', this.$().val()); - }, - - /** - The action to be sent when the user inserts a new line. - - Called by the `Ember.TextSupport` mixin on keyUp if keycode matches 13. - Uses sendAction to send the `enter` action to the controller. - - @method insertNewline - @param {Event} event - */ - insertNewline: function(event) { - sendAction('enter', this, event); - sendAction('insert-newline', this, event); - }, - - /** - Called when the user hits escape. - - Called by the `Ember.TextSupport` mixin on keyUp if keycode matches 27. - Uses sendAction to send the `escape-press` action to the controller. - - @method cancel - @param {Event} event - */ - cancel: function(event) { - sendAction('escape-press', this, event); - }, - - /** - Called when the text area is focused. - - @method focusIn - @param {Event} event - */ - focusIn: function(event) { - sendAction('focus-in', this, event); - }, - - /** - Called when the text area is blurred. - - @method focusOut - @param {Event} event - */ - focusOut: function(event) { - sendAction('focus-out', this, event); - }, - - /** - The action to be sent when the user presses a key. Enabled by setting - the `onEvent` property to `keyPress`. - - Uses sendAction to send the `keyPress` action to the controller. - - @method keyPress - @param {Event} event - */ - keyPress: function(event) { - sendAction('key-press', this, event); - } - - }); - - TextSupport.KEY_EVENTS = { - 13: 'insertNewline', - 27: 'cancel' - }; - - // In principle, this shouldn't be necessary, but the legacy - // sendAction semantics for TextField are different from - // the component semantics so this method normalizes them. - function sendAction(eventName, view, event) { - var action = get(view, eventName), - on = get(view, 'onEvent'), - value = get(view, 'value'); - - // back-compat support for keyPress as an event name even though - // it's also a method name that consumes the event (and therefore - // incompatible with sendAction semantics). - if (on === eventName || (on === 'keyPress' && eventName === 'key-press')) { - view.sendAction('action', value); - } - - view.sendAction(eventName, value); - - if (action || on === eventName) { - if(!get(view, 'bubbles')) { - event.stopPropagation(); - } - } - } - - __exports__["default"] = TextSupport; - }); -define("ember-handlebars/ext", - ["ember-metal/core","ember-runtime/system/string","ember-handlebars-compiler","ember-metal/property_get","ember-metal/binding","ember-metal/error","ember-metal/mixin","ember-metal/is_empty","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __exports__) { - "use strict"; - var Ember = __dependency1__["default"]; - // Ember.FEATURES, Ember.assert, Ember.Handlebars, Ember.lookup - // var emberAssert = Ember.assert; - - var fmt = __dependency2__.fmt; - - var EmberHandlebars = __dependency3__["default"]; - var helpers = EmberHandlebars.helpers; - - var get = __dependency4__.get; - var isGlobalPath = __dependency5__.isGlobalPath; - var EmberError = __dependency6__["default"]; - var IS_BINDING = __dependency7__.IS_BINDING; - - // late bound via requireModule because of circular dependencies. - var resolveHelper, - SimpleHandlebarsView; - - var isEmpty = __dependency8__["default"]; - - var slice = [].slice, originalTemplate = EmberHandlebars.template; - - /** - If a path starts with a reserved keyword, returns the root - that should be used. - - @private - @method normalizePath - @for Ember - @param root {Object} - @param path {String} - @param data {Hash} - */ - function normalizePath(root, path, data) { - var keywords = (data && data.keywords) || {}, - keyword, isKeyword; - - // Get the first segment of the path. For example, if the - // path is "foo.bar.baz", returns "foo". - keyword = path.split('.', 1)[0]; - - // Test to see if the first path is a keyword that has been - // passed along in the view's data hash. If so, we will treat - // that object as the new root. - if (keywords.hasOwnProperty(keyword)) { - // Look up the value in the template's data hash. - root = keywords[keyword]; - isKeyword = true; - - // Handle cases where the entire path is the reserved - // word. In that case, return the object itself. - if (path === keyword) { - path = ''; - } else { - // Strip the keyword from the path and look up - // the remainder from the newly found root. - path = path.substr(keyword.length+1); - } - } - - return { root: root, path: path, isKeyword: isKeyword }; - }; - - - /** - Lookup both on root and on window. If the path starts with - a keyword, the corresponding object will be looked up in the - template's data hash and used to resolve the path. - - @method get - @for Ember.Handlebars - @param {Object} root The object to look up the property on - @param {String} path The path to be lookedup - @param {Object} options The template's option hash - */ - function handlebarsGet(root, path, options) { - var data = options && options.data, - normalizedPath = normalizePath(root, path, data), - value; - - - root = normalizedPath.root; - path = normalizedPath.path; - - value = get(root, path); - - if (value === undefined && root !== Ember.lookup && isGlobalPath(path)) { - value = get(Ember.lookup, path); - } - - - return value; - } - - /** - This method uses `Ember.Handlebars.get` to lookup a value, then ensures - that the value is escaped properly. - - If `unescaped` is a truthy value then the escaping will not be performed. - - @method getEscaped - @for Ember.Handlebars - @param {Object} root The object to look up the property on - @param {String} path The path to be lookedup - @param {Object} options The template's option hash - @since 1.4.0 - */ - function getEscaped(root, path, options) { - var result = handlebarsGet(root, path, options); - - if (result === null || result === undefined) { - result = ""; - } else if (!(result instanceof Handlebars.SafeString)) { - result = String(result); - } - if (!options.hash.unescaped){ - result = Handlebars.Utils.escapeExpression(result); - } - - return result; - }; - - function resolveParams(context, params, options) { - var resolvedParams = [], types = options.types, param, type; - - for (var i=0, l=params.length; i{{user.name}} - -
-
{{user.role.label}}
- {{user.role.id}} - -

{{user.role.description}}

-
- ``` - - `{{with}}` can be our best friend in these cases, - instead of writing `user.role.*` over and over, we use `{{#with user.role}}`. - Now the context within the `{{#with}} .. {{/with}}` block is `user.role` so you can do the following: - - ```handlebars -
{{user.name}}
- -
- {{#with user.role}} -
{{label}}
- {{id}} - -

{{description}}

- {{/with}} -
- ``` - - ### `as` operator - - This operator aliases the scope to a new name. It's helpful for semantic clarity and to retain - default scope or to reference from another `{{with}}` block. - - ```handlebars - // posts might not be - {{#with user.posts as blogPosts}} -
- There are {{blogPosts.length}} blog posts written by {{user.name}}. -
- - {{#each post in blogPosts}} -
  • {{post.title}}
  • - {{/each}} - {{/with}} - ``` - - Without the `as` operator, it would be impossible to reference `user.name` in the example above. - - NOTE: The alias should not reuse a name from the bound property path. - For example: `{{#with foo.bar as foo}}` is not supported because it attempts to alias using - the first part of the property path, `foo`. Instead, use `{{#with foo.bar as baz}}`. - - ### `controller` option - - Adding `controller='something'` instructs the `{{with}}` helper to create and use an instance of - the specified controller with the new context as its content. - - This is very similar to using an `itemController` option with the `{{each}}` helper. - - ```handlebars - {{#with users.posts controller='userBlogPosts'}} - {{!- The current context is wrapped in our controller instance }} - {{/with}} - ``` - - In the above example, the template provided to the `{{with}}` block is now wrapped in the - `userBlogPost` controller, which provides a very elegant way to decorate the context with custom - functions/properties. - - @method with - @for Ember.Handlebars.helpers - @param {Function} context - @param {Hash} options - @return {String} HTML string - */ - function withHelper(context, options) { - var bindContext, preserveContext, controller, helperName = 'with'; - - if (arguments.length === 4) { - var keywordName, path, rootPath, normalized, contextPath; - - Ember.assert("If you pass more than one argument to the with helper, it must be in the form #with foo as bar", arguments[1] === "as"); - options = arguments[3]; - keywordName = arguments[2]; - path = arguments[0]; - - if (path) { - helperName += ' ' + path + ' as ' + keywordName; - } - - Ember.assert("You must pass a block to the with helper", options.fn && options.fn !== Handlebars.VM.noop); - - var localizedOptions = o_create(options); - localizedOptions.data = o_create(options.data); - localizedOptions.data.keywords = o_create(options.data.keywords || {}); - - if (isGlobalPath(path)) { - contextPath = path; - } else { - normalized = normalizePath(this, path, options.data); - path = normalized.path; - rootPath = normalized.root; - - // This is a workaround for the fact that you cannot bind separate objects - // together. When we implement that functionality, we should use it here. - var contextKey = jQuery.expando + guidFor(rootPath); - localizedOptions.data.keywords[contextKey] = rootPath; - // if the path is '' ("this"), just bind directly to the current context - contextPath = path ? contextKey + '.' + path : contextKey; - } - - localizedOptions.hash.keywordName = keywordName; - localizedOptions.hash.keywordPath = contextPath; - - bindContext = this; - context = path; - options = localizedOptions; - preserveContext = true; - } else { - Ember.assert("You must pass exactly one argument to the with helper", arguments.length === 2); - Ember.assert("You must pass a block to the with helper", options.fn && options.fn !== Handlebars.VM.noop); - - helperName += ' ' + context; - bindContext = options.contexts[0]; - preserveContext = false; - } - - options.helperName = helperName; - options.isWithHelper = true; - - return bind.call(bindContext, context, options, preserveContext, exists); - } - /** - See [boundIf](/api/classes/Ember.Handlebars.helpers.html#method_boundIf) - and [unboundIf](/api/classes/Ember.Handlebars.helpers.html#method_unboundIf) - - @method if - @for Ember.Handlebars.helpers - @param {Function} context - @param {Hash} options - @return {String} HTML string - */ - function ifHelper(context, options) { - Ember.assert("You must pass exactly one argument to the if helper", arguments.length === 2); - Ember.assert("You must pass a block to the if helper", options.fn && options.fn !== Handlebars.VM.noop); - - options.helperName = options.helperName || ('if ' + context); - - if (options.data.isUnbound) { - return helpers.unboundIf.call(options.contexts[0], context, options); - } else { - return helpers.boundIf.call(options.contexts[0], context, options); - } - } - - /** - @method unless - @for Ember.Handlebars.helpers - @param {Function} context - @param {Hash} options - @return {String} HTML string - */ - function unlessHelper(context, options) { - Ember.assert("You must pass exactly one argument to the unless helper", arguments.length === 2); - Ember.assert("You must pass a block to the unless helper", options.fn && options.fn !== Handlebars.VM.noop); - - var fn = options.fn, inverse = options.inverse, helperName = 'unless'; - - if (context) { - helperName += ' ' + context; - } - - options.fn = inverse; - options.inverse = fn; - - options.helperName = options.helperName || helperName; - - if (options.data.isUnbound) { - return helpers.unboundIf.call(options.contexts[0], context, options); - } else { - return helpers.boundIf.call(options.contexts[0], context, options); - } - } - - /** - `bind-attr` allows you to create a binding between DOM element attributes and - Ember objects. For example: - - ```handlebars - imageTitle - ``` - - The above handlebars template will fill the ``'s `src` attribute will - the value of the property referenced with `"imageUrl"` and its `alt` - attribute with the value of the property referenced with `"imageTitle"`. - - If the rendering context of this template is the following object: - - ```javascript - { - imageUrl: 'http://lolcats.info/haz-a-funny', - imageTitle: 'A humorous image of a cat' - } - ``` - - The resulting HTML output will be: - - ```html - A humorous image of a cat - ``` - - `bind-attr` cannot redeclare existing DOM element attributes. The use of `src` - in the following `bind-attr` example will be ignored and the hard coded value - of `src="/failwhale.gif"` will take precedence: - - ```handlebars - imageTitle - ``` - - ### `bind-attr` and the `class` attribute - - `bind-attr` supports a special syntax for handling a number of cases unique - to the `class` DOM element attribute. The `class` attribute combines - multiple discrete values into a single attribute as a space-delimited - list of strings. Each string can be: - - * a string return value of an object's property. - * a boolean return value of an object's property - * a hard-coded value - - A string return value works identically to other uses of `bind-attr`. The - return value of the property will become the value of the attribute. For - example, the following view and template: - - ```javascript - AView = View.extend({ - someProperty: function() { - return "aValue"; - }.property() - }) - ``` - - ```handlebars - - ``` - - A boolean return value will insert a specified class name if the property - returns `true` and remove the class name if the property returns `false`. - - A class name is provided via the syntax - `somePropertyName:class-name-if-true`. - - ```javascript - AView = View.extend({ - someBool: true - }) - ``` - - ```handlebars - - ``` - - Result in the following rendered output: - - ```html - - ``` - - An additional section of the binding can be provided if you want to - replace the existing class instead of removing it when the boolean - value changes: - - ```handlebars - - ``` - - A hard-coded value can be used by prepending `:` to the desired - class name: `:class-name-to-always-apply`. - - ```handlebars - - ``` - - Results in the following rendered output: - - ```html - - ``` - - All three strategies - string return value, boolean return value, and - hard-coded value – can be combined in a single declaration: - - ```handlebars - - ``` - - @method bind-attr - @for Ember.Handlebars.helpers - @param {Hash} options - @return {String} HTML string - */ - function bindAttrHelper(options) { - var attrs = options.hash; - - Ember.assert("You must specify at least one hash argument to bind-attr", !!keys(attrs).length); - - var view = options.data.view; - var ret = []; - - // we relied on the behavior of calling without - // context to mean this === window, but when running - // "use strict", it's possible for this to === undefined; - var ctx = this || window; - - // Generate a unique id for this element. This will be added as a - // data attribute to the element so it can be looked up when - // the bound property changes. - var dataId = ++Ember.uuid; - - // Handle classes differently, as we can bind multiple classes - var classBindings = attrs['class']; - if (classBindings != null) { - var classResults = bindClasses(ctx, classBindings, view, dataId, options); - - ret.push('class="' + Handlebars.Utils.escapeExpression(classResults.join(' ')) + '"'); - delete attrs['class']; - } - - var attrKeys = keys(attrs); - - // For each attribute passed, create an observer and emit the - // current value of the property as an attribute. - forEach.call(attrKeys, function(attr) { - var path = attrs[attr], - normalized; - - Ember.assert(fmt("You must provide an expression as the value of bound attribute. You specified: %@=%@", [attr, path]), typeof path === 'string'); - - normalized = normalizePath(ctx, path, options.data); - - var value = (path === 'this') ? normalized.root : handlebarsGet(ctx, path, options), - type = typeOf(value); - - Ember.assert(fmt("Attributes must be numbers, strings or booleans, not %@", [value]), value === null || value === undefined || type === 'number' || type === 'string' || type === 'boolean'); - - var observer, invoker; - - observer = function observer() { - var result = handlebarsGet(ctx, path, options); - - Ember.assert(fmt("Attributes must be numbers, strings or booleans, not %@", [result]), - result === null || result === undefined || typeof result === 'number' || - typeof result === 'string' || typeof result === 'boolean'); - - var elem = view.$("[data-bindattr-" + dataId + "='" + dataId + "']"); - - // If we aren't able to find the element, it means the element - // to which we were bound has been removed from the view. - // In that case, we can assume the template has been re-rendered - // and we need to clean up the observer. - if (!elem || elem.length === 0) { - removeObserver(normalized.root, normalized.path, invoker); - return; - } - - View.applyAttributeBindings(elem, attr, result); - }; - - // Add an observer to the view for when the property changes. - // When the observer fires, find the element using the - // unique data id and update the attribute to the new value. - // Note: don't add observer when path is 'this' or path - // is whole keyword e.g. {{#each x in list}} ... {{bind-attr attr="x"}} - if (path !== 'this' && !(normalized.isKeyword && normalized.path === '' )) { - view.registerObserver(normalized.root, normalized.path, observer); - } - - // if this changes, also change the logic in ember-views/lib/views/view.js - if ((type === 'string' || (type === 'number' && !isNaN(value)))) { - ret.push(attr + '="' + Handlebars.Utils.escapeExpression(value) + '"'); - } else if (value && type === 'boolean') { - // The developer controls the attr name, so it should always be safe - ret.push(attr + '="' + attr + '"'); - } - }, this); - - // Add the unique identifier - // NOTE: We use all lower-case since Firefox has problems with mixed case in SVG - ret.push('data-bindattr-' + dataId + '="' + dataId + '"'); - return new SafeString(ret.join(' ')); - } - - /** - See `bind-attr` - - @method bindAttr - @for Ember.Handlebars.helpers - @deprecated - @param {Function} context - @param {Hash} options - @return {String} HTML string - */ - function bindAttrHelperDeprecated() { - Ember.warn("The 'bindAttr' view helper is deprecated in favor of 'bind-attr'"); - return helpers['bind-attr'].apply(this, arguments); - } - - /** - Helper that, given a space-separated string of property paths and a context, - returns an array of class names. Calling this method also has the side - effect of setting up observers at those property paths, such that if they - change, the correct class name will be reapplied to the DOM element. - - For example, if you pass the string "fooBar", it will first look up the - "fooBar" value of the context. If that value is true, it will add the - "foo-bar" class to the current element (i.e., the dasherized form of - "fooBar"). If the value is a string, it will add that string as the class. - Otherwise, it will not add any new class name. - - @private - @method bindClasses - @for Ember.Handlebars - @param {Ember.Object} context The context from which to lookup properties - @param {String} classBindings A string, space-separated, of class bindings - to use - @param {View} view The view in which observers should look for the - element to update - @param {Srting} bindAttrId Optional bindAttr id used to lookup elements - @return {Array} An array of class names to add - */ - function bindClasses(context, classBindings, view, bindAttrId, options) { - var ret = [], newClass, value, elem; - - // Helper method to retrieve the property from the context and - // determine which class string to return, based on whether it is - // a Boolean or not. - var classStringForPath = function(root, parsedPath, options) { - var val, - path = parsedPath.path; - - if (path === 'this') { - val = root; - } else if (path === '') { - val = true; - } else { - val = handlebarsGet(root, path, options); - } - - return View._classStringForValue(path, val, parsedPath.className, parsedPath.falsyClassName); - }; - - // For each property passed, loop through and setup - // an observer. - forEach.call(classBindings.split(' '), function(binding) { - - // Variable in which the old class value is saved. The observer function - // closes over this variable, so it knows which string to remove when - // the property changes. - var oldClass; - - var observer, invoker; - - var parsedPath = View._parsePropertyPath(binding), - path = parsedPath.path, - pathRoot = context, - normalized; - - if (path !== '' && path !== 'this') { - normalized = normalizePath(context, path, options.data); - - pathRoot = normalized.root; - path = normalized.path; - } - - // Set up an observer on the context. If the property changes, toggle the - // class name. - observer = function() { - // Get the current value of the property - newClass = classStringForPath(context, parsedPath, options); - elem = bindAttrId ? view.$("[data-bindattr-" + bindAttrId + "='" + bindAttrId + "']") : view.$(); - - // If we can't find the element anymore, a parent template has been - // re-rendered and we've been nuked. Remove the observer. - if (!elem || elem.length === 0) { - removeObserver(pathRoot, path, invoker); - } else { - // If we had previously added a class to the element, remove it. - if (oldClass) { - elem.removeClass(oldClass); - } - - // If necessary, add a new class. Make sure we keep track of it so - // it can be removed in the future. - if (newClass) { - elem.addClass(newClass); - oldClass = newClass; - } else { - oldClass = null; - } - } - }; - - if (path !== '' && path !== 'this') { - view.registerObserver(pathRoot, path, observer); - } - - // We've already setup the observer; now we just need to figure out the - // correct behavior right now on the first pass through. - value = classStringForPath(context, parsedPath, options); - - if (value) { - ret.push(value); - - // Make sure we save the current value so that it can be removed if the - // observer fires. - oldClass = value; - } - }); - - return ret; - }; - - __exports__.bind = bind; - __exports__._triageMustacheHelper = _triageMustacheHelper; - __exports__.resolveHelper = resolveHelper; - __exports__.bindHelper = bindHelper; - __exports__.boundIfHelper = boundIfHelper; - __exports__.unboundIfHelper = unboundIfHelper; - __exports__.withHelper = withHelper; - __exports__.ifHelper = ifHelper; - __exports__.unlessHelper = unlessHelper; - __exports__.bindAttrHelper = bindAttrHelper; - __exports__.bindAttrHelperDeprecated = bindAttrHelperDeprecated; - __exports__.bindClasses = bindClasses; - }); -define("ember-handlebars/helpers/collection", - ["ember-metal/core","ember-metal/utils","ember-handlebars-compiler","ember-runtime/system/string","ember-metal/property_get","ember-handlebars/ext","ember-handlebars/helpers/view","ember-metal/computed","ember-views/views/collection_view","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __exports__) { - "use strict"; - /** - @module ember - @submodule ember-handlebars - */ - - var Ember = __dependency1__["default"]; - // Ember.assert, Ember.deprecate - var inspect = __dependency2__.inspect; - - // var emberAssert = Ember.assert; - // emberDeprecate = Ember.deprecate; - - var EmberHandlebars = __dependency3__["default"]; - var helpers = EmberHandlebars.helpers; - - var fmt = __dependency4__.fmt; - var get = __dependency5__.get; - var handlebarsGet = __dependency6__.handlebarsGet; - var ViewHelper = __dependency7__.ViewHelper; - var computed = __dependency8__.computed; - var CollectionView = __dependency9__["default"]; - - var alias = computed.alias; - /** - `{{collection}}` is a `Ember.Handlebars` helper for adding instances of - `Ember.CollectionView` to a template. See [Ember.CollectionView](/api/classes/Ember.CollectionView.html) - for additional information on how a `CollectionView` functions. - - `{{collection}}`'s primary use is as a block helper with a `contentBinding` - option pointing towards an `Ember.Array`-compatible object. An `Ember.View` - instance will be created for each item in its `content` property. Each view - will have its own `content` property set to the appropriate item in the - collection. - - The provided block will be applied as the template for each item's view. - - Given an empty `` the following template: - - ```handlebars - {{#collection contentBinding="App.items"}} - Hi {{view.content.name}} - {{/collection}} - ``` - - And the following application code - - ```javascript - App = Ember.Application.create() - App.items = [ - Ember.Object.create({name: 'Dave'}), - Ember.Object.create({name: 'Mary'}), - Ember.Object.create({name: 'Sara'}) - ] - ``` - - Will result in the HTML structure below - - ```html -
    -
    Hi Dave
    -
    Hi Mary
    -
    Hi Sara
    -
    - ``` - - ### Blockless use in a collection - - If you provide an `itemViewClass` option that has its own `template` you can - omit the block. - - The following template: - - ```handlebars - {{collection contentBinding="App.items" itemViewClass="App.AnItemView"}} - ``` - - And application code - - ```javascript - App = Ember.Application.create(); - App.items = [ - Ember.Object.create({name: 'Dave'}), - Ember.Object.create({name: 'Mary'}), - Ember.Object.create({name: 'Sara'}) - ]; - - App.AnItemView = Ember.View.extend({ - template: Ember.Handlebars.compile("Greetings {{view.content.name}}") - }); - ``` - - Will result in the HTML structure below - - ```html -
    -
    Greetings Dave
    -
    Greetings Mary
    -
    Greetings Sara
    -
    - ``` - - ### Specifying a CollectionView subclass - - By default the `{{collection}}` helper will create an instance of - `Ember.CollectionView`. You can supply a `Ember.CollectionView` subclass to - the helper by passing it as the first argument: - - ```handlebars - {{#collection App.MyCustomCollectionClass contentBinding="App.items"}} - Hi {{view.content.name}} - {{/collection}} - ``` - - ### Forwarded `item.*`-named Options - - As with the `{{view}}`, helper options passed to the `{{collection}}` will be - set on the resulting `Ember.CollectionView` as properties. Additionally, - options prefixed with `item` will be applied to the views rendered for each - item (note the camelcasing): - - ```handlebars - {{#collection contentBinding="App.items" - itemTagName="p" - itemClassNames="greeting"}} - Howdy {{view.content.name}} - {{/collection}} - ``` - - Will result in the following HTML structure: - - ```html -
    -

    Howdy Dave

    -

    Howdy Mary

    -

    Howdy Sara

    -
    - ``` - - @method collection - @for Ember.Handlebars.helpers - @param {String} path - @param {Hash} options - @return {String} HTML string - @deprecated Use `{{each}}` helper instead. - */ - function collectionHelper(path, options) { - Ember.deprecate("Using the {{collection}} helper without specifying a class has been deprecated as the {{each}} helper now supports the same functionality.", path !== 'collection'); - - // If no path is provided, treat path param as options. - if (path && path.data && path.data.isRenderData) { - options = path; - path = undefined; - Ember.assert("You cannot pass more than one argument to the collection helper", arguments.length === 1); - } else { - Ember.assert("You cannot pass more than one argument to the collection helper", arguments.length === 2); - } - - var fn = options.fn; - var data = options.data; - var inverse = options.inverse; - var view = options.data.view; - - - var controller, container; - // If passed a path string, convert that into an object. - // Otherwise, just default to the standard class. - var collectionClass; - if (path) { - controller = data.keywords.controller; - container = controller && controller.container; - collectionClass = handlebarsGet(this, path, options) || container.lookupFactory('view:' + path); - Ember.assert(fmt("%@ #collection: Could not find collection class %@", [data.view, path]), !!collectionClass); - } - else { - collectionClass = CollectionView; - } - - var hash = options.hash, itemHash = {}, match; - - // Extract item view class if provided else default to the standard class - var collectionPrototype = collectionClass.proto(), itemViewClass; - - if (hash.itemView) { - controller = data.keywords.controller; - Ember.assert('You specified an itemView, but the current context has no ' + - 'container to look the itemView up in. This probably means ' + - 'that you created a view manually, instead of through the ' + - 'container. Instead, use container.lookup("view:viewName"), ' + - 'which will properly instantiate your view.', - controller && controller.container); - container = controller.container; - itemViewClass = container.lookupFactory('view:' + hash.itemView); - Ember.assert('You specified the itemView ' + hash.itemView + ", but it was " + - "not found at " + container.describe("view:" + hash.itemView) + - " (and it was not registered in the container)", !!itemViewClass); - } else if (hash.itemViewClass) { - itemViewClass = handlebarsGet(collectionPrototype, hash.itemViewClass, options); - } else { - itemViewClass = collectionPrototype.itemViewClass; - } - - Ember.assert(fmt("%@ #collection: Could not find itemViewClass %@", [data.view, itemViewClass]), !!itemViewClass); - - delete hash.itemViewClass; - delete hash.itemView; - - // Go through options passed to the {{collection}} helper and extract options - // that configure item views instead of the collection itself. - for (var prop in hash) { - if (hash.hasOwnProperty(prop)) { - match = prop.match(/^item(.)(.*)$/); - - if (match && prop !== 'itemController') { - // Convert itemShouldFoo -> shouldFoo - itemHash[match[1].toLowerCase() + match[2]] = hash[prop]; - // Delete from hash as this will end up getting passed to the - // {{view}} helper method. - delete hash[prop]; - } - } - } - - if (fn) { - itemHash.template = fn; - delete options.fn; - } - - var emptyViewClass; - if (inverse && inverse !== EmberHandlebars.VM.noop) { - emptyViewClass = get(collectionPrototype, 'emptyViewClass'); - emptyViewClass = emptyViewClass.extend({ - template: inverse, - tagName: itemHash.tagName - }); - } else if (hash.emptyViewClass) { - emptyViewClass = handlebarsGet(this, hash.emptyViewClass, options); - } - if (emptyViewClass) { hash.emptyView = emptyViewClass; } - - if (hash.keyword) { - itemHash._context = this; - } else { - itemHash._context = alias('content'); - } - - var viewOptions = ViewHelper.propertiesFromHTMLOptions({ data: data, hash: itemHash }, this); - hash.itemViewClass = itemViewClass.extend(viewOptions); - - options.helperName = options.helperName || 'collection'; - - return helpers.view.call(this, collectionClass, options); - } - - __exports__["default"] = collectionHelper; - }); -define("ember-handlebars/helpers/debug", - ["ember-metal/core","ember-metal/utils","ember-metal/logger","ember-metal/property_get","ember-handlebars/ext","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) { - "use strict"; - /*jshint debug:true*/ - - /** - @module ember - @submodule ember-handlebars - */ - var Ember = __dependency1__["default"]; - // Ember.FEATURES, - var inspect = __dependency2__.inspect; - var Logger = __dependency3__["default"]; - - var get = __dependency4__.get; - var normalizePath = __dependency5__.normalizePath; - var handlebarsGet = __dependency5__.handlebarsGet; - - var a_slice = [].slice; - - /** - `log` allows you to output the value of variables in the current rendering - context. `log` also accepts primitive types such as strings or numbers. - - ```handlebars - {{log "myVariable:" myVariable }} - ``` - - @method log - @for Ember.Handlebars.helpers - @param {String} property - */ - function logHelper() { - var params = a_slice.call(arguments, 0, -1), - options = arguments[arguments.length - 1], - logger = Logger.log, - values = [], - allowPrimitives = true; - - for (var i = 0; i < params.length; i++) { - var type = options.types[i]; - - if (type === 'ID' || !allowPrimitives) { - var context = (options.contexts && options.contexts[i]) || this, - normalized = normalizePath(context, params[i], options.data); - - if (normalized.path === 'this') { - values.push(normalized.root); - } else { - values.push(handlebarsGet(normalized.root, normalized.path, options)); - } - } else { - values.push(params[i]); - } - } - - logger.apply(logger, values); - }; - - /** - Execute the `debugger` statement in the current context. - - ```handlebars - {{debugger}} - ``` - - Before invoking the `debugger` statement, there - are a few helpful variables defined in the - body of this helper that you can inspect while - debugging that describe how and where this - helper was invoked: - - - templateContext: this is most likely a controller - from which this template looks up / displays properties - - typeOfTemplateContext: a string description of - what the templateContext is - - For example, if you're wondering why a value `{{foo}}` - isn't rendering as expected within a template, you - could place a `{{debugger}}` statement, and when - the `debugger;` breakpoint is hit, you can inspect - `templateContext`, determine if it's the object you - expect, and/or evaluate expressions in the console - to perform property lookups on the `templateContext`: - - ``` - > templateContext.get('foo') // -> "" - ``` - - @method debugger - @for Ember.Handlebars.helpers - @param {String} property - */ - function debuggerHelper(options) { - - // These are helpful values you can inspect while debugging. - var templateContext = this; - var typeOfTemplateContext = inspect(templateContext); - - debugger; - } - - __exports__.logHelper = logHelper; - __exports__.debuggerHelper = debuggerHelper; - }); -define("ember-handlebars/helpers/each", - ["ember-metal/core","ember-handlebars-compiler","ember-runtime/system/string","ember-metal/property_get","ember-metal/property_set","ember-handlebars/views/metamorph_view","ember-views/views/collection_view","ember-metal/binding","ember-runtime/controllers/controller","ember-runtime/controllers/array_controller","ember-runtime/mixins/array","ember-runtime/copy","ember-metal/run_loop","ember-metal/observer","ember-metal/events","ember-handlebars/ext","ember-metal/computed","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __dependency15__, __dependency16__, __dependency17__, __exports__) { - "use strict"; - - /** - @module ember - @submodule ember-handlebars - */ - var Ember = __dependency1__["default"]; - // Ember.assert;, Ember.K - // var emberAssert = Ember.assert, - var K = Ember.K; - - var EmberHandlebars = __dependency2__["default"]; - var helpers = EmberHandlebars.helpers; - - var fmt = __dependency3__.fmt; - var get = __dependency4__.get; - var set = __dependency5__.set; - var _Metamorph = __dependency6__._Metamorph; - var _MetamorphView = __dependency6__._MetamorphView; - var CollectionView = __dependency7__["default"]; - var Binding = __dependency8__.Binding; - var ControllerMixin = __dependency9__.ControllerMixin; - var ArrayController = __dependency10__["default"]; - var EmberArray = __dependency11__["default"]; - var copy = __dependency12__["default"]; - var run = __dependency13__["default"]; - var addObserver = __dependency14__.addObserver; - var removeObserver = __dependency14__.removeObserver; - var addBeforeObserver = __dependency14__.addBeforeObserver; - var removeBeforeObserver = __dependency14__.removeBeforeObserver; - var on = __dependency15__.on; - var handlebarsGet = __dependency16__.handlebarsGet; - var computed = __dependency17__.computed; - - var handlebarsGet = __dependency16__.handlebarsGet; - - var EachView = CollectionView.extend(_Metamorph, { - - init: function() { - var itemController = get(this, 'itemController'); - var binding; - - if (itemController) { - var controller = get(this, 'controller.container').lookupFactory('controller:array').create({ - _isVirtual: true, - parentController: get(this, 'controller'), - itemController: itemController, - target: get(this, 'controller'), - _eachView: this - }); - - this.disableContentObservers(function() { - set(this, 'content', controller); - binding = new Binding('content', '_eachView.dataSource').oneWay(); - binding.connect(controller); - }); - - set(this, '_arrayController', controller); - } else { - this.disableContentObservers(function() { - binding = new Binding('content', 'dataSource').oneWay(); - binding.connect(this); - }); - } - - return this._super(); - }, - - _assertArrayLike: function(content) { - Ember.assert(fmt("The value that #each loops over must be an Array. You " + - "passed %@, but it should have been an ArrayController", - [content.constructor]), - !ControllerMixin.detect(content) || - (content && content.isGenerated) || - content instanceof ArrayController); - Ember.assert(fmt("The value that #each loops over must be an Array. You passed %@", [(ControllerMixin.detect(content) && content.get('model') !== undefined) ? fmt("'%@' (wrapped in %@)", [content.get('model'), content]) : content]), EmberArray.detect(content)); - }, - - disableContentObservers: function(callback) { - removeBeforeObserver(this, 'content', null, '_contentWillChange'); - removeObserver(this, 'content', null, '_contentDidChange'); - - callback.call(this); - - addBeforeObserver(this, 'content', null, '_contentWillChange'); - addObserver(this, 'content', null, '_contentDidChange'); - }, - - itemViewClass: _MetamorphView, - emptyViewClass: _MetamorphView, - - createChildView: function(view, attrs) { - view = this._super(view, attrs); - - // At the moment, if a container view subclass wants - // to insert keywords, it is responsible for cloning - // the keywords hash. This will be fixed momentarily. - var keyword = get(this, 'keyword'); - var content = get(view, 'content'); - - if (keyword) { - var data = get(view, 'templateData'); - - data = copy(data); - data.keywords = view.cloneKeywords(); - set(view, 'templateData', data); - - // In this case, we do not bind, because the `content` of - // a #each item cannot change. - data.keywords[keyword] = content; - } - - // If {{#each}} is looping over an array of controllers, - // point each child view at their respective controller. - if (content && content.isController) { - set(view, 'controller', content); - } - - return view; - }, - - destroy: function() { - if (!this._super()) { return; } - - var arrayController = get(this, '_arrayController'); - - if (arrayController) { - arrayController.destroy(); - } - - return this; - } - }); - - // Defeatureify doesn't seem to like nested functions that need to be removed - function _addMetamorphCheck() { - EachView.reopen({ - _checkMetamorph: on('didInsertElement', function() { - Ember.assert("The metamorph tags, " + - this.morph.start + " and " + this.morph.end + - ", have different parents.\nThe browser has fixed your template to output valid HTML (for example, check that you have properly closed all tags and have used a TBODY tag when creating a table with '{{#each}}')", - document.getElementById( this.morph.start ).parentNode === - document.getElementById( this.morph.end ).parentNode - ); - }) - }); - } - - // until ember-debug is es6ed - var runInDebug = function(f){f()}; - runInDebug( function() { - _addMetamorphCheck(); - }); - - var GroupedEach = EmberHandlebars.GroupedEach = function(context, path, options) { - var self = this, - normalized = EmberHandlebars.normalizePath(context, path, options.data); - - this.context = context; - this.path = path; - this.options = options; - this.template = options.fn; - this.containingView = options.data.view; - this.normalizedRoot = normalized.root; - this.normalizedPath = normalized.path; - this.content = this.lookupContent(); - - this.addContentObservers(); - this.addArrayObservers(); - - this.containingView.on('willClearRender', function() { - self.destroy(); - }); - }; - - GroupedEach.prototype = { - contentWillChange: function() { - this.removeArrayObservers(); - }, - - contentDidChange: function() { - this.content = this.lookupContent(); - this.addArrayObservers(); - this.rerenderContainingView(); - }, - - contentArrayWillChange: K, - - contentArrayDidChange: function() { - this.rerenderContainingView(); - }, - - lookupContent: function() { - return handlebarsGet(this.normalizedRoot, this.normalizedPath, this.options); - }, - - addArrayObservers: function() { - if (!this.content) { return; } - - this.content.addArrayObserver(this, { - willChange: 'contentArrayWillChange', - didChange: 'contentArrayDidChange' - }); - }, - - removeArrayObservers: function() { - if (!this.content) { return; } - - this.content.removeArrayObserver(this, { - willChange: 'contentArrayWillChange', - didChange: 'contentArrayDidChange' - }); - }, - - addContentObservers: function() { - addBeforeObserver(this.normalizedRoot, this.normalizedPath, this, this.contentWillChange); - addObserver(this.normalizedRoot, this.normalizedPath, this, this.contentDidChange); - }, - - removeContentObservers: function() { - removeBeforeObserver(this.normalizedRoot, this.normalizedPath, this.contentWillChange); - removeObserver(this.normalizedRoot, this.normalizedPath, this.contentDidChange); - }, - - render: function() { - if (!this.content) { return; } - - var content = this.content, - contentLength = get(content, 'length'), - data = this.options.data, - template = this.template; - - data.insideEach = true; - for (var i = 0; i < contentLength; i++) { - template(content.objectAt(i), { data: data }); - } - }, - - rerenderContainingView: function() { - var self = this; - run.scheduleOnce('render', this, function() { - // It's possible it's been destroyed after we enqueued a re-render call. - if (!self.destroyed) { - self.containingView.rerender(); - } - }); - }, - - destroy: function() { - this.removeContentObservers(); - if (this.content) { - this.removeArrayObservers(); - } - this.destroyed = true; - } - }; - - /** - The `{{#each}}` helper loops over elements in a collection, rendering its - block once for each item. It is an extension of the base Handlebars `{{#each}}` - helper: - - ```javascript - Developers = [{name: 'Yehuda'},{name: 'Tom'}, {name: 'Paul'}]; - ``` - - ```handlebars - {{#each Developers}} - {{name}} - {{/each}} - ``` - - `{{each}}` supports an alternative syntax with element naming: - - ```handlebars - {{#each person in Developers}} - {{person.name}} - {{/each}} - ``` - - When looping over objects that do not have properties, `{{this}}` can be used - to render the object: - - ```javascript - DeveloperNames = ['Yehuda', 'Tom', 'Paul'] - ``` - - ```handlebars - {{#each DeveloperNames}} - {{this}} - {{/each}} - ``` - ### {{else}} condition - `{{#each}}` can have a matching `{{else}}`. The contents of this block will render - if the collection is empty. - - ``` - {{#each person in Developers}} - {{person.name}} - {{else}} -

    Sorry, nobody is available for this task.

    - {{/each}} - ``` - ### Specifying a View class for items - If you provide an `itemViewClass` option that references a view class - with its own `template` you can omit the block. - - The following template: - - ```handlebars - {{#view App.MyView }} - {{each view.items itemViewClass="App.AnItemView"}} - {{/view}} - ``` - - And application code - - ```javascript - App = Ember.Application.create({ - MyView: Ember.View.extend({ - items: [ - Ember.Object.create({name: 'Dave'}), - Ember.Object.create({name: 'Mary'}), - Ember.Object.create({name: 'Sara'}) - ] - }) - }); - - App.AnItemView = Ember.View.extend({ - template: Ember.Handlebars.compile("Greetings {{name}}") - }); - ``` - - Will result in the HTML structure below - - ```html -
    -
    Greetings Dave
    -
    Greetings Mary
    -
    Greetings Sara
    -
    - ``` - - If an `itemViewClass` is defined on the helper, and therefore the helper is not - being used as a block, an `emptyViewClass` can also be provided optionally. - The `emptyViewClass` will match the behavior of the `{{else}}` condition - described above. That is, the `emptyViewClass` will render if the collection - is empty. - - ### Representing each item with a Controller. - By default the controller lookup within an `{{#each}}` block will be - the controller of the template where the `{{#each}}` was used. If each - item needs to be presented by a custom controller you can provide a - `itemController` option which references a controller by lookup name. - Each item in the loop will be wrapped in an instance of this controller - and the item itself will be set to the `content` property of that controller. - - This is useful in cases where properties of model objects need transformation - or synthesis for display: - - ```javascript - App.DeveloperController = Ember.ObjectController.extend({ - isAvailableForHire: function() { - return !this.get('content.isEmployed') && this.get('content.isSeekingWork'); - }.property('isEmployed', 'isSeekingWork') - }) - ``` - - ```handlebars - {{#each person in developers itemController="developer"}} - {{person.name}} {{#if person.isAvailableForHire}}Hire me!{{/if}} - {{/each}} - ``` - - Each itemController will receive a reference to the current controller as - a `parentController` property. - - ### (Experimental) Grouped Each - - When used in conjunction with the experimental [group helper](https://github.com/emberjs/group-helper), - you can inform Handlebars to re-render an entire group of items instead of - re-rendering them one at a time (in the event that they are changed en masse - or an item is added/removed). - - ```handlebars - {{#group}} - {{#each people}} - {{firstName}} {{lastName}} - {{/each}} - {{/group}} - ``` - - This can be faster than the normal way that Handlebars re-renders items - in some cases. - - If for some reason you have a group with more than one `#each`, you can make - one of the collections be updated in normal (non-grouped) fashion by setting - the option `groupedRows=true` (counter-intuitive, I know). - - For example, - - ```handlebars - {{dealershipName}} - - {{#group}} - {{#each dealers}} - {{firstName}} {{lastName}} - {{/each}} - - {{#each car in cars groupedRows=true}} - {{car.make}} {{car.model}} {{car.color}} - {{/each}} - {{/group}} - ``` - Any change to `dealershipName` or the `dealers` collection will cause the - entire group to be re-rendered. However, changes to the `cars` collection - will be re-rendered individually (as normal). - - Note that `group` behavior is also disabled by specifying an `itemViewClass`. - - @method each - @for Ember.Handlebars.helpers - @param [name] {String} name for item (used with `in`) - @param [path] {String} path - @param [options] {Object} Handlebars key/value pairs of options - @param [options.itemViewClass] {String} a path to a view class used for each item - @param [options.itemController] {String} name of a controller to be created for each item - @param [options.groupedRows] {boolean} enable normal item-by-item rendering when inside a `#group` helper - */ - function eachHelper(path, options) { - var ctx, helperName = 'each'; - - if (arguments.length === 4) { - Ember.assert("If you pass more than one argument to the each helper, it must be in the form #each foo in bar", arguments[1] === "in"); - - var keywordName = arguments[0]; - - - options = arguments[3]; - path = arguments[2]; - - helperName += ' ' + keywordName + ' in ' + path; - - if (path === '') { path = "this"; } - - options.hash.keyword = keywordName; - - } else if (arguments.length === 1) { - options = path; - path = 'this'; - } else { - helperName += ' ' + path; - } - - options.hash.dataSourceBinding = path; - // Set up emptyView as a metamorph with no tag - //options.hash.emptyViewClass = Ember._MetamorphView; - - // can't rely on this default behavior when use strict - ctx = this || window; - - options.helperName = options.helperName || helperName; - - if (options.data.insideGroup && !options.hash.groupedRows && !options.hash.itemViewClass) { - new GroupedEach(ctx, path, options).render(); - } else { - // ES6TODO: figure out how to do this without global lookup. - return helpers.collection.call(ctx, 'Ember.Handlebars.EachView', options); - } - } - - __exports__.EachView = EachView; - __exports__.GroupedEach = GroupedEach; - __exports__.eachHelper = eachHelper; - }); -define("ember-handlebars/helpers/loc", - ["ember-runtime/system/string","exports"], - function(__dependency1__, __exports__) { - "use strict"; - var loc = __dependency1__.loc; - - /** - @module ember - @submodule ember-handlebars - */ - - // ES6TODO: - // Pretty sure this can be expressed as - // var locHelper EmberStringUtils.loc ? - - /** - Calls [Ember.String.loc](/api/classes/Ember.String.html#method_loc) with the - provided string. - - This is a convenient way to localize text. For example: - - ```html - - ``` - - Take note that `"welcome"` is a string and not an object - reference. - - See [Ember.String.loc](/api/classes/Ember.String.html#method_loc) for how to - set up localized string references. - - @method loc - @for Ember.Handlebars.helpers - @param {String} str The string to format - @see {Ember.String#loc} - */ - function locHelper(str) { - return loc(str); - } - - __exports__["default"] = locHelper; - }); -define("ember-handlebars/helpers/partial", - ["ember-metal/core","ember-metal/is_none","ember-handlebars/ext","ember-handlebars/helpers/binding","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) { - "use strict"; - var Ember = __dependency1__["default"]; - // Ember.assert - // var emberAssert = Ember.assert; - - var isNone = __dependency2__.isNone; - var handlebarsGet = __dependency3__.handlebarsGet; - var bind = __dependency4__.bind; - - /** - @module ember - @submodule ember-handlebars - */ - - /** - The `partial` helper renders another template without - changing the template context: - - ```handlebars - {{foo}} - {{partial "nav"}} - ``` - - The above example template will render a template named - "_nav", which has the same context as the parent template - it's rendered into, so if the "_nav" template also referenced - `{{foo}}`, it would print the same thing as the `{{foo}}` - in the above example. - - If a "_nav" template isn't found, the `partial` helper will - fall back to a template named "nav". - - ## Bound template names - - The parameter supplied to `partial` can also be a path - to a property containing a template name, e.g.: - - ```handlebars - {{partial someTemplateName}} - ``` - - The above example will look up the value of `someTemplateName` - on the template context (e.g. a controller) and use that - value as the name of the template to render. If the resolved - value is falsy, nothing will be rendered. If `someTemplateName` - changes, the partial will be re-rendered using the new template - name. - - ## Setting the partial's context with `with` - - The `partial` helper can be used in conjunction with the `with` - helper to set a context that will be used by the partial: - - ```handlebars - {{#with currentUser}} - {{partial "user_info"}} - {{/with}} - ``` - - @method partial - @for Ember.Handlebars.helpers - @param {String} partialName the name of the template to render minus the leading underscore - */ - - function partialHelper(name, options) { - - var context = (options.contexts && options.contexts.length) ? options.contexts[0] : this; - - options.helperName = options.helperName || 'partial'; - - if (options.types[0] === "ID") { - // Helper was passed a property path; we need to - // create a binding that will re-render whenever - // this property changes. - options.fn = function(context, fnOptions) { - var partialName = handlebarsGet(context, name, fnOptions); - renderPartial(context, partialName, fnOptions); - }; - - return bind.call(context, name, options, true, exists); - } else { - // Render the partial right into parent template. - renderPartial(context, name, options); - } - } - - function exists(value) { - return !isNone(value); - } - - function renderPartial(context, name, options) { - var nameParts = name.split("/"), - lastPart = nameParts[nameParts.length - 1]; - - nameParts[nameParts.length - 1] = "_" + lastPart; - - var view = options.data.view, - underscoredName = nameParts.join("/"), - template = view.templateForName(underscoredName), - deprecatedTemplate = !template && view.templateForName(name); - - Ember.assert("Unable to find partial with name '"+name+"'.", template || deprecatedTemplate); - - template = template || deprecatedTemplate; - - template(context, { data: options.data }); - } - - __exports__["default"] = partialHelper; - }); -define("ember-handlebars/helpers/shared", - ["ember-handlebars/ext","exports"], - function(__dependency1__, __exports__) { - "use strict"; - var handlebarsGet = __dependency1__.handlebarsGet; - - function resolvePaths(options) { - var ret = [], - contexts = options.contexts, - roots = options.roots, - data = options.data; - - for (var i=0, l=contexts.length; i - {{#with loggedInUser}} - Last Login: {{lastLogin}} - User Info: {{template "user_info"}} - {{/with}} - - ``` - - ```html - - ``` - - ```handlebars - {{#if isUser}} - {{template "user_info"}} - {{else}} - {{template "unlogged_user_info"}} - {{/if}} - ``` - - This helper looks for templates in the global `Ember.TEMPLATES` hash. If you - add `