{{#if showAllLinksControls}}
diff --git a/vendor/assets/javascripts/development/ember.js b/vendor/assets/javascripts/development/ember.js
index d048ddf7bc6..ae2418d020b 100644
--- a/vendor/assets/javascripts/development/ember.js
+++ b/vendor/assets/javascripts/development/ember.js
@@ -5,10 +5,9 @@
* 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.6.0-beta.3+pre.2e4d67f6
+ * @version 1.7.1
*/
-
(function() {
var define, requireModule, require, requirejs, Ember;
@@ -72,7 +71,3612 @@ var define, requireModule, require, requirejs, Ember;
requirejs = require = requireModule = Ember.__loader.require;
}
})();
-(function() {
+
+define("backburner",
+ ["backburner/utils","backburner/deferred_action_queues","exports"],
+ function(__dependency1__, __dependency2__, __exports__) {
+ "use strict";
+ var Utils = __dependency1__["default"];
+ var DeferredActionQueues = __dependency2__.DeferredActionQueues;
+
+ var slice = [].slice,
+ pop = [].pop,
+ each = Utils.each,
+ isString = Utils.isString,
+ isFunction = Utils.isFunction,
+ isNumber = Utils.isNumber,
+ timers = [],
+ global = this,
+ NUMBER = /\d+/;
+
+ // In IE 6-8, try/finally doesn't work without a catch.
+ // Unfortunately, this is impossible to test for since wrapping it in a parent try/catch doesn't trigger the bug.
+ // This tests for another broken try/catch behavior that only exhibits in the same versions of IE.
+ var needsIETryCatchFix = (function(e,x){
+ try{ x(); }
+ catch(e) { } // jshint ignore:line
+ return !!e;
+ })();
+
+ function isCoercableNumber(number) {
+ return isNumber(number) || NUMBER.test(number);
+ }
+
+ function Backburner(queueNames, options) {
+ this.queueNames = queueNames;
+ this.options = options || {};
+ if (!this.options.defaultQueue) {
+ this.options.defaultQueue = queueNames[0];
+ }
+ this.instanceStack = [];
+ this._debouncees = [];
+ this._throttlers = [];
+ }
+
+ Backburner.prototype = {
+ queueNames: null,
+ options: null,
+ currentInstance: null,
+ instanceStack: null,
+
+ begin: function() {
+ var options = this.options,
+ onBegin = options && options.onBegin,
+ previousInstance = this.currentInstance;
+
+ if (previousInstance) {
+ this.instanceStack.push(previousInstance);
+ }
+
+ this.currentInstance = new DeferredActionQueues(this.queueNames, options);
+ if (onBegin) {
+ onBegin(this.currentInstance, previousInstance);
+ }
+ },
+
+ end: function() {
+ var options = this.options,
+ onEnd = options && options.onEnd,
+ currentInstance = this.currentInstance,
+ nextInstance = null;
+
+ // Prevent double-finally bug in Safari 6.0.2 and iOS 6
+ // This bug appears to be resolved in Safari 6.0.5 and iOS 7
+ var finallyAlreadyCalled = false;
+ try {
+ currentInstance.flush();
+ } finally {
+ if (!finallyAlreadyCalled) {
+ finallyAlreadyCalled = true;
+
+ this.currentInstance = null;
+
+ if (this.instanceStack.length) {
+ nextInstance = this.instanceStack.pop();
+ this.currentInstance = nextInstance;
+ }
+
+ if (onEnd) {
+ onEnd(currentInstance, nextInstance);
+ }
+ }
+ }
+ },
+
+ run: function(target, method /*, args */) {
+ var onError = getOnError(this.options);
+
+ this.begin();
+
+ if (!method) {
+ method = target;
+ target = null;
+ }
+
+ if (isString(method)) {
+ method = target[method];
+ }
+
+ var args = slice.call(arguments, 2);
+
+ // guard against Safari 6's double-finally bug
+ var didFinally = false;
+
+ if (onError) {
+ try {
+ return method.apply(target, args);
+ } catch(error) {
+ onError(error);
+ } finally {
+ if (!didFinally) {
+ didFinally = true;
+ this.end();
+ }
+ }
+ } else {
+ try {
+ return method.apply(target, args);
+ } finally {
+ if (!didFinally) {
+ didFinally = true;
+ this.end();
+ }
+ }
+ }
+ },
+
+ defer: function(queueName, target, method /* , args */) {
+ if (!method) {
+ method = target;
+ target = null;
+ }
+
+ if (isString(method)) {
+ method = target[method];
+ }
+
+ var stack = this.DEBUG ? new Error() : undefined,
+ args = arguments.length > 3 ? slice.call(arguments, 3) : undefined;
+ if (!this.currentInstance) { createAutorun(this); }
+ return this.currentInstance.schedule(queueName, target, method, args, false, stack);
+ },
+
+ deferOnce: function(queueName, target, method /* , args */) {
+ if (!method) {
+ method = target;
+ target = null;
+ }
+
+ if (isString(method)) {
+ method = target[method];
+ }
+
+ var stack = this.DEBUG ? new Error() : undefined,
+ args = arguments.length > 3 ? slice.call(arguments, 3) : undefined;
+ if (!this.currentInstance) { createAutorun(this); }
+ return this.currentInstance.schedule(queueName, target, method, args, true, stack);
+ },
+
+ setTimeout: function() {
+ var args = slice.call(arguments),
+ length = args.length,
+ method, wait, target,
+ methodOrTarget, methodOrWait, methodOrArgs;
+
+ if (length === 0) {
+ return;
+ } else if (length === 1) {
+ method = args.shift();
+ wait = 0;
+ } else if (length === 2) {
+ methodOrTarget = args[0];
+ methodOrWait = args[1];
+
+ if (isFunction(methodOrWait) || isFunction(methodOrTarget[methodOrWait])) {
+ target = args.shift();
+ method = args.shift();
+ wait = 0;
+ } else if (isCoercableNumber(methodOrWait)) {
+ method = args.shift();
+ wait = args.shift();
+ } else {
+ method = args.shift();
+ wait = 0;
+ }
+ } else {
+ var last = args[args.length - 1];
+
+ if (isCoercableNumber(last)) {
+ wait = args.pop();
+ } else {
+ wait = 0;
+ }
+
+ methodOrTarget = args[0];
+ methodOrArgs = args[1];
+
+ if (isFunction(methodOrArgs) || (isString(methodOrArgs) &&
+ methodOrTarget !== null &&
+ methodOrArgs in methodOrTarget)) {
+ target = args.shift();
+ method = args.shift();
+ } else {
+ method = args.shift();
+ }
+ }
+
+ var executeAt = (+new Date()) + parseInt(wait, 10);
+
+ if (isString(method)) {
+ method = target[method];
+ }
+
+ var onError = getOnError(this.options);
+
+ function fn() {
+ if (onError) {
+ try {
+ method.apply(target, args);
+ } catch (e) {
+ onError(e);
+ }
+ } else {
+ method.apply(target, args);
+ }
+ }
+
+ // find position to insert
+ var i = searchTimer(executeAt, timers);
+
+ timers.splice(i, 0, executeAt, fn);
+
+ updateLaterTimer(this, executeAt, wait);
+
+ return fn;
+ },
+
+ throttle: function(target, method /* , args, wait, [immediate] */) {
+ var self = this,
+ args = arguments,
+ immediate = pop.call(args),
+ wait,
+ throttler,
+ index,
+ timer;
+
+ if (isNumber(immediate) || isString(immediate)) {
+ wait = immediate;
+ immediate = true;
+ } else {
+ wait = pop.call(args);
+ }
+
+ wait = parseInt(wait, 10);
+
+ index = findThrottler(target, method, this._throttlers);
+ if (index > -1) { return this._throttlers[index]; } // throttled
+
+ timer = global.setTimeout(function() {
+ if (!immediate) {
+ self.run.apply(self, args);
+ }
+ var index = findThrottler(target, method, self._throttlers);
+ if (index > -1) {
+ self._throttlers.splice(index, 1);
+ }
+ }, wait);
+
+ if (immediate) {
+ self.run.apply(self, args);
+ }
+
+ throttler = [target, method, timer];
+
+ this._throttlers.push(throttler);
+
+ return throttler;
+ },
+
+ debounce: function(target, method /* , args, wait, [immediate] */) {
+ var self = this,
+ args = arguments,
+ immediate = pop.call(args),
+ wait,
+ index,
+ debouncee,
+ timer;
+
+ if (isNumber(immediate) || isString(immediate)) {
+ wait = immediate;
+ immediate = false;
+ } else {
+ wait = pop.call(args);
+ }
+
+ wait = parseInt(wait, 10);
+ // Remove debouncee
+ index = findDebouncee(target, method, this._debouncees);
+
+ if (index > -1) {
+ debouncee = this._debouncees[index];
+ this._debouncees.splice(index, 1);
+ clearTimeout(debouncee[2]);
+ }
+
+ timer = global.setTimeout(function() {
+ if (!immediate) {
+ self.run.apply(self, args);
+ }
+ var index = findDebouncee(target, method, self._debouncees);
+ if (index > -1) {
+ self._debouncees.splice(index, 1);
+ }
+ }, wait);
+
+ if (immediate && index === -1) {
+ self.run.apply(self, args);
+ }
+
+ debouncee = [target, method, timer];
+
+ self._debouncees.push(debouncee);
+
+ return debouncee;
+ },
+
+ cancelTimers: function() {
+ var clearItems = function(item) {
+ clearTimeout(item[2]);
+ };
+
+ each(this._throttlers, clearItems);
+ this._throttlers = [];
+
+ each(this._debouncees, clearItems);
+ this._debouncees = [];
+
+ if (this._laterTimer) {
+ clearTimeout(this._laterTimer);
+ this._laterTimer = null;
+ }
+ timers = [];
+
+ if (this._autorun) {
+ clearTimeout(this._autorun);
+ this._autorun = null;
+ }
+ },
+
+ hasTimers: function() {
+ return !!timers.length || !!this._debouncees.length || !!this._throttlers.length || this._autorun;
+ },
+
+ cancel: function(timer) {
+ var timerType = typeof timer;
+
+ if (timer && timerType === 'object' && timer.queue && timer.method) { // we're cancelling a deferOnce
+ return timer.queue.cancel(timer);
+ } else if (timerType === 'function') { // we're cancelling a setTimeout
+ for (var i = 0, l = timers.length; i < l; i += 2) {
+ if (timers[i + 1] === timer) {
+ timers.splice(i, 2); // remove the two elements
+ return true;
+ }
+ }
+ } else if (Object.prototype.toString.call(timer) === "[object Array]"){ // we're cancelling a throttle or debounce
+ return this._cancelItem(findThrottler, this._throttlers, timer) ||
+ this._cancelItem(findDebouncee, this._debouncees, timer);
+ } else {
+ return; // timer was null or not a timer
+ }
+ },
+
+ _cancelItem: function(findMethod, array, timer){
+ var item,
+ index;
+
+ if (timer.length < 3) { return false; }
+
+ index = findMethod(timer[0], timer[1], array);
+
+ if(index > -1) {
+
+ item = array[index];
+
+ if(item[2] === timer[2]){
+ array.splice(index, 1);
+ clearTimeout(timer[2]);
+ return true;
+ }
+ }
+
+ return false;
+ }
+ };
+
+ Backburner.prototype.schedule = Backburner.prototype.defer;
+ Backburner.prototype.scheduleOnce = Backburner.prototype.deferOnce;
+ Backburner.prototype.later = Backburner.prototype.setTimeout;
+
+ if (needsIETryCatchFix) {
+ var originalRun = Backburner.prototype.run;
+ Backburner.prototype.run = wrapInTryCatch(originalRun);
+
+ var originalEnd = Backburner.prototype.end;
+ Backburner.prototype.end = wrapInTryCatch(originalEnd);
+ }
+
+ function wrapInTryCatch(func) {
+ return function () {
+ try {
+ return func.apply(this, arguments);
+ } catch (e) {
+ throw e;
+ }
+ };
+ }
+
+ function getOnError(options) {
+ return options.onError || (options.onErrorTarget && options.onErrorTarget[options.onErrorMethod]);
+ }
+
+
+ function createAutorun(backburner) {
+ backburner.begin();
+ backburner._autorun = global.setTimeout(function() {
+ backburner._autorun = null;
+ backburner.end();
+ });
+ }
+
+ function updateLaterTimer(self, executeAt, wait) {
+ if (!self._laterTimer || executeAt < self._laterTimerExpiresAt) {
+ self._laterTimer = global.setTimeout(function() {
+ self._laterTimer = null;
+ self._laterTimerExpiresAt = null;
+ executeTimers(self);
+ }, wait);
+ self._laterTimerExpiresAt = executeAt;
+ }
+ }
+
+ function executeTimers(self) {
+ var now = +new Date(),
+ time, fns, i, l;
+
+ self.run(function() {
+ i = searchTimer(now, timers);
+
+ fns = timers.splice(0, i);
+
+ for (i = 1, l = fns.length; i < l; i += 2) {
+ self.schedule(self.options.defaultQueue, null, fns[i]);
+ }
+ });
+
+ if (timers.length) {
+ updateLaterTimer(self, timers[0], timers[0] - now);
+ }
+ }
+
+ function findDebouncee(target, method, debouncees) {
+ return findItem(target, method, debouncees);
+ }
+
+ function findThrottler(target, method, throttlers) {
+ return findItem(target, method, throttlers);
+ }
+
+ function findItem(target, method, collection) {
+ var item,
+ index = -1;
+
+ for (var i = 0, l = collection.length; i < l; i++) {
+ item = collection[i];
+ if (item[0] === target && item[1] === method) {
+ index = i;
+ break;
+ }
+ }
+
+ return index;
+ }
+
+ function searchTimer(time, timers) {
+ var start = 0,
+ end = timers.length - 2,
+ middle, l;
+
+ while (start < end) {
+ // since timers is an array of pairs 'l' will always
+ // be an integer
+ l = (end - start) / 2;
+
+ // compensate for the index in case even number
+ // of pairs inside timers
+ middle = start + l - (l % 2);
+
+ if (time >= timers[middle]) {
+ start = middle + 2;
+ } else {
+ end = middle;
+ }
+ }
+
+ return (time >= timers[start]) ? start + 2 : start;
+ }
+
+ __exports__.Backburner = Backburner;
+ });
+define("backburner/deferred_action_queues",
+ ["backburner/utils","backburner/queue","exports"],
+ function(__dependency1__, __dependency2__, __exports__) {
+ "use strict";
+ var Utils = __dependency1__["default"];
+ var Queue = __dependency2__.Queue;
+
+ var each = Utils.each,
+ isString = Utils.isString;
+
+ function DeferredActionQueues(queueNames, options) {
+ var queues = this.queues = {};
+ this.queueNames = queueNames = queueNames || [];
+
+ this.options = options;
+
+ each(queueNames, function(queueName) {
+ queues[queueName] = new Queue(this, queueName, options);
+ });
+ }
+
+ DeferredActionQueues.prototype = {
+ queueNames: null,
+ queues: null,
+ options: null,
+
+ schedule: function(queueName, target, method, args, onceFlag, stack) {
+ var queues = this.queues,
+ queue = queues[queueName];
+
+ if (!queue) { throw new Error("You attempted to schedule an action in a queue (" + queueName + ") that doesn't exist"); }
+
+ if (onceFlag) {
+ return queue.pushUnique(target, method, args, stack);
+ } else {
+ return queue.push(target, method, args, stack);
+ }
+ },
+
+ invoke: function(target, method, args, _) {
+ if (args && args.length > 0) {
+ method.apply(target, args);
+ } else {
+ method.call(target);
+ }
+ },
+
+ invokeWithOnError: function(target, method, args, onError) {
+ try {
+ if (args && args.length > 0) {
+ method.apply(target, args);
+ } else {
+ method.call(target);
+ }
+ } catch(error) {
+ onError(error);
+ }
+ },
+
+ flush: function() {
+ var queues = this.queues,
+ queueNames = this.queueNames,
+ queueName, queue, queueItems, priorQueueNameIndex,
+ queueNameIndex = 0, numberOfQueues = queueNames.length,
+ options = this.options,
+ onError = options.onError || (options.onErrorTarget && options.onErrorTarget[options.onErrorMethod]),
+ invoke = onError ? this.invokeWithOnError : this.invoke;
+
+ outerloop:
+ while (queueNameIndex < numberOfQueues) {
+ queueName = queueNames[queueNameIndex];
+ queue = queues[queueName];
+ queueItems = queue._queueBeingFlushed = queue._queue.slice();
+ queue._queue = [];
+
+ var queueOptions = queue.options, // TODO: write a test for this
+ before = queueOptions && queueOptions.before,
+ after = queueOptions && queueOptions.after,
+ target, method, args, stack,
+ queueIndex = 0, numberOfQueueItems = queueItems.length;
+
+ if (numberOfQueueItems && before) { before(); }
+
+ while (queueIndex < numberOfQueueItems) {
+ target = queueItems[queueIndex];
+ method = queueItems[queueIndex+1];
+ args = queueItems[queueIndex+2];
+ stack = queueItems[queueIndex+3]; // Debugging assistance
+
+ if (isString(method)) { method = target[method]; }
+
+ // method could have been nullified / canceled during flush
+ if (method) {
+ invoke(target, method, args, onError);
+ }
+
+ queueIndex += 4;
+ }
+
+ queue._queueBeingFlushed = null;
+ if (numberOfQueueItems && after) { after(); }
+
+ if ((priorQueueNameIndex = indexOfPriorQueueWithActions(this, queueNameIndex)) !== -1) {
+ queueNameIndex = priorQueueNameIndex;
+ continue outerloop;
+ }
+
+ queueNameIndex++;
+ }
+ }
+ };
+
+ function indexOfPriorQueueWithActions(daq, currentQueueIndex) {
+ var queueName, queue;
+
+ for (var i = 0, l = currentQueueIndex; i <= l; i++) {
+ queueName = daq.queueNames[i];
+ queue = daq.queues[queueName];
+ if (queue._queue.length) { return i; }
+ }
+
+ return -1;
+ }
+
+ __exports__.DeferredActionQueues = DeferredActionQueues;
+ });
+define("backburner/queue",
+ ["exports"],
+ function(__exports__) {
+ "use strict";
+ function Queue(daq, name, options) {
+ this.daq = daq;
+ this.name = name;
+ this.globalOptions = options;
+ this.options = options[name];
+ this._queue = [];
+ }
+
+ Queue.prototype = {
+ daq: null,
+ name: null,
+ options: null,
+ onError: null,
+ _queue: null,
+
+ push: function(target, method, args, stack) {
+ var queue = this._queue;
+ queue.push(target, method, args, stack);
+ return {queue: this, target: target, method: method};
+ },
+
+ pushUnique: function(target, method, args, stack) {
+ var queue = this._queue, currentTarget, currentMethod, i, l;
+
+ for (i = 0, l = queue.length; i < l; i += 4) {
+ currentTarget = queue[i];
+ currentMethod = queue[i+1];
+
+ if (currentTarget === target && currentMethod === method) {
+ queue[i+2] = args; // replace args
+ queue[i+3] = stack; // replace stack
+ return {queue: this, target: target, method: method};
+ }
+ }
+
+ queue.push(target, method, args, stack);
+ return {queue: this, target: target, method: method};
+ },
+
+ // TODO: remove me, only being used for Ember.run.sync
+ flush: function() {
+ var queue = this._queue,
+ globalOptions = this.globalOptions,
+ options = this.options,
+ before = options && options.before,
+ after = options && options.after,
+ onError = globalOptions.onError || (globalOptions.onErrorTarget && globalOptions.onErrorTarget[globalOptions.onErrorMethod]),
+ target, method, args, stack, i, l = queue.length;
+
+ if (l && before) { before(); }
+ for (i = 0; i < l; i += 4) {
+ target = queue[i];
+ method = queue[i+1];
+ args = queue[i+2];
+ stack = queue[i+3]; // Debugging assistance
+
+ // TODO: error handling
+ if (args && args.length > 0) {
+ if (onError) {
+ try {
+ method.apply(target, args);
+ } catch (e) {
+ onError(e);
+ }
+ } else {
+ method.apply(target, args);
+ }
+ } else {
+ if (onError) {
+ try {
+ method.call(target);
+ } catch(e) {
+ onError(e);
+ }
+ } else {
+ method.call(target);
+ }
+ }
+ }
+ if (l && after) { after(); }
+
+ // check if new items have been added
+ if (queue.length > l) {
+ this._queue = queue.slice(l);
+ this.flush();
+ } else {
+ this._queue.length = 0;
+ }
+ },
+
+ cancel: function(actionToCancel) {
+ var queue = this._queue, currentTarget, currentMethod, i, l;
+
+ for (i = 0, l = queue.length; i < l; i += 4) {
+ currentTarget = queue[i];
+ currentMethod = queue[i+1];
+
+ if (currentTarget === actionToCancel.target && currentMethod === actionToCancel.method) {
+ queue.splice(i, 4);
+ return true;
+ }
+ }
+
+ // if not found in current queue
+ // could be in the queue that is being flushed
+ queue = this._queueBeingFlushed;
+ if (!queue) {
+ return;
+ }
+ for (i = 0, l = queue.length; i < l; i += 4) {
+ currentTarget = queue[i];
+ currentMethod = queue[i+1];
+
+ if (currentTarget === actionToCancel.target && currentMethod === actionToCancel.method) {
+ // don't mess with array during flush
+ // just nullify the method
+ queue[i+1] = null;
+ return true;
+ }
+ }
+ }
+ };
+
+ __exports__.Queue = Queue;
+ });
+define("backburner/utils",
+ ["exports"],
+ function(__exports__) {
+ "use strict";
+ __exports__["default"] = {
+ each: function(collection, callback) {
+ for (var i = 0; i < collection.length; i++) {
+ callback(collection[i]);
+ }
+ },
+
+ isString: function(suspect) {
+ return typeof suspect === 'string';
+ },
+
+ isFunction: function(suspect) {
+ return typeof suspect === 'function';
+ },
+
+ isNumber: function(suspect) {
+ return typeof suspect === 'number';
+ }
+ };
+ });
+
+define("calculateVersion",
+ [],
+ function() {
+ "use strict";
+ 'use strict';
+
+ var fs = require('fs');
+ var path = require('path');
+
+ module.exports = function () {
+ var packageVersion = require('../package.json').version;
+ var output = [packageVersion];
+ var gitPath = path.join(__dirname,'..','.git');
+ var headFilePath = path.join(gitPath, 'HEAD');
+
+ if (packageVersion.indexOf('+') > -1) {
+ try {
+ if (fs.existsSync(headFilePath)) {
+ var headFile = fs.readFileSync(headFilePath, {encoding: 'utf8'});
+ var branchName = headFile.split('/').slice(-1)[0].trim();
+ var refPath = headFile.split(' ')[1];
+ var branchSHA;
+
+ if (refPath) {
+ var branchPath = path.join(gitPath, refPath.trim());
+ branchSHA = fs.readFileSync(branchPath);
+ } else {
+ branchSHA = branchName;
+ }
+
+ output.push(branchSHA.slice(0,10));
+ }
+ } catch (err) {
+ console.error(err.stack);
+ }
+ return output.join('.');
+ } else {
+ return packageVersion;
+ }
+ };
+ });
+define("container",
+ ["container/container","exports"],
+ function(__dependency1__, __exports__) {
+ "use strict";
+ /*
+ Public api for the container is still in flux.
+ The public api, specified on the application namespace should be considered the stable api.
+ // @module container
+ @private
+ */
+
+ /*
+ Flag to enable/disable model factory injections (disabled by default)
+ If model factory injections are enabled, models should not be
+ accessed globally (only through `container.lookupFactory('model:modelName'))`);
+ */
+ Ember.MODEL_FACTORY_INJECTIONS = false;
+
+ if (Ember.ENV && typeof Ember.ENV.MODEL_FACTORY_INJECTIONS !== 'undefined') {
+ Ember.MODEL_FACTORY_INJECTIONS = !!Ember.ENV.MODEL_FACTORY_INJECTIONS;
+ }
+
+
+ var Container = __dependency1__["default"];
+
+ __exports__["default"] = Container;
+ });
+define("container/container",
+ ["container/inheriting_dict","ember-metal/core","exports"],
+ function(__dependency1__, __dependency2__, __exports__) {
+ "use strict";
+ var InheritingDict = __dependency1__["default"];
+ var Ember = __dependency2__["default"];
+ // Ember.assert
+
+ // A lightweight container that helps to assemble and decouple components.
+ // Public api for the container is still in flux.
+ // The public api, specified on the application namespace should be considered the stable api.
+ function Container(parent) {
+ this.parent = parent;
+ this.children = [];
+
+ this.resolver = parent && parent.resolver || function() {};
+
+ this.registry = new InheritingDict(parent && parent.registry);
+ this.cache = new InheritingDict(parent && parent.cache);
+ this.factoryCache = new InheritingDict(parent && parent.factoryCache);
+ this.resolveCache = new InheritingDict(parent && parent.resolveCache);
+ this.typeInjections = new InheritingDict(parent && parent.typeInjections);
+ this.injections = {};
+
+ this.factoryTypeInjections = new InheritingDict(parent && parent.factoryTypeInjections);
+ this.factoryInjections = {};
+
+ this._options = new InheritingDict(parent && parent._options);
+ this._typeOptions = new InheritingDict(parent && parent._typeOptions);
+ }
+
+ Container.prototype = {
+
+ /**
+ @property parent
+ @type Container
+ @default null
+ */
+ parent: null,
+
+ /**
+ @property children
+ @type Array
+ @default []
+ */
+ children: null,
+
+ /**
+ @property resolver
+ @type function
+ */
+ resolver: null,
+
+ /**
+ @property registry
+ @type InheritingDict
+ */
+ registry: null,
+
+ /**
+ @property cache
+ @type InheritingDict
+ */
+ cache: null,
+
+ /**
+ @property typeInjections
+ @type InheritingDict
+ */
+ typeInjections: null,
+
+ /**
+ @property injections
+ @type Object
+ @default {}
+ */
+ injections: null,
+
+ /**
+ @private
+
+ @property _options
+ @type InheritingDict
+ @default null
+ */
+ _options: null,
+
+ /**
+ @private
+
+ @property _typeOptions
+ @type InheritingDict
+ */
+ _typeOptions: null,
+
+ /**
+ Returns a new child of the current container. These children are configured
+ to correctly inherit from the current container.
+
+ @method child
+ @return {Container}
+ */
+ child: function() {
+ var container = new Container(this);
+ this.children.push(container);
+ return container;
+ },
+
+ /**
+ Sets a key-value pair on the current container. If a parent container,
+ has the same key, once set on a child, the parent and child will diverge
+ as expected.
+
+ @method set
+ @param {Object} object
+ @param {String} key
+ @param {any} value
+ */
+ set: function(object, key, value) {
+ object[key] = value;
+ },
+
+ /**
+ Registers a factory for later injection.
+
+ Example:
+
+ ```javascript
+ var container = new Container();
+
+ container.register('model:user', Person, {singleton: false });
+ container.register('fruit:favorite', Orange);
+ container.register('communication:main', Email, {singleton: false});
+ ```
+
+ @method register
+ @param {String} fullName
+ @param {Function} factory
+ @param {Object} options
+ */
+ register: function(fullName, factory, options) {
+ Ember.assert('fullName must be a proper full name', validateFullName(fullName));
+
+ if (factory === undefined) {
+ throw new TypeError('Attempting to register an unknown factory: `' + fullName + '`');
+ }
+
+ var normalizedName = this.normalize(fullName);
+
+ if (this.cache.has(normalizedName)) {
+ throw new Error('Cannot re-register: `' + fullName +'`, as it has already been looked up.');
+ }
+
+ this.registry.set(normalizedName, factory);
+ this._options.set(normalizedName, options || {});
+ },
+
+ /**
+ Unregister a fullName
+
+ ```javascript
+ var container = new Container();
+ container.register('model:user', User);
+
+ container.lookup('model:user') instanceof User //=> true
+
+ container.unregister('model:user')
+ container.lookup('model:user') === undefined //=> true
+ ```
+
+ @method unregister
+ @param {String} fullName
+ */
+ unregister: function(fullName) {
+ Ember.assert('fullName must be a proper full name', validateFullName(fullName));
+
+ var normalizedName = this.normalize(fullName);
+
+ this.registry.remove(normalizedName);
+ this.cache.remove(normalizedName);
+ this.factoryCache.remove(normalizedName);
+ this.resolveCache.remove(normalizedName);
+ this._options.remove(normalizedName);
+ },
+
+ /**
+ Given a fullName return the corresponding factory.
+
+ By default `resolve` will retrieve the factory from
+ its container's registry.
+
+ ```javascript
+ var container = new Container();
+ container.register('api:twitter', Twitter);
+
+ container.resolve('api:twitter') // => Twitter
+ ```
+
+ Optionally the container can be provided with a custom resolver.
+ If provided, `resolve` will first provide the custom resolver
+ the opportunity to resolve the fullName, otherwise it will fallback
+ to the registry.
+
+ ```javascript
+ var container = new Container();
+ container.resolver = function(fullName) {
+ // lookup via the module system of choice
+ };
+
+ // the twitter factory is added to the module system
+ container.resolve('api:twitter') // => Twitter
+ ```
+
+ @method resolve
+ @param {String} fullName
+ @return {Function} fullName's factory
+ */
+ resolve: function(fullName) {
+ Ember.assert('fullName must be a proper full name', validateFullName(fullName));
+ return resolve(this, this.normalize(fullName));
+ },
+
+ /**
+ A hook that can be used to describe how the resolver will
+ attempt to find the factory.
+
+ For example, the default Ember `.describe` returns the full
+ class name (including namespace) where Ember's resolver expects
+ to find the `fullName`.
+
+ @method describe
+ @param {String} fullName
+ @return {string} described fullName
+ */
+ describe: function(fullName) {
+ return fullName;
+ },
+
+ /**
+ A hook to enable custom fullName normalization behaviour
+
+ @method normalize
+ @param {String} fullName
+ @return {string} normalized fullName
+ */
+ normalize: function(fullName) {
+ return fullName;
+ },
+
+ /**
+ @method makeToString
+
+ @param {any} factory
+ @param {string} fullName
+ @return {function} toString function
+ */
+ makeToString: function(factory, fullName) {
+ return factory.toString();
+ },
+
+ /**
+ Given a fullName return a corresponding instance.
+
+ The default behaviour is for lookup to return a singleton instance.
+ The singleton is scoped to the container, allowing multiple containers
+ to all have their own locally scoped singletons.
+
+ ```javascript
+ var container = new Container();
+ container.register('api:twitter', Twitter);
+
+ var twitter = container.lookup('api:twitter');
+
+ twitter instanceof Twitter; // => true
+
+ // by default the container will return singletons
+ var twitter2 = container.lookup('api:twitter');
+ twitter2 instanceof Twitter; // => true
+
+ twitter === twitter2; //=> true
+ ```
+
+ If singletons are not wanted an optional flag can be provided at lookup.
+
+ ```javascript
+ var container = new Container();
+ container.register('api:twitter', Twitter);
+
+ var twitter = container.lookup('api:twitter', { singleton: false });
+ var twitter2 = container.lookup('api:twitter', { singleton: false });
+
+ twitter === twitter2; //=> false
+ ```
+
+ @method lookup
+ @param {String} fullName
+ @param {Object} options
+ @return {any}
+ */
+ lookup: function(fullName, options) {
+ Ember.assert('fullName must be a proper full name', validateFullName(fullName));
+ return lookup(this, this.normalize(fullName), options);
+ },
+
+ /**
+ Given a fullName return the corresponding factory.
+
+ @method lookupFactory
+ @param {String} fullName
+ @return {any}
+ */
+ lookupFactory: function(fullName) {
+ Ember.assert('fullName must be a proper full name', validateFullName(fullName));
+ return factoryFor(this, this.normalize(fullName));
+ },
+
+ /**
+ Given a fullName check if the container is aware of its factory
+ or singleton instance.
+
+ @method has
+ @param {String} fullName
+ @return {Boolean}
+ */
+ has: function(fullName) {
+ Ember.assert('fullName must be a proper full name', validateFullName(fullName));
+ return has(this, this.normalize(fullName));
+ },
+
+ /**
+ Allow registering options for all factories of a type.
+
+ ```javascript
+ var container = new Container();
+
+ // if all of type `connection` must not be singletons
+ container.optionsForType('connection', { singleton: false });
+
+ container.register('connection:twitter', TwitterConnection);
+ container.register('connection:facebook', FacebookConnection);
+
+ var twitter = container.lookup('connection:twitter');
+ var twitter2 = container.lookup('connection:twitter');
+
+ twitter === twitter2; // => false
+
+ var facebook = container.lookup('connection:facebook');
+ var facebook2 = container.lookup('connection:facebook');
+
+ facebook === facebook2; // => false
+ ```
+
+ @method optionsForType
+ @param {String} type
+ @param {Object} options
+ */
+ optionsForType: function(type, options) {
+ if (this.parent) { illegalChildOperation('optionsForType'); }
+
+ this._typeOptions.set(type, options);
+ },
+
+ /**
+ @method options
+ @param {String} type
+ @param {Object} options
+ */
+ options: function(type, options) {
+ this.optionsForType(type, options);
+ },
+
+ /**
+ Used only via `injection`.
+
+ Provides a specialized form of injection, specifically enabling
+ all objects of one type to be injected with a reference to another
+ object.
+
+ For example, provided each object of type `controller` needed a `router`.
+ one would do the following:
+
+ ```javascript
+ var container = new Container();
+
+ container.register('router:main', Router);
+ container.register('controller:user', UserController);
+ container.register('controller:post', PostController);
+
+ container.typeInjection('controller', 'router', 'router:main');
+
+ var user = container.lookup('controller:user');
+ var post = container.lookup('controller:post');
+
+ user.router instanceof Router; //=> true
+ post.router instanceof Router; //=> true
+
+ // both controllers share the same router
+ user.router === post.router; //=> true
+ ```
+
+ @private
+ @method typeInjection
+ @param {String} type
+ @param {String} property
+ @param {String} fullName
+ */
+ typeInjection: function(type, property, fullName) {
+ Ember.assert('fullName must be a proper full name', validateFullName(fullName));
+ if (this.parent) { illegalChildOperation('typeInjection'); }
+
+ var fullNameType = fullName.split(':')[0];
+ if(fullNameType === type) {
+ throw new Error('Cannot inject a `' + fullName + '` on other ' + type + '(s). Register the `' + fullName + '` as a different type and perform the typeInjection.');
+ }
+ addTypeInjection(this.typeInjections, type, property, fullName);
+ },
+
+ /**
+ Defines injection rules.
+
+ These rules are used to inject dependencies onto objects when they
+ are instantiated.
+
+ Two forms of injections are possible:
+
+ * Injecting one fullName on another fullName
+ * Injecting one fullName on a type
+
+ Example:
+
+ ```javascript
+ var container = new Container();
+
+ container.register('source:main', Source);
+ container.register('model:user', User);
+ container.register('model:post', Post);
+
+ // injecting one fullName on another fullName
+ // eg. each user model gets a post model
+ container.injection('model:user', 'post', 'model:post');
+
+ // injecting one fullName on another type
+ container.injection('model', 'source', 'source:main');
+
+ var user = container.lookup('model:user');
+ var post = container.lookup('model:post');
+
+ user.source instanceof Source; //=> true
+ post.source instanceof Source; //=> true
+
+ user.post instanceof Post; //=> true
+
+ // and both models share the same source
+ user.source === post.source; //=> true
+ ```
+
+ @method injection
+ @param {String} factoryName
+ @param {String} property
+ @param {String} injectionName
+ */
+ injection: function(fullName, property, injectionName) {
+ if (this.parent) { illegalChildOperation('injection'); }
+
+ validateFullName(injectionName);
+ var normalizedInjectionName = this.normalize(injectionName);
+
+ if (fullName.indexOf(':') === -1) {
+ return this.typeInjection(fullName, property, normalizedInjectionName);
+ }
+
+ Ember.assert('fullName must be a proper full name', validateFullName(fullName));
+ var normalizedName = this.normalize(fullName);
+
+ if (this.cache.has(normalizedName)) {
+ throw new Error("Attempted to register an injection for a type that has already been looked up. ('" + normalizedName + "', '" + property + "', '" + injectionName + "')");
+ }
+ addInjection(this.injections, normalizedName, property, normalizedInjectionName);
+ },
+
+
+ /**
+ Used only via `factoryInjection`.
+
+ Provides a specialized form of injection, specifically enabling
+ all factory of one type to be injected with a reference to another
+ object.
+
+ For example, provided each factory of type `model` needed a `store`.
+ one would do the following:
+
+ ```javascript
+ var container = new Container();
+
+ container.register('store:main', SomeStore);
+
+ container.factoryTypeInjection('model', 'store', 'store:main');
+
+ var store = container.lookup('store:main');
+ var UserFactory = container.lookupFactory('model:user');
+
+ UserFactory.store instanceof SomeStore; //=> true
+ ```
+
+ @private
+ @method factoryTypeInjection
+ @param {String} type
+ @param {String} property
+ @param {String} fullName
+ */
+ factoryTypeInjection: function(type, property, fullName) {
+ if (this.parent) { illegalChildOperation('factoryTypeInjection'); }
+
+ addTypeInjection(this.factoryTypeInjections, type, property, this.normalize(fullName));
+ },
+
+ /**
+ Defines factory injection rules.
+
+ Similar to regular injection rules, but are run against factories, via
+ `Container#lookupFactory`.
+
+ These rules are used to inject objects onto factories when they
+ are looked up.
+
+ Two forms of injections are possible:
+
+ * Injecting one fullName on another fullName
+ * Injecting one fullName on a type
+
+ Example:
+
+ ```javascript
+ var container = new Container();
+
+ container.register('store:main', Store);
+ container.register('store:secondary', OtherStore);
+ container.register('model:user', User);
+ container.register('model:post', Post);
+
+ // injecting one fullName on another type
+ container.factoryInjection('model', 'store', 'store:main');
+
+ // injecting one fullName on another fullName
+ container.factoryInjection('model:post', 'secondaryStore', 'store:secondary');
+
+ var UserFactory = container.lookupFactory('model:user');
+ var PostFactory = container.lookupFactory('model:post');
+ var store = container.lookup('store:main');
+
+ UserFactory.store instanceof Store; //=> true
+ UserFactory.secondaryStore instanceof OtherStore; //=> false
+
+ PostFactory.store instanceof Store; //=> true
+ PostFactory.secondaryStore instanceof OtherStore; //=> true
+
+ // and both models share the same source instance
+ UserFactory.store === PostFactory.store; //=> true
+ ```
+
+ @method factoryInjection
+ @param {String} factoryName
+ @param {String} property
+ @param {String} injectionName
+ */
+ factoryInjection: function(fullName, property, injectionName) {
+ if (this.parent) { illegalChildOperation('injection'); }
+
+ var normalizedName = this.normalize(fullName);
+ var normalizedInjectionName = this.normalize(injectionName);
+
+ validateFullName(injectionName);
+
+ if (fullName.indexOf(':') === -1) {
+ return this.factoryTypeInjection(normalizedName, property, normalizedInjectionName);
+ }
+
+ Ember.assert('fullName must be a proper full name', validateFullName(fullName));
+
+ if (this.factoryCache.has(normalizedName)) {
+ throw new Error('Attempted to register a factoryInjection for a type that has already ' +
+ 'been looked up. (\'' + normalizedName + '\', \'' + property + '\', \'' + injectionName + '\')');
+ }
+
+ addInjection(this.factoryInjections, normalizedName, property, normalizedInjectionName);
+ },
+
+ /**
+ A depth first traversal, destroying the container, its descendant containers and all
+ their managed objects.
+
+ @method destroy
+ */
+ destroy: function() {
+ for (var i = 0, length = this.children.length; i < length; i++) {
+ this.children[i].destroy();
+ }
+
+ this.children = [];
+
+ eachDestroyable(this, function(item) {
+ item.destroy();
+ });
+
+ this.parent = undefined;
+ this.isDestroyed = true;
+ },
+
+ /**
+ @method reset
+ */
+ reset: function() {
+ for (var i = 0, length = this.children.length; i < length; i++) {
+ resetCache(this.children[i]);
+ }
+
+ resetCache(this);
+ }
+ };
+
+ function resolve(container, normalizedName) {
+ var cached = container.resolveCache.get(normalizedName);
+ if (cached) { return cached; }
+
+ var resolved = container.resolver(normalizedName) || container.registry.get(normalizedName);
+ container.resolveCache.set(normalizedName, resolved);
+
+ return resolved;
+ }
+
+ function has(container, fullName){
+ if (container.cache.has(fullName)) {
+ return true;
+ }
+
+ return !!container.resolve(fullName);
+ }
+
+ function lookup(container, fullName, options) {
+ options = options || {};
+
+ if (container.cache.has(fullName) && options.singleton !== false) {
+ return container.cache.get(fullName);
+ }
+
+ var value = instantiate(container, fullName);
+
+ if (value === undefined) { return; }
+
+ if (isSingleton(container, fullName) && options.singleton !== false) {
+ container.cache.set(fullName, value);
+ }
+
+ return value;
+ }
+
+ function illegalChildOperation(operation) {
+ throw new Error(operation + ' is not currently supported on child containers');
+ }
+
+ function isSingleton(container, fullName) {
+ var singleton = option(container, fullName, 'singleton');
+
+ return singleton !== false;
+ }
+
+ function buildInjections(container, injections) {
+ var hash = {};
+
+ if (!injections) { return hash; }
+
+ var injection, injectable;
+
+ for (var i = 0, length = injections.length; i < length; i++) {
+ injection = injections[i];
+ injectable = lookup(container, injection.fullName);
+
+ if (injectable !== undefined) {
+ hash[injection.property] = injectable;
+ } else {
+ throw new Error('Attempting to inject an unknown injection: `' + injection.fullName + '`');
+ }
+ }
+
+ return hash;
+ }
+
+ function option(container, fullName, optionName) {
+ var options = container._options.get(fullName);
+
+ if (options && options[optionName] !== undefined) {
+ return options[optionName];
+ }
+
+ var type = fullName.split(':')[0];
+ options = container._typeOptions.get(type);
+
+ if (options) {
+ return options[optionName];
+ }
+ }
+
+ function factoryFor(container, fullName) {
+ var cache = container.factoryCache;
+ if (cache.has(fullName)) {
+ return cache.get(fullName);
+ }
+ var factory = container.resolve(fullName);
+ if (factory === undefined) { return; }
+
+ var type = fullName.split(':')[0];
+ if (!factory || typeof factory.extend !== 'function' || (!Ember.MODEL_FACTORY_INJECTIONS && type === 'model')) {
+ // TODO: think about a 'safe' merge style extension
+ // for now just fallback to create time injection
+ return factory;
+ } else {
+ var injections = injectionsFor(container, fullName);
+ var factoryInjections = factoryInjectionsFor(container, fullName);
+
+ factoryInjections._toString = container.makeToString(factory, fullName);
+
+ var injectedFactory = factory.extend(injections);
+ injectedFactory.reopenClass(factoryInjections);
+
+ cache.set(fullName, injectedFactory);
+
+ return injectedFactory;
+ }
+ }
+
+ function injectionsFor(container, fullName) {
+ var splitName = fullName.split(':'),
+ type = splitName[0],
+ injections = [];
+
+ injections = injections.concat(container.typeInjections.get(type) || []);
+ injections = injections.concat(container.injections[fullName] || []);
+
+ injections = buildInjections(container, injections);
+ injections._debugContainerKey = fullName;
+ injections.container = container;
+
+ return injections;
+ }
+
+ function factoryInjectionsFor(container, fullName) {
+ var splitName = fullName.split(':'),
+ type = splitName[0],
+ factoryInjections = [];
+
+ factoryInjections = factoryInjections.concat(container.factoryTypeInjections.get(type) || []);
+ factoryInjections = factoryInjections.concat(container.factoryInjections[fullName] || []);
+
+ factoryInjections = buildInjections(container, factoryInjections);
+ factoryInjections._debugContainerKey = fullName;
+
+ return factoryInjections;
+ }
+
+ function instantiate(container, fullName) {
+ var factory = factoryFor(container, fullName);
+
+ if (option(container, fullName, 'instantiate') === false) {
+ return factory;
+ }
+
+ if (factory) {
+ if (typeof factory.create !== 'function') {
+ throw new Error('Failed to create an instance of \'' + fullName + '\'. ' +
+ 'Most likely an improperly defined class or an invalid module export.');
+ }
+
+ if (typeof factory.extend === 'function') {
+ // assume the factory was extendable and is already injected
+ return factory.create();
+ } else {
+ // assume the factory was extendable
+ // to create time injections
+ // TODO: support new'ing for instantiation and merge injections for pure JS Functions
+ return factory.create(injectionsFor(container, fullName));
+ }
+ }
+ }
+
+ function eachDestroyable(container, callback) {
+ container.cache.eachLocal(function(key, value) {
+ if (option(container, key, 'instantiate') === false) { return; }
+ callback(value);
+ });
+ }
+
+ function resetCache(container) {
+ container.cache.eachLocal(function(key, value) {
+ if (option(container, key, 'instantiate') === false) { return; }
+ value.destroy();
+ });
+ container.cache.dict = {};
+ }
+
+ function addTypeInjection(rules, type, property, fullName) {
+ var injections = rules.get(type);
+
+ if (!injections) {
+ injections = [];
+ rules.set(type, injections);
+ }
+
+ injections.push({
+ property: property,
+ fullName: fullName
+ });
+ }
+
+ var VALID_FULL_NAME_REGEXP = /^[^:]+.+:[^:]+$/;
+ function validateFullName(fullName) {
+ if (!VALID_FULL_NAME_REGEXP.test(fullName)) {
+ throw new TypeError('Invalid Fullname, expected: `type:name` got: ' + fullName);
+ }
+ return true;
+ }
+
+ function addInjection(rules, factoryName, property, injectionName) {
+ var injections = rules[factoryName] = rules[factoryName] || [];
+ injections.push({ property: property, fullName: injectionName });
+ }
+
+ __exports__["default"] = Container;
+ });
+define("container/inheriting_dict",
+ ["exports"],
+ function(__exports__) {
+ "use strict";
+ // A safe and simple inheriting object.
+ function InheritingDict(parent) {
+ this.parent = parent;
+ this.dict = {};
+ }
+
+ InheritingDict.prototype = {
+
+ /**
+ @property parent
+ @type InheritingDict
+ @default null
+ */
+
+ parent: null,
+
+ /**
+ Object used to store the current nodes data.
+
+ @property dict
+ @type Object
+ @default Object
+ */
+ dict: null,
+
+ /**
+ Retrieve the value given a key, if the value is present at the current
+ level use it, otherwise walk up the parent hierarchy and try again. If
+ no matching key is found, return undefined.
+
+ @method get
+ @param {String} key
+ @return {any}
+ */
+ get: function(key) {
+ var dict = this.dict;
+
+ if (dict.hasOwnProperty(key)) {
+ return dict[key];
+ }
+
+ if (this.parent) {
+ return this.parent.get(key);
+ }
+ },
+
+ /**
+ Set the given value for the given key, at the current level.
+
+ @method set
+ @param {String} key
+ @param {Any} value
+ */
+ set: function(key, value) {
+ this.dict[key] = value;
+ },
+
+ /**
+ Delete the given key
+
+ @method remove
+ @param {String} key
+ */
+ remove: function(key) {
+ delete this.dict[key];
+ },
+
+ /**
+ Check for the existence of given a key, if the key is present at the current
+ level return true, otherwise walk up the parent hierarchy and try again. If
+ no matching key is found, return false.
+
+ @method has
+ @param {String} key
+ @return {Boolean}
+ */
+ has: function(key) {
+ var dict = this.dict;
+
+ if (dict.hasOwnProperty(key)) {
+ return true;
+ }
+
+ if (this.parent) {
+ return this.parent.has(key);
+ }
+
+ return false;
+ },
+
+ /**
+ Iterate and invoke a callback for each local key-value pair.
+
+ @method eachLocal
+ @param {Function} callback
+ @param {Object} binding
+ */
+ eachLocal: function(callback, binding) {
+ var dict = this.dict;
+
+ for (var prop in dict) {
+ if (dict.hasOwnProperty(prop)) {
+ callback.call(binding, prop, dict[prop]);
+ }
+ }
+ }
+ };
+
+ __exports__["default"] = InheritingDict;
+ });
+define("ember-application",
+ ["ember-metal/core","ember-runtime/system/lazy_load","ember-application/system/dag","ember-application/system/resolver","ember-application/system/application","ember-application/ext/controller"],
+ function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__) {
+ "use strict";
+ var Ember = __dependency1__["default"];
+ var runLoadHooks = __dependency2__.runLoadHooks;
+
+ /**
+ Ember Application
+
+ @module ember
+ @submodule ember-application
+ @requires ember-views, ember-routing
+ */
+
+ var DAG = __dependency3__["default"];
+ var Resolver = __dependency4__.Resolver;
+ var DefaultResolver = __dependency4__["default"];
+ var Application = __dependency5__["default"];
+ // side effect of extending ControllerMixin
+
+ Ember.Application = Application;
+ Ember.DAG = DAG;
+ Ember.Resolver = Resolver;
+ Ember.DefaultResolver = DefaultResolver;
+
+ runLoadHooks('Ember.Application', Application);
+ });
+define("ember-application/ext/controller",
+ ["ember-metal/core","ember-metal/property_get","ember-metal/property_set","ember-metal/error","ember-metal/utils","ember-metal/computed","ember-runtime/mixins/controller","ember-routing/system/controller_for","exports"],
+ function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __exports__) {
+ "use strict";
+ /**
+ @module ember
+ @submodule ember-application
+ */
+
+ var Ember = __dependency1__["default"];
+ // Ember.assert
+ var get = __dependency2__.get;
+ var set = __dependency3__.set;
+ var EmberError = __dependency4__["default"];
+ var inspect = __dependency5__.inspect;
+ var computed = __dependency6__.computed;
+ var ControllerMixin = __dependency7__["default"];
+ var meta = __dependency5__.meta;
+ var controllerFor = __dependency8__["default"];
+
+ function verifyNeedsDependencies(controller, container, needs) {
+ var dependency, i, l, missing = [];
+
+ for (i=0, l=needs.length; i 1 ? 'they' : 'it') + " could not be found");
+ }
+ }
+
+ var defaultControllersComputedProperty = computed(function() {
+ var controller = this;
+
+ return {
+ needs: get(controller, 'needs'),
+ container: get(controller, 'container'),
+ unknownProperty: function(controllerName) {
+ var needs = this.needs,
+ dependency, i, l;
+ for (i=0, l=needs.length; i 0) {
+ Ember.assert(' `' + inspect(this) + ' specifies `needs`, but does ' +
+ "not have a container. Please ensure this controller was " +
+ "instantiated with a container.",
+ this.container || meta(this, false).descs.controllers !== defaultControllersComputedProperty);
+
+ if (this.container) {
+ verifyNeedsDependencies(this, this.container, needs);
+ }
+
+ // if needs then initialize controllers proxy
+ get(this, 'controllers');
+ }
+
+ this._super.apply(this, arguments);
+ },
+
+ /**
+ @method controllerFor
+ @see {Ember.Route#controllerFor}
+ @deprecated Use `needs` instead
+ */
+ controllerFor: function(controllerName) {
+ Ember.deprecate("Controller#controllerFor is deprecated, please use Controller#needs instead");
+ return controllerFor(get(this, 'container'), controllerName);
+ },
+
+ /**
+ Stores the instances of other controllers available from within
+ this controller. Any controller listed by name in the `needs`
+ property will be accessible by name through this property.
+
+ ```javascript
+ App.CommentsController = Ember.ArrayController.extend({
+ needs: ['post'],
+ postTitle: function(){
+ var currentPost = this.get('controllers.post'); // instance of App.PostController
+ return currentPost.get('title');
+ }.property('controllers.post.title')
+ });
+ ```
+
+ @see {Ember.ControllerMixin#needs}
+ @property {Object} controllers
+ @default null
+ */
+ controllers: defaultControllersComputedProperty
+ });
+
+ __exports__["default"] = ControllerMixin;
+ });
+define("ember-application/system/application",
+ ["ember-metal","ember-metal/property_get","ember-metal/property_set","ember-runtime/system/lazy_load","ember-application/system/dag","ember-runtime/system/namespace","ember-runtime/mixins/deferred","ember-application/system/resolver","ember-metal/platform","ember-metal/run_loop","ember-metal/utils","container/container","ember-runtime/controllers/controller","ember-metal/enumerable_utils","ember-runtime/controllers/object_controller","ember-runtime/controllers/array_controller","ember-views/system/event_dispatcher","ember-views/system/jquery","ember-routing/system/route","ember-routing/system/router","ember-routing/location/hash_location","ember-routing/location/history_location","ember-routing/location/auto_location","ember-routing/location/none_location","ember-routing/system/cache","ember-metal/core","ember-handlebars-compiler","exports"],
+ function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __dependency15__, __dependency16__, __dependency17__, __dependency18__, __dependency19__, __dependency20__, __dependency21__, __dependency22__, __dependency23__, __dependency24__, __dependency25__, __dependency26__, __dependency27__, __exports__) {
+ "use strict";
+ /**
+ @module ember
+ @submodule ember-application
+ */
+
+ var Ember = __dependency1__["default"];
+ // Ember.FEATURES, Ember.deprecate, Ember.assert, Ember.libraries, LOG_VERSION, Namespace, BOOTED
+ var get = __dependency2__.get;
+ var set = __dependency3__.set;
+ var runLoadHooks = __dependency4__.runLoadHooks;
+ var DAG = __dependency5__["default"];
+ var Namespace = __dependency6__["default"];
+ var DeferredMixin = __dependency7__["default"];
+ var DefaultResolver = __dependency8__["default"];
+ var create = __dependency9__.create;
+ var run = __dependency10__["default"];
+ var canInvoke = __dependency11__.canInvoke;
+ var Container = __dependency12__["default"];
+ var Controller = __dependency13__["default"];
+ var EnumerableUtils = __dependency14__["default"];
+ var ObjectController = __dependency15__["default"];
+ var ArrayController = __dependency16__["default"];
+ var EventDispatcher = __dependency17__["default"];
+ //import ContainerDebugAdapter from "ember-extension-support/container_debug_adapter";
+ var jQuery = __dependency18__["default"];
+ var Route = __dependency19__["default"];
+ var Router = __dependency20__["default"];
+ var HashLocation = __dependency21__["default"];
+ var HistoryLocation = __dependency22__["default"];
+ var AutoLocation = __dependency23__["default"];
+ var NoneLocation = __dependency24__["default"];
+ var BucketCache = __dependency25__["default"];
+
+ var K = __dependency26__.K;
+ var EmberHandlebars = __dependency27__["default"];
+
+ var ContainerDebugAdapter;
+
+ /**
+ An instance of `Ember.Application` is the starting point for every Ember
+ application. It helps to instantiate, initialize and coordinate the many
+ objects that make up your app.
+
+ Each Ember app has one and only one `Ember.Application` object. In fact, the
+ very first thing you should do in your application is create the instance:
+
+ ```javascript
+ window.App = Ember.Application.create();
+ ```
+
+ Typically, the application object is the only global variable. All other
+ classes in your app should be properties on the `Ember.Application` instance,
+ which highlights its first role: a global namespace.
+
+ For example, if you define a view class, it might look like this:
+
+ ```javascript
+ App.MyView = Ember.View.extend();
+ ```
+
+ By default, calling `Ember.Application.create()` will automatically initialize
+ your application by calling the `Ember.Application.initialize()` method. If
+ you need to delay initialization, you can call your app's `deferReadiness()`
+ method. When you are ready for your app to be initialized, call its
+ `advanceReadiness()` method.
+
+ You can define a `ready` method on the `Ember.Application` instance, which
+ will be run by Ember when the application is initialized.
+
+ Because `Ember.Application` inherits from `Ember.Namespace`, any classes
+ you create will have useful string representations when calling `toString()`.
+ See the `Ember.Namespace` documentation for more information.
+
+ While you can think of your `Ember.Application` as a container that holds the
+ other classes in your application, there are several other responsibilities
+ going on under-the-hood that you may want to understand.
+
+ ### Event Delegation
+
+ Ember uses a technique called _event delegation_. This allows the framework
+ to set up a global, shared event listener instead of requiring each view to
+ do it manually. For example, instead of each view registering its own
+ `mousedown` listener on its associated element, Ember sets up a `mousedown`
+ listener on the `body`.
+
+ If a `mousedown` event occurs, Ember will look at the target of the event and
+ start walking up the DOM node tree, finding corresponding views and invoking
+ their `mouseDown` method as it goes.
+
+ `Ember.Application` has a number of default events that it listens for, as
+ well as a mapping from lowercase events to camel-cased view method names. For
+ example, the `keypress` event causes the `keyPress` method on the view to be
+ called, the `dblclick` event causes `doubleClick` to be called, and so on.
+
+ If there is a bubbling browser event that Ember does not listen for by
+ default, you can specify custom events and their corresponding view method
+ names by setting the application's `customEvents` property:
+
+ ```javascript
+ App = Ember.Application.create({
+ customEvents: {
+ // add support for the paste event
+ paste: "paste"
+ }
+ });
+ ```
+
+ By default, the application sets up these event listeners on the document
+ body. However, in cases where you are embedding an Ember application inside
+ an existing page, you may want it to set up the listeners on an element
+ inside the body.
+
+ For example, if only events inside a DOM element with the ID of `ember-app`
+ should be delegated, set your application's `rootElement` property:
+
+ ```javascript
+ window.App = Ember.Application.create({
+ rootElement: '#ember-app'
+ });
+ ```
+
+ The `rootElement` can be either a DOM element or a jQuery-compatible selector
+ string. Note that *views appended to the DOM outside the root element will
+ not receive events.* If you specify a custom root element, make sure you only
+ append views inside it!
+
+ To learn more about the advantages of event delegation and the Ember view
+ layer, and a list of the event listeners that are setup by default, visit the
+ [Ember View Layer guide](http://emberjs.com/guides/understanding-ember/the-view-layer/#toc_event-delegation).
+
+ ### Initializers
+
+ Libraries on top of Ember can add initializers, like so:
+
+ ```javascript
+ Ember.Application.initializer({
+ name: 'api-adapter',
+
+ initialize: function(container, application) {
+ application.register('api-adapter:main', ApiAdapter);
+ }
+ });
+ ```
+
+ Initializers provide an opportunity to access the container, which
+ organizes the different components of an Ember application. Additionally
+ they provide a chance to access the instantiated application. Beyond
+ being used for libraries, initializers are also a great way to organize
+ dependency injection or setup in your own application.
+
+ ### Routing
+
+ In addition to creating your application's router, `Ember.Application` is
+ also responsible for telling the router when to start routing. Transitions
+ between routes can be logged with the `LOG_TRANSITIONS` flag, and more
+ detailed intra-transition logging can be logged with
+ the `LOG_TRANSITIONS_INTERNAL` flag:
+
+ ```javascript
+ window.App = Ember.Application.create({
+ LOG_TRANSITIONS: true, // basic logging of successful transitions
+ LOG_TRANSITIONS_INTERNAL: true // detailed logging of all routing steps
+ });
+ ```
+
+ By default, the router will begin trying to translate the current URL into
+ application state once the browser emits the `DOMContentReady` event. If you
+ need to defer routing, you can call the application's `deferReadiness()`
+ method. Once routing can begin, call the `advanceReadiness()` method.
+
+ If there is any setup required before routing begins, you can implement a
+ `ready()` method on your app that will be invoked immediately before routing
+ begins.
+ ```
+
+ @class Application
+ @namespace Ember
+ @extends Ember.Namespace
+ */
+
+ var Application = Namespace.extend(DeferredMixin, {
+ _suppressDeferredDeprecation: true,
+
+ /**
+ The root DOM element of the Application. This can be specified as an
+ element or a
+ [jQuery-compatible selector string](http://api.jquery.com/category/selectors/).
+
+ This is the element that will be passed to the Application's,
+ `eventDispatcher`, which sets up the listeners for event delegation. Every
+ view in your application should be a child of the element you specify here.
+
+ @property rootElement
+ @type DOMElement
+ @default 'body'
+ */
+ rootElement: 'body',
+
+ /**
+ The `Ember.EventDispatcher` responsible for delegating events to this
+ application's views.
+
+ The event dispatcher is created by the application at initialization time
+ and sets up event listeners on the DOM element described by the
+ application's `rootElement` property.
+
+ See the documentation for `Ember.EventDispatcher` for more information.
+
+ @property eventDispatcher
+ @type Ember.EventDispatcher
+ @default null
+ */
+ eventDispatcher: null,
+
+ /**
+ The DOM events for which the event dispatcher should listen.
+
+ By default, the application's `Ember.EventDispatcher` listens
+ for a set of standard DOM events, such as `mousedown` and
+ `keyup`, and delegates them to your application's `Ember.View`
+ instances.
+
+ If you would like additional bubbling events to be delegated to your
+ views, set your `Ember.Application`'s `customEvents` property
+ to a hash containing the DOM event name as the key and the
+ corresponding view method name as the value. For example:
+
+ ```javascript
+ App = Ember.Application.create({
+ customEvents: {
+ // add support for the paste event
+ paste: "paste"
+ }
+ });
+ ```
+
+ @property customEvents
+ @type Object
+ @default null
+ */
+ customEvents: null,
+
+ // Start off the number of deferrals at 1. This will be
+ // decremented by the Application's own `initialize` method.
+ _readinessDeferrals: 1,
+
+ init: function() {
+ if (!this.$) { this.$ = jQuery; }
+ this.__container__ = this.buildContainer();
+
+ this.Router = this.defaultRouter();
+
+ this._super();
+
+ this.scheduleInitialize();
+
+ Ember.libraries.registerCoreLibrary('Handlebars', EmberHandlebars.VERSION);
+ Ember.libraries.registerCoreLibrary('jQuery', jQuery().jquery);
+
+ if ( Ember.LOG_VERSION ) {
+ Ember.LOG_VERSION = false; // we only need to see this once per Application#init
+
+ var nameLengths = EnumerableUtils.map(Ember.libraries, function(item) {
+ return get(item, "name.length");
+ });
+
+ var maxNameLength = Math.max.apply(this, nameLengths);
+
+ Ember.debug('-------------------------------');
+ Ember.libraries.each(function(name, version) {
+ var spaces = new Array(maxNameLength - name.length + 1).join(" ");
+ Ember.debug([name, spaces, ' : ', version].join(""));
+ });
+ Ember.debug('-------------------------------');
+ }
+ },
+
+ /**
+ Build the container for the current application.
+
+ Also register a default application view in case the application
+ itself does not.
+
+ @private
+ @method buildContainer
+ @return {Ember.Container} the configured container
+ */
+ buildContainer: function() {
+ var container = this.__container__ = Application.buildContainer(this);
+
+ return container;
+ },
+
+ /**
+ If the application has not opted out of routing and has not explicitly
+ defined a router, supply a default router for the application author
+ to configure.
+
+ This allows application developers to do:
+
+ ```javascript
+ var App = Ember.Application.create();
+
+ App.Router.map(function() {
+ this.resource('posts');
+ });
+ ```
+
+ @private
+ @method defaultRouter
+ @return {Ember.Router} the default router
+ */
+
+ defaultRouter: function() {
+ if (this.Router === false) { return; }
+ var container = this.__container__;
+
+ if (this.Router) {
+ container.unregister('router:main');
+ container.register('router:main', this.Router);
+ }
+
+ return container.lookupFactory('router:main');
+ },
+
+ /**
+ Automatically initialize the application once the DOM has
+ become ready.
+
+ The initialization itself is scheduled on the actions queue
+ which ensures that application loading finishes before
+ booting.
+
+ If you are asynchronously loading code, you should call
+ `deferReadiness()` to defer booting, and then call
+ `advanceReadiness()` once all of your code has finished
+ loading.
+
+ @private
+ @method scheduleInitialize
+ */
+ scheduleInitialize: function() {
+ var self = this;
+
+ if (!this.$ || this.$.isReady) {
+ run.schedule('actions', self, '_initialize');
+ } else {
+ this.$().ready(function runInitialize() {
+ run(self, '_initialize');
+ });
+ }
+ },
+
+ /**
+ Use this to defer readiness until some condition is true.
+
+ Example:
+
+ ```javascript
+ App = Ember.Application.create();
+ App.deferReadiness();
+
+ jQuery.getJSON("/auth-token", function(token) {
+ App.token = token;
+ App.advanceReadiness();
+ });
+ ```
+
+ This allows you to perform asynchronous setup logic and defer
+ booting your application until the setup has finished.
+
+ However, if the setup requires a loading UI, it might be better
+ to use the router for this purpose.
+
+ @method deferReadiness
+ */
+ deferReadiness: function() {
+ Ember.assert("You must call deferReadiness on an instance of Ember.Application", this instanceof Application);
+ Ember.assert("You cannot defer readiness since the `ready()` hook has already been called.", this._readinessDeferrals > 0);
+ this._readinessDeferrals++;
+ },
+
+ /**
+ Call `advanceReadiness` after any asynchronous setup logic has completed.
+ Each call to `deferReadiness` must be matched by a call to `advanceReadiness`
+ or the application will never become ready and routing will not begin.
+
+ @method advanceReadiness
+ @see {Ember.Application#deferReadiness}
+ */
+ advanceReadiness: function() {
+ Ember.assert("You must call advanceReadiness on an instance of Ember.Application", this instanceof Application);
+ this._readinessDeferrals--;
+
+ if (this._readinessDeferrals === 0) {
+ run.once(this, this.didBecomeReady);
+ }
+ },
+
+ /**
+ Registers a factory that can be used for dependency injection (with
+ `App.inject`) or for service lookup. Each factory is registered with
+ a full name including two parts: `type:name`.
+
+ A simple example:
+
+ ```javascript
+ var App = Ember.Application.create();
+ App.Orange = Ember.Object.extend();
+ App.register('fruit:favorite', App.Orange);
+ ```
+
+ Ember will resolve factories from the `App` namespace automatically.
+ For example `App.CarsController` will be discovered and returned if
+ an application requests `controller:cars`.
+
+ An example of registering a controller with a non-standard name:
+
+ ```javascript
+ var App = Ember.Application.create(),
+ Session = Ember.Controller.extend();
+
+ App.register('controller:session', Session);
+
+ // The Session controller can now be treated like a normal controller,
+ // despite its non-standard name.
+ App.ApplicationController = Ember.Controller.extend({
+ needs: ['session']
+ });
+ ```
+
+ Registered factories are **instantiated** by having `create`
+ called on them. Additionally they are **singletons**, each time
+ they are looked up they return the same instance.
+
+ Some examples modifying that default behavior:
+
+ ```javascript
+ var App = Ember.Application.create();
+
+ App.Person = Ember.Object.extend();
+ App.Orange = Ember.Object.extend();
+ App.Email = Ember.Object.extend();
+ App.session = Ember.Object.create();
+
+ App.register('model:user', App.Person, {singleton: false });
+ App.register('fruit:favorite', App.Orange);
+ App.register('communication:main', App.Email, {singleton: false});
+ App.register('session', App.session, {instantiate: false});
+ ```
+
+ @method register
+ @param fullName {String} type:name (e.g., 'model:user')
+ @param factory {Function} (e.g., App.Person)
+ @param options {Object} (optional) disable instantiation or singleton usage
+ **/
+ register: function() {
+ var container = this.__container__;
+ container.register.apply(container, arguments);
+ },
+
+ /**
+ Define a dependency injection onto a specific factory or all factories
+ of a type.
+
+ When Ember instantiates a controller, view, or other framework component
+ it can attach a dependency to that component. This is often used to
+ provide services to a set of framework components.
+
+ An example of providing a session object to all controllers:
+
+ ```javascript
+ var App = Ember.Application.create(),
+ Session = Ember.Object.extend({ isAuthenticated: false });
+
+ // A factory must be registered before it can be injected
+ App.register('session:main', Session);
+
+ // Inject 'session:main' onto all factories of the type 'controller'
+ // with the name 'session'
+ App.inject('controller', 'session', 'session:main');
+
+ App.IndexController = Ember.Controller.extend({
+ isLoggedIn: Ember.computed.alias('session.isAuthenticated')
+ });
+ ```
+
+ Injections can also be performed on specific factories.
+
+ ```javascript
+ App.inject(, , )
+ App.inject('route', 'source', 'source:main')
+ App.inject('route:application', 'email', 'model:email')
+ ```
+
+ It is important to note that injections can only be performed on
+ classes that are instantiated by Ember itself. Instantiating a class
+ directly (via `create` or `new`) bypasses the dependency injection
+ system.
+
+ Ember-Data instantiates its models in a unique manner, and consequently
+ injections onto models (or all models) will not work as expected. Injections
+ on models can be enabled by setting `Ember.MODEL_FACTORY_INJECTIONS`
+ to `true`.
+
+ @method inject
+ @param factoryNameOrType {String}
+ @param property {String}
+ @param injectionName {String}
+ **/
+ inject: function() {
+ var container = this.__container__;
+ container.injection.apply(container, arguments);
+ },
+
+ /**
+ Calling initialize manually is not supported.
+
+ Please see Ember.Application#advanceReadiness and
+ Ember.Application#deferReadiness.
+
+ @private
+ @deprecated
+ @method initialize
+ **/
+ initialize: function() {
+ Ember.deprecate('Calling initialize manually is not supported. Please see Ember.Application#advanceReadiness and Ember.Application#deferReadiness');
+ },
+
+ /**
+ Initialize the application. This happens automatically.
+
+ Run any initializers and run the application load hook. These hooks may
+ choose to defer readiness. For example, an authentication hook might want
+ to defer readiness until the auth token has been retrieved.
+
+ @private
+ @method _initialize
+ */
+ _initialize: function() {
+ if (this.isDestroyed) { return; }
+
+ // At this point, the App.Router must already be assigned
+ if (this.Router) {
+ var container = this.__container__;
+ container.unregister('router:main');
+ container.register('router:main', this.Router);
+ }
+
+ this.runInitializers();
+ runLoadHooks('application', this);
+
+ // At this point, any initializers or load hooks that would have wanted
+ // to defer readiness have fired. In general, advancing readiness here
+ // will proceed to didBecomeReady.
+ this.advanceReadiness();
+
+ return this;
+ },
+
+ /**
+ Reset the application. This is typically used only in tests. It cleans up
+ the application in the following order:
+
+ 1. Deactivate existing routes
+ 2. Destroy all objects in the container
+ 3. Create a new application container
+ 4. Re-route to the existing url
+
+ Typical Example:
+
+ ```javascript
+
+ var App;
+
+ run(function() {
+ App = Ember.Application.create();
+ });
+
+ module("acceptance test", {
+ setup: function() {
+ App.reset();
+ }
+ });
+
+ test("first test", function() {
+ // App is freshly reset
+ });
+
+ test("first test", function() {
+ // App is again freshly reset
+ });
+ ```
+
+ Advanced Example:
+
+ Occasionally you may want to prevent the app from initializing during
+ setup. This could enable extra configuration, or enable asserting prior
+ to the app becoming ready.
+
+ ```javascript
+
+ var App;
+
+ run(function() {
+ App = Ember.Application.create();
+ });
+
+ module("acceptance test", {
+ setup: function() {
+ run(function() {
+ App.reset();
+ App.deferReadiness();
+ });
+ }
+ });
+
+ test("first test", function() {
+ ok(true, 'something before app is initialized');
+
+ run(function() {
+ App.advanceReadiness();
+ });
+ ok(true, 'something after app is initialized');
+ });
+ ```
+
+ @method reset
+ **/
+ reset: function() {
+ this._readinessDeferrals = 1;
+
+ function handleReset() {
+ var router = this.__container__.lookup('router:main');
+ router.reset();
+
+ run(this.__container__, 'destroy');
+
+ this.buildContainer();
+
+ run.schedule('actions', this, function() {
+ this._initialize();
+ });
+ }
+
+ run.join(this, handleReset);
+ },
+
+ /**
+ @private
+ @method runInitializers
+ */
+ runInitializers: function() {
+ var initializers = get(this.constructor, 'initializers');
+ var container = this.__container__;
+ var graph = new DAG();
+ var namespace = this;
+ var name, initializer;
+
+ for (name in initializers) {
+ initializer = initializers[name];
+ graph.addEdges(initializer.name, initializer.initialize, initializer.before, initializer.after);
+ }
+
+ graph.topsort(function (vertex) {
+ var initializer = vertex.value;
+ Ember.assert("No application initializer named '"+vertex.name+"'", initializer);
+ initializer(container, namespace);
+ });
+ },
+
+ /**
+ @private
+ @method didBecomeReady
+ */
+ didBecomeReady: function() {
+ this.setupEventDispatcher();
+ this.ready(); // user hook
+ this.startRouting();
+
+ if (!Ember.testing) {
+ // Eagerly name all classes that are already loaded
+ Ember.Namespace.processAll();
+ Ember.BOOTED = true;
+ }
+
+ this.resolve(this);
+ },
+
+ /**
+ Setup up the event dispatcher to receive events on the
+ application's `rootElement` with any registered
+ `customEvents`.
+
+ @private
+ @method setupEventDispatcher
+ */
+ setupEventDispatcher: function() {
+ var customEvents = get(this, 'customEvents');
+ var rootElement = get(this, 'rootElement');
+ var dispatcher = this.__container__.lookup('event_dispatcher:main');
+
+ set(this, 'eventDispatcher', dispatcher);
+ dispatcher.setup(customEvents, rootElement);
+ },
+
+ /**
+ If the application has a router, use it to route to the current URL, and
+ trigger a new call to `route` whenever the URL changes.
+
+ @private
+ @method startRouting
+ @property router {Ember.Router}
+ */
+ startRouting: function() {
+ var router = this.__container__.lookup('router:main');
+ if (!router) { return; }
+
+ router.startRouting();
+ },
+
+ handleURL: function(url) {
+ var router = this.__container__.lookup('router:main');
+
+ router.handleURL(url);
+ },
+
+ /**
+ Called when the Application has become ready.
+ The call will be delayed until the DOM has become ready.
+
+ @event ready
+ */
+ ready: K,
+
+ /**
+ @deprecated Use 'Resolver' instead
+ Set this to provide an alternate class to `Ember.DefaultResolver`
+
+
+ @property resolver
+ */
+ resolver: null,
+
+ /**
+ Set this to provide an alternate class to `Ember.DefaultResolver`
+
+ @property resolver
+ */
+ Resolver: null,
+
+ willDestroy: function() {
+ Ember.BOOTED = false;
+ // Ensure deactivation of routes before objects are destroyed
+ this.__container__.lookup('router:main').reset();
+
+ this.__container__.destroy();
+ },
+
+ initializer: function(options) {
+ this.constructor.initializer(options);
+ },
+
+ /**
+ @method then
+ @private
+ @deprecated
+ */
+ then: function() {
+ Ember.deprecate('Do not use `.then` on an instance of Ember.Application. Please use the `.ready` hook instead.');
+
+ this._super.apply(this, arguments);
+ }
+ });
+
+ Application.reopenClass({
+ initializers: {},
+
+ /**
+ Initializer receives an object which has the following attributes:
+ `name`, `before`, `after`, `initialize`. The only required attribute is
+ `initialize, all others are optional.
+
+ * `name` allows you to specify under which name the initializer is registered.
+ This must be a unique name, as trying to register two initializers with the
+ same name will result in an error.
+
+ ```javascript
+ Ember.Application.initializer({
+ name: 'namedInitializer',
+ initialize: function(container, application) {
+ Ember.debug("Running namedInitializer!");
+ }
+ });
+ ```
+
+ * `before` and `after` are used to ensure that this initializer is ran prior
+ or after the one identified by the value. This value can be a single string
+ or an array of strings, referencing the `name` of other initializers.
+
+ An example of ordering initializers, we create an initializer named `first`:
+
+ ```javascript
+ Ember.Application.initializer({
+ name: 'first',
+ initialize: function(container, application) {
+ Ember.debug("First initializer!");
+ }
+ });
+
+ // DEBUG: First initializer!
+ ```
+
+ We add another initializer named `second`, specifying that it should run
+ after the initializer named `first`:
+
+ ```javascript
+ Ember.Application.initializer({
+ name: 'second',
+ after: 'first',
+
+ initialize: function(container, application) {
+ Ember.debug("Second initializer!");
+ }
+ });
+
+ // DEBUG: First initializer!
+ // DEBUG: Second initializer!
+ ```
+
+ Afterwards we add a further initializer named `pre`, this time specifying
+ that it should run before the initializer named `first`:
+
+ ```javascript
+ Ember.Application.initializer({
+ name: 'pre',
+ before: 'first',
+
+ initialize: function(container, application) {
+ Ember.debug("Pre initializer!");
+ }
+ });
+
+ // DEBUG: Pre initializer!
+ // DEBUG: First initializer!
+ // DEBUG: Second initializer!
+ ```
+
+ Finally we add an initializer named `post`, specifying it should run after
+ both the `first` and the `second` initializers:
+
+ ```javascript
+ Ember.Application.initializer({
+ name: 'post',
+ after: ['first', 'second'],
+
+ initialize: function(container, application) {
+ Ember.debug("Post initializer!");
+ }
+ });
+
+ // DEBUG: Pre initializer!
+ // DEBUG: First initializer!
+ // DEBUG: Second initializer!
+ // DEBUG: Post initializer!
+ ```
+
+ * `initialize` is a callback function that receives two arguments, `container`
+ and `application` on which you can operate.
+
+ Example of using `container` to preload data into the store:
+
+ ```javascript
+ Ember.Application.initializer({
+ name: "preload-data",
+
+ initialize: function(container, application) {
+ var store = container.lookup('store:main');
+ store.pushPayload(preloadedData);
+ }
+ });
+ ```
+
+ Example of using `application` to register an adapter:
+
+ ```javascript
+ Ember.Application.initializer({
+ name: 'api-adapter',
+
+ initialize: function(container, application) {
+ application.register('api-adapter:main', ApiAdapter);
+ }
+ });
+ ```
+
+ @method initializer
+ @param initializer {Object}
+ */
+ initializer: function(initializer) {
+ // If this is the first initializer being added to a subclass, we are going to reopen the class
+ // to make sure we have a new `initializers` object, which extends from the parent class' using
+ // prototypal inheritance. Without this, attempting to add initializers to the subclass would
+ // pollute the parent class as well as other subclasses.
+ if (this.superclass.initializers !== undefined && this.superclass.initializers === this.initializers) {
+ this.reopenClass({
+ initializers: create(this.initializers)
+ });
+ }
+
+ Ember.assert("The initializer '" + initializer.name + "' has already been registered", !this.initializers[initializer.name]);
+ Ember.assert("An initializer cannot be registered without an initialize function", canInvoke(initializer, 'initialize'));
+
+ this.initializers[initializer.name] = initializer;
+ },
+
+ /**
+ This creates a container with the default Ember naming conventions.
+
+ It also configures the container:
+
+ * registered views are created every time they are looked up (they are
+ not singletons)
+ * registered templates are not factories; the registered value is
+ returned directly.
+ * the router receives the application as its `namespace` property
+ * all controllers receive the router as their `target` and `controllers`
+ properties
+ * all controllers receive the application as their `namespace` property
+ * the application view receives the application controller as its
+ `controller` property
+ * the application view receives the application template as its
+ `defaultTemplate` property
+
+ @private
+ @method buildContainer
+ @static
+ @param {Ember.Application} namespace the application to build the
+ container for.
+ @return {Ember.Container} the built container
+ */
+ buildContainer: function(namespace) {
+ var container = new Container();
+
+ container.set = set;
+ container.resolver = resolverFor(namespace);
+ container.normalize = container.resolver.normalize;
+ container.describe = container.resolver.describe;
+ container.makeToString = container.resolver.makeToString;
+
+ container.optionsForType('component', { singleton: false });
+ container.optionsForType('view', { singleton: false });
+ container.optionsForType('template', { instantiate: false });
+ container.optionsForType('helper', { instantiate: false });
+
+ container.register('application:main', namespace, { instantiate: false });
+
+ container.register('controller:basic', Controller, { instantiate: false });
+ container.register('controller:object', ObjectController, { instantiate: false });
+ container.register('controller:array', ArrayController, { instantiate: false });
+ container.register('route:basic', Route, { instantiate: false });
+ container.register('event_dispatcher:main', EventDispatcher);
+
+ container.register('router:main', Router);
+ container.injection('router:main', 'namespace', 'application:main');
+
+ container.register('location:auto', AutoLocation);
+ container.register('location:hash', HashLocation);
+ container.register('location:history', HistoryLocation);
+ container.register('location:none', NoneLocation);
+
+ container.injection('controller', 'target', 'router:main');
+ container.injection('controller', 'namespace', 'application:main');
+
+ container.register('-bucket-cache:main', BucketCache);
+ container.injection('router', '_bucketCache', '-bucket-cache:main');
+ container.injection('route', '_bucketCache', '-bucket-cache:main');
+ container.injection('controller', '_bucketCache', '-bucket-cache:main');
+
+ container.injection('route', 'router', 'router:main');
+ container.injection('location', 'rootURL', '-location-setting:root-url');
+
+ // DEBUGGING
+ container.register('resolver-for-debugging:main', container.resolver.__resolver__, { instantiate: false });
+ container.injection('container-debug-adapter:main', 'resolver', 'resolver-for-debugging:main');
+ container.injection('data-adapter:main', 'containerDebugAdapter', 'container-debug-adapter:main');
+ // Custom resolver authors may want to register their own ContainerDebugAdapter with this key
+
+ // ES6TODO: resolve this via import once ember-application package is ES6'ed
+ if (!ContainerDebugAdapter) { ContainerDebugAdapter = requireModule('ember-extension-support/container_debug_adapter')['default']; }
+ container.register('container-debug-adapter:main', ContainerDebugAdapter);
+
+ return container;
+ }
+ });
+
+ /**
+ This function defines the default lookup rules for container lookups:
+
+ * templates are looked up on `Ember.TEMPLATES`
+ * other names are looked up on the application after classifying the name.
+ For example, `controller:post` looks up `App.PostController` by default.
+ * if the default lookup fails, look for registered classes on the container
+
+ This allows the application to register default injections in the container
+ that could be overridden by the normal naming convention.
+
+ @private
+ @method resolverFor
+ @param {Ember.Namespace} namespace the namespace to look for classes
+ @return {*} the resolved value for a given lookup
+ */
+ function resolverFor(namespace) {
+ if (namespace.get('resolver')) {
+ Ember.deprecate('Application.resolver is deprecated in favor of Application.Resolver', false);
+ }
+
+ var ResolverClass = namespace.get('resolver') || namespace.get('Resolver') || DefaultResolver;
+ var resolver = ResolverClass.create({
+ namespace: namespace
+ });
+
+ function resolve(fullName) {
+ return resolver.resolve(fullName);
+ }
+
+ resolve.describe = function(fullName) {
+ return resolver.lookupDescription(fullName);
+ };
+
+ resolve.makeToString = function(factory, fullName) {
+ return resolver.makeToString(factory, fullName);
+ };
+
+ resolve.normalize = function(fullName) {
+ if (resolver.normalize) {
+ return resolver.normalize(fullName);
+ } else {
+ Ember.deprecate('The Resolver should now provide a \'normalize\' function', false);
+ return fullName;
+ }
+ };
+
+ resolve.__resolver__ = resolver;
+
+ return resolve;
+ }
+
+ __exports__["default"] = Application;
+ });
+define("ember-application/system/dag",
+ ["ember-metal/error","exports"],
+ function(__dependency1__, __exports__) {
+ "use strict";
+ var EmberError = __dependency1__["default"];
+
+ function visit(vertex, fn, visited, path) {
+ var name = vertex.name;
+ var vertices = vertex.incoming;
+ var names = vertex.incomingNames;
+ var len = names.length;
+ var i;
+
+ if (!visited) {
+ visited = {};
+ }
+ if (!path) {
+ path = [];
+ }
+ if (visited.hasOwnProperty(name)) {
+ return;
+ }
+ path.push(name);
+ visited[name] = true;
+ for (i = 0; i < len; i++) {
+ visit(vertices[names[i]], fn, visited, path);
+ }
+ fn(vertex, path);
+ path.pop();
+ }
+
+
+ /**
+ * DAG stands for Directed acyclic graph.
+ *
+ * It is used to build a graph of dependencies checking that there isn't circular
+ * dependencies. p.e Registering initializers with a certain precedence order.
+ *
+ * @class DAG
+ * @constructor
+ */
+ function DAG() {
+ this.names = [];
+ this.vertices = {};
+ }
+
+ /**
+ * Adds a vertex entry to the graph unless it is already added.
+ *
+ * @private
+ * @method add
+ * @param {String} name The name of the vertex to add
+ */
+ DAG.prototype.add = function(name) {
+ if (!name) { return; }
+ if (this.vertices.hasOwnProperty(name)) {
+ return this.vertices[name];
+ }
+ var vertex = {
+ name: name, incoming: {}, incomingNames: [], hasOutgoing: false, value: null
+ };
+ this.vertices[name] = vertex;
+ this.names.push(name);
+ return vertex;
+ };
+
+ /**
+ * Adds a vertex to the graph and sets its value.
+ *
+ * @private
+ * @method map
+ * @param {String} name The name of the vertex.
+ * @param value The value to put in the vertex.
+ */
+ DAG.prototype.map = function(name, value) {
+ this.add(name).value = value;
+ };
+
+ /**
+ * Connects the vertices with the given names, adding them to the graph if
+ * necesary, only if this does not produce is any circular dependency.
+ *
+ * @private
+ * @method addEdge
+ * @param {String} fromName The name the vertex where the edge starts.
+ * @param {String} toName The name the vertex where the edge ends.
+ */
+ DAG.prototype.addEdge = function(fromName, toName) {
+ if (!fromName || !toName || fromName === toName) {
+ return;
+ }
+ var from = this.add(fromName), to = this.add(toName);
+ if (to.incoming.hasOwnProperty(fromName)) {
+ return;
+ }
+ function checkCycle(vertex, path) {
+ if (vertex.name === toName) {
+ throw new EmberError("cycle detected: " + toName + " <- " + path.join(" <- "));
+ }
+ }
+ visit(from, checkCycle);
+ from.hasOutgoing = true;
+ to.incoming[fromName] = from;
+ to.incomingNames.push(fromName);
+ };
+
+ /**
+ * Visits all the vertex of the graph calling the given function with each one,
+ * ensuring that the vertices are visited respecting their precedence.
+ *
+ * @method topsort
+ * @param {Function} fn The function to be invoked on each vertex.
+ */
+ DAG.prototype.topsort = function(fn) {
+ var visited = {};
+ var vertices = this.vertices;
+ var names = this.names;
+ var len = names.length;
+ var i, vertex;
+
+ for (i = 0; i < len; i++) {
+ vertex = vertices[names[i]];
+ if (!vertex.hasOutgoing) {
+ visit(vertex, fn, visited);
+ }
+ }
+ };
+
+ /**
+ * Adds a vertex with the given name and value to the graph and joins it with the
+ * vertices referenced in _before_ and _after_. If there isn't vertices with those
+ * names, they are added too.
+ *
+ * If either _before_ or _after_ are falsy/empty, the added vertex will not have
+ * an incoming/outgoing edge.
+ *
+ * @method addEdges
+ * @param {String} name The name of the vertex to be added.
+ * @param value The value of that vertex.
+ * @param before An string or array of strings with the names of the vertices before
+ * which this vertex must be visited.
+ * @param after An string or array of strings with the names of the vertex after
+ * which this vertex must be visited.
+ *
+ */
+ DAG.prototype.addEdges = function(name, value, before, after) {
+ var i;
+ this.map(name, value);
+ if (before) {
+ if (typeof before === 'string') {
+ this.addEdge(name, before);
+ } else {
+ for (i = 0; i < before.length; i++) {
+ this.addEdge(name, before[i]);
+ }
+ }
+ }
+ if (after) {
+ if (typeof after === 'string') {
+ this.addEdge(after, name);
+ } else {
+ for (i = 0; i < after.length; i++) {
+ this.addEdge(after[i], name);
+ }
+ }
+ }
+ };
+
+ __exports__["default"] = DAG;
+ });
+define("ember-application/system/resolver",
+ ["ember-metal/core","ember-metal/property_get","ember-metal/logger","ember-runtime/system/string","ember-runtime/system/object","ember-runtime/system/namespace","ember-handlebars","exports"],
+ function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __exports__) {
+ "use strict";
+ /**
+ @module ember
+ @submodule ember-application
+ */
+
+ var Ember = __dependency1__["default"];
+ // Ember.TEMPLATES, Ember.assert
+ var get = __dependency2__.get;
+ var Logger = __dependency3__["default"];
+ var classify = __dependency4__.classify;
+ var capitalize = __dependency4__.capitalize;
+ var decamelize = __dependency4__.decamelize;
+ var EmberObject = __dependency5__["default"];
+ var Namespace = __dependency6__["default"];
+ var EmberHandlebars = __dependency7__["default"];
+
+ var Resolver = EmberObject.extend({
+ /**
+ This will be set to the Application instance when it is
+ created.
+
+ @property namespace
+ */
+ namespace: null,
+ normalize: Ember.required(Function),
+ resolve: Ember.required(Function),
+ parseName: Ember.required(Function),
+ lookupDescription: Ember.required(Function),
+ makeToString: Ember.required(Function),
+ resolveOther: Ember.required(Function),
+ _logLookup: Ember.required(Function)
+ });
+ __exports__.Resolver = Resolver;
+ /**
+ The DefaultResolver defines the default lookup rules to resolve
+ container lookups before consulting the container for registered
+ items:
+
+ * templates are looked up on `Ember.TEMPLATES`
+ * other names are looked up on the application after converting
+ the name. For example, `controller:post` looks up
+ `App.PostController` by default.
+ * there are some nuances (see examples below)
+
+ ### How Resolving Works
+
+ The container calls this object's `resolve` method with the
+ `fullName` argument.
+
+ It first parses the fullName into an object using `parseName`.
+
+ Then it checks for the presence of a type-specific instance
+ method of the form `resolve[Type]` and calls it if it exists.
+ For example if it was resolving 'template:post', it would call
+ the `resolveTemplate` method.
+
+ Its last resort is to call the `resolveOther` method.
+
+ The methods of this object are designed to be easy to override
+ in a subclass. For example, you could enhance how a template
+ is resolved like so:
+
+ ```javascript
+ App = Ember.Application.create({
+ Resolver: Ember.DefaultResolver.extend({
+ resolveTemplate: function(parsedName) {
+ var resolvedTemplate = this._super(parsedName);
+ if (resolvedTemplate) { return resolvedTemplate; }
+ return Ember.TEMPLATES['not_found'];
+ }
+ })
+ });
+ ```
+
+ Some examples of how names are resolved:
+
+ ```
+ 'template:post' //=> Ember.TEMPLATES['post']
+ 'template:posts/byline' //=> Ember.TEMPLATES['posts/byline']
+ 'template:posts.byline' //=> Ember.TEMPLATES['posts/byline']
+ 'template:blogPost' //=> Ember.TEMPLATES['blogPost']
+ // OR
+ // Ember.TEMPLATES['blog_post']
+ 'controller:post' //=> App.PostController
+ 'controller:posts.index' //=> App.PostsIndexController
+ 'controller:blog/post' //=> Blog.PostController
+ 'controller:basic' //=> Ember.Controller
+ 'route:post' //=> App.PostRoute
+ 'route:posts.index' //=> App.PostsIndexRoute
+ 'route:blog/post' //=> Blog.PostRoute
+ 'route:basic' //=> Ember.Route
+ 'view:post' //=> App.PostView
+ 'view:posts.index' //=> App.PostsIndexView
+ 'view:blog/post' //=> Blog.PostView
+ 'view:basic' //=> Ember.View
+ 'foo:post' //=> App.PostFoo
+ 'model:post' //=> App.Post
+ ```
+
+ @class DefaultResolver
+ @namespace Ember
+ @extends Ember.Object
+ */
+
+ __exports__["default"] = EmberObject.extend({
+ /**
+ This will be set to the Application instance when it is
+ created.
+
+ @property namespace
+ */
+ namespace: null,
+
+ normalize: function(fullName) {
+ var split = fullName.split(':', 2),
+ type = split[0],
+ name = split[1];
+
+ Ember.assert("Tried to normalize a container name without a colon (:) in it. You probably tried to lookup a name that did not contain a type, a colon, and a name. A proper lookup name would be `view:post`.", split.length === 2);
+
+ if (type !== 'template') {
+ var result = name;
+
+ if (result.indexOf('.') > -1) {
+ result = result.replace(/\.(.)/g, function(m) { return m.charAt(1).toUpperCase(); });
+ }
+
+ if (name.indexOf('_') > -1) {
+ result = result.replace(/_(.)/g, function(m) { return m.charAt(1).toUpperCase(); });
+ }
+
+ return type + ':' + result;
+ } else {
+ return fullName;
+ }
+ },
+
+
+ /**
+ This method is called via the container's resolver method.
+ It parses the provided `fullName` and then looks up and
+ returns the appropriate template or class.
+
+ @method resolve
+ @param {String} fullName the lookup string
+ @return {Object} the resolved factory
+ */
+ resolve: function(fullName) {
+ var parsedName = this.parseName(fullName),
+ resolveMethodName = parsedName.resolveMethodName,
+ resolved;
+
+ if (!(parsedName.name && parsedName.type)) {
+ throw new TypeError('Invalid fullName: `' + fullName + '`, must be of the form `type:name` ');
+ }
+
+ if (this[resolveMethodName]) {
+ resolved = this[resolveMethodName](parsedName);
+ }
+
+ if (!resolved) {
+ resolved = this.resolveOther(parsedName);
+ }
+
+ if (parsedName.root && parsedName.root.LOG_RESOLVER) {
+ this._logLookup(resolved, parsedName);
+ }
+
+ return resolved;
+ },
+ /**
+ Convert the string name of the form 'type:name' to
+ a Javascript object with the parsed aspects of the name
+ broken out.
+
+ @protected
+ @param {String} fullName the lookup string
+ @method parseName
+ */
+ parseName: function(fullName) {
+ var nameParts = fullName.split(':'),
+ type = nameParts[0], fullNameWithoutType = nameParts[1],
+ name = fullNameWithoutType,
+ namespace = get(this, 'namespace'),
+ root = namespace;
+
+ if (type !== 'template' && name.indexOf('/') !== -1) {
+ var parts = name.split('/');
+ name = parts[parts.length - 1];
+ var namespaceName = capitalize(parts.slice(0, -1).join('.'));
+ root = Namespace.byName(namespaceName);
+
+ Ember.assert('You are looking for a ' + name + ' ' + type + ' in the ' + namespaceName + ' namespace, but the namespace could not be found', root);
+ }
+
+ return {
+ fullName: fullName,
+ type: type,
+ fullNameWithoutType: fullNameWithoutType,
+ name: name,
+ root: root,
+ resolveMethodName: 'resolve' + classify(type)
+ };
+ },
+
+ /**
+ Returns a human-readable description for a fullName. Used by the
+ Application namespace in assertions to describe the
+ precise name of the class that Ember is looking for, rather than
+ container keys.
+
+ @protected
+ @param {String} fullName the lookup string
+ @method lookupDescription
+ */
+ lookupDescription: function(fullName) {
+ var parsedName = this.parseName(fullName);
+
+ if (parsedName.type === 'template') {
+ return 'template at ' + parsedName.fullNameWithoutType.replace(/\./g, '/');
+ }
+
+ var description = parsedName.root + '.' + classify(parsedName.name);
+ if (parsedName.type !== 'model') { description += classify(parsedName.type); }
+
+ return description;
+ },
+
+ makeToString: function(factory, fullName) {
+ return factory.toString();
+ },
+ /**
+ Given a parseName object (output from `parseName`), apply
+ the conventions expected by `Ember.Router`
+
+ @protected
+ @param {Object} parsedName a parseName object with the parsed
+ fullName lookup string
+ @method useRouterNaming
+ */
+ useRouterNaming: function(parsedName) {
+ parsedName.name = parsedName.name.replace(/\./g, '_');
+ if (parsedName.name === 'basic') {
+ parsedName.name = '';
+ }
+ },
+ /**
+ Look up the template in Ember.TEMPLATES
+
+ @protected
+ @param {Object} parsedName a parseName object with the parsed
+ fullName lookup string
+ @method resolveTemplate
+ */
+ resolveTemplate: function(parsedName) {
+ var templateName = parsedName.fullNameWithoutType.replace(/\./g, '/');
+
+ if (Ember.TEMPLATES[templateName]) {
+ return Ember.TEMPLATES[templateName];
+ }
+
+ templateName = decamelize(templateName);
+ if (Ember.TEMPLATES[templateName]) {
+ return Ember.TEMPLATES[templateName];
+ }
+ },
+ /**
+ Lookup the view using `resolveOther`
+
+ @protected
+ @param {Object} parsedName a parseName object with the parsed
+ fullName lookup string
+ @method resolveView
+ */
+ resolveView: function(parsedName) {
+ this.useRouterNaming(parsedName);
+ return this.resolveOther(parsedName);
+ },
+ /**
+ Lookup the controller using `resolveOther`
+
+ @protected
+ @param {Object} parsedName a parseName object with the parsed
+ fullName lookup string
+ @method resolveController
+ */
+ resolveController: function(parsedName) {
+ this.useRouterNaming(parsedName);
+ return this.resolveOther(parsedName);
+ },
+ /**
+ Lookup the route using `resolveOther`
+
+ @protected
+ @param {Object} parsedName a parseName object with the parsed
+ fullName lookup string
+ @method resolveRoute
+ */
+ resolveRoute: function(parsedName) {
+ this.useRouterNaming(parsedName);
+ return this.resolveOther(parsedName);
+ },
+
+ /**
+ Lookup the model on the Application namespace
+
+ @protected
+ @param {Object} parsedName a parseName object with the parsed
+ fullName lookup string
+ @method resolveModel
+ */
+ resolveModel: function(parsedName) {
+ var className = classify(parsedName.name);
+ var factory = get(parsedName.root, className);
+
+ if (factory) { return factory; }
+ },
+ /**
+ Look up the specified object (from parsedName) on the appropriate
+ namespace (usually on the Application)
+
+ @protected
+ @param {Object} parsedName a parseName object with the parsed
+ fullName lookup string
+ @method resolveHelper
+ */
+ resolveHelper: function(parsedName) {
+ return this.resolveOther(parsedName) || EmberHandlebars.helpers[parsedName.fullNameWithoutType];
+ },
+ /**
+ Look up the specified object (from parsedName) on the appropriate
+ namespace (usually on the Application)
+
+ @protected
+ @param {Object} parsedName a parseName object with the parsed
+ fullName lookup string
+ @method resolveOther
+ */
+ resolveOther: function(parsedName) {
+ var className = classify(parsedName.name) + classify(parsedName.type);
+ var factory = get(parsedName.root, className);
+ if (factory) { return factory; }
+ },
+
+ /**
+ @method _logLookup
+ @param {Boolean} found
+ @param {Object} parsedName
+ @private
+ */
+ _logLookup: function(found, parsedName) {
+ var symbol, padding;
+
+ if (found) { symbol = '[✓]'; }
+ else { symbol = '[ ]'; }
+
+ if (parsedName.fullName.length > 60) {
+ padding = '.';
+ } else {
+ padding = new Array(60 - parsedName.fullName.length).join('.');
+ }
+
+ Logger.info(symbol, parsedName.fullName, padding, this.lookupDescription(parsedName.fullName));
+ }
+ });
+ });
define("ember-debug",
["ember-metal/core","ember-metal/error","ember-metal/logger"],
function(__dependency1__, __dependency2__, __dependency3__) {
@@ -102,8 +3706,9 @@ define("ember-debug",
```javascript
// Test for truthiness
Ember.assert('Must pass a valid object', obj);
+
// Fail unconditionally
- Ember.assert('This code path should never be run')
+ Ember.assert('This code path should never be run');
```
@method assert
@@ -140,7 +3745,7 @@ define("ember-debug",
`Ember.debug()` when doing a production build.
```javascript
- Ember.debug("I'm a debug notice!");
+ Ember.debug('I\'m a debug notice!');
```
@method debug
@@ -227,7 +3832,7 @@ define("ember-debug",
Ember.runInDebug(function() {
Ember.Handlebars.EachView.reopen({
didInsertElement: function() {
- console.log("I'm happy");
+ console.log('I\'m happy');
}
});
});
@@ -238,7 +3843,7 @@ define("ember-debug",
@since 1.5.0
*/
Ember.runInDebug = function(func) {
- func()
+ func();
};
// Inform the developer about the Ember Inspector if not installed.
@@ -263,24 +3868,6929 @@ define("ember-debug",
}
}
});
-})();
+define("ember-extension-support",
+ ["ember-metal/core","ember-extension-support/data_adapter","ember-extension-support/container_debug_adapter"],
+ function(__dependency1__, __dependency2__, __dependency3__) {
+ "use strict";
+ /**
+ Ember Extension Support
-(function() {
+ @module ember
+ @submodule ember-extension-support
+ @requires ember-application
+ */
+
+ var Ember = __dependency1__["default"];
+ var DataAdapter = __dependency2__["default"];
+ var ContainerDebugAdapter = __dependency3__["default"];
+
+ Ember.DataAdapter = DataAdapter;
+ Ember.ContainerDebugAdapter = ContainerDebugAdapter;
+ });
+define("ember-extension-support/container_debug_adapter",
+ ["ember-metal/core","ember-runtime/system/native_array","ember-metal/utils","ember-runtime/system/string","ember-runtime/system/namespace","ember-runtime/system/object","exports"],
+ function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __exports__) {
+ "use strict";
+ var Ember = __dependency1__["default"];
+ var emberA = __dependency2__.A;
+ var typeOf = __dependency3__.typeOf;
+ var dasherize = __dependency4__.dasherize;
+ var classify = __dependency4__.classify;
+ var Namespace = __dependency5__["default"];
+ var EmberObject = __dependency6__["default"];
+
+ /**
+ @module ember
+ @submodule ember-extension-support
+ */
+
+ /**
+ The `ContainerDebugAdapter` helps the container and resolver interface
+ with tools that debug Ember such as the
+ [Ember Extension](https://github.com/tildeio/ember-extension)
+ for Chrome and Firefox.
+
+ This class can be extended by a custom resolver implementer
+ to override some of the methods with library-specific code.
+
+ The methods likely to be overridden are:
+
+ * `canCatalogEntriesByType`
+ * `catalogEntriesByType`
+
+ The adapter will need to be registered
+ in the application's container as `container-debug-adapter:main`
+
+ Example:
+
+ ```javascript
+ Application.initializer({
+ name: "containerDebugAdapter",
+
+ initialize: function(container, application) {
+ application.register('container-debug-adapter:main', require('app/container-debug-adapter'));
+ }
+ });
+ ```
+
+ @class ContainerDebugAdapter
+ @namespace Ember
+ @extends EmberObject
+ @since 1.5.0
+ */
+ __exports__["default"] = EmberObject.extend({
+ /**
+ The container of the application being debugged.
+ This property will be injected
+ on creation.
+
+ @property container
+ @default null
+ */
+ container: null,
+
+ /**
+ The resolver instance of the application
+ being debugged. This property will be injected
+ on creation.
+
+ @property resolver
+ @default null
+ */
+ resolver: null,
+
+ /**
+ Returns true if it is possible to catalog a list of available
+ classes in the resolver for a given type.
+
+ @method canCatalogEntriesByType
+ @param {string} type The type. e.g. "model", "controller", "route"
+ @return {boolean} whether a list is available for this type.
+ */
+ canCatalogEntriesByType: function(type) {
+ if (type === 'model' || type === 'template') return false;
+ return true;
+ },
+
+ /**
+ Returns the available classes a given type.
+
+ @method catalogEntriesByType
+ @param {string} type The type. e.g. "model", "controller", "route"
+ @return {Array} An array of strings.
+ */
+ catalogEntriesByType: function(type) {
+ var namespaces = emberA(Namespace.NAMESPACES), types = emberA(), self = this;
+ var typeSuffixRegex = new RegExp(classify(type) + "$");
+
+ namespaces.forEach(function(namespace) {
+ if (namespace !== Ember) {
+ for (var key in namespace) {
+ if (!namespace.hasOwnProperty(key)) { continue; }
+ if (typeSuffixRegex.test(key)) {
+ var klass = namespace[key];
+ if (typeOf(klass) === 'class') {
+ types.push(dasherize(key.replace(typeSuffixRegex, '')));
+ }
+ }
+ }
+ }
+ });
+ return types;
+ }
+ });
+ });
+define("ember-extension-support/data_adapter",
+ ["ember-metal/core","ember-metal/property_get","ember-metal/run_loop","ember-runtime/system/string","ember-runtime/system/namespace","ember-runtime/system/object","ember-runtime/system/native_array","ember-application/system/application","exports"],
+ function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __exports__) {
+ "use strict";
+ var Ember = __dependency1__["default"];
+ var get = __dependency2__.get;
+ var run = __dependency3__["default"];
+ var dasherize = __dependency4__.dasherize;
+ var Namespace = __dependency5__["default"];
+ var EmberObject = __dependency6__["default"];
+ var emberA = __dependency7__.A;
+ var Application = __dependency8__["default"];
+
+ /**
+ @module ember
+ @submodule ember-extension-support
+ */
+
+ /**
+ The `DataAdapter` helps a data persistence library
+ interface with tools that debug Ember such
+ as the [Ember Extension](https://github.com/tildeio/ember-extension)
+ for Chrome and Firefox.
+
+ This class will be extended by a persistence library
+ which will override some of the methods with
+ library-specific code.
+
+ The methods likely to be overridden are:
+
+ * `getFilters`
+ * `detect`
+ * `columnsForType`
+ * `getRecords`
+ * `getRecordColumnValues`
+ * `getRecordKeywords`
+ * `getRecordFilterValues`
+ * `getRecordColor`
+ * `observeRecord`
+
+ The adapter will need to be registered
+ in the application's container as `dataAdapter:main`
+
+ Example:
+
+ ```javascript
+ Application.initializer({
+ name: "data-adapter",
+
+ initialize: function(container, application) {
+ application.register('data-adapter:main', DS.DataAdapter);
+ }
+ });
+ ```
+
+ @class DataAdapter
+ @namespace Ember
+ @extends EmberObject
+ */
+ __exports__["default"] = EmberObject.extend({
+ init: function() {
+ this._super();
+ this.releaseMethods = emberA();
+ },
+
+ /**
+ The container of the application being debugged.
+ This property will be injected
+ on creation.
+
+ @property container
+ @default null
+ @since 1.3.0
+ */
+ container: null,
+
+
+ /**
+ The container-debug-adapter which is used
+ to list all models.
+
+ @property containerDebugAdapter
+ @default undefined
+ @since 1.5.0
+ **/
+ containerDebugAdapter: undefined,
+
+ /**
+ Number of attributes to send
+ as columns. (Enough to make the record
+ identifiable).
+
+ @private
+ @property attributeLimit
+ @default 3
+ @since 1.3.0
+ */
+ attributeLimit: 3,
+
+ /**
+ Stores all methods that clear observers.
+ These methods will be called on destruction.
+
+ @private
+ @property releaseMethods
+ @since 1.3.0
+ */
+ releaseMethods: emberA(),
+
+ /**
+ Specifies how records can be filtered.
+ Records returned will need to have a `filterValues`
+ property with a key for every name in the returned array.
+
+ @public
+ @method getFilters
+ @return {Array} List of objects defining filters.
+ The object should have a `name` and `desc` property.
+ */
+ getFilters: function() {
+ return emberA();
+ },
+
+ /**
+ Fetch the model types and observe them for changes.
+
+ @public
+ @method watchModelTypes
+
+ @param {Function} typesAdded Callback to call to add types.
+ Takes an array of objects containing wrapped types (returned from `wrapModelType`).
+
+ @param {Function} typesUpdated Callback to call when a type has changed.
+ Takes an array of objects containing wrapped types.
+
+ @return {Function} Method to call to remove all observers
+ */
+ watchModelTypes: function(typesAdded, typesUpdated) {
+ var modelTypes = this.getModelTypes(),
+ self = this, typesToSend, releaseMethods = emberA();
+
+ typesToSend = modelTypes.map(function(type) {
+ var klass = type.klass;
+ var wrapped = self.wrapModelType(klass, type.name);
+ releaseMethods.push(self.observeModelType(klass, typesUpdated));
+ return wrapped;
+ });
+
+ typesAdded(typesToSend);
+
+ var release = function() {
+ releaseMethods.forEach(function(fn) { fn(); });
+ self.releaseMethods.removeObject(release);
+ };
+ this.releaseMethods.pushObject(release);
+ return release;
+ },
+
+ _nameToClass: function(type) {
+ if (typeof type === 'string') {
+ type = this.container.lookupFactory('model:' + type);
+ }
+ return type;
+ },
+
+ /**
+ Fetch the records of a given type and observe them for changes.
+
+ @public
+ @method watchRecords
+
+ @param {Function} recordsAdded Callback to call to add records.
+ Takes an array of objects containing wrapped records.
+ The object should have the following properties:
+ columnValues: {Object} key and value of a table cell
+ object: {Object} the actual record object
+
+ @param {Function} recordsUpdated Callback to call when a record has changed.
+ Takes an array of objects containing wrapped records.
+
+ @param {Function} recordsRemoved Callback to call when a record has removed.
+ Takes the following parameters:
+ index: the array index where the records were removed
+ count: the number of records removed
+
+ @return {Function} Method to call to remove all observers
+ */
+ watchRecords: function(type, recordsAdded, recordsUpdated, recordsRemoved) {
+ var self = this, releaseMethods = emberA(), records = this.getRecords(type), release;
+
+ var recordUpdated = function(updatedRecord) {
+ recordsUpdated([updatedRecord]);
+ };
+
+ var recordsToSend = records.map(function(record) {
+ releaseMethods.push(self.observeRecord(record, recordUpdated));
+ return self.wrapRecord(record);
+ });
+
+
+ var contentDidChange = function(array, idx, removedCount, addedCount) {
+ for (var i = idx; i < idx + addedCount; i++) {
+ var record = array.objectAt(i);
+ var wrapped = self.wrapRecord(record);
+ releaseMethods.push(self.observeRecord(record, recordUpdated));
+ recordsAdded([wrapped]);
+ }
+
+ if (removedCount) {
+ recordsRemoved(idx, removedCount);
+ }
+ };
+
+ var observer = { didChange: contentDidChange, willChange: Ember.K };
+ records.addArrayObserver(self, observer);
+
+ release = function() {
+ releaseMethods.forEach(function(fn) { fn(); });
+ records.removeArrayObserver(self, observer);
+ self.releaseMethods.removeObject(release);
+ };
+
+ recordsAdded(recordsToSend);
+
+ this.releaseMethods.pushObject(release);
+ return release;
+ },
+
+ /**
+ Clear all observers before destruction
+ @private
+ @method willDestroy
+ */
+ willDestroy: function() {
+ this._super();
+ this.releaseMethods.forEach(function(fn) {
+ fn();
+ });
+ },
+
+ /**
+ Detect whether a class is a model.
+
+ Test that against the model class
+ of your persistence library
+
+ @private
+ @method detect
+ @param {Class} klass The class to test
+ @return boolean Whether the class is a model class or not
+ */
+ detect: function(klass) {
+ return false;
+ },
+
+ /**
+ Get the columns for a given model type.
+
+ @private
+ @method columnsForType
+ @param {Class} type The model type
+ @return {Array} An array of columns of the following format:
+ name: {String} name of the column
+ desc: {String} Humanized description (what would show in a table column name)
+ */
+ columnsForType: function(type) {
+ return emberA();
+ },
+
+ /**
+ Adds observers to a model type class.
+
+ @private
+ @method observeModelType
+ @param {Class} type The model type class
+ @param {Function} typesUpdated Called when a type is modified.
+ @return {Function} The function to call to remove observers
+ */
+
+ observeModelType: function(type, typesUpdated) {
+ var self = this, records = this.getRecords(type);
+
+ var onChange = function() {
+ typesUpdated([self.wrapModelType(type)]);
+ };
+ var observer = {
+ didChange: function() {
+ run.scheduleOnce('actions', this, onChange);
+ },
+ willChange: Ember.K
+ };
+
+ records.addArrayObserver(this, observer);
+
+ var release = function() {
+ records.removeArrayObserver(self, observer);
+ };
+
+ return release;
+ },
+
+
+ /**
+ Wraps a given model type and observes changes to it.
+
+ @private
+ @method wrapModelType
+ @param {Class} type A model class
+ @param {String} Optional name of the class
+ @return {Object} contains the wrapped type and the function to remove observers
+ Format:
+ type: {Object} the wrapped type
+ The wrapped type has the following format:
+ name: {String} name of the type
+ count: {Integer} number of records available
+ columns: {Columns} array of columns to describe the record
+ object: {Class} the actual Model type class
+ release: {Function} The function to remove observers
+ */
+ wrapModelType: function(type, name) {
+ var release, records = this.getRecords(type),
+ typeToSend, self = this;
+
+ typeToSend = {
+ name: name || type.toString(),
+ count: get(records, 'length'),
+ columns: this.columnsForType(type),
+ object: type
+ };
+
+
+ return typeToSend;
+ },
+
+
+ /**
+ Fetches all models defined in the application.
+
+ @private
+ @method getModelTypes
+ @return {Array} Array of model types
+ */
+ getModelTypes: function() {
+ var types, self = this,
+ containerDebugAdapter = this.get('containerDebugAdapter');
+
+ if (containerDebugAdapter.canCatalogEntriesByType('model')) {
+ types = containerDebugAdapter.catalogEntriesByType('model');
+ } else {
+ types = this._getObjectsOnNamespaces();
+ }
+
+ // New adapters return strings instead of classes
+ types = emberA(types).map(function(name) {
+ return {
+ klass: self._nameToClass(name),
+ name: name
+ };
+ });
+ types = emberA(types).filter(function(type) {
+ return self.detect(type.klass);
+ });
+
+ return emberA(types);
+ },
+
+ /**
+ Loops over all namespaces and all objects
+ attached to them
+
+ @private
+ @method _getObjectsOnNamespaces
+ @return {Array} Array of model type strings
+ */
+ _getObjectsOnNamespaces: function() {
+ var namespaces = emberA(Namespace.NAMESPACES),
+ types = emberA(),
+ self = this;
+
+ namespaces.forEach(function(namespace) {
+ for (var key in namespace) {
+ if (!namespace.hasOwnProperty(key)) { continue; }
+ // Even though we will filter again in `getModelTypes`,
+ // we should not call `lookupContainer` on non-models
+ // (especially when `Ember.MODEL_FACTORY_INJECTIONS` is `true`)
+ if (!self.detect(namespace[key])) { continue; }
+ var name = dasherize(key);
+ if (!(namespace instanceof Application) && namespace.toString()) {
+ name = namespace + '/' + name;
+ }
+ types.push(name);
+ }
+ });
+ return types;
+ },
+
+ /**
+ Fetches all loaded records for a given type.
+
+ @private
+ @method getRecords
+ @return {Array} An array of records.
+ This array will be observed for changes,
+ so it should update when new records are added/removed.
+ */
+ getRecords: function(type) {
+ return emberA();
+ },
+
+ /**
+ Wraps a record and observers changes to it.
+
+ @private
+ @method wrapRecord
+ @param {Object} record The record instance.
+ @return {Object} The wrapped record. Format:
+ columnValues: {Array}
+ searchKeywords: {Array}
+ */
+ wrapRecord: function(record) {
+ var recordToSend = { object: record }, columnValues = {}, self = this;
+
+ recordToSend.columnValues = this.getRecordColumnValues(record);
+ recordToSend.searchKeywords = this.getRecordKeywords(record);
+ recordToSend.filterValues = this.getRecordFilterValues(record);
+ recordToSend.color = this.getRecordColor(record);
+
+ return recordToSend;
+ },
+
+ /**
+ Gets the values for each column.
+
+ @private
+ @method getRecordColumnValues
+ @return {Object} Keys should match column names defined
+ by the model type.
+ */
+ getRecordColumnValues: function(record) {
+ return {};
+ },
+
+ /**
+ Returns keywords to match when searching records.
+
+ @private
+ @method getRecordKeywords
+ @return {Array} Relevant keywords for search.
+ */
+ getRecordKeywords: function(record) {
+ return emberA();
+ },
+
+ /**
+ Returns the values of filters defined by `getFilters`.
+
+ @private
+ @method getRecordFilterValues
+ @param {Object} record The record instance
+ @return {Object} The filter values
+ */
+ getRecordFilterValues: function(record) {
+ return {};
+ },
+
+ /**
+ Each record can have a color that represents its state.
+
+ @private
+ @method getRecordColor
+ @param {Object} record The record instance
+ @return {String} The record's color
+ Possible options: black, red, blue, green
+ */
+ getRecordColor: function(record) {
+ return null;
+ },
+
+ /**
+ Observes all relevant properties and re-sends the wrapped record
+ when a change occurs.
+
+ @private
+ @method observerRecord
+ @param {Object} record The record instance
+ @param {Function} recordUpdated The callback to call when a record is updated.
+ @return {Function} The function to call to remove all observers.
+ */
+ observeRecord: function(record, recordUpdated) {
+ return function(){};
+ }
+ });
+ });
+define("ember-extension-support/initializers",
+ [],
+ function() {
+ "use strict";
+
+ });
+define("ember-handlebars-compiler",
+ ["ember-metal/core","exports"],
+ function(__dependency1__, __exports__) {
+ "use strict";
+ /* global Handlebars:true */
+
+ /**
+ @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')['default']; } // 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;
+ });
+define("ember-handlebars",
+ ["ember-handlebars-compiler","ember-metal/core","ember-runtime/system/lazy_load","ember-handlebars/loader","ember-handlebars/ext","ember-handlebars/string","ember-handlebars/helpers/shared","ember-handlebars/helpers/binding","ember-handlebars/helpers/collection","ember-handlebars/helpers/view","ember-handlebars/helpers/unbound","ember-handlebars/helpers/debug","ember-handlebars/helpers/each","ember-handlebars/helpers/template","ember-handlebars/helpers/partial","ember-handlebars/helpers/yield","ember-handlebars/helpers/loc","ember-handlebars/controls/checkbox","ember-handlebars/controls/select","ember-handlebars/controls/text_area","ember-handlebars/controls/text_field","ember-handlebars/controls/text_support","ember-handlebars/controls","ember-handlebars/component_lookup","ember-handlebars/views/handlebars_bound_view","ember-handlebars/views/metamorph_view","exports"],
+ function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __dependency15__, __dependency16__, __dependency17__, __dependency18__, __dependency19__, __dependency20__, __dependency21__, __dependency22__, __dependency23__, __dependency24__, __dependency25__, __dependency26__, __exports__) {
+ "use strict";
+ var EmberHandlebars = __dependency1__["default"];
+ var Ember = __dependency2__["default"];
+ // to add to globals
+
+ var runLoadHooks = __dependency3__.runLoadHooks;
+ var bootstrap = __dependency4__["default"];
+
+ var normalizePath = __dependency5__.normalizePath;
+ var template = __dependency5__.template;
+ var makeBoundHelper = __dependency5__.makeBoundHelper;
+ var registerBoundHelper = __dependency5__.registerBoundHelper;
+ var resolveHash = __dependency5__.resolveHash;
+ var resolveParams = __dependency5__.resolveParams;
+ var getEscaped = __dependency5__.getEscaped;
+ var handlebarsGet = __dependency5__.handlebarsGet;
+ var evaluateUnboundHelper = __dependency5__.evaluateUnboundHelper;
+ var helperMissingHelper = __dependency5__.helperMissingHelper;
+ var blockHelperMissingHelper = __dependency5__.blockHelperMissingHelper;
+
+
+ // side effect of extending StringUtils of htmlSafe
+
+ var resolvePaths = __dependency7__["default"];
+ var bind = __dependency8__.bind;
+ var _triageMustacheHelper = __dependency8__._triageMustacheHelper;
+ var resolveHelper = __dependency8__.resolveHelper;
+ var bindHelper = __dependency8__.bindHelper;
+ var boundIfHelper = __dependency8__.boundIfHelper;
+ var unboundIfHelper = __dependency8__.unboundIfHelper;
+ var withHelper = __dependency8__.withHelper;
+ var ifHelper = __dependency8__.ifHelper;
+ var unlessHelper = __dependency8__.unlessHelper;
+ var bindAttrHelper = __dependency8__.bindAttrHelper;
+ var bindAttrHelperDeprecated = __dependency8__.bindAttrHelperDeprecated;
+ var bindClasses = __dependency8__.bindClasses;
+
+ var collectionHelper = __dependency9__["default"];
+ var ViewHelper = __dependency10__.ViewHelper;
+ var viewHelper = __dependency10__.viewHelper;
+ var unboundHelper = __dependency11__["default"];
+ var logHelper = __dependency12__.logHelper;
+ var debuggerHelper = __dependency12__.debuggerHelper;
+ var EachView = __dependency13__.EachView;
+ var GroupedEach = __dependency13__.GroupedEach;
+ var eachHelper = __dependency13__.eachHelper;
+ var templateHelper = __dependency14__["default"];
+ var partialHelper = __dependency15__["default"];
+ var yieldHelper = __dependency16__["default"];
+ var locHelper = __dependency17__["default"];
+
+
+ var Checkbox = __dependency18__["default"];
+ var Select = __dependency19__.Select;
+ var SelectOption = __dependency19__.SelectOption;
+ var SelectOptgroup = __dependency19__.SelectOptgroup;
+ var TextArea = __dependency20__["default"];
+ var TextField = __dependency21__["default"];
+ var TextSupport = __dependency22__["default"];
+ var inputHelper = __dependency23__.inputHelper;
+ var textareaHelper = __dependency23__.textareaHelper;
+
+
+ var ComponentLookup = __dependency24__["default"];
+ var _HandlebarsBoundView = __dependency25__._HandlebarsBoundView;
+ var SimpleHandlebarsView = __dependency25__.SimpleHandlebarsView;
+ var _wrapMap = __dependency26__._wrapMap;
+ var _SimpleMetamorphView = __dependency26__._SimpleMetamorphView;
+ var _MetamorphView = __dependency26__._MetamorphView;
+ var _Metamorph = __dependency26__._Metamorph;
+
+
+ /**
+ Ember Handlebars
+
+ @module ember
+ @submodule ember-handlebars
+ @requires ember-views
+ */
+
+ // Ember.Handlebars.Globals
+ EmberHandlebars.bootstrap = bootstrap;
+ EmberHandlebars.template = template;
+ EmberHandlebars.makeBoundHelper = makeBoundHelper;
+ EmberHandlebars.registerBoundHelper = registerBoundHelper;
+ EmberHandlebars.resolveHash = resolveHash;
+ EmberHandlebars.resolveParams = resolveParams;
+ EmberHandlebars.resolveHelper = resolveHelper;
+ EmberHandlebars.get = handlebarsGet;
+ EmberHandlebars.getEscaped = getEscaped;
+ EmberHandlebars.evaluateUnboundHelper = evaluateUnboundHelper;
+ EmberHandlebars.bind = bind;
+ EmberHandlebars.bindClasses = bindClasses;
+ EmberHandlebars.EachView = EachView;
+ EmberHandlebars.GroupedEach = GroupedEach;
+ EmberHandlebars.resolvePaths = resolvePaths;
+ EmberHandlebars.ViewHelper = ViewHelper;
+ EmberHandlebars.normalizePath = normalizePath;
+
+
+ // Ember Globals
+ Ember.Handlebars = EmberHandlebars;
+ Ember.ComponentLookup = ComponentLookup;
+ Ember._SimpleHandlebarsView = SimpleHandlebarsView;
+ Ember._HandlebarsBoundView = _HandlebarsBoundView;
+ Ember._SimpleMetamorphView = _SimpleMetamorphView;
+ Ember._MetamorphView = _MetamorphView;
+ Ember._Metamorph = _Metamorph;
+ Ember._metamorphWrapMap = _wrapMap;
+ Ember.TextSupport = TextSupport;
+ Ember.Checkbox = Checkbox;
+ Ember.Select = Select;
+ Ember.SelectOption = SelectOption;
+ Ember.SelectOptgroup = SelectOptgroup;
+ Ember.TextArea = TextArea;
+ Ember.TextField = TextField;
+ Ember.TextSupport = TextSupport;
+
+ // register helpers
+ EmberHandlebars.registerHelper('helperMissing', helperMissingHelper);
+ EmberHandlebars.registerHelper('blockHelperMissing', blockHelperMissingHelper);
+ EmberHandlebars.registerHelper('bind', bindHelper);
+ EmberHandlebars.registerHelper('boundIf', boundIfHelper);
+ EmberHandlebars.registerHelper('_triageMustache', _triageMustacheHelper);
+ EmberHandlebars.registerHelper('unboundIf', unboundIfHelper);
+ EmberHandlebars.registerHelper('with', withHelper);
+ EmberHandlebars.registerHelper('if', ifHelper);
+ EmberHandlebars.registerHelper('unless', unlessHelper);
+ EmberHandlebars.registerHelper('bind-attr', bindAttrHelper);
+ EmberHandlebars.registerHelper('bindAttr', bindAttrHelperDeprecated);
+ EmberHandlebars.registerHelper('collection', collectionHelper);
+ EmberHandlebars.registerHelper("log", logHelper);
+ EmberHandlebars.registerHelper("debugger", debuggerHelper);
+ EmberHandlebars.registerHelper("each", eachHelper);
+ EmberHandlebars.registerHelper("loc", locHelper);
+ EmberHandlebars.registerHelper("partial", partialHelper);
+ EmberHandlebars.registerHelper("template", templateHelper);
+ EmberHandlebars.registerHelper("yield", yieldHelper);
+ EmberHandlebars.registerHelper("view", viewHelper);
+ EmberHandlebars.registerHelper("unbound", unboundHelper);
+ EmberHandlebars.registerHelper("input", inputHelper);
+ EmberHandlebars.registerHelper("textarea", textareaHelper);
+
+ // run load hooks
+ runLoadHooks('Ember.Handlebars', EmberHandlebars);
+
+ __exports__["default"] = EmberHandlebars;
+ });
+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","ember-handlebars/ext","exports"],
+ function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __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 handlebarsGet = __dependency6__.handlebarsGet;
+ var helpers = EmberHandlebars.helpers;
+ /**
+ @module ember
+ @submodule ember-handlebars-compiler
+ */
+
+ function _resolveOption(context, options, key) {
+ if (options.hashTypes[key] === "ID") {
+ return handlebarsGet(context, options.hash[key], options);
+ } else {
+ return options.hash[key];
+ }
+ }
+
+ /**
+
+ 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
+
+ ```
+
+ ## Actions
+
+ The helper can send multiple actions based on user events.
+
+ The action property defines the action which is send when
+ the user presses the return key.
+
+ ```handlebars
+ {{input action="submit"}}
+ ```
+
+ The helper allows some user events to send actions.
+
+ * `enter`
+ * `insert-newline`
+ * `escape-press`
+ * `focus-in`
+ * `focus-out`
+ * `key-press`
+
+ For example, if you desire an action to be sent when the input is blurred,
+ you only need to setup the action name to the event name property.
+
+ ```handlebars
+ {{input focus-in="alertMessage"}}
+ ```
+
+ See more about [Text Support Actions](/api/classes/Ember.TextField.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 = _resolveOption(this, options, 'type'),
+ onEvent = hash.on;
+
+ if (inputType === 'checkbox') {
+ delete hash.type;
+ delete types.type;
+
+ 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 {
+ delete hash.on;
+
+ hash.onEvent = onEvent || 'enter';
+ return helpers.view.call(this, TextField, options);
+ }
+ }
+
+ __exports__.inputHelper = inputHelper;/**
+ `{{textarea}}` inserts a new instance of `
');
- },
-
- willInsertElement: function() {
- if (!this.get("height") || !this.get("rowHeight")) {
- throw "A ListView must be created with a height and a rowHeight.";
- }
- this._super();
- },
-
- /**
- @private
-
- Sets inline styles of the view:
- - height
- - width
- - position
- - overflow
- - -webkit-overflow
- - overflow-scrolling
-
- Called while attributes binding.
-
- @property {Ember.ComputedProperty} style
- */
- style: Ember.computed('height', 'width', function() {
- var height, width, style, css;
-
- height = get(this, 'height');
- width = get(this, 'width');
- css = get(this, 'css');
-
- style = '';
-
- if (height) { style += 'height:' + height + 'px;'; }
- if (width) { style += 'width:' + width + 'px;'; }
-
- for ( var rule in css ){
- if (css.hasOwnProperty(rule)) {
- style += rule + ':' + css[rule] + ';';
+ function willInsertElementIfNeeded(view) {
+ if (view.willInsertElement) {
+ view.willInsertElement();
}
}
- return style;
- }),
+ function didInsertElementIfNeeded(view) {
+ if (view.didInsertElement) {
+ view.didInsertElement();
+ }
+ }
- /**
- @private
+ function rerender() {
+ var element, buffer, context, hasChildViews;
+ element = get(this, 'element');
- Performs visual scrolling. Is overridden in Ember.ListView.
+ if (!element) { return; }
- @method scrollTo
- */
- scrollTo: function(y) {
- throw 'must override to perform the visual scroll and effectively delegate to _scrollContentTo';
- },
+ context = get(this, 'context');
- /**
- @private
- Internal method used to force scroll position
+ // releases action helpers in contents
+ // this means though that the ListItemView itself can't use classBindings or attributeBindings
+ // need support for rerender contents in ember
+ this.triggerRecursively('willClearRender');
- @method scrollTo
- */
- _scrollTo: Ember.K,
+ if (this.lengthAfterRender > this.lengthBeforeRender) {
+ this.clearRenderedChildren();
+ this._childViews.length = this.lengthBeforeRender; // triage bug in ember
+ }
- /**
- @private
- @method _scrollContentTo
- */
- _scrollContentTo: function(y) {
- var startingIndex, endingIndex,
- contentIndex, visibleEndingIndex, maxContentIndex,
- contentIndexEnd, contentLength, scrollTop;
+ if (context) {
+ buffer = Ember.RenderBuffer();
+ buffer = this.renderToBuffer(buffer);
- scrollTop = max(0, y);
+ // check again for childViews, since rendering may have added some
+ hasChildViews = this._childViews.length > 0;
- Ember.instrument('view._scrollContentTo', {
- scrollTop: scrollTop,
- content: get(this, 'content'),
- startingIndex: this._startingIndex(),
- endingIndex: min(max(get(this, 'content.length') - 1, 0), this._startingIndex() + this._numChildViewsForViewport())
- }, function () {
- contentLength = get(this, 'content.length');
- set(this, 'scrollTop', scrollTop);
+ if (hasChildViews) {
+ this.invokeRecursively(willInsertElementIfNeeded, false);
+ }
- maxContentIndex = max(contentLength - 1, 0);
+ element.innerHTML = buffer.innerString ? buffer.innerString() : backportedInnerString(buffer);
- startingIndex = this._startingIndex();
- visibleEndingIndex = startingIndex + this._numChildViewsForViewport();
+ set(this, 'element', element);
- endingIndex = min(maxContentIndex, visibleEndingIndex);
+ var transitionTo = this._transitionTo ? this._transitionTo : this.transitionTo;
- this.trigger('scrollYChanged', y);
+ transitionTo.call(this, 'inDOM');
- if (startingIndex === this._lastStartingIndex &&
- endingIndex === this._lastEndingIndex) {
+ if (hasChildViews) {
+ this.invokeRecursively(didInsertElementIfNeeded, false);
+ }
+ } else {
+ element.innerHTML = ''; // when there is no context, this view should be completely empty
+ }
+ }
+
+ /**
+ The `Ember.ListItemView` view class renders a
+ [div](https://developer.mozilla.org/en/HTML/Element/div) HTML element
+ with `ember-list-item-view` class. It allows you to specify a custom item
+ handlebars template for `Ember.ListView`.
+
+ Example:
+
+ ```handlebars
+
+ ```
+
+ ```javascript
+ App.ListView = Ember.ListView.extend({
+ height: 500,
+ rowHeight: 20,
+ itemViewClass: Ember.ListItemView.extend({templateName: "row_item"})
+ });
+ ```
+
+ @extends Ember.View
+ @class ListItemView
+ @namespace Ember
+ */
+ __exports__["default"] = Ember.View.extend(ListItemViewMixin, {
+ updateContext: function(newContext){
+ var context = get(this, 'context');
+ Ember.instrument('view.updateContext.render', this, function() {
+ if (context !== newContext) {
+ set(this, 'context', newContext);
+ if (newContext && newContext.isController) {
+ set(this, 'controller', newContext);
+ }
+ }
+ }, this);
+ },
+ rerender: function () {
+ Ember.run.scheduleOnce('render', this, rerender);
+ },
+ _contextDidChange: Ember.observer(rerender, 'context', 'controller')
+ });
+ });
+define("list-view/list_item_view_mixin",
+ ["exports"],
+ function(__exports__) {
+ "use strict";
+ // jshint validthis: true
+
+ var get = Ember.get, set = Ember.set;
+
+ function samePosition(a, b) {
+ return a && b && a.x === b.x && a.y === b.y;
+ }
+
+ function positionElement() {
+ var element, position, _position;
+
+ Ember.instrument('view.updateContext.positionElement', this, function() {
+ element = get(this, 'element');
+ position = this.position;
+ _position = this._position;
+
+ if (!position || !element) { return; }
+
+ // TODO: avoid needing this by avoiding unnecessary
+ // calls to this method in the first place
+ if (samePosition(position, _position)) { return; }
+ Ember.run.schedule('render', this, this._parentView.applyTransform, element, position.x, position.y);
+ this._position = position;
+ }, this);
+ }
+
+ __exports__["default"] = Ember.Mixin.create({
+ init: function(){
+ this._super();
+ this.one('didInsertElement', positionElement);
+ },
+ classNames: ['ember-list-item-view'],
+ _position: null,
+ updatePosition: function(position) {
+ this.position = position;
+ this._positionElement();
+ },
+ _positionElement: positionElement
+ });
+ });
+define("list-view/list_view",
+ ["list-view/list_view_helper","list-view/list_view_mixin","exports"],
+ function(__dependency1__, __dependency2__, __exports__) {
+ "use strict";
+ var ListViewHelper = __dependency1__["default"];
+ var ListViewMixin = __dependency2__["default"];
+
+ var get = Ember.get, set = Ember.set;
+
+ /**
+ The `Ember.ListView` view class renders a
+ [div](https://developer.mozilla.org/en/HTML/Element/div) HTML element,
+ with `ember-list-view` class.
+
+ The context of each item element within the `Ember.ListView` are populated
+ from the objects in the `Element.ListView`'s `content` property.
+
+ ### `content` as an Array of Objects
+
+ The simplest version of an `Ember.ListView` takes an array of object as its
+ `content` property. The object will be used as the `context` each item element
+ inside the rendered `div`.
+
+ Example:
+
+ ```javascript
+ App.ContributorsRoute = Ember.Route.extend({
+ model: function() {
+ return [{ name: 'Stefan Penner' }, { name: 'Alex Navasardyan' }, { name: 'Ray Cohen'}];
+ }
+ });
+ ```
+
+ ```handlebars
+ {{#ember-list items=contributors height=500 rowHeight=50}}
+ {{name}}
+ {{/ember-list}}
+ ```
+
+ Would result in the following HTML:
+
+ ```html
+
+
+
+ Stefan Penner
+
+
+ Alex Navasardyan
+
+
+ Rey Cohen
+
+
+
+
+ ```
+
+ By default `Ember.ListView` provides support for `height`,
+ `rowHeight`, `width`, `elementWidth`, `scrollTop` parameters.
+
+ Note, that `height` and `rowHeight` are required parameters.
+
+ ```handlebars
+ {{#ember-list items=this height=500 rowHeight=50}}
+ {{name}}
+ {{/ember-list}}
+ ```
+
+ If you would like to have multiple columns in your view layout, you can
+ set `width` and `elementWidth` parameters respectively.
+
+ ```handlebars
+ {{#ember-list items=this height=500 rowHeight=50 width=500 elementWidth=80}}
+ {{name}}
+ {{/ember-list}}
+ ```
+
+ ### extending `Ember.ListView`
+
+ Example:
+
+ ```handlebars
+ {{view App.ListView contentBinding="content"}}
+
+
+ ```
+
+ ```javascript
+ App.ListView = Ember.ListView.extend({
+ height: 500,
+ width: 500,
+ elementWidth: 80,
+ rowHeight: 20,
+ itemViewClass: Ember.ListItemView.extend({templateName: "row_item"})
+ });
+ ```
+
+ @extends Ember.ContainerView
+ @class ListView
+ @namespace Ember
+ */
+ __exports__["default"] = Ember.ContainerView.extend(ListViewMixin, {
+ css: {
+ position: 'relative',
+ overflow: 'auto',
+ '-webkit-overflow-scrolling': 'touch',
+ 'overflow-scrolling': 'touch'
+ },
+
+ applyTransform: ListViewHelper.applyTransform,
+
+ _scrollTo: function(scrollTop) {
+ var element = get(this, 'element');
+
+ if (element) { element.scrollTop = scrollTop; }
+ },
+
+ didInsertElement: function() {
+ var that = this;
+ var element = get(this, 'element');
+
+ this._updateScrollableHeight();
+
+ this._scroll = function(e) { that.scroll(e); };
+
+ Ember.$(element).on('scroll', this._scroll);
+ },
+
+ willDestroyElement: function() {
+ var element;
+
+ element = get(this, 'element');
+
+ Ember.$(element).off('scroll', this._scroll);
+ },
+
+ scroll: function(e) {
+ this.scrollTo(e.target.scrollTop);
+ },
+
+ scrollTo: function(y){
+ var element = get(this, 'element');
+ this._scrollTo(y);
+ this._scrollContentTo(y);
+ },
+
+ totalHeightDidChange: Ember.observer(function () {
+ Ember.run.scheduleOnce('afterRender', this, this._updateScrollableHeight);
+ }, 'totalHeight'),
+
+ _updateScrollableHeight: function () {
+ var height, state;
+
+ // Support old and new Ember versions
+ state = this._state || this.state;
+
+ if (state === 'inDOM') {
+ // if the list is currently displaying the emptyView, remove the height
+ if (this._isChildEmptyView()) {
+ height = '';
+ } else {
+ height = get(this, 'totalHeight');
+ }
+
+ this.$('.ember-list-container').css({
+ height: height
+ });
+ }
+ }
+ });
+ });
+define("list-view/list_view_helper",
+ ["exports"],
+ function(__exports__) {
+ "use strict";
+ // TODO - remove this!
+ var el = document.createElement('div'), style = el.style;
+
+ var propPrefixes = ['Webkit', 'Moz', 'O', 'ms'];
+
+ function testProp(prop) {
+ if (prop in style) return prop;
+ var uppercaseProp = prop.charAt(0).toUpperCase() + prop.slice(1);
+ for (var i=0; i 0) {
- // invoked by observer
- Ember.run.schedule('afterRender', this, syncListContainerWidth);
- }
- }, 'columnCount'),
-
- /**
- @private
-
- Computes max possible scrollTop value given the visible viewport
- and scrollable container div height.
-
- @property {Ember.ComputedProperty} maxScrollTop
- */
- maxScrollTop: Ember.computed('height', 'totalHeight', function(){
- var totalHeight, viewportHeight;
-
- totalHeight = get(this, 'totalHeight');
- viewportHeight = get(this, 'height');
-
- return max(0, totalHeight - viewportHeight);
- }),
-
- /**
- @private
-
- Computes the number of views that would fit in the viewport area.
- You must specify `height` and `rowHeight` parameters for the number of
- views to be computed properly.
-
- @method _numChildViewsForViewport
- */
- _numChildViewsForViewport: function() {
- var height, rowHeight, paddingCount, columnCount;
-
- height = get(this, 'height');
- rowHeight = get(this, 'rowHeight');
- paddingCount = get(this, 'paddingCount');
- columnCount = get(this, 'columnCount');
-
- return (ceil(height / rowHeight) * columnCount) + (paddingCount * columnCount);
- },
-
- /**
- @private
-
- Computes the starting index of the item views array.
- Takes `scrollTop` property of the element into account.
-
- Is used in `_syncChildViews`.
-
- @method _startingIndex
- */
- _startingIndex: function() {
- var scrollTop, rowHeight, columnCount, calculatedStartingIndex,
- contentLength, largestStartingIndex;
-
- contentLength = get(this, 'content.length');
- scrollTop = get(this, 'scrollTop');
- rowHeight = get(this, 'rowHeight');
- columnCount = get(this, 'columnCount');
-
- calculatedStartingIndex = floor(scrollTop / rowHeight) * columnCount;
-
- largestStartingIndex = max(contentLength - 1, 0);
-
- return min(calculatedStartingIndex, largestStartingIndex);
- },
-
- /**
- @private
- @event contentWillChange
- */
- contentWillChange: Ember.beforeObserver(function() {
- var content;
-
- content = get(this, 'content');
-
- if (content) {
- content.removeArrayObserver(this);
- }
- }, 'content'),
-
- /**),
- @private
- @event contentDidChange
- */
- contentDidChange: Ember.observer(function() {
- addContentArrayObserver.call(this);
- syncChildViews.call(this);
- }, 'content'),
-
- /**
- @private
- @property {Function} needsSyncChildViews
- */
- needsSyncChildViews: Ember.observer(syncChildViews, 'height', 'width', 'columnCount'),
-
- /**
- @private
-
- Returns a new item view. Takes `contentIndex` to set the context
- of the returned view properly.
-
- @param {Number} contentIndex item index in the content array
- @method _addItemView
- */
- _addItemView: function(contentIndex){
- var itemViewClass, childView;
-
- itemViewClass = get(this, 'itemViewClass');
- childView = this.createChildView(itemViewClass);
-
- this.pushObject(childView);
- },
-
- /**
- @private
-
- Intelligently manages the number of childviews.
-
- @method _syncChildViews
- **/
- _syncChildViews: function(){
- var itemViewClass, startingIndex, childViewCount,
- endingIndex, numberOfChildViews, numberOfChildViewsNeeded,
- childViews, count, delta, index, childViewsLength, contentIndex;
-
- if (get(this, 'isDestroyed') || get(this, 'isDestroying')) {
- return;
- }
-
- childViewCount = this._childViewCount();
- childViews = this.positionOrderedChildViews();
-
- startingIndex = this._startingIndex();
- endingIndex = startingIndex + childViewCount;
-
- numberOfChildViewsNeeded = childViewCount;
- numberOfChildViews = childViews.length;
-
- delta = numberOfChildViewsNeeded - numberOfChildViews;
-
- if (delta === 0) {
- // no change
- } else if (delta > 0) {
- // more views are needed
- contentIndex = this._lastEndingIndex;
-
- for (count = 0; count < delta; count++, contentIndex++) {
- this._addItemView(contentIndex);
+ function enableProfilingOutput() {
+ function before(name, time, payload) {
+ console.time(name);
}
- } else {
- // less views are needed
- forEach.call(
- childViews.splice(numberOfChildViewsNeeded, numberOfChildViews),
- removeAndDestroy,
- this
- );
- }
-
- this._scrollContentTo(get(this, 'scrollTop'));
-
- // if _scrollContentTo short-circuits, we still need
- // to call _reuseChildren to get new views positioned
- // and rendered correctly
- this._reuseChildren();
-
- this._lastStartingIndex = startingIndex;
- this._lastEndingIndex = this._lastEndingIndex + delta;
- },
-
- /**
- @private
- @method _reuseChildren
- */
- _reuseChildren: function(){
- var contentLength, childViews, childViewsLength,
- startingIndex, endingIndex, childView, attrs,
- contentIndex, visibleEndingIndex, maxContentIndex,
- contentIndexEnd, scrollTop;
-
- scrollTop = get(this, 'scrollTop');
- contentLength = get(this, 'content.length');
- maxContentIndex = max(contentLength - 1, 0);
- childViews = this._childViews;
- childViewsLength = childViews.length;
-
- startingIndex = this._startingIndex();
- visibleEndingIndex = startingIndex + this._numChildViewsForViewport();
-
- endingIndex = min(maxContentIndex, visibleEndingIndex);
-
- this.trigger('scrollContentTo', scrollTop);
-
- contentIndexEnd = min(visibleEndingIndex, startingIndex + childViewsLength);
-
- for (contentIndex = startingIndex; contentIndex < contentIndexEnd; contentIndex++) {
- childView = childViews[contentIndex % childViewsLength];
- this._reuseChildForContentIndex(childView, contentIndex);
- }
- },
-
- /**
- @private
- @method positionOrderedChildViews
- */
- positionOrderedChildViews: function() {
- return this._childViews.sort(sortByContentIndex);
- },
-
- arrayWillChange: Ember.K,
-
- /**
- @private
- @event arrayDidChange
- */
- // TODO: refactor
- arrayDidChange: function(content, start, removedCount, addedCount) {
- var index, contentIndex;
-
- if (this.state === 'inDOM') {
- // ignore if all changes are out of the visible change
- if( start >= this._lastStartingIndex || start < this._lastEndingIndex) {
- index = 0;
- // ignore all changes not in the visible range
- // this can re-position many, rather then causing a cascade of re-renders
- forEach.call(
- this.positionOrderedChildViews(),
- function(childView) {
- contentIndex = this._lastStartingIndex + index;
- this._reuseChildForContentIndex(childView, contentIndex);
- index++;
- },
- this
- );
+ function after (name, time, payload) {
+ console.timeEnd(name);
}
- syncChildViews.call(this);
+ if (Ember.ENABLE_PROFILING) {
+ Ember.subscribe('view._scrollContentTo', {
+ before: before,
+ after: after
+ });
+ Ember.subscribe('view.updateContext', {
+ before: before,
+ after: after
+ });
+ }
}
- }
-});
-})();
+ /**
+ @class Ember.ListViewMixin
+ @namespace Ember
+ */
+ __exports__["default"] = Ember.Mixin.create({
+ itemViewClass: ReusableListItemView,
+ emptyViewClass: Ember.View,
+ classNames: ['ember-list-view'],
+ attributeBindings: ['style'],
+ classNameBindings: ['_isGrid:ember-list-view-grid:ember-list-view-list'],
+ domManager: domManager,
+ scrollTop: 0,
+ bottomPadding: 0, // TODO: maybe this can go away
+ _lastEndingIndex: 0,
+ paddingCount: 1,
+ _cachedPos: 0,
+
+ _isGrid: Ember.computed('columnCount', function() {
+ return this.get('columnCount') > 1;
+ }).readOnly(),
+
+ /**
+ @private
+
+ Setup a mixin.
+ - adding observer to content array
+ - creating child views based on height and length of the content array
+
+ @method init
+ */
+ init: function() {
+ this._super();
+ this._cachedHeights = [0];
+ this.on('didInsertElement', this._syncListContainerWidth);
+ this.columnCountDidChange();
+ this._syncChildViews();
+ this._addContentArrayObserver();
+ },
+
+ _addContentArrayObserver: Ember.beforeObserver(function() {
+ addContentArrayObserver.call(this);
+ }, 'content'),
+
+ /**
+ Called on your view when it should push strings of HTML into a
+ `Ember.RenderBuffer`.
+
+ Adds a [div](https://developer.mozilla.org/en-US/docs/HTML/Element/div)
+ with a required `ember-list-container` class.
+
+ @method render
+ @param {Ember.RenderBuffer} buffer The render buffer
+ */
+ render: function(buffer) {
+ buffer.push('
');
+ this._super(buffer);
+ buffer.push('
');
+ },
+
+ willInsertElement: function() {
+ if (!this.get("height") || !this.get("rowHeight")) {
+ throw new Error("A ListView must be created with a height and a rowHeight.");
+ }
+ this._super();
+ },
+
+ /**
+ @private
+
+ Sets inline styles of the view:
+ - height
+ - width
+ - position
+ - overflow
+ - -webkit-overflow
+ - overflow-scrolling
+
+ Called while attributes binding.
+
+ @property {Ember.ComputedProperty} style
+ */
+ style: Ember.computed('height', 'width', function() {
+ var height, width, style, css;
+
+ height = get(this, 'height');
+ width = get(this, 'width');
+ css = get(this, 'css');
+
+ style = '';
+
+ if (height) {
+ style += 'height:' + height + 'px;';
+ }
+
+ if (width) {
+ style += 'width:' + width + 'px;';
+ }
+
+ for ( var rule in css ) {
+ if (css.hasOwnProperty(rule)) {
+ style += rule + ':' + css[rule] + ';';
+ }
+ }
+
+ return style;
+ }),
+
+ /**
+ @private
+
+ Performs visual scrolling. Is overridden in Ember.ListView.
+
+ @method scrollTo
+ */
+ scrollTo: function(y) {
+ throw new Error('must override to perform the visual scroll and effectively delegate to _scrollContentTo');
+ },
+
+ /**
+ @private
+
+ Internal method used to force scroll position
+
+ @method scrollTo
+ */
+ _scrollTo: Ember.K,
+
+ /**
+ @private
+ @method _scrollContentTo
+ */
+ _scrollContentTo: function(y) {
+ var startingIndex, endingIndex,
+ contentIndex, visibleEndingIndex, maxContentIndex,
+ contentIndexEnd, contentLength, scrollTop, content;
+
+ scrollTop = max(0, y);
+
+ if (this.scrollTop === scrollTop) {
+ return;
+ }
+
+ // allow a visual overscroll, but don't scroll the content. As we are doing needless
+ // recycyling, and adding unexpected nodes to the DOM.
+ var maxScrollTop = max(0, get(this, 'totalHeight') - get(this, 'height'));
+ scrollTop = min(scrollTop, maxScrollTop);
+
+ content = get(this, 'content');
+ contentLength = get(content, 'length');
+ startingIndex = this._startingIndex(contentLength);
+
+ Ember.instrument('view._scrollContentTo', {
+ scrollTop: scrollTop,
+ content: content,
+ startingIndex: startingIndex,
+ endingIndex: min(max(contentLength - 1, 0), startingIndex + this._numChildViewsForViewport())
+ }, function () {
+ this.scrollTop = scrollTop;
+
+ maxContentIndex = max(contentLength - 1, 0);
+
+ startingIndex = this._startingIndex();
+ visibleEndingIndex = startingIndex + this._numChildViewsForViewport();
+
+ endingIndex = min(maxContentIndex, visibleEndingIndex);
+
+ if (startingIndex === this._lastStartingIndex &&
+ endingIndex === this._lastEndingIndex) {
+
+ this.trigger('scrollYChanged', y);
+ return;
+ } else {
+
+ Ember.run(this, function() {
+ this._reuseChildren();
+
+ this._lastStartingIndex = startingIndex;
+ this._lastEndingIndex = endingIndex;
+ this.trigger('scrollYChanged', y);
+ });
+ }
+ }, this);
+
+ },
+
+ /**
+ @private
+
+ Computes the height for a `Ember.ListView` scrollable container div.
+ You must specify `rowHeight` parameter for the height to be computed properly.
+
+ @property {Ember.ComputedProperty} totalHeight
+ */
+ totalHeight: Ember.computed('content.length',
+ 'rowHeight',
+ 'columnCount',
+ 'bottomPadding', function() {
+ if (typeof this.heightForIndex === 'function') {
+ return this._totalHeightWithHeightForIndex();
+ } else {
+ return this._totalHeightWithStaticRowHeight();
+ }
+ }),
+
+ _doRowHeightDidChange: function() {
+ this._cachedHeights = [0];
+ this._cachedPos = 0;
+ this._syncChildViews();
+ },
+
+ _rowHeightDidChange: Ember.observer('rowHeight', function() {
+ Ember.run.once(this, this._doRowHeightDidChange);
+ }),
+
+ _totalHeightWithHeightForIndex: function() {
+ var length = this.get('content.length');
+ return this._cachedHeightLookup(length);
+ },
+
+ _totalHeightWithStaticRowHeight: function() {
+ var contentLength, rowHeight, columnCount, bottomPadding;
+
+ contentLength = get(this, 'content.length');
+ rowHeight = get(this, 'rowHeight');
+ columnCount = get(this, 'columnCount');
+ bottomPadding = get(this, 'bottomPadding');
+
+ return ((ceil(contentLength / columnCount)) * rowHeight) + bottomPadding;
+ },
+
+ /**
+ @private
+ @method _prepareChildForReuse
+ */
+ _prepareChildForReuse: function(childView) {
+ childView.prepareForReuse();
+ },
+
+ /**
+ @private
+ @method _reuseChildForContentIndex
+ */
+ _reuseChildForContentIndex: function(childView, contentIndex) {
+ var content, context, newContext, childsCurrentContentIndex, position, enableProfiling, oldChildView;
+
+ var contentViewClass = this.itemViewForIndex(contentIndex);
+
+ if (childView.constructor !== contentViewClass) {
+ // rather then associative arrays, lets move childView + contentEntry maping to a Map
+ var i = this._childViews.indexOf(childView);
+
+ childView.destroy();
+ childView = this.createChildView(contentViewClass);
+
+ this.insertAt(i, childView);
+ }
+
+ content = get(this, 'content');
+ enableProfiling = get(this, 'enableProfiling');
+ position = this.positionForIndex(contentIndex);
+ childView.updatePosition(position);
+
+ set(childView, 'contentIndex', contentIndex);
+
+ if (enableProfiling) {
+ Ember.instrument('view._reuseChildForContentIndex', position, function() {
+
+ }, this);
+ }
+
+ newContext = content.objectAt(contentIndex);
+ childView.updateContext(newContext);
+ },
+
+ /**
+ @private
+ @method positionForIndex
+ */
+ positionForIndex: function(index) {
+ if (typeof this.heightForIndex !== 'function') {
+ return this._singleHeightPosForIndex(index);
+ }
+ else {
+ return this._multiHeightPosForIndex(index);
+ }
+ },
+
+ _singleHeightPosForIndex: function(index) {
+ var elementWidth, width, columnCount, rowHeight, y, x;
+
+ elementWidth = get(this, 'elementWidth') || 1;
+ width = get(this, 'width') || 1;
+ columnCount = get(this, 'columnCount');
+ rowHeight = get(this, 'rowHeight');
+
+ y = (rowHeight * floor(index/columnCount));
+ x = (index % columnCount) * elementWidth;
+
+ return {
+ y: y,
+ x: x
+ };
+ },
+
+ // 0 maps to 0, 1 maps to heightForIndex(i)
+ _multiHeightPosForIndex: function(index) {
+ var elementWidth, width, columnCount, rowHeight, y, x;
+
+ elementWidth = get(this, 'elementWidth') || 1;
+ width = get(this, 'width') || 1;
+ columnCount = get(this, 'columnCount');
+
+ x = (index % columnCount) * elementWidth;
+ y = this._cachedHeightLookup(index);
+
+ return {
+ x: x,
+ y: y
+ };
+ },
+
+ _cachedHeightLookup: function(index) {
+ for (var i = this._cachedPos; i < index; i++) {
+ this._cachedHeights[i + 1] = this._cachedHeights[i] + this.heightForIndex(i);
+ }
+ this._cachedPos = i;
+ return this._cachedHeights[index];
+ },
+
+ /**
+ @private
+ @method _childViewCount
+ */
+ _childViewCount: function() {
+ var contentLength, childViewCountForHeight;
+
+ contentLength = get(this, 'content.length');
+ childViewCountForHeight = this._numChildViewsForViewport();
+
+ return min(contentLength, childViewCountForHeight);
+ },
+
+ /**
+ @private
+
+ Returns a number of columns in the Ember.ListView (for grid layout).
+
+ If you want to have a multi column layout, you need to specify both
+ `width` and `elementWidth`.
+
+ If no `elementWidth` is specified, it returns `1`. Otherwise, it will
+ try to fit as many columns as possible for a given `width`.
+
+ @property {Ember.ComputedProperty} columnCount
+ */
+ columnCount: Ember.computed('width', 'elementWidth', function() {
+ var elementWidth, width, count;
+
+ elementWidth = get(this, 'elementWidth');
+ width = get(this, 'width');
+
+ if (elementWidth && width > elementWidth) {
+ count = floor(width / elementWidth);
+ } else {
+ count = 1;
+ }
+
+ return count;
+ }),
+
+ /**
+ @private
+
+ Fires every time column count is changed.
+
+ @event columnCountDidChange
+ */
+ columnCountDidChange: Ember.observer(function() {
+ var ratio, currentScrollTop, proposedScrollTop, maxScrollTop,
+ scrollTop, lastColumnCount, newColumnCount, element;
+
+ lastColumnCount = this._lastColumnCount;
+
+ currentScrollTop = this.scrollTop;
+ newColumnCount = get(this, 'columnCount');
+ maxScrollTop = get(this, 'maxScrollTop');
+ element = get(this, 'element');
+
+ this._lastColumnCount = newColumnCount;
+
+ if (lastColumnCount) {
+ ratio = (lastColumnCount / newColumnCount);
+ proposedScrollTop = currentScrollTop * ratio;
+ scrollTop = min(maxScrollTop, proposedScrollTop);
+
+ this._scrollTo(scrollTop);
+ this.scrollTop = scrollTop;
+ }
+
+ if (arguments.length > 0) {
+ // invoked by observer
+ Ember.run.schedule('afterRender', this, this._syncListContainerWidth);
+ }
+ }, 'columnCount'),
+
+ /**
+ @private
+
+ Computes max possible scrollTop value given the visible viewport
+ and scrollable container div height.
+
+ @property {Ember.ComputedProperty} maxScrollTop
+ */
+ maxScrollTop: Ember.computed('height', 'totalHeight', function(){
+ var totalHeight, viewportHeight;
+
+ totalHeight = get(this, 'totalHeight');
+ viewportHeight = get(this, 'height');
+
+ return max(0, totalHeight - viewportHeight);
+ }),
+
+ /**
+ @private
+
+ Determines whether the emptyView is the current childView.
+
+ @method _isChildEmptyView
+ */
+ _isChildEmptyView: function() {
+ var emptyView = get(this, 'emptyView');
+
+ return emptyView && emptyView instanceof Ember.View &&
+ this._childViews.length === 1 && this._childViews.indexOf(emptyView) === 0;
+ },
+
+ /**
+ @private
+
+ Computes the number of views that would fit in the viewport area.
+ You must specify `height` and `rowHeight` parameters for the number of
+ views to be computed properly.
+
+ @method _numChildViewsForViewport
+ */
+ _numChildViewsForViewport: function() {
+
+ if (this.heightForIndex) {
+ return this._numChildViewsForViewportWithMultiHeight();
+ } else {
+ return this._numChildViewsForViewportWithoutMultiHeight();
+ }
+ },
+
+ _numChildViewsForViewportWithoutMultiHeight: function() {
+ var height, rowHeight, paddingCount, columnCount;
+
+ height = get(this, 'height');
+ rowHeight = get(this, 'rowHeight');
+ paddingCount = get(this, 'paddingCount');
+ columnCount = get(this, 'columnCount');
+
+ return (ceil(height / rowHeight) * columnCount) + (paddingCount * columnCount);
+ },
+
+ _numChildViewsForViewportWithMultiHeight: function() {
+ var rowHeight, paddingCount, columnCount;
+ var scrollTop = this.scrollTop;
+ var viewportHeight = this.get('height');
+ var length = this.get('content.length');
+ var heightfromTop = 0;
+ var padding = get(this, 'paddingCount');
+
+ var startingIndex = this._calculatedStartingIndex();
+ var currentHeight = 0;
+
+ var offsetHeight = this._cachedHeightLookup(startingIndex);
+ for (var i = 0; i < length; i++) {
+ if (this._cachedHeightLookup(startingIndex + i + 1) - offsetHeight > viewportHeight) {
+ break;
+ }
+ }
+
+ return i + padding + 1;
+ },
+ /**
+ @private
-(function() {
-var get = Ember.get, set = Ember.set;
+ Computes the starting index of the item views array.
+ Takes `scrollTop` property of the element into account.
-/**
- The `Ember.ListView` view class renders a
- [div](https://developer.mozilla.org/en/HTML/Element/div) HTML element,
- with `ember-list-view` class.
+ Is used in `_syncChildViews`.
- The context of each item element within the `Ember.ListView` are populated
- from the objects in the `Element.ListView`'s `content` property.
+ @method _startingIndex
+ */
+ _startingIndex: function(_contentLength) {
+ var scrollTop, rowHeight, columnCount, calculatedStartingIndex,
+ contentLength;
- ### `content` as an Array of Objects
+ if (_contentLength === undefined) {
+ contentLength = get(this, 'content.length');
+ } else {
+ contentLength = _contentLength;
+ }
- The simplest version of an `Ember.ListView` takes an array of object as its
- `content` property. The object will be used as the `context` each item element
- inside the rendered `div`.
+ scrollTop = this.scrollTop;
+ rowHeight = get(this, 'rowHeight');
+ columnCount = get(this, 'columnCount');
- Example:
+ if (this.heightForIndex) {
+ calculatedStartingIndex = this._calculatedStartingIndex();
+ } else {
+ calculatedStartingIndex = floor(scrollTop / rowHeight) * columnCount;
+ }
- ```javascript
- App.contributors = [{ name: 'Stefan Penner' }, { name: 'Alex Navasardyan' }, { name: 'Rey Cohen'}];
- ```
+ var viewsNeededForViewport = this._numChildViewsForViewport();
+ var paddingCount = (1 * columnCount);
+ var largestStartingIndex = max(contentLength - viewsNeededForViewport, 0);
- ```handlebars
- {{#collection Ember.ListView contentBinding="App.contributors" height=500 rowHeight=50}}
- {{name}}
- {{/collection}}
- ```
+ return min(calculatedStartingIndex, largestStartingIndex);
+ },
- Would result in the following HTML:
+ _calculatedStartingIndex: function() {
+ var rowHeight, paddingCount, columnCount;
+ var scrollTop = this.scrollTop;
+ var viewportHeight = this.get('height');
+ var length = this.get('content.length');
+ var heightfromTop = 0;
+ var padding = get(this, 'paddingCount');
- ```html
-
-
-
- Stefan Penner
-
-
- Alex Navasardyan
-
-
- Rey Cohen
-
-
-
-
- ```
+ for (var i = 0; i < length; i++) {
+ if (this._cachedHeightLookup(i + 1) >= scrollTop) {
+ break;
+ }
+ }
- By default `Ember.ListView` provides support for `height`,
- `rowHeight`, `width`, `elementWidth`, `scrollTop` parameters.
+ return i;
+ },
- Note, that `height` and `rowHeight` are required parameters.
+ /**
+ @private
+ @event contentWillChange
+ */
+ contentWillChange: Ember.beforeObserver(function() {
+ var content;
- ```handlebars
- {{#collection Ember.ListView contentBinding="App.contributors" height=500 rowHeight=50}}
- {{name}}
- {{/collection}}
- ```
+ content = get(this, 'content');
- If you would like to have multiple columns in your view layout, you can
- set `width` and `elementWidth` parameters respectively.
+ if (content) {
+ content.removeArrayObserver(this);
+ }
+ }, 'content'),
- ```handlebars
- {{#collection Ember.ListView contentBinding="App.contributors" height=500 rowHeight=50 width=500 elementWidth=80}}
- {{name}}
- {{/collection}}
- ```
+ /**),
+ @private
+ @event contentDidChange
+ */
+ contentDidChange: Ember.observer(function() {
+ addContentArrayObserver.call(this);
+ syncChildViews.call(this);
+ }, 'content'),
- ### extending `Ember.ListView`
+ /**
+ @private
+ @property {Function} needsSyncChildViews
+ */
+ needsSyncChildViews: Ember.observer(syncChildViews, 'height', 'width', 'columnCount'),
- Example:
+ /**
+ @private
- ```handlebars
- {{view App.ListView contentBinding="content"}}
+ Returns a new item view. Takes `contentIndex` to set the context
+ of the returned view properly.
-
- ```
+ @param {Number} contentIndex item index in the content array
+ @method _addItemView
+ */
+ _addItemView: function(contentIndex){
+ var itemViewClass, childView;
- ```javascript
- App.ListView = Ember.ListView.extend({
- height: 500,
- width: 500,
- elementWidth: 80,
- rowHeight: 20,
- itemViewClass: Ember.ListItemView.extend({templateName: "row_item"})
+ itemViewClass = this.itemViewForIndex(contentIndex);
+ childView = this.createChildView(itemViewClass);
+
+ this.pushObject(childView);
+ },
+
+ /**
+ @public
+
+ Returns a view class for the provided contentIndex. If the view is
+ different then the one currently present it will remove the existing view
+ and replace it with an instance of the class provided
+
+ @param {Number} contentIndex item index in the content array
+ @method _addItemView
+ @returns {Ember.View} ember view class for this index
+ */
+ itemViewForIndex: function(contentIndex) {
+ return get(this, 'itemViewClass');
+ },
+
+ /**
+ @public
+
+ Returns a view class for the provided contentIndex. If the view is
+ different then the one currently present it will remove the existing view
+ and replace it with an instance of the class provided
+
+ @param {Number} contentIndex item index in the content array
+ @method _addItemView
+ @returns {Ember.View} ember view class for this index
+ */
+ heightForIndex: null,
+
+ /**
+ @private
+
+ Intelligently manages the number of childviews.
+
+ @method _syncChildViews
+ **/
+ _syncChildViews: function(){
+ var childViews, childViewCount,
+ numberOfChildViews, numberOfChildViewsNeeded,
+ contentIndex, startingIndex, endingIndex,
+ contentLength, emptyView, count, delta;
+
+ if (get(this, 'isDestroyed') || get(this, 'isDestroying')) {
+ return;
+ }
+
+ contentLength = get(this, 'content.length');
+ emptyView = get(this, 'emptyView');
+
+ childViewCount = this._childViewCount();
+ childViews = this.positionOrderedChildViews();
+
+ if (this._isChildEmptyView()) {
+ removeEmptyView.call(this);
+ }
+
+ startingIndex = this._startingIndex();
+ endingIndex = startingIndex + childViewCount;
+
+ numberOfChildViewsNeeded = childViewCount;
+ numberOfChildViews = childViews.length;
+
+ delta = numberOfChildViewsNeeded - numberOfChildViews;
+
+ if (delta === 0) {
+ // no change
+ } else if (delta > 0) {
+ // more views are needed
+ contentIndex = this._lastEndingIndex;
+
+ for (count = 0; count < delta; count++, contentIndex++) {
+ this._addItemView(contentIndex);
+ }
+ } else {
+ // less views are needed
+ forEach.call(
+ childViews.splice(numberOfChildViewsNeeded, numberOfChildViews),
+ removeAndDestroy,
+ this
+ );
+ }
+
+ this._reuseChildren();
+
+ this._lastStartingIndex = startingIndex;
+ this._lastEndingIndex = this._lastEndingIndex + delta;
+
+ if (contentLength === 0 || contentLength === undefined) {
+ addEmptyView.call(this);
+ }
+ },
+
+ /**
+ @private
+
+ Applies an inline width style to the list container.
+
+ @method _syncListContainerWidth
+ **/
+ _syncListContainerWidth: function() {
+ var elementWidth, columnCount, containerWidth, element;
+
+ elementWidth = get(this, 'elementWidth');
+ columnCount = get(this, 'columnCount');
+ containerWidth = elementWidth * columnCount;
+ element = this.$('.ember-list-container');
+
+ if (containerWidth && element) {
+ element.css('width', containerWidth);
+ }
+ },
+
+ /**
+ @private
+ @method _reuseChildren
+ */
+ _reuseChildren: function(){
+ var contentLength, childViews, childViewsLength,
+ startingIndex, endingIndex, childView, attrs,
+ contentIndex, visibleEndingIndex, maxContentIndex,
+ contentIndexEnd, scrollTop;
+
+ scrollTop = this.scrollTop;
+ contentLength = get(this, 'content.length');
+ maxContentIndex = max(contentLength - 1, 0);
+ childViews = this.getReusableChildViews();
+ childViewsLength = childViews.length;
+
+ startingIndex = this._startingIndex();
+ visibleEndingIndex = startingIndex + this._numChildViewsForViewport();
+
+ endingIndex = min(maxContentIndex, visibleEndingIndex);
+
+ contentIndexEnd = min(visibleEndingIndex, startingIndex + childViewsLength);
+
+ for (contentIndex = startingIndex; contentIndex < contentIndexEnd; contentIndex++) {
+ childView = childViews[contentIndex % childViewsLength];
+ this._reuseChildForContentIndex(childView, contentIndex);
+ }
+ },
+
+ /**
+ @private
+ @method getReusableChildViews
+ */
+ getReusableChildViews: function() {
+ return this._childViews;
+ },
+
+ /**
+ @private
+ @method positionOrderedChildViews
+ */
+ positionOrderedChildViews: function() {
+ return this.getReusableChildViews().sort(sortByContentIndex);
+ },
+
+ arrayWillChange: Ember.K,
+
+ /**
+ @private
+ @event arrayDidChange
+ */
+ // TODO: refactor
+ arrayDidChange: function(content, start, removedCount, addedCount) {
+ var index, contentIndex, state;
+
+ if (this._isChildEmptyView()) {
+ removeEmptyView.call(this);
+ }
+
+ // Support old and new Ember versions
+ state = this._state || this.state;
+
+ if (state === 'inDOM') {
+ // ignore if all changes are out of the visible change
+ if (start >= this._lastStartingIndex || start < this._lastEndingIndex) {
+ index = 0;
+ // ignore all changes not in the visible range
+ // this can re-position many, rather then causing a cascade of re-renders
+ forEach.call(
+ this.positionOrderedChildViews(),
+ function(childView) {
+ contentIndex = this._lastStartingIndex + index;
+ this._reuseChildForContentIndex(childView, contentIndex);
+ index++;
+ },
+ this
+ );
+ }
+
+ syncChildViews.call(this);
+ }
+ },
+
+ destroy: function () {
+ if (!this._super()) { return; }
+
+ if (this._createdEmptyView) {
+ this._createdEmptyView.destroy();
+ }
+
+ return this;
+ }
+ });
});
- ```
+define("list-view/main",
+ ["list-view/reusable_list_item_view","list-view/virtual_list_view","list-view/list_item_view","list-view/helper","list-view/list_view","list-view/list_view_helper"],
+ function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__) {
+ "use strict";
+ var ReusableListItemView = __dependency1__["default"];
+ var VirtualListView = __dependency2__["default"];
+ var ListItemView = __dependency3__["default"];
+ var EmberList = __dependency4__["default"];
+ var ListView = __dependency5__["default"];
+ var ListViewHelper = __dependency6__["default"];
- @extends Ember.ContainerView
- @class ListView
- @namespace Ember
-*/
-Ember.ListView = Ember.ContainerView.extend(Ember.ListViewMixin, {
- css: {
- position: 'relative',
- overflow: 'scroll',
- '-webkit-overflow-scrolling': 'touch',
- 'overflow-scrolling': 'touch'
- },
+ Ember.ReusableListItemView = ReusableListItemView;
+ Ember.VirtualListView = VirtualListView;
+ Ember.ListItemView = ListItemView;
+ Ember.ListView = ListView;
+ Ember.ListViewHelper = ListViewHelper;
- applyTransform: Ember.ListViewHelper.applyTransform,
+ Ember.Handlebars.registerHelper('ember-list', EmberList);
+ });
+define("list-view/reusable_list_item_view",
+ ["list-view/list_item_view_mixin","exports"],
+ function(__dependency1__, __exports__) {
+ "use strict";
+ var ListItemViewMixin = __dependency1__["default"];
- _scrollTo: function(scrollTop) {
- var element = get(this, 'element');
+ var get = Ember.get, set = Ember.set;
- if (element) { element.scrollTop = scrollTop; }
- },
+ __exports__["default"] = Ember.View.extend(ListItemViewMixin, {
+ init: function(){
+ this._super();
+ var context = Ember.ObjectProxy.create();
+ this.set('context', context);
+ this._proxyContext = context;
+ },
+ isVisible: Ember.computed('context.content', function(){
+ return !!this.get('context.content');
+ }),
+ updateContext: function(newContext){
+ var context = get(this._proxyContext, 'content'), state;
- didInsertElement: function() {
- var that, element;
+ // Support old and new Ember versions
+ state = this._state || this.state;
- that = this,
- element = get(this, 'element');
+ if (context !== newContext) {
+ if (state === 'inDOM') {
+ this.prepareForReuse(newContext);
+ }
- this._updateScrollableHeight();
+ set(this._proxyContext, 'content', newContext);
- this._scroll = function(e) { that.scroll(e); };
-
- Ember.$(element).on('scroll', this._scroll);
- },
-
- willDestroyElement: function() {
- var element;
-
- element = get(this, 'element');
-
- Ember.$(element).off('scroll', this._scroll);
- },
-
- scroll: function(e) {
- Ember.run(this, this.scrollTo, e.target.scrollTop);
- },
-
- scrollTo: function(y){
- var element = get(this, 'element');
- this._scrollTo(y);
- this._scrollContentTo(y);
- },
-
- totalHeightDidChange: Ember.observer(function () {
- Ember.run.scheduleOnce('afterRender', this, this._updateScrollableHeight);
- }, 'totalHeight'),
-
- _updateScrollableHeight: function () {
- if (this.state === 'inDOM') {
- this.$('.ember-list-container').css({
- height: get(this, 'totalHeight')
- });
+ if (newContext && newContext.isController) {
+ set(this, 'controller', newContext);
+ }
+ }
+ },
+ prepareForReuse: Ember.K
+ });
+ });
+define("list-view/virtual_list_scroller_events",
+ ["exports"],
+ function(__exports__) {
+ "use strict";
+ // jshint validthis: true
+ var fieldRegex = /input|textarea|select/i,
+ hasTouch = ('ontouchstart' in window) || window.DocumentTouch && document instanceof window.DocumentTouch,
+ handleStart, handleMove, handleEnd, handleCancel,
+ startEvent, moveEvent, endEvent, cancelEvent;
+ if (hasTouch) {
+ startEvent = 'touchstart';
+ handleStart = function (e) {
+ var touch = e.touches[0],
+ target = touch && touch.target;
+ // avoid e.preventDefault() on fields
+ if (target && fieldRegex.test(target.tagName)) {
+ return;
+ }
+ bindWindow(this.scrollerEventHandlers);
+ this.willBeginScroll(e.touches, e.timeStamp);
+ e.preventDefault();
+ };
+ moveEvent = 'touchmove';
+ handleMove = function (e) {
+ this.continueScroll(e.touches, e.timeStamp);
+ };
+ endEvent = 'touchend';
+ handleEnd = function (e) {
+ // if we didn't end up scrolling we need to
+ // synthesize click since we did e.preventDefault()
+ // on touchstart
+ if (!this._isScrolling) {
+ synthesizeClick(e);
+ }
+ unbindWindow(this.scrollerEventHandlers);
+ this.endScroll(e.timeStamp);
+ };
+ cancelEvent = 'touchcancel';
+ handleCancel = function (e) {
+ unbindWindow(this.scrollerEventHandlers);
+ this.endScroll(e.timeStamp);
+ };
+ } else {
+ startEvent = 'mousedown';
+ handleStart = function (e) {
+ if (e.which !== 1) return;
+ var target = e.target;
+ // avoid e.preventDefault() on fields
+ if (target && fieldRegex.test(target.tagName)) {
+ return;
+ }
+ bindWindow(this.scrollerEventHandlers);
+ this.willBeginScroll([e], e.timeStamp);
+ e.preventDefault();
+ };
+ moveEvent = 'mousemove';
+ handleMove = function (e) {
+ this.continueScroll([e], e.timeStamp);
+ };
+ endEvent = 'mouseup';
+ handleEnd = function (e) {
+ unbindWindow(this.scrollerEventHandlers);
+ this.endScroll(e.timeStamp);
+ };
+ cancelEvent = 'mouseout';
+ handleCancel = function (e) {
+ if (e.relatedTarget) return;
+ unbindWindow(this.scrollerEventHandlers);
+ this.endScroll(e.timeStamp);
+ };
}
- }
-});
-})();
-
-
-
-(function() {
-var fieldRegex = /input|textarea|select/i,
- hasTouch = ('ontouchstart' in window) || window.DocumentTouch && document instanceof window.DocumentTouch,
- handleStart, handleMove, handleEnd, handleCancel,
- startEvent, moveEvent, endEvent, cancelEvent;
-if (hasTouch) {
- startEvent = 'touchstart';
- handleStart = function (e) {
- var touch = e.touches[0],
- target = touch && touch.target;
- // avoid e.preventDefault() on fields
- if (target && fieldRegex.test(target.tagName)) {
- return;
+ function handleWheel(e) {
+ this.mouseWheel(e);
+ e.preventDefault();
}
- bindWindow(this.scrollerEventHandlers);
- this.willBeginScroll(e.touches, e.timeStamp);
- e.preventDefault();
- };
- moveEvent = 'touchmove';
- handleMove = function (e) {
- this.continueScroll(e.touches, e.timeStamp);
- };
- endEvent = 'touchend';
- handleEnd = function (e) {
- // if we didn't end up scrolling we need to
- // synthesize click since we did e.preventDefault()
- // on touchstart
- if (!this._isScrolling) {
- synthesizeClick(e);
+
+ function bindElement(el, handlers) {
+ el.addEventListener(startEvent, handlers.start, false);
+ el.addEventListener('mousewheel', handlers.wheel, false);
}
- unbindWindow(this.scrollerEventHandlers);
- this.endScroll(e.timeStamp);
- };
- cancelEvent = 'touchcancel';
- handleCancel = function (e) {
- unbindWindow(this.scrollerEventHandlers);
- this.endScroll(e.timeStamp);
- };
-} else {
- startEvent = 'mousedown';
- handleStart = function (e) {
- if (e.which !== 1) return;
- var target = e.target;
- // avoid e.preventDefault() on fields
- if (target && fieldRegex.test(target.tagName)) {
- return;
+
+ function unbindElement(el, handlers) {
+ el.removeEventListener(startEvent, handlers.start, false);
+ el.removeEventListener('mousewheel', handlers.wheel, false);
}
- bindWindow(this.scrollerEventHandlers);
- this.willBeginScroll([e], e.timeStamp);
- e.preventDefault();
- };
- moveEvent = 'mousemove';
- handleMove = function (e) {
- this.continueScroll([e], e.timeStamp);
- };
- endEvent = 'mouseup';
- handleEnd = function (e) {
- unbindWindow(this.scrollerEventHandlers);
- this.endScroll(e.timeStamp);
- };
- cancelEvent = 'mouseout';
- handleCancel = function (e) {
- if (e.relatedTarget) return;
- unbindWindow(this.scrollerEventHandlers);
- this.endScroll(e.timeStamp);
- };
-}
-function handleWheel(e) {
- this.mouseWheel(e);
- e.preventDefault();
-}
+ function bindWindow(handlers) {
+ window.addEventListener(moveEvent, handlers.move, true);
+ window.addEventListener(endEvent, handlers.end, true);
+ window.addEventListener(cancelEvent, handlers.cancel, true);
+ }
-function bindElement(el, handlers) {
- el.addEventListener(startEvent, handlers.start, false);
- el.addEventListener('mousewheel', handlers.wheel, false);
-}
+ function unbindWindow(handlers) {
+ window.removeEventListener(moveEvent, handlers.move, true);
+ window.removeEventListener(endEvent, handlers.end, true);
+ window.removeEventListener(cancelEvent, handlers.cancel, true);
+ }
-function unbindElement(el, handlers) {
- el.removeEventListener(startEvent, handlers.start, false);
- el.removeEventListener('mousewheel', handlers.wheel, false);
-}
-
-function bindWindow(handlers) {
- window.addEventListener(moveEvent, handlers.move, true);
- window.addEventListener(endEvent, handlers.end, true);
- window.addEventListener(cancelEvent, handlers.cancel, true);
-}
-
-function unbindWindow(handlers) {
- window.removeEventListener(moveEvent, handlers.move, true);
- window.removeEventListener(endEvent, handlers.end, true);
- window.removeEventListener(cancelEvent, handlers.cancel, true);
-}
-
-Ember.VirtualListScrollerEvents = Ember.Mixin.create({
- init: function() {
- this.on('didInsertElement', this, 'bindScrollerEvents');
- this.on('willDestroyElement', this, 'unbindScrollerEvents');
- this.scrollerEventHandlers = {
- start: bind(this, handleStart),
- move: bind(this, handleMove),
- end: bind(this, handleEnd),
- cancel: bind(this, handleCancel),
- wheel: bind(this, handleWheel)
- };
- return this._super();
- },
- bindScrollerEvents: function() {
- var el = this.get('element'),
- handlers = this.scrollerEventHandlers;
- bindElement(el, handlers);
- },
- unbindScrollerEvents: function() {
- var el = this.get('element'),
- handlers = this.scrollerEventHandlers;
- unbindElement(el, handlers);
- unbindWindow(handlers);
- }
-});
-
-function bind(view, handler) {
- return function (evt) {
- handler.call(view, evt);
- };
-}
-
-function synthesizeClick(e) {
- var point = e.changedTouches[0],
- target = point.target,
- ev;
- if (target && fieldRegex.test(target.tagName)) {
- ev = document.createEvent('MouseEvents');
- ev.initMouseEvent('click', true, true, e.view, 1, point.screenX, point.screenY, point.clientX, point.clientY, e.ctrlKey, e.altKey, e.shiftKey, e.metaKey, 0, null);
- return target.dispatchEvent(ev);
- }
-}
-
-})();
-
-
-
-(function() {
-/*global Scroller*/
-var max = Math.max, get = Ember.get, set = Ember.set;
-
-function updateScrollerDimensions(target) {
- var width, height, totalHeight;
-
- target = target || this;
-
- width = get(target, 'width');
- height = get(target, 'height');
- totalHeight = get(target, 'totalHeight');
-
- target.scroller.setDimensions(width, height, width, totalHeight);
- target.trigger('scrollerDimensionsDidChange');
-}
-
-/**
- VirtualListView
-
- @class VirtualListView
- @namespace Ember
-*/
-Ember.VirtualListView = Ember.ContainerView.extend(Ember.ListViewMixin, Ember.VirtualListScrollerEvents, {
- _isScrolling: false,
- _mouseWheel: null,
- css: {
- position: 'relative',
- overflow: 'hidden'
- },
-
- init: function(){
- this._super();
- this.setupScroller();
- },
- _scrollerTop: 0,
- applyTransform: Ember.ListViewHelper.apply3DTransform,
-
- setupScroller: function(){
- var view, y;
-
- view = this;
-
- view.scroller = new Scroller(function(left, top, zoom) {
- if (view.state !== 'inDOM') { return; }
-
- if (view.listContainerElement) {
- view.applyTransform(view.listContainerElement, 0, -top);
- view._scrollerTop = top;
- view._scrollContentTo(top);
- }
- }, {
- scrollingX: false,
- scrollingComplete: function(){
- view.trigger('scrollingDidComplete');
+ __exports__["default"] = Ember.Mixin.create({
+ init: function() {
+ this.on('didInsertElement', this, 'bindScrollerEvents');
+ this.on('willDestroyElement', this, 'unbindScrollerEvents');
+ this.scrollerEventHandlers = {
+ start: bind(this, handleStart),
+ move: bind(this, handleMove),
+ end: bind(this, handleEnd),
+ cancel: bind(this, handleCancel),
+ wheel: bind(this, handleWheel)
+ };
+ return this._super();
+ },
+ scrollElement: Ember.computed.oneWay('element').readOnly(),
+ bindScrollerEvents: function() {
+ var el = this.get('scrollElement'),
+ handlers = this.scrollerEventHandlers;
+ bindElement(el, handlers);
+ },
+ unbindScrollerEvents: function() {
+ var el = this.get('scrollElement'),
+ handlers = this.scrollerEventHandlers;
+ unbindElement(el, handlers);
+ unbindWindow(handlers);
}
});
- view.trigger('didInitializeScroller');
- updateScrollerDimensions(view);
- },
+ function bind(view, handler) {
+ return function (evt) {
+ handler.call(view, evt);
+ };
+ }
- scrollerDimensionsNeedToChange: Ember.observer(function() {
- Ember.run.once(this, updateScrollerDimensions);
- }, 'width', 'height', 'totalHeight'),
-
- didInsertElement: function() {
- this.listContainerElement = this.$('> .ember-list-container')[0];
- },
-
- willBeginScroll: function(touches, timeStamp) {
- this._isScrolling = false;
- this.trigger('scrollingDidStart');
-
- this.scroller.doTouchStart(touches, timeStamp);
- },
-
- continueScroll: function(touches, timeStamp) {
- var startingScrollTop, endingScrollTop, event;
-
- if (this._isScrolling) {
- this.scroller.doTouchMove(touches, timeStamp);
- } else {
- startingScrollTop = this._scrollerTop;
-
- this.scroller.doTouchMove(touches, timeStamp);
-
- endingScrollTop = this._scrollerTop;
-
- if (startingScrollTop !== endingScrollTop) {
- event = Ember.$.Event("scrollerstart");
- Ember.$(touches[0].target).trigger(event);
-
- this._isScrolling = true;
+ function synthesizeClick(e) {
+ var point = e.changedTouches[0],
+ target = point.target,
+ ev;
+ if (target && fieldRegex.test(target.tagName)) {
+ ev = document.createEvent('MouseEvents');
+ ev.initMouseEvent('click', true, true, e.view, 1, point.screenX, point.screenY, point.clientX, point.clientY, e.ctrlKey, e.altKey, e.shiftKey, e.metaKey, 0, null);
+ return target.dispatchEvent(ev);
}
}
- },
+ });
+define("list-view/virtual_list_view",
+ ["list-view/list_view_mixin","list-view/list_view_helper","list-view/virtual_list_scroller_events","exports"],
+ function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
+ "use strict";
+ /*
+ global Scroller
+ */
- endScroll: function(timeStamp) {
- this.scroller.doTouchEnd(timeStamp);
- },
+ var ListViewMixin = __dependency1__["default"];
+ var ListViewHelper = __dependency2__["default"];
+ var VirtualListScrollerEvents = __dependency3__["default"];
- // api
- scrollTo: function(y, animate) {
- if (animate === undefined) {
- animate = true;
+ var max = Math.max, get = Ember.get, set = Ember.set;
+
+ function updateScrollerDimensions(target) {
+ var width, height, totalHeight;
+
+ target = target || this; // jshint ignore:line
+
+ width = get(target, 'width');
+ height = get(target, 'height');
+ totalHeight = get(target, 'totalHeight'); // jshint ignore:line
+
+ target.scroller.setDimensions(width, height, width, totalHeight);
+ target.trigger('scrollerDimensionsDidChange');
}
- this.scroller.scrollTo(0, y, animate, 1);
- },
+ /**
+ VirtualListView
- // events
- mouseWheel: function(e){
- var inverted, delta, candidatePosition;
+ @class VirtualListView
+ @namespace Ember
+ */
+ __exports__["default"] = Ember.ContainerView.extend(ListViewMixin, VirtualListScrollerEvents, {
+ _isScrolling: false,
+ _mouseWheel: null,
+ css: {
+ position: 'relative',
+ overflow: 'hidden'
+ },
- inverted = e.webkitDirectionInvertedFromDevice;
- delta = e.wheelDeltaY * (inverted ? 0.8 : -0.8);
- candidatePosition = this.scroller.__scrollTop + delta;
+ init: function(){
+ this._super();
+ this.setupScroller();
+ this.setupPullToRefresh();
+ },
+ _scrollerTop: 0,
+ applyTransform: ListViewHelper.apply3DTransform,
- if ((candidatePosition >= 0) && (candidatePosition <= this.scroller.__maxScrollTop)) {
- this.scroller.scrollBy(0, delta, true);
- }
+ setupScroller: function(){
+ var view, y;
- return false;
- }
-});
+ view = this;
-})();
+ view.scroller = new Scroller(function(left, top, zoom) {
+ // Support old and new Ember versions
+ var state = view._state || view.state;
+ if (state !== 'inDOM') { return; }
+ if (view.listContainerElement) {
+ view._scrollerTop = top;
+ view._scrollContentTo(top);
+ view.applyTransform(view.listContainerElement, 0, -top);
+ }
+ }, {
+ scrollingX: false,
+ scrollingComplete: function(){
+ view.trigger('scrollingDidComplete');
+ }
+ });
-(function() {
+ view.trigger('didInitializeScroller');
+ updateScrollerDimensions(view);
+ },
+ setupPullToRefresh: function() {
+ if (!this.pullToRefreshViewClass) { return; }
+ this._insertPullToRefreshView();
+ this._activateScrollerPullToRefresh();
+ },
+ _insertPullToRefreshView: function(){
+ this.pullToRefreshView = this.createChildView(this.pullToRefreshViewClass);
+ this.insertAt(0, this.pullToRefreshView);
+ var view = this;
+ this.pullToRefreshView.on('didInsertElement', function(){
+ Ember.run.schedule('afterRender', this, function(){
+ view.applyTransform(this.get('element'), 0, -1 * view.pullToRefreshViewHeight);
+ });
+ });
+ },
+ _activateScrollerPullToRefresh: function(){
+ var view = this;
+ function activatePullToRefresh(){
+ view.pullToRefreshView.set('active', true);
+ view.trigger('activatePullToRefresh');
+ }
+ function deactivatePullToRefresh() {
+ view.pullToRefreshView.set('active', false);
+ view.trigger('deactivatePullToRefresh');
+ }
+ function startPullToRefresh() {
+ Ember.run(function(){
+ view.pullToRefreshView.set('refreshing', true);
-})();
+ function finishRefresh(){
+ if (view && !view.get('isDestroyed') && !view.get('isDestroying')) {
+ view.scroller.finishPullToRefresh();
+ view.pullToRefreshView.set('refreshing', false);
+ }
+ }
+ view.startRefresh(finishRefresh);
+ });
+ }
+ this.scroller.activatePullToRefresh(
+ this.pullToRefreshViewHeight,
+ activatePullToRefresh,
+ deactivatePullToRefresh,
+ startPullToRefresh
+ );
+ },
+ getReusableChildViews: function(){
+ var firstView = this._childViews[0];
+ if (firstView && firstView === this.pullToRefreshView) {
+ return this._childViews.slice(1);
+ } else {
+ return this._childViews;
+ }
+ },
+
+ scrollerDimensionsNeedToChange: Ember.observer(function() {
+ Ember.run.once(this, updateScrollerDimensions);
+ }, 'width', 'height', 'totalHeight'),
+
+ didInsertElement: function() {
+ this.listContainerElement = this.$('> .ember-list-container')[0];
+ },
+
+ willBeginScroll: function(touches, timeStamp) {
+ this._isScrolling = false;
+ this.trigger('scrollingDidStart');
+
+ this.scroller.doTouchStart(touches, timeStamp);
+ },
+
+ continueScroll: function(touches, timeStamp) {
+ var startingScrollTop, endingScrollTop, event;
+
+ if (this._isScrolling) {
+ this.scroller.doTouchMove(touches, timeStamp);
+ } else {
+ startingScrollTop = this._scrollerTop;
+
+ this.scroller.doTouchMove(touches, timeStamp);
+
+ endingScrollTop = this._scrollerTop;
+
+ if (startingScrollTop !== endingScrollTop) {
+ event = Ember.$.Event("scrollerstart");
+ Ember.$(touches[0].target).trigger(event);
+
+ this._isScrolling = true;
+ }
+ }
+ },
+
+ endScroll: function(timeStamp) {
+ this.scroller.doTouchEnd(timeStamp);
+ },
+
+ // api
+ scrollTo: function(y, animate) {
+ if (animate === undefined) {
+ animate = true;
+ }
+
+ this.scroller.scrollTo(0, y, animate, 1);
+ },
+
+ // events
+ mouseWheel: function(e){
+ var inverted, delta, candidatePosition;
+
+ inverted = e.webkitDirectionInvertedFromDevice;
+ delta = e.wheelDeltaY * (inverted ? 0.8 : -0.8);
+ candidatePosition = this.scroller.__scrollTop + delta;
+
+ if ((candidatePosition >= 0) && (candidatePosition <= this.scroller.__maxScrollTop)) {
+ this.scroller.scrollBy(0, delta, true);
+ e.stopPropagation();
+ }
+
+ return false;
+ }
+ });
+ });
+ requireModule('list-view/main');
+})(this);
\ No newline at end of file
diff --git a/vendor/assets/javascripts/production/ember.js b/vendor/assets/javascripts/production/ember.js
index 497265a63a3..2744df8552d 100644
--- a/vendor/assets/javascripts/production/ember.js
+++ b/vendor/assets/javascripts/production/ember.js
@@ -5,10 +5,9 @@
* 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.6.0-beta.3+pre.2e4d67f6
+ * @version 1.7.1
*/
-
(function() {
var define, requireModule, require, requirejs, Ember;
@@ -72,22 +71,10425 @@ var define, requireModule, require, requirejs, Ember;
requirejs = require = requireModule = Ember.__loader.require;
}
})();
-(function() {
+
+define("backburner",
+ ["backburner/utils","backburner/deferred_action_queues","exports"],
+ function(__dependency1__, __dependency2__, __exports__) {
+ "use strict";
+ var Utils = __dependency1__["default"];
+ var DeferredActionQueues = __dependency2__.DeferredActionQueues;
+
+ var slice = [].slice,
+ pop = [].pop,
+ each = Utils.each,
+ isString = Utils.isString,
+ isFunction = Utils.isFunction,
+ isNumber = Utils.isNumber,
+ timers = [],
+ global = this,
+ NUMBER = /\d+/;
+
+ // In IE 6-8, try/finally doesn't work without a catch.
+ // Unfortunately, this is impossible to test for since wrapping it in a parent try/catch doesn't trigger the bug.
+ // This tests for another broken try/catch behavior that only exhibits in the same versions of IE.
+ var needsIETryCatchFix = (function(e,x){
+ try{ x(); }
+ catch(e) { } // jshint ignore:line
+ return !!e;
+ })();
+
+ function isCoercableNumber(number) {
+ return isNumber(number) || NUMBER.test(number);
+ }
+
+ function Backburner(queueNames, options) {
+ this.queueNames = queueNames;
+ this.options = options || {};
+ if (!this.options.defaultQueue) {
+ this.options.defaultQueue = queueNames[0];
+ }
+ this.instanceStack = [];
+ this._debouncees = [];
+ this._throttlers = [];
+ }
+
+ Backburner.prototype = {
+ queueNames: null,
+ options: null,
+ currentInstance: null,
+ instanceStack: null,
+
+ begin: function() {
+ var options = this.options,
+ onBegin = options && options.onBegin,
+ previousInstance = this.currentInstance;
+
+ if (previousInstance) {
+ this.instanceStack.push(previousInstance);
+ }
+
+ this.currentInstance = new DeferredActionQueues(this.queueNames, options);
+ if (onBegin) {
+ onBegin(this.currentInstance, previousInstance);
+ }
+ },
+
+ end: function() {
+ var options = this.options,
+ onEnd = options && options.onEnd,
+ currentInstance = this.currentInstance,
+ nextInstance = null;
+
+ // Prevent double-finally bug in Safari 6.0.2 and iOS 6
+ // This bug appears to be resolved in Safari 6.0.5 and iOS 7
+ var finallyAlreadyCalled = false;
+ try {
+ currentInstance.flush();
+ } finally {
+ if (!finallyAlreadyCalled) {
+ finallyAlreadyCalled = true;
+
+ this.currentInstance = null;
+
+ if (this.instanceStack.length) {
+ nextInstance = this.instanceStack.pop();
+ this.currentInstance = nextInstance;
+ }
+
+ if (onEnd) {
+ onEnd(currentInstance, nextInstance);
+ }
+ }
+ }
+ },
+
+ run: function(target, method /*, args */) {
+ var onError = getOnError(this.options);
+
+ this.begin();
+
+ if (!method) {
+ method = target;
+ target = null;
+ }
+
+ if (isString(method)) {
+ method = target[method];
+ }
+
+ var args = slice.call(arguments, 2);
+
+ // guard against Safari 6's double-finally bug
+ var didFinally = false;
+
+ if (onError) {
+ try {
+ return method.apply(target, args);
+ } catch(error) {
+ onError(error);
+ } finally {
+ if (!didFinally) {
+ didFinally = true;
+ this.end();
+ }
+ }
+ } else {
+ try {
+ return method.apply(target, args);
+ } finally {
+ if (!didFinally) {
+ didFinally = true;
+ this.end();
+ }
+ }
+ }
+ },
+
+ defer: function(queueName, target, method /* , args */) {
+ if (!method) {
+ method = target;
+ target = null;
+ }
+
+ if (isString(method)) {
+ method = target[method];
+ }
+
+ var stack = this.DEBUG ? new Error() : undefined,
+ args = arguments.length > 3 ? slice.call(arguments, 3) : undefined;
+ if (!this.currentInstance) { createAutorun(this); }
+ return this.currentInstance.schedule(queueName, target, method, args, false, stack);
+ },
+
+ deferOnce: function(queueName, target, method /* , args */) {
+ if (!method) {
+ method = target;
+ target = null;
+ }
+
+ if (isString(method)) {
+ method = target[method];
+ }
+
+ var stack = this.DEBUG ? new Error() : undefined,
+ args = arguments.length > 3 ? slice.call(arguments, 3) : undefined;
+ if (!this.currentInstance) { createAutorun(this); }
+ return this.currentInstance.schedule(queueName, target, method, args, true, stack);
+ },
+
+ setTimeout: function() {
+ var args = slice.call(arguments),
+ length = args.length,
+ method, wait, target,
+ methodOrTarget, methodOrWait, methodOrArgs;
+
+ if (length === 0) {
+ return;
+ } else if (length === 1) {
+ method = args.shift();
+ wait = 0;
+ } else if (length === 2) {
+ methodOrTarget = args[0];
+ methodOrWait = args[1];
+
+ if (isFunction(methodOrWait) || isFunction(methodOrTarget[methodOrWait])) {
+ target = args.shift();
+ method = args.shift();
+ wait = 0;
+ } else if (isCoercableNumber(methodOrWait)) {
+ method = args.shift();
+ wait = args.shift();
+ } else {
+ method = args.shift();
+ wait = 0;
+ }
+ } else {
+ var last = args[args.length - 1];
+
+ if (isCoercableNumber(last)) {
+ wait = args.pop();
+ } else {
+ wait = 0;
+ }
+
+ methodOrTarget = args[0];
+ methodOrArgs = args[1];
+
+ if (isFunction(methodOrArgs) || (isString(methodOrArgs) &&
+ methodOrTarget !== null &&
+ methodOrArgs in methodOrTarget)) {
+ target = args.shift();
+ method = args.shift();
+ } else {
+ method = args.shift();
+ }
+ }
+
+ var executeAt = (+new Date()) + parseInt(wait, 10);
+
+ if (isString(method)) {
+ method = target[method];
+ }
+
+ var onError = getOnError(this.options);
+
+ function fn() {
+ if (onError) {
+ try {
+ method.apply(target, args);
+ } catch (e) {
+ onError(e);
+ }
+ } else {
+ method.apply(target, args);
+ }
+ }
+
+ // find position to insert
+ var i = searchTimer(executeAt, timers);
+
+ timers.splice(i, 0, executeAt, fn);
+
+ updateLaterTimer(this, executeAt, wait);
+
+ return fn;
+ },
+
+ throttle: function(target, method /* , args, wait, [immediate] */) {
+ var self = this,
+ args = arguments,
+ immediate = pop.call(args),
+ wait,
+ throttler,
+ index,
+ timer;
+
+ if (isNumber(immediate) || isString(immediate)) {
+ wait = immediate;
+ immediate = true;
+ } else {
+ wait = pop.call(args);
+ }
+
+ wait = parseInt(wait, 10);
+
+ index = findThrottler(target, method, this._throttlers);
+ if (index > -1) { return this._throttlers[index]; } // throttled
+
+ timer = global.setTimeout(function() {
+ if (!immediate) {
+ self.run.apply(self, args);
+ }
+ var index = findThrottler(target, method, self._throttlers);
+ if (index > -1) {
+ self._throttlers.splice(index, 1);
+ }
+ }, wait);
+
+ if (immediate) {
+ self.run.apply(self, args);
+ }
+
+ throttler = [target, method, timer];
+
+ this._throttlers.push(throttler);
+
+ return throttler;
+ },
+
+ debounce: function(target, method /* , args, wait, [immediate] */) {
+ var self = this,
+ args = arguments,
+ immediate = pop.call(args),
+ wait,
+ index,
+ debouncee,
+ timer;
+
+ if (isNumber(immediate) || isString(immediate)) {
+ wait = immediate;
+ immediate = false;
+ } else {
+ wait = pop.call(args);
+ }
+
+ wait = parseInt(wait, 10);
+ // Remove debouncee
+ index = findDebouncee(target, method, this._debouncees);
+
+ if (index > -1) {
+ debouncee = this._debouncees[index];
+ this._debouncees.splice(index, 1);
+ clearTimeout(debouncee[2]);
+ }
+
+ timer = global.setTimeout(function() {
+ if (!immediate) {
+ self.run.apply(self, args);
+ }
+ var index = findDebouncee(target, method, self._debouncees);
+ if (index > -1) {
+ self._debouncees.splice(index, 1);
+ }
+ }, wait);
+
+ if (immediate && index === -1) {
+ self.run.apply(self, args);
+ }
+
+ debouncee = [target, method, timer];
+
+ self._debouncees.push(debouncee);
+
+ return debouncee;
+ },
+
+ cancelTimers: function() {
+ var clearItems = function(item) {
+ clearTimeout(item[2]);
+ };
+
+ each(this._throttlers, clearItems);
+ this._throttlers = [];
+
+ each(this._debouncees, clearItems);
+ this._debouncees = [];
+
+ if (this._laterTimer) {
+ clearTimeout(this._laterTimer);
+ this._laterTimer = null;
+ }
+ timers = [];
+
+ if (this._autorun) {
+ clearTimeout(this._autorun);
+ this._autorun = null;
+ }
+ },
+
+ hasTimers: function() {
+ return !!timers.length || !!this._debouncees.length || !!this._throttlers.length || this._autorun;
+ },
+
+ cancel: function(timer) {
+ var timerType = typeof timer;
+
+ if (timer && timerType === 'object' && timer.queue && timer.method) { // we're cancelling a deferOnce
+ return timer.queue.cancel(timer);
+ } else if (timerType === 'function') { // we're cancelling a setTimeout
+ for (var i = 0, l = timers.length; i < l; i += 2) {
+ if (timers[i + 1] === timer) {
+ timers.splice(i, 2); // remove the two elements
+ return true;
+ }
+ }
+ } else if (Object.prototype.toString.call(timer) === "[object Array]"){ // we're cancelling a throttle or debounce
+ return this._cancelItem(findThrottler, this._throttlers, timer) ||
+ this._cancelItem(findDebouncee, this._debouncees, timer);
+ } else {
+ return; // timer was null or not a timer
+ }
+ },
+
+ _cancelItem: function(findMethod, array, timer){
+ var item,
+ index;
+
+ if (timer.length < 3) { return false; }
+
+ index = findMethod(timer[0], timer[1], array);
+
+ if(index > -1) {
+
+ item = array[index];
+
+ if(item[2] === timer[2]){
+ array.splice(index, 1);
+ clearTimeout(timer[2]);
+ return true;
+ }
+ }
+
+ return false;
+ }
+ };
+
+ Backburner.prototype.schedule = Backburner.prototype.defer;
+ Backburner.prototype.scheduleOnce = Backburner.prototype.deferOnce;
+ Backburner.prototype.later = Backburner.prototype.setTimeout;
+
+ if (needsIETryCatchFix) {
+ var originalRun = Backburner.prototype.run;
+ Backburner.prototype.run = wrapInTryCatch(originalRun);
+
+ var originalEnd = Backburner.prototype.end;
+ Backburner.prototype.end = wrapInTryCatch(originalEnd);
+ }
+
+ function wrapInTryCatch(func) {
+ return function () {
+ try {
+ return func.apply(this, arguments);
+ } catch (e) {
+ throw e;
+ }
+ };
+ }
+
+ function getOnError(options) {
+ return options.onError || (options.onErrorTarget && options.onErrorTarget[options.onErrorMethod]);
+ }
+
+
+ function createAutorun(backburner) {
+ backburner.begin();
+ backburner._autorun = global.setTimeout(function() {
+ backburner._autorun = null;
+ backburner.end();
+ });
+ }
+
+ function updateLaterTimer(self, executeAt, wait) {
+ if (!self._laterTimer || executeAt < self._laterTimerExpiresAt) {
+ self._laterTimer = global.setTimeout(function() {
+ self._laterTimer = null;
+ self._laterTimerExpiresAt = null;
+ executeTimers(self);
+ }, wait);
+ self._laterTimerExpiresAt = executeAt;
+ }
+ }
+
+ function executeTimers(self) {
+ var now = +new Date(),
+ time, fns, i, l;
+
+ self.run(function() {
+ i = searchTimer(now, timers);
+
+ fns = timers.splice(0, i);
+
+ for (i = 1, l = fns.length; i < l; i += 2) {
+ self.schedule(self.options.defaultQueue, null, fns[i]);
+ }
+ });
+
+ if (timers.length) {
+ updateLaterTimer(self, timers[0], timers[0] - now);
+ }
+ }
+
+ function findDebouncee(target, method, debouncees) {
+ return findItem(target, method, debouncees);
+ }
+
+ function findThrottler(target, method, throttlers) {
+ return findItem(target, method, throttlers);
+ }
+
+ function findItem(target, method, collection) {
+ var item,
+ index = -1;
+
+ for (var i = 0, l = collection.length; i < l; i++) {
+ item = collection[i];
+ if (item[0] === target && item[1] === method) {
+ index = i;
+ break;
+ }
+ }
+
+ return index;
+ }
+
+ function searchTimer(time, timers) {
+ var start = 0,
+ end = timers.length - 2,
+ middle, l;
+
+ while (start < end) {
+ // since timers is an array of pairs 'l' will always
+ // be an integer
+ l = (end - start) / 2;
+
+ // compensate for the index in case even number
+ // of pairs inside timers
+ middle = start + l - (l % 2);
+
+ if (time >= timers[middle]) {
+ start = middle + 2;
+ } else {
+ end = middle;
+ }
+ }
+
+ return (time >= timers[start]) ? start + 2 : start;
+ }
+
+ __exports__.Backburner = Backburner;
+ });
+define("backburner/deferred_action_queues",
+ ["backburner/utils","backburner/queue","exports"],
+ function(__dependency1__, __dependency2__, __exports__) {
+ "use strict";
+ var Utils = __dependency1__["default"];
+ var Queue = __dependency2__.Queue;
+
+ var each = Utils.each,
+ isString = Utils.isString;
+
+ function DeferredActionQueues(queueNames, options) {
+ var queues = this.queues = {};
+ this.queueNames = queueNames = queueNames || [];
+
+ this.options = options;
+
+ each(queueNames, function(queueName) {
+ queues[queueName] = new Queue(this, queueName, options);
+ });
+ }
+
+ DeferredActionQueues.prototype = {
+ queueNames: null,
+ queues: null,
+ options: null,
+
+ schedule: function(queueName, target, method, args, onceFlag, stack) {
+ var queues = this.queues,
+ queue = queues[queueName];
+
+ if (!queue) { throw new Error("You attempted to schedule an action in a queue (" + queueName + ") that doesn't exist"); }
+
+ if (onceFlag) {
+ return queue.pushUnique(target, method, args, stack);
+ } else {
+ return queue.push(target, method, args, stack);
+ }
+ },
+
+ invoke: function(target, method, args, _) {
+ if (args && args.length > 0) {
+ method.apply(target, args);
+ } else {
+ method.call(target);
+ }
+ },
+
+ invokeWithOnError: function(target, method, args, onError) {
+ try {
+ if (args && args.length > 0) {
+ method.apply(target, args);
+ } else {
+ method.call(target);
+ }
+ } catch(error) {
+ onError(error);
+ }
+ },
+
+ flush: function() {
+ var queues = this.queues,
+ queueNames = this.queueNames,
+ queueName, queue, queueItems, priorQueueNameIndex,
+ queueNameIndex = 0, numberOfQueues = queueNames.length,
+ options = this.options,
+ onError = options.onError || (options.onErrorTarget && options.onErrorTarget[options.onErrorMethod]),
+ invoke = onError ? this.invokeWithOnError : this.invoke;
+
+ outerloop:
+ while (queueNameIndex < numberOfQueues) {
+ queueName = queueNames[queueNameIndex];
+ queue = queues[queueName];
+ queueItems = queue._queueBeingFlushed = queue._queue.slice();
+ queue._queue = [];
+
+ var queueOptions = queue.options, // TODO: write a test for this
+ before = queueOptions && queueOptions.before,
+ after = queueOptions && queueOptions.after,
+ target, method, args, stack,
+ queueIndex = 0, numberOfQueueItems = queueItems.length;
+
+ if (numberOfQueueItems && before) { before(); }
+
+ while (queueIndex < numberOfQueueItems) {
+ target = queueItems[queueIndex];
+ method = queueItems[queueIndex+1];
+ args = queueItems[queueIndex+2];
+ stack = queueItems[queueIndex+3]; // Debugging assistance
+
+ if (isString(method)) { method = target[method]; }
+
+ // method could have been nullified / canceled during flush
+ if (method) {
+ invoke(target, method, args, onError);
+ }
+
+ queueIndex += 4;
+ }
+
+ queue._queueBeingFlushed = null;
+ if (numberOfQueueItems && after) { after(); }
+
+ if ((priorQueueNameIndex = indexOfPriorQueueWithActions(this, queueNameIndex)) !== -1) {
+ queueNameIndex = priorQueueNameIndex;
+ continue outerloop;
+ }
+
+ queueNameIndex++;
+ }
+ }
+ };
+
+ function indexOfPriorQueueWithActions(daq, currentQueueIndex) {
+ var queueName, queue;
+
+ for (var i = 0, l = currentQueueIndex; i <= l; i++) {
+ queueName = daq.queueNames[i];
+ queue = daq.queues[queueName];
+ if (queue._queue.length) { return i; }
+ }
+
+ return -1;
+ }
+
+ __exports__.DeferredActionQueues = DeferredActionQueues;
+ });
+define("backburner/queue",
+ ["exports"],
+ function(__exports__) {
+ "use strict";
+ function Queue(daq, name, options) {
+ this.daq = daq;
+ this.name = name;
+ this.globalOptions = options;
+ this.options = options[name];
+ this._queue = [];
+ }
+
+ Queue.prototype = {
+ daq: null,
+ name: null,
+ options: null,
+ onError: null,
+ _queue: null,
+
+ push: function(target, method, args, stack) {
+ var queue = this._queue;
+ queue.push(target, method, args, stack);
+ return {queue: this, target: target, method: method};
+ },
+
+ pushUnique: function(target, method, args, stack) {
+ var queue = this._queue, currentTarget, currentMethod, i, l;
+
+ for (i = 0, l = queue.length; i < l; i += 4) {
+ currentTarget = queue[i];
+ currentMethod = queue[i+1];
+
+ if (currentTarget === target && currentMethod === method) {
+ queue[i+2] = args; // replace args
+ queue[i+3] = stack; // replace stack
+ return {queue: this, target: target, method: method};
+ }
+ }
+
+ queue.push(target, method, args, stack);
+ return {queue: this, target: target, method: method};
+ },
+
+ // TODO: remove me, only being used for Ember.run.sync
+ flush: function() {
+ var queue = this._queue,
+ globalOptions = this.globalOptions,
+ options = this.options,
+ before = options && options.before,
+ after = options && options.after,
+ onError = globalOptions.onError || (globalOptions.onErrorTarget && globalOptions.onErrorTarget[globalOptions.onErrorMethod]),
+ target, method, args, stack, i, l = queue.length;
+
+ if (l && before) { before(); }
+ for (i = 0; i < l; i += 4) {
+ target = queue[i];
+ method = queue[i+1];
+ args = queue[i+2];
+ stack = queue[i+3]; // Debugging assistance
+
+ // TODO: error handling
+ if (args && args.length > 0) {
+ if (onError) {
+ try {
+ method.apply(target, args);
+ } catch (e) {
+ onError(e);
+ }
+ } else {
+ method.apply(target, args);
+ }
+ } else {
+ if (onError) {
+ try {
+ method.call(target);
+ } catch(e) {
+ onError(e);
+ }
+ } else {
+ method.call(target);
+ }
+ }
+ }
+ if (l && after) { after(); }
+
+ // check if new items have been added
+ if (queue.length > l) {
+ this._queue = queue.slice(l);
+ this.flush();
+ } else {
+ this._queue.length = 0;
+ }
+ },
+
+ cancel: function(actionToCancel) {
+ var queue = this._queue, currentTarget, currentMethod, i, l;
+
+ for (i = 0, l = queue.length; i < l; i += 4) {
+ currentTarget = queue[i];
+ currentMethod = queue[i+1];
+
+ if (currentTarget === actionToCancel.target && currentMethod === actionToCancel.method) {
+ queue.splice(i, 4);
+ return true;
+ }
+ }
+
+ // if not found in current queue
+ // could be in the queue that is being flushed
+ queue = this._queueBeingFlushed;
+ if (!queue) {
+ return;
+ }
+ for (i = 0, l = queue.length; i < l; i += 4) {
+ currentTarget = queue[i];
+ currentMethod = queue[i+1];
+
+ if (currentTarget === actionToCancel.target && currentMethod === actionToCancel.method) {
+ // don't mess with array during flush
+ // just nullify the method
+ queue[i+1] = null;
+ return true;
+ }
+ }
+ }
+ };
+
+ __exports__.Queue = Queue;
+ });
+define("backburner/utils",
+ ["exports"],
+ function(__exports__) {
+ "use strict";
+ __exports__["default"] = {
+ each: function(collection, callback) {
+ for (var i = 0; i < collection.length; i++) {
+ callback(collection[i]);
+ }
+ },
+
+ isString: function(suspect) {
+ return typeof suspect === 'string';
+ },
+
+ isFunction: function(suspect) {
+ return typeof suspect === 'function';
+ },
+
+ isNumber: function(suspect) {
+ return typeof suspect === 'number';
+ }
+ };
+ });
+
+define("calculateVersion",
+ [],
+ function() {
+ "use strict";
+ 'use strict';
+
+ var fs = require('fs');
+ var path = require('path');
+
+ module.exports = function () {
+ var packageVersion = require('../package.json').version;
+ var output = [packageVersion];
+ var gitPath = path.join(__dirname,'..','.git');
+ var headFilePath = path.join(gitPath, 'HEAD');
+
+ if (packageVersion.indexOf('+') > -1) {
+ try {
+ if (fs.existsSync(headFilePath)) {
+ var headFile = fs.readFileSync(headFilePath, {encoding: 'utf8'});
+ var branchName = headFile.split('/').slice(-1)[0].trim();
+ var refPath = headFile.split(' ')[1];
+ var branchSHA;
+
+ if (refPath) {
+ var branchPath = path.join(gitPath, refPath.trim());
+ branchSHA = fs.readFileSync(branchPath);
+ } else {
+ branchSHA = branchName;
+ }
+
+ output.push(branchSHA.slice(0,10));
+ }
+ } catch (err) {
+ console.error(err.stack);
+ }
+ return output.join('.');
+ } else {
+ return packageVersion;
+ }
+ };
+ });
+define("container",
+ ["container/container","exports"],
+ function(__dependency1__, __exports__) {
+ "use strict";
+ /*
+ Public api for the container is still in flux.
+ The public api, specified on the application namespace should be considered the stable api.
+ // @module container
+ @private
+ */
+
+ /*
+ Flag to enable/disable model factory injections (disabled by default)
+ If model factory injections are enabled, models should not be
+ accessed globally (only through `container.lookupFactory('model:modelName'))`);
+ */
+ Ember.MODEL_FACTORY_INJECTIONS = false;
+
+ if (Ember.ENV && typeof Ember.ENV.MODEL_FACTORY_INJECTIONS !== 'undefined') {
+ Ember.MODEL_FACTORY_INJECTIONS = !!Ember.ENV.MODEL_FACTORY_INJECTIONS;
+ }
+
+
+ var Container = __dependency1__["default"];
+
+ __exports__["default"] = Container;
+ });
+define("container/container",
+ ["container/inheriting_dict","ember-metal/core","exports"],
+ function(__dependency1__, __dependency2__, __exports__) {
+ "use strict";
+ var InheritingDict = __dependency1__["default"];
+ var Ember = __dependency2__["default"];
+ // Ember.assert
+
+ // A lightweight container that helps to assemble and decouple components.
+ // Public api for the container is still in flux.
+ // The public api, specified on the application namespace should be considered the stable api.
+ function Container(parent) {
+ this.parent = parent;
+ this.children = [];
+
+ this.resolver = parent && parent.resolver || function() {};
+
+ this.registry = new InheritingDict(parent && parent.registry);
+ this.cache = new InheritingDict(parent && parent.cache);
+ this.factoryCache = new InheritingDict(parent && parent.factoryCache);
+ this.resolveCache = new InheritingDict(parent && parent.resolveCache);
+ this.typeInjections = new InheritingDict(parent && parent.typeInjections);
+ this.injections = {};
+
+ this.factoryTypeInjections = new InheritingDict(parent && parent.factoryTypeInjections);
+ this.factoryInjections = {};
+
+ this._options = new InheritingDict(parent && parent._options);
+ this._typeOptions = new InheritingDict(parent && parent._typeOptions);
+ }
+
+ Container.prototype = {
+
+ /**
+ @property parent
+ @type Container
+ @default null
+ */
+ parent: null,
+
+ /**
+ @property children
+ @type Array
+ @default []
+ */
+ children: null,
+
+ /**
+ @property resolver
+ @type function
+ */
+ resolver: null,
+
+ /**
+ @property registry
+ @type InheritingDict
+ */
+ registry: null,
+
+ /**
+ @property cache
+ @type InheritingDict
+ */
+ cache: null,
+
+ /**
+ @property typeInjections
+ @type InheritingDict
+ */
+ typeInjections: null,
+
+ /**
+ @property injections
+ @type Object
+ @default {}
+ */
+ injections: null,
+
+ /**
+ @private
+
+ @property _options
+ @type InheritingDict
+ @default null
+ */
+ _options: null,
+
+ /**
+ @private
+
+ @property _typeOptions
+ @type InheritingDict
+ */
+ _typeOptions: null,
+
+ /**
+ Returns a new child of the current container. These children are configured
+ to correctly inherit from the current container.
+
+ @method child
+ @return {Container}
+ */
+ child: function() {
+ var container = new Container(this);
+ this.children.push(container);
+ return container;
+ },
+
+ /**
+ Sets a key-value pair on the current container. If a parent container,
+ has the same key, once set on a child, the parent and child will diverge
+ as expected.
+
+ @method set
+ @param {Object} object
+ @param {String} key
+ @param {any} value
+ */
+ set: function(object, key, value) {
+ object[key] = value;
+ },
+
+ /**
+ Registers a factory for later injection.
+
+ Example:
+
+ ```javascript
+ var container = new Container();
+
+ container.register('model:user', Person, {singleton: false });
+ container.register('fruit:favorite', Orange);
+ container.register('communication:main', Email, {singleton: false});
+ ```
+
+ @method register
+ @param {String} fullName
+ @param {Function} factory
+ @param {Object} options
+ */
+ register: function(fullName, factory, options) {
+
+ if (factory === undefined) {
+ throw new TypeError('Attempting to register an unknown factory: `' + fullName + '`');
+ }
+
+ var normalizedName = this.normalize(fullName);
+
+ if (this.cache.has(normalizedName)) {
+ throw new Error('Cannot re-register: `' + fullName +'`, as it has already been looked up.');
+ }
+
+ this.registry.set(normalizedName, factory);
+ this._options.set(normalizedName, options || {});
+ },
+
+ /**
+ Unregister a fullName
+
+ ```javascript
+ var container = new Container();
+ container.register('model:user', User);
+
+ container.lookup('model:user') instanceof User //=> true
+
+ container.unregister('model:user')
+ container.lookup('model:user') === undefined //=> true
+ ```
+
+ @method unregister
+ @param {String} fullName
+ */
+ unregister: function(fullName) {
+
+ var normalizedName = this.normalize(fullName);
+
+ this.registry.remove(normalizedName);
+ this.cache.remove(normalizedName);
+ this.factoryCache.remove(normalizedName);
+ this.resolveCache.remove(normalizedName);
+ this._options.remove(normalizedName);
+ },
+
+ /**
+ Given a fullName return the corresponding factory.
+
+ By default `resolve` will retrieve the factory from
+ its container's registry.
+
+ ```javascript
+ var container = new Container();
+ container.register('api:twitter', Twitter);
+
+ container.resolve('api:twitter') // => Twitter
+ ```
+
+ Optionally the container can be provided with a custom resolver.
+ If provided, `resolve` will first provide the custom resolver
+ the opportunity to resolve the fullName, otherwise it will fallback
+ to the registry.
+
+ ```javascript
+ var container = new Container();
+ container.resolver = function(fullName) {
+ // lookup via the module system of choice
+ };
+
+ // the twitter factory is added to the module system
+ container.resolve('api:twitter') // => Twitter
+ ```
+
+ @method resolve
+ @param {String} fullName
+ @return {Function} fullName's factory
+ */
+ resolve: function(fullName) {
+ return resolve(this, this.normalize(fullName));
+ },
+
+ /**
+ A hook that can be used to describe how the resolver will
+ attempt to find the factory.
+
+ For example, the default Ember `.describe` returns the full
+ class name (including namespace) where Ember's resolver expects
+ to find the `fullName`.
+
+ @method describe
+ @param {String} fullName
+ @return {string} described fullName
+ */
+ describe: function(fullName) {
+ return fullName;
+ },
+
+ /**
+ A hook to enable custom fullName normalization behaviour
+
+ @method normalize
+ @param {String} fullName
+ @return {string} normalized fullName
+ */
+ normalize: function(fullName) {
+ return fullName;
+ },
+
+ /**
+ @method makeToString
+
+ @param {any} factory
+ @param {string} fullName
+ @return {function} toString function
+ */
+ makeToString: function(factory, fullName) {
+ return factory.toString();
+ },
+
+ /**
+ Given a fullName return a corresponding instance.
+
+ The default behaviour is for lookup to return a singleton instance.
+ The singleton is scoped to the container, allowing multiple containers
+ to all have their own locally scoped singletons.
+
+ ```javascript
+ var container = new Container();
+ container.register('api:twitter', Twitter);
+
+ var twitter = container.lookup('api:twitter');
+
+ twitter instanceof Twitter; // => true
+
+ // by default the container will return singletons
+ var twitter2 = container.lookup('api:twitter');
+ twitter2 instanceof Twitter; // => true
+
+ twitter === twitter2; //=> true
+ ```
+
+ If singletons are not wanted an optional flag can be provided at lookup.
+
+ ```javascript
+ var container = new Container();
+ container.register('api:twitter', Twitter);
+
+ var twitter = container.lookup('api:twitter', { singleton: false });
+ var twitter2 = container.lookup('api:twitter', { singleton: false });
+
+ twitter === twitter2; //=> false
+ ```
+
+ @method lookup
+ @param {String} fullName
+ @param {Object} options
+ @return {any}
+ */
+ lookup: function(fullName, options) {
+ return lookup(this, this.normalize(fullName), options);
+ },
+
+ /**
+ Given a fullName return the corresponding factory.
+
+ @method lookupFactory
+ @param {String} fullName
+ @return {any}
+ */
+ lookupFactory: function(fullName) {
+ return factoryFor(this, this.normalize(fullName));
+ },
+
+ /**
+ Given a fullName check if the container is aware of its factory
+ or singleton instance.
+
+ @method has
+ @param {String} fullName
+ @return {Boolean}
+ */
+ has: function(fullName) {
+ return has(this, this.normalize(fullName));
+ },
+
+ /**
+ Allow registering options for all factories of a type.
+
+ ```javascript
+ var container = new Container();
+
+ // if all of type `connection` must not be singletons
+ container.optionsForType('connection', { singleton: false });
+
+ container.register('connection:twitter', TwitterConnection);
+ container.register('connection:facebook', FacebookConnection);
+
+ var twitter = container.lookup('connection:twitter');
+ var twitter2 = container.lookup('connection:twitter');
+
+ twitter === twitter2; // => false
+
+ var facebook = container.lookup('connection:facebook');
+ var facebook2 = container.lookup('connection:facebook');
+
+ facebook === facebook2; // => false
+ ```
+
+ @method optionsForType
+ @param {String} type
+ @param {Object} options
+ */
+ optionsForType: function(type, options) {
+ if (this.parent) { illegalChildOperation('optionsForType'); }
+
+ this._typeOptions.set(type, options);
+ },
+
+ /**
+ @method options
+ @param {String} type
+ @param {Object} options
+ */
+ options: function(type, options) {
+ this.optionsForType(type, options);
+ },
+
+ /**
+ Used only via `injection`.
+
+ Provides a specialized form of injection, specifically enabling
+ all objects of one type to be injected with a reference to another
+ object.
+
+ For example, provided each object of type `controller` needed a `router`.
+ one would do the following:
+
+ ```javascript
+ var container = new Container();
+
+ container.register('router:main', Router);
+ container.register('controller:user', UserController);
+ container.register('controller:post', PostController);
+
+ container.typeInjection('controller', 'router', 'router:main');
+
+ var user = container.lookup('controller:user');
+ var post = container.lookup('controller:post');
+
+ user.router instanceof Router; //=> true
+ post.router instanceof Router; //=> true
+
+ // both controllers share the same router
+ user.router === post.router; //=> true
+ ```
+
+ @private
+ @method typeInjection
+ @param {String} type
+ @param {String} property
+ @param {String} fullName
+ */
+ typeInjection: function(type, property, fullName) {
+ if (this.parent) { illegalChildOperation('typeInjection'); }
+
+ var fullNameType = fullName.split(':')[0];
+ if(fullNameType === type) {
+ throw new Error('Cannot inject a `' + fullName + '` on other ' + type + '(s). Register the `' + fullName + '` as a different type and perform the typeInjection.');
+ }
+ addTypeInjection(this.typeInjections, type, property, fullName);
+ },
+
+ /**
+ Defines injection rules.
+
+ These rules are used to inject dependencies onto objects when they
+ are instantiated.
+
+ Two forms of injections are possible:
+
+ * Injecting one fullName on another fullName
+ * Injecting one fullName on a type
+
+ Example:
+
+ ```javascript
+ var container = new Container();
+
+ container.register('source:main', Source);
+ container.register('model:user', User);
+ container.register('model:post', Post);
+
+ // injecting one fullName on another fullName
+ // eg. each user model gets a post model
+ container.injection('model:user', 'post', 'model:post');
+
+ // injecting one fullName on another type
+ container.injection('model', 'source', 'source:main');
+
+ var user = container.lookup('model:user');
+ var post = container.lookup('model:post');
+
+ user.source instanceof Source; //=> true
+ post.source instanceof Source; //=> true
+
+ user.post instanceof Post; //=> true
+
+ // and both models share the same source
+ user.source === post.source; //=> true
+ ```
+
+ @method injection
+ @param {String} factoryName
+ @param {String} property
+ @param {String} injectionName
+ */
+ injection: function(fullName, property, injectionName) {
+ if (this.parent) { illegalChildOperation('injection'); }
+
+ validateFullName(injectionName);
+ var normalizedInjectionName = this.normalize(injectionName);
+
+ if (fullName.indexOf(':') === -1) {
+ return this.typeInjection(fullName, property, normalizedInjectionName);
+ }
+
+ var normalizedName = this.normalize(fullName);
+
+ if (this.cache.has(normalizedName)) {
+ throw new Error("Attempted to register an injection for a type that has already been looked up. ('" + normalizedName + "', '" + property + "', '" + injectionName + "')");
+ }
+ addInjection(this.injections, normalizedName, property, normalizedInjectionName);
+ },
+
+
+ /**
+ Used only via `factoryInjection`.
+
+ Provides a specialized form of injection, specifically enabling
+ all factory of one type to be injected with a reference to another
+ object.
+
+ For example, provided each factory of type `model` needed a `store`.
+ one would do the following:
+
+ ```javascript
+ var container = new Container();
+
+ container.register('store:main', SomeStore);
+
+ container.factoryTypeInjection('model', 'store', 'store:main');
+
+ var store = container.lookup('store:main');
+ var UserFactory = container.lookupFactory('model:user');
+
+ UserFactory.store instanceof SomeStore; //=> true
+ ```
+
+ @private
+ @method factoryTypeInjection
+ @param {String} type
+ @param {String} property
+ @param {String} fullName
+ */
+ factoryTypeInjection: function(type, property, fullName) {
+ if (this.parent) { illegalChildOperation('factoryTypeInjection'); }
+
+ addTypeInjection(this.factoryTypeInjections, type, property, this.normalize(fullName));
+ },
+
+ /**
+ Defines factory injection rules.
+
+ Similar to regular injection rules, but are run against factories, via
+ `Container#lookupFactory`.
+
+ These rules are used to inject objects onto factories when they
+ are looked up.
+
+ Two forms of injections are possible:
+
+ * Injecting one fullName on another fullName
+ * Injecting one fullName on a type
+
+ Example:
+
+ ```javascript
+ var container = new Container();
+
+ container.register('store:main', Store);
+ container.register('store:secondary', OtherStore);
+ container.register('model:user', User);
+ container.register('model:post', Post);
+
+ // injecting one fullName on another type
+ container.factoryInjection('model', 'store', 'store:main');
+
+ // injecting one fullName on another fullName
+ container.factoryInjection('model:post', 'secondaryStore', 'store:secondary');
+
+ var UserFactory = container.lookupFactory('model:user');
+ var PostFactory = container.lookupFactory('model:post');
+ var store = container.lookup('store:main');
+
+ UserFactory.store instanceof Store; //=> true
+ UserFactory.secondaryStore instanceof OtherStore; //=> false
+
+ PostFactory.store instanceof Store; //=> true
+ PostFactory.secondaryStore instanceof OtherStore; //=> true
+
+ // and both models share the same source instance
+ UserFactory.store === PostFactory.store; //=> true
+ ```
+
+ @method factoryInjection
+ @param {String} factoryName
+ @param {String} property
+ @param {String} injectionName
+ */
+ factoryInjection: function(fullName, property, injectionName) {
+ if (this.parent) { illegalChildOperation('injection'); }
+
+ var normalizedName = this.normalize(fullName);
+ var normalizedInjectionName = this.normalize(injectionName);
+
+ validateFullName(injectionName);
+
+ if (fullName.indexOf(':') === -1) {
+ return this.factoryTypeInjection(normalizedName, property, normalizedInjectionName);
+ }
+
+
+ if (this.factoryCache.has(normalizedName)) {
+ throw new Error('Attempted to register a factoryInjection for a type that has already ' +
+ 'been looked up. (\'' + normalizedName + '\', \'' + property + '\', \'' + injectionName + '\')');
+ }
+
+ addInjection(this.factoryInjections, normalizedName, property, normalizedInjectionName);
+ },
+
+ /**
+ A depth first traversal, destroying the container, its descendant containers and all
+ their managed objects.
+
+ @method destroy
+ */
+ destroy: function() {
+ for (var i = 0, length = this.children.length; i < length; i++) {
+ this.children[i].destroy();
+ }
+
+ this.children = [];
+
+ eachDestroyable(this, function(item) {
+ item.destroy();
+ });
+
+ this.parent = undefined;
+ this.isDestroyed = true;
+ },
+
+ /**
+ @method reset
+ */
+ reset: function() {
+ for (var i = 0, length = this.children.length; i < length; i++) {
+ resetCache(this.children[i]);
+ }
+
+ resetCache(this);
+ }
+ };
+
+ function resolve(container, normalizedName) {
+ var cached = container.resolveCache.get(normalizedName);
+ if (cached) { return cached; }
+
+ var resolved = container.resolver(normalizedName) || container.registry.get(normalizedName);
+ container.resolveCache.set(normalizedName, resolved);
+
+ return resolved;
+ }
+
+ function has(container, fullName){
+ if (container.cache.has(fullName)) {
+ return true;
+ }
+
+ return !!container.resolve(fullName);
+ }
+
+ function lookup(container, fullName, options) {
+ options = options || {};
+
+ if (container.cache.has(fullName) && options.singleton !== false) {
+ return container.cache.get(fullName);
+ }
+
+ var value = instantiate(container, fullName);
+
+ if (value === undefined) { return; }
+
+ if (isSingleton(container, fullName) && options.singleton !== false) {
+ container.cache.set(fullName, value);
+ }
+
+ return value;
+ }
+
+ function illegalChildOperation(operation) {
+ throw new Error(operation + ' is not currently supported on child containers');
+ }
+
+ function isSingleton(container, fullName) {
+ var singleton = option(container, fullName, 'singleton');
+
+ return singleton !== false;
+ }
+
+ function buildInjections(container, injections) {
+ var hash = {};
+
+ if (!injections) { return hash; }
+
+ var injection, injectable;
+
+ for (var i = 0, length = injections.length; i < length; i++) {
+ injection = injections[i];
+ injectable = lookup(container, injection.fullName);
+
+ if (injectable !== undefined) {
+ hash[injection.property] = injectable;
+ } else {
+ throw new Error('Attempting to inject an unknown injection: `' + injection.fullName + '`');
+ }
+ }
+
+ return hash;
+ }
+
+ function option(container, fullName, optionName) {
+ var options = container._options.get(fullName);
+
+ if (options && options[optionName] !== undefined) {
+ return options[optionName];
+ }
+
+ var type = fullName.split(':')[0];
+ options = container._typeOptions.get(type);
+
+ if (options) {
+ return options[optionName];
+ }
+ }
+
+ function factoryFor(container, fullName) {
+ var cache = container.factoryCache;
+ if (cache.has(fullName)) {
+ return cache.get(fullName);
+ }
+ var factory = container.resolve(fullName);
+ if (factory === undefined) { return; }
+
+ var type = fullName.split(':')[0];
+ if (!factory || typeof factory.extend !== 'function' || (!Ember.MODEL_FACTORY_INJECTIONS && type === 'model')) {
+ // TODO: think about a 'safe' merge style extension
+ // for now just fallback to create time injection
+ return factory;
+ } else {
+ var injections = injectionsFor(container, fullName);
+ var factoryInjections = factoryInjectionsFor(container, fullName);
+
+ factoryInjections._toString = container.makeToString(factory, fullName);
+
+ var injectedFactory = factory.extend(injections);
+ injectedFactory.reopenClass(factoryInjections);
+
+ cache.set(fullName, injectedFactory);
+
+ return injectedFactory;
+ }
+ }
+
+ function injectionsFor(container, fullName) {
+ var splitName = fullName.split(':'),
+ type = splitName[0],
+ injections = [];
+
+ injections = injections.concat(container.typeInjections.get(type) || []);
+ injections = injections.concat(container.injections[fullName] || []);
+
+ injections = buildInjections(container, injections);
+ injections._debugContainerKey = fullName;
+ injections.container = container;
+
+ return injections;
+ }
+
+ function factoryInjectionsFor(container, fullName) {
+ var splitName = fullName.split(':'),
+ type = splitName[0],
+ factoryInjections = [];
+
+ factoryInjections = factoryInjections.concat(container.factoryTypeInjections.get(type) || []);
+ factoryInjections = factoryInjections.concat(container.factoryInjections[fullName] || []);
+
+ factoryInjections = buildInjections(container, factoryInjections);
+ factoryInjections._debugContainerKey = fullName;
+
+ return factoryInjections;
+ }
+
+ function instantiate(container, fullName) {
+ var factory = factoryFor(container, fullName);
+
+ if (option(container, fullName, 'instantiate') === false) {
+ return factory;
+ }
+
+ if (factory) {
+ if (typeof factory.create !== 'function') {
+ throw new Error('Failed to create an instance of \'' + fullName + '\'. ' +
+ 'Most likely an improperly defined class or an invalid module export.');
+ }
+
+ if (typeof factory.extend === 'function') {
+ // assume the factory was extendable and is already injected
+ return factory.create();
+ } else {
+ // assume the factory was extendable
+ // to create time injections
+ // TODO: support new'ing for instantiation and merge injections for pure JS Functions
+ return factory.create(injectionsFor(container, fullName));
+ }
+ }
+ }
+
+ function eachDestroyable(container, callback) {
+ container.cache.eachLocal(function(key, value) {
+ if (option(container, key, 'instantiate') === false) { return; }
+ callback(value);
+ });
+ }
+
+ function resetCache(container) {
+ container.cache.eachLocal(function(key, value) {
+ if (option(container, key, 'instantiate') === false) { return; }
+ value.destroy();
+ });
+ container.cache.dict = {};
+ }
+
+ function addTypeInjection(rules, type, property, fullName) {
+ var injections = rules.get(type);
+
+ if (!injections) {
+ injections = [];
+ rules.set(type, injections);
+ }
+
+ injections.push({
+ property: property,
+ fullName: fullName
+ });
+ }
+
+ var VALID_FULL_NAME_REGEXP = /^[^:]+.+:[^:]+$/;
+ function validateFullName(fullName) {
+ if (!VALID_FULL_NAME_REGEXP.test(fullName)) {
+ throw new TypeError('Invalid Fullname, expected: `type:name` got: ' + fullName);
+ }
+ return true;
+ }
+
+ function addInjection(rules, factoryName, property, injectionName) {
+ var injections = rules[factoryName] = rules[factoryName] || [];
+ injections.push({ property: property, fullName: injectionName });
+ }
+
+ __exports__["default"] = Container;
+ });
+define("container/inheriting_dict",
+ ["exports"],
+ function(__exports__) {
+ "use strict";
+ // A safe and simple inheriting object.
+ function InheritingDict(parent) {
+ this.parent = parent;
+ this.dict = {};
+ }
+
+ InheritingDict.prototype = {
+
+ /**
+ @property parent
+ @type InheritingDict
+ @default null
+ */
+
+ parent: null,
+
+ /**
+ Object used to store the current nodes data.
+
+ @property dict
+ @type Object
+ @default Object
+ */
+ dict: null,
+
+ /**
+ Retrieve the value given a key, if the value is present at the current
+ level use it, otherwise walk up the parent hierarchy and try again. If
+ no matching key is found, return undefined.
+
+ @method get
+ @param {String} key
+ @return {any}
+ */
+ get: function(key) {
+ var dict = this.dict;
+
+ if (dict.hasOwnProperty(key)) {
+ return dict[key];
+ }
+
+ if (this.parent) {
+ return this.parent.get(key);
+ }
+ },
+
+ /**
+ Set the given value for the given key, at the current level.
+
+ @method set
+ @param {String} key
+ @param {Any} value
+ */
+ set: function(key, value) {
+ this.dict[key] = value;
+ },
+
+ /**
+ Delete the given key
+
+ @method remove
+ @param {String} key
+ */
+ remove: function(key) {
+ delete this.dict[key];
+ },
+
+ /**
+ Check for the existence of given a key, if the key is present at the current
+ level return true, otherwise walk up the parent hierarchy and try again. If
+ no matching key is found, return false.
+
+ @method has
+ @param {String} key
+ @return {Boolean}
+ */
+ has: function(key) {
+ var dict = this.dict;
+
+ if (dict.hasOwnProperty(key)) {
+ return true;
+ }
+
+ if (this.parent) {
+ return this.parent.has(key);
+ }
+
+ return false;
+ },
+
+ /**
+ Iterate and invoke a callback for each local key-value pair.
+
+ @method eachLocal
+ @param {Function} callback
+ @param {Object} binding
+ */
+ eachLocal: function(callback, binding) {
+ var dict = this.dict;
+
+ for (var prop in dict) {
+ if (dict.hasOwnProperty(prop)) {
+ callback.call(binding, prop, dict[prop]);
+ }
+ }
+ }
+ };
+
+ __exports__["default"] = InheritingDict;
+ });
+define("ember-application",
+ ["ember-metal/core","ember-runtime/system/lazy_load","ember-application/system/dag","ember-application/system/resolver","ember-application/system/application","ember-application/ext/controller"],
+ function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__) {
+ "use strict";
+ var Ember = __dependency1__["default"];
+ var runLoadHooks = __dependency2__.runLoadHooks;
+
+ /**
+ Ember Application
+
+ @module ember
+ @submodule ember-application
+ @requires ember-views, ember-routing
+ */
+
+ var DAG = __dependency3__["default"];
+ var Resolver = __dependency4__.Resolver;
+ var DefaultResolver = __dependency4__["default"];
+ var Application = __dependency5__["default"];
+ // side effect of extending ControllerMixin
+
+ Ember.Application = Application;
+ Ember.DAG = DAG;
+ Ember.Resolver = Resolver;
+ Ember.DefaultResolver = DefaultResolver;
+
+ runLoadHooks('Ember.Application', Application);
+ });
+define("ember-application/ext/controller",
+ ["ember-metal/core","ember-metal/property_get","ember-metal/property_set","ember-metal/error","ember-metal/utils","ember-metal/computed","ember-runtime/mixins/controller","ember-routing/system/controller_for","exports"],
+ function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __exports__) {
+ "use strict";
+ /**
+ @module ember
+ @submodule ember-application
+ */
+
+ var Ember = __dependency1__["default"];
+ // Ember.assert
+ var get = __dependency2__.get;
+ var set = __dependency3__.set;
+ var EmberError = __dependency4__["default"];
+ var inspect = __dependency5__.inspect;
+ var computed = __dependency6__.computed;
+ var ControllerMixin = __dependency7__["default"];
+ var meta = __dependency5__.meta;
+ var controllerFor = __dependency8__["default"];
+
+ function verifyNeedsDependencies(controller, container, needs) {
+ var dependency, i, l, missing = [];
+
+ for (i=0, l=needs.length; i 1 ? 'they' : 'it') + " could not be found");
+ }
+ }
+
+ var defaultControllersComputedProperty = computed(function() {
+ var controller = this;
+
+ return {
+ needs: get(controller, 'needs'),
+ container: get(controller, 'container'),
+ unknownProperty: function(controllerName) {
+ var needs = this.needs,
+ dependency, i, l;
+ for (i=0, l=needs.length; i 0) {
+
+ if (this.container) {
+ verifyNeedsDependencies(this, this.container, needs);
+ }
+
+ // if needs then initialize controllers proxy
+ get(this, 'controllers');
+ }
+
+ this._super.apply(this, arguments);
+ },
+
+ /**
+ @method controllerFor
+ @see {Ember.Route#controllerFor}
+ @deprecated Use `needs` instead
+ */
+ controllerFor: function(controllerName) {
+ return controllerFor(get(this, 'container'), controllerName);
+ },
+
+ /**
+ Stores the instances of other controllers available from within
+ this controller. Any controller listed by name in the `needs`
+ property will be accessible by name through this property.
+
+ ```javascript
+ App.CommentsController = Ember.ArrayController.extend({
+ needs: ['post'],
+ postTitle: function(){
+ var currentPost = this.get('controllers.post'); // instance of App.PostController
+ return currentPost.get('title');
+ }.property('controllers.post.title')
+ });
+ ```
+
+ @see {Ember.ControllerMixin#needs}
+ @property {Object} controllers
+ @default null
+ */
+ controllers: defaultControllersComputedProperty
+ });
+
+ __exports__["default"] = ControllerMixin;
+ });
+define("ember-application/system/application",
+ ["ember-metal","ember-metal/property_get","ember-metal/property_set","ember-runtime/system/lazy_load","ember-application/system/dag","ember-runtime/system/namespace","ember-runtime/mixins/deferred","ember-application/system/resolver","ember-metal/platform","ember-metal/run_loop","ember-metal/utils","container/container","ember-runtime/controllers/controller","ember-metal/enumerable_utils","ember-runtime/controllers/object_controller","ember-runtime/controllers/array_controller","ember-views/system/event_dispatcher","ember-views/system/jquery","ember-routing/system/route","ember-routing/system/router","ember-routing/location/hash_location","ember-routing/location/history_location","ember-routing/location/auto_location","ember-routing/location/none_location","ember-routing/system/cache","ember-metal/core","ember-handlebars-compiler","exports"],
+ function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __dependency15__, __dependency16__, __dependency17__, __dependency18__, __dependency19__, __dependency20__, __dependency21__, __dependency22__, __dependency23__, __dependency24__, __dependency25__, __dependency26__, __dependency27__, __exports__) {
+ "use strict";
+ /**
+ @module ember
+ @submodule ember-application
+ */
+
+ var Ember = __dependency1__["default"];
+ // Ember.FEATURES, Ember.deprecate, Ember.assert, Ember.libraries, LOG_VERSION, Namespace, BOOTED
+ var get = __dependency2__.get;
+ var set = __dependency3__.set;
+ var runLoadHooks = __dependency4__.runLoadHooks;
+ var DAG = __dependency5__["default"];
+ var Namespace = __dependency6__["default"];
+ var DeferredMixin = __dependency7__["default"];
+ var DefaultResolver = __dependency8__["default"];
+ var create = __dependency9__.create;
+ var run = __dependency10__["default"];
+ var canInvoke = __dependency11__.canInvoke;
+ var Container = __dependency12__["default"];
+ var Controller = __dependency13__["default"];
+ var EnumerableUtils = __dependency14__["default"];
+ var ObjectController = __dependency15__["default"];
+ var ArrayController = __dependency16__["default"];
+ var EventDispatcher = __dependency17__["default"];
+ //import ContainerDebugAdapter from "ember-extension-support/container_debug_adapter";
+ var jQuery = __dependency18__["default"];
+ var Route = __dependency19__["default"];
+ var Router = __dependency20__["default"];
+ var HashLocation = __dependency21__["default"];
+ var HistoryLocation = __dependency22__["default"];
+ var AutoLocation = __dependency23__["default"];
+ var NoneLocation = __dependency24__["default"];
+ var BucketCache = __dependency25__["default"];
+
+ var K = __dependency26__.K;
+ var EmberHandlebars = __dependency27__["default"];
+
+ var ContainerDebugAdapter;
+
+ /**
+ An instance of `Ember.Application` is the starting point for every Ember
+ application. It helps to instantiate, initialize and coordinate the many
+ objects that make up your app.
+
+ Each Ember app has one and only one `Ember.Application` object. In fact, the
+ very first thing you should do in your application is create the instance:
+
+ ```javascript
+ window.App = Ember.Application.create();
+ ```
+
+ Typically, the application object is the only global variable. All other
+ classes in your app should be properties on the `Ember.Application` instance,
+ which highlights its first role: a global namespace.
+
+ For example, if you define a view class, it might look like this:
+
+ ```javascript
+ App.MyView = Ember.View.extend();
+ ```
+
+ By default, calling `Ember.Application.create()` will automatically initialize
+ your application by calling the `Ember.Application.initialize()` method. If
+ you need to delay initialization, you can call your app's `deferReadiness()`
+ method. When you are ready for your app to be initialized, call its
+ `advanceReadiness()` method.
+
+ You can define a `ready` method on the `Ember.Application` instance, which
+ will be run by Ember when the application is initialized.
+
+ Because `Ember.Application` inherits from `Ember.Namespace`, any classes
+ you create will have useful string representations when calling `toString()`.
+ See the `Ember.Namespace` documentation for more information.
+
+ While you can think of your `Ember.Application` as a container that holds the
+ other classes in your application, there are several other responsibilities
+ going on under-the-hood that you may want to understand.
+
+ ### Event Delegation
+
+ Ember uses a technique called _event delegation_. This allows the framework
+ to set up a global, shared event listener instead of requiring each view to
+ do it manually. For example, instead of each view registering its own
+ `mousedown` listener on its associated element, Ember sets up a `mousedown`
+ listener on the `body`.
+
+ If a `mousedown` event occurs, Ember will look at the target of the event and
+ start walking up the DOM node tree, finding corresponding views and invoking
+ their `mouseDown` method as it goes.
+
+ `Ember.Application` has a number of default events that it listens for, as
+ well as a mapping from lowercase events to camel-cased view method names. For
+ example, the `keypress` event causes the `keyPress` method on the view to be
+ called, the `dblclick` event causes `doubleClick` to be called, and so on.
+
+ If there is a bubbling browser event that Ember does not listen for by
+ default, you can specify custom events and their corresponding view method
+ names by setting the application's `customEvents` property:
+
+ ```javascript
+ App = Ember.Application.create({
+ customEvents: {
+ // add support for the paste event
+ paste: "paste"
+ }
+ });
+ ```
+
+ By default, the application sets up these event listeners on the document
+ body. However, in cases where you are embedding an Ember application inside
+ an existing page, you may want it to set up the listeners on an element
+ inside the body.
+
+ For example, if only events inside a DOM element with the ID of `ember-app`
+ should be delegated, set your application's `rootElement` property:
+
+ ```javascript
+ window.App = Ember.Application.create({
+ rootElement: '#ember-app'
+ });
+ ```
+
+ The `rootElement` can be either a DOM element or a jQuery-compatible selector
+ string. Note that *views appended to the DOM outside the root element will
+ not receive events.* If you specify a custom root element, make sure you only
+ append views inside it!
+
+ To learn more about the advantages of event delegation and the Ember view
+ layer, and a list of the event listeners that are setup by default, visit the
+ [Ember View Layer guide](http://emberjs.com/guides/understanding-ember/the-view-layer/#toc_event-delegation).
+
+ ### Initializers
+
+ Libraries on top of Ember can add initializers, like so:
+
+ ```javascript
+ Ember.Application.initializer({
+ name: 'api-adapter',
+
+ initialize: function(container, application) {
+ application.register('api-adapter:main', ApiAdapter);
+ }
+ });
+ ```
+
+ Initializers provide an opportunity to access the container, which
+ organizes the different components of an Ember application. Additionally
+ they provide a chance to access the instantiated application. Beyond
+ being used for libraries, initializers are also a great way to organize
+ dependency injection or setup in your own application.
+
+ ### Routing
+
+ In addition to creating your application's router, `Ember.Application` is
+ also responsible for telling the router when to start routing. Transitions
+ between routes can be logged with the `LOG_TRANSITIONS` flag, and more
+ detailed intra-transition logging can be logged with
+ the `LOG_TRANSITIONS_INTERNAL` flag:
+
+ ```javascript
+ window.App = Ember.Application.create({
+ LOG_TRANSITIONS: true, // basic logging of successful transitions
+ LOG_TRANSITIONS_INTERNAL: true // detailed logging of all routing steps
+ });
+ ```
+
+ By default, the router will begin trying to translate the current URL into
+ application state once the browser emits the `DOMContentReady` event. If you
+ need to defer routing, you can call the application's `deferReadiness()`
+ method. Once routing can begin, call the `advanceReadiness()` method.
+
+ If there is any setup required before routing begins, you can implement a
+ `ready()` method on your app that will be invoked immediately before routing
+ begins.
+ ```
+
+ @class Application
+ @namespace Ember
+ @extends Ember.Namespace
+ */
+
+ var Application = Namespace.extend(DeferredMixin, {
+ _suppressDeferredDeprecation: true,
+
+ /**
+ The root DOM element of the Application. This can be specified as an
+ element or a
+ [jQuery-compatible selector string](http://api.jquery.com/category/selectors/).
+
+ This is the element that will be passed to the Application's,
+ `eventDispatcher`, which sets up the listeners for event delegation. Every
+ view in your application should be a child of the element you specify here.
+
+ @property rootElement
+ @type DOMElement
+ @default 'body'
+ */
+ rootElement: 'body',
+
+ /**
+ The `Ember.EventDispatcher` responsible for delegating events to this
+ application's views.
+
+ The event dispatcher is created by the application at initialization time
+ and sets up event listeners on the DOM element described by the
+ application's `rootElement` property.
+
+ See the documentation for `Ember.EventDispatcher` for more information.
+
+ @property eventDispatcher
+ @type Ember.EventDispatcher
+ @default null
+ */
+ eventDispatcher: null,
+
+ /**
+ The DOM events for which the event dispatcher should listen.
+
+ By default, the application's `Ember.EventDispatcher` listens
+ for a set of standard DOM events, such as `mousedown` and
+ `keyup`, and delegates them to your application's `Ember.View`
+ instances.
+
+ If you would like additional bubbling events to be delegated to your
+ views, set your `Ember.Application`'s `customEvents` property
+ to a hash containing the DOM event name as the key and the
+ corresponding view method name as the value. For example:
+
+ ```javascript
+ App = Ember.Application.create({
+ customEvents: {
+ // add support for the paste event
+ paste: "paste"
+ }
+ });
+ ```
+
+ @property customEvents
+ @type Object
+ @default null
+ */
+ customEvents: null,
+
+ // Start off the number of deferrals at 1. This will be
+ // decremented by the Application's own `initialize` method.
+ _readinessDeferrals: 1,
+
+ init: function() {
+ if (!this.$) { this.$ = jQuery; }
+ this.__container__ = this.buildContainer();
+
+ this.Router = this.defaultRouter();
+
+ this._super();
+
+ this.scheduleInitialize();
+
+ Ember.libraries.registerCoreLibrary('Handlebars', EmberHandlebars.VERSION);
+ Ember.libraries.registerCoreLibrary('jQuery', jQuery().jquery);
+
+ if ( Ember.LOG_VERSION ) {
+ Ember.LOG_VERSION = false; // we only need to see this once per Application#init
+
+ var nameLengths = EnumerableUtils.map(Ember.libraries, function(item) {
+ return get(item, "name.length");
+ });
+
+ var maxNameLength = Math.max.apply(this, nameLengths);
+
+ Ember.libraries.each(function(name, version) {
+ var spaces = new Array(maxNameLength - name.length + 1).join(" ");
+ });
+ }
+ },
+
+ /**
+ Build the container for the current application.
+
+ Also register a default application view in case the application
+ itself does not.
+
+ @private
+ @method buildContainer
+ @return {Ember.Container} the configured container
+ */
+ buildContainer: function() {
+ var container = this.__container__ = Application.buildContainer(this);
+
+ return container;
+ },
+
+ /**
+ If the application has not opted out of routing and has not explicitly
+ defined a router, supply a default router for the application author
+ to configure.
+
+ This allows application developers to do:
+
+ ```javascript
+ var App = Ember.Application.create();
+
+ App.Router.map(function() {
+ this.resource('posts');
+ });
+ ```
+
+ @private
+ @method defaultRouter
+ @return {Ember.Router} the default router
+ */
+
+ defaultRouter: function() {
+ if (this.Router === false) { return; }
+ var container = this.__container__;
+
+ if (this.Router) {
+ container.unregister('router:main');
+ container.register('router:main', this.Router);
+ }
+
+ return container.lookupFactory('router:main');
+ },
+
+ /**
+ Automatically initialize the application once the DOM has
+ become ready.
+
+ The initialization itself is scheduled on the actions queue
+ which ensures that application loading finishes before
+ booting.
+
+ If you are asynchronously loading code, you should call
+ `deferReadiness()` to defer booting, and then call
+ `advanceReadiness()` once all of your code has finished
+ loading.
+
+ @private
+ @method scheduleInitialize
+ */
+ scheduleInitialize: function() {
+ var self = this;
+
+ if (!this.$ || this.$.isReady) {
+ run.schedule('actions', self, '_initialize');
+ } else {
+ this.$().ready(function runInitialize() {
+ run(self, '_initialize');
+ });
+ }
+ },
+
+ /**
+ Use this to defer readiness until some condition is true.
+
+ Example:
+
+ ```javascript
+ App = Ember.Application.create();
+ App.deferReadiness();
+
+ jQuery.getJSON("/auth-token", function(token) {
+ App.token = token;
+ App.advanceReadiness();
+ });
+ ```
+
+ This allows you to perform asynchronous setup logic and defer
+ booting your application until the setup has finished.
+
+ However, if the setup requires a loading UI, it might be better
+ to use the router for this purpose.
+
+ @method deferReadiness
+ */
+ deferReadiness: function() {
+ this._readinessDeferrals++;
+ },
+
+ /**
+ Call `advanceReadiness` after any asynchronous setup logic has completed.
+ Each call to `deferReadiness` must be matched by a call to `advanceReadiness`
+ or the application will never become ready and routing will not begin.
+
+ @method advanceReadiness
+ @see {Ember.Application#deferReadiness}
+ */
+ advanceReadiness: function() {
+ this._readinessDeferrals--;
+
+ if (this._readinessDeferrals === 0) {
+ run.once(this, this.didBecomeReady);
+ }
+ },
+
+ /**
+ Registers a factory that can be used for dependency injection (with
+ `App.inject`) or for service lookup. Each factory is registered with
+ a full name including two parts: `type:name`.
+
+ A simple example:
+
+ ```javascript
+ var App = Ember.Application.create();
+ App.Orange = Ember.Object.extend();
+ App.register('fruit:favorite', App.Orange);
+ ```
+
+ Ember will resolve factories from the `App` namespace automatically.
+ For example `App.CarsController` will be discovered and returned if
+ an application requests `controller:cars`.
+
+ An example of registering a controller with a non-standard name:
+
+ ```javascript
+ var App = Ember.Application.create(),
+ Session = Ember.Controller.extend();
+
+ App.register('controller:session', Session);
+
+ // The Session controller can now be treated like a normal controller,
+ // despite its non-standard name.
+ App.ApplicationController = Ember.Controller.extend({
+ needs: ['session']
+ });
+ ```
+
+ Registered factories are **instantiated** by having `create`
+ called on them. Additionally they are **singletons**, each time
+ they are looked up they return the same instance.
+
+ Some examples modifying that default behavior:
+
+ ```javascript
+ var App = Ember.Application.create();
+
+ App.Person = Ember.Object.extend();
+ App.Orange = Ember.Object.extend();
+ App.Email = Ember.Object.extend();
+ App.session = Ember.Object.create();
+
+ App.register('model:user', App.Person, {singleton: false });
+ App.register('fruit:favorite', App.Orange);
+ App.register('communication:main', App.Email, {singleton: false});
+ App.register('session', App.session, {instantiate: false});
+ ```
+
+ @method register
+ @param fullName {String} type:name (e.g., 'model:user')
+ @param factory {Function} (e.g., App.Person)
+ @param options {Object} (optional) disable instantiation or singleton usage
+ **/
+ register: function() {
+ var container = this.__container__;
+ container.register.apply(container, arguments);
+ },
+
+ /**
+ Define a dependency injection onto a specific factory or all factories
+ of a type.
+
+ When Ember instantiates a controller, view, or other framework component
+ it can attach a dependency to that component. This is often used to
+ provide services to a set of framework components.
+
+ An example of providing a session object to all controllers:
+
+ ```javascript
+ var App = Ember.Application.create(),
+ Session = Ember.Object.extend({ isAuthenticated: false });
+
+ // A factory must be registered before it can be injected
+ App.register('session:main', Session);
+
+ // Inject 'session:main' onto all factories of the type 'controller'
+ // with the name 'session'
+ App.inject('controller', 'session', 'session:main');
+
+ App.IndexController = Ember.Controller.extend({
+ isLoggedIn: Ember.computed.alias('session.isAuthenticated')
+ });
+ ```
+
+ Injections can also be performed on specific factories.
+
+ ```javascript
+ App.inject(, , )
+ App.inject('route', 'source', 'source:main')
+ App.inject('route:application', 'email', 'model:email')
+ ```
+
+ It is important to note that injections can only be performed on
+ classes that are instantiated by Ember itself. Instantiating a class
+ directly (via `create` or `new`) bypasses the dependency injection
+ system.
+
+ Ember-Data instantiates its models in a unique manner, and consequently
+ injections onto models (or all models) will not work as expected. Injections
+ on models can be enabled by setting `Ember.MODEL_FACTORY_INJECTIONS`
+ to `true`.
+
+ @method inject
+ @param factoryNameOrType {String}
+ @param property {String}
+ @param injectionName {String}
+ **/
+ inject: function() {
+ var container = this.__container__;
+ container.injection.apply(container, arguments);
+ },
+
+ /**
+ Calling initialize manually is not supported.
+
+ Please see Ember.Application#advanceReadiness and
+ Ember.Application#deferReadiness.
+
+ @private
+ @deprecated
+ @method initialize
+ **/
+ initialize: function() {
+ },
+
+ /**
+ Initialize the application. This happens automatically.
+
+ Run any initializers and run the application load hook. These hooks may
+ choose to defer readiness. For example, an authentication hook might want
+ to defer readiness until the auth token has been retrieved.
+
+ @private
+ @method _initialize
+ */
+ _initialize: function() {
+ if (this.isDestroyed) { return; }
+
+ // At this point, the App.Router must already be assigned
+ if (this.Router) {
+ var container = this.__container__;
+ container.unregister('router:main');
+ container.register('router:main', this.Router);
+ }
+
+ this.runInitializers();
+ runLoadHooks('application', this);
+
+ // At this point, any initializers or load hooks that would have wanted
+ // to defer readiness have fired. In general, advancing readiness here
+ // will proceed to didBecomeReady.
+ this.advanceReadiness();
+
+ return this;
+ },
+
+ /**
+ Reset the application. This is typically used only in tests. It cleans up
+ the application in the following order:
+
+ 1. Deactivate existing routes
+ 2. Destroy all objects in the container
+ 3. Create a new application container
+ 4. Re-route to the existing url
+
+ Typical Example:
+
+ ```javascript
+
+ var App;
+
+ run(function() {
+ App = Ember.Application.create();
+ });
+
+ module("acceptance test", {
+ setup: function() {
+ App.reset();
+ }
+ });
+
+ test("first test", function() {
+ // App is freshly reset
+ });
+
+ test("first test", function() {
+ // App is again freshly reset
+ });
+ ```
+
+ Advanced Example:
+
+ Occasionally you may want to prevent the app from initializing during
+ setup. This could enable extra configuration, or enable asserting prior
+ to the app becoming ready.
+
+ ```javascript
+
+ var App;
+
+ run(function() {
+ App = Ember.Application.create();
+ });
+
+ module("acceptance test", {
+ setup: function() {
+ run(function() {
+ App.reset();
+ App.deferReadiness();
+ });
+ }
+ });
+
+ test("first test", function() {
+ ok(true, 'something before app is initialized');
+
+ run(function() {
+ App.advanceReadiness();
+ });
+ ok(true, 'something after app is initialized');
+ });
+ ```
+
+ @method reset
+ **/
+ reset: function() {
+ this._readinessDeferrals = 1;
+
+ function handleReset() {
+ var router = this.__container__.lookup('router:main');
+ router.reset();
+
+ run(this.__container__, 'destroy');
+
+ this.buildContainer();
+
+ run.schedule('actions', this, function() {
+ this._initialize();
+ });
+ }
+
+ run.join(this, handleReset);
+ },
+
+ /**
+ @private
+ @method runInitializers
+ */
+ runInitializers: function() {
+ var initializers = get(this.constructor, 'initializers');
+ var container = this.__container__;
+ var graph = new DAG();
+ var namespace = this;
+ var name, initializer;
+
+ for (name in initializers) {
+ initializer = initializers[name];
+ graph.addEdges(initializer.name, initializer.initialize, initializer.before, initializer.after);
+ }
+
+ graph.topsort(function (vertex) {
+ var initializer = vertex.value;
+ initializer(container, namespace);
+ });
+ },
+
+ /**
+ @private
+ @method didBecomeReady
+ */
+ didBecomeReady: function() {
+ this.setupEventDispatcher();
+ this.ready(); // user hook
+ this.startRouting();
+
+ if (!Ember.testing) {
+ // Eagerly name all classes that are already loaded
+ Ember.Namespace.processAll();
+ Ember.BOOTED = true;
+ }
+
+ this.resolve(this);
+ },
+
+ /**
+ Setup up the event dispatcher to receive events on the
+ application's `rootElement` with any registered
+ `customEvents`.
+
+ @private
+ @method setupEventDispatcher
+ */
+ setupEventDispatcher: function() {
+ var customEvents = get(this, 'customEvents');
+ var rootElement = get(this, 'rootElement');
+ var dispatcher = this.__container__.lookup('event_dispatcher:main');
+
+ set(this, 'eventDispatcher', dispatcher);
+ dispatcher.setup(customEvents, rootElement);
+ },
+
+ /**
+ If the application has a router, use it to route to the current URL, and
+ trigger a new call to `route` whenever the URL changes.
+
+ @private
+ @method startRouting
+ @property router {Ember.Router}
+ */
+ startRouting: function() {
+ var router = this.__container__.lookup('router:main');
+ if (!router) { return; }
+
+ router.startRouting();
+ },
+
+ handleURL: function(url) {
+ var router = this.__container__.lookup('router:main');
+
+ router.handleURL(url);
+ },
+
+ /**
+ Called when the Application has become ready.
+ The call will be delayed until the DOM has become ready.
+
+ @event ready
+ */
+ ready: K,
+
+ /**
+ @deprecated Use 'Resolver' instead
+ Set this to provide an alternate class to `Ember.DefaultResolver`
+
+
+ @property resolver
+ */
+ resolver: null,
+
+ /**
+ Set this to provide an alternate class to `Ember.DefaultResolver`
+
+ @property resolver
+ */
+ Resolver: null,
+
+ willDestroy: function() {
+ Ember.BOOTED = false;
+ // Ensure deactivation of routes before objects are destroyed
+ this.__container__.lookup('router:main').reset();
+
+ this.__container__.destroy();
+ },
+
+ initializer: function(options) {
+ this.constructor.initializer(options);
+ },
+
+ /**
+ @method then
+ @private
+ @deprecated
+ */
+ then: function() {
+
+ this._super.apply(this, arguments);
+ }
+ });
+
+ Application.reopenClass({
+ initializers: {},
+
+ /**
+ Initializer receives an object which has the following attributes:
+ `name`, `before`, `after`, `initialize`. The only required attribute is
+ `initialize, all others are optional.
+
+ * `name` allows you to specify under which name the initializer is registered.
+ This must be a unique name, as trying to register two initializers with the
+ same name will result in an error.
+
+ ```javascript
+ Ember.Application.initializer({
+ name: 'namedInitializer',
+ initialize: function(container, application) {
+ Ember.debug("Running namedInitializer!");
+ }
+ });
+ ```
+
+ * `before` and `after` are used to ensure that this initializer is ran prior
+ or after the one identified by the value. This value can be a single string
+ or an array of strings, referencing the `name` of other initializers.
+
+ An example of ordering initializers, we create an initializer named `first`:
+
+ ```javascript
+ Ember.Application.initializer({
+ name: 'first',
+ initialize: function(container, application) {
+ Ember.debug("First initializer!");
+ }
+ });
+
+ // DEBUG: First initializer!
+ ```
+
+ We add another initializer named `second`, specifying that it should run
+ after the initializer named `first`:
+
+ ```javascript
+ Ember.Application.initializer({
+ name: 'second',
+ after: 'first',
+
+ initialize: function(container, application) {
+ Ember.debug("Second initializer!");
+ }
+ });
+
+ // DEBUG: First initializer!
+ // DEBUG: Second initializer!
+ ```
+
+ Afterwards we add a further initializer named `pre`, this time specifying
+ that it should run before the initializer named `first`:
+
+ ```javascript
+ Ember.Application.initializer({
+ name: 'pre',
+ before: 'first',
+
+ initialize: function(container, application) {
+ Ember.debug("Pre initializer!");
+ }
+ });
+
+ // DEBUG: Pre initializer!
+ // DEBUG: First initializer!
+ // DEBUG: Second initializer!
+ ```
+
+ Finally we add an initializer named `post`, specifying it should run after
+ both the `first` and the `second` initializers:
+
+ ```javascript
+ Ember.Application.initializer({
+ name: 'post',
+ after: ['first', 'second'],
+
+ initialize: function(container, application) {
+ Ember.debug("Post initializer!");
+ }
+ });
+
+ // DEBUG: Pre initializer!
+ // DEBUG: First initializer!
+ // DEBUG: Second initializer!
+ // DEBUG: Post initializer!
+ ```
+
+ * `initialize` is a callback function that receives two arguments, `container`
+ and `application` on which you can operate.
+
+ Example of using `container` to preload data into the store:
+
+ ```javascript
+ Ember.Application.initializer({
+ name: "preload-data",
+
+ initialize: function(container, application) {
+ var store = container.lookup('store:main');
+ store.pushPayload(preloadedData);
+ }
+ });
+ ```
+
+ Example of using `application` to register an adapter:
+
+ ```javascript
+ Ember.Application.initializer({
+ name: 'api-adapter',
+
+ initialize: function(container, application) {
+ application.register('api-adapter:main', ApiAdapter);
+ }
+ });
+ ```
+
+ @method initializer
+ @param initializer {Object}
+ */
+ initializer: function(initializer) {
+ // If this is the first initializer being added to a subclass, we are going to reopen the class
+ // to make sure we have a new `initializers` object, which extends from the parent class' using
+ // prototypal inheritance. Without this, attempting to add initializers to the subclass would
+ // pollute the parent class as well as other subclasses.
+ if (this.superclass.initializers !== undefined && this.superclass.initializers === this.initializers) {
+ this.reopenClass({
+ initializers: create(this.initializers)
+ });
+ }
+
+
+ this.initializers[initializer.name] = initializer;
+ },
+
+ /**
+ This creates a container with the default Ember naming conventions.
+
+ It also configures the container:
+
+ * registered views are created every time they are looked up (they are
+ not singletons)
+ * registered templates are not factories; the registered value is
+ returned directly.
+ * the router receives the application as its `namespace` property
+ * all controllers receive the router as their `target` and `controllers`
+ properties
+ * all controllers receive the application as their `namespace` property
+ * the application view receives the application controller as its
+ `controller` property
+ * the application view receives the application template as its
+ `defaultTemplate` property
+
+ @private
+ @method buildContainer
+ @static
+ @param {Ember.Application} namespace the application to build the
+ container for.
+ @return {Ember.Container} the built container
+ */
+ buildContainer: function(namespace) {
+ var container = new Container();
+
+ container.set = set;
+ container.resolver = resolverFor(namespace);
+ container.normalize = container.resolver.normalize;
+ container.describe = container.resolver.describe;
+ container.makeToString = container.resolver.makeToString;
+
+ container.optionsForType('component', { singleton: false });
+ container.optionsForType('view', { singleton: false });
+ container.optionsForType('template', { instantiate: false });
+ container.optionsForType('helper', { instantiate: false });
+
+ container.register('application:main', namespace, { instantiate: false });
+
+ container.register('controller:basic', Controller, { instantiate: false });
+ container.register('controller:object', ObjectController, { instantiate: false });
+ container.register('controller:array', ArrayController, { instantiate: false });
+ container.register('route:basic', Route, { instantiate: false });
+ container.register('event_dispatcher:main', EventDispatcher);
+
+ container.register('router:main', Router);
+ container.injection('router:main', 'namespace', 'application:main');
+
+ container.register('location:auto', AutoLocation);
+ container.register('location:hash', HashLocation);
+ container.register('location:history', HistoryLocation);
+ container.register('location:none', NoneLocation);
+
+ container.injection('controller', 'target', 'router:main');
+ container.injection('controller', 'namespace', 'application:main');
+
+ container.register('-bucket-cache:main', BucketCache);
+ container.injection('router', '_bucketCache', '-bucket-cache:main');
+ container.injection('route', '_bucketCache', '-bucket-cache:main');
+ container.injection('controller', '_bucketCache', '-bucket-cache:main');
+
+ container.injection('route', 'router', 'router:main');
+ container.injection('location', 'rootURL', '-location-setting:root-url');
+
+ // DEBUGGING
+ container.register('resolver-for-debugging:main', container.resolver.__resolver__, { instantiate: false });
+ container.injection('container-debug-adapter:main', 'resolver', 'resolver-for-debugging:main');
+ container.injection('data-adapter:main', 'containerDebugAdapter', 'container-debug-adapter:main');
+ // Custom resolver authors may want to register their own ContainerDebugAdapter with this key
+
+ // ES6TODO: resolve this via import once ember-application package is ES6'ed
+ if (!ContainerDebugAdapter) { ContainerDebugAdapter = requireModule('ember-extension-support/container_debug_adapter')['default']; }
+ container.register('container-debug-adapter:main', ContainerDebugAdapter);
+
+ return container;
+ }
+ });
+
+ /**
+ This function defines the default lookup rules for container lookups:
+
+ * templates are looked up on `Ember.TEMPLATES`
+ * other names are looked up on the application after classifying the name.
+ For example, `controller:post` looks up `App.PostController` by default.
+ * if the default lookup fails, look for registered classes on the container
+
+ This allows the application to register default injections in the container
+ that could be overridden by the normal naming convention.
+
+ @private
+ @method resolverFor
+ @param {Ember.Namespace} namespace the namespace to look for classes
+ @return {*} the resolved value for a given lookup
+ */
+ function resolverFor(namespace) {
+ if (namespace.get('resolver')) {
+ }
+
+ var ResolverClass = namespace.get('resolver') || namespace.get('Resolver') || DefaultResolver;
+ var resolver = ResolverClass.create({
+ namespace: namespace
+ });
+
+ function resolve(fullName) {
+ return resolver.resolve(fullName);
+ }
+
+ resolve.describe = function(fullName) {
+ return resolver.lookupDescription(fullName);
+ };
+
+ resolve.makeToString = function(factory, fullName) {
+ return resolver.makeToString(factory, fullName);
+ };
+
+ resolve.normalize = function(fullName) {
+ if (resolver.normalize) {
+ return resolver.normalize(fullName);
+ } else {
+ return fullName;
+ }
+ };
+
+ resolve.__resolver__ = resolver;
+
+ return resolve;
+ }
+
+ __exports__["default"] = Application;
+ });
+define("ember-application/system/dag",
+ ["ember-metal/error","exports"],
+ function(__dependency1__, __exports__) {
+ "use strict";
+ var EmberError = __dependency1__["default"];
+
+ function visit(vertex, fn, visited, path) {
+ var name = vertex.name;
+ var vertices = vertex.incoming;
+ var names = vertex.incomingNames;
+ var len = names.length;
+ var i;
+
+ if (!visited) {
+ visited = {};
+ }
+ if (!path) {
+ path = [];
+ }
+ if (visited.hasOwnProperty(name)) {
+ return;
+ }
+ path.push(name);
+ visited[name] = true;
+ for (i = 0; i < len; i++) {
+ visit(vertices[names[i]], fn, visited, path);
+ }
+ fn(vertex, path);
+ path.pop();
+ }
+
+
+ /**
+ * DAG stands for Directed acyclic graph.
+ *
+ * It is used to build a graph of dependencies checking that there isn't circular
+ * dependencies. p.e Registering initializers with a certain precedence order.
+ *
+ * @class DAG
+ * @constructor
+ */
+ function DAG() {
+ this.names = [];
+ this.vertices = {};
+ }
+
+ /**
+ * Adds a vertex entry to the graph unless it is already added.
+ *
+ * @private
+ * @method add
+ * @param {String} name The name of the vertex to add
+ */
+ DAG.prototype.add = function(name) {
+ if (!name) { return; }
+ if (this.vertices.hasOwnProperty(name)) {
+ return this.vertices[name];
+ }
+ var vertex = {
+ name: name, incoming: {}, incomingNames: [], hasOutgoing: false, value: null
+ };
+ this.vertices[name] = vertex;
+ this.names.push(name);
+ return vertex;
+ };
+
+ /**
+ * Adds a vertex to the graph and sets its value.
+ *
+ * @private
+ * @method map
+ * @param {String} name The name of the vertex.
+ * @param value The value to put in the vertex.
+ */
+ DAG.prototype.map = function(name, value) {
+ this.add(name).value = value;
+ };
+
+ /**
+ * Connects the vertices with the given names, adding them to the graph if
+ * necesary, only if this does not produce is any circular dependency.
+ *
+ * @private
+ * @method addEdge
+ * @param {String} fromName The name the vertex where the edge starts.
+ * @param {String} toName The name the vertex where the edge ends.
+ */
+ DAG.prototype.addEdge = function(fromName, toName) {
+ if (!fromName || !toName || fromName === toName) {
+ return;
+ }
+ var from = this.add(fromName), to = this.add(toName);
+ if (to.incoming.hasOwnProperty(fromName)) {
+ return;
+ }
+ function checkCycle(vertex, path) {
+ if (vertex.name === toName) {
+ throw new EmberError("cycle detected: " + toName + " <- " + path.join(" <- "));
+ }
+ }
+ visit(from, checkCycle);
+ from.hasOutgoing = true;
+ to.incoming[fromName] = from;
+ to.incomingNames.push(fromName);
+ };
+
+ /**
+ * Visits all the vertex of the graph calling the given function with each one,
+ * ensuring that the vertices are visited respecting their precedence.
+ *
+ * @method topsort
+ * @param {Function} fn The function to be invoked on each vertex.
+ */
+ DAG.prototype.topsort = function(fn) {
+ var visited = {};
+ var vertices = this.vertices;
+ var names = this.names;
+ var len = names.length;
+ var i, vertex;
+
+ for (i = 0; i < len; i++) {
+ vertex = vertices[names[i]];
+ if (!vertex.hasOutgoing) {
+ visit(vertex, fn, visited);
+ }
+ }
+ };
+
+ /**
+ * Adds a vertex with the given name and value to the graph and joins it with the
+ * vertices referenced in _before_ and _after_. If there isn't vertices with those
+ * names, they are added too.
+ *
+ * If either _before_ or _after_ are falsy/empty, the added vertex will not have
+ * an incoming/outgoing edge.
+ *
+ * @method addEdges
+ * @param {String} name The name of the vertex to be added.
+ * @param value The value of that vertex.
+ * @param before An string or array of strings with the names of the vertices before
+ * which this vertex must be visited.
+ * @param after An string or array of strings with the names of the vertex after
+ * which this vertex must be visited.
+ *
+ */
+ DAG.prototype.addEdges = function(name, value, before, after) {
+ var i;
+ this.map(name, value);
+ if (before) {
+ if (typeof before === 'string') {
+ this.addEdge(name, before);
+ } else {
+ for (i = 0; i < before.length; i++) {
+ this.addEdge(name, before[i]);
+ }
+ }
+ }
+ if (after) {
+ if (typeof after === 'string') {
+ this.addEdge(after, name);
+ } else {
+ for (i = 0; i < after.length; i++) {
+ this.addEdge(after[i], name);
+ }
+ }
+ }
+ };
+
+ __exports__["default"] = DAG;
+ });
+define("ember-application/system/resolver",
+ ["ember-metal/core","ember-metal/property_get","ember-metal/logger","ember-runtime/system/string","ember-runtime/system/object","ember-runtime/system/namespace","ember-handlebars","exports"],
+ function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __exports__) {
+ "use strict";
+ /**
+ @module ember
+ @submodule ember-application
+ */
+
+ var Ember = __dependency1__["default"];
+ // Ember.TEMPLATES, Ember.assert
+ var get = __dependency2__.get;
+ var Logger = __dependency3__["default"];
+ var classify = __dependency4__.classify;
+ var capitalize = __dependency4__.capitalize;
+ var decamelize = __dependency4__.decamelize;
+ var EmberObject = __dependency5__["default"];
+ var Namespace = __dependency6__["default"];
+ var EmberHandlebars = __dependency7__["default"];
+
+ var Resolver = EmberObject.extend({
+ /**
+ This will be set to the Application instance when it is
+ created.
+
+ @property namespace
+ */
+ namespace: null,
+ normalize: Ember.required(Function),
+ resolve: Ember.required(Function),
+ parseName: Ember.required(Function),
+ lookupDescription: Ember.required(Function),
+ makeToString: Ember.required(Function),
+ resolveOther: Ember.required(Function),
+ _logLookup: Ember.required(Function)
+ });
+ __exports__.Resolver = Resolver;
+ /**
+ The DefaultResolver defines the default lookup rules to resolve
+ container lookups before consulting the container for registered
+ items:
+
+ * templates are looked up on `Ember.TEMPLATES`
+ * other names are looked up on the application after converting
+ the name. For example, `controller:post` looks up
+ `App.PostController` by default.
+ * there are some nuances (see examples below)
+
+ ### How Resolving Works
+
+ The container calls this object's `resolve` method with the
+ `fullName` argument.
+
+ It first parses the fullName into an object using `parseName`.
+
+ Then it checks for the presence of a type-specific instance
+ method of the form `resolve[Type]` and calls it if it exists.
+ For example if it was resolving 'template:post', it would call
+ the `resolveTemplate` method.
+
+ Its last resort is to call the `resolveOther` method.
+
+ The methods of this object are designed to be easy to override
+ in a subclass. For example, you could enhance how a template
+ is resolved like so:
+
+ ```javascript
+ App = Ember.Application.create({
+ Resolver: Ember.DefaultResolver.extend({
+ resolveTemplate: function(parsedName) {
+ var resolvedTemplate = this._super(parsedName);
+ if (resolvedTemplate) { return resolvedTemplate; }
+ return Ember.TEMPLATES['not_found'];
+ }
+ })
+ });
+ ```
+
+ Some examples of how names are resolved:
+
+ ```
+ 'template:post' //=> Ember.TEMPLATES['post']
+ 'template:posts/byline' //=> Ember.TEMPLATES['posts/byline']
+ 'template:posts.byline' //=> Ember.TEMPLATES['posts/byline']
+ 'template:blogPost' //=> Ember.TEMPLATES['blogPost']
+ // OR
+ // Ember.TEMPLATES['blog_post']
+ 'controller:post' //=> App.PostController
+ 'controller:posts.index' //=> App.PostsIndexController
+ 'controller:blog/post' //=> Blog.PostController
+ 'controller:basic' //=> Ember.Controller
+ 'route:post' //=> App.PostRoute
+ 'route:posts.index' //=> App.PostsIndexRoute
+ 'route:blog/post' //=> Blog.PostRoute
+ 'route:basic' //=> Ember.Route
+ 'view:post' //=> App.PostView
+ 'view:posts.index' //=> App.PostsIndexView
+ 'view:blog/post' //=> Blog.PostView
+ 'view:basic' //=> Ember.View
+ 'foo:post' //=> App.PostFoo
+ 'model:post' //=> App.Post
+ ```
+
+ @class DefaultResolver
+ @namespace Ember
+ @extends Ember.Object
+ */
+
+ __exports__["default"] = EmberObject.extend({
+ /**
+ This will be set to the Application instance when it is
+ created.
+
+ @property namespace
+ */
+ namespace: null,
+
+ normalize: function(fullName) {
+ var split = fullName.split(':', 2),
+ type = split[0],
+ name = split[1];
+
+
+ if (type !== 'template') {
+ var result = name;
+
+ if (result.indexOf('.') > -1) {
+ result = result.replace(/\.(.)/g, function(m) { return m.charAt(1).toUpperCase(); });
+ }
+
+ if (name.indexOf('_') > -1) {
+ result = result.replace(/_(.)/g, function(m) { return m.charAt(1).toUpperCase(); });
+ }
+
+ return type + ':' + result;
+ } else {
+ return fullName;
+ }
+ },
+
+
+ /**
+ This method is called via the container's resolver method.
+ It parses the provided `fullName` and then looks up and
+ returns the appropriate template or class.
+
+ @method resolve
+ @param {String} fullName the lookup string
+ @return {Object} the resolved factory
+ */
+ resolve: function(fullName) {
+ var parsedName = this.parseName(fullName),
+ resolveMethodName = parsedName.resolveMethodName,
+ resolved;
+
+ if (!(parsedName.name && parsedName.type)) {
+ throw new TypeError('Invalid fullName: `' + fullName + '`, must be of the form `type:name` ');
+ }
+
+ if (this[resolveMethodName]) {
+ resolved = this[resolveMethodName](parsedName);
+ }
+
+ if (!resolved) {
+ resolved = this.resolveOther(parsedName);
+ }
+
+ if (parsedName.root && parsedName.root.LOG_RESOLVER) {
+ this._logLookup(resolved, parsedName);
+ }
+
+ return resolved;
+ },
+ /**
+ Convert the string name of the form 'type:name' to
+ a Javascript object with the parsed aspects of the name
+ broken out.
+
+ @protected
+ @param {String} fullName the lookup string
+ @method parseName
+ */
+ parseName: function(fullName) {
+ var nameParts = fullName.split(':'),
+ type = nameParts[0], fullNameWithoutType = nameParts[1],
+ name = fullNameWithoutType,
+ namespace = get(this, 'namespace'),
+ root = namespace;
+
+ if (type !== 'template' && name.indexOf('/') !== -1) {
+ var parts = name.split('/');
+ name = parts[parts.length - 1];
+ var namespaceName = capitalize(parts.slice(0, -1).join('.'));
+ root = Namespace.byName(namespaceName);
+
+ }
+
+ return {
+ fullName: fullName,
+ type: type,
+ fullNameWithoutType: fullNameWithoutType,
+ name: name,
+ root: root,
+ resolveMethodName: 'resolve' + classify(type)
+ };
+ },
+
+ /**
+ Returns a human-readable description for a fullName. Used by the
+ Application namespace in assertions to describe the
+ precise name of the class that Ember is looking for, rather than
+ container keys.
+
+ @protected
+ @param {String} fullName the lookup string
+ @method lookupDescription
+ */
+ lookupDescription: function(fullName) {
+ var parsedName = this.parseName(fullName);
+
+ if (parsedName.type === 'template') {
+ return 'template at ' + parsedName.fullNameWithoutType.replace(/\./g, '/');
+ }
+
+ var description = parsedName.root + '.' + classify(parsedName.name);
+ if (parsedName.type !== 'model') { description += classify(parsedName.type); }
+
+ return description;
+ },
+
+ makeToString: function(factory, fullName) {
+ return factory.toString();
+ },
+ /**
+ Given a parseName object (output from `parseName`), apply
+ the conventions expected by `Ember.Router`
+
+ @protected
+ @param {Object} parsedName a parseName object with the parsed
+ fullName lookup string
+ @method useRouterNaming
+ */
+ useRouterNaming: function(parsedName) {
+ parsedName.name = parsedName.name.replace(/\./g, '_');
+ if (parsedName.name === 'basic') {
+ parsedName.name = '';
+ }
+ },
+ /**
+ Look up the template in Ember.TEMPLATES
+
+ @protected
+ @param {Object} parsedName a parseName object with the parsed
+ fullName lookup string
+ @method resolveTemplate
+ */
+ resolveTemplate: function(parsedName) {
+ var templateName = parsedName.fullNameWithoutType.replace(/\./g, '/');
+
+ if (Ember.TEMPLATES[templateName]) {
+ return Ember.TEMPLATES[templateName];
+ }
+
+ templateName = decamelize(templateName);
+ if (Ember.TEMPLATES[templateName]) {
+ return Ember.TEMPLATES[templateName];
+ }
+ },
+ /**
+ Lookup the view using `resolveOther`
+
+ @protected
+ @param {Object} parsedName a parseName object with the parsed
+ fullName lookup string
+ @method resolveView
+ */
+ resolveView: function(parsedName) {
+ this.useRouterNaming(parsedName);
+ return this.resolveOther(parsedName);
+ },
+ /**
+ Lookup the controller using `resolveOther`
+
+ @protected
+ @param {Object} parsedName a parseName object with the parsed
+ fullName lookup string
+ @method resolveController
+ */
+ resolveController: function(parsedName) {
+ this.useRouterNaming(parsedName);
+ return this.resolveOther(parsedName);
+ },
+ /**
+ Lookup the route using `resolveOther`
+
+ @protected
+ @param {Object} parsedName a parseName object with the parsed
+ fullName lookup string
+ @method resolveRoute
+ */
+ resolveRoute: function(parsedName) {
+ this.useRouterNaming(parsedName);
+ return this.resolveOther(parsedName);
+ },
+
+ /**
+ Lookup the model on the Application namespace
+
+ @protected
+ @param {Object} parsedName a parseName object with the parsed
+ fullName lookup string
+ @method resolveModel
+ */
+ resolveModel: function(parsedName) {
+ var className = classify(parsedName.name);
+ var factory = get(parsedName.root, className);
+
+ if (factory) { return factory; }
+ },
+ /**
+ Look up the specified object (from parsedName) on the appropriate
+ namespace (usually on the Application)
+
+ @protected
+ @param {Object} parsedName a parseName object with the parsed
+ fullName lookup string
+ @method resolveHelper
+ */
+ resolveHelper: function(parsedName) {
+ return this.resolveOther(parsedName) || EmberHandlebars.helpers[parsedName.fullNameWithoutType];
+ },
+ /**
+ Look up the specified object (from parsedName) on the appropriate
+ namespace (usually on the Application)
+
+ @protected
+ @param {Object} parsedName a parseName object with the parsed
+ fullName lookup string
+ @method resolveOther
+ */
+ resolveOther: function(parsedName) {
+ var className = classify(parsedName.name) + classify(parsedName.type);
+ var factory = get(parsedName.root, className);
+ if (factory) { return factory; }
+ },
+
+ /**
+ @method _logLookup
+ @param {Boolean} found
+ @param {Object} parsedName
+ @private
+ */
+ _logLookup: function(found, parsedName) {
+ var symbol, padding;
+
+ if (found) { symbol = '[✓]'; }
+ else { symbol = '[ ]'; }
+
+ if (parsedName.fullName.length > 60) {
+ padding = '.';
+ } else {
+ padding = new Array(60 - parsedName.fullName.length).join('.');
+ }
+
+ Logger.info(symbol, parsedName.fullName, padding, this.lookupDescription(parsedName.fullName));
+ }
+ });
+ });
+define("ember-extension-support",
+ ["ember-metal/core","ember-extension-support/data_adapter","ember-extension-support/container_debug_adapter"],
+ function(__dependency1__, __dependency2__, __dependency3__) {
+ "use strict";
+ /**
+ Ember Extension Support
+
+ @module ember
+ @submodule ember-extension-support
+ @requires ember-application
+ */
+
+ var Ember = __dependency1__["default"];
+ var DataAdapter = __dependency2__["default"];
+ var ContainerDebugAdapter = __dependency3__["default"];
+
+ Ember.DataAdapter = DataAdapter;
+ Ember.ContainerDebugAdapter = ContainerDebugAdapter;
+ });
+define("ember-extension-support/container_debug_adapter",
+ ["ember-metal/core","ember-runtime/system/native_array","ember-metal/utils","ember-runtime/system/string","ember-runtime/system/namespace","ember-runtime/system/object","exports"],
+ function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __exports__) {
+ "use strict";
+ var Ember = __dependency1__["default"];
+ var emberA = __dependency2__.A;
+ var typeOf = __dependency3__.typeOf;
+ var dasherize = __dependency4__.dasherize;
+ var classify = __dependency4__.classify;
+ var Namespace = __dependency5__["default"];
+ var EmberObject = __dependency6__["default"];
+
+ /**
+ @module ember
+ @submodule ember-extension-support
+ */
+
+ /**
+ The `ContainerDebugAdapter` helps the container and resolver interface
+ with tools that debug Ember such as the
+ [Ember Extension](https://github.com/tildeio/ember-extension)
+ for Chrome and Firefox.
+
+ This class can be extended by a custom resolver implementer
+ to override some of the methods with library-specific code.
+
+ The methods likely to be overridden are:
+
+ * `canCatalogEntriesByType`
+ * `catalogEntriesByType`
+
+ The adapter will need to be registered
+ in the application's container as `container-debug-adapter:main`
+
+ Example:
+
+ ```javascript
+ Application.initializer({
+ name: "containerDebugAdapter",
+
+ initialize: function(container, application) {
+ application.register('container-debug-adapter:main', require('app/container-debug-adapter'));
+ }
+ });
+ ```
+
+ @class ContainerDebugAdapter
+ @namespace Ember
+ @extends EmberObject
+ @since 1.5.0
+ */
+ __exports__["default"] = EmberObject.extend({
+ /**
+ The container of the application being debugged.
+ This property will be injected
+ on creation.
+
+ @property container
+ @default null
+ */
+ container: null,
+
+ /**
+ The resolver instance of the application
+ being debugged. This property will be injected
+ on creation.
+
+ @property resolver
+ @default null
+ */
+ resolver: null,
+
+ /**
+ Returns true if it is possible to catalog a list of available
+ classes in the resolver for a given type.
+
+ @method canCatalogEntriesByType
+ @param {string} type The type. e.g. "model", "controller", "route"
+ @return {boolean} whether a list is available for this type.
+ */
+ canCatalogEntriesByType: function(type) {
+ if (type === 'model' || type === 'template') return false;
+ return true;
+ },
+
+ /**
+ Returns the available classes a given type.
+
+ @method catalogEntriesByType
+ @param {string} type The type. e.g. "model", "controller", "route"
+ @return {Array} An array of strings.
+ */
+ catalogEntriesByType: function(type) {
+ var namespaces = emberA(Namespace.NAMESPACES), types = emberA(), self = this;
+ var typeSuffixRegex = new RegExp(classify(type) + "$");
+
+ namespaces.forEach(function(namespace) {
+ if (namespace !== Ember) {
+ for (var key in namespace) {
+ if (!namespace.hasOwnProperty(key)) { continue; }
+ if (typeSuffixRegex.test(key)) {
+ var klass = namespace[key];
+ if (typeOf(klass) === 'class') {
+ types.push(dasherize(key.replace(typeSuffixRegex, '')));
+ }
+ }
+ }
+ }
+ });
+ return types;
+ }
+ });
+ });
+define("ember-extension-support/data_adapter",
+ ["ember-metal/core","ember-metal/property_get","ember-metal/run_loop","ember-runtime/system/string","ember-runtime/system/namespace","ember-runtime/system/object","ember-runtime/system/native_array","ember-application/system/application","exports"],
+ function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __exports__) {
+ "use strict";
+ var Ember = __dependency1__["default"];
+ var get = __dependency2__.get;
+ var run = __dependency3__["default"];
+ var dasherize = __dependency4__.dasherize;
+ var Namespace = __dependency5__["default"];
+ var EmberObject = __dependency6__["default"];
+ var emberA = __dependency7__.A;
+ var Application = __dependency8__["default"];
+
+ /**
+ @module ember
+ @submodule ember-extension-support
+ */
+
+ /**
+ The `DataAdapter` helps a data persistence library
+ interface with tools that debug Ember such
+ as the [Ember Extension](https://github.com/tildeio/ember-extension)
+ for Chrome and Firefox.
+
+ This class will be extended by a persistence library
+ which will override some of the methods with
+ library-specific code.
+
+ The methods likely to be overridden are:
+
+ * `getFilters`
+ * `detect`
+ * `columnsForType`
+ * `getRecords`
+ * `getRecordColumnValues`
+ * `getRecordKeywords`
+ * `getRecordFilterValues`
+ * `getRecordColor`
+ * `observeRecord`
+
+ The adapter will need to be registered
+ in the application's container as `dataAdapter:main`
+
+ Example:
+
+ ```javascript
+ Application.initializer({
+ name: "data-adapter",
+
+ initialize: function(container, application) {
+ application.register('data-adapter:main', DS.DataAdapter);
+ }
+ });
+ ```
+
+ @class DataAdapter
+ @namespace Ember
+ @extends EmberObject
+ */
+ __exports__["default"] = EmberObject.extend({
+ init: function() {
+ this._super();
+ this.releaseMethods = emberA();
+ },
+
+ /**
+ The container of the application being debugged.
+ This property will be injected
+ on creation.
+
+ @property container
+ @default null
+ @since 1.3.0
+ */
+ container: null,
+
+
+ /**
+ The container-debug-adapter which is used
+ to list all models.
+
+ @property containerDebugAdapter
+ @default undefined
+ @since 1.5.0
+ **/
+ containerDebugAdapter: undefined,
+
+ /**
+ Number of attributes to send
+ as columns. (Enough to make the record
+ identifiable).
+
+ @private
+ @property attributeLimit
+ @default 3
+ @since 1.3.0
+ */
+ attributeLimit: 3,
+
+ /**
+ Stores all methods that clear observers.
+ These methods will be called on destruction.
+
+ @private
+ @property releaseMethods
+ @since 1.3.0
+ */
+ releaseMethods: emberA(),
+
+ /**
+ Specifies how records can be filtered.
+ Records returned will need to have a `filterValues`
+ property with a key for every name in the returned array.
+
+ @public
+ @method getFilters
+ @return {Array} List of objects defining filters.
+ The object should have a `name` and `desc` property.
+ */
+ getFilters: function() {
+ return emberA();
+ },
+
+ /**
+ Fetch the model types and observe them for changes.
+
+ @public
+ @method watchModelTypes
+
+ @param {Function} typesAdded Callback to call to add types.
+ Takes an array of objects containing wrapped types (returned from `wrapModelType`).
+
+ @param {Function} typesUpdated Callback to call when a type has changed.
+ Takes an array of objects containing wrapped types.
+
+ @return {Function} Method to call to remove all observers
+ */
+ watchModelTypes: function(typesAdded, typesUpdated) {
+ var modelTypes = this.getModelTypes(),
+ self = this, typesToSend, releaseMethods = emberA();
+
+ typesToSend = modelTypes.map(function(type) {
+ var klass = type.klass;
+ var wrapped = self.wrapModelType(klass, type.name);
+ releaseMethods.push(self.observeModelType(klass, typesUpdated));
+ return wrapped;
+ });
+
+ typesAdded(typesToSend);
+
+ var release = function() {
+ releaseMethods.forEach(function(fn) { fn(); });
+ self.releaseMethods.removeObject(release);
+ };
+ this.releaseMethods.pushObject(release);
+ return release;
+ },
+
+ _nameToClass: function(type) {
+ if (typeof type === 'string') {
+ type = this.container.lookupFactory('model:' + type);
+ }
+ return type;
+ },
+
+ /**
+ Fetch the records of a given type and observe them for changes.
+
+ @public
+ @method watchRecords
+
+ @param {Function} recordsAdded Callback to call to add records.
+ Takes an array of objects containing wrapped records.
+ The object should have the following properties:
+ columnValues: {Object} key and value of a table cell
+ object: {Object} the actual record object
+
+ @param {Function} recordsUpdated Callback to call when a record has changed.
+ Takes an array of objects containing wrapped records.
+
+ @param {Function} recordsRemoved Callback to call when a record has removed.
+ Takes the following parameters:
+ index: the array index where the records were removed
+ count: the number of records removed
+
+ @return {Function} Method to call to remove all observers
+ */
+ watchRecords: function(type, recordsAdded, recordsUpdated, recordsRemoved) {
+ var self = this, releaseMethods = emberA(), records = this.getRecords(type), release;
+
+ var recordUpdated = function(updatedRecord) {
+ recordsUpdated([updatedRecord]);
+ };
+
+ var recordsToSend = records.map(function(record) {
+ releaseMethods.push(self.observeRecord(record, recordUpdated));
+ return self.wrapRecord(record);
+ });
+
+
+ var contentDidChange = function(array, idx, removedCount, addedCount) {
+ for (var i = idx; i < idx + addedCount; i++) {
+ var record = array.objectAt(i);
+ var wrapped = self.wrapRecord(record);
+ releaseMethods.push(self.observeRecord(record, recordUpdated));
+ recordsAdded([wrapped]);
+ }
+
+ if (removedCount) {
+ recordsRemoved(idx, removedCount);
+ }
+ };
+
+ var observer = { didChange: contentDidChange, willChange: Ember.K };
+ records.addArrayObserver(self, observer);
+
+ release = function() {
+ releaseMethods.forEach(function(fn) { fn(); });
+ records.removeArrayObserver(self, observer);
+ self.releaseMethods.removeObject(release);
+ };
+
+ recordsAdded(recordsToSend);
+
+ this.releaseMethods.pushObject(release);
+ return release;
+ },
+
+ /**
+ Clear all observers before destruction
+ @private
+ @method willDestroy
+ */
+ willDestroy: function() {
+ this._super();
+ this.releaseMethods.forEach(function(fn) {
+ fn();
+ });
+ },
+
+ /**
+ Detect whether a class is a model.
+
+ Test that against the model class
+ of your persistence library
+
+ @private
+ @method detect
+ @param {Class} klass The class to test
+ @return boolean Whether the class is a model class or not
+ */
+ detect: function(klass) {
+ return false;
+ },
+
+ /**
+ Get the columns for a given model type.
+
+ @private
+ @method columnsForType
+ @param {Class} type The model type
+ @return {Array} An array of columns of the following format:
+ name: {String} name of the column
+ desc: {String} Humanized description (what would show in a table column name)
+ */
+ columnsForType: function(type) {
+ return emberA();
+ },
+
+ /**
+ Adds observers to a model type class.
+
+ @private
+ @method observeModelType
+ @param {Class} type The model type class
+ @param {Function} typesUpdated Called when a type is modified.
+ @return {Function} The function to call to remove observers
+ */
+
+ observeModelType: function(type, typesUpdated) {
+ var self = this, records = this.getRecords(type);
+
+ var onChange = function() {
+ typesUpdated([self.wrapModelType(type)]);
+ };
+ var observer = {
+ didChange: function() {
+ run.scheduleOnce('actions', this, onChange);
+ },
+ willChange: Ember.K
+ };
+
+ records.addArrayObserver(this, observer);
+
+ var release = function() {
+ records.removeArrayObserver(self, observer);
+ };
+
+ return release;
+ },
+
+
+ /**
+ Wraps a given model type and observes changes to it.
+
+ @private
+ @method wrapModelType
+ @param {Class} type A model class
+ @param {String} Optional name of the class
+ @return {Object} contains the wrapped type and the function to remove observers
+ Format:
+ type: {Object} the wrapped type
+ The wrapped type has the following format:
+ name: {String} name of the type
+ count: {Integer} number of records available
+ columns: {Columns} array of columns to describe the record
+ object: {Class} the actual Model type class
+ release: {Function} The function to remove observers
+ */
+ wrapModelType: function(type, name) {
+ var release, records = this.getRecords(type),
+ typeToSend, self = this;
+
+ typeToSend = {
+ name: name || type.toString(),
+ count: get(records, 'length'),
+ columns: this.columnsForType(type),
+ object: type
+ };
+
+
+ return typeToSend;
+ },
+
+
+ /**
+ Fetches all models defined in the application.
+
+ @private
+ @method getModelTypes
+ @return {Array} Array of model types
+ */
+ getModelTypes: function() {
+ var types, self = this,
+ containerDebugAdapter = this.get('containerDebugAdapter');
+
+ if (containerDebugAdapter.canCatalogEntriesByType('model')) {
+ types = containerDebugAdapter.catalogEntriesByType('model');
+ } else {
+ types = this._getObjectsOnNamespaces();
+ }
+
+ // New adapters return strings instead of classes
+ types = emberA(types).map(function(name) {
+ return {
+ klass: self._nameToClass(name),
+ name: name
+ };
+ });
+ types = emberA(types).filter(function(type) {
+ return self.detect(type.klass);
+ });
+
+ return emberA(types);
+ },
+
+ /**
+ Loops over all namespaces and all objects
+ attached to them
+
+ @private
+ @method _getObjectsOnNamespaces
+ @return {Array} Array of model type strings
+ */
+ _getObjectsOnNamespaces: function() {
+ var namespaces = emberA(Namespace.NAMESPACES),
+ types = emberA(),
+ self = this;
+
+ namespaces.forEach(function(namespace) {
+ for (var key in namespace) {
+ if (!namespace.hasOwnProperty(key)) { continue; }
+ // Even though we will filter again in `getModelTypes`,
+ // we should not call `lookupContainer` on non-models
+ // (especially when `Ember.MODEL_FACTORY_INJECTIONS` is `true`)
+ if (!self.detect(namespace[key])) { continue; }
+ var name = dasherize(key);
+ if (!(namespace instanceof Application) && namespace.toString()) {
+ name = namespace + '/' + name;
+ }
+ types.push(name);
+ }
+ });
+ return types;
+ },
+
+ /**
+ Fetches all loaded records for a given type.
+
+ @private
+ @method getRecords
+ @return {Array} An array of records.
+ This array will be observed for changes,
+ so it should update when new records are added/removed.
+ */
+ getRecords: function(type) {
+ return emberA();
+ },
+
+ /**
+ Wraps a record and observers changes to it.
+
+ @private
+ @method wrapRecord
+ @param {Object} record The record instance.
+ @return {Object} The wrapped record. Format:
+ columnValues: {Array}
+ searchKeywords: {Array}
+ */
+ wrapRecord: function(record) {
+ var recordToSend = { object: record }, columnValues = {}, self = this;
+
+ recordToSend.columnValues = this.getRecordColumnValues(record);
+ recordToSend.searchKeywords = this.getRecordKeywords(record);
+ recordToSend.filterValues = this.getRecordFilterValues(record);
+ recordToSend.color = this.getRecordColor(record);
+
+ return recordToSend;
+ },
+
+ /**
+ Gets the values for each column.
+
+ @private
+ @method getRecordColumnValues
+ @return {Object} Keys should match column names defined
+ by the model type.
+ */
+ getRecordColumnValues: function(record) {
+ return {};
+ },
+
+ /**
+ Returns keywords to match when searching records.
+
+ @private
+ @method getRecordKeywords
+ @return {Array} Relevant keywords for search.
+ */
+ getRecordKeywords: function(record) {
+ return emberA();
+ },
+
+ /**
+ Returns the values of filters defined by `getFilters`.
+
+ @private
+ @method getRecordFilterValues
+ @param {Object} record The record instance
+ @return {Object} The filter values
+ */
+ getRecordFilterValues: function(record) {
+ return {};
+ },
+
+ /**
+ Each record can have a color that represents its state.
+
+ @private
+ @method getRecordColor
+ @param {Object} record The record instance
+ @return {String} The record's color
+ Possible options: black, red, blue, green
+ */
+ getRecordColor: function(record) {
+ return null;
+ },
+
+ /**
+ Observes all relevant properties and re-sends the wrapped record
+ when a change occurs.
+
+ @private
+ @method observerRecord
+ @param {Object} record The record instance
+ @param {Function} recordUpdated The callback to call when a record is updated.
+ @return {Function} The function to call to remove all observers.
+ */
+ observeRecord: function(record, recordUpdated) {
+ return function(){};
+ }
+ });
+ });
+define("ember-extension-support/initializers",
+ [],
+ function() {
+ "use strict";
+
+ });
+define("ember-handlebars-compiler",
+ ["ember-metal/core","exports"],
+ function(__dependency1__, __exports__) {
+ "use strict";
+ /* global Handlebars:true */
+
+ /**
+ @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');
+ }
+
+
+
+ /**
+ 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')['default']; } // ES6TODO: stupid circular dep
+ if (!Component) { Component = requireModule('ember-views/views/component')['default']; } // ES6TODO: stupid circular dep
+
+
+ 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) {
+ 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;
+ });
+define("ember-handlebars",
+ ["ember-handlebars-compiler","ember-metal/core","ember-runtime/system/lazy_load","ember-handlebars/loader","ember-handlebars/ext","ember-handlebars/string","ember-handlebars/helpers/shared","ember-handlebars/helpers/binding","ember-handlebars/helpers/collection","ember-handlebars/helpers/view","ember-handlebars/helpers/unbound","ember-handlebars/helpers/debug","ember-handlebars/helpers/each","ember-handlebars/helpers/template","ember-handlebars/helpers/partial","ember-handlebars/helpers/yield","ember-handlebars/helpers/loc","ember-handlebars/controls/checkbox","ember-handlebars/controls/select","ember-handlebars/controls/text_area","ember-handlebars/controls/text_field","ember-handlebars/controls/text_support","ember-handlebars/controls","ember-handlebars/component_lookup","ember-handlebars/views/handlebars_bound_view","ember-handlebars/views/metamorph_view","exports"],
+ function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __dependency15__, __dependency16__, __dependency17__, __dependency18__, __dependency19__, __dependency20__, __dependency21__, __dependency22__, __dependency23__, __dependency24__, __dependency25__, __dependency26__, __exports__) {
+ "use strict";
+ var EmberHandlebars = __dependency1__["default"];
+ var Ember = __dependency2__["default"];
+ // to add to globals
+
+ var runLoadHooks = __dependency3__.runLoadHooks;
+ var bootstrap = __dependency4__["default"];
+
+ var normalizePath = __dependency5__.normalizePath;
+ var template = __dependency5__.template;
+ var makeBoundHelper = __dependency5__.makeBoundHelper;
+ var registerBoundHelper = __dependency5__.registerBoundHelper;
+ var resolveHash = __dependency5__.resolveHash;
+ var resolveParams = __dependency5__.resolveParams;
+ var getEscaped = __dependency5__.getEscaped;
+ var handlebarsGet = __dependency5__.handlebarsGet;
+ var evaluateUnboundHelper = __dependency5__.evaluateUnboundHelper;
+ var helperMissingHelper = __dependency5__.helperMissingHelper;
+ var blockHelperMissingHelper = __dependency5__.blockHelperMissingHelper;
+
+
+ // side effect of extending StringUtils of htmlSafe
+
+ var resolvePaths = __dependency7__["default"];
+ var bind = __dependency8__.bind;
+ var _triageMustacheHelper = __dependency8__._triageMustacheHelper;
+ var resolveHelper = __dependency8__.resolveHelper;
+ var bindHelper = __dependency8__.bindHelper;
+ var boundIfHelper = __dependency8__.boundIfHelper;
+ var unboundIfHelper = __dependency8__.unboundIfHelper;
+ var withHelper = __dependency8__.withHelper;
+ var ifHelper = __dependency8__.ifHelper;
+ var unlessHelper = __dependency8__.unlessHelper;
+ var bindAttrHelper = __dependency8__.bindAttrHelper;
+ var bindAttrHelperDeprecated = __dependency8__.bindAttrHelperDeprecated;
+ var bindClasses = __dependency8__.bindClasses;
+
+ var collectionHelper = __dependency9__["default"];
+ var ViewHelper = __dependency10__.ViewHelper;
+ var viewHelper = __dependency10__.viewHelper;
+ var unboundHelper = __dependency11__["default"];
+ var logHelper = __dependency12__.logHelper;
+ var debuggerHelper = __dependency12__.debuggerHelper;
+ var EachView = __dependency13__.EachView;
+ var GroupedEach = __dependency13__.GroupedEach;
+ var eachHelper = __dependency13__.eachHelper;
+ var templateHelper = __dependency14__["default"];
+ var partialHelper = __dependency15__["default"];
+ var yieldHelper = __dependency16__["default"];
+ var locHelper = __dependency17__["default"];
+
+
+ var Checkbox = __dependency18__["default"];
+ var Select = __dependency19__.Select;
+ var SelectOption = __dependency19__.SelectOption;
+ var SelectOptgroup = __dependency19__.SelectOptgroup;
+ var TextArea = __dependency20__["default"];
+ var TextField = __dependency21__["default"];
+ var TextSupport = __dependency22__["default"];
+ var inputHelper = __dependency23__.inputHelper;
+ var textareaHelper = __dependency23__.textareaHelper;
+
+
+ var ComponentLookup = __dependency24__["default"];
+ var _HandlebarsBoundView = __dependency25__._HandlebarsBoundView;
+ var SimpleHandlebarsView = __dependency25__.SimpleHandlebarsView;
+ var _wrapMap = __dependency26__._wrapMap;
+ var _SimpleMetamorphView = __dependency26__._SimpleMetamorphView;
+ var _MetamorphView = __dependency26__._MetamorphView;
+ var _Metamorph = __dependency26__._Metamorph;
+
+
+ /**
+ Ember Handlebars
+
+ @module ember
+ @submodule ember-handlebars
+ @requires ember-views
+ */
+
+ // Ember.Handlebars.Globals
+ EmberHandlebars.bootstrap = bootstrap;
+ EmberHandlebars.template = template;
+ EmberHandlebars.makeBoundHelper = makeBoundHelper;
+ EmberHandlebars.registerBoundHelper = registerBoundHelper;
+ EmberHandlebars.resolveHash = resolveHash;
+ EmberHandlebars.resolveParams = resolveParams;
+ EmberHandlebars.resolveHelper = resolveHelper;
+ EmberHandlebars.get = handlebarsGet;
+ EmberHandlebars.getEscaped = getEscaped;
+ EmberHandlebars.evaluateUnboundHelper = evaluateUnboundHelper;
+ EmberHandlebars.bind = bind;
+ EmberHandlebars.bindClasses = bindClasses;
+ EmberHandlebars.EachView = EachView;
+ EmberHandlebars.GroupedEach = GroupedEach;
+ EmberHandlebars.resolvePaths = resolvePaths;
+ EmberHandlebars.ViewHelper = ViewHelper;
+ EmberHandlebars.normalizePath = normalizePath;
+
+
+ // Ember Globals
+ Ember.Handlebars = EmberHandlebars;
+ Ember.ComponentLookup = ComponentLookup;
+ Ember._SimpleHandlebarsView = SimpleHandlebarsView;
+ Ember._HandlebarsBoundView = _HandlebarsBoundView;
+ Ember._SimpleMetamorphView = _SimpleMetamorphView;
+ Ember._MetamorphView = _MetamorphView;
+ Ember._Metamorph = _Metamorph;
+ Ember._metamorphWrapMap = _wrapMap;
+ Ember.TextSupport = TextSupport;
+ Ember.Checkbox = Checkbox;
+ Ember.Select = Select;
+ Ember.SelectOption = SelectOption;
+ Ember.SelectOptgroup = SelectOptgroup;
+ Ember.TextArea = TextArea;
+ Ember.TextField = TextField;
+ Ember.TextSupport = TextSupport;
+
+ // register helpers
+ EmberHandlebars.registerHelper('helperMissing', helperMissingHelper);
+ EmberHandlebars.registerHelper('blockHelperMissing', blockHelperMissingHelper);
+ EmberHandlebars.registerHelper('bind', bindHelper);
+ EmberHandlebars.registerHelper('boundIf', boundIfHelper);
+ EmberHandlebars.registerHelper('_triageMustache', _triageMustacheHelper);
+ EmberHandlebars.registerHelper('unboundIf', unboundIfHelper);
+ EmberHandlebars.registerHelper('with', withHelper);
+ EmberHandlebars.registerHelper('if', ifHelper);
+ EmberHandlebars.registerHelper('unless', unlessHelper);
+ EmberHandlebars.registerHelper('bind-attr', bindAttrHelper);
+ EmberHandlebars.registerHelper('bindAttr', bindAttrHelperDeprecated);
+ EmberHandlebars.registerHelper('collection', collectionHelper);
+ EmberHandlebars.registerHelper("log", logHelper);
+ EmberHandlebars.registerHelper("debugger", debuggerHelper);
+ EmberHandlebars.registerHelper("each", eachHelper);
+ EmberHandlebars.registerHelper("loc", locHelper);
+ EmberHandlebars.registerHelper("partial", partialHelper);
+ EmberHandlebars.registerHelper("template", templateHelper);
+ EmberHandlebars.registerHelper("yield", yieldHelper);
+ EmberHandlebars.registerHelper("view", viewHelper);
+ EmberHandlebars.registerHelper("unbound", unboundHelper);
+ EmberHandlebars.registerHelper("input", inputHelper);
+ EmberHandlebars.registerHelper("textarea", textareaHelper);
+
+ // run load hooks
+ runLoadHooks('Ember.Handlebars', EmberHandlebars);
+
+ __exports__["default"] = EmberHandlebars;
+ });
+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","ember-handlebars/ext","exports"],
+ function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __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 handlebarsGet = __dependency6__.handlebarsGet;
+ var helpers = EmberHandlebars.helpers;
+ /**
+ @module ember
+ @submodule ember-handlebars-compiler
+ */
+
+ function _resolveOption(context, options, key) {
+ if (options.hashTypes[key] === "ID") {
+ return handlebarsGet(context, options.hash[key], options);
+ } else {
+ return options.hash[key];
+ }
+ }
+
+ /**
+
+ 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
+
+ ```
+
+ ## Actions
+
+ The helper can send multiple actions based on user events.
+
+ The action property defines the action which is send when
+ the user presses the return key.
+
+ ```handlebars
+ {{input action="submit"}}
+ ```
+
+ The helper allows some user events to send actions.
+
+ * `enter`
+ * `insert-newline`
+ * `escape-press`
+ * `focus-in`
+ * `focus-out`
+ * `key-press`
+
+ For example, if you desire an action to be sent when the input is blurred,
+ you only need to setup the action name to the event name property.
+
+ ```handlebars
+ {{input focus-in="alertMessage"}}
+ ```
+
+ See more about [Text Support Actions](/api/classes/Ember.TextField.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) {
+
+ var hash = options.hash,
+ types = options.hashTypes,
+ inputType = _resolveOption(this, options, 'type'),
+ onEvent = hash.on;
+
+ if (inputType === 'checkbox') {
+ delete hash.type;
+ delete types.type;
+
+
+ return helpers.view.call(this, Checkbox, options);
+ } else {
+ delete hash.on;
+
+ hash.onEvent = onEvent || 'enter';
+ return helpers.view.call(this, TextField, options);
+ }
+ }
+
+ __exports__.inputHelper = inputHelper;/**
+ `{{textarea}}` inserts a new instance of `
` tag into the template.
+ The attributes of `{{textarea}}` match those of the native HTML tags as
+ closely as possible.
+
+ The following HTML attributes can be set:
+
+ * `value`
+ * `name`
+ * `rows`
+ * `cols`
+ * `placeholder`
+ * `disabled`
+ * `maxlength`
+ * `tabindex`
+ * `selectionEnd`
+ * `selectionStart`
+ * `selectionDirection`
+ * `wrap`
+ * `readonly`
+ * `autofocus`
+ * `form`
+ * `spellcheck`
+ * `required`
+
+ When set to a quoted string, these value 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
+ {{textarea value="Lots of static text that ISN'T bound"}}
+ ```
+
+ Would result in the following HTML:
+
+ ```html
+
+ Lots of static text that ISN'T bound
+
+ ```
+
+ 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
+
+ Lots of text that IS bound
+
+ ```
+
+ 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
+
+ Lots of text that IS bound
+
+
+ <-- 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
+
+ Lots of text that IS bound
+
+
+ <-- both updated in real time -->
+
+
+ Lots of text that IS bound
+
+ ```
+
+ ## Actions
+
+ The helper can send multiple actions based on user events.
+
+ The action property defines the action which is send when
+ the user presses the return key.
+
+ ```handlebars
+ {{input action="submit"}}
+ ```
+
+ The helper allows some user events to send actions.
+
+ * `enter`
+ * `insert-newline`
+ * `escape-press`
+ * `focus-in`
+ * `focus-out`
+ * `key-press`
+
+ For example, if you desire an action to be sent when the input is blurred,
+ you only need to setup the action name to the event name property.
+
+ ```handlebars
+ {{textarea focus-in="alertMessage"}}
+ ```
+
+ See more about [Text Support Actions](/api/classes/Ember.TextArea.html)
+
+ ## 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) {
+
+ var hash = options.hash,
+ types = options.hashTypes;
+
+ return helpers.view.call(this, TextArea, options);
+ }
+
+ __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__["default"];
+
+ /**
+ @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
+ */
+ __exports__["default"] = 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'));
+ }
+ });
+ });
+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";
+ /**
+ @module ember
+ @submodule ember-handlebars
+ */
+
+ var EmberHandlebars = __dependency1__["default"];
+
+ var forEach = __dependency2__.forEach;
+ var indexOf = __dependency2__.indexOf;
+ var indexesOf = __dependency2__.indexesOf;
+ var replace = __dependency2__.replace;
+
+ var get = __dependency3__.get;
+ var set = __dependency4__.set;
+ var View = __dependency5__["default"];
+ var CollectionView = __dependency6__["default"];
+ var isArray = __dependency7__.isArray;
+ var isNone = __dependency8__["default"];
+ var computed = __dependency9__.computed;
+ var emberA = __dependency10__.A;
+ var observer = __dependency11__.observer;
+ var defineProperty = __dependency12__.defineProperty;
+
+ var 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; // jshint ignore:line
+ }
+ }).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 `