summaryrefslogtreecommitdiff
path: root/imdb-lookup/js/libs/ember-1.9.0.js
diff options
context:
space:
mode:
authorYves Fischer <yvesf-git@xapek.org>2014-12-23 01:35:48 +0100
committerYves Fischer <yvesf-git@xapek.org>2014-12-23 01:35:48 +0100
commit94a86bb23d97c2fd1bc38fca73b99e72a7fdfa8e (patch)
treebecf09c66ee26dc2dd4f7fd26652fbd296baf828 /imdb-lookup/js/libs/ember-1.9.0.js
parent82f5bd6a4aff840f21076a8bf47a022d08b1dddf (diff)
downloadscripts-94a86bb23d97c2fd1bc38fca73b99e72a7fdfa8e.tar.gz
scripts-94a86bb23d97c2fd1bc38fca73b99e72a7fdfa8e.zip
remove jinja
Diffstat (limited to 'imdb-lookup/js/libs/ember-1.9.0.js')
-rw-r--r--imdb-lookup/js/libs/ember-1.9.0.js50331
1 files changed, 0 insertions, 50331 deletions
diff --git a/imdb-lookup/js/libs/ember-1.9.0.js b/imdb-lookup/js/libs/ember-1.9.0.js
deleted file mode 100644
index 3ec5c65..0000000
--- a/imdb-lookup/js/libs/ember-1.9.0.js
+++ /dev/null
@@ -1,50331 +0,0 @@
-/*!
- * @overview Ember - JavaScript Application Framework
- * @copyright Copyright 2011-2014 Tilde Inc. and contributors
- * Portions Copyright 2006-2011 Strobe Inc.
- * Portions Copyright 2008-2011 Apple Inc. All rights reserved.
- * @license Licensed under MIT license
- * See https://raw.github.com/emberjs/ember.js/master/LICENSE
- * @version 1.9.0
- */
-
-(function() {
-var enifed, requireModule, eriuqer, requirejs, Ember;
-
-(function() {
- Ember = this.Ember = this.Ember || {};
- if (typeof Ember === 'undefined') { Ember = {}; };
- function UNDEFINED() { }
-
- if (typeof Ember.__loader === 'undefined') {
- var registry = {}, seen = {};
-
- enifed = function(name, deps, callback) {
- registry[name] = { deps: deps, callback: callback };
- };
-
- requirejs = eriuqer = requireModule = function(name) {
- var s = seen[name];
-
- if (s !== undefined) { return seen[name]; }
- if (s === UNDEFINED) { return undefined; }
-
- seen[name] = {};
-
- if (!registry[name]) {
- throw new Error("Could not find module " + name);
- }
-
- var mod = registry[name];
- var deps = mod.deps;
- var callback = mod.callback;
- var reified = [];
- var exports;
- var length = deps.length;
-
- for (var i=0; i<length; i++) {
- if (deps[i] === 'exports') {
- reified.push(exports = {});
- } else {
- reified.push(requireModule(resolve(deps[i], name)));
- }
- }
-
- var value = length === 0 ? callback.call(this) : callback.apply(this, reified);
-
- return seen[name] = exports || (value === undefined ? UNDEFINED : value);
- };
-
- function resolve(child, name) {
- if (child.charAt(0) !== '.') { return child; }
- var parts = child.split("/");
- var parentBase = name.split("/").slice(0, -1);
-
- for (var i=0, l=parts.length; i<l; i++) {
- var part = parts[i];
-
- if (part === '..') { parentBase.pop(); }
- else if (part === '.') { continue; }
- else { parentBase.push(part); }
- }
-
- return parentBase.join("/");
- }
-
- requirejs._eak_seen = registry;
-
- Ember.__loader = {define: enifed, require: eriuqer, registry: registry};
- } else {
- enifed = Ember.__loader.define;
- requirejs = eriuqer = requireModule = Ember.__loader.require;
- }
-})();
-
-enifed("backburner",
- ["backburner/utils","backburner/platform","backburner/binary-search","backburner/deferred-action-queues","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
- "use strict";
- var each = __dependency1__.each;
- var isString = __dependency1__.isString;
- var isFunction = __dependency1__.isFunction;
- var isNumber = __dependency1__.isNumber;
- var isCoercableNumber = __dependency1__.isCoercableNumber;
- var wrapInTryCatch = __dependency1__.wrapInTryCatch;
- var now = __dependency1__.now;
-
- var needsIETryCatchFix = __dependency2__.needsIETryCatchFix;
-
- var searchTimer = __dependency3__["default"];
-
- var DeferredActionQueues = __dependency4__["default"];
-
- var slice = [].slice;
- var pop = [].pop;
- var global = this;
-
- 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 = [];
- this._timers = [];
- }
-
- Backburner.prototype = {
- begin: function() {
- var options = this.options;
- var onBegin = options && options.onBegin;
- var 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;
- var onEnd = options && options.onEnd;
- var currentInstance = this.currentInstance;
- var 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();
- }
- }
- }
- },
-
- join: function(target, method /*, args */) {
- if (this.currentInstance) {
- if (!method) {
- method = target;
- target = null;
- }
-
- if (isString(method)) {
- method = target[method];
- }
-
- return method.apply(target, slice.call(arguments, 2));
- } else {
- return this.run.apply(this, arguments);
- }
- },
-
- 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;
- var length = arguments.length;
- var args;
-
- if (length > 3) {
- args = new Array(length - 3);
- for (var i = 3; i < length; i++) {
- args[i-3] = arguments[i];
- }
- } else {
- args = 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;
- var length = arguments.length;
- var args;
-
- if (length > 3) {
- args = new Array(length - 3);
- for (var i = 3; i < length; i++) {
- args[i-3] = arguments[i];
- }
- } else {
- args = undefined;
- }
-
- if (!this.currentInstance) {
- createAutorun(this);
- }
- return this.currentInstance.schedule(queueName, target, method, args, true, stack);
- },
-
- setTimeout: function() {
- var l = arguments.length;
- var args = new Array(l);
-
- for (var x = 0; x < l; x++) {
- args[x] = arguments[x];
- }
-
- var 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 = now() + 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, this._timers);
-
- this._timers.splice(i, 0, executeAt, fn);
-
- updateLaterTimer(this, executeAt, wait);
-
- return fn;
- },
-
- throttle: function(target, method /* , args, wait, [immediate] */) {
- var backburner = this;
- var args = arguments;
- var immediate = pop.call(args);
- var 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) {
- backburner.run.apply(backburner, args);
- }
- var index = findThrottler(target, method, backburner._throttlers);
- if (index > -1) {
- backburner._throttlers.splice(index, 1);
- }
- }, wait);
-
- if (immediate) {
- this.run.apply(this, args);
- }
-
- throttler = [target, method, timer];
-
- this._throttlers.push(throttler);
-
- return throttler;
- },
-
- debounce: function(target, method /* , args, wait, [immediate] */) {
- var backburner = this;
- var args = arguments;
- var immediate = pop.call(args);
- var 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) {
- backburner.run.apply(backburner, args);
- }
- var index = findDebouncee(target, method, backburner._debouncees);
- if (index > -1) {
- backburner._debouncees.splice(index, 1);
- }
- }, wait);
-
- if (immediate && index === -1) {
- backburner.run.apply(backburner, args);
- }
-
- debouncee = [
- target,
- method,
- timer
- ];
-
- backburner._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;
- }
- this._timers = [];
-
- if (this._autorun) {
- clearTimeout(this._autorun);
- this._autorun = null;
- }
- },
-
- hasTimers: function() {
- return !!this._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 = this._timers.length; i < l; i += 2) {
- if (this._timers[i + 1] === timer) {
- this._timers.splice(i, 2); // remove the two elements
- if (i === 0) {
- if (this._laterTimer) { // Active timer? Then clear timer and reset for future timer
- clearTimeout(this._laterTimer);
- this._laterTimer = null;
- }
- if (this._timers.length > 0) { // Update to next available timer when available
- updateLaterTimer(this, this._timers[0], this._timers[0] - now());
- }
- }
- 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 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(backburner, executeAt, wait) {
- var n = now();
- if (!backburner._laterTimer || executeAt < backburner._laterTimerExpiresAt || backburner._laterTimerExpiresAt < n) {
-
- if (backburner._laterTimer) {
- // Clear when:
- // - Already expired
- // - New timer is earlier
- clearTimeout(backburner._laterTimer);
-
- if (backburner._laterTimerExpiresAt < n) { // If timer was never triggered
- // Calculate the left-over wait-time
- wait = Math.max(0, executeAt - n);
- }
- }
-
- backburner._laterTimer = global.setTimeout(function() {
- backburner._laterTimer = null;
- backburner._laterTimerExpiresAt = null;
- executeTimers(backburner);
- }, wait);
-
- backburner._laterTimerExpiresAt = n + wait;
- }
- }
-
- function executeTimers(backburner) {
- var n = now();
- var fns, i, l;
-
- backburner.run(function() {
- i = searchTimer(n, backburner._timers);
-
- fns = backburner._timers.splice(0, i);
-
- for (i = 1, l = fns.length; i < l; i += 2) {
- backburner.schedule(backburner.options.defaultQueue, null, fns[i]);
- }
- });
-
- if (backburner._timers.length) {
- updateLaterTimer(backburner, backburner._timers[0], backburner._timers[0] - n);
- }
- }
-
- 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;
- var 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;
- }
-
- __exports__["default"] = Backburner;
- });
-enifed("backburner.umd",
- ["./backburner"],
- function(__dependency1__) {
- "use strict";
- var Backburner = __dependency1__["default"];
-
- /* global define:true module:true window: true */
- if (typeof enifed === 'function' && enifed.amd) {
- enifed(function() { return Backburner; });
- } else if (typeof module !== 'undefined' && module.exports) {
- module.exports = Backburner;
- } else if (typeof this !== 'undefined') {
- this['Backburner'] = Backburner;
- }
- });
-enifed("backburner/binary-search",
- ["exports"],
- function(__exports__) {
- "use strict";
- __exports__["default"] = function binarySearch(time, timers) {
- var start = 0;
- var end = timers.length - 2;
- var 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;
- }
- });
-enifed("backburner/deferred-action-queues",
- ["./utils","./queue","exports"],
- function(__dependency1__, __dependency2__, __exports__) {
- "use strict";
- var each = __dependency1__.each;
- var Queue = __dependency2__["default"];
-
- function DeferredActionQueues(queueNames, options) {
- var queues = this.queues = Object.create(null);
- this.queueNames = queueNames = queueNames || [];
-
- this.options = options;
-
- each(queueNames, function(queueName) {
- queues[queueName] = new Queue(queueName, options[queueName], options);
- });
- }
-
- function noSuchQueue(name) {
- throw new Error("You attempted to schedule an action in a queue (" + name + ") that doesn't exist");
- }
-
- DeferredActionQueues.prototype = {
- schedule: function(name, target, method, args, onceFlag, stack) {
- var queues = this.queues;
- var queue = queues[name];
-
- if (!queue) {
- noSuchQueue(name);
- }
-
- if (onceFlag) {
- return queue.pushUnique(target, method, args, stack);
- } else {
- return queue.push(target, method, args, stack);
- }
- },
-
- flush: function() {
- var queues = this.queues;
- var queueNames = this.queueNames;
- var queueName, queue, queueItems, priorQueueNameIndex;
- var queueNameIndex = 0;
- var numberOfQueues = queueNames.length;
- var options = this.options;
-
- while (queueNameIndex < numberOfQueues) {
- queueName = queueNames[queueNameIndex];
- queue = queues[queueName];
-
- var numberOfQueueItems = queue._queue.length;
-
- if (numberOfQueueItems === 0) {
- queueNameIndex++;
- } else {
- queue.flush(false /* async */);
- queueNameIndex = 0;
- }
- }
- }
- };
-
- __exports__["default"] = DeferredActionQueues;
- });
-enifed("backburner/platform",
- ["exports"],
- function(__exports__) {
- "use strict";
- // 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;
- })();
- __exports__.needsIETryCatchFix = needsIETryCatchFix;
- });
-enifed("backburner/queue",
- ["./utils","exports"],
- function(__dependency1__, __exports__) {
- "use strict";
- var isString = __dependency1__.isString;
-
- function Queue(name, options, globalOptions) {
- this.name = name;
- this.globalOptions = globalOptions || {};
- this.options = options;
- this._queue = [];
- this.targetQueues = Object.create(null);
- this._queueBeingFlushed = undefined;
- }
-
- Queue.prototype = {
- push: function(target, method, args, stack) {
- var queue = this._queue;
- queue.push(target, method, args, stack);
-
- return {
- queue: this,
- target: target,
- method: method
- };
- },
-
- pushUniqueWithoutGuid: function(target, method, args, stack) {
- var queue = this._queue;
-
- for (var i = 0, l = queue.length; i < l; i += 4) {
- var currentTarget = queue[i];
- var currentMethod = queue[i+1];
-
- if (currentTarget === target && currentMethod === method) {
- queue[i+2] = args; // replace args
- queue[i+3] = stack; // replace stack
- return;
- }
- }
-
- queue.push(target, method, args, stack);
- },
-
- targetQueue: function(targetQueue, target, method, args, stack) {
- var queue = this._queue;
-
- for (var i = 0, l = targetQueue.length; i < l; i += 4) {
- var currentMethod = targetQueue[i];
- var currentIndex = targetQueue[i + 1];
-
- if (currentMethod === method) {
- queue[currentIndex + 2] = args; // replace args
- queue[currentIndex + 3] = stack; // replace stack
- return;
- }
- }
-
- targetQueue.push(
- method,
- queue.push(target, method, args, stack) - 4
- );
- },
-
- pushUniqueWithGuid: function(guid, target, method, args, stack) {
- var hasLocalQueue = this.targetQueues[guid];
-
- if (hasLocalQueue) {
- this.targetQueue(hasLocalQueue, target, method, args, stack);
- } else {
- this.targetQueues[guid] = [
- method,
- this._queue.push(target, method, args, stack) - 4
- ];
- }
-
- return {
- queue: this,
- target: target,
- method: method
- };
- },
-
- pushUnique: function(target, method, args, stack) {
- var queue = this._queue, currentTarget, currentMethod, i, l;
- var KEY = this.globalOptions.GUID_KEY;
-
- if (target && KEY) {
- var guid = target[KEY];
- if (guid) {
- return this.pushUniqueWithGuid(guid, target, method, args, stack);
- }
- }
-
- this.pushUniqueWithoutGuid(target, method, args, stack);
-
- return {
- queue: this,
- target: target,
- method: method
- };
- },
-
- invoke: function(target, method, args, _, _errorRecordedForStack) {
- if (args && args.length > 0) {
- method.apply(target, args);
- } else {
- method.call(target);
- }
- },
-
- invokeWithOnError: function(target, method, args, onError, errorRecordedForStack) {
- try {
- if (args && args.length > 0) {
- method.apply(target, args);
- } else {
- method.call(target);
- }
- } catch(error) {
- onError(error, errorRecordedForStack);
- }
- },
-
- flush: function(sync) {
- var queue = this._queue;
- var length = queue.length;
-
- if (length === 0) {
- return;
- }
-
- var globalOptions = this.globalOptions;
- var options = this.options;
- var before = options && options.before;
- var after = options && options.after;
- var onError = globalOptions.onError || (globalOptions.onErrorTarget &&
- globalOptions.onErrorTarget[globalOptions.onErrorMethod]);
- var target, method, args, errorRecordedForStack;
- var invoke = onError ? this.invokeWithOnError : this.invoke;
-
- this.targetQueues = Object.create(null);
- var queueItems = this._queueBeingFlushed = this._queue.slice();
- this._queue = [];
-
- if (before) {
- before();
- }
-
- for (var i = 0; i < length; i += 4) {
- target = queueItems[i];
- method = queueItems[i+1];
- args = queueItems[i+2];
- errorRecordedForStack = queueItems[i+3]; // Debugging assistance
-
- if (isString(method)) {
- method = target[method];
- }
-
- // method could have been nullified / canceled during flush
- if (method) {
- //
- // ** Attention intrepid developer **
- //
- // To find out the stack of this task when it was scheduled onto
- // the run loop, add the following to your app.js:
- //
- // Ember.run.backburner.DEBUG = true; // NOTE: This slows your app, don't leave it on in production.
- //
- // Once that is in place, when you are at a breakpoint and navigate
- // here in the stack explorer, you can look at `errorRecordedForStack.stack`,
- // which will be the captured stack when this job was scheduled.
- //
- invoke(target, method, args, onError, errorRecordedForStack);
- }
- }
-
- if (after) {
- after();
- }
-
- this._queueBeingFlushed = undefined;
-
- if (sync !== false &&
- this._queue.length > 0) {
- // check if new items have been added
- this.flush(true);
- }
- },
-
- cancel: function(actionToCancel) {
- var queue = this._queue, currentTarget, currentMethod, i, l;
- var target = actionToCancel.target;
- var method = actionToCancel.method;
- var GUID_KEY = this.globalOptions.GUID_KEY;
-
- if (GUID_KEY && this.targetQueues && target) {
- var targetQueue = this.targetQueues[target[GUID_KEY]];
-
- if (targetQueue) {
- for (i = 0, l = targetQueue.length; i < l; i++) {
- if (targetQueue[i] === method) {
- targetQueue.splice(i, 1);
- }
- }
- }
- }
-
- for (i = 0, l = queue.length; i < l; i += 4) {
- currentTarget = queue[i];
- currentMethod = queue[i+1];
-
- if (currentTarget === target &&
- currentMethod === 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 === target &&
- currentMethod === method) {
- // don't mess with array during flush
- // just nullify the method
- queue[i+1] = null;
- return true;
- }
- }
- }
- };
-
- __exports__["default"] = Queue;
- });
-enifed("backburner/utils",
- ["exports"],
- function(__exports__) {
- "use strict";
- var NUMBER = /\d+/;
-
- function each(collection, callback) {
- for (var i = 0; i < collection.length; i++) {
- callback(collection[i]);
- }
- }
-
- __exports__.each = each;// Date.now is not available in browsers < IE9
- // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/now#Compatibility
- var now = Date.now || function() { return new Date().getTime(); };
- __exports__.now = now;
- function isString(suspect) {
- return typeof suspect === 'string';
- }
-
- __exports__.isString = isString;function isFunction(suspect) {
- return typeof suspect === 'function';
- }
-
- __exports__.isFunction = isFunction;function isNumber(suspect) {
- return typeof suspect === 'number';
- }
-
- __exports__.isNumber = isNumber;function isCoercableNumber(number) {
- return isNumber(number) || NUMBER.test(number);
- }
-
- __exports__.isCoercableNumber = isCoercableNumber;function wrapInTryCatch(func) {
- return function () {
- try {
- return func.apply(this, arguments);
- } catch (e) {
- throw e;
- }
- };
- }
-
- __exports__.wrapInTryCatch = wrapInTryCatch;
- });
-enifed("calculateVersion",
- [],
- function() {
- "use strict";
- 'use strict';
-
- var fs = eriuqer('fs');
- var path = eriuqer('path');
-
- module.exports = function () {
- var packageVersion = eriuqer('../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;
- }
- };
- });
-enifed("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;
- });
-enifed("container/container",
- ["ember-metal/core","ember-metal/keys","ember-metal/dictionary","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
- "use strict";
- var Ember = __dependency1__["default"];
- // Ember.assert
- var emberKeys = __dependency2__["default"];
- var dictionary = __dependency3__["default"];
-
- // 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 = dictionary(parent ? parent.registry : null);
- this.cache = dictionary(parent ? parent.cache : null);
- this.factoryCache = dictionary(parent ? parent.factoryCache : null);
- this.resolveCache = dictionary(parent ? parent.resolveCache : null);
- this.typeInjections = dictionary(parent ? parent.typeInjections : null);
- this.injections = dictionary(null);
- this.normalizeCache = dictionary(null);
-
- this.factoryTypeInjections = dictionary(parent ? parent.factoryTypeInjections : null);
- this.factoryInjections = dictionary(null);
-
- this._options = dictionary(parent ? parent._options : null);
- this._typeOptions = dictionary(parent ? parent._typeOptions : null);
- }
-
- 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;
- },
-
- /**
- 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 (normalizedName in this.cache) {
- throw new Error('Cannot re-register: `' + fullName +'`, as it has already been looked up.');
- }
-
- this.registry[normalizedName] = factory;
- this._options[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);
-
- delete this.registry[normalizedName];
- delete this.cache[normalizedName];
- delete this.factoryCache[normalizedName];
- delete this.resolveCache[normalizedName];
- delete this._options[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 normalizeFullName
- @param {String} fullName
- @return {string} normalized fullName
- */
- normalizeFullName: function(fullName) {
- return fullName;
- },
-
- /**
- normalize a fullName based on the applications conventions
-
- @method normalize
- @param {String} fullName
- @return {string} normalized fullName
- */
- normalize: function(fullName) {
- return this.normalizeCache[fullName] || (
- this.normalizeCache[fullName] = this.normalizeFullName(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[type] = options;
- },
-
- /**
- @method options
- @param {String} fullName
- @param {Object} options
- */
- options: function(fullName, options) {
- options = options || {};
- var normalizedName = this.normalize(fullName);
- this._options[normalizedName] = 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[normalizedName]) {
- throw new Error("Attempted to register an injection for a type that has already been looked up. ('" +
- normalizedName + "', '" +
- property + "', '" +
- injectionName + "')");
- }
-
- addInjection(initRules(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[normalizedName]) {
- throw new Error('Attempted to register a factoryInjection for a type that has already ' +
- 'been looked up. (\'' + normalizedName + '\', \'' + property + '\', \'' + injectionName + '\')');
- }
-
- addInjection(initRules(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[normalizedName];
- if (cached) { return cached; }
-
- var resolved = container.resolver(normalizedName) || container.registry[normalizedName];
- container.resolveCache[normalizedName] = resolved;
-
- return resolved;
- }
-
- function has(container, fullName){
- if (container.cache[fullName]) {
- return true;
- }
-
- return container.resolve(fullName) !== undefined;
- }
-
- function lookup(container, fullName, options) {
- options = options || {};
-
- if (container.cache[fullName] && options.singleton !== false) {
- return container.cache[fullName];
- }
-
- var value = instantiate(container, fullName);
-
- if (value === undefined) { return; }
-
- if (isSingleton(container, fullName) && options.singleton !== false) {
- container.cache[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; }
-
- validateInjections(container, injections);
-
- var injection;
-
- for (var i = 0, length = injections.length; i < length; i++) {
- injection = injections[i];
- hash[injection.property] = lookup(container, injection.fullName);
- }
-
- return hash;
- }
-
- function validateInjections(container, injections) {
- if (!injections) { return; }
-
- var fullName;
-
- for (var i = 0, length = injections.length; i < length; i++) {
- fullName = injections[i].fullName;
-
- if (!container.has(fullName)) {
- throw new Error('Attempting to inject an unknown injection: `' + fullName + '`');
- }
- }
- }
-
- function option(container, fullName, optionName) {
- var options = container._options[fullName];
-
- if (options && options[optionName] !== undefined) {
- return options[optionName];
- }
-
- var type = fullName.split(':')[0];
- options = container._typeOptions[type];
-
- if (options) {
- return options[optionName];
- }
- }
-
- function factoryFor(container, fullName) {
- var cache = container.factoryCache;
- if (cache[fullName]) {
- return cache[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
- cache[fullName] = factory;
- 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[fullName] = injectedFactory;
-
- return injectedFactory;
- }
- }
-
- function injectionsFor(container, fullName) {
- var splitName = fullName.split(':');
- var type = splitName[0];
- var injections = [];
-
- injections = injections.concat(container.typeInjections[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(':');
- var type = splitName[0];
- var factoryInjections = [];
-
- factoryInjections = factoryInjections.concat(container.factoryTypeInjections[type] || []);
- factoryInjections = factoryInjections.concat(container.factoryInjections[fullName] || []);
-
- factoryInjections = buildInjections(container, factoryInjections);
- factoryInjections._debugContainerKey = fullName;
-
- return factoryInjections;
- }
-
- function normalizeInjectionsHash(hash) {
- var injections = [];
-
- for (var key in hash) {
- if (hash.hasOwnProperty(key)) {
- Ember.assert("Expected a proper full name, given '" + hash[key] + "'", validateFullName(hash[key]));
-
- addInjection(injections, key, hash[key]);
- }
- }
-
- return injections;
- }
-
- function instantiate(container, fullName) {
- var factory = factoryFor(container, fullName);
- var lazyInjections;
-
- 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) {
- var cache = container.cache;
- var keys = emberKeys(cache);
- var key, value;
-
- for (var i = 0, l = keys.length; i < l; i++) {
- key = keys[i];
- value = cache[key];
-
- if (option(container, key, 'instantiate') !== false) {
- callback(value);
- }
- }
- }
-
- function resetCache(container) {
- eachDestroyable(container, function(value) {
- value.destroy();
- });
-
- container.cache.dict = dictionary(null);
- }
-
- function addTypeInjection(rules, type, property, fullName) {
- var injections = rules[type];
-
- if (!injections) {
- injections = [];
- rules[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 initRules(rules, factoryName) {
- return rules[factoryName] || (rules[factoryName] = []);
- }
-
- function addInjection(injections, property, injectionName) {
- injections.push({
- property: property,
- fullName: injectionName
- });
- }
-
- __exports__["default"] = Container;
- });
-enifed("dag-map",
- ["exports"],
- function(__exports__) {
- "use strict";
- 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 = Object.create(null);
- }
-
- /**
- * DAG Vertex
- *
- * @class Vertex
- * @constructor
- */
-
- function Vertex(name) {
- this.name = name;
- this.incoming = {};
- this.incomingNames = [];
- this.hasOutgoing = false;
- this.value = null;
- }
-
- /**
- * 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) {
- throw new Error("Can't add Vertex without name");
- }
- if (this.vertices[name] !== undefined) {
- return this.vertices[name];
- }
- var vertex = new Vertex(name);
- 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
- * necessary, 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);
- var to = this.add(toName);
- if (to.incoming.hasOwnProperty(fromName)) {
- return;
- }
- function checkCycle(vertex, path) {
- if (vertex.name === toName) {
- throw new Error("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;
- });
-enifed("dag-map.umd",
- ["./dag-map"],
- function(__dependency1__) {
- "use strict";
- var DAG = __dependency1__["default"];
-
- /* global define:true module:true window: true */
- if (typeof enifed === 'function' && enifed.amd) {
- enifed(function() { return DAG; });
- } else if (typeof module !== 'undefined' && module.exports) {
- module.exports = DAG;
- } else if (typeof this !== 'undefined') {
- this['DAG'] = DAG;
- }
- });
-enifed("ember-application",
- ["ember-metal/core","ember-runtime/system/lazy_load","ember-application/system/resolver","ember-application/system/application","ember-application/ext/controller"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__) {
- "use strict";
- var Ember = __dependency1__["default"];
- var runLoadHooks = __dependency2__.runLoadHooks;
-
- /**
- Ember Application
-
- @module ember
- @submodule ember-application
- @requires ember-views, ember-routing
- */
-
- var Resolver = __dependency3__.Resolver;
- var DefaultResolver = __dependency3__["default"];
- var Application = __dependency4__["default"];
- // side effect of extending ControllerMixin
-
- Ember.Application = Application;
- Ember.Resolver = Resolver;
- Ember.DefaultResolver = DefaultResolver;
-
- runLoadHooks('Ember.Application', Application);
- });
-enifed("ember-application/ext/controller",
- ["ember-metal/core","ember-metal/property_get","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__, __exports__) {
- "use strict";
- /**
- @module ember
- @submodule ember-application
- */
-
- var Ember = __dependency1__["default"];
- // Ember.assert
- var get = __dependency2__.get;
- var EmberError = __dependency3__["default"];
- var inspect = __dependency4__.inspect;
- var computed = __dependency5__.computed;
- var ControllerMixin = __dependency6__["default"];
- var meta = __dependency4__.meta;
- var controllerFor = __dependency7__["default"];
-
- function verifyNeedsDependencies(controller, container, needs) {
- var dependency, i, l;
- var missing = [];
-
- for (i=0, l=needs.length; i<l; i++) {
- dependency = needs[i];
-
- Ember.assert(inspect(controller) + "#needs must not specify dependencies with periods in their names (" +
- dependency + ")", dependency.indexOf('.') === -1);
-
- if (dependency.indexOf(':') === -1) {
- dependency = "controller:" + dependency;
- }
-
- // Structure assert to still do verification but not string concat in production
- if (!container.has(dependency)) {
- missing.push(dependency);
- }
- }
- if (missing.length) {
- throw new EmberError(inspect(controller) + " needs [ " + missing.join(', ') +
- " ] but " + (missing.length > 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;
- var dependency, i, l;
-
- for (i=0, l=needs.length; i<l; i++) {
- dependency = needs[i];
- if (dependency === controllerName) {
- return this.container.lookup('controller:' + controllerName);
- }
- }
-
- var errorMessage = inspect(controller) + '#needs does not include `' +
- controllerName + '`. To access the ' +
- controllerName + ' controller from ' +
- inspect(controller) + ', ' +
- inspect(controller) +
- ' should have a `needs` property that is an array of the controllers it has access to.';
- throw new ReferenceError(errorMessage);
- },
- setUnknownProperty: function (key, value) {
- throw new Error("You cannot overwrite the value of `controllers." + key + "` of " + inspect(controller));
- }
- };
- });
-
- /**
- @class ControllerMixin
- @namespace Ember
- */
- ControllerMixin.reopen({
- concatenatedProperties: ['needs'],
-
- /**
- An array of other controller objects available inside
- instances of this controller via the `controllers`
- property:
-
- For example, when you define a controller:
-
- ```javascript
- App.CommentsController = Ember.ArrayController.extend({
- needs: ['post']
- });
- ```
-
- The application's single instance of these other
- controllers are accessible by name through the
- `controllers` property:
-
- ```javascript
- this.get('controllers.post'); // instance of App.PostController
- ```
-
- Given that you have a nested controller (nested resource):
-
- ```javascript
- App.CommentsNewController = Ember.ObjectController.extend({
- });
- ```
-
- When you define a controller that requires access to a nested one:
-
- ```javascript
- App.IndexController = Ember.ObjectController.extend({
- needs: ['commentsNew']
- });
- ```
-
- You will be able to get access to it:
-
- ```javascript
- this.get('controllers.commentsNew'); // instance of App.CommentsNewController
- ```
-
- This is only available for singleton controllers.
-
- @property {Array} needs
- @default []
- */
- needs: [],
-
- init: function() {
- var needs = get(this, 'needs');
- var length = get(needs, 'length');
-
- if (length > 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;
- });
-enifed("ember-application/system/application",
- ["dag-map","container/container","ember-metal","ember-metal/property_get","ember-metal/property_set","ember-runtime/system/lazy_load","ember-runtime/system/namespace","ember-runtime/mixins/deferred","ember-application/system/resolver","ember-metal/platform","ember-metal/run_loop","ember-metal/utils","ember-runtime/controllers/controller","ember-metal/enumerable_utils","ember-runtime/controllers/object_controller","ember-runtime/controllers/array_controller","ember-handlebars/controls/select","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-extension-support/container_debug_adapter","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__, __dependency28__, __dependency29__, __exports__) {
- "use strict";
- /**
- @module ember
- @submodule ember-application
- */
- var DAG = __dependency1__["default"];
- var Container = __dependency2__["default"];
-
-
- var Ember = __dependency3__["default"];
- // Ember.FEATURES, Ember.deprecate, Ember.assert, Ember.libraries, LOG_VERSION, Namespace, BOOTED
- var get = __dependency4__.get;
- var set = __dependency5__.set;
- var runLoadHooks = __dependency6__.runLoadHooks;
- var Namespace = __dependency7__["default"];
- var DeferredMixin = __dependency8__["default"];
- var DefaultResolver = __dependency9__["default"];
- var create = __dependency10__.create;
- var run = __dependency11__["default"];
- var canInvoke = __dependency12__.canInvoke;
- var Controller = __dependency13__["default"];
- var EnumerableUtils = __dependency14__["default"];
- var ObjectController = __dependency15__["default"];
- var ArrayController = __dependency16__["default"];
- var SelectView = __dependency17__["default"];
- var EventDispatcher = __dependency18__["default"];
- var jQuery = __dependency19__["default"];
- var Route = __dependency20__["default"];
- var Router = __dependency21__["default"];
- var HashLocation = __dependency22__["default"];
- var HistoryLocation = __dependency23__["default"];
- var AutoLocation = __dependency24__["default"];
- var NoneLocation = __dependency25__["default"];
- var BucketCache = __dependency26__["default"];
-
- // this is technically incorrect (per @wycats)
- // it should work properly with:
- // `import ContainerDebugAdapter from 'ember-extension-support/container_debug_adapter';` but
- // es6-module-transpiler 0.4.0 eagerly grabs the module (which is undefined)
-
- var ContainerDebugAdapter = __dependency27__["default"];
-
- var K = __dependency28__.K;
- var EmberHandlebars = __dependency29__["default"];
-
- function props(obj) {
- var properties = [];
-
- for (var key in obj) {
- properties.push(key);
- }
-
- return properties;
- }
-
- /**
- 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
- var 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
- var 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
- var 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
- var 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.compile ? '' : '-runtime'), 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
- var App = Ember.Application.create();
-
- App.deferReadiness();
- // Ember.$ is a reference to the jQuery object/function
- Ember.$.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();
- var 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();
- var 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(<full_name or type>, <property name>, <full_name>)
- 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.
-
- **Note:** 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('second 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 initializersByName = get(this.constructor, 'initializers');
- var initializers = props(initializersByName);
- var container = this.__container__;
- var graph = new DAG();
- var namespace = this;
- var initializer;
-
- for (var i = 0; i < initializers.length; i++) {
- initializer = initializersByName[initializers[i]];
- 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: create(null),
-
- /**
- 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'));
- Ember.assert("An initializer cannot be registered without a name property", initializer.name !== undefined);
-
- 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.normalizeFullName = 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('view:select', SelectView);
-
- 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
-
- 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;
- });
-enifed("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","ember-metal/dictionary","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __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
- */
- var dictionary = __dependency8__["default"];
-
- __exports__["default"] = EmberObject.extend({
- /**
- This will be set to the Application instance when it is
- created.
-
- @property namespace
- */
- namespace: null,
-
- init: function() {
- this._parseNameCache = dictionary(null);
- },
- normalize: function(fullName) {
- var split = fullName.split(':', 2);
- var type = split[0];
- var 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);
- var resolveMethodName = parsedName.resolveMethodName;
- var 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) {
- return this._parseNameCache[fullName] || (
- this._parseNameCache[fullName] = this._parseName(fullName)
- );
- },
-
- _parseName: function(fullName) {
- var nameParts = fullName.split(':');
- var type = nameParts[0], fullNameWithoutType = nameParts[1];
- var name = fullNameWithoutType;
- var namespace = get(this, 'namespace');
- var 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));
- }
- });
- });
-enifed("ember-debug",
- ["ember-metal/core","ember-metal/error","ember-metal/logger","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
- "use strict";
- /*global __fail__*/
-
- var Ember = __dependency1__["default"];
- var EmberError = __dependency2__["default"];
- var Logger = __dependency3__["default"];
-
- /**
- Ember Debug
-
- @module ember
- @submodule ember-debug
- */
-
- /**
- @class Ember
- */
-
- /**
- Define an assertion that will throw an exception if the condition is not
- met. Ember build tools will remove any calls to `Ember.assert()` when
- doing a production build. Example:
-
- ```javascript
- // Test for truthiness
- Ember.assert('Must pass a valid object', obj);
-
- // Fail unconditionally
- Ember.assert('This code path should never be run');
- ```
-
- @method assert
- @param {String} desc A description of the assertion. This will become
- the text of the Error thrown if the assertion fails.
- @param {Boolean} test Must be truthy for the assertion to pass. If
- falsy, an exception will be thrown.
- */
- Ember.assert = function(desc, test) {
- if (!test) {
- throw new EmberError("Assertion Failed: " + desc);
- }
- };
-
-
- /**
- Display a warning with the provided message. Ember build tools will
- remove any calls to `Ember.warn()` when doing a production build.
-
- @method warn
- @param {String} message A warning to display.
- @param {Boolean} test An optional boolean. If falsy, the warning
- will be displayed.
- */
- Ember.warn = function(message, test) {
- if (!test) {
- Logger.warn("WARNING: "+message);
- if ('trace' in Logger) Logger.trace();
- }
- };
-
- /**
- Display a debug notice. Ember build tools will remove any calls to
- `Ember.debug()` when doing a production build.
-
- ```javascript
- Ember.debug('I\'m a debug notice!');
- ```
-
- @method debug
- @param {String} message A debug message to display.
- */
- Ember.debug = function(message) {
- Logger.debug("DEBUG: "+message);
- };
-
- /**
- Display a deprecation warning with the provided message and a stack trace
- (Chrome and Firefox only). Ember build tools will remove any calls to
- `Ember.deprecate()` when doing a production build.
-
- @method deprecate
- @param {String} message A description of the deprecation.
- @param {Boolean} test An optional boolean. If falsy, the deprecation
- will be displayed.
- */
- Ember.deprecate = function(message, test) {
- if (test) { return; }
-
- if (Ember.ENV.RAISE_ON_DEPRECATION) { throw new EmberError(message); }
-
- var error;
-
- // When using new Error, we can't do the arguments check for Chrome. Alternatives are welcome
- try { __fail__.fail(); } catch (e) { error = e; }
-
- if (Ember.LOG_STACKTRACE_ON_DEPRECATION && error.stack) {
- var stack;
- var stackStr = '';
-
- if (error['arguments']) {
- // Chrome
- stack = error.stack.replace(/^\s+at\s+/gm, '').
- replace(/^([^\(]+?)([\n$])/gm, '{anonymous}($1)$2').
- replace(/^Object.<anonymous>\s*\(([^\)]+)\)/gm, '{anonymous}($1)').split('\n');
- stack.shift();
- } else {
- // Firefox
- stack = error.stack.replace(/(?:\n@:0)?\s+$/m, '').
- replace(/^\(/gm, '{anonymous}(').split('\n');
- }
-
- stackStr = "\n " + stack.slice(2).join("\n ");
- message = message + stackStr;
- }
-
- Logger.warn("DEPRECATION: "+message);
- };
-
-
-
- /**
- Alias an old, deprecated method with its new counterpart.
-
- Display a deprecation warning with the provided message and a stack trace
- (Chrome and Firefox only) when the assigned method is called.
-
- Ember build tools will not remove calls to `Ember.deprecateFunc()`, though
- no warnings will be shown in production.
-
- ```javascript
- Ember.oldMethod = Ember.deprecateFunc('Please use the new, updated method', Ember.newMethod);
- ```
-
- @method deprecateFunc
- @param {String} message A description of the deprecation.
- @param {Function} func The new function called to replace its deprecated counterpart.
- @return {Function} a new function that wrapped the original function with a deprecation warning
- */
- Ember.deprecateFunc = function(message, func) {
- return function() {
- Ember.deprecate(message);
- return func.apply(this, arguments);
- };
- };
-
-
- /**
- Run a function meant for debugging. Ember build tools will remove any calls to
- `Ember.runInDebug()` when doing a production build.
-
- ```javascript
- Ember.runInDebug(function() {
- Ember.Handlebars.EachView.reopen({
- didInsertElement: function() {
- console.log('I\'m happy');
- }
- });
- });
- ```
-
- @method runInDebug
- @param {Function} func The function to be executed.
- @since 1.5.0
- */
- Ember.runInDebug = function(func) {
- func();
- };
-
- /**
- Will call `Ember.warn()` if ENABLE_ALL_FEATURES, ENABLE_OPTIONAL_FEATURES, or
- any specific FEATURES flag is truthy.
-
- This method is called automatically in debug canary builds.
-
- @private
- @method _warnIfUsingStrippedFeatureFlags
- @return {void}
- */
- function _warnIfUsingStrippedFeatureFlags(FEATURES, featuresWereStripped) {
- if (featuresWereStripped) {
- Ember.warn('Ember.ENV.ENABLE_ALL_FEATURES is only available in canary builds.', !Ember.ENV.ENABLE_ALL_FEATURES);
- Ember.warn('Ember.ENV.ENABLE_OPTIONAL_FEATURES is only available in canary builds.', !Ember.ENV.ENABLE_OPTIONAL_FEATURES);
-
- for (var key in FEATURES) {
- if (FEATURES.hasOwnProperty(key) && key !== 'isEnabled') {
- Ember.warn('FEATURE["' + key + '"] is set as enabled, but FEATURE flags are only available in canary builds.', !FEATURES[key]);
- }
- }
- }
- }
-
- __exports__._warnIfUsingStrippedFeatureFlags = _warnIfUsingStrippedFeatureFlags;if (!Ember.testing) {
- // Complain if they're using FEATURE flags in builds other than canary
- Ember.FEATURES['features-stripped-test'] = true;
- var featuresWereStripped = true;
-
-
- delete Ember.FEATURES['features-stripped-test'];
- _warnIfUsingStrippedFeatureFlags(Ember.ENV.FEATURES, featuresWereStripped);
-
- // Inform the developer about the Ember Inspector if not installed.
- var isFirefox = typeof InstallTrigger !== 'undefined';
- var isChrome = !!window.chrome && !window.opera;
-
- if (typeof window !== 'undefined' && (isFirefox || isChrome) && window.addEventListener) {
- window.addEventListener("load", function() {
- if (document.documentElement && document.documentElement.dataset && !document.documentElement.dataset.emberExtension) {
- var downloadURL;
-
- if(isChrome) {
- downloadURL = 'https://chrome.google.com/webstore/detail/ember-inspector/bmdblncegkenkacieihfhpjfppoconhi';
- } else if(isFirefox) {
- downloadURL = 'https://addons.mozilla.org/en-US/firefox/addon/ember-inspector/';
- }
-
- Ember.debug('For more advanced debugging, install the Ember Inspector from ' + downloadURL);
- }
- }, false);
- }
- }
- });
-enifed("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;
- });
-enifed("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();
- 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;
- }
- });
- });
-enifed("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();
- var self = this;
- var releaseMethods = emberA();
- var typesToSend;
-
- 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;
- var 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 records = this.getRecords(type);
- var typeToSend;
-
- 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 self = this;
- var containerDebugAdapter = this.get('containerDebugAdapter');
- var types;
-
- 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);
- var types = emberA();
- var 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 };
-
- 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(){};
- }
- });
- });
-enifed("ember-extension-support/initializers",
- [],
- function() {
- "use strict";
-
- });
-enifed("ember-handlebars-compiler",
- ["ember-metal/core","exports"],
- function(__dependency1__, __exports__) {
- /* global Handlebars:true */
-
- // Remove "use strict"; from transpiled module (in browser builds only) until
- // https://bugs.webkit.org/show_bug.cgi?id=138038 is fixed
- //
- // REMOVE_USE_STRICT: 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 eriuqer === 'function') {
- Handlebars = eriuqer('handlebars');
- }
-
- Ember.assert("Ember Handlebars requires Handlebars version 2.0. 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 2.0. " +
- "Please see more details at http://emberjs.com/blog/2014/10/16/handlebars-update.html.",
- Handlebars.COMPILER_REVISION === 6);
-
- /**
- 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 = Handlebars.create();
-
- /**
- 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 'calendar'}}
- ```
-
- 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+");";
- };
-
- /**
- 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|Object} value The template to precompile or an Handlebars AST
- @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(value, asObject) {
- var ast = Handlebars.parse(value);
-
- 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;
- });
-enifed("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/binding","ember-handlebars/helpers/if_unless","ember-handlebars/helpers/with","ember-handlebars/helpers/bind_attr","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__, __dependency27__, __dependency28__, __exports__) {
- "use strict";
- var EmberHandlebars = __dependency1__["default"];
- var Ember = __dependency2__["default"];
- // to add to globals
-
- var runLoadHooks = __dependency3__.runLoadHooks;
- var bootstrap = __dependency4__["default"];
-
- var makeBoundHelper = __dependency5__.makeBoundHelper;
- var registerBoundHelper = __dependency5__.registerBoundHelper;
- var helperMissingHelper = __dependency5__.helperMissingHelper;
- var blockHelperMissingHelper = __dependency5__.blockHelperMissingHelper;
- var handlebarsGet = __dependency5__.handlebarsGet;
-
-
- // side effect of extending StringUtils of htmlSafe
-
- var bind = __dependency7__.bind;
- var _triageMustacheHelper = __dependency7__._triageMustacheHelper;
- var resolveHelper = __dependency7__.resolveHelper;
- var bindHelper = __dependency7__.bindHelper;
-
- var ifHelper = __dependency8__.ifHelper;
- var boundIfHelper = __dependency8__.boundIfHelper;
- var unboundIfHelper = __dependency8__.unboundIfHelper;
- var unlessHelper = __dependency8__.unlessHelper;
-
- var withHelper = __dependency9__["default"];
-
- var bindAttrHelper = __dependency10__.bindAttrHelper;
- var bindAttrHelperDeprecated = __dependency10__.bindAttrHelperDeprecated;
- var bindClasses = __dependency10__.bindClasses;
-
- var collectionHelper = __dependency11__["default"];
- var ViewHelper = __dependency12__.ViewHelper;
- var viewHelper = __dependency12__.viewHelper;
- var unboundHelper = __dependency13__["default"];
- var logHelper = __dependency14__.logHelper;
- var debuggerHelper = __dependency14__.debuggerHelper;
- var EachView = __dependency15__.EachView;
- var eachHelper = __dependency15__.eachHelper;
- var templateHelper = __dependency16__["default"];
- var partialHelper = __dependency17__["default"];
- var yieldHelper = __dependency18__["default"];
- var locHelper = __dependency19__["default"];
-
-
- var Checkbox = __dependency20__["default"];
- var Select = __dependency21__.Select;
- var SelectOption = __dependency21__.SelectOption;
- var SelectOptgroup = __dependency21__.SelectOptgroup;
- var TextArea = __dependency22__["default"];
- var TextField = __dependency23__["default"];
- var TextSupport = __dependency24__["default"];
- var inputHelper = __dependency25__.inputHelper;
- var textareaHelper = __dependency25__.textareaHelper;
-
- var ComponentLookup = __dependency26__["default"];
- var _HandlebarsBoundView = __dependency27__._HandlebarsBoundView;
- var SimpleHandlebarsView = __dependency27__.SimpleHandlebarsView;
- var _MetamorphView = __dependency28__["default"];
- var _SimpleMetamorphView = __dependency28__._SimpleMetamorphView;
- var _Metamorph = __dependency28__._Metamorph;
-
-
- /**
- Ember Handlebars
-
- @module ember
- @submodule ember-handlebars
- @requires ember-views
- */
-
- // Ember.Handlebars.Globals
- EmberHandlebars.bootstrap = bootstrap;
- EmberHandlebars.makeBoundHelper = makeBoundHelper;
- EmberHandlebars.registerBoundHelper = registerBoundHelper;
- EmberHandlebars.resolveHelper = resolveHelper;
- EmberHandlebars.bind = bind;
- EmberHandlebars.bindClasses = bindClasses;
- EmberHandlebars.EachView = EachView;
- EmberHandlebars.ViewHelper = ViewHelper;
-
-
- // Ember Globals
- Ember.Handlebars = EmberHandlebars;
- EmberHandlebars.get = handlebarsGet;
- Ember.ComponentLookup = ComponentLookup;
- Ember._SimpleHandlebarsView = SimpleHandlebarsView;
- Ember._HandlebarsBoundView = _HandlebarsBoundView;
- Ember._SimpleMetamorphView = _SimpleMetamorphView;
- Ember._MetamorphView = _MetamorphView;
- Ember._Metamorph = _Metamorph;
- 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;
- });
-enifed("ember-handlebars/component_lookup",
- ["ember-runtime/system/object","exports"],
- function(__dependency1__, __exports__) {
- "use strict";
- var EmberObject = __dependency1__["default"];
-
- __exports__["default"] = EmberObject.extend({
- lookupFactory: function(name, container) {
-
- container = container || this.container;
-
- var fullName = 'component:' + name;
- var templateFullName = 'template:components/' + name;
- var 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;
- }
- }
- });
- });
-enifed("ember-handlebars/controls",
- ["ember-handlebars/controls/checkbox","ember-handlebars/controls/text_field","ember-handlebars/controls/text_area","ember-metal/core","ember-handlebars-compiler","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) {
- "use strict";
- var Checkbox = __dependency1__["default"];
- var TextField = __dependency2__["default"];
- var TextArea = __dependency3__["default"];
-
- var Ember = __dependency4__["default"];
- // Ember.assert
- // var emberAssert = Ember.assert;
-
- var EmberHandlebars = __dependency5__["default"];
-
- /**
- @module ember
- @submodule ember-handlebars-compiler
- */
-
- /**
-
- The `{{input}}` helper inserts an HTML `<input>` 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:
-
- <table>
- <tr><td>`readonly`</td><td>`required`</td><td>`autofocus`</td></tr>
- <tr><td>`value`</td><td>`placeholder`</td><td>`disabled`</td></tr>
- <tr><td>`size`</td><td>`tabindex`</td><td>`maxlength`</td></tr>
- <tr><td>`name`</td><td>`min`</td><td>`max`</td></tr>
- <tr><td>`pattern`</td><td>`accept`</td><td>`autocomplete`</td></tr>
- <tr><td>`autosave`</td><td>`formaction`</td><td>`formenctype`</td></tr>
- <tr><td>`formmethod`</td><td>`formnovalidate`</td><td>`formtarget`</td></tr>
- <tr><td>`height`</td><td>`inputmode`</td><td>`multiple`</td></tr>
- <tr><td>`step`</td><td>`width`</td><td>`form`</td></tr>
- <tr><td>`selectionDirection`</td><td>`spellcheck`</td><td>&nbsp;</td></tr>
- </table>
-
-
- 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
- <input type="text" value="http://www.facebook.com"/>
- ```
-
- ## Bound:
-
- ```javascript
- App.ApplicationController = Ember.Controller.extend({
- firstName: "Stanley",
- entryNotAllowed: true
- });
- ```
-
-
- ```handlebars
- {{input type="text" value=firstName disabled=entryNotAllowed size="50"}}
- ```
-
-
- ```html
- <input type="text" value="Stanley" disabled="disabled" size="50"/>
- ```
-
- ## Actions
-
- The helper can send multiple actions based on user events.
-
- The action property defines the action which is sent 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
- <input type="checkbox" name="isAdmin" />
- ```
-
- ## Bound:
-
- ```javascript
- App.ApplicationController = Ember.Controller.extend({
- isAdmin: true
- });
- ```
-
-
- ```handlebars
- {{input type="checkbox" checked=isAdmin }}
- ```
-
-
- ```html
- <input type="checkbox" checked="checked" />
- ```
-
- ## 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 view = options.data.view;
- var hash = options.hash;
- var types = options.hashTypes;
- var onEvent = hash.on;
- var inputType;
-
- if (types.type === 'ID') {
- inputType = view.getStream(hash.type).value();
- } else {
- inputType = hash.type;
- }
-
- 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 EmberHandlebars.helpers.view.call(this, Checkbox, options);
- } else {
- delete hash.on;
-
- hash.onEvent = onEvent || 'enter';
- return EmberHandlebars.helpers.view.call(this, TextField, options);
- }
- }
-
- __exports__.inputHelper = inputHelper;/**
- `{{textarea}}` inserts a new instance of `<textarea>` 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
- <textarea class="ember-text-area">
- Lots of static text that ISN'T bound
- </textarea>
- ```
-
- 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
- <textarea class="ember-text-area">
- Lots of text that IS bound
- </textarea>
- ```
-
- 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}}
-
- <div>
- {{outputWrittenWords}}
- </div>
- ```
-
- Would result in the following HTML:
-
- ```html
- <textarea class="ember-text-area">
- Lots of text that IS bound
- </textarea>
-
- <-- the following div will be updated in real time as you type -->
-
- <div>
- Lots of text that IS bound
- </div>
- ```
-
- 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
- <textarea id="ember1" class="ember-text-area">
- Lots of text that IS bound
- </textarea>
-
- <-- both updated in real time -->
-
- <textarea id="ember2" class="ember-text-area">
- Lots of text that IS bound
- </textarea>
- ```
-
- ## 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) {
- Ember.assert('You can only pass attributes to the `textarea` helper, not arguments', arguments.length < 2);
-
- return EmberHandlebars.helpers.view.call(this, TextArea, options);
- }
-
- __exports__.textareaHelper = textareaHelper;
- });
-enifed("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'));
- }
- });
- });
-enifed("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 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');
- var 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 `<option>` element within the
- `<select>` element are populated from the objects in the `Element.Select`'s
- `content` property. The underlying data object of the selected `<option>` is
- stored in the `Element.Select`'s `value` property.
-
- ## The Content Property (array of strings)
-
- The simplest version of an `Ember.Select` takes an array of strings as its
- `content` property. The string will be used as both the `value` property and
- the inner text of each `<option>` element inside the rendered `<select>`.
-
- Example:
-
- ```javascript
- App.ApplicationController = Ember.ObjectController.extend({
- names: ["Yehuda", "Tom"]
- });
- ```
-
- ```handlebars
- {{view "select" content=names}}
- ```
-
- Would result in the following HTML:
-
- ```html
- <select class="ember-select">
- <option value="Yehuda">Yehuda</option>
- <option value="Tom">Tom</option>
- </select>
- ```
-
- You can control which `<option>` is selected through the `Ember.Select`'s
- `value` property:
-
- ```javascript
- App.ApplicationController = Ember.ObjectController.extend({
- selectedName: 'Tom',
- names: ["Yehuda", "Tom"]
- });
- ```
-
- ```handlebars
- {{view "select" content=names value=selectedName}}
- ```
-
- Would result in the following HTML with the `<option>` for 'Tom' selected:
-
- ```html
- <select class="ember-select">
- <option value="Yehuda">Yehuda</option>
- <option value="Tom" selected="selected">Tom</option>
- </select>
- ```
-
- A user interacting with the rendered `<select>` to choose "Yehuda" would
- update the value of `selectedName` to "Yehuda".
-
- ## The Content Property (array of Objects)
-
- An `Ember.Select` can also take an array of JavaScript or Ember objects as
- its `content` property.
-
- When using objects you need to tell the `Ember.Select` which property should
- be accessed on each object to supply the `value` attribute of the `<option>`
- and which property should be used to supply the element text.
-
- The `optionValuePath` option is used to specify the path on each object to
- the desired property for the `value` attribute. The `optionLabelPath`
- specifies the path on each object to the desired property for the
- element's text. Both paths must reference each object itself as `content`:
-
- ```javascript
- App.ApplicationController = Ember.ObjectController.extend({
- programmers: [
- {firstName: "Yehuda", id: 1},
- {firstName: "Tom", id: 2}
- ]
- });
- ```
-
- ```handlebars
- {{view "select"
- content=programmers
- optionValuePath="content.id"
- optionLabelPath="content.firstName"}}
- ```
-
- Would result in the following HTML:
-
- ```html
- <select class="ember-select">
- <option value="1">Yehuda</option>
- <option value="2">Tom</option>
- </select>
- ```
-
- The `value` attribute of the selected `<option>` within an `Ember.Select`
- can be bound to a property on another object:
-
- ```javascript
- App.ApplicationController = Ember.ObjectController.extend({
- programmers: [
- {firstName: "Yehuda", id: 1},
- {firstName: "Tom", id: 2}
- ],
- currentProgrammer: {
- id: 2
- }
- });
- ```
-
- ```handlebars
- {{view "select"
- content=programmers
- optionValuePath="content.id"
- optionLabelPath="content.firstName"
- value=currentProgrammer.id}}
- ```
-
- Would result in the following HTML with a selected option:
-
- ```html
- <select class="ember-select">
- <option value="1">Yehuda</option>
- <option value="2" selected="selected">Tom</option>
- </select>
- ```
-
- Interacting with the rendered element by selecting the first option
- ('Yehuda') will update the `id` of `currentProgrammer`
- to match the `value` property of the newly selected `<option>`.
-
- Alternatively, you can control selection through the underlying objects
- used to render each object by binding the `selection` option. When the selected
- `<option>` is changed, the property path provided to `selection`
- will be updated to match the content object of the rendered `<option>`
- element:
-
- ```javascript
-
- var yehuda = {firstName: "Yehuda", id: 1, bff4eva: 'tom'}
- var tom = {firstName: "Tom", id: 2, bff4eva: 'yehuda'};
-
- App.ApplicationController = Ember.ObjectController.extend({
- selectedPerson: tom,
- programmers: [ yehuda, tom ]
- });
- ```
-
- ```handlebars
- {{view "select"
- content=programmers
- optionValuePath="content.id"
- optionLabelPath="content.firstName"
- selection=selectedPerson}}
- ```
-
- Would result in the following HTML with a selected option:
-
- ```html
- <select class="ember-select">
- <option value="1">Yehuda</option>
- <option value="2" selected="selected">Tom</option>
- </select>
- ```
-
- Interacting with the rendered element by selecting the first option
- ('Yehuda') will update the `selectedPerson` to match the object of
- the newly selected `<option>`. In this case it is the first object
- in the `programmers`
-
- ## Supplying a Prompt
-
- A `null` value for the `Ember.Select`'s `value` or `selection` property
- results in there being no `<option>` with a `selected` attribute:
-
- ```javascript
- App.ApplicationController = Ember.ObjectController.extend({
- selectedProgrammer: null,
- programmers: ["Yehuda", "Tom"]
- });
- ```
-
- ``` handlebars
- {{view "select"
- content=programmers
- value=selectedProgrammer
- }}
- ```
-
- Would result in the following HTML:
-
- ```html
- <select class="ember-select">
- <option value="Yehuda">Yehuda</option>
- <option value="Tom">Tom</option>
- </select>
- ```
-
- Although `selectedProgrammer` is `null` and no `<option>`
- has a `selected` attribute the rendered HTML will display the
- first item as though it were selected. You can supply a string
- value for the `Ember.Select` to display when there is no selection
- with the `prompt` option:
-
- ```javascript
- App.ApplicationController = Ember.ObjectController.extend({
- selectedProgrammer: null,
- programmers: [ "Yehuda", "Tom" ]
- });
- ```
-
- ```handlebars
- {{view "select"
- content=programmers
- value=selectedProgrammer
- prompt="Please select a name"
- }}
- ```
-
- Would result in the following HTML:
-
- ```html
- <select class="ember-select">
- <option>Please select a name</option>
- <option value="Yehuda">Yehuda</option>
- <option value="Tom">Tom</option>
- </select>
- ```
-
- @class Select
- @namespace Ember
- @extends Ember.View
- */
- var Select = View.extend({
- instrumentDisplay: 'Ember.Select',
-
- tagName: 'select',
- classNames: ['ember-select'],
- defaultTemplate: Ember.Handlebars.template({"1":function(depth0,helpers,partials,data) {
- var stack1, buffer = '';
- data.buffer.push("<option value=\"\">");
- stack1 = helpers._triageMustache.call(depth0, "view.prompt", {"name":"_triageMustache","hash":{},"hashTypes":{},"hashContexts":{},"types":["ID"],"contexts":[depth0],"data":data});
- if (stack1 != null) { data.buffer.push(stack1); }
- data.buffer.push("</option>");
- return buffer;
- },"3":function(depth0,helpers,partials,data) {
- var stack1;
- stack1 = helpers.each.call(depth0, "group", "in", "view.groupedContent", {"name":"each","hash":{},"hashTypes":{},"hashContexts":{},"fn":this.program(4, data),"inverse":this.noop,"types":["ID","ID","ID"],"contexts":[depth0,depth0,depth0],"data":data});
- if (stack1 != null) { data.buffer.push(stack1); }
- else { data.buffer.push(''); }
- },"4":function(depth0,helpers,partials,data) {
- var escapeExpression=this.escapeExpression;
- data.buffer.push(escapeExpression(helpers.view.call(depth0, "view.groupView", {"name":"view","hash":{
- 'label': ("group.label"),
- 'content': ("group.content")
- },"hashTypes":{'label': "ID",'content': "ID"},"hashContexts":{'label': depth0,'content': depth0},"types":["ID"],"contexts":[depth0],"data":data})));
- },"6":function(depth0,helpers,partials,data) {
- var stack1;
- stack1 = helpers.each.call(depth0, "item", "in", "view.content", {"name":"each","hash":{},"hashTypes":{},"hashContexts":{},"fn":this.program(7, data),"inverse":this.noop,"types":["ID","ID","ID"],"contexts":[depth0,depth0,depth0],"data":data});
- if (stack1 != null) { data.buffer.push(stack1); }
- else { data.buffer.push(''); }
- },"7":function(depth0,helpers,partials,data) {
- var escapeExpression=this.escapeExpression;
- data.buffer.push(escapeExpression(helpers.view.call(depth0, "view.optionView", {"name":"view","hash":{
- 'content': ("item")
- },"hashTypes":{'content': "ID"},"hashContexts":{'content': depth0},"types":["ID"],"contexts":[depth0],"data":data})));
- },"compiler":[6,">= 2.0.0-beta.1"],"main":function(depth0,helpers,partials,data) {
- var stack1, buffer = '';
- stack1 = helpers['if'].call(depth0, "view.prompt", {"name":"if","hash":{},"hashTypes":{},"hashContexts":{},"fn":this.program(1, data),"inverse":this.noop,"types":["ID"],"contexts":[depth0],"data":data});
- if (stack1 != null) { data.buffer.push(stack1); }
- stack1 = helpers['if'].call(depth0, "view.optionGroupPath", {"name":"if","hash":{},"hashTypes":{},"hashContexts":{},"fn":this.program(3, data),"inverse":this.program(6, data),"types":["ID"],"contexts":[depth0],"data":data});
- if (stack1 != null) { data.buffer.push(stack1); }
- return buffer;
- },"useData":true}),
- attributeBindings: ['multiple', 'disabled', 'tabindex', 'name', 'required', 'autofocus',
- 'form', 'size'],
-
- /**
- The `multiple` attribute of the select element. Indicates whether multiple
- options can be selected.
-
- @property multiple
- @type Boolean
- @default false
- */
- multiple: false,
-
- /**
- The `disabled` attribute of the select element. Indicates whether
- the element is disabled from interactions.
-
- @property disabled
- @type Boolean
- @default false
- */
- disabled: false,
-
- /**
- The `required` attribute of the select element. Indicates whether
- a selected option is required for form validation.
-
- @property required
- @type Boolean
- @default false
- @since 1.5.0
- */
- required: false,
-
- /**
- The list of options.
-
- If `optionLabelPath` and `optionValuePath` are not overridden, this should
- be a list of strings, which will serve simultaneously as labels and values.
-
- Otherwise, this should be a list of objects. For instance:
-
- ```javascript
- var App = Ember.Application.create();
- var App.MySelect = Ember.Select.extend({
- content: Ember.A([
- { id: 1, firstName: 'Yehuda' },
- { id: 2, firstName: 'Tom' }
- ]),
- optionLabelPath: 'content.firstName',
- optionValuePath: 'content.id'
- });
- ```
-
- @property content
- @type Array
- @default null
- */
- content: null,
-
- /**
- When `multiple` is `false`, the element of `content` that is currently
- selected, if any.
-
- When `multiple` is `true`, an array of such elements.
-
- @property selection
- @type Object or Array
- @default null
- */
- selection: null,
-
- /**
- In single selection mode (when `multiple` is `false`), value can be used to
- get the current selection's value or set the selection by it's value.
-
- It is not currently supported in multiple selection mode.
-
- @property value
- @type String
- @default null
- */
- value: computed(function(key, value) {
- if (arguments.length === 2) { return value; }
- var valuePath = get(this, 'optionValuePath').replace(/^content\.?/, '');
- return valuePath ? get(this, 'selection.' + valuePath) : get(this, 'selection');
- }).property('selection'),
-
- /**
- If given, a top-most dummy option will be rendered to serve as a user
- prompt.
-
- @property prompt
- @type String
- @default null
- */
- prompt: null,
-
- /**
- The path of the option labels. See [content](/api/classes/Ember.Select.html#property_content).
-
- @property optionLabelPath
- @type String
- @default 'content'
- */
- optionLabelPath: 'content',
-
- /**
- The path of the option values. See [content](/api/classes/Ember.Select.html#property_content).
-
- @property optionValuePath
- @type String
- @default 'content'
- */
- optionValuePath: 'content',
-
- /**
- The path of the option group.
- When this property is used, `content` should be sorted by `optionGroupPath`.
-
- @property optionGroupPath
- @type String
- @default null
- */
- optionGroupPath: null,
-
- /**
- The view class for optgroup.
-
- @property groupView
- @type Ember.View
- @default Ember.SelectOptgroup
- */
- groupView: SelectOptgroup,
-
- groupedContent: computed(function() {
- var groupPath = get(this, 'optionGroupPath');
- var groupedContent = emberA();
- var content = get(this, 'content') || [];
-
- forEach(content, function(item) {
- var label = get(item, groupPath);
-
- if (get(groupedContent, 'lastObject.label') !== label) {
- groupedContent.pushObject({
- label: label,
- content: emberA()
- });
- }
-
- get(groupedContent, 'lastObject.content').push(item);
- });
-
- return groupedContent;
- }).property('optionGroupPath', 'content.@each'),
-
- /**
- The view class for option.
-
- @property optionView
- @type Ember.View
- @default Ember.SelectOption
- */
- optionView: SelectOption,
-
- _change: function() {
- if (get(this, 'multiple')) {
- this._changeMultiple();
- } else {
- this._changeSingle();
- }
- },
-
- selectionDidChange: observer('selection.@each', function() {
- var selection = get(this, 'selection');
- if (get(this, 'multiple')) {
- if (!isArray(selection)) {
- set(this, 'selection', emberA([selection]));
- return;
- }
- this._selectionDidChangeMultiple();
- } else {
- this._selectionDidChangeSingle();
- }
- }),
-
- valueDidChange: observer('value', function() {
- var content = get(this, 'content');
- var value = get(this, 'value');
- var valuePath = get(this, 'optionValuePath').replace(/^content\.?/, '');
- var selectedValue = (valuePath ? get(this, 'selection.' + valuePath) : get(this, 'selection'));
- var selection;
-
- if (value !== selectedValue) {
- selection = content ? content.find(function(obj) {
- return value === (valuePath ? get(obj, valuePath) : obj);
- }) : null;
-
- this.set('selection', selection);
- }
- }),
-
-
- _triggerChange: function() {
- var selection = get(this, 'selection');
- var value = get(this, 'value');
-
- if (!isNone(selection)) { this.selectionDidChange(); }
- if (!isNone(value)) { this.valueDidChange(); }
-
- this._change();
- },
-
- _changeSingle: function() {
- var selectedIndex = this.$()[0].selectedIndex;
- var content = get(this, 'content');
- var prompt = get(this, 'prompt');
-
- if (!content || !get(content, 'length')) { return; }
- if (prompt && selectedIndex === 0) { set(this, 'selection', null); return; }
-
- if (prompt) { selectedIndex -= 1; }
- set(this, 'selection', content.objectAt(selectedIndex));
- },
-
-
- _changeMultiple: function() {
- var options = this.$('option:selected');
- var prompt = get(this, 'prompt');
- var offset = prompt ? 1 : 0;
- var content = get(this, 'content');
- var selection = get(this, 'selection');
-
- if (!content) { return; }
- if (options) {
- var selectedIndexes = options.map(function() {
- return this.index - offset;
- }).toArray();
- var newSelection = content.objectsAt(selectedIndexes);
-
- if (isArray(selection)) {
- replace(selection, 0, get(selection, 'length'), newSelection);
- } else {
- set(this, 'selection', newSelection);
- }
- }
- },
-
- _selectionDidChangeSingle: function() {
- var el = this.get('element');
- if (!el) { return; }
-
- var content = get(this, 'content');
- var selection = get(this, 'selection');
- var selectionIndex = content ? indexOf(content, selection) : -1;
- var prompt = get(this, 'prompt');
-
- if (prompt) { selectionIndex += 1; }
- if (el) { el.selectedIndex = selectionIndex; }
- },
-
- _selectionDidChangeMultiple: function() {
- var content = get(this, 'content');
- var selection = get(this, 'selection');
- var selectedIndexes = content ? indexesOf(content, selection) : [-1];
- var prompt = get(this, 'prompt');
- var offset = prompt ? 1 : 0;
- var options = this.$('option');
- var adjusted;
-
- if (options) {
- options.each(function() {
- adjusted = this.index > -1 ? this.index - offset : -1;
- this.selected = indexOf(selectedIndexes, adjusted) > -1;
- });
- }
- },
-
- init: function() {
- this._super();
- this.on("didInsertElement", this, this._triggerChange);
- this.on("change", this, this._change);
- }
- });
-
- __exports__["default"] = Select;
- __exports__.Select = Select;
- __exports__.SelectOption = SelectOption;
- __exports__.SelectOptgroup = SelectOptgroup;
- });
-enifed("ember-handlebars/controls/text_area",
- ["ember-metal/property_get","ember-views/views/component","ember-handlebars/controls/text_support","ember-metal/mixin","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
- "use strict";
-
- /**
- @module ember
- @submodule ember-handlebars
- */
- var get = __dependency1__.get;
- var Component = __dependency2__["default"];
- var TextSupport = __dependency3__["default"];
- var observer = __dependency4__.observer;
-
- /**
- The internal class used to create textarea element when the `{{textarea}}`
- helper is used.
-
- See [handlebars.helpers.textarea](/api/classes/Ember.Handlebars.helpers.html#method_textarea) for usage details.
-
- ## Layout and LayoutName properties
-
- Because HTML `textarea` elements do not contain inner HTML the `layout` and
- `layoutName` properties will not be applied. See [Ember.View](/api/classes/Ember.View.html)'s
- layout section for more information.
-
- @class TextArea
- @namespace Ember
- @extends Ember.Component
- @uses Ember.TextSupport
- */
- __exports__["default"] = Component.extend(TextSupport, {
- instrumentDisplay: '{{textarea}}',
-
- classNames: ['ember-text-area'],
-
- tagName: "textarea",
- attributeBindings: [
- 'rows',
- 'cols',
- 'name',
- 'selectionEnd',
- 'selectionStart',
- 'wrap',
- 'lang',
- 'dir'
- ],
- rows: null,
- cols: null,
-
- _updateElementValue: observer('value', function() {
- // We do this check so cursor position doesn't get affected in IE
- var value = get(this, 'value');
- var $el = this.$();
- if ($el && value !== $el.val()) {
- $el.val(value);
- }
- }),
-
- init: function() {
- this._super();
- this.on("didInsertElement", this, this._updateElementValue);
- }
- });
- });
-enifed("ember-handlebars/controls/text_field",
- ["ember-views/views/component","ember-handlebars/controls/text_support","exports"],
- function(__dependency1__, __dependency2__, __exports__) {
- "use strict";
- /**
- @module ember
- @submodule ember-handlebars
- */
- var Component = __dependency1__["default"];
- var TextSupport = __dependency2__["default"];
-
- /**
-
- The internal class used to create text inputs when the `{{input}}`
- helper is used with `type` of `text`.
-
- See [Handlebars.helpers.input](/api/classes/Ember.Handlebars.helpers.html#method_input) for usage details.
-
- ## Layout and LayoutName properties
-
- Because HTML `input` elements are self closing `layout` and `layoutName`
- properties will not be applied. See [Ember.View](/api/classes/Ember.View.html)'s
- layout section for more information.
-
- @class TextField
- @namespace Ember
- @extends Ember.Component
- @uses Ember.TextSupport
- */
- __exports__["default"] = Component.extend(TextSupport, {
- instrumentDisplay: '{{input type="text"}}',
-
- classNames: ['ember-text-field'],
- tagName: "input",
- attributeBindings: [
- 'accept',
- 'autocomplete',
- 'autosave',
- 'dir',
- 'formaction',
- 'formenctype',
- 'formmethod',
- 'formnovalidate',
- 'formtarget',
- 'height',
- 'inputmode',
- 'lang',
- 'list',
- 'max',
- 'min',
- 'multiple',
- 'name',
- 'pattern',
- 'size',
- 'step',
- 'type',
- 'value',
- 'width'
- ],
-
- /**
- The `value` attribute of the input element. As the user inputs text, this
- property is updated live.
-
- @property value
- @type String
- @default ""
- */
- value: "",
-
- /**
- The `type` attribute of the input element.
-
- @property type
- @type String
- @default "text"
- */
- type: "text",
-
- /**
- The `size` of the text field in characters.
-
- @property size
- @type String
- @default null
- */
- size: null,
-
- /**
- The `pattern` attribute of input element.
-
- @property pattern
- @type String
- @default null
- */
- pattern: null,
-
- /**
- The `min` attribute of input element used with `type="number"` or `type="range"`.
-
- @property min
- @type String
- @default null
- @since 1.4.0
- */
- min: null,
-
- /**
- The `max` attribute of input element used with `type="number"` or `type="range"`.
-
- @property max
- @type String
- @default null
- @since 1.4.0
- */
- max: null
- });
- });
-enifed("ember-handlebars/controls/text_support",
- ["ember-metal/property_get","ember-metal/property_set","ember-metal/mixin","ember-runtime/mixins/target_action_support","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
- "use strict";
- /**
- @module ember
- @submodule ember-handlebars
- */
-
- var get = __dependency1__.get;
- var set = __dependency2__.set;
- var Mixin = __dependency3__.Mixin;
- var TargetActionSupport = __dependency4__["default"];
-
- /**
- Shared mixin used by `Ember.TextField` and `Ember.TextArea`.
-
- @class TextSupport
- @namespace Ember
- @uses Ember.TargetActionSupport
- @extends Ember.Mixin
- @private
- */
- var TextSupport = Mixin.create(TargetActionSupport, {
- value: "",
-
- attributeBindings: [
- 'autocapitalize',
- 'autocorrect',
- 'autofocus',
- 'disabled',
- 'form',
- 'maxlength',
- 'placeholder',
- 'readonly',
- 'required',
- 'selectionDirection',
- 'spellcheck',
- 'tabindex',
- 'title'
- ],
- placeholder: null,
- disabled: false,
- maxlength: null,
-
- init: function() {
- this._super();
- this.on("paste", this, this._elementValueDidChange);
- this.on("cut", this, this._elementValueDidChange);
- this.on("input", this, this._elementValueDidChange);
- },
-
- /**
- The action to be sent when the user presses the return key.
-
- This is similar to the `{{action}}` helper, but is fired when
- the user presses the return key when editing a text field, and sends
- the value of the field as the context.
-
- @property action
- @type String
- @default null
- */
- action: null,
-
- /**
- The event that should send the action.
-
- Options are:
-
- * `enter`: the user pressed enter
- * `keyPress`: the user pressed a key
-
- @property onEvent
- @type String
- @default enter
- */
- onEvent: 'enter',
-
- /**
- Whether the `keyUp` event that triggers an `action` to be sent continues
- propagating to other views.
-
- By default, when the user presses the return key on their keyboard and
- the text field has an `action` set, the action will be sent to the view's
- controller and the key event will stop propagating.
-
- If you would like parent views to receive the `keyUp` event even after an
- action has been dispatched, set `bubbles` to true.
-
- @property bubbles
- @type Boolean
- @default false
- */
- bubbles: false,
-
- interpretKeyEvents: function(event) {
- var map = TextSupport.KEY_EVENTS;
- var method = map[event.keyCode];
-
- this._elementValueDidChange();
- if (method) { return this[method](event); }
- },
-
- _elementValueDidChange: function() {
- set(this, 'value', this.$().val());
- },
-
- /**
- Called when the user inserts a new line.
-
- Called by the `Ember.TextSupport` mixin on keyUp if keycode matches 13.
- Uses sendAction to send the `enter` action.
-
- @method insertNewline
- @param {Event} event
- */
- insertNewline: function(event) {
- sendAction('enter', this, event);
- sendAction('insert-newline', this, event);
- },
-
- /**
- Called when the user hits escape.
-
- Called by the `Ember.TextSupport` mixin on keyUp if keycode matches 27.
- Uses sendAction to send the `escape-press` action.
-
- @method cancel
- @param {Event} event
- */
- cancel: function(event) {
- sendAction('escape-press', this, event);
- },
-
- change: function(event) {
- this._elementValueDidChange(event);
- },
-
- /**
- Called when the text area is focused.
-
- Uses sendAction to send the `focus-in` action.
-
- @method focusIn
- @param {Event} event
- */
- focusIn: function(event) {
- sendAction('focus-in', this, event);
- },
-
- /**
- Called when the text area is blurred.
-
- Uses sendAction to send the `focus-out` action.
-
- @method focusOut
- @param {Event} event
- */
- focusOut: function(event) {
- this._elementValueDidChange(event);
- sendAction('focus-out', this, event);
- },
-
- /**
- Called when the user presses a key. Enabled by setting
- the `onEvent` property to `keyPress`.
-
- Uses sendAction to send the `key-press` action.
-
- @method keyPress
- @param {Event} event
- */
- keyPress: function(event) {
- sendAction('key-press', this, event);
- },
-
- /**
- Called when the browser triggers a `keyup` event on the element.
-
- Uses sendAction to send the `key-up` action passing the current value
- and event as parameters.
-
- @method keyUp
- @param {Event} event
- */
- keyUp: function(event) {
- this.interpretKeyEvents(event);
-
- this.sendAction('key-up', get(this, 'value'), event);
- },
-
- /**
- Called when the browser triggers a `keydown` event on the element.
-
- Uses sendAction to send the `key-down` action passing the current value
- and event as parameters. Note that generally in key-down the value is unchanged
- (as the key pressing has not completed yet).
-
- @method keyDown
- @param {Event} event
- */
- keyDown: function(event) {
- this.sendAction('key-down', get(this, 'value'), event);
- }
- });
-
- TextSupport.KEY_EVENTS = {
- 13: 'insertNewline',
- 27: 'cancel'
- };
-
- // In principle, this shouldn't be necessary, but the legacy
- // sendAction semantics for TextField are different from
- // the component semantics so this method normalizes them.
- function sendAction(eventName, view, event) {
- var action = get(view, eventName);
- var on = get(view, 'onEvent');
- var value = get(view, 'value');
-
- // back-compat support for keyPress as an event name even though
- // it's also a method name that consumes the event (and therefore
- // incompatible with sendAction semantics).
- if (on === eventName || (on === 'keyPress' && eventName === 'key-press')) {
- view.sendAction('action', value);
- }
-
- view.sendAction(eventName, value);
-
- if (action || on === eventName) {
- if(!get(view, 'bubbles')) {
- event.stopPropagation();
- }
- }
- }
-
- __exports__["default"] = TextSupport;
- });
-enifed("ember-handlebars/ext",
- ["ember-metal/core","ember-runtime/system/string","ember-handlebars-compiler","ember-metal/property_get","ember-metal/error","ember-metal/mixin","ember-views/views/view","ember-metal/path_cache","ember-metal/streams/stream","ember-metal/streams/read","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __exports__) {
- "use strict";
- var Ember = __dependency1__["default"];
- // Ember.FEATURES, Ember.assert, Ember.Handlebars, Ember.lookup
- // var emberAssert = Ember.assert;
-
- var fmt = __dependency2__.fmt;
-
- var EmberHandlebars = __dependency3__["default"];
-
- var get = __dependency4__.get;
- var EmberError = __dependency5__["default"];
- var IS_BINDING = __dependency6__.IS_BINDING;
-
- var View = __dependency7__["default"];
- var detectIsGlobal = __dependency8__.isGlobal;
-
- // late bound via requireModule because of circular dependencies.
- var resolveHelper, SimpleHandlebarsView;
-
- var Stream = __dependency9__["default"];
- var readArray = __dependency10__.readArray;
- var readHash = __dependency10__.readHash;
-
- var slice = [].slice;
-
- /**
- Lookup both on root and on window. If the path starts with
- a keyword, the corresponding object will be looked up in the
- template's data hash and used to resolve the path.
-
- @method get
- @for Ember.Handlebars
- @param {Object} root The object to look up the property on
- @param {String} path The path to be lookedup
- @param {Object} options The template's option hash
- @deprecated
- */
- function handlebarsGet(root, path, options) {
- Ember.deprecate('Usage of Ember.Handlebars.get is deprecated, use a Component or Ember.Handlebars.makeBoundHelper instead.');
-
- return options.data.view.getStream(path).value();
- }
-
- /**
- handlebarsGetView resolves a view based on strings passed into a template.
- For example:
-
- ```handlebars
- {{view "some-view"}}
- {{view view.someView}}
- {{view App.SomeView}} {{! deprecated }}
- ```
-
- A value is first checked to be a string- non-strings are presumed to be
- an object and returned. This handles the "access a view on a context"
- case (line 2 in the above examples).
-
- Next a string is normalized, then called on the context with `get`. If
- there is still no value, a GlobalPath will be fetched from the global
- context (raising a deprecation) and a localPath will be passed to the
- container to be looked up.
-
- @private
- @for Ember.Handlebars
- @param {Object} context The context of the template being rendered
- @param {String} path The path to be lookedup
- @param {Object} container The container
- @param {Object} data The template's data hash
- */
- function handlebarsGetView(context, path, container, data) {
- var viewClass;
- if ('string' === typeof path) {
- if (!data) {
- throw new Error("handlebarsGetView: must pass data");
- }
-
- // Only lookup view class on context if there is a context. If not,
- // the global lookup path on get may kick in.
- var lazyValue = data.view.getStream(path);
- viewClass = lazyValue.value();
- var isGlobal = detectIsGlobal(path);
-
- if (!viewClass && !isGlobal) {
- Ember.assert("View requires a container to resolve views not passed in through the context", !!container);
- viewClass = container.lookupFactory('view:'+path);
- }
- if (!viewClass && isGlobal) {
- var globalViewClass = get(path);
- Ember.deprecate('Resolved the view "'+path+'" on the global context. Pass a view name to be looked' +
- ' up on the container instead, such as {{view "select"}}.' +
- ' http://emberjs.com/guides/deprecations#toc_global-lookup-of-views', !globalViewClass);
- if (globalViewClass) {
- viewClass = globalViewClass;
- }
- }
- } else {
- viewClass = path;
- }
-
- // Sometimes a view's value is yet another path
- if ('string' === typeof viewClass && data && data.view) {
- viewClass = handlebarsGetView(data.view, viewClass, container, data);
- }
-
- Ember.assert(
- fmt(path+" must be a subclass of Ember.View, not %@", [viewClass]),
- View.detect(viewClass)
- );
-
- return viewClass;
- }
-
- function stringifyValue(value, shouldEscape) {
- if (value === null || value === undefined) {
- value = "";
- } else if (!(value instanceof Handlebars.SafeString)) {
- value = String(value);
- }
-
- if (shouldEscape) {
- value = Handlebars.Utils.escapeExpression(value);
- }
-
- return value;
- }
-
- __exports__.stringifyValue = stringifyValue;/**
- Registers a helper in Handlebars that will be called if no property with the
- given name can be found on the current context object, and no helper with
- that name is registered.
-
- This throws an exception with a more helpful error message so the user can
- track down where the problem is happening.
-
- @private
- @method helperMissing
- @for Ember.Handlebars.helpers
- @param {String} path
- @param {Hash} options
- */
- function helperMissingHelper(path) {
- if (!resolveHelper) {
- resolveHelper = requireModule('ember-handlebars/helpers/binding')['resolveHelper'];
- } // ES6TODO: stupid circular dep
-
- var error, fmtError, view = "";
-
- var options = arguments[arguments.length - 1];
-
- var helper = resolveHelper(options.data.view.container, options.name);
-
- if (helper) {
- return helper.apply(this, arguments);
- }
-
- if (options.data) {
- view = options.data.view;
- }
-
- if (options.name.match(/-/)) {
- error = "%@ Handlebars error: Could not find component or helper named '%@'";
- fmtError = fmt(error, [view, options.name]);
- } else {
- error = "%@ Handlebars error: Could not find property '%@' on object %@.";
- fmtError = fmt(error, [view, options.name, this]);
- }
-
- throw new EmberError(fmtError);
- }
-
- __exports__.helperMissingHelper = helperMissingHelper;/**
- @private
- @method blockHelperMissingHelper
- @for Ember.Handlebars.helpers
- */
- function blockHelperMissingHelper() {
- return;
- }
-
- __exports__.blockHelperMissingHelper = blockHelperMissingHelper;/**
- Register a bound handlebars helper. Bound helpers behave similarly to regular
- handlebars helpers, with the added ability to re-render when the underlying data
- changes.
-
- ## Simple example
-
- ```javascript
- Ember.Handlebars.registerBoundHelper('capitalize', function(value) {
- return Ember.String.capitalize(value);
- });
- ```
-
- 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.
-
- ## Example with options
-
- Like normal handlebars helpers, bound helpers have access to the options
- passed into the helper call.
-
- ```javascript
- Ember.Handlebars.registerBoundHelper('repeat', function(value, options) {
- var count = options.hash.count;
- var a = [];
- while(a.length < count) {
- a.push(value);
- }
- return a.join('');
- });
- ```
-
- This helper could be used in a template as follows:
-
- ```handlebars
- {{repeat text count=3}}
- ```
-
- ## Example with bound options
-
- Bound hash options are also supported. Example:
-
- ```handlebars
- {{repeat text count=numRepeats}}
- ```
-
- In this example, count will be bound to the value of
- the `numRepeats` property on the context. If that property
- changes, the helper will be re-rendered.
-
- ## Example with extra dependencies
-
- The `Ember.Handlebars.registerBoundHelper` method takes a variable length
- third parameter which indicates extra dependencies on the passed in value.
- This allows the handlebars helper to update when these dependencies change.
-
- ```javascript
- Ember.Handlebars.registerBoundHelper('capitalizeName', function(value) {
- return value.get('name').toUpperCase();
- }, 'name');
- ```
-
- ## Example with multiple bound properties
-
- `Ember.Handlebars.registerBoundHelper` supports binding to
- multiple properties, e.g.:
-
- ```javascript
- Ember.Handlebars.registerBoundHelper('concatenate', function() {
- var values = Array.prototype.slice.call(arguments, 0, -1);
- return values.join('||');
- });
- ```
-
- Which allows for template syntax such as `{{concatenate prop1 prop2}}` or
- `{{concatenate prop1 prop2 prop3}}`. If any of the properties change,
- the helper will re-render. Note that dependency keys cannot be
- using in conjunction with multi-property helpers, since it is ambiguous
- which property the dependent keys would belong to.
-
- ## Use with unbound helper
-
- The `{{unbound}}` helper can be used with bound helper invocations
- to render them in their unbound form, e.g.
-
- ```handlebars
- {{unbound capitalize name}}
- ```
-
- In this example, if the name property changes, the helper
- will not re-render.
-
- ## Use with blocks not supported
-
- Bound helpers do not support use with Handlebars blocks or
- the addition of child views of any kind.
-
- @method registerBoundHelper
- @for Ember.Handlebars
- @param {String} name
- @param {Function} function
- @param {String} dependentKeys*
- */
- function registerBoundHelper(name, fn) {
- var boundHelperArgs = slice.call(arguments, 1);
- var boundFn = makeBoundHelper.apply(this, boundHelperArgs);
- EmberHandlebars.registerHelper(name, boundFn);
- }
-
- __exports__.registerBoundHelper = registerBoundHelper;/**
- A helper function used by `registerBoundHelper`. Takes the
- provided Handlebars helper function fn and returns it in wrapped
- bound helper form.
-
- The main use case for using this outside of `registerBoundHelper`
- is for registering helpers on the container:
-
- ```js
- var boundHelperFn = Ember.Handlebars.makeBoundHelper(function(word) {
- return word.toUpperCase();
- });
-
- container.register('helper:my-bound-helper', boundHelperFn);
- ```
-
- In the above example, if the helper function hadn't been wrapped in
- `makeBoundHelper`, the registered helper would be unbound.
-
- @method makeBoundHelper
- @for Ember.Handlebars
- @param {Function} function
- @param {String} dependentKeys*
- @since 1.2.0
- */
- function makeBoundHelper(fn) {
- if (!SimpleHandlebarsView) {
- SimpleHandlebarsView = requireModule('ember-handlebars/views/handlebars_bound_view')['SimpleHandlebarsView'];
- } // ES6TODO: stupid circular dep
-
- var dependentKeys = [];
- for (var i = 1; i < arguments.length; i++) {
- dependentKeys.push(arguments[i]);
- }
-
- function helper() {
- var numParams = arguments.length - 1;
- var options = arguments[numParams];
- var data = options.data;
- var view = data.view;
- var types = options.types;
- var hash = options.hash;
- var hashTypes = options.hashTypes;
- var context = this;
-
- Ember.assert("registerBoundHelper-generated helpers do not support use with Handlebars blocks.", !options.fn);
-
- var properties = new Array(numParams);
- var params = new Array(numParams);
-
- for (var i = 0; i < numParams; i++) {
- properties[i] = arguments[i];
- if (types[i] === 'ID') {
- params[i] = view.getStream(arguments[i]);
- } else {
- params[i] = arguments[i];
- }
- }
-
- for (var prop in hash) {
- if (IS_BINDING.test(prop)) {
- hash[prop.slice(0, -7)] = view.getStream(hash[prop]);
- hash[prop] = undefined;
- } else if (hashTypes[prop] === 'ID') {
- hash[prop] = view.getStream(hash[prop]);
- }
- }
-
- var valueFn = function() {
- var args = readArray(params);
- args.push({
- hash: readHash(hash),
- data: { properties: properties }
- });
- return fn.apply(context, args);
- };
-
- if (data.isUnbound) {
- return valueFn();
- } else {
- var lazyValue = new Stream(valueFn);
- var bindView = new SimpleHandlebarsView(lazyValue, !options.hash.unescaped);
- view.appendChild(bindView);
-
- var scheduledRerender = view._wrapAsScheduled(bindView.rerender);
- lazyValue.subscribe(scheduledRerender, bindView);
-
- var param;
-
- for (i = 0; i < numParams; i++) {
- param = params[i];
- if (param && param.isStream) {
- param.subscribe(lazyValue.notify, lazyValue);
- }
- }
-
- for (prop in hash) {
- param = hash[prop];
- if (param && param.isStream) {
- param.subscribe(lazyValue.notify, lazyValue);
- }
- }
-
- if (numParams > 0) {
- var firstParam = params[0];
- // Only bother with subscriptions if the first argument
- // is a stream itself, and not a primitive.
- if (firstParam && firstParam.isStream) {
- var onDependentKeyNotify = function onDependentKeyNotify(stream) {
- stream.value();
- lazyValue.notify();
- };
- for (i = 0; i < dependentKeys.length; i++) {
- var childParam = firstParam.get(dependentKeys[i]);
- childParam.value();
- childParam.subscribe(onDependentKeyNotify);
- }
- }
- }
- }
- }
-
- return helper;
- }
-
- __exports__.makeBoundHelper = makeBoundHelper;
- __exports__.handlebarsGetView = handlebarsGetView;
- __exports__.handlebarsGet = handlebarsGet;
- });
-enifed("ember-handlebars/helpers/bind_attr",
- ["ember-metal/core","ember-handlebars-compiler","ember-metal/utils","ember-runtime/system/string","ember-metal/array","ember-views/views/view","ember-metal/keys","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __exports__) {
- "use strict";
- /**
- @module ember
- @submodule ember-handlebars
- */
-
- var Ember = __dependency1__["default"];
- // Ember.assert
- var EmberHandlebars = __dependency2__["default"];
-
- var uuid = __dependency3__.uuid;
- var fmt = __dependency4__.fmt;
- var typeOf = __dependency3__.typeOf;
- var forEach = __dependency5__.forEach;
- var View = __dependency6__["default"];
- var keys = __dependency7__["default"];
-
- var helpers = EmberHandlebars.helpers;
- var SafeString = EmberHandlebars.SafeString;
-
- /**
- `bind-attr` allows you to create a binding between DOM element attributes and
- Ember objects. For example:
-
- ```handlebars
- <img {{bind-attr src="imageUrl" alt="imageTitle"}}>
- ```
-
- The above handlebars template will fill the `<img>`'s `src` attribute with
- the value of the property referenced with `"imageUrl"` and its `alt`
- attribute with the value of the property referenced with `"imageTitle"`.
-
- If the rendering context of this template is the following object:
-
- ```javascript
- {
- imageUrl: 'http://lolcats.info/haz-a-funny',
- imageTitle: 'A humorous image of a cat'
- }
- ```
-
- The resulting HTML output will be:
-
- ```html
- <img src="http://lolcats.info/haz-a-funny" alt="A humorous image of a cat">
- ```
-
- `bind-attr` cannot redeclare existing DOM element attributes. The use of `src`
- in the following `bind-attr` example will be ignored and the hard coded value
- of `src="/failwhale.gif"` will take precedence:
-
- ```handlebars
- <img src="/failwhale.gif" {{bind-attr src="imageUrl" alt="imageTitle"}}>
- ```
-
- ### `bind-attr` and the `class` attribute
-
- `bind-attr` supports a special syntax for handling a number of cases unique
- to the `class` DOM element attribute. The `class` attribute combines
- multiple discrete values into a single attribute as a space-delimited
- list of strings. Each string can be:
-
- * a string return value of an object's property.
- * a boolean return value of an object's property
- * a hard-coded value
-
- A string return value works identically to other uses of `bind-attr`. The
- return value of the property will become the value of the attribute. For
- example, the following view and template:
-
- ```javascript
- AView = View.extend({
- someProperty: function() {
- return "aValue";
- }.property()
- })
- ```
-
- ```handlebars
- <img {{bind-attr class="view.someProperty}}>
- ```
-
- Result in the following rendered output:
-
- ```html
- <img class="aValue">
- ```
-
- A boolean return value will insert a specified class name if the property
- returns `true` and remove the class name if the property returns `false`.
-
- A class name is provided via the syntax
- `somePropertyName:class-name-if-true`.
-
- ```javascript
- AView = View.extend({
- someBool: true
- })
- ```
-
- ```handlebars
- <img {{bind-attr class="view.someBool:class-name-if-true"}}>
- ```
-
- Result in the following rendered output:
-
- ```html
- <img class="class-name-if-true">
- ```
-
- An additional section of the binding can be provided if you want to
- replace the existing class instead of removing it when the boolean
- value changes:
-
- ```handlebars
- <img {{bind-attr class="view.someBool:class-name-if-true:class-name-if-false"}}>
- ```
-
- A hard-coded value can be used by prepending `:` to the desired
- class name: `:class-name-to-always-apply`.
-
- ```handlebars
- <img {{bind-attr class=":class-name-to-always-apply"}}>
- ```
-
- Results in the following rendered output:
-
- ```html
- <img class="class-name-to-always-apply">
- ```
-
- All three strategies - string return value, boolean return value, and
- hard-coded value – can be combined in a single declaration:
-
- ```handlebars
- <img {{bind-attr class=":class-name-to-always-apply view.someBool:class-name-if-true view.someProperty"}}>
- ```
-
- @method bind-attr
- @for Ember.Handlebars.helpers
- @param {Hash} options
- @return {String} HTML string
- */
- function bindAttrHelper(options) {
- var attrs = options.hash;
-
- Ember.assert("You must specify at least one hash argument to bind-attr", !!keys(attrs).length);
-
- var view = options.data.view;
- var ret = [];
-
- // we relied on the behavior of calling without
- // context to mean this === window, but when running
- // "use strict", it's possible for this to === undefined;
- var ctx = this || window;
-
- // Generate a unique id for this element. This will be added as a
- // data attribute to the element so it can be looked up when
- // the bound property changes.
- var dataId = uuid();
-
- // Handle classes differently, as we can bind multiple classes
- var classBindings = attrs['class'];
- if (classBindings != null) {
- var classResults = bindClasses(ctx, classBindings, view, dataId, options);
-
- ret.push('class="' + Handlebars.Utils.escapeExpression(classResults.join(' ')) + '"');
- delete attrs['class'];
- }
-
- var attrKeys = keys(attrs);
-
- // For each attribute passed, create an observer and emit the
- // current value of the property as an attribute.
- forEach.call(attrKeys, function(attr) {
- var path = attrs[attr];
-
- Ember.assert(fmt("You must provide an expression as the value of bound attribute." +
- " You specified: %@=%@", [attr, path]), typeof path === 'string');
-
- var lazyValue = view.getStream(path);
- var value = lazyValue.value();
- var type = typeOf(value);
-
- Ember.assert(fmt("Attributes must be numbers, strings or booleans, not %@", [value]),
- value === null || value === undefined || type === 'number' || type === 'string' || type === 'boolean');
-
- lazyValue.subscribe(view._wrapAsScheduled(function applyAttributeBindings() {
- var result = lazyValue.value();
-
- Ember.assert(fmt("Attributes must be numbers, strings or booleans, not %@", [result]),
- result === null || result === undefined || typeof result === 'number' ||
- typeof result === 'string' || typeof result === 'boolean');
-
- var elem = view.$("[data-bindattr-" + dataId + "='" + dataId + "']");
-
- Ember.assert("An attribute binding was triggered when the element was not in the DOM", elem && elem.length !== 0);
-
- View.applyAttributeBindings(elem, attr, result);
- }));
-
- // if this changes, also change the logic in ember-views/lib/views/view.js
- if ((type === 'string' || (type === 'number' && !isNaN(value)))) {
- ret.push(attr + '="' + Handlebars.Utils.escapeExpression(value) + '"');
- } else if (value && type === 'boolean') {
- // The developer controls the attr name, so it should always be safe
- ret.push(attr + '="' + attr + '"');
- }
- }, this);
-
- // Add the unique identifier
- // NOTE: We use all lower-case since Firefox has problems with mixed case in SVG
- ret.push('data-bindattr-' + dataId + '="' + dataId + '"');
- return new SafeString(ret.join(' '));
- }
-
- /**
- See `bind-attr`
-
- @method bindAttr
- @for Ember.Handlebars.helpers
- @deprecated
- @param {Function} context
- @param {Hash} options
- @return {String} HTML string
- */
- function bindAttrHelperDeprecated() {
- Ember.deprecate("The 'bindAttr' view helper is deprecated in favor of 'bind-attr'");
-
- return helpers['bind-attr'].apply(this, arguments);
- }
-
- /**
- Helper that, given a space-separated string of property paths and a context,
- returns an array of class names. Calling this method also has the side
- effect of setting up observers at those property paths, such that if they
- change, the correct class name will be reapplied to the DOM element.
-
- For example, if you pass the string "fooBar", it will first look up the
- "fooBar" value of the context. If that value is true, it will add the
- "foo-bar" class to the current element (i.e., the dasherized form of
- "fooBar"). If the value is a string, it will add that string as the class.
- Otherwise, it will not add any new class name.
-
- @private
- @method bindClasses
- @for Ember.Handlebars
- @param {Ember.Object} context The context from which to lookup properties
- @param {String} classBindings A string, space-separated, of class bindings
- to use
- @param {View} view The view in which observers should look for the
- element to update
- @param {Srting} bindAttrId Optional bindAttr id used to lookup elements
- @return {Array} An array of class names to add
- */
- function bindClasses(context, classBindings, view, bindAttrId, options) {
- var ret = [];
- var newClass, value, elem;
-
- // For each property passed, loop through and setup
- // an observer.
- forEach.call(classBindings.split(' '), function(binding) {
-
- // Variable in which the old class value is saved. The observer function
- // closes over this variable, so it knows which string to remove when
- // the property changes.
- var oldClass;
- var parsedPath = View._parsePropertyPath(binding);
- var path = parsedPath.path;
- var initialValue;
-
- if (path === '') {
- initialValue = true;
- } else {
- var lazyValue = view.getStream(path);
- initialValue = lazyValue.value();
-
- // Set up an observer on the context. If the property changes, toggle the
- // class name.
- lazyValue.subscribe(view._wrapAsScheduled(function applyClassNameBindings() {
- // Get the current value of the property
- var value = lazyValue.value();
- newClass = classStringForParsedPath(parsedPath, value);
- elem = bindAttrId ? view.$("[data-bindattr-" + bindAttrId + "='" + bindAttrId + "']") : view.$();
-
- Ember.assert("A class name binding was triggered when the element was not in the DOM", elem && elem.length !== 0);
-
- // If we had previously added a class to the element, remove it.
- if (oldClass) {
- elem.removeClass(oldClass);
- }
-
- // If necessary, add a new class. Make sure we keep track of it so
- // it can be removed in the future.
- if (newClass) {
- elem.addClass(newClass);
- oldClass = newClass;
- } else {
- oldClass = null;
- }
- }));
- }
-
- // We've already setup the observer; now we just need to figure out the
- // correct behavior right now on the first pass through.
- value = classStringForParsedPath(parsedPath, initialValue);
-
- if (value) {
- ret.push(value);
-
- // Make sure we save the current value so that it can be removed if the
- // observer fires.
- oldClass = value;
- }
- });
-
- return ret;
- }
-
- function classStringForParsedPath(parsedPath, value) {
- return View._classStringForValue(parsedPath.path, value, parsedPath.className, parsedPath.falsyClassName);
- }
-
- __exports__["default"] = bindAttrHelper;
-
- __exports__.bindAttrHelper = bindAttrHelper;
- __exports__.bindAttrHelperDeprecated = bindAttrHelperDeprecated;
- __exports__.bindClasses = bindClasses;
- });
-enifed("ember-handlebars/helpers/binding",
- ["ember-metal/core","ember-handlebars-compiler","ember-metal/is_none","ember-metal/run_loop","ember-metal/cache","ember-metal/streams/simple","ember-handlebars/views/handlebars_bound_view","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __exports__) {
- "use strict";
- /**
- @module ember
- @submodule ember-handlebars
- */
-
- var Ember = __dependency1__["default"];
- // Ember.assert
- var EmberHandlebars = __dependency2__["default"];
-
- var isNone = __dependency3__["default"];
- var run = __dependency4__["default"];
- var Cache = __dependency5__["default"];
- var SimpleStream = __dependency6__["default"];
-
- var _HandlebarsBoundView = __dependency7__._HandlebarsBoundView;
- var SimpleHandlebarsView = __dependency7__.SimpleHandlebarsView;
-
- var helpers = EmberHandlebars.helpers;
-
- function exists(value) {
- return !isNone(value);
- }
-
- // Binds a property into the DOM. This will create a hook in DOM that the
- // KVO system will look for and update if the property changes.
- function bind(property, options, preserveContext, shouldDisplay, valueNormalizer, childProperties, _viewClass) {
- var data = options.data;
- var view = data.view;
-
- // we relied on the behavior of calling without
- // context to mean this === window, but when running
- // "use strict", it's possible for this to === undefined;
- var currentContext = this || window;
-
- var valueStream = view.getStream(property);
- var lazyValue;
-
- if (childProperties) {
- lazyValue = new SimpleStream(valueStream);
-
- var subscriber = function(childStream) {
- childStream.value();
- lazyValue.notify();
- };
-
- for (var i = 0; i < childProperties.length; i++) {
- var childStream = valueStream.get(childProperties[i]);
- childStream.value();
- childStream.subscribe(subscriber);
- }
- } else {
- lazyValue = valueStream;
- }
-
- // Set up observers for observable objects
- var viewClass = _viewClass || _HandlebarsBoundView;
- var viewOptions = {
- preserveContext: preserveContext,
- shouldDisplayFunc: shouldDisplay,
- valueNormalizerFunc: valueNormalizer,
- displayTemplate: options.fn,
- inverseTemplate: options.inverse,
- lazyValue: lazyValue,
- previousContext: currentContext,
- isEscaped: !options.hash.unescaped,
- templateData: options.data,
- templateHash: options.hash,
- helperName: options.helperName
- };
-
- if (options.keywords) {
- viewOptions._keywords = options.keywords;
- }
-
- // Create the view that will wrap the output of this template/property
- // and add it to the nearest view's childViews array.
- // See the documentation of Ember._HandlebarsBoundView for more.
- var bindView = view.createChildView(viewClass, viewOptions);
-
- view.appendChild(bindView);
-
- lazyValue.subscribe(view._wrapAsScheduled(function() {
- run.scheduleOnce('render', bindView, 'rerenderIfNeeded');
- }));
- }
-
- function simpleBind(currentContext, lazyValue, options) {
- var data = options.data;
- var view = data.view;
-
- var bindView = new SimpleHandlebarsView(
- lazyValue, !options.hash.unescaped
- );
-
- bindView._parentView = view;
- view.appendChild(bindView);
-
- lazyValue.subscribe(view._wrapAsScheduled(function() {
- run.scheduleOnce('render', bindView, 'rerender');
- }));
- }
-
- /**
- '_triageMustache' is used internally select between a binding, helper, or component for
- the given context. Until this point, it would be hard to determine if the
- mustache is a property reference or a regular helper reference. This triage
- helper resolves that.
-
- This would not be typically invoked by directly.
-
- @private
- @method _triageMustache
- @for Ember.Handlebars.helpers
- @param {String} property Property/helperID to triage
- @param {Object} options hash of template/rendering options
- @return {String} HTML string
- */
- function _triageMustacheHelper(property, options) {
- Ember.assert("You cannot pass more than one argument to the _triageMustache helper", arguments.length <= 2);
-
- var helper = EmberHandlebars.resolveHelper(options.data.view.container, property);
- if (helper) {
- return helper.call(this, options);
- }
-
- return helpers.bind.call(this, property, options);
- }
-
- var ISNT_HELPER_CACHE = new Cache(1000, function(key) {
- return key.indexOf('-') === -1;
- });
- __exports__.ISNT_HELPER_CACHE = ISNT_HELPER_CACHE;
- /**
- Used to lookup/resolve handlebars helpers. The lookup order is:
-
- * Look for a registered helper
- * If a dash exists in the name:
- * Look for a helper registed in the container
- * Use Ember.ComponentLookup to find an Ember.Component that resolves
- to the given name
-
- @private
- @method resolveHelper
- @param {Container} container
- @param {String} name the name of the helper to lookup
- @return {Handlebars Helper}
- */
- function resolveHelper(container, name) {
- if (helpers[name]) {
- return helpers[name];
- }
-
- if (!container || ISNT_HELPER_CACHE.get(name)) {
- return;
- }
-
- var helper = container.lookup('helper:' + name);
- if (!helper) {
- var componentLookup = container.lookup('component-lookup:main');
- Ember.assert("Could not find 'component-lookup:main' on the provided container," +
- " which is necessary for performing component lookups", componentLookup);
-
- var Component = componentLookup.lookupFactory(name, container);
- if (Component) {
- helper = EmberHandlebars.makeViewHelper(Component);
- container.register('helper:' + name, helper);
- }
- }
- return helper;
- }
-
-
- /**
- `bind` can be used to display a value, then update that value if it
- changes. For example, if you wanted to print the `title` property of
- `content`:
-
- ```handlebars
- {{bind "content.title"}}
- ```
-
- This will return the `title` property as a string, then create a new observer
- at the specified path. If it changes, it will update the value in DOM. Note
- that if you need to support IE7 and IE8 you must modify the model objects
- properties using `Ember.get()` and `Ember.set()` for this to work as it
- relies on Ember's KVO system. For all other browsers this will be handled for
- you automatically.
-
- @private
- @method bind
- @for Ember.Handlebars.helpers
- @param {String} property Property to bind
- @param {Function} fn Context to provide for rendering
- @return {String} HTML string
- */
- function bindHelper(property, options) {
- Ember.assert("You cannot pass more than one argument to the bind helper", arguments.length <= 2);
-
- var context = (options.contexts && options.contexts.length) ? options.contexts[0] : this;
-
- if (!options.fn) {
- var lazyValue = options.data.view.getStream(property);
- return simpleBind(context, lazyValue, options);
- }
-
- options.helperName = 'bind';
-
- return bind.call(context, property, options, false, exists);
- }
-
- __exports__.bind = bind;
- __exports__._triageMustacheHelper = _triageMustacheHelper;
- __exports__.resolveHelper = resolveHelper;
- __exports__.bindHelper = bindHelper;
- });
-enifed("ember-handlebars/helpers/collection",
- ["ember-metal/core","ember-handlebars-compiler","ember-metal/mixin","ember-runtime/system/string","ember-metal/property_get","ember-metal/streams/simple","ember-handlebars/ext","ember-handlebars/helpers/view","ember-views/views/view","ember-views/views/collection_view","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __exports__) {
- "use strict";
- /**
- @module ember
- @submodule ember-handlebars
- */
-
- var Ember = __dependency1__["default"];
- // Ember.assert, Ember.deprecate
-
- // var emberAssert = Ember.assert;
- // emberDeprecate = Ember.deprecate;
-
- var EmberHandlebars = __dependency2__["default"];
-
- var IS_BINDING = __dependency3__.IS_BINDING;
- var fmt = __dependency4__.fmt;
- var get = __dependency5__.get;
- var SimpleStream = __dependency6__["default"];
- var handlebarsGetView = __dependency7__.handlebarsGetView;
- var ViewHelper = __dependency8__.ViewHelper;
- var View = __dependency9__["default"];
- var CollectionView = __dependency10__["default"];
-
- /**
- `{{collection}}` is a `Ember.Handlebars` helper for adding instances of
- `Ember.CollectionView` to a template. See [Ember.CollectionView](/api/classes/Ember.CollectionView.html)
- for additional information on how a `CollectionView` functions.
-
- `{{collection}}`'s primary use is as a block helper with a `contentBinding`
- option pointing towards an `Ember.Array`-compatible object. An `Ember.View`
- instance will be created for each item in its `content` property. Each view
- will have its own `content` property set to the appropriate item in the
- collection.
-
- The provided block will be applied as the template for each item's view.
-
- Given an empty `<body>` the following template:
-
- ```handlebars
- {{! application.hbs }}
- {{#collection content=model}}
- Hi {{view.content.name}}
- {{/collection}}
- ```
-
- And the following application code
-
- ```javascript
- App = Ember.Application.create();
- App.ApplicationRoute = Ember.Route.extend({
- model: function(){
- return [{name: 'Yehuda'},{name: 'Tom'},{name: 'Peter'}];
- }
- });
- ```
-
- The following HTML will result:
-
- ```html
- <div class="ember-view">
- <div class="ember-view">Hi Yehuda</div>
- <div class="ember-view">Hi Tom</div>
- <div class="ember-view">Hi Peter</div>
- </div>
- ```
-
- ### Non-block version of collection
-
- If you provide an `itemViewClass` option that has its own `template` you may
- omit the block.
-
- The following template:
-
- ```handlebars
- {{! application.hbs }}
- {{collection content=model itemViewClass="an-item"}}
- ```
-
- And application code
-
- ```javascript
- App = Ember.Application.create();
- App.ApplicationRoute = Ember.Route.extend({
- model: function(){
- return [{name: 'Yehuda'},{name: 'Tom'},{name: 'Peter'}];
- }
- });
-
- App.AnItemView = Ember.View.extend({
- template: Ember.Handlebars.compile("Greetings {{view.content.name}}")
- });
- ```
-
- Will result in the HTML structure below
-
- ```html
- <div class="ember-view">
- <div class="ember-view">Greetings Yehuda</div>
- <div class="ember-view">Greetings Tom</div>
- <div class="ember-view">Greetings Peter</div>
- </div>
- ```
-
- ### Specifying a CollectionView subclass
-
- By default the `{{collection}}` helper will create an instance of
- `Ember.CollectionView`. You can supply a `Ember.CollectionView` subclass to
- the helper by passing it as the first argument:
-
- ```handlebars
- {{#collection "my-custom-collection" content=model}}
- Hi {{view.content.name}}
- {{/collection}}
- ```
-
- This example would look for the class `App.MyCustomCollection`.
-
- ### Forwarded `item.*`-named Options
-
- As with the `{{view}}`, helper options passed to the `{{collection}}` will be
- set on the resulting `Ember.CollectionView` as properties. Additionally,
- options prefixed with `item` will be applied to the views rendered for each
- item (note the camelcasing):
-
- ```handlebars
- {{#collection content=model
- itemTagName="p"
- itemClassNames="greeting"}}
- Howdy {{view.content.name}}
- {{/collection}}
- ```
-
- Will result in the following HTML structure:
-
- ```html
- <div class="ember-view">
- <p class="ember-view greeting">Howdy Yehuda</p>
- <p class="ember-view greeting">Howdy Tom</p>
- <p class="ember-view greeting">Howdy Peter</p>
- </div>
- ```
-
- @method collection
- @for Ember.Handlebars.helpers
- @param {String} path
- @param {Hash} options
- @return {String} HTML string
- @deprecated Use `{{each}}` helper instead.
- */
- function collectionHelper(path, options) {
- Ember.deprecate("Using the {{collection}} helper without specifying a class has been" +
- " deprecated as the {{each}} helper now supports the same functionality.", path !== 'collection');
-
- // If no path is provided, treat path param as options.
- if (path && path.data && path.data.isRenderData) {
- options = path;
- path = undefined;
- Ember.assert("You cannot pass more than one argument to the collection helper", arguments.length === 1);
- } else {
- Ember.assert("You cannot pass more than one argument to the collection helper", arguments.length === 2);
- }
-
- var fn = options.fn,
- data = options.data,
- inverse = options.inverse,
- view = options.data.view,
- // This should be deterministic, and should probably come from a
- // parent view and not the controller.
- container = (view.controller && view.controller.container ? view.controller.container : view.container);
-
- // If passed a path string, convert that into an object.
- // Otherwise, just default to the standard class.
- var collectionClass;
- if (path) {
- collectionClass = handlebarsGetView(this, path, container, options.data);
- Ember.assert(fmt("%@ #collection: Could not find collection class %@", [data.view, path]), !!collectionClass);
- }
- else {
- collectionClass = CollectionView;
- }
-
- var hash = options.hash;
- var hashTypes = options.hashTypes;
- var itemHash = {};
- var match;
-
- // Extract item view class if provided else default to the standard class
- var collectionPrototype = collectionClass.proto();
- var itemViewClass;
-
- if (hash.itemView) {
- itemViewClass = hash.itemView;
- } else if (hash.itemViewClass) {
- if (hashTypes.itemViewClass === 'ID') {
- var itemViewClassStream = view.getStream(hash.itemViewClass);
- Ember.deprecate('Resolved the view "'+hash.itemViewClass+'" on the global context. Pass a view name to be looked up on the container instead, such as {{view "select"}}. http://emberjs.com/guides/deprecations#toc_global-lookup-of-views', !itemViewClassStream.isGlobal());
- itemViewClass = itemViewClassStream.value();
- } else {
- itemViewClass = hash.itemViewClass;
- }
- } else {
- itemViewClass = collectionPrototype.itemViewClass;
- }
-
- if (typeof itemViewClass === 'string') {
- itemViewClass = container.lookupFactory('view:'+itemViewClass);
- }
-
- Ember.assert(fmt("%@ #collection: Could not find itemViewClass %@", [data.view, itemViewClass]), !!itemViewClass);
-
- delete hash.itemViewClass;
- delete hash.itemView;
- delete hashTypes.itemViewClass;
- delete hashTypes.itemView;
-
- // Go through options passed to the {{collection}} helper and extract options
- // that configure item views instead of the collection itself.
- for (var prop in hash) {
- if (prop === 'itemController' || prop === 'itemClassBinding') {
- continue;
- }
- if (hash.hasOwnProperty(prop)) {
- match = prop.match(/^item(.)(.*)$/);
- if (match) {
- var childProp = match[1].toLowerCase() + match[2];
-
- if (hashTypes[prop] === 'ID' || IS_BINDING.test(prop)) {
- itemHash[childProp] = view._getBindingForStream(hash[prop]);
- } else {
- itemHash[childProp] = hash[prop];
- }
- delete hash[prop];
- }
- }
- }
-
- if (fn) {
- itemHash.template = fn;
- delete options.fn;
- }
-
- var emptyViewClass;
- if (inverse && inverse !== EmberHandlebars.VM.noop) {
- emptyViewClass = get(collectionPrototype, 'emptyViewClass');
- emptyViewClass = emptyViewClass.extend({
- template: inverse,
- tagName: itemHash.tagName
- });
- } else if (hash.emptyViewClass) {
- emptyViewClass = handlebarsGetView(this, hash.emptyViewClass, container, options.data);
- }
- if (emptyViewClass) { hash.emptyView = emptyViewClass; }
-
- if (hash.keyword) {
- itemHash._contextBinding = '_parentView.context';
- } else {
- itemHash._contextBinding = 'content';
- }
-
- var viewOptions = ViewHelper.propertiesFromHTMLOptions({ data: data, hash: itemHash }, this);
-
- if (hash.itemClassBinding) {
- var itemClassBindings = hash.itemClassBinding.split(' ');
-
- for (var i = 0; i < itemClassBindings.length; i++) {
- var parsedPath = View._parsePropertyPath(itemClassBindings[i]);
- if (parsedPath.path === '') {
- parsedPath.stream = new SimpleStream(true);
- } else {
- parsedPath.stream = view.getStream(parsedPath.path);
- }
- itemClassBindings[i] = parsedPath;
- }
-
- viewOptions.classNameBindings = itemClassBindings;
- }
-
- hash.itemViewClass = itemViewClass;
- hash._itemViewProps = viewOptions;
-
- options.helperName = options.helperName || 'collection';
-
- return EmberHandlebars.helpers.view.call(this, collectionClass, options);
- }
-
- __exports__["default"] = collectionHelper;
- });
-enifed("ember-handlebars/helpers/debug",
- ["ember-metal/core","ember-metal/utils","ember-metal/logger","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
- "use strict";
- /*jshint debug:true*/
-
- /**
- @module ember
- @submodule ember-handlebars
- */
- var Ember = __dependency1__["default"];
- // Ember.FEATURES,
- var inspect = __dependency2__.inspect;
- var Logger = __dependency3__["default"];
-
- var a_slice = [].slice;
-
- /**
- `log` allows you to output the value of variables in the current rendering
- context. `log` also accepts primitive types such as strings or numbers.
-
- ```handlebars
- {{log "myVariable:" myVariable }}
- ```
-
- @method log
- @for Ember.Handlebars.helpers
- @param {String} property
- */
- function logHelper() {
- var params = a_slice.call(arguments, 0, -1);
- var options = arguments[arguments.length - 1];
- var view = options.data.view;
- var logger = Logger.log;
- var values = [];
-
- for (var i = 0; i < params.length; i++) {
- if (options.types[i] === 'ID') {
- var stream = view.getStream(params[i]);
- values.push(stream.value());
- } else {
- values.push(params[i]);
- }
- }
-
- logger.apply(logger, values);
- }
-
- /**
- Execute the `debugger` statement in the current context.
-
- ```handlebars
- {{debugger}}
- ```
-
- Before invoking the `debugger` statement, there
- are a few helpful variables defined in the
- body of this helper that you can inspect while
- debugging that describe how and where this
- helper was invoked:
-
- - templateContext: this is most likely a controller
- from which this template looks up / displays properties
- - typeOfTemplateContext: a string description of
- what the templateContext is
-
- For example, if you're wondering why a value `{{foo}}`
- isn't rendering as expected within a template, you
- could place a `{{debugger}}` statement, and when
- the `debugger;` breakpoint is hit, you can inspect
- `templateContext`, determine if it's the object you
- expect, and/or evaluate expressions in the console
- to perform property lookups on the `templateContext`:
-
- ```
- > templateContext.get('foo') // -> "<value of {{foo}}>"
- ```
-
- @method debugger
- @for Ember.Handlebars.helpers
- @param {String} property
- */
- function debuggerHelper(options) {
-
- // These are helpful values you can inspect while debugging.
- /* jshint unused: false */
- var templateContext = this;
- var typeOfTemplateContext = inspect(templateContext);
- Ember.Logger.info('Use `this` to access the context of the calling template.');
-
- debugger;
- }
-
- __exports__.logHelper = logHelper;
- __exports__.debuggerHelper = debuggerHelper;
- });
-enifed("ember-handlebars/helpers/each",
- ["ember-metal/core","ember-handlebars-compiler","ember-runtime/system/string","ember-metal/property_get","ember-metal/property_set","ember-views/views/collection_view","ember-metal/binding","ember-runtime/mixins/controller","ember-runtime/controllers/array_controller","ember-runtime/mixins/array","ember-metal/observer","ember-handlebars/views/metamorph_view","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __exports__) {
- "use strict";
-
- /**
- @module ember
- @submodule ember-handlebars
- */
- var Ember = __dependency1__["default"];
- // Ember.assert;, Ember.K
-
- var EmberHandlebars = __dependency2__["default"];
-
- var fmt = __dependency3__.fmt;
- var get = __dependency4__.get;
- var set = __dependency5__.set;
- var CollectionView = __dependency6__["default"];
- var Binding = __dependency7__.Binding;
- var ControllerMixin = __dependency8__["default"];
- var ArrayController = __dependency9__["default"];
- var EmberArray = __dependency10__["default"];
-
- var addObserver = __dependency11__.addObserver;
- var removeObserver = __dependency11__.removeObserver;
- var addBeforeObserver = __dependency11__.addBeforeObserver;
- var removeBeforeObserver = __dependency11__.removeBeforeObserver;
-
- var _MetamorphView = __dependency12__["default"];
- var _Metamorph = __dependency12__._Metamorph;
-
- var EachView = CollectionView.extend(_Metamorph, {
-
- init: function() {
- var itemController = get(this, 'itemController');
- var binding;
-
- if (itemController) {
- var controller = get(this, 'controller.container').lookupFactory('controller:array').create({
- _isVirtual: true,
- parentController: get(this, 'controller'),
- itemController: itemController,
- target: get(this, 'controller'),
- _eachView: this
- });
-
- this.disableContentObservers(function() {
- set(this, 'content', controller);
- binding = new Binding('content', '_eachView.dataSource').oneWay();
- binding.connect(controller);
- });
-
- set(this, '_arrayController', controller);
- } else {
- this.disableContentObservers(function() {
- binding = new Binding('content', 'dataSource').oneWay();
- binding.connect(this);
- });
- }
-
- return this._super();
- },
-
- _assertArrayLike: function(content) {
- Ember.assert(fmt("The value that #each loops over must be an Array. You " +
- "passed %@, but it should have been an ArrayController",
- [content.constructor]),
- !ControllerMixin.detect(content) ||
- (content && content.isGenerated) ||
- content instanceof ArrayController);
- Ember.assert(fmt("The value that #each loops over must be an Array. You passed %@",
- [(ControllerMixin.detect(content) &&
- content.get('model') !== undefined) ?
- fmt("'%@' (wrapped in %@)", [content.get('model'), content]) : content]),
- EmberArray.detect(content));
- },
-
- disableContentObservers: function(callback) {
- removeBeforeObserver(this, 'content', null, '_contentWillChange');
- removeObserver(this, 'content', null, '_contentDidChange');
-
- callback.call(this);
-
- addBeforeObserver(this, 'content', null, '_contentWillChange');
- addObserver(this, 'content', null, '_contentDidChange');
- },
-
- itemViewClass: _MetamorphView,
- emptyViewClass: _MetamorphView,
-
- createChildView: function(view, attrs) {
- view = this._super(view, attrs);
-
- var content = get(view, 'content');
- var keyword = get(this, 'keyword');
-
- if (keyword) {
- view._keywords[keyword] = content;
- }
-
- // If {{#each}} is looping over an array of controllers,
- // point each child view at their respective controller.
- if (content && content.isController) {
- set(view, 'controller', content);
- }
-
- return view;
- },
-
- destroy: function() {
- if (!this._super()) { return; }
-
- var arrayController = get(this, '_arrayController');
-
- if (arrayController) {
- arrayController.destroy();
- }
-
- return this;
- }
- });
-
- /**
- The `{{#each}}` helper loops over elements in a collection. It is an extension
- of the base Handlebars `{{#each}}` helper.
-
- The default behavior of `{{#each}}` is to yield its inner block once for every
- item in an array.
-
- ```javascript
- var developers = [{name: 'Yehuda'},{name: 'Tom'}, {name: 'Paul'}];
- ```
-
- ```handlebars
- {{#each person in developers}}
- {{person.name}}
- {{! `this` is whatever it was outside the #each }}
- {{/each}}
- ```
-
- The same rules apply to arrays of primitives, but the items may need to be
- references with `{{this}}`.
-
- ```javascript
- var developerNames = ['Yehuda', 'Tom', 'Paul']
- ```
-
- ```handlebars
- {{#each name in developerNames}}
- {{name}}
- {{/each}}
- ```
-
- ### {{else}} condition
-
- `{{#each}}` can have a matching `{{else}}`. The contents of this block will render
- if the collection is empty.
-
- ```
- {{#each person in developers}}
- {{person.name}}
- {{else}}
- <p>Sorry, nobody is available for this task.</p>
- {{/each}}
- ```
-
- ### Specifying an alternative view for each item
-
- `itemViewClass` can control which view will be used during the render of each
- item's template.
-
- The following template:
-
- ```handlebars
- <ul>
- {{#each developer in developers itemViewClass="person"}}
- {{developer.name}}
- {{/each}}
- </ul>
- ```
-
- Will use the following view for each item
-
- ```javascript
- App.PersonView = Ember.View.extend({
- tagName: 'li'
- });
- ```
-
- Resulting in HTML output that looks like the following:
-
- ```html
- <ul>
- <li class="ember-view">Yehuda</li>
- <li class="ember-view">Tom</li>
- <li class="ember-view">Paul</li>
- </ul>
- ```
-
- `itemViewClass` also enables a non-block form of `{{each}}`. The view
- must {{#crossLink "Ember.View/toc_templates"}}provide its own template{{/crossLink}},
- and then the block should be dropped. An example that outputs the same HTML
- as the previous one:
-
- ```javascript
- App.PersonView = Ember.View.extend({
- tagName: 'li',
- template: '{{developer.name}}'
- });
- ```
-
- ```handlebars
- <ul>
- {{each developer in developers itemViewClass="person"}}
- </ul>
- ```
-
- ### Specifying an alternative view for no items (else)
-
- The `emptyViewClass` option provides the same flexibility to the `{{else}}`
- case of the each helper.
-
- ```javascript
- App.NoPeopleView = Ember.View.extend({
- tagName: 'li',
- template: 'No person is available, sorry'
- });
- ```
-
- ```handlebars
- <ul>
- {{#each developer in developers emptyViewClass="no-people"}}
- <li>{{developer.name}}</li>
- {{/each}}
- </ul>
- ```
-
- ### Wrapping each item in a controller
-
- Controllers in Ember manage state and decorate data. In many cases,
- providing a controller for each item in a list can be useful.
- Specifically, an {{#crossLink "Ember.ObjectController"}}Ember.ObjectController{{/crossLink}}
- should probably be used. Item controllers are passed the item they
- will present as a `model` property, and an object controller will
- proxy property lookups to `model` for us.
-
- This allows state and decoration to be added to the controller
- while any other property lookups are delegated to the model. An example:
-
- ```javascript
- App.RecruitController = Ember.ObjectController.extend({
- isAvailableForHire: function() {
- return !this.get('isEmployed') && this.get('isSeekingWork');
- }.property('isEmployed', 'isSeekingWork')
- })
- ```
-
- ```handlebars
- {{#each person in developers itemController="recruit"}}
- {{person.name}} {{#if person.isAvailableForHire}}Hire me!{{/if}}
- {{/each}}
- ```
-
- @method each
- @for Ember.Handlebars.helpers
- @param [name] {String} name for item (used with `in`)
- @param [path] {String} path
- @param [options] {Object} Handlebars key/value pairs of options
- @param [options.itemViewClass] {String} a path to a view class used for each item
- @param [options.emptyViewClass] {String} a path to a view class used for each item
- @param [options.itemController] {String} name of a controller to be created for each item
- */
- function eachHelper(path) {
- var options = arguments[arguments.length - 1];
- var helperName = 'each';
- var keywordName;
-
- if (arguments.length === 4) {
- Ember.assert("If you pass more than one argument to the each helper," +
- " it must be in the form #each foo in bar", arguments[1] === "in");
-
- keywordName = arguments[0];
- path = arguments[2];
-
- helperName += ' ' + keywordName + ' in ' + path;
-
- options.hash.keyword = keywordName;
- } else if (arguments.length === 1) {
- path = '';
- } else {
- helperName += ' ' + path;
- }
-
- Ember.deprecate('Using the context switching form of {{each}} is deprecated. Please use the keyword form (`{{#each foo in bar}}`) instead. See http://emberjs.com/guides/deprecations/#toc_more-consistent-handlebars-scope for more details.', keywordName);
-
- options.hash.emptyViewClass = Ember._MetamorphView;
- options.hash.dataSourceBinding = path;
- options.hashTypes.dataSourceBinding = 'STRING';
- options.helperName = options.helperName || helperName;
-
- return EmberHandlebars.helpers.collection.call(this, EmberHandlebars.EachView, options);
- }
-
- __exports__.EachView = EachView;
- __exports__.eachHelper = eachHelper;
- });
-enifed("ember-handlebars/helpers/if_unless",
- ["ember-metal/core","ember-handlebars-compiler","ember-handlebars/helpers/binding","ember-metal/property_get","ember-metal/utils","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) {
- "use strict";
- /**
- @module ember
- @submodule ember-handlebars
- */
-
- var Ember = __dependency1__["default"];
- // Ember.assert
- var EmberHandlebars = __dependency2__["default"];
-
- var bind = __dependency3__.bind;
-
- var get = __dependency4__.get;
- var isArray = __dependency5__.isArray;
-
- var helpers = EmberHandlebars.helpers;
-
- function shouldDisplayIfHelperContent(result) {
- var truthy = result && get(result, 'isTruthy');
- if (typeof truthy === 'boolean') { return truthy; }
-
- if (isArray(result)) {
- return get(result, 'length') !== 0;
- } else {
- return !!result;
- }
- }
-
- /**
- Use the `boundIf` helper to create a conditional that re-evaluates
- whenever the truthiness of the bound value changes.
-
- ```handlebars
- {{#boundIf "content.shouldDisplayTitle"}}
- {{content.title}}
- {{/boundIf}}
- ```
-
- @private
- @method boundIf
- @for Ember.Handlebars.helpers
- @param {String} property Property to bind
- @param {Function} fn Context to provide for rendering
- @return {String} HTML string
- */
- function boundIfHelper(property, fn) {
- var context = (fn.contexts && fn.contexts.length) ? fn.contexts[0] : this;
-
- fn.helperName = fn.helperName || 'boundIf';
-
- return bind.call(context, property, fn, true, shouldDisplayIfHelperContent, shouldDisplayIfHelperContent, [
- 'isTruthy',
- 'length'
- ]);
- }
-
- /**
- @private
-
- Use the `unboundIf` helper to create a conditional that evaluates once.
-
- ```handlebars
- {{#unboundIf "content.shouldDisplayTitle"}}
- {{content.title}}
- {{/unboundIf}}
- ```
-
- @method unboundIf
- @for Ember.Handlebars.helpers
- @param {String} property Property to bind
- @param {Function} fn Context to provide for rendering
- @return {String} HTML string
- @since 1.4.0
- */
- function unboundIfHelper(property, fn) {
- var context = (fn.contexts && fn.contexts.length) ? fn.contexts[0] : this;
- var data = fn.data;
- var view = data.view;
- var template = fn.fn;
- var inverse = fn.inverse;
-
- var propertyValue = view.getStream(property).value();
-
- if (!shouldDisplayIfHelperContent(propertyValue)) {
- template = inverse;
- }
-
- template(context, { data: data });
- }
-
- /**
- See [boundIf](/api/classes/Ember.Handlebars.helpers.html#method_boundIf)
- and [unboundIf](/api/classes/Ember.Handlebars.helpers.html#method_unboundIf)
-
- @method if
- @for Ember.Handlebars.helpers
- @param {Function} context
- @param {Hash} options
- @return {String} HTML string
- */
- function ifHelper(context, options) {
- Ember.assert("You must pass exactly one argument to the if helper", arguments.length === 2);
- Ember.assert("You must pass a block to the if helper", options.fn && options.fn !== Handlebars.VM.noop);
-
- options.helperName = options.helperName || ('if ' + context);
-
- if (options.data.isUnbound) {
- return helpers.unboundIf.call(options.contexts[0], context, options);
- } else {
- return helpers.boundIf.call(options.contexts[0], context, options);
- }
- }
-
- /**
- @method unless
- @for Ember.Handlebars.helpers
- @param {Function} context
- @param {Hash} options
- @return {String} HTML string
- */
- function unlessHelper(context, options) {
- Ember.assert("You must pass exactly one argument to the unless helper", arguments.length === 2);
- Ember.assert("You must pass a block to the unless helper", options.fn && options.fn !== Handlebars.VM.noop);
-
- var fn = options.fn;
- var inverse = options.inverse;
- var helperName = 'unless';
-
- if (context) {
- helperName += ' ' + context;
- }
-
- options.fn = inverse;
- options.inverse = fn;
-
- options.helperName = options.helperName || helperName;
-
- if (options.data.isUnbound) {
- return helpers.unboundIf.call(options.contexts[0], context, options);
- } else {
- return helpers.boundIf.call(options.contexts[0], context, options);
- }
- }
-
- __exports__.ifHelper = ifHelper;
- __exports__.boundIfHelper = boundIfHelper;
- __exports__.unboundIfHelper = unboundIfHelper;
- __exports__.unlessHelper = unlessHelper;
- });
-enifed("ember-handlebars/helpers/loc",
- ["ember-runtime/system/string","exports"],
- function(__dependency1__, __exports__) {
- "use strict";
- var loc = __dependency1__.loc;
-
- /**
- @module ember
- @submodule ember-handlebars
- */
-
- /**
- Calls [Ember.String.loc](/api/classes/Ember.String.html#method_loc) with the
- provided string.
-
- This is a convenient way to localize text within a template:
-
- ```javascript
- Ember.STRINGS = {
- '_welcome_': 'Bonjour'
- };
- ```
-
- ```handlebars
- <div class='message'>
- {{loc '_welcome_'}}
- </div>
- ```
-
- ```html
- <div class='message'>
- Bonjour
- </div>
- ```
-
- See [Ember.String.loc](/api/classes/Ember.String.html#method_loc) for how to
- set up localized string references.
-
- @method loc
- @for Ember.Handlebars.helpers
- @param {String} str The string to format
- @see {Ember.String#loc}
- */
- __exports__["default"] = loc;
- });
-enifed("ember-handlebars/helpers/partial",
- ["ember-metal/core","ember-metal/is_none","ember-handlebars/helpers/binding","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
- "use strict";
- var Ember = __dependency1__["default"];
- // Ember.assert
- // var emberAssert = Ember.assert;
-
- var isNone = __dependency2__["default"];
- var bind = __dependency3__.bind;
-
- /**
- @module ember
- @submodule ember-handlebars
- */
-
- /**
- The `partial` helper renders another template without
- changing the template context:
-
- ```handlebars
- {{foo}}
- {{partial "nav"}}
- ```
-
- The above example template will render a template named
- "_nav", which has the same context as the parent template
- it's rendered into, so if the "_nav" template also referenced
- `{{foo}}`, it would print the same thing as the `{{foo}}`
- in the above example.
-
- If a "_nav" template isn't found, the `partial` helper will
- fall back to a template named "nav".
-
- ## Bound template names
-
- The parameter supplied to `partial` can also be a path
- to a property containing a template name, e.g.:
-
- ```handlebars
- {{partial someTemplateName}}
- ```
-
- The above example will look up the value of `someTemplateName`
- on the template context (e.g. a controller) and use that
- value as the name of the template to render. If the resolved
- value is falsy, nothing will be rendered. If `someTemplateName`
- changes, the partial will be re-rendered using the new template
- name.
-
-
- @method partial
- @for Ember.Handlebars.helpers
- @param {String} partialName the name of the template to render minus the leading underscore
- */
-
- __exports__["default"] = function partialHelper(name, options) {
- var view = options.data.view;
-
- var context = (options.contexts && options.contexts.length) ? options.contexts[0] : this;
-
- options.helperName = options.helperName || 'partial';
-
- if (options.types[0] === "ID") {
- var partialNameStream = view.getStream(name);
- // Helper was passed a property path; we need to
- // create a binding that will re-render whenever
- // this property changes.
- options.fn = function(context, fnOptions) {
- renderPartial(context, partialNameStream.value(), fnOptions);
- };
-
- return bind.call(context, name, options, true, exists);
- } else {
- // Render the partial right into parent template.
- renderPartial(context, name, options);
- }
- }
-
- function exists(value) {
- return !isNone(value);
- }
-
- function renderPartial(context, name, options) {
- var nameParts = name.split("/");
- var lastPart = nameParts[nameParts.length - 1];
-
- nameParts[nameParts.length - 1] = "_" + lastPart;
-
- var view = options.data.view;
- var underscoredName = nameParts.join("/");
- var template = view.templateForName(underscoredName);
- var deprecatedTemplate = !template && view.templateForName(name);
-
- Ember.assert("Unable to find partial with name '"+name+"'.", template || deprecatedTemplate);
-
- template = template || deprecatedTemplate;
-
- template(context, {
- data: options.data
- });
- }
- });
-enifed("ember-handlebars/helpers/template",
- ["ember-metal/core","ember-handlebars-compiler","exports"],
- function(__dependency1__, __dependency2__, __exports__) {
- "use strict";
- var Ember = __dependency1__["default"];
- // Ember.deprecate;
-
- var EmberHandlebars = __dependency2__["default"];
- /**
- @module ember
- @submodule ember-handlebars
- */
-
- /**
- @deprecated
- @method template
- @for Ember.Handlebars.helpers
- @param {String} templateName the template to render
- */
- __exports__["default"] = function templateHelper(name, options) {
- Ember.deprecate("The `template` helper has been deprecated in favor of the `partial` helper." +
- " Please use `partial` instead, which will work the same way.");
-
- options.helperName = options.helperName || 'template';
-
- return EmberHandlebars.helpers.partial.apply(this, arguments);
- }
- });
-enifed("ember-handlebars/helpers/unbound",
- ["ember-handlebars-compiler","ember-handlebars/helpers/binding","exports"],
- function(__dependency1__, __dependency2__, __exports__) {
- "use strict";
- /**
- @module ember
- @submodule ember-handlebars
- */
-
- var EmberHandlebars = __dependency1__["default"];
-
- var resolveHelper = __dependency2__.resolveHelper;
-
- /**
- `unbound` allows you to output a property without binding. *Important:* The
- output will not be updated if the property changes. Use with caution.
-
- ```handlebars
- <div>{{unbound somePropertyThatDoesntChange}}</div>
- ```
-
- `unbound` can also be used in conjunction with a bound helper to
- render it in its unbound form:
-
- ```handlebars
- <div>{{unbound helperName somePropertyThatDoesntChange}}</div>
- ```
-
- @method unbound
- @for Ember.Handlebars.helpers
- @param {String} property
- @return {String} HTML string
- */
- __exports__["default"] = function unboundHelper(property) {
- var argsLength = arguments.length;
- var options = arguments[argsLength - 1];
- var view = options.data.view;
- var container = view.container;
-
- if (argsLength <= 2) {
- return view.getStream(property).value();
- } else {
- options.data.isUnbound = true;
- options.types.shift();
-
- var args = new Array(argsLength - 1);
- for (var i = 1; i < argsLength; i++) {
- args[i - 1] = arguments[i];
- }
-
- var helper = resolveHelper(container, property) || EmberHandlebars.helpers.helperMissing;
-
- // Attempt to exec the first field as a helper
- options.name = arguments[0];
-
- var result = helper.apply(this, args);
-
- delete options.data.isUnbound;
- return result;
- }
- }
- });
-enifed("ember-handlebars/helpers/view",
- ["ember-metal/core","ember-runtime/system/object","ember-metal/property_get","ember-metal/keys","ember-metal/mixin","ember-views/streams/read","ember-views/views/view","ember-metal/streams/simple","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __exports__) {
- "use strict";
- /**
- @module ember
- @submodule ember-handlebars
- */
-
- var Ember = __dependency1__["default"];
- // Ember.warn, Ember.assert
- // var emberWarn = Ember.warn, emberAssert = Ember.assert;
-
- var EmberObject = __dependency2__["default"];
- var get = __dependency3__.get;
- var keys = __dependency4__["default"];
- var IS_BINDING = __dependency5__.IS_BINDING;
- var readViewFactory = __dependency6__.readViewFactory;
- var View = __dependency7__["default"];
- var SimpleStream = __dependency8__["default"];
-
- function makeBindings(options) {
- var hash = options.hash;
- var hashTypes = options.hashTypes;
- var view = options.data.view;
-
- for (var prop in hash) {
- var hashType = hashTypes[prop];
- var value = hash[prop];
-
- if (IS_BINDING.test(prop)) {
- // classBinding is processed separately
- if (prop === 'classBinding') {
- continue;
- }
-
- if (hashType === 'ID') {
- Ember.warn("You're attempting to render a view by passing " +
- prop + "=" + value +
- " to a view helper, but this syntax is ambiguous. You should either surround " +
- value + " in quotes or remove `Binding` from " + prop + ".");
- hash[prop] = view._getBindingForStream(value);
- } else if (typeof value === 'string') {
- hash[prop] = view._getBindingForStream(value);
- }
- } else {
- if (hashType === 'ID') {
- if (prop === 'class') {
- hash.classBinding = value;
- } else {
- hash[prop + 'Binding'] = view._getBindingForStream(value);
- }
- delete hash[prop];
- delete hashTypes[prop];
- }
- }
- }
-
- if (hash.idBinding) {
- // id can't be bound, so just perform one-time lookup.
- hash.id = hash.idBinding.value();
- hashTypes.id = 'STRING';
- delete hash.idBinding;
- delete hashTypes.idBinding;
- }
- }
-
- var ViewHelper = EmberObject.create({
- propertiesFromHTMLOptions: function(options) {
- var view = options.data.view;
- var hash = options.hash;
- var classes = hash['class'];
-
- var extensions = {
- helperName: options.helperName || ''
- };
-
- if (hash.id) {
- extensions.elementId = hash.id;
- }
-
- if (hash.tag) {
- extensions.tagName = hash.tag;
- }
-
- if (classes) {
- classes = classes.split(' ');
- extensions.classNames = classes;
- }
-
- if (hash.classBinding) {
- extensions.classNameBindings = hash.classBinding.split(' ');
- }
-
- if (hash.classNameBindings) {
- if (extensions.classNameBindings === undefined) {
- extensions.classNameBindings = [];
- }
- extensions.classNameBindings = extensions.classNameBindings.concat(hash.classNameBindings.split(' '));
- }
-
- if (hash.attributeBindings) {
- Ember.assert("Setting 'attributeBindings' via Handlebars is not allowed." +
- " Please subclass Ember.View and set it there instead.");
- extensions.attributeBindings = null;
- }
-
- // Set the proper context for all bindings passed to the helper. This applies to regular attribute bindings
- // as well as class name bindings. If the bindings are local, make them relative to the current context
- // instead of the view.
-
- var hashKeys = keys(hash);
-
- for (var i = 0, l = hashKeys.length; i < l; i++) {
- var prop = hashKeys[i];
-
- if (prop !== 'classNameBindings') {
- extensions[prop] = hash[prop];
- }
- }
-
- var classNameBindings = extensions.classNameBindings;
- if (classNameBindings) {
- for (var j = 0; j < classNameBindings.length; j++) {
- var parsedPath = View._parsePropertyPath(classNameBindings[j]);
- if (parsedPath.path === '') {
- parsedPath.stream = new SimpleStream(true);
- } else {
- parsedPath.stream = view.getStream(parsedPath.path);
- }
- classNameBindings[j] = parsedPath;
- }
- }
-
- return extensions;
- },
-
- helper: function(thisContext, newView, options) {
- var data = options.data;
- var fn = options.fn;
-
- makeBindings(options);
-
- var viewOptions = this.propertiesFromHTMLOptions(options, thisContext);
- var currentView = data.view;
- viewOptions.templateData = data;
- var newViewProto = newView.proto();
-
- if (fn) {
- Ember.assert("You cannot provide a template block if you also specified a templateName",
- !get(viewOptions, 'templateName') && !get(newViewProto, 'templateName'));
- viewOptions.template = fn;
- }
-
- // We only want to override the `_context` computed property if there is
- // no specified controller. See View#_context for more information.
- if (!newViewProto.controller && !newViewProto.controllerBinding && !viewOptions.controller && !viewOptions.controllerBinding) {
- viewOptions._context = thisContext;
- }
-
- currentView.appendChild(newView, viewOptions);
- },
-
- instanceHelper: function(thisContext, newView, options) {
- var data = options.data;
- var fn = options.fn;
-
- makeBindings(options);
-
- Ember.assert(
- 'Only a instance of a view may be passed to the ViewHelper.instanceHelper',
- View.detectInstance(newView)
- );
-
- var viewOptions = this.propertiesFromHTMLOptions(options, thisContext);
- var currentView = data.view;
- viewOptions.templateData = data;
-
- if (fn) {
- Ember.assert("You cannot provide a template block if you also specified a templateName",
- !get(viewOptions, 'templateName') && !get(newView, 'templateName'));
- viewOptions.template = fn;
- }
-
- // We only want to override the `_context` computed property if there is
- // no specified controller. See View#_context for more information.
- if (!newView.controller && !newView.controllerBinding &&
- !viewOptions.controller && !viewOptions.controllerBinding) {
- viewOptions._context = thisContext;
- }
-
- currentView.appendChild(newView, viewOptions);
- }
- });
- __exports__.ViewHelper = ViewHelper;
- /**
- `{{view}}` inserts a new instance of an `Ember.View` into a template passing its
- options to the `Ember.View`'s `create` method and using the supplied block as
- the view's own template.
-
- An empty `<body>` and the following template:
-
- ```handlebars
- A span:
- {{#view tagName="span"}}
- hello.
- {{/view}}
- ```
-
- Will result in HTML structure:
-
- ```html
- <body>
- <!-- Note: the handlebars template script
- also results in a rendered Ember.View
- which is the outer <div> here -->
-
- <div class="ember-view">
- A span:
- <span id="ember1" class="ember-view">
- Hello.
- </span>
- </div>
- </body>
- ```
-
- ### `parentView` setting
-
- The `parentView` property of the new `Ember.View` instance created through
- `{{view}}` will be set to the `Ember.View` instance of the template where
- `{{view}}` was called.
-
- ```javascript
- aView = Ember.View.create({
- template: Ember.Handlebars.compile("{{#view}} my parent: {{parentView.elementId}} {{/view}}")
- });
-
- aView.appendTo('body');
- ```
-
- Will result in HTML structure:
-
- ```html
- <div id="ember1" class="ember-view">
- <div id="ember2" class="ember-view">
- my parent: ember1
- </div>
- </div>
- ```
-
- ### Setting CSS id and class attributes
-
- The HTML `id` attribute can be set on the `{{view}}`'s resulting element with
- the `id` option. This option will _not_ be passed to `Ember.View.create`.
-
- ```handlebars
- {{#view tagName="span" id="a-custom-id"}}
- hello.
- {{/view}}
- ```
-
- Results in the following HTML structure:
-
- ```html
- <div class="ember-view">
- <span id="a-custom-id" class="ember-view">
- hello.
- </span>
- </div>
- ```
-
- The HTML `class` attribute can be set on the `{{view}}`'s resulting element
- with the `class` or `classNameBindings` options. The `class` option will
- directly set the CSS `class` attribute and will not be passed to
- `Ember.View.create`. `classNameBindings` will be passed to `create` and use
- `Ember.View`'s class name binding functionality:
-
- ```handlebars
- {{#view tagName="span" class="a-custom-class"}}
- hello.
- {{/view}}
- ```
-
- Results in the following HTML structure:
-
- ```html
- <div class="ember-view">
- <span id="ember2" class="ember-view a-custom-class">
- hello.
- </span>
- </div>
- ```
-
- ### Supplying a different view class
-
- `{{view}}` can take an optional first argument before its supplied options to
- specify a path to a custom view class.
-
- ```handlebars
- {{#view "custom"}}{{! will look up App.CustomView }}
- hello.
- {{/view}}
- ```
-
- The first argument can also be a relative path accessible from the current
- context.
-
- ```javascript
- MyApp = Ember.Application.create({});
- MyApp.OuterView = Ember.View.extend({
- innerViewClass: Ember.View.extend({
- classNames: ['a-custom-view-class-as-property']
- }),
- template: Ember.Handlebars.compile('{{#view view.innerViewClass}} hi {{/view}}')
- });
-
- MyApp.OuterView.create().appendTo('body');
- ```
-
- Will result in the following HTML:
-
- ```html
- <div id="ember1" class="ember-view">
- <div id="ember2" class="ember-view a-custom-view-class-as-property">
- hi
- </div>
- </div>
- ```
-
- ### Blockless use
-
- If you supply a custom `Ember.View` subclass that specifies its own template
- or provide a `templateName` option to `{{view}}` it can be used without
- supplying a block. Attempts to use both a `templateName` option and supply a
- block will throw an error.
-
- ```javascript
- var App = Ember.Application.create();
- App.WithTemplateDefinedView = Ember.View.extend({
- templateName: 'defined-template'
- });
- ```
-
- ```handlebars
- {{! application.hbs }}
- {{view 'with-template-defined'}}
- ```
-
- ```handlebars
- {{! defined-template.hbs }}
- Some content for the defined template view.
- ```
-
- ### `viewName` property
-
- You can supply a `viewName` option to `{{view}}`. The `Ember.View` instance
- will be referenced as a property of its parent view by this name.
-
- ```javascript
- aView = Ember.View.create({
- template: Ember.Handlebars.compile('{{#view viewName="aChildByName"}} hi {{/view}}')
- });
-
- aView.appendTo('body');
- aView.get('aChildByName') // the instance of Ember.View created by {{view}} helper
- ```
-
- @method view
- @for Ember.Handlebars.helpers
- @param {String} path
- @param {Hash} options
- @return {String} HTML string
- */
- function viewHelper(path) {
- Ember.assert("The view helper only takes a single argument", arguments.length <= 2);
-
- var options = arguments[arguments.length - 1];
- var types = options.types;
- var view = options.data.view;
- var container = view.container || view._keywords.view.value().container;
- var viewClass;
-
- // If no path is provided, treat path param as options
- // and get an instance of the registered `view:toplevel`
- if (arguments.length === 1) {
- if (container) {
- viewClass = container.lookupFactory('view:toplevel');
- } else {
- viewClass = View;
- }
- } else {
- var pathStream;
- if (typeof path === 'string' && types[0] === 'ID') {
- pathStream = view.getStream(path);
- Ember.deprecate('Resolved the view "'+path+'" on the global context. Pass a view name to be looked up on the container instead, such as {{view "select"}}. http://emberjs.com/guides/deprecations#toc_global-lookup-of-views', !pathStream.isGlobal());
- } else {
- pathStream = path;
- }
-
- viewClass = readViewFactory(pathStream, container);
- }
-
- options.helperName = options.helperName || 'view';
-
- return ViewHelper.helper(this, viewClass, options);
- }
-
- __exports__.viewHelper = viewHelper;
- });
-enifed("ember-handlebars/helpers/with",
- ["ember-metal/core","ember-metal/property_set","ember-metal/utils","ember-metal/platform","ember-metal/is_none","ember-handlebars/helpers/binding","ember-handlebars/views/handlebars_bound_view","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __exports__) {
- "use strict";
- /**
- @module ember
- @submodule ember-handlebars
- */
-
- var Ember = __dependency1__["default"];
- // Ember.assert
-
- var set = __dependency2__.set;
- var apply = __dependency3__.apply;
- var o_create = __dependency4__.create;
- var isNone = __dependency5__["default"];
- var bind = __dependency6__.bind;
- var _HandlebarsBoundView = __dependency7__._HandlebarsBoundView;
-
- function exists(value) {
- return !isNone(value);
- }
-
- var WithView = _HandlebarsBoundView.extend({
- init: function() {
- apply(this, this._super, arguments);
-
- var keywordName = this.templateHash.keywordName;
- var controllerName = this.templateHash.controller;
-
- if (controllerName) {
- var previousContext = this.previousContext;
- var controller = this.container.lookupFactory('controller:'+controllerName).create({
- parentController: previousContext,
- target: previousContext
- });
-
- this._generatedController = controller;
-
- if (this.preserveContext) {
- this._keywords[keywordName] = controller;
- this.lazyValue.subscribe(function(modelStream) {
- set(controller, 'model', modelStream.value());
- });
- } else {
- set(this, 'controller', controller);
- this.valueNormalizerFunc = function(result) {
- controller.set('model', result);
- return controller;
- };
- }
-
- set(controller, 'model', this.lazyValue.value());
- }
- },
-
- willDestroy: function() {
- this._super();
-
- if (this._generatedController) {
- this._generatedController.destroy();
- }
- }
- });
-
- /**
- Use the `{{with}}` helper when you want to aliases the to a new name. It's helpful
- for semantic clarity and to retain default scope or to reference from another
- `{{with}}` block.
-
- ```handlebars
- // posts might not be
- {{#with user.posts as blogPosts}}
- <div class="notice">
- There are {{blogPosts.length}} blog posts written by {{user.name}}.
- </div>
-
- {{#each post in blogPosts}}
- <li>{{post.title}}</li>
- {{/each}}
- {{/with}}
- ```
-
- Without the `as` operator, it would be impossible to reference `user.name` in the example above.
-
- NOTE: The alias should not reuse a name from the bound property path.
- For example: `{{#with foo.bar as foo}}` is not supported because it attempts to alias using
- the first part of the property path, `foo`. Instead, use `{{#with foo.bar as baz}}`.
-
- ### `controller` option
-
- Adding `controller='something'` instructs the `{{with}}` helper to create and use an instance of
- the specified controller wrapping the aliased keyword.
-
- This is very similar to using an `itemController` option with the `{{each}}` helper.
-
- ```handlebars
- {{#with users.posts as posts controller='userBlogPosts'}}
- {{!- `posts` is wrapped in our controller instance }}
- {{/with}}
- ```
-
- In the above example, the `posts` keyword is now wrapped in the `userBlogPost` controller,
- which provides an elegant way to decorate the context with custom
- functions/properties.
-
- @method with
- @for Ember.Handlebars.helpers
- @param {Function} context
- @param {Hash} options
- @return {String} HTML string
- */
- __exports__["default"] = function withHelper(contextPath) {
- var options = arguments[arguments.length - 1];
- var view = options.data.view;
- var bindContext, preserveContext;
- var helperName = 'with';
-
- if (arguments.length === 4) {
- Ember.assert("If you pass more than one argument to the with helper," +
- " it must be in the form #with foo as bar", arguments[1] === "as");
-
- var keywordName = arguments[2];
-
- if (contextPath) {
- helperName += ' ' + contextPath + ' as ' + keywordName;
- }
-
- Ember.assert("You must pass a block to the with helper", options.fn && options.fn !== Handlebars.VM.noop);
-
- var localizedOptions = o_create(options);
- localizedOptions.data = o_create(options.data);
-
- localizedOptions.keywords = {};
- localizedOptions.keywords[keywordName] = view.getStream(contextPath);
-
- localizedOptions.hash.keywordName = keywordName;
-
- bindContext = this;
- options = localizedOptions;
- preserveContext = true;
- } else {
- Ember.deprecate('Using the context switching form of `{{with}}` is deprecated. Please use the keyword form (`{{with foo as bar}}`) instead. See http://emberjs.com/guides/deprecations/#toc_more-consistent-handlebars-scope for more details.');
-
- Ember.assert("You must pass exactly one argument to the with helper", arguments.length === 2);
- Ember.assert("You must pass a block to the with helper", options.fn && options.fn !== Handlebars.VM.noop);
-
- helperName += ' ' + contextPath;
- bindContext = options.contexts[0];
- preserveContext = false;
- }
-
- options.helperName = helperName;
-
- return bind.call(bindContext, contextPath, options, preserveContext, exists, undefined, undefined, WithView);
- }
- });
-enifed("ember-handlebars/helpers/yield",
- ["ember-metal/core","ember-metal/property_get","exports"],
- function(__dependency1__, __dependency2__, __exports__) {
- "use strict";
- /**
- @module ember
- @submodule ember-handlebars
- */
-
- var Ember = __dependency1__["default"];
- // var emberAssert = Ember.assert;
-
- var get = __dependency2__.get;
-
- /**
- `{{yield}}` denotes an area of a template that will be rendered inside
- of another template. It has two main uses:
-
- ### Use with `layout`
- When used in a Handlebars template that is assigned to an `Ember.View`
- instance's `layout` property Ember will render the layout template first,
- inserting the view's own rendered output at the `{{yield}}` location.
-
- An empty `<body>` and the following application code:
-
- ```javascript
- AView = Ember.View.extend({
- classNames: ['a-view-with-layout'],
- layout: Ember.Handlebars.compile('<div class="wrapper">{{yield}}</div>'),
- template: Ember.Handlebars.compile('<span>I am wrapped</span>')
- });
-
- aView = AView.create();
- aView.appendTo('body');
- ```
-
- Will result in the following HTML output:
-
- ```html
- <body>
- <div class='ember-view a-view-with-layout'>
- <div class="wrapper">
- <span>I am wrapped</span>
- </div>
- </div>
- </body>
- ```
-
- The `yield` helper cannot be used outside of a template assigned to an
- `Ember.View`'s `layout` property and will throw an error if attempted.
-
- ```javascript
- BView = Ember.View.extend({
- classNames: ['a-view-with-layout'],
- template: Ember.Handlebars.compile('{{yield}}')
- });
-
- bView = BView.create();
- bView.appendTo('body');
-
- // throws
- // Uncaught Error: assertion failed:
- // You called yield in a template that was not a layout
- ```
-
- ### Use with Ember.Component
- When designing components `{{yield}}` is used to denote where, inside the component's
- template, an optional block passed to the component should render:
-
- ```handlebars
- <!-- application.hbs -->
- {{#labeled-textfield value=someProperty}}
- First name:
- {{/labeled-textfield}}
- ```
-
- ```handlebars
- <!-- components/labeled-textfield.hbs -->
- <label>
- {{yield}} {{input value=value}}
- </label>
- ```
-
- Result:
-
- ```html
- <label>
- First name: <input type="text" />
- </label>
- ```
-
- @method yield
- @for Ember.Handlebars.helpers
- @param {Hash} options
- @return {String} HTML string
- */
- __exports__["default"] = function yieldHelper(options) {
- var view = options.data.view;
-
- while (view && !get(view, 'layout')) {
- if (view._contextView) {
- view = view._contextView;
- } else {
- view = get(view, '_parentView');
- }
- }
-
- Ember.assert("You called yield in a template that was not a layout", !!view);
-
- view._yield(this, options);
- }
- });
-enifed("ember-handlebars/loader",
- ["ember-handlebars/component_lookup","ember-views/system/jquery","ember-metal/error","ember-runtime/system/lazy_load","ember-handlebars-compiler","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) {
- "use strict";
- /*globals Handlebars */
-
- var ComponentLookup = __dependency1__["default"];
- var jQuery = __dependency2__["default"];
- var EmberError = __dependency3__["default"];
- var onLoad = __dependency4__.onLoad;
-
- var EmberHandlebars = __dependency5__["default"];
-
- /**
- @module ember
- @submodule ember-handlebars
- */
-
- /**
- Find templates stored in the head tag as script tags and make them available
- to `Ember.CoreView` in the global `Ember.TEMPLATES` object. This will be run
- as as jQuery DOM-ready callback.
-
- Script tags with `text/x-handlebars` will be compiled
- with Ember's Handlebars and are suitable for use as a view's template.
- Those with type `text/x-raw-handlebars` will be compiled with regular
- Handlebars and are suitable for use in views' computed properties.
-
- @private
- @method bootstrap
- @for Ember.Handlebars
- @static
- @param ctx
- */
- function bootstrap(ctx) {
- var selectors = 'script[type="text/x-handlebars"], script[type="text/x-raw-handlebars"]';
-
- jQuery(selectors, ctx)
- .each(function() {
- // Get a reference to the script tag
- var script = jQuery(this);
-
- var compile = (script.attr('type') === 'text/x-raw-handlebars') ?
- jQuery.proxy(Handlebars.compile, Handlebars) :
- jQuery.proxy(EmberHandlebars.compile, EmberHandlebars);
- // Get the name of the script, used by Ember.View's templateName property.
- // First look for data-template-name attribute, then fall back to its
- // id if no name is found.
- var templateName = script.attr('data-template-name') || script.attr('id') || 'application';
- var template = compile(script.html());
-
- // Check if template of same name already exists
- if (Ember.TEMPLATES[templateName] !== undefined) {
- throw new EmberError('Template named "' + templateName + '" already exists.');
- }
-
- // For templates which have a name, we save them and then remove them from the DOM
- Ember.TEMPLATES[templateName] = template;
-
- // Remove script tag from DOM
- script.remove();
- });
- }
-
- function _bootstrap() {
- bootstrap( jQuery(document) );
- }
-
- function registerComponentLookup(container) {
- container.register('component-lookup:main', ComponentLookup);
- }
-
- /*
- We tie this to application.load to ensure that we've at least
- attempted to bootstrap at the point that the application is loaded.
-
- We also tie this to document ready since we're guaranteed that all
- the inline templates are present at this point.
-
- There's no harm to running this twice, since we remove the templates
- from the DOM after processing.
- */
-
- onLoad('Ember.Application', function(Application) {
- Application.initializer({
- name: 'domTemplates',
- initialize: _bootstrap
- });
-
- Application.initializer({
- name: 'registerComponentLookup',
- after: 'domTemplates',
- initialize: registerComponentLookup
- });
- });
-
- __exports__["default"] = bootstrap;
- });
-enifed("ember-handlebars/string",
- ["ember-runtime/system/string","exports"],
- function(__dependency1__, __exports__) {
- "use strict";
- // required so we can extend this object.
- var EmberStringUtils = __dependency1__["default"];
-
- /**
- Mark a string as safe for unescaped output with Handlebars. If you
- return HTML from a Handlebars helper, use this function to
- ensure Handlebars does not escape the HTML.
-
- ```javascript
- Ember.String.htmlSafe('<div>someString</div>')
- ```
-
- @method htmlSafe
- @for Ember.String
- @static
- @return {Handlebars.SafeString} a string that will not be html escaped by Handlebars
- */
- function htmlSafe(str) {
- if (str === null || str === undefined) {
- return "";
- }
-
- if (typeof str !== 'string') {
- str = ''+str;
- }
- return new Handlebars.SafeString(str);
- }
-
- EmberStringUtils.htmlSafe = htmlSafe;
- if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.String) {
-
- /**
- Mark a string as being safe for unescaped output with Handlebars.
-
- ```javascript
- '<div>someString</div>'.htmlSafe()
- ```
-
- See [Ember.String.htmlSafe](/api/classes/Ember.String.html#method_htmlSafe).
-
- @method htmlSafe
- @for String
- @return {Handlebars.SafeString} a string that will not be html escaped by Handlebars
- */
- String.prototype.htmlSafe = function() {
- return htmlSafe(this);
- };
- }
-
- __exports__["default"] = htmlSafe;
- });
-enifed("ember-handlebars/views/handlebars_bound_view",
- ["ember-handlebars-compiler","ember-metal/core","ember-metal/error","ember-metal/property_get","ember-metal/property_set","ember-metal/merge","ember-metal/run_loop","ember-handlebars/string","ember-views/views/states","ember-handlebars/views/metamorph_view","ember-metal/utils","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __exports__) {
- "use strict";
- /*jshint newcap:false*/
-
-
- /**
- @module ember
- @submodule ember-handlebars
- */
-
- var EmberHandlebars = __dependency1__["default"];
- // EmberHandlebars.SafeString;
-
- var Ember = __dependency2__["default"];
- // Ember.K
- var K = Ember.K;
-
- var EmberError = __dependency3__["default"];
- var get = __dependency4__.get;
- var set = __dependency5__.set;
- var merge = __dependency6__["default"];
- var run = __dependency7__["default"];
- var htmlSafe = __dependency8__["default"];
- var cloneStates = __dependency9__.cloneStates;
- var viewStates = __dependency9__.states;
-
- var _MetamorphView = __dependency10__["default"];
- var uuid = __dependency11__.uuid;
-
- function SimpleHandlebarsView(lazyValue, isEscaped) {
- this.lazyValue = lazyValue;
- this.isEscaped = isEscaped;
- this[Ember.GUID_KEY] = uuid();
- this._lastNormalizedValue = undefined;
- this.state = 'preRender';
- this.updateId = null;
- this._parentView = null;
- this.buffer = null;
- this._morph = null;
- }
-
- SimpleHandlebarsView.prototype = {
- isVirtual: true,
- isView: true,
-
- destroy: function () {
- if (this.updateId) {
- run.cancel(this.updateId);
- this.updateId = null;
- }
- if (this._parentView) {
- this._parentView.removeChild(this);
- }
- this.morph = null;
- this.state = 'destroyed';
- },
-
- propertyWillChange: K,
-
- propertyDidChange: K,
-
- normalizedValue: function() {
- var result = this.lazyValue.value();
-
- if (result === null || result === undefined) {
- result = "";
- } else if (!this.isEscaped && !(result instanceof EmberHandlebars.SafeString)) {
- result = htmlSafe(result);
- }
-
- return result;
- },
-
- render: function(buffer) {
- var value = this.normalizedValue();
- this._lastNormalizedValue = value;
- buffer._element = value;
- },
-
- rerender: function() {
- switch(this.state) {
- case 'preRender':
- case 'destroyed':
- break;
- case 'inBuffer':
- throw new EmberError("Something you did tried to replace an {{expression}} before it was inserted into the DOM.");
- case 'hasElement':
- case 'inDOM':
- this.updateId = run.scheduleOnce('render', this, 'update');
- break;
- }
- return this;
- },
-
- update: function () {
- this.updateId = null;
- var value = this.normalizedValue();
- // doesn't diff EmberHandlebars.SafeString instances
- if (value !== this._lastNormalizedValue) {
- this._lastNormalizedValue = value;
- this._morph.update(value);
- }
- },
-
- _transitionTo: function(state) {
- this.state = state;
- }
- };
-
- var states = cloneStates(viewStates);
-
- merge(states._default, {
- rerenderIfNeeded: K
- });
-
- merge(states.inDOM, {
- rerenderIfNeeded: function(view) {
- if (view.normalizedValue() !== view._lastNormalizedValue) {
- view.rerender();
- }
- }
- });
-
- /**
- `Ember._HandlebarsBoundView` is a private view created by the Handlebars
- `{{bind}}` helpers that is used to keep track of bound properties.
-
- Every time a property is bound using a `{{mustache}}`, an anonymous subclass
- of `Ember._HandlebarsBoundView` is created with the appropriate sub-template
- and context set up. When the associated property changes, just the template
- for this view will re-render.
-
- @class _HandlebarsBoundView
- @namespace Ember
- @extends Ember._MetamorphView
- @private
- */
- var _HandlebarsBoundView = _MetamorphView.extend({
- instrumentName: 'boundHandlebars',
-
- _states: states,
-
- /**
- The function used to determine if the `displayTemplate` or
- `inverseTemplate` should be rendered. This should be a function that takes
- a value and returns a Boolean.
-
- @property shouldDisplayFunc
- @type Function
- @default null
- */
- shouldDisplayFunc: null,
-
- /**
- Whether the template rendered by this view gets passed the context object
- of its parent template, or gets passed the value of retrieving `path`
- from the `pathRoot`.
-
- For example, this is true when using the `{{#if}}` helper, because the
- template inside the helper should look up properties relative to the same
- object as outside the block. This would be `false` when used with `{{#with
- foo}}` because the template should receive the object found by evaluating
- `foo`.
-
- @property preserveContext
- @type Boolean
- @default false
- */
- preserveContext: false,
-
- /**
- If `preserveContext` is true, this is the object that will be used
- to render the template.
-
- @property previousContext
- @type Object
- */
- previousContext: null,
-
- /**
- The template to render when `shouldDisplayFunc` evaluates to `true`.
-
- @property displayTemplate
- @type Function
- @default null
- */
- displayTemplate: null,
-
- /**
- The template to render when `shouldDisplayFunc` evaluates to `false`.
-
- @property inverseTemplate
- @type Function
- @default null
- */
- inverseTemplate: null,
-
- lazyValue: null,
-
- normalizedValue: function() {
- var value = this.lazyValue.value();
- var valueNormalizer = get(this, 'valueNormalizerFunc');
- return valueNormalizer ? valueNormalizer(value) : value;
- },
-
- rerenderIfNeeded: function() {
- this.currentState.rerenderIfNeeded(this);
- },
-
- /**
- Determines which template to invoke, sets up the correct state based on
- that logic, then invokes the default `Ember.View` `render` implementation.
-
- This method will first look up the `path` key on `pathRoot`,
- then pass that value to the `shouldDisplayFunc` function. If that returns
- `true,` the `displayTemplate` function will be rendered to DOM. Otherwise,
- `inverseTemplate`, if specified, will be rendered.
-
- For example, if this `Ember._HandlebarsBoundView` represented the `{{#with
- foo}}` helper, it would look up the `foo` property of its context, and
- `shouldDisplayFunc` would always return true. The object found by looking
- up `foo` would be passed to `displayTemplate`.
-
- @method render
- @param {Ember.RenderBuffer} buffer
- */
- render: function(buffer) {
- // If not invoked via a triple-mustache ({{{foo}}}), escape
- // the content of the template.
- var escape = get(this, 'isEscaped');
-
- var shouldDisplay = get(this, 'shouldDisplayFunc');
- var preserveContext = get(this, 'preserveContext');
- var context = get(this, 'previousContext');
-
- var inverseTemplate = get(this, 'inverseTemplate');
- var displayTemplate = get(this, 'displayTemplate');
-
- var result = this.normalizedValue();
-
- this._lastNormalizedValue = result;
-
- // First, test the conditional to see if we should
- // render the template or not.
- if (shouldDisplay(result)) {
- set(this, 'template', displayTemplate);
-
- // If we are preserving the context (for example, if this
- // is an #if block, call the template with the same object.
- if (preserveContext) {
- set(this, '_context', context);
- } else {
- // Otherwise, determine if this is a block bind or not.
- // If so, pass the specified object to the template
- if (displayTemplate) {
- set(this, '_context', result);
- } else {
- // This is not a bind block, just push the result of the
- // expression to the render context and return.
- if (result === null || result === undefined) {
- result = "";
- } else if (!(result instanceof EmberHandlebars.SafeString)) {
- result = String(result);
- }
-
- if (escape) { result = Handlebars.Utils.escapeExpression(result); }
- buffer.push(result);
- return;
- }
- }
- } else if (inverseTemplate) {
- set(this, 'template', inverseTemplate);
-
- if (preserveContext) {
- set(this, '_context', context);
- } else {
- set(this, '_context', result);
- }
- } else {
- set(this, 'template', function() { return ''; });
- }
-
- return this._super(buffer);
- }
- });
-
- __exports__._HandlebarsBoundView = _HandlebarsBoundView;
- __exports__.SimpleHandlebarsView = SimpleHandlebarsView;
- });
-enifed("ember-handlebars/views/metamorph_view",
- ["ember-metal/core","ember-views/views/core_view","ember-views/views/view","ember-metal/mixin","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
- "use strict";
- /*jshint newcap:false*/
- var Ember = __dependency1__["default"];
- // Ember.deprecate
-
- var CoreView = __dependency2__["default"];
- var View = __dependency3__["default"];
- var Mixin = __dependency4__.Mixin;
-
- /**
- @module ember
- @submodule ember-handlebars
- */
-
- // The `morph` and `outerHTML` properties are internal only
- // and not observable.
-
- /**
- @class _Metamorph
- @namespace Ember
- @private
- */
- var _Metamorph = Mixin.create({
- isVirtual: true,
- tagName: '',
-
- instrumentName: 'metamorph',
-
- init: function() {
- this._super();
- Ember.deprecate('Supplying a tagName to Metamorph views is unreliable and is deprecated.' +
- ' You may be setting the tagName on a Handlebars helper that creates a Metamorph.', !this.tagName);
- }
- });
- __exports__._Metamorph = _Metamorph;
- /**
- @class _MetamorphView
- @namespace Ember
- @extends Ember.View
- @uses Ember._Metamorph
- @private
- */
- __exports__["default"] = View.extend(_Metamorph);
-
- /**
- @class _SimpleMetamorphView
- @namespace Ember
- @extends Ember.CoreView
- @uses Ember._Metamorph
- @private
- */
- var _SimpleMetamorphView = CoreView.extend(_Metamorph);
- __exports__._SimpleMetamorphView = _SimpleMetamorphView;
- });
-enifed("ember-metal-views",
- ["ember-metal-views/renderer","exports"],
- function(__dependency1__, __exports__) {
- "use strict";
- var Renderer = __dependency1__["default"];
- __exports__.Renderer = Renderer;
- });
-enifed("ember-metal-views/renderer",
- ["morph","exports"],
- function(__dependency1__, __exports__) {
- "use strict";
- var DOMHelper = __dependency1__.DOMHelper;
-
- function Renderer() {
- this._uuid = 0;
- this._views = new Array(2000);
- this._queue = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
- this._parents = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
- this._elements = new Array(17);
- this._inserts = {};
- this._dom = new DOMHelper();
- }
-
- function Renderer_renderTree(_view, _parentView, _insertAt) {
- var views = this._views;
- views[0] = _view;
- var insertAt = _insertAt === undefined ? -1 : _insertAt;
- var index = 0;
- var total = 1;
- var levelBase = _parentView ? _parentView._level+1 : 0;
-
- var root = _parentView == null ? _view : _parentView._root;
-
- // if root view has a _morph assigned
- var willInsert = !!root._morph;
-
- var queue = this._queue;
- queue[0] = 0;
- var length = 1;
-
- var parentIndex = -1;
- var parents = this._parents;
- var parent = _parentView || null;
- var elements = this._elements;
- var element = null;
- var contextualElement = null;
- var level = 0;
-
- var view = _view;
- var children, i, child;
- while (length) {
- elements[level] = element;
- if (!view._morph) {
- // ensure props we add are in same order
- view._morph = null;
- }
- view._root = root;
- this.uuid(view);
- view._level = levelBase + level;
- if (view._elementCreated) {
- this.remove(view, false, true);
- }
-
- this.willCreateElement(view);
-
- contextualElement = view._morph && view._morph.contextualElement;
- if (!contextualElement && parent && parent._childViewsMorph) {
- contextualElement = parent._childViewsMorph.contextualElement;
- }
- if (!contextualElement && view._didCreateElementWithoutMorph) {
- // This code path is only used by createElement and rerender when createElement
- // was previously called on a view.
- contextualElement = document.body;
- }
- Ember.assert("Required contextualElement for view "+_view+" is missing", contextualElement);
- element = this.createElement(view, contextualElement);
-
- parents[level++] = parentIndex;
- parentIndex = index;
- parent = view;
-
- // enqueue for end
- queue[length++] = index;
- // enqueue children
- children = this.childViews(view);
- if (children) {
- for (i=children.length-1;i>=0;i--) {
- child = children[i];
- index = total++;
- views[index] = child;
- queue[length++] = index;
- view = child;
- }
- }
-
- index = queue[--length];
- view = views[index];
-
- while (parentIndex === index) {
- level--;
- view._elementCreated = true;
- this.didCreateElement(view);
- if (willInsert) {
- this.willInsertElement(view);
- }
-
- if (level === 0) {
- length--;
- break;
- }
-
- parentIndex = parents[level];
- parent = parentIndex === -1 ? _parentView : views[parentIndex];
- this.insertElement(view, parent, element, -1);
- index = queue[--length];
- view = views[index];
- element = elements[level];
- elements[level] = null;
- }
- }
-
- this.insertElement(view, _parentView, element, insertAt);
-
- for (i=total-1; i>=0; i--) {
- if (willInsert) {
- views[i]._elementInserted = true;
- this.didInsertElement(views[i]);
- }
- views[i] = null;
- }
-
- return element;
- }
-
- Renderer.prototype.uuid = function Renderer_uuid(view) {
- if (view._uuid === undefined) {
- view._uuid = ++this._uuid;
- view._renderer = this;
- } // else assert(view._renderer === this)
- return view._uuid;
- };
-
- Renderer.prototype.scheduleInsert =
- function Renderer_scheduleInsert(view, morph) {
- if (view._morph || view._elementCreated) {
- throw new Error("You cannot insert a View that has already been rendered");
- }
- Ember.assert("You cannot insert a View without a morph", morph);
- view._morph = morph;
- var viewId = this.uuid(view);
- this._inserts[viewId] = this.scheduleRender(this, function scheduledRenderTree() {
- this._inserts[viewId] = null;
- this.renderTree(view);
- });
- };
-
- Renderer.prototype.appendTo =
- function Renderer_appendTo(view, target) {
- var morph = this._dom.appendMorph(target);
- this.scheduleInsert(view, morph);
- };
-
- Renderer.prototype.replaceIn =
- function Renderer_replaceIn(view, target) {
- var morph = this._dom.createMorph(target, null, null);
- this.scheduleInsert(view, morph);
- };
-
- function Renderer_remove(_view, shouldDestroy, reset) {
- var viewId = this.uuid(_view);
-
- if (this._inserts[viewId]) {
- this.cancelRender(this._inserts[viewId]);
- this._inserts[viewId] = undefined;
- }
-
- if (!_view._elementCreated) {
- return;
- }
-
- var removeQueue = [];
- var destroyQueue = [];
- var morph = _view._morph;
- var idx, len, view, queue, childViews, i, l;
-
- removeQueue.push(_view);
-
- for (idx=0; idx<removeQueue.length; idx++) {
- view = removeQueue[idx];
-
- if (!shouldDestroy && view._childViewsMorph) {
- queue = removeQueue;
- } else {
- queue = destroyQueue;
- }
-
- this.beforeRemove(removeQueue[idx]);
-
- childViews = view._childViews;
- if (childViews) {
- for (i=0,l=childViews.length; i<l; i++) {
- queue.push(childViews[i]);
- }
- }
- }
-
- for (idx=0; idx<destroyQueue.length; idx++) {
- view = destroyQueue[idx];
-
- this.beforeRemove(destroyQueue[idx]);
-
- childViews = view._childViews;
- if (childViews) {
- for (i=0,l=childViews.length; i<l; i++) {
- destroyQueue.push(childViews[i]);
- }
- }
- }
-
- // destroy DOM from root insertion
- if (morph && !reset) {
- morph.destroy();
- }
-
- for (idx=0, len=removeQueue.length; idx < len; idx++) {
- this.afterRemove(removeQueue[idx], false);
- }
-
- for (idx=0, len=destroyQueue.length; idx < len; idx++) {
- this.afterRemove(destroyQueue[idx], true);
- }
-
- if (reset) {
- _view._morph = morph;
- }
- }
-
- function Renderer_insertElement(view, parentView, element, index) {
- if (element === null || element === undefined) return;
- if (view._morph) {
- view._morph.update(element);
- } else if (parentView) {
- if (index === -1) {
- view._morph = parentView._childViewsMorph.append(element);
- } else {
- view._morph = parentView._childViewsMorph.insert(index, element);
- }
- }
- }
-
- function Renderer_beforeRemove(view) {
- if (view._elementCreated) {
- this.willDestroyElement(view);
- }
- if (view._elementInserted) {
- this.willRemoveElement(view);
- }
- }
-
- function Renderer_afterRemove(view, shouldDestroy) {
- view._elementInserted = false;
- view._morph = null;
- view._childViewsMorph = null;
- if (view._elementCreated) {
- view._elementCreated = false;
- this.didDestroyElement(view);
- }
- if (shouldDestroy) {
- this.destroyView(view);
- }
- }
-
- Renderer.prototype.remove = Renderer_remove;
- Renderer.prototype.destroy = function (view) {
- this.remove(view, true);
- };
-
- Renderer.prototype.renderTree = Renderer_renderTree;
- Renderer.prototype.insertElement = Renderer_insertElement;
- Renderer.prototype.beforeRemove = Renderer_beforeRemove;
- Renderer.prototype.afterRemove = Renderer_afterRemove;
-
- /// HOOKS
- var noop = function () {};
-
- Renderer.prototype.willCreateElement = noop; // inBuffer
- Renderer.prototype.createElement = noop; // renderToBuffer or createElement
- Renderer.prototype.didCreateElement = noop; // hasElement
- Renderer.prototype.willInsertElement = noop; // will place into DOM
- Renderer.prototype.didInsertElement = noop; // inDOM // placed into DOM
- Renderer.prototype.willRemoveElement = noop; // removed from DOM willDestroyElement currently paired with didInsertElement
- Renderer.prototype.willDestroyElement = noop; // willClearRender (currently balanced with render) this is now paired with createElement
- Renderer.prototype.didDestroyElement = noop; // element destroyed so view.destroy shouldn't try to remove it removedFromDOM
- Renderer.prototype.destroyView = noop;
- Renderer.prototype.childViews = noop;
-
- __exports__["default"] = Renderer;
- });
-enifed("ember-metal",
- ["ember-metal/core","ember-metal/merge","ember-metal/instrumentation","ember-metal/utils","ember-metal/error","ember-metal/enumerable_utils","ember-metal/cache","ember-metal/platform","ember-metal/array","ember-metal/logger","ember-metal/property_get","ember-metal/events","ember-metal/observer_set","ember-metal/property_events","ember-metal/properties","ember-metal/property_set","ember-metal/map","ember-metal/get_properties","ember-metal/set_properties","ember-metal/watch_key","ember-metal/chains","ember-metal/watch_path","ember-metal/watching","ember-metal/expand_properties","ember-metal/computed","ember-metal/computed_macros","ember-metal/observer","ember-metal/mixin","ember-metal/binding","ember-metal/run_loop","ember-metal/libraries","ember-metal/is_none","ember-metal/is_empty","ember-metal/is_blank","ember-metal/is_present","ember-metal/keys","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__, __dependency28__, __dependency29__, __dependency30__, __dependency31__, __dependency32__, __dependency33__, __dependency34__, __dependency35__, __dependency36__, __exports__) {
- "use strict";
- /**
- Ember Metal
-
- @module ember
- @submodule ember-metal
- */
-
- // BEGIN IMPORTS
- var Ember = __dependency1__["default"];
- var merge = __dependency2__["default"];
- var instrument = __dependency3__.instrument;
- var reset = __dependency3__.reset;
- var subscribe = __dependency3__.subscribe;
- var unsubscribe = __dependency3__.unsubscribe;
- var EMPTY_META = __dependency4__.EMPTY_META;
- var GUID_KEY = __dependency4__.GUID_KEY;
- var META_DESC = __dependency4__.META_DESC;
- var apply = __dependency4__.apply;
- var applyStr = __dependency4__.applyStr;
- var canInvoke = __dependency4__.canInvoke;
- var generateGuid = __dependency4__.generateGuid;
- var getMeta = __dependency4__.getMeta;
- var guidFor = __dependency4__.guidFor;
- var inspect = __dependency4__.inspect;
- var isArray = __dependency4__.isArray;
- var makeArray = __dependency4__.makeArray;
- var meta = __dependency4__.meta;
- var metaPath = __dependency4__.metaPath;
- var setMeta = __dependency4__.setMeta;
- var tryCatchFinally = __dependency4__.tryCatchFinally;
- var tryFinally = __dependency4__.tryFinally;
- var tryInvoke = __dependency4__.tryInvoke;
- var typeOf = __dependency4__.typeOf;
- var uuid = __dependency4__.uuid;
- var wrap = __dependency4__.wrap;
- var EmberError = __dependency5__["default"];
- var EnumerableUtils = __dependency6__["default"];
- var Cache = __dependency7__["default"];
- var create = __dependency8__.create;
- var hasPropertyAccessors = __dependency8__.hasPropertyAccessors;
- var filter = __dependency9__.filter;
- var forEach = __dependency9__.forEach;
- var indexOf = __dependency9__.indexOf;
- var map = __dependency9__.map;
- var Logger = __dependency10__["default"];
-
- var _getPath = __dependency11__._getPath;
- var get = __dependency11__.get;
- var getWithDefault = __dependency11__.getWithDefault;
- var normalizeTuple = __dependency11__.normalizeTuple;
-
- var addListener = __dependency12__.addListener;
- var hasListeners = __dependency12__.hasListeners;
- var listenersDiff = __dependency12__.listenersDiff;
- var listenersFor = __dependency12__.listenersFor;
- var listenersUnion = __dependency12__.listenersUnion;
- var on = __dependency12__.on;
- var removeListener = __dependency12__.removeListener;
- var sendEvent = __dependency12__.sendEvent;
- var suspendListener = __dependency12__.suspendListener;
- var suspendListeners = __dependency12__.suspendListeners;
- var watchedEvents = __dependency12__.watchedEvents;
-
- var ObserverSet = __dependency13__["default"];
-
- var beginPropertyChanges = __dependency14__.beginPropertyChanges;
- var changeProperties = __dependency14__.changeProperties;
- var endPropertyChanges = __dependency14__.endPropertyChanges;
- var overrideChains = __dependency14__.overrideChains;
- var propertyDidChange = __dependency14__.propertyDidChange;
- var propertyWillChange = __dependency14__.propertyWillChange;
-
- var Descriptor = __dependency15__.Descriptor;
- var defineProperty = __dependency15__.defineProperty;
- var set = __dependency16__.set;
- var trySet = __dependency16__.trySet;
-
- var Map = __dependency17__.Map;
- var MapWithDefault = __dependency17__.MapWithDefault;
- var OrderedSet = __dependency17__.OrderedSet;
- var getProperties = __dependency18__["default"];
- var setProperties = __dependency19__["default"];
- var watchKey = __dependency20__.watchKey;
- var unwatchKey = __dependency20__.unwatchKey;
- var ChainNode = __dependency21__.ChainNode;
- var finishChains = __dependency21__.finishChains;
- var flushPendingChains = __dependency21__.flushPendingChains;
- var removeChainWatcher = __dependency21__.removeChainWatcher;
- var watchPath = __dependency22__.watchPath;
- var unwatchPath = __dependency22__.unwatchPath;
- var destroy = __dependency23__.destroy;
- var isWatching = __dependency23__.isWatching;
- var rewatch = __dependency23__.rewatch;
- var unwatch = __dependency23__.unwatch;
- var watch = __dependency23__.watch;
- var expandProperties = __dependency24__["default"];
- var ComputedProperty = __dependency25__.ComputedProperty;
- var computed = __dependency25__.computed;
- var cacheFor = __dependency25__.cacheFor;
-
- // side effect of defining the computed.* macros
-
- var _suspendBeforeObserver = __dependency27__._suspendBeforeObserver;
- var _suspendBeforeObservers = __dependency27__._suspendBeforeObservers;
- var _suspendObserver = __dependency27__._suspendObserver;
- var _suspendObservers = __dependency27__._suspendObservers;
- var addBeforeObserver = __dependency27__.addBeforeObserver;
- var addObserver = __dependency27__.addObserver;
- var beforeObserversFor = __dependency27__.beforeObserversFor;
- var observersFor = __dependency27__.observersFor;
- var removeBeforeObserver = __dependency27__.removeBeforeObserver;
- var removeObserver = __dependency27__.removeObserver;
- var IS_BINDING = __dependency28__.IS_BINDING;
- var Mixin = __dependency28__.Mixin;
- var aliasMethod = __dependency28__.aliasMethod;
- var beforeObserver = __dependency28__.beforeObserver;
- var immediateObserver = __dependency28__.immediateObserver;
- var mixin = __dependency28__.mixin;
- var observer = __dependency28__.observer;
- var required = __dependency28__.required;
- var Binding = __dependency29__.Binding;
- var bind = __dependency29__.bind;
- var isGlobalPath = __dependency29__.isGlobalPath;
- var oneWay = __dependency29__.oneWay;
- var run = __dependency30__["default"];
- var libraries = __dependency31__["default"];
- var isNone = __dependency32__["default"];
- var isEmpty = __dependency33__["default"];
- var isBlank = __dependency34__["default"];
- var isPresent = __dependency35__["default"];
- var keys = __dependency36__["default"];
-
- // END IMPORTS
-
- // BEGIN EXPORTS
- var EmberInstrumentation = Ember.Instrumentation = {};
- EmberInstrumentation.instrument = instrument;
- EmberInstrumentation.subscribe = subscribe;
- EmberInstrumentation.unsubscribe = unsubscribe;
- EmberInstrumentation.reset = reset;
-
- Ember.instrument = instrument;
- Ember.subscribe = subscribe;
-
- Ember._Cache = Cache;
-
- Ember.generateGuid = generateGuid;
- Ember.GUID_KEY = GUID_KEY;
- Ember.create = create;
- Ember.keys = keys;
- Ember.platform = {
- defineProperty: defineProperty,
- hasPropertyAccessors: hasPropertyAccessors
- };
-
- var EmberArrayPolyfills = Ember.ArrayPolyfills = {};
-
- EmberArrayPolyfills.map = map;
- EmberArrayPolyfills.forEach = forEach;
- EmberArrayPolyfills.filter = filter;
- EmberArrayPolyfills.indexOf = indexOf;
-
- Ember.Error = EmberError;
- Ember.guidFor = guidFor;
- Ember.META_DESC = META_DESC;
- Ember.EMPTY_META = EMPTY_META;
- Ember.meta = meta;
- Ember.getMeta = getMeta;
- Ember.setMeta = setMeta;
- Ember.metaPath = metaPath;
- Ember.inspect = inspect;
- Ember.typeOf = typeOf;
- Ember.tryCatchFinally = tryCatchFinally;
- Ember.isArray = isArray;
- Ember.makeArray = makeArray;
- Ember.canInvoke = canInvoke;
- Ember.tryInvoke = tryInvoke;
- Ember.tryFinally = tryFinally;
- Ember.wrap = wrap;
- Ember.apply = apply;
- Ember.applyStr = applyStr;
- Ember.uuid = uuid;
-
- Ember.Logger = Logger;
-
- Ember.get = get;
- Ember.getWithDefault = getWithDefault;
- Ember.normalizeTuple = normalizeTuple;
- Ember._getPath = _getPath;
-
- Ember.EnumerableUtils = EnumerableUtils;
-
- Ember.on = on;
- Ember.addListener = addListener;
- Ember.removeListener = removeListener;
- Ember._suspendListener = suspendListener;
- Ember._suspendListeners = suspendListeners;
- Ember.sendEvent = sendEvent;
- Ember.hasListeners = hasListeners;
- Ember.watchedEvents = watchedEvents;
- Ember.listenersFor = listenersFor;
- Ember.listenersDiff = listenersDiff;
- Ember.listenersUnion = listenersUnion;
-
- Ember._ObserverSet = ObserverSet;
-
- Ember.propertyWillChange = propertyWillChange;
- Ember.propertyDidChange = propertyDidChange;
- Ember.overrideChains = overrideChains;
- Ember.beginPropertyChanges = beginPropertyChanges;
- Ember.endPropertyChanges = endPropertyChanges;
- Ember.changeProperties = changeProperties;
-
- Ember.Descriptor = Descriptor;
- Ember.defineProperty = defineProperty;
-
- Ember.set = set;
- Ember.trySet = trySet;
-
- Ember.OrderedSet = OrderedSet;
- Ember.Map = Map;
- Ember.MapWithDefault = MapWithDefault;
-
- Ember.getProperties = getProperties;
- Ember.setProperties = setProperties;
-
- Ember.watchKey = watchKey;
- Ember.unwatchKey = unwatchKey;
-
- Ember.flushPendingChains = flushPendingChains;
- Ember.removeChainWatcher = removeChainWatcher;
- Ember._ChainNode = ChainNode;
- Ember.finishChains = finishChains;
-
- Ember.watchPath = watchPath;
- Ember.unwatchPath = unwatchPath;
-
- Ember.watch = watch;
- Ember.isWatching = isWatching;
- Ember.unwatch = unwatch;
- Ember.rewatch = rewatch;
- Ember.destroy = destroy;
-
- Ember.expandProperties = expandProperties;
-
- Ember.ComputedProperty = ComputedProperty;
- Ember.computed = computed;
- Ember.cacheFor = cacheFor;
-
- Ember.addObserver = addObserver;
- Ember.observersFor = observersFor;
- Ember.removeObserver = removeObserver;
- Ember.addBeforeObserver = addBeforeObserver;
- Ember._suspendBeforeObserver = _suspendBeforeObserver;
- Ember._suspendBeforeObservers = _suspendBeforeObservers;
- Ember._suspendObserver = _suspendObserver;
- Ember._suspendObservers = _suspendObservers;
- Ember.beforeObserversFor = beforeObserversFor;
- Ember.removeBeforeObserver = removeBeforeObserver;
-
- Ember.IS_BINDING = IS_BINDING;
- Ember.required = required;
- Ember.aliasMethod = aliasMethod;
- Ember.observer = observer;
- Ember.immediateObserver = immediateObserver;
- Ember.beforeObserver = beforeObserver;
- Ember.mixin = mixin;
- Ember.Mixin = Mixin;
-
- Ember.oneWay = oneWay;
- Ember.bind = bind;
- Ember.Binding = Binding;
- Ember.isGlobalPath = isGlobalPath;
-
- Ember.run = run;
-
- Ember.libraries = libraries;
- Ember.libraries.registerCoreLibrary('Ember', Ember.VERSION);
-
- Ember.isNone = isNone;
- Ember.isEmpty = isEmpty;
- Ember.isBlank = isBlank;
-
-
- Ember.isPresent = isPresent;
-
-
- Ember.merge = merge;
-
- /**
- A function may be assigned to `Ember.onerror` to be called when Ember
- internals encounter an error. This is useful for specialized error handling
- and reporting code.
-
- ```javascript
- Ember.onerror = function(error) {
- Em.$.ajax('/report-error', 'POST', {
- stack: error.stack,
- otherInformation: 'whatever app state you want to provide'
- });
- };
- ```
-
- Internally, `Ember.onerror` is used as Backburner's error handler.
-
- @event onerror
- @for Ember
- @param {Exception} error the error object
- */
- Ember.onerror = null;
- // END EXPORTS
-
- // do this for side-effects of updating Ember.assert, warn, etc when
- // ember-debug is present
- if (Ember.__loader.registry['ember-debug']) {
- requireModule('ember-debug');
- }
-
- __exports__["default"] = Ember;
- });
-enifed("ember-metal/alias",
- ["ember-metal/property_get","ember-metal/property_set","ember-metal/core","ember-metal/error","ember-metal/properties","ember-metal/computed","ember-metal/platform","ember-metal/utils","ember-metal/dependent_keys","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __exports__) {
- "use strict";
- var get = __dependency1__.get;
- var set = __dependency2__.set;
- var Ember = __dependency3__["default"];
- // Ember.assert
- var EmberError = __dependency4__["default"];
- var Descriptor = __dependency5__.Descriptor;
- var defineProperty = __dependency5__.defineProperty;
- var ComputedProperty = __dependency6__.ComputedProperty;
- var create = __dependency7__.create;
- var meta = __dependency8__.meta;
- var inspect = __dependency8__.inspect;
- var addDependentKeys = __dependency9__.addDependentKeys;
- var removeDependentKeys = __dependency9__.removeDependentKeys;
-
- __exports__["default"] = function alias(altKey) {
- return new AliasedProperty(altKey);
- }
-
- function AliasedProperty(altKey) {
- this.altKey = altKey;
- this._dependentKeys = [ altKey ];
- }
-
- __exports__.AliasedProperty = AliasedProperty;AliasedProperty.prototype = create(Descriptor.prototype);
-
- AliasedProperty.prototype.get = function AliasedProperty_get(obj, keyName) {
- return get(obj, this.altKey);
- };
-
- AliasedProperty.prototype.set = function AliasedProperty_set(obj, keyName, value) {
- return set(obj, this.altKey, value);
- };
-
- AliasedProperty.prototype.willWatch = function(obj, keyName) {
- addDependentKeys(this, obj, keyName, meta(obj));
- };
-
- AliasedProperty.prototype.didUnwatch = function(obj, keyName) {
- removeDependentKeys(this, obj, keyName, meta(obj));
- };
-
- AliasedProperty.prototype.setup = function(obj, keyName) {
- Ember.assert("Setting alias '" + keyName + "' on self", this.altKey !== keyName);
- var m = meta(obj);
- if (m.watching[keyName]) {
- addDependentKeys(this, obj, keyName, m);
- }
- };
-
- AliasedProperty.prototype.teardown = function(obj, keyName) {
- var m = meta(obj);
- if (m.watching[keyName]) {
- removeDependentKeys(this, obj, keyName, m);
- }
- };
-
- AliasedProperty.prototype.readOnly = function() {
- this.set = AliasedProperty_readOnlySet;
- return this;
- };
-
- function AliasedProperty_readOnlySet(obj, keyName, value) {
- throw new EmberError('Cannot set read-only property "' + keyName + '" on object: ' + inspect(obj));
- }
-
- AliasedProperty.prototype.oneWay = function() {
- this.set = AliasedProperty_oneWaySet;
- return this;
- };
-
- function AliasedProperty_oneWaySet(obj, keyName, value) {
- defineProperty(obj, keyName, null);
- return set(obj, keyName, value);
- }
-
- // Backwards compatibility with Ember Data
- AliasedProperty.prototype._meta = undefined;
- AliasedProperty.prototype.meta = ComputedProperty.prototype.meta;
- });
-enifed("ember-metal/array",
- ["exports"],
- function(__exports__) {
- "use strict";
- /**
- @module ember-metal
- */
-
- var ArrayPrototype = Array.prototype;
-
- // Testing this is not ideal, but we want to use native functions
- // if available, but not to use versions created by libraries like Prototype
- var isNativeFunc = function(func) {
- // This should probably work in all browsers likely to have ES5 array methods
- return func && Function.prototype.toString.call(func).indexOf('[native code]') > -1;
- };
-
- var defineNativeShim = function(nativeFunc, shim) {
- if (isNativeFunc(nativeFunc)) {
- return nativeFunc;
- }
- return shim;
- };
-
- // From: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/array/map
- var map = defineNativeShim(ArrayPrototype.map, function(fun /*, thisp */) {
- //"use strict";
-
- if (this === void 0 || this === null || typeof fun !== "function") {
- throw new TypeError();
- }
-
- var t = Object(this);
- var len = t.length >>> 0;
- var res = new Array(len);
- var thisp = arguments[1];
-
- for (var i = 0; i < len; i++) {
- if (i in t) {
- res[i] = fun.call(thisp, t[i], i, t);
- }
- }
-
- return res;
- });
-
- // From: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/array/foreach
- var forEach = defineNativeShim(ArrayPrototype.forEach, function(fun /*, thisp */) {
- //"use strict";
-
- if (this === void 0 || this === null || typeof fun !== "function") {
- throw new TypeError();
- }
-
- var t = Object(this);
- var len = t.length >>> 0;
- var thisp = arguments[1];
-
- for (var i = 0; i < len; i++) {
- if (i in t) {
- fun.call(thisp, t[i], i, t);
- }
- }
- });
-
- var indexOf = defineNativeShim(ArrayPrototype.indexOf, function (obj, fromIndex) {
- if (fromIndex === null || fromIndex === undefined) {
- fromIndex = 0;
- }
- else if (fromIndex < 0) {
- fromIndex = Math.max(0, this.length + fromIndex);
- }
-
- for (var i = fromIndex, j = this.length; i < j; i++) {
- if (this[i] === obj) {
- return i;
- }
- }
- return -1;
- });
-
- var lastIndexOf = defineNativeShim(ArrayPrototype.lastIndexOf, function(obj, fromIndex) {
- var len = this.length;
- var idx;
-
- if (fromIndex === undefined) fromIndex = len-1;
- else fromIndex = (fromIndex < 0) ? Math.ceil(fromIndex) : Math.floor(fromIndex);
- if (fromIndex < 0) fromIndex += len;
-
- for(idx = fromIndex;idx>=0;idx--) {
- if (this[idx] === obj) return idx ;
- }
- return -1;
- });
-
- var filter = defineNativeShim(ArrayPrototype.filter, function (fn, context) {
- var i, value;
- var result = [];
- var length = this.length;
-
- for (i = 0; i < length; i++) {
- if (this.hasOwnProperty(i)) {
- value = this[i];
- if (fn.call(context, value, i, this)) {
- result.push(value);
- }
- }
- }
- return result;
- });
-
- if (Ember.SHIM_ES5) {
- ArrayPrototype.map = ArrayPrototype.map || map;
- ArrayPrototype.forEach = ArrayPrototype.forEach || forEach;
- ArrayPrototype.filter = ArrayPrototype.filter || filter;
- ArrayPrototype.indexOf = ArrayPrototype.indexOf || indexOf;
- ArrayPrototype.lastIndexOf = ArrayPrototype.lastIndexOf || lastIndexOf;
- }
-
- /**
- Array polyfills to support ES5 features in older browsers.
-
- @namespace Ember
- @property ArrayPolyfills
- */
- __exports__.map = map;
- __exports__.forEach = forEach;
- __exports__.filter = filter;
- __exports__.indexOf = indexOf;
- __exports__.lastIndexOf = lastIndexOf;
- });
-enifed("ember-metal/binding",
- ["ember-metal/core","ember-metal/property_get","ember-metal/property_set","ember-metal/utils","ember-metal/observer","ember-metal/run_loop","ember-metal/path_cache","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __exports__) {
- "use strict";
- var Ember = __dependency1__["default"];
- // Ember.Logger, Ember.LOG_BINDINGS, assert
- var get = __dependency2__.get;
- var trySet = __dependency3__.trySet;
- var guidFor = __dependency4__.guidFor;
- var addObserver = __dependency5__.addObserver;
- var removeObserver = __dependency5__.removeObserver;
- var _suspendObserver = __dependency5__._suspendObserver;
- var run = __dependency6__["default"];
- var isGlobalPath = __dependency7__.isGlobal;
-
-
- // ES6TODO: where is Ember.lookup defined?
- /**
- @module ember-metal
- */
-
- // ..........................................................
- // CONSTANTS
- //
-
- /**
- Debug parameter you can turn on. This will log all bindings that fire to
- the console. This should be disabled in production code. Note that you
- can also enable this from the console or temporarily.
-
- @property LOG_BINDINGS
- @for Ember
- @type Boolean
- @default false
- */
- Ember.LOG_BINDINGS = false || !!Ember.ENV.LOG_BINDINGS;
-
- /**
- Returns true if the provided path is global (e.g., `MyApp.fooController.bar`)
- instead of local (`foo.bar.baz`).
-
- @method isGlobalPath
- @for Ember
- @private
- @param {String} path
- @return Boolean
- */
-
- function getWithGlobals(obj, path) {
- return get(isGlobalPath(path) ? Ember.lookup : obj, path);
- }
-
- // ..........................................................
- // BINDING
- //
-
- function Binding(toPath, fromPath) {
- this._direction = undefined;
- this._from = fromPath;
- this._to = toPath;
- this._readyToSync = undefined;
- this._oneWay = undefined;
- }
-
- /**
- @class Binding
- @namespace Ember
- */
-
- Binding.prototype = {
- /**
- This copies the Binding so it can be connected to another object.
-
- @method copy
- @return {Ember.Binding} `this`
- */
- copy: function () {
- var copy = new Binding(this._to, this._from);
- if (this._oneWay) { copy._oneWay = true; }
- return copy;
- },
-
- // ..........................................................
- // CONFIG
- //
-
- /**
- This will set `from` property path to the specified value. It will not
- attempt to resolve this property path to an actual object until you
- connect the binding.
-
- The binding will search for the property path starting at the root object
- you pass when you `connect()` the binding. It follows the same rules as
- `get()` - see that method for more information.
-
- @method from
- @param {String} path the property path to connect to
- @return {Ember.Binding} `this`
- */
- from: function(path) {
- this._from = path;
- return this;
- },
-
- /**
- This will set the `to` property path to the specified value. It will not
- attempt to resolve this property path to an actual object until you
- connect the binding.
-
- The binding will search for the property path starting at the root object
- you pass when you `connect()` the binding. It follows the same rules as
- `get()` - see that method for more information.
-
- @method to
- @param {String|Tuple} path A property path or tuple
- @return {Ember.Binding} `this`
- */
- to: function(path) {
- this._to = path;
- return this;
- },
-
- /**
- Configures the binding as one way. A one-way binding will relay changes
- on the `from` side to the `to` side, but not the other way around. This
- means that if you change the `to` side directly, the `from` side may have
- a different value.
-
- @method oneWay
- @return {Ember.Binding} `this`
- */
- oneWay: function() {
- this._oneWay = true;
- return this;
- },
-
- /**
- @method toString
- @return {String} string representation of binding
- */
- toString: function() {
- var oneWay = this._oneWay ? '[oneWay]' : '';
- return "Ember.Binding<" + guidFor(this) + ">(" + this._from + " -> " + this._to + ")" + oneWay;
- },
-
- // ..........................................................
- // CONNECT AND SYNC
- //
-
- /**
- Attempts to connect this binding instance so that it can receive and relay
- changes. This method will raise an exception if you have not set the
- from/to properties yet.
-
- @method connect
- @param {Object} obj The root object for this binding.
- @return {Ember.Binding} `this`
- */
- connect: function(obj) {
- Ember.assert('Must pass a valid object to Ember.Binding.connect()', !!obj);
-
- var fromPath = this._from;
- var toPath = this._to;
- trySet(obj, toPath, getWithGlobals(obj, fromPath));
-
- // add an observer on the object to be notified when the binding should be updated
- addObserver(obj, fromPath, this, this.fromDidChange);
-
- // if the binding is a two-way binding, also set up an observer on the target
- if (!this._oneWay) {
- addObserver(obj, toPath, this, this.toDidChange);
- }
-
- this._readyToSync = true;
-
- return this;
- },
-
- /**
- Disconnects the binding instance. Changes will no longer be relayed. You
- will not usually need to call this method.
-
- @method disconnect
- @param {Object} obj The root object you passed when connecting the binding.
- @return {Ember.Binding} `this`
- */
- disconnect: function(obj) {
- Ember.assert('Must pass a valid object to Ember.Binding.disconnect()', !!obj);
-
- var twoWay = !this._oneWay;
-
- // remove an observer on the object so we're no longer notified of
- // changes that should update bindings.
- removeObserver(obj, this._from, this, this.fromDidChange);
-
- // if the binding is two-way, remove the observer from the target as well
- if (twoWay) {
- removeObserver(obj, this._to, this, this.toDidChange);
- }
-
- this._readyToSync = false; // disable scheduled syncs...
- return this;
- },
-
- // ..........................................................
- // PRIVATE
- //
-
- /* called when the from side changes */
- fromDidChange: function(target) {
- this._scheduleSync(target, 'fwd');
- },
-
- /* called when the to side changes */
- toDidChange: function(target) {
- this._scheduleSync(target, 'back');
- },
-
- _scheduleSync: function(obj, dir) {
- var existingDir = this._direction;
-
- // if we haven't scheduled the binding yet, schedule it
- if (existingDir === undefined) {
- run.schedule('sync', this, this._sync, obj);
- this._direction = dir;
- }
-
- // If both a 'back' and 'fwd' sync have been scheduled on the same object,
- // default to a 'fwd' sync so that it remains deterministic.
- if (existingDir === 'back' && dir === 'fwd') {
- this._direction = 'fwd';
- }
- },
-
- _sync: function(obj) {
- var log = Ember.LOG_BINDINGS;
-
- // don't synchronize destroyed objects or disconnected bindings
- if (obj.isDestroyed || !this._readyToSync) { return; }
-
- // get the direction of the binding for the object we are
- // synchronizing from
- var direction = this._direction;
-
- var fromPath = this._from;
- var toPath = this._to;
-
- this._direction = undefined;
-
- // if we're synchronizing from the remote object...
- if (direction === 'fwd') {
- var fromValue = getWithGlobals(obj, this._from);
- if (log) {
- Ember.Logger.log(' ', this.toString(), '->', fromValue, obj);
- }
- if (this._oneWay) {
- trySet(obj, toPath, fromValue);
- } else {
- _suspendObserver(obj, toPath, this, this.toDidChange, function () {
- trySet(obj, toPath, fromValue);
- });
- }
- // if we're synchronizing *to* the remote object
- } else if (direction === 'back') {
- var toValue = get(obj, this._to);
- if (log) {
- Ember.Logger.log(' ', this.toString(), '<-', toValue, obj);
- }
- _suspendObserver(obj, fromPath, this, this.fromDidChange, function () {
- trySet(isGlobalPath(fromPath) ? Ember.lookup : obj, fromPath, toValue);
- });
- }
- }
-
- };
-
- function mixinProperties(to, from) {
- for (var key in from) {
- if (from.hasOwnProperty(key)) {
- to[key] = from[key];
- }
- }
- }
-
- mixinProperties(Binding, {
-
- /*
- See `Ember.Binding.from`.
-
- @method from
- @static
- */
- from: function(from) {
- var C = this;
- return new C(undefined, from);
- },
-
- /*
- See `Ember.Binding.to`.
-
- @method to
- @static
- */
- to: function(to) {
- var C = this;
- return new C(to, undefined);
- },
-
- /**
- Creates a new Binding instance and makes it apply in a single direction.
- A one-way binding will relay changes on the `from` side object (supplied
- as the `from` argument) the `to` side, but not the other way around.
- This means that if you change the "to" side directly, the "from" side may have
- a different value.
-
- See `Binding.oneWay`.
-
- @method oneWay
- @param {String} from from path.
- @param {Boolean} [flag] (Optional) passing nothing here will make the
- binding `oneWay`. You can instead pass `false` to disable `oneWay`, making the
- binding two way again.
- @return {Ember.Binding} `this`
- */
- oneWay: function(from, flag) {
- var C = this;
- return new C(undefined, from).oneWay(flag);
- }
-
- });
- /**
- An `Ember.Binding` connects the properties of two objects so that whenever
- the value of one property changes, the other property will be changed also.
-
- ## Automatic Creation of Bindings with `/^*Binding/`-named Properties
-
- You do not usually create Binding objects directly but instead describe
- bindings in your class or object definition using automatic binding
- detection.
-
- Properties ending in a `Binding` suffix will be converted to `Ember.Binding`
- instances. The value of this property should be a string representing a path
- to another object or a custom binding instance created using Binding helpers
- (see "One Way Bindings"):
-
- ```
- valueBinding: "MyApp.someController.title"
- ```
-
- This will create a binding from `MyApp.someController.title` to the `value`
- property of your object instance automatically. Now the two values will be
- kept in sync.
-
- ## One Way Bindings
-
- One especially useful binding customization you can use is the `oneWay()`
- helper. This helper tells Ember that you are only interested in
- receiving changes on the object you are binding from. For example, if you
- are binding to a preference and you want to be notified if the preference
- has changed, but your object will not be changing the preference itself, you
- could do:
-
- ```
- bigTitlesBinding: Ember.Binding.oneWay("MyApp.preferencesController.bigTitles")
- ```
-
- This way if the value of `MyApp.preferencesController.bigTitles` changes the
- `bigTitles` property of your object will change also. However, if you
- change the value of your `bigTitles` property, it will not update the
- `preferencesController`.
-
- One way bindings are almost twice as fast to setup and twice as fast to
- execute because the binding only has to worry about changes to one side.
-
- You should consider using one way bindings anytime you have an object that
- may be created frequently and you do not intend to change a property; only
- to monitor it for changes (such as in the example above).
-
- ## Adding Bindings Manually
-
- All of the examples above show you how to configure a custom binding, but the
- result of these customizations will be a binding template, not a fully active
- Binding instance. The binding will actually become active only when you
- instantiate the object the binding belongs to. It is useful however, to
- understand what actually happens when the binding is activated.
-
- For a binding to function it must have at least a `from` property and a `to`
- property. The `from` property path points to the object/key that you want to
- bind from while the `to` path points to the object/key you want to bind to.
-
- When you define a custom binding, you are usually describing the property
- you want to bind from (such as `MyApp.someController.value` in the examples
- above). When your object is created, it will automatically assign the value
- you want to bind `to` based on the name of your binding key. In the
- examples above, during init, Ember objects will effectively call
- something like this on your binding:
-
- ```javascript
- binding = Ember.Binding.from("valueBinding").to("value");
- ```
-
- This creates a new binding instance based on the template you provide, and
- sets the to path to the `value` property of the new object. Now that the
- binding is fully configured with a `from` and a `to`, it simply needs to be
- connected to become active. This is done through the `connect()` method:
-
- ```javascript
- binding.connect(this);
- ```
-
- Note that when you connect a binding you pass the object you want it to be
- connected to. This object will be used as the root for both the from and
- to side of the binding when inspecting relative paths. This allows the
- binding to be automatically inherited by subclassed objects as well.
-
- This also allows you to bind between objects using the paths you declare in
- `from` and `to`:
-
- ```javascript
- // Example 1
- binding = Ember.Binding.from("App.someObject.value").to("value");
- binding.connect(this);
-
- // Example 2
- binding = Ember.Binding.from("parentView.value").to("App.someObject.value");
- binding.connect(this);
- ```
-
- Now that the binding is connected, it will observe both the from and to side
- and relay changes.
-
- If you ever needed to do so (you almost never will, but it is useful to
- understand this anyway), you could manually create an active binding by
- using the `Ember.bind()` helper method. (This is the same method used by
- to setup your bindings on objects):
-
- ```javascript
- Ember.bind(MyApp.anotherObject, "value", "MyApp.someController.value");
- ```
-
- Both of these code fragments have the same effect as doing the most friendly
- form of binding creation like so:
-
- ```javascript
- MyApp.anotherObject = Ember.Object.create({
- valueBinding: "MyApp.someController.value",
-
- // OTHER CODE FOR THIS OBJECT...
- });
- ```
-
- Ember's built in binding creation method makes it easy to automatically
- create bindings for you. You should always use the highest-level APIs
- available, even if you understand how it works underneath.
-
- @class Binding
- @namespace Ember
- @since Ember 0.9
- */
- // Ember.Binding = Binding; ES6TODO: where to put this?
-
-
- /**
- Global helper method to create a new binding. Just pass the root object
- along with a `to` and `from` path to create and connect the binding.
-
- @method bind
- @for Ember
- @param {Object} obj The root object of the transform.
- @param {String} to The path to the 'to' side of the binding.
- Must be relative to obj.
- @param {String} from The path to the 'from' side of the binding.
- Must be relative to obj or a global path.
- @return {Ember.Binding} binding instance
- */
- function bind(obj, to, from) {
- return new Binding(to, from).connect(obj);
- }
-
- __exports__.bind = bind;/**
- @method oneWay
- @for Ember
- @param {Object} obj The root object of the transform.
- @param {String} to The path to the 'to' side of the binding.
- Must be relative to obj.
- @param {String} from The path to the 'from' side of the binding.
- Must be relative to obj or a global path.
- @return {Ember.Binding} binding instance
- */
- function oneWay(obj, to, from) {
- return new Binding(to, from).oneWay().connect(obj);
- }
-
- __exports__.oneWay = oneWay;__exports__.Binding = Binding;
- __exports__.isGlobalPath = isGlobalPath;
- });
-enifed("ember-metal/cache",
- ["ember-metal/dictionary","exports"],
- function(__dependency1__, __exports__) {
- "use strict";
- var dictionary = __dependency1__["default"];
- __exports__["default"] = Cache;
-
- function Cache(limit, func) {
- this.store = dictionary(null);
- this.size = 0;
- this.misses = 0;
- this.hits = 0;
- this.limit = limit;
- this.func = func;
- }
-
- var UNDEFINED = function() { };
-
- Cache.prototype = {
- set: function(key, value) {
- if (this.limit > this.size) {
- this.size ++;
- if (value === undefined) {
- this.store[key] = UNDEFINED;
- } else {
- this.store[key] = value;
- }
- }
-
- return value;
- },
-
- get: function(key) {
- var value = this.store[key];
-
- if (value === undefined) {
- this.misses ++;
- value = this.set(key, this.func(key));
- } else if (value === UNDEFINED) {
- this.hits ++;
- value = undefined;
- } else {
- this.hits ++;
- // nothing to translate
- }
-
- return value;
- },
-
- purge: function() {
- this.store = dictionary(null);
- this.size = 0;
- this.hits = 0;
- this.misses = 0;
- }
- };
- });
-enifed("ember-metal/chains",
- ["ember-metal/core","ember-metal/property_get","ember-metal/utils","ember-metal/array","ember-metal/watch_key","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) {
- "use strict";
- var Ember = __dependency1__["default"];
- // warn, assert, etc;
- var get = __dependency2__.get;
- var normalizeTuple = __dependency2__.normalizeTuple;
- var metaFor = __dependency3__.meta;
- var forEach = __dependency4__.forEach;
- var watchKey = __dependency5__.watchKey;
- var unwatchKey = __dependency5__.unwatchKey;
-
- var warn = Ember.warn;
- var FIRST_KEY = /^([^\.]+)/;
-
- function firstKey(path) {
- return path.match(FIRST_KEY)[0];
- }
-
- var pendingQueue = [];
-
- // attempts to add the pendingQueue chains again. If some of them end up
- // back in the queue and reschedule is true, schedules a timeout to try
- // again.
- function flushPendingChains() {
- if (pendingQueue.length === 0) { return; } // nothing to do
-
- var queue = pendingQueue;
- pendingQueue = [];
-
- forEach.call(queue, function(q) {
- q[0].add(q[1]);
- });
-
- warn('Watching an undefined global, Ember expects watched globals to be' +
- ' setup by the time the run loop is flushed, check for typos', pendingQueue.length === 0);
- }
-
- __exports__.flushPendingChains = flushPendingChains;function addChainWatcher(obj, keyName, node) {
- if (!obj || ('object' !== typeof obj)) { return; } // nothing to do
-
- var m = metaFor(obj);
- var nodes = m.chainWatchers;
-
- if (!m.hasOwnProperty('chainWatchers')) {
- nodes = m.chainWatchers = {};
- }
-
- if (!nodes[keyName]) {
- nodes[keyName] = [];
- }
- nodes[keyName].push(node);
- watchKey(obj, keyName, m);
- }
-
- function removeChainWatcher(obj, keyName, node) {
- if (!obj || 'object' !== typeof obj) { return; } // nothing to do
-
- var m = obj['__ember_meta__'];
- if (m && !m.hasOwnProperty('chainWatchers')) { return; } // nothing to do
-
- var nodes = m && m.chainWatchers;
-
- if (nodes && nodes[keyName]) {
- nodes = nodes[keyName];
- for (var i = 0, l = nodes.length; i < l; i++) {
- if (nodes[i] === node) {
- nodes.splice(i, 1);
- break;
- }
- }
- }
- unwatchKey(obj, keyName, m);
- }
-
- // A ChainNode watches a single key on an object. If you provide a starting
- // value for the key then the node won't actually watch it. For a root node
- // pass null for parent and key and object for value.
- function ChainNode(parent, key, value) {
- this._parent = parent;
- this._key = key;
-
- // _watching is true when calling get(this._parent, this._key) will
- // return the value of this node.
- //
- // It is false for the root of a chain (because we have no parent)
- // and for global paths (because the parent node is the object with
- // the observer on it)
- this._watching = value===undefined;
-
- this._value = value;
- this._paths = {};
- if (this._watching) {
- this._object = parent.value();
- if (this._object) {
- addChainWatcher(this._object, this._key, this);
- }
- }
-
- // Special-case: the EachProxy relies on immediate evaluation to
- // establish its observers.
- //
- // TODO: Replace this with an efficient callback that the EachProxy
- // can implement.
- if (this._parent && this._parent._key === '@each') {
- this.value();
- }
- }
-
- var ChainNodePrototype = ChainNode.prototype;
-
- function lazyGet(obj, key) {
- if (!obj) return undefined;
-
- var meta = obj['__ember_meta__'];
- // check if object meant only to be a prototype
- if (meta && meta.proto === obj) {
- return undefined;
- }
-
- if (key === "@each") {
- return get(obj, key);
- }
-
- // if a CP only return cached value
- var desc = meta && meta.descs[key];
- if (desc && desc._cacheable) {
- if (key in meta.cache) {
- return meta.cache[key];
- } else {
- return undefined;
- }
- }
-
- return get(obj, key);
- }
-
- ChainNodePrototype.value = function() {
- if (this._value === undefined && this._watching) {
- var obj = this._parent.value();
- this._value = lazyGet(obj, this._key);
- }
- return this._value;
- };
-
- ChainNodePrototype.destroy = function() {
- if (this._watching) {
- var obj = this._object;
- if (obj) {
- removeChainWatcher(obj, this._key, this);
- }
- this._watching = false; // so future calls do nothing
- }
- };
-
- // copies a top level object only
- ChainNodePrototype.copy = function(obj) {
- var ret = new ChainNode(null, null, obj);
- var paths = this._paths;
- var path;
-
- for (path in paths) {
- // this check will also catch non-number vals.
- if (paths[path] <= 0) {
- continue;
- }
- ret.add(path);
- }
- return ret;
- };
-
- // called on the root node of a chain to setup watchers on the specified
- // path.
- ChainNodePrototype.add = function(path) {
- var obj, tuple, key, src, paths;
-
- paths = this._paths;
- paths[path] = (paths[path] || 0) + 1;
-
- obj = this.value();
- tuple = normalizeTuple(obj, path);
-
- // the path was a local path
- if (tuple[0] && tuple[0] === obj) {
- path = tuple[1];
- key = firstKey(path);
- path = path.slice(key.length+1);
-
- // global path, but object does not exist yet.
- // put into a queue and try to connect later.
- } else if (!tuple[0]) {
- pendingQueue.push([this, path]);
- tuple.length = 0;
- return;
-
- // global path, and object already exists
- } else {
- src = tuple[0];
- key = path.slice(0, 0-(tuple[1].length+1));
- path = tuple[1];
- }
-
- tuple.length = 0;
- this.chain(key, path, src);
- };
-
- // called on the root node of a chain to teardown watcher on the specified
- // path
- ChainNodePrototype.remove = function(path) {
- var obj, tuple, key, src, paths;
-
- paths = this._paths;
- if (paths[path] > 0) {
- paths[path]--;
- }
-
- obj = this.value();
- tuple = normalizeTuple(obj, path);
- if (tuple[0] === obj) {
- path = tuple[1];
- key = firstKey(path);
- path = path.slice(key.length+1);
- } else {
- src = tuple[0];
- key = path.slice(0, 0-(tuple[1].length+1));
- path = tuple[1];
- }
-
- tuple.length = 0;
- this.unchain(key, path);
- };
-
- ChainNodePrototype.count = 0;
-
- ChainNodePrototype.chain = function(key, path, src) {
- var chains = this._chains;
- var node;
- if (!chains) {
- chains = this._chains = {};
- }
-
- node = chains[key];
- if (!node) {
- node = chains[key] = new ChainNode(this, key, src);
- }
- node.count++; // count chains...
-
- // chain rest of path if there is one
- if (path) {
- key = firstKey(path);
- path = path.slice(key.length+1);
- node.chain(key, path); // NOTE: no src means it will observe changes...
- }
- };
-
- ChainNodePrototype.unchain = function(key, path) {
- var chains = this._chains;
- var node = chains[key];
-
- // unchain rest of path first...
- if (path && path.length > 1) {
- var nextKey = firstKey(path);
- var nextPath = path.slice(nextKey.length + 1);
- node.unchain(nextKey, nextPath);
- }
-
- // delete node if needed.
- node.count--;
- if (node.count<=0) {
- delete chains[node._key];
- node.destroy();
- }
-
- };
-
- ChainNodePrototype.willChange = function(events) {
- var chains = this._chains;
- if (chains) {
- for(var key in chains) {
- if (!chains.hasOwnProperty(key)) {
- continue;
- }
- chains[key].willChange(events);
- }
- }
-
- if (this._parent) {
- this._parent.chainWillChange(this, this._key, 1, events);
- }
- };
-
- ChainNodePrototype.chainWillChange = function(chain, path, depth, events) {
- if (this._key) {
- path = this._key + '.' + path;
- }
-
- if (this._parent) {
- this._parent.chainWillChange(this, path, depth+1, events);
- } else {
- if (depth > 1) {
- events.push(this.value(), path);
- }
- path = 'this.' + path;
- if (this._paths[path] > 0) {
- events.push(this.value(), path);
- }
- }
- };
-
- ChainNodePrototype.chainDidChange = function(chain, path, depth, events) {
- if (this._key) {
- path = this._key + '.' + path;
- }
-
- if (this._parent) {
- this._parent.chainDidChange(this, path, depth+1, events);
- } else {
- if (depth > 1) {
- events.push(this.value(), path);
- }
- path = 'this.' + path;
- if (this._paths[path] > 0) {
- events.push(this.value(), path);
- }
- }
- };
-
- ChainNodePrototype.didChange = function(events) {
- // invalidate my own value first.
- if (this._watching) {
- var obj = this._parent.value();
- if (obj !== this._object) {
- removeChainWatcher(this._object, this._key, this);
- this._object = obj;
- addChainWatcher(obj, this._key, this);
- }
- this._value = undefined;
-
- // Special-case: the EachProxy relies on immediate evaluation to
- // establish its observers.
- if (this._parent && this._parent._key === '@each') {
- this.value();
- }
- }
-
- // then notify chains...
- var chains = this._chains;
- if (chains) {
- for(var key in chains) {
- if (!chains.hasOwnProperty(key)) { continue; }
- chains[key].didChange(events);
- }
- }
-
- // if no events are passed in then we only care about the above wiring update
- if (events === null) {
- return;
- }
-
- // and finally tell parent about my path changing...
- if (this._parent) {
- this._parent.chainDidChange(this, this._key, 1, events);
- }
- };
-
- function finishChains(obj) {
- // We only create meta if we really have to
- var m = obj['__ember_meta__'];
- var chains, chainWatchers, chainNodes;
-
- if (m) {
- // finish any current chains node watchers that reference obj
- chainWatchers = m.chainWatchers;
- if (chainWatchers) {
- for(var key in chainWatchers) {
- if (!chainWatchers.hasOwnProperty(key)) {
- continue;
- }
-
- chainNodes = chainWatchers[key];
- if (chainNodes) {
- for (var i=0,l=chainNodes.length;i<l;i++) {
- chainNodes[i].didChange(null);
- }
- }
- }
- }
- // copy chains from prototype
- chains = m.chains;
- if (chains && chains.value() !== obj) {
- metaFor(obj).chains = chains = chains.copy(obj);
- }
- }
- }
-
- __exports__.finishChains = finishChains;__exports__.removeChainWatcher = removeChainWatcher;
- __exports__.ChainNode = ChainNode;
- });
-enifed("ember-metal/computed",
- ["ember-metal/property_set","ember-metal/utils","ember-metal/expand_properties","ember-metal/error","ember-metal/properties","ember-metal/property_events","ember-metal/dependent_keys","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __exports__) {
- "use strict";
- var set = __dependency1__.set;
- var meta = __dependency2__.meta;
- var inspect = __dependency2__.inspect;
- var expandProperties = __dependency3__["default"];
- var EmberError = __dependency4__["default"];
- var Descriptor = __dependency5__.Descriptor;
- var defineProperty = __dependency5__.defineProperty;
- var propertyWillChange = __dependency6__.propertyWillChange;
- var propertyDidChange = __dependency6__.propertyDidChange;
- var addDependentKeys = __dependency7__.addDependentKeys;
- var removeDependentKeys = __dependency7__.removeDependentKeys;
-
- /**
- @module ember-metal
- */
-
- Ember.warn("The CP_DEFAULT_CACHEABLE flag has been removed and computed properties" +
- "are always cached by default. Use `volatile` if you don't want caching.", Ember.ENV.CP_DEFAULT_CACHEABLE !== false);
-
- var metaFor = meta;
- var a_slice = [].slice;
-
- function UNDEFINED() { }
-
- // ..........................................................
- // COMPUTED PROPERTY
- //
-
- /**
- A computed property transforms an object's function into a property.
-
- By default the function backing the computed property will only be called
- once and the result will be cached. You can specify various properties
- that your computed property depends on. This will force the cached
- result to be recomputed if the dependencies are modified.
-
- In the following example we declare a computed property (by calling
- `.property()` on the fullName function) and setup the property
- dependencies (depending on firstName and lastName). The fullName function
- will be called once (regardless of how many times it is accessed) as long
- as its dependencies have not changed. Once firstName or lastName are updated
- any future calls (or anything bound) to fullName will incorporate the new
- values.
-
- ```javascript
- var Person = Ember.Object.extend({
- // these will be supplied by `create`
- firstName: null,
- lastName: null,
-
- fullName: function() {
- var firstName = this.get('firstName');
- var lastName = this.get('lastName');
-
- return firstName + ' ' + lastName;
- }.property('firstName', 'lastName')
- });
-
- var tom = Person.create({
- firstName: 'Tom',
- lastName: 'Dale'
- });
-
- tom.get('fullName') // 'Tom Dale'
- ```
-
- You can also define what Ember should do when setting a computed property.
- If you try to set a computed property, it will be invoked with the key and
- value you want to set it to. You can also accept the previous value as the
- third parameter.
-
- ```javascript
- var Person = Ember.Object.extend({
- // these will be supplied by `create`
- firstName: null,
- lastName: null,
-
- fullName: function(key, value, oldValue) {
- // getter
- if (arguments.length === 1) {
- var firstName = this.get('firstName');
- var lastName = this.get('lastName');
-
- return firstName + ' ' + lastName;
-
- // setter
- } else {
- var name = value.split(' ');
-
- this.set('firstName', name[0]);
- this.set('lastName', name[1]);
-
- return value;
- }
- }.property('firstName', 'lastName')
- });
-
- var person = Person.create();
-
- person.set('fullName', 'Peter Wagenet');
- person.get('firstName'); // 'Peter'
- person.get('lastName'); // 'Wagenet'
- ```
-
- @class ComputedProperty
- @namespace Ember
- @extends Ember.Descriptor
- @constructor
- */
- function ComputedProperty(func, opts) {
- func.__ember_arity__ = func.length;
- this.func = func;
-
- this._dependentKeys = undefined;
- this._suspended = undefined;
- this._meta = undefined;
-
- this._cacheable = (opts && opts.cacheable !== undefined) ? opts.cacheable : true;
- this._dependentKeys = opts && opts.dependentKeys;
- this._readOnly = opts && (opts.readOnly !== undefined || !!opts.readOnly) || false;
- }
-
- ComputedProperty.prototype = new Descriptor();
-
- var ComputedPropertyPrototype = ComputedProperty.prototype;
-
- /**
- Properties are cacheable by default. Computed property will automatically
- cache the return value of your function until one of the dependent keys changes.
-
- Call `volatile()` to set it into non-cached mode. When in this mode
- the computed property will not automatically cache the return value.
-
- However, if a property is properly observable, there is no reason to disable
- caching.
-
- @method cacheable
- @param {Boolean} aFlag optional set to `false` to disable caching
- @return {Ember.ComputedProperty} this
- @chainable
- */
- ComputedPropertyPrototype.cacheable = function(aFlag) {
- this._cacheable = aFlag !== false;
- return this;
- };
-
- /**
- Call on a computed property to set it into non-cached mode. When in this
- mode the computed property will not automatically cache the return value.
-
- ```javascript
- var outsideService = Ember.Object.extend({
- value: function() {
- return OutsideService.getValue();
- }.property().volatile()
- }).create();
- ```
-
- @method volatile
- @return {Ember.ComputedProperty} this
- @chainable
- */
- ComputedPropertyPrototype["volatile"] = function() {
- return this.cacheable(false);
- };
-
- /**
- Call on a computed property to set it into read-only mode. When in this
- mode the computed property will throw an error when set.
-
- ```javascript
- var Person = Ember.Object.extend({
- guid: function() {
- return 'guid-guid-guid';
- }.property().readOnly()
- });
-
- var person = Person.create();
-
- person.set('guid', 'new-guid'); // will throw an exception
- ```
-
- @method readOnly
- @return {Ember.ComputedProperty} this
- @chainable
- */
- ComputedPropertyPrototype.readOnly = function(readOnly) {
- this._readOnly = readOnly === undefined || !!readOnly;
- return this;
- };
-
- /**
- Sets the dependent keys on this computed property. Pass any number of
- arguments containing key paths that this computed property depends on.
-
- ```javascript
- var President = Ember.Object.extend({
- fullName: computed(function() {
- return this.get('firstName') + ' ' + this.get('lastName');
-
- // Tell Ember that this computed property depends on firstName
- // and lastName
- }).property('firstName', 'lastName')
- });
-
- var president = President.create({
- firstName: 'Barack',
- lastName: 'Obama'
- });
-
- president.get('fullName'); // 'Barack Obama'
- ```
-
- @method property
- @param {String} path* zero or more property paths
- @return {Ember.ComputedProperty} this
- @chainable
- */
- ComputedPropertyPrototype.property = function() {
- var args;
-
- var addArg = function (property) {
- args.push(property);
- };
-
- args = [];
- for (var i = 0, l = arguments.length; i < l; i++) {
- expandProperties(arguments[i], addArg);
- }
-
- this._dependentKeys = args;
- return this;
- };
-
- /**
- In some cases, you may want to annotate computed properties with additional
- metadata about how they function or what values they operate on. For example,
- computed property functions may close over variables that are then no longer
- available for introspection.
-
- You can pass a hash of these values to a computed property like this:
-
- ```
- person: function() {
- var personId = this.get('personId');
- return App.Person.create({ id: personId });
- }.property().meta({ type: App.Person })
- ```
-
- The hash that you pass to the `meta()` function will be saved on the
- computed property descriptor under the `_meta` key. Ember runtime
- exposes a public API for retrieving these values from classes,
- via the `metaForProperty()` function.
-
- @method meta
- @param {Hash} meta
- @chainable
- */
-
- ComputedPropertyPrototype.meta = function(meta) {
- if (arguments.length === 0) {
- return this._meta || {};
- } else {
- this._meta = meta;
- return this;
- }
- };
-
- /* impl descriptor API */
- ComputedPropertyPrototype.didChange = function(obj, keyName) {
- // _suspended is set via a CP.set to ensure we don't clear
- // the cached value set by the setter
- if (this._cacheable && this._suspended !== obj) {
- var meta = metaFor(obj);
- if (meta.cache[keyName] !== undefined) {
- meta.cache[keyName] = undefined;
- removeDependentKeys(this, obj, keyName, meta);
- }
- }
- };
-
- function finishChains(chainNodes)
- {
- for (var i=0, l=chainNodes.length; i<l; i++) {
- chainNodes[i].didChange(null);
- }
- }
-
- /**
- Access the value of the function backing the computed property.
- If this property has already been cached, return the cached result.
- Otherwise, call the function passing the property name as an argument.
-
- ```javascript
- var Person = Ember.Object.extend({
- fullName: function(keyName) {
- // the keyName parameter is 'fullName' in this case.
- return this.get('firstName') + ' ' + this.get('lastName');
- }.property('firstName', 'lastName')
- });
-
-
- var tom = Person.create({
- firstName: 'Tom',
- lastName: 'Dale'
- });
-
- tom.get('fullName') // 'Tom Dale'
- ```
-
- @method get
- @param {String} keyName The key being accessed.
- @return {Object} The return value of the function backing the CP.
- */
- ComputedPropertyPrototype.get = function(obj, keyName) {
- var ret, cache, meta, chainNodes;
- if (this._cacheable) {
- meta = metaFor(obj);
- cache = meta.cache;
-
- var result = cache[keyName];
-
- if (result === UNDEFINED) {
- return undefined;
- } else if (result !== undefined) {
- return result;
- }
-
- ret = this.func.call(obj, keyName);
- if (ret === undefined) {
- cache[keyName] = UNDEFINED;
- } else {
- cache[keyName] = ret;
- }
-
- chainNodes = meta.chainWatchers && meta.chainWatchers[keyName];
- if (chainNodes) {
- finishChains(chainNodes);
- }
- addDependentKeys(this, obj, keyName, meta);
- } else {
- ret = this.func.call(obj, keyName);
- }
- return ret;
- };
-
- /**
- Set the value of a computed property. If the function that backs your
- computed property does not accept arguments then the default action for
- setting would be to define the property on the current object, and set
- the value of the property to the value being set.
-
- Generally speaking if you intend for your computed property to be set
- your backing function should accept either two or three arguments.
-
- ```javascript
- var Person = Ember.Object.extend({
- // these will be supplied by `create`
- firstName: null,
- lastName: null,
-
- fullName: function(key, value, oldValue) {
- // getter
- if (arguments.length === 1) {
- var firstName = this.get('firstName');
- var lastName = this.get('lastName');
-
- return firstName + ' ' + lastName;
-
- // setter
- } else {
- var name = value.split(' ');
-
- this.set('firstName', name[0]);
- this.set('lastName', name[1]);
-
- return value;
- }
- }.property('firstName', 'lastName')
- });
-
- var person = Person.create();
-
- person.set('fullName', 'Peter Wagenet');
- person.get('firstName'); // 'Peter'
- person.get('lastName'); // 'Wagenet'
- ```
-
- @method set
- @param {String} keyName The key being accessed.
- @param {Object} newValue The new value being assigned.
- @param {String} oldValue The old value being replaced.
- @return {Object} The return value of the function backing the CP.
- */
- ComputedPropertyPrototype.set = function computedPropertySetWithSuspend(obj, keyName, value) {
- var oldSuspended = this._suspended;
-
- this._suspended = obj;
-
- try {
- this._set(obj, keyName, value);
- } finally {
- this._suspended = oldSuspended;
- }
- };
-
- ComputedPropertyPrototype._set = function computedPropertySet(obj, keyName, value) {
- var cacheable = this._cacheable;
- var func = this.func;
- var meta = metaFor(obj, cacheable);
- var cache = meta.cache;
- var hadCachedValue = false;
-
- var funcArgLength, cachedValue, ret;
-
- if (this._readOnly) {
- throw new EmberError('Cannot set read-only property "' + keyName + '" on object: ' + inspect(obj));
- }
-
- if (cacheable && cache[keyName] !== undefined) {
- if(cache[keyName] !== UNDEFINED) {
- cachedValue = cache[keyName];
- }
-
- hadCachedValue = true;
- }
-
- // Check if the CP has been wrapped. If it has, use the
- // length from the wrapped function.
-
- funcArgLength = func.wrappedFunction ? func.wrappedFunction.__ember_arity__ : func.__ember_arity__;
-
- // For backwards-compatibility with computed properties
- // that check for arguments.length === 2 to determine if
- // they are being get or set, only pass the old cached
- // value if the computed property opts into a third
- // argument.
- if (funcArgLength === 3) {
- ret = func.call(obj, keyName, value, cachedValue);
- } else if (funcArgLength === 2) {
- ret = func.call(obj, keyName, value);
- } else {
- defineProperty(obj, keyName, null, cachedValue);
- set(obj, keyName, value);
- return;
- }
-
- if (hadCachedValue && cachedValue === ret) { return; }
-
- var watched = meta.watching[keyName];
- if (watched) {
- propertyWillChange(obj, keyName);
- }
-
- if (hadCachedValue) {
- cache[keyName] = undefined;
- }
-
- if (cacheable) {
- if (!hadCachedValue) {
- addDependentKeys(this, obj, keyName, meta);
- }
- if (ret === undefined) {
- cache[keyName] = UNDEFINED;
- } else {
- cache[keyName] = ret;
- }
- }
-
- if (watched) {
- propertyDidChange(obj, keyName);
- }
-
- return ret;
- };
-
- /* called before property is overridden */
- ComputedPropertyPrototype.teardown = function(obj, keyName) {
- var meta = metaFor(obj);
-
- if (keyName in meta.cache) {
- removeDependentKeys(this, obj, keyName, meta);
- }
-
- if (this._cacheable) { delete meta.cache[keyName]; }
-
- return null; // no value to restore
- };
-
-
- /**
- This helper returns a new property descriptor that wraps the passed
- computed property function. You can use this helper to define properties
- with mixins or via `Ember.defineProperty()`.
-
- The function you pass will be used to both get and set property values.
- The function should accept two parameters, key and value. If value is not
- undefined you should set the value first. In either case return the
- current value of the property.
-
- A computed property defined in this way might look like this:
-
- ```js
- var Person = Ember.Object.extend({
- firstName: 'Betty',
- lastName: 'Jones',
-
- fullName: Ember.computed('firstName', 'lastName', function(key, value) {
- return this.get('firstName') + ' ' + this.get('lastName');
- })
- });
-
- var client = Person.create();
-
- client.get('fullName'); // 'Betty Jones'
-
- client.set('lastName', 'Fuller');
- client.get('fullName'); // 'Betty Fuller'
- ```
-
- _Note: This is the prefered way to define computed properties when writing third-party
- libraries that depend on or use Ember, since there is no guarantee that the user
- will have prototype extensions enabled._
-
- You might use this method if you disabled
- [Prototype Extensions](http://emberjs.com/guides/configuring-ember/disabling-prototype-extensions/).
- The alternative syntax might look like this
- (if prototype extensions are enabled, which is the default behavior):
-
- ```js
- fullName: function () {
- return this.get('firstName') + ' ' + this.get('lastName');
- }.property('firstName', 'lastName')
- ```
-
- @method computed
- @for Ember
- @param {String} [dependentKeys*] Optional dependent keys that trigger this computed property.
- @param {Function} func The computed property function.
- @return {Ember.ComputedProperty} property descriptor instance
- */
- function computed(func) {
- var args;
-
- if (arguments.length > 1) {
- args = a_slice.call(arguments);
- func = args.pop();
- }
-
- if (typeof func !== "function") {
- throw new EmberError("Computed Property declared without a property function");
- }
-
- var cp = new ComputedProperty(func);
-
- if (args) {
- cp.property.apply(cp, args);
- }
-
- return cp;
- }
-
- /**
- Returns the cached value for a property, if one exists.
- This can be useful for peeking at the value of a computed
- property that is generated lazily, without accidentally causing
- it to be created.
-
- @method cacheFor
- @for Ember
- @param {Object} obj the object whose property you want to check
- @param {String} key the name of the property whose cached value you want
- to return
- @return {Object} the cached value
- */
- function cacheFor(obj, key) {
- var meta = obj['__ember_meta__'];
- var cache = meta && meta.cache;
- var ret = cache && cache[key];
-
- if (ret === UNDEFINED) {
- return undefined;
- }
- return ret;
- }
-
- cacheFor.set = function(cache, key, value) {
- if (value === undefined) {
- cache[key] = UNDEFINED;
- } else {
- cache[key] = value;
- }
- };
-
- cacheFor.get = function(cache, key) {
- var ret = cache[key];
- if (ret === UNDEFINED) {
- return undefined;
- }
- return ret;
- };
-
- cacheFor.remove = function(cache, key) {
- cache[key] = undefined;
- };
-
- __exports__.ComputedProperty = ComputedProperty;
- __exports__.computed = computed;
- __exports__.cacheFor = cacheFor;
- });
-enifed("ember-metal/computed_macros",
- ["ember-metal/core","ember-metal/property_get","ember-metal/property_set","ember-metal/computed","ember-metal/is_empty","ember-metal/is_none","ember-metal/alias"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__) {
- "use strict";
- var Ember = __dependency1__["default"];
- var get = __dependency2__.get;
- var set = __dependency3__.set;
- var computed = __dependency4__.computed;
- var isEmpty = __dependency5__["default"];
- var isNone = __dependency6__["default"];
- var alias = __dependency7__["default"];
-
- /**
- @module ember-metal
- */
-
- var a_slice = [].slice;
-
- function getProperties(self, propertyNames) {
- var ret = {};
- for(var i = 0; i < propertyNames.length; i++) {
- ret[propertyNames[i]] = get(self, propertyNames[i]);
- }
- return ret;
- }
-
- function registerComputed(name, macro) {
- computed[name] = function(dependentKey) {
- var args = a_slice.call(arguments);
- return computed(dependentKey, function() {
- return macro.apply(this, args);
- });
- };
- }
-
- function registerComputedWithProperties(name, macro) {
- computed[name] = function() {
- var properties = a_slice.call(arguments);
-
- var computedFunc = computed(function() {
- return macro.apply(this, [getProperties(this, properties)]);
- });
-
- return computedFunc.property.apply(computedFunc, properties);
- };
- }
-
- /**
- A computed property that returns true if the value of the dependent
- property is null, an empty string, empty array, or empty function.
-
- Example
-
- ```javascript
- var ToDoList = Ember.Object.extend({
- done: Ember.computed.empty('todos')
- });
-
- var todoList = ToDoList.create({
- todos: ['Unit Test', 'Documentation', 'Release']
- });
-
- todoList.get('done'); // false
- todoList.get('todos').clear();
- todoList.get('done'); // true
- ```
-
- @since 1.6.0
- @method computed.empty
- @for Ember
- @param {String} dependentKey
- @return {Ember.ComputedProperty} computed property which negate
- the original value for property
- */
- computed.empty = function (dependentKey) {
- return computed(dependentKey + '.length', function () {
- return isEmpty(get(this, dependentKey));
- });
- };
-
- /**
- A computed property that returns true if the value of the dependent
- property is NOT null, an empty string, empty array, or empty function.
-
- Example
-
- ```javascript
- var Hamster = Ember.Object.extend({
- hasStuff: Ember.computed.notEmpty('backpack')
- });
-
- var hamster = Hamster.create({ backpack: ['Food', 'Sleeping Bag', 'Tent'] });
-
- hamster.get('hasStuff'); // true
- hamster.get('backpack').clear(); // []
- hamster.get('hasStuff'); // false
- ```
-
- @method computed.notEmpty
- @for Ember
- @param {String} dependentKey
- @return {Ember.ComputedProperty} computed property which returns true if
- original value for property is not empty.
- */
- computed.notEmpty = function(dependentKey) {
- return computed(dependentKey + '.length', function () {
- return !isEmpty(get(this, dependentKey));
- });
- };
-
- /**
- A computed property that returns true if the value of the dependent
- property is null or undefined. This avoids errors from JSLint complaining
- about use of ==, which can be technically confusing.
-
- Example
-
- ```javascript
- var Hamster = Ember.Object.extend({
- isHungry: Ember.computed.none('food')
- });
-
- var hamster = Hamster.create();
-
- hamster.get('isHungry'); // true
- hamster.set('food', 'Banana');
- hamster.get('isHungry'); // false
- hamster.set('food', null);
- hamster.get('isHungry'); // true
- ```
-
- @method computed.none
- @for Ember
- @param {String} dependentKey
- @return {Ember.ComputedProperty} computed property which
- returns true if original value for property is null or undefined.
- */
- registerComputed('none', function(dependentKey) {
- return isNone(get(this, dependentKey));
- });
-
- /**
- A computed property that returns the inverse boolean value
- of the original value for the dependent property.
-
- Example
-
- ```javascript
- var User = Ember.Object.extend({
- isAnonymous: Ember.computed.not('loggedIn')
- });
-
- var user = User.create({loggedIn: false});
-
- user.get('isAnonymous'); // true
- user.set('loggedIn', true);
- user.get('isAnonymous'); // false
- ```
-
- @method computed.not
- @for Ember
- @param {String} dependentKey
- @return {Ember.ComputedProperty} computed property which returns
- inverse of the original value for property
- */
- registerComputed('not', function(dependentKey) {
- return !get(this, dependentKey);
- });
-
- /**
- A computed property that converts the provided dependent property
- into a boolean value.
-
- ```javascript
- var Hamster = Ember.Object.extend({
- hasBananas: Ember.computed.bool('numBananas')
- });
-
- var hamster = Hamster.create();
-
- hamster.get('hasBananas'); // false
- hamster.set('numBananas', 0);
- hamster.get('hasBananas'); // false
- hamster.set('numBananas', 1);
- hamster.get('hasBananas'); // true
- hamster.set('numBananas', null);
- hamster.get('hasBananas'); // false
- ```
-
- @method computed.bool
- @for Ember
- @param {String} dependentKey
- @return {Ember.ComputedProperty} computed property which converts
- to boolean the original value for property
- */
- registerComputed('bool', function(dependentKey) {
- return !!get(this, dependentKey);
- });
-
- /**
- A computed property which matches the original value for the
- dependent property against a given RegExp, returning `true`
- if they values matches the RegExp and `false` if it does not.
-
- Example
-
- ```javascript
- var User = Ember.Object.extend({
- hasValidEmail: Ember.computed.match('email', /^.+@.+\..+$/)
- });
-
- var user = User.create({loggedIn: false});
-
- user.get('hasValidEmail'); // false
- user.set('email', '');
- user.get('hasValidEmail'); // false
- user.set('email', 'ember_hamster@example.com');
- user.get('hasValidEmail'); // true
- ```
-
- @method computed.match
- @for Ember
- @param {String} dependentKey
- @param {RegExp} regexp
- @return {Ember.ComputedProperty} computed property which match
- the original value for property against a given RegExp
- */
- registerComputed('match', function(dependentKey, regexp) {
- var value = get(this, dependentKey);
- return typeof value === 'string' ? regexp.test(value) : false;
- });
-
- /**
- A computed property that returns true if the provided dependent property
- is equal to the given value.
-
- Example
-
- ```javascript
- var Hamster = Ember.Object.extend({
- napTime: Ember.computed.equal('state', 'sleepy')
- });
-
- var hamster = Hamster.create();
-
- hamster.get('napTime'); // false
- hamster.set('state', 'sleepy');
- hamster.get('napTime'); // true
- hamster.set('state', 'hungry');
- hamster.get('napTime'); // false
- ```
-
- @method computed.equal
- @for Ember
- @param {String} dependentKey
- @param {String|Number|Object} value
- @return {Ember.ComputedProperty} computed property which returns true if
- the original value for property is equal to the given value.
- */
- registerComputed('equal', function(dependentKey, value) {
- return get(this, dependentKey) === value;
- });
-
- /**
- A computed property that returns true if the provided dependent property
- is greater than the provided value.
-
- Example
-
- ```javascript
- var Hamster = Ember.Object.extend({
- hasTooManyBananas: Ember.computed.gt('numBananas', 10)
- });
-
- var hamster = Hamster.create();
-
- hamster.get('hasTooManyBananas'); // false
- hamster.set('numBananas', 3);
- hamster.get('hasTooManyBananas'); // false
- hamster.set('numBananas', 11);
- hamster.get('hasTooManyBananas'); // true
- ```
-
- @method computed.gt
- @for Ember
- @param {String} dependentKey
- @param {Number} value
- @return {Ember.ComputedProperty} computed property which returns true if
- the original value for property is greater than given value.
- */
- registerComputed('gt', function(dependentKey, value) {
- return get(this, dependentKey) > value;
- });
-
- /**
- A computed property that returns true if the provided dependent property
- is greater than or equal to the provided value.
-
- Example
-
- ```javascript
- var Hamster = Ember.Object.extend({
- hasTooManyBananas: Ember.computed.gte('numBananas', 10)
- });
-
- var hamster = Hamster.create();
-
- hamster.get('hasTooManyBananas'); // false
- hamster.set('numBananas', 3);
- hamster.get('hasTooManyBananas'); // false
- hamster.set('numBananas', 10);
- hamster.get('hasTooManyBananas'); // true
- ```
-
- @method computed.gte
- @for Ember
- @param {String} dependentKey
- @param {Number} value
- @return {Ember.ComputedProperty} computed property which returns true if
- the original value for property is greater or equal then given value.
- */
- registerComputed('gte', function(dependentKey, value) {
- return get(this, dependentKey) >= value;
- });
-
- /**
- A computed property that returns true if the provided dependent property
- is less than the provided value.
-
- Example
-
- ```javascript
- var Hamster = Ember.Object.extend({
- needsMoreBananas: Ember.computed.lt('numBananas', 3)
- });
-
- var hamster = Hamster.create();
-
- hamster.get('needsMoreBananas'); // true
- hamster.set('numBananas', 3);
- hamster.get('needsMoreBananas'); // false
- hamster.set('numBananas', 2);
- hamster.get('needsMoreBananas'); // true
- ```
-
- @method computed.lt
- @for Ember
- @param {String} dependentKey
- @param {Number} value
- @return {Ember.ComputedProperty} computed property which returns true if
- the original value for property is less then given value.
- */
- registerComputed('lt', function(dependentKey, value) {
- return get(this, dependentKey) < value;
- });
-
- /**
- A computed property that returns true if the provided dependent property
- is less than or equal to the provided value.
-
- Example
-
- ```javascript
- var Hamster = Ember.Object.extend({
- needsMoreBananas: Ember.computed.lte('numBananas', 3)
- });
-
- var hamster = Hamster.create();
-
- hamster.get('needsMoreBananas'); // true
- hamster.set('numBananas', 5);
- hamster.get('needsMoreBananas'); // false
- hamster.set('numBananas', 3);
- hamster.get('needsMoreBananas'); // true
- ```
-
- @method computed.lte
- @for Ember
- @param {String} dependentKey
- @param {Number} value
- @return {Ember.ComputedProperty} computed property which returns true if
- the original value for property is less or equal than given value.
- */
- registerComputed('lte', function(dependentKey, value) {
- return get(this, dependentKey) <= value;
- });
-
- /**
- A computed property that performs a logical `and` on the
- original values for the provided dependent properties.
-
- Example
-
- ```javascript
- var Hamster = Ember.Object.extend({
- readyForCamp: Ember.computed.and('hasTent', 'hasBackpack')
- });
-
- var hamster = Hamster.create();
-
- hamster.get('readyForCamp'); // false
- hamster.set('hasTent', true);
- hamster.get('readyForCamp'); // false
- hamster.set('hasBackpack', true);
- hamster.get('readyForCamp'); // true
- ```
-
- @method computed.and
- @for Ember
- @param {String} dependentKey*
- @return {Ember.ComputedProperty} computed property which performs
- a logical `and` on the values of all the original values for properties.
- */
- registerComputedWithProperties('and', function(properties) {
- for (var key in properties) {
- if (properties.hasOwnProperty(key) && !properties[key]) {
- return false;
- }
- }
- return true;
- });
-
- /**
- A computed property which performs a logical `or` on the
- original values for the provided dependent properties.
-
- Example
-
- ```javascript
- var Hamster = Ember.Object.extend({
- readyForRain: Ember.computed.or('hasJacket', 'hasUmbrella')
- });
-
- var hamster = Hamster.create();
-
- hamster.get('readyForRain'); // false
- hamster.set('hasJacket', true);
- hamster.get('readyForRain'); // true
- ```
-
- @method computed.or
- @for Ember
- @param {String} dependentKey*
- @return {Ember.ComputedProperty} computed property which performs
- a logical `or` on the values of all the original values for properties.
- */
- registerComputedWithProperties('or', function(properties) {
- for (var key in properties) {
- if (properties.hasOwnProperty(key) && properties[key]) {
- return true;
- }
- }
- return false;
- });
-
- /**
- A computed property that returns the first truthy value
- from a list of dependent properties.
-
- Example
-
- ```javascript
- var Hamster = Ember.Object.extend({
- hasClothes: Ember.computed.any('hat', 'shirt')
- });
-
- var hamster = Hamster.create();
-
- hamster.get('hasClothes'); // null
- hamster.set('shirt', 'Hawaiian Shirt');
- hamster.get('hasClothes'); // 'Hawaiian Shirt'
- ```
-
- @method computed.any
- @for Ember
- @param {String} dependentKey*
- @return {Ember.ComputedProperty} computed property which returns
- the first truthy value of given list of properties.
- */
- registerComputedWithProperties('any', function(properties) {
- for (var key in properties) {
- if (properties.hasOwnProperty(key) && properties[key]) {
- return properties[key];
- }
- }
- return null;
- });
-
- /**
- A computed property that returns the array of values
- for the provided dependent properties.
-
- Example
-
- ```javascript
- var Hamster = Ember.Object.extend({
- clothes: Ember.computed.collect('hat', 'shirt')
- });
-
- var hamster = Hamster.create();
-
- hamster.get('clothes'); // [null, null]
- hamster.set('hat', 'Camp Hat');
- hamster.set('shirt', 'Camp Shirt');
- hamster.get('clothes'); // ['Camp Hat', 'Camp Shirt']
- ```
-
- @method computed.collect
- @for Ember
- @param {String} dependentKey*
- @return {Ember.ComputedProperty} computed property which maps
- values of all passed in properties to an array.
- */
- registerComputedWithProperties('collect', function(properties) {
- var res = Ember.A();
- for (var key in properties) {
- if (properties.hasOwnProperty(key)) {
- if (isNone(properties[key])) {
- res.push(null);
- } else {
- res.push(properties[key]);
- }
- }
- }
- return res;
- });
-
- /**
- Creates a new property that is an alias for another property
- on an object. Calls to `get` or `set` this property behave as
- though they were called on the original property.
-
- ```javascript
- var Person = Ember.Object.extend({
- name: 'Alex Matchneer',
- nomen: Ember.computed.alias('name')
- });
-
- var alex = Person.create();
-
- alex.get('nomen'); // 'Alex Matchneer'
- alex.get('name'); // 'Alex Matchneer'
-
- alex.set('nomen', '@machty');
- alex.get('name'); // '@machty'
- ```
-
- @method computed.alias
- @for Ember
- @param {String} dependentKey
- @return {Ember.ComputedProperty} computed property which creates an
- alias to the original value for property.
- */
- computed.alias = alias;
-
- /**
- Where `computed.alias` aliases `get` and `set`, and allows for bidirectional
- data flow, `computed.oneWay` only provides an aliased `get`. The `set` will
- not mutate the upstream property, rather causes the current property to
- become the value set. This causes the downstream property to permanently
- diverge from the upstream property.
-
- Example
-
- ```javascript
- var User = Ember.Object.extend({
- firstName: null,
- lastName: null,
- nickName: Ember.computed.oneWay('firstName')
- });
-
- var teddy = User.create({
- firstName: 'Teddy',
- lastName: 'Zeenny'
- });
-
- teddy.get('nickName'); // 'Teddy'
- teddy.set('nickName', 'TeddyBear'); // 'TeddyBear'
- teddy.get('firstName'); // 'Teddy'
- ```
-
- @method computed.oneWay
- @for Ember
- @param {String} dependentKey
- @return {Ember.ComputedProperty} computed property which creates a
- one way computed property to the original value for property.
- */
- computed.oneWay = function(dependentKey) {
- return alias(dependentKey).oneWay();
- };
-
- /**
- This is a more semantically meaningful alias of `computed.oneWay`,
- whose name is somewhat ambiguous as to which direction the data flows.
-
- @method computed.reads
- @for Ember
- @param {String} dependentKey
- @return {Ember.ComputedProperty} computed property which creates a
- one way computed property to the original value for property.
- */
- computed.reads = computed.oneWay;
-
- /**
- Where `computed.oneWay` provides oneWay bindings, `computed.readOnly` provides
- a readOnly one way binding. Very often when using `computed.oneWay` one does
- not also want changes to propogate back up, as they will replace the value.
-
- This prevents the reverse flow, and also throws an exception when it occurs.
-
- Example
-
- ```javascript
- var User = Ember.Object.extend({
- firstName: null,
- lastName: null,
- nickName: Ember.computed.readOnly('firstName')
- });
-
- var teddy = User.create({
- firstName: 'Teddy',
- lastName: 'Zeenny'
- });
-
- teddy.get('nickName'); // 'Teddy'
- teddy.set('nickName', 'TeddyBear'); // throws Exception
- // throw new Ember.Error('Cannot Set: nickName on: <User:ember27288>' );`
- teddy.get('firstName'); // 'Teddy'
- ```
-
- @method computed.readOnly
- @for Ember
- @param {String} dependentKey
- @return {Ember.ComputedProperty} computed property which creates a
- one way computed property to the original value for property.
- @since 1.5.0
- */
- computed.readOnly = function(dependentKey) {
- return alias(dependentKey).readOnly();
- };
- /**
- A computed property that acts like a standard getter and setter,
- but returns the value at the provided `defaultPath` if the
- property itself has not been set to a value
-
- Example
-
- ```javascript
- var Hamster = Ember.Object.extend({
- wishList: Ember.computed.defaultTo('favoriteFood')
- });
-
- var hamster = Hamster.create({ favoriteFood: 'Banana' });
-
- hamster.get('wishList'); // 'Banana'
- hamster.set('wishList', 'More Unit Tests');
- hamster.get('wishList'); // 'More Unit Tests'
- hamster.get('favoriteFood'); // 'Banana'
- ```
-
- @method computed.defaultTo
- @for Ember
- @param {String} defaultPath
- @return {Ember.ComputedProperty} computed property which acts like
- a standard getter and setter, but defaults to the value from `defaultPath`.
- @deprecated Use `Ember.computed.oneWay` or custom CP with default instead.
- */
- // ES6TODO: computed should have its own export path so you can do import {defaultTo} from computed
- computed.defaultTo = function(defaultPath) {
- return computed(function(key, newValue, cachedValue) {
- Ember.deprecate('Usage of Ember.computed.defaultTo is deprecated, use `Ember.computed.oneWay` instead.');
-
- if (arguments.length === 1) {
- return get(this, defaultPath);
- }
- return newValue != null ? newValue : get(this, defaultPath);
- });
- };
-
- /**
- Creates a new property that is an alias for another property
- on an object. Calls to `get` or `set` this property behave as
- though they were called on the original property, but also
- print a deprecation warning.
-
- @method computed.deprecatingAlias
- @for Ember
- @param {String} dependentKey
- @return {Ember.ComputedProperty} computed property which creates an
- alias with a deprecation to the original value for property.
- @since 1.7.0
- */
- computed.deprecatingAlias = function(dependentKey) {
- return computed(dependentKey, function(key, value) {
- Ember.deprecate('Usage of `' + key + '` is deprecated, use `' + dependentKey + '` instead.');
-
- if (arguments.length > 1) {
- set(this, dependentKey, value);
- return value;
- } else {
- return get(this, dependentKey);
- }
- });
- };
- });
-enifed("ember-metal/core",
- ["exports"],
- function(__exports__) {
- "use strict";
- /*globals Ember:true,ENV,EmberENV,MetamorphENV:true */
-
- /**
- @module ember
- @submodule ember-metal
- */
-
- /**
- All Ember methods and functions are defined inside of this namespace. You
- generally should not add new properties to this namespace as it may be
- overwritten by future versions of Ember.
-
- You can also use the shorthand `Em` instead of `Ember`.
-
- Ember-Runtime is a framework that provides core functions for Ember including
- cross-platform functions, support for property observing and objects. Its
- focus is on small size and performance. You can use this in place of or
- along-side other cross-platform libraries such as jQuery.
-
- The core Runtime framework is based on the jQuery API with a number of
- performance optimizations.
-
- @class Ember
- @static
- @version 1.9.0
- */
-
- if ('undefined' === typeof Ember) {
- // Create core object. Make it act like an instance of Ember.Namespace so that
- // objects assigned to it are given a sane string representation.
- Ember = {};
- }
-
- // Default imports, exports and lookup to the global object;
- Ember.imports = Ember.imports || this;
- Ember.lookup = Ember.lookup || this;
- var exports = Ember.exports = Ember.exports || this;
-
- // aliases needed to keep minifiers from removing the global context
- exports.Em = exports.Ember = Ember;
-
- // Make sure these are set whether Ember was already defined or not
-
- Ember.isNamespace = true;
-
- Ember.toString = function() { return "Ember"; };
-
-
- /**
- @property VERSION
- @type String
- @default '1.9.0'
- @static
- */
- Ember.VERSION = '1.9.0';
-
- /**
- Standard environmental variables. You can define these in a global `EmberENV`
- variable before loading Ember to control various configuration settings.
-
- For backwards compatibility with earlier versions of Ember the global `ENV`
- variable will be used if `EmberENV` is not defined.
-
- @property ENV
- @type Hash
- */
-
- if (Ember.ENV) {
- // do nothing if Ember.ENV is already setup
- } else if ('undefined' !== typeof EmberENV) {
- Ember.ENV = EmberENV;
- } else if('undefined' !== typeof ENV) {
- Ember.ENV = ENV;
- } else {
- Ember.ENV = {};
- }
-
- Ember.config = Ember.config || {};
-
- // We disable the RANGE API by default for performance reasons
- if ('undefined' === typeof Ember.ENV.DISABLE_RANGE_API) {
- Ember.ENV.DISABLE_RANGE_API = true;
- }
-
- if ("undefined" === typeof MetamorphENV) {
- exports.MetamorphENV = {};
- }
-
- MetamorphENV.DISABLE_RANGE_API = Ember.ENV.DISABLE_RANGE_API;
-
- /**
- Hash of enabled Canary features. Add to this before creating your application.
-
- You can also define `ENV.FEATURES` if you need to enable features flagged at runtime.
-
- @class FEATURES
- @namespace Ember
- @static
- @since 1.1.0
- */
-
- Ember.FEATURES = Ember.ENV.FEATURES || {};
-
- /**
- Test that a feature is enabled. Parsed by Ember's build tools to leave
- experimental features out of beta/stable builds.
-
- You can define the following configuration options:
-
- * `ENV.ENABLE_ALL_FEATURES` - force all features to be enabled.
- * `ENV.ENABLE_OPTIONAL_FEATURES` - enable any features that have not been explicitly
- enabled/disabled.
-
- @method isEnabled
- @param {String} feature
- @return {Boolean}
- @for Ember.FEATURES
- @since 1.1.0
- */
-
- Ember.FEATURES.isEnabled = function(feature) {
- var featureValue = Ember.FEATURES[feature];
-
- if (Ember.ENV.ENABLE_ALL_FEATURES) {
- return true;
- } else if (featureValue === true || featureValue === false || featureValue === undefined) {
- return featureValue;
- } else if (Ember.ENV.ENABLE_OPTIONAL_FEATURES) {
- return true;
- } else {
- return false;
- }
- };
-
- // ..........................................................
- // BOOTSTRAP
- //
-
- /**
- Determines whether Ember should enhance some built-in object prototypes to
- provide a more friendly API. If enabled, a few methods will be added to
- `Function`, `String`, and `Array`. `Object.prototype` will not be enhanced,
- which is the one that causes most trouble for people.
-
- In general we recommend leaving this option set to true since it rarely
- conflicts with other code. If you need to turn it off however, you can
- define an `ENV.EXTEND_PROTOTYPES` config to disable it.
-
- @property EXTEND_PROTOTYPES
- @type Boolean
- @default true
- @for Ember
- */
- Ember.EXTEND_PROTOTYPES = Ember.ENV.EXTEND_PROTOTYPES;
-
- if (typeof Ember.EXTEND_PROTOTYPES === 'undefined') {
- Ember.EXTEND_PROTOTYPES = true;
- }
-
- /**
- Determines whether Ember logs a full stack trace during deprecation warnings
-
- @property LOG_STACKTRACE_ON_DEPRECATION
- @type Boolean
- @default true
- */
- Ember.LOG_STACKTRACE_ON_DEPRECATION = (Ember.ENV.LOG_STACKTRACE_ON_DEPRECATION !== false);
-
- /**
- Determines whether Ember should add ECMAScript 5 Array shims to older browsers.
-
- @property SHIM_ES5
- @type Boolean
- @default Ember.EXTEND_PROTOTYPES
- */
- Ember.SHIM_ES5 = (Ember.ENV.SHIM_ES5 === false) ? false : Ember.EXTEND_PROTOTYPES;
-
- /**
- Determines whether Ember logs info about version of used libraries
-
- @property LOG_VERSION
- @type Boolean
- @default true
- */
- Ember.LOG_VERSION = (Ember.ENV.LOG_VERSION === false) ? false : true;
-
- /**
- Empty function. Useful for some operations. Always returns `this`.
-
- @method K
- @private
- @return {Object}
- */
- function K() { return this; }
- __exports__.K = K;
- Ember.K = K;
- //TODO: ES6 GLOBAL TODO
-
- // Stub out the methods defined by the ember-debug package in case it's not loaded
-
- if ('undefined' === typeof Ember.assert) { Ember.assert = Ember.K; }
- if ('undefined' === typeof Ember.warn) { Ember.warn = Ember.K; }
- if ('undefined' === typeof Ember.debug) { Ember.debug = Ember.K; }
- if ('undefined' === typeof Ember.runInDebug) { Ember.runInDebug = Ember.K; }
- if ('undefined' === typeof Ember.deprecate) { Ember.deprecate = Ember.K; }
- if ('undefined' === typeof Ember.deprecateFunc) {
- Ember.deprecateFunc = function(_, func) { return func; };
- }
-
- __exports__["default"] = Ember;
- });
-enifed("ember-metal/dependent_keys",
- ["ember-metal/platform","ember-metal/watching","exports"],
- function(__dependency1__, __dependency2__, __exports__) {
- // Remove "use strict"; from transpiled module until
- // https://bugs.webkit.org/show_bug.cgi?id=138038 is fixed
- //
- // REMOVE_USE_STRICT: true
-
- var o_create = __dependency1__.create;
- var watch = __dependency2__.watch;
- var unwatch = __dependency2__.unwatch;
-
- /**
- @module ember-metal
- */
-
- // ..........................................................
- // DEPENDENT KEYS
- //
-
- // data structure:
- // meta.deps = {
- // 'depKey': {
- // 'keyName': count,
- // }
- // }
-
- /*
- This function returns a map of unique dependencies for a
- given object and key.
- */
- function keysForDep(depsMeta, depKey) {
- var keys = depsMeta[depKey];
- if (!keys) {
- // if there are no dependencies yet for a the given key
- // create a new empty list of dependencies for the key
- keys = depsMeta[depKey] = {};
- } else if (!depsMeta.hasOwnProperty(depKey)) {
- // otherwise if the dependency list is inherited from
- // a superclass, clone the hash
- keys = depsMeta[depKey] = o_create(keys);
- }
- return keys;
- }
-
- function metaForDeps(meta) {
- return keysForDep(meta, 'deps');
- }
-
- function addDependentKeys(desc, obj, keyName, meta) {
- // the descriptor has a list of dependent keys, so
- // add all of its dependent keys.
- var depKeys = desc._dependentKeys, depsMeta, idx, len, depKey, keys;
- if (!depKeys) return;
-
- depsMeta = metaForDeps(meta);
-
- for(idx = 0, len = depKeys.length; idx < len; idx++) {
- depKey = depKeys[idx];
- // Lookup keys meta for depKey
- keys = keysForDep(depsMeta, depKey);
- // Increment the number of times depKey depends on keyName.
- keys[keyName] = (keys[keyName] || 0) + 1;
- // Watch the depKey
- watch(obj, depKey, meta);
- }
- }
-
- __exports__.addDependentKeys = addDependentKeys;function removeDependentKeys(desc, obj, keyName, meta) {
- // the descriptor has a list of dependent keys, so
- // remove all of its dependent keys.
- var depKeys = desc._dependentKeys, depsMeta, idx, len, depKey, keys;
- if (!depKeys) return;
-
- depsMeta = metaForDeps(meta);
-
- for(idx = 0, len = depKeys.length; idx < len; idx++) {
- depKey = depKeys[idx];
- // Lookup keys meta for depKey
- keys = keysForDep(depsMeta, depKey);
- // Decrement the number of times depKey depends on keyName.
- keys[keyName] = (keys[keyName] || 0) - 1;
- // Unwatch the depKey
- unwatch(obj, depKey, meta);
- }
- }
-
- __exports__.removeDependentKeys = removeDependentKeys;
- });
-enifed("ember-metal/deprecate_property",
- ["ember-metal/core","ember-metal/platform","ember-metal/properties","ember-metal/property_get","ember-metal/property_set","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) {
- "use strict";
- /**
- @module ember-metal
- */
-
- var Ember = __dependency1__["default"];
- var hasPropertyAccessors = __dependency2__.hasPropertyAccessors;
- var defineProperty = __dependency3__.defineProperty;
- var get = __dependency4__.get;
- var set = __dependency5__.set;
-
-
- /**
- Used internally to allow changing properties in a backwards compatible way, and print a helpful
- deprecation warning.
-
- @method deprecateProperty
- @param {Object} object The object to add the deprecated property to.
- @param {String} deprecatedKey The property to add (and print deprecation warnings upon accessing).
- @param {String} newKey The property that will be aliased.
- @private
- @since 1.7.0
- */
-
- function deprecateProperty(object, deprecatedKey, newKey) {
- function deprecate() {
- Ember.deprecate('Usage of `' + deprecatedKey + '` is deprecated, use `' + newKey + '` instead.');
- }
-
- if (hasPropertyAccessors) {
- defineProperty(object, deprecatedKey, {
- configurable: true,
- enumerable: false,
- set: function(value) { deprecate(); set(this, newKey, value); },
- get: function() { deprecate(); return get(this, newKey); }
- });
- }
- }
-
- __exports__.deprecateProperty = deprecateProperty;
- });
-enifed("ember-metal/dictionary",
- ["ember-metal/platform","exports"],
- function(__dependency1__, __exports__) {
- "use strict";
- var create = __dependency1__.create;
-
- // the delete is meant to hint at runtimes that this object should remain in
- // dictionary mode. This is clearly a runtime specific hack, but currently it
- // appears worthwile in some usecases. Please note, these deletes do increase
- // the cost of creation dramatically over a plain Object.create. And as this
- // only makes sense for long-lived dictionaries that aren't instantiated often.
- __exports__["default"] = function makeDictionary(parent) {
- var dict = create(parent);
- dict['_dict'] = null;
- delete dict['_dict'];
- return dict;
- }
- });
-enifed("ember-metal/enumerable_utils",
- ["ember-metal/array","exports"],
- function(__dependency1__, __exports__) {
- "use strict";
- var _filter = __dependency1__.filter;
- var a_forEach = __dependency1__.forEach;
- var _indexOf = __dependency1__.indexOf;
- var _map = __dependency1__.map;
-
- var splice = Array.prototype.splice;
-
- /**
- * Defines some convenience methods for working with Enumerables.
- * `Ember.EnumerableUtils` uses `Ember.ArrayPolyfills` when necessary.
- *
- * @class EnumerableUtils
- * @namespace Ember
- * @static
- * */
-
- /**
- * Calls the map function on the passed object with a specified callback. This
- * uses `Ember.ArrayPolyfill`'s-map method when necessary.
- *
- * @method map
- * @param {Object} obj The object that should be mapped
- * @param {Function} callback The callback to execute
- * @param {Object} thisArg Value to use as this when executing *callback*
- *
- * @return {Array} An array of mapped values.
- */
- function map(obj, callback, thisArg) {
- return obj.map ? obj.map(callback, thisArg) : _map.call(obj, callback, thisArg);
- }
-
- __exports__.map = map;/**
- * Calls the forEach function on the passed object with a specified callback. This
- * uses `Ember.ArrayPolyfill`'s-forEach method when necessary.
- *
- * @method forEach
- * @param {Object} obj The object to call forEach on
- * @param {Function} callback The callback to execute
- * @param {Object} thisArg Value to use as this when executing *callback*
- *
- */
- function forEach(obj, callback, thisArg) {
- return obj.forEach ? obj.forEach(callback, thisArg) : a_forEach.call(obj, callback, thisArg);
- }
-
- __exports__.forEach = forEach;/**
- * Calls the filter function on the passed object with a specified callback. This
- * uses `Ember.ArrayPolyfill`'s-filter method when necessary.
- *
- * @method filter
- * @param {Object} obj The object to call filter on
- * @param {Function} callback The callback to execute
- * @param {Object} thisArg Value to use as this when executing *callback*
- *
- * @return {Array} An array containing the filtered values
- * @since 1.4.0
- */
- function filter(obj, callback, thisArg) {
- return obj.filter ? obj.filter(callback, thisArg) : _filter.call(obj, callback, thisArg);
- }
-
- __exports__.filter = filter;/**
- * Calls the indexOf function on the passed object with a specified callback. This
- * uses `Ember.ArrayPolyfill`'s-indexOf method when necessary.
- *
- * @method indexOf
- * @param {Object} obj The object to call indexOn on
- * @param {Function} callback The callback to execute
- * @param {Object} index The index to start searching from
- *
- */
- function indexOf(obj, element, index) {
- return obj.indexOf ? obj.indexOf(element, index) : _indexOf.call(obj, element, index);
- }
-
- __exports__.indexOf = indexOf;/**
- * Returns an array of indexes of the first occurrences of the passed elements
- * on the passed object.
- *
- * ```javascript
- * var array = [1, 2, 3, 4, 5];
- * Ember.EnumerableUtils.indexesOf(array, [2, 5]); // [1, 4]
- *
- * var fubar = "Fubarr";
- * Ember.EnumerableUtils.indexesOf(fubar, ['b', 'r']); // [2, 4]
- * ```
- *
- * @method indexesOf
- * @param {Object} obj The object to check for element indexes
- * @param {Array} elements The elements to search for on *obj*
- *
- * @return {Array} An array of indexes.
- *
- */
- function indexesOf(obj, elements) {
- return elements === undefined ? [] : map(elements, function(item) {
- return indexOf(obj, item);
- });
- }
-
- __exports__.indexesOf = indexesOf;/**
- * Adds an object to an array. If the array already includes the object this
- * method has no effect.
- *
- * @method addObject
- * @param {Array} array The array the passed item should be added to
- * @param {Object} item The item to add to the passed array
- *
- * @return 'undefined'
- */
- function addObject(array, item) {
- var index = indexOf(array, item);
- if (index === -1) { array.push(item); }
- }
-
- __exports__.addObject = addObject;/**
- * Removes an object from an array. If the array does not contain the passed
- * object this method has no effect.
- *
- * @method removeObject
- * @param {Array} array The array to remove the item from.
- * @param {Object} item The item to remove from the passed array.
- *
- * @return 'undefined'
- */
- function removeObject(array, item) {
- var index = indexOf(array, item);
- if (index !== -1) { array.splice(index, 1); }
- }
-
- __exports__.removeObject = removeObject;function _replace(array, idx, amt, objects) {
- var args = [].concat(objects);
- var ret = [];
- // https://code.google.com/p/chromium/issues/detail?id=56588
- var size = 60000;
- var start = idx;
- var ends = amt;
- var count, chunk;
-
- while (args.length) {
- count = ends > size ? size : ends;
- if (count <= 0) { count = 0; }
-
- chunk = args.splice(0, size);
- chunk = [start, count].concat(chunk);
-
- start += size;
- ends -= count;
-
- ret = ret.concat(splice.apply(array, chunk));
- }
- return ret;
- }
-
- __exports__._replace = _replace;/**
- * Replaces objects in an array with the passed objects.
- *
- * ```javascript
- * var array = [1,2,3];
- * Ember.EnumerableUtils.replace(array, 1, 2, [4, 5]); // [1, 4, 5]
- *
- * var array = [1,2,3];
- * Ember.EnumerableUtils.replace(array, 1, 1, [4, 5]); // [1, 4, 5, 3]
- *
- * var array = [1,2,3];
- * Ember.EnumerableUtils.replace(array, 10, 1, [4, 5]); // [1, 2, 3, 4, 5]
- * ```
- *
- * @method replace
- * @param {Array} array The array the objects should be inserted into.
- * @param {Number} idx Starting index in the array to replace. If *idx* >=
- * length, then append to the end of the array.
- * @param {Number} amt Number of elements that should be removed from the array,
- * starting at *idx*
- * @param {Array} objects An array of zero or more objects that should be
- * inserted into the array at *idx*
- *
- * @return {Array} The modified array.
- */
- function replace(array, idx, amt, objects) {
- if (array.replace) {
- return array.replace(idx, amt, objects);
- } else {
- return _replace(array, idx, amt, objects);
- }
- }
-
- __exports__.replace = replace;/**
- * Calculates the intersection of two arrays. This method returns a new array
- * filled with the records that the two passed arrays share with each other.
- * If there is no intersection, an empty array will be returned.
- *
- * ```javascript
- * var array1 = [1, 2, 3, 4, 5];
- * var array2 = [1, 3, 5, 6, 7];
- *
- * Ember.EnumerableUtils.intersection(array1, array2); // [1, 3, 5]
- *
- * var array1 = [1, 2, 3];
- * var array2 = [4, 5, 6];
- *
- * Ember.EnumerableUtils.intersection(array1, array2); // []
- * ```
- *
- * @method intersection
- * @param {Array} array1 The first array
- * @param {Array} array2 The second array
- *
- * @return {Array} The intersection of the two passed arrays.
- */
- function intersection(array1, array2) {
- var result = [];
- forEach(array1, function(element) {
- if (indexOf(array2, element) >= 0) {
- result.push(element);
- }
- });
-
- return result;
- }
-
- __exports__.intersection = intersection;// TODO: this only exists to maintain the existing api, as we move forward it
- // should only be part of the "global build" via some shim
- __exports__["default"] = {
- _replace: _replace,
- addObject: addObject,
- filter: filter,
- forEach: forEach,
- indexOf: indexOf,
- indexesOf: indexesOf,
- intersection: intersection,
- map: map,
- removeObject: removeObject,
- replace: replace
- };
- });
-enifed("ember-metal/error",
- ["ember-metal/platform","exports"],
- function(__dependency1__, __exports__) {
- "use strict";
- var create = __dependency1__.create;
-
- var errorProps = [
- 'description',
- 'fileName',
- 'lineNumber',
- 'message',
- 'name',
- 'number',
- 'stack'
- ];
-
- /**
- A subclass of the JavaScript Error object for use in Ember.
-
- @class Error
- @namespace Ember
- @extends Error
- @constructor
- */
- function EmberError() {
- var tmp = Error.apply(this, arguments);
-
- // Adds a `stack` property to the given error object that will yield the
- // stack trace at the time captureStackTrace was called.
- // When collecting the stack trace all frames above the topmost call
- // to this function, including that call, will be left out of the
- // stack trace.
- // This is useful because we can hide Ember implementation details
- // that are not very helpful for the user.
- if (Error.captureStackTrace) {
- Error.captureStackTrace(this, Ember.Error);
- }
- // Unfortunately errors are not enumerable in Chrome (at least), so `for prop in tmp` doesn't work.
- for (var idx = 0; idx < errorProps.length; idx++) {
- this[errorProps[idx]] = tmp[errorProps[idx]];
- }
- }
-
- EmberError.prototype = create(Error.prototype);
-
- __exports__["default"] = EmberError;
- });
-enifed("ember-metal/events",
- ["ember-metal/core","ember-metal/utils","ember-metal/platform","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
- // Remove "use strict"; from transpiled module until
- // https://bugs.webkit.org/show_bug.cgi?id=138038 is fixed
- //
- // REMOVE_USE_STRICT: true
-
- /**
- @module ember-metal
- */
- var Ember = __dependency1__["default"];
- var metaFor = __dependency2__.meta;
- var tryFinally = __dependency2__.tryFinally;
- var apply = __dependency2__.apply;
- var applyStr = __dependency2__.applyStr;
- var create = __dependency3__.create;
-
- var a_slice = [].slice;
-
- /* listener flags */
- var ONCE = 1;
- var SUSPENDED = 2;
-
-
- /*
- The event system uses a series of nested hashes to store listeners on an
- object. When a listener is registered, or when an event arrives, these
- hashes are consulted to determine which target and action pair to invoke.
-
- The hashes are stored in the object's meta hash, and look like this:
-
- // Object's meta hash
- {
- listeners: { // variable name: `listenerSet`
- "foo:changed": [ // variable name: `actions`
- target, method, flags
- ]
- }
- }
-
- */
-
- function indexOf(array, target, method) {
- var index = -1;
- // hashes are added to the end of the event array
- // so it makes sense to start searching at the end
- // of the array and search in reverse
- for (var i = array.length - 3 ; i >=0; i -= 3) {
- if (target === array[i] && method === array[i + 1]) {
- index = i; break;
- }
- }
- return index;
- }
-
- function actionsFor(obj, eventName) {
- var meta = metaFor(obj, true);
- var actions;
- var listeners = meta.listeners;
-
- if (!listeners) {
- listeners = meta.listeners = create(null);
- listeners.__source__ = obj;
- } else if (listeners.__source__ !== obj) {
- // setup inherited copy of the listeners object
- listeners = meta.listeners = create(listeners);
- listeners.__source__ = obj;
- }
-
- actions = listeners[eventName];
-
- // if there are actions, but the eventName doesn't exist in our listeners, then copy them from the prototype
- if (actions && actions.__source__ !== obj) {
- actions = listeners[eventName] = listeners[eventName].slice();
- actions.__source__ = obj;
- } else if (!actions) {
- actions = listeners[eventName] = [];
- actions.__source__ = obj;
- }
-
- return actions;
- }
-
- function listenersUnion(obj, eventName, otherActions) {
- var meta = obj['__ember_meta__'];
- var actions = meta && meta.listeners && meta.listeners[eventName];
-
- if (!actions) { return; }
- for (var i = actions.length - 3; i >= 0; i -= 3) {
- var target = actions[i];
- var method = actions[i+1];
- var flags = actions[i+2];
- var actionIndex = indexOf(otherActions, target, method);
-
- if (actionIndex === -1) {
- otherActions.push(target, method, flags);
- }
- }
- }
-
- __exports__.listenersUnion = listenersUnion;function listenersDiff(obj, eventName, otherActions) {
- var meta = obj['__ember_meta__'];
- var actions = meta && meta.listeners && meta.listeners[eventName];
- var diffActions = [];
-
- if (!actions) { return; }
- for (var i = actions.length - 3; i >= 0; i -= 3) {
- var target = actions[i];
- var method = actions[i+1];
- var flags = actions[i+2];
- var actionIndex = indexOf(otherActions, target, method);
-
- if (actionIndex !== -1) { continue; }
-
- otherActions.push(target, method, flags);
- diffActions.push(target, method, flags);
- }
-
- return diffActions;
- }
-
- __exports__.listenersDiff = listenersDiff;/**
- Add an event listener
-
- @method addListener
- @for Ember
- @param obj
- @param {String} eventName
- @param {Object|Function} target A target object or a function
- @param {Function|String} method A function or the name of a function to be called on `target`
- @param {Boolean} once A flag whether a function should only be called once
- */
- function addListener(obj, eventName, target, method, once) {
- Ember.assert("You must pass at least an object and event name to Ember.addListener", !!obj && !!eventName);
-
- if (!method && 'function' === typeof target) {
- method = target;
- target = null;
- }
-
- var actions = actionsFor(obj, eventName);
- var actionIndex = indexOf(actions, target, method);
- var flags = 0;
-
- if (once) flags |= ONCE;
-
- if (actionIndex !== -1) { return; }
-
- actions.push(target, method, flags);
-
- if ('function' === typeof obj.didAddListener) {
- obj.didAddListener(eventName, target, method);
- }
- }
-
- __exports__.addListener = addListener;/**
- Remove an event listener
-
- Arguments should match those passed to `Ember.addListener`.
-
- @method removeListener
- @for Ember
- @param obj
- @param {String} eventName
- @param {Object|Function} target A target object or a function
- @param {Function|String} method A function or the name of a function to be called on `target`
- */
- function removeListener(obj, eventName, target, method) {
- Ember.assert("You must pass at least an object and event name to Ember.removeListener", !!obj && !!eventName);
-
- if (!method && 'function' === typeof target) {
- method = target;
- target = null;
- }
-
- function _removeListener(target, method) {
- var actions = actionsFor(obj, eventName);
- var actionIndex = indexOf(actions, target, method);
-
- // action doesn't exist, give up silently
- if (actionIndex === -1) { return; }
-
- actions.splice(actionIndex, 3);
-
- if ('function' === typeof obj.didRemoveListener) {
- obj.didRemoveListener(eventName, target, method);
- }
- }
-
- if (method) {
- _removeListener(target, method);
- } else {
- var meta = obj['__ember_meta__'];
- var actions = meta && meta.listeners && meta.listeners[eventName];
-
- if (!actions) { return; }
- for (var i = actions.length - 3; i >= 0; i -= 3) {
- _removeListener(actions[i], actions[i+1]);
- }
- }
- }
-
- /**
- Suspend listener during callback.
-
- This should only be used by the target of the event listener
- when it is taking an action that would cause the event, e.g.
- an object might suspend its property change listener while it is
- setting that property.
-
- @method suspendListener
- @for Ember
-
- @private
- @param obj
- @param {String} eventName
- @param {Object|Function} target A target object or a function
- @param {Function|String} method A function or the name of a function to be called on `target`
- @param {Function} callback
- */
- function suspendListener(obj, eventName, target, method, callback) {
- if (!method && 'function' === typeof target) {
- method = target;
- target = null;
- }
-
- var actions = actionsFor(obj, eventName);
- var actionIndex = indexOf(actions, target, method);
-
- if (actionIndex !== -1) {
- actions[actionIndex+2] |= SUSPENDED; // mark the action as suspended
- }
-
- function tryable() { return callback.call(target); }
- function finalizer() { if (actionIndex !== -1) { actions[actionIndex+2] &= ~SUSPENDED; } }
-
- return tryFinally(tryable, finalizer);
- }
-
- __exports__.suspendListener = suspendListener;/**
- Suspends multiple listeners during a callback.
-
- @method suspendListeners
- @for Ember
-
- @private
- @param obj
- @param {Array} eventNames Array of event names
- @param {Object|Function} target A target object or a function
- @param {Function|String} method A function or the name of a function to be called on `target`
- @param {Function} callback
- */
- function suspendListeners(obj, eventNames, target, method, callback) {
- if (!method && 'function' === typeof target) {
- method = target;
- target = null;
- }
-
- var suspendedActions = [];
- var actionsList = [];
- var eventName, actions, i, l;
-
- for (i=0, l=eventNames.length; i<l; i++) {
- eventName = eventNames[i];
- actions = actionsFor(obj, eventName);
- var actionIndex = indexOf(actions, target, method);
-
- if (actionIndex !== -1) {
- actions[actionIndex+2] |= SUSPENDED;
- suspendedActions.push(actionIndex);
- actionsList.push(actions);
- }
- }
-
- function tryable() { return callback.call(target); }
-
- function finalizer() {
- for (var i = 0, l = suspendedActions.length; i < l; i++) {
- var actionIndex = suspendedActions[i];
- actionsList[i][actionIndex+2] &= ~SUSPENDED;
- }
- }
-
- return tryFinally(tryable, finalizer);
- }
-
- __exports__.suspendListeners = suspendListeners;/**
- Return a list of currently watched events
-
- @private
- @method watchedEvents
- @for Ember
- @param obj
- */
- function watchedEvents(obj) {
- var listeners = obj['__ember_meta__'].listeners, ret = [];
-
- if (listeners) {
- for (var eventName in listeners) {
- if (eventName !== '__source__' &&
- listeners[eventName]) {
- ret.push(eventName);
- }
- }
- }
- return ret;
- }
-
- __exports__.watchedEvents = watchedEvents;/**
- Send an event. The execution of suspended listeners
- is skipped, and once listeners are removed. A listener without
- a target is executed on the passed object. If an array of actions
- is not passed, the actions stored on the passed object are invoked.
-
- @method sendEvent
- @for Ember
- @param obj
- @param {String} eventName
- @param {Array} params Optional parameters for each listener.
- @param {Array} actions Optional array of actions (listeners).
- @return true
- */
- function sendEvent(obj, eventName, params, actions) {
- // first give object a chance to handle it
- if (obj !== Ember && 'function' === typeof obj.sendEvent) {
- obj.sendEvent(eventName, params);
- }
-
- if (!actions) {
- var meta = obj['__ember_meta__'];
- actions = meta && meta.listeners && meta.listeners[eventName];
- }
-
- if (!actions) { return; }
-
- for (var i = actions.length - 3; i >= 0; i -= 3) { // looping in reverse for once listeners
- var target = actions[i], method = actions[i+1], flags = actions[i+2];
- if (!method) { continue; }
- if (flags & SUSPENDED) { continue; }
- if (flags & ONCE) { removeListener(obj, eventName, target, method); }
- if (!target) { target = obj; }
- if ('string' === typeof method) {
- if (params) {
- applyStr(target, method, params);
- } else {
- target[method]();
- }
- } else {
- if (params) {
- apply(target, method, params);
- } else {
- method.call(target);
- }
- }
- }
- return true;
- }
-
- __exports__.sendEvent = sendEvent;/**
- @private
- @method hasListeners
- @for Ember
- @param obj
- @param {String} eventName
- */
- function hasListeners(obj, eventName) {
- var meta = obj['__ember_meta__'];
- var actions = meta && meta.listeners && meta.listeners[eventName];
-
- return !!(actions && actions.length);
- }
-
- __exports__.hasListeners = hasListeners;/**
- @private
- @method listenersFor
- @for Ember
- @param obj
- @param {String} eventName
- */
- function listenersFor(obj, eventName) {
- var ret = [];
- var meta = obj['__ember_meta__'];
- var actions = meta && meta.listeners && meta.listeners[eventName];
-
- if (!actions) { return ret; }
-
- for (var i = 0, l = actions.length; i < l; i += 3) {
- var target = actions[i];
- var method = actions[i+1];
- ret.push([target, method]);
- }
-
- return ret;
- }
-
- __exports__.listenersFor = listenersFor;/**
- Define a property as a function that should be executed when
- a specified event or events are triggered.
-
-
- ``` javascript
- var Job = Ember.Object.extend({
- logCompleted: Ember.on('completed', function() {
- console.log('Job completed!');
- })
- });
-
- var job = Job.create();
-
- Ember.sendEvent(job, 'completed'); // Logs 'Job completed!'
- ```
-
- @method on
- @for Ember
- @param {String} eventNames*
- @param {Function} func
- @return func
- */
- function on(){
- var func = a_slice.call(arguments, -1)[0];
- var events = a_slice.call(arguments, 0, -1);
- func.__ember_listens__ = events;
- return func;
- }
-
- __exports__.on = on;__exports__.removeListener = removeListener;
- });
-enifed("ember-metal/expand_properties",
- ["ember-metal/core","ember-metal/error","ember-metal/enumerable_utils","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
- "use strict";
- var Ember = __dependency1__["default"];
- var EmberError = __dependency2__["default"];
- var forEach = __dependency3__.forEach;
-
- /**
- @module ember-metal
- */
-
- var BRACE_EXPANSION = /^((?:[^\.]*\.)*)\{(.*)\}$/;
- var SPLIT_REGEX = /\{|\}/;
-
- /**
- Expands `pattern`, invoking `callback` for each expansion.
-
- The only pattern supported is brace-expansion, anything else will be passed
- once to `callback` directly.
-
- Example
-
- ```js
- function echo(arg){ console.log(arg); }
-
- Ember.expandProperties('foo.bar', echo); //=> 'foo.bar'
- Ember.expandProperties('{foo,bar}', echo); //=> 'foo', 'bar'
- Ember.expandProperties('foo.{bar,baz}', echo); //=> 'foo.bar', 'foo.baz'
- Ember.expandProperties('{foo,bar}.baz', echo); //=> '{foo,bar}.baz'
- Ember.expandProperties('foo.{bar,baz}.@each', echo) //=> 'foo.bar.@each', 'foo.baz.@each'
- Ember.expandProperties('{foo,bar}.{spam,eggs}', echo) //=> 'foo.spam', 'foo.eggs', 'bar.spam', 'bar.eggs'
- Ember.expandProperties('{foo}.bar.{baz}') //=> 'foo.bar.baz'
- ```
-
- @method
- @private
- @param {String} pattern The property pattern to expand.
- @param {Function} callback The callback to invoke. It is invoked once per
- expansion, and is passed the expansion.
- */
- __exports__["default"] = function expandProperties(pattern, callback) {
- if (pattern.indexOf(' ') > -1) {
- throw new EmberError('Brace expanded properties cannot contain spaces, ' +
- 'e.g. `user.{firstName, lastName}` should be `user.{firstName,lastName}`');
- }
-
-
- return newExpandProperties(pattern, callback);
- }
-
- function oldExpandProperties(pattern, callback) {
- var match, prefix, list;
-
- if (match = BRACE_EXPANSION.exec(pattern)) {
- prefix = match[1];
- list = match[2];
-
- forEach(list.split(','), function (suffix) {
- callback(prefix + suffix);
- });
- } else {
- callback(pattern);
- }
- }
-
- function newExpandProperties(pattern, callback) {
- if ('string' === Ember.typeOf(pattern)) {
- var parts = pattern.split(SPLIT_REGEX);
- var properties = [parts];
-
- forEach(parts, function(part, index) {
- if (part.indexOf(',') >= 0) {
- properties = duplicateAndReplace(properties, part.split(','), index);
- }
- });
-
- forEach(properties, function(property) {
- callback(property.join(''));
- });
- } else {
- callback(pattern);
- }
- }
-
- function duplicateAndReplace(properties, currentParts, index) {
- var all = [];
-
- forEach(properties, function(property) {
- forEach(currentParts, function(part) {
- var current = property.slice(0);
- current[index] = part;
- all.push(current);
- });
- });
-
- return all;
- }
- });
-enifed("ember-metal/get_properties",
- ["ember-metal/property_get","ember-metal/utils","exports"],
- function(__dependency1__, __dependency2__, __exports__) {
- "use strict";
- var get = __dependency1__.get;
- var typeOf = __dependency2__.typeOf;
-
- /**
- To get multiple properties at once, call `Ember.getProperties`
- with an object followed by a list of strings or an array:
-
- ```javascript
- Ember.getProperties(record, 'firstName', 'lastName', 'zipCode');
- // { firstName: 'John', lastName: 'Doe', zipCode: '10011' }
- ```
-
- is equivalent to:
-
- ```javascript
- Ember.getProperties(record, ['firstName', 'lastName', 'zipCode']);
- // { firstName: 'John', lastName: 'Doe', zipCode: '10011' }
- ```
-
- @method getProperties
- @param obj
- @param {String...|Array} list of keys to get
- @return {Hash}
- */
- __exports__["default"] = function getProperties(obj) {
- var ret = {};
- var propertyNames = arguments;
- var i = 1;
-
- if (arguments.length === 2 && typeOf(arguments[1]) === 'array') {
- i = 0;
- propertyNames = arguments[1];
- }
- for(var len = propertyNames.length; i < len; i++) {
- ret[propertyNames[i]] = get(obj, propertyNames[i]);
- }
- return ret;
- }
- });
-enifed("ember-metal/injected_property",
- ["ember-metal/core","ember-metal/computed","ember-metal/properties","ember-metal/platform","ember-metal/utils","ember-metal/error","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __exports__) {
- "use strict";
- var Ember = __dependency1__["default"];
- // Ember.assert
- var ComputedProperty = __dependency2__.ComputedProperty;
- var Descriptor = __dependency3__.Descriptor;
- var create = __dependency4__.create;
- var inspect = __dependency5__.inspect;
- var EmberError = __dependency6__["default"];
-
- /**
- Read-only property that returns the result of a container lookup.
-
- @class InjectedProperty
- @namespace Ember
- @extends Ember.Descriptor
- @constructor
- @param {String} type The container type the property will lookup
- @param {String} name (optional) The name the property will lookup, defaults
- to the property's name
- */
- function InjectedProperty(type, name) {
- this.type = type;
- this.name = name;
-
- this._super$Constructor(function(keyName) {
- Ember.assert("Attempting to lookup an injected property on an object " +
- "without a container, ensure that the object was " +
- "instantiated via a container.", this.container);
-
- return this.container.lookup(type + ':' + (name || keyName));
- }, { readOnly: true });
- }
-
- InjectedProperty.prototype = create(Descriptor.prototype);
-
- var InjectedPropertyPrototype = InjectedProperty.prototype;
- var ComputedPropertyPrototype = ComputedProperty.prototype;
-
- InjectedPropertyPrototype._super$Constructor = ComputedProperty;
-
- InjectedPropertyPrototype.get = ComputedPropertyPrototype.get;
-
- InjectedPropertyPrototype.set = function(obj, keyName) {
- throw new EmberError("Cannot set injected property '" + keyName + "' on object: " + inspect(obj));
- };
-
- InjectedPropertyPrototype.teardown = ComputedPropertyPrototype.teardown;
-
- __exports__["default"] = InjectedProperty;
- });
-enifed("ember-metal/instrumentation",
- ["ember-metal/core","ember-metal/utils","exports"],
- function(__dependency1__, __dependency2__, __exports__) {
- "use strict";
- var Ember = __dependency1__["default"];
- var tryCatchFinally = __dependency2__.tryCatchFinally;
-
- /**
- The purpose of the Ember Instrumentation module is
- to provide efficient, general-purpose instrumentation
- for Ember.
-
- Subscribe to a listener by using `Ember.subscribe`:
-
- ```javascript
- Ember.subscribe("render", {
- before: function(name, timestamp, payload) {
-
- },
-
- after: function(name, timestamp, payload) {
-
- }
- });
- ```
-
- If you return a value from the `before` callback, that same
- value will be passed as a fourth parameter to the `after`
- callback.
-
- Instrument a block of code by using `Ember.instrument`:
-
- ```javascript
- Ember.instrument("render.handlebars", payload, function() {
- // rendering logic
- }, binding);
- ```
-
- Event names passed to `Ember.instrument` are namespaced
- by periods, from more general to more specific. Subscribers
- can listen for events by whatever level of granularity they
- are interested in.
-
- In the above example, the event is `render.handlebars`,
- and the subscriber listened for all events beginning with
- `render`. It would receive callbacks for events named
- `render`, `render.handlebars`, `render.container`, or
- even `render.handlebars.layout`.
-
- @class Instrumentation
- @namespace Ember
- @static
- */
- var subscribers = [];
- __exports__.subscribers = subscribers;var cache = {};
-
- var populateListeners = function(name) {
- var listeners = [];
- var subscriber;
-
- for (var i=0, l=subscribers.length; i<l; i++) {
- subscriber = subscribers[i];
- if (subscriber.regex.test(name)) {
- listeners.push(subscriber.object);
- }
- }
-
- cache[name] = listeners;
- return listeners;
- };
-
- var time = (function() {
- var perf = 'undefined' !== typeof window ? window.performance || {} : {};
- var fn = perf.now || perf.mozNow || perf.webkitNow || perf.msNow || perf.oNow;
- // fn.bind will be available in all the browsers that support the advanced window.performance... ;-)
- return fn ? fn.bind(perf) : function() { return +new Date(); };
- })();
-
- /**
- Notifies event's subscribers, calls `before` and `after` hooks.
-
- @method instrument
- @namespace Ember.Instrumentation
-
- @param {String} [name] Namespaced event name.
- @param {Object} payload
- @param {Function} callback Function that you're instrumenting.
- @param {Object} binding Context that instrument function is called with.
- */
- function instrument(name, _payload, callback, binding) {
- if (subscribers.length === 0) {
- return callback.call(binding);
- }
- var payload = _payload || {};
- var finalizer = _instrumentStart(name, function () {
- return payload;
- });
- if (finalizer) {
- var tryable = function _instrumenTryable() {
- return callback.call(binding);
- };
- var catchable = function _instrumentCatchable(e) {
- payload.exception = e;
- };
- return tryCatchFinally(tryable, catchable, finalizer);
- } else {
- return callback.call(binding);
- }
- }
-
- __exports__.instrument = instrument;// private for now
- function _instrumentStart(name, _payload) {
- var listeners = cache[name];
-
- if (!listeners) {
- listeners = populateListeners(name);
- }
-
- if (listeners.length === 0) {
- return;
- }
-
- var payload = _payload();
-
- var STRUCTURED_PROFILE = Ember.STRUCTURED_PROFILE;
- var timeName;
- if (STRUCTURED_PROFILE) {
- timeName = name + ": " + payload.object;
- console.time(timeName);
- }
-
- var l = listeners.length;
- var beforeValues = new Array(l);
- var i, listener;
- var timestamp = time();
- for (i=0; i<l; i++) {
- listener = listeners[i];
- beforeValues[i] = listener.before(name, timestamp, payload);
- }
-
- return function _instrumentEnd() {
- var i, l, listener;
- var timestamp = time();
- for (i=0, l=listeners.length; i<l; i++) {
- listener = listeners[i];
- listener.after(name, timestamp, payload, beforeValues[i]);
- }
-
- if (STRUCTURED_PROFILE) {
- console.timeEnd(timeName);
- }
- };
- }
-
- __exports__._instrumentStart = _instrumentStart;/**
- Subscribes to a particular event or instrumented block of code.
-
- @method subscribe
- @namespace Ember.Instrumentation
-
- @param {String} [pattern] Namespaced event name.
- @param {Object} [object] Before and After hooks.
-
- @return {Subscriber}
- */
- function subscribe(pattern, object) {
- var paths = pattern.split("."), path, regex = [];
-
- for (var i=0, l=paths.length; i<l; i++) {
- path = paths[i];
- if (path === "*") {
- regex.push("[^\\.]*");
- } else {
- regex.push(path);
- }
- }
-
- regex = regex.join("\\.");
- regex = regex + "(\\..*)?";
-
- var subscriber = {
- pattern: pattern,
- regex: new RegExp("^" + regex + "$"),
- object: object
- };
-
- subscribers.push(subscriber);
- cache = {};
-
- return subscriber;
- }
-
- __exports__.subscribe = subscribe;/**
- Unsubscribes from a particular event or instrumented block of code.
-
- @method unsubscribe
- @namespace Ember.Instrumentation
-
- @param {Object} [subscriber]
- */
- function unsubscribe(subscriber) {
- var index;
-
- for (var i=0, l=subscribers.length; i<l; i++) {
- if (subscribers[i] === subscriber) {
- index = i;
- }
- }
-
- subscribers.splice(index, 1);
- cache = {};
- }
-
- __exports__.unsubscribe = unsubscribe;/**
- Resets `Ember.Instrumentation` by flushing list of subscribers.
-
- @method reset
- @namespace Ember.Instrumentation
- */
- function reset() {
- subscribers.length = 0;
- cache = {};
- }
-
- __exports__.reset = reset;
- });
-enifed("ember-metal/is_blank",
- ["ember-metal/is_empty","exports"],
- function(__dependency1__, __exports__) {
- "use strict";
- var isEmpty = __dependency1__["default"];
-
- /**
- A value is blank if it is empty or a whitespace string.
-
- ```javascript
- Ember.isBlank(); // true
- Ember.isBlank(null); // true
- Ember.isBlank(undefined); // true
- Ember.isBlank(''); // true
- Ember.isBlank([]); // true
- Ember.isBlank('\n\t'); // true
- Ember.isBlank(' '); // true
- Ember.isBlank({}); // false
- Ember.isBlank('\n\t Hello'); // false
- Ember.isBlank('Hello world'); // false
- Ember.isBlank([1,2,3]); // false
- ```
-
- @method isBlank
- @for Ember
- @param {Object} obj Value to test
- @return {Boolean}
- @since 1.5.0
- */
- __exports__["default"] = function isBlank(obj) {
- return isEmpty(obj) || (typeof obj === 'string' && obj.match(/\S/) === null);
- }
- });
-enifed("ember-metal/is_empty",
- ["ember-metal/property_get","ember-metal/is_none","exports"],
- function(__dependency1__, __dependency2__, __exports__) {
- "use strict";
- var get = __dependency1__.get;
- var isNone = __dependency2__["default"];
-
- /**
- Verifies that a value is `null` or an empty string, empty array,
- or empty function.
-
- Constrains the rules on `Ember.isNone` by returning true for empty
- string and empty arrays.
-
- ```javascript
- Ember.isEmpty(); // true
- Ember.isEmpty(null); // true
- Ember.isEmpty(undefined); // true
- Ember.isEmpty(''); // true
- Ember.isEmpty([]); // true
- Ember.isEmpty({}); // false
- Ember.isEmpty('Adam Hawkins'); // false
- Ember.isEmpty([0,1,2]); // false
- ```
-
- @method isEmpty
- @for Ember
- @param {Object} obj Value to test
- @return {Boolean}
- */
- function isEmpty(obj) {
- var none = isNone(obj);
- if (none) {
- return none;
- }
-
- if (typeof obj.size === 'number') {
- return !obj.size;
- }
-
- var objectType = typeof obj;
-
- if (objectType === 'object') {
- var size = get(obj, 'size');
- if (typeof size === 'number') {
- return !size;
- }
- }
-
- if (typeof obj.length === 'number' && objectType !== 'function') {
- return !obj.length;
- }
-
- if (objectType === 'object') {
- var length = get(obj, 'length');
- if (typeof length === 'number') {
- return !length;
- }
- }
-
- return false;
- }
-
- __exports__["default"] = isEmpty;
- });
-enifed("ember-metal/is_none",
- ["exports"],
- function(__exports__) {
- "use strict";
- /**
- Returns true if the passed value is null or undefined. This avoids errors
- from JSLint complaining about use of ==, which can be technically
- confusing.
-
- ```javascript
- Ember.isNone(); // true
- Ember.isNone(null); // true
- Ember.isNone(undefined); // true
- Ember.isNone(''); // false
- Ember.isNone([]); // false
- Ember.isNone(function() {}); // false
- ```
-
- @method isNone
- @for Ember
- @param {Object} obj Value to test
- @return {Boolean}
- */
- function isNone(obj) {
- return obj === null || obj === undefined;
- }
-
- __exports__["default"] = isNone;
- });
-enifed("ember-metal/is_present",
- ["ember-metal/is_blank","exports"],
- function(__dependency1__, __exports__) {
- "use strict";
- var isBlank = __dependency1__["default"];
- var isPresent;
-
-
- /**
- A value is present if it not `isBlank`.
-
- ```javascript
- Ember.isPresent(); // false
- Ember.isPresent(null); // false
- Ember.isPresent(undefined); // false
- Ember.isPresent(''); // false
- Ember.isPresent([]); // false
- Ember.isPresent('\n\t'); // false
- Ember.isPresent(' '); // false
- Ember.isPresent({}); // true
- Ember.isPresent('\n\t Hello'); // true
- Ember.isPresent('Hello world'); // true
- Ember.isPresent([1,2,3]); // true
- ```
-
- @method isPresent
- @for Ember
- @param {Object} obj Value to test
- @return {Boolean}
- @since 1.7.0
- */
- isPresent = function isPresent(obj) {
- return !isBlank(obj);
- };
-
-
- __exports__["default"] = isPresent;
- });
-enifed("ember-metal/keys",
- ["ember-metal/platform","exports"],
- function(__dependency1__, __exports__) {
- "use strict";
- var canDefineNonEnumerableProperties = __dependency1__.canDefineNonEnumerableProperties;
-
- /**
- Returns all of the keys defined on an object or hash. This is useful
- when inspecting objects for debugging. On browsers that support it, this
- uses the native `Object.keys` implementation.
-
- @method keys
- @for Ember
- @param {Object} obj
- @return {Array} Array containing keys of obj
- */
- var keys = Object.keys;
-
- if (!keys || !canDefineNonEnumerableProperties) {
- // modified from
- // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys
- keys = (function () {
- var hasOwnProperty = Object.prototype.hasOwnProperty,
- hasDontEnumBug = !({toString: null}).propertyIsEnumerable('toString'),
- dontEnums = [
- 'toString',
- 'toLocaleString',
- 'valueOf',
- 'hasOwnProperty',
- 'isPrototypeOf',
- 'propertyIsEnumerable',
- 'constructor'
- ],
- dontEnumsLength = dontEnums.length;
-
- return function keys(obj) {
- if (typeof obj !== 'object' && (typeof obj !== 'function' || obj === null)) {
- throw new TypeError('Object.keys called on non-object');
- }
-
- var result = [];
- var prop, i;
-
- for (prop in obj) {
- if (prop !== '_super' &&
- prop.lastIndexOf('__',0) !== 0 &&
- hasOwnProperty.call(obj, prop)) {
- result.push(prop);
- }
- }
-
- if (hasDontEnumBug) {
- for (i = 0; i < dontEnumsLength; i++) {
- if (hasOwnProperty.call(obj, dontEnums[i])) {
- result.push(dontEnums[i]);
- }
- }
- }
- return result;
- };
- }());
- }
-
- __exports__["default"] = keys;
- });
-enifed("ember-metal/libraries",
- ["ember-metal/enumerable_utils","exports"],
- function(__dependency1__, __exports__) {
- "use strict";
- // Provides a way to register library versions with ember.
- var forEach = __dependency1__.forEach;
- var indexOf = __dependency1__.indexOf;
-
- var libraries = function() {
- var _libraries = [];
- var coreLibIndex = 0;
-
- var getLibrary = function(name) {
- for (var i = 0; i < _libraries.length; i++) {
- if (_libraries[i].name === name) {
- return _libraries[i];
- }
- }
- };
-
- _libraries.register = function(name, version) {
- if (!getLibrary(name)) {
- _libraries.push({name: name, version: version});
- }
- };
-
- _libraries.registerCoreLibrary = function(name, version) {
- if (!getLibrary(name)) {
- _libraries.splice(coreLibIndex++, 0, {name: name, version: version});
- }
- };
-
- _libraries.deRegister = function(name) {
- var lib = getLibrary(name);
- if (lib) _libraries.splice(indexOf(_libraries, lib), 1);
- };
-
- _libraries.each = function (callback) {
- forEach(_libraries, function(lib) {
- callback(lib.name, lib.version);
- });
- };
-
- return _libraries;
- }();
-
- __exports__["default"] = libraries;
- });
-enifed("ember-metal/logger",
- ["ember-metal/core","ember-metal/error","exports"],
- function(__dependency1__, __dependency2__, __exports__) {
- "use strict";
- var Ember = __dependency1__["default"];
- var EmberError = __dependency2__["default"];
-
- function consoleMethod(name) {
- var consoleObj, logToConsole;
- if (Ember.imports.console) {
- consoleObj = Ember.imports.console;
- } else if (typeof console !== 'undefined') {
- consoleObj = console;
- }
-
- var method = typeof consoleObj === 'object' ? consoleObj[name] : null;
-
- if (method) {
- // Older IE doesn't support bind, but Chrome needs it
- if (typeof method.bind === 'function') {
- logToConsole = method.bind(consoleObj);
- logToConsole.displayName = 'console.' + name;
- return logToConsole;
- } else if (typeof method.apply === 'function') {
- logToConsole = function() {
- method.apply(consoleObj, arguments);
- };
- logToConsole.displayName = 'console.' + name;
- return logToConsole;
- } else {
- return function() {
- var message = Array.prototype.join.call(arguments, ', ');
- method(message);
- };
- }
- }
- }
-
- function assertPolyfill(test, message) {
- if (!test) {
- try {
- // attempt to preserve the stack
- throw new EmberError("assertion failed: " + message);
- } catch(error) {
- setTimeout(function() {
- throw error;
- }, 0);
- }
- }
- }
-
- /**
- Inside Ember-Metal, simply uses the methods from `imports.console`.
- Override this to provide more robust logging functionality.
-
- @class Logger
- @namespace Ember
- */
- __exports__["default"] = {
- /**
- Logs the arguments to the console.
- You can pass as many arguments as you want and they will be joined together with a space.
-
- ```javascript
- var foo = 1;
- Ember.Logger.log('log value of foo:', foo);
- // "log value of foo: 1" will be printed to the console
- ```
-
- @method log
- @for Ember.Logger
- @param {*} arguments
- */
- log: consoleMethod('log') || Ember.K,
-
- /**
- Prints the arguments to the console with a warning icon.
- You can pass as many arguments as you want and they will be joined together with a space.
-
- ```javascript
- Ember.Logger.warn('Something happened!');
- // "Something happened!" will be printed to the console with a warning icon.
- ```
-
- @method warn
- @for Ember.Logger
- @param {*} arguments
- */
- warn: consoleMethod('warn') || Ember.K,
-
- /**
- Prints the arguments to the console with an error icon, red text and a stack trace.
- You can pass as many arguments as you want and they will be joined together with a space.
-
- ```javascript
- Ember.Logger.error('Danger! Danger!');
- // "Danger! Danger!" will be printed to the console in red text.
- ```
-
- @method error
- @for Ember.Logger
- @param {*} arguments
- */
- error: consoleMethod('error') || Ember.K,
-
- /**
- Logs the arguments to the console.
- You can pass as many arguments as you want and they will be joined together with a space.
-
- ```javascript
- var foo = 1;
- Ember.Logger.info('log value of foo:', foo);
- // "log value of foo: 1" will be printed to the console
- ```
-
- @method info
- @for Ember.Logger
- @param {*} arguments
- */
- info: consoleMethod('info') || Ember.K,
-
- /**
- Logs the arguments to the console in blue text.
- You can pass as many arguments as you want and they will be joined together with a space.
-
- ```javascript
- var foo = 1;
- Ember.Logger.debug('log value of foo:', foo);
- // "log value of foo: 1" will be printed to the console
- ```
-
- @method debug
- @for Ember.Logger
- @param {*} arguments
- */
- debug: consoleMethod('debug') || consoleMethod('info') || Ember.K,
-
- /**
- If the value passed into `Ember.Logger.assert` is not truthy it will throw an error with a stack trace.
-
- ```javascript
- Ember.Logger.assert(true); // undefined
- Ember.Logger.assert(true === false); // Throws an Assertion failed error.
- ```
-
- @method assert
- @for Ember.Logger
- @param {Boolean} bool Value to test
- */
- assert: consoleMethod('assert') || assertPolyfill
- };
- });
-enifed("ember-metal/map",
- ["ember-metal/utils","ember-metal/array","ember-metal/platform","ember-metal/deprecate_property","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
- "use strict";
- /**
- @module ember-metal
- */
-
- /*
- JavaScript (before ES6) does not have a Map implementation. Objects,
- which are often used as dictionaries, may only have Strings as keys.
-
- Because Ember has a way to get a unique identifier for every object
- via `Ember.guidFor`, we can implement a performant Map with arbitrary
- keys. Because it is commonly used in low-level bookkeeping, Map is
- implemented as a pure JavaScript object for performance.
-
- This implementation follows the current iteration of the ES6 proposal for
- maps (http://wiki.ecmascript.org/doku.php?id=harmony:simple_maps_and_sets),
- with one exception: as we do not have the luxury of in-VM iteration, we implement a
- forEach method for iteration.
-
- Map is mocked out to look like an Ember object, so you can do
- `Ember.Map.create()` for symmetry with other Ember classes.
- */
-
- var guidFor = __dependency1__.guidFor;
- var indexOf = __dependency2__.indexOf;
- var create = __dependency3__.create;
- var deprecateProperty = __dependency4__.deprecateProperty;
-
- function missingFunction(fn) {
- throw new TypeError('' + Object.prototype.toString.call(fn) + " is not a function");
- }
-
- function missingNew(name) {
- throw new TypeError("Constructor " + name + "requires 'new'");
- }
-
- function copyNull(obj) {
- var output = create(null);
-
- for (var prop in obj) {
- // hasOwnPropery is not needed because obj is Object.create(null);
- output[prop] = obj[prop];
- }
-
- return output;
- }
-
- function copyMap(original, newObject) {
- var keys = original.keys.copy();
- var values = copyNull(original.values);
-
- newObject.keys = keys;
- newObject.values = values;
- newObject.size = original.size;
-
- return newObject;
- }
-
- /**
- This class is used internally by Ember and Ember Data.
- Please do not use it at this time. We plan to clean it up
- and add many tests soon.
-
- @class OrderedSet
- @namespace Ember
- @constructor
- @private
- */
- function OrderedSet() {
-
- if (this instanceof OrderedSet) {
- this.clear();
- this._silenceRemoveDeprecation = false;
- } else {
- missingNew("OrderedSet");
- }
- }
-
- /**
- @method create
- @static
- @return {Ember.OrderedSet}
- */
- OrderedSet.create = function() {
- var Constructor = this;
-
- return new Constructor();
- };
-
- OrderedSet.prototype = {
- constructor: OrderedSet,
- /**
- @method clear
- */
- clear: function() {
- this.presenceSet = create(null);
- this.list = [];
- this.size = 0;
- },
-
- /**
- @method add
- @param obj
- @param guid (optional, and for internal use)
- @return {Ember.OrderedSet}
- */
- add: function(obj, _guid) {
- var guid = _guid || guidFor(obj);
- var presenceSet = this.presenceSet;
- var list = this.list;
-
- if (presenceSet[guid] === true) {
- return;
- }
-
- presenceSet[guid] = true;
- this.size = list.push(obj);
-
- return this;
- },
-
- /**
- @deprecated
-
- @method remove
- @param obj
- @param _guid (optional and for internal use only)
- @return {Boolean}
- */
- remove: function(obj, _guid) {
- Ember.deprecate('Calling `OrderedSet.prototype.remove` has been deprecated, please use `OrderedSet.prototype.delete` instead.', this._silenceRemoveDeprecation);
-
- return this["delete"](obj, _guid);
- },
-
- /**
- @method delete
- @param obj
- @param _guid (optional and for internal use only)
- @return {Boolean}
- */
- "delete": function(obj, _guid) {
- var guid = _guid || guidFor(obj);
- var presenceSet = this.presenceSet;
- var list = this.list;
-
- if (presenceSet[guid] === true) {
- delete presenceSet[guid];
- var index = indexOf.call(list, obj);
- if (index > -1) {
- list.splice(index, 1);
- }
- this.size = list.length;
- return true;
- } else {
- return false;
- }
- },
-
- /**
- @method isEmpty
- @return {Boolean}
- */
- isEmpty: function() {
- return this.size === 0;
- },
-
- /**
- @method has
- @param obj
- @return {Boolean}
- */
- has: function(obj) {
- if (this.size === 0) { return false; }
-
- var guid = guidFor(obj);
- var presenceSet = this.presenceSet;
-
- return presenceSet[guid] === true;
- },
-
- /**
- @method forEach
- @param {Function} fn
- @param self
- */
- forEach: function(fn /*, thisArg*/) {
- if (typeof fn !== 'function') {
- missingFunction(fn);
- }
-
- if (this.size === 0) { return; }
-
- var list = this.list;
- var length = arguments.length;
- var i;
-
- if (length === 2) {
- for (i = 0; i < list.length; i++) {
- fn.call(arguments[1], list[i]);
- }
- } else {
- for (i = 0; i < list.length; i++) {
- fn(list[i]);
- }
- }
- },
-
- /**
- @method toArray
- @return {Array}
- */
- toArray: function() {
- return this.list.slice();
- },
-
- /**
- @method copy
- @return {Ember.OrderedSet}
- */
- copy: function() {
- var Constructor = this.constructor;
- var set = new Constructor();
-
- set._silenceRemoveDeprecation = this._silenceRemoveDeprecation;
- set.presenceSet = copyNull(this.presenceSet);
- set.list = this.toArray();
- set.size = this.size;
-
- return set;
- }
- };
-
- deprecateProperty(OrderedSet.prototype, 'length', 'size');
-
- /**
- A Map stores values indexed by keys. Unlike JavaScript's
- default Objects, the keys of a Map can be any JavaScript
- object.
-
- Internally, a Map has two data structures:
-
- 1. `keys`: an OrderedSet of all of the existing keys
- 2. `values`: a JavaScript Object indexed by the `Ember.guidFor(key)`
-
- When a key/value pair is added for the first time, we
- add the key to the `keys` OrderedSet, and create or
- replace an entry in `values`. When an entry is deleted,
- we delete its entry in `keys` and `values`.
-
- @class Map
- @namespace Ember
- @private
- @constructor
- */
- function Map() {
- if (this instanceof this.constructor) {
- this.keys = OrderedSet.create();
- this.keys._silenceRemoveDeprecation = true;
- this.values = create(null);
- this.size = 0;
- } else {
- missingNew("OrderedSet");
- }
- }
-
- Ember.Map = Map;
-
- /**
- @method create
- @static
- */
- Map.create = function() {
- var Constructor = this;
- return new Constructor();
- };
-
- Map.prototype = {
- constructor: Map,
-
- /**
- This property will change as the number of objects in the map changes.
-
- @property size
- @type number
- @default 0
- */
- size: 0,
-
- /**
- Retrieve the value associated with a given key.
-
- @method get
- @param {*} key
- @return {*} the value associated with the key, or `undefined`
- */
- get: function(key) {
- if (this.size === 0) { return; }
-
- var values = this.values;
- var guid = guidFor(key);
-
- return values[guid];
- },
-
- /**
- Adds a value to the map. If a value for the given key has already been
- provided, the new value will replace the old value.
-
- @method set
- @param {*} key
- @param {*} value
- @return {Ember.Map}
- */
- set: function(key, value) {
- var keys = this.keys;
- var values = this.values;
- var guid = guidFor(key);
-
- // ensure we don't store -0
- var k = key === -0 ? 0 : key;
-
- keys.add(k, guid);
-
- values[guid] = value;
-
- this.size = keys.size;
-
- return this;
- },
-
- /**
- @deprecated see delete
- Removes a value from the map for an associated key.
-
- @method remove
- @param {*} key
- @return {Boolean} true if an item was removed, false otherwise
- */
- remove: function(key) {
- Ember.deprecate('Calling `Map.prototype.remove` has been deprecated, please use `Map.prototype.delete` instead.');
-
- return this["delete"](key);
- },
-
- /**
- Removes a value from the map for an associated key.
-
- @method delete
- @param {*} key
- @return {Boolean} true if an item was removed, false otherwise
- */
- "delete": function(key) {
- if (this.size === 0) { return false; }
- // don't use ES6 "delete" because it will be annoying
- // to use in browsers that are not ES6 friendly;
- var keys = this.keys;
- var values = this.values;
- var guid = guidFor(key);
-
- if (keys["delete"](key, guid)) {
- delete values[guid];
- this.size = keys.size;
- return true;
- } else {
- return false;
- }
- },
-
- /**
- Check whether a key is present.
-
- @method has
- @param {*} key
- @return {Boolean} true if the item was present, false otherwise
- */
- has: function(key) {
- return this.keys.has(key);
- },
-
- /**
- Iterate over all the keys and values. Calls the function once
- for each key, passing in value, key, and the map being iterated over,
- in that order.
-
- The keys are guaranteed to be iterated over in insertion order.
-
- @method forEach
- @param {Function} callback
- @param {*} self if passed, the `this` value inside the
- callback. By default, `this` is the map.
- */
- forEach: function(callback /*, thisArg*/) {
- if (typeof callback !== 'function') {
- missingFunction(callback);
- }
-
- if (this.size === 0) { return; }
-
- var length = arguments.length;
- var map = this;
- var cb, thisArg;
-
- if (length === 2) {
- thisArg = arguments[1];
- cb = function(key) {
- callback.call(thisArg, map.get(key), key, map);
- };
- } else {
- cb = function(key) {
- callback(map.get(key), key, map);
- };
- }
-
- this.keys.forEach(cb);
- },
-
- /**
- @method clear
- */
- clear: function() {
- this.keys.clear();
- this.values = create(null);
- this.size = 0;
- },
-
- /**
- @method copy
- @return {Ember.Map}
- */
- copy: function() {
- return copyMap(this, new Map());
- }
- };
-
- deprecateProperty(Map.prototype, 'length', 'size');
-
- /**
- @class MapWithDefault
- @namespace Ember
- @extends Ember.Map
- @private
- @constructor
- @param [options]
- @param {*} [options.defaultValue]
- */
- function MapWithDefault(options) {
- this._super$constructor();
- this.defaultValue = options.defaultValue;
- }
-
- /**
- @method create
- @static
- @param [options]
- @param {*} [options.defaultValue]
- @return {Ember.MapWithDefault|Ember.Map} If options are passed, returns
- `Ember.MapWithDefault` otherwise returns `Ember.Map`
- */
- MapWithDefault.create = function(options) {
- if (options) {
- return new MapWithDefault(options);
- } else {
- return new Map();
- }
- };
-
- MapWithDefault.prototype = create(Map.prototype);
- MapWithDefault.prototype.constructor = MapWithDefault;
- MapWithDefault.prototype._super$constructor = Map;
- MapWithDefault.prototype._super$get = Map.prototype.get;
-
- /**
- Retrieve the value associated with a given key.
-
- @method get
- @param {*} key
- @return {*} the value associated with the key, or the default value
- */
- MapWithDefault.prototype.get = function(key) {
- var hasValue = this.has(key);
-
- if (hasValue) {
- return this._super$get(key);
- } else {
- var defaultValue = this.defaultValue(key);
- this.set(key, defaultValue);
- return defaultValue;
- }
- };
-
- /**
- @method copy
- @return {Ember.MapWithDefault}
- */
- MapWithDefault.prototype.copy = function() {
- var Constructor = this.constructor;
- return copyMap(this, new Constructor({
- defaultValue: this.defaultValue
- }));
- };
-
- __exports__["default"] = Map;
-
- __exports__.OrderedSet = OrderedSet;
- __exports__.Map = Map;
- __exports__.MapWithDefault = MapWithDefault;
- });
-enifed("ember-metal/merge",
- ["ember-metal/keys","exports"],
- function(__dependency1__, __exports__) {
- "use strict";
- var keys = __dependency1__["default"];
-
- /**
- Merge the contents of two objects together into the first object.
-
- ```javascript
- Ember.merge({first: 'Tom'}, {last: 'Dale'}); // {first: 'Tom', last: 'Dale'}
- var a = {first: 'Yehuda'}, b = {last: 'Katz'};
- Ember.merge(a, b); // a == {first: 'Yehuda', last: 'Katz'}, b == {last: 'Katz'}
- ```
-
- @method merge
- @for Ember
- @param {Object} original The object to merge into
- @param {Object} updates The object to copy properties from
- @return {Object}
- */
- __exports__["default"] = function merge(original, updates) {
- if (!updates || typeof updates !== 'object') {
- return original;
- }
-
- var props = keys(updates);
- var prop;
- var length = props.length;
-
- for (var i = 0; i < length; i++) {
- prop = props[i];
- original[prop] = updates[prop];
- }
-
- return original;
- }
- });
-enifed("ember-metal/mixin",
- ["ember-metal/core","ember-metal/merge","ember-metal/array","ember-metal/platform","ember-metal/property_get","ember-metal/property_set","ember-metal/utils","ember-metal/expand_properties","ember-metal/properties","ember-metal/computed","ember-metal/binding","ember-metal/observer","ember-metal/events","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __exports__) {
- // Remove "use strict"; from transpiled module until
- // https://bugs.webkit.org/show_bug.cgi?id=138038 is fixed
- //
- // REMOVE_USE_STRICT: true
-
- /**
- @module ember
- @submodule ember-metal
- */
-
- var Ember = __dependency1__["default"];
- // warn, assert, wrap, et;
- var merge = __dependency2__["default"];
- var a_indexOf = __dependency3__.indexOf;
- var a_forEach = __dependency3__.forEach;
- var o_create = __dependency4__.create;
- var get = __dependency5__.get;
- var set = __dependency6__.set;
- var trySet = __dependency6__.trySet;
- var guidFor = __dependency7__.guidFor;
- var metaFor = __dependency7__.meta;
- var wrap = __dependency7__.wrap;
- var makeArray = __dependency7__.makeArray;
- var apply = __dependency7__.apply;
- var isArray = __dependency7__.isArray;
- var expandProperties = __dependency8__["default"];
- var Descriptor = __dependency9__.Descriptor;
- var defineProperty = __dependency9__.defineProperty;
- var ComputedProperty = __dependency10__.ComputedProperty;
- var Binding = __dependency11__.Binding;
- var addObserver = __dependency12__.addObserver;
- var removeObserver = __dependency12__.removeObserver;
- var addBeforeObserver = __dependency12__.addBeforeObserver;
- var removeBeforeObserver = __dependency12__.removeBeforeObserver;
- var _suspendObserver = __dependency12__._suspendObserver;
- var addListener = __dependency13__.addListener;
- var removeListener = __dependency13__.removeListener;
-
- var REQUIRED;
- var a_slice = [].slice;
-
- function superFunction(){
- var func = this.__nextSuper;
- var ret;
- if (func) {
- var args = new Array(arguments.length);
- for (var i = 0, l = args.length; i < l; i++) {
- args[i] = arguments[i];
- }
- this.__nextSuper = null;
- ret = apply(this, func, args);
- this.__nextSuper = func;
- }
- return ret;
- }
-
- function mixinsMeta(obj) {
- var m = metaFor(obj, true);
- var ret = m.mixins;
- if (!ret) {
- ret = m.mixins = {};
- } else if (!m.hasOwnProperty('mixins')) {
- ret = m.mixins = o_create(ret);
- }
- return ret;
- }
-
- function isMethod(obj) {
- return 'function' === typeof obj &&
- obj.isMethod !== false &&
- obj !== Boolean &&
- obj !== Object &&
- obj !== Number &&
- obj !== Array &&
- obj !== Date &&
- obj !== String;
- }
-
- var CONTINUE = {};
-
- function mixinProperties(mixinsMeta, mixin) {
- var guid;
-
- if (mixin instanceof Mixin) {
- guid = guidFor(mixin);
- if (mixinsMeta[guid]) { return CONTINUE; }
- mixinsMeta[guid] = mixin;
- return mixin.properties;
- } else {
- return mixin; // apply anonymous mixin properties
- }
- }
-
- function concatenatedMixinProperties(concatProp, props, values, base) {
- var concats;
-
- // reset before adding each new mixin to pickup concats from previous
- concats = values[concatProp] || base[concatProp];
- if (props[concatProp]) {
- concats = concats ? concats.concat(props[concatProp]) : props[concatProp];
- }
-
- return concats;
- }
-
- function giveDescriptorSuper(meta, key, property, values, descs) {
- var superProperty;
-
- // Computed properties override methods, and do not call super to them
- if (values[key] === undefined) {
- // Find the original descriptor in a parent mixin
- superProperty = descs[key];
- }
-
- // If we didn't find the original descriptor in a parent mixin, find
- // it on the original object.
- superProperty = superProperty || meta.descs[key];
-
- if (superProperty === undefined || !(superProperty instanceof ComputedProperty)) {
- return property;
- }
-
- // Since multiple mixins may inherit from the same parent, we need
- // to clone the computed property so that other mixins do not receive
- // the wrapped version.
- property = o_create(property);
- property.func = wrap(property.func, superProperty.func);
-
- return property;
- }
-
- var sourceAvailable = (function() {
- return this;
- }).toString().indexOf('return this;') > -1;
-
- function giveMethodSuper(obj, key, method, values, descs) {
- var superMethod;
-
- // Methods overwrite computed properties, and do not call super to them.
- if (descs[key] === undefined) {
- // Find the original method in a parent mixin
- superMethod = values[key];
- }
-
- // If we didn't find the original value in a parent mixin, find it in
- // the original object
- superMethod = superMethod || obj[key];
-
- // Only wrap the new method if the original method was a function
- if (superMethod === undefined || 'function' !== typeof superMethod) {
- return method;
- }
-
- var hasSuper;
- if (sourceAvailable) {
- hasSuper = method.__hasSuper;
-
- if (hasSuper === undefined) {
- hasSuper = method.toString().indexOf('_super') > -1;
- method.__hasSuper = hasSuper;
- }
- }
-
- if (sourceAvailable === false || hasSuper) {
- return wrap(method, superMethod);
- } else {
- return method;
- }
- }
-
- function applyConcatenatedProperties(obj, key, value, values) {
- var baseValue = values[key] || obj[key];
-
- if (baseValue) {
- if ('function' === typeof baseValue.concat) {
- if (value === null || value === undefined) {
- return baseValue;
- } else {
- return baseValue.concat(value);
- }
- } else {
- return makeArray(baseValue).concat(value);
- }
- } else {
- return makeArray(value);
- }
- }
-
- function applyMergedProperties(obj, key, value, values) {
- var baseValue = values[key] || obj[key];
-
- Ember.assert("You passed in `" + JSON.stringify(value) + "` as the value for `" + key +
- "` but `" + key + "` cannot be an Array", !isArray(value));
-
- if (!baseValue) { return value; }
-
- var newBase = merge({}, baseValue);
- var hasFunction = false;
-
- for (var prop in value) {
- if (!value.hasOwnProperty(prop)) { continue; }
-
- var propValue = value[prop];
- if (isMethod(propValue)) {
- // TODO: support for Computed Properties, etc?
- hasFunction = true;
- newBase[prop] = giveMethodSuper(obj, prop, propValue, baseValue, {});
- } else {
- newBase[prop] = propValue;
- }
- }
-
- if (hasFunction) {
- newBase._super = superFunction;
- }
-
- return newBase;
- }
-
- function addNormalizedProperty(base, key, value, meta, descs, values, concats, mergings) {
- if (value instanceof Descriptor) {
- if (value === REQUIRED && descs[key]) { return CONTINUE; }
-
- // Wrap descriptor function to implement
- // __nextSuper() if needed
- if (value.func) {
- value = giveDescriptorSuper(meta, key, value, values, descs);
- }
-
- descs[key] = value;
- values[key] = undefined;
- } else {
- if ((concats && a_indexOf.call(concats, key) >= 0) ||
- key === 'concatenatedProperties' ||
- key === 'mergedProperties') {
- value = applyConcatenatedProperties(base, key, value, values);
- } else if ((mergings && a_indexOf.call(mergings, key) >= 0)) {
- value = applyMergedProperties(base, key, value, values);
- } else if (isMethod(value)) {
- value = giveMethodSuper(base, key, value, values, descs);
- }
-
- descs[key] = undefined;
- values[key] = value;
- }
- }
-
- function mergeMixins(mixins, m, descs, values, base, keys) {
- var mixin, props, key, concats, mergings, meta;
-
- function removeKeys(keyName) {
- delete descs[keyName];
- delete values[keyName];
- }
-
- for(var i=0, l=mixins.length; i<l; i++) {
- mixin = mixins[i];
- Ember.assert('Expected hash or Mixin instance, got ' + Object.prototype.toString.call(mixin),
- typeof mixin === 'object' && mixin !== null && Object.prototype.toString.call(mixin) !== '[object Array]');
-
- props = mixinProperties(m, mixin);
- if (props === CONTINUE) { continue; }
-
- if (props) {
- meta = metaFor(base);
- if (base.willMergeMixin) { base.willMergeMixin(props); }
- concats = concatenatedMixinProperties('concatenatedProperties', props, values, base);
- mergings = concatenatedMixinProperties('mergedProperties', props, values, base);
-
- for (key in props) {
- if (!props.hasOwnProperty(key)) { continue; }
- keys.push(key);
- addNormalizedProperty(base, key, props[key], meta, descs, values, concats, mergings);
- }
-
- // manually copy toString() because some JS engines do not enumerate it
- if (props.hasOwnProperty('toString')) { base.toString = props.toString; }
- } else if (mixin.mixins) {
- mergeMixins(mixin.mixins, m, descs, values, base, keys);
- if (mixin._without) { a_forEach.call(mixin._without, removeKeys); }
- }
- }
- }
-
- var IS_BINDING = /^.+Binding$/;
-
- function detectBinding(obj, key, value, m) {
- if (IS_BINDING.test(key)) {
- var bindings = m.bindings;
- if (!bindings) {
- bindings = m.bindings = {};
- } else if (!m.hasOwnProperty('bindings')) {
- bindings = m.bindings = o_create(m.bindings);
- }
- bindings[key] = value;
- }
- }
-
- function connectStreamBinding(obj, key, stream) {
- var onNotify = function(stream) {
- _suspendObserver(obj, key, null, didChange, function() {
- trySet(obj, key, stream.value());
- });
- };
-
- var didChange = function() {
- stream.setValue(get(obj, key), onNotify);
- };
-
- // Initialize value
- set(obj, key, stream.value());
-
- addObserver(obj, key, null, didChange);
-
- stream.subscribe(onNotify);
-
- if (obj._streamBindingSubscriptions === undefined) {
- obj._streamBindingSubscriptions = o_create(null);
- }
-
- obj._streamBindingSubscriptions[key] = onNotify;
- }
-
- function connectBindings(obj, m) {
- // TODO Mixin.apply(instance) should disconnect binding if exists
- var bindings = m.bindings;
- var key, binding, to;
- if (bindings) {
- for (key in bindings) {
- binding = bindings[key];
- if (binding) {
- to = key.slice(0, -7); // strip Binding off end
- if (binding.isStream) {
- connectStreamBinding(obj, to, binding);
- continue;
- } else if (binding instanceof Binding) {
- binding = binding.copy(); // copy prototypes' instance
- binding.to(to);
- } else { // binding is string path
- binding = new Binding(to, binding);
- }
- binding.connect(obj);
- obj[key] = binding;
- }
- }
- // mark as applied
- m.bindings = {};
- }
- }
-
- function finishPartial(obj, m) {
- connectBindings(obj, m || metaFor(obj));
- return obj;
- }
-
- function followAlias(obj, desc, m, descs, values) {
- var altKey = desc.methodName;
- var value;
- if (descs[altKey] || values[altKey]) {
- value = values[altKey];
- desc = descs[altKey];
- } else if (m.descs[altKey]) {
- desc = m.descs[altKey];
- value = undefined;
- } else {
- desc = undefined;
- value = obj[altKey];
- }
-
- return { desc: desc, value: value };
- }
-
- function updateObserversAndListeners(obj, key, observerOrListener, pathsKey, updateMethod) {
- var paths = observerOrListener[pathsKey];
-
- if (paths) {
- for (var i=0, l=paths.length; i<l; i++) {
- updateMethod(obj, paths[i], null, key);
- }
- }
- }
-
- function replaceObserversAndListeners(obj, key, observerOrListener) {
- var prev = obj[key];
-
- if ('function' === typeof prev) {
- updateObserversAndListeners(obj, key, prev, '__ember_observesBefore__', removeBeforeObserver);
- updateObserversAndListeners(obj, key, prev, '__ember_observes__', removeObserver);
- updateObserversAndListeners(obj, key, prev, '__ember_listens__', removeListener);
- }
-
- if ('function' === typeof observerOrListener) {
- updateObserversAndListeners(obj, key, observerOrListener, '__ember_observesBefore__', addBeforeObserver);
- updateObserversAndListeners(obj, key, observerOrListener, '__ember_observes__', addObserver);
- updateObserversAndListeners(obj, key, observerOrListener, '__ember_listens__', addListener);
- }
- }
-
- function applyMixin(obj, mixins, partial) {
- var descs = {};
- var values = {};
- var m = metaFor(obj);
- var keys = [];
- var key, value, desc;
-
- obj._super = superFunction;
-
- // Go through all mixins and hashes passed in, and:
- //
- // * Handle concatenated properties
- // * Handle merged properties
- // * Set up _super wrapping if necessary
- // * Set up computed property descriptors
- // * Copying `toString` in broken browsers
- mergeMixins(mixins, mixinsMeta(obj), descs, values, obj, keys);
-
- for(var i = 0, l = keys.length; i < l; i++) {
- key = keys[i];
- if (key === 'constructor' || !values.hasOwnProperty(key)) { continue; }
-
- desc = descs[key];
- value = values[key];
-
- if (desc === REQUIRED) { continue; }
-
- while (desc && desc instanceof Alias) {
- var followed = followAlias(obj, desc, m, descs, values);
- desc = followed.desc;
- value = followed.value;
- }
-
- if (desc === undefined && value === undefined) { continue; }
-
- replaceObserversAndListeners(obj, key, value);
- detectBinding(obj, key, value, m);
- defineProperty(obj, key, desc, value, m);
- }
-
- if (!partial) { // don't apply to prototype
- finishPartial(obj, m);
- }
-
- return obj;
- }
-
- /**
- @method mixin
- @for Ember
- @param obj
- @param mixins*
- @return obj
- */
- function mixin(obj) {
- var args = a_slice.call(arguments, 1);
- applyMixin(obj, args, false);
- return obj;
- }
-
- __exports__.mixin = mixin;/**
- The `Ember.Mixin` class allows you to create mixins, whose properties can be
- added to other classes. For instance,
-
- ```javascript
- App.Editable = Ember.Mixin.create({
- edit: function() {
- console.log('starting to edit');
- this.set('isEditing', true);
- },
- isEditing: false
- });
-
- // Mix mixins into classes by passing them as the first arguments to
- // .extend.
- App.CommentView = Ember.View.extend(App.Editable, {
- template: Ember.Handlebars.compile('{{#if view.isEditing}}...{{else}}...{{/if}}')
- });
-
- commentView = App.CommentView.create();
- commentView.edit(); // outputs 'starting to edit'
- ```
-
- Note that Mixins are created with `Ember.Mixin.create`, not
- `Ember.Mixin.extend`.
-
- Note that mixins extend a constructor's prototype so arrays and object literals
- defined as properties will be shared amongst objects that implement the mixin.
- If you want to define a property in a mixin that is not shared, you can define
- it either as a computed property or have it be created on initialization of the object.
-
- ```javascript
- //filters array will be shared amongst any object implementing mixin
- App.Filterable = Ember.Mixin.create({
- filters: Ember.A()
- });
-
- //filters will be a separate array for every object implementing the mixin
- App.Filterable = Ember.Mixin.create({
- filters: Ember.computed(function(){return Ember.A();})
- });
-
- //filters will be created as a separate array during the object's initialization
- App.Filterable = Ember.Mixin.create({
- init: function() {
- this._super();
- this.set("filters", Ember.A());
- }
- });
- ```
-
- @class Mixin
- @namespace Ember
- */
- __exports__["default"] = Mixin;
- function Mixin(args, properties) {
- this.properties = properties;
-
- var length = args && args.length;
-
- if (length > 0) {
- var m = new Array(length);
-
- for (var i = 0; i < length; i++) {
- var x = args[i];
- if (x instanceof Mixin) {
- m[i] = x;
- } else {
- m[i] = new Mixin(undefined, x);
- }
- }
-
- this.mixins = m;
- } else {
- this.mixins = undefined;
- }
- this.ownerConstructor = undefined;
- }
-
- Mixin._apply = applyMixin;
-
- Mixin.applyPartial = function(obj) {
- var args = a_slice.call(arguments, 1);
- return applyMixin(obj, args, true);
- };
-
- Mixin.finishPartial = finishPartial;
-
- // ES6TODO: this relies on a global state?
- Ember.anyUnprocessedMixins = false;
-
- /**
- @method create
- @static
- @param arguments*
- */
- Mixin.create = function() {
- // ES6TODO: this relies on a global state?
- Ember.anyUnprocessedMixins = true;
- var M = this;
- var length = arguments.length;
- var args = new Array(length);
- for (var i = 0; i < length; i++) {
- args[i] = arguments[i];
- }
- return new M(args, undefined);
- };
-
- var MixinPrototype = Mixin.prototype;
-
- /**
- @method reopen
- @param arguments*
- */
- MixinPrototype.reopen = function() {
- var mixin;
-
- if (this.properties) {
- mixin = new Mixin(undefined, this.properties);
- this.properties = undefined;
- this.mixins = [mixin];
- } else if (!this.mixins) {
- this.mixins = [];
- }
-
- var len = arguments.length;
- var mixins = this.mixins;
- var idx;
-
- for(idx=0; idx < len; idx++) {
- mixin = arguments[idx];
- Ember.assert('Expected hash or Mixin instance, got ' + Object.prototype.toString.call(mixin),
- typeof mixin === 'object' && mixin !== null &&
- Object.prototype.toString.call(mixin) !== '[object Array]');
-
- if (mixin instanceof Mixin) {
- mixins.push(mixin);
- } else {
- mixins.push(new Mixin(undefined, mixin));
- }
- }
-
- return this;
- };
-
- /**
- @method apply
- @param obj
- @return applied object
- */
- MixinPrototype.apply = function(obj) {
- return applyMixin(obj, [this], false);
- };
-
- MixinPrototype.applyPartial = function(obj) {
- return applyMixin(obj, [this], true);
- };
-
- function _detect(curMixin, targetMixin, seen) {
- var guid = guidFor(curMixin);
-
- if (seen[guid]) { return false; }
- seen[guid] = true;
-
- if (curMixin === targetMixin) { return true; }
- var mixins = curMixin.mixins;
- var loc = mixins ? mixins.length : 0;
- while (--loc >= 0) {
- if (_detect(mixins[loc], targetMixin, seen)) { return true; }
- }
- return false;
- }
-
- /**
- @method detect
- @param obj
- @return {Boolean}
- */
- MixinPrototype.detect = function(obj) {
- if (!obj) { return false; }
- if (obj instanceof Mixin) { return _detect(obj, this, {}); }
- var m = obj['__ember_meta__'];
- var mixins = m && m.mixins;
- if (mixins) {
- return !!mixins[guidFor(this)];
- }
- return false;
- };
-
- MixinPrototype.without = function() {
- var ret = new Mixin([this]);
- ret._without = a_slice.call(arguments);
- return ret;
- };
-
- function _keys(ret, mixin, seen) {
- if (seen[guidFor(mixin)]) { return; }
- seen[guidFor(mixin)] = true;
-
- if (mixin.properties) {
- var props = mixin.properties;
- for (var key in props) {
- if (props.hasOwnProperty(key)) { ret[key] = true; }
- }
- } else if (mixin.mixins) {
- a_forEach.call(mixin.mixins, function(x) { _keys(ret, x, seen); });
- }
- }
-
- MixinPrototype.keys = function() {
- var keys = {};
- var seen = {};
- var ret = [];
- _keys(keys, this, seen);
- for(var key in keys) {
- if (keys.hasOwnProperty(key)) {
- ret.push(key);
- }
- }
- return ret;
- };
-
- // returns the mixins currently applied to the specified object
- // TODO: Make Ember.mixin
- Mixin.mixins = function(obj) {
- var m = obj['__ember_meta__'];
- var mixins = m && m.mixins;
- var ret = [];
-
- if (!mixins) { return ret; }
-
- for (var key in mixins) {
- var mixin = mixins[key];
-
- // skip primitive mixins since these are always anonymous
- if (!mixin.properties) { ret.push(mixin); }
- }
-
- return ret;
- };
-
- REQUIRED = new Descriptor();
- REQUIRED.toString = function() { return '(Required Property)'; };
-
- /**
- Denotes a required property for a mixin
-
- @method required
- @for Ember
- */
- function required() {
- return REQUIRED;
- }
-
- __exports__.required = required;function Alias(methodName) {
- this.methodName = methodName;
- }
-
- Alias.prototype = new Descriptor();
-
- /**
- Makes a method available via an additional name.
-
- ```javascript
- App.Person = Ember.Object.extend({
- name: function() {
- return 'Tomhuda Katzdale';
- },
- moniker: Ember.aliasMethod('name')
- });
-
- var goodGuy = App.Person.create();
-
- goodGuy.name(); // 'Tomhuda Katzdale'
- goodGuy.moniker(); // 'Tomhuda Katzdale'
- ```
-
- @method aliasMethod
- @for Ember
- @param {String} methodName name of the method to alias
- @return {Ember.Descriptor}
- */
- function aliasMethod(methodName) {
- return new Alias(methodName);
- }
-
- __exports__.aliasMethod = aliasMethod;// ..........................................................
- // OBSERVER HELPER
- //
-
- /**
- Specify a method that observes property changes.
-
- ```javascript
- Ember.Object.extend({
- valueObserver: Ember.observer('value', function() {
- // Executes whenever the "value" property changes
- })
- });
- ```
-
- In the future this method may become asynchronous. If you want to ensure
- synchronous behavior, use `immediateObserver`.
-
- Also available as `Function.prototype.observes` if prototype extensions are
- enabled.
-
- @method observer
- @for Ember
- @param {String} propertyNames*
- @param {Function} func
- @return func
- */
- function observer() {
- var func = a_slice.call(arguments, -1)[0];
- var paths;
-
- var addWatchedProperty = function (path) { paths.push(path); };
- var _paths = a_slice.call(arguments, 0, -1);
-
- if (typeof func !== "function") {
- // revert to old, soft-deprecated argument ordering
-
- func = arguments[0];
- _paths = a_slice.call(arguments, 1);
- }
-
- paths = [];
-
- for (var i=0; i<_paths.length; ++i) {
- expandProperties(_paths[i], addWatchedProperty);
- }
-
- if (typeof func !== "function") {
- throw new Ember.Error("Ember.observer called without a function");
- }
-
- func.__ember_observes__ = paths;
- return func;
- }
-
- __exports__.observer = observer;/**
- Specify a method that observes property changes.
-
- ```javascript
- Ember.Object.extend({
- valueObserver: Ember.immediateObserver('value', function() {
- // Executes whenever the "value" property changes
- })
- });
- ```
-
- In the future, `Ember.observer` may become asynchronous. In this event,
- `Ember.immediateObserver` will maintain the synchronous behavior.
-
- Also available as `Function.prototype.observesImmediately` if prototype extensions are
- enabled.
-
- @method immediateObserver
- @for Ember
- @param {String} propertyNames*
- @param {Function} func
- @return func
- */
- function immediateObserver() {
- for (var i=0, l=arguments.length; i<l; i++) {
- var arg = arguments[i];
- Ember.assert("Immediate observers must observe internal properties only, not properties on other objects.",
- typeof arg !== "string" || arg.indexOf('.') === -1);
- }
-
- return observer.apply(this, arguments);
- }
-
- __exports__.immediateObserver = immediateObserver;/**
- When observers fire, they are called with the arguments `obj`, `keyName`.
-
- Note, `@each.property` observer is called per each add or replace of an element
- and it's not called with a specific enumeration item.
-
- A `beforeObserver` fires before a property changes.
-
- A `beforeObserver` is an alternative form of `.observesBefore()`.
-
- ```javascript
- App.PersonView = Ember.View.extend({
- friends: [{ name: 'Tom' }, { name: 'Stefan' }, { name: 'Kris' }],
-
- valueWillChange: Ember.beforeObserver('content.value', function(obj, keyName) {
- this.changingFrom = obj.get(keyName);
- }),
-
- valueDidChange: Ember.observer('content.value', function(obj, keyName) {
- // only run if updating a value already in the DOM
- if (this.get('state') === 'inDOM') {
- var color = obj.get(keyName) > this.changingFrom ? 'green' : 'red';
- // logic
- }
- }),
-
- friendsDidChange: Ember.observer('friends.@each.name', function(obj, keyName) {
- // some logic
- // obj.get(keyName) returns friends array
- })
- });
- ```
-
- Also available as `Function.prototype.observesBefore` if prototype extensions are
- enabled.
-
- @method beforeObserver
- @for Ember
- @param {String} propertyNames*
- @param {Function} func
- @return func
- */
- function beforeObserver() {
- var func = a_slice.call(arguments, -1)[0];
- var paths;
-
- var addWatchedProperty = function(path) { paths.push(path); };
-
- var _paths = a_slice.call(arguments, 0, -1);
-
- if (typeof func !== "function") {
- // revert to old, soft-deprecated argument ordering
-
- func = arguments[0];
- _paths = a_slice.call(arguments, 1);
- }
-
- paths = [];
-
- for (var i=0; i<_paths.length; ++i) {
- expandProperties(_paths[i], addWatchedProperty);
- }
-
- if (typeof func !== "function") {
- throw new Ember.Error("Ember.beforeObserver called without a function");
- }
-
- func.__ember_observesBefore__ = paths;
- return func;
- }
-
- __exports__.beforeObserver = beforeObserver;__exports__.IS_BINDING = IS_BINDING;
- __exports__.Mixin = Mixin;
- });
-enifed("ember-metal/observer",
- ["ember-metal/watching","ember-metal/array","ember-metal/events","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
- "use strict";
- var watch = __dependency1__.watch;
- var unwatch = __dependency1__.unwatch;
- var map = __dependency2__.map;
- var listenersFor = __dependency3__.listenersFor;
- var addListener = __dependency3__.addListener;
- var removeListener = __dependency3__.removeListener;
- var suspendListeners = __dependency3__.suspendListeners;
- var suspendListener = __dependency3__.suspendListener;
- /**
- @module ember-metal
- */
-
- var AFTER_OBSERVERS = ':change';
- var BEFORE_OBSERVERS = ':before';
-
- function changeEvent(keyName) {
- return keyName + AFTER_OBSERVERS;
- }
-
- function beforeEvent(keyName) {
- return keyName + BEFORE_OBSERVERS;
- }
-
- /**
- @method addObserver
- @for Ember
- @param obj
- @param {String} path
- @param {Object|Function} targetOrMethod
- @param {Function|String} [method]
- */
- function addObserver(obj, _path, target, method) {
- addListener(obj, changeEvent(_path), target, method);
- watch(obj, _path);
-
- return this;
- }
-
- __exports__.addObserver = addObserver;function observersFor(obj, path) {
- return listenersFor(obj, changeEvent(path));
- }
-
- __exports__.observersFor = observersFor;/**
- @method removeObserver
- @for Ember
- @param obj
- @param {String} path
- @param {Object|Function} target
- @param {Function|String} [method]
- */
- function removeObserver(obj, path, target, method) {
- unwatch(obj, path);
- removeListener(obj, changeEvent(path), target, method);
-
- return this;
- }
-
- __exports__.removeObserver = removeObserver;/**
- @method addBeforeObserver
- @for Ember
- @param obj
- @param {String} path
- @param {Object|Function} target
- @param {Function|String} [method]
- */
- function addBeforeObserver(obj, path, target, method) {
- addListener(obj, beforeEvent(path), target, method);
- watch(obj, path);
-
- return this;
- }
-
- __exports__.addBeforeObserver = addBeforeObserver;// Suspend observer during callback.
- //
- // This should only be used by the target of the observer
- // while it is setting the observed path.
- function _suspendBeforeObserver(obj, path, target, method, callback) {
- return suspendListener(obj, beforeEvent(path), target, method, callback);
- }
-
- __exports__._suspendBeforeObserver = _suspendBeforeObserver;function _suspendObserver(obj, path, target, method, callback) {
- return suspendListener(obj, changeEvent(path), target, method, callback);
- }
-
- __exports__._suspendObserver = _suspendObserver;function _suspendBeforeObservers(obj, paths, target, method, callback) {
- var events = map.call(paths, beforeEvent);
- return suspendListeners(obj, events, target, method, callback);
- }
-
- __exports__._suspendBeforeObservers = _suspendBeforeObservers;function _suspendObservers(obj, paths, target, method, callback) {
- var events = map.call(paths, changeEvent);
- return suspendListeners(obj, events, target, method, callback);
- }
-
- __exports__._suspendObservers = _suspendObservers;function beforeObserversFor(obj, path) {
- return listenersFor(obj, beforeEvent(path));
- }
-
- __exports__.beforeObserversFor = beforeObserversFor;/**
- @method removeBeforeObserver
- @for Ember
- @param obj
- @param {String} path
- @param {Object|Function} target
- @param {Function|String} [method]
- */
- function removeBeforeObserver(obj, path, target, method) {
- unwatch(obj, path);
- removeListener(obj, beforeEvent(path), target, method);
-
- return this;
- }
-
- __exports__.removeBeforeObserver = removeBeforeObserver;
- });
-enifed("ember-metal/observer_set",
- ["ember-metal/utils","ember-metal/events","exports"],
- function(__dependency1__, __dependency2__, __exports__) {
- "use strict";
- var guidFor = __dependency1__.guidFor;
- var sendEvent = __dependency2__.sendEvent;
-
- /*
- this.observerSet = {
- [senderGuid]: { // variable name: `keySet`
- [keyName]: listIndex
- }
- },
- this.observers = [
- {
- sender: obj,
- keyName: keyName,
- eventName: eventName,
- listeners: [
- [target, method, flags]
- ]
- },
- ...
- ]
- */
- __exports__["default"] = ObserverSet;
- function ObserverSet() {
- this.clear();
- }
-
-
- ObserverSet.prototype.add = function(sender, keyName, eventName) {
- var observerSet = this.observerSet;
- var observers = this.observers;
- var senderGuid = guidFor(sender);
- var keySet = observerSet[senderGuid];
- var index;
-
- if (!keySet) {
- observerSet[senderGuid] = keySet = {};
- }
- index = keySet[keyName];
- if (index === undefined) {
- index = observers.push({
- sender: sender,
- keyName: keyName,
- eventName: eventName,
- listeners: []
- }) - 1;
- keySet[keyName] = index;
- }
- return observers[index].listeners;
- };
-
- ObserverSet.prototype.flush = function() {
- var observers = this.observers;
- var i, len, observer, sender;
- this.clear();
- for (i=0, len=observers.length; i < len; ++i) {
- observer = observers[i];
- sender = observer.sender;
- if (sender.isDestroying || sender.isDestroyed) { continue; }
- sendEvent(sender, observer.eventName, [sender, observer.keyName], observer.listeners);
- }
- };
-
- ObserverSet.prototype.clear = function() {
- this.observerSet = {};
- this.observers = [];
- };
- });
-enifed("ember-metal/path_cache",
- ["ember-metal/cache","exports"],
- function(__dependency1__, __exports__) {
- "use strict";
- var Cache = __dependency1__["default"];
-
- var IS_GLOBAL = /^([A-Z$]|([0-9][A-Z$]))/;
- var IS_GLOBAL_PATH = /^([A-Z$]|([0-9][A-Z$])).*[\.]/;
- var HAS_THIS = 'this.';
-
- var isGlobalCache = new Cache(1000, function(key) { return IS_GLOBAL.test(key); });
- var isGlobalPathCache = new Cache(1000, function(key) { return IS_GLOBAL_PATH.test(key); });
- var hasThisCache = new Cache(1000, function(key) { return key.indexOf(HAS_THIS) !== -1; });
- var firstDotIndexCache = new Cache(1000, function(key) { return key.indexOf('.'); });
-
- var firstKeyCache = new Cache(1000, function(path) {
- var index = firstDotIndexCache.get(path);
- if (index === -1) {
- return path;
- } else {
- return path.slice(0, index);
- }
- });
-
- var tailPathCache = new Cache(1000, function(path) {
- var index = firstDotIndexCache.get(path);
- if (index !== -1) {
- return path.slice(index + 1);
- }
- });
-
- var caches = {
- isGlobalCache: isGlobalCache,
- isGlobalPathCache: isGlobalPathCache,
- hasThisCache: hasThisCache,
- firstDotIndexCache: firstDotIndexCache,
- firstKeyCache: firstKeyCache,
- tailPathCache: tailPathCache
- };
- __exports__.caches = caches;
- function isGlobal(path) {
- return isGlobalCache.get(path);
- }
-
- __exports__.isGlobal = isGlobal;function isGlobalPath(path) {
- return isGlobalPathCache.get(path);
- }
-
- __exports__.isGlobalPath = isGlobalPath;function hasThis(path) {
- return hasThisCache.get(path);
- }
-
- __exports__.hasThis = hasThis;function isPath(path) {
- return firstDotIndexCache.get(path) !== -1;
- }
-
- __exports__.isPath = isPath;function getFirstKey(path) {
- return firstKeyCache.get(path);
- }
-
- __exports__.getFirstKey = getFirstKey;function getTailPath(path) {
- return tailPathCache.get(path);
- }
-
- __exports__.getTailPath = getTailPath;
- });
-enifed("ember-metal/platform",
- ["ember-metal/platform/define_property","ember-metal/platform/define_properties","ember-metal/platform/create","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
- "use strict";
- var hasES5CompliantDefineProperty = __dependency1__.hasES5CompliantDefineProperty;
- var defineProperty = __dependency1__.defineProperty;
- var defineProperties = __dependency2__["default"];
- var create = __dependency3__["default"];
-
- /**
- @module ember-metal
- */
-
- var hasPropertyAccessors = hasES5CompliantDefineProperty;
- var canDefineNonEnumerableProperties = hasES5CompliantDefineProperty;
-
- /**
- Platform specific methods and feature detectors needed by the framework.
-
- @class platform
- @namespace Ember
- @static
- */
-
- __exports__.create = create;
- __exports__.defineProperty = defineProperty;
- __exports__.defineProperties = defineProperties;
- __exports__.hasPropertyAccessors = hasPropertyAccessors;
- __exports__.canDefineNonEnumerableProperties = canDefineNonEnumerableProperties;
- });
-enifed("ember-metal/platform/create",
- ["exports"],
- function(__exports__) {
- // Remove "use strict"; from transpiled module until
- // https://bugs.webkit.org/show_bug.cgi?id=138038 is fixed
- //
- // REMOVE_USE_STRICT: true
-
- /**
- @class platform
- @namespace Ember
- @static
- */
-
- /**
- Identical to `Object.create()`. Implements if not available natively.
-
- @method create
- @for Ember
- */
- var create;
- // ES5 15.2.3.5
- // http://es5.github.com/#x15.2.3.5
- if (!(Object.create && !Object.create(null).hasOwnProperty)) {
- /* jshint scripturl:true, proto:true */
- // Contributed by Brandon Benvie, October, 2012
- var createEmpty;
- var supportsProto = !({'__proto__':null} instanceof Object);
- // the following produces false positives
- // in Opera Mini => not a reliable check
- // Object.prototype.__proto__ === null
- if (supportsProto || typeof document === 'undefined') {
- createEmpty = function () {
- return { "__proto__": null };
- };
- } else {
- // In old IE __proto__ can't be used to manually set `null`, nor does
- // any other method exist to make an object that inherits from nothing,
- // aside from Object.prototype itself. Instead, create a new global
- // object and *steal* its Object.prototype and strip it bare. This is
- // used as the prototype to create nullary objects.
- createEmpty = function () {
- var iframe = document.createElement('iframe');
- var parent = document.body || document.documentElement;
- iframe.style.display = 'none';
- parent.appendChild(iframe);
- iframe.src = 'javascript:';
- var empty = iframe.contentWindow.Object.prototype;
- parent.removeChild(iframe);
- iframe = null;
- delete empty.constructor;
- delete empty.hasOwnProperty;
- delete empty.propertyIsEnumerable;
- delete empty.isPrototypeOf;
- delete empty.toLocaleString;
- delete empty.toString;
- delete empty.valueOf;
-
- function Empty() {}
- Empty.prototype = empty;
- // short-circuit future calls
- createEmpty = function () {
- return new Empty();
- };
- return new Empty();
- };
- }
-
- create = Object.create = function create(prototype, properties) {
-
- var object;
- function Type() {} // An empty constructor.
-
- if (prototype === null) {
- object = createEmpty();
- } else {
- if (typeof prototype !== "object" && typeof prototype !== "function") {
- // In the native implementation `parent` can be `null`
- // OR *any* `instanceof Object` (Object|Function|Array|RegExp|etc)
- // Use `typeof` tho, b/c in old IE, DOM elements are not `instanceof Object`
- // like they are in modern browsers. Using `Object.create` on DOM elements
- // is...err...probably inappropriate, but the native version allows for it.
- throw new TypeError("Object prototype may only be an Object or null"); // same msg as Chrome
- }
-
- Type.prototype = prototype;
-
- object = new Type();
- }
-
- if (properties !== undefined) {
- Object.defineProperties(object, properties);
- }
-
- return object;
- };
- } else {
- create = Object.create;
- }
-
- __exports__["default"] = create;
- });
-enifed("ember-metal/platform/define_properties",
- ["ember-metal/platform/define_property","exports"],
- function(__dependency1__, __exports__) {
- "use strict";
- var defineProperty = __dependency1__.defineProperty;
-
- var defineProperties = Object.defineProperties;
-
- // ES5 15.2.3.7
- // http://es5.github.com/#x15.2.3.7
- if (!defineProperties) {
- defineProperties = function defineProperties(object, properties) {
- for (var property in properties) {
- if (properties.hasOwnProperty(property) && property !== "__proto__") {
- defineProperty(object, property, properties[property]);
- }
- }
- return object;
- };
-
- Object.defineProperties = defineProperties;
- }
-
- __exports__["default"] = defineProperties;
- });
-enifed("ember-metal/platform/define_property",
- ["exports"],
- function(__exports__) {
- "use strict";
- /*globals Node */
-
- /**
- @class platform
- @namespace Ember
- @static
- */
-
- /**
- Set to true if the platform supports native getters and setters.
-
- @property hasPropertyAccessors
- @final
- */
-
- /**
- Identical to `Object.defineProperty()`. Implements as much functionality
- as possible if not available natively.
-
- @method defineProperty
- @param {Object} obj The object to modify
- @param {String} keyName property name to modify
- @param {Object} desc descriptor hash
- @return {void}
- */
- var defineProperty = (function checkCompliance(defineProperty) {
- if (!defineProperty) return;
- try {
- var a = 5;
- var obj = {};
- defineProperty(obj, 'a', {
- configurable: true,
- enumerable: true,
- get: function () {
- return a;
- },
- set: function (v) {
- a = v;
- }
- });
- if (obj.a !== 5) return;
- obj.a = 10;
- if (a !== 10) return;
-
- // check non-enumerability
- defineProperty(obj, 'a', {
- configurable: true,
- enumerable: false,
- writable: true,
- value: true
- });
- for (var key in obj) {
- if (key === 'a') return;
- }
-
- // Detects a bug in Android <3.2 where you cannot redefine a property using
- // Object.defineProperty once accessors have already been set.
- if (obj.a !== true) return;
-
- // defineProperty is compliant
- return defineProperty;
- } catch (e) {
- // IE8 defines Object.defineProperty but calling it on an Object throws
- return;
- }
- })(Object.defineProperty);
-
- var hasES5CompliantDefineProperty = !!defineProperty;
-
- if (hasES5CompliantDefineProperty && typeof document !== 'undefined') {
- // This is for Safari 5.0, which supports Object.defineProperty, but not
- // on DOM nodes.
- var canDefinePropertyOnDOM = (function() {
- try {
- defineProperty(document.createElement('div'), 'definePropertyOnDOM', {});
- return true;
- } catch(e) { }
-
- return false;
- })();
-
- if (!canDefinePropertyOnDOM) {
- defineProperty = function(obj, keyName, desc) {
- var isNode;
-
- if (typeof Node === "object") {
- isNode = obj instanceof Node;
- } else {
- isNode = typeof obj === "object" && typeof obj.nodeType === "number" && typeof obj.nodeName === "string";
- }
-
- if (isNode) {
- // TODO: Should we have a warning here?
- return (obj[keyName] = desc.value);
- } else {
- return Object.defineProperty(obj, keyName, desc);
- }
- };
- }
- }
-
- if (!hasES5CompliantDefineProperty) {
- defineProperty = function defineProperty(obj, keyName, desc) {
- if (!desc.get) { obj[keyName] = desc.value; }
- };
- }
-
- __exports__.hasES5CompliantDefineProperty = hasES5CompliantDefineProperty;
- __exports__.defineProperty = defineProperty;
- });
-enifed("ember-metal/properties",
- ["ember-metal/core","ember-metal/utils","ember-metal/platform","ember-metal/property_events","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
- "use strict";
- /**
- @module ember-metal
- */
-
- var Ember = __dependency1__["default"];
- var metaFor = __dependency2__.meta;
- var objectDefineProperty = __dependency3__.defineProperty;
- var hasPropertyAccessors = __dependency3__.hasPropertyAccessors;
- var overrideChains = __dependency4__.overrideChains;
- // ..........................................................
- // DESCRIPTOR
- //
-
- /**
- Objects of this type can implement an interface to respond to requests to
- get and set. The default implementation handles simple properties.
-
- You generally won't need to create or subclass this directly.
-
- @class Descriptor
- @namespace Ember
- @private
- @constructor
- */
- function Descriptor() {}
-
- __exports__.Descriptor = Descriptor;// ..........................................................
- // DEFINING PROPERTIES API
- //
-
- function MANDATORY_SETTER_FUNCTION(name) {
- return function SETTER_FUNCTION(value) {
- Ember.assert("You must use Ember.set() to set the `" + name + "` property (of " + this + ") to `" + value + "`.", false);
- };
- }
-
- __exports__.MANDATORY_SETTER_FUNCTION = MANDATORY_SETTER_FUNCTION;function DEFAULT_GETTER_FUNCTION(name) {
- return function GETTER_FUNCTION() {
- var meta = this['__ember_meta__'];
- return meta && meta.values[name];
- };
- }
-
- __exports__.DEFAULT_GETTER_FUNCTION = DEFAULT_GETTER_FUNCTION;/**
- NOTE: This is a low-level method used by other parts of the API. You almost
- never want to call this method directly. Instead you should use
- `Ember.mixin()` to define new properties.
-
- Defines a property on an object. This method works much like the ES5
- `Object.defineProperty()` method except that it can also accept computed
- properties and other special descriptors.
-
- Normally this method takes only three parameters. However if you pass an
- instance of `Ember.Descriptor` as the third param then you can pass an
- optional value as the fourth parameter. This is often more efficient than
- creating new descriptor hashes for each property.
-
- ## Examples
-
- ```javascript
- // ES5 compatible mode
- Ember.defineProperty(contact, 'firstName', {
- writable: true,
- configurable: false,
- enumerable: true,
- value: 'Charles'
- });
-
- // define a simple property
- Ember.defineProperty(contact, 'lastName', undefined, 'Jolley');
-
- // define a computed property
- Ember.defineProperty(contact, 'fullName', Ember.computed(function() {
- return this.firstName+' '+this.lastName;
- }).property('firstName', 'lastName'));
- ```
-
- @private
- @method defineProperty
- @for Ember
- @param {Object} obj the object to define this property on. This may be a prototype.
- @param {String} keyName the name of the property
- @param {Ember.Descriptor} [desc] an instance of `Ember.Descriptor` (typically a
- computed property) or an ES5 descriptor.
- You must provide this or `data` but not both.
- @param {*} [data] something other than a descriptor, that will
- become the explicit value of this property.
- */
- function defineProperty(obj, keyName, desc, data, meta) {
- var descs, existingDesc, watching, value;
-
- if (!meta) meta = metaFor(obj);
- descs = meta.descs;
- existingDesc = meta.descs[keyName];
- var watchEntry = meta.watching[keyName];
-
- watching = watchEntry !== undefined && watchEntry > 0;
-
- if (existingDesc instanceof Descriptor) {
- existingDesc.teardown(obj, keyName);
- }
-
- if (desc instanceof Descriptor) {
- value = desc;
-
- descs[keyName] = desc;
-
- if (watching && hasPropertyAccessors) {
- objectDefineProperty(obj, keyName, {
- configurable: true,
- enumerable: true,
- writable: true,
- value: undefined // make enumerable
- });
- } else {
- obj[keyName] = undefined; // make enumerable
- }
- if (desc.setup) { desc.setup(obj, keyName); }
- } else {
- descs[keyName] = undefined; // shadow descriptor in proto
- if (desc == null) {
- value = data;
-
-
- if (watching && hasPropertyAccessors) {
- meta.values[keyName] = data;
- objectDefineProperty(obj, keyName, {
- configurable: true,
- enumerable: true,
- set: MANDATORY_SETTER_FUNCTION(keyName),
- get: DEFAULT_GETTER_FUNCTION(keyName)
- });
- } else {
- obj[keyName] = data;
- }
- } else {
- value = desc;
-
- // compatibility with ES5
- objectDefineProperty(obj, keyName, desc);
- }
- }
-
- // if key is being watched, override chains that
- // were initialized with the prototype
- if (watching) { overrideChains(obj, keyName, meta); }
-
- // The `value` passed to the `didDefineProperty` hook is
- // either the descriptor or data, whichever was passed.
- if (obj.didDefineProperty) { obj.didDefineProperty(obj, keyName, value); }
-
- return this;
- }
-
- __exports__.defineProperty = defineProperty;
- });
-enifed("ember-metal/property_events",
- ["ember-metal/utils","ember-metal/events","ember-metal/observer_set","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
- "use strict";
- var guidFor = __dependency1__.guidFor;
- var tryFinally = __dependency1__.tryFinally;
- var sendEvent = __dependency2__.sendEvent;
- var listenersUnion = __dependency2__.listenersUnion;
- var listenersDiff = __dependency2__.listenersDiff;
- var ObserverSet = __dependency3__["default"];
-
- var beforeObserverSet = new ObserverSet();
- var observerSet = new ObserverSet();
- var deferred = 0;
-
- // ..........................................................
- // PROPERTY CHANGES
- //
-
- /**
- This function is called just before an object property is about to change.
- It will notify any before observers and prepare caches among other things.
-
- Normally you will not need to call this method directly but if for some
- reason you can't directly watch a property you can invoke this method
- manually along with `Ember.propertyDidChange()` which you should call just
- after the property value changes.
-
- @method propertyWillChange
- @for Ember
- @param {Object} obj The object with the property that will change
- @param {String} keyName The property key (or path) that will change.
- @return {void}
- */
- function propertyWillChange(obj, keyName) {
- var m = obj['__ember_meta__'];
- var watching = (m && m.watching[keyName] > 0) || keyName === 'length';
- var proto = m && m.proto;
- var desc = m && m.descs[keyName];
-
- if (!watching) {
- return;
- }
-
- if (proto === obj) {
- return;
- }
-
- if (desc && desc.willChange) {
- desc.willChange(obj, keyName);
- }
-
- dependentKeysWillChange(obj, keyName, m);
- chainsWillChange(obj, keyName, m);
- notifyBeforeObservers(obj, keyName);
- }
-
- /**
- This function is called just after an object property has changed.
- It will notify any observers and clear caches among other things.
-
- Normally you will not need to call this method directly but if for some
- reason you can't directly watch a property you can invoke this method
- manually along with `Ember.propertyWillChange()` which you should call just
- before the property value changes.
-
- @method propertyDidChange
- @for Ember
- @param {Object} obj The object with the property that will change
- @param {String} keyName The property key (or path) that will change.
- @return {void}
- */
- function propertyDidChange(obj, keyName) {
- var m = obj['__ember_meta__'];
- var watching = (m && m.watching[keyName] > 0) || keyName === 'length';
- var proto = m && m.proto;
- var desc = m && m.descs[keyName];
-
- if (proto === obj) {
- return;
- }
-
- // shouldn't this mean that we're watching this key?
- if (desc && desc.didChange) {
- desc.didChange(obj, keyName);
- }
-
- if (!watching && keyName !== 'length') {
- return;
- }
-
- if (m && m.deps && m.deps[keyName]) {
- dependentKeysDidChange(obj, keyName, m);
- }
-
- chainsDidChange(obj, keyName, m, false);
- notifyObservers(obj, keyName);
- }
-
- var WILL_SEEN, DID_SEEN;
- // called whenever a property is about to change to clear the cache of any dependent keys (and notify those properties of changes, etc...)
- function dependentKeysWillChange(obj, depKey, meta) {
- if (obj.isDestroying) { return; }
-
- var deps;
- if (meta && meta.deps && (deps = meta.deps[depKey])) {
- var seen = WILL_SEEN;
- var top = !seen;
-
- if (top) {
- seen = WILL_SEEN = {};
- }
-
- iterDeps(propertyWillChange, obj, deps, depKey, seen, meta);
-
- if (top) {
- WILL_SEEN = null;
- }
- }
- }
-
- // called whenever a property has just changed to update dependent keys
- function dependentKeysDidChange(obj, depKey, meta) {
- if (obj.isDestroying) { return; }
-
- var deps;
- if (meta && meta.deps && (deps = meta.deps[depKey])) {
- var seen = DID_SEEN;
- var top = !seen;
-
- if (top) {
- seen = DID_SEEN = {};
- }
-
- iterDeps(propertyDidChange, obj, deps, depKey, seen, meta);
-
- if (top) {
- DID_SEEN = null;
- }
- }
- }
-
- function keysOf(obj) {
- var keys = [];
-
- for (var key in obj) {
- keys.push(key);
- }
-
- return keys;
- }
-
- function iterDeps(method, obj, deps, depKey, seen, meta) {
- var keys, key, i, desc;
- var guid = guidFor(obj);
- var current = seen[guid];
-
- if (!current) {
- current = seen[guid] = {};
- }
-
- if (current[depKey]) {
- return;
- }
-
- current[depKey] = true;
-
- if (deps) {
- keys = keysOf(deps);
- var descs = meta.descs;
- for (i=0; i<keys.length; i++) {
- key = keys[i];
- desc = descs[key];
-
- if (desc && desc._suspended === obj) {
- continue;
- }
-
- method(obj, key);
- }
- }
- }
-
- function chainsWillChange(obj, keyName, m) {
- if (!(m.hasOwnProperty('chainWatchers') &&
- m.chainWatchers[keyName])) {
- return;
- }
-
- var nodes = m.chainWatchers[keyName];
- var events = [];
- var i, l;
-
- for(i = 0, l = nodes.length; i < l; i++) {
- nodes[i].willChange(events);
- }
-
- for (i = 0, l = events.length; i < l; i += 2) {
- propertyWillChange(events[i], events[i+1]);
- }
- }
-
- function chainsDidChange(obj, keyName, m, suppressEvents) {
- if (!(m && m.hasOwnProperty('chainWatchers') &&
- m.chainWatchers[keyName])) {
- return;
- }
-
- var nodes = m.chainWatchers[keyName];
- var events = suppressEvents ? null : [];
- var i, l;
-
- for(i = 0, l = nodes.length; i < l; i++) {
- nodes[i].didChange(events);
- }
-
- if (suppressEvents) {
- return;
- }
-
- for (i = 0, l = events.length; i < l; i += 2) {
- propertyDidChange(events[i], events[i+1]);
- }
- }
-
- function overrideChains(obj, keyName, m) {
- chainsDidChange(obj, keyName, m, true);
- }
-
- /**
- @method beginPropertyChanges
- @chainable
- @private
- */
- function beginPropertyChanges() {
- deferred++;
- }
-
- /**
- @method endPropertyChanges
- @private
- */
- function endPropertyChanges() {
- deferred--;
- if (deferred<=0) {
- beforeObserverSet.clear();
- observerSet.flush();
- }
- }
-
- /**
- Make a series of property changes together in an
- exception-safe way.
-
- ```javascript
- Ember.changeProperties(function() {
- obj1.set('foo', mayBlowUpWhenSet);
- obj2.set('bar', baz);
- });
- ```
-
- @method changeProperties
- @param {Function} callback
- @param [binding]
- */
- function changeProperties(cb, binding) {
- beginPropertyChanges();
- tryFinally(cb, endPropertyChanges, binding);
- }
-
- function notifyBeforeObservers(obj, keyName) {
- if (obj.isDestroying) { return; }
-
- var eventName = keyName + ':before';
- var listeners, diff;
- if (deferred) {
- listeners = beforeObserverSet.add(obj, keyName, eventName);
- diff = listenersDiff(obj, eventName, listeners);
- sendEvent(obj, eventName, [obj, keyName], diff);
- } else {
- sendEvent(obj, eventName, [obj, keyName]);
- }
- }
-
- function notifyObservers(obj, keyName) {
- if (obj.isDestroying) { return; }
-
- var eventName = keyName + ':change';
- var listeners;
- if (deferred) {
- listeners = observerSet.add(obj, keyName, eventName);
- listenersUnion(obj, eventName, listeners);
- } else {
- sendEvent(obj, eventName, [obj, keyName]);
- }
- }
-
- __exports__.propertyWillChange = propertyWillChange;
- __exports__.propertyDidChange = propertyDidChange;
- __exports__.overrideChains = overrideChains;
- __exports__.beginPropertyChanges = beginPropertyChanges;
- __exports__.endPropertyChanges = endPropertyChanges;
- __exports__.changeProperties = changeProperties;
- });
-enifed("ember-metal/property_get",
- ["ember-metal/core","ember-metal/error","ember-metal/path_cache","ember-metal/platform","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
- "use strict";
- /**
- @module ember-metal
- */
-
- var Ember = __dependency1__["default"];
- var EmberError = __dependency2__["default"];
- var isGlobalPath = __dependency3__.isGlobalPath;
- var isPath = __dependency3__.isPath;
- var pathHasThis = __dependency3__.hasThis;
- var hasPropertyAccessors = __dependency4__.hasPropertyAccessors;
-
- var FIRST_KEY = /^([^\.]+)/;
-
- // ..........................................................
- // GET AND SET
- //
- // If we are on a platform that supports accessors we can use those.
- // Otherwise simulate accessors by looking up the property directly on the
- // object.
-
- /**
- Gets the value of a property on an object. If the property is computed,
- the function will be invoked. If the property is not defined but the
- object implements the `unknownProperty` method then that will be invoked.
-
- If you plan to run on IE8 and older browsers then you should use this
- method anytime you want to retrieve a property on an object that you don't
- know for sure is private. (Properties beginning with an underscore '_'
- are considered private.)
-
- On all newer browsers, you only need to use this method to retrieve
- properties if the property might not be defined on the object and you want
- to respect the `unknownProperty` handler. Otherwise you can ignore this
- method.
-
- Note that if the object itself is `undefined`, this method will throw
- an error.
-
- @method get
- @for Ember
- @param {Object} obj The object to retrieve from.
- @param {String} keyName The property key to retrieve
- @return {Object} the property value or `null`.
- */
- var get = function get(obj, keyName) {
- // Helpers that operate with 'this' within an #each
- if (keyName === '') {
- return obj;
- }
-
- if (!keyName && 'string' === typeof obj) {
- keyName = obj;
- obj = null;
- }
-
- Ember.assert("Cannot call get with "+ keyName +" key.", !!keyName);
- Ember.assert("Cannot call get with '"+ keyName +"' on an undefined object.", obj !== undefined);
-
- if (obj === null) {
- var value = _getPath(obj, keyName);
- Ember.deprecate(
- "Ember.get fetched '"+keyName+"' from the global context. This behavior will change in the future (issue #3852)",
- !value || (obj && obj !== Ember.lookup) || isPath(keyName) || isGlobalPath(keyName+".") // Add a . to ensure simple paths are matched.
- );
- return value;
- }
-
- var meta = obj['__ember_meta__'];
- var desc = meta && meta.descs[keyName];
- var ret;
-
- if (desc === undefined && isPath(keyName)) {
- return _getPath(obj, keyName);
- }
-
- if (desc) {
- return desc.get(obj, keyName);
- } else {
-
- if (hasPropertyAccessors && meta && meta.watching[keyName] > 0) {
- ret = meta.values[keyName];
- } else {
- ret = obj[keyName];
- }
-
- if (ret === undefined &&
- 'object' === typeof obj && !(keyName in obj) && 'function' === typeof obj.unknownProperty) {
- return obj.unknownProperty(keyName);
- }
-
- return ret;
- }
- };
-
- // Currently used only by Ember Data tests
- if (Ember.config.overrideAccessors) {
- Ember.get = get;
- Ember.config.overrideAccessors();
- get = Ember.get;
- }
-
- /**
- Normalizes a target/path pair to reflect that actual target/path that should
- be observed, etc. This takes into account passing in global property
- paths (i.e. a path beginning with a captial letter not defined on the
- target).
-
- @private
- @method normalizeTuple
- @for Ember
- @param {Object} target The current target. May be `null`.
- @param {String} path A path on the target or a global property path.
- @return {Array} a temporary array with the normalized target/path pair.
- */
- function normalizeTuple(target, path) {
- var hasThis = pathHasThis(path);
- var isGlobal = !hasThis && isGlobalPath(path);
- var key;
-
- if (!target || isGlobal) target = Ember.lookup;
- if (hasThis) path = path.slice(5);
-
- Ember.deprecate(
- "normalizeTuple will return '"+path+"' as a non-global. This behavior will change in the future (issue #3852)",
- target === Ember.lookup || !target || hasThis || isGlobal || !isGlobalPath(path+'.')
- );
-
- if (target === Ember.lookup) {
- key = path.match(FIRST_KEY)[0];
- target = get(target, key);
- path = path.slice(key.length+1);
- }
-
- // must return some kind of path to be valid else other things will break.
- if (!path || path.length===0) throw new EmberError('Path cannot be empty');
-
- return [ target, path ];
- }
-
- function _getPath(root, path) {
- var hasThis, parts, tuple, idx, len;
-
- // If there is no root and path is a key name, return that
- // property from the global object.
- // E.g. get('Ember') -> Ember
- if (root === null && !isPath(path)) {
- return get(Ember.lookup, path);
- }
-
- // detect complicated paths and normalize them
- hasThis = pathHasThis(path);
-
- if (!root || hasThis) {
- tuple = normalizeTuple(root, path);
- root = tuple[0];
- path = tuple[1];
- tuple.length = 0;
- }
-
- parts = path.split(".");
- len = parts.length;
- for (idx = 0; root != null && idx < len; idx++) {
- root = get(root, parts[idx], true);
- if (root && root.isDestroyed) { return undefined; }
- }
- return root;
- }
-
- function getWithDefault(root, key, defaultValue) {
- var value = get(root, key);
-
- if (value === undefined) { return defaultValue; }
- return value;
- }
-
- __exports__.getWithDefault = getWithDefault;__exports__["default"] = get;
- __exports__.get = get;
- __exports__.normalizeTuple = normalizeTuple;
- __exports__._getPath = _getPath;
- });
-enifed("ember-metal/property_set",
- ["ember-metal/core","ember-metal/property_get","ember-metal/property_events","ember-metal/properties","ember-metal/error","ember-metal/path_cache","ember-metal/platform","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __exports__) {
- "use strict";
- var Ember = __dependency1__["default"];
- var getPath = __dependency2__._getPath;
- var propertyWillChange = __dependency3__.propertyWillChange;
- var propertyDidChange = __dependency3__.propertyDidChange;
- var defineProperty = __dependency4__.defineProperty;
- var EmberError = __dependency5__["default"];
- var isPath = __dependency6__.isPath;
- var hasPropertyAccessors = __dependency7__.hasPropertyAccessors;
-
- var IS_GLOBAL = /^([A-Z$]|([0-9][A-Z$]))/;
-
- /**
- Sets the value of a property on an object, respecting computed properties
- and notifying observers and other listeners of the change. If the
- property is not defined but the object implements the `setUnknownProperty`
- method then that will be invoked as well.
-
- @method set
- @for Ember
- @param {Object} obj The object to modify.
- @param {String} keyName The property key to set
- @param {Object} value The value to set
- @return {Object} the passed value.
- */
- var set = function set(obj, keyName, value, tolerant) {
- if (typeof obj === 'string') {
- Ember.assert("Path '" + obj + "' must be global if no obj is given.", IS_GLOBAL.test(obj));
- value = keyName;
- keyName = obj;
- obj = null;
- }
-
- Ember.assert("Cannot call set with "+ keyName +" key.", !!keyName);
-
- if (!obj) {
- return setPath(obj, keyName, value, tolerant);
- }
-
- var meta = obj['__ember_meta__'];
- var desc = meta && meta.descs[keyName];
- var isUnknown, currentValue;
-
- if (desc === undefined && isPath(keyName)) {
- return setPath(obj, keyName, value, tolerant);
- }
-
- Ember.assert("You need to provide an object and key to `set`.", !!obj && keyName !== undefined);
- Ember.assert('calling set on destroyed object', !obj.isDestroyed);
-
- if (desc !== undefined) {
- desc.set(obj, keyName, value);
- } else {
-
- if (typeof obj === 'object' && obj !== null && value !== undefined && obj[keyName] === value) {
- return value;
- }
-
- isUnknown = 'object' === typeof obj && !(keyName in obj);
-
- // setUnknownProperty is called if `obj` is an object,
- // the property does not already exist, and the
- // `setUnknownProperty` method exists on the object
- if (isUnknown && 'function' === typeof obj.setUnknownProperty) {
- obj.setUnknownProperty(keyName, value);
- } else if (meta && meta.watching[keyName] > 0) {
-
- if (hasPropertyAccessors) {
- currentValue = meta.values[keyName];
- } else {
- currentValue = obj[keyName];
- }
- // only trigger a change if the value has changed
- if (value !== currentValue) {
- propertyWillChange(obj, keyName);
-
- if (hasPropertyAccessors) {
- if (
- (currentValue === undefined && !(keyName in obj)) ||
- !Object.prototype.propertyIsEnumerable.call(obj, keyName)
- ) {
- defineProperty(obj, keyName, null, value); // setup mandatory setter
- } else {
- meta.values[keyName] = value;
- }
- } else {
- obj[keyName] = value;
- }
- propertyDidChange(obj, keyName);
- }
- } else {
- obj[keyName] = value;
- }
- }
- return value;
- };
-
- // Currently used only by Ember Data tests
- // ES6TODO: Verify still true
- if (Ember.config.overrideAccessors) {
- Ember.set = set;
- Ember.config.overrideAccessors();
- set = Ember.set;
- }
-
- function setPath(root, path, value, tolerant) {
- var keyName;
-
- // get the last part of the path
- keyName = path.slice(path.lastIndexOf('.') + 1);
-
- // get the first part of the part
- path = (path === keyName) ? keyName : path.slice(0, path.length-(keyName.length+1));
-
- // unless the path is this, look up the first part to
- // get the root
- if (path !== 'this') {
- root = getPath(root, path);
- }
-
- if (!keyName || keyName.length === 0) {
- throw new EmberError('Property set failed: You passed an empty path');
- }
-
- if (!root) {
- if (tolerant) { return; }
- else { throw new EmberError('Property set failed: object in path "'+path+'" could not be found or was destroyed.'); }
- }
-
- return set(root, keyName, value);
- }
-
- /**
- Error-tolerant form of `Ember.set`. Will not blow up if any part of the
- chain is `undefined`, `null`, or destroyed.
-
- This is primarily used when syncing bindings, which may try to update after
- an object has been destroyed.
-
- @method trySet
- @for Ember
- @param {Object} obj The object to modify.
- @param {String} path The property path to set
- @param {Object} value The value to set
- */
- function trySet(root, path, value) {
- return set(root, path, value, true);
- }
-
- __exports__.trySet = trySet;__exports__.set = set;
- });
-enifed("ember-metal/run_loop",
- ["ember-metal/core","ember-metal/utils","ember-metal/array","ember-metal/property_events","backburner","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) {
- "use strict";
- var Ember = __dependency1__["default"];
- var apply = __dependency2__.apply;
- var GUID_KEY = __dependency2__.GUID_KEY;
- var indexOf = __dependency3__.indexOf;
- var beginPropertyChanges = __dependency4__.beginPropertyChanges;
- var endPropertyChanges = __dependency4__.endPropertyChanges;
- var Backburner = __dependency5__["default"];
-
- function onBegin(current) {
- run.currentRunLoop = current;
- }
-
- function onEnd(current, next) {
- run.currentRunLoop = next;
- }
-
- // ES6TODO: should Backburner become es6?
- var backburner = new Backburner(['sync', 'actions', 'destroy'], {
- GUID_KEY: GUID_KEY,
- sync: {
- before: beginPropertyChanges,
- after: endPropertyChanges
- },
- defaultQueue: 'actions',
- onBegin: onBegin,
- onEnd: onEnd,
- onErrorTarget: Ember,
- onErrorMethod: 'onerror'
- });
- var slice = [].slice;
-
- // ..........................................................
- // run - this is ideally the only public API the dev sees
- //
-
- /**
- Runs the passed target and method inside of a RunLoop, ensuring any
- deferred actions including bindings and views updates are flushed at the
- end.
-
- Normally you should not need to invoke this method yourself. However if
- you are implementing raw event handlers when interfacing with other
- libraries or plugins, you should probably wrap all of your code inside this
- call.
-
- ```javascript
- run(function() {
- // code to be execute within a RunLoop
- });
- ```
-
- @class run
- @namespace Ember
- @static
- @constructor
- @param {Object} [target] target of method to call
- @param {Function|String} method Method to invoke.
- May be a function or a string. If you pass a string
- then it will be looked up on the passed target.
- @param {Object} [args*] Any additional arguments you wish to pass to the method.
- @return {Object} return value from invoking the passed function.
- */
- __exports__["default"] = run;
- function run() {
- return backburner.run.apply(backburner, arguments);
- }
-
- /**
- If no run-loop is present, it creates a new one. If a run loop is
- present it will queue itself to run on the existing run-loops action
- queue.
-
- Please note: This is not for normal usage, and should be used sparingly.
-
- If invoked when not within a run loop:
-
- ```javascript
- run.join(function() {
- // creates a new run-loop
- });
- ```
-
- Alternatively, if called within an existing run loop:
-
- ```javascript
- run(function() {
- // creates a new run-loop
- run.join(function() {
- // joins with the existing run-loop, and queues for invocation on
- // the existing run-loops action queue.
- });
- });
- ```
-
- @method join
- @namespace Ember
- @param {Object} [target] target of method to call
- @param {Function|String} method Method to invoke.
- May be a function or a string. If you pass a string
- then it will be looked up on the passed target.
- @param {Object} [args*] Any additional arguments you wish to pass to the method.
- @return {Object} Return value from invoking the passed function. Please note,
- when called within an existing loop, no return value is possible.
- */
- run.join = function() {
- return backburner.join.apply(backburner, arguments);
- };
-
- /**
- Allows you to specify which context to call the specified function in while
- adding the execution of that function to the Ember run loop. This ability
- makes this method a great way to asynchronusly integrate third-party libraries
- into your Ember application.
-
- `run.bind` takes two main arguments, the desired context and the function to
- invoke in that context. Any additional arguments will be supplied as arguments
- to the function that is passed in.
-
- Let's use the creation of a TinyMCE component as an example. Currently,
- TinyMCE provides a setup configuration option we can use to do some processing
- after the TinyMCE instance is initialized but before it is actually rendered.
- We can use that setup option to do some additional setup for our component.
- The component itself could look something like the following:
-
- ```javascript
- App.RichTextEditorComponent = Ember.Component.extend({
- initializeTinyMCE: function(){
- tinymce.init({
- selector: '#' + this.$().prop('id'),
- setup: Ember.run.bind(this, this.setupEditor)
- });
- }.on('didInsertElement'),
-
- setupEditor: function(editor) {
- this.set('editor', editor);
- editor.on('change', function(){ console.log('content changed!')} );
- }
- });
- ```
-
- In this example, we use Ember.run.bind to bind the setupEditor message to the
- context of the App.RichTextEditorComponent and to have the invocation of that
- method be safely handled and excuted by the Ember run loop.
-
- @method bind
- @namespace Ember
- @param {Object} [target] target of method to call
- @param {Function|String} method Method to invoke.
- May be a function or a string. If you pass a string
- then it will be looked up on the passed target.
- @param {Object} [args*] Any additional arguments you wish to pass to the method.
- @return {Object} return value from invoking the passed function. Please note,
- when called within an existing loop, no return value is possible.
- @since 1.4.0
- */
- run.bind = function(target, method /* args */) {
- var args = slice.call(arguments);
- return function() {
- return run.join.apply(run, args.concat(slice.call(arguments)));
- };
- };
-
- run.backburner = backburner;
- run.currentRunLoop = null;
- run.queues = backburner.queueNames;
-
- /**
- Begins a new RunLoop. Any deferred actions invoked after the begin will
- be buffered until you invoke a matching call to `run.end()`. This is
- a lower-level way to use a RunLoop instead of using `run()`.
-
- ```javascript
- run.begin();
- // code to be execute within a RunLoop
- run.end();
- ```
-
- @method begin
- @return {void}
- */
- run.begin = function() {
- backburner.begin();
- };
-
- /**
- Ends a RunLoop. This must be called sometime after you call
- `run.begin()` to flush any deferred actions. This is a lower-level way
- to use a RunLoop instead of using `run()`.
-
- ```javascript
- run.begin();
- // code to be execute within a RunLoop
- run.end();
- ```
-
- @method end
- @return {void}
- */
- run.end = function() {
- backburner.end();
- };
-
- /**
- Array of named queues. This array determines the order in which queues
- are flushed at the end of the RunLoop. You can define your own queues by
- simply adding the queue name to this array. Normally you should not need
- to inspect or modify this property.
-
- @property queues
- @type Array
- @default ['sync', 'actions', 'destroy']
- */
-
- /**
- Adds the passed target/method and any optional arguments to the named
- queue to be executed at the end of the RunLoop. If you have not already
- started a RunLoop when calling this method one will be started for you
- automatically.
-
- At the end of a RunLoop, any methods scheduled in this way will be invoked.
- Methods will be invoked in an order matching the named queues defined in
- the `run.queues` property.
-
- ```javascript
- run.schedule('sync', this, function() {
- // this will be executed in the first RunLoop queue, when bindings are synced
- console.log("scheduled on sync queue");
- });
-
- run.schedule('actions', this, function() {
- // this will be executed in the 'actions' queue, after bindings have synced.
- console.log("scheduled on actions queue");
- });
-
- // Note the functions will be run in order based on the run queues order.
- // Output would be:
- // scheduled on sync queue
- // scheduled on actions queue
- ```
-
- @method schedule
- @param {String} queue The name of the queue to schedule against.
- Default queues are 'sync' and 'actions'
- @param {Object} [target] target object to use as the context when invoking a method.
- @param {String|Function} method The method to invoke. If you pass a string it
- will be resolved on the target object at the time the scheduled item is
- invoked allowing you to change the target function.
- @param {Object} [arguments*] Optional arguments to be passed to the queued method.
- @return {void}
- */
- run.schedule = function(queue, target, method) {
- checkAutoRun();
- backburner.schedule.apply(backburner, arguments);
- };
-
- // Used by global test teardown
- run.hasScheduledTimers = function() {
- return backburner.hasTimers();
- };
-
- // Used by global test teardown
- run.cancelTimers = function () {
- backburner.cancelTimers();
- };
-
- /**
- Immediately flushes any events scheduled in the 'sync' queue. Bindings
- use this queue so this method is a useful way to immediately force all
- bindings in the application to sync.
-
- You should call this method anytime you need any changed state to propagate
- throughout the app immediately without repainting the UI (which happens
- in the later 'render' queue added by the `ember-views` package).
-
- ```javascript
- run.sync();
- ```
-
- @method sync
- @return {void}
- */
- run.sync = function() {
- if (backburner.currentInstance) {
- backburner.currentInstance.queues.sync.flush();
- }
- };
-
- /**
- Invokes the passed target/method and optional arguments after a specified
- period of time. The last parameter of this method must always be a number
- of milliseconds.
-
- You should use this method whenever you need to run some action after a
- period of time instead of using `setTimeout()`. This method will ensure that
- items that expire during the same script execution cycle all execute
- together, which is often more efficient than using a real setTimeout.
-
- ```javascript
- run.later(myContext, function() {
- // code here will execute within a RunLoop in about 500ms with this == myContext
- }, 500);
- ```
-
- @method later
- @param {Object} [target] target of method to invoke
- @param {Function|String} method The method to invoke.
- If you pass a string it will be resolved on the
- target at the time the method is invoked.
- @param {Object} [args*] Optional arguments to pass to the timeout.
- @param {Number} wait Number of milliseconds to wait.
- @return {Object} Timer information for use in cancelling, see `run.cancel`.
- */
- run.later = function(/*target, method*/) {
- return backburner.later.apply(backburner, arguments);
- };
-
- /**
- Schedule a function to run one time during the current RunLoop. This is equivalent
- to calling `scheduleOnce` with the "actions" queue.
-
- @method once
- @param {Object} [target] The target of the method to invoke.
- @param {Function|String} method The method to invoke.
- If you pass a string it will be resolved on the
- target at the time the method is invoked.
- @param {Object} [args*] Optional arguments to pass to the timeout.
- @return {Object} Timer information for use in cancelling, see `run.cancel`.
- */
- run.once = function(/*target, method */) {
- checkAutoRun();
- var length = arguments.length;
- var args = new Array(length);
- args[0] = 'actions';
- for (var i = 0; i < length; i++) {
- args[i + 1] = arguments[i];
- }
- return apply(backburner, backburner.scheduleOnce, args);
- };
-
- /**
- Schedules a function to run one time in a given queue of the current RunLoop.
- Calling this method with the same queue/target/method combination will have
- no effect (past the initial call).
-
- Note that although you can pass optional arguments these will not be
- considered when looking for duplicates. New arguments will replace previous
- calls.
-
- ```javascript
- run(function() {
- var sayHi = function() { console.log('hi'); }
- run.scheduleOnce('afterRender', myContext, sayHi);
- run.scheduleOnce('afterRender', myContext, sayHi);
- // sayHi will only be executed once, in the afterRender queue of the RunLoop
- });
- ```
-
- Also note that passing an anonymous function to `run.scheduleOnce` will
- not prevent additional calls with an identical anonymous function from
- scheduling the items multiple times, e.g.:
-
- ```javascript
- function scheduleIt() {
- run.scheduleOnce('actions', myContext, function() { console.log("Closure"); });
- }
- scheduleIt();
- scheduleIt();
- // "Closure" will print twice, even though we're using `run.scheduleOnce`,
- // because the function we pass to it is anonymous and won't match the
- // previously scheduled operation.
- ```
-
- Available queues, and their order, can be found at `run.queues`
-
- @method scheduleOnce
- @param {String} [queue] The name of the queue to schedule against. Default queues are 'sync' and 'actions'.
- @param {Object} [target] The target of the method to invoke.
- @param {Function|String} method The method to invoke.
- If you pass a string it will be resolved on the
- target at the time the method is invoked.
- @param {Object} [args*] Optional arguments to pass to the timeout.
- @return {Object} Timer information for use in cancelling, see `run.cancel`.
- */
- run.scheduleOnce = function(/*queue, target, method*/) {
- checkAutoRun();
- return backburner.scheduleOnce.apply(backburner, arguments);
- };
-
- /**
- Schedules an item to run from within a separate run loop, after
- control has been returned to the system. This is equivalent to calling
- `run.later` with a wait time of 1ms.
-
- ```javascript
- run.next(myContext, function() {
- // code to be executed in the next run loop,
- // which will be scheduled after the current one
- });
- ```
-
- Multiple operations scheduled with `run.next` will coalesce
- into the same later run loop, along with any other operations
- scheduled by `run.later` that expire right around the same
- time that `run.next` operations will fire.
-
- Note that there are often alternatives to using `run.next`.
- For instance, if you'd like to schedule an operation to happen
- after all DOM element operations have completed within the current
- run loop, you can make use of the `afterRender` run loop queue (added
- by the `ember-views` package, along with the preceding `render` queue
- where all the DOM element operations happen). Example:
-
- ```javascript
- App.MyCollectionView = Ember.CollectionView.extend({
- didInsertElement: function() {
- run.scheduleOnce('afterRender', this, 'processChildElements');
- },
- processChildElements: function() {
- // ... do something with collectionView's child view
- // elements after they've finished rendering, which
- // can't be done within the CollectionView's
- // `didInsertElement` hook because that gets run
- // before the child elements have been added to the DOM.
- }
- });
- ```
-
- One benefit of the above approach compared to using `run.next` is
- that you will be able to perform DOM/CSS operations before unprocessed
- elements are rendered to the screen, which may prevent flickering or
- other artifacts caused by delaying processing until after rendering.
-
- The other major benefit to the above approach is that `run.next`
- introduces an element of non-determinism, which can make things much
- harder to test, due to its reliance on `setTimeout`; it's much harder
- to guarantee the order of scheduled operations when they are scheduled
- outside of the current run loop, i.e. with `run.next`.
-
- @method next
- @param {Object} [target] target of method to invoke
- @param {Function|String} method The method to invoke.
- If you pass a string it will be resolved on the
- target at the time the method is invoked.
- @param {Object} [args*] Optional arguments to pass to the timeout.
- @return {Object} Timer information for use in cancelling, see `run.cancel`.
- */
- run.next = function() {
- var args = slice.call(arguments);
- args.push(1);
- return apply(backburner, backburner.later, args);
- };
-
- /**
- Cancels a scheduled item. Must be a value returned by `run.later()`,
- `run.once()`, `run.next()`, `run.debounce()`, or
- `run.throttle()`.
-
- ```javascript
- var runNext = run.next(myContext, function() {
- // will not be executed
- });
- run.cancel(runNext);
-
- var runLater = run.later(myContext, function() {
- // will not be executed
- }, 500);
- run.cancel(runLater);
-
- var runOnce = run.once(myContext, function() {
- // will not be executed
- });
- run.cancel(runOnce);
-
- var throttle = run.throttle(myContext, function() {
- // will not be executed
- }, 1, false);
- run.cancel(throttle);
-
- var debounce = run.debounce(myContext, function() {
- // will not be executed
- }, 1);
- run.cancel(debounce);
-
- var debounceImmediate = run.debounce(myContext, function() {
- // will be executed since we passed in true (immediate)
- }, 100, true);
- // the 100ms delay until this method can be called again will be cancelled
- run.cancel(debounceImmediate);
- ```
-
- @method cancel
- @param {Object} timer Timer object to cancel
- @return {Boolean} true if cancelled or false/undefined if it wasn't found
- */
- run.cancel = function(timer) {
- return backburner.cancel(timer);
- };
-
- /**
- Delay calling the target method until the debounce period has elapsed
- with no additional debounce calls. If `debounce` is called again before
- the specified time has elapsed, the timer is reset and the entire period
- must pass again before the target method is called.
-
- This method should be used when an event may be called multiple times
- but the action should only be called once when the event is done firing.
- A common example is for scroll events where you only want updates to
- happen once scrolling has ceased.
-
- ```javascript
- var myFunc = function() { console.log(this.name + ' ran.'); };
- var myContext = {name: 'debounce'};
-
- run.debounce(myContext, myFunc, 150);
-
- // less than 150ms passes
-
- run.debounce(myContext, myFunc, 150);
-
- // 150ms passes
- // myFunc is invoked with context myContext
- // console logs 'debounce ran.' one time.
- ```
-
- Immediate allows you to run the function immediately, but debounce
- other calls for this function until the wait time has elapsed. If
- `debounce` is called again before the specified time has elapsed,
- the timer is reset and the entire period must pass again before
- the method can be called again.
-
- ```javascript
- var myFunc = function() { console.log(this.name + ' ran.'); };
- var myContext = {name: 'debounce'};
-
- run.debounce(myContext, myFunc, 150, true);
-
- // console logs 'debounce ran.' one time immediately.
- // 100ms passes
-
- run.debounce(myContext, myFunc, 150, true);
-
- // 150ms passes and nothing else is logged to the console and
- // the debouncee is no longer being watched
-
- run.debounce(myContext, myFunc, 150, true);
-
- // console logs 'debounce ran.' one time immediately.
- // 150ms passes and nothing else is logged to the console and
- // the debouncee is no longer being watched
-
- ```
-
- @method debounce
- @param {Object} [target] target of method to invoke
- @param {Function|String} method The method to invoke.
- May be a function or a string. If you pass a string
- then it will be looked up on the passed target.
- @param {Object} [args*] Optional arguments to pass to the timeout.
- @param {Number} wait Number of milliseconds to wait.
- @param {Boolean} immediate Trigger the function on the leading instead
- of the trailing edge of the wait interval. Defaults to false.
- @return {Array} Timer information for use in cancelling, see `run.cancel`.
- */
- run.debounce = function() {
- return backburner.debounce.apply(backburner, arguments);
- };
-
- /**
- Ensure that the target method is never called more frequently than
- the specified spacing period. The target method is called immediately.
-
- ```javascript
- var myFunc = function() { console.log(this.name + ' ran.'); };
- var myContext = {name: 'throttle'};
-
- run.throttle(myContext, myFunc, 150);
- // myFunc is invoked with context myContext
- // console logs 'throttle ran.'
-
- // 50ms passes
- run.throttle(myContext, myFunc, 150);
-
- // 50ms passes
- run.throttle(myContext, myFunc, 150);
-
- // 150ms passes
- run.throttle(myContext, myFunc, 150);
- // myFunc is invoked with context myContext
- // console logs 'throttle ran.'
- ```
-
- @method throttle
- @param {Object} [target] target of method to invoke
- @param {Function|String} method The method to invoke.
- May be a function or a string. If you pass a string
- then it will be looked up on the passed target.
- @param {Object} [args*] Optional arguments to pass to the timeout.
- @param {Number} spacing Number of milliseconds to space out requests.
- @param {Boolean} immediate Trigger the function on the leading instead
- of the trailing edge of the wait interval. Defaults to true.
- @return {Array} Timer information for use in cancelling, see `run.cancel`.
- */
- run.throttle = function() {
- return backburner.throttle.apply(backburner, arguments);
- };
-
- // Make sure it's not an autorun during testing
- function checkAutoRun() {
- if (!run.currentRunLoop) {
- Ember.assert("You have turned on testing mode, which disabled the run-loop's autorun." +
- " You will need to wrap any code with asynchronous side-effects in an run", !Ember.testing);
- }
- }
-
- /**
- Add a new named queue after the specified queue.
-
- The queue to add will only be added once.
-
- @method _addQueue
- @param {String} name the name of the queue to add.
- @param {String} after the name of the queue to add after.
- @private
- */
- run._addQueue = function(name, after) {
- if (indexOf.call(run.queues, name) === -1) {
- run.queues.splice(indexOf.call(run.queues, after)+1, 0, name);
- }
- };
- });
-enifed("ember-metal/set_properties",
- ["ember-metal/property_events","ember-metal/property_set","ember-metal/keys","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
- "use strict";
- var changeProperties = __dependency1__.changeProperties;
- var set = __dependency2__.set;
- var keys = __dependency3__["default"];
-
- /**
- Set a list of properties on an object. These properties are set inside
- a single `beginPropertyChanges` and `endPropertyChanges` batch, so
- observers will be buffered.
-
- ```javascript
- var anObject = Ember.Object.create();
-
- anObject.setProperties({
- firstName: 'Stanley',
- lastName: 'Stuart',
- age: 21
- });
- ```
-
- @method setProperties
- @param obj
- @param {Object} properties
- @return obj
- */
- __exports__["default"] = function setProperties(obj, properties) {
- if (!properties || typeof properties !== "object") { return obj; }
- changeProperties(function() {
- var props = keys(properties);
- var propertyName;
-
- for (var i = 0, l = props.length; i < l; i++) {
- propertyName = props[i];
-
- set(obj, propertyName, properties[propertyName]);
- }
- });
- return obj;
- }
- });
-enifed("ember-metal/streams/read",
- ["exports"],
- function(__exports__) {
- "use strict";
- function read(object) {
- if (object && object.isStream) {
- return object.value();
- } else {
- return object;
- }
- }
-
- __exports__.read = read;function readArray(array) {
- var length = array.length;
- var ret = new Array(length);
- for (var i = 0; i < length; i++) {
- ret[i] = read(array[i]);
- }
- return ret;
- }
-
- __exports__.readArray = readArray;function readHash(object) {
- var ret = {};
- for (var key in object) {
- ret[key] = read(object[key]);
- }
- return ret;
- }
-
- __exports__.readHash = readHash;
- });
-enifed("ember-metal/streams/simple",
- ["ember-metal/merge","ember-metal/streams/stream","ember-metal/platform","ember-metal/streams/read","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
- "use strict";
- var merge = __dependency1__["default"];
- var Stream = __dependency2__["default"];
- var create = __dependency3__.create;
- var read = __dependency4__.read;
-
- function SimpleStream(source) {
- this.source = source;
-
- if (source && source.isStream) {
- source.subscribe(this._didChange, this);
- }
- }
-
- SimpleStream.prototype = create(Stream.prototype);
-
- merge(SimpleStream.prototype, {
- valueFn: function() {
- return read(this.source);
- },
-
- setValue: function(value) {
- var source = this.source;
-
- if (source && source.isStream) {
- source.setValue(value);
- }
- },
-
- setSource: function(nextSource) {
- var prevSource = this.source;
- if (nextSource !== prevSource) {
- if (prevSource && prevSource.isStream) {
- prevSource.unsubscribe(this._didChange, this);
- }
-
- if (nextSource && nextSource.isStream) {
- nextSource.subscribe(this._didChange, this);
- }
-
- this.source = nextSource;
- this.notify();
- }
- },
-
- _didChange: function() {
- this.notify();
- },
-
- destroy: function() {
- if (this.source && this.source.isStream) {
- this.source.unsubscribe(this._didChange, this);
- }
-
- this.source = undefined;
- Stream.prototype.destroy.call(this);
- }
- });
-
- __exports__["default"] = SimpleStream;
- });
-enifed("ember-metal/streams/stream",
- ["ember-metal/platform","ember-metal/path_cache","exports"],
- function(__dependency1__, __dependency2__, __exports__) {
- "use strict";
- var create = __dependency1__.create;
- var getFirstKey = __dependency2__.getFirstKey;
- var getTailPath = __dependency2__.getTailPath;
-
- var NIL = function NIL(){};
-
- function Stream(fn) {
- this.valueFn = fn;
- this.cache = NIL;
- this.subscribers = undefined;
- this.children = undefined;
- this.destroyed = false;
- }
-
- Stream.prototype = {
- isStream: true,
-
- cache: NIL,
-
- get: function(path) {
- var firstKey = getFirstKey(path);
- var tailPath = getTailPath(path);
-
- if (this.children === undefined) {
- this.children = create(null);
- }
-
- var keyStream = this.children[firstKey];
-
- if (keyStream === undefined) {
- keyStream = this._makeChildStream(firstKey, path);
- this.children[firstKey] = keyStream;
- }
-
- if (tailPath === undefined) {
- return keyStream;
- } else {
- return keyStream.get(tailPath);
- }
- },
-
- value: function() {
- if (this.cache !== NIL) {
- return this.cache;
- } else {
- return this.cache = this.valueFn();
- }
- },
-
- setValue: function() {
- throw new Error("Stream error: setValue not implemented");
- },
-
- notify: function() {
- this.notifyExcept();
- },
-
- notifyExcept: function(callbackToSkip, contextToSkip) {
- if (this.cache !== NIL) {
- this.cache = NIL;
- this.notifySubscribers(callbackToSkip, contextToSkip);
- }
- },
-
- subscribe: function(callback, context) {
- if (this.subscribers === undefined) {
- this.subscribers = [callback, context];
- } else {
- this.subscribers.push(callback, context);
- }
- },
-
- unsubscribe: function(callback, context) {
- var subscribers = this.subscribers;
-
- if (subscribers !== undefined) {
- for (var i = 0, l = subscribers.length; i < l; i += 2) {
- if (subscribers[i] === callback && subscribers[i+1] === context) {
- subscribers.splice(i, 2);
- return;
- }
- }
- }
- },
-
- notifySubscribers: function(callbackToSkip, contextToSkip) {
- var subscribers = this.subscribers;
-
- if (subscribers !== undefined) {
- for (var i = 0, l = subscribers.length; i < l; i += 2) {
- var callback = subscribers[i];
- var context = subscribers[i+1];
-
- if (callback === callbackToSkip && context === contextToSkip) {
- continue;
- }
-
- if (context === undefined) {
- callback(this);
- } else {
- callback.call(context, this);
- }
- }
- }
- },
-
- destroy: function() {
- if (this.destroyed) return;
- this.destroyed = true;
-
- var children = this.children;
- for (var key in children) {
- children[key].destroy();
- }
- },
-
- isGlobal: function() {
- var stream = this;
- while (stream !== undefined) {
- if (stream._isRoot) {
- return stream._isGlobal;
- }
- stream = stream.source;
- }
- }
- };
-
- __exports__["default"] = Stream;
- });
-enifed("ember-metal/streams/stream_binding",
- ["ember-metal/platform","ember-metal/merge","ember-metal/run_loop","ember-metal/streams/stream","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
- "use strict";
- var create = __dependency1__.create;
- var merge = __dependency2__["default"];
- var run = __dependency3__["default"];
- var Stream = __dependency4__["default"];
-
- function StreamBinding(stream) {
- Ember.assert("StreamBinding error: tried to bind to object that is not a stream", stream && stream.isStream);
-
- this.stream = stream;
- this.senderCallback = undefined;
- this.senderContext = undefined;
- this.senderValue = undefined;
- this.destroyed = false;
-
- stream.subscribe(this._onNotify, this);
- }
-
- StreamBinding.prototype = create(Stream.prototype);
-
- merge(StreamBinding.prototype, {
- valueFn: function() {
- return this.stream.value();
- },
-
- _onNotify: function() {
- this._scheduleSync(undefined, undefined, this);
- },
-
- setValue: function(value, callback, context) {
- this._scheduleSync(value, callback, context);
- },
-
- _scheduleSync: function(value, callback, context) {
- if (this.senderCallback === undefined && this.senderContext === undefined) {
- this.senderCallback = callback;
- this.senderContext = context;
- this.senderValue = value;
- run.schedule('sync', this, this._sync);
- } else if (this.senderContext !== this) {
- this.senderCallback = callback;
- this.senderContext = context;
- this.senderValue = value;
- }
- },
-
- _sync: function() {
- if (this.destroyed) {
- return;
- }
-
- if (this.senderContext !== this) {
- this.stream.setValue(this.senderValue);
- }
-
- var senderCallback = this.senderCallback;
- var senderContext = this.senderContext;
- this.senderCallback = undefined;
- this.senderContext = undefined;
- this.senderValue = undefined;
-
- // Force StreamBindings to always notify
- this.cache = undefined;
-
- this.notifyExcept(senderCallback, senderContext);
- },
-
- destroy: function() {
- if (this.destroyed) {
- return;
- }
-
- this.destroyed = true;
- this.stream.unsubscribe(this._onNotify, this);
- }
- });
-
- __exports__["default"] = StreamBinding;
- });
-enifed("ember-metal/utils",
- ["ember-metal/core","ember-metal/platform","ember-metal/array","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
- // Remove "use strict"; from transpiled module until
- // https://bugs.webkit.org/show_bug.cgi?id=138038 is fixed
- //
- // REMOVE_USE_STRICT: true
-
- var Ember = __dependency1__["default"];
- var o_defineProperty = __dependency2__.defineProperty;
- var canDefineNonEnumerableProperties = __dependency2__.canDefineNonEnumerableProperties;
- var hasPropertyAccessors = __dependency2__.hasPropertyAccessors;
- var o_create = __dependency2__.create;
-
- var forEach = __dependency3__.forEach;
-
- /**
- @module ember-metal
- */
-
- /**
- Previously we used `Ember.$.uuid`, however `$.uuid` has been removed from
- jQuery master. We'll just bootstrap our own uuid now.
-
- @private
- @return {Number} the uuid
- */
- var _uuid = 0;
-
- /**
- Generates a universally unique identifier. This method
- is used internally by Ember for assisting with
- the generation of GUID's and other unique identifiers
- such as `bind-attr` data attributes.
-
- @public
- @return {Number} [description]
- */
- function uuid() {
- return ++_uuid;
- }
-
- __exports__.uuid = uuid;/**
- Prefix used for guids through out Ember.
- @private
- @property GUID_PREFIX
- @for Ember
- @type String
- @final
- */
- var GUID_PREFIX = 'ember';
-
- // Used for guid generation...
- var numberCache = [];
- var stringCache = {};
-
- /**
- Strongly hint runtimes to intern the provided string.
-
- When do I need to use this function?
-
- For the most part, never. Pre-mature optimization is bad, and often the
- runtime does exactly what you need it to, and more often the trade-off isn't
- worth it.
-
- Why?
-
- Runtimes store strings in at least 2 different representations:
- Ropes and Symbols (interned strings). The Rope provides a memory efficient
- data-structure for strings created from concatenation or some other string
- manipulation like splitting.
-
- Unfortunately checking equality of different ropes can be quite costly as
- runtimes must resort to clever string comparison algorithims. These
- algorithims typically cost in proportion to the length of the string.
- Luckily, this is where the Symbols (interned strings) shine. As Symbols are
- unique by their string content, equality checks can be done by pointer
- comparision.
-
- How do I know if my string is a rope or symbol?
-
- Typically (warning general sweeping statement, but truthy in runtimes at
- present) static strings created as part of the JS source are interned.
- Strings often used for comparisions can be interned at runtime if some
- criteria are met. One of these criteria can be the size of the entire rope.
- For example, in chrome 38 a rope longer then 12 characters will not
- intern, nor will segments of that rope.
-
- Some numbers: http://jsperf.com/eval-vs-keys/8
-
- Known Trick™
-
- @private
- @return {String} interned version of the provided string
- */
- function intern(str) {
- var obj = {};
- obj[str] = 1;
- for (var key in obj) {
- if (key === str) return key;
- }
- return str;
- }
-
- /**
- A unique key used to assign guids and other private metadata to objects.
- If you inspect an object in your browser debugger you will often see these.
- They can be safely ignored.
-
- On browsers that support it, these properties are added with enumeration
- disabled so they won't show up when you iterate over your properties.
-
- @private
- @property GUID_KEY
- @for Ember
- @type String
- @final
- */
- var GUID_KEY = intern('__ember' + (+ new Date()));
-
- var GUID_DESC = {
- writable: false,
- configurable: false,
- enumerable: false,
- value: null
- };
-
- /**
- Generates a new guid, optionally saving the guid to the object that you
- pass in. You will rarely need to use this method. Instead you should
- call `Ember.guidFor(obj)`, which return an existing guid if available.
-
- @private
- @method generateGuid
- @for Ember
- @param {Object} [obj] Object the guid will be used for. If passed in, the guid will
- be saved on the object and reused whenever you pass the same object
- again.
-
- If no object is passed, just generate a new guid.
- @param {String} [prefix] Prefix to place in front of the guid. Useful when you want to
- separate the guid into separate namespaces.
- @return {String} the guid
- */
- function generateGuid(obj, prefix) {
- if (!prefix) prefix = GUID_PREFIX;
- var ret = (prefix + uuid());
- if (obj) {
- if (obj[GUID_KEY] === null) {
- obj[GUID_KEY] = ret;
- } else {
- GUID_DESC.value = ret;
- o_defineProperty(obj, GUID_KEY, GUID_DESC);
- }
- }
- return ret;
- }
-
- __exports__.generateGuid = generateGuid;/**
- Returns a unique id for the object. If the object does not yet have a guid,
- one will be assigned to it. You can call this on any object,
- `Ember.Object`-based or not, but be aware that it will add a `_guid`
- property.
-
- You can also use this method on DOM Element objects.
-
- @private
- @method guidFor
- @for Ember
- @param {Object} obj any object, string, number, Element, or primitive
- @return {String} the unique guid for this instance.
- */
- function guidFor(obj) {
-
- // special cases where we don't want to add a key to object
- if (obj === undefined) return "(undefined)";
- if (obj === null) return "(null)";
-
- var ret;
- var type = typeof obj;
-
- // Don't allow prototype changes to String etc. to change the guidFor
- switch(type) {
- case 'number':
- ret = numberCache[obj];
- if (!ret) ret = numberCache[obj] = 'nu'+obj;
- return ret;
-
- case 'string':
- ret = stringCache[obj];
- if (!ret) ret = stringCache[obj] = 'st' + uuid();
- return ret;
-
- case 'boolean':
- return obj ? '(true)' : '(false)';
-
- default:
- if (obj[GUID_KEY]) return obj[GUID_KEY];
- if (obj === Object) return '(Object)';
- if (obj === Array) return '(Array)';
- ret = GUID_PREFIX + uuid();
-
- if (obj[GUID_KEY] === null) {
- obj[GUID_KEY] = ret;
- } else {
- GUID_DESC.value = ret;
- o_defineProperty(obj, GUID_KEY, GUID_DESC);
- }
- return ret;
- }
- }
-
- __exports__.guidFor = guidFor;// ..........................................................
- // META
- //
-
- var META_DESC = {
- writable: true,
- configurable: false,
- enumerable: false,
- value: null
- };
-
- function Meta(obj) {
- this.descs = {};
- this.watching = {};
- this.cache = {};
- this.cacheMeta = {};
- this.source = obj;
- this.deps = undefined;
- this.listeners = undefined;
- this.mixins = undefined;
- this.bindings = undefined;
- this.chains = undefined;
- this.values = undefined;
- this.proto = undefined;
- }
-
- Meta.prototype = {
- chainWatchers: null
- };
-
- if (!canDefineNonEnumerableProperties) {
- // on platforms that don't support enumerable false
- // make meta fail jQuery.isPlainObject() to hide from
- // jQuery.extend() by having a property that fails
- // hasOwnProperty check.
- Meta.prototype.__preventPlainObject__ = true;
-
- // Without non-enumerable properties, meta objects will be output in JSON
- // unless explicitly suppressed
- Meta.prototype.toJSON = function () { };
- }
-
- // Placeholder for non-writable metas.
- var EMPTY_META = new Meta(null);
-
-
- if (hasPropertyAccessors) {
- EMPTY_META.values = {};
- }
-
-
- /**
- Retrieves the meta hash for an object. If `writable` is true ensures the
- hash is writable for this object as well.
-
- The meta object contains information about computed property descriptors as
- well as any watched properties and other information. You generally will
- not access this information directly but instead work with higher level
- methods that manipulate this hash indirectly.
-
- @method meta
- @for Ember
- @private
-
- @param {Object} obj The object to retrieve meta for
- @param {Boolean} [writable=true] Pass `false` if you do not intend to modify
- the meta hash, allowing the method to avoid making an unnecessary copy.
- @return {Object} the meta hash for an object
- */
- function meta(obj, writable) {
- var ret = obj['__ember_meta__'];
- if (writable===false) return ret || EMPTY_META;
-
- if (!ret) {
- if (canDefineNonEnumerableProperties) o_defineProperty(obj, '__ember_meta__', META_DESC);
-
- ret = new Meta(obj);
-
-
- if (hasPropertyAccessors) {
- ret.values = {};
- }
-
-
- obj['__ember_meta__'] = ret;
-
- // make sure we don't accidentally try to create constructor like desc
- ret.descs.constructor = null;
-
- } else if (ret.source !== obj) {
- if (canDefineNonEnumerableProperties) o_defineProperty(obj, '__ember_meta__', META_DESC);
-
- ret = o_create(ret);
- ret.descs = o_create(ret.descs);
- ret.watching = o_create(ret.watching);
- ret.cache = {};
- ret.cacheMeta = {};
- ret.source = obj;
-
-
- if (hasPropertyAccessors) {
- ret.values = o_create(ret.values);
- }
-
-
- obj['__ember_meta__'] = ret;
- }
- return ret;
- }
-
- function getMeta(obj, property) {
- var _meta = meta(obj, false);
- return _meta[property];
- }
-
- __exports__.getMeta = getMeta;function setMeta(obj, property, value) {
- var _meta = meta(obj, true);
- _meta[property] = value;
- return value;
- }
-
- __exports__.setMeta = setMeta;/**
- @deprecated
- @private
-
- In order to store defaults for a class, a prototype may need to create
- a default meta object, which will be inherited by any objects instantiated
- from the class's constructor.
-
- However, the properties of that meta object are only shallow-cloned,
- so if a property is a hash (like the event system's `listeners` hash),
- it will by default be shared across all instances of that class.
-
- This method allows extensions to deeply clone a series of nested hashes or
- other complex objects. For instance, the event system might pass
- `['listeners', 'foo:change', 'ember157']` to `prepareMetaPath`, which will
- walk down the keys provided.
-
- For each key, if the key does not exist, it is created. If it already
- exists and it was inherited from its constructor, the constructor's
- key is cloned.
-
- You can also pass false for `writable`, which will simply return
- undefined if `prepareMetaPath` discovers any part of the path that
- shared or undefined.
-
- @method metaPath
- @for Ember
- @param {Object} obj The object whose meta we are examining
- @param {Array} path An array of keys to walk down
- @param {Boolean} writable whether or not to create a new meta
- (or meta property) if one does not already exist or if it's
- shared with its constructor
- */
- function metaPath(obj, path, writable) {
- Ember.deprecate("Ember.metaPath is deprecated and will be removed from future releases.");
- var _meta = meta(obj, writable);
- var keyName, value;
-
- for (var i=0, l=path.length; i<l; i++) {
- keyName = path[i];
- value = _meta[keyName];
-
- if (!value) {
- if (!writable) { return undefined; }
- value = _meta[keyName] = { __ember_source__: obj };
- } else if (value.__ember_source__ !== obj) {
- if (!writable) { return undefined; }
- value = _meta[keyName] = o_create(value);
- value.__ember_source__ = obj;
- }
-
- _meta = value;
- }
-
- return value;
- }
-
- __exports__.metaPath = metaPath;/**
- Wraps the passed function so that `this._super` will point to the superFunc
- when the function is invoked. This is the primitive we use to implement
- calls to super.
-
- @private
- @method wrap
- @for Ember
- @param {Function} func The function to call
- @param {Function} superFunc The super function.
- @return {Function} wrapped function.
- */
- function wrap(func, superFunc) {
- function superWrapper() {
- var ret;
- var sup = this && this.__nextSuper;
- var args = new Array(arguments.length);
- for (var i = 0, l = args.length; i < l; i++) {
- args[i] = arguments[i];
- }
- if(this) { this.__nextSuper = superFunc; }
- ret = apply(this, func, args);
- if(this) { this.__nextSuper = sup; }
- return ret;
- }
-
- superWrapper.wrappedFunction = func;
- superWrapper.wrappedFunction.__ember_arity__ = func.length;
- superWrapper.__ember_observes__ = func.__ember_observes__;
- superWrapper.__ember_observesBefore__ = func.__ember_observesBefore__;
- superWrapper.__ember_listens__ = func.__ember_listens__;
-
- return superWrapper;
- }
-
- __exports__.wrap = wrap;var EmberArray;
-
- /**
- Returns true if the passed object is an array or Array-like.
-
- Ember Array Protocol:
-
- - the object has an objectAt property
- - the object is a native Array
- - the object is an Object, and has a length property
-
- Unlike `Ember.typeOf` this method returns true even if the passed object is
- not formally array but appears to be array-like (i.e. implements `Ember.Array`)
-
- ```javascript
- Ember.isArray(); // false
- Ember.isArray([]); // true
- Ember.isArray(Ember.ArrayProxy.create({ content: [] })); // true
- ```
-
- @method isArray
- @for Ember
- @param {Object} obj The object to test
- @return {Boolean} true if the passed object is an array or Array-like
- */
- // ES6TODO: Move up to runtime? This is only use in ember-metal by concatenatedProperties
- function isArray(obj) {
- var modulePath, type;
-
- if (typeof EmberArray === "undefined") {
- modulePath = 'ember-runtime/mixins/array';
- if (Ember.__loader.registry[modulePath]) {
- EmberArray = Ember.__loader.require(modulePath)['default'];
- }
- }
-
- if (!obj || obj.setInterval) { return false; }
- if (Array.isArray && Array.isArray(obj)) { return true; }
- if (EmberArray && EmberArray.detect(obj)) { return true; }
-
- type = typeOf(obj);
- if ('array' === type) { return true; }
- if ((obj.length !== undefined) && 'object' === type) { return true; }
- return false;
- }
-
- /**
- Forces the passed object to be part of an array. If the object is already
- an array or array-like, it will return the object. Otherwise, it will add the object to
- an array. If obj is `null` or `undefined`, it will return an empty array.
-
- ```javascript
- Ember.makeArray(); // []
- Ember.makeArray(null); // []
- Ember.makeArray(undefined); // []
- Ember.makeArray('lindsay'); // ['lindsay']
- Ember.makeArray([1, 2, 42]); // [1, 2, 42]
-
- var controller = Ember.ArrayProxy.create({ content: [] });
-
- Ember.makeArray(controller) === controller; // true
- ```
-
- @method makeArray
- @for Ember
- @param {Object} obj the object
- @return {Array}
- */
- function makeArray(obj) {
- if (obj === null || obj === undefined) { return []; }
- return isArray(obj) ? obj : [obj];
- }
-
- __exports__.makeArray = makeArray;/**
- Checks to see if the `methodName` exists on the `obj`.
-
- ```javascript
- var foo = { bar: Ember.K, baz: null };
-
- Ember.canInvoke(foo, 'bar'); // true
- Ember.canInvoke(foo, 'baz'); // false
- Ember.canInvoke(foo, 'bat'); // false
- ```
-
- @method canInvoke
- @for Ember
- @param {Object} obj The object to check for the method
- @param {String} methodName The method name to check for
- @return {Boolean}
- */
- function canInvoke(obj, methodName) {
- return !!(obj && typeof obj[methodName] === 'function');
- }
-
- /**
- Checks to see if the `methodName` exists on the `obj`,
- and if it does, invokes it with the arguments passed.
-
- ```javascript
- var d = new Date('03/15/2013');
-
- Ember.tryInvoke(d, 'getTime'); // 1363320000000
- Ember.tryInvoke(d, 'setFullYear', [2014]); // 1394856000000
- Ember.tryInvoke(d, 'noSuchMethod', [2014]); // undefined
- ```
-
- @method tryInvoke
- @for Ember
- @param {Object} obj The object to check for the method
- @param {String} methodName The method name to check for
- @param {Array} [args] The arguments to pass to the method
- @return {*} the return value of the invoked method or undefined if it cannot be invoked
- */
- function tryInvoke(obj, methodName, args) {
- if (canInvoke(obj, methodName)) {
- return args ? applyStr(obj, methodName, args) : applyStr(obj, methodName);
- }
- }
-
- __exports__.tryInvoke = tryInvoke;// https://github.com/emberjs/ember.js/pull/1617
- var needsFinallyFix = (function() {
- var count = 0;
- try{
- try { }
- finally {
- count++;
- throw new Error('needsFinallyFixTest');
- }
- } catch (e) {}
-
- return count !== 1;
- })();
-
- /**
- Provides try/finally functionality, while working
- around Safari's double finally bug.
-
- ```javascript
- var tryable = function() {
- someResource.lock();
- runCallback(); // May throw error.
- };
-
- var finalizer = function() {
- someResource.unlock();
- };
-
- Ember.tryFinally(tryable, finalizer);
- ```
-
- @method tryFinally
- @for Ember
- @param {Function} tryable The function to run the try callback
- @param {Function} finalizer The function to run the finally callback
- @param {Object} [binding] The optional calling object. Defaults to 'this'
- @return {*} The return value is the that of the finalizer,
- unless that value is undefined, in which case it is the return value
- of the tryable
- */
-
- var tryFinally;
- if (needsFinallyFix) {
- tryFinally = function(tryable, finalizer, binding) {
- var result, finalResult, finalError;
-
- binding = binding || this;
-
- try {
- result = tryable.call(binding);
- } finally {
- try {
- finalResult = finalizer.call(binding);
- } catch (e) {
- finalError = e;
- }
- }
-
- if (finalError) { throw finalError; }
-
- return (finalResult === undefined) ? result : finalResult;
- };
- } else {
- tryFinally = function(tryable, finalizer, binding) {
- var result, finalResult;
-
- binding = binding || this;
-
- try {
- result = tryable.call(binding);
- } finally {
- finalResult = finalizer.call(binding);
- }
-
- return (finalResult === undefined) ? result : finalResult;
- };
- }
-
- /**
- Provides try/catch/finally functionality, while working
- around Safari's double finally bug.
-
- ```javascript
- var tryable = function() {
- for (i = 0, l = listeners.length; i < l; i++) {
- listener = listeners[i];
- beforeValues[i] = listener.before(name, time(), payload);
- }
-
- return callback.call(binding);
- };
-
- var catchable = function(e) {
- payload = payload || {};
- payload.exception = e;
- };
-
- var finalizer = function() {
- for (i = 0, l = listeners.length; i < l; i++) {
- listener = listeners[i];
- listener.after(name, time(), payload, beforeValues[i]);
- }
- };
-
- Ember.tryCatchFinally(tryable, catchable, finalizer);
- ```
-
- @method tryCatchFinally
- @for Ember
- @param {Function} tryable The function to run the try callback
- @param {Function} catchable The function to run the catchable callback
- @param {Function} finalizer The function to run the finally callback
- @param {Object} [binding] The optional calling object. Defaults to 'this'
- @return {*} The return value is the that of the finalizer,
- unless that value is undefined, in which case it is the return value
- of the tryable.
- */
- var tryCatchFinally;
- if (needsFinallyFix) {
- tryCatchFinally = function(tryable, catchable, finalizer, binding) {
- var result, finalResult, finalError;
-
- binding = binding || this;
-
- try {
- result = tryable.call(binding);
- } catch(error) {
- result = catchable.call(binding, error);
- } finally {
- try {
- finalResult = finalizer.call(binding);
- } catch (e) {
- finalError = e;
- }
- }
-
- if (finalError) { throw finalError; }
-
- return (finalResult === undefined) ? result : finalResult;
- };
- } else {
- tryCatchFinally = function(tryable, catchable, finalizer, binding) {
- var result, finalResult;
-
- binding = binding || this;
-
- try {
- result = tryable.call(binding);
- } catch(error) {
- result = catchable.call(binding, error);
- } finally {
- finalResult = finalizer.call(binding);
- }
-
- return (finalResult === undefined) ? result : finalResult;
- };
- }
-
- // ........................................
- // TYPING & ARRAY MESSAGING
- //
-
- var TYPE_MAP = {};
- var t = "Boolean Number String Function Array Date RegExp Object".split(" ");
- forEach.call(t, function(name) {
- TYPE_MAP[ "[object " + name + "]" ] = name.toLowerCase();
- });
-
- var toString = Object.prototype.toString;
-
- var EmberObject;
-
- /**
- Returns a consistent type for the passed item.
-
- Use this instead of the built-in `typeof` to get the type of an item.
- It will return the same result across all browsers and includes a bit
- more detail. Here is what will be returned:
-
- | Return Value | Meaning |
- |---------------|------------------------------------------------------|
- | 'string' | String primitive or String object. |
- | 'number' | Number primitive or Number object. |
- | 'boolean' | Boolean primitive or Boolean object. |
- | 'null' | Null value |
- | 'undefined' | Undefined value |
- | 'function' | A function |
- | 'array' | An instance of Array |
- | 'regexp' | An instance of RegExp |
- | 'date' | An instance of Date |
- | 'class' | An Ember class (created using Ember.Object.extend()) |
- | 'instance' | An Ember object instance |
- | 'error' | An instance of the Error object |
- | 'object' | A JavaScript object not inheriting from Ember.Object |
-
- Examples:
-
- ```javascript
- Ember.typeOf(); // 'undefined'
- Ember.typeOf(null); // 'null'
- Ember.typeOf(undefined); // 'undefined'
- Ember.typeOf('michael'); // 'string'
- Ember.typeOf(new String('michael')); // 'string'
- Ember.typeOf(101); // 'number'
- Ember.typeOf(new Number(101)); // 'number'
- Ember.typeOf(true); // 'boolean'
- Ember.typeOf(new Boolean(true)); // 'boolean'
- Ember.typeOf(Ember.makeArray); // 'function'
- Ember.typeOf([1, 2, 90]); // 'array'
- Ember.typeOf(/abc/); // 'regexp'
- Ember.typeOf(new Date()); // 'date'
- Ember.typeOf(Ember.Object.extend()); // 'class'
- Ember.typeOf(Ember.Object.create()); // 'instance'
- Ember.typeOf(new Error('teamocil')); // 'error'
-
- // 'normal' JavaScript object
- Ember.typeOf({ a: 'b' }); // 'object'
- ```
-
- @method typeOf
- @for Ember
- @param {Object} item the item to check
- @return {String} the type
- */
- function typeOf(item) {
- var ret, modulePath;
-
- // ES6TODO: Depends on Ember.Object which is defined in runtime.
- if (typeof EmberObject === "undefined") {
- modulePath = 'ember-runtime/system/object';
- if (Ember.__loader.registry[modulePath]) {
- EmberObject = Ember.__loader.require(modulePath)['default'];
- }
- }
-
- ret = (item === null || item === undefined) ? String(item) : TYPE_MAP[toString.call(item)] || 'object';
-
- if (ret === 'function') {
- if (EmberObject && EmberObject.detect(item)) ret = 'class';
- } else if (ret === 'object') {
- if (item instanceof Error) ret = 'error';
- else if (EmberObject && item instanceof EmberObject) ret = 'instance';
- else if (item instanceof Date) ret = 'date';
- }
-
- return ret;
- }
-
- /**
- Convenience method to inspect an object. This method will attempt to
- convert the object into a useful string description.
-
- It is a pretty simple implementation. If you want something more robust,
- use something like JSDump: https://github.com/NV/jsDump
-
- @method inspect
- @for Ember
- @param {Object} obj The object you want to inspect.
- @return {String} A description of the object
- @since 1.4.0
- */
- function inspect(obj) {
- var type = typeOf(obj);
- if (type === 'array') {
- return '[' + obj + ']';
- }
- if (type !== 'object') {
- return obj + '';
- }
-
- var v;
- var ret = [];
- for(var key in obj) {
- if (obj.hasOwnProperty(key)) {
- v = obj[key];
- if (v === 'toString') { continue; } // ignore useless items
- if (typeOf(v) === 'function') { v = "function() { ... }"; }
-
- if (v && typeof v.toString !== 'function') {
- ret.push(key + ": " + toString.call(v));
- } else {
- ret.push(key + ": " + v);
- }
- }
- }
- return "{" + ret.join(", ") + "}";
- }
-
- __exports__.inspect = inspect;// The following functions are intentionally minified to keep the functions
- // below Chrome's function body size inlining limit of 600 chars.
-
- function apply(t /* target */, m /* method */, a /* args */) {
- var l = a && a.length;
- if (!a || !l) { return m.call(t); }
- switch (l) {
- case 1: return m.call(t, a[0]);
- case 2: return m.call(t, a[0], a[1]);
- case 3: return m.call(t, a[0], a[1], a[2]);
- case 4: return m.call(t, a[0], a[1], a[2], a[3]);
- case 5: return m.call(t, a[0], a[1], a[2], a[3], a[4]);
- default: return m.apply(t, a);
- }
- }
-
- __exports__.apply = apply;function applyStr(t /* target */, m /* method */, a /* args */) {
- var l = a && a.length;
- if (!a || !l) { return t[m](); }
- switch (l) {
- case 1: return t[m](a[0]);
- case 2: return t[m](a[0], a[1]);
- case 3: return t[m](a[0], a[1], a[2]);
- case 4: return t[m](a[0], a[1], a[2], a[3]);
- case 5: return t[m](a[0], a[1], a[2], a[3], a[4]);
- default: return t[m].apply(t, a);
- }
- }
-
- __exports__.applyStr = applyStr;__exports__.GUID_KEY = GUID_KEY;
- __exports__.META_DESC = META_DESC;
- __exports__.EMPTY_META = EMPTY_META;
- __exports__.meta = meta;
- __exports__.typeOf = typeOf;
- __exports__.tryCatchFinally = tryCatchFinally;
- __exports__.isArray = isArray;
- __exports__.canInvoke = canInvoke;
- __exports__.tryFinally = tryFinally;
- });
-enifed("ember-metal/watch_key",
- ["ember-metal/core","ember-metal/utils","ember-metal/platform","ember-metal/properties","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
- "use strict";
- var Ember = __dependency1__["default"];
- var metaFor = __dependency2__.meta;
- var typeOf = __dependency2__.typeOf;
- var o_defineProperty = __dependency3__.defineProperty;
- var hasPropertyAccessors = __dependency3__.hasPropertyAccessors;
- var MANDATORY_SETTER_FUNCTION = __dependency4__.MANDATORY_SETTER_FUNCTION;
- var DEFAULT_GETTER_FUNCTION = __dependency4__.DEFAULT_GETTER_FUNCTION;
-
- function watchKey(obj, keyName, meta) {
- // can't watch length on Array - it is special...
- if (keyName === 'length' && typeOf(obj) === 'array') { return; }
-
- var m = meta || metaFor(obj), watching = m.watching;
-
- // activate watching first time
- if (!watching[keyName]) {
- watching[keyName] = 1;
-
- var desc = m.descs[keyName];
- if (desc && desc.willWatch) { desc.willWatch(obj, keyName); }
-
- if ('function' === typeof obj.willWatchProperty) {
- obj.willWatchProperty(keyName);
- }
-
-
- if (hasPropertyAccessors) {
- handleMandatorySetter(m, obj, keyName);
- }
-
- } else {
- watching[keyName] = (watching[keyName] || 0) + 1;
- }
- }
-
- __exports__.watchKey = watchKey;
-
- var handleMandatorySetter = function handleMandatorySetter(m, obj, keyName) {
- var descriptor = Object.getOwnPropertyDescriptor && Object.getOwnPropertyDescriptor(obj, keyName);
- var configurable = descriptor ? descriptor.configurable : true;
-
- // this x in Y deopts, so keeping it in this function is better;
- if (configurable && keyName in obj) {
- m.values[keyName] = obj[keyName];
- o_defineProperty(obj, keyName, {
- configurable: true,
- enumerable: Object.prototype.propertyIsEnumerable.call(obj, keyName),
- set: MANDATORY_SETTER_FUNCTION(keyName),
- get: DEFAULT_GETTER_FUNCTION(keyName)
- });
- }
- };
-
-
- function unwatchKey(obj, keyName, meta) {
- var m = meta || metaFor(obj);
- var watching = m.watching;
-
- if (watching[keyName] === 1) {
- watching[keyName] = 0;
-
- var desc = m.descs[keyName];
- if (desc && desc.didUnwatch) { desc.didUnwatch(obj, keyName); }
-
- if ('function' === typeof obj.didUnwatchProperty) {
- obj.didUnwatchProperty(keyName);
- }
-
-
- if (hasPropertyAccessors && keyName in obj) {
- o_defineProperty(obj, keyName, {
- configurable: true,
- enumerable: Object.prototype.propertyIsEnumerable.call(obj, keyName),
- set: function(val) {
- // redefine to set as enumerable
- o_defineProperty(obj, keyName, {
- configurable: true,
- writable: true,
- enumerable: true,
- value: val
- });
- delete m.values[keyName];
- },
- get: DEFAULT_GETTER_FUNCTION(keyName)
- });
- }
-
- } else if (watching[keyName] > 1) {
- watching[keyName]--;
- }
- }
-
- __exports__.unwatchKey = unwatchKey;
- });
-enifed("ember-metal/watch_path",
- ["ember-metal/utils","ember-metal/chains","exports"],
- function(__dependency1__, __dependency2__, __exports__) {
- "use strict";
- var metaFor = __dependency1__.meta;
- var typeOf = __dependency1__.typeOf;
- var ChainNode = __dependency2__.ChainNode;
-
- // get the chains for the current object. If the current object has
- // chains inherited from the proto they will be cloned and reconfigured for
- // the current object.
- function chainsFor(obj, meta) {
- var m = meta || metaFor(obj);
- var ret = m.chains;
- if (!ret) {
- ret = m.chains = new ChainNode(null, null, obj);
- } else if (ret.value() !== obj) {
- ret = m.chains = ret.copy(obj);
- }
- return ret;
- }
-
- function watchPath(obj, keyPath, meta) {
- // can't watch length on Array - it is special...
- if (keyPath === 'length' && typeOf(obj) === 'array') { return; }
-
- var m = meta || metaFor(obj);
- var watching = m.watching;
-
- if (!watching[keyPath]) { // activate watching first time
- watching[keyPath] = 1;
- chainsFor(obj, m).add(keyPath);
- } else {
- watching[keyPath] = (watching[keyPath] || 0) + 1;
- }
- }
-
- __exports__.watchPath = watchPath;function unwatchPath(obj, keyPath, meta) {
- var m = meta || metaFor(obj);
- var watching = m.watching;
-
- if (watching[keyPath] === 1) {
- watching[keyPath] = 0;
- chainsFor(obj, m).remove(keyPath);
- } else if (watching[keyPath] > 1) {
- watching[keyPath]--;
- }
- }
-
- __exports__.unwatchPath = unwatchPath;
- });
-enifed("ember-metal/watching",
- ["ember-metal/utils","ember-metal/chains","ember-metal/watch_key","ember-metal/watch_path","ember-metal/path_cache","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) {
- "use strict";
- /**
- @module ember-metal
- */
-
- var typeOf = __dependency1__.typeOf;
- var removeChainWatcher = __dependency2__.removeChainWatcher;
- var flushPendingChains = __dependency2__.flushPendingChains;
- var watchKey = __dependency3__.watchKey;
- var unwatchKey = __dependency3__.unwatchKey;
- var watchPath = __dependency4__.watchPath;
- var unwatchPath = __dependency4__.unwatchPath;
-
- var isPath = __dependency5__.isPath;
-
- /**
- Starts watching a property on an object. Whenever the property changes,
- invokes `Ember.propertyWillChange` and `Ember.propertyDidChange`. This is the
- primitive used by observers and dependent keys; usually you will never call
- this method directly but instead use higher level methods like
- `Ember.addObserver()`
-
- @private
- @method watch
- @for Ember
- @param obj
- @param {String} keyName
- */
- function watch(obj, _keyPath, m) {
- // can't watch length on Array - it is special...
- if (_keyPath === 'length' && typeOf(obj) === 'array') { return; }
-
- if (!isPath(_keyPath)) {
- watchKey(obj, _keyPath, m);
- } else {
- watchPath(obj, _keyPath, m);
- }
- }
-
- __exports__.watch = watch;
-
- function isWatching(obj, key) {
- var meta = obj['__ember_meta__'];
- return (meta && meta.watching[key]) > 0;
- }
-
- __exports__.isWatching = isWatching;watch.flushPending = flushPendingChains;
-
- function unwatch(obj, _keyPath, m) {
- // can't watch length on Array - it is special...
- if (_keyPath === 'length' && typeOf(obj) === 'array') { return; }
-
- if (!isPath(_keyPath)) {
- unwatchKey(obj, _keyPath, m);
- } else {
- unwatchPath(obj, _keyPath, m);
- }
- }
-
- __exports__.unwatch = unwatch;var NODE_STACK = [];
-
- /**
- Tears down the meta on an object so that it can be garbage collected.
- Multiple calls will have no effect.
-
- @method destroy
- @for Ember
- @param {Object} obj the object to destroy
- @return {void}
- */
- function destroy(obj) {
- var meta = obj['__ember_meta__'], node, nodes, key, nodeObject;
- if (meta) {
- obj['__ember_meta__'] = null;
- // remove chainWatchers to remove circular references that would prevent GC
- node = meta.chains;
- if (node) {
- NODE_STACK.push(node);
- // process tree
- while (NODE_STACK.length > 0) {
- node = NODE_STACK.pop();
- // push children
- nodes = node._chains;
- if (nodes) {
- for (key in nodes) {
- if (nodes.hasOwnProperty(key)) {
- NODE_STACK.push(nodes[key]);
- }
- }
- }
- // remove chainWatcher in node object
- if (node._watching) {
- nodeObject = node._object;
- if (nodeObject) {
- removeChainWatcher(nodeObject, node._key, node);
- }
- }
- }
- }
- }
- }
-
- __exports__.destroy = destroy;
- });
-enifed("ember-routing-handlebars",
- ["ember-metal/core","ember-handlebars","ember-routing-handlebars/helpers/link_to","ember-routing-handlebars/helpers/outlet","ember-routing-handlebars/helpers/render","ember-routing-handlebars/helpers/action","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __exports__) {
- "use strict";
- /**
- Ember Routing Handlebars
-
- @module ember
- @submodule ember-routing-handlebars
- @requires ember-views
- */
-
- var Ember = __dependency1__["default"];
- var EmberHandlebars = __dependency2__["default"];
-
- var deprecatedLinkToHelper = __dependency3__.deprecatedLinkToHelper;
- var linkToHelper = __dependency3__.linkToHelper;
- var LinkView = __dependency3__.LinkView;
- var queryParamsHelper = __dependency3__.queryParamsHelper;
-
- var outletHelper = __dependency4__.outletHelper;
- var OutletView = __dependency4__.OutletView;
-
- var renderHelper = __dependency5__["default"];
-
- var ActionHelper = __dependency6__.ActionHelper;
- var actionHelper = __dependency6__.actionHelper;
-
- Ember.LinkView = LinkView;
- EmberHandlebars.ActionHelper = ActionHelper;
- EmberHandlebars.OutletView = OutletView;
-
- EmberHandlebars.registerHelper('render', renderHelper);
- EmberHandlebars.registerHelper('action', actionHelper);
- EmberHandlebars.registerHelper('outlet', outletHelper);
- EmberHandlebars.registerHelper('link-to', linkToHelper);
- EmberHandlebars.registerHelper('linkTo', deprecatedLinkToHelper);
- EmberHandlebars.registerHelper('query-params', queryParamsHelper);
-
- __exports__["default"] = Ember;
- });
-enifed("ember-routing-handlebars/helpers/action",
- ["ember-metal/core","ember-metal/array","ember-metal/utils","ember-metal/run_loop","ember-views/streams/read","ember-views/system/utils","ember-views/system/action_manager","ember-handlebars","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __exports__) {
- "use strict";
- var Ember = __dependency1__["default"];
- // Handlebars, uuid, FEATURES, assert, deprecate
- var forEach = __dependency2__.forEach;
- var uuid = __dependency3__.uuid;
- var run = __dependency4__["default"];
-
- var readUnwrappedModel = __dependency5__.readUnwrappedModel;
- var isSimpleClick = __dependency6__.isSimpleClick;
- var ActionManager = __dependency7__["default"];
- var EmberHandlebars = __dependency8__["default"];
-
- /**
- @module ember
- @submodule ember-routing
- */
-
- function actionArgs(parameters, actionName) {
- var ret, i;
-
- if (actionName === undefined) {
- ret = new Array(parameters.length);
- for (i = 0; i < parameters.length; i++) {
- ret[i] = readUnwrappedModel(parameters[i]);
- }
- } else {
- ret = new Array(parameters.length + 1);
- ret[0] = actionName;
- for (i = 0; i < parameters.length; i++) {
- ret[i + 1] = readUnwrappedModel(parameters[i]);
- }
- }
-
- return ret;
- }
-
- var ActionHelper = {};
-
- // registeredActions is re-exported for compatibility with older plugins
- // that were using this undocumented API.
- ActionHelper.registeredActions = ActionManager.registeredActions;
-
- __exports__.ActionHelper = ActionHelper;
-
- var keys = ["alt", "shift", "meta", "ctrl"];
-
- var POINTER_EVENT_TYPE_REGEX = /^click|mouse|touch/;
-
- var isAllowedEvent = function(event, allowedKeys) {
- if (typeof allowedKeys === "undefined") {
- if (POINTER_EVENT_TYPE_REGEX.test(event.type)) {
- return isSimpleClick(event);
- } else {
- allowedKeys = '';
- }
- }
-
- if (allowedKeys.indexOf("any") >= 0) {
- return true;
- }
-
- var allowed = true;
-
- forEach.call(keys, function(key) {
- if (event[key + "Key"] && allowedKeys.indexOf(key) === -1) {
- allowed = false;
- }
- });
-
- return allowed;
- };
-
- function isKeyEvent(eventName) {
- return ['keyUp', 'keyPress', 'keyDown'].indexOf(eventName) !== -1;
- }
-
- function ignoreKeyEvent(eventName, event, keyCode) {
- var any = 'any';
- keyCode = keyCode || any;
- return isKeyEvent(eventName) && keyCode !== any && keyCode !== event.which.toString();
- }
-
- ActionHelper.registerAction = function(actionNameOrStream, options, allowedKeys) {
- var actionId = uuid();
- var eventName = options.eventName;
- var parameters = options.parameters;
-
- ActionManager.registeredActions[actionId] = {
- eventName: eventName,
- handler: function handleRegisteredAction(event) {
- if (!isAllowedEvent(event, allowedKeys)) { return true; }
-
- if (options.preventDefault !== false) {
- event.preventDefault();
- }
-
- if (options.bubbles === false) {
- event.stopPropagation();
- }
-
- var target = options.target.value();
-
-
- var actionName;
-
- if (actionNameOrStream.isStream) {
- actionName = actionNameOrStream.value();
-
- if (typeof actionName === 'undefined' || typeof actionName === 'function') {
- actionName = actionNameOrStream._originalPath;
- Ember.deprecate("You specified a quoteless path to the {{action}} helper '" +
- actionName + "' which did not resolve to an actionName." +
- " Perhaps you meant to use a quoted actionName? (e.g. {{action '" + actionName + "'}}).");
- }
- }
-
- if (!actionName) {
- actionName = actionNameOrStream;
- }
-
- run(function runRegisteredAction() {
- if (target.send) {
- target.send.apply(target, actionArgs(parameters, actionName));
- } else {
- Ember.assert("The action '" + actionName + "' did not exist on " + target, typeof target[actionName] === 'function');
- target[actionName].apply(target, actionArgs(parameters));
- }
- });
- }
- };
-
- options.view.on('willClearRender', function() {
- delete ActionManager.registeredActions[actionId];
- });
-
- return actionId;
- };
-
- /**
- The `{{action}}` helper provides a useful shortcut for registering an HTML
- element within a template for a single DOM event and forwarding that
- interaction to the template's controller or specified `target` option.
-
- If the controller does not implement the specified action, the event is sent
- to the current route, and it bubbles up the route hierarchy from there.
-
- For more advanced event handling see [Ember.Component](/api/classes/Ember.Component.html)
-
-
- ### Use
- Given the following application Handlebars template on the page
-
- ```handlebars
- <div {{action 'anActionName'}}>
- click me
- </div>
- ```
-
- And application code
-
- ```javascript
- App.ApplicationController = Ember.Controller.extend({
- actions: {
- anActionName: function() {
- }
- }
- });
- ```
-
- Will result in the following rendered HTML
-
- ```html
- <div class="ember-view">
- <div data-ember-action="1">
- click me
- </div>
- </div>
- ```
-
- Clicking "click me" will trigger the `anActionName` action of the
- `App.ApplicationController`. In this case, no additional parameters will be passed.
-
- If you provide additional parameters to the helper:
-
- ```handlebars
- <button {{action 'edit' post}}>Edit</button>
- ```
-
- Those parameters will be passed along as arguments to the JavaScript
- function implementing the action.
-
- ### Event Propagation
-
- Events triggered through the action helper will automatically have
- `.preventDefault()` called on them. You do not need to do so in your event
- handlers. If you need to allow event propagation (to handle file inputs for
- example) you can supply the `preventDefault=false` option to the `{{action}}` helper:
-
- ```handlebars
- <div {{action "sayHello" preventDefault=false}}>
- <input type="file" />
- <input type="checkbox" />
- </div>
- ```
-
- To disable bubbling, pass `bubbles=false` to the helper:
-
- ```handlebars
- <button {{action 'edit' post bubbles=false}}>Edit</button>
- ```
-
- If you need the default handler to trigger you should either register your
- own event handler, or use event methods on your view class. See [Ember.View](/api/classes/Ember.View.html)
- 'Responding to Browser Events' for more information.
-
- ### Specifying DOM event type
-
- By default the `{{action}}` helper registers for DOM `click` events. You can
- supply an `on` option to the helper to specify a different DOM event name:
-
- ```handlebars
- <div {{action "anActionName" on="doubleClick"}}>
- click me
- </div>
- ```
-
- See `Ember.View` 'Responding to Browser Events' for a list of
- acceptable DOM event names.
-
- ### Specifying whitelisted modifier keys
-
- By default the `{{action}}` helper will ignore click event with pressed modifier
- keys. You can supply an `allowedKeys` option to specify which keys should not be ignored.
-
- ```handlebars
- <div {{action "anActionName" allowedKeys="alt"}}>
- click me
- </div>
- ```
-
- This way the `{{action}}` will fire when clicking with the alt key pressed down.
-
- Alternatively, supply "any" to the `allowedKeys` option to accept any combination of modifier keys.
-
- ```handlebars
- <div {{action "anActionName" allowedKeys="any"}}>
- click me with any key pressed
- </div>
- ```
-
- ### Specifying a Target
-
- There are several possible target objects for `{{action}}` helpers:
-
- In a typical Ember application, where templates are managed through use of the
- `{{outlet}}` helper, actions will bubble to the current controller, then
- to the current route, and then up the route hierarchy.
-
- Alternatively, a `target` option can be provided to the helper to change
- which object will receive the method call. This option must be a path
- to an object, accessible in the current context:
-
- ```handlebars
- {{! the application template }}
- <div {{action "anActionName" target=view}}>
- click me
- </div>
- ```
-
- ```javascript
- App.ApplicationView = Ember.View.extend({
- actions: {
- anActionName: function(){}
- }
- });
-
- ```
-
- ### Additional Parameters
-
- You may specify additional parameters to the `{{action}}` helper. These
- parameters are passed along as the arguments to the JavaScript function
- implementing the action.
-
- ```handlebars
- {{#each person in people}}
- <div {{action "edit" person}}>
- click me
- </div>
- {{/each}}
- ```
-
- Clicking "click me" will trigger the `edit` method on the current controller
- with the value of `person` as a parameter.
-
- @method action
- @for Ember.Handlebars.helpers
- @param {String} actionName
- @param {Object} [context]*
- @param {Hash} options
- */
- function actionHelper(actionName) {
- var length = arguments.length;
- var options = arguments[length - 1];
- var view = options.data.view;
- var hash = options.hash;
- var types = options.types;
-
- // create a hash to pass along to registerAction
- var parameters = [];
-
- var actionOptions = {
- eventName: hash.on || "click",
- parameters: parameters,
- view: options.data.view,
- bubbles: hash.bubbles,
- preventDefault: hash.preventDefault,
- target: view.getStream(hash.target || 'controller'),
- withKeyCode: hash.withKeyCode
- };
-
- var actionNameStream;
-
- if (types[0] === "ID") {
- actionNameStream = view.getStream(actionName);
- actionNameStream._originalPath = actionName;
- } else {
- actionNameStream = actionName;
- }
-
- for (var i = 1; i < length - 1; i++) {
- if (types[i] === "ID") {
- parameters.push(view.getStream(arguments[i]));
- } else {
- parameters.push(arguments[i]);
- }
- }
-
- var actionId = ActionHelper.registerAction(actionNameStream, actionOptions, hash.allowedKeys);
- return new EmberHandlebars.SafeString('data-ember-action="' + actionId + '"');
- }
-
- __exports__.actionHelper = actionHelper;
- });
-enifed("ember-routing-handlebars/helpers/link_to",
- ["ember-metal/core","ember-metal/property_get","ember-metal/merge","ember-metal/run_loop","ember-metal/computed","ember-runtime/system/string","ember-runtime/system/object","ember-runtime/mixins/controller","ember-metal/keys","ember-views/system/utils","ember-views/views/component","ember-handlebars/helpers/view","ember-routing/utils","ember-handlebars/ext","ember-metal/streams/read","ember-handlebars","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __dependency15__, __dependency16__, __exports__) {
- "use strict";
- var Ember = __dependency1__["default"];
- // FEATURES, Logger, Handlebars, warn, assert
- var get = __dependency2__.get;
- var merge = __dependency3__["default"];
- var run = __dependency4__["default"];
- var computed = __dependency5__.computed;
-
- var fmt = __dependency6__.fmt;
- var EmberObject = __dependency7__["default"];
- var ControllerMixin = __dependency8__["default"];
- var keys = __dependency9__["default"];
- var isSimpleClick = __dependency10__.isSimpleClick;
- var EmberComponent = __dependency11__["default"];
- var viewHelper = __dependency12__.viewHelper;
- var routeArgs = __dependency13__.routeArgs;
- var stringifyValue = __dependency14__.stringifyValue;
- var read = __dependency15__.read;
-
-
- /**
- @module ember
- @submodule ember-routing
- */
-
- var slice = [].slice;
-
- var numberOfContextsAcceptedByHandler = function(handler, handlerInfos) {
- var req = 0;
- for (var i = 0, l = handlerInfos.length; i < l; i++) {
- req = req + handlerInfos[i].names.length;
- if (handlerInfos[i].handler === handler)
- break;
- }
-
- return req;
- };
-
- var QueryParams = EmberObject.extend({
- values: null
- });
-
- /**
- `Ember.LinkView` renders an element whose `click` event triggers a
- transition of the application's instance of `Ember.Router` to
- a supplied route by name.
-
- Instances of `LinkView` will most likely be created through
- the `link-to` Handlebars helper, but properties of this class
- can be overridden to customize application-wide behavior.
-
- @class LinkView
- @namespace Ember
- @extends Ember.View
- @see {Handlebars.helpers.link-to}
- **/
- var LinkView = Ember.LinkView = EmberComponent.extend({
- tagName: 'a',
-
- /**
- @deprecated Use current-when instead.
- @property currentWhen
- */
- currentWhen: null,
-
- /**
- Used to determine when this LinkView is active.
-
- @property currentWhen
- */
- 'current-when': null,
-
- /**
- Sets the `title` attribute of the `LinkView`'s HTML element.
-
- @property title
- @default null
- **/
- title: null,
-
- /**
- Sets the `rel` attribute of the `LinkView`'s HTML element.
-
- @property rel
- @default null
- **/
- rel: null,
-
- /**
- The CSS class to apply to `LinkView`'s element when its `active`
- property is `true`.
-
- @property activeClass
- @type String
- @default active
- **/
- activeClass: 'active',
-
- /**
- The CSS class to apply to `LinkView`'s element when its `loading`
- property is `true`.
-
- @property loadingClass
- @type String
- @default loading
- **/
- loadingClass: 'loading',
-
- /**
- The CSS class to apply to a `LinkView`'s element when its `disabled`
- property is `true`.
-
- @property disabledClass
- @type String
- @default disabled
- **/
- disabledClass: 'disabled',
- _isDisabled: false,
-
- /**
- Determines whether the `LinkView` will trigger routing via
- the `replaceWith` routing strategy.
-
- @property replace
- @type Boolean
- @default false
- **/
- replace: false,
-
- /**
- By default the `{{link-to}}` helper will bind to the `href` and
- `title` attributes. It's discourage that you override these defaults,
- however you can push onto the array if needed.
-
- @property attributeBindings
- @type Array | String
- @default ['href', 'title', 'rel']
- **/
- attributeBindings: ['href', 'title', 'rel', 'tabindex'],
-
- /**
- By default the `{{link-to}}` helper will bind to the `active`, `loading`, and
- `disabled` classes. It is discouraged to override these directly.
-
- @property classNameBindings
- @type Array
- @default ['active', 'loading', 'disabled']
- **/
- classNameBindings: ['active', 'loading', 'disabled'],
-
- /**
- By default the `{{link-to}}` helper responds to the `click` event. You
- can override this globally by setting this property to your custom
- event name.
-
- This is particularly useful on mobile when one wants to avoid the 300ms
- click delay using some sort of custom `tap` event.
-
- @property eventName
- @type String
- @default click
- */
- eventName: 'click',
-
- // this is doc'ed here so it shows up in the events
- // section of the API documentation, which is where
- // people will likely go looking for it.
- /**
- Triggers the `LinkView`'s routing behavior. If
- `eventName` is changed to a value other than `click`
- the routing behavior will trigger on that custom event
- instead.
-
- @event click
- **/
-
- /**
- An overridable method called when LinkView objects are instantiated.
-
- Example:
-
- ```javascript
- App.MyLinkView = Ember.LinkView.extend({
- init: function() {
- this._super();
- Ember.Logger.log('Event is ' + this.get('eventName'));
- }
- });
- ```
-
- NOTE: If you do override `init` for a framework class like `Ember.View` or
- `Ember.ArrayController`, be sure to call `this._super()` in your
- `init` declaration! If you don't, Ember may not have an opportunity to
- do important setup work, and you'll see strange behavior in your
- application.
-
- @method init
- */
- init: function() {
- this._super.apply(this, arguments);
-
- Ember.deprecate('Using currentWhen with {{link-to}} is deprecated in favor of `current-when`.', !this.currentWhen);
-
- // Map desired event name to invoke function
- var eventName = get(this, 'eventName');
- this.on(eventName, this, this._invoke);
- },
-
- /**
- This method is invoked by observers installed during `init` that fire
- whenever the params change
-
- @private
- @method _paramsChanged
- @since 1.3.0
- */
- _paramsChanged: function() {
- this.notifyPropertyChange('resolvedParams');
- },
-
- /**
- This is called to setup observers that will trigger a rerender.
-
- @private
- @method _setupPathObservers
- @since 1.3.0
- **/
- _setupPathObservers: function(){
- var params = this.params;
-
- var scheduledRerender = this._wrapAsScheduled(this.rerender);
- var scheduledParamsChanged = this._wrapAsScheduled(this._paramsChanged);
-
- if (this.linkTitle) {
- this.linkTitle.subscribe(scheduledRerender, this);
- }
-
- for (var i = 0; i < params.length; i++) {
- var param = params[i];
- if (param && param.isStream) {
- param.subscribe(scheduledParamsChanged, this);
- }
- }
-
- var queryParamsObject = this.queryParamsObject;
- if (queryParamsObject) {
- var values = queryParamsObject.values;
- for (var k in values) {
- if (!values.hasOwnProperty(k)) {
- continue;
- }
-
- var value = values[k];
- if (value && value.isStream) {
- value.subscribe(scheduledParamsChanged, this);
- }
- }
- }
- },
-
- afterRender: function(){
- this._super.apply(this, arguments);
- this._setupPathObservers();
- },
-
- /**
-
- Accessed as a classname binding to apply the `LinkView`'s `disabledClass`
- CSS `class` to the element when the link is disabled.
-
- When `true` interactions with the element will not trigger route changes.
- @property disabled
- */
- disabled: computed(function computeLinkViewDisabled(key, value) {
- if (value !== undefined) { this.set('_isDisabled', value); }
-
- return value ? get(this, 'disabledClass') : false;
- }),
-
- /**
- Accessed as a classname binding to apply the `LinkView`'s `activeClass`
- CSS `class` to the element when the link is active.
-
- A `LinkView` is considered active when its `currentWhen` property is `true`
- or the application's current route is the route the `LinkView` would trigger
- transitions into.
-
- The `currentWhen` property can match against multiple routes by separating
- route names using the ` ` (space) character.
-
- @property active
- **/
- active: computed('loadedParams', function computeLinkViewActive() {
- if (get(this, 'loading')) { return false; }
-
- var router = get(this, 'router');
- var loadedParams = get(this, 'loadedParams');
- var contexts = loadedParams.models;
- var currentWhen = this['current-when'] || this.currentWhen;
- var isCurrentWhenSpecified = Boolean(currentWhen);
- currentWhen = currentWhen || loadedParams.targetRouteName;
-
- function isActiveForRoute(routeName) {
- var handlers = router.router.recognizer.handlersFor(routeName);
- var leafName = handlers[handlers.length-1].handler;
- var maximumContexts = numberOfContextsAcceptedByHandler(routeName, handlers);
-
- // NOTE: any ugliness in the calculation of activeness is largely
- // due to the fact that we support automatic normalizing of
- // `resource` -> `resource.index`, even though there might be
- // dynamic segments / query params defined on `resource.index`
- // which complicates (and makes somewhat ambiguous) the calculation
- // of activeness for links that link to `resource` instead of
- // directly to `resource.index`.
-
- // if we don't have enough contexts revert back to full route name
- // this is because the leaf route will use one of the contexts
- if (contexts.length > maximumContexts) {
- routeName = leafName;
- }
-
- var args = routeArgs(routeName, contexts, null);
- var isActive = router.isActive.apply(router, args);
- if (!isActive) { return false; }
-
- var emptyQueryParams = Ember.isEmpty(Ember.keys(loadedParams.queryParams));
-
- if (!isCurrentWhenSpecified && !emptyQueryParams && isActive) {
- var visibleQueryParams = {};
- merge(visibleQueryParams, loadedParams.queryParams);
- router._prepareQueryParams(loadedParams.targetRouteName, loadedParams.models, visibleQueryParams);
- isActive = shallowEqual(visibleQueryParams, router.router.state.queryParams);
- }
-
- return isActive;
- }
-
-
- currentWhen = currentWhen.split(' ');
- for (var i = 0, len = currentWhen.length; i < len; i++) {
- if (isActiveForRoute(currentWhen[i])) {
- return get(this, 'activeClass');
- }
- }
- }),
-
- /**
- Accessed as a classname binding to apply the `LinkView`'s `loadingClass`
- CSS `class` to the element when the link is loading.
-
- A `LinkView` is considered loading when it has at least one
- parameter whose value is currently null or undefined. During
- this time, clicking the link will perform no transition and
- emit a warning that the link is still in a loading state.
-
- @property loading
- **/
- loading: computed('loadedParams', function computeLinkViewLoading() {
- if (!get(this, 'loadedParams')) { return get(this, 'loadingClass'); }
- }),
-
- /**
- Returns the application's main router from the container.
-
- @private
- @property router
- **/
- router: computed(function() {
- var controller = get(this, 'controller');
- if (controller && controller.container) {
- return controller.container.lookup('router:main');
- }
- }),
-
- /**
- Event handler that invokes the link, activating the associated route.
-
- @private
- @method _invoke
- @param {Event} event
- */
- _invoke: function(event) {
- if (!isSimpleClick(event)) { return true; }
-
- if (this.preventDefault !== false) {
-
- var targetAttribute = get(this, 'target');
- if (!targetAttribute || targetAttribute === '_self') {
- event.preventDefault();
- }
- }
-
- if (this.bubbles === false) { event.stopPropagation(); }
-
- if (get(this, '_isDisabled')) { return false; }
-
- if (get(this, 'loading')) {
- Ember.Logger.warn("This link-to is in an inactive loading state because at least one of its parameters presently has a null/undefined value, or the provided route name is invalid.");
- return false;
- }
-
-
- var targetAttribute2 = get(this, 'target');
- if (targetAttribute2 && targetAttribute2 !== '_self') {
- return false;
- }
-
-
- var router = get(this, 'router');
- var loadedParams = get(this, 'loadedParams');
-
- var transition = router._doTransition(loadedParams.targetRouteName, loadedParams.models, loadedParams.queryParams);
- if (get(this, 'replace')) {
- transition.method('replace');
- }
-
- // Schedule eager URL update, but after we've given the transition
- // a chance to synchronously redirect.
- // We need to always generate the URL instead of using the href because
- // the href will include any rootURL set, but the router expects a URL
- // without it! Note that we don't use the first level router because it
- // calls location.formatURL(), which also would add the rootURL!
- var args = routeArgs(loadedParams.targetRouteName, loadedParams.models, transition.state.queryParams);
- var url = router.router.generate.apply(router.router, args);
-
- run.scheduleOnce('routerTransitions', this, this._eagerUpdateUrl, transition, url);
- },
-
- /**
- @private
- @method _eagerUpdateUrl
- @param transition
- @param href
- */
- _eagerUpdateUrl: function(transition, href) {
- if (!transition.isActive || !transition.urlMethod) {
- // transition was aborted, already ran to completion,
- // or it has a null url-updated method.
- return;
- }
-
- if (href.indexOf('#') === 0) {
- href = href.slice(1);
- }
-
- // Re-use the routerjs hooks set up by the Ember router.
- var routerjs = get(this, 'router.router');
- if (transition.urlMethod === 'update') {
- routerjs.updateURL(href);
- } else if (transition.urlMethod === 'replace') {
- routerjs.replaceURL(href);
- }
-
- // Prevent later update url refire.
- transition.method(null);
- },
-
- /**
- Computed property that returns an array of the
- resolved parameters passed to the `link-to` helper,
- e.g.:
-
- ```hbs
- {{link-to a b '123' c}}
- ```
-
- will generate a `resolvedParams` of:
-
- ```js
- [aObject, bObject, '123', cObject]
- ```
-
- @private
- @property
- @return {Array}
- */
- resolvedParams: computed('router.url', function() {
- var params = this.params;
- var targetRouteName;
- var models = [];
- var onlyQueryParamsSupplied = (params.length === 0);
-
- if (onlyQueryParamsSupplied) {
- var appController = this.container.lookup('controller:application');
- targetRouteName = get(appController, 'currentRouteName');
- } else {
- targetRouteName = read(params[0]);
-
- for (var i = 1; i < params.length; i++) {
- models.push(read(params[i]));
- }
- }
-
- var suppliedQueryParams = getResolvedQueryParams(this, targetRouteName);
-
- return {
- targetRouteName: targetRouteName,
- models: models,
- queryParams: suppliedQueryParams
- };
- }),
-
- /**
- Computed property that returns the current route name,
- dynamic segments, and query params. Returns falsy if
- for null/undefined params to indicate that the link view
- is still in a loading state.
-
- @private
- @property
- @return {Array} An array with the route name and any dynamic segments
- **/
- loadedParams: computed('resolvedParams', function computeLinkViewRouteArgs() {
- var router = get(this, 'router');
- if (!router) { return; }
-
- var resolvedParams = get(this, 'resolvedParams');
- var namedRoute = resolvedParams.targetRouteName;
-
- if (!namedRoute) { return; }
-
- Ember.assert(fmt("The attempt to link-to route '%@' failed. " +
- "The router did not find '%@' in its possible routes: '%@'",
- [namedRoute, namedRoute, keys(router.router.recognizer.names).join("', '")]),
- router.hasRoute(namedRoute));
-
- if (!paramsAreLoaded(resolvedParams.models)) { return; }
-
- return resolvedParams;
- }),
-
- queryParamsObject: null,
-
- /**
- Sets the element's `href` attribute to the url for
- the `LinkView`'s targeted route.
-
- If the `LinkView`'s `tagName` is changed to a value other
- than `a`, this property will be ignored.
-
- @property href
- **/
- href: computed('loadedParams', function computeLinkViewHref() {
- if (get(this, 'tagName') !== 'a') { return; }
-
- var router = get(this, 'router');
- var loadedParams = get(this, 'loadedParams');
-
- if (!loadedParams) {
- return get(this, 'loadingHref');
- }
-
- var visibleQueryParams = {};
- merge(visibleQueryParams, loadedParams.queryParams);
- router._prepareQueryParams(loadedParams.targetRouteName, loadedParams.models, visibleQueryParams);
-
- var args = routeArgs(loadedParams.targetRouteName, loadedParams.models, visibleQueryParams);
- var result = router.generate.apply(router, args);
- return result;
- }),
-
- /**
- The default href value to use while a link-to is loading.
- Only applies when tagName is 'a'
-
- @property loadingHref
- @type String
- @default #
- */
- loadingHref: '#'
- });
-
- LinkView.toString = function() { return "LinkView"; };
-
-
- LinkView.reopen({
- attributeBindings: ['target'],
-
- /**
- Sets the `target` attribute of the `LinkView`'s anchor element.
-
- @property target
- @default null
- **/
- target: null
- });
-
-
- /**
- The `{{link-to}}` helper renders a link to the supplied
- `routeName` passing an optionally supplied model to the
- route as its `model` context of the route. The block
- for `{{link-to}}` becomes the innerHTML of the rendered
- element:
-
- ```handlebars
- {{#link-to 'photoGallery'}}
- Great Hamster Photos
- {{/link-to}}
- ```
-
- ```html
- <a href="/hamster-photos">
- Great Hamster Photos
- </a>
- ```
-
- ### Supplying a tagName
- By default `{{link-to}}` renders an `<a>` element. This can
- be overridden for a single use of `{{link-to}}` by supplying
- a `tagName` option:
-
- ```handlebars
- {{#link-to 'photoGallery' tagName="li"}}
- Great Hamster Photos
- {{/link-to}}
- ```
-
- ```html
- <li>
- Great Hamster Photos
- </li>
- ```
-
- To override this option for your entire application, see
- "Overriding Application-wide Defaults".
-
- ### Disabling the `link-to` helper
- By default `{{link-to}}` is enabled.
- any passed value to `disabled` helper property will disable the `link-to` helper.
-
- static use: the `disabled` option:
-
- ```handlebars
- {{#link-to 'photoGallery' disabled=true}}
- Great Hamster Photos
- {{/link-to}}
- ```
-
- dynamic use: the `disabledWhen` option:
-
- ```handlebars
- {{#link-to 'photoGallery' disabledWhen=controller.someProperty}}
- Great Hamster Photos
- {{/link-to}}
- ```
-
- any passed value to `disabled` will disable it except `undefined`.
- to ensure that only `true` disable the `link-to` helper you can
- override the global behaviour of `Ember.LinkView`.
-
- ```javascript
- Ember.LinkView.reopen({
- disabled: Ember.computed(function(key, value) {
- if (value !== undefined) {
- this.set('_isDisabled', value === true);
- }
- return value === true ? get(this, 'disabledClass') : false;
- })
- });
- ```
-
- see "Overriding Application-wide Defaults" for more.
-
- ### Handling `href`
- `{{link-to}}` will use your application's Router to
- fill the element's `href` property with a url that
- matches the path to the supplied `routeName` for your
- routers's configured `Location` scheme, which defaults
- to Ember.HashLocation.
-
- ### Handling current route
- `{{link-to}}` will apply a CSS class name of 'active'
- when the application's current route matches
- the supplied routeName. For example, if the application's
- current route is 'photoGallery.recent' the following
- use of `{{link-to}}`:
-
- ```handlebars
- {{#link-to 'photoGallery.recent'}}
- Great Hamster Photos from the last week
- {{/link-to}}
- ```
-
- will result in
-
- ```html
- <a href="/hamster-photos/this-week" class="active">
- Great Hamster Photos
- </a>
- ```
-
- The CSS class name used for active classes can be customized
- for a single use of `{{link-to}}` by passing an `activeClass`
- option:
-
- ```handlebars
- {{#link-to 'photoGallery.recent' activeClass="current-url"}}
- Great Hamster Photos from the last week
- {{/link-to}}
- ```
-
- ```html
- <a href="/hamster-photos/this-week" class="current-url">
- Great Hamster Photos
- </a>
- ```
-
- To override this option for your entire application, see
- "Overriding Application-wide Defaults".
-
- ### Supplying a model
- An optional model argument can be used for routes whose
- paths contain dynamic segments. This argument will become
- the model context of the linked route:
-
- ```javascript
- App.Router.map(function() {
- this.resource("photoGallery", {path: "hamster-photos/:photo_id"});
- });
- ```
-
- ```handlebars
- {{#link-to 'photoGallery' aPhoto}}
- {{aPhoto.title}}
- {{/link-to}}
- ```
-
- ```html
- <a href="/hamster-photos/42">
- Tomster
- </a>
- ```
-
- ### Supplying multiple models
- For deep-linking to route paths that contain multiple
- dynamic segments, multiple model arguments can be used.
- As the router transitions through the route path, each
- supplied model argument will become the context for the
- route with the dynamic segments:
-
- ```javascript
- App.Router.map(function() {
- this.resource("photoGallery", {path: "hamster-photos/:photo_id"}, function() {
- this.route("comment", {path: "comments/:comment_id"});
- });
- });
- ```
- This argument will become the model context of the linked route:
-
- ```handlebars
- {{#link-to 'photoGallery.comment' aPhoto comment}}
- {{comment.body}}
- {{/link-to}}
- ```
-
- ```html
- <a href="/hamster-photos/42/comment/718">
- A+++ would snuggle again.
- </a>
- ```
-
- ### Supplying an explicit dynamic segment value
- If you don't have a model object available to pass to `{{link-to}}`,
- an optional string or integer argument can be passed for routes whose
- paths contain dynamic segments. This argument will become the value
- of the dynamic segment:
-
- ```javascript
- App.Router.map(function() {
- this.resource("photoGallery", {path: "hamster-photos/:photo_id"});
- });
- ```
-
- ```handlebars
- {{#link-to 'photoGallery' aPhotoId}}
- {{aPhoto.title}}
- {{/link-to}}
- ```
-
- ```html
- <a href="/hamster-photos/42">
- Tomster
- </a>
- ```
-
- When transitioning into the linked route, the `model` hook will
- be triggered with parameters including this passed identifier.
-
- ### Allowing Default Action
-
- By default the `{{link-to}}` helper prevents the default browser action
- by calling `preventDefault()` as this sort of action bubbling is normally
- handled internally and we do not want to take the browser to a new URL (for
- example).
-
- If you need to override this behavior specify `preventDefault=false` in
- your template:
-
- ```handlebars
- {{#link-to 'photoGallery' aPhotoId preventDefault=false}}
- {{aPhotoId.title}}
- {{/link-to}}
- ```
-
- ### Overriding attributes
- You can override any given property of the Ember.LinkView
- that is generated by the `{{link-to}}` helper by passing
- key/value pairs, like so:
-
- ```handlebars
- {{#link-to aPhoto tagName='li' title='Following this link will change your life' classNames='pic sweet'}}
- Uh-mazing!
- {{/link-to}}
- ```
-
- See [Ember.LinkView](/api/classes/Ember.LinkView.html) for a
- complete list of overrideable properties. Be sure to also
- check out inherited properties of `LinkView`.
-
- ### Overriding Application-wide Defaults
- ``{{link-to}}`` creates an instance of Ember.LinkView
- for rendering. To override options for your entire
- application, reopen Ember.LinkView and supply the
- desired values:
-
- ``` javascript
- Ember.LinkView.reopen({
- activeClass: "is-active",
- tagName: 'li'
- })
- ```
-
- It is also possible to override the default event in
- this manner:
-
- ``` javascript
- Ember.LinkView.reopen({
- eventName: 'customEventName'
- });
- ```
-
- @method link-to
- @for Ember.Handlebars.helpers
- @param {String} routeName
- @param {Object} [context]*
- @param [options] {Object} Handlebars key/value pairs of options, you can override any property of Ember.LinkView
- @return {String} HTML string
- @see {Ember.LinkView}
- */
- function linkToHelper(name) {
- var options = slice.call(arguments, -1)[0];
- var params = slice.call(arguments, 0, -1);
- var view = options.data.view;
- var hash = options.hash;
- var hashTypes = options.hashTypes;
- var types = options.types;
- var shouldEscape = !hash.unescaped;
- var queryParamsObject;
-
- Ember.assert("You must provide one or more parameters to the link-to helper.", params.length);
-
- if (params[params.length - 1] instanceof QueryParams) {
- hash.queryParamsObject = queryParamsObject = params.pop();
- }
-
- if (hash.disabledWhen) {
- hash.disabledBinding = hash.disabledWhen;
- hashTypes.disabledBinding = hashTypes.disabledWhen;
- delete hash.disabledWhen;
- delete hashTypes.disabledWhen;
- }
-
- if (!options.fn) {
- var linkTitle = params.shift();
- var linkTitleType = types.shift();
- if (linkTitleType === 'ID') {
- hash.linkTitle = linkTitle = view.getStream(linkTitle);
- options.fn = function() {
- return stringifyValue(linkTitle.value(), shouldEscape);
- };
- } else {
- options.fn = function() {
- return linkTitle;
- };
- }
- }
-
- // Setup route & param streams
- for (var i = 0; i < params.length; i++) {
- var paramPath = params[i];
- if (types[i] === 'ID') {
- var lazyValue = view.getStream(paramPath);
-
- // TODO: Consider a better approach to unwrapping controllers.
- if (paramPath !== 'controller') {
- while (ControllerMixin.detect(lazyValue.value())) {
- paramPath = (paramPath === '') ? 'model' : paramPath + '.model';
- lazyValue = view.getStream(paramPath);
- }
- }
- params[i] = lazyValue;
- }
- }
-
- hash.params = params;
-
- options.helperName = options.helperName || 'link-to';
-
- return viewHelper.call(this, LinkView, options);
- }
-
- /**
- This is a sub-expression to be used in conjunction with the link-to helper.
- It will supply url query parameters to the target route.
-
- Example
-
- {#link-to 'posts' (query-params direction="asc")}}Sort{{/link-to}}
-
- @method query-params
- @for Ember.Handlebars.helpers
- @param {Object} hash takes a hash of query parameters
- @return {String} HTML string
- */
- function queryParamsHelper(options) {
- Ember.assert(fmt("The `query-params` helper only accepts hash parameters, e.g. (query-params queryParamPropertyName='%@') as opposed to just (query-params '%@')", [options, options]), arguments.length === 1);
-
- var view = options.data.view;
- var hash = options.hash;
- var hashTypes = options.hashTypes;
-
- for (var k in hash) {
- if (hashTypes[k] === 'ID') {
- hash[k] = view.getStream(hash[k]);
- }
- }
-
- return QueryParams.create({
- values: options.hash
- });
- }
-
- __exports__.queryParamsHelper = queryParamsHelper;/**
- See [link-to](/api/classes/Ember.Handlebars.helpers.html#method_link-to)
-
- @method linkTo
- @for Ember.Handlebars.helpers
- @deprecated
- @param {String} routeName
- @param {Object} [context]*
- @return {String} HTML string
- */
- function deprecatedLinkToHelper() {
- Ember.deprecate("The 'linkTo' view helper is deprecated in favor of 'link-to'");
-
- return linkToHelper.apply(this, arguments);
- }
-
- function getResolvedQueryParams(linkView, targetRouteName) {
- var queryParamsObject = linkView.queryParamsObject;
- var resolvedQueryParams = {};
-
- if (!queryParamsObject) { return resolvedQueryParams; }
-
- var values = queryParamsObject.values;
- for (var key in values) {
- if (!values.hasOwnProperty(key)) { continue; }
- resolvedQueryParams[key] = read(values[key]);
- }
-
- return resolvedQueryParams;
- }
-
- function paramsAreLoaded(params) {
- for (var i = 0, len = params.length; i < len; ++i) {
- var param = params[i];
- if (param === null || typeof param === 'undefined') {
- return false;
- }
- }
- return true;
- }
-
- function shallowEqual(a, b) {
- var k;
- for (k in a) {
- if (a.hasOwnProperty(k) && a[k] !== b[k]) { return false; }
- }
- for (k in b) {
- if (b.hasOwnProperty(k) && a[k] !== b[k]) { return false; }
- }
- return true;
- }
-
- __exports__.LinkView = LinkView;
- __exports__.deprecatedLinkToHelper = deprecatedLinkToHelper;
- __exports__.linkToHelper = linkToHelper;
- });
-enifed("ember-routing-handlebars/helpers/outlet",
- ["ember-metal/core","ember-metal/property_set","ember-views/views/container_view","ember-handlebars/views/metamorph_view","ember-handlebars/helpers/view","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) {
- "use strict";
- var Ember = __dependency1__["default"];
- // assert
- var set = __dependency2__.set;
- var ContainerView = __dependency3__["default"];
- var _Metamorph = __dependency4__._Metamorph;
- var viewHelper = __dependency5__.viewHelper;
-
- /**
- @module ember
- @submodule ember-routing
- */
-
- /**
- @module ember
- @submodule ember-routing
- */
-
- var OutletView = ContainerView.extend(_Metamorph);
- __exports__.OutletView = OutletView;
- /**
- The `outlet` helper is a placeholder that the router will fill in with
- the appropriate template based on the current state of the application.
-
- ``` handlebars
- {{outlet}}
- ```
-
- By default, a template based on Ember's naming conventions will be rendered
- into the `outlet` (e.g. `App.PostsRoute` will render the `posts` template).
-
- You can render a different template by using the `render()` method in the
- route's `renderTemplate` hook. The following will render the `favoritePost`
- template into the `outlet`.
-
- ``` javascript
- App.PostsRoute = Ember.Route.extend({
- renderTemplate: function() {
- this.render('favoritePost');
- }
- });
- ```
-
- You can create custom named outlets for more control.
-
- ``` handlebars
- {{outlet 'favoritePost'}}
- {{outlet 'posts'}}
- ```
-
- Then you can define what template is rendered into each outlet in your
- route.
-
-
- ``` javascript
- App.PostsRoute = Ember.Route.extend({
- renderTemplate: function() {
- this.render('favoritePost', { outlet: 'favoritePost' });
- this.render('posts', { outlet: 'posts' });
- }
- });
- ```
-
- You can specify the view that the outlet uses to contain and manage the
- templates rendered into it.
-
- ``` handlebars
- {{outlet view='sectionContainer'}}
- ```
-
- ``` javascript
- App.SectionContainer = Ember.ContainerView.extend({
- tagName: 'section',
- classNames: ['special']
- });
- ```
-
- @method outlet
- @for Ember.Handlebars.helpers
- @param {String} property the property on the controller
- that holds the view for this outlet
- @return {String} HTML string
- */
- function outletHelper(property, options) {
- var outletSource;
- var viewName;
- var viewClass;
- var viewFullName;
-
- if (property && property.data && property.data.isRenderData) {
- options = property;
- property = 'main';
- }
-
- Ember.deprecate(
- "Using {{outlet}} with an unquoted name is not supported. " +
- "Please update to quoted usage '{{outlet \"" + property + "\"}}'.",
- arguments.length === 1 || options.types[0] === 'STRING'
- );
-
- var view = options.data.view;
- var container = view.container;
-
- outletSource = view;
- while (!outletSource.get('template.isTop')) {
- outletSource = outletSource.get('_parentView');
- }
- set(view, 'outletSource', outletSource);
-
- // provide controller override
- viewName = options.hash.view;
-
- if (viewName) {
- viewFullName = 'view:' + viewName;
- Ember.assert(
- "Using a quoteless view parameter with {{outlet}} is not supported." +
- " Please update to quoted usage '{{outlet ... view=\"" + viewName + "\"}}.",
- options.hashTypes.view !== 'ID'
- );
- Ember.assert(
- "The view name you supplied '" + viewName + "' did not resolve to a view.",
- container.has(viewFullName)
- );
- }
-
- viewClass = viewName ? container.lookupFactory(viewFullName) : options.hash.viewClass || OutletView;
- options.types = [ 'ID' ];
-
- options.hash.currentViewBinding = '_view.outletSource._outlets.' + property;
- options.hashTypes.currentViewBinding = 'STRING';
-
- options.helperName = options.helperName || 'outlet';
-
- return viewHelper.call(this, viewClass, options);
- }
-
- __exports__.outletHelper = outletHelper;
- });
-enifed("ember-routing-handlebars/helpers/render",
- ["ember-metal/core","ember-metal/error","ember-runtime/system/string","ember-routing/system/generate_controller","ember-handlebars/helpers/view","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) {
- "use strict";
- var Ember = __dependency1__["default"];
- // assert, deprecate
- var EmberError = __dependency2__["default"];
- var camelize = __dependency3__.camelize;
- var generateControllerFactory = __dependency4__.generateControllerFactory;
- var generateController = __dependency4__["default"];
- var ViewHelper = __dependency5__.ViewHelper;
-
- /**
- @module ember
- @submodule ember-routing
- */
-
- /**
- Calling ``{{render}}`` from within a template will insert another
- template that matches the provided name. The inserted template will
- access its properties on its own controller (rather than the controller
- of the parent template).
-
- If a view class with the same name exists, the view class also will be used.
-
- Note: A given controller may only be used *once* in your app in this manner.
- A singleton instance of the controller will be created for you.
-
- Example:
-
- ```javascript
- App.NavigationController = Ember.Controller.extend({
- who: "world"
- });
- ```
-
- ```handlebars
- <!-- navigation.hbs -->
- Hello, {{who}}.
- ```
-
- ```handlebars
- <!-- application.hbs -->
- <h1>My great app</h1>
- {{render "navigation"}}
- ```
-
- ```html
- <h1>My great app</h1>
- <div class='ember-view'>
- Hello, world.
- </div>
- ```
-
- Optionally you may provide a second argument: a property path
- that will be bound to the `model` property of the controller.
-
- If a `model` property path is specified, then a new instance of the
- controller will be created and `{{render}}` can be used multiple times
- with the same name.
-
- For example if you had this `author` template.
-
- ```handlebars
- <div class="author">
- Written by {{firstName}} {{lastName}}.
- Total Posts: {{postCount}}
- </div>
- ```
-
- You could render it inside the `post` template using the `render` helper.
-
- ```handlebars
- <div class="post">
- <h1>{{title}}</h1>
- <div>{{body}}</div>
- {{render "author" author}}
- </div>
- ```
-
- @method render
- @for Ember.Handlebars.helpers
- @param {String} name
- @param {Object?} contextString
- @param {Hash} options
- @return {String} HTML string
- */
- __exports__["default"] = function renderHelper(name, contextString, options) {
- var length = arguments.length;
- var container, router, controller, view, initialContext;
-
- container = (options || contextString).data.view._keywords.controller.value().container;
- router = container.lookup('router:main');
-
- if (length === 2) {
- // use the singleton controller
- options = contextString;
- contextString = undefined;
- Ember.assert("You can only use the {{render}} helper once without a model object as its" +
- " second argument, as in {{render \"post\" post}}.", !router || !router._lookupActiveView(name));
- } else if (length === 3) {
- // create a new controller
- initialContext = options.data.view.getStream(contextString).value();
- } else {
- throw new EmberError("You must pass a templateName to render");
- }
-
- Ember.deprecate("Using a quoteless parameter with {{render}} is deprecated. Please update to" +
- " quoted usage '{{render \"" + name + "\"}}.", options.types[0] !== 'ID');
-
- // # legacy namespace
- name = name.replace(/\//g, '.');
- // \ legacy slash as namespace support
-
-
- view = container.lookup('view:' + name) || container.lookup('view:default');
-
- // provide controller override
- var controllerName = options.hash.controller || name;
- var controllerFullName = 'controller:' + controllerName;
-
- if (options.hash.controller) {
- Ember.assert("The controller name you supplied '" + controllerName +
- "' did not resolve to a controller.", container.has(controllerFullName));
- }
-
- var parentController = options.data.view._keywords.controller.value();
-
- // choose name
- if (length > 2) {
- var factory = container.lookupFactory(controllerFullName) ||
- generateControllerFactory(container, controllerName, initialContext);
-
- controller = factory.create({
- modelBinding: options.data.view._getBindingForStream(contextString),
- parentController: parentController,
- target: parentController
- });
-
- view.one('willDestroyElement', function() {
- controller.destroy();
- });
- } else {
- controller = container.lookup(controllerFullName) ||
- generateController(container, controllerName);
-
- controller.setProperties({
- target: parentController,
- parentController: parentController
- });
- }
-
- options.hash.viewName = camelize(name);
-
- var templateName = 'template:' + name;
- Ember.assert("You used `{{render '" + name + "'}}`, but '" + name + "' can not be found as either" +
- " a template or a view.", container.has("view:" + name) || container.has(templateName) || options.fn);
- options.hash.template = container.lookup(templateName);
-
- options.hash.controller = controller;
-
- if (router && !initialContext) {
- router._connectActiveView(name, view);
- }
-
- options.helperName = options.helperName || ('render "' + name + '"');
-
- ViewHelper.instanceHelper(this, view, options);
- }
- });
-enifed("ember-routing",
- ["ember-metal/core","ember-routing/ext/run_loop","ember-routing/ext/controller","ember-routing/ext/view","ember-routing/location/api","ember-routing/location/none_location","ember-routing/location/hash_location","ember-routing/location/history_location","ember-routing/location/auto_location","ember-routing/system/generate_controller","ember-routing/system/controller_for","ember-routing/system/dsl","ember-routing/system/router","ember-routing/system/route","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __exports__) {
- "use strict";
- /**
- Ember Routing
-
- @module ember
- @submodule ember-routing
- @requires ember-views
- */
-
- var Ember = __dependency1__["default"];
-
- // ES6TODO: Cleanup modules with side-effects below
-
- var EmberLocation = __dependency5__["default"];
- var NoneLocation = __dependency6__["default"];
- var HashLocation = __dependency7__["default"];
- var HistoryLocation = __dependency8__["default"];
- var AutoLocation = __dependency9__["default"];
-
- var generateControllerFactory = __dependency10__.generateControllerFactory;
- var generateController = __dependency10__["default"];
- var controllerFor = __dependency11__["default"];
- var RouterDSL = __dependency12__["default"];
- var Router = __dependency13__["default"];
- var Route = __dependency14__["default"];
-
- Ember.Location = EmberLocation;
- Ember.AutoLocation = AutoLocation;
- Ember.HashLocation = HashLocation;
- Ember.HistoryLocation = HistoryLocation;
- Ember.NoneLocation = NoneLocation;
-
- Ember.controllerFor = controllerFor;
- Ember.generateControllerFactory = generateControllerFactory;
- Ember.generateController = generateController;
- Ember.RouterDSL = RouterDSL;
- Ember.Router = Router;
- Ember.Route = Route;
-
- __exports__["default"] = Ember;
- });
-enifed("ember-routing/ext/controller",
- ["ember-metal/core","ember-metal/property_get","ember-metal/property_set","ember-metal/computed","ember-metal/utils","ember-metal/merge","ember-runtime/mixins/controller","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __exports__) {
- "use strict";
- var Ember = __dependency1__["default"];
- // FEATURES, deprecate
- var get = __dependency2__.get;
- var set = __dependency3__.set;
- var computed = __dependency4__.computed;
- var typeOf = __dependency5__.typeOf;
- var meta = __dependency5__.meta;
- var merge = __dependency6__["default"];
-
- var ControllerMixin = __dependency7__["default"];
-
- /**
- @module ember
- @submodule ember-routing
- */
-
- ControllerMixin.reopen({
- concatenatedProperties: ['queryParams', '_pCacheMeta'],
-
- init: function() {
- this._super.apply(this, arguments);
- listenForQueryParamChanges(this);
- },
-
- /**
- Defines which query parameters the controller accepts.
- If you give the names ['category','page'] it will bind
- the values of these query parameters to the variables
- `this.category` and `this.page`
-
- @property queryParams
- @public
- */
- queryParams: null,
-
- /**
- @property _qpDelegate
- @private
- */
- _qpDelegate: null,
-
- /**
- @property _normalizedQueryParams
- @private
- */
- _normalizedQueryParams: computed(function() {
- var m = meta(this);
- if (m.proto !== this) {
- return get(m.proto, '_normalizedQueryParams');
- }
-
- var queryParams = get(this, 'queryParams');
- if (queryParams._qpMap) {
- return queryParams._qpMap;
- }
-
- var qpMap = queryParams._qpMap = {};
-
- for (var i = 0, len = queryParams.length; i < len; ++i) {
- accumulateQueryParamDescriptors(queryParams[i], qpMap);
- }
-
- return qpMap;
- }),
-
- /**
- @property _cacheMeta
- @private
- */
- _cacheMeta: computed(function() {
- var m = meta(this);
- if (m.proto !== this) {
- return get(m.proto, '_cacheMeta');
- }
-
- var cacheMeta = {};
- var qpMap = get(this, '_normalizedQueryParams');
- for (var prop in qpMap) {
- if (!qpMap.hasOwnProperty(prop)) { continue; }
-
- var qp = qpMap[prop];
- var scope = qp.scope;
- var parts;
-
- if (scope === 'controller') {
- parts = [];
- }
-
- cacheMeta[prop] = {
- parts: parts, // provided by route if 'model' scope
- values: null, // provided by route
- scope: scope,
- prefix: "",
- def: get(this, prop)
- };
- }
-
- return cacheMeta;
- }),
-
- /**
- @method _updateCacheParams
- @private
- */
- _updateCacheParams: function(params) {
- var cacheMeta = get(this, '_cacheMeta');
- for (var prop in cacheMeta) {
- if (!cacheMeta.hasOwnProperty(prop)) { continue; }
- var propMeta = cacheMeta[prop];
- propMeta.values = params;
-
- var cacheKey = this._calculateCacheKey(propMeta.prefix, propMeta.parts, propMeta.values);
- var cache = this._bucketCache;
-
- if (cache) {
- var value = cache.lookup(cacheKey, prop, propMeta.def);
- set(this, prop, value);
- }
- }
- },
-
- /**
- @method _qpChanged
- @private
- */
- _qpChanged: function(controller, _prop) {
- var prop = _prop.substr(0, _prop.length-3);
- var cacheMeta = get(controller, '_cacheMeta');
- var propCache = cacheMeta[prop];
- var cacheKey = controller._calculateCacheKey(propCache.prefix || "", propCache.parts, propCache.values);
- var value = get(controller, prop);
-
- // 1. Update model-dep cache
- var cache = this._bucketCache;
- if (cache) {
- controller._bucketCache.stash(cacheKey, prop, value);
- }
-
- // 2. Notify a delegate (e.g. to fire a qp transition)
- var delegate = controller._qpDelegate;
- if (delegate) {
- delegate(controller, prop);
- }
- },
-
- /**
- @method _calculateCacheKey
- @private
- */
- _calculateCacheKey: function(prefix, _parts, values) {
- var parts = _parts || [], suffixes = "";
- for (var i = 0, len = parts.length; i < len; ++i) {
- var part = parts[i];
- var value = get(values, part);
- suffixes += "::" + part + ":" + value;
- }
- return prefix + suffixes.replace(ALL_PERIODS_REGEX, '-');
- },
-
- /**
- Transition the application into another route. The route may
- be either a single route or route path:
-
- ```javascript
- aController.transitionToRoute('blogPosts');
- aController.transitionToRoute('blogPosts.recentEntries');
- ```
-
- Optionally supply a model for the route in question. The model
- will be serialized into the URL using the `serialize` hook of
- the route:
-
- ```javascript
- aController.transitionToRoute('blogPost', aPost);
- ```
-
- If a literal is passed (such as a number or a string), it will
- be treated as an identifier instead. In this case, the `model`
- hook of the route will be triggered:
-
- ```javascript
- aController.transitionToRoute('blogPost', 1);
- ```
-
- Multiple models will be applied last to first recursively up the
- resource tree.
-
- ```javascript
- App.Router.map(function() {
- this.resource('blogPost', {path:':blogPostId'}, function(){
- this.resource('blogComment', {path: ':blogCommentId'});
- });
- });
-
- aController.transitionToRoute('blogComment', aPost, aComment);
- aController.transitionToRoute('blogComment', 1, 13);
- ```
-
- It is also possible to pass a URL (a string that starts with a
- `/`). This is intended for testing and debugging purposes and
- should rarely be used in production code.
-
- ```javascript
- aController.transitionToRoute('/');
- aController.transitionToRoute('/blog/post/1/comment/13');
- ```
-
- See also [replaceRoute](/api/classes/Ember.ControllerMixin.html#method_replaceRoute).
-
- @param {String} name the name of the route or a URL
- @param {...Object} models the model(s) or identifier(s) to be used
- while transitioning to the route.
- @for Ember.ControllerMixin
- @method transitionToRoute
- */
- transitionToRoute: function() {
- // target may be either another controller or a router
- var target = get(this, 'target');
- var method = target.transitionToRoute || target.transitionTo;
- return method.apply(target, arguments);
- },
-
- /**
- @deprecated
- @for Ember.ControllerMixin
- @method transitionTo
- */
- transitionTo: function() {
- Ember.deprecate("transitionTo is deprecated. Please use transitionToRoute.");
- return this.transitionToRoute.apply(this, arguments);
- },
-
- /**
- Transition into another route while replacing the current URL, if possible.
- This will replace the current history entry instead of adding a new one.
- Beside that, it is identical to `transitionToRoute` in all other respects.
-
- ```javascript
- aController.replaceRoute('blogPosts');
- aController.replaceRoute('blogPosts.recentEntries');
- ```
-
- Optionally supply a model for the route in question. The model
- will be serialized into the URL using the `serialize` hook of
- the route:
-
- ```javascript
- aController.replaceRoute('blogPost', aPost);
- ```
-
- If a literal is passed (such as a number or a string), it will
- be treated as an identifier instead. In this case, the `model`
- hook of the route will be triggered:
-
- ```javascript
- aController.replaceRoute('blogPost', 1);
- ```
-
- Multiple models will be applied last to first recursively up the
- resource tree.
-
- ```javascript
- App.Router.map(function() {
- this.resource('blogPost', {path:':blogPostId'}, function(){
- this.resource('blogComment', {path: ':blogCommentId'});
- });
- });
-
- aController.replaceRoute('blogComment', aPost, aComment);
- aController.replaceRoute('blogComment', 1, 13);
- ```
-
- It is also possible to pass a URL (a string that starts with a
- `/`). This is intended for testing and debugging purposes and
- should rarely be used in production code.
-
- ```javascript
- aController.replaceRoute('/');
- aController.replaceRoute('/blog/post/1/comment/13');
- ```
-
- @param {String} name the name of the route or a URL
- @param {...Object} models the model(s) or identifier(s) to be used
- while transitioning to the route.
- @for Ember.ControllerMixin
- @method replaceRoute
- */
- replaceRoute: function() {
- // target may be either another controller or a router
- var target = get(this, 'target');
- var method = target.replaceRoute || target.replaceWith;
- return method.apply(target, arguments);
- },
-
- /**
- @deprecated
- @for Ember.ControllerMixin
- @method replaceWith
- */
- replaceWith: function() {
- Ember.deprecate("replaceWith is deprecated. Please use replaceRoute.");
- return this.replaceRoute.apply(this, arguments);
- }
- });
-
- var ALL_PERIODS_REGEX = /\./g;
-
- function accumulateQueryParamDescriptors(_desc, accum) {
- var desc = _desc, tmp;
- if (typeOf(desc) === 'string') {
- tmp = {};
- tmp[desc] = { as: null };
- desc = tmp;
- }
-
- for (var key in desc) {
- if (!desc.hasOwnProperty(key)) { return; }
-
- var singleDesc = desc[key];
- if (typeOf(singleDesc) === 'string') {
- singleDesc = { as: singleDesc };
- }
-
- tmp = accum[key] || { as: null, scope: 'model' };
- merge(tmp, singleDesc);
-
- accum[key] = tmp;
- }
- }
-
- function listenForQueryParamChanges(controller) {
- var qpMap = get(controller, '_normalizedQueryParams');
- for (var prop in qpMap) {
- if (!qpMap.hasOwnProperty(prop)) { continue; }
- controller.addObserver(prop + '.[]', controller, controller._qpChanged);
- }
- }
-
-
- __exports__["default"] = ControllerMixin;
- });
-enifed("ember-routing/ext/run_loop",
- ["ember-metal/run_loop"],
- function(__dependency1__) {
- "use strict";
- var run = __dependency1__["default"];
-
- /**
- @module ember
- @submodule ember-views
- */
-
- // Add a new named queue after the 'actions' queue (where RSVP promises
- // resolve), which is used in router transitions to prevent unnecessary
- // loading state entry if all context promises resolve on the
- // 'actions' queue first.
- run._addQueue('routerTransitions', 'actions');
- });
-enifed("ember-routing/ext/view",
- ["ember-metal/property_get","ember-metal/property_set","ember-metal/run_loop","ember-views/views/view","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
- "use strict";
- var get = __dependency1__.get;
- var set = __dependency2__.set;
- var run = __dependency3__["default"];
- var EmberView = __dependency4__["default"];
-
- /**
- @module ember
- @submodule ember-routing
- */
-
- EmberView.reopen({
-
- /**
- Sets the private `_outlets` object on the view.
-
- @method init
- */
- init: function() {
- this._outlets = {};
- this._super();
- },
-
- /**
- Manually fill any of a view's `{{outlet}}` areas with the
- supplied view.
-
- Example
-
- ```javascript
- var MyView = Ember.View.extend({
- template: Ember.Handlebars.compile('Child view: {{outlet "main"}} ')
- });
- var myView = MyView.create();
- myView.appendTo('body');
- // The html for myView now looks like:
- // <div id="ember228" class="ember-view">Child view: </div>
-
- var FooView = Ember.View.extend({
- template: Ember.Handlebars.compile('<h1>Foo</h1> ')
- });
- var fooView = FooView.create();
- myView.connectOutlet('main', fooView);
- // The html for myView now looks like:
- // <div id="ember228" class="ember-view">Child view:
- // <div id="ember234" class="ember-view"><h1>Foo</h1> </div>
- // </div>
- ```
- @method connectOutlet
- @param {String} outletName A unique name for the outlet
- @param {Object} view An Ember.View
- */
- connectOutlet: function(outletName, view) {
- if (this._pendingDisconnections) {
- delete this._pendingDisconnections[outletName];
- }
-
- if (this._hasEquivalentView(outletName, view)) {
- view.destroy();
- return;
- }
-
- var outlets = get(this, '_outlets');
- var container = get(this, 'container');
- var router = container && container.lookup('router:main');
- var renderedName = get(view, 'renderedName');
-
- set(outlets, outletName, view);
-
- if (router && renderedName) {
- router._connectActiveView(renderedName, view);
- }
- },
-
- /**
- Determines if the view has already been created by checking if
- the view has the same constructor, template, and context as the
- view in the `_outlets` object.
-
- @private
- @method _hasEquivalentView
- @param {String} outletName The name of the outlet we are checking
- @param {Object} view An Ember.View
- @return {Boolean}
- */
- _hasEquivalentView: function(outletName, view) {
- var existingView = get(this, '_outlets.'+outletName);
- return existingView &&
- existingView.constructor === view.constructor &&
- existingView.get('template') === view.get('template') &&
- existingView.get('context') === view.get('context');
- },
-
- /**
- Removes an outlet from the view.
-
- Example
-
- ```javascript
- var MyView = Ember.View.extend({
- template: Ember.Handlebars.compile('Child view: {{outlet "main"}} ')
- });
- var myView = MyView.create();
- myView.appendTo('body');
- // myView's html:
- // <div id="ember228" class="ember-view">Child view: </div>
-
- var FooView = Ember.View.extend({
- template: Ember.Handlebars.compile('<h1>Foo</h1> ')
- });
- var fooView = FooView.create();
- myView.connectOutlet('main', fooView);
- // myView's html:
- // <div id="ember228" class="ember-view">Child view:
- // <div id="ember234" class="ember-view"><h1>Foo</h1> </div>
- // </div>
-
- myView.disconnectOutlet('main');
- // myView's html:
- // <div id="ember228" class="ember-view">Child view: </div>
- ```
-
- @method disconnectOutlet
- @param {String} outletName The name of the outlet to be removed
- */
- disconnectOutlet: function(outletName) {
- if (!this._pendingDisconnections) {
- this._pendingDisconnections = {};
- }
- this._pendingDisconnections[outletName] = true;
- run.once(this, '_finishDisconnections');
- },
-
- /**
- Gets an outlet that is pending disconnection and then
- nullifys the object on the `_outlet` object.
-
- @private
- @method _finishDisconnections
- */
- _finishDisconnections: function() {
- if (this.isDestroyed) return; // _outlets will be gone anyway
- var outlets = get(this, '_outlets');
- var pendingDisconnections = this._pendingDisconnections;
- this._pendingDisconnections = null;
-
- for (var outletName in pendingDisconnections) {
- set(outlets, outletName, null);
- }
- }
- });
-
- __exports__["default"] = EmberView;
- });
-enifed("ember-routing/location/api",
- ["ember-metal/core","exports"],
- function(__dependency1__, __exports__) {
- "use strict";
- var Ember = __dependency1__["default"];
- // deprecate, assert
-
- /**
- @module ember
- @submodule ember-routing
- */
-
- /**
- Ember.Location returns an instance of the correct implementation of
- the `location` API.
-
- ## Implementations
-
- You can pass an implementation name (`hash`, `history`, `none`) to force a
- particular implementation to be used in your application.
-
- ### HashLocation
-
- Using `HashLocation` results in URLs with a `#` (hash sign) separating the
- server side URL portion of the URL from the portion that is used by Ember.
- This relies upon the `hashchange` event existing in the browser.
-
- Example:
-
- ```javascript
- App.Router.map(function() {
- this.resource('posts', function() {
- this.route('new');
- });
- });
-
- App.Router.reopen({
- location: 'hash'
- });
- ```
-
- This will result in a posts.new url of `/#/posts/new`.
-
- ### HistoryLocation
-
- Using `HistoryLocation` results in URLs that are indistinguishable from a
- standard URL. This relies upon the browser's `history` API.
-
- Example:
-
- ```javascript
- App.Router.map(function() {
- this.resource('posts', function() {
- this.route('new');
- });
- });
-
- App.Router.reopen({
- location: 'history'
- });
- ```
-
- This will result in a posts.new url of `/posts/new`.
-
- Keep in mind that your server must serve the Ember app at all the routes you
- define.
-
- ### AutoLocation
-
- Using `AutoLocation`, the router will use the best Location class supported by
- the browser it is running in.
-
- Browsers that support the `history` API will use `HistoryLocation`, those that
- do not, but still support the `hashchange` event will use `HashLocation`, and
- in the rare case neither is supported will use `NoneLocation`.
-
- Example:
-
- ```javascript
- App.Router.map(function() {
- this.resource('posts', function() {
- this.route('new');
- });
- });
-
- App.Router.reopen({
- location: 'auto'
- });
- ```
-
- This will result in a posts.new url of `/posts/new` for modern browsers that
- support the `history` api or `/#/posts/new` for older ones, like Internet
- Explorer 9 and below.
-
- When a user visits a link to your application, they will be automatically
- upgraded or downgraded to the appropriate `Location` class, with the URL
- transformed accordingly, if needed.
-
- Keep in mind that since some of your users will use `HistoryLocation`, your
- server must serve the Ember app at all the routes you define.
-
- ### NoneLocation
-
- Using `NoneLocation` causes Ember to not store the applications URL state
- in the actual URL. This is generally used for testing purposes, and is one
- of the changes made when calling `App.setupForTesting()`.
-
- ## Location API
-
- Each location implementation must provide the following methods:
-
- * implementation: returns the string name used to reference the implementation.
- * getURL: returns the current URL.
- * setURL(path): sets the current URL.
- * replaceURL(path): replace the current URL (optional).
- * onUpdateURL(callback): triggers the callback when the URL changes.
- * formatURL(url): formats `url` to be placed into `href` attribute.
-
- Calling setURL or replaceURL will not trigger onUpdateURL callbacks.
-
- @class Location
- @namespace Ember
- @static
- */
- __exports__["default"] = {
- /**
- This is deprecated in favor of using the container to lookup the location
- implementation as desired.
-
- For example:
-
- ```javascript
- // Given a location registered as follows:
- container.register('location:history-test', HistoryTestLocation);
-
- // You could create a new instance via:
- container.lookup('location:history-test');
- ```
-
- @method create
- @param {Object} options
- @return {Object} an instance of an implementation of the `location` API
- @deprecated Use the container to lookup the location implementation that you
- need.
- */
- create: function(options) {
- var implementation = options && options.implementation;
- Ember.assert("Ember.Location.create: you must specify a 'implementation' option", !!implementation);
-
- var implementationClass = this.implementations[implementation];
- Ember.assert("Ember.Location.create: " + implementation + " is not a valid implementation", !!implementationClass);
-
- return implementationClass.create.apply(implementationClass, arguments);
- },
-
- /**
- This is deprecated in favor of using the container to register the
- location implementation as desired.
-
- Example:
-
- ```javascript
- Application.initializer({
- name: "history-test-location",
-
- initialize: function(container, application) {
- application.register('location:history-test', HistoryTestLocation);
- }
- });
- ```
-
- @method registerImplementation
- @param {String} name
- @param {Object} implementation of the `location` API
- @deprecated Register your custom location implementation with the
- container directly.
- */
- registerImplementation: function(name, implementation) {
- Ember.deprecate('Using the Ember.Location.registerImplementation is no longer supported.' +
- ' Register your custom location implementation with the container instead.', false);
-
- this.implementations[name] = implementation;
- },
-
- implementations: {},
- _location: window.location,
-
- /**
- Returns the current `location.hash` by parsing location.href since browsers
- inconsistently URL-decode `location.hash`.
-
- https://bugzilla.mozilla.org/show_bug.cgi?id=483304
-
- @private
- @method getHash
- @since 1.4.0
- */
- _getHash: function () {
- // AutoLocation has it at _location, HashLocation at .location.
- // Being nice and not changing
- var href = (this._location || this.location).href;
- var hashIndex = href.indexOf('#');
-
- if (hashIndex === -1) {
- return '';
- } else {
- return href.substr(hashIndex);
- }
- }
- };
- });
-enifed("ember-routing/location/auto_location",
- ["ember-metal/core","ember-metal/property_set","ember-routing/location/api","ember-routing/location/history_location","ember-routing/location/hash_location","ember-routing/location/none_location","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __exports__) {
- "use strict";
- var Ember = __dependency1__["default"];
- // FEATURES
- var set = __dependency2__.set;
-
- var EmberLocation = __dependency3__["default"];
- var HistoryLocation = __dependency4__["default"];
- var HashLocation = __dependency5__["default"];
- var NoneLocation = __dependency6__["default"];
-
- /**
- @module ember
- @submodule ember-routing
- */
-
- /**
- Ember.AutoLocation will select the best location option based off browser
- support with the priority order: history, hash, none.
-
- Clean pushState paths accessed by hashchange-only browsers will be redirected
- to the hash-equivalent and vice versa so future transitions are consistent.
-
- Keep in mind that since some of your users will use `HistoryLocation`, your
- server must serve the Ember app at all the routes you define.
-
- @class AutoLocation
- @namespace Ember
- @static
- */
- __exports__["default"] = {
-
- /**
- @private
-
- This property is used by router:main to know whether to cancel the routing
- setup process, which is needed while we redirect the browser.
-
- @since 1.5.1
- @property cancelRouterSetup
- @default false
- */
- cancelRouterSetup: false,
-
- /**
- @private
-
- Will be pre-pended to path upon state change.
-
- @since 1.5.1
- @property rootURL
- @default '/'
- */
- rootURL: '/',
-
- /**
- @private
-
- Attached for mocking in tests
-
- @since 1.5.1
- @property _window
- @default window
- */
- _window: window,
-
- /**
- @private
-
- Attached for mocking in tests
-
- @property location
- @default window.location
- */
- _location: window.location,
-
- /**
- @private
-
- Attached for mocking in tests
-
- @since 1.5.1
- @property _history
- @default window.history
- */
- _history: window.history,
-
- /**
- @private
-
- Attached for mocking in tests
-
- @since 1.5.1
- @property _HistoryLocation
- @default Ember.HistoryLocation
- */
- _HistoryLocation: HistoryLocation,
-
- /**
- @private
-
- Attached for mocking in tests
-
- @since 1.5.1
- @property _HashLocation
- @default Ember.HashLocation
- */
- _HashLocation: HashLocation,
-
- /**
- @private
-
- Attached for mocking in tests
-
- @since 1.5.1
- @property _NoneLocation
- @default Ember.NoneLocation
- */
- _NoneLocation: NoneLocation,
-
- /**
- @private
-
- Returns location.origin or builds it if device doesn't support it.
-
- @method _getOrigin
- */
- _getOrigin: function () {
- var location = this._location;
- var origin = location.origin;
-
- // Older browsers, especially IE, don't have origin
- if (!origin) {
- origin = location.protocol + '//' + location.hostname;
-
- if (location.port) {
- origin += ':' + location.port;
- }
- }
-
- return origin;
- },
-
- /**
- @private
-
- We assume that if the history object has a pushState method, the host should
- support HistoryLocation.
-
- @method _getSupportsHistory
- */
- _getSupportsHistory: function () {
- // Boosted from Modernizr: https://github.com/Modernizr/Modernizr/blob/master/feature-detects/history.js
- // The stock browser on Android 2.2 & 2.3 returns positive on history support
- // Unfortunately support is really buggy and there is no clean way to detect
- // these bugs, so we fall back to a user agent sniff :(
- var userAgent = this._window.navigator.userAgent;
-
- // We only want Android 2, stock browser, and not Chrome which identifies
- // itself as 'Mobile Safari' as well
- if (userAgent.indexOf('Android 2') !== -1 &&
- userAgent.indexOf('Mobile Safari') !== -1 &&
- userAgent.indexOf('Chrome') === -1) {
- return false;
- }
-
- return !!(this._history && 'pushState' in this._history);
- },
-
- /**
- @private
-
- IE8 running in IE7 compatibility mode gives false positive, so we must also
- check documentMode.
-
- @method _getSupportsHashChange
- */
- _getSupportsHashChange: function () {
- var _window = this._window;
- var documentMode = _window.document.documentMode;
-
- return ('onhashchange' in _window && (documentMode === undefined || documentMode > 7 ));
- },
-
- /**
- @private
-
- Redirects the browser using location.replace, prepending the locatin.origin
- to prevent phishing attempts
-
- @method _replacePath
- */
- _replacePath: function (path) {
- this._location.replace(this._getOrigin() + path);
- },
-
- /**
- @since 1.5.1
- @private
- @method _getRootURL
- */
- _getRootURL: function () {
- return this.rootURL;
- },
-
- /**
- @private
-
- Returns the current `location.pathname`, normalized for IE inconsistencies.
-
- @method _getPath
- */
- _getPath: function () {
- var pathname = this._location.pathname;
- // Various versions of IE/Opera don't always return a leading slash
- if (pathname.charAt(0) !== '/') {
- pathname = '/' + pathname;
- }
-
- return pathname;
- },
-
- /**
- @private
-
- Returns normalized location.hash as an alias to Ember.Location._getHash
-
- @since 1.5.1
- @method _getHash
- */
- _getHash: EmberLocation._getHash,
-
- /**
- @private
-
- Returns location.search
-
- @since 1.5.1
- @method _getQuery
- */
- _getQuery: function () {
- return this._location.search;
- },
-
- /**
- @private
-
- Returns the full pathname including query and hash
-
- @method _getFullPath
- */
- _getFullPath: function () {
- return this._getPath() + this._getQuery() + this._getHash();
- },
-
- /**
- @private
-
- Returns the current path as it should appear for HistoryLocation supported
- browsers. This may very well differ from the real current path (e.g. if it
- starts off as a hashed URL)
-
- @method _getHistoryPath
- */
- _getHistoryPath: function () {
- var rootURL = this._getRootURL();
- var path = this._getPath();
- var hash = this._getHash();
- var query = this._getQuery();
- var rootURLIndex = path.indexOf(rootURL);
- var routeHash, hashParts;
-
- Ember.assert('Path ' + path + ' does not start with the provided rootURL ' + rootURL, rootURLIndex === 0);
-
- // By convention, Ember.js routes using HashLocation are required to start
- // with `#/`. Anything else should NOT be considered a route and should
- // be passed straight through, without transformation.
- if (hash.substr(0, 2) === '#/') {
- // There could be extra hash segments after the route
- hashParts = hash.substr(1).split('#');
- // The first one is always the route url
- routeHash = hashParts.shift();
-
- // If the path already has a trailing slash, remove the one
- // from the hashed route so we don't double up.
- if (path.slice(-1) === '/') {
- routeHash = routeHash.substr(1);
- }
-
- // This is the "expected" final order
- path += routeHash;
- path += query;
-
- if (hashParts.length) {
- path += '#' + hashParts.join('#');
- }
- } else {
- path += query;
- path += hash;
- }
-
- return path;
- },
-
- /**
- @private
-
- Returns the current path as it should appear for HashLocation supported
- browsers. This may very well differ from the real current path.
-
- @method _getHashPath
- */
- _getHashPath: function () {
- var rootURL = this._getRootURL();
- var path = rootURL;
- var historyPath = this._getHistoryPath();
- var routePath = historyPath.substr(rootURL.length);
-
- if (routePath !== '') {
- if (routePath.charAt(0) !== '/') {
- routePath = '/' + routePath;
- }
-
- path += '#' + routePath;
- }
-
- return path;
- },
-
- /**
- Selects the best location option based off browser support and returns an
- instance of that Location class.
-
- @see Ember.AutoLocation
- @method create
- */
- create: function (options) {
- if (options && options.rootURL) {
- Ember.assert('rootURL must end with a trailing forward slash e.g. "/app/"',
- options.rootURL.charAt(options.rootURL.length-1) === '/');
- this.rootURL = options.rootURL;
- }
-
- var historyPath, hashPath;
- var cancelRouterSetup = false;
- var implementationClass = this._NoneLocation;
- var currentPath = this._getFullPath();
-
- if (this._getSupportsHistory()) {
- historyPath = this._getHistoryPath();
-
- // Since we support history paths, let's be sure we're using them else
- // switch the location over to it.
- if (currentPath === historyPath) {
- implementationClass = this._HistoryLocation;
- } else {
-
- if (currentPath.substr(0, 2) === '/#') {
- this._history.replaceState({ path: historyPath }, null, historyPath);
- implementationClass = this._HistoryLocation;
- } else {
- cancelRouterSetup = true;
- this._replacePath(historyPath);
- }
- }
-
- } else if (this._getSupportsHashChange()) {
- hashPath = this._getHashPath();
-
- // Be sure we're using a hashed path, otherwise let's switch over it to so
- // we start off clean and consistent. We'll count an index path with no
- // hash as "good enough" as well.
- if (currentPath === hashPath || (currentPath === '/' && hashPath === '/#/')) {
- implementationClass = this._HashLocation;
- } else {
- // Our URL isn't in the expected hash-supported format, so we want to
- // cancel the router setup and replace the URL to start off clean
- cancelRouterSetup = true;
- this._replacePath(hashPath);
- }
- }
-
- var implementation = implementationClass.create.apply(implementationClass, arguments);
-
- if (cancelRouterSetup) {
- set(implementation, 'cancelRouterSetup', true);
- }
-
- return implementation;
- }
- };
- });
-enifed("ember-routing/location/hash_location",
- ["ember-metal/core","ember-metal/property_get","ember-metal/property_set","ember-metal/run_loop","ember-metal/utils","ember-runtime/system/object","ember-routing/location/api","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __exports__) {
- "use strict";
- var Ember = __dependency1__["default"];
- var get = __dependency2__.get;
- var set = __dependency3__.set;
- var run = __dependency4__["default"];
- var guidFor = __dependency5__.guidFor;
-
- var EmberObject = __dependency6__["default"];
- var EmberLocation = __dependency7__["default"];
-
- /**
- @module ember
- @submodule ember-routing
- */
-
- /**
- `Ember.HashLocation` implements the location API using the browser's
- hash. At present, it relies on a `hashchange` event existing in the
- browser.
-
- @class HashLocation
- @namespace Ember
- @extends Ember.Object
- */
- __exports__["default"] = EmberObject.extend({
- implementation: 'hash',
-
- init: function() {
- set(this, 'location', get(this, '_location') || window.location);
- },
-
- /**
- @private
-
- Returns normalized location.hash
-
- @since 1.5.1
- @method getHash
- */
- getHash: EmberLocation._getHash,
-
- /**
- Returns the normalized URL, constructed from `location.hash`.
-
- e.g. `#/foo` => `/foo` as well as `#/foo#bar` => `/foo#bar`.
-
- By convention, hashed paths must begin with a forward slash, otherwise they
- are not treated as a path so we can distinguish intent.
-
- @private
- @method getURL
- */
- getURL: function() {
- var originalPath = this.getHash().substr(1);
- var outPath = originalPath;
-
- if (outPath.charAt(0) !== '/') {
- outPath = '/';
-
- // Only add the # if the path isn't empty.
- // We do NOT want `/#` since the ampersand
- // is only included (conventionally) when
- // the location.hash has a value
- if (originalPath) {
- outPath += '#' + originalPath;
- }
- }
-
- return outPath;
- },
-
- /**
- Set the `location.hash` and remembers what was set. This prevents
- `onUpdateURL` callbacks from triggering when the hash was set by
- `HashLocation`.
-
- @private
- @method setURL
- @param path {String}
- */
- setURL: function(path) {
- get(this, 'location').hash = path;
- set(this, 'lastSetURL', path);
- },
-
- /**
- Uses location.replace to update the url without a page reload
- or history modification.
-
- @private
- @method replaceURL
- @param path {String}
- */
- replaceURL: function(path) {
- get(this, 'location').replace('#' + path);
- set(this, 'lastSetURL', path);
- },
-
- /**
- Register a callback to be invoked when the hash changes. These
- callbacks will execute when the user presses the back or forward
- button, but not after `setURL` is invoked.
-
- @private
- @method onUpdateURL
- @param callback {Function}
- */
- onUpdateURL: function(callback) {
- var self = this;
- var guid = guidFor(this);
-
- Ember.$(window).on('hashchange.ember-location-'+guid, function() {
- run(function() {
- var path = self.getURL();
- if (get(self, 'lastSetURL') === path) { return; }
-
- set(self, 'lastSetURL', null);
-
- callback(path);
- });
- });
- },
-
- /**
- Given a URL, formats it to be placed into the page as part
- of an element's `href` attribute.
-
- This is used, for example, when using the {{action}} helper
- to generate a URL based on an event.
-
- @private
- @method formatURL
- @param url {String}
- */
- formatURL: function(url) {
- return '#' + url;
- },
-
- /**
- Cleans up the HashLocation event listener.
-
- @private
- @method willDestroy
- */
- willDestroy: function() {
- var guid = guidFor(this);
-
- Ember.$(window).off('hashchange.ember-location-'+guid);
- }
- });
- });
-enifed("ember-routing/location/history_location",
- ["ember-metal/property_get","ember-metal/property_set","ember-metal/utils","ember-runtime/system/object","ember-routing/location/api","ember-views/system/jquery","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __exports__) {
- "use strict";
- var get = __dependency1__.get;
- var set = __dependency2__.set;
- var guidFor = __dependency3__.guidFor;
-
- var EmberObject = __dependency4__["default"];
- var EmberLocation = __dependency5__["default"];
- var jQuery = __dependency6__["default"];
-
- /**
- @module ember
- @submodule ember-routing
- */
-
- var popstateFired = false;
- var supportsHistoryState = window.history && 'state' in window.history;
-
- /**
- Ember.HistoryLocation implements the location API using the browser's
- history.pushState API.
-
- @class HistoryLocation
- @namespace Ember
- @extends Ember.Object
- */
- __exports__["default"] = EmberObject.extend({
- implementation: 'history',
-
- init: function() {
- set(this, 'location', get(this, 'location') || window.location);
- set(this, 'baseURL', jQuery('base').attr('href') || '');
- },
-
- /**
- Used to set state on first call to setURL
-
- @private
- @method initState
- */
- initState: function() {
- set(this, 'history', get(this, 'history') || window.history);
- this.replaceState(this.formatURL(this.getURL()));
- },
-
- /**
- Will be pre-pended to path upon state change
-
- @property rootURL
- @default '/'
- */
- rootURL: '/',
-
- /**
- Returns the current `location.pathname` without `rootURL` or `baseURL`
-
- @private
- @method getURL
- @return url {String}
- */
- getURL: function() {
- var rootURL = get(this, 'rootURL');
- var location = get(this, 'location');
- var path = location.pathname;
- var baseURL = get(this, 'baseURL');
-
- rootURL = rootURL.replace(/\/$/, '');
- baseURL = baseURL.replace(/\/$/, '');
-
- var url = path.replace(baseURL, '').replace(rootURL, '');
- var search = location.search || '';
-
- url += search;
- url += this.getHash();
-
- return url;
- },
-
- /**
- Uses `history.pushState` to update the url without a page reload.
-
- @private
- @method setURL
- @param path {String}
- */
- setURL: function(path) {
- var state = this.getState();
- path = this.formatURL(path);
-
- if (!state || state.path !== path) {
- this.pushState(path);
- }
- },
-
- /**
- Uses `history.replaceState` to update the url without a page reload
- or history modification.
-
- @private
- @method replaceURL
- @param path {String}
- */
- replaceURL: function(path) {
- var state = this.getState();
- path = this.formatURL(path);
-
- if (!state || state.path !== path) {
- this.replaceState(path);
- }
- },
-
- /**
- Get the current `history.state`. Checks for if a polyfill is
- required and if so fetches this._historyState. The state returned
- from getState may be null if an iframe has changed a window's
- history.
-
- @private
- @method getState
- @return state {Object}
- */
- getState: function() {
- return supportsHistoryState ? get(this, 'history').state : this._historyState;
- },
-
- /**
- Pushes a new state.
-
- @private
- @method pushState
- @param path {String}
- */
- pushState: function(path) {
- var state = { path: path };
-
- get(this, 'history').pushState(state, null, path);
-
- // store state if browser doesn't support `history.state`
- if (!supportsHistoryState) {
- this._historyState = state;
- }
-
- // used for webkit workaround
- this._previousURL = this.getURL();
- },
-
- /**
- Replaces the current state.
-
- @private
- @method replaceState
- @param path {String}
- */
- replaceState: function(path) {
- var state = { path: path };
- get(this, 'history').replaceState(state, null, path);
-
- // store state if browser doesn't support `history.state`
- if (!supportsHistoryState) {
- this._historyState = state;
- }
-
- // used for webkit workaround
- this._previousURL = this.getURL();
- },
-
- /**
- Register a callback to be invoked whenever the browser
- history changes, including using forward and back buttons.
-
- @private
- @method onUpdateURL
- @param callback {Function}
- */
- onUpdateURL: function(callback) {
- var guid = guidFor(this);
- var self = this;
-
- jQuery(window).on('popstate.ember-location-'+guid, function(e) {
- // Ignore initial page load popstate event in Chrome
- if (!popstateFired) {
- popstateFired = true;
- if (self.getURL() === self._previousURL) { return; }
- }
- callback(self.getURL());
- });
- },
-
- /**
- Used when using `{{action}}` helper. The url is always appended to the rootURL.
-
- @private
- @method formatURL
- @param url {String}
- @return formatted url {String}
- */
- formatURL: function(url) {
- var rootURL = get(this, 'rootURL');
- var baseURL = get(this, 'baseURL');
-
- if (url !== '') {
- rootURL = rootURL.replace(/\/$/, '');
- baseURL = baseURL.replace(/\/$/, '');
- } else if(baseURL.match(/^\//) && rootURL.match(/^\//)) {
- baseURL = baseURL.replace(/\/$/, '');
- }
-
- return baseURL + rootURL + url;
- },
-
- /**
- Cleans up the HistoryLocation event listener.
-
- @private
- @method willDestroy
- */
- willDestroy: function() {
- var guid = guidFor(this);
-
- jQuery(window).off('popstate.ember-location-'+guid);
- },
-
- /**
- @private
-
- Returns normalized location.hash
-
- @method getHash
- */
- getHash: EmberLocation._getHash
- });
- });
-enifed("ember-routing/location/none_location",
- ["ember-metal/property_get","ember-metal/property_set","ember-runtime/system/object","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
- "use strict";
- var get = __dependency1__.get;
- var set = __dependency2__.set;
- var EmberObject = __dependency3__["default"];
-
- /**
- @module ember
- @submodule ember-routing
- */
-
- /**
- Ember.NoneLocation does not interact with the browser. It is useful for
- testing, or when you need to manage state with your Router, but temporarily
- don't want it to muck with the URL (for example when you embed your
- application in a larger page).
-
- @class NoneLocation
- @namespace Ember
- @extends Ember.Object
- */
- __exports__["default"] = EmberObject.extend({
- implementation: 'none',
- path: '',
-
- /**
- Returns the current path.
-
- @private
- @method getURL
- @return {String} path
- */
- getURL: function() {
- return get(this, 'path');
- },
-
- /**
- Set the path and remembers what was set. Using this method
- to change the path will not invoke the `updateURL` callback.
-
- @private
- @method setURL
- @param path {String}
- */
- setURL: function(path) {
- set(this, 'path', path);
- },
-
- /**
- Register a callback to be invoked when the path changes. These
- callbacks will execute when the user presses the back or forward
- button, but not after `setURL` is invoked.
-
- @private
- @method onUpdateURL
- @param callback {Function}
- */
- onUpdateURL: function(callback) {
- this.updateCallback = callback;
- },
-
- /**
- Sets the path and calls the `updateURL` callback.
-
- @private
- @method handleURL
- @param callback {Function}
- */
- handleURL: function(url) {
- set(this, 'path', url);
- this.updateCallback(url);
- },
-
- /**
- Given a URL, formats it to be placed into the page as part
- of an element's `href` attribute.
-
- This is used, for example, when using the {{action}} helper
- to generate a URL based on an event.
-
- @private
- @method formatURL
- @param url {String}
- @return {String} url
- */
- formatURL: function(url) {
- // The return value is not overly meaningful, but we do not want to throw
- // errors when test code renders templates containing {{action href=true}}
- // helpers.
- return url;
- }
- });
- });
-enifed("ember-routing/system/cache",
- ["ember-runtime/system/object","exports"],
- function(__dependency1__, __exports__) {
- "use strict";
- var EmberObject = __dependency1__["default"];
-
- __exports__["default"] = EmberObject.extend({
- init: function() {
- this.cache = {};
- },
- has: function(bucketKey) {
- return bucketKey in this.cache;
- },
- stash: function(bucketKey, key, value) {
- var bucket = this.cache[bucketKey];
- if (!bucket) {
- bucket = this.cache[bucketKey] = {};
- }
- bucket[key] = value;
- },
- lookup: function(bucketKey, prop, defaultValue) {
- var cache = this.cache;
- if (!(bucketKey in cache)) {
- return defaultValue;
- }
- var bucket = cache[bucketKey];
- if (prop in bucket) {
- return bucket[prop];
- } else {
- return defaultValue;
- }
- },
- cache: null
- });
- });
-enifed("ember-routing/system/controller_for",
- ["exports"],
- function(__exports__) {
- "use strict";
- /**
- @module ember
- @submodule ember-routing
- */
-
- /**
-
- Finds a controller instance.
-
- @for Ember
- @method controllerFor
- @private
- */
- __exports__["default"] = function controllerFor(container, controllerName, lookupOptions) {
- return container.lookup('controller:' + controllerName, lookupOptions);
- }
- });
-enifed("ember-routing/system/dsl",
- ["ember-metal/core","exports"],
- function(__dependency1__, __exports__) {
- "use strict";
- var Ember = __dependency1__["default"];
- // FEATURES, assert
-
- /**
- @module ember
- @submodule ember-routing
- */
-
- function DSL(name) {
- this.parent = name;
- this.matches = [];
- }
- __exports__["default"] = DSL;
-
- DSL.prototype = {
- route: function(name, options, callback) {
- if (arguments.length === 2 && typeof options === 'function') {
- callback = options;
- options = {};
- }
-
- if (arguments.length === 1) {
- options = {};
- }
-
- var type = options.resetNamespace === true ? 'resource' : 'route';
- Ember.assert("'basic' cannot be used as a " + type + " name.", name !== 'basic');
-
-
- if (callback) {
- var fullName = getFullName(this, name, options.resetNamespace);
- var dsl = new DSL(fullName);
- createRoute(dsl, 'loading');
- createRoute(dsl, 'error', { path: "/_unused_dummy_error_path_route_" + name + "/:error" });
-
- callback.call(dsl);
-
- createRoute(this, name, options, dsl.generate());
- } else {
- createRoute(this, name, options);
- }
- },
-
- push: function(url, name, callback) {
- var parts = name.split('.');
- if (url === "" || url === "/" || parts[parts.length-1] === "index") { this.explicitIndex = true; }
-
- this.matches.push([url, name, callback]);
- },
-
- resource: function(name, options, callback) {
- if (arguments.length === 2 && typeof options === 'function') {
- callback = options;
- options = {};
- }
-
- if (arguments.length === 1) {
- options = {};
- }
-
- options.resetNamespace = true;
- this.route(name, options, callback);
- },
-
- generate: function() {
- var dslMatches = this.matches;
-
- if (!this.explicitIndex) {
- this.route("index", { path: "/" });
- }
-
- return function(match) {
- for (var i=0, l=dslMatches.length; i<l; i++) {
- var dslMatch = dslMatches[i];
- match(dslMatch[0]).to(dslMatch[1], dslMatch[2]);
- }
- };
- }
- };
-
- function canNest(dsl) {
- return dsl.parent && dsl.parent !== 'application';
- }
-
- function getFullName(dsl, name, resetNamespace) {
- if (canNest(dsl) && resetNamespace !== true) {
- return dsl.parent + "." + name;
- } else {
- return name;
- }
- }
-
- function createRoute(dsl, name, options, callback) {
- options = options || {};
-
- var fullName = getFullName(dsl, name, options.resetNamespace);
-
- if (typeof options.path !== 'string') {
- options.path = "/" + name;
- }
-
- dsl.push(options.path, fullName, callback);
- }
-
- DSL.map = function(callback) {
- var dsl = new DSL();
- callback.call(dsl);
- return dsl;
- };
- });
-enifed("ember-routing/system/generate_controller",
- ["ember-metal/core","ember-metal/property_get","ember-metal/utils","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
- "use strict";
- var Ember = __dependency1__["default"];
- // Logger
- var get = __dependency2__.get;
- var isArray = __dependency3__.isArray;
-
- /**
- @module ember
- @submodule ember-routing
- */
-
- /**
- Generates a controller factory
-
- The type of the generated controller factory is derived
- from the context. If the context is an array an array controller
- is generated, if an object, an object controller otherwise, a basic
- controller is generated.
-
- You can customize your generated controllers by defining
- `App.ObjectController` or `App.ArrayController`.
-
- @for Ember
- @method generateControllerFactory
- @private
- */
-
- function generateControllerFactory(container, controllerName, context) {
- var Factory, fullName, factoryName, controllerType;
-
- if (context && isArray(context)) {
- controllerType = 'array';
- } else if (context) {
- controllerType = 'object';
- } else {
- controllerType = 'basic';
- }
-
- factoryName = 'controller:' + controllerType;
-
- Factory = container.lookupFactory(factoryName).extend({
- isGenerated: true,
- toString: function() {
- return "(generated " + controllerName + " controller)";
- }
- });
-
- fullName = 'controller:' + controllerName;
-
- container.register(fullName, Factory);
-
- return Factory;
- }
-
- __exports__.generateControllerFactory = generateControllerFactory;/**
- Generates and instantiates a controller.
-
- The type of the generated controller factory is derived
- from the context. If the context is an array an array controller
- is generated, if an object, an object controller otherwise, a basic
- controller is generated.
-
- @for Ember
- @method generateController
- @private
- @since 1.3.0
- */
- __exports__["default"] = function generateController(container, controllerName, context) {
- generateControllerFactory(container, controllerName, context);
- var fullName = 'controller:' + controllerName;
- var instance = container.lookup(fullName);
-
- if (get(instance, 'namespace.LOG_ACTIVE_GENERATION')) {
- Ember.Logger.info("generated -> " + fullName, { fullName: fullName });
- }
-
- return instance;
- }
- });
-enifed("ember-routing/system/route",
- ["ember-metal/core","ember-metal/error","ember-metal/property_get","ember-metal/property_set","ember-metal/get_properties","ember-metal/enumerable_utils","ember-metal/is_none","ember-metal/computed","ember-metal/merge","ember-metal/utils","ember-metal/run_loop","ember-metal/keys","ember-runtime/copy","ember-runtime/system/string","ember-runtime/system/object","ember-runtime/mixins/evented","ember-runtime/mixins/action_handler","ember-routing/system/generate_controller","ember-routing/utils","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __dependency15__, __dependency16__, __dependency17__, __dependency18__, __dependency19__, __exports__) {
- "use strict";
- var Ember = __dependency1__["default"];
- // FEATURES, K, A, deprecate, assert, Logger
- var EmberError = __dependency2__["default"];
- var get = __dependency3__.get;
- var set = __dependency4__.set;
- var getProperties = __dependency5__["default"];
- var forEach = __dependency6__.forEach;
- var replace = __dependency6__.replace;
- var isNone = __dependency7__["default"];
- var computed = __dependency8__.computed;
- var merge = __dependency9__["default"];
- var isArray = __dependency10__.isArray;
- var typeOf = __dependency10__.typeOf;
- var run = __dependency11__["default"];
- var keys = __dependency12__["default"];
- var copy = __dependency13__["default"];
- var classify = __dependency14__.classify;
- var EmberObject = __dependency15__["default"];
- var Evented = __dependency16__["default"];
- var ActionHandler = __dependency17__["default"];
- var generateController = __dependency18__["default"];
- var stashParamNames = __dependency19__.stashParamNames;
-
- var slice = Array.prototype.slice;
-
- /**
- @module ember
- @submodule ember-routing
- */
-
- /**
- The `Ember.Route` class is used to define individual routes. Refer to
- the [routing guide](http://emberjs.com/guides/routing/) for documentation.
-
- @class Route
- @namespace Ember
- @extends Ember.Object
- @uses Ember.ActionHandler
- */
- var Route = EmberObject.extend(ActionHandler, {
- /**
- Configuration hash for this route's queryParams. The possible
- configuration options and their defaults are as follows
- (assuming a query param whose URL key is `page`):
-
- ```javascript
- queryParams: {
- page: {
- // By default, controller query param properties don't
- // cause a full transition when they are changed, but
- // rather only cause the URL to update. Setting
- // `refreshModel` to true will cause an "in-place"
- // transition to occur, whereby the model hooks for
- // this route (and any child routes) will re-fire, allowing
- // you to reload models (e.g., from the server) using the
- // updated query param values.
- refreshModel: false,
-
- // By default, changes to controller query param properties
- // cause the URL to update via `pushState`, which means an
- // item will be added to the browser's history, allowing
- // you to use the back button to restore the app to the
- // previous state before the query param property was changed.
- // Setting `replace` to true will use `replaceState` (or its
- // hash location equivalent), which causes no browser history
- // item to be added. This options name and default value are
- // the same as the `link-to` helper's `replace` option.
- replace: false
- }
- }
- ```
-
- @property queryParams
- @for Ember.Route
- @type Hash
- */
- queryParams: {},
-
- /**
- @private
-
- @property _qp
- */
- _qp: computed(function() {
- var controllerName = this.controllerName || this.routeName;
- var controllerClass = this.container.lookupFactory('controller:' + controllerName);
-
- if (!controllerClass) {
- return defaultQPMeta;
- }
-
- var controllerProto = controllerClass.proto();
- var qpProps = get(controllerProto, '_normalizedQueryParams');
- var cacheMeta = get(controllerProto, '_cacheMeta');
-
- var qps = [], map = {}, self = this;
- for (var propName in qpProps) {
- if (!qpProps.hasOwnProperty(propName)) { continue; }
-
- var desc = qpProps[propName];
- var urlKey = desc.as || this.serializeQueryParamKey(propName);
- var defaultValue = get(controllerProto, propName);
-
- if (isArray(defaultValue)) {
- defaultValue = Ember.A(defaultValue.slice());
- }
-
- var type = typeOf(defaultValue);
- var defaultValueSerialized = this.serializeQueryParam(defaultValue, urlKey, type);
- var fprop = controllerName + ':' + propName;
- var qp = {
- def: defaultValue,
- sdef: defaultValueSerialized,
- type: type,
- urlKey: urlKey,
- prop: propName,
- fprop: fprop,
- ctrl: controllerName,
- cProto: controllerProto,
- svalue: defaultValueSerialized,
- cacheType: desc.scope,
- route: this,
- cacheMeta: cacheMeta[propName]
- };
-
- map[propName] = map[urlKey] = map[fprop] = qp;
- qps.push(qp);
- }
-
- return {
- qps: qps,
- map: map,
- states: {
- active: function(controller, prop) {
- return self._activeQPChanged(controller, map[prop]);
- },
- allowOverrides: function(controller, prop) {
- return self._updatingQPChanged(controller, map[prop]);
- },
- changingKeys: function(controller, prop) {
- return self._updateSerializedQPValue(controller, map[prop]);
- }
- }
- };
- }),
-
- /**
- @private
-
- @property _names
- */
- _names: null,
-
- /**
- @private
-
- @method _stashNames
- */
- _stashNames: function(_handlerInfo, dynamicParent) {
- var handlerInfo = _handlerInfo;
- if (this._names) { return; }
- var names = this._names = handlerInfo._names;
-
- if (!names.length) {
- handlerInfo = dynamicParent;
- names = handlerInfo && handlerInfo._names || [];
- }
-
- var qps = get(this, '_qp.qps');
- var len = qps.length;
-
- var namePaths = new Array(names.length);
- for (var a = 0, nlen = names.length; a < nlen; ++a) {
- namePaths[a] = handlerInfo.name + '.' + names[a];
- }
-
- for (var i = 0; i < len; ++i) {
- var qp = qps[i];
- var cacheMeta = qp.cacheMeta;
- if (cacheMeta.scope === 'model') {
- cacheMeta.parts = namePaths;
- }
- cacheMeta.prefix = qp.ctrl;
- }
- },
-
- /**
- @private
-
- @property _updateSerializedQPValue
- */
- _updateSerializedQPValue: function(controller, qp) {
- var value = get(controller, qp.prop);
- qp.svalue = this.serializeQueryParam(value, qp.urlKey, qp.type);
- },
-
- /**
- @private
-
- @property _activeQPChanged
- */
- _activeQPChanged: function(controller, qp) {
- var value = get(controller, qp.prop);
- this.router._queuedQPChanges[qp.fprop] = value;
- run.once(this, this._fireQueryParamTransition);
- },
-
- /**
- @private
- @method _updatingQPChanged
- */
- _updatingQPChanged: function(controller, qp) {
- var router = this.router;
- if (!router._qpUpdates) {
- router._qpUpdates = {};
- }
- router._qpUpdates[qp.urlKey] = true;
- },
-
- mergedProperties: ['events', 'queryParams'],
-
- /**
- Retrieves parameters, for current route using the state.params
- variable and getQueryParamsFor, using the supplied routeName.
-
- @method paramsFor
- @param {String} routename
-
- */
- paramsFor: function(name) {
- var route = this.container.lookup('route:' + name);
-
- if (!route) {
- return {};
- }
-
- var transition = this.router.router.activeTransition;
- var state = transition ? transition.state : this.router.router.state;
-
- var params = {};
- merge(params, state.params[name]);
- merge(params, getQueryParamsFor(route, state));
-
- return params;
- },
-
- /**
- Serializes the query parameter key
-
- @method serializeQueryParamKey
- @param {String} controllerPropertyName
- */
- serializeQueryParamKey: function(controllerPropertyName) {
- return controllerPropertyName;
- },
-
- /**
- Serializes value of the query parameter based on defaultValueType
-
- @method serializeQueryParam
- @param {Object} value
- @param {String} urlKey
- @param {String} defaultValueType
- */
- serializeQueryParam: function(value, urlKey, defaultValueType) {
- // urlKey isn't used here, but anyone overriding
- // can use it to provide serialization specific
- // to a certain query param.
- if (defaultValueType === 'array') {
- return JSON.stringify(value);
- }
- return '' + value;
- },
-
- /**
- Deserializes value of the query parameter based on defaultValueType
-
- @method deserializeQueryParam
- @param {Object} value
- @param {String} urlKey
- @param {String} defaultValueType
- */
- deserializeQueryParam: function(value, urlKey, defaultValueType) {
- // urlKey isn't used here, but anyone overriding
- // can use it to provide deserialization specific
- // to a certain query param.
-
- // Use the defaultValueType of the default value (the initial value assigned to a
- // controller query param property), to intelligently deserialize and cast.
- if (defaultValueType === 'boolean') {
- return (value === 'true') ? true : false;
- } else if (defaultValueType === 'number') {
- return (Number(value)).valueOf();
- } else if (defaultValueType === 'array') {
- return Ember.A(JSON.parse(value));
- }
- return value;
- },
-
-
- /**
- @private
- @property _fireQueryParamTransition
- */
- _fireQueryParamTransition: function() {
- this.transitionTo({ queryParams: this.router._queuedQPChanges });
- this.router._queuedQPChanges = {};
- },
-
- /**
- @private
-
- @property _optionsForQueryParam
- */
- _optionsForQueryParam: function(qp) {
- return get(this, 'queryParams.' + qp.urlKey) || get(this, 'queryParams.' + qp.prop) || {};
- },
-
- /**
- A hook you can use to reset controller values either when the model
- changes or the route is exiting.
-
- ```javascript
- App.ArticlesRoute = Ember.Route.extend({
- // ...
-
- resetController: function (controller, isExiting, transition) {
- if (isExiting) {
- controller.set('page', 1);
- }
- }
- });
- ```
-
- @method resetController
- @param {Controller} controller instance
- @param {Boolean} isExiting
- @param {Object} transition
- @since 1.7.0
- */
- resetController: Ember.K,
-
- /**
- @private
-
- @method exit
- */
- exit: function() {
- this.deactivate();
-
- this.trigger('deactivate');
-
- this.teardownViews();
- },
-
- /**
- @private
-
- @method _reset
- @since 1.7.0
- */
- _reset: function(isExiting, transition) {
- var controller = this.controller;
-
- controller._qpDelegate = get(this, '_qp.states.inactive');
-
- this.resetController(controller, isExiting, transition);
- },
-
- /**
- @private
-
- @method enter
- */
- enter: function() {
- this.activate();
-
- this.trigger('activate');
-
- },
-
- /**
- The name of the view to use by default when rendering this routes template.
-
- When rendering a template, the route will, by default, determine the
- template and view to use from the name of the route itself. If you need to
- define a specific view, set this property.
-
- This is useful when multiple routes would benefit from using the same view
- because it doesn't require a custom `renderTemplate` method. For example,
- the following routes will all render using the `App.PostsListView` view:
-
- ```javascript
- var PostsList = Ember.Route.extend({
- viewName: 'postsList'
- });
-
- App.PostsIndexRoute = PostsList.extend();
- App.PostsArchivedRoute = PostsList.extend();
- ```
-
- @property viewName
- @type String
- @default null
- @since 1.4.0
- */
- viewName: null,
-
- /**
- The name of the template to use by default when rendering this routes
- template.
-
- This is similar with `viewName`, but is useful when you just want a custom
- template without a view.
-
- ```javascript
- var PostsList = Ember.Route.extend({
- templateName: 'posts/list'
- });
-
- App.PostsIndexRoute = PostsList.extend();
- App.PostsArchivedRoute = PostsList.extend();
- ```
-
- @property templateName
- @type String
- @default null
- @since 1.4.0
- */
- templateName: null,
-
- /**
- The name of the controller to associate with this route.
-
- By default, Ember will lookup a route's controller that matches the name
- of the route (i.e. `App.PostController` for `App.PostRoute`). However,
- if you would like to define a specific controller to use, you can do so
- using this property.
-
- This is useful in many ways, as the controller specified will be:
-
- * passed to the `setupController` method.
- * used as the controller for the view being rendered by the route.
- * returned from a call to `controllerFor` for the route.
-
- @property controllerName
- @type String
- @default null
- @since 1.4.0
- */
- controllerName: null,
-
- /**
- The `willTransition` action is fired at the beginning of any
- attempted transition with a `Transition` object as the sole
- argument. This action can be used for aborting, redirecting,
- or decorating the transition from the currently active routes.
-
- A good example is preventing navigation when a form is
- half-filled out:
-
- ```javascript
- App.ContactFormRoute = Ember.Route.extend({
- actions: {
- willTransition: function(transition) {
- if (this.controller.get('userHasEnteredData')) {
- this.controller.displayNavigationConfirm();
- transition.abort();
- }
- }
- }
- });
- ```
-
- You can also redirect elsewhere by calling
- `this.transitionTo('elsewhere')` from within `willTransition`.
- Note that `willTransition` will not be fired for the
- redirecting `transitionTo`, since `willTransition` doesn't
- fire when there is already a transition underway. If you want
- subsequent `willTransition` actions to fire for the redirecting
- transition, you must first explicitly call
- `transition.abort()`.
-
- @event willTransition
- @param {Transition} transition
- */
-
- /**
- The `didTransition` action is fired after a transition has
- successfully been completed. This occurs after the normal model
- hooks (`beforeModel`, `model`, `afterModel`, `setupController`)
- have resolved. The `didTransition` action has no arguments,
- however, it can be useful for tracking page views or resetting
- state on the controller.
-
- ```javascript
- App.LoginRoute = Ember.Route.extend({
- actions: {
- didTransition: function() {
- this.controller.get('errors.base').clear();
- return true; // Bubble the didTransition event
- }
- }
- });
- ```
-
- @event didTransition
- @since 1.2.0
- */
-
- /**
- The `loading` action is fired on the route when a route's `model`
- hook returns a promise that is not already resolved. The current
- `Transition` object is the first parameter and the route that
- triggered the loading event is the second parameter.
-
- ```javascript
- App.ApplicationRoute = Ember.Route.extend({
- actions: {
- loading: function(transition, route) {
- var view = Ember.View.create({
- classNames: ['app-loading']
- })
- .append();
-
- this.router.one('didTransition', function() {
- view.destroy();
- });
-
- return true; // Bubble the loading event
- }
- }
- });
- ```
-
- @event loading
- @param {Transition} transition
- @param {Ember.Route} route The route that triggered the loading event
- @since 1.2.0
- */
-
- /**
- When attempting to transition into a route, any of the hooks
- may return a promise that rejects, at which point an `error`
- action will be fired on the partially-entered routes, allowing
- for per-route error handling logic, or shared error handling
- logic defined on a parent route.
-
- Here is an example of an error handler that will be invoked
- for rejected promises from the various hooks on the route,
- as well as any unhandled errors from child routes:
-
- ```javascript
- App.AdminRoute = Ember.Route.extend({
- beforeModel: function() {
- return Ember.RSVP.reject('bad things!');
- },
-
- actions: {
- error: function(error, transition) {
- // Assuming we got here due to the error in `beforeModel`,
- // we can expect that error === "bad things!",
- // but a promise model rejecting would also
- // call this hook, as would any errors encountered
- // in `afterModel`.
-
- // The `error` hook is also provided the failed
- // `transition`, which can be stored and later
- // `.retry()`d if desired.
-
- this.transitionTo('login');
- }
- }
- });
- ```
-
- `error` actions that bubble up all the way to `ApplicationRoute`
- will fire a default error handler that logs the error. You can
- specify your own global default error handler by overriding the
- `error` handler on `ApplicationRoute`:
-
- ```javascript
- App.ApplicationRoute = Ember.Route.extend({
- actions: {
- error: function(error, transition) {
- this.controllerFor('banner').displayError(error.message);
- }
- }
- });
- ```
- @event error
- @param {Error} error
- @param {Transition} transition
- */
-
- /**
- The controller associated with this route.
-
- Example
-
- ```javascript
- App.FormRoute = Ember.Route.extend({
- actions: {
- willTransition: function(transition) {
- if (this.controller.get('userHasEnteredData') &&
- !confirm('Are you sure you want to abandon progress?')) {
- transition.abort();
- } else {
- // Bubble the `willTransition` action so that
- // parent routes can decide whether or not to abort.
- return true;
- }
- }
- }
- });
- ```
-
- @property controller
- @type Ember.Controller
- @since 1.6.0
- */
-
- _actions: {
-
- queryParamsDidChange: function(changed, totalPresent, removed) {
- var qpMap = this.get('_qp').map;
-
- var totalChanged = keys(changed).concat(keys(removed));
- for (var i = 0, len = totalChanged.length; i < len; ++i) {
- var qp = qpMap[totalChanged[i]];
- if (qp && get(this._optionsForQueryParam(qp), 'refreshModel')) {
- this.refresh();
- }
- }
-
- return true;
- },
-
- finalizeQueryParamChange: function(params, finalParams, transition) {
- if (this.routeName !== 'application') { return true; }
-
- // Transition object is absent for intermediate transitions.
- if (!transition) { return; }
-
- var handlerInfos = transition.state.handlerInfos;
- var router = this.router;
- var qpMeta = router._queryParamsFor(handlerInfos[handlerInfos.length-1].name);
- var changes = router._qpUpdates;
- var replaceUrl;
-
- stashParamNames(router, handlerInfos);
-
- for (var i = 0, len = qpMeta.qps.length; i < len; ++i) {
- var qp = qpMeta.qps[i];
- var route = qp.route;
- var controller = route.controller;
- var presentKey = qp.urlKey in params && qp.urlKey;
-
- // Do a reverse lookup to see if the changed query
- // param URL key corresponds to a QP property on
- // this controller.
- var value, svalue;
- if (changes && qp.urlKey in changes) {
- // Value updated in/before setupController
- value = get(controller, qp.prop);
- svalue = route.serializeQueryParam(value, qp.urlKey, qp.type);
- } else {
- if (presentKey) {
- svalue = params[presentKey];
- value = route.deserializeQueryParam(svalue, qp.urlKey, qp.type);
- } else {
- // No QP provided; use default value.
- svalue = qp.sdef;
- value = copyDefaultValue(qp.def);
- }
- }
-
- controller._qpDelegate = get(this, '_qp.states.inactive');
-
- var thisQueryParamChanged = (svalue !== qp.svalue);
- if (thisQueryParamChanged) {
- if (transition.queryParamsOnly && replaceUrl !== false) {
- var options = route._optionsForQueryParam(qp);
- var replaceConfigValue = get(options, 'replace');
- if (replaceConfigValue) {
- replaceUrl = true;
- } else if (replaceConfigValue === false) {
- // Explicit pushState wins over any other replaceStates.
- replaceUrl = false;
- }
- }
-
- set(controller, qp.prop, value);
- }
-
- // Stash current serialized value of controller.
- qp.svalue = svalue;
-
- var thisQueryParamHasDefaultValue = (qp.sdef === svalue);
- if (!thisQueryParamHasDefaultValue) {
- finalParams.push({
- value: svalue,
- visible: true,
- key: presentKey || qp.urlKey
- });
- }
- }
-
- if (replaceUrl) {
- transition.method('replace');
- }
-
- forEach(qpMeta.qps, function(qp) {
- var routeQpMeta = get(qp.route, '_qp');
- var finalizedController = qp.route.controller;
- finalizedController._qpDelegate = get(routeQpMeta, 'states.active');
- });
-
- router._qpUpdates = null;
- }
- },
-
- /**
- @deprecated
-
- Please use `actions` instead.
- @method events
- */
- events: null,
-
- /**
- This hook is executed when the router completely exits this route. It is
- not executed when the model for the route changes.
-
- @method deactivate
- */
- deactivate: Ember.K,
-
- /**
- This hook is executed when the router enters the route. It is not executed
- when the model for the route changes.
-
- @method activate
- */
- activate: Ember.K,
-
- /**
- Transition the application into another route. The route may
- be either a single route or route path:
-
- ```javascript
- this.transitionTo('blogPosts');
- this.transitionTo('blogPosts.recentEntries');
- ```
-
- Optionally supply a model for the route in question. The model
- will be serialized into the URL using the `serialize` hook of
- the route:
-
- ```javascript
- this.transitionTo('blogPost', aPost);
- ```
-
- If a literal is passed (such as a number or a string), it will
- be treated as an identifier instead. In this case, the `model`
- hook of the route will be triggered:
-
- ```javascript
- this.transitionTo('blogPost', 1);
- ```
-
- Multiple models will be applied last to first recursively up the
- resource tree.
-
- ```javascript
- App.Router.map(function() {
- this.resource('blogPost', { path:':blogPostId' }, function() {
- this.resource('blogComment', { path: ':blogCommentId' });
- });
- });
-
- this.transitionTo('blogComment', aPost, aComment);
- this.transitionTo('blogComment', 1, 13);
- ```
-
- It is also possible to pass a URL (a string that starts with a
- `/`). This is intended for testing and debugging purposes and
- should rarely be used in production code.
-
- ```javascript
- this.transitionTo('/');
- this.transitionTo('/blog/post/1/comment/13');
- ```
-
- See also 'replaceWith'.
-
- Simple Transition Example
-
- ```javascript
- App.Router.map(function() {
- this.route('index');
- this.route('secret');
- this.route('fourOhFour', { path: '*:' });
- });
-
- App.IndexRoute = Ember.Route.extend({
- actions: {
- moveToSecret: function(context) {
- if (authorized()) {
- this.transitionTo('secret', context);
- } else {
- this.transitionTo('fourOhFour');
- }
- }
- }
- });
- ```
-
- Transition to a nested route
-
- ```javascript
- App.Router.map(function() {
- this.resource('articles', { path: '/articles' }, function() {
- this.route('new');
- });
- });
-
- App.IndexRoute = Ember.Route.extend({
- actions: {
- transitionToNewArticle: function() {
- this.transitionTo('articles.new');
- }
- }
- });
- ```
-
- Multiple Models Example
-
- ```javascript
- App.Router.map(function() {
- this.route('index');
-
- this.resource('breakfast', { path: ':breakfastId' }, function() {
- this.resource('cereal', { path: ':cerealId' });
- });
- });
-
- App.IndexRoute = Ember.Route.extend({
- actions: {
- moveToChocolateCereal: function() {
- var cereal = { cerealId: 'ChocolateYumminess' };
- var breakfast = { breakfastId: 'CerealAndMilk' };
-
- this.transitionTo('cereal', breakfast, cereal);
- }
- }
- });
- ```
-
- @method transitionTo
- @param {String} name the name of the route or a URL
- @param {...Object} models the model(s) or identifier(s) to be used while
- transitioning to the route.
- @return {Transition} the transition object associated with this
- attempted transition
- */
- transitionTo: function(name, context) {
- var router = this.router;
- return router.transitionTo.apply(router, arguments);
- },
-
- /**
- Perform a synchronous transition into another route without attempting
- to resolve promises, update the URL, or abort any currently active
- asynchronous transitions (i.e. regular transitions caused by
- `transitionTo` or URL changes).
-
- This method is handy for performing intermediate transitions on the
- way to a final destination route, and is called internally by the
- default implementations of the `error` and `loading` handlers.
-
- @method intermediateTransitionTo
- @param {String} name the name of the route
- @param {...Object} models the model(s) to be used while transitioning
- to the route.
- @since 1.2.0
- */
- intermediateTransitionTo: function() {
- var router = this.router;
- router.intermediateTransitionTo.apply(router, arguments);
- },
-
- /**
- Refresh the model on this route and any child routes, firing the
- `beforeModel`, `model`, and `afterModel` hooks in a similar fashion
- to how routes are entered when transitioning in from other route.
- The current route params (e.g. `article_id`) will be passed in
- to the respective model hooks, and if a different model is returned,
- `setupController` and associated route hooks will re-fire as well.
-
- An example usage of this method is re-querying the server for the
- latest information using the same parameters as when the route
- was first entered.
-
- Note that this will cause `model` hooks to fire even on routes
- that were provided a model object when the route was initially
- entered.
-
- @method refresh
- @return {Transition} the transition object associated with this
- attempted transition
- @since 1.4.0
- */
- refresh: function() {
- return this.router.router.refresh(this);
- },
-
- /**
- Transition into another route while replacing the current URL, if possible.
- This will replace the current history entry instead of adding a new one.
- Beside that, it is identical to `transitionTo` in all other respects. See
- 'transitionTo' for additional information regarding multiple models.
-
- Example
-
- ```javascript
- App.Router.map(function() {
- this.route('index');
- this.route('secret');
- });
-
- App.SecretRoute = Ember.Route.extend({
- afterModel: function() {
- if (!authorized()){
- this.replaceWith('index');
- }
- }
- });
- ```
-
- @method replaceWith
- @param {String} name the name of the route or a URL
- @param {...Object} models the model(s) or identifier(s) to be used while
- transitioning to the route.
- @return {Transition} the transition object associated with this
- attempted transition
- */
- replaceWith: function() {
- var router = this.router;
- return router.replaceWith.apply(router, arguments);
- },
-
- /**
- Sends an action to the router, which will delegate it to the currently
- active route hierarchy per the bubbling rules explained under `actions`.
-
- Example
-
- ```javascript
- App.Router.map(function() {
- this.route("index");
- });
-
- App.ApplicationRoute = Ember.Route.extend({
- actions: {
- track: function(arg) {
- console.log(arg, 'was clicked');
- }
- }
- });
-
- App.IndexRoute = Ember.Route.extend({
- actions: {
- trackIfDebug: function(arg) {
- if (debug) {
- this.send('track', arg);
- }
- }
- }
- });
- ```
-
- @method send
- @param {String} name the name of the action to trigger
- @param {...*} args
- */
- send: function() {
- if (this.router || !Ember.testing) {
- this.router.send.apply(this.router, arguments);
- } else {
- var name = arguments[0];
- var args = slice.call(arguments, 1);
- var action = this._actions[name];
- if (action) {
- return this._actions[name].apply(this, args);
- }
- }
- },
-
- /**
- This hook is the entry point for router.js
-
- @private
- @method setup
- */
- setup: function(context, transition) {
- var controllerName = this.controllerName || this.routeName;
- var controller = this.controllerFor(controllerName, true);
-
- if (!controller) {
- controller = this.generateController(controllerName, context);
- }
-
- // Assign the route's controller so that it can more easily be
- // referenced in action handlers
- this.controller = controller;
-
- if (this.setupControllers) {
- Ember.deprecate("Ember.Route.setupControllers is deprecated. Please use Ember.Route.setupController(controller, model) instead.");
- this.setupControllers(controller, context);
- } else {
- var states = get(this, '_qp.states');
- if (transition) {
- // Update the model dep values used to calculate cache keys.
- stashParamNames(this.router, transition.state.handlerInfos);
- controller._qpDelegate = states.changingKeys;
- controller._updateCacheParams(transition.params);
- }
- controller._qpDelegate = states.allowOverrides;
-
- if (transition) {
- var qpValues = getQueryParamsFor(this, transition.state);
- controller.setProperties(qpValues);
- }
-
- this.setupController(controller, context, transition);
- }
-
- if (this.renderTemplates) {
- Ember.deprecate("Ember.Route.renderTemplates is deprecated. Please use Ember.Route.renderTemplate(controller, model) instead.");
- this.renderTemplates(context);
- } else {
- this.renderTemplate(controller, context);
- }
- },
-
- /**
- This hook is the first of the route entry validation hooks
- called when an attempt is made to transition into a route
- or one of its children. It is called before `model` and
- `afterModel`, and is appropriate for cases when:
-
- 1) A decision can be made to redirect elsewhere without
- needing to resolve the model first.
- 2) Any async operations need to occur first before the
- model is attempted to be resolved.
-
- This hook is provided the current `transition` attempt
- as a parameter, which can be used to `.abort()` the transition,
- save it for a later `.retry()`, or retrieve values set
- on it from a previous hook. You can also just call
- `this.transitionTo` to another route to implicitly
- abort the `transition`.
-
- You can return a promise from this hook to pause the
- transition until the promise resolves (or rejects). This could
- be useful, for instance, for retrieving async code from
- the server that is required to enter a route.
-
- ```javascript
- App.PostRoute = Ember.Route.extend({
- beforeModel: function(transition) {
- if (!App.Post) {
- return Ember.$.getScript('/models/post.js');
- }
- }
- });
- ```
-
- If `App.Post` doesn't exist in the above example,
- `beforeModel` will use jQuery's `getScript`, which
- returns a promise that resolves after the server has
- successfully retrieved and executed the code from the
- server. Note that if an error were to occur, it would
- be passed to the `error` hook on `Ember.Route`, but
- it's also possible to handle errors specific to
- `beforeModel` right from within the hook (to distinguish
- from the shared error handling behavior of the `error`
- hook):
-
- ```javascript
- App.PostRoute = Ember.Route.extend({
- beforeModel: function(transition) {
- if (!App.Post) {
- var self = this;
- return Ember.$.getScript('post.js').then(null, function(e) {
- self.transitionTo('help');
-
- // Note that the above transitionTo will implicitly
- // halt the transition. If you were to return
- // nothing from this promise reject handler,
- // according to promise semantics, that would
- // convert the reject into a resolve and the
- // transition would continue. To propagate the
- // error so that it'd be handled by the `error`
- // hook, you would have to either
- return Ember.RSVP.reject(e);
- });
- }
- }
- });
- ```
-
- @method beforeModel
- @param {Transition} transition
- @param {Object} queryParams the active query params for this route
- @return {Promise} if the value returned from this hook is
- a promise, the transition will pause until the transition
- resolves. Otherwise, non-promise return values are not
- utilized in any way.
- */
- beforeModel: Ember.K,
-
- /**
- This hook is called after this route's model has resolved.
- It follows identical async/promise semantics to `beforeModel`
- but is provided the route's resolved model in addition to
- the `transition`, and is therefore suited to performing
- logic that can only take place after the model has already
- resolved.
-
- ```javascript
- App.PostsRoute = Ember.Route.extend({
- afterModel: function(posts, transition) {
- if (posts.get('length') === 1) {
- this.transitionTo('post.show', posts.get('firstObject'));
- }
- }
- });
- ```
-
- Refer to documentation for `beforeModel` for a description
- of transition-pausing semantics when a promise is returned
- from this hook.
-
- @method afterModel
- @param {Object} resolvedModel the value returned from `model`,
- or its resolved value if it was a promise
- @param {Transition} transition
- @param {Object} queryParams the active query params for this handler
- @return {Promise} if the value returned from this hook is
- a promise, the transition will pause until the transition
- resolves. Otherwise, non-promise return values are not
- utilized in any way.
- */
- afterModel: Ember.K,
-
- /**
- A hook you can implement to optionally redirect to another route.
-
- If you call `this.transitionTo` from inside of this hook, this route
- will not be entered in favor of the other hook.
-
- `redirect` and `afterModel` behave very similarly and are
- called almost at the same time, but they have an important
- distinction in the case that, from one of these hooks, a
- redirect into a child route of this route occurs: redirects
- from `afterModel` essentially invalidate the current attempt
- to enter this route, and will result in this route's `beforeModel`,
- `model`, and `afterModel` hooks being fired again within
- the new, redirecting transition. Redirects that occur within
- the `redirect` hook, on the other hand, will _not_ cause
- these hooks to be fired again the second time around; in
- other words, by the time the `redirect` hook has been called,
- both the resolved model and attempted entry into this route
- are considered to be fully validated.
-
- @method redirect
- @param {Object} model the model for this route
- @param {Transition} transition the transition object associated with the current transition
- */
- redirect: Ember.K,
-
- /**
- Called when the context is changed by router.js.
-
- @private
- @method contextDidChange
- */
- contextDidChange: function() {
- this.currentModel = this.context;
- },
-
- /**
- A hook you can implement to convert the URL into the model for
- this route.
-
- ```javascript
- App.Router.map(function() {
- this.resource('post', { path: '/posts/:post_id' });
- });
- ```
-
- The model for the `post` route is `store.find('post', params.post_id)`.
-
- By default, if your route has a dynamic segment ending in `_id`:
-
- * The model class is determined from the segment (`post_id`'s
- class is `App.Post`)
- * The find method is called on the model class with the value of
- the dynamic segment.
-
- Note that for routes with dynamic segments, this hook is not always
- executed. If the route is entered through a transition (e.g. when
- using the `link-to` Handlebars helper or the `transitionTo` method
- of routes), and a model context is already provided this hook
- is not called.
-
- A model context does not include a primitive string or number,
- which does cause the model hook to be called.
-
- Routes without dynamic segments will always execute the model hook.
-
- ```javascript
- // no dynamic segment, model hook always called
- this.transitionTo('posts');
-
- // model passed in, so model hook not called
- thePost = store.find('post', 1);
- this.transitionTo('post', thePost);
-
- // integer passed in, model hook is called
- this.transitionTo('post', 1);
- ```
-
-
- This hook follows the asynchronous/promise semantics
- described in the documentation for `beforeModel`. In particular,
- if a promise returned from `model` fails, the error will be
- handled by the `error` hook on `Ember.Route`.
-
- Example
-
- ```javascript
- App.PostRoute = Ember.Route.extend({
- model: function(params) {
- return this.store.find('post', params.post_id);
- }
- });
- ```
-
- @method model
- @param {Object} params the parameters extracted from the URL
- @param {Transition} transition
- @param {Object} queryParams the query params for this route
- @return {Object|Promise} the model for this route. If
- a promise is returned, the transition will pause until
- the promise resolves, and the resolved value of the promise
- will be used as the model for this route.
- */
- model: function(params, transition) {
- var match, name, sawParams, value;
-
- var queryParams = get(this, '_qp.map');
-
- for (var prop in params) {
- if (prop === 'queryParams' || (queryParams && prop in queryParams)) {
- continue;
- }
-
- if (match = prop.match(/^(.*)_id$/)) {
- name = match[1];
- value = params[prop];
- }
- sawParams = true;
- }
-
- if (!name && sawParams) { return copy(params); }
- else if (!name) {
- if (transition.resolveIndex < 1) { return; }
-
- var parentModel = transition.state.handlerInfos[transition.resolveIndex-1].context;
-
- return parentModel;
- }
-
- return this.findModel(name, value);
- },
-
- /**
- @private
- @method deserialize
- @param {Object} params the parameters extracted from the URL
- @param {Transition} transition
- @return {Object|Promise} the model for this route.
-
- Router.js hook.
- */
- deserialize: function(params, transition) {
- return this.model(this.paramsFor(this.routeName), transition);
- },
-
- /**
-
- @method findModel
- @param {String} type the model type
- @param {Object} value the value passed to find
- */
- findModel: function(){
- var store = get(this, 'store');
- return store.find.apply(store, arguments);
- },
-
- /**
- Store property provides a hook for data persistence libraries to inject themselves.
-
- By default, this store property provides the exact same functionality previously
- in the model hook.
-
- Currently, the required interface is:
-
- `store.find(modelName, findArguments)`
-
- @method store
- @param {Object} store
- */
- store: computed(function(){
- var container = this.container;
- var routeName = this.routeName;
- var namespace = get(this, 'router.namespace');
-
- return {
- find: function(name, value) {
- var modelClass = container.lookupFactory('model:' + name);
-
- Ember.assert("You used the dynamic segment " + name + "_id in your route " +
- routeName + ", but " + namespace + "." + classify(name) +
- " did not exist and you did not override your route's `model` " +
- "hook.", modelClass);
-
- if (!modelClass) { return; }
-
- Ember.assert(classify(name) + ' has no method `find`.', typeof modelClass.find === 'function');
-
- return modelClass.find(value);
- }
- };
- }),
-
- /**
- A hook you can implement to convert the route's model into parameters
- for the URL.
-
- ```javascript
- App.Router.map(function() {
- this.resource('post', { path: '/posts/:post_id' });
- });
-
- App.PostRoute = Ember.Route.extend({
- model: function(params) {
- // the server returns `{ id: 12 }`
- return Ember.$.getJSON('/posts/' + params.post_id);
- },
-
- serialize: function(model) {
- // this will make the URL `/posts/12`
- return { post_id: model.id };
- }
- });
- ```
-
- The default `serialize` method will insert the model's `id` into the
- route's dynamic segment (in this case, `:post_id`) if the segment contains '_id'.
- If the route has multiple dynamic segments or does not contain '_id', `serialize`
- will return `Ember.getProperties(model, params)`
-
- This method is called when `transitionTo` is called with a context
- in order to populate the URL.
-
- @method serialize
- @param {Object} model the route's model
- @param {Array} params an Array of parameter names for the current
- route (in the example, `['post_id']`.
- @return {Object} the serialized parameters
- */
- serialize: function(model, params) {
- if (params.length < 1) { return; }
- if (!model) { return; }
-
- var name = params[0], object = {};
-
- if (/_id$/.test(name) && params.length === 1) {
- object[name] = get(model, "id");
- } else {
- object = getProperties(model, params);
- }
-
- return object;
- },
-
- /**
- A hook you can use to setup the controller for the current route.
-
- This method is called with the controller for the current route and the
- model supplied by the `model` hook.
-
- By default, the `setupController` hook sets the `model` property of
- the controller to the `model`.
-
- If you implement the `setupController` hook in your Route, it will
- prevent this default behavior. If you want to preserve that behavior
- when implementing your `setupController` function, make sure to call
- `_super`:
-
- ```javascript
- App.PhotosRoute = Ember.Route.extend({
- model: function() {
- return this.store.find('photo');
- },
-
- setupController: function (controller, model) {
- // Call _super for default behavior
- this._super(controller, model);
- // Implement your custom setup after
- this.controllerFor('application').set('showingPhotos', true);
- }
- });
- ```
-
- This means that your template will get a proxy for the model as its
- context, and you can act as though the model itself was the context.
-
- The provided controller will be one resolved based on the name
- of this route.
-
- If no explicit controller is defined, Ember will automatically create
- an appropriate controller for the model.
-
- * if the model is an `Ember.Array` (including record arrays from Ember
- Data), the controller is an `Ember.ArrayController`.
- * otherwise, the controller is an `Ember.ObjectController`.
-
- As an example, consider the router:
-
- ```javascript
- App.Router.map(function() {
- this.resource('post', { path: '/posts/:post_id' });
- });
- ```
-
- For the `post` route, a controller named `App.PostController` would
- be used if it is defined. If it is not defined, an `Ember.ObjectController`
- instance would be used.
-
- Example
-
- ```javascript
- App.PostRoute = Ember.Route.extend({
- setupController: function(controller, model) {
- controller.set('model', model);
- }
- });
- ```
-
- @method setupController
- @param {Controller} controller instance
- @param {Object} model
- */
- setupController: function(controller, context, transition) {
- if (controller && (context !== undefined)) {
- set(controller, 'model', context);
- }
- },
-
- /**
- Returns the controller for a particular route or name.
-
- The controller instance must already have been created, either through entering the
- associated route or using `generateController`.
-
- ```javascript
- App.PostRoute = Ember.Route.extend({
- setupController: function(controller, post) {
- this._super(controller, post);
- this.controllerFor('posts').set('currentPost', post);
- }
- });
- ```
-
- @method controllerFor
- @param {String} name the name of the route or controller
- @return {Ember.Controller}
- */
- controllerFor: function(name, _skipAssert) {
- var container = this.container;
- var route = container.lookup('route:'+name);
- var controller;
-
- if (route && route.controllerName) {
- name = route.controllerName;
- }
-
- controller = container.lookup('controller:' + name);
-
- // NOTE: We're specifically checking that skipAssert is true, because according
- // to the old API the second parameter was model. We do not want people who
- // passed a model to skip the assertion.
- Ember.assert("The controller named '"+name+"' could not be found. Make sure " +
- "that this route exists and has already been entered at least " +
- "once. If you are accessing a controller not associated with a " +
- "route, make sure the controller class is explicitly defined.",
- controller || _skipAssert === true);
-
- return controller;
- },
-
- /**
- Generates a controller for a route.
-
- If the optional model is passed then the controller type is determined automatically,
- e.g., an ArrayController for arrays.
-
- Example
-
- ```javascript
- App.PostRoute = Ember.Route.extend({
- setupController: function(controller, post) {
- this._super(controller, post);
- this.generateController('posts', post);
- }
- });
- ```
-
- @method generateController
- @param {String} name the name of the controller
- @param {Object} model the model to infer the type of the controller (optional)
- */
- generateController: function(name, model) {
- var container = this.container;
-
- model = model || this.modelFor(name);
-
- return generateController(container, name, model);
- },
-
- /**
- Returns the model of a parent (or any ancestor) route
- in a route hierarchy. During a transition, all routes
- must resolve a model object, and if a route
- needs access to a parent route's model in order to
- resolve a model (or just reuse the model from a parent),
- it can call `this.modelFor(theNameOfParentRoute)` to
- retrieve it.
-
- Example
-
- ```javascript
- App.Router.map(function() {
- this.resource('post', { path: '/post/:post_id' }, function() {
- this.resource('comments');
- });
- });
-
- App.CommentsRoute = Ember.Route.extend({
- afterModel: function() {
- this.set('post', this.modelFor('post'));
- }
- });
- ```
-
- @method modelFor
- @param {String} name the name of the route
- @return {Object} the model object
- */
- modelFor: function(name) {
- var route = this.container.lookup('route:' + name);
- var transition = this.router ? this.router.router.activeTransition : null;
-
- // If we are mid-transition, we want to try and look up
- // resolved parent contexts on the current transitionEvent.
- if (transition) {
- var modelLookupName = (route && route.routeName) || name;
- if (transition.resolvedModels.hasOwnProperty(modelLookupName)) {
- return transition.resolvedModels[modelLookupName];
- }
- }
-
- return route && route.currentModel;
- },
-
- /**
- A hook you can use to render the template for the current route.
-
- This method is called with the controller for the current route and the
- model supplied by the `model` hook. By default, it renders the route's
- template, configured with the controller for the route.
-
- This method can be overridden to set up and render additional or
- alternative templates.
-
- ```javascript
- App.PostsRoute = Ember.Route.extend({
- renderTemplate: function(controller, model) {
- var favController = this.controllerFor('favoritePost');
-
- // Render the `favoritePost` template into
- // the outlet `posts`, and display the `favoritePost`
- // controller.
- this.render('favoritePost', {
- outlet: 'posts',
- controller: favController
- });
- }
- });
- ```
-
- @method renderTemplate
- @param {Object} controller the route's controller
- @param {Object} model the route's model
- */
- renderTemplate: function(controller, model) {
- this.render();
- },
-
- /**
- `render` is used to render a template into a region of another template
- (indicated by an `{{outlet}}`). `render` is used both during the entry
- phase of routing (via the `renderTemplate` hook) and later in response to
- user interaction.
-
- For example, given the following minimal router and templates:
-
- ```javascript
- Router.map(function() {
- this.resource('photos');
- });
- ```
-
- ```handlebars
- <!-- application.hbs -->
- <div class='something-in-the-app-hbs'>
- {{outlet "anOutletName"}}
- </div>
- ```
-
- ```handlebars
- <!-- photos.hbs -->
- <h1>Photos</h1>
- ```
-
- You can render `photos.hbs` into the `"anOutletName"` outlet of
- `application.hbs` by calling `render`:
-
- ```javascript
- // posts route
- Ember.Route.extend({
- renderTemplate: function(){
- this.render('photos', {
- into: 'application',
- outlet: 'anOutletName'
- })
- }
- });
- ```
-
- `render` additionally allows you to supply which `view`, `controller`, and
- `model` objects should be loaded and associated with the rendered template.
-
-
- ```javascript
- // posts route
- Ember.Route.extend({
- renderTemplate: function(controller, model){
- this.render('posts', { // the template to render, referenced by name
- into: 'application', // the template to render into, referenced by name
- outlet: 'anOutletName', // the outlet inside `options.template` to render into.
- view: 'aViewName', // the view to use for this template, referenced by name
- controller: 'someControllerName', // the controller to use for this template, referenced by name
- model: model // the model to set on `options.controller`.
- })
- }
- });
- ```
-
- The string values provided for the template name, view, and controller
- will eventually pass through to the resolver for lookup. See
- Ember.Resolver for how these are mapped to JavaScript objects in your
- application.
-
- Not all options need to be passed to `render`. Default values will be used
- based on the name of the route specified in the router or the Route's
- `controllerName`, `viewName` and `templateName` properties.
-
- For example:
-
- ```javascript
- // router
- Router.map(function() {
- this.route('index');
- this.resource('post', { path: '/posts/:post_id' });
- });
- ```
-
- ```javascript
- // post route
- PostRoute = App.Route.extend({
- renderTemplate: function() {
- this.render(); // all defaults apply
- }
- });
- ```
-
- The name of the `PostRoute`, defined by the router, is `post`.
-
- The following equivalent default options will be applied when
- the Route calls `render`:
-
- ```javascript
- //
- this.render('post', { // the template name associated with 'post' Route
- into: 'application', // the parent route to 'post' Route
- outlet: 'main', // {{outlet}} and {{outlet 'main' are synonymous}},
- view: 'post', // the view associated with the 'post' Route
- controller: 'post', // the controller associated with the 'post' Route
- })
- ```
-
- By default the controller's `model` will be the route's model, so it does not
- need to be passed unless you wish to change which model is being used.
-
- @method render
- @param {String} name the name of the template to render
- @param {Object} [options] the options
- @param {String} [options.into] the template to render into,
- referenced by name. Defaults to the parent template
- @param {String} [options.outlet] the outlet inside `options.template` to render into.
- Defaults to 'main'
- @param {String} [options.controller] the controller to use for this template,
- referenced by name. Defaults to the Route's paired controller
- @param {String} [options.model] the model object to set on `options.controller`
- Defaults to the return value of the Route's model hook
- */
- render: function(name, options) {
- Ember.assert("The name in the given arguments is undefined", arguments.length > 0 ? !isNone(arguments[0]) : true);
-
- var namePassed = typeof name === 'string' && !!name;
-
- if (typeof name === 'object' && !options) {
- options = name;
- name = this.routeName;
- }
-
- options = options || {};
- options.namePassed = namePassed;
-
- var templateName;
-
- if (name) {
- name = name.replace(/\//g, '.');
- templateName = name;
- } else {
- name = this.routeName;
- templateName = this.templateName || name;
- }
-
- var viewName = options.view || namePassed && name || this.viewName || name;
-
- var container = this.container;
- var view = container.lookup('view:' + viewName);
- var template = view ? view.get('template') : null;
-
- if (!template) {
- template = container.lookup('template:' + templateName);
- }
-
- if (!view && !template) {
- Ember.assert("Could not find \"" + name + "\" template or view.", Ember.isEmpty(arguments[0]));
- if (get(this.router, 'namespace.LOG_VIEW_LOOKUPS')) {
- Ember.Logger.info("Could not find \"" + name + "\" template or view. Nothing will be rendered", { fullName: 'template:' + name });
- }
- return;
- }
-
- options = normalizeOptions(this, name, template, options);
- view = setupView(view, container, options);
-
- if (options.outlet === 'main') { this.lastRenderedTemplate = name; }
-
- appendView(this, view, options);
- },
-
- /**
- Disconnects a view that has been rendered into an outlet.
-
- You may pass any or all of the following options to `disconnectOutlet`:
-
- * `outlet`: the name of the outlet to clear (default: 'main')
- * `parentView`: the name of the view containing the outlet to clear
- (default: the view rendered by the parent route)
-
- Example:
-
- ```javascript
- App.ApplicationRoute = App.Route.extend({
- actions: {
- showModal: function(evt) {
- this.render(evt.modalName, {
- outlet: 'modal',
- into: 'application'
- });
- },
- hideModal: function(evt) {
- this.disconnectOutlet({
- outlet: 'modal',
- parentView: 'application'
- });
- }
- }
- });
- ```
-
- Alternatively, you can pass the `outlet` name directly as a string.
-
- Example:
-
- ```javascript
- hideModal: function(evt) {
- this.disconnectOutlet('modal');
- }
- ```
-
- @method disconnectOutlet
- @param {Object|String} options the options hash or outlet name
- */
- disconnectOutlet: function(options) {
- if (!options || typeof options === "string") {
- var outletName = options;
- options = {};
- options.outlet = outletName;
- }
- options.parentView = options.parentView ? options.parentView.replace(/\//g, '.') : parentTemplate(this);
- options.outlet = options.outlet || 'main';
-
- var parentView = this.router._lookupActiveView(options.parentView);
- if (parentView) { parentView.disconnectOutlet(options.outlet); }
- },
-
- willDestroy: function() {
- this.teardownViews();
- },
-
- /**
- @private
-
- @method teardownViews
- */
- teardownViews: function() {
- // Tear down the top level view
- if (this.teardownTopLevelView) { this.teardownTopLevelView(); }
-
- // Tear down any outlets rendered with 'into'
- var teardownOutletViews = this.teardownOutletViews || [];
- forEach(teardownOutletViews, function(teardownOutletView) {
- teardownOutletView();
- });
-
- delete this.teardownTopLevelView;
- delete this.teardownOutletViews;
- delete this.lastRenderedTemplate;
- }
- });
-
-
- // TODO add mixin directly to `Route` class definition above, once this
- // feature is merged:
- Route.reopen(Evented);
-
-
- var defaultQPMeta = {
- qps: [],
- map: {},
- states: {}
- };
-
- function parentRoute(route) {
- var handlerInfo = handlerInfoFor(route, route.router.router.state.handlerInfos, -1);
- return handlerInfo && handlerInfo.handler;
- }
-
- function handlerInfoFor(route, handlerInfos, _offset) {
- if (!handlerInfos) { return; }
-
- var offset = _offset || 0, current;
- for (var i=0, l=handlerInfos.length; i<l; i++) {
- current = handlerInfos[i].handler;
- if (current === route) { return handlerInfos[i+offset]; }
- }
- }
-
- function parentTemplate(route) {
- var parent = parentRoute(route), template;
-
- if (!parent) { return; }
-
- if (template = parent.lastRenderedTemplate) {
- return template;
- } else {
- return parentTemplate(parent);
- }
- }
-
- function normalizeOptions(route, name, template, options) {
- options = options || {};
- options.into = options.into ? options.into.replace(/\//g, '.') : parentTemplate(route);
- options.outlet = options.outlet || 'main';
- options.name = name;
- options.template = template;
- options.LOG_VIEW_LOOKUPS = get(route.router, 'namespace.LOG_VIEW_LOOKUPS');
-
- Ember.assert("An outlet ("+options.outlet+") was specified but was not found.", options.outlet === 'main' || options.into);
-
- var controller = options.controller;
- var model = options.model;
-
- if (options.controller) {
- controller = options.controller;
- } else if (options.namePassed) {
- controller = route.container.lookup('controller:' + name) || route.controllerName || route.routeName;
- } else {
- controller = route.controllerName || route.container.lookup('controller:' + name);
- }
-
- if (typeof controller === 'string') {
- var controllerName = controller;
- controller = route.container.lookup('controller:' + controllerName);
- if (!controller) {
- throw new EmberError("You passed `controller: '" + controllerName + "'` into the `render` method, but no such controller could be found.");
- }
- }
-
- if (model) {
- controller.set('model', model);
- }
-
- options.controller = controller;
-
- return options;
- }
-
- function setupView(view, container, options) {
- if (view) {
- if (options.LOG_VIEW_LOOKUPS) {
- Ember.Logger.info("Rendering " + options.name + " with " + view, { fullName: 'view:' + options.name });
- }
- } else {
- var defaultView = options.into ? 'view:default' : 'view:toplevel';
- view = container.lookup(defaultView);
- if (options.LOG_VIEW_LOOKUPS) {
- Ember.Logger.info("Rendering " + options.name + " with default view " + view, { fullName: 'view:' + options.name });
- }
- }
-
- if (!get(view, 'templateName')) {
- set(view, 'template', options.template);
-
- set(view, '_debugTemplateName', options.name);
- }
-
- set(view, 'renderedName', options.name);
- set(view, 'controller', options.controller);
-
- return view;
- }
-
- function appendView(route, view, options) {
- if (options.into) {
- var parentView = route.router._lookupActiveView(options.into);
- var teardownOutletView = generateOutletTeardown(parentView, options.outlet);
- if (!route.teardownOutletViews) { route.teardownOutletViews = []; }
- replace(route.teardownOutletViews, 0, 0, [teardownOutletView]);
- parentView.connectOutlet(options.outlet, view);
- } else {
- var rootElement = get(route, 'router.namespace.rootElement');
- // tear down view if one is already rendered
- if (route.teardownTopLevelView) {
- route.teardownTopLevelView();
- }
- route.router._connectActiveView(options.name, view);
- route.teardownTopLevelView = generateTopLevelTeardown(view);
- view.appendTo(rootElement);
- }
- }
-
- function generateTopLevelTeardown(view) {
- return function() {
- view.destroy();
- };
- }
-
- function generateOutletTeardown(parentView, outlet) {
- return function() {
- parentView.disconnectOutlet(outlet);
- };
- }
-
- function getFullQueryParams(router, state) {
- if (state.fullQueryParams) { return state.fullQueryParams; }
-
- state.fullQueryParams = {};
- merge(state.fullQueryParams, state.queryParams);
-
- var targetRouteName = state.handlerInfos[state.handlerInfos.length-1].name;
- router._deserializeQueryParams(targetRouteName, state.fullQueryParams);
- return state.fullQueryParams;
- }
-
- function getQueryParamsFor(route, state) {
- state.queryParamsFor = state.queryParamsFor || {};
- var name = route.routeName;
-
- if (state.queryParamsFor[name]) { return state.queryParamsFor[name]; }
-
- var fullQueryParams = getFullQueryParams(route.router, state);
-
- var params = state.queryParamsFor[name] = {};
-
- // Copy over all the query params for this route/controller into params hash.
- var qpMeta = get(route, '_qp');
- var qps = qpMeta.qps;
- for (var i = 0, len = qps.length; i < len; ++i) {
- // Put deserialized qp on params hash.
- var qp = qps[i];
-
- var qpValueWasPassedIn = (qp.prop in fullQueryParams);
- params[qp.prop] = qpValueWasPassedIn ?
- fullQueryParams[qp.prop] :
- copyDefaultValue(qp.def);
- }
-
- return params;
- }
-
- function copyDefaultValue(value) {
- if (isArray(value)) {
- return Ember.A(value.slice());
- }
- return value;
- }
-
- __exports__["default"] = Route;
- });
-enifed("ember-routing/system/router",
- ["ember-metal/core","ember-metal/error","ember-metal/property_get","ember-metal/property_set","ember-metal/properties","ember-metal/computed","ember-metal/merge","ember-metal/run_loop","ember-runtime/system/string","ember-runtime/system/object","ember-runtime/mixins/evented","ember-routing/system/dsl","ember-views/views/view","ember-routing/location/api","ember-handlebars/views/metamorph_view","ember-routing/utils","ember-metal/platform","router","router/transition","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __dependency15__, __dependency16__, __dependency17__, __dependency18__, __dependency19__, __exports__) {
- "use strict";
- var Ember = __dependency1__["default"];
- // FEATURES, Logger, K, assert
- var EmberError = __dependency2__["default"];
- var get = __dependency3__.get;
- var set = __dependency4__.set;
- var defineProperty = __dependency5__.defineProperty;
- var computed = __dependency6__.computed;
- var merge = __dependency7__["default"];
- var run = __dependency8__["default"];
-
- var fmt = __dependency9__.fmt;
- var EmberObject = __dependency10__["default"];
- var Evented = __dependency11__["default"];
- var EmberRouterDSL = __dependency12__["default"];
- var EmberView = __dependency13__["default"];
- var EmberLocation = __dependency14__["default"];
- var _MetamorphView = __dependency15__["default"];
- var routeArgs = __dependency16__.routeArgs;
- var getActiveTargetName = __dependency16__.getActiveTargetName;
- var stashParamNames = __dependency16__.stashParamNames;
- var create = __dependency17__.create;
-
- /**
- @module ember
- @submodule ember-routing
- */
-
- var Router = __dependency18__["default"];
-
- var slice = [].slice;
-
- /**
- The `Ember.Router` class manages the application state and URLs. Refer to
- the [routing guide](http://emberjs.com/guides/routing/) for documentation.
-
- @class Router
- @namespace Ember
- @extends Ember.Object
- */
- var EmberRouter = EmberObject.extend(Evented, {
- /**
- The `location` property determines the type of URL's that your
- application will use.
-
- The following location types are currently available:
-
- * `hash`
- * `history`
- * `none`
-
- @property location
- @default 'hash'
- @see {Ember.Location}
- */
- location: 'hash',
-
- /**
- Represents the URL of the root of the application, often '/'. This prefix is
- assumed on all routes defined on this router.
-
- @property rootURL
- @default '/'
- */
- rootURL: '/',
-
- init: function() {
- this.router = this.constructor.router || this.constructor.map(Ember.K);
- this._activeViews = {};
- this._setupLocation();
- this._qpCache = {};
- this._queuedQPChanges = {};
-
- if (get(this, 'namespace.LOG_TRANSITIONS_INTERNAL')) {
- this.router.log = Ember.Logger.debug;
- }
- },
-
- /**
- Represents the current URL.
-
- @method url
- @return {String} The current URL.
- */
- url: computed(function() {
- return get(this, 'location').getURL();
- }),
-
- /**
- Initializes the current router instance and sets up the change handling
- event listeners used by the instances `location` implementation.
-
- A property named `initialURL` will be used to determine the initial URL.
- If no value is found `/` will be used.
-
- @method startRouting
- @private
- */
- startRouting: function() {
- this.router = this.router || this.constructor.map(Ember.K);
-
- var router = this.router;
- var location = get(this, 'location');
- var container = this.container;
- var self = this;
- var initialURL = get(this, 'initialURL');
- var initialTransition;
-
- // Allow the Location class to cancel the router setup while it refreshes
- // the page
- if (get(location, 'cancelRouterSetup')) {
- return;
- }
-
- this._setupRouter(router, location);
-
- container.register('view:default', _MetamorphView);
- container.register('view:toplevel', EmberView.extend());
-
- location.onUpdateURL(function(url) {
- self.handleURL(url);
- });
-
- if (typeof initialURL === "undefined") {
- initialURL = location.getURL();
- }
- initialTransition = this.handleURL(initialURL);
- if (initialTransition && initialTransition.error) {
- throw initialTransition.error;
- }
- },
-
- /**
- Handles updating the paths and notifying any listeners of the URL
- change.
-
- Triggers the router level `didTransition` hook.
-
- @method didTransition
- @private
- @since 1.2.0
- */
- didTransition: function(infos) {
- updatePaths(this);
-
- this._cancelLoadingEvent();
-
- this.notifyPropertyChange('url');
-
- // Put this in the runloop so url will be accurate. Seems
- // less surprising than didTransition being out of sync.
- run.once(this, this.trigger, 'didTransition');
-
- if (get(this, 'namespace').LOG_TRANSITIONS) {
- Ember.Logger.log("Transitioned into '" + EmberRouter._routePath(infos) + "'");
- }
- },
-
- handleURL: function(url) {
- // Until we have an ember-idiomatic way of accessing #hashes, we need to
- // remove it because router.js doesn't know how to handle it.
- url = url.split(/#(.+)?/)[0];
- return this._doURLTransition('handleURL', url);
- },
-
- _doURLTransition: function(routerJsMethod, url) {
- var transition = this.router[routerJsMethod](url || '/');
- listenForTransitionErrors(transition);
- return transition;
- },
-
- transitionTo: function() {
- var args = slice.call(arguments), queryParams;
- if (resemblesURL(args[0])) {
- return this._doURLTransition('transitionTo', args[0]);
- }
-
- var possibleQueryParams = args[args.length-1];
- if (possibleQueryParams && possibleQueryParams.hasOwnProperty('queryParams')) {
- queryParams = args.pop().queryParams;
- } else {
- queryParams = {};
- }
-
- var targetRouteName = args.shift();
- return this._doTransition(targetRouteName, args, queryParams);
- },
-
- intermediateTransitionTo: function() {
- this.router.intermediateTransitionTo.apply(this.router, arguments);
-
- updatePaths(this);
-
- var infos = this.router.currentHandlerInfos;
- if (get(this, 'namespace').LOG_TRANSITIONS) {
- Ember.Logger.log("Intermediate-transitioned into '" + EmberRouter._routePath(infos) + "'");
- }
- },
-
- replaceWith: function() {
- return this.transitionTo.apply(this, arguments).method('replace');
- },
-
- generate: function() {
- var url = this.router.generate.apply(this.router, arguments);
- return this.location.formatURL(url);
- },
-
- /**
- Determines if the supplied route is currently active.
-
- @method isActive
- @param routeName
- @return {Boolean}
- @private
- */
- isActive: function(routeName) {
- var router = this.router;
- return router.isActive.apply(router, arguments);
- },
-
- /**
- An alternative form of `isActive` that doesn't require
- manual concatenation of the arguments into a single
- array.
-
- @method isActiveIntent
- @param routeName
- @param models
- @param queryParams
- @return {Boolean}
- @private
- @since 1.7.0
- */
- isActiveIntent: function(routeName, models, queryParams) {
- var router = this.router;
- return router.isActive.apply(router, arguments);
- },
-
- send: function(name, context) {
- this.router.trigger.apply(this.router, arguments);
- },
-
- /**
- Does this router instance have the given route.
-
- @method hasRoute
- @return {Boolean}
- @private
- */
- hasRoute: function(route) {
- return this.router.hasRoute(route);
- },
-
- /**
- Resets the state of the router by clearing the current route
- handlers and deactivating them.
-
- @private
- @method reset
- */
- reset: function() {
- this.router.reset();
- },
-
- _lookupActiveView: function(templateName) {
- var active = this._activeViews[templateName];
- return active && active[0];
- },
-
- _connectActiveView: function(templateName, view) {
- var existing = this._activeViews[templateName];
-
- if (existing) {
- existing[0].off('willDestroyElement', this, existing[1]);
- }
-
- function disconnectActiveView() {
- delete this._activeViews[templateName];
- }
-
- this._activeViews[templateName] = [view, disconnectActiveView];
- view.one('willDestroyElement', this, disconnectActiveView);
- },
-
- _setupLocation: function() {
- var location = get(this, 'location');
- var rootURL = get(this, 'rootURL');
-
- if (rootURL && this.container && !this.container.has('-location-setting:root-url')) {
- this.container.register('-location-setting:root-url', rootURL, {
- instantiate: false
- });
- }
-
- if ('string' === typeof location && this.container) {
- var resolvedLocation = this.container.lookup('location:' + location);
-
- if ('undefined' !== typeof resolvedLocation) {
- location = set(this, 'location', resolvedLocation);
- } else {
- // Allow for deprecated registration of custom location API's
- var options = {
- implementation: location
- };
-
- location = set(this, 'location', EmberLocation.create(options));
- }
- }
-
- if (location !== null && typeof location === 'object') {
- if (rootURL && typeof rootURL === 'string') {
- location.rootURL = rootURL;
- }
-
- // ensure that initState is called AFTER the rootURL is set on
- // the location instance
- if (typeof location.initState === 'function') {
- location.initState();
- }
- }
- },
-
- _getHandlerFunction: function() {
- var seen = create(null);
- var container = this.container;
- var DefaultRoute = container.lookupFactory('route:basic');
- var self = this;
-
- return function(name) {
- var routeName = 'route:' + name;
- var handler = container.lookup(routeName);
-
- if (seen[name]) {
- return handler;
- }
-
- seen[name] = true;
-
- if (!handler) {
- container.register(routeName, DefaultRoute.extend());
- handler = container.lookup(routeName);
-
- if (get(self, 'namespace.LOG_ACTIVE_GENERATION')) {
- Ember.Logger.info("generated -> " + routeName, { fullName: routeName });
- }
- }
-
- handler.routeName = name;
- return handler;
- };
- },
-
- _setupRouter: function(router, location) {
- var lastURL, emberRouter = this;
-
- router.getHandler = this._getHandlerFunction();
-
- var doUpdateURL = function() {
- location.setURL(lastURL);
- };
-
- router.updateURL = function(path) {
- lastURL = path;
- run.once(doUpdateURL);
- };
-
- if (location.replaceURL) {
- var doReplaceURL = function() {
- location.replaceURL(lastURL);
- };
-
- router.replaceURL = function(path) {
- lastURL = path;
- run.once(doReplaceURL);
- };
- }
-
- router.didTransition = function(infos) {
- emberRouter.didTransition(infos);
- };
- },
-
- _serializeQueryParams: function(targetRouteName, queryParams) {
- var groupedByUrlKey = {};
-
- forEachQueryParam(this, targetRouteName, queryParams, function(key, value, qp) {
- var urlKey = qp.urlKey;
- if (!groupedByUrlKey[urlKey]) {
- groupedByUrlKey[urlKey] = [];
- }
- groupedByUrlKey[urlKey].push({
- qp: qp,
- value: value
- });
- delete queryParams[key];
- });
-
- for (var key in groupedByUrlKey) {
- var qps = groupedByUrlKey[key];
- if (qps.length > 1) {
- var qp0 = qps[0].qp, qp1=qps[1].qp;
- Ember.assert(fmt("You're not allowed to have more than one controller property map to the same query param key, but both `%@` and `%@` map to `%@`. You can fix this by mapping one of the controller properties to a different query param key via the `as` config option, e.g. `%@: { as: 'other-%@' }`", [qp0.fprop, qp1.fprop, qp0.urlKey, qp0.prop, qp0.prop]), false);
- }
- var qp = qps[0].qp;
- queryParams[qp.urlKey] = qp.route.serializeQueryParam(qps[0].value, qp.urlKey, qp.type);
- }
- },
-
- _deserializeQueryParams: function(targetRouteName, queryParams) {
- forEachQueryParam(this, targetRouteName, queryParams, function(key, value, qp) {
- delete queryParams[key];
- queryParams[qp.prop] = qp.route.deserializeQueryParam(value, qp.urlKey, qp.type);
- });
- },
-
- _pruneDefaultQueryParamValues: function(targetRouteName, queryParams) {
- var qps = this._queryParamsFor(targetRouteName);
- for (var key in queryParams) {
- var qp = qps.map[key];
- if (qp && qp.sdef === queryParams[key]) {
- delete queryParams[key];
- }
- }
- },
-
- _doTransition: function(_targetRouteName, models, _queryParams) {
- var targetRouteName = _targetRouteName || getActiveTargetName(this.router);
- Ember.assert("The route " + targetRouteName + " was not found", targetRouteName && this.router.hasRoute(targetRouteName));
-
- var queryParams = {};
- merge(queryParams, _queryParams);
- this._prepareQueryParams(targetRouteName, models, queryParams);
-
- var transitionArgs = routeArgs(targetRouteName, models, queryParams);
- var transitionPromise = this.router.transitionTo.apply(this.router, transitionArgs);
-
- listenForTransitionErrors(transitionPromise);
-
- return transitionPromise;
- },
-
- _prepareQueryParams: function(targetRouteName, models, queryParams) {
- this._hydrateUnsuppliedQueryParams(targetRouteName, models, queryParams);
- this._serializeQueryParams(targetRouteName, queryParams);
- this._pruneDefaultQueryParamValues(targetRouteName, queryParams);
- },
-
- /**
- Returns a merged query params meta object for a given route.
- Useful for asking a route what its known query params are.
- */
- _queryParamsFor: function(leafRouteName) {
- if (this._qpCache[leafRouteName]) {
- return this._qpCache[leafRouteName];
- }
-
- var map = {}, qps = [];
- this._qpCache[leafRouteName] = {
- map: map,
- qps: qps
- };
-
- var routerjs = this.router;
- var recogHandlerInfos = routerjs.recognizer.handlersFor(leafRouteName);
-
- for (var i = 0, len = recogHandlerInfos.length; i < len; ++i) {
- var recogHandler = recogHandlerInfos[i];
- var route = routerjs.getHandler(recogHandler.handler);
- var qpMeta = get(route, '_qp');
-
- if (!qpMeta) { continue; }
-
- merge(map, qpMeta.map);
- qps.push.apply(qps, qpMeta.qps);
- }
-
- return {
- qps: qps,
- map: map
- };
- },
-
- /*
- becomeResolved: function(payload, resolvedContext) {
- var params = this.serialize(resolvedContext);
-
- if (payload) {
- this.stashResolvedModel(payload, resolvedContext);
- payload.params = payload.params || {};
- payload.params[this.name] = params;
- }
-
- return this.factory('resolved', {
- context: resolvedContext,
- name: this.name,
- handler: this.handler,
- params: params
- });
- },
- */
-
- _hydrateUnsuppliedQueryParams: function(leafRouteName, contexts, queryParams) {
- var state = calculatePostTransitionState(this, leafRouteName, contexts);
- var handlerInfos = state.handlerInfos;
- var appCache = this._bucketCache;
-
- stashParamNames(this, handlerInfos);
-
- for (var i = 0, len = handlerInfos.length; i < len; ++i) {
- var route = handlerInfos[i].handler;
- var qpMeta = get(route, '_qp');
-
- for (var j = 0, qpLen = qpMeta.qps.length; j < qpLen; ++j) {
- var qp = qpMeta.qps[j];
- var presentProp = qp.prop in queryParams && qp.prop ||
- qp.fprop in queryParams && qp.fprop;
-
- if (presentProp) {
- if (presentProp !== qp.fprop) {
- queryParams[qp.fprop] = queryParams[presentProp];
- delete queryParams[presentProp];
- }
- } else {
- var controllerProto = qp.cProto;
- var cacheMeta = get(controllerProto, '_cacheMeta');
-
- var cacheKey = controllerProto._calculateCacheKey(qp.ctrl, cacheMeta[qp.prop].parts, state.params);
- queryParams[qp.fprop] = appCache.lookup(cacheKey, qp.prop, qp.def);
- }
- }
- }
- },
-
- _scheduleLoadingEvent: function(transition, originRoute) {
- this._cancelLoadingEvent();
- this._loadingStateTimer = run.scheduleOnce('routerTransitions', this, '_fireLoadingEvent', transition, originRoute);
- },
-
- _fireLoadingEvent: function(transition, originRoute) {
- if (!this.router.activeTransition) {
- // Don't fire an event if we've since moved on from
- // the transition that put us in a loading state.
- return;
- }
-
- transition.trigger(true, 'loading', transition, originRoute);
- },
-
- _cancelLoadingEvent: function () {
- if (this._loadingStateTimer) {
- run.cancel(this._loadingStateTimer);
- }
- this._loadingStateTimer = null;
- }
- });
-
- /*
- Helper function for iterating root-ward, starting
- from (but not including) the provided `originRoute`.
-
- Returns true if the last callback fired requested
- to bubble upward.
-
- @private
- */
- function forEachRouteAbove(originRoute, transition, callback) {
- var handlerInfos = transition.state.handlerInfos;
- var originRouteFound = false;
- var handlerInfo, route;
-
- for (var i = handlerInfos.length - 1; i >= 0; --i) {
- handlerInfo = handlerInfos[i];
- route = handlerInfo.handler;
-
- if (!originRouteFound) {
- if (originRoute === route) {
- originRouteFound = true;
- }
- continue;
- }
-
- if (callback(route, handlerInfos[i + 1].handler) !== true) {
- return false;
- }
- }
- return true;
- }
-
- // These get invoked when an action bubbles above ApplicationRoute
- // and are not meant to be overridable.
- var defaultActionHandlers = {
-
- willResolveModel: function(transition, originRoute) {
- originRoute.router._scheduleLoadingEvent(transition, originRoute);
- },
-
- error: function(error, transition, originRoute) {
- // Attempt to find an appropriate error substate to enter.
- var router = originRoute.router;
-
- var tryTopLevel = forEachRouteAbove(originRoute, transition, function(route, childRoute) {
- var childErrorRouteName = findChildRouteName(route, childRoute, 'error');
- if (childErrorRouteName) {
- router.intermediateTransitionTo(childErrorRouteName, error);
- return;
- }
- return true;
- });
-
- if (tryTopLevel) {
- // Check for top-level error state to enter.
- if (routeHasBeenDefined(originRoute.router, 'application_error')) {
- router.intermediateTransitionTo('application_error', error);
- return;
- }
- }
-
- logError(error, 'Error while processing route: ' + transition.targetName);
- },
-
- loading: function(transition, originRoute) {
- // Attempt to find an appropriate loading substate to enter.
- var router = originRoute.router;
-
- var tryTopLevel = forEachRouteAbove(originRoute, transition, function(route, childRoute) {
- var childLoadingRouteName = findChildRouteName(route, childRoute, 'loading');
-
- if (childLoadingRouteName) {
- router.intermediateTransitionTo(childLoadingRouteName);
- return;
- }
-
- // Don't bubble above pivot route.
- if (transition.pivotHandler !== route) {
- return true;
- }
- });
-
- if (tryTopLevel) {
- // Check for top-level loading state to enter.
- if (routeHasBeenDefined(originRoute.router, 'application_loading')) {
- router.intermediateTransitionTo('application_loading');
- return;
- }
- }
- }
- };
-
- function logError(error, initialMessage) {
- var errorArgs = [];
-
- if (initialMessage) { errorArgs.push(initialMessage); }
-
- if (error) {
- if (error.message) { errorArgs.push(error.message); }
- if (error.stack) { errorArgs.push(error.stack); }
-
- if (typeof error === "string") { errorArgs.push(error); }
- }
-
- Ember.Logger.error.apply(this, errorArgs);
- }
-
- function findChildRouteName(parentRoute, originatingChildRoute, name) {
- var router = parentRoute.router;
- var childName;
- var targetChildRouteName = originatingChildRoute.routeName.split('.').pop();
- var namespace = parentRoute.routeName === 'application' ? '' : parentRoute.routeName + '.';
-
-
- // Second, try general loading state, e.g. 'loading'
- childName = namespace + name;
- if (routeHasBeenDefined(router, childName)) {
- return childName;
- }
- }
-
- function routeHasBeenDefined(router, name) {
- var container = router.container;
- return router.hasRoute(name) &&
- (container.has('template:' + name) || container.has('route:' + name));
- }
-
- function triggerEvent(handlerInfos, ignoreFailure, args) {
- var name = args.shift();
-
- if (!handlerInfos) {
- if (ignoreFailure) { return; }
- throw new EmberError("Can't trigger action '" + name + "' because your app hasn't finished transitioning into its first route. To trigger an action on destination routes during a transition, you can call `.send()` on the `Transition` object passed to the `model/beforeModel/afterModel` hooks.");
- }
-
- var eventWasHandled = false;
- var handlerInfo, handler;
-
- for (var i = handlerInfos.length - 1; i >= 0; i--) {
- handlerInfo = handlerInfos[i];
- handler = handlerInfo.handler;
-
- if (handler._actions && handler._actions[name]) {
- if (handler._actions[name].apply(handler, args) === true) {
- eventWasHandled = true;
- } else {
- return;
- }
- }
- }
-
- if (defaultActionHandlers[name]) {
- defaultActionHandlers[name].apply(null, args);
- return;
- }
-
- if (!eventWasHandled && !ignoreFailure) {
- throw new EmberError("Nothing handled the action '" + name + "'. If you did handle the action, this error can be caused by returning true from an action handler in a controller, causing the action to bubble.");
- }
- }
-
- function calculatePostTransitionState(emberRouter, leafRouteName, contexts) {
- var routerjs = emberRouter.router;
- var state = routerjs.applyIntent(leafRouteName, contexts);
- var handlerInfos = state.handlerInfos;
- var params = state.params;
-
- for (var i = 0, len = handlerInfos.length; i < len; ++i) {
- var handlerInfo = handlerInfos[i];
- if (!handlerInfo.isResolved) {
- handlerInfo = handlerInfo.becomeResolved(null, handlerInfo.context);
- }
- params[handlerInfo.name] = handlerInfo.params;
- }
- return state;
- }
-
- function updatePaths(router) {
- var appController = router.container.lookup('controller:application');
-
- if (!appController) {
- // appController might not exist when top-level loading/error
- // substates have been entered since ApplicationRoute hasn't
- // actually been entered at that point.
- return;
- }
-
- var infos = router.router.currentHandlerInfos;
- var path = EmberRouter._routePath(infos);
-
- if (!('currentPath' in appController)) {
- defineProperty(appController, 'currentPath');
- }
-
- set(appController, 'currentPath', path);
-
- if (!('currentRouteName' in appController)) {
- defineProperty(appController, 'currentRouteName');
- }
-
- set(appController, 'currentRouteName', infos[infos.length - 1].name);
- }
-
- EmberRouter.reopenClass({
- router: null,
-
- /**
- The `Router.map` function allows you to define mappings from URLs to routes
- and resources in your application. These mappings are defined within the
- supplied callback function using `this.resource` and `this.route`.
-
- ```javascript
- App.Router.map(function({
- this.route('about');
- this.resource('article');
- }));
- ```
-
- For more detailed examples please see
- [the guides](http://emberjs.com/guides/routing/defining-your-routes/).
-
- @method map
- @param callback
- */
- map: function(callback) {
- var router = this.router;
- if (!router) {
- router = new Router();
-
-
- router._triggerWillChangeContext = Ember.K;
- router._triggerWillLeave = Ember.K;
-
-
- router.callbacks = [];
- router.triggerEvent = triggerEvent;
- this.reopenClass({ router: router });
- }
-
- var dsl = EmberRouterDSL.map(function() {
- this.resource('application', { path: "/" }, function() {
- for (var i=0; i < router.callbacks.length; i++) {
- router.callbacks[i].call(this);
- }
- callback.call(this);
- });
- });
-
- router.callbacks.push(callback);
- router.map(dsl.generate());
- return router;
- },
-
- _routePath: function(handlerInfos) {
- var path = [];
-
- // We have to handle coalescing resource names that
- // are prefixed with their parent's names, e.g.
- // ['foo', 'foo.bar.baz'] => 'foo.bar.baz', not 'foo.foo.bar.baz'
-
- function intersectionMatches(a1, a2) {
- for (var i = 0, len = a1.length; i < len; ++i) {
- if (a1[i] !== a2[i]) {
- return false;
- }
- }
- return true;
- }
-
- var name, nameParts, oldNameParts;
- for (var i=1, l=handlerInfos.length; i<l; i++) {
- name = handlerInfos[i].name;
- nameParts = name.split(".");
- oldNameParts = slice.call(path);
-
- while (oldNameParts.length) {
- if (intersectionMatches(oldNameParts, nameParts)) {
- break;
- }
- oldNameParts.shift();
- }
-
- path.push.apply(path, nameParts.slice(oldNameParts.length));
- }
-
- return path.join(".");
- }
- });
-
- function listenForTransitionErrors(transition) {
- transition.then(null, function(error) {
- if (!error || !error.name) { return; }
-
- if (error.name === "UnrecognizedURLError") {
- Ember.assert("The URL '" + error.message + "' did not match any routes in your application");
- }
- return error;
- }, 'Ember: Process errors from Router');
- }
-
- function resemblesURL(str) {
- return typeof str === 'string' && ( str === '' || str.charAt(0) === '/');
- }
-
- function forEachQueryParam(router, targetRouteName, queryParams, callback) {
- var qpCache = router._queryParamsFor(targetRouteName);
-
- for (var key in queryParams) {
- if (!queryParams.hasOwnProperty(key)) { continue; }
- var value = queryParams[key];
- var qp = qpCache.map[key];
-
- if (qp) {
- callback(key, value, qp);
- }
- }
- }
-
- __exports__["default"] = EmberRouter;
- });
-enifed("ember-routing/utils",
- ["ember-metal/utils","exports"],
- function(__dependency1__, __exports__) {
- "use strict";
- var typeOf = __dependency1__.typeOf;
-
- function routeArgs(targetRouteName, models, queryParams) {
- var args = [];
- if (typeOf(targetRouteName) === 'string') {
- args.push('' + targetRouteName);
- }
- args.push.apply(args, models);
- args.push({ queryParams: queryParams });
- return args;
- }
-
- __exports__.routeArgs = routeArgs;function getActiveTargetName(router) {
- var handlerInfos = router.activeTransition ?
- router.activeTransition.state.handlerInfos :
- router.state.handlerInfos;
- return handlerInfos[handlerInfos.length - 1].name;
- }
-
- __exports__.getActiveTargetName = getActiveTargetName;function stashParamNames(router, handlerInfos) {
- if (handlerInfos._namesStashed) { return; }
-
- // This helper exists because router.js/route-recognizer.js awkwardly
- // keeps separate a handlerInfo's list of parameter names depending
- // on whether a URL transition or named transition is happening.
- // Hopefully we can remove this in the future.
- var targetRouteName = handlerInfos[handlerInfos.length-1].name;
- var recogHandlers = router.router.recognizer.handlersFor(targetRouteName);
- var dynamicParent = null;
-
- for (var i = 0, len = handlerInfos.length; i < len; ++i) {
- var handlerInfo = handlerInfos[i];
- var names = recogHandlers[i].names;
-
- if (names.length) {
- dynamicParent = handlerInfo;
- }
-
- handlerInfo._names = names;
-
- var route = handlerInfo.handler;
- route._stashNames(handlerInfo, dynamicParent);
- }
-
- handlerInfos._namesStashed = true;
- }
-
- __exports__.stashParamNames = stashParamNames;
- });
-enifed("ember-runtime",
- ["ember-metal","ember-runtime/core","ember-runtime/compare","ember-runtime/copy","ember-runtime/inject","ember-runtime/system/namespace","ember-runtime/system/object","ember-runtime/system/tracked_array","ember-runtime/system/subarray","ember-runtime/system/container","ember-runtime/system/array_proxy","ember-runtime/system/object_proxy","ember-runtime/system/core_object","ember-runtime/system/each_proxy","ember-runtime/system/native_array","ember-runtime/system/set","ember-runtime/system/string","ember-runtime/system/deferred","ember-runtime/system/lazy_load","ember-runtime/mixins/array","ember-runtime/mixins/comparable","ember-runtime/mixins/copyable","ember-runtime/mixins/enumerable","ember-runtime/mixins/freezable","ember-runtime/mixins/-proxy","ember-runtime/mixins/observable","ember-runtime/mixins/action_handler","ember-runtime/mixins/deferred","ember-runtime/mixins/mutable_enumerable","ember-runtime/mixins/mutable_array","ember-runtime/mixins/target_action_support","ember-runtime/mixins/evented","ember-runtime/mixins/promise_proxy","ember-runtime/mixins/sortable","ember-runtime/computed/array_computed","ember-runtime/computed/reduce_computed","ember-runtime/computed/reduce_computed_macros","ember-runtime/controllers/array_controller","ember-runtime/controllers/object_controller","ember-runtime/controllers/controller","ember-runtime/mixins/controller","ember-runtime/system/service","ember-runtime/ext/rsvp","ember-runtime/ext/string","ember-runtime/ext/function","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__, __dependency28__, __dependency29__, __dependency30__, __dependency31__, __dependency32__, __dependency33__, __dependency34__, __dependency35__, __dependency36__, __dependency37__, __dependency38__, __dependency39__, __dependency40__, __dependency41__, __dependency42__, __dependency43__, __dependency44__, __dependency45__, __exports__) {
- "use strict";
- /**
- Ember Runtime
-
- @module ember
- @submodule ember-runtime
- @requires ember-metal
- */
-
- // BEGIN IMPORTS
- var Ember = __dependency1__["default"];
- var isEqual = __dependency2__.isEqual;
- var compare = __dependency3__["default"];
- var copy = __dependency4__["default"];
- var inject = __dependency5__["default"];
-
- var Namespace = __dependency6__["default"];
- var EmberObject = __dependency7__["default"];
- var TrackedArray = __dependency8__["default"];
- var SubArray = __dependency9__["default"];
- var Container = __dependency10__["default"];
- var ArrayProxy = __dependency11__["default"];
- var ObjectProxy = __dependency12__["default"];
- var CoreObject = __dependency13__["default"];
- var EachArray = __dependency14__.EachArray;
- var EachProxy = __dependency14__.EachProxy;
-
- var NativeArray = __dependency15__["default"];
- var Set = __dependency16__["default"];
- var EmberStringUtils = __dependency17__["default"];
- var Deferred = __dependency18__["default"];
- var onLoad = __dependency19__.onLoad;
- var runLoadHooks = __dependency19__.runLoadHooks;
-
- var EmberArray = __dependency20__["default"];
- var Comparable = __dependency21__["default"];
- var Copyable = __dependency22__["default"];
- var Enumerable = __dependency23__["default"];
- var Freezable = __dependency24__.Freezable;
- var FROZEN_ERROR = __dependency24__.FROZEN_ERROR;
- var _ProxyMixin = __dependency25__["default"];
-
- var Observable = __dependency26__["default"];
- var ActionHandler = __dependency27__["default"];
- var DeferredMixin = __dependency28__["default"];
- var MutableEnumerable = __dependency29__["default"];
- var MutableArray = __dependency30__["default"];
- var TargetActionSupport = __dependency31__["default"];
- var Evented = __dependency32__["default"];
- var PromiseProxyMixin = __dependency33__["default"];
- var SortableMixin = __dependency34__["default"];
- var arrayComputed = __dependency35__.arrayComputed;
- var ArrayComputedProperty = __dependency35__.ArrayComputedProperty;
-
- var reduceComputed = __dependency36__.reduceComputed;
- var ReduceComputedProperty = __dependency36__.ReduceComputedProperty;
-
- var sum = __dependency37__.sum;
- var min = __dependency37__.min;
- var max = __dependency37__.max;
- var map = __dependency37__.map;
- var sort = __dependency37__.sort;
- var setDiff = __dependency37__.setDiff;
- var mapBy = __dependency37__.mapBy;
- var mapProperty = __dependency37__.mapProperty;
- var filter = __dependency37__.filter;
- var filterBy = __dependency37__.filterBy;
- var filterProperty = __dependency37__.filterProperty;
- var uniq = __dependency37__.uniq;
- var union = __dependency37__.union;
- var intersect = __dependency37__.intersect;
-
- var ArrayController = __dependency38__["default"];
- var ObjectController = __dependency39__["default"];
- var Controller = __dependency40__["default"];
- var ControllerMixin = __dependency41__["default"];
-
- var Service = __dependency42__["default"];
-
- var RSVP = __dependency43__["default"];
- // just for side effect of extending Ember.RSVP
- // just for side effect of extending String.prototype
- // just for side effect of extending Function.prototype
- // END IMPORTS
-
- // BEGIN EXPORTS
- Ember.compare = compare;
- Ember.copy = copy;
- Ember.isEqual = isEqual;
-
-
- Ember.Array = EmberArray;
-
- Ember.Comparable = Comparable;
- Ember.Copyable = Copyable;
-
- Ember.SortableMixin = SortableMixin;
-
- Ember.Freezable = Freezable;
- Ember.FROZEN_ERROR = FROZEN_ERROR;
-
- Ember.DeferredMixin = DeferredMixin;
-
- Ember.MutableEnumerable = MutableEnumerable;
- Ember.MutableArray = MutableArray;
-
- Ember.TargetActionSupport = TargetActionSupport;
- Ember.Evented = Evented;
-
- Ember.PromiseProxyMixin = PromiseProxyMixin;
-
- Ember.Observable = Observable;
-
- Ember.arrayComputed = arrayComputed;
- Ember.ArrayComputedProperty = ArrayComputedProperty;
- Ember.reduceComputed = reduceComputed;
- Ember.ReduceComputedProperty = ReduceComputedProperty;
-
- // ES6TODO: this seems a less than ideal way/place to add properties to Ember.computed
- var EmComputed = Ember.computed;
-
- EmComputed.sum = sum;
- EmComputed.min = min;
- EmComputed.max = max;
- EmComputed.map = map;
- EmComputed.sort = sort;
- EmComputed.setDiff = setDiff;
- EmComputed.mapBy = mapBy;
- EmComputed.mapProperty = mapProperty;
- EmComputed.filter = filter;
- EmComputed.filterBy = filterBy;
- EmComputed.filterProperty = filterProperty;
- EmComputed.uniq = uniq;
- EmComputed.union = union;
- EmComputed.intersect = intersect;
-
- Ember.String = EmberStringUtils;
- Ember.Object = EmberObject;
- Ember.TrackedArray = TrackedArray;
- Ember.SubArray = SubArray;
- Ember.Container = Container;
- Ember.Namespace = Namespace;
- Ember.Enumerable = Enumerable;
- Ember.ArrayProxy = ArrayProxy;
- Ember.ObjectProxy = ObjectProxy;
- Ember.ActionHandler = ActionHandler;
- Ember.CoreObject = CoreObject;
- Ember.EachArray = EachArray;
- Ember.EachProxy = EachProxy;
- Ember.NativeArray = NativeArray;
- // ES6TODO: Currently we must rely on the global from ember-metal/core to avoid circular deps
- // Ember.A = A;
- Ember.Set = Set;
- Ember.Deferred = Deferred;
- Ember.onLoad = onLoad;
- Ember.runLoadHooks = runLoadHooks;
-
- Ember.ArrayController = ArrayController;
- Ember.ObjectController = ObjectController;
- Ember.Controller = Controller;
- Ember.ControllerMixin = ControllerMixin;
-
-
- Ember._ProxyMixin = _ProxyMixin;
-
- Ember.RSVP = RSVP;
- // END EXPORTS
-
- __exports__["default"] = Ember;
- });
-enifed("ember-runtime/compare",
- ["ember-metal/utils","ember-runtime/mixins/comparable","exports"],
- function(__dependency1__, __dependency2__, __exports__) {
- "use strict";
- var typeOf = __dependency1__.typeOf;
- var Comparable = __dependency2__["default"];
-
- var TYPE_ORDER = {
- 'undefined': 0,
- 'null': 1,
- 'boolean': 2,
- 'number': 3,
- 'string': 4,
- 'array': 5,
- 'object': 6,
- 'instance': 7,
- 'function': 8,
- 'class': 9,
- 'date': 10
- };
-
- //
- // the spaceship operator
- //
- function spaceship(a, b) {
- var diff = a - b;
- return (diff > 0) - (diff < 0);
- }
-
- /**
- This will compare two javascript values of possibly different types.
- It will tell you which one is greater than the other by returning:
-
- - -1 if the first is smaller than the second,
- - 0 if both are equal,
- - 1 if the first is greater than the second.
-
- The order is calculated based on `Ember.ORDER_DEFINITION`, if types are different.
- In case they have the same type an appropriate comparison for this type is made.
-
- ```javascript
- Ember.compare('hello', 'hello'); // 0
- Ember.compare('abc', 'dfg'); // -1
- Ember.compare(2, 1); // 1
- ```
-
- @method compare
- @for Ember
- @param {Object} v First value to compare
- @param {Object} w Second value to compare
- @return {Number} -1 if v < w, 0 if v = w and 1 if v > w.
- */
- __exports__["default"] = function compare(v, w) {
- if (v === w) {
- return 0;
- }
-
- var type1 = typeOf(v);
- var type2 = typeOf(w);
-
- if (Comparable) {
- if (type1 ==='instance' && Comparable.detect(v.constructor)) {
- return v.constructor.compare(v, w);
- }
-
- if (type2 === 'instance' && Comparable.detect(w.constructor)) {
- return 1 - w.constructor.compare(w, v);
- }
- }
-
- var res = spaceship(TYPE_ORDER[type1], TYPE_ORDER[type2]);
- if (res !== 0) {
- return res;
- }
-
- // types are equal - so we have to check values now
- switch (type1) {
- case 'boolean':
- case 'number':
- return spaceship(v,w);
-
- case 'string':
- return spaceship(v.localeCompare(w), 0);
-
- case 'array':
- var vLen = v.length;
- var wLen = w.length;
- var len = Math.min(vLen, wLen);
-
- for (var i = 0; i < len; i++) {
- var r = compare(v[i], w[i]);
- if (r !== 0) {
- return r;
- }
- }
-
- // all elements are equal now
- // shorter array should be ordered first
- return spaceship(vLen, wLen);
-
- case 'instance':
- if (Comparable && Comparable.detect(v)) {
- return v.compare(v, w);
- }
- return 0;
-
- case 'date':
- return spaceship(v.getTime(), w.getTime());
-
- default:
- return 0;
- }
- }
- });
-enifed("ember-runtime/computed/array_computed",
- ["ember-metal/core","ember-runtime/computed/reduce_computed","ember-metal/enumerable_utils","ember-metal/platform","ember-metal/observer","ember-metal/error","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __exports__) {
- "use strict";
- var Ember = __dependency1__["default"];
- var ReduceComputedProperty = __dependency2__.ReduceComputedProperty;
- var forEach = __dependency3__.forEach;
- var o_create = __dependency4__.create;
- var addObserver = __dependency5__.addObserver;
- var EmberError = __dependency6__["default"];
-
- var a_slice = [].slice;
-
- function ArrayComputedProperty() {
- var cp = this;
-
- ReduceComputedProperty.apply(this, arguments);
-
- this.func = (function(reduceFunc) {
- return function (propertyName) {
- if (!cp._hasInstanceMeta(this, propertyName)) {
- // When we recompute an array computed property, we need already
- // retrieved arrays to be updated; we can't simply empty the cache and
- // hope the array is re-retrieved.
- forEach(cp._dependentKeys, function(dependentKey) {
- addObserver(this, dependentKey, function() {
- cp.recomputeOnce.call(this, propertyName);
- });
- }, this);
- }
-
- return reduceFunc.apply(this, arguments);
- };
- })(this.func);
-
- return this;
- }
-
- ArrayComputedProperty.prototype = o_create(ReduceComputedProperty.prototype);
-
- ArrayComputedProperty.prototype.initialValue = function () {
- return Ember.A();
- };
-
- ArrayComputedProperty.prototype.resetValue = function (array) {
- array.clear();
- return array;
- };
-
- // This is a stopgap to keep the reference counts correct with lazy CPs.
- ArrayComputedProperty.prototype.didChange = function (obj, keyName) {
- return;
- };
-
- /**
- Creates a computed property which operates on dependent arrays and
- is updated with "one at a time" semantics. When items are added or
- removed from the dependent array(s) an array computed only operates
- on the change instead of re-evaluating the entire array. This should
- return an array, if you'd like to use "one at a time" semantics and
- compute some value other then an array look at
- `Ember.reduceComputed`.
-
- If there are more than one arguments the first arguments are
- considered to be dependent property keys. The last argument is
- required to be an options object. The options object can have the
- following three properties.
-
- `initialize` - An optional initialize function. Typically this will be used
- to set up state on the instanceMeta object.
-
- `removedItem` - A function that is called each time an element is
- removed from the array.
-
- `addedItem` - A function that is called each time an element is
- added to the array.
-
-
- The `initialize` function has the following signature:
-
- ```javascript
- function(array, changeMeta, instanceMeta)
- ```
-
- `array` - The initial value of the arrayComputed, an empty array.
-
- `changeMeta` - An object which contains meta information about the
- computed. It contains the following properties:
-
- - `property` the computed property
- - `propertyName` the name of the property on the object
-
- `instanceMeta` - An object that can be used to store meta
- information needed for calculating your computed. For example a
- unique computed might use this to store the number of times a given
- element is found in the dependent array.
-
-
- The `removedItem` and `addedItem` functions both have the following signature:
-
- ```javascript
- function(accumulatedValue, item, changeMeta, instanceMeta)
- ```
-
- `accumulatedValue` - The value returned from the last time
- `removedItem` or `addedItem` was called or an empty array.
-
- `item` - the element added or removed from the array
-
- `changeMeta` - An object which contains meta information about the
- change. It contains the following properties:
-
- - `property` the computed property
- - `propertyName` the name of the property on the object
- - `index` the index of the added or removed item
- - `item` the added or removed item: this is exactly the same as
- the second arg
- - `arrayChanged` the array that triggered the change. Can be
- useful when depending on multiple arrays.
-
- For property changes triggered on an item property change (when
- depKey is something like `someArray.@each.someProperty`),
- `changeMeta` will also contain the following property:
-
- - `previousValues` an object whose keys are the properties that changed on
- the item, and whose values are the item's previous values.
-
- `previousValues` is important Ember coalesces item property changes via
- Ember.run.once. This means that by the time removedItem gets called, item has
- the new values, but you may need the previous value (eg for sorting &
- filtering).
-
- `instanceMeta` - An object that can be used to store meta
- information needed for calculating your computed. For example a
- unique computed might use this to store the number of times a given
- element is found in the dependent array.
-
- The `removedItem` and `addedItem` functions should return the accumulated
- value. It is acceptable to not return anything (ie return undefined)
- to invalidate the computation. This is generally not a good idea for
- arrayComputed but it's used in eg max and min.
-
- Example
-
- ```javascript
- Ember.computed.map = function(dependentKey, callback) {
- var options = {
- addedItem: function(array, item, changeMeta, instanceMeta) {
- var mapped = callback(item);
- array.insertAt(changeMeta.index, mapped);
- return array;
- },
- removedItem: function(array, item, changeMeta, instanceMeta) {
- array.removeAt(changeMeta.index, 1);
- return array;
- }
- };
-
- return Ember.arrayComputed(dependentKey, options);
- };
- ```
-
- @method arrayComputed
- @for Ember
- @param {String} [dependentKeys*]
- @param {Object} options
- @return {Ember.ComputedProperty}
- */
- function arrayComputed (options) {
- var args;
-
- if (arguments.length > 1) {
- args = a_slice.call(arguments, 0, -1);
- options = a_slice.call(arguments, -1)[0];
- }
-
- if (typeof options !== 'object') {
- throw new EmberError('Array Computed Property declared without an options hash');
- }
-
- var cp = new ArrayComputedProperty(options);
-
- if (args) {
- cp.property.apply(cp, args);
- }
-
- return cp;
- }
-
- __exports__.arrayComputed = arrayComputed;
- __exports__.ArrayComputedProperty = ArrayComputedProperty;
- });
-enifed("ember-runtime/computed/reduce_computed",
- ["ember-metal/core","ember-metal/property_get","ember-metal/utils","ember-metal/error","ember-metal/property_events","ember-metal/expand_properties","ember-metal/observer","ember-metal/computed","ember-metal/platform","ember-metal/enumerable_utils","ember-runtime/system/tracked_array","ember-runtime/mixins/array","ember-metal/run_loop","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __exports__) {
- "use strict";
- var Ember = __dependency1__["default"];
- // Ember.assert
- var e_get = __dependency2__.get;
- var guidFor = __dependency3__.guidFor;
- var metaFor = __dependency3__.meta;
- var EmberError = __dependency4__["default"];
- var propertyWillChange = __dependency5__.propertyWillChange;
- var propertyDidChange = __dependency5__.propertyDidChange;
- var expandProperties = __dependency6__["default"];
- var addObserver = __dependency7__.addObserver;
- var removeObserver = __dependency7__.removeObserver;
- var addBeforeObserver = __dependency7__.addBeforeObserver;
- var removeBeforeObserver = __dependency7__.removeBeforeObserver;
- var ComputedProperty = __dependency8__.ComputedProperty;
- var cacheFor = __dependency8__.cacheFor;
- var o_create = __dependency9__.create;
- var forEach = __dependency10__.forEach;
- var TrackedArray = __dependency11__["default"];
- var EmberArray = __dependency12__["default"];
- var run = __dependency13__["default"];
- var isArray = __dependency3__.isArray;
-
- var cacheSet = cacheFor.set;
- var cacheGet = cacheFor.get;
- var cacheRemove = cacheFor.remove;
- var a_slice = [].slice;
- // Here we explicitly don't allow `@each.foo`; it would require some special
- // testing, but there's no particular reason why it should be disallowed.
- var eachPropertyPattern = /^(.*)\.@each\.(.*)/;
- var doubleEachPropertyPattern = /(.*\.@each){2,}/;
- var arrayBracketPattern = /\.\[\]$/;
-
- function get(obj, key) {
- if (key === '@this') {
- return obj;
- }
-
- return e_get(obj, key);
- }
-
- /*
- Tracks changes to dependent arrays, as well as to properties of items in
- dependent arrays.
-
- @class DependentArraysObserver
- */
- function DependentArraysObserver(callbacks, cp, instanceMeta, context, propertyName, sugarMeta) {
- // user specified callbacks for `addedItem` and `removedItem`
- this.callbacks = callbacks;
-
- // the computed property: remember these are shared across instances
- this.cp = cp;
-
- // the ReduceComputedPropertyInstanceMeta this DependentArraysObserver is
- // associated with
- this.instanceMeta = instanceMeta;
-
- // A map of array guids to dependentKeys, for the given context. We track
- // this because we want to set up the computed property potentially before the
- // dependent array even exists, but when the array observer fires, we lack
- // enough context to know what to update: we can recover that context by
- // getting the dependentKey.
- this.dependentKeysByGuid = {};
-
- // a map of dependent array guids -> TrackedArray instances. We use
- // this to lazily recompute indexes for item property observers.
- this.trackedArraysByGuid = {};
-
- // We suspend observers to ignore replacements from `reset` when totally
- // recomputing. Unfortunately we cannot properly suspend the observers
- // because we only have the key; instead we make the observers no-ops
- this.suspended = false;
-
- // This is used to coalesce item changes from property observers within a
- // single item.
- this.changedItems = {};
- // This is used to coalesce item changes for multiple items that depend on
- // some shared state.
- this.changedItemCount = 0;
- }
-
- function ItemPropertyObserverContext (dependentArray, index, trackedArray) {
- Ember.assert('Internal error: trackedArray is null or undefined', trackedArray);
-
- this.dependentArray = dependentArray;
- this.index = index;
- this.item = dependentArray.objectAt(index);
- this.trackedArray = trackedArray;
- this.beforeObserver = null;
- this.observer = null;
- this.destroyed = false;
- }
-
- DependentArraysObserver.prototype = {
- setValue: function (newValue) {
- this.instanceMeta.setValue(newValue, true);
- },
-
- getValue: function () {
- return this.instanceMeta.getValue();
- },
-
- setupObservers: function (dependentArray, dependentKey) {
- this.dependentKeysByGuid[guidFor(dependentArray)] = dependentKey;
-
- dependentArray.addArrayObserver(this, {
- willChange: 'dependentArrayWillChange',
- didChange: 'dependentArrayDidChange'
- });
-
- if (this.cp._itemPropertyKeys[dependentKey]) {
- this.setupPropertyObservers(dependentKey, this.cp._itemPropertyKeys[dependentKey]);
- }
- },
-
- teardownObservers: function (dependentArray, dependentKey) {
- var itemPropertyKeys = this.cp._itemPropertyKeys[dependentKey] || [];
-
- delete this.dependentKeysByGuid[guidFor(dependentArray)];
-
- this.teardownPropertyObservers(dependentKey, itemPropertyKeys);
-
- dependentArray.removeArrayObserver(this, {
- willChange: 'dependentArrayWillChange',
- didChange: 'dependentArrayDidChange'
- });
- },
-
- suspendArrayObservers: function (callback, binding) {
- var oldSuspended = this.suspended;
- this.suspended = true;
- callback.call(binding);
- this.suspended = oldSuspended;
- },
-
- setupPropertyObservers: function (dependentKey, itemPropertyKeys) {
- var dependentArray = get(this.instanceMeta.context, dependentKey);
- var length = get(dependentArray, 'length');
- var observerContexts = new Array(length);
-
- this.resetTransformations(dependentKey, observerContexts);
-
- forEach(dependentArray, function (item, index) {
- var observerContext = this.createPropertyObserverContext(dependentArray, index, this.trackedArraysByGuid[dependentKey]);
- observerContexts[index] = observerContext;
-
- forEach(itemPropertyKeys, function (propertyKey) {
- addBeforeObserver(item, propertyKey, this, observerContext.beforeObserver);
- addObserver(item, propertyKey, this, observerContext.observer);
- }, this);
- }, this);
- },
-
- teardownPropertyObservers: function (dependentKey, itemPropertyKeys) {
- var dependentArrayObserver = this;
- var trackedArray = this.trackedArraysByGuid[dependentKey];
- var beforeObserver, observer, item;
-
- if (!trackedArray) { return; }
-
- trackedArray.apply(function (observerContexts, offset, operation) {
- if (operation === TrackedArray.DELETE) { return; }
-
- forEach(observerContexts, function (observerContext) {
- observerContext.destroyed = true;
- beforeObserver = observerContext.beforeObserver;
- observer = observerContext.observer;
- item = observerContext.item;
-
- forEach(itemPropertyKeys, function (propertyKey) {
- removeBeforeObserver(item, propertyKey, dependentArrayObserver, beforeObserver);
- removeObserver(item, propertyKey, dependentArrayObserver, observer);
- });
- });
- });
- },
-
- createPropertyObserverContext: function (dependentArray, index, trackedArray) {
- var observerContext = new ItemPropertyObserverContext(dependentArray, index, trackedArray);
-
- this.createPropertyObserver(observerContext);
-
- return observerContext;
- },
-
- createPropertyObserver: function (observerContext) {
- var dependentArrayObserver = this;
-
- observerContext.beforeObserver = function (obj, keyName) {
- return dependentArrayObserver.itemPropertyWillChange(obj, keyName, observerContext.dependentArray, observerContext);
- };
-
- observerContext.observer = function (obj, keyName) {
- return dependentArrayObserver.itemPropertyDidChange(obj, keyName, observerContext.dependentArray, observerContext);
- };
- },
-
- resetTransformations: function (dependentKey, observerContexts) {
- this.trackedArraysByGuid[dependentKey] = new TrackedArray(observerContexts);
- },
-
- trackAdd: function (dependentKey, index, newItems) {
- var trackedArray = this.trackedArraysByGuid[dependentKey];
-
- if (trackedArray) {
- trackedArray.addItems(index, newItems);
- }
- },
-
- trackRemove: function (dependentKey, index, removedCount) {
- var trackedArray = this.trackedArraysByGuid[dependentKey];
-
- if (trackedArray) {
- return trackedArray.removeItems(index, removedCount);
- }
-
- return [];
- },
-
- updateIndexes: function (trackedArray, array) {
- var length = get(array, 'length');
- // OPTIMIZE: we could stop updating once we hit the object whose observer
- // fired; ie partially apply the transformations
- trackedArray.apply(function (observerContexts, offset, operation, operationIndex) {
- // we don't even have observer contexts for removed items, even if we did,
- // they no longer have any index in the array
- if (operation === TrackedArray.DELETE) { return; }
- if (operationIndex === 0 && operation === TrackedArray.RETAIN && observerContexts.length === length && offset === 0) {
- // If we update many items we don't want to walk the array each time: we
- // only need to update the indexes at most once per run loop.
- return;
- }
-
- forEach(observerContexts, function (context, index) {
- context.index = index + offset;
- });
- });
- },
-
- dependentArrayWillChange: function (dependentArray, index, removedCount, addedCount) {
- if (this.suspended) { return; }
-
- var removedItem = this.callbacks.removedItem;
- var changeMeta;
- var guid = guidFor(dependentArray);
- var dependentKey = this.dependentKeysByGuid[guid];
- var itemPropertyKeys = this.cp._itemPropertyKeys[dependentKey] || [];
- var length = get(dependentArray, 'length');
- var normalizedIndex = normalizeIndex(index, length, 0);
- var normalizedRemoveCount = normalizeRemoveCount(normalizedIndex, length, removedCount);
- var item, itemIndex, sliceIndex, observerContexts;
-
- observerContexts = this.trackRemove(dependentKey, normalizedIndex, normalizedRemoveCount);
-
- function removeObservers(propertyKey) {
- observerContexts[sliceIndex].destroyed = true;
- removeBeforeObserver(item, propertyKey, this, observerContexts[sliceIndex].beforeObserver);
- removeObserver(item, propertyKey, this, observerContexts[sliceIndex].observer);
- }
-
- for (sliceIndex = normalizedRemoveCount - 1; sliceIndex >= 0; --sliceIndex) {
- itemIndex = normalizedIndex + sliceIndex;
- if (itemIndex >= length) { break; }
-
- item = dependentArray.objectAt(itemIndex);
-
- forEach(itemPropertyKeys, removeObservers, this);
-
- changeMeta = new ChangeMeta(dependentArray, item, itemIndex, this.instanceMeta.propertyName, this.cp, normalizedRemoveCount);
- this.setValue(removedItem.call(
- this.instanceMeta.context, this.getValue(), item, changeMeta, this.instanceMeta.sugarMeta));
- }
- this.callbacks.flushedChanges.call(this.instanceMeta.context, this.getValue(), this.instanceMeta.sugarMeta);
- },
-
- dependentArrayDidChange: function (dependentArray, index, removedCount, addedCount) {
- if (this.suspended) { return; }
-
- var addedItem = this.callbacks.addedItem;
- var guid = guidFor(dependentArray);
- var dependentKey = this.dependentKeysByGuid[guid];
- var observerContexts = new Array(addedCount);
- var itemPropertyKeys = this.cp._itemPropertyKeys[dependentKey];
- var length = get(dependentArray, 'length');
- var normalizedIndex = normalizeIndex(index, length, addedCount);
- var endIndex = normalizedIndex + addedCount;
- var changeMeta, observerContext;
-
- forEach(dependentArray.slice(normalizedIndex, endIndex), function (item, sliceIndex) {
- if (itemPropertyKeys) {
- observerContext = this.createPropertyObserverContext(dependentArray, normalizedIndex + sliceIndex,
- this.trackedArraysByGuid[dependentKey]);
- observerContexts[sliceIndex] = observerContext;
-
- forEach(itemPropertyKeys, function (propertyKey) {
- addBeforeObserver(item, propertyKey, this, observerContext.beforeObserver);
- addObserver(item, propertyKey, this, observerContext.observer);
- }, this);
- }
-
- changeMeta = new ChangeMeta(dependentArray, item, normalizedIndex + sliceIndex, this.instanceMeta.propertyName, this.cp, addedCount);
- this.setValue(addedItem.call(
- this.instanceMeta.context, this.getValue(), item, changeMeta, this.instanceMeta.sugarMeta));
- }, this);
- this.callbacks.flushedChanges.call(this.instanceMeta.context, this.getValue(), this.instanceMeta.sugarMeta);
- this.trackAdd(dependentKey, normalizedIndex, observerContexts);
- },
-
- itemPropertyWillChange: function (obj, keyName, array, observerContext) {
- var guid = guidFor(obj);
-
- if (!this.changedItems[guid]) {
- this.changedItems[guid] = {
- array: array,
- observerContext: observerContext,
- obj: obj,
- previousValues: {}
- };
- }
-
- ++this.changedItemCount;
- this.changedItems[guid].previousValues[keyName] = get(obj, keyName);
- },
-
- itemPropertyDidChange: function (obj, keyName, array, observerContext) {
- if (--this.changedItemCount === 0) {
- this.flushChanges();
- }
- },
-
- flushChanges: function () {
- var changedItems = this.changedItems;
- var key, c, changeMeta;
-
- for (key in changedItems) {
- c = changedItems[key];
- if (c.observerContext.destroyed) { continue; }
-
- this.updateIndexes(c.observerContext.trackedArray, c.observerContext.dependentArray);
-
- changeMeta = new ChangeMeta(c.array, c.obj, c.observerContext.index, this.instanceMeta.propertyName, this.cp, changedItems.length, c.previousValues);
- this.setValue(
- this.callbacks.removedItem.call(this.instanceMeta.context, this.getValue(), c.obj, changeMeta, this.instanceMeta.sugarMeta));
- this.setValue(
- this.callbacks.addedItem.call(this.instanceMeta.context, this.getValue(), c.obj, changeMeta, this.instanceMeta.sugarMeta));
- }
-
- this.changedItems = {};
- this.callbacks.flushedChanges.call(this.instanceMeta.context, this.getValue(), this.instanceMeta.sugarMeta);
- }
- };
-
- function normalizeIndex(index, length, newItemsOffset) {
- if (index < 0) {
- return Math.max(0, length + index);
- } else if (index < length) {
- return index;
- } else /* index > length */ {
- return Math.min(length - newItemsOffset, index);
- }
- }
-
- function normalizeRemoveCount(index, length, removedCount) {
- return Math.min(removedCount, length - index);
- }
-
- function ChangeMeta(dependentArray, item, index, propertyName, property, changedCount, previousValues){
- this.arrayChanged = dependentArray;
- this.index = index;
- this.item = item;
- this.propertyName = propertyName;
- this.property = property;
- this.changedCount = changedCount;
-
- if (previousValues) {
- // previous values only available for item property changes
- this.previousValues = previousValues;
- }
- }
-
- function addItems(dependentArray, callbacks, cp, propertyName, meta) {
- forEach(dependentArray, function (item, index) {
- meta.setValue( callbacks.addedItem.call(
- this, meta.getValue(), item, new ChangeMeta(dependentArray, item, index, propertyName, cp, dependentArray.length), meta.sugarMeta));
- }, this);
- callbacks.flushedChanges.call(this, meta.getValue(), meta.sugarMeta);
- }
-
- function reset(cp, propertyName) {
- var hadMeta = cp._hasInstanceMeta(this, propertyName);
- var meta = cp._instanceMeta(this, propertyName);
-
- if (hadMeta) { meta.setValue(cp.resetValue(meta.getValue())); }
-
- if (cp.options.initialize) {
- cp.options.initialize.call(this, meta.getValue(), {
- property: cp,
- propertyName: propertyName
- }, meta.sugarMeta);
- }
- }
-
- function partiallyRecomputeFor(obj, dependentKey) {
- if (arrayBracketPattern.test(dependentKey)) {
- return false;
- }
-
- var value = get(obj, dependentKey);
- return EmberArray.detect(value);
- }
-
- function ReduceComputedPropertyInstanceMeta(context, propertyName, initialValue) {
- this.context = context;
- this.propertyName = propertyName;
- this.cache = metaFor(context).cache;
- this.dependentArrays = {};
- this.sugarMeta = {};
- this.initialValue = initialValue;
- }
-
- ReduceComputedPropertyInstanceMeta.prototype = {
- getValue: function () {
- var value = cacheGet(this.cache, this.propertyName);
-
- if (value !== undefined) {
- return value;
- } else {
- return this.initialValue;
- }
- },
-
- setValue: function(newValue, triggerObservers) {
- // This lets sugars force a recomputation, handy for very simple
- // implementations of eg max.
- if (newValue === cacheGet(this.cache, this.propertyName)) {
- return;
- }
-
- if (triggerObservers) {
- propertyWillChange(this.context, this.propertyName);
- }
-
- if (newValue === undefined) {
- cacheRemove(this.cache, this.propertyName);
- } else {
- cacheSet(this.cache, this.propertyName, newValue);
- }
-
- if (triggerObservers) {
- propertyDidChange(this.context, this.propertyName);
- }
- }
- };
-
- /**
- A computed property whose dependent keys are arrays and which is updated with
- "one at a time" semantics.
-
- @class ReduceComputedProperty
- @namespace Ember
- @extends Ember.ComputedProperty
- @constructor
- */
-
- __exports__.ReduceComputedProperty = ReduceComputedProperty;
- // TODO: default export
-
- function ReduceComputedProperty(options) {
- var cp = this;
-
- this.options = options;
- this._dependentKeys = null;
- // A map of dependentKey -> [itemProperty, ...] that tracks what properties of
- // items in the array we must track to update this property.
- this._itemPropertyKeys = {};
- this._previousItemPropertyKeys = {};
-
- this.readOnly();
- this.cacheable();
-
- this.recomputeOnce = function(propertyName) {
- // What we really want to do is coalesce by <cp, propertyName>.
- // We need a form of `scheduleOnce` that accepts an arbitrary token to
- // coalesce by, in addition to the target and method.
- run.once(this, recompute, propertyName);
- };
-
- var recompute = function(propertyName) {
- var meta = cp._instanceMeta(this, propertyName);
- var callbacks = cp._callbacks();
-
- reset.call(this, cp, propertyName);
-
- meta.dependentArraysObserver.suspendArrayObservers(function () {
- forEach(cp._dependentKeys, function (dependentKey) {
- Ember.assert(
- 'dependent array ' + dependentKey + ' must be an `Ember.Array`. ' +
- 'If you are not extending arrays, you will need to wrap native arrays with `Ember.A`',
- !(isArray(get(this, dependentKey)) && !EmberArray.detect(get(this, dependentKey))));
-
- if (!partiallyRecomputeFor(this, dependentKey)) { return; }
-
- var dependentArray = get(this, dependentKey);
- var previousDependentArray = meta.dependentArrays[dependentKey];
-
- if (dependentArray === previousDependentArray) {
- // The array may be the same, but our item property keys may have
- // changed, so we set them up again. We can't easily tell if they've
- // changed: the array may be the same object, but with different
- // contents.
- if (cp._previousItemPropertyKeys[dependentKey]) {
- delete cp._previousItemPropertyKeys[dependentKey];
- meta.dependentArraysObserver.setupPropertyObservers(dependentKey, cp._itemPropertyKeys[dependentKey]);
- }
- } else {
- meta.dependentArrays[dependentKey] = dependentArray;
-
- if (previousDependentArray) {
- meta.dependentArraysObserver.teardownObservers(previousDependentArray, dependentKey);
- }
-
- if (dependentArray) {
- meta.dependentArraysObserver.setupObservers(dependentArray, dependentKey);
- }
- }
- }, this);
- }, this);
-
- forEach(cp._dependentKeys, function(dependentKey) {
- if (!partiallyRecomputeFor(this, dependentKey)) { return; }
-
- var dependentArray = get(this, dependentKey);
-
- if (dependentArray) {
- addItems.call(this, dependentArray, callbacks, cp, propertyName, meta);
- }
- }, this);
- };
-
-
- this.func = function (propertyName) {
- Ember.assert('Computed reduce values require at least one dependent key', cp._dependentKeys);
-
- recompute.call(this, propertyName);
-
- return cp._instanceMeta(this, propertyName).getValue();
- };
- }
-
- ReduceComputedProperty.prototype = o_create(ComputedProperty.prototype);
-
- function defaultCallback(computedValue) {
- return computedValue;
- }
-
- ReduceComputedProperty.prototype._callbacks = function () {
- if (!this.callbacks) {
- var options = this.options;
-
- this.callbacks = {
- removedItem: options.removedItem || defaultCallback,
- addedItem: options.addedItem || defaultCallback,
- flushedChanges: options.flushedChanges || defaultCallback
- };
- }
-
- return this.callbacks;
- };
-
- ReduceComputedProperty.prototype._hasInstanceMeta = function (context, propertyName) {
- return !!metaFor(context).cacheMeta[propertyName];
- };
-
- ReduceComputedProperty.prototype._instanceMeta = function (context, propertyName) {
- var cacheMeta = metaFor(context).cacheMeta;
- var meta = cacheMeta[propertyName];
-
- if (!meta) {
- meta = cacheMeta[propertyName] = new ReduceComputedPropertyInstanceMeta(context, propertyName, this.initialValue());
- meta.dependentArraysObserver = new DependentArraysObserver(this._callbacks(), this, meta, context, propertyName, meta.sugarMeta);
- }
-
- return meta;
- };
-
- ReduceComputedProperty.prototype.initialValue = function () {
- if (typeof this.options.initialValue === 'function') {
- return this.options.initialValue();
- }
- else {
- return this.options.initialValue;
- }
- };
-
- ReduceComputedProperty.prototype.resetValue = function (value) {
- return this.initialValue();
- };
-
- ReduceComputedProperty.prototype.itemPropertyKey = function (dependentArrayKey, itemPropertyKey) {
- this._itemPropertyKeys[dependentArrayKey] = this._itemPropertyKeys[dependentArrayKey] || [];
- this._itemPropertyKeys[dependentArrayKey].push(itemPropertyKey);
- };
-
- ReduceComputedProperty.prototype.clearItemPropertyKeys = function (dependentArrayKey) {
- if (this._itemPropertyKeys[dependentArrayKey]) {
- this._previousItemPropertyKeys[dependentArrayKey] = this._itemPropertyKeys[dependentArrayKey];
- this._itemPropertyKeys[dependentArrayKey] = [];
- }
- };
-
- ReduceComputedProperty.prototype.property = function () {
- var cp = this;
- var args = a_slice.call(arguments);
- var propertyArgs = {};
- var match, dependentArrayKey;
-
- forEach(args, function (dependentKey) {
- if (doubleEachPropertyPattern.test(dependentKey)) {
- throw new EmberError('Nested @each properties not supported: ' + dependentKey);
- } else if (match = eachPropertyPattern.exec(dependentKey)) {
- dependentArrayKey = match[1];
-
- var itemPropertyKeyPattern = match[2];
- var addItemPropertyKey = function (itemPropertyKey) {
- cp.itemPropertyKey(dependentArrayKey, itemPropertyKey);
- };
-
- expandProperties(itemPropertyKeyPattern, addItemPropertyKey);
- propertyArgs[guidFor(dependentArrayKey)] = dependentArrayKey;
- } else {
- propertyArgs[guidFor(dependentKey)] = dependentKey;
- }
- });
-
- var propertyArgsToArray = [];
- for (var guid in propertyArgs) {
- propertyArgsToArray.push(propertyArgs[guid]);
- }
-
- return ComputedProperty.prototype.property.apply(this, propertyArgsToArray);
- };
-
- /**
- Creates a computed property which operates on dependent arrays and
- is updated with "one at a time" semantics. When items are added or
- removed from the dependent array(s) a reduce computed only operates
- on the change instead of re-evaluating the entire array.
-
- If there are more than one arguments the first arguments are
- considered to be dependent property keys. The last argument is
- required to be an options object. The options object can have the
- following four properties:
-
- `initialValue` - A value or function that will be used as the initial
- value for the computed. If this property is a function the result of calling
- the function will be used as the initial value. This property is required.
-
- `initialize` - An optional initialize function. Typically this will be used
- to set up state on the instanceMeta object.
-
- `removedItem` - A function that is called each time an element is removed
- from the array.
-
- `addedItem` - A function that is called each time an element is added to
- the array.
-
-
- The `initialize` function has the following signature:
-
- ```javascript
- function(initialValue, changeMeta, instanceMeta)
- ```
-
- `initialValue` - The value of the `initialValue` property from the
- options object.
-
- `changeMeta` - An object which contains meta information about the
- computed. It contains the following properties:
-
- - `property` the computed property
- - `propertyName` the name of the property on the object
-
- `instanceMeta` - An object that can be used to store meta
- information needed for calculating your computed. For example a
- unique computed might use this to store the number of times a given
- element is found in the dependent array.
-
-
- The `removedItem` and `addedItem` functions both have the following signature:
-
- ```javascript
- function(accumulatedValue, item, changeMeta, instanceMeta)
- ```
-
- `accumulatedValue` - The value returned from the last time
- `removedItem` or `addedItem` was called or `initialValue`.
-
- `item` - the element added or removed from the array
-
- `changeMeta` - An object which contains meta information about the
- change. It contains the following properties:
-
- - `property` the computed property
- - `propertyName` the name of the property on the object
- - `index` the index of the added or removed item
- - `item` the added or removed item: this is exactly the same as
- the second arg
- - `arrayChanged` the array that triggered the change. Can be
- useful when depending on multiple arrays.
-
- For property changes triggered on an item property change (when
- depKey is something like `someArray.@each.someProperty`),
- `changeMeta` will also contain the following property:
-
- - `previousValues` an object whose keys are the properties that changed on
- the item, and whose values are the item's previous values.
-
- `previousValues` is important Ember coalesces item property changes via
- Ember.run.once. This means that by the time removedItem gets called, item has
- the new values, but you may need the previous value (eg for sorting &
- filtering).
-
- `instanceMeta` - An object that can be used to store meta
- information needed for calculating your computed. For example a
- unique computed might use this to store the number of times a given
- element is found in the dependent array.
-
- The `removedItem` and `addedItem` functions should return the accumulated
- value. It is acceptable to not return anything (ie return undefined)
- to invalidate the computation. This is generally not a good idea for
- arrayComputed but it's used in eg max and min.
-
- Note that observers will be fired if either of these functions return a value
- that differs from the accumulated value. When returning an object that
- mutates in response to array changes, for example an array that maps
- everything from some other array (see `Ember.computed.map`), it is usually
- important that the *same* array be returned to avoid accidentally triggering observers.
-
- Example
-
- ```javascript
- Ember.computed.max = function(dependentKey) {
- return Ember.reduceComputed(dependentKey, {
- initialValue: -Infinity,
-
- addedItem: function(accumulatedValue, item, changeMeta, instanceMeta) {
- return Math.max(accumulatedValue, item);
- },
-
- removedItem: function(accumulatedValue, item, changeMeta, instanceMeta) {
- if (item < accumulatedValue) {
- return accumulatedValue;
- }
- }
- });
- };
- ```
-
- Dependent keys may refer to `@this` to observe changes to the object itself,
- which must be array-like, rather than a property of the object. This is
- mostly useful for array proxies, to ensure objects are retrieved via
- `objectAtContent`. This is how you could sort items by properties defined on an item controller.
-
- Example
-
- ```javascript
- App.PeopleController = Ember.ArrayController.extend({
- itemController: 'person',
-
- sortedPeople: Ember.computed.sort('@this.@each.reversedName', function(personA, personB) {
- // `reversedName` isn't defined on Person, but we have access to it via
- // the item controller App.PersonController. If we'd used
- // `content.@each.reversedName` above, we would be getting the objects
- // directly and not have access to `reversedName`.
- //
- var reversedNameA = get(personA, 'reversedName');
- var reversedNameB = get(personB, 'reversedName');
-
- return Ember.compare(reversedNameA, reversedNameB);
- })
- });
-
- App.PersonController = Ember.ObjectController.extend({
- reversedName: function() {
- return reverse(get(this, 'name'));
- }.property('name')
- });
- ```
-
- Dependent keys whose values are not arrays are treated as regular
- dependencies: when they change, the computed property is completely
- recalculated. It is sometimes useful to have dependent arrays with similar
- semantics. Dependent keys which end in `.[]` do not use "one at a time"
- semantics. When an item is added or removed from such a dependency, the
- computed property is completely recomputed.
-
- When the computed property is completely recomputed, the `accumulatedValue`
- is discarded, it starts with `initialValue` again, and each item is passed
- to `addedItem` in turn.
-
- Example
-
- ```javascript
- Ember.Object.extend({
- // When `string` is changed, `computed` is completely recomputed.
- string: 'a string',
-
- // When an item is added to `array`, `addedItem` is called.
- array: [],
-
- // When an item is added to `anotherArray`, `computed` is completely
- // recomputed.
- anotherArray: [],
-
- computed: Ember.reduceComputed('string', 'array', 'anotherArray.[]', {
- addedItem: addedItemCallback,
- removedItem: removedItemCallback
- })
- });
- ```
-
- @method reduceComputed
- @for Ember
- @param {String} [dependentKeys*]
- @param {Object} options
- @return {Ember.ComputedProperty}
- */
- function reduceComputed(options) {
- var args;
-
- if (arguments.length > 1) {
- args = a_slice.call(arguments, 0, -1);
- options = a_slice.call(arguments, -1)[0];
- }
-
- if (typeof options !== 'object') {
- throw new EmberError('Reduce Computed Property declared without an options hash');
- }
-
- if (!('initialValue' in options)) {
- throw new EmberError('Reduce Computed Property declared without an initial value');
- }
-
- var cp = new ReduceComputedProperty(options);
-
- if (args) {
- cp.property.apply(cp, args);
- }
-
- return cp;
- }
-
- __exports__.reduceComputed = reduceComputed;
- });
-enifed("ember-runtime/computed/reduce_computed_macros",
- ["ember-metal/core","ember-metal/property_get","ember-metal/utils","ember-metal/error","ember-metal/enumerable_utils","ember-metal/run_loop","ember-metal/observer","ember-runtime/computed/array_computed","ember-runtime/computed/reduce_computed","ember-runtime/system/subarray","ember-metal/keys","ember-runtime/compare","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __exports__) {
- "use strict";
- /**
- @module ember
- @submodule ember-runtime
- */
-
- var Ember = __dependency1__["default"];
- // Ember.assert
- var get = __dependency2__.get;
- var isArray = __dependency3__.isArray;
- var guidFor = __dependency3__.guidFor;
- var EmberError = __dependency4__["default"];
- var forEach = __dependency5__.forEach;
- var run = __dependency6__["default"];
- var addObserver = __dependency7__.addObserver;
- var arrayComputed = __dependency8__.arrayComputed;
- var reduceComputed = __dependency9__.reduceComputed;
- var SubArray = __dependency10__["default"];
- var keys = __dependency11__["default"];
- var compare = __dependency12__["default"];
-
- var a_slice = [].slice;
-
- /**
- A computed property that returns the sum of the value
- in the dependent array.
-
- @method computed.sum
- @for Ember
- @param {String} dependentKey
- @return {Ember.ComputedProperty} computes the sum of all values in the dependentKey's array
- @since 1.4.0
- */
-
- function sum(dependentKey){
- return reduceComputed(dependentKey, {
- initialValue: 0,
-
- addedItem: function(accumulatedValue, item, changeMeta, instanceMeta){
- return accumulatedValue + item;
- },
-
- removedItem: function(accumulatedValue, item, changeMeta, instanceMeta){
- return accumulatedValue - item;
- }
- });
- }
-
- __exports__.sum = sum;/**
- A computed property that calculates the maximum value in the
- dependent array. This will return `-Infinity` when the dependent
- array is empty.
-
- ```javascript
- var Person = Ember.Object.extend({
- childAges: Ember.computed.mapBy('children', 'age'),
- maxChildAge: Ember.computed.max('childAges')
- });
-
- var lordByron = Person.create({ children: [] });
-
- lordByron.get('maxChildAge'); // -Infinity
- lordByron.get('children').pushObject({
- name: 'Augusta Ada Byron', age: 7
- });
- lordByron.get('maxChildAge'); // 7
- lordByron.get('children').pushObjects([{
- name: 'Allegra Byron',
- age: 5
- }, {
- name: 'Elizabeth Medora Leigh',
- age: 8
- }]);
- lordByron.get('maxChildAge'); // 8
- ```
-
- @method computed.max
- @for Ember
- @param {String} dependentKey
- @return {Ember.ComputedProperty} computes the largest value in the dependentKey's array
- */
- function max(dependentKey) {
- return reduceComputed(dependentKey, {
- initialValue: -Infinity,
-
- addedItem: function (accumulatedValue, item, changeMeta, instanceMeta) {
- return Math.max(accumulatedValue, item);
- },
-
- removedItem: function (accumulatedValue, item, changeMeta, instanceMeta) {
- if (item < accumulatedValue) {
- return accumulatedValue;
- }
- }
- });
- }
-
- __exports__.max = max;/**
- A computed property that calculates the minimum value in the
- dependent array. This will return `Infinity` when the dependent
- array is empty.
-
- ```javascript
- var Person = Ember.Object.extend({
- childAges: Ember.computed.mapBy('children', 'age'),
- minChildAge: Ember.computed.min('childAges')
- });
-
- var lordByron = Person.create({ children: [] });
-
- lordByron.get('minChildAge'); // Infinity
- lordByron.get('children').pushObject({
- name: 'Augusta Ada Byron', age: 7
- });
- lordByron.get('minChildAge'); // 7
- lordByron.get('children').pushObjects([{
- name: 'Allegra Byron',
- age: 5
- }, {
- name: 'Elizabeth Medora Leigh',
- age: 8
- }]);
- lordByron.get('minChildAge'); // 5
- ```
-
- @method computed.min
- @for Ember
- @param {String} dependentKey
- @return {Ember.ComputedProperty} computes the smallest value in the dependentKey's array
- */
- function min(dependentKey) {
- return reduceComputed(dependentKey, {
- initialValue: Infinity,
-
- addedItem: function (accumulatedValue, item, changeMeta, instanceMeta) {
- return Math.min(accumulatedValue, item);
- },
-
- removedItem: function (accumulatedValue, item, changeMeta, instanceMeta) {
- if (item > accumulatedValue) {
- return accumulatedValue;
- }
- }
- });
- }
-
- __exports__.min = min;/**
- Returns an array mapped via the callback
-
- The callback method you provide should have the following signature.
- `item` is the current item in the iteration.
- `index` is the integer index of the current item in the iteration.
-
- ```javascript
- function(item, index);
- ```
-
- Example
-
- ```javascript
- var Hamster = Ember.Object.extend({
- excitingChores: Ember.computed.map('chores', function(chore, index) {
- return chore.toUpperCase() + '!';
- })
- });
-
- var hamster = Hamster.create({
- chores: ['clean', 'write more unit tests']
- });
-
- hamster.get('excitingChores'); // ['CLEAN!', 'WRITE MORE UNIT TESTS!']
- ```
-
- @method computed.map
- @for Ember
- @param {String} dependentKey
- @param {Function} callback
- @return {Ember.ComputedProperty} an array mapped via the callback
- */
- function map(dependentKey, callback) {
- var options = {
- addedItem: function(array, item, changeMeta, instanceMeta) {
- var mapped = callback.call(this, item, changeMeta.index);
- array.insertAt(changeMeta.index, mapped);
- return array;
- },
- removedItem: function(array, item, changeMeta, instanceMeta) {
- array.removeAt(changeMeta.index, 1);
- return array;
- }
- };
-
- return arrayComputed(dependentKey, options);
- }
-
- __exports__.map = map;/**
- Returns an array mapped to the specified key.
-
- ```javascript
- var Person = Ember.Object.extend({
- childAges: Ember.computed.mapBy('children', 'age')
- });
-
- var lordByron = Person.create({ children: [] });
-
- lordByron.get('childAges'); // []
- lordByron.get('children').pushObject({ name: 'Augusta Ada Byron', age: 7 });
- lordByron.get('childAges'); // [7]
- lordByron.get('children').pushObjects([{
- name: 'Allegra Byron',
- age: 5
- }, {
- name: 'Elizabeth Medora Leigh',
- age: 8
- }]);
- lordByron.get('childAges'); // [7, 5, 8]
- ```
-
- @method computed.mapBy
- @for Ember
- @param {String} dependentKey
- @param {String} propertyKey
- @return {Ember.ComputedProperty} an array mapped to the specified key
- */
- function mapBy (dependentKey, propertyKey) {
- var callback = function(item) { return get(item, propertyKey); };
- return map(dependentKey + '.@each.' + propertyKey, callback);
- }
-
- __exports__.mapBy = mapBy;/**
- @method computed.mapProperty
- @for Ember
- @deprecated Use `Ember.computed.mapBy` instead
- @param dependentKey
- @param propertyKey
- */
- var mapProperty = mapBy;
- __exports__.mapProperty = mapProperty;
- /**
- Filters the array by the callback.
-
- The callback method you provide should have the following signature.
- `item` is the current item in the iteration.
- `index` is the integer index of the current item in the iteration.
-
- ```javascript
- function(item, index);
- ```
-
- ```javascript
- var Hamster = Ember.Object.extend({
- remainingChores: Ember.computed.filter('chores', function(chore, index) {
- return !chore.done;
- })
- });
-
- var hamster = Hamster.create({
- chores: [
- { name: 'cook', done: true },
- { name: 'clean', done: true },
- { name: 'write more unit tests', done: false }
- ]
- });
-
- hamster.get('remainingChores'); // [{name: 'write more unit tests', done: false}]
- ```
-
- @method computed.filter
- @for Ember
- @param {String} dependentKey
- @param {Function} callback
- @return {Ember.ComputedProperty} the filtered array
- */
- function filter(dependentKey, callback) {
- var options = {
- initialize: function (array, changeMeta, instanceMeta) {
- instanceMeta.filteredArrayIndexes = new SubArray();
- },
-
- addedItem: function (array, item, changeMeta, instanceMeta) {
- var match = !!callback.call(this, item, changeMeta.index);
- var filterIndex = instanceMeta.filteredArrayIndexes.addItem(changeMeta.index, match);
-
- if (match) {
- array.insertAt(filterIndex, item);
- }
-
- return array;
- },
-
- removedItem: function(array, item, changeMeta, instanceMeta) {
- var filterIndex = instanceMeta.filteredArrayIndexes.removeItem(changeMeta.index);
-
- if (filterIndex > -1) {
- array.removeAt(filterIndex);
- }
-
- return array;
- }
- };
-
- return arrayComputed(dependentKey, options);
- }
-
- __exports__.filter = filter;/**
- Filters the array by the property and value
-
- ```javascript
- var Hamster = Ember.Object.extend({
- remainingChores: Ember.computed.filterBy('chores', 'done', false)
- });
-
- var hamster = Hamster.create({
- chores: [
- { name: 'cook', done: true },
- { name: 'clean', done: true },
- { name: 'write more unit tests', done: false }
- ]
- });
-
- hamster.get('remainingChores'); // [{ name: 'write more unit tests', done: false }]
- ```
-
- @method computed.filterBy
- @for Ember
- @param {String} dependentKey
- @param {String} propertyKey
- @param {*} value
- @return {Ember.ComputedProperty} the filtered array
- */
- function filterBy (dependentKey, propertyKey, value) {
- var callback;
-
- if (arguments.length === 2) {
- callback = function(item) {
- return get(item, propertyKey);
- };
- } else {
- callback = function(item) {
- return get(item, propertyKey) === value;
- };
- }
-
- return filter(dependentKey + '.@each.' + propertyKey, callback);
- }
-
- __exports__.filterBy = filterBy;/**
- @method computed.filterProperty
- @for Ember
- @param dependentKey
- @param propertyKey
- @param value
- @deprecated Use `Ember.computed.filterBy` instead
- */
- var filterProperty = filterBy;
- __exports__.filterProperty = filterProperty;
- /**
- A computed property which returns a new array with all the unique
- elements from one or more dependent arrays.
-
- Example
-
- ```javascript
- var Hamster = Ember.Object.extend({
- uniqueFruits: Ember.computed.uniq('fruits')
- });
-
- var hamster = Hamster.create({
- fruits: [
- 'banana',
- 'grape',
- 'kale',
- 'banana'
- ]
- });
-
- hamster.get('uniqueFruits'); // ['banana', 'grape', 'kale']
- ```
-
- @method computed.uniq
- @for Ember
- @param {String} propertyKey*
- @return {Ember.ComputedProperty} computes a new array with all the
- unique elements from the dependent array
- */
- function uniq() {
- var args = a_slice.call(arguments);
-
- args.push({
- initialize: function(array, changeMeta, instanceMeta) {
- instanceMeta.itemCounts = {};
- },
-
- addedItem: function(array, item, changeMeta, instanceMeta) {
- var guid = guidFor(item);
-
- if (!instanceMeta.itemCounts[guid]) {
- instanceMeta.itemCounts[guid] = 1;
- array.pushObject(item);
- } else {
- ++instanceMeta.itemCounts[guid];
- }
- return array;
- },
-
- removedItem: function(array, item, _, instanceMeta) {
- var guid = guidFor(item);
- var itemCounts = instanceMeta.itemCounts;
-
- if (--itemCounts[guid] === 0) {
- array.removeObject(item);
- }
-
- return array;
- }
- });
-
- return arrayComputed.apply(null, args);
- }
-
- __exports__.uniq = uniq;/**
- Alias for [Ember.computed.uniq](/api/#method_computed_uniq).
-
- @method computed.union
- @for Ember
- @param {String} propertyKey*
- @return {Ember.ComputedProperty} computes a new array with all the
- unique elements from the dependent array
- */
- var union = uniq;
- __exports__.union = union;
- /**
- A computed property which returns a new array with all the duplicated
- elements from two or more dependent arrays.
-
- Example
-
- ```javascript
- var obj = Ember.Object.createWithMixins({
- adaFriends: ['Charles Babbage', 'John Hobhouse', 'William King', 'Mary Somerville'],
- charlesFriends: ['William King', 'Mary Somerville', 'Ada Lovelace', 'George Peacock'],
- friendsInCommon: Ember.computed.intersect('adaFriends', 'charlesFriends')
- });
-
- obj.get('friendsInCommon'); // ['William King', 'Mary Somerville']
- ```
-
- @method computed.intersect
- @for Ember
- @param {String} propertyKey*
- @return {Ember.ComputedProperty} computes a new array with all the
- duplicated elements from the dependent arrays
- */
- function intersect() {
- var args = a_slice.call(arguments);
-
- args.push({
- initialize: function (array, changeMeta, instanceMeta) {
- instanceMeta.itemCounts = {};
- },
-
- addedItem: function(array, item, changeMeta, instanceMeta) {
- var itemGuid = guidFor(item);
- var dependentGuid = guidFor(changeMeta.arrayChanged);
- var numberOfDependentArrays = changeMeta.property._dependentKeys.length;
- var itemCounts = instanceMeta.itemCounts;
-
- if (!itemCounts[itemGuid]) {
- itemCounts[itemGuid] = {};
- }
-
- if (itemCounts[itemGuid][dependentGuid] === undefined) {
- itemCounts[itemGuid][dependentGuid] = 0;
- }
-
- if (++itemCounts[itemGuid][dependentGuid] === 1 &&
- numberOfDependentArrays === keys(itemCounts[itemGuid]).length) {
- array.addObject(item);
- }
-
- return array;
- },
-
- removedItem: function(array, item, changeMeta, instanceMeta) {
- var itemGuid = guidFor(item);
- var dependentGuid = guidFor(changeMeta.arrayChanged);
- var numberOfArraysItemAppearsIn;
- var itemCounts = instanceMeta.itemCounts;
-
- if (itemCounts[itemGuid][dependentGuid] === undefined) {
- itemCounts[itemGuid][dependentGuid] = 0;
- }
-
- if (--itemCounts[itemGuid][dependentGuid] === 0) {
- delete itemCounts[itemGuid][dependentGuid];
- numberOfArraysItemAppearsIn = keys(itemCounts[itemGuid]).length;
-
- if (numberOfArraysItemAppearsIn === 0) {
- delete itemCounts[itemGuid];
- }
-
- array.removeObject(item);
- }
-
- return array;
- }
- });
-
- return arrayComputed.apply(null, args);
- }
-
- __exports__.intersect = intersect;/**
- A computed property which returns a new array with all the
- properties from the first dependent array that are not in the second
- dependent array.
-
- Example
-
- ```javascript
- var Hamster = Ember.Object.extend({
- likes: ['banana', 'grape', 'kale'],
- wants: Ember.computed.setDiff('likes', 'fruits')
- });
-
- var hamster = Hamster.create({
- fruits: [
- 'grape',
- 'kale',
- ]
- });
-
- hamster.get('wants'); // ['banana']
- ```
-
- @method computed.setDiff
- @for Ember
- @param {String} setAProperty
- @param {String} setBProperty
- @return {Ember.ComputedProperty} computes a new array with all the
- items from the first dependent array that are not in the second
- dependent array
- */
- function setDiff(setAProperty, setBProperty) {
- if (arguments.length !== 2) {
- throw new EmberError('setDiff requires exactly two dependent arrays.');
- }
-
- return arrayComputed(setAProperty, setBProperty, {
- addedItem: function (array, item, changeMeta, instanceMeta) {
- var setA = get(this, setAProperty);
- var setB = get(this, setBProperty);
-
- if (changeMeta.arrayChanged === setA) {
- if (!setB.contains(item)) {
- array.addObject(item);
- }
- } else {
- array.removeObject(item);
- }
-
- return array;
- },
-
- removedItem: function (array, item, changeMeta, instanceMeta) {
- var setA = get(this, setAProperty);
- var setB = get(this, setBProperty);
-
- if (changeMeta.arrayChanged === setB) {
- if (setA.contains(item)) {
- array.addObject(item);
- }
- } else {
- array.removeObject(item);
- }
-
- return array;
- }
- });
- }
-
- __exports__.setDiff = setDiff;function binarySearch(array, item, low, high) {
- var mid, midItem, res, guidMid, guidItem;
-
- if (arguments.length < 4) {
- high = get(array, 'length');
- }
-
- if (arguments.length < 3) {
- low = 0;
- }
-
- if (low === high) {
- return low;
- }
-
- mid = low + Math.floor((high - low) / 2);
- midItem = array.objectAt(mid);
-
- guidMid = guidFor(midItem);
- guidItem = guidFor(item);
-
- if (guidMid === guidItem) {
- return mid;
- }
-
- res = this.order(midItem, item);
-
- if (res === 0) {
- res = guidMid < guidItem ? -1 : 1;
- }
-
-
- if (res < 0) {
- return this.binarySearch(array, item, mid+1, high);
- } else if (res > 0) {
- return this.binarySearch(array, item, low, mid);
- }
-
- return mid;
- }
-
-
- /**
- A computed property which returns a new array with all the
- properties from the first dependent array sorted based on a property
- or sort function.
-
- The callback method you provide should have the following signature:
-
- ```javascript
- function(itemA, itemB);
- ```
-
- - `itemA` the first item to compare.
- - `itemB` the second item to compare.
-
- This function should return negative number (e.g. `-1`) when `itemA` should come before
- `itemB`. It should return positive number (e.g. `1`) when `itemA` should come after
- `itemB`. If the `itemA` and `itemB` are equal this function should return `0`.
-
- Therefore, if this function is comparing some numeric values, simple `itemA - itemB` or
- `itemA.get( 'foo' ) - itemB.get( 'foo' )` can be used instead of series of `if`.
-
- Example
-
- ```javascript
- var ToDoList = Ember.Object.extend({
- // using standard ascending sort
- todosSorting: ['name'],
- sortedTodos: Ember.computed.sort('todos', 'todosSorting'),
-
- // using descending sort
- todosSortingDesc: ['name:desc'],
- sortedTodosDesc: Ember.computed.sort('todos', 'todosSortingDesc'),
-
- // using a custom sort function
- priorityTodos: Ember.computed.sort('todos', function(a, b){
- if (a.priority > b.priority) {
- return 1;
- } else if (a.priority < b.priority) {
- return -1;
- }
-
- return 0;
- })
- });
-
- var todoList = ToDoList.create({todos: [
- { name: 'Unit Test', priority: 2 },
- { name: 'Documentation', priority: 3 },
- { name: 'Release', priority: 1 }
- ]});
-
- todoList.get('sortedTodos'); // [{ name:'Documentation', priority:3 }, { name:'Release', priority:1 }, { name:'Unit Test', priority:2 }]
- todoList.get('sortedTodosDesc'); // [{ name:'Unit Test', priority:2 }, { name:'Release', priority:1 }, { name:'Documentation', priority:3 }]
- todoList.get('priorityTodos'); // [{ name:'Release', priority:1 }, { name:'Unit Test', priority:2 }, { name:'Documentation', priority:3 }]
- ```
-
- @method computed.sort
- @for Ember
- @param {String} dependentKey
- @param {String or Function} sortDefinition a dependent key to an
- array of sort properties (add `:desc` to the arrays sort properties to sort descending) or a function to use when sorting
- @return {Ember.ComputedProperty} computes a new sorted array based
- on the sort property array or callback function
- */
- function sort(itemsKey, sortDefinition) {
- Ember.assert('Ember.computed.sort requires two arguments: an array key to sort and ' +
- 'either a sort properties key or sort function', arguments.length === 2);
-
- if (typeof sortDefinition === 'function') {
- return customSort(itemsKey, sortDefinition);
- } else {
- return propertySort(itemsKey, sortDefinition);
- }
- }
-
- __exports__.sort = sort;function customSort(itemsKey, comparator) {
- return arrayComputed(itemsKey, {
- initialize: function (array, changeMeta, instanceMeta) {
- instanceMeta.order = comparator;
- instanceMeta.binarySearch = binarySearch;
- instanceMeta.waitingInsertions = [];
- instanceMeta.insertWaiting = function() {
- var index, item;
- var waiting = instanceMeta.waitingInsertions;
- instanceMeta.waitingInsertions = [];
- for (var i=0; i<waiting.length; i++) {
- item = waiting[i];
- index = instanceMeta.binarySearch(array, item);
- array.insertAt(index, item);
- }
- };
- instanceMeta.insertLater = function(item) {
- this.waitingInsertions.push(item);
- };
- },
-
- addedItem: function (array, item, changeMeta, instanceMeta) {
- instanceMeta.insertLater(item);
- return array;
- },
-
- removedItem: function (array, item, changeMeta, instanceMeta) {
- array.removeObject(item);
- return array;
- },
-
- flushedChanges: function(array, instanceMeta) {
- instanceMeta.insertWaiting();
- }
- });
- }
-
- function propertySort(itemsKey, sortPropertiesKey) {
- return arrayComputed(itemsKey, {
- initialize: function (array, changeMeta, instanceMeta) {
- function setupSortProperties() {
- var sortPropertyDefinitions = get(this, sortPropertiesKey);
- var sortProperties = instanceMeta.sortProperties = [];
- var sortPropertyAscending = instanceMeta.sortPropertyAscending = {};
- var sortProperty, idx, asc;
-
- Ember.assert('Cannot sort: \'' + sortPropertiesKey + '\' is not an array.',
- isArray(sortPropertyDefinitions));
-
- changeMeta.property.clearItemPropertyKeys(itemsKey);
-
- forEach(sortPropertyDefinitions, function (sortPropertyDefinition) {
- if ((idx = sortPropertyDefinition.indexOf(':')) !== -1) {
- sortProperty = sortPropertyDefinition.substring(0, idx);
- asc = sortPropertyDefinition.substring(idx+1).toLowerCase() !== 'desc';
- } else {
- sortProperty = sortPropertyDefinition;
- asc = true;
- }
-
- sortProperties.push(sortProperty);
- sortPropertyAscending[sortProperty] = asc;
- changeMeta.property.itemPropertyKey(itemsKey, sortProperty);
- });
-
- sortPropertyDefinitions.addObserver('@each', this, updateSortPropertiesOnce);
- }
-
- function updateSortPropertiesOnce() {
- run.once(this, updateSortProperties, changeMeta.propertyName);
- }
-
- function updateSortProperties(propertyName) {
- setupSortProperties.call(this);
- changeMeta.property.recomputeOnce.call(this, propertyName);
- }
-
- addObserver(this, sortPropertiesKey, updateSortPropertiesOnce);
- setupSortProperties.call(this);
-
- instanceMeta.order = function (itemA, itemB) {
- var sortProperty, result, asc;
- var keyA = this.keyFor(itemA);
- var keyB = this.keyFor(itemB);
-
- for (var i = 0; i < this.sortProperties.length; ++i) {
- sortProperty = this.sortProperties[i];
-
- result = compare(keyA[sortProperty], keyB[sortProperty]);
-
- if (result !== 0) {
- asc = this.sortPropertyAscending[sortProperty];
- return asc ? result : (-1 * result);
- }
- }
-
- return 0;
- };
-
- instanceMeta.binarySearch = binarySearch;
- setupKeyCache(instanceMeta);
- },
-
- addedItem: function (array, item, changeMeta, instanceMeta) {
- var index = instanceMeta.binarySearch(array, item);
- array.insertAt(index, item);
- return array;
- },
-
- removedItem: function (array, item, changeMeta, instanceMeta) {
- var index = instanceMeta.binarySearch(array, item);
- array.removeAt(index);
- instanceMeta.dropKeyFor(item);
- return array;
- }
- });
- }
-
- function setupKeyCache(instanceMeta) {
- instanceMeta.keyFor = function(item) {
- var guid = guidFor(item);
- if (this.keyCache[guid]) {
- return this.keyCache[guid];
- }
- var sortProperty;
- var key = {};
- for (var i = 0; i < this.sortProperties.length; ++i) {
- sortProperty = this.sortProperties[i];
- key[sortProperty] = get(item, sortProperty);
- }
- return this.keyCache[guid] = key;
- };
-
- instanceMeta.dropKeyFor = function(item) {
- var guid = guidFor(item);
- this.keyCache[guid] = null;
- };
-
- instanceMeta.keyCache = {};
- }
- });
-enifed("ember-runtime/controllers/array_controller",
- ["ember-metal/core","ember-metal/property_get","ember-metal/enumerable_utils","ember-runtime/system/array_proxy","ember-runtime/mixins/sortable","ember-runtime/mixins/controller","ember-metal/computed","ember-metal/error","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __exports__) {
- "use strict";
- /**
- @module ember
- @submodule ember-runtime
- */
-
- var Ember = __dependency1__["default"];
- var get = __dependency2__.get;
- var forEach = __dependency3__.forEach;
- var replace = __dependency3__.replace;
- var ArrayProxy = __dependency4__["default"];
- var SortableMixin = __dependency5__["default"];
- var ControllerMixin = __dependency6__["default"];
- var computed = __dependency7__.computed;
- var EmberError = __dependency8__["default"];
-
-
- /**
- `Ember.ArrayController` provides a way for you to publish a collection of
- objects so that you can easily bind to the collection from a Handlebars
- `#each` helper, an `Ember.CollectionView`, or other controllers.
-
- The advantage of using an `ArrayController` is that you only have to set up
- your view bindings once; to change what's displayed, simply swap out the
- `model` property on the controller.
-
- For example, imagine you wanted to display a list of items fetched via an XHR
- request. Create an `Ember.ArrayController` and set its `model` property:
-
- ```javascript
- MyApp.listController = Ember.ArrayController.create();
-
- $.get('people.json', function(data) {
- MyApp.listController.set('model', data);
- });
- ```
-
- Then, create a view that binds to your new controller:
-
- ```handlebars
- {{#each person in MyApp.listController}}
- {{person.firstName}} {{person.lastName}}
- {{/each}}
- ```
-
- Although you are binding to the controller, the behavior of this controller
- is to pass through any methods or properties to the underlying array. This
- capability comes from `Ember.ArrayProxy`, which this class inherits from.
-
- Sometimes you want to display computed properties within the body of an
- `#each` helper that depend on the underlying items in `model`, but are not
- present on those items. To do this, set `itemController` to the name of a
- controller (probably an `ObjectController`) that will wrap each individual item.
-
- For example:
-
- ```handlebars
- {{#each post in controller}}
- <li>{{post.title}} ({{post.titleLength}} characters)</li>
- {{/each}}
- ```
-
- ```javascript
- App.PostsController = Ember.ArrayController.extend({
- itemController: 'post'
- });
-
- App.PostController = Ember.ObjectController.extend({
- // the `title` property will be proxied to the underlying post.
- titleLength: function() {
- return this.get('title').length;
- }.property('title')
- });
- ```
-
- In some cases it is helpful to return a different `itemController` depending
- on the particular item. Subclasses can do this by overriding
- `lookupItemController`.
-
- For example:
-
- ```javascript
- App.MyArrayController = Ember.ArrayController.extend({
- lookupItemController: function( object ) {
- if (object.get('isSpecial')) {
- return "special"; // use App.SpecialController
- } else {
- return "regular"; // use App.RegularController
- }
- }
- });
- ```
-
- The itemController instances will have a `parentController` property set to
- the `ArrayController` instance.
-
- @class ArrayController
- @namespace Ember
- @extends Ember.ArrayProxy
- @uses Ember.SortableMixin
- @uses Ember.ControllerMixin
- */
-
- __exports__["default"] = ArrayProxy.extend(ControllerMixin, SortableMixin, {
-
- /**
- The controller used to wrap items, if any. If the value is a string, it will
- be used to lookup the container for the controller. As an alternative, you
- can also provide a controller class as the value.
-
- For example:
-
- ```javascript
- App.MyArrayController = Ember.ArrayController.extend({
- itemController: Ember.ObjectController.extend({
- //Item Controller Implementation
- })
- });
- ```
-
- @property itemController
- @type String | Ember.Controller
- @default null
- */
- itemController: null,
-
- /**
- Return the name of the controller to wrap items, or `null` if items should
- be returned directly. The default implementation simply returns the
- `itemController` property, but subclasses can override this method to return
- different controllers for different objects.
-
- For example:
-
- ```javascript
- App.MyArrayController = Ember.ArrayController.extend({
- lookupItemController: function( object ) {
- if (object.get('isSpecial')) {
- return "special"; // use App.SpecialController
- } else {
- return "regular"; // use App.RegularController
- }
- }
- });
- ```
-
- @method lookupItemController
- @param {Object} object
- @return {String}
- */
- lookupItemController: function(object) {
- return get(this, 'itemController');
- },
-
- objectAtContent: function(idx) {
- var length = get(this, 'length');
- var arrangedContent = get(this, 'arrangedContent');
- var object = arrangedContent && arrangedContent.objectAt(idx);
- var controllerClass;
-
- if (idx >= 0 && idx < length) {
- controllerClass = this.lookupItemController(object);
-
- if (controllerClass) {
- return this.controllerAt(idx, object, controllerClass);
- }
- }
-
- // When `controllerClass` is falsy, we have not opted in to using item
- // controllers, so return the object directly.
-
- // When the index is out of range, we want to return the "out of range"
- // value, whatever that might be. Rather than make assumptions
- // (e.g. guessing `null` or `undefined`) we defer this to `arrangedContent`.
- return object;
- },
-
- arrangedContentDidChange: function() {
- this._super();
- this._resetSubControllers();
- },
-
- arrayContentDidChange: function(idx, removedCnt, addedCnt) {
- var subControllers = this._subControllers;
-
- if (subControllers.length) {
- var subControllersToRemove = subControllers.slice(idx, idx + removedCnt);
-
- forEach(subControllersToRemove, function(subController) {
- if (subController) {
- subController.destroy();
- }
- });
-
- replace(subControllers, idx, removedCnt, new Array(addedCnt));
- }
-
- // The shadow array of subcontrollers must be updated before we trigger
- // observers, otherwise observers will get the wrong subcontainer when
- // calling `objectAt`
- this._super(idx, removedCnt, addedCnt);
- },
-
- init: function() {
- this._super();
- this._subControllers = [];
- },
-
- model: computed(function () {
- return Ember.A();
- }),
-
- /**
- * Flag to mark as being "virtual". Used to keep this instance
- * from participating in the parentController hierarchy.
- *
- * @private
- * @property _isVirtual
- * @type Boolean
- */
- _isVirtual: false,
-
- controllerAt: function(idx, object, controllerClass) {
- var container = get(this, 'container');
- var subControllers = this._subControllers;
- var fullName, subController, subControllerFactory, parentController, options;
-
- if (subControllers.length > idx) {
- subController = subControllers[idx];
-
- if (subController) {
- return subController;
- }
- }
-
- if (this._isVirtual) {
- parentController = get(this, 'parentController');
- } else {
- parentController = this;
- }
-
-
- fullName = 'controller:' + controllerClass;
-
- if (!container.has(fullName)) {
- throw new EmberError('Could not resolve itemController: "' + controllerClass + '"');
- }
-
- subController = container.lookupFactory(fullName).create({
- target: parentController,
- parentController: parentController,
- model: object
- });
-
-
- subControllers[idx] = subController;
-
- return subController;
- },
-
- _subControllers: null,
-
- _resetSubControllers: function() {
- var controller;
- var subControllers = this._subControllers;
-
- if (subControllers.length) {
- for (var i = 0, length = subControllers.length; length > i; i++) {
- controller = subControllers[i];
-
- if (controller) {
- controller.destroy();
- }
- }
-
- subControllers.length = 0;
- }
- },
-
- willDestroy: function() {
- this._resetSubControllers();
- this._super();
- }
- });
- });
-enifed("ember-runtime/controllers/controller",
- ["ember-metal/core","ember-runtime/system/object","ember-runtime/mixins/controller","ember-runtime/inject","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
- "use strict";
- var Ember = __dependency1__["default"];
- // Ember.assert
- var EmberObject = __dependency2__["default"];
- var Mixin = __dependency3__["default"];
- var createInjectionHelper = __dependency4__.createInjectionHelper;
-
- /**
- @module ember
- @submodule ember-runtime
- */
-
- /**
- @class Controller
- @namespace Ember
- @extends Ember.Object
- @uses Ember.ControllerMixin
- */
- var Controller = EmberObject.extend(Mixin);
-
- function controllerInjectionHelper(factory) {
- Ember.assert("Defining an injected controller property on a " +
- "non-controller is not allowed.", Controller.detect(factory));
- }
-
-
- __exports__["default"] = Controller;
- });
-enifed("ember-runtime/controllers/object_controller",
- ["ember-runtime/mixins/controller","ember-runtime/system/object_proxy","exports"],
- function(__dependency1__, __dependency2__, __exports__) {
- "use strict";
- var ControllerMixin = __dependency1__["default"];
- var ObjectProxy = __dependency2__["default"];
-
- /**
- @module ember
- @submodule ember-runtime
- */
-
- /**
- `Ember.ObjectController` is part of Ember's Controller layer. It is intended
- to wrap a single object, proxying unhandled attempts to `get` and `set` to the underlying
- model object, and to forward unhandled action attempts to its `target`.
-
- `Ember.ObjectController` derives this functionality from its superclass
- `Ember.ObjectProxy` and the `Ember.ControllerMixin` mixin.
-
- @class ObjectController
- @namespace Ember
- @extends Ember.ObjectProxy
- @uses Ember.ControllerMixin
- **/
- __exports__["default"] = ObjectProxy.extend(ControllerMixin);
- });
-enifed("ember-runtime/copy",
- ["ember-metal/enumerable_utils","ember-metal/utils","ember-runtime/system/object","ember-runtime/mixins/copyable","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
- "use strict";
- var indexOf = __dependency1__.indexOf;
- var typeOf = __dependency2__.typeOf;
- var EmberObject = __dependency3__["default"];
- var Copyable = __dependency4__["default"];
-
- function _copy(obj, deep, seen, copies) {
- var ret, loc, key;
-
- // primitive data types are immutable, just return them.
- if (typeof obj !== 'object' || obj === null) {
- return obj;
- }
-
- // avoid cyclical loops
- if (deep && (loc = indexOf(seen, obj)) >= 0) {
- return copies[loc];
- }
-
- Ember.assert('Cannot clone an Ember.Object that does not implement Ember.Copyable',
- !(obj instanceof EmberObject) || (Copyable && Copyable.detect(obj)));
-
- // IMPORTANT: this specific test will detect a native array only. Any other
- // object will need to implement Copyable.
- if (typeOf(obj) === 'array') {
- ret = obj.slice();
-
- if (deep) {
- loc = ret.length;
-
- while (--loc >= 0) {
- ret[loc] = _copy(ret[loc], deep, seen, copies);
- }
- }
- } else if (Copyable && Copyable.detect(obj)) {
- ret = obj.copy(deep, seen, copies);
- } else if (obj instanceof Date) {
- ret = new Date(obj.getTime());
- } else {
- ret = {};
-
- for (key in obj) {
- // support Null prototype
- if (!Object.prototype.hasOwnProperty.call(obj, key)) {
- continue;
- }
-
- // Prevents browsers that don't respect non-enumerability from
- // copying internal Ember properties
- if (key.substring(0, 2) === '__') {
- continue;
- }
-
- ret[key] = deep ? _copy(obj[key], deep, seen, copies) : obj[key];
- }
- }
-
- if (deep) {
- seen.push(obj);
- copies.push(ret);
- }
-
- return ret;
- }
-
- /**
- Creates a clone of the passed object. This function can take just about
- any type of object and create a clone of it, including primitive values
- (which are not actually cloned because they are immutable).
-
- If the passed object implements the `copy()` method, then this function
- will simply call that method and return the result. Please see
- `Ember.Copyable` for further details.
-
- @method copy
- @for Ember
- @param {Object} obj The object to clone
- @param {Boolean} deep If true, a deep copy of the object is made
- @return {Object} The cloned object
- */
- __exports__["default"] = function copy(obj, deep) {
- // fast paths
- if ('object' !== typeof obj || obj === null) {
- return obj; // can't copy primitives
- }
-
- if (Copyable && Copyable.detect(obj)) {
- return obj.copy(deep);
- }
-
- return _copy(obj, deep, deep ? [] : null, deep ? [] : null);
- }
- });
-enifed("ember-runtime/core",
- ["exports"],
- function(__exports__) {
- "use strict";
- /**
- @module ember
- @submodule ember-runtime
- */
-
- /**
- Compares two objects, returning true if they are logically equal. This is
- a deeper comparison than a simple triple equal. For sets it will compare the
- internal objects. For any other object that implements `isEqual()` it will
- respect that method.
-
- ```javascript
- Ember.isEqual('hello', 'hello'); // true
- Ember.isEqual(1, 2); // false
- Ember.isEqual([4, 2], [4, 2]); // false
- ```
-
- @method isEqual
- @for Ember
- @param {Object} a first object to compare
- @param {Object} b second object to compare
- @return {Boolean}
- */
- var isEqual = function isEqual(a, b) {
- if (a && typeof a.isEqual === 'function') {
- return a.isEqual(b);
- }
-
- if (a instanceof Date && b instanceof Date) {
- return a.getTime() === b.getTime();
- }
-
- return a === b;
- };
- __exports__.isEqual = isEqual;
- });
-enifed("ember-runtime/ext/function",
- ["ember-metal/core","ember-metal/expand_properties","ember-metal/computed","ember-metal/mixin"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__) {
- "use strict";
- /**
- @module ember
- @submodule ember-runtime
- */
-
- var Ember = __dependency1__["default"];
- // Ember.EXTEND_PROTOTYPES, Ember.assert
- var expandProperties = __dependency2__["default"];
- var computed = __dependency3__.computed;
- var observer = __dependency4__.observer;
-
- var a_slice = Array.prototype.slice;
- var FunctionPrototype = Function.prototype;
-
- if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.Function) {
-
- /**
- The `property` extension of Javascript's Function prototype is available
- when `Ember.EXTEND_PROTOTYPES` or `Ember.EXTEND_PROTOTYPES.Function` is
- `true`, which is the default.
-
- Computed properties allow you to treat a function like a property:
-
- ```javascript
- MyApp.President = Ember.Object.extend({
- firstName: '',
- lastName: '',
-
- fullName: function() {
- return this.get('firstName') + ' ' + this.get('lastName');
- }.property() // Call this flag to mark the function as a property
- });
-
- var president = MyApp.President.create({
- firstName: 'Barack',
- lastName: 'Obama'
- });
-
- president.get('fullName'); // 'Barack Obama'
- ```
-
- Treating a function like a property is useful because they can work with
- bindings, just like any other property.
-
- Many computed properties have dependencies on other properties. For
- example, in the above example, the `fullName` property depends on
- `firstName` and `lastName` to determine its value. You can tell Ember
- about these dependencies like this:
-
- ```javascript
- MyApp.President = Ember.Object.extend({
- firstName: '',
- lastName: '',
-
- fullName: function() {
- return this.get('firstName') + ' ' + this.get('lastName');
-
- // Tell Ember.js that this computed property depends on firstName
- // and lastName
- }.property('firstName', 'lastName')
- });
- ```
-
- Make sure you list these dependencies so Ember knows when to update
- bindings that connect to a computed property. Changing a dependency
- will not immediately trigger an update of the computed property, but
- will instead clear the cache so that it is updated when the next `get`
- is called on the property.
-
- See [Ember.ComputedProperty](/api/classes/Ember.ComputedProperty.html), [Ember.computed](/api/#method_computed).
-
- @method property
- @for Function
- */
- FunctionPrototype.property = function () {
- var ret = computed(this);
- // ComputedProperty.prototype.property expands properties; no need for us to
- // do so here.
- return ret.property.apply(ret, arguments);
- };
-
- /**
- The `observes` extension of Javascript's Function prototype is available
- when `Ember.EXTEND_PROTOTYPES` or `Ember.EXTEND_PROTOTYPES.Function` is
- true, which is the default.
-
- You can observe property changes simply by adding the `observes`
- call to the end of your method declarations in classes that you write.
- For example:
-
- ```javascript
- Ember.Object.extend({
- valueObserver: function() {
- // Executes whenever the "value" property changes
- }.observes('value')
- });
- ```
-
- In the future this method may become asynchronous. If you want to ensure
- synchronous behavior, use `observesImmediately`.
-
- See `Ember.observer`.
-
- @method observes
- @for Function
- */
- FunctionPrototype.observes = function() {
- var length = arguments.length;
- var args = new Array(length);
- for (var x = 0; x < length; x++) {
- args[x] = arguments[x];
- }
- return observer.apply(this, args.concat(this));
- };
-
- /**
- The `observesImmediately` extension of Javascript's Function prototype is
- available when `Ember.EXTEND_PROTOTYPES` or
- `Ember.EXTEND_PROTOTYPES.Function` is true, which is the default.
-
- You can observe property changes simply by adding the `observesImmediately`
- call to the end of your method declarations in classes that you write.
- For example:
-
- ```javascript
- Ember.Object.extend({
- valueObserver: function() {
- // Executes immediately after the "value" property changes
- }.observesImmediately('value')
- });
- ```
-
- In the future, `observes` may become asynchronous. In this event,
- `observesImmediately` will maintain the synchronous behavior.
-
- See `Ember.immediateObserver`.
-
- @method observesImmediately
- @for Function
- */
- FunctionPrototype.observesImmediately = function () {
- for (var i = 0, l = arguments.length; i < l; i++) {
- var arg = arguments[i];
- Ember.assert('Immediate observers must observe internal properties only, ' +
- 'not properties on other objects.', arg.indexOf('.') === -1);
- }
-
- // observes handles property expansion
- return this.observes.apply(this, arguments);
- };
-
- /**
- The `observesBefore` extension of Javascript's Function prototype is
- available when `Ember.EXTEND_PROTOTYPES` or
- `Ember.EXTEND_PROTOTYPES.Function` is true, which is the default.
-
- You can get notified when a property change is about to happen by
- by adding the `observesBefore` call to the end of your method
- declarations in classes that you write. For example:
-
- ```javascript
- Ember.Object.extend({
- valueObserver: function() {
- // Executes whenever the "value" property is about to change
- }.observesBefore('value')
- });
- ```
-
- See `Ember.beforeObserver`.
-
- @method observesBefore
- @for Function
- */
- FunctionPrototype.observesBefore = function () {
- var watched = [];
- var addWatchedProperty = function (obs) {
- watched.push(obs);
- };
-
- for (var i = 0, l = arguments.length; i < l; ++i) {
- expandProperties(arguments[i], addWatchedProperty);
- }
-
- this.__ember_observesBefore__ = watched;
-
- return this;
- };
-
- /**
- The `on` extension of Javascript's Function prototype is available
- when `Ember.EXTEND_PROTOTYPES` or `Ember.EXTEND_PROTOTYPES.Function` is
- true, which is the default.
-
- You can listen for events simply by adding the `on` call to the end of
- your method declarations in classes or mixins that you write. For example:
-
- ```javascript
- Ember.Mixin.create({
- doSomethingWithElement: function() {
- // Executes whenever the "didInsertElement" event fires
- }.on('didInsertElement')
- });
- ```
-
- See `Ember.on`.
-
- @method on
- @for Function
- */
- FunctionPrototype.on = function () {
- var events = a_slice.call(arguments);
- this.__ember_listens__ = events;
-
- return this;
- };
- }
- });
-enifed("ember-runtime/ext/rsvp",
- ["ember-metal/core","ember-metal/logger","ember-metal/run_loop","rsvp","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
- "use strict";
- /* globals RSVP:true */
-
- var Ember = __dependency1__["default"];
- var Logger = __dependency2__["default"];
- var run = __dependency3__["default"];
-
- // this is technically incorrect (per @wycats)
- // it should be `import * as RSVP from 'rsvp';` but
- // Esprima does not support this syntax yet (and neither does
- // es6-module-transpiler 0.4.0 - 0.6.2).
- var RSVP = __dependency4__;
-
- var testModuleName = 'ember-testing/test';
- var Test;
-
- var asyncStart = function() {
- if (Ember.Test && Ember.Test.adapter) {
- Ember.Test.adapter.asyncStart();
- }
- };
-
- var asyncEnd = function() {
- if (Ember.Test && Ember.Test.adapter) {
- Ember.Test.adapter.asyncEnd();
- }
- };
-
- RSVP.configure('async', function(callback, promise) {
- var async = !run.currentRunLoop;
-
- if (Ember.testing && async) { asyncStart(); }
-
- run.backburner.schedule('actions', function(){
- if (Ember.testing && async) { asyncEnd(); }
- callback(promise);
- });
- });
-
- RSVP.Promise.prototype.fail = function(callback, label){
- Ember.deprecate('RSVP.Promise.fail has been renamed as RSVP.Promise.catch');
- return this['catch'](callback, label);
- };
-
- RSVP.onerrorDefault = function (error) {
- if (error && error.name !== 'TransitionAborted') {
- if (Ember.testing) {
- // ES6TODO: remove when possible
- if (!Test && Ember.__loader.registry[testModuleName]) {
- Test = requireModule(testModuleName)['default'];
- }
-
- if (Test && Test.adapter) {
- Test.adapter.exception(error);
- Logger.error(error.stack);
- } else {
- throw error;
- }
- } else if (Ember.onerror) {
- Ember.onerror(error);
- } else {
- Logger.error(error.stack);
- Ember.assert(error, false);
- }
- }
- };
-
- RSVP.on('error', RSVP.onerrorDefault);
-
- __exports__["default"] = RSVP;
- });
-enifed("ember-runtime/ext/string",
- ["ember-metal/core","ember-runtime/system/string"],
- function(__dependency1__, __dependency2__) {
- "use strict";
- /**
- @module ember
- @submodule ember-runtime
- */
-
- var Ember = __dependency1__["default"];
- // Ember.EXTEND_PROTOTYPES, Ember.assert, Ember.FEATURES
- var fmt = __dependency2__.fmt;
- var w = __dependency2__.w;
- var loc = __dependency2__.loc;
- var camelize = __dependency2__.camelize;
- var decamelize = __dependency2__.decamelize;
- var dasherize = __dependency2__.dasherize;
- var underscore = __dependency2__.underscore;
- var capitalize = __dependency2__.capitalize;
- var classify = __dependency2__.classify;
-
- var StringPrototype = String.prototype;
-
- if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.String) {
-
- /**
- See [Ember.String.fmt](/api/classes/Ember.String.html#method_fmt).
-
- @method fmt
- @for String
- */
- StringPrototype.fmt = function () {
- return fmt(this, arguments);
- };
-
- /**
- See [Ember.String.w](/api/classes/Ember.String.html#method_w).
-
- @method w
- @for String
- */
- StringPrototype.w = function () {
- return w(this);
- };
-
- /**
- See [Ember.String.loc](/api/classes/Ember.String.html#method_loc).
-
- @method loc
- @for String
- */
- StringPrototype.loc = function () {
- return loc(this, arguments);
- };
-
- /**
- See [Ember.String.camelize](/api/classes/Ember.String.html#method_camelize).
-
- @method camelize
- @for String
- */
- StringPrototype.camelize = function () {
- return camelize(this);
- };
-
- /**
- See [Ember.String.decamelize](/api/classes/Ember.String.html#method_decamelize).
-
- @method decamelize
- @for String
- */
- StringPrototype.decamelize = function () {
- return decamelize(this);
- };
-
- /**
- See [Ember.String.dasherize](/api/classes/Ember.String.html#method_dasherize).
-
- @method dasherize
- @for String
- */
- StringPrototype.dasherize = function () {
- return dasherize(this);
- };
-
- /**
- See [Ember.String.underscore](/api/classes/Ember.String.html#method_underscore).
-
- @method underscore
- @for String
- */
- StringPrototype.underscore = function () {
- return underscore(this);
- };
-
- /**
- See [Ember.String.classify](/api/classes/Ember.String.html#method_classify).
-
- @method classify
- @for String
- */
- StringPrototype.classify = function () {
- return classify(this);
- };
-
- /**
- See [Ember.String.capitalize](/api/classes/Ember.String.html#method_capitalize).
-
- @method capitalize
- @for String
- */
- StringPrototype.capitalize = function () {
- return capitalize(this);
- };
- }
- });
-enifed("ember-runtime/inject",
- ["ember-metal/core","ember-metal/enumerable_utils","ember-metal/injected_property","ember-metal/keys","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
- "use strict";
- var Ember = __dependency1__["default"];
- // Ember.assert
- var indexOf = __dependency2__.indexOf;
- var InjectedProperty = __dependency3__["default"];
- var keys = __dependency4__["default"];
-
- /**
- Namespace for injection helper methods.
-
- @class inject
- @namespace Ember
- */
- function inject() {
- Ember.assert("Injected properties must be created through helpers, see `" +
- keys(inject).join("`, `") + "`");
- }
-
- // Dictionary of injection validations by type, added to by `createInjectionHelper`
- var typeValidators = {};
-
- /**
- This method allows other Ember modules to register injection helpers for a
- given container type. Helpers are exported to the `inject` namespace as the
- container type itself.
-
- @private
- @method createInjectionHelper
- @namespace Ember
- @param {String} type The container type the helper will inject
- @param {Function} validator A validation callback that is executed at mixin-time
- */
- function createInjectionHelper(type, validator) {
- typeValidators[type] = validator;
-
- inject[type] = function(name) {
- return new InjectedProperty(type, name);
- };
- }
-
- __exports__.createInjectionHelper = createInjectionHelper;/**
- Validation function intended to be invoked at when extending a factory with
- injected properties. Runs per-type validation functions once for each injected
- type encountered.
-
- Note that this currently modifies the mixin themselves, which is technically
- dubious but is practically of little consequence. This may change in the
- future.
-
- @private
- @method validatePropertyInjections
- @namespace Ember
- @param {Object} factory The factory object being extended
- @param {Object} props A hash of properties to be added to the factory
- */
- function validatePropertyInjections(factory, props) {
- var types = [];
- var key, desc, validator, i, l;
-
- for (key in props) {
- desc = props[key];
- if (desc instanceof InjectedProperty && indexOf(types, desc.type) === -1) {
- types.push(desc.type);
- }
- }
-
- if (types.length) {
- for (i = 0, l = types.length; i < l; i++) {
- validator = typeValidators[types[i]];
-
- if (typeof validator === 'function') {
- validator(factory);
- }
- }
- }
-
- return true;
- }
-
- __exports__.validatePropertyInjections = validatePropertyInjections;__exports__["default"] = inject;
- });
-enifed("ember-runtime/mixins/-proxy",
- ["ember-metal/core","ember-metal/property_get","ember-metal/property_set","ember-metal/utils","ember-metal/observer","ember-metal/property_events","ember-metal/computed","ember-metal/properties","ember-metal/mixin","ember-runtime/system/string","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __exports__) {
- "use strict";
- /**
- @module ember
- @submodule ember-runtime
- */
-
- var Ember = __dependency1__["default"];
- // Ember.assert
- var get = __dependency2__.get;
- var set = __dependency3__.set;
- var meta = __dependency4__.meta;
- var addObserver = __dependency5__.addObserver;
- var removeObserver = __dependency5__.removeObserver;
- var addBeforeObserver = __dependency5__.addBeforeObserver;
- var removeBeforeObserver = __dependency5__.removeBeforeObserver;
- var propertyWillChange = __dependency6__.propertyWillChange;
- var propertyDidChange = __dependency6__.propertyDidChange;
- var computed = __dependency7__.computed;
- var defineProperty = __dependency8__.defineProperty;
- var Mixin = __dependency9__.Mixin;
- var observer = __dependency9__.observer;
- var fmt = __dependency10__.fmt;
-
- function contentPropertyWillChange(content, contentKey) {
- var key = contentKey.slice(8); // remove "content."
- if (key in this) { return; } // if shadowed in proxy
- propertyWillChange(this, key);
- }
-
- function contentPropertyDidChange(content, contentKey) {
- var key = contentKey.slice(8); // remove "content."
- if (key in this) { return; } // if shadowed in proxy
- propertyDidChange(this, key);
- }
-
- /**
- `Ember.ProxyMixin` forwards all properties not defined by the proxy itself
- to a proxied `content` object. See Ember.ObjectProxy for more details.
-
- @class ProxyMixin
- @namespace Ember
- */
- __exports__["default"] = Mixin.create({
- /**
- The object whose properties will be forwarded.
-
- @property content
- @type Ember.Object
- @default null
- */
- content: null,
- _contentDidChange: observer('content', function() {
- Ember.assert("Can't set Proxy's content to itself", get(this, 'content') !== this);
- }),
-
- isTruthy: computed.bool('content'),
-
- _debugContainerKey: null,
-
- willWatchProperty: function (key) {
- var contentKey = 'content.' + key;
- addBeforeObserver(this, contentKey, null, contentPropertyWillChange);
- addObserver(this, contentKey, null, contentPropertyDidChange);
- },
-
- didUnwatchProperty: function (key) {
- var contentKey = 'content.' + key;
- removeBeforeObserver(this, contentKey, null, contentPropertyWillChange);
- removeObserver(this, contentKey, null, contentPropertyDidChange);
- },
-
- unknownProperty: function (key) {
- var content = get(this, 'content');
- if (content) {
- return get(content, key);
- }
- },
-
- setUnknownProperty: function (key, value) {
- var m = meta(this);
- if (m.proto === this) {
- // if marked as prototype then just defineProperty
- // rather than delegate
- defineProperty(this, key, null, value);
- return value;
- }
-
- var content = get(this, 'content');
- Ember.assert(fmt("Cannot delegate set('%@', %@) to the 'content' property of" +
- " object proxy %@: its 'content' is undefined.", [key, value, this]), content);
- return set(content, key, value);
- }
-
- });
- });
-enifed("ember-runtime/mixins/action_handler",
- ["ember-metal/merge","ember-metal/mixin","ember-metal/property_get","ember-metal/utils","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
- "use strict";
- /**
- @module ember
- @submodule ember-runtime
- */
- var merge = __dependency1__["default"];
- var Mixin = __dependency2__.Mixin;
- var get = __dependency3__.get;
- var typeOf = __dependency4__.typeOf;
-
- /**
- The `Ember.ActionHandler` mixin implements support for moving an `actions`
- property to an `_actions` property at extend time, and adding `_actions`
- to the object's mergedProperties list.
-
- `Ember.ActionHandler` is available on some familiar classes including
- `Ember.Route`, `Ember.View`, `Ember.Component`, and controllers such as
- `Ember.Controller` and `Ember.ObjectController`.
- (Internally the mixin is used by `Ember.CoreView`, `Ember.ControllerMixin`,
- and `Ember.Route` and available to the above classes through
- inheritance.)
-
- @class ActionHandler
- @namespace Ember
- */
- var ActionHandler = Mixin.create({
- mergedProperties: ['_actions'],
-
- /**
- The collection of functions, keyed by name, available on this
- `ActionHandler` as action targets.
-
- These functions will be invoked when a matching `{{action}}` is triggered
- from within a template and the application's current route is this route.
-
- Actions can also be invoked from other parts of your application
- via `ActionHandler#send`.
-
- The `actions` hash will inherit action handlers from
- the `actions` hash defined on extended parent classes
- or mixins rather than just replace the entire hash, e.g.:
-
- ```js
- App.CanDisplayBanner = Ember.Mixin.create({
- actions: {
- displayBanner: function(msg) {
- // ...
- }
- }
- });
-
- App.WelcomeRoute = Ember.Route.extend(App.CanDisplayBanner, {
- actions: {
- playMusic: function() {
- // ...
- }
- }
- });
-
- // `WelcomeRoute`, when active, will be able to respond
- // to both actions, since the actions hash is merged rather
- // then replaced when extending mixins / parent classes.
- this.send('displayBanner');
- this.send('playMusic');
- ```
-
- Within a Controller, Route, View or Component's action handler,
- the value of the `this` context is the Controller, Route, View or
- Component object:
-
- ```js
- App.SongRoute = Ember.Route.extend({
- actions: {
- myAction: function() {
- this.controllerFor("song");
- this.transitionTo("other.route");
- ...
- }
- }
- });
- ```
-
- It is also possible to call `this._super()` from within an
- action handler if it overrides a handler defined on a parent
- class or mixin:
-
- Take for example the following routes:
-
- ```js
- App.DebugRoute = Ember.Mixin.create({
- actions: {
- debugRouteInformation: function() {
- console.debug("trololo");
- }
- }
- });
-
- App.AnnoyingDebugRoute = Ember.Route.extend(App.DebugRoute, {
- actions: {
- debugRouteInformation: function() {
- // also call the debugRouteInformation of mixed in App.DebugRoute
- this._super();
-
- // show additional annoyance
- window.alert(...);
- }
- }
- });
- ```
-
- ## Bubbling
-
- By default, an action will stop bubbling once a handler defined
- on the `actions` hash handles it. To continue bubbling the action,
- you must return `true` from the handler:
-
- ```js
- App.Router.map(function() {
- this.resource("album", function() {
- this.route("song");
- });
- });
-
- App.AlbumRoute = Ember.Route.extend({
- actions: {
- startPlaying: function() {
- }
- }
- });
-
- App.AlbumSongRoute = Ember.Route.extend({
- actions: {
- startPlaying: function() {
- // ...
-
- if (actionShouldAlsoBeTriggeredOnParentRoute) {
- return true;
- }
- }
- }
- });
- ```
-
- @property actions
- @type Hash
- @default null
- */
-
- /**
- Moves `actions` to `_actions` at extend time. Note that this currently
- modifies the mixin themselves, which is technically dubious but
- is practically of little consequence. This may change in the future.
-
- @private
- @method willMergeMixin
- */
- willMergeMixin: function(props) {
-
- var hashName;
-
- if (!props._actions) {
- Ember.assert("'actions' should not be a function", typeof(props.actions) !== 'function');
-
- if (typeOf(props.actions) === 'object') {
- hashName = 'actions';
- } else if (typeOf(props.events) === 'object') {
- Ember.deprecate('Action handlers contained in an `events` object are deprecated in favor' +
- ' of putting them in an `actions` object', false);
- hashName = 'events';
- }
-
- if (hashName) {
- props._actions = merge(props._actions || {}, props[hashName]);
- }
-
- delete props[hashName];
- }
- },
-
- /**
- Triggers a named action on the `ActionHandler`. Any parameters
- supplied after the `actionName` string will be passed as arguments
- to the action target function.
-
- If the `ActionHandler` has its `target` property set, actions may
- bubble to the `target`. Bubbling happens when an `actionName` can
- not be found in the `ActionHandler`'s `actions` hash or if the
- action target function returns `true`.
-
- Example
-
- ```js
- App.WelcomeRoute = Ember.Route.extend({
- actions: {
- playTheme: function() {
- this.send('playMusic', 'theme.mp3');
- },
- playMusic: function(track) {
- // ...
- }
- }
- });
- ```
-
- @method send
- @param {String} actionName The action to trigger
- @param {*} context a context to send with the action
- */
- send: function(actionName) {
- var args = [].slice.call(arguments, 1);
- var target;
-
- if (this._actions && this._actions[actionName]) {
- if (this._actions[actionName].apply(this, args) === true) {
- // handler returned true, so this action will bubble
- } else {
- return;
- }
- }
-
- if (target = get(this, 'target')) {
- Ember.assert("The `target` for " + this + " (" + target +
- ") does not have a `send` method", typeof target.send === 'function');
- target.send.apply(target, arguments);
- }
- }
- });
-
- __exports__["default"] = ActionHandler;
- });
-enifed("ember-runtime/mixins/array",
- ["ember-metal/core","ember-metal/property_get","ember-metal/computed","ember-metal/is_none","ember-runtime/mixins/enumerable","ember-metal/enumerable_utils","ember-metal/mixin","ember-metal/property_events","ember-metal/events","ember-metal/watching","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __exports__) {
- "use strict";
- /**
- @module ember
- @submodule ember-runtime
- */
-
- // ..........................................................
- // HELPERS
- //
- var Ember = __dependency1__["default"];
- // ES6TODO: Ember.A
-
- var get = __dependency2__.get;
- var computed = __dependency3__.computed;
- var cacheFor = __dependency3__.cacheFor;
- var isNone = __dependency4__["default"];
- var Enumerable = __dependency5__["default"];
- var map = __dependency6__.map;
- var Mixin = __dependency7__.Mixin;
- var required = __dependency7__.required;
- var propertyWillChange = __dependency8__.propertyWillChange;
- var propertyDidChange = __dependency8__.propertyDidChange;
- var addListener = __dependency9__.addListener;
- var removeListener = __dependency9__.removeListener;
- var sendEvent = __dependency9__.sendEvent;
- var hasListeners = __dependency9__.hasListeners;
- var isWatching = __dependency10__.isWatching;
-
- function arrayObserversHelper(obj, target, opts, operation, notify) {
- var willChange = (opts && opts.willChange) || 'arrayWillChange';
- var didChange = (opts && opts.didChange) || 'arrayDidChange';
- var hasObservers = get(obj, 'hasArrayObservers');
-
- if (hasObservers === notify) {
- propertyWillChange(obj, 'hasArrayObservers');
- }
-
- operation(obj, '@array:before', target, willChange);
- operation(obj, '@array:change', target, didChange);
-
- if (hasObservers === notify) {
- propertyDidChange(obj, 'hasArrayObservers');
- }
-
- return obj;
- }
-
- // ..........................................................
- // ARRAY
- //
- /**
- This mixin implements Observer-friendly Array-like behavior. It is not a
- concrete implementation, but it can be used up by other classes that want
- to appear like arrays.
-
- For example, ArrayProxy and ArrayController are both concrete classes that can
- be instantiated to implement array-like behavior. Both of these classes use
- the Array Mixin by way of the MutableArray mixin, which allows observable
- changes to be made to the underlying array.
-
- Unlike `Ember.Enumerable,` this mixin defines methods specifically for
- collections that provide index-ordered access to their contents. When you
- are designing code that needs to accept any kind of Array-like object, you
- should use these methods instead of Array primitives because these will
- properly notify observers of changes to the array.
-
- Although these methods are efficient, they do add a layer of indirection to
- your application so it is a good idea to use them only when you need the
- flexibility of using both true JavaScript arrays and "virtual" arrays such
- as controllers and collections.
-
- You can use the methods defined in this module to access and modify array
- contents in a KVO-friendly way. You can also be notified whenever the
- membership of an array changes by using `.observes('myArray.[]')`.
-
- To support `Ember.Array` in your own class, you must override two
- primitives to use it: `replace()` and `objectAt()`.
-
- Note that the Ember.Array mixin also incorporates the `Ember.Enumerable`
- mixin. All `Ember.Array`-like objects are also enumerable.
-
- @class Array
- @namespace Ember
- @uses Ember.Enumerable
- @since Ember 0.9.0
- */
- __exports__["default"] = Mixin.create(Enumerable, {
-
- /**
- Your array must support the `length` property. Your replace methods should
- set this property whenever it changes.
-
- @property {Number} length
- */
- length: required(),
-
- /**
- Returns the object at the given `index`. If the given `index` is negative
- or is greater or equal than the array length, returns `undefined`.
-
- This is one of the primitives you must implement to support `Ember.Array`.
- If your object supports retrieving the value of an array item using `get()`
- (i.e. `myArray.get(0)`), then you do not need to implement this method
- yourself.
-
- ```javascript
- var arr = ['a', 'b', 'c', 'd'];
-
- arr.objectAt(0); // 'a'
- arr.objectAt(3); // 'd'
- arr.objectAt(-1); // undefined
- arr.objectAt(4); // undefined
- arr.objectAt(5); // undefined
- ```
-
- @method objectAt
- @param {Number} idx The index of the item to return.
- @return {*} item at index or undefined
- */
- objectAt: function(idx) {
- if (idx < 0 || idx >= get(this, 'length')) {
- return undefined;
- }
-
- return get(this, idx);
- },
-
- /**
- This returns the objects at the specified indexes, using `objectAt`.
-
- ```javascript
- var arr = ['a', 'b', 'c', 'd'];
-
- arr.objectsAt([0, 1, 2]); // ['a', 'b', 'c']
- arr.objectsAt([2, 3, 4]); // ['c', 'd', undefined]
- ```
-
- @method objectsAt
- @param {Array} indexes An array of indexes of items to return.
- @return {Array}
- */
- objectsAt: function(indexes) {
- var self = this;
-
- return map(indexes, function(idx) {
- return self.objectAt(idx);
- });
- },
-
- // overrides Ember.Enumerable version
- nextObject: function(idx) {
- return this.objectAt(idx);
- },
-
- /**
- This is the handler for the special array content property. If you get
- this property, it will return this. If you set this property to a new
- array, it will replace the current content.
-
- This property overrides the default property defined in `Ember.Enumerable`.
-
- @property []
- @return this
- */
- '[]': computed(function(key, value) {
- if (value !== undefined) {
- this.replace(0, get(this, 'length'), value);
- }
-
- return this;
- }),
-
- firstObject: computed(function() {
- return this.objectAt(0);
- }),
-
- lastObject: computed(function() {
- return this.objectAt(get(this, 'length') - 1);
- }),
-
- // optimized version from Enumerable
- contains: function(obj) {
- return this.indexOf(obj) >= 0;
- },
-
- // Add any extra methods to Ember.Array that are native to the built-in Array.
- /**
- Returns a new array that is a slice of the receiver. This implementation
- uses the observable array methods to retrieve the objects for the new
- slice.
-
- ```javascript
- var arr = ['red', 'green', 'blue'];
-
- arr.slice(0); // ['red', 'green', 'blue']
- arr.slice(0, 2); // ['red', 'green']
- arr.slice(1, 100); // ['green', 'blue']
- ```
-
- @method slice
- @param {Integer} beginIndex (Optional) index to begin slicing from.
- @param {Integer} endIndex (Optional) index to end the slice at (but not included).
- @return {Array} New array with specified slice
- */
- slice: function(beginIndex, endIndex) {
- var ret = Ember.A();
- var length = get(this, 'length');
-
- if (isNone(beginIndex)) {
- beginIndex = 0;
- }
-
- if (isNone(endIndex) || (endIndex > length)) {
- endIndex = length;
- }
-
- if (beginIndex < 0) {
- beginIndex = length + beginIndex;
- }
-
- if (endIndex < 0) {
- endIndex = length + endIndex;
- }
-
- while (beginIndex < endIndex) {
- ret[ret.length] = this.objectAt(beginIndex++);
- }
-
- return ret;
- },
-
- /**
- Returns the index of the given object's first occurrence.
- If no `startAt` argument is given, the starting location to
- search is 0. If it's negative, will count backward from
- the end of the array. Returns -1 if no match is found.
-
- ```javascript
- var arr = ['a', 'b', 'c', 'd', 'a'];
-
- arr.indexOf('a'); // 0
- arr.indexOf('z'); // -1
- arr.indexOf('a', 2); // 4
- arr.indexOf('a', -1); // 4
- arr.indexOf('b', 3); // -1
- arr.indexOf('a', 100); // -1
- ```
-
- @method indexOf
- @param {Object} object the item to search for
- @param {Number} startAt optional starting location to search, default 0
- @return {Number} index or -1 if not found
- */
- indexOf: function(object, startAt) {
- var len = get(this, 'length');
- var idx;
-
- if (startAt === undefined) {
- startAt = 0;
- }
-
- if (startAt < 0) {
- startAt += len;
- }
-
- for (idx = startAt; idx < len; idx++) {
- if (this.objectAt(idx) === object) {
- return idx;
- }
- }
-
- return -1;
- },
-
- /**
- Returns the index of the given object's last occurrence.
- If no `startAt` argument is given, the search starts from
- the last position. If it's negative, will count backward
- from the end of the array. Returns -1 if no match is found.
-
- ```javascript
- var arr = ['a', 'b', 'c', 'd', 'a'];
-
- arr.lastIndexOf('a'); // 4
- arr.lastIndexOf('z'); // -1
- arr.lastIndexOf('a', 2); // 0
- arr.lastIndexOf('a', -1); // 4
- arr.lastIndexOf('b', 3); // 1
- arr.lastIndexOf('a', 100); // 4
- ```
-
- @method lastIndexOf
- @param {Object} object the item to search for
- @param {Number} startAt optional starting location to search, default 0
- @return {Number} index or -1 if not found
- */
- lastIndexOf: function(object, startAt) {
- var len = get(this, 'length');
- var idx;
-
- if (startAt === undefined || startAt >= len) {
- startAt = len-1;
- }
-
- if (startAt < 0) {
- startAt += len;
- }
-
- for (idx = startAt; idx >= 0; idx--) {
- if (this.objectAt(idx) === object) {
- return idx;
- }
- }
-
- return -1;
- },
-
- // ..........................................................
- // ARRAY OBSERVERS
- //
-
- /**
- Adds an array observer to the receiving array. The array observer object
- normally must implement two methods:
-
- * `arrayWillChange(observedObj, start, removeCount, addCount)` - This method will be
- called just before the array is modified.
- * `arrayDidChange(observedObj, start, removeCount, addCount)` - This method will be
- called just after the array is modified.
-
- Both callbacks will be passed the observed object, starting index of the
- change as well a a count of the items to be removed and added. You can use
- these callbacks to optionally inspect the array during the change, clear
- caches, or do any other bookkeeping necessary.
-
- In addition to passing a target, you can also include an options hash
- which you can use to override the method names that will be invoked on the
- target.
-
- @method addArrayObserver
- @param {Object} target The observer object.
- @param {Hash} opts Optional hash of configuration options including
- `willChange` and `didChange` option.
- @return {Ember.Array} receiver
- */
-
- addArrayObserver: function(target, opts) {
- return arrayObserversHelper(this, target, opts, addListener, false);
- },
-
- /**
- Removes an array observer from the object if the observer is current
- registered. Calling this method multiple times with the same object will
- have no effect.
-
- @method removeArrayObserver
- @param {Object} target The object observing the array.
- @param {Hash} opts Optional hash of configuration options including
- `willChange` and `didChange` option.
- @return {Ember.Array} receiver
- */
- removeArrayObserver: function(target, opts) {
- return arrayObserversHelper(this, target, opts, removeListener, true);
- },
-
- /**
- Becomes true whenever the array currently has observers watching changes
- on the array.
-
- @property {Boolean} hasArrayObservers
- */
- hasArrayObservers: computed(function() {
- return hasListeners(this, '@array:change') || hasListeners(this, '@array:before');
- }),
-
- /**
- If you are implementing an object that supports `Ember.Array`, call this
- method just before the array content changes to notify any observers and
- invalidate any related properties. Pass the starting index of the change
- as well as a delta of the amounts to change.
-
- @method arrayContentWillChange
- @param {Number} startIdx The starting index in the array that will change.
- @param {Number} removeAmt The number of items that will be removed. If you
- pass `null` assumes 0
- @param {Number} addAmt The number of items that will be added. If you
- pass `null` assumes 0.
- @return {Ember.Array} receiver
- */
- arrayContentWillChange: function(startIdx, removeAmt, addAmt) {
- var removing, lim;
-
- // if no args are passed assume everything changes
- if (startIdx === undefined) {
- startIdx = 0;
- removeAmt = addAmt = -1;
- } else {
- if (removeAmt === undefined) {
- removeAmt = -1;
- }
-
- if (addAmt === undefined) {
- addAmt = -1;
- }
- }
-
- // Make sure the @each proxy is set up if anyone is observing @each
- if (isWatching(this, '@each')) {
- get(this, '@each');
- }
-
- sendEvent(this, '@array:before', [this, startIdx, removeAmt, addAmt]);
-
- if (startIdx >= 0 && removeAmt >= 0 && get(this, 'hasEnumerableObservers')) {
- removing = [];
- lim = startIdx + removeAmt;
-
- for (var idx = startIdx; idx < lim; idx++) {
- removing.push(this.objectAt(idx));
- }
- } else {
- removing = removeAmt;
- }
-
- this.enumerableContentWillChange(removing, addAmt);
-
- return this;
- },
-
- /**
- If you are implementing an object that supports `Ember.Array`, call this
- method just after the array content changes to notify any observers and
- invalidate any related properties. Pass the starting index of the change
- as well as a delta of the amounts to change.
-
- @method arrayContentDidChange
- @param {Number} startIdx The starting index in the array that did change.
- @param {Number} removeAmt The number of items that were removed. If you
- pass `null` assumes 0
- @param {Number} addAmt The number of items that were added. If you
- pass `null` assumes 0.
- @return {Ember.Array} receiver
- */
- arrayContentDidChange: function(startIdx, removeAmt, addAmt) {
- var adding, lim;
-
- // if no args are passed assume everything changes
- if (startIdx === undefined) {
- startIdx = 0;
- removeAmt = addAmt = -1;
- } else {
- if (removeAmt === undefined) {
- removeAmt = -1;
- }
-
- if (addAmt === undefined) {
- addAmt = -1;
- }
- }
-
- if (startIdx >= 0 && addAmt >= 0 && get(this, 'hasEnumerableObservers')) {
- adding = [];
- lim = startIdx + addAmt;
-
- for (var idx = startIdx; idx < lim; idx++) {
- adding.push(this.objectAt(idx));
- }
- } else {
- adding = addAmt;
- }
-
- this.enumerableContentDidChange(removeAmt, adding);
- sendEvent(this, '@array:change', [this, startIdx, removeAmt, addAmt]);
-
- var length = get(this, 'length');
- var cachedFirst = cacheFor(this, 'firstObject');
- var cachedLast = cacheFor(this, 'lastObject');
-
- if (this.objectAt(0) !== cachedFirst) {
- propertyWillChange(this, 'firstObject');
- propertyDidChange(this, 'firstObject');
- }
-
- if (this.objectAt(length-1) !== cachedLast) {
- propertyWillChange(this, 'lastObject');
- propertyDidChange(this, 'lastObject');
- }
-
- return this;
- },
-
- // ..........................................................
- // ENUMERATED PROPERTIES
- //
-
- /**
- Returns a special object that can be used to observe individual properties
- on the array. Just get an equivalent property on this object and it will
- return an enumerable that maps automatically to the named key on the
- member objects.
-
- If you merely want to watch for any items being added or removed to the array,
- use the `[]` property instead of `@each`.
-
- @property @each
- */
- '@each': computed(function() {
- if (!this.__each) {
- // ES6TODO: GRRRRR
- var EachProxy = requireModule('ember-runtime/system/each_proxy')['EachProxy'];
-
- this.__each = new EachProxy(this);
- }
-
- return this.__each;
- })
- });
- });
-enifed("ember-runtime/mixins/comparable",
- ["ember-metal/mixin","exports"],
- function(__dependency1__, __exports__) {
- "use strict";
- var Mixin = __dependency1__.Mixin;
- var required = __dependency1__.required;
-
- /**
- @module ember
- @submodule ember-runtime
- */
-
- /**
- Implements some standard methods for comparing objects. Add this mixin to
- any class you create that can compare its instances.
-
- You should implement the `compare()` method.
-
- @class Comparable
- @namespace Ember
- @since Ember 0.9
- */
- __exports__["default"] = Mixin.create({
-
- /**
- Override to return the result of the comparison of the two parameters. The
- compare method should return:
-
- - `-1` if `a < b`
- - `0` if `a == b`
- - `1` if `a > b`
-
- Default implementation raises an exception.
-
- @method compare
- @param a {Object} the first object to compare
- @param b {Object} the second object to compare
- @return {Integer} the result of the comparison
- */
- compare: required(Function)
- });
- });
-enifed("ember-runtime/mixins/controller",
- ["ember-metal/mixin","ember-metal/computed","ember-runtime/mixins/action_handler","ember-runtime/mixins/controller_content_model_alias_deprecation","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
- "use strict";
- var Mixin = __dependency1__.Mixin;
- var computed = __dependency2__.computed;
- var ActionHandler = __dependency3__["default"];
- var ControllerContentModelAliasDeprecation = __dependency4__["default"];
-
- /**
- `Ember.ControllerMixin` provides a standard interface for all classes that
- compose Ember's controller layer: `Ember.Controller`,
- `Ember.ArrayController`, and `Ember.ObjectController`.
-
- @class ControllerMixin
- @namespace Ember
- @uses Ember.ActionHandler
- */
- __exports__["default"] = Mixin.create(ActionHandler, ControllerContentModelAliasDeprecation, {
- /* ducktype as a controller */
- isController: true,
-
- /**
- The object to which actions from the view should be sent.
-
- For example, when a Handlebars template uses the `{{action}}` helper,
- it will attempt to send the action to the view's controller's `target`.
-
- By default, the value of the target property is set to the router, and
- is injected when a controller is instantiated. This injection is defined
- in Ember.Application#buildContainer, and is applied as part of the
- applications initialization process. It can also be set after a controller
- has been instantiated, for instance when using the render helper in a
- template, or when a controller is used as an `itemController`. In most
- cases the `target` property will automatically be set to the logical
- consumer of actions for the controller.
-
- @property target
- @default null
- */
- target: null,
-
- container: null,
-
- parentController: null,
-
- store: null,
-
- /**
- The controller's current model. When retrieving or modifying a controller's
- model, this property should be used instead of the `content` property.
-
- @property model
- @public
- */
- model: null,
-
- /**
- @private
- */
- content: computed.alias('model')
-
- });
- });
-enifed("ember-runtime/mixins/controller_content_model_alias_deprecation",
- ["ember-metal/core","ember-metal/mixin","exports"],
- function(__dependency1__, __dependency2__, __exports__) {
- "use strict";
- var Ember = __dependency1__["default"];
- // Ember.deprecate
- var Mixin = __dependency2__.Mixin;
-
- /**
- The ControllerContentModelAliasDeprecation mixin is used to provide a useful
- deprecation warning when specifying `content` directly on a `Ember.Controller`
- (without also specifying `model`).
-
- Ember versions prior to 1.7 used `model` as an alias of `content`, but due to
- much confusion this alias was reversed (so `content` is now an alias of `model).
-
- This change reduces many caveats with model/content, and also sets a
- simple ground rule: Never set a controllers content, rather always set
- it's model and ember will do the right thing.
-
-
- `Ember.ControllerContentModelAliasDeprecation` is used internally by Ember in
- `Ember.Controller`.
-
- @class ControllerContentModelAliasDeprecation
- @namespace Ember
- @private
- @since 1.7.0
- */
- __exports__["default"] = Mixin.create({
- /**
- @private
-
- Moves `content` to `model` at extend time if a `model` is not also specified.
-
- Note that this currently modifies the mixin themselves, which is technically
- dubious but is practically of little consequence. This may change in the
- future.
-
- @method willMergeMixin
- @since 1.4.0
- */
- willMergeMixin: function(props) {
- // Calling super is only OK here since we KNOW that
- // there is another Mixin loaded first.
- this._super.apply(this, arguments);
-
- var modelSpecified = !!props.model;
-
- if (props.content && !modelSpecified) {
- props.model = props.content;
- delete props['content'];
-
- Ember.deprecate('Do not specify `content` on a Controller, use `model` instead.', false);
- }
- }
- });
- });
-enifed("ember-runtime/mixins/copyable",
- ["ember-metal/property_get","ember-metal/mixin","ember-runtime/mixins/freezable","ember-runtime/system/string","ember-metal/error","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) {
- "use strict";
- /**
- @module ember
- @submodule ember-runtime
- */
-
-
- var get = __dependency1__.get;
- var required = __dependency2__.required;
- var Freezable = __dependency3__.Freezable;
- var Mixin = __dependency2__.Mixin;
- var fmt = __dependency4__.fmt;
- var EmberError = __dependency5__["default"];
-
-
- /**
- Implements some standard methods for copying an object. Add this mixin to
- any object you create that can create a copy of itself. This mixin is
- added automatically to the built-in array.
-
- You should generally implement the `copy()` method to return a copy of the
- receiver.
-
- Note that `frozenCopy()` will only work if you also implement
- `Ember.Freezable`.
-
- @class Copyable
- @namespace Ember
- @since Ember 0.9
- */
- __exports__["default"] = Mixin.create({
- /**
- Override to return a copy of the receiver. Default implementation raises
- an exception.
-
- @method copy
- @param {Boolean} deep if `true`, a deep copy of the object should be made
- @return {Object} copy of receiver
- */
- copy: required(Function),
-
- /**
- If the object implements `Ember.Freezable`, then this will return a new
- copy if the object is not frozen and the receiver if the object is frozen.
-
- Raises an exception if you try to call this method on a object that does
- not support freezing.
-
- You should use this method whenever you want a copy of a freezable object
- since a freezable object can simply return itself without actually
- consuming more memory.
-
- @method frozenCopy
- @return {Object} copy of receiver or receiver
- */
- frozenCopy: function() {
- if (Freezable && Freezable.detect(this)) {
- return get(this, 'isFrozen') ? this : this.copy().freeze();
- } else {
- throw new EmberError(fmt("%@ does not support freezing", [this]));
- }
- }
- });
- });
-enifed("ember-runtime/mixins/deferred",
- ["ember-metal/core","ember-metal/property_get","ember-metal/mixin","ember-metal/computed","ember-runtime/ext/rsvp","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) {
- "use strict";
- var Ember = __dependency1__["default"];
- // Ember.FEATURES, Ember.Test
- var get = __dependency2__.get;
- var Mixin = __dependency3__.Mixin;
- var computed = __dependency4__.computed;
- var RSVP = __dependency5__["default"];
-
- /**
- @module ember
- @submodule ember-runtime
- */
-
-
- /**
- @class Deferred
- @namespace Ember
- */
- __exports__["default"] = Mixin.create({
- /**
- Add handlers to be called when the Deferred object is resolved or rejected.
-
- @method then
- @param {Function} resolve a callback function to be called when done
- @param {Function} reject a callback function to be called when failed
- */
- then: function(resolve, reject, label) {
- var deferred, promise, entity;
-
- entity = this;
- deferred = get(this, '_deferred');
- promise = deferred.promise;
-
- function fulfillmentHandler(fulfillment) {
- if (fulfillment === promise) {
- return resolve(entity);
- } else {
- return resolve(fulfillment);
- }
- }
-
- return promise.then(resolve && fulfillmentHandler, reject, label);
- },
-
- /**
- Resolve a Deferred object and call any `doneCallbacks` with the given args.
-
- @method resolve
- */
- resolve: function(value) {
- var deferred, promise;
-
- deferred = get(this, '_deferred');
- promise = deferred.promise;
-
- if (value === this) {
- deferred.resolve(promise);
- } else {
- deferred.resolve(value);
- }
- },
-
- /**
- Reject a Deferred object and call any `failCallbacks` with the given args.
-
- @method reject
- */
- reject: function(value) {
- get(this, '_deferred').reject(value);
- },
-
- _deferred: computed(function() {
- Ember.deprecate('Usage of Ember.DeferredMixin or Ember.Deferred is deprecated.', this._suppressDeferredDeprecation);
-
- return RSVP.defer('Ember: DeferredMixin - ' + this);
- })
- });
- });
-enifed("ember-runtime/mixins/enumerable",
- ["ember-metal/core","ember-metal/property_get","ember-metal/property_set","ember-metal/utils","ember-metal/mixin","ember-metal/enumerable_utils","ember-metal/computed","ember-metal/property_events","ember-metal/events","ember-runtime/compare","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __exports__) {
- "use strict";
- /**
- @module ember
- @submodule ember-runtime
- */
-
- // ..........................................................
- // HELPERS
- //
-
- var Ember = __dependency1__["default"];
- var get = __dependency2__.get;
- var set = __dependency3__.set;
- var apply = __dependency4__.apply;
- var Mixin = __dependency5__.Mixin;
- var required = __dependency5__.required;
- var aliasMethod = __dependency5__.aliasMethod;
- var indexOf = __dependency6__.indexOf;
- var computed = __dependency7__.computed;
- var propertyWillChange = __dependency8__.propertyWillChange;
- var propertyDidChange = __dependency8__.propertyDidChange;
- var addListener = __dependency9__.addListener;
- var removeListener = __dependency9__.removeListener;
- var sendEvent = __dependency9__.sendEvent;
- var hasListeners = __dependency9__.hasListeners;
- var compare = __dependency10__["default"];
-
- var a_slice = Array.prototype.slice;
-
- var contexts = [];
-
- function popCtx() {
- return contexts.length === 0 ? {} : contexts.pop();
- }
-
- function pushCtx(ctx) {
- contexts.push(ctx);
- return null;
- }
-
- function iter(key, value) {
- var valueProvided = arguments.length === 2;
-
- function i(item) {
- var cur = get(item, key);
- return valueProvided ? value === cur : !!cur;
- }
-
- return i;
- }
-
- /**
- This mixin defines the common interface implemented by enumerable objects
- in Ember. Most of these methods follow the standard Array iteration
- API defined up to JavaScript 1.8 (excluding language-specific features that
- cannot be emulated in older versions of JavaScript).
-
- This mixin is applied automatically to the Array class on page load, so you
- can use any of these methods on simple arrays. If Array already implements
- one of these methods, the mixin will not override them.
-
- ## Writing Your Own Enumerable
-
- To make your own custom class enumerable, you need two items:
-
- 1. You must have a length property. This property should change whenever
- the number of items in your enumerable object changes. If you use this
- with an `Ember.Object` subclass, you should be sure to change the length
- property using `set().`
-
- 2. You must implement `nextObject().` See documentation.
-
- Once you have these two methods implemented, apply the `Ember.Enumerable` mixin
- to your class and you will be able to enumerate the contents of your object
- like any other collection.
-
- ## Using Ember Enumeration with Other Libraries
-
- Many other libraries provide some kind of iterator or enumeration like
- facility. This is often where the most common API conflicts occur.
- Ember's API is designed to be as friendly as possible with other
- libraries by implementing only methods that mostly correspond to the
- JavaScript 1.8 API.
-
- @class Enumerable
- @namespace Ember
- @since Ember 0.9
- */
- __exports__["default"] = Mixin.create({
-
- /**
- Implement this method to make your class enumerable.
-
- This method will be call repeatedly during enumeration. The index value
- will always begin with 0 and increment monotonically. You don't have to
- rely on the index value to determine what object to return, but you should
- always check the value and start from the beginning when you see the
- requested index is 0.
-
- The `previousObject` is the object that was returned from the last call
- to `nextObject` for the current iteration. This is a useful way to
- manage iteration if you are tracing a linked list, for example.
-
- Finally the context parameter will always contain a hash you can use as
- a "scratchpad" to maintain any other state you need in order to iterate
- properly. The context object is reused and is not reset between
- iterations so make sure you setup the context with a fresh state whenever
- the index parameter is 0.
-
- Generally iterators will continue to call `nextObject` until the index
- reaches the your current length-1. If you run out of data before this
- time for some reason, you should simply return undefined.
-
- The default implementation of this method simply looks up the index.
- This works great on any Array-like objects.
-
- @method nextObject
- @param {Number} index the current index of the iteration
- @param {Object} previousObject the value returned by the last call to
- `nextObject`.
- @param {Object} context a context object you can use to maintain state.
- @return {Object} the next object in the iteration or undefined
- */
- nextObject: required(Function),
-
- /**
- Helper method returns the first object from a collection. This is usually
- used by bindings and other parts of the framework to extract a single
- object if the enumerable contains only one item.
-
- If you override this method, you should implement it so that it will
- always return the same value each time it is called. If your enumerable
- contains only one object, this method should always return that object.
- If your enumerable is empty, this method should return `undefined`.
-
- ```javascript
- var arr = ['a', 'b', 'c'];
- arr.get('firstObject'); // 'a'
-
- var arr = [];
- arr.get('firstObject'); // undefined
- ```
-
- @property firstObject
- @return {Object} the object or undefined
- */
- firstObject: computed('[]', function() {
- if (get(this, 'length') === 0) {
- return undefined;
- }
-
- // handle generic enumerables
- var context = popCtx();
- var ret = this.nextObject(0, null, context);
-
- pushCtx(context);
-
- return ret;
- }),
-
- /**
- Helper method returns the last object from a collection. If your enumerable
- contains only one object, this method should always return that object.
- If your enumerable is empty, this method should return `undefined`.
-
- ```javascript
- var arr = ['a', 'b', 'c'];
- arr.get('lastObject'); // 'c'
-
- var arr = [];
- arr.get('lastObject'); // undefined
- ```
-
- @property lastObject
- @return {Object} the last object or undefined
- */
- lastObject: computed('[]', function() {
- var len = get(this, 'length');
-
- if (len === 0) {
- return undefined;
- }
-
- var context = popCtx();
- var idx = 0;
- var last = null;
- var cur;
-
- do {
- last = cur;
- cur = this.nextObject(idx++, last, context);
- } while (cur !== undefined);
-
- pushCtx(context);
-
- return last;
- }),
-
- /**
- Returns `true` if the passed object can be found in the receiver. The
- default version will iterate through the enumerable until the object
- is found. You may want to override this with a more efficient version.
-
- ```javascript
- var arr = ['a', 'b', 'c'];
-
- arr.contains('a'); // true
- arr.contains('z'); // false
- ```
-
- @method contains
- @param {Object} obj The object to search for.
- @return {Boolean} `true` if object is found in enumerable.
- */
- contains: function(obj) {
- var found = this.find(function(item) {
- return item === obj;
- });
-
- return found !== undefined;
- },
-
- /**
- Iterates through the enumerable, calling the passed function on each
- item. This method corresponds to the `forEach()` method defined in
- JavaScript 1.6.
-
- The callback method you provide should have the following signature (all
- parameters are optional):
-
- ```javascript
- function(item, index, enumerable);
- ```
-
- - `item` is the current item in the iteration.
- - `index` is the current index in the iteration.
- - `enumerable` is the enumerable object itself.
-
- Note that in addition to a callback, you can also pass an optional target
- object that will be set as `this` on the context. This is a good way
- to give your iterator function access to the current object.
-
- @method forEach
- @param {Function} callback The callback to execute
- @param {Object} [target] The target object to use
- @return {Object} receiver
- */
- forEach: function(callback, target) {
- if (typeof callback !== 'function') {
- throw new TypeError();
- }
-
- var context = popCtx();
- var len = get(this, 'length');
- var last = null;
-
- if (target === undefined) {
- target = null;
- }
-
- for(var idx = 0; idx < len; idx++) {
- var next = this.nextObject(idx, last, context) ;
- callback.call(target, next, idx, this);
- last = next ;
- }
-
- last = null ;
- context = pushCtx(context);
-
- return this ;
- },
-
- /**
- Alias for `mapBy`
-
- @method getEach
- @param {String} key name of the property
- @return {Array} The mapped array.
- */
- getEach: function(key) {
- return this.mapBy(key);
- },
-
- /**
- Sets the value on the named property for each member. This is more
- efficient than using other methods defined on this helper. If the object
- implements Ember.Observable, the value will be changed to `set(),` otherwise
- it will be set directly. `null` objects are skipped.
-
- @method setEach
- @param {String} key The key to set
- @param {Object} value The object to set
- @return {Object} receiver
- */
- setEach: function(key, value) {
- return this.forEach(function(item) {
- set(item, key, value);
- });
- },
-
- /**
- Maps all of the items in the enumeration to another value, returning
- a new array. This method corresponds to `map()` defined in JavaScript 1.6.
-
- The callback method you provide should have the following signature (all
- parameters are optional):
-
- ```javascript
- function(item, index, enumerable);
- ```
-
- - `item` is the current item in the iteration.
- - `index` is the current index in the iteration.
- - `enumerable` is the enumerable object itself.
-
- It should return the mapped value.
-
- Note that in addition to a callback, you can also pass an optional target
- object that will be set as `this` on the context. This is a good way
- to give your iterator function access to the current object.
-
- @method map
- @param {Function} callback The callback to execute
- @param {Object} [target] The target object to use
- @return {Array} The mapped array.
- */
- map: function(callback, target) {
- var ret = Ember.A();
-
- this.forEach(function(x, idx, i) {
- ret[idx] = callback.call(target, x, idx,i);
- });
-
- return ret ;
- },
-
- /**
- Similar to map, this specialized function returns the value of the named
- property on all items in the enumeration.
-
- @method mapBy
- @param {String} key name of the property
- @return {Array} The mapped array.
- */
- mapBy: function(key) {
- return this.map(function(next) {
- return get(next, key);
- });
- },
-
- /**
- Similar to map, this specialized function returns the value of the named
- property on all items in the enumeration.
-
- @method mapProperty
- @param {String} key name of the property
- @return {Array} The mapped array.
- @deprecated Use `mapBy` instead
- */
-
- mapProperty: aliasMethod('mapBy'),
-
- /**
- Returns an array with all of the items in the enumeration that the passed
- function returns true for. This method corresponds to `filter()` defined in
- JavaScript 1.6.
-
- The callback method you provide should have the following signature (all
- parameters are optional):
-
- ```javascript
- function(item, index, enumerable);
- ```
-
- - `item` is the current item in the iteration.
- - `index` is the current index in the iteration.
- - `enumerable` is the enumerable object itself.
-
- It should return `true` to include the item in the results, `false`
- otherwise.
-
- Note that in addition to a callback, you can also pass an optional target
- object that will be set as `this` on the context. This is a good way
- to give your iterator function access to the current object.
-
- @method filter
- @param {Function} callback The callback to execute
- @param {Object} [target] The target object to use
- @return {Array} A filtered array.
- */
- filter: function(callback, target) {
- var ret = Ember.A();
-
- this.forEach(function(x, idx, i) {
- if (callback.call(target, x, idx, i)) {
- ret.push(x);
- }
- });
-
- return ret ;
- },
-
- /**
- Returns an array with all of the items in the enumeration where the passed
- function returns false for. This method is the inverse of filter().
-
- The callback method you provide should have the following signature (all
- parameters are optional):
-
- ```javascript
- function(item, index, enumerable);
- ```
-
- - *item* is the current item in the iteration.
- - *index* is the current index in the iteration
- - *enumerable* is the enumerable object itself.
-
- It should return the a falsey value to include the item in the results.
-
- Note that in addition to a callback, you can also pass an optional target
- object that will be set as "this" on the context. This is a good way
- to give your iterator function access to the current object.
-
- @method reject
- @param {Function} callback The callback to execute
- @param {Object} [target] The target object to use
- @return {Array} A rejected array.
- */
- reject: function(callback, target) {
- return this.filter(function() {
- return !(apply(target, callback, arguments));
- });
- },
-
- /**
- Returns an array with just the items with the matched property. You
- can pass an optional second argument with the target value. Otherwise
- this will match any property that evaluates to `true`.
-
- @method filterBy
- @param {String} key the property to test
- @param {*} [value] optional value to test against.
- @return {Array} filtered array
- */
- filterBy: function(key, value) {
- return this.filter(apply(this, iter, arguments));
- },
-
- /**
- Returns an array with just the items with the matched property. You
- can pass an optional second argument with the target value. Otherwise
- this will match any property that evaluates to `true`.
-
- @method filterProperty
- @param {String} key the property to test
- @param {String} [value] optional value to test against.
- @return {Array} filtered array
- @deprecated Use `filterBy` instead
- */
- filterProperty: aliasMethod('filterBy'),
-
- /**
- Returns an array with the items that do not have truthy values for
- key. You can pass an optional second argument with the target value. Otherwise
- this will match any property that evaluates to false.
-
- @method rejectBy
- @param {String} key the property to test
- @param {String} [value] optional value to test against.
- @return {Array} rejected array
- */
- rejectBy: function(key, value) {
- var exactValue = function(item) {
- return get(item, key) === value;
- };
-
- var hasValue = function(item) {
- return !!get(item, key);
- };
-
- var use = (arguments.length === 2 ? exactValue : hasValue);
-
- return this.reject(use);
- },
-
- /**
- Returns an array with the items that do not have truthy values for
- key. You can pass an optional second argument with the target value. Otherwise
- this will match any property that evaluates to false.
-
- @method rejectProperty
- @param {String} key the property to test
- @param {String} [value] optional value to test against.
- @return {Array} rejected array
- @deprecated Use `rejectBy` instead
- */
- rejectProperty: aliasMethod('rejectBy'),
-
- /**
- Returns the first item in the array for which the callback returns true.
- This method works similar to the `filter()` method defined in JavaScript 1.6
- except that it will stop working on the array once a match is found.
-
- The callback method you provide should have the following signature (all
- parameters are optional):
-
- ```javascript
- function(item, index, enumerable);
- ```
-
- - `item` is the current item in the iteration.
- - `index` is the current index in the iteration.
- - `enumerable` is the enumerable object itself.
-
- It should return the `true` to include the item in the results, `false`
- otherwise.
-
- Note that in addition to a callback, you can also pass an optional target
- object that will be set as `this` on the context. This is a good way
- to give your iterator function access to the current object.
-
- @method find
- @param {Function} callback The callback to execute
- @param {Object} [target] The target object to use
- @return {Object} Found item or `undefined`.
- */
- find: function(callback, target) {
- var len = get(this, 'length');
-
- if (target === undefined) {
- target = null;
- }
-
- var context = popCtx();
- var found = false;
- var last = null;
- var next, ret;
-
- for(var idx = 0; idx < len && !found; idx++) {
- next = this.nextObject(idx, last, context);
-
- if (found = callback.call(target, next, idx, this)) {
- ret = next;
- }
-
- last = next;
- }
-
- next = last = null;
- context = pushCtx(context);
-
- return ret;
- },
-
- /**
- Returns the first item with a property matching the passed value. You
- can pass an optional second argument with the target value. Otherwise
- this will match any property that evaluates to `true`.
-
- This method works much like the more generic `find()` method.
-
- @method findBy
- @param {String} key the property to test
- @param {String} [value] optional value to test against.
- @return {Object} found item or `undefined`
- */
- findBy: function(key, value) {
- return this.find(apply(this, iter, arguments));
- },
-
- /**
- Returns the first item with a property matching the passed value. You
- can pass an optional second argument with the target value. Otherwise
- this will match any property that evaluates to `true`.
-
- This method works much like the more generic `find()` method.
-
- @method findProperty
- @param {String} key the property to test
- @param {String} [value] optional value to test against.
- @return {Object} found item or `undefined`
- @deprecated Use `findBy` instead
- */
- findProperty: aliasMethod('findBy'),
-
- /**
- Returns `true` if the passed function returns true for every item in the
- enumeration. This corresponds with the `every()` method in JavaScript 1.6.
-
- The callback method you provide should have the following signature (all
- parameters are optional):
-
- ```javascript
- function(item, index, enumerable);
- ```
-
- - `item` is the current item in the iteration.
- - `index` is the current index in the iteration.
- - `enumerable` is the enumerable object itself.
-
- It should return the `true` or `false`.
-
- Note that in addition to a callback, you can also pass an optional target
- object that will be set as `this` on the context. This is a good way
- to give your iterator function access to the current object.
-
- Example Usage:
-
- ```javascript
- if (people.every(isEngineer)) {
- Paychecks.addBigBonus();
- }
- ```
-
- @method every
- @param {Function} callback The callback to execute
- @param {Object} [target] The target object to use
- @return {Boolean}
- */
- every: function(callback, target) {
- return !this.find(function(x, idx, i) {
- return !callback.call(target, x, idx, i);
- });
- },
-
- /**
- @method everyBy
- @param {String} key the property to test
- @param {String} [value] optional value to test against.
- @deprecated Use `isEvery` instead
- @return {Boolean}
- */
- everyBy: aliasMethod('isEvery'),
-
- /**
- @method everyProperty
- @param {String} key the property to test
- @param {String} [value] optional value to test against.
- @deprecated Use `isEvery` instead
- @return {Boolean}
- */
- everyProperty: aliasMethod('isEvery'),
-
- /**
- Returns `true` if the passed property resolves to `true` for all items in
- the enumerable. This method is often simpler/faster than using a callback.
-
- @method isEvery
- @param {String} key the property to test
- @param {String} [value] optional value to test against.
- @return {Boolean}
- @since 1.3.0
- */
- isEvery: function(key, value) {
- return this.every(apply(this, iter, arguments));
- },
-
- /**
- Returns `true` if the passed function returns true for any item in the
- enumeration. This corresponds with the `some()` method in JavaScript 1.6.
-
- The callback method you provide should have the following signature (all
- parameters are optional):
-
- ```javascript
- function(item, index, enumerable);
- ```
-
- - `item` is the current item in the iteration.
- - `index` is the current index in the iteration.
- - `enumerable` is the enumerable object itself.
-
- It should return the `true` to include the item in the results, `false`
- otherwise.
-
- Note that in addition to a callback, you can also pass an optional target
- object that will be set as `this` on the context. This is a good way
- to give your iterator function access to the current object.
-
- Usage Example:
-
- ```javascript
- if (people.any(isManager)) {
- Paychecks.addBiggerBonus();
- }
- ```
-
- @method any
- @param {Function} callback The callback to execute
- @param {Object} [target] The target object to use
- @return {Boolean} `true` if the passed function returns `true` for any item
- */
- any: function(callback, target) {
- var len = get(this, 'length');
- var context = popCtx();
- var found = false;
- var last = null;
- var next, idx;
-
- if (target === undefined) {
- target = null;
- }
-
- for (idx = 0; idx < len && !found; idx++) {
- next = this.nextObject(idx, last, context);
- found = callback.call(target, next, idx, this);
- last = next;
- }
-
- next = last = null;
- context = pushCtx(context);
- return found;
- },
-
- /**
- Returns `true` if the passed function returns true for any item in the
- enumeration. This corresponds with the `some()` method in JavaScript 1.6.
-
- The callback method you provide should have the following signature (all
- parameters are optional):
-
- ```javascript
- function(item, index, enumerable);
- ```
-
- - `item` is the current item in the iteration.
- - `index` is the current index in the iteration.
- - `enumerable` is the enumerable object itself.
-
- It should return the `true` to include the item in the results, `false`
- otherwise.
-
- Note that in addition to a callback, you can also pass an optional target
- object that will be set as `this` on the context. This is a good way
- to give your iterator function access to the current object.
-
- Usage Example:
-
- ```javascript
- if (people.some(isManager)) {
- Paychecks.addBiggerBonus();
- }
- ```
-
- @method some
- @param {Function} callback The callback to execute
- @param {Object} [target] The target object to use
- @return {Boolean} `true` if the passed function returns `true` for any item
- @deprecated Use `any` instead
- */
- some: aliasMethod('any'),
-
- /**
- Returns `true` if the passed property resolves to `true` for any item in
- the enumerable. This method is often simpler/faster than using a callback.
-
- @method isAny
- @param {String} key the property to test
- @param {String} [value] optional value to test against.
- @return {Boolean} `true` if the passed function returns `true` for any item
- @since 1.3.0
- */
- isAny: function(key, value) {
- return this.any(apply(this, iter, arguments));
- },
-
- /**
- @method anyBy
- @param {String} key the property to test
- @param {String} [value] optional value to test against.
- @return {Boolean} `true` if the passed function returns `true` for any item
- @deprecated Use `isAny` instead
- */
- anyBy: aliasMethod('isAny'),
-
- /**
- @method someProperty
- @param {String} key the property to test
- @param {String} [value] optional value to test against.
- @return {Boolean} `true` if the passed function returns `true` for any item
- @deprecated Use `isAny` instead
- */
- someProperty: aliasMethod('isAny'),
-
- /**
- This will combine the values of the enumerator into a single value. It
- is a useful way to collect a summary value from an enumeration. This
- corresponds to the `reduce()` method defined in JavaScript 1.8.
-
- The callback method you provide should have the following signature (all
- parameters are optional):
-
- ```javascript
- function(previousValue, item, index, enumerable);
- ```
-
- - `previousValue` is the value returned by the last call to the iterator.
- - `item` is the current item in the iteration.
- - `index` is the current index in the iteration.
- - `enumerable` is the enumerable object itself.
-
- Return the new cumulative value.
-
- In addition to the callback you can also pass an `initialValue`. An error
- will be raised if you do not pass an initial value and the enumerator is
- empty.
-
- Note that unlike the other methods, this method does not allow you to
- pass a target object to set as this for the callback. It's part of the
- spec. Sorry.
-
- @method reduce
- @param {Function} callback The callback to execute
- @param {Object} initialValue Initial value for the reduce
- @param {String} reducerProperty internal use only.
- @return {Object} The reduced value.
- */
- reduce: function(callback, initialValue, reducerProperty) {
- if (typeof callback !== 'function') {
- throw new TypeError();
- }
-
- var ret = initialValue;
-
- this.forEach(function(item, i) {
- ret = callback(ret, item, i, this, reducerProperty);
- }, this);
-
- return ret;
- },
-
- /**
- Invokes the named method on every object in the receiver that
- implements it. This method corresponds to the implementation in
- Prototype 1.6.
-
- @method invoke
- @param {String} methodName the name of the method
- @param {Object...} args optional arguments to pass as well.
- @return {Array} return values from calling invoke.
- */
- invoke: function(methodName) {
- var ret = Ember.A();
- var args;
-
- if (arguments.length > 1) {
- args = a_slice.call(arguments, 1);
- }
-
- this.forEach(function(x, idx) {
- var method = x && x[methodName];
-
- if ('function' === typeof method) {
- ret[idx] = args ? apply(x, method, args) : x[methodName]();
- }
- }, this);
-
- return ret;
- },
-
- /**
- Simply converts the enumerable into a genuine array. The order is not
- guaranteed. Corresponds to the method implemented by Prototype.
-
- @method toArray
- @return {Array} the enumerable as an array.
- */
- toArray: function() {
- var ret = Ember.A();
-
- this.forEach(function(o, idx) {
- ret[idx] = o;
- });
-
- return ret;
- },
-
- /**
- Returns a copy of the array with all `null` and `undefined` elements removed.
-
- ```javascript
- var arr = ['a', null, 'c', undefined];
- arr.compact(); // ['a', 'c']
- ```
-
- @method compact
- @return {Array} the array without null and undefined elements.
- */
- compact: function() {
- return this.filter(function(value) {
- return value != null;
- });
- },
-
- /**
- Returns a new enumerable that excludes the passed value. The default
- implementation returns an array regardless of the receiver type unless
- the receiver does not contain the value.
-
- ```javascript
- var arr = ['a', 'b', 'a', 'c'];
- arr.without('a'); // ['b', 'c']
- ```
-
- @method without
- @param {Object} value
- @return {Ember.Enumerable}
- */
- without: function(value) {
- if (!this.contains(value)) {
- return this; // nothing to do
- }
-
- var ret = Ember.A();
-
- this.forEach(function(k) {
- if (k !== value) {
- ret[ret.length] = k;
- }
- });
-
- return ret;
- },
-
- /**
- Returns a new enumerable that contains only unique values. The default
- implementation returns an array regardless of the receiver type.
-
- ```javascript
- var arr = ['a', 'a', 'b', 'b'];
- arr.uniq(); // ['a', 'b']
- ```
-
- This only works on primitive data types, e.g. Strings, Numbers, etc.
-
- @method uniq
- @return {Ember.Enumerable}
- */
- uniq: function() {
- var ret = Ember.A();
-
- this.forEach(function(k) {
- if (indexOf(ret, k) < 0) {
- ret.push(k);
- }
- });
-
- return ret;
- },
-
- /**
- This property will trigger anytime the enumerable's content changes.
- You can observe this property to be notified of changes to the enumerables
- content.
-
- For plain enumerables, this property is read only. `Array` overrides
- this method.
-
- @property []
- @type Array
- @return this
- */
- '[]': computed(function(key, value) {
- return this;
- }),
-
- // ..........................................................
- // ENUMERABLE OBSERVERS
- //
-
- /**
- Registers an enumerable observer. Must implement `Ember.EnumerableObserver`
- mixin.
-
- @method addEnumerableObserver
- @param {Object} target
- @param {Hash} [opts]
- @return this
- */
- addEnumerableObserver: function(target, opts) {
- var willChange = (opts && opts.willChange) || 'enumerableWillChange';
- var didChange = (opts && opts.didChange) || 'enumerableDidChange';
- var hasObservers = get(this, 'hasEnumerableObservers');
-
- if (!hasObservers) {
- propertyWillChange(this, 'hasEnumerableObservers');
- }
-
- addListener(this, '@enumerable:before', target, willChange);
- addListener(this, '@enumerable:change', target, didChange);
-
- if (!hasObservers) {
- propertyDidChange(this, 'hasEnumerableObservers');
- }
-
- return this;
- },
-
- /**
- Removes a registered enumerable observer.
-
- @method removeEnumerableObserver
- @param {Object} target
- @param {Hash} [opts]
- @return this
- */
- removeEnumerableObserver: function(target, opts) {
- var willChange = (opts && opts.willChange) || 'enumerableWillChange';
- var didChange = (opts && opts.didChange) || 'enumerableDidChange';
- var hasObservers = get(this, 'hasEnumerableObservers');
-
- if (hasObservers) {
- propertyWillChange(this, 'hasEnumerableObservers');
- }
-
- removeListener(this, '@enumerable:before', target, willChange);
- removeListener(this, '@enumerable:change', target, didChange);
-
- if (hasObservers) {
- propertyDidChange(this, 'hasEnumerableObservers');
- }
-
- return this;
- },
-
- /**
- Becomes true whenever the array currently has observers watching changes
- on the array.
-
- @property hasEnumerableObservers
- @type Boolean
- */
- hasEnumerableObservers: computed(function() {
- return hasListeners(this, '@enumerable:change') || hasListeners(this, '@enumerable:before');
- }),
-
-
- /**
- Invoke this method just before the contents of your enumerable will
- change. You can either omit the parameters completely or pass the objects
- to be removed or added if available or just a count.
-
- @method enumerableContentWillChange
- @param {Ember.Enumerable|Number} removing An enumerable of the objects to
- be removed or the number of items to be removed.
- @param {Ember.Enumerable|Number} adding An enumerable of the objects to be
- added or the number of items to be added.
- @chainable
- */
- enumerableContentWillChange: function(removing, adding) {
- var removeCnt, addCnt, hasDelta;
-
- if ('number' === typeof removing) {
- removeCnt = removing;
- } else if (removing) {
- removeCnt = get(removing, 'length');
- } else {
- removeCnt = removing = -1;
- }
-
- if ('number' === typeof adding) {
- addCnt = adding;
- } else if (adding) {
- addCnt = get(adding,'length');
- } else {
- addCnt = adding = -1;
- }
-
- hasDelta = addCnt < 0 || removeCnt < 0 || addCnt - removeCnt !== 0;
-
- if (removing === -1) {
- removing = null;
- }
-
- if (adding === -1) {
- adding = null;
- }
-
- propertyWillChange(this, '[]');
-
- if (hasDelta) {
- propertyWillChange(this, 'length');
- }
-
- sendEvent(this, '@enumerable:before', [this, removing, adding]);
-
- return this;
- },
-
- /**
- Invoke this method when the contents of your enumerable has changed.
- This will notify any observers watching for content changes. If you are
- implementing an ordered enumerable (such as an array), also pass the
- start and end values where the content changed so that it can be used to
- notify range observers.
-
- @method enumerableContentDidChange
- @param {Ember.Enumerable|Number} removing An enumerable of the objects to
- be removed or the number of items to be removed.
- @param {Ember.Enumerable|Number} adding An enumerable of the objects to
- be added or the number of items to be added.
- @chainable
- */
- enumerableContentDidChange: function(removing, adding) {
- var removeCnt, addCnt, hasDelta;
-
- if ('number' === typeof removing) {
- removeCnt = removing;
- } else if (removing) {
- removeCnt = get(removing, 'length');
- } else {
- removeCnt = removing = -1;
- }
-
- if ('number' === typeof adding) {
- addCnt = adding;
- } else if (adding) {
- addCnt = get(adding, 'length');
- } else {
- addCnt = adding = -1;
- }
-
- hasDelta = addCnt < 0 || removeCnt < 0 || addCnt - removeCnt !== 0;
-
- if (removing === -1) {
- removing = null;
- }
-
- if (adding === -1) {
- adding = null;
- }
-
- sendEvent(this, '@enumerable:change', [this, removing, adding]);
-
- if (hasDelta) {
- propertyDidChange(this, 'length');
- }
-
- propertyDidChange(this, '[]');
-
- return this ;
- },
-
- /**
- Converts the enumerable into an array and sorts by the keys
- specified in the argument.
-
- You may provide multiple arguments to sort by multiple properties.
-
- @method sortBy
- @param {String} property name(s) to sort on
- @return {Array} The sorted array.
- @since 1.2.0
- */
- sortBy: function() {
- var sortKeys = arguments;
-
- return this.toArray().sort(function(a, b){
- for(var i = 0; i < sortKeys.length; i++) {
- var key = sortKeys[i];
- var propA = get(a, key);
- var propB = get(b, key);
- // return 1 or -1 else continue to the next sortKey
- var compareValue = compare(propA, propB);
-
- if (compareValue) {
- return compareValue;
- }
- }
- return 0;
- });
- }
- });
- });
-enifed("ember-runtime/mixins/evented",
- ["ember-metal/mixin","ember-metal/events","exports"],
- function(__dependency1__, __dependency2__, __exports__) {
- "use strict";
- var Mixin = __dependency1__.Mixin;
- var addListener = __dependency2__.addListener;
- var removeListener = __dependency2__.removeListener;
- var hasListeners = __dependency2__.hasListeners;
- var sendEvent = __dependency2__.sendEvent;
-
- /**
- @module ember
- @submodule ember-runtime
- */
-
- /**
- This mixin allows for Ember objects to subscribe to and emit events.
-
- ```javascript
- App.Person = Ember.Object.extend(Ember.Evented, {
- greet: function() {
- // ...
- this.trigger('greet');
- }
- });
-
- var person = App.Person.create();
-
- person.on('greet', function() {
- console.log('Our person has greeted');
- });
-
- person.greet();
-
- // outputs: 'Our person has greeted'
- ```
-
- You can also chain multiple event subscriptions:
-
- ```javascript
- person.on('greet', function() {
- console.log('Our person has greeted');
- }).one('greet', function() {
- console.log('Offer one-time special');
- }).off('event', this, forgetThis);
- ```
-
- @class Evented
- @namespace Ember
- */
- __exports__["default"] = Mixin.create({
-
- /**
- Subscribes to a named event with given function.
-
- ```javascript
- person.on('didLoad', function() {
- // fired once the person has loaded
- });
- ```
-
- An optional target can be passed in as the 2nd argument that will
- be set as the "this" for the callback. This is a good way to give your
- function access to the object triggering the event. When the target
- parameter is used the callback becomes the third argument.
-
- @method on
- @param {String} name The name of the event
- @param {Object} [target] The "this" binding for the callback
- @param {Function} method The callback to execute
- @return this
- */
- on: function(name, target, method) {
- addListener(this, name, target, method);
- return this;
- },
-
- /**
- Subscribes a function to a named event and then cancels the subscription
- after the first time the event is triggered. It is good to use ``one`` when
- you only care about the first time an event has taken place.
-
- This function takes an optional 2nd argument that will become the "this"
- value for the callback. If this argument is passed then the 3rd argument
- becomes the function.
-
- @method one
- @param {String} name The name of the event
- @param {Object} [target] The "this" binding for the callback
- @param {Function} method The callback to execute
- @return this
- */
- one: function(name, target, method) {
- if (!method) {
- method = target;
- target = null;
- }
-
- addListener(this, name, target, method, true);
- return this;
- },
-
- /**
- Triggers a named event for the object. Any additional arguments
- will be passed as parameters to the functions that are subscribed to the
- event.
-
- ```javascript
- person.on('didEat', function(food) {
- console.log('person ate some ' + food);
- });
-
- person.trigger('didEat', 'broccoli');
-
- // outputs: person ate some broccoli
- ```
- @method trigger
- @param {String} name The name of the event
- @param {Object...} args Optional arguments to pass on
- */
- trigger: function(name) {
- var length = arguments.length;
- var args = new Array(length - 1);
-
- for (var i = 1; i < length; i++) {
- args[i - 1] = arguments[i];
- }
-
- sendEvent(this, name, args);
- },
-
- /**
- Cancels subscription for given name, target, and method.
-
- @method off
- @param {String} name The name of the event
- @param {Object} target The target of the subscription
- @param {Function} method The function of the subscription
- @return this
- */
- off: function(name, target, method) {
- removeListener(this, name, target, method);
- return this;
- },
-
- /**
- Checks to see if object has any subscriptions for named event.
-
- @method has
- @param {String} name The name of the event
- @return {Boolean} does the object have a subscription for event
- */
- has: function(name) {
- return hasListeners(this, name);
- }
- });
- });
-enifed("ember-runtime/mixins/freezable",
- ["ember-metal/mixin","ember-metal/property_get","ember-metal/property_set","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
- "use strict";
- /**
- @module ember
- @submodule ember-runtime
- */
-
- var Mixin = __dependency1__.Mixin;
- var get = __dependency2__.get;
- var set = __dependency3__.set;
-
- /**
- The `Ember.Freezable` mixin implements some basic methods for marking an
- object as frozen. Once an object is frozen it should be read only. No changes
- may be made the internal state of the object.
-
- ## Enforcement
-
- To fully support freezing in your subclass, you must include this mixin and
- override any method that might alter any property on the object to instead
- raise an exception. You can check the state of an object by checking the
- `isFrozen` property.
-
- Although future versions of JavaScript may support language-level freezing
- object objects, that is not the case today. Even if an object is freezable,
- it is still technically possible to modify the object, even though it could
- break other parts of your application that do not expect a frozen object to
- change. It is, therefore, very important that you always respect the
- `isFrozen` property on all freezable objects.
-
- ## Example Usage
-
- The example below shows a simple object that implement the `Ember.Freezable`
- protocol.
-
- ```javascript
- Contact = Ember.Object.extend(Ember.Freezable, {
- firstName: null,
- lastName: null,
-
- // swaps the names
- swapNames: function() {
- if (this.get('isFrozen')) throw Ember.FROZEN_ERROR;
- var tmp = this.get('firstName');
- this.set('firstName', this.get('lastName'));
- this.set('lastName', tmp);
- return this;
- }
-
- });
-
- c = Contact.create({ firstName: "John", lastName: "Doe" });
- c.swapNames(); // returns c
- c.freeze();
- c.swapNames(); // EXCEPTION
- ```
-
- ## Copying
-
- Usually the `Ember.Freezable` protocol is implemented in cooperation with the
- `Ember.Copyable` protocol, which defines a `frozenCopy()` method that will
- return a frozen object, if the object implements this method as well.
-
- @class Freezable
- @namespace Ember
- @since Ember 0.9
- */
- var Freezable = Mixin.create({
-
- /**
- Set to `true` when the object is frozen. Use this property to detect
- whether your object is frozen or not.
-
- @property isFrozen
- @type Boolean
- */
- isFrozen: false,
-
- /**
- Freezes the object. Once this method has been called the object should
- no longer allow any properties to be edited.
-
- @method freeze
- @return {Object} receiver
- */
- freeze: function() {
- if (get(this, 'isFrozen')) return this;
- set(this, 'isFrozen', true);
- return this;
- }
-
- });
- __exports__.Freezable = Freezable;
- var FROZEN_ERROR = "Frozen object cannot be modified.";
- __exports__.FROZEN_ERROR = FROZEN_ERROR;
- });
-enifed("ember-runtime/mixins/mutable_array",
- ["ember-metal/property_get","ember-metal/utils","ember-metal/error","ember-metal/mixin","ember-runtime/mixins/array","ember-runtime/mixins/mutable_enumerable","ember-runtime/mixins/enumerable","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __exports__) {
- "use strict";
- /**
- @module ember
- @submodule ember-runtime
- */
-
-
- // require('ember-runtime/mixins/array');
- // require('ember-runtime/mixins/mutable_enumerable');
-
- // ..........................................................
- // CONSTANTS
- //
-
- var OUT_OF_RANGE_EXCEPTION = "Index out of range";
- var EMPTY = [];
-
- // ..........................................................
- // HELPERS
- //
-
- var get = __dependency1__.get;
- var isArray = __dependency2__.isArray;
- var EmberError = __dependency3__["default"];
- var Mixin = __dependency4__.Mixin;
- var required = __dependency4__.required;
- var EmberArray = __dependency5__["default"];
- var MutableEnumerable = __dependency6__["default"];
- var Enumerable = __dependency7__["default"];
- /**
- This mixin defines the API for modifying array-like objects. These methods
- can be applied only to a collection that keeps its items in an ordered set.
- It builds upon the Array mixin and adds methods to modify the array.
- Concrete implementations of this class include ArrayProxy and ArrayController.
-
- It is important to use the methods in this class to modify arrays so that
- changes are observable. This allows the binding system in Ember to function
- correctly.
-
-
- Note that an Array can change even if it does not implement this mixin.
- For example, one might implement a SparseArray that cannot be directly
- modified, but if its underlying enumerable changes, it will change also.
-
- @class MutableArray
- @namespace Ember
- @uses Ember.Array
- @uses Ember.MutableEnumerable
- */
- __exports__["default"] = Mixin.create(EmberArray, MutableEnumerable, {
-
- /**
- __Required.__ You must implement this method to apply this mixin.
-
- This is one of the primitives you must implement to support `Ember.Array`.
- You should replace amt objects started at idx with the objects in the
- passed array. You should also call `this.enumerableContentDidChange()`
-
- @method replace
- @param {Number} idx Starting index in the array to replace. If
- idx >= length, then append to the end of the array.
- @param {Number} amt Number of elements that should be removed from
- the array, starting at *idx*.
- @param {Array} objects An array of zero or more objects that should be
- inserted into the array at *idx*
- */
- replace: required(),
-
- /**
- Remove all elements from the array. This is useful if you
- want to reuse an existing array without having to recreate it.
-
- ```javascript
- var colors = ["red", "green", "blue"];
- color.length(); // 3
- colors.clear(); // []
- colors.length(); // 0
- ```
-
- @method clear
- @return {Ember.Array} An empty Array.
- */
- clear: function () {
- var len = get(this, 'length');
- if (len === 0) return this;
- this.replace(0, len, EMPTY);
- return this;
- },
-
- /**
- This will use the primitive `replace()` method to insert an object at the
- specified index.
-
- ```javascript
- var colors = ["red", "green", "blue"];
- colors.insertAt(2, "yellow"); // ["red", "green", "yellow", "blue"]
- colors.insertAt(5, "orange"); // Error: Index out of range
- ```
-
- @method insertAt
- @param {Number} idx index of insert the object at.
- @param {Object} object object to insert
- @return {Ember.Array} receiver
- */
- insertAt: function(idx, object) {
- if (idx > get(this, 'length')) throw new EmberError(OUT_OF_RANGE_EXCEPTION);
- this.replace(idx, 0, [object]);
- return this;
- },
-
- /**
- Remove an object at the specified index using the `replace()` primitive
- method. You can pass either a single index, or a start and a length.
-
- If you pass a start and length that is beyond the
- length this method will throw an `OUT_OF_RANGE_EXCEPTION`.
-
- ```javascript
- var colors = ["red", "green", "blue", "yellow", "orange"];
- colors.removeAt(0); // ["green", "blue", "yellow", "orange"]
- colors.removeAt(2, 2); // ["green", "blue"]
- colors.removeAt(4, 2); // Error: Index out of range
- ```
-
- @method removeAt
- @param {Number} start index, start of range
- @param {Number} len length of passing range
- @return {Ember.Array} receiver
- */
- removeAt: function(start, len) {
- if ('number' === typeof start) {
-
- if ((start < 0) || (start >= get(this, 'length'))) {
- throw new EmberError(OUT_OF_RANGE_EXCEPTION);
- }
-
- // fast case
- if (len === undefined) len = 1;
- this.replace(start, len, EMPTY);
- }
-
- return this;
- },
-
- /**
- Push the object onto the end of the array. Works just like `push()` but it
- is KVO-compliant.
-
- ```javascript
- var colors = ["red", "green"];
- colors.pushObject("black"); // ["red", "green", "black"]
- colors.pushObject(["yellow"]); // ["red", "green", ["yellow"]]
- ```
-
- @method pushObject
- @param {*} obj object to push
- @return object same object passed as a param
- */
- pushObject: function(obj) {
- this.insertAt(get(this, 'length'), obj);
- return obj;
- },
-
- /**
- Add the objects in the passed numerable to the end of the array. Defers
- notifying observers of the change until all objects are added.
-
- ```javascript
- var colors = ["red"];
- colors.pushObjects(["yellow", "orange"]); // ["red", "yellow", "orange"]
- ```
-
- @method pushObjects
- @param {Ember.Enumerable} objects the objects to add
- @return {Ember.Array} receiver
- */
- pushObjects: function(objects) {
- if (!(Enumerable.detect(objects) || isArray(objects))) {
- throw new TypeError("Must pass Ember.Enumerable to Ember.MutableArray#pushObjects");
- }
- this.replace(get(this, 'length'), 0, objects);
- return this;
- },
-
- /**
- Pop object from array or nil if none are left. Works just like `pop()` but
- it is KVO-compliant.
-
- ```javascript
- var colors = ["red", "green", "blue"];
- colors.popObject(); // "blue"
- console.log(colors); // ["red", "green"]
- ```
-
- @method popObject
- @return object
- */
- popObject: function() {
- var len = get(this, 'length');
- if (len === 0) return null;
-
- var ret = this.objectAt(len-1);
- this.removeAt(len-1, 1);
- return ret;
- },
-
- /**
- Shift an object from start of array or nil if none are left. Works just
- like `shift()` but it is KVO-compliant.
-
- ```javascript
- var colors = ["red", "green", "blue"];
- colors.shiftObject(); // "red"
- console.log(colors); // ["green", "blue"]
- ```
-
- @method shiftObject
- @return object
- */
- shiftObject: function() {
- if (get(this, 'length') === 0) return null;
- var ret = this.objectAt(0);
- this.removeAt(0);
- return ret;
- },
-
- /**
- Unshift an object to start of array. Works just like `unshift()` but it is
- KVO-compliant.
-
- ```javascript
- var colors = ["red"];
- colors.unshiftObject("yellow"); // ["yellow", "red"]
- colors.unshiftObject(["black"]); // [["black"], "yellow", "red"]
- ```
-
- @method unshiftObject
- @param {*} obj object to unshift
- @return object same object passed as a param
- */
- unshiftObject: function(obj) {
- this.insertAt(0, obj);
- return obj;
- },
-
- /**
- Adds the named objects to the beginning of the array. Defers notifying
- observers until all objects have been added.
-
- ```javascript
- var colors = ["red"];
- colors.unshiftObjects(["black", "white"]); // ["black", "white", "red"]
- colors.unshiftObjects("yellow"); // Type Error: 'undefined' is not a function
- ```
-
- @method unshiftObjects
- @param {Ember.Enumerable} objects the objects to add
- @return {Ember.Array} receiver
- */
- unshiftObjects: function(objects) {
- this.replace(0, 0, objects);
- return this;
- },
-
- /**
- Reverse objects in the array. Works just like `reverse()` but it is
- KVO-compliant.
-
- @method reverseObjects
- @return {Ember.Array} receiver
- */
- reverseObjects: function() {
- var len = get(this, 'length');
- if (len === 0) return this;
- var objects = this.toArray().reverse();
- this.replace(0, len, objects);
- return this;
- },
-
- /**
- Replace all the receiver's content with content of the argument.
- If argument is an empty array receiver will be cleared.
-
- ```javascript
- var colors = ["red", "green", "blue"];
- colors.setObjects(["black", "white"]); // ["black", "white"]
- colors.setObjects([]); // []
- ```
-
- @method setObjects
- @param {Ember.Array} objects array whose content will be used for replacing
- the content of the receiver
- @return {Ember.Array} receiver with the new content
- */
- setObjects: function(objects) {
- if (objects.length === 0) return this.clear();
-
- var len = get(this, 'length');
- this.replace(0, len, objects);
- return this;
- },
-
- // ..........................................................
- // IMPLEMENT Ember.MutableEnumerable
- //
-
- /**
- Remove all occurrences of an object in the array.
-
- ```javascript
- var cities = ["Chicago", "Berlin", "Lima", "Chicago"];
- cities.removeObject("Chicago"); // ["Berlin", "Lima"]
- cities.removeObject("Lima"); // ["Berlin"]
- cities.removeObject("Tokyo") // ["Berlin"]
- ```
-
- @method removeObject
- @param {*} obj object to remove
- @return {Ember.Array} receiver
- */
- removeObject: function(obj) {
- var loc = get(this, 'length') || 0;
- while(--loc >= 0) {
- var curObject = this.objectAt(loc);
- if (curObject === obj) this.removeAt(loc);
- }
- return this;
- },
-
- /**
- Push the object onto the end of the array if it is not already
- present in the array.
-
- ```javascript
- var cities = ["Chicago", "Berlin"];
- cities.addObject("Lima"); // ["Chicago", "Berlin", "Lima"]
- cities.addObject("Berlin"); // ["Chicago", "Berlin", "Lima"]
- ```
-
- @method addObject
- @param {*} obj object to add, if not already present
- @return {Ember.Array} receiver
- */
- addObject: function(obj) {
- if (!this.contains(obj)) this.pushObject(obj);
- return this;
- }
-
- });
- });
-enifed("ember-runtime/mixins/mutable_enumerable",
- ["ember-metal/enumerable_utils","ember-runtime/mixins/enumerable","ember-metal/mixin","ember-metal/property_events","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
- "use strict";
- var forEach = __dependency1__.forEach;
- var Enumerable = __dependency2__["default"];
- var Mixin = __dependency3__.Mixin;
- var required = __dependency3__.required;
- var beginPropertyChanges = __dependency4__.beginPropertyChanges;
- var endPropertyChanges = __dependency4__.endPropertyChanges;
-
- /**
- @module ember
- @submodule ember-runtime
- */
-
- /**
- This mixin defines the API for modifying generic enumerables. These methods
- can be applied to an object regardless of whether it is ordered or
- unordered.
-
- Note that an Enumerable can change even if it does not implement this mixin.
- For example, a MappedEnumerable cannot be directly modified but if its
- underlying enumerable changes, it will change also.
-
- ## Adding Objects
-
- To add an object to an enumerable, use the `addObject()` method. This
- method will only add the object to the enumerable if the object is not
- already present and is of a type supported by the enumerable.
-
- ```javascript
- set.addObject(contact);
- ```
-
- ## Removing Objects
-
- To remove an object from an enumerable, use the `removeObject()` method. This
- will only remove the object if it is present in the enumerable, otherwise
- this method has no effect.
-
- ```javascript
- set.removeObject(contact);
- ```
-
- ## Implementing In Your Own Code
-
- If you are implementing an object and want to support this API, just include
- this mixin in your class and implement the required methods. In your unit
- tests, be sure to apply the Ember.MutableEnumerableTests to your object.
-
- @class MutableEnumerable
- @namespace Ember
- @uses Ember.Enumerable
- */
- __exports__["default"] = Mixin.create(Enumerable, {
-
- /**
- __Required.__ You must implement this method to apply this mixin.
-
- Attempts to add the passed object to the receiver if the object is not
- already present in the collection. If the object is present, this method
- has no effect.
-
- If the passed object is of a type not supported by the receiver,
- then this method should raise an exception.
-
- @method addObject
- @param {Object} object The object to add to the enumerable.
- @return {Object} the passed object
- */
- addObject: required(Function),
-
- /**
- Adds each object in the passed enumerable to the receiver.
-
- @method addObjects
- @param {Ember.Enumerable} objects the objects to add.
- @return {Object} receiver
- */
- addObjects: function(objects) {
- beginPropertyChanges(this);
- forEach(objects, function(obj) { this.addObject(obj); }, this);
- endPropertyChanges(this);
- return this;
- },
-
- /**
- __Required.__ You must implement this method to apply this mixin.
-
- Attempts to remove the passed object from the receiver collection if the
- object is present in the collection. If the object is not present,
- this method has no effect.
-
- If the passed object is of a type not supported by the receiver,
- then this method should raise an exception.
-
- @method removeObject
- @param {Object} object The object to remove from the enumerable.
- @return {Object} the passed object
- */
- removeObject: required(Function),
-
-
- /**
- Removes each object in the passed enumerable from the receiver.
-
- @method removeObjects
- @param {Ember.Enumerable} objects the objects to remove
- @return {Object} receiver
- */
- removeObjects: function(objects) {
- beginPropertyChanges(this);
- for (var i = objects.length - 1; i >= 0; i--) {
- this.removeObject(objects[i]);
- }
- endPropertyChanges(this);
- return this;
- }
- });
- });
-enifed("ember-runtime/mixins/observable",
- ["ember-metal/core","ember-metal/property_get","ember-metal/property_set","ember-metal/utils","ember-metal/get_properties","ember-metal/set_properties","ember-metal/mixin","ember-metal/events","ember-metal/property_events","ember-metal/observer","ember-metal/computed","ember-metal/is_none","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __exports__) {
- "use strict";
- /**
- @module ember
- @submodule ember-runtime
- */
- var Ember = __dependency1__["default"];
- // Ember.assert
-
- var get = __dependency2__.get;
- var getWithDefault = __dependency2__.getWithDefault;
- var set = __dependency3__.set;
- var apply = __dependency4__.apply;
- var getProperties = __dependency5__["default"];
- var setProperties = __dependency6__["default"];
- var Mixin = __dependency7__.Mixin;
- var hasListeners = __dependency8__.hasListeners;
- var beginPropertyChanges = __dependency9__.beginPropertyChanges;
- var propertyWillChange = __dependency9__.propertyWillChange;
- var propertyDidChange = __dependency9__.propertyDidChange;
- var endPropertyChanges = __dependency9__.endPropertyChanges;
- var addObserver = __dependency10__.addObserver;
- var addBeforeObserver = __dependency10__.addBeforeObserver;
- var removeObserver = __dependency10__.removeObserver;
- var observersFor = __dependency10__.observersFor;
- var cacheFor = __dependency11__.cacheFor;
- var isNone = __dependency12__["default"];
-
-
- var slice = Array.prototype.slice;
- /**
- ## Overview
-
- This mixin provides properties and property observing functionality, core
- features of the Ember object model.
-
- Properties and observers allow one object to observe changes to a
- property on another object. This is one of the fundamental ways that
- models, controllers and views communicate with each other in an Ember
- application.
-
- Any object that has this mixin applied can be used in observer
- operations. That includes `Ember.Object` and most objects you will
- interact with as you write your Ember application.
-
- Note that you will not generally apply this mixin to classes yourself,
- but you will use the features provided by this module frequently, so it
- is important to understand how to use it.
-
- ## Using `get()` and `set()`
-
- Because of Ember's support for bindings and observers, you will always
- access properties using the get method, and set properties using the
- set method. This allows the observing objects to be notified and
- computed properties to be handled properly.
-
- More documentation about `get` and `set` are below.
-
- ## Observing Property Changes
-
- You typically observe property changes simply by adding the `observes`
- call to the end of your method declarations in classes that you write.
- For example:
-
- ```javascript
- Ember.Object.extend({
- valueObserver: function() {
- // Executes whenever the "value" property changes
- }.observes('value')
- });
- ```
-
- Although this is the most common way to add an observer, this capability
- is actually built into the `Ember.Object` class on top of two methods
- defined in this mixin: `addObserver` and `removeObserver`. You can use
- these two methods to add and remove observers yourself if you need to
- do so at runtime.
-
- To add an observer for a property, call:
-
- ```javascript
- object.addObserver('propertyKey', targetObject, targetAction)
- ```
-
- This will call the `targetAction` method on the `targetObject` whenever
- the value of the `propertyKey` changes.
-
- Note that if `propertyKey` is a computed property, the observer will be
- called when any of the property dependencies are changed, even if the
- resulting value of the computed property is unchanged. This is necessary
- because computed properties are not computed until `get` is called.
-
- @class Observable
- @namespace Ember
- */
- __exports__["default"] = Mixin.create({
-
- /**
- Retrieves the value of a property from the object.
-
- This method is usually similar to using `object[keyName]` or `object.keyName`,
- however it supports both computed properties and the unknownProperty
- handler.
-
- Because `get` unifies the syntax for accessing all these kinds
- of properties, it can make many refactorings easier, such as replacing a
- simple property with a computed property, or vice versa.
-
- ### Computed Properties
-
- Computed properties are methods defined with the `property` modifier
- declared at the end, such as:
-
- ```javascript
- fullName: function() {
- return this.get('firstName') + ' ' + this.get('lastName');
- }.property('firstName', 'lastName')
- ```
-
- When you call `get` on a computed property, the function will be
- called and the return value will be returned instead of the function
- itself.
-
- ### Unknown Properties
-
- Likewise, if you try to call `get` on a property whose value is
- `undefined`, the `unknownProperty()` method will be called on the object.
- If this method returns any value other than `undefined`, it will be returned
- instead. This allows you to implement "virtual" properties that are
- not defined upfront.
-
- @method get
- @param {String} keyName The property to retrieve
- @return {Object} The property value or undefined.
- */
- get: function(keyName) {
- return get(this, keyName);
- },
-
- /**
- To get the values of multiple properties at once, call `getProperties`
- with a list of strings or an array:
-
- ```javascript
- record.getProperties('firstName', 'lastName', 'zipCode');
- // { firstName: 'John', lastName: 'Doe', zipCode: '10011' }
- ```
-
- is equivalent to:
-
- ```javascript
- record.getProperties(['firstName', 'lastName', 'zipCode']);
- // { firstName: 'John', lastName: 'Doe', zipCode: '10011' }
- ```
-
- @method getProperties
- @param {String...|Array} list of keys to get
- @return {Hash}
- */
- getProperties: function() {
- return apply(null, getProperties, [this].concat(slice.call(arguments)));
- },
-
- /**
- Sets the provided key or path to the value.
-
- This method is generally very similar to calling `object[key] = value` or
- `object.key = value`, except that it provides support for computed
- properties, the `setUnknownProperty()` method and property observers.
-
- ### Computed Properties
-
- If you try to set a value on a key that has a computed property handler
- defined (see the `get()` method for an example), then `set()` will call
- that method, passing both the value and key instead of simply changing
- the value itself. This is useful for those times when you need to
- implement a property that is composed of one or more member
- properties.
-
- ### Unknown Properties
-
- If you try to set a value on a key that is undefined in the target
- object, then the `setUnknownProperty()` handler will be called instead. This
- gives you an opportunity to implement complex "virtual" properties that
- are not predefined on the object. If `setUnknownProperty()` returns
- undefined, then `set()` will simply set the value on the object.
-
- ### Property Observers
-
- In addition to changing the property, `set()` will also register a property
- change with the object. Unless you have placed this call inside of a
- `beginPropertyChanges()` and `endPropertyChanges(),` any "local" observers
- (i.e. observer methods declared on the same object), will be called
- immediately. Any "remote" observers (i.e. observer methods declared on
- another object) will be placed in a queue and called at a later time in a
- coalesced manner.
-
- ### Chaining
-
- In addition to property changes, `set()` returns the value of the object
- itself so you can do chaining like this:
-
- ```javascript
- record.set('firstName', 'Charles').set('lastName', 'Jolley');
- ```
-
- @method set
- @param {String} keyName The property to set
- @param {Object} value The value to set or `null`.
- @return {Ember.Observable}
- */
- set: function(keyName, value) {
- set(this, keyName, value);
- return this;
- },
-
-
- /**
- Sets a list of properties at once. These properties are set inside
- a single `beginPropertyChanges` and `endPropertyChanges` batch, so
- observers will be buffered.
-
- ```javascript
- record.setProperties({ firstName: 'Charles', lastName: 'Jolley' });
- ```
-
- @method setProperties
- @param {Hash} hash the hash of keys and values to set
- @return {Ember.Observable}
- */
- setProperties: function(hash) {
- return setProperties(this, hash);
- },
-
- /**
- Begins a grouping of property changes.
-
- You can use this method to group property changes so that notifications
- will not be sent until the changes are finished. If you plan to make a
- large number of changes to an object at one time, you should call this
- method at the beginning of the changes to begin deferring change
- notifications. When you are done making changes, call
- `endPropertyChanges()` to deliver the deferred change notifications and end
- deferring.
-
- @method beginPropertyChanges
- @return {Ember.Observable}
- */
- beginPropertyChanges: function() {
- beginPropertyChanges();
- return this;
- },
-
- /**
- Ends a grouping of property changes.
-
- You can use this method to group property changes so that notifications
- will not be sent until the changes are finished. If you plan to make a
- large number of changes to an object at one time, you should call
- `beginPropertyChanges()` at the beginning of the changes to defer change
- notifications. When you are done making changes, call this method to
- deliver the deferred change notifications and end deferring.
-
- @method endPropertyChanges
- @return {Ember.Observable}
- */
- endPropertyChanges: function() {
- endPropertyChanges();
- return this;
- },
-
- /**
- Notify the observer system that a property is about to change.
-
- Sometimes you need to change a value directly or indirectly without
- actually calling `get()` or `set()` on it. In this case, you can use this
- method and `propertyDidChange()` instead. Calling these two methods
- together will notify all observers that the property has potentially
- changed value.
-
- Note that you must always call `propertyWillChange` and `propertyDidChange`
- as a pair. If you do not, it may get the property change groups out of
- order and cause notifications to be delivered more often than you would
- like.
-
- @method propertyWillChange
- @param {String} keyName The property key that is about to change.
- @return {Ember.Observable}
- */
- propertyWillChange: function(keyName) {
- propertyWillChange(this, keyName);
- return this;
- },
-
- /**
- Notify the observer system that a property has just changed.
-
- Sometimes you need to change a value directly or indirectly without
- actually calling `get()` or `set()` on it. In this case, you can use this
- method and `propertyWillChange()` instead. Calling these two methods
- together will notify all observers that the property has potentially
- changed value.
-
- Note that you must always call `propertyWillChange` and `propertyDidChange`
- as a pair. If you do not, it may get the property change groups out of
- order and cause notifications to be delivered more often than you would
- like.
-
- @method propertyDidChange
- @param {String} keyName The property key that has just changed.
- @return {Ember.Observable}
- */
- propertyDidChange: function(keyName) {
- propertyDidChange(this, keyName);
- return this;
- },
-
- /**
- Convenience method to call `propertyWillChange` and `propertyDidChange` in
- succession.
-
- @method notifyPropertyChange
- @param {String} keyName The property key to be notified about.
- @return {Ember.Observable}
- */
- notifyPropertyChange: function(keyName) {
- this.propertyWillChange(keyName);
- this.propertyDidChange(keyName);
- return this;
- },
-
- addBeforeObserver: function(key, target, method) {
- addBeforeObserver(this, key, target, method);
- },
-
- /**
- Adds an observer on a property.
-
- This is the core method used to register an observer for a property.
-
- Once you call this method, any time the key's value is set, your observer
- will be notified. Note that the observers are triggered any time the
- value is set, regardless of whether it has actually changed. Your
- observer should be prepared to handle that.
-
- You can also pass an optional context parameter to this method. The
- context will be passed to your observer method whenever it is triggered.
- Note that if you add the same target/method pair on a key multiple times
- with different context parameters, your observer will only be called once
- with the last context you passed.
-
- ### Observer Methods
-
- Observer methods you pass should generally have the following signature if
- you do not pass a `context` parameter:
-
- ```javascript
- fooDidChange: function(sender, key, value, rev) { };
- ```
-
- The sender is the object that changed. The key is the property that
- changes. The value property is currently reserved and unused. The rev
- is the last property revision of the object when it changed, which you can
- use to detect if the key value has really changed or not.
-
- If you pass a `context` parameter, the context will be passed before the
- revision like so:
-
- ```javascript
- fooDidChange: function(sender, key, value, context, rev) { };
- ```
-
- Usually you will not need the value, context or revision parameters at
- the end. In this case, it is common to write observer methods that take
- only a sender and key value as parameters or, if you aren't interested in
- any of these values, to write an observer that has no parameters at all.
-
- @method addObserver
- @param {String} key The key to observer
- @param {Object} target The target object to invoke
- @param {String|Function} method The method to invoke.
- */
- addObserver: function(key, target, method) {
- addObserver(this, key, target, method);
- },
-
- /**
- Remove an observer you have previously registered on this object. Pass
- the same key, target, and method you passed to `addObserver()` and your
- target will no longer receive notifications.
-
- @method removeObserver
- @param {String} key The key to observer
- @param {Object} target The target object to invoke
- @param {String|Function} method The method to invoke.
- */
- removeObserver: function(key, target, method) {
- removeObserver(this, key, target, method);
- },
-
- /**
- Returns `true` if the object currently has observers registered for a
- particular key. You can use this method to potentially defer performing
- an expensive action until someone begins observing a particular property
- on the object.
-
- @method hasObserverFor
- @param {String} key Key to check
- @return {Boolean}
- */
- hasObserverFor: function(key) {
- return hasListeners(this, key+':change');
- },
-
- /**
- Retrieves the value of a property, or a default value in the case that the
- property returns `undefined`.
-
- ```javascript
- person.getWithDefault('lastName', 'Doe');
- ```
-
- @method getWithDefault
- @param {String} keyName The name of the property to retrieve
- @param {Object} defaultValue The value to return if the property value is undefined
- @return {Object} The property value or the defaultValue.
- */
- getWithDefault: function(keyName, defaultValue) {
- return getWithDefault(this, keyName, defaultValue);
- },
-
- /**
- Set the value of a property to the current value plus some amount.
-
- ```javascript
- person.incrementProperty('age');
- team.incrementProperty('score', 2);
- ```
-
- @method incrementProperty
- @param {String} keyName The name of the property to increment
- @param {Number} increment The amount to increment by. Defaults to 1
- @return {Number} The new property value
- */
- incrementProperty: function(keyName, increment) {
- if (isNone(increment)) { increment = 1; }
- Ember.assert("Must pass a numeric value to incrementProperty", (!isNaN(parseFloat(increment)) && isFinite(increment)));
- set(this, keyName, (parseFloat(get(this, keyName)) || 0) + increment);
- return get(this, keyName);
- },
-
- /**
- Set the value of a property to the current value minus some amount.
-
- ```javascript
- player.decrementProperty('lives');
- orc.decrementProperty('health', 5);
- ```
-
- @method decrementProperty
- @param {String} keyName The name of the property to decrement
- @param {Number} decrement The amount to decrement by. Defaults to 1
- @return {Number} The new property value
- */
- decrementProperty: function(keyName, decrement) {
- if (isNone(decrement)) { decrement = 1; }
- Ember.assert("Must pass a numeric value to decrementProperty", (!isNaN(parseFloat(decrement)) && isFinite(decrement)));
- set(this, keyName, (get(this, keyName) || 0) - decrement);
- return get(this, keyName);
- },
-
- /**
- Set the value of a boolean property to the opposite of it's
- current value.
-
- ```javascript
- starship.toggleProperty('warpDriveEngaged');
- ```
-
- @method toggleProperty
- @param {String} keyName The name of the property to toggle
- @return {Object} The new property value
- */
- toggleProperty: function(keyName) {
- set(this, keyName, !get(this, keyName));
- return get(this, keyName);
- },
-
- /**
- Returns the cached value of a computed property, if it exists.
- This allows you to inspect the value of a computed property
- without accidentally invoking it if it is intended to be
- generated lazily.
-
- @method cacheFor
- @param {String} keyName
- @return {Object} The cached value of the computed property, if any
- */
- cacheFor: function(keyName) {
- return cacheFor(this, keyName);
- },
-
- // intended for debugging purposes
- observersForKey: function(keyName) {
- return observersFor(this, keyName);
- }
- });
- });
-enifed("ember-runtime/mixins/promise_proxy",
- ["ember-metal/property_get","ember-metal/set_properties","ember-metal/computed","ember-metal/mixin","ember-metal/error","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) {
- "use strict";
- var get = __dependency1__.get;
- var setProperties = __dependency2__["default"];
- var computed = __dependency3__.computed;
- var Mixin = __dependency4__.Mixin;
- var EmberError = __dependency5__["default"];
-
- var not = computed.not;
- var or = computed.or;
-
- /**
- @module ember
- @submodule ember-runtime
- */
-
- function tap(proxy, promise) {
- setProperties(proxy, {
- isFulfilled: false,
- isRejected: false
- });
-
- return promise.then(function(value) {
- setProperties(proxy, {
- content: value,
- isFulfilled: true
- });
- return value;
- }, function(reason) {
- setProperties(proxy, {
- reason: reason,
- isRejected: true
- });
- throw reason;
- }, "Ember: PromiseProxy");
- }
-
- /**
- A low level mixin making ObjectProxy, ObjectController or ArrayController's promise aware.
-
- ```javascript
- var ObjectPromiseController = Ember.ObjectController.extend(Ember.PromiseProxyMixin);
-
- var controller = ObjectPromiseController.create({
- promise: $.getJSON('/some/remote/data.json')
- });
-
- controller.then(function(json){
- // the json
- }, function(reason) {
- // the reason why you have no json
- });
- ```
-
- the controller has bindable attributes which
- track the promises life cycle
-
- ```javascript
- controller.get('isPending') //=> true
- controller.get('isSettled') //=> false
- controller.get('isRejected') //=> false
- controller.get('isFulfilled') //=> false
- ```
-
- When the the $.getJSON completes, and the promise is fulfilled
- with json, the life cycle attributes will update accordingly.
-
- ```javascript
- controller.get('isPending') //=> false
- controller.get('isSettled') //=> true
- controller.get('isRejected') //=> false
- controller.get('isFulfilled') //=> true
- ```
-
- As the controller is an ObjectController, and the json now its content,
- all the json properties will be available directly from the controller.
-
- ```javascript
- // Assuming the following json:
- {
- firstName: 'Stefan',
- lastName: 'Penner'
- }
-
- // both properties will accessible on the controller
- controller.get('firstName') //=> 'Stefan'
- controller.get('lastName') //=> 'Penner'
- ```
-
- If the controller is backing a template, the attributes are
- bindable from within that template
-
- ```handlebars
- {{#if isPending}}
- loading...
- {{else}}
- firstName: {{firstName}}
- lastName: {{lastName}}
- {{/if}}
- ```
- @class Ember.PromiseProxyMixin
- */
- __exports__["default"] = Mixin.create({
- /**
- If the proxied promise is rejected this will contain the reason
- provided.
-
- @property reason
- @default null
- */
- reason: null,
-
- /**
- Once the proxied promise has settled this will become `false`.
-
- @property isPending
- @default true
- */
- isPending: not('isSettled').readOnly(),
-
- /**
- Once the proxied promise has settled this will become `true`.
-
- @property isSettled
- @default false
- */
- isSettled: or('isRejected', 'isFulfilled').readOnly(),
-
- /**
- Will become `true` if the proxied promise is rejected.
-
- @property isRejected
- @default false
- */
- isRejected: false,
-
- /**
- Will become `true` if the proxied promise is fulfilled.
-
- @property isFulfilled
- @default false
- */
- isFulfilled: false,
-
- /**
- The promise whose fulfillment value is being proxied by this object.
-
- This property must be specified upon creation, and should not be
- changed once created.
-
- Example:
-
- ```javascript
- Ember.ObjectController.extend(Ember.PromiseProxyMixin).create({
- promise: <thenable>
- });
- ```
-
- @property promise
- */
- promise: computed(function(key, promise) {
- if (arguments.length === 2) {
- return tap(this, promise);
- } else {
- throw new EmberError("PromiseProxy's promise must be set");
- }
- }),
-
- /**
- An alias to the proxied promise's `then`.
-
- See RSVP.Promise.then.
-
- @method then
- @param {Function} callback
- @return {RSVP.Promise}
- */
- then: promiseAlias('then'),
-
- /**
- An alias to the proxied promise's `catch`.
-
- See RSVP.Promise.catch.
-
- @method catch
- @param {Function} callback
- @return {RSVP.Promise}
- @since 1.3.0
- */
- 'catch': promiseAlias('catch'),
-
- /**
- An alias to the proxied promise's `finally`.
-
- See RSVP.Promise.finally.
-
- @method finally
- @param {Function} callback
- @return {RSVP.Promise}
- @since 1.3.0
- */
- 'finally': promiseAlias('finally')
-
- });
-
- function promiseAlias(name) {
- return function () {
- var promise = get(this, 'promise');
- return promise[name].apply(promise, arguments);
- };
- }
- });
-enifed("ember-runtime/mixins/sortable",
- ["ember-metal/core","ember-metal/property_get","ember-metal/enumerable_utils","ember-metal/mixin","ember-runtime/mixins/mutable_enumerable","ember-runtime/compare","ember-metal/observer","ember-metal/computed","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __exports__) {
- "use strict";
- /**
- @module ember
- @submodule ember-runtime
- */
-
- var Ember = __dependency1__["default"];
- // Ember.assert, Ember.A
-
- var get = __dependency2__.get;
- var forEach = __dependency3__.forEach;
- var Mixin = __dependency4__.Mixin;
- var MutableEnumerable = __dependency5__["default"];
- var compare = __dependency6__["default"];
- var addObserver = __dependency7__.addObserver;
- var removeObserver = __dependency7__.removeObserver;
- var computed = __dependency8__.computed;
- var beforeObserver = __dependency4__.beforeObserver;
- var observer = __dependency4__.observer;
- //ES6TODO: should we access these directly from their package or from how their exposed in ember-metal?
-
- /**
- `Ember.SortableMixin` provides a standard interface for array proxies
- to specify a sort order and maintain this sorting when objects are added,
- removed, or updated without changing the implicit order of their underlying
- model array:
-
- ```javascript
- songs = [
- {trackNumber: 4, title: 'Ob-La-Di, Ob-La-Da'},
- {trackNumber: 2, title: 'Back in the U.S.S.R.'},
- {trackNumber: 3, title: 'Glass Onion'},
- ];
-
- songsController = Ember.ArrayController.create({
- model: songs,
- sortProperties: ['trackNumber'],
- sortAscending: true
- });
-
- songsController.get('firstObject'); // {trackNumber: 2, title: 'Back in the U.S.S.R.'}
-
- songsController.addObject({trackNumber: 1, title: 'Dear Prudence'});
- songsController.get('firstObject'); // {trackNumber: 1, title: 'Dear Prudence'}
- ```
-
- If you add or remove the properties to sort by or change the sort direction the model
- sort order will be automatically updated.
-
- ```javascript
- songsController.set('sortProperties', ['title']);
- songsController.get('firstObject'); // {trackNumber: 2, title: 'Back in the U.S.S.R.'}
-
- songsController.toggleProperty('sortAscending');
- songsController.get('firstObject'); // {trackNumber: 4, title: 'Ob-La-Di, Ob-La-Da'}
- ```
-
- `SortableMixin` works by sorting the `arrangedContent` array, which is the array that
- `ArrayProxy` displays. Due to the fact that the underlying 'content' array is not changed, that
- array will not display the sorted list:
-
- ```javascript
- songsController.get('content').get('firstObject'); // Returns the unsorted original content
- songsController.get('firstObject'); // Returns the sorted content.
- ```
-
- Although the sorted content can also be accessed through the `arrangedContent` property,
- it is preferable to use the proxied class and not the `arrangedContent` array directly.
-
- @class SortableMixin
- @namespace Ember
- @uses Ember.MutableEnumerable
- */
- __exports__["default"] = Mixin.create(MutableEnumerable, {
-
- /**
- Specifies which properties dictate the `arrangedContent`'s sort order.
-
- When specifying multiple properties the sorting will use properties
- from the `sortProperties` array prioritized from first to last.
-
- @property {Array} sortProperties
- */
- sortProperties: null,
-
- /**
- Specifies the `arrangedContent`'s sort direction.
- Sorts the content in ascending order by default. Set to `false` to
- use descending order.
-
- @property {Boolean} sortAscending
- @default true
- */
- sortAscending: true,
-
- /**
- The function used to compare two values. You can override this if you
- want to do custom comparisons. Functions must be of the type expected by
- Array#sort, i.e.,
-
- * return 0 if the two parameters are equal,
- * return a negative value if the first parameter is smaller than the second or
- * return a positive value otherwise:
-
- ```javascript
- function(x, y) { // These are assumed to be integers
- if (x === y)
- return 0;
- return x < y ? -1 : 1;
- }
- ```
-
- @property sortFunction
- @type {Function}
- @default Ember.compare
- */
- sortFunction: compare,
-
- orderBy: function(item1, item2) {
- var result = 0;
- var sortProperties = get(this, 'sortProperties');
- var sortAscending = get(this, 'sortAscending');
- var sortFunction = get(this, 'sortFunction');
-
- Ember.assert("you need to define `sortProperties`", !!sortProperties);
-
- forEach(sortProperties, function(propertyName) {
- if (result === 0) {
- result = sortFunction.call(this, get(item1, propertyName), get(item2, propertyName));
- if ((result !== 0) && !sortAscending) {
- result = (-1) * result;
- }
- }
- }, this);
-
- return result;
- },
-
- destroy: function() {
- var content = get(this, 'content');
- var sortProperties = get(this, 'sortProperties');
-
- if (content && sortProperties) {
- forEach(content, function(item) {
- forEach(sortProperties, function(sortProperty) {
- removeObserver(item, sortProperty, this, 'contentItemSortPropertyDidChange');
- }, this);
- }, this);
- }
-
- return this._super();
- },
-
- isSorted: computed.notEmpty('sortProperties'),
-
- /**
- Overrides the default `arrangedContent` from `ArrayProxy` in order to sort by `sortFunction`.
- Also sets up observers for each `sortProperty` on each item in the content Array.
-
- @property arrangedContent
- */
- arrangedContent: computed('content', 'sortProperties.@each', function(key, value) {
- var content = get(this, 'content');
- var isSorted = get(this, 'isSorted');
- var sortProperties = get(this, 'sortProperties');
- var self = this;
-
- if (content && isSorted) {
- content = content.slice();
- content.sort(function(item1, item2) {
- return self.orderBy(item1, item2);
- });
- forEach(content, function(item) {
- forEach(sortProperties, function(sortProperty) {
- addObserver(item, sortProperty, this, 'contentItemSortPropertyDidChange');
- }, this);
- }, this);
- return Ember.A(content);
- }
-
- return content;
- }),
-
- _contentWillChange: beforeObserver('content', function() {
- var content = get(this, 'content');
- var sortProperties = get(this, 'sortProperties');
-
- if (content && sortProperties) {
- forEach(content, function(item) {
- forEach(sortProperties, function(sortProperty) {
- removeObserver(item, sortProperty, this, 'contentItemSortPropertyDidChange');
- }, this);
- }, this);
- }
-
- this._super();
- }),
-
- sortPropertiesWillChange: beforeObserver('sortProperties', function() {
- this._lastSortAscending = undefined;
- }),
-
- sortPropertiesDidChange: observer('sortProperties', function() {
- this._lastSortAscending = undefined;
- }),
-
- sortAscendingWillChange: beforeObserver('sortAscending', function() {
- this._lastSortAscending = get(this, 'sortAscending');
- }),
-
- sortAscendingDidChange: observer('sortAscending', function() {
- if (this._lastSortAscending !== undefined && get(this, 'sortAscending') !== this._lastSortAscending) {
- var arrangedContent = get(this, 'arrangedContent');
- arrangedContent.reverseObjects();
- }
- }),
-
- contentArrayWillChange: function(array, idx, removedCount, addedCount) {
- var isSorted = get(this, 'isSorted');
-
- if (isSorted) {
- var arrangedContent = get(this, 'arrangedContent');
- var removedObjects = array.slice(idx, idx+removedCount);
- var sortProperties = get(this, 'sortProperties');
-
- forEach(removedObjects, function(item) {
- arrangedContent.removeObject(item);
-
- forEach(sortProperties, function(sortProperty) {
- removeObserver(item, sortProperty, this, 'contentItemSortPropertyDidChange');
- }, this);
- }, this);
- }
-
- return this._super(array, idx, removedCount, addedCount);
- },
-
- contentArrayDidChange: function(array, idx, removedCount, addedCount) {
- var isSorted = get(this, 'isSorted');
- var sortProperties = get(this, 'sortProperties');
-
- if (isSorted) {
- var addedObjects = array.slice(idx, idx+addedCount);
-
- forEach(addedObjects, function(item) {
- this.insertItemSorted(item);
-
- forEach(sortProperties, function(sortProperty) {
- addObserver(item, sortProperty, this, 'contentItemSortPropertyDidChange');
- }, this);
- }, this);
- }
-
- return this._super(array, idx, removedCount, addedCount);
- },
-
- insertItemSorted: function(item) {
- var arrangedContent = get(this, 'arrangedContent');
- var length = get(arrangedContent, 'length');
-
- var idx = this._binarySearch(item, 0, length);
- arrangedContent.insertAt(idx, item);
- },
-
- contentItemSortPropertyDidChange: function(item) {
- var arrangedContent = get(this, 'arrangedContent');
- var oldIndex = arrangedContent.indexOf(item);
- var leftItem = arrangedContent.objectAt(oldIndex - 1);
- var rightItem = arrangedContent.objectAt(oldIndex + 1);
- var leftResult = leftItem && this.orderBy(item, leftItem);
- var rightResult = rightItem && this.orderBy(item, rightItem);
-
- if (leftResult < 0 || rightResult > 0) {
- arrangedContent.removeObject(item);
- this.insertItemSorted(item);
- }
- },
-
- _binarySearch: function(item, low, high) {
- var mid, midItem, res, arrangedContent;
-
- if (low === high) {
- return low;
- }
-
- arrangedContent = get(this, 'arrangedContent');
-
- mid = low + Math.floor((high - low) / 2);
- midItem = arrangedContent.objectAt(mid);
-
- res = this.orderBy(midItem, item);
-
- if (res < 0) {
- return this._binarySearch(item, mid+1, high);
- } else if (res > 0) {
- return this._binarySearch(item, low, mid);
- }
-
- return mid;
- }
- });
- });
-enifed("ember-runtime/mixins/target_action_support",
- ["ember-metal/core","ember-metal/property_get","ember-metal/utils","ember-metal/mixin","ember-metal/computed","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) {
- "use strict";
- /**
- @module ember
- @submodule ember-runtime
- */
- var Ember = __dependency1__["default"];
- // Ember.lookup, Ember.assert
-
- var get = __dependency2__.get;
- var typeOf = __dependency3__.typeOf;
- var Mixin = __dependency4__.Mixin;
- var computed = __dependency5__.computed;
-
- /**
- `Ember.TargetActionSupport` is a mixin that can be included in a class
- to add a `triggerAction` method with semantics similar to the Handlebars
- `{{action}}` helper. In normal Ember usage, the `{{action}}` helper is
- usually the best choice. This mixin is most often useful when you are
- doing more complex event handling in View objects.
-
- See also `Ember.ViewTargetActionSupport`, which has
- view-aware defaults for target and actionContext.
-
- @class TargetActionSupport
- @namespace Ember
- @extends Ember.Mixin
- */
- var TargetActionSupport = Mixin.create({
- target: null,
- action: null,
- actionContext: null,
-
- targetObject: computed(function() {
- var target = get(this, 'target');
-
- if (typeOf(target) === "string") {
- var value = get(this, target);
- if (value === undefined) { value = get(Ember.lookup, target); }
- return value;
- } else {
- return target;
- }
- }).property('target'),
-
- actionContextObject: computed(function() {
- var actionContext = get(this, 'actionContext');
-
- if (typeOf(actionContext) === "string") {
- var value = get(this, actionContext);
- if (value === undefined) { value = get(Ember.lookup, actionContext); }
- return value;
- } else {
- return actionContext;
- }
- }).property('actionContext'),
-
- /**
- Send an `action` with an `actionContext` to a `target`. The action, actionContext
- and target will be retrieved from properties of the object. For example:
-
- ```javascript
- App.SaveButtonView = Ember.View.extend(Ember.TargetActionSupport, {
- target: Ember.computed.alias('controller'),
- action: 'save',
- actionContext: Ember.computed.alias('context'),
- click: function() {
- this.triggerAction(); // Sends the `save` action, along with the current context
- // to the current controller
- }
- });
- ```
-
- The `target`, `action`, and `actionContext` can be provided as properties of
- an optional object argument to `triggerAction` as well.
-
- ```javascript
- App.SaveButtonView = Ember.View.extend(Ember.TargetActionSupport, {
- click: function() {
- this.triggerAction({
- action: 'save',
- target: this.get('controller'),
- actionContext: this.get('context')
- }); // Sends the `save` action, along with the current context
- // to the current controller
- }
- });
- ```
-
- The `actionContext` defaults to the object you are mixing `TargetActionSupport` into.
- But `target` and `action` must be specified either as properties or with the argument
- to `triggerAction`, or a combination:
-
- ```javascript
- App.SaveButtonView = Ember.View.extend(Ember.TargetActionSupport, {
- target: Ember.computed.alias('controller'),
- click: function() {
- this.triggerAction({
- action: 'save'
- }); // Sends the `save` action, along with a reference to `this`,
- // to the current controller
- }
- });
- ```
-
- @method triggerAction
- @param opts {Hash} (optional, with the optional keys action, target and/or actionContext)
- @return {Boolean} true if the action was sent successfully and did not return false
- */
- triggerAction: function(opts) {
- opts = opts || {};
- var action = opts.action || get(this, 'action');
- var target = opts.target || get(this, 'targetObject');
- var actionContext = opts.actionContext;
-
- function args(options, actionName) {
- var ret = [];
- if (actionName) { ret.push(actionName); }
-
- return ret.concat(options);
- }
-
- if (typeof actionContext === 'undefined') {
- actionContext = get(this, 'actionContextObject') || this;
- }
-
- if (target && action) {
- var ret;
-
- if (target.send) {
- ret = target.send.apply(target, args(actionContext, action));
- } else {
- Ember.assert("The action '" + action + "' did not exist on " + target, typeof target[action] === 'function');
- ret = target[action].apply(target, args(actionContext));
- }
-
- if (ret !== false) ret = true;
-
- return ret;
- } else {
- return false;
- }
- }
- });
-
- __exports__["default"] = TargetActionSupport;
- });
-enifed("ember-runtime/system/application",
- ["ember-runtime/system/namespace","exports"],
- function(__dependency1__, __exports__) {
- "use strict";
- var Namespace = __dependency1__["default"];
-
- __exports__["default"] = Namespace.extend();
- });
-enifed("ember-runtime/system/array_proxy",
- ["ember-metal/core","ember-metal/property_get","ember-metal/utils","ember-metal/computed","ember-metal/mixin","ember-metal/property_events","ember-metal/error","ember-runtime/system/object","ember-runtime/mixins/mutable_array","ember-runtime/mixins/enumerable","ember-runtime/system/string","ember-metal/alias","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __exports__) {
- "use strict";
- var Ember = __dependency1__["default"];
- // Ember.K, Ember.assert
- var get = __dependency2__.get;
- var isArray = __dependency3__.isArray;
- var apply = __dependency3__.apply;
- var computed = __dependency4__.computed;
- var beforeObserver = __dependency5__.beforeObserver;
- var observer = __dependency5__.observer;
- var beginPropertyChanges = __dependency6__.beginPropertyChanges;
- var endPropertyChanges = __dependency6__.endPropertyChanges;
- var EmberError = __dependency7__["default"];
- var EmberObject = __dependency8__["default"];
- var MutableArray = __dependency9__["default"];
- var Enumerable = __dependency10__["default"];
- var fmt = __dependency11__.fmt;
- var alias = __dependency12__["default"];
-
- /**
- @module ember
- @submodule ember-runtime
- */
-
- var OUT_OF_RANGE_EXCEPTION = "Index out of range";
- var EMPTY = [];
- var K = Ember.K;
-
- /**
- An ArrayProxy wraps any other object that implements `Ember.Array` and/or
- `Ember.MutableArray,` forwarding all requests. This makes it very useful for
- a number of binding use cases or other cases where being able to swap
- out the underlying array is useful.
-
- A simple example of usage:
-
- ```javascript
- var pets = ['dog', 'cat', 'fish'];
- var ap = Ember.ArrayProxy.create({ content: Ember.A(pets) });
-
- ap.get('firstObject'); // 'dog'
- ap.set('content', ['amoeba', 'paramecium']);
- ap.get('firstObject'); // 'amoeba'
- ```
-
- This class can also be useful as a layer to transform the contents of
- an array, as they are accessed. This can be done by overriding
- `objectAtContent`:
-
- ```javascript
- var pets = ['dog', 'cat', 'fish'];
- var ap = Ember.ArrayProxy.create({
- content: Ember.A(pets),
- objectAtContent: function(idx) {
- return this.get('content').objectAt(idx).toUpperCase();
- }
- });
-
- ap.get('firstObject'); // . 'DOG'
- ```
-
- @class ArrayProxy
- @namespace Ember
- @extends Ember.Object
- @uses Ember.MutableArray
- */
- var ArrayProxy = EmberObject.extend(MutableArray, {
-
- /**
- The content array. Must be an object that implements `Ember.Array` and/or
- `Ember.MutableArray.`
-
- @property content
- @type Ember.Array
- */
- content: null,
-
- /**
- The array that the proxy pretends to be. In the default `ArrayProxy`
- implementation, this and `content` are the same. Subclasses of `ArrayProxy`
- can override this property to provide things like sorting and filtering.
-
- @property arrangedContent
- */
- arrangedContent: alias('content'),
-
- /**
- Should actually retrieve the object at the specified index from the
- content. You can override this method in subclasses to transform the
- content item to something new.
-
- This method will only be called if content is non-`null`.
-
- @method objectAtContent
- @param {Number} idx The index to retrieve.
- @return {Object} the value or undefined if none found
- */
- objectAtContent: function(idx) {
- return get(this, 'arrangedContent').objectAt(idx);
- },
-
- /**
- Should actually replace the specified objects on the content array.
- You can override this method in subclasses to transform the content item
- into something new.
-
- This method will only be called if content is non-`null`.
-
- @method replaceContent
- @param {Number} idx The starting index
- @param {Number} amt The number of items to remove from the content.
- @param {Array} objects Optional array of objects to insert or null if no
- objects.
- @return {void}
- */
- replaceContent: function(idx, amt, objects) {
- get(this, 'content').replace(idx, amt, objects);
- },
-
- /**
- Invoked when the content property is about to change. Notifies observers that the
- entire array content will change.
-
- @private
- @method _contentWillChange
- */
- _contentWillChange: beforeObserver('content', function() {
- this._teardownContent();
- }),
-
- _teardownContent: function() {
- var content = get(this, 'content');
-
- if (content) {
- content.removeArrayObserver(this, {
- willChange: 'contentArrayWillChange',
- didChange: 'contentArrayDidChange'
- });
- }
- },
-
- /**
- Override to implement content array `willChange` observer.
-
- @method contentArrayWillChange
-
- @param {Ember.Array} contentArray the content array
- @param {Number} start starting index of the change
- @param {Number} removeCount count of items removed
- @param {Number} addCount count of items added
-
- */
- contentArrayWillChange: K,
- /**
- Override to implement content array `didChange` observer.
-
- @method contentArrayDidChange
-
- @param {Ember.Array} contentArray the content array
- @param {Number} start starting index of the change
- @param {Number} removeCount count of items removed
- @param {Number} addCount count of items added
- */
- contentArrayDidChange: K,
-
- /**
- Invoked when the content property changes. Notifies observers that the
- entire array content has changed.
-
- @private
- @method _contentDidChange
- */
- _contentDidChange: observer('content', function() {
- var content = get(this, 'content');
-
- Ember.assert("Can't set ArrayProxy's content to itself", content !== this);
-
- this._setupContent();
- }),
-
- _setupContent: function() {
- var content = get(this, 'content');
-
- if (content) {
- Ember.assert(fmt('ArrayProxy expects an Array or ' +
- 'Ember.ArrayProxy, but you passed %@', [typeof content]),
- isArray(content) || content.isDestroyed);
-
- content.addArrayObserver(this, {
- willChange: 'contentArrayWillChange',
- didChange: 'contentArrayDidChange'
- });
- }
- },
-
- _arrangedContentWillChange: beforeObserver('arrangedContent', function() {
- var arrangedContent = get(this, 'arrangedContent');
- var len = arrangedContent ? get(arrangedContent, 'length') : 0;
-
- this.arrangedContentArrayWillChange(this, 0, len, undefined);
- this.arrangedContentWillChange(this);
-
- this._teardownArrangedContent(arrangedContent);
- }),
-
- _arrangedContentDidChange: observer('arrangedContent', function() {
- var arrangedContent = get(this, 'arrangedContent');
- var len = arrangedContent ? get(arrangedContent, 'length') : 0;
-
- Ember.assert("Can't set ArrayProxy's content to itself", arrangedContent !== this);
-
- this._setupArrangedContent();
-
- this.arrangedContentDidChange(this);
- this.arrangedContentArrayDidChange(this, 0, undefined, len);
- }),
-
- _setupArrangedContent: function() {
- var arrangedContent = get(this, 'arrangedContent');
-
- if (arrangedContent) {
- Ember.assert(fmt('ArrayProxy expects an Array or ' +
- 'Ember.ArrayProxy, but you passed %@', [typeof arrangedContent]),
- isArray(arrangedContent) || arrangedContent.isDestroyed);
-
- arrangedContent.addArrayObserver(this, {
- willChange: 'arrangedContentArrayWillChange',
- didChange: 'arrangedContentArrayDidChange'
- });
- }
- },
-
- _teardownArrangedContent: function() {
- var arrangedContent = get(this, 'arrangedContent');
-
- if (arrangedContent) {
- arrangedContent.removeArrayObserver(this, {
- willChange: 'arrangedContentArrayWillChange',
- didChange: 'arrangedContentArrayDidChange'
- });
- }
- },
-
- arrangedContentWillChange: K,
- arrangedContentDidChange: K,
-
- objectAt: function(idx) {
- return get(this, 'content') && this.objectAtContent(idx);
- },
-
- length: computed(function() {
- var arrangedContent = get(this, 'arrangedContent');
- return arrangedContent ? get(arrangedContent, 'length') : 0;
- // No dependencies since Enumerable notifies length of change
- }),
-
- _replace: function(idx, amt, objects) {
- var content = get(this, 'content');
- Ember.assert('The content property of '+ this.constructor + ' should be set before modifying it', content);
- if (content) this.replaceContent(idx, amt, objects);
- return this;
- },
-
- replace: function() {
- if (get(this, 'arrangedContent') === get(this, 'content')) {
- apply(this, this._replace, arguments);
- } else {
- throw new EmberError("Using replace on an arranged ArrayProxy is not allowed.");
- }
- },
-
- _insertAt: function(idx, object) {
- if (idx > get(this, 'content.length')) throw new EmberError(OUT_OF_RANGE_EXCEPTION);
- this._replace(idx, 0, [object]);
- return this;
- },
-
- insertAt: function(idx, object) {
- if (get(this, 'arrangedContent') === get(this, 'content')) {
- return this._insertAt(idx, object);
- } else {
- throw new EmberError("Using insertAt on an arranged ArrayProxy is not allowed.");
- }
- },
-
- removeAt: function(start, len) {
- if ('number' === typeof start) {
- var content = get(this, 'content');
- var arrangedContent = get(this, 'arrangedContent');
- var indices = [];
- var i;
-
- if ((start < 0) || (start >= get(this, 'length'))) {
- throw new EmberError(OUT_OF_RANGE_EXCEPTION);
- }
-
- if (len === undefined) len = 1;
-
- // Get a list of indices in original content to remove
- for (i=start; i<start+len; i++) {
- // Use arrangedContent here so we avoid confusion with objects transformed by objectAtContent
- indices.push(content.indexOf(arrangedContent.objectAt(i)));
- }
-
- // Replace in reverse order since indices will change
- indices.sort(function(a,b) { return b - a; });
-
- beginPropertyChanges();
- for (i=0; i<indices.length; i++) {
- this._replace(indices[i], 1, EMPTY);
- }
- endPropertyChanges();
- }
-
- return this ;
- },
-
- pushObject: function(obj) {
- this._insertAt(get(this, 'content.length'), obj) ;
- return obj ;
- },
-
- pushObjects: function(objects) {
- if (!(Enumerable.detect(objects) || isArray(objects))) {
- throw new TypeError("Must pass Ember.Enumerable to Ember.MutableArray#pushObjects");
- }
- this._replace(get(this, 'length'), 0, objects);
- return this;
- },
-
- setObjects: function(objects) {
- if (objects.length === 0) return this.clear();
-
- var len = get(this, 'length');
- this._replace(0, len, objects);
- return this;
- },
-
- unshiftObject: function(obj) {
- this._insertAt(0, obj) ;
- return obj ;
- },
-
- unshiftObjects: function(objects) {
- this._replace(0, 0, objects);
- return this;
- },
-
- slice: function() {
- var arr = this.toArray();
- return arr.slice.apply(arr, arguments);
- },
-
- arrangedContentArrayWillChange: function(item, idx, removedCnt, addedCnt) {
- this.arrayContentWillChange(idx, removedCnt, addedCnt);
- },
-
- arrangedContentArrayDidChange: function(item, idx, removedCnt, addedCnt) {
- this.arrayContentDidChange(idx, removedCnt, addedCnt);
- },
-
- init: function() {
- this._super();
- this._setupContent();
- this._setupArrangedContent();
- },
-
- willDestroy: function() {
- this._teardownArrangedContent();
- this._teardownContent();
- }
- });
-
- __exports__["default"] = ArrayProxy;
- });
-enifed("ember-runtime/system/container",
- ["ember-metal/property_set","container","exports"],
- function(__dependency1__, __dependency2__, __exports__) {
- "use strict";
- var set = __dependency1__.set;
- var Container = __dependency2__["default"];
-
- Container.set = set;
-
- __exports__["default"] = Container;
- });
-enifed("ember-runtime/system/core_object",
- ["ember-metal/core","ember-metal/property_get","ember-metal/utils","ember-metal/platform","ember-metal/chains","ember-metal/events","ember-metal/mixin","ember-metal/enumerable_utils","ember-metal/error","ember-metal/keys","ember-runtime/mixins/action_handler","ember-metal/properties","ember-metal/binding","ember-metal/computed","ember-metal/injected_property","ember-metal/run_loop","ember-metal/watching","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __dependency15__, __dependency16__, __dependency17__, __exports__) {
- // Remove "use strict"; from transpiled module until
- // https://bugs.webkit.org/show_bug.cgi?id=138038 is fixed
- //
- // REMOVE_USE_STRICT: true
-
- /**
- @module ember
- @submodule ember-runtime
- */
-
- var Ember = __dependency1__["default"];
- // Ember.assert, Ember.K, Ember.config
-
- // NOTE: this object should never be included directly. Instead use `Ember.Object`.
- // We only define this separately so that `Ember.Set` can depend on it.
- var get = __dependency2__.get;
- var guidFor = __dependency3__.guidFor;
- var apply = __dependency3__.apply;
- var o_create = __dependency4__.create;
- var generateGuid = __dependency3__.generateGuid;
- var GUID_KEY = __dependency3__.GUID_KEY;
- var meta = __dependency3__.meta;
- var makeArray = __dependency3__.makeArray;
- var finishChains = __dependency5__.finishChains;
- var sendEvent = __dependency6__.sendEvent;
- var IS_BINDING = __dependency7__.IS_BINDING;
- var Mixin = __dependency7__.Mixin;
- var required = __dependency7__.required;
- var indexOf = __dependency8__.indexOf;
- var EmberError = __dependency9__["default"];
- var o_defineProperty = __dependency4__.defineProperty;
- var keys = __dependency10__["default"];
- var ActionHandler = __dependency11__["default"];
- var defineProperty = __dependency12__.defineProperty;
- var Binding = __dependency13__.Binding;
- var ComputedProperty = __dependency14__.ComputedProperty;
- var computed = __dependency14__.computed;
- var InjectedProperty = __dependency15__["default"];
- var run = __dependency16__["default"];
- var destroy = __dependency17__.destroy;
- var K = __dependency1__.K;
- var hasPropertyAccessors = __dependency4__.hasPropertyAccessors;
-
- var schedule = run.schedule;
- var applyMixin = Mixin._apply;
- var finishPartial = Mixin.finishPartial;
- var reopen = Mixin.prototype.reopen;
- var hasCachedComputedProperties = false;
-
- var undefinedDescriptor = {
- configurable: true,
- writable: true,
- enumerable: false,
- value: undefined
- };
-
- var nullDescriptor = {
- configurable: true,
- writable: true,
- enumerable: false,
- value: null
- };
-
- function makeCtor() {
-
- // Note: avoid accessing any properties on the object since it makes the
- // method a lot faster. This is glue code so we want it to be as fast as
- // possible.
-
- var wasApplied = false;
- var initMixins, initProperties;
-
- var Class = function() {
- if (!wasApplied) {
- Class.proto(); // prepare prototype...
- }
- o_defineProperty(this, GUID_KEY, nullDescriptor);
- o_defineProperty(this, '__nextSuper', undefinedDescriptor);
- var m = meta(this);
- var proto = m.proto;
- m.proto = this;
- if (initMixins) {
- // capture locally so we can clear the closed over variable
- var mixins = initMixins;
- initMixins = null;
- apply(this, this.reopen, mixins);
- }
- if (initProperties) {
- // capture locally so we can clear the closed over variable
- var props = initProperties;
- initProperties = null;
-
- var concatenatedProperties = this.concatenatedProperties;
-
- for (var i = 0, l = props.length; i < l; i++) {
- var properties = props[i];
-
- Ember.assert("Ember.Object.create no longer supports mixing in other definitions, use createWithMixins instead.", !(properties instanceof Mixin));
-
- if (typeof properties !== 'object' && properties !== undefined) {
- throw new EmberError("Ember.Object.create only accepts objects.");
- }
-
- if (!properties) { continue; }
-
- var keyNames = keys(properties);
-
- for (var j = 0, ll = keyNames.length; j < ll; j++) {
- var keyName = keyNames[j];
- var value = properties[keyName];
-
- if (IS_BINDING.test(keyName)) {
- var bindings = m.bindings;
- if (!bindings) {
- bindings = m.bindings = {};
- } else if (!m.hasOwnProperty('bindings')) {
- bindings = m.bindings = o_create(m.bindings);
- }
- bindings[keyName] = value;
- }
-
- var desc = m.descs[keyName];
-
- Ember.assert("Ember.Object.create no longer supports defining computed properties. Define computed properties using extend() or reopen() before calling create().", !(value instanceof ComputedProperty));
- Ember.assert("Ember.Object.create no longer supports defining methods that call _super.", !(typeof value === 'function' && value.toString().indexOf('._super') !== -1));
- Ember.assert("`actions` must be provided at extend time, not at create " +
- "time, when Ember.ActionHandler is used (i.e. views, " +
- "controllers & routes).", !((keyName === 'actions') && ActionHandler.detect(this)));
-
- if (concatenatedProperties &&
- concatenatedProperties.length > 0 &&
- indexOf(concatenatedProperties, keyName) >= 0) {
- var baseValue = this[keyName];
-
- if (baseValue) {
- if ('function' === typeof baseValue.concat) {
- value = baseValue.concat(value);
- } else {
- value = makeArray(baseValue).concat(value);
- }
- } else {
- value = makeArray(value);
- }
- }
-
- if (desc) {
- desc.set(this, keyName, value);
- } else {
- if (typeof this.setUnknownProperty === 'function' && !(keyName in this)) {
- this.setUnknownProperty(keyName, value);
- } else {
-
- if (hasPropertyAccessors) {
- defineProperty(this, keyName, null, value); // setup mandatory setter
- } else {
- this[keyName] = value;
- }
- }
- }
- }
- }
- }
- finishPartial(this, m);
- var length = arguments.length;
- var args = new Array(length);
- for (var x = 0; x < length; x++) {
- args[x] = arguments[x];
- }
- apply(this, this.init, args);
- m.proto = proto;
- finishChains(this);
- sendEvent(this, "init");
- };
-
- Class.toString = Mixin.prototype.toString;
- Class.willReopen = function() {
- if (wasApplied) {
- Class.PrototypeMixin = Mixin.create(Class.PrototypeMixin);
- }
-
- wasApplied = false;
- };
- Class._initMixins = function(args) { initMixins = args; };
- Class._initProperties = function(args) { initProperties = args; };
-
- Class.proto = function() {
- var superclass = Class.superclass;
- if (superclass) { superclass.proto(); }
-
- if (!wasApplied) {
- wasApplied = true;
- Class.PrototypeMixin.applyPartial(Class.prototype);
- }
-
- return this.prototype;
- };
-
- return Class;
-
- }
-
- /**
- @class CoreObject
- @namespace Ember
- */
- var CoreObject = makeCtor();
- CoreObject.toString = function() { return "Ember.CoreObject"; };
- CoreObject.PrototypeMixin = Mixin.create({
- reopen: function() {
- var length = arguments.length;
- var args = new Array(length);
- for (var i = 0; i < length; i++) {
- args[i] = arguments[i];
- }
- applyMixin(this, args, true);
- return this;
- },
-
- /**
- An overridable method called when objects are instantiated. By default,
- does nothing unless it is overridden during class definition.
-
- Example:
-
- ```javascript
- App.Person = Ember.Object.extend({
- init: function() {
- alert('Name is ' + this.get('name'));
- }
- });
-
- var steve = App.Person.create({
- name: "Steve"
- });
-
- // alerts 'Name is Steve'.
- ```
-
- NOTE: If you do override `init` for a framework class like `Ember.View` or
- `Ember.ArrayController`, be sure to call `this._super()` in your
- `init` declaration! If you don't, Ember may not have an opportunity to
- do important setup work, and you'll see strange behavior in your
- application.
-
- @method init
- */
- init: function() {},
-
- /**
- Defines the properties that will be concatenated from the superclass
- (instead of overridden).
-
- By default, when you extend an Ember class a property defined in
- the subclass overrides a property with the same name that is defined
- in the superclass. However, there are some cases where it is preferable
- to build up a property's value by combining the superclass' property
- value with the subclass' value. An example of this in use within Ember
- is the `classNames` property of `Ember.View`.
-
- Here is some sample code showing the difference between a concatenated
- property and a normal one:
-
- ```javascript
- App.BarView = Ember.View.extend({
- someNonConcatenatedProperty: ['bar'],
- classNames: ['bar']
- });
-
- App.FooBarView = App.BarView.extend({
- someNonConcatenatedProperty: ['foo'],
- classNames: ['foo']
- });
-
- var fooBarView = App.FooBarView.create();
- fooBarView.get('someNonConcatenatedProperty'); // ['foo']
- fooBarView.get('classNames'); // ['ember-view', 'bar', 'foo']
- ```
-
- This behavior extends to object creation as well. Continuing the
- above example:
-
- ```javascript
- var view = App.FooBarView.create({
- someNonConcatenatedProperty: ['baz'],
- classNames: ['baz']
- })
- view.get('someNonConcatenatedProperty'); // ['baz']
- view.get('classNames'); // ['ember-view', 'bar', 'foo', 'baz']
- ```
- Adding a single property that is not an array will just add it in the array:
-
- ```javascript
- var view = App.FooBarView.create({
- classNames: 'baz'
- })
- view.get('classNames'); // ['ember-view', 'bar', 'foo', 'baz']
- ```
-
- Using the `concatenatedProperties` property, we can tell to Ember that mix
- the content of the properties.
-
- In `Ember.View` the `classNameBindings` and `attributeBindings` properties
- are also concatenated, in addition to `classNames`.
-
- This feature is available for you to use throughout the Ember object model,
- although typical app developers are likely to use it infrequently. Since
- it changes expectations about behavior of properties, you should properly
- document its usage in each individual concatenated property (to not
- mislead your users to think they can override the property in a subclass).
-
- @property concatenatedProperties
- @type Array
- @default null
- */
- concatenatedProperties: null,
-
- /**
- Destroyed object property flag.
-
- if this property is `true` the observers and bindings were already
- removed by the effect of calling the `destroy()` method.
-
- @property isDestroyed
- @default false
- */
- isDestroyed: false,
-
- /**
- Destruction scheduled flag. The `destroy()` method has been called.
-
- The object stays intact until the end of the run loop at which point
- the `isDestroyed` flag is set.
-
- @property isDestroying
- @default false
- */
- isDestroying: false,
-
- /**
- Destroys an object by setting the `isDestroyed` flag and removing its
- metadata, which effectively destroys observers and bindings.
-
- If you try to set a property on a destroyed object, an exception will be
- raised.
-
- Note that destruction is scheduled for the end of the run loop and does not
- happen immediately. It will set an isDestroying flag immediately.
-
- @method destroy
- @return {Ember.Object} receiver
- */
- destroy: function() {
- if (this.isDestroying) { return; }
- this.isDestroying = true;
-
- schedule('actions', this, this.willDestroy);
- schedule('destroy', this, this._scheduledDestroy);
- return this;
- },
-
- /**
- Override to implement teardown.
-
- @method willDestroy
- */
- willDestroy: K,
-
- /**
- Invoked by the run loop to actually destroy the object. This is
- scheduled for execution by the `destroy` method.
-
- @private
- @method _scheduledDestroy
- */
- _scheduledDestroy: function() {
- if (this.isDestroyed) { return; }
- destroy(this);
- this.isDestroyed = true;
- },
-
- bind: function(to, from) {
- if (!(from instanceof Binding)) { from = Binding.from(from); }
- from.to(to).connect(this);
- return from;
- },
-
- /**
- Returns a string representation which attempts to provide more information
- than Javascript's `toString` typically does, in a generic way for all Ember
- objects.
-
- ```javascript
- App.Person = Em.Object.extend()
- person = App.Person.create()
- person.toString() //=> "<App.Person:ember1024>"
- ```
-
- If the object's class is not defined on an Ember namespace, it will
- indicate it is a subclass of the registered superclass:
-
- ```javascript
- Student = App.Person.extend()
- student = Student.create()
- student.toString() //=> "<(subclass of App.Person):ember1025>"
- ```
-
- If the method `toStringExtension` is defined, its return value will be
- included in the output.
-
- ```javascript
- App.Teacher = App.Person.extend({
- toStringExtension: function() {
- return this.get('fullName');
- }
- });
- teacher = App.Teacher.create()
- teacher.toString(); //=> "<App.Teacher:ember1026:Tom Dale>"
- ```
-
- @method toString
- @return {String} string representation
- */
- toString: function toString() {
- var hasToStringExtension = typeof this.toStringExtension === 'function';
- var extension = hasToStringExtension ? ":" + this.toStringExtension() : '';
- var ret = '<'+this.constructor.toString()+':'+guidFor(this)+extension+'>';
-
- this.toString = makeToString(ret);
- return ret;
- }
- });
-
- CoreObject.PrototypeMixin.ownerConstructor = CoreObject;
-
- function makeToString(ret) {
- return function() { return ret; };
- }
-
- if (Ember.config.overridePrototypeMixin) {
- Ember.config.overridePrototypeMixin(CoreObject.PrototypeMixin);
- }
-
- CoreObject.__super__ = null;
-
- var ClassMixinProps = {
-
- ClassMixin: required(),
-
- PrototypeMixin: required(),
-
- isClass: true,
-
- isMethod: false,
-
- /**
- Creates a new subclass.
-
- ```javascript
- App.Person = Ember.Object.extend({
- say: function(thing) {
- alert(thing);
- }
- });
- ```
-
- This defines a new subclass of Ember.Object: `App.Person`. It contains one method: `say()`.
-
- You can also create a subclass from any existing class by calling its `extend()` method. For example, you might want to create a subclass of Ember's built-in `Ember.View` class:
-
- ```javascript
- App.PersonView = Ember.View.extend({
- tagName: 'li',
- classNameBindings: ['isAdministrator']
- });
- ```
-
- When defining a subclass, you can override methods but still access the implementation of your parent class by calling the special `_super()` method:
-
- ```javascript
- App.Person = Ember.Object.extend({
- say: function(thing) {
- var name = this.get('name');
- alert(name + ' says: ' + thing);
- }
- });
-
- App.Soldier = App.Person.extend({
- say: function(thing) {
- this._super(thing + ", sir!");
- },
- march: function(numberOfHours) {
- alert(this.get('name') + ' marches for ' + numberOfHours + ' hours.')
- }
- });
-
- var yehuda = App.Soldier.create({
- name: "Yehuda Katz"
- });
-
- yehuda.say("Yes"); // alerts "Yehuda Katz says: Yes, sir!"
- ```
-
- The `create()` on line #17 creates an *instance* of the `App.Soldier` class. The `extend()` on line #8 creates a *subclass* of `App.Person`. Any instance of the `App.Person` class will *not* have the `march()` method.
-
- You can also pass `Mixin` classes to add additional properties to the subclass.
-
- ```javascript
- App.Person = Ember.Object.extend({
- say: function(thing) {
- alert(this.get('name') + ' says: ' + thing);
- }
- });
-
- App.SingingMixin = Mixin.create({
- sing: function(thing){
- alert(this.get('name') + ' sings: la la la ' + thing);
- }
- });
-
- App.BroadwayStar = App.Person.extend(App.SingingMixin, {
- dance: function() {
- alert(this.get('name') + ' dances: tap tap tap tap ');
- }
- });
- ```
-
- The `App.BroadwayStar` class contains three methods: `say()`, `sing()`, and `dance()`.
-
- @method extend
- @static
-
- @param {Mixin} [mixins]* One or more Mixin classes
- @param {Object} [arguments]* Object containing values to use within the new class
- */
- extend: function extend() {
- var Class = makeCtor();
- var proto;
- Class.ClassMixin = Mixin.create(this.ClassMixin);
- Class.PrototypeMixin = Mixin.create(this.PrototypeMixin);
-
- Class.ClassMixin.ownerConstructor = Class;
- Class.PrototypeMixin.ownerConstructor = Class;
-
- reopen.apply(Class.PrototypeMixin, arguments);
-
- Class.superclass = this;
- Class.__super__ = this.prototype;
-
- proto = Class.prototype = o_create(this.prototype);
- proto.constructor = Class;
- generateGuid(proto);
- meta(proto).proto = proto; // this will disable observers on prototype
-
- Class.ClassMixin.apply(Class);
- return Class;
- },
-
- /**
- Equivalent to doing `extend(arguments).create()`.
- If possible use the normal `create` method instead.
-
- @method createWithMixins
- @static
- @param [arguments]*
- */
- createWithMixins: function() {
- var C = this;
- var l= arguments.length;
- if (l > 0) {
- var args = new Array(l);
- for (var i = 0; i < l; i++) {
- args[i] = arguments[i];
- }
- this._initMixins(args);
- }
- return new C();
- },
-
- /**
- Creates an instance of a class. Accepts either no arguments, or an object
- containing values to initialize the newly instantiated object with.
-
- ```javascript
- App.Person = Ember.Object.extend({
- helloWorld: function() {
- alert("Hi, my name is " + this.get('name'));
- }
- });
-
- var tom = App.Person.create({
- name: 'Tom Dale'
- });
-
- tom.helloWorld(); // alerts "Hi, my name is Tom Dale".
- ```
-
- `create` will call the `init` function if defined during
- `Ember.AnyObject.extend`
-
- If no arguments are passed to `create`, it will not set values to the new
- instance during initialization:
-
- ```javascript
- var noName = App.Person.create();
- noName.helloWorld(); // alerts undefined
- ```
-
- NOTE: For performance reasons, you cannot declare methods or computed
- properties during `create`. You should instead declare methods and computed
- properties when using `extend` or use the `createWithMixins` shorthand.
-
- @method create
- @static
- @param [arguments]*
- */
- create: function() {
- var C = this;
- var l = arguments.length;
- if (l > 0) {
- var args = new Array(l);
- for (var i = 0; i < l; i++) {
- args[i] = arguments[i];
- }
- this._initProperties(args);
- }
- return new C();
- },
-
- /**
- Augments a constructor's prototype with additional
- properties and functions:
-
- ```javascript
- MyObject = Ember.Object.extend({
- name: 'an object'
- });
-
- o = MyObject.create();
- o.get('name'); // 'an object'
-
- MyObject.reopen({
- say: function(msg){
- console.log(msg);
- }
- })
-
- o2 = MyObject.create();
- o2.say("hello"); // logs "hello"
-
- o.say("goodbye"); // logs "goodbye"
- ```
-
- To add functions and properties to the constructor itself,
- see `reopenClass`
-
- @method reopen
- */
- reopen: function() {
- this.willReopen();
-
- var l = arguments.length;
- var args = new Array(l);
- if (l > 0) {
- for (var i = 0; i < l; i++) {
- args[i] = arguments[i];
- }
- }
-
- apply(this.PrototypeMixin, reopen, args);
- return this;
- },
-
- /**
- Augments a constructor's own properties and functions:
-
- ```javascript
- MyObject = Ember.Object.extend({
- name: 'an object'
- });
-
- MyObject.reopenClass({
- canBuild: false
- });
-
- MyObject.canBuild; // false
- o = MyObject.create();
- ```
-
- In other words, this creates static properties and functions for the class. These are only available on the class
- and not on any instance of that class.
-
- ```javascript
- App.Person = Ember.Object.extend({
- name : "",
- sayHello : function(){
- alert("Hello. My name is " + this.get('name'));
- }
- });
-
- App.Person.reopenClass({
- species : "Homo sapiens",
- createPerson: function(newPersonsName){
- return App.Person.create({
- name:newPersonsName
- });
- }
- });
-
- var tom = App.Person.create({
- name : "Tom Dale"
- });
- var yehuda = App.Person.createPerson("Yehuda Katz");
-
- tom.sayHello(); // "Hello. My name is Tom Dale"
- yehuda.sayHello(); // "Hello. My name is Yehuda Katz"
- alert(App.Person.species); // "Homo sapiens"
- ```
-
- Note that `species` and `createPerson` are *not* valid on the `tom` and `yehuda`
- variables. They are only valid on `App.Person`.
-
- To add functions and properties to instances of
- a constructor by extending the constructor's prototype
- see `reopen`
-
- @method reopenClass
- */
- reopenClass: function() {
- var l = arguments.length;
- var args = new Array(l);
- if (l > 0) {
- for (var i = 0; i < l; i++) {
- args[i] = arguments[i];
- }
- }
-
- apply(this.ClassMixin, reopen, args);
- applyMixin(this, arguments, false);
- return this;
- },
-
- detect: function(obj) {
- if ('function' !== typeof obj) { return false; }
- while(obj) {
- if (obj===this) { return true; }
- obj = obj.superclass;
- }
- return false;
- },
-
- detectInstance: function(obj) {
- return obj instanceof this;
- },
-
- /**
- In some cases, you may want to annotate computed properties with additional
- metadata about how they function or what values they operate on. For
- example, computed property functions may close over variables that are then
- no longer available for introspection.
-
- You can pass a hash of these values to a computed property like this:
-
- ```javascript
- person: function() {
- var personId = this.get('personId');
- return App.Person.create({ id: personId });
- }.property().meta({ type: App.Person })
- ```
-
- Once you've done this, you can retrieve the values saved to the computed
- property from your class like this:
-
- ```javascript
- MyClass.metaForProperty('person');
- ```
-
- This will return the original hash that was passed to `meta()`.
-
- @method metaForProperty
- @param key {String} property name
- */
- metaForProperty: function(key) {
- var meta = this.proto()['__ember_meta__'];
- var desc = meta && meta.descs[key];
-
- Ember.assert("metaForProperty() could not find a computed property with key '"+key+"'.", !!desc && desc instanceof ComputedProperty);
- return desc._meta || {};
- },
-
- _computedProperties: computed(function() {
- hasCachedComputedProperties = true;
- var proto = this.proto();
- var descs = meta(proto).descs;
- var property;
- var properties = [];
-
- for (var name in descs) {
- property = descs[name];
-
- if (property instanceof ComputedProperty) {
- properties.push({
- name: name,
- meta: property._meta
- });
- }
- }
- return properties;
- }).readOnly(),
-
- /**
- Iterate over each computed property for the class, passing its name
- and any associated metadata (see `metaForProperty`) to the callback.
-
- @method eachComputedProperty
- @param {Function} callback
- @param {Object} binding
- */
- eachComputedProperty: function(callback, binding) {
- var property, name;
- var empty = {};
-
- var properties = get(this, '_computedProperties');
-
- for (var i = 0, length = properties.length; i < length; i++) {
- property = properties[i];
- name = property.name;
- callback.call(binding || this, property.name, property.meta || empty);
- }
- }
- };
-
-
- var ClassMixin = Mixin.create(ClassMixinProps);
-
- ClassMixin.ownerConstructor = CoreObject;
-
- if (Ember.config.overrideClassMixin) {
- Ember.config.overrideClassMixin(ClassMixin);
- }
-
- CoreObject.ClassMixin = ClassMixin;
-
- ClassMixin.apply(CoreObject);
-
- CoreObject.reopen({
- didDefineProperty: function(proto, key, value) {
- if (hasCachedComputedProperties === false) { return; }
- if (value instanceof Ember.ComputedProperty) {
- var cache = Ember.meta(this.constructor).cache;
-
- if (cache._computedProperties !== undefined) {
- cache._computedProperties = undefined;
- }
- }
- }
- });
-
- __exports__["default"] = CoreObject;
- });
-enifed("ember-runtime/system/deferred",
- ["ember-metal/core","ember-runtime/mixins/deferred","ember-runtime/system/object","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
- "use strict";
- var Ember = __dependency1__["default"];
- var DeferredMixin = __dependency2__["default"];
- var EmberObject = __dependency3__["default"];
-
- var Deferred = EmberObject.extend(DeferredMixin, {
- init: function() {
- Ember.deprecate('Usage of Ember.Deferred is deprecated.');
- this._super();
- }
- });
-
- Deferred.reopenClass({
- promise: function(callback, binding) {
- var deferred = Deferred.create();
- callback.call(binding, deferred);
- return deferred;
- }
- });
-
- __exports__["default"] = Deferred;
- });
-enifed("ember-runtime/system/each_proxy",
- ["ember-metal/core","ember-metal/property_get","ember-metal/utils","ember-metal/enumerable_utils","ember-metal/array","ember-runtime/mixins/array","ember-runtime/system/object","ember-metal/computed","ember-metal/observer","ember-metal/events","ember-metal/properties","ember-metal/property_events","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __exports__) {
- "use strict";
- /**
- @module ember
- @submodule ember-runtime
- */
-
- var Ember = __dependency1__["default"];
- // Ember.assert
-
- var get = __dependency2__.get;
- var guidFor = __dependency3__.guidFor;
- var forEach = __dependency4__.forEach;
- var indexOf = __dependency5__.indexOf;
- var EmberArray = __dependency6__["default"];
- // ES6TODO: WAT? Circular dep?
- var EmberObject = __dependency7__["default"];
- var computed = __dependency8__.computed;
- var addObserver = __dependency9__.addObserver;
- var addBeforeObserver = __dependency9__.addBeforeObserver;
- var removeBeforeObserver = __dependency9__.removeBeforeObserver;
- var removeObserver = __dependency9__.removeObserver;
- var typeOf = __dependency3__.typeOf;
- var watchedEvents = __dependency10__.watchedEvents;
- var defineProperty = __dependency11__.defineProperty;
- var beginPropertyChanges = __dependency12__.beginPropertyChanges;
- var propertyDidChange = __dependency12__.propertyDidChange;
- var propertyWillChange = __dependency12__.propertyWillChange;
- var endPropertyChanges = __dependency12__.endPropertyChanges;
- var changeProperties = __dependency12__.changeProperties;
-
- var EachArray = EmberObject.extend(EmberArray, {
-
- init: function(content, keyName, owner) {
- this._super();
- this._keyName = keyName;
- this._owner = owner;
- this._content = content;
- },
-
- objectAt: function(idx) {
- var item = this._content.objectAt(idx);
- return item && get(item, this._keyName);
- },
-
- length: computed(function() {
- var content = this._content;
- return content ? get(content, 'length') : 0;
- })
-
- });
-
- var IS_OBSERVER = /^.+:(before|change)$/;
-
- function addObserverForContentKey(content, keyName, proxy, idx, loc) {
- var objects = proxy._objects;
- var guid;
- if (!objects) objects = proxy._objects = {};
-
- while(--loc>=idx) {
- var item = content.objectAt(loc);
- if (item) {
- Ember.assert('When using @each to observe the array ' + content + ', the array must return an object', typeOf(item) === 'instance' || typeOf(item) === 'object');
- addBeforeObserver(item, keyName, proxy, 'contentKeyWillChange');
- addObserver(item, keyName, proxy, 'contentKeyDidChange');
-
- // keep track of the index each item was found at so we can map
- // it back when the obj changes.
- guid = guidFor(item);
- if (!objects[guid]) objects[guid] = [];
- objects[guid].push(loc);
- }
- }
- }
-
- function removeObserverForContentKey(content, keyName, proxy, idx, loc) {
- var objects = proxy._objects;
- if (!objects) objects = proxy._objects = {};
- var indicies, guid;
-
- while(--loc>=idx) {
- var item = content.objectAt(loc);
- if (item) {
- removeBeforeObserver(item, keyName, proxy, 'contentKeyWillChange');
- removeObserver(item, keyName, proxy, 'contentKeyDidChange');
-
- guid = guidFor(item);
- indicies = objects[guid];
- indicies[indexOf.call(indicies, loc)] = null;
- }
- }
- }
-
- /**
- This is the object instance returned when you get the `@each` property on an
- array. It uses the unknownProperty handler to automatically create
- EachArray instances for property names.
-
- @private
- @class EachProxy
- @namespace Ember
- @extends Ember.Object
- */
- var EachProxy = EmberObject.extend({
-
- init: function(content) {
- this._super();
- this._content = content;
- content.addArrayObserver(this);
-
- // in case someone is already observing some keys make sure they are
- // added
- forEach(watchedEvents(this), function(eventName) {
- this.didAddListener(eventName);
- }, this);
- },
-
- /**
- You can directly access mapped properties by simply requesting them.
- The `unknownProperty` handler will generate an EachArray of each item.
-
- @method unknownProperty
- @param keyName {String}
- @param value {*}
- */
- unknownProperty: function(keyName, value) {
- var ret;
- ret = new EachArray(this._content, keyName, this);
- defineProperty(this, keyName, null, ret);
- this.beginObservingContentKey(keyName);
- return ret;
- },
-
- // ..........................................................
- // ARRAY CHANGES
- // Invokes whenever the content array itself changes.
-
- arrayWillChange: function(content, idx, removedCnt, addedCnt) {
- var keys = this._keys;
- var key, lim;
-
- lim = removedCnt>0 ? idx+removedCnt : -1;
- beginPropertyChanges(this);
-
- for(key in keys) {
- if (!keys.hasOwnProperty(key)) { continue; }
-
- if (lim>0) { removeObserverForContentKey(content, key, this, idx, lim); }
-
- propertyWillChange(this, key);
- }
-
- propertyWillChange(this._content, '@each');
- endPropertyChanges(this);
- },
-
- arrayDidChange: function(content, idx, removedCnt, addedCnt) {
- var keys = this._keys;
- var lim;
-
- lim = addedCnt>0 ? idx+addedCnt : -1;
- changeProperties(function() {
- for(var key in keys) {
- if (!keys.hasOwnProperty(key)) { continue; }
-
- if (lim>0) { addObserverForContentKey(content, key, this, idx, lim); }
-
- propertyDidChange(this, key);
- }
-
- propertyDidChange(this._content, '@each');
- }, this);
- },
-
- // ..........................................................
- // LISTEN FOR NEW OBSERVERS AND OTHER EVENT LISTENERS
- // Start monitoring keys based on who is listening...
-
- didAddListener: function(eventName) {
- if (IS_OBSERVER.test(eventName)) {
- this.beginObservingContentKey(eventName.slice(0, -7));
- }
- },
-
- didRemoveListener: function(eventName) {
- if (IS_OBSERVER.test(eventName)) {
- this.stopObservingContentKey(eventName.slice(0, -7));
- }
- },
-
- // ..........................................................
- // CONTENT KEY OBSERVING
- // Actual watch keys on the source content.
-
- beginObservingContentKey: function(keyName) {
- var keys = this._keys;
- if (!keys) keys = this._keys = {};
- if (!keys[keyName]) {
- keys[keyName] = 1;
- var content = this._content;
- var len = get(content, 'length');
-
- addObserverForContentKey(content, keyName, this, 0, len);
- } else {
- keys[keyName]++;
- }
- },
-
- stopObservingContentKey: function(keyName) {
- var keys = this._keys;
- if (keys && (keys[keyName]>0) && (--keys[keyName]<=0)) {
- var content = this._content;
- var len = get(content, 'length');
-
- removeObserverForContentKey(content, keyName, this, 0, len);
- }
- },
-
- contentKeyWillChange: function(obj, keyName) {
- propertyWillChange(this, keyName);
- },
-
- contentKeyDidChange: function(obj, keyName) {
- propertyDidChange(this, keyName);
- }
- });
-
- __exports__.EachArray = EachArray;
- __exports__.EachProxy = EachProxy;
- });
-enifed("ember-runtime/system/lazy_load",
- ["ember-metal/core","ember-metal/array","ember-runtime/system/native_array","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
- "use strict";
- /*globals CustomEvent */
-
- var Ember = __dependency1__["default"];
- // Ember.ENV.EMBER_LOAD_HOOKS
- var forEach = __dependency2__.forEach;
- // make sure Ember.A is setup.
-
- /**
- @module ember
- @submodule ember-runtime
- */
-
- var loadHooks = Ember.ENV.EMBER_LOAD_HOOKS || {};
- var loaded = {};
-
- /**
- Detects when a specific package of Ember (e.g. 'Ember.Handlebars')
- has fully loaded and is available for extension.
-
- The provided `callback` will be called with the `name` passed
- resolved from a string into the object:
-
- ``` javascript
- Ember.onLoad('Ember.Handlebars' function(hbars) {
- hbars.registerHelper(...);
- });
- ```
-
- @method onLoad
- @for Ember
- @param name {String} name of hook
- @param callback {Function} callback to be called
- */
- function onLoad(name, callback) {
- var object;
-
- loadHooks[name] = loadHooks[name] || Ember.A();
- loadHooks[name].pushObject(callback);
-
- if (object = loaded[name]) {
- callback(object);
- }
- }
-
- __exports__.onLoad = onLoad;/**
- Called when an Ember.js package (e.g Ember.Handlebars) has finished
- loading. Triggers any callbacks registered for this event.
-
- @method runLoadHooks
- @for Ember
- @param name {String} name of hook
- @param object {Object} object to pass to callbacks
- */
- function runLoadHooks(name, object) {
- loaded[name] = object;
-
- if (typeof window === 'object' && typeof window.dispatchEvent === 'function' && typeof CustomEvent === "function") {
- var event = new CustomEvent(name, {detail: object, name: name});
- window.dispatchEvent(event);
- }
-
- if (loadHooks[name]) {
- forEach.call(loadHooks[name], function(callback) {
- callback(object);
- });
- }
- }
-
- __exports__.runLoadHooks = runLoadHooks;
- });
-enifed("ember-runtime/system/namespace",
- ["ember-metal/core","ember-metal/property_get","ember-metal/array","ember-metal/utils","ember-metal/mixin","ember-runtime/system/object","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __exports__) {
- "use strict";
- /**
- @module ember
- @submodule ember-runtime
- */
-
- // Ember.lookup, Ember.BOOTED, Ember.deprecate, Ember.NAME_KEY, Ember.anyUnprocessedMixins
- var Ember = __dependency1__["default"];
- var get = __dependency2__.get;
- var indexOf = __dependency3__.indexOf;
- var GUID_KEY = __dependency4__.GUID_KEY;
- var guidFor = __dependency4__.guidFor;
- var Mixin = __dependency5__.Mixin;
-
- var EmberObject = __dependency6__["default"];
-
- /**
- A Namespace is an object usually used to contain other objects or methods
- such as an application or framework. Create a namespace anytime you want
- to define one of these new containers.
-
- # Example Usage
-
- ```javascript
- MyFramework = Ember.Namespace.create({
- VERSION: '1.0.0'
- });
- ```
-
- @class Namespace
- @namespace Ember
- @extends Ember.Object
- */
- var Namespace = EmberObject.extend({
- isNamespace: true,
-
- init: function() {
- Namespace.NAMESPACES.push(this);
- Namespace.PROCESSED = false;
- },
-
- toString: function() {
- var name = get(this, 'name') || get(this, 'modulePrefix');
- if (name) { return name; }
-
- findNamespaces();
- return this[NAME_KEY];
- },
-
- nameClasses: function() {
- processNamespace([this.toString()], this, {});
- },
-
- destroy: function() {
- var namespaces = Namespace.NAMESPACES;
- var toString = this.toString();
-
- if (toString) {
- Ember.lookup[toString] = undefined;
- delete Namespace.NAMESPACES_BY_ID[toString];
- }
- namespaces.splice(indexOf.call(namespaces, this), 1);
- this._super();
- }
- });
-
- Namespace.reopenClass({
- NAMESPACES: [Ember],
- NAMESPACES_BY_ID: {},
- PROCESSED: false,
- processAll: processAllNamespaces,
- byName: function(name) {
- if (!Ember.BOOTED) {
- processAllNamespaces();
- }
-
- return NAMESPACES_BY_ID[name];
- }
- });
-
- var NAMESPACES_BY_ID = Namespace.NAMESPACES_BY_ID;
-
- var hasOwnProp = ({}).hasOwnProperty;
-
- function processNamespace(paths, root, seen) {
- var idx = paths.length;
-
- NAMESPACES_BY_ID[paths.join('.')] = root;
-
- // Loop over all of the keys in the namespace, looking for classes
- for(var key in root) {
- if (!hasOwnProp.call(root, key)) { continue; }
- var obj = root[key];
-
- // If we are processing the `Ember` namespace, for example, the
- // `paths` will start with `["Ember"]`. Every iteration through
- // the loop will update the **second** element of this list with
- // the key, so processing `Ember.View` will make the Array
- // `['Ember', 'View']`.
- paths[idx] = key;
-
- // If we have found an unprocessed class
- if (obj && obj.toString === classToString) {
- // Replace the class' `toString` with the dot-separated path
- // and set its `NAME_KEY`
- obj.toString = makeToString(paths.join('.'));
- obj[NAME_KEY] = paths.join('.');
-
- // Support nested namespaces
- } else if (obj && obj.isNamespace) {
- // Skip aliased namespaces
- if (seen[guidFor(obj)]) { continue; }
- seen[guidFor(obj)] = true;
-
- // Process the child namespace
- processNamespace(paths, obj, seen);
- }
- }
-
- paths.length = idx; // cut out last item
- }
-
- var STARTS_WITH_UPPERCASE = /^[A-Z]/;
-
- function tryIsNamespace(lookup, prop) {
- try {
- var obj = lookup[prop];
- return obj && obj.isNamespace && obj;
- } catch (e) {
- // continue
- }
- }
-
- function findNamespaces() {
- var lookup = Ember.lookup;
- var obj;
-
- if (Namespace.PROCESSED) { return; }
-
- for (var prop in lookup) {
- // Only process entities that start with uppercase A-Z
- if (!STARTS_WITH_UPPERCASE.test(prop)) { continue; }
-
- // Unfortunately, some versions of IE don't support window.hasOwnProperty
- if (lookup.hasOwnProperty && !lookup.hasOwnProperty(prop)) { continue; }
-
- // At times we are not allowed to access certain properties for security reasons.
- // There are also times where even if we can access them, we are not allowed to access their properties.
- obj = tryIsNamespace(lookup, prop);
- if (obj) {
- obj[NAME_KEY] = prop;
- }
- }
- }
-
- var NAME_KEY = Ember.NAME_KEY = GUID_KEY + '_name';
-
- function superClassString(mixin) {
- var superclass = mixin.superclass;
- if (superclass) {
- if (superclass[NAME_KEY]) { return superclass[NAME_KEY]; }
- else { return superClassString(superclass); }
- } else {
- return;
- }
- }
-
- function classToString() {
- if (!Ember.BOOTED && !this[NAME_KEY]) {
- processAllNamespaces();
- }
-
- var ret;
-
- if (this[NAME_KEY]) {
- ret = this[NAME_KEY];
- } else if (this._toString) {
- ret = this._toString;
- } else {
- var str = superClassString(this);
- if (str) {
- ret = "(subclass of " + str + ")";
- } else {
- ret = "(unknown mixin)";
- }
- this.toString = makeToString(ret);
- }
-
- return ret;
- }
-
- function processAllNamespaces() {
- var unprocessedNamespaces = !Namespace.PROCESSED;
- var unprocessedMixins = Ember.anyUnprocessedMixins;
-
- if (unprocessedNamespaces) {
- findNamespaces();
- Namespace.PROCESSED = true;
- }
-
- if (unprocessedNamespaces || unprocessedMixins) {
- var namespaces = Namespace.NAMESPACES;
- var namespace;
-
- for (var i=0, l=namespaces.length; i<l; i++) {
- namespace = namespaces[i];
- processNamespace([namespace.toString()], namespace, {});
- }
-
- Ember.anyUnprocessedMixins = false;
- }
- }
-
- function makeToString(ret) {
- return function() { return ret; };
- }
-
- Mixin.prototype.toString = classToString; // ES6TODO: altering imported objects. SBB.
-
- __exports__["default"] = Namespace;
- });
-enifed("ember-runtime/system/native_array",
- ["ember-metal/core","ember-metal/property_get","ember-metal/enumerable_utils","ember-metal/mixin","ember-metal/array","ember-runtime/mixins/array","ember-runtime/mixins/mutable_array","ember-runtime/mixins/observable","ember-runtime/mixins/copyable","ember-runtime/mixins/freezable","ember-runtime/copy","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __exports__) {
- "use strict";
- /**
- @module ember
- @submodule ember-runtime
- */
-
- var Ember = __dependency1__["default"];
- // Ember.EXTEND_PROTOTYPES
-
- var get = __dependency2__.get;
- var replace = __dependency3__._replace;
- var forEach = __dependency3__.forEach;
- var Mixin = __dependency4__.Mixin;
- var indexOf = __dependency5__.indexOf;
- var lastIndexOf = __dependency5__.lastIndexOf;
- var EmberArray = __dependency6__["default"];
- var MutableArray = __dependency7__["default"];
- var Observable = __dependency8__["default"];
- var Copyable = __dependency9__["default"];
- var FROZEN_ERROR = __dependency10__.FROZEN_ERROR;
- var copy = __dependency11__["default"];
-
- // Add Ember.Array to Array.prototype. Remove methods with native
- // implementations and supply some more optimized versions of generic methods
- // because they are so common.
-
- /**
- The NativeArray mixin contains the properties needed to to make the native
- Array support Ember.MutableArray and all of its dependent APIs. Unless you
- have `Ember.EXTEND_PROTOTYPES` or `Ember.EXTEND_PROTOTYPES.Array` set to
- false, this will be applied automatically. Otherwise you can apply the mixin
- at anytime by calling `Ember.NativeArray.activate`.
-
- @class NativeArray
- @namespace Ember
- @uses Ember.MutableArray
- @uses Ember.Observable
- @uses Ember.Copyable
- */
- var NativeArray = Mixin.create(MutableArray, Observable, Copyable, {
-
- // because length is a built-in property we need to know to just get the
- // original property.
- get: function(key) {
- if (key==='length') return this.length;
- else if ('number' === typeof key) return this[key];
- else return this._super(key);
- },
-
- objectAt: function(idx) {
- return this[idx];
- },
-
- // primitive for array support.
- replace: function(idx, amt, objects) {
-
- if (this.isFrozen) throw FROZEN_ERROR;
-
- // if we replaced exactly the same number of items, then pass only the
- // replaced range. Otherwise, pass the full remaining array length
- // since everything has shifted
- var len = objects ? get(objects, 'length') : 0;
- this.arrayContentWillChange(idx, amt, len);
-
- if (len === 0) {
- this.splice(idx, amt);
- } else {
- replace(this, idx, amt, objects);
- }
-
- this.arrayContentDidChange(idx, amt, len);
- return this;
- },
-
- // If you ask for an unknown property, then try to collect the value
- // from member items.
- unknownProperty: function(key, value) {
- var ret;// = this.reducedProperty(key, value) ;
- if (value !== undefined && ret === undefined) {
- ret = this[key] = value;
- }
- return ret;
- },
-
- indexOf: indexOf,
-
- lastIndexOf: lastIndexOf,
-
- copy: function(deep) {
- if (deep) {
- return this.map(function(item) { return copy(item, true); });
- }
-
- return this.slice();
- }
- });
-
- // Remove any methods implemented natively so we don't override them
- var ignore = ['length'];
- forEach(NativeArray.keys(), function(methodName) {
- if (Array.prototype[methodName]) ignore.push(methodName);
- });
-
- if (ignore.length > 0) {
- NativeArray = NativeArray.without.apply(NativeArray, ignore);
- }
-
- /**
- Creates an `Ember.NativeArray` from an Array like object.
- Does not modify the original object. Ember.A is not needed if
- `Ember.EXTEND_PROTOTYPES` is `true` (the default value). However,
- it is recommended that you use Ember.A when creating addons for
- ember or when you can not guarantee that `Ember.EXTEND_PROTOTYPES`
- will be `true`.
-
- Example
-
- ```js
- var Pagination = Ember.CollectionView.extend({
- tagName: 'ul',
- classNames: ['pagination'],
-
- init: function() {
- this._super();
- if (!this.get('content')) {
- this.set('content', Ember.A());
- }
- }
- });
- ```
-
- @method A
- @for Ember
- @return {Ember.NativeArray}
- */
- var A = function(arr) {
- if (arr === undefined) { arr = []; }
- return EmberArray.detect(arr) ? arr : NativeArray.apply(arr);
- };
-
- /**
- Activates the mixin on the Array.prototype if not already applied. Calling
- this method more than once is safe. This will be called when ember is loaded
- unless you have `Ember.EXTEND_PROTOTYPES` or `Ember.EXTEND_PROTOTYPES.Array`
- set to `false`.
-
- Example
-
- ```js
- if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.Array) {
- Ember.NativeArray.activate();
- }
- ```
-
- @method activate
- @for Ember.NativeArray
- @static
- @return {void}
- */
- NativeArray.activate = function() {
- NativeArray.apply(Array.prototype);
-
- A = function(arr) { return arr || []; };
- };
-
- if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.Array) {
- NativeArray.activate();
- }
-
- Ember.A = A; // ES6TODO: Setting A onto the object returned by ember-metal/core to avoid circles
- __exports__.A = A;
- __exports__.NativeArray = NativeArray;
- __exports__["default"] = NativeArray;
- });
-enifed("ember-runtime/system/object",
- ["ember-metal/core","ember-runtime/system/core_object","ember-runtime/mixins/observable","ember-runtime/inject","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
- "use strict";
- /**
- @module ember
- @submodule ember-runtime
- */
-
- var Ember = __dependency1__["default"];
- // Ember.assert
- var CoreObject = __dependency2__["default"];
- var Observable = __dependency3__["default"];
- var validatePropertyInjections = __dependency4__.validatePropertyInjections;
-
- /**
- `Ember.Object` is the main base class for all Ember objects. It is a subclass
- of `Ember.CoreObject` with the `Ember.Observable` mixin applied. For details,
- see the documentation for each of these.
-
- @class Object
- @namespace Ember
- @extends Ember.CoreObject
- @uses Ember.Observable
- */
- var EmberObject = CoreObject.extend(Observable);
- EmberObject.toString = function() {
- return "Ember.Object";
- };
-
- function injectedPropertyAssertion(props) {
- // Injection validations are a debugging aid only, so ensure that they are
- // not performed in production builds by invoking from an assertion
- Ember.assert("Injected properties are invalid", validatePropertyInjections(this.constructor, props));
- }
-
-
- __exports__["default"] = EmberObject;
- });
-enifed("ember-runtime/system/object_proxy",
- ["ember-runtime/system/object","ember-runtime/mixins/-proxy","exports"],
- function(__dependency1__, __dependency2__, __exports__) {
- "use strict";
- var EmberObject = __dependency1__["default"];
- var _ProxyMixin = __dependency2__["default"];
-
- /**
- `Ember.ObjectProxy` forwards all properties not defined by the proxy itself
- to a proxied `content` object.
-
- ```javascript
- object = Ember.Object.create({
- name: 'Foo'
- });
-
- proxy = Ember.ObjectProxy.create({
- content: object
- });
-
- // Access and change existing properties
- proxy.get('name') // 'Foo'
- proxy.set('name', 'Bar');
- object.get('name') // 'Bar'
-
- // Create new 'description' property on `object`
- proxy.set('description', 'Foo is a whizboo baz');
- object.get('description') // 'Foo is a whizboo baz'
- ```
-
- While `content` is unset, setting a property to be delegated will throw an
- Error.
-
- ```javascript
- proxy = Ember.ObjectProxy.create({
- content: null,
- flag: null
- });
- proxy.set('flag', true);
- proxy.get('flag'); // true
- proxy.get('foo'); // undefined
- proxy.set('foo', 'data'); // throws Error
- ```
-
- Delegated properties can be bound to and will change when content is updated.
-
- Computed properties on the proxy itself can depend on delegated properties.
-
- ```javascript
- ProxyWithComputedProperty = Ember.ObjectProxy.extend({
- fullName: function () {
- var firstName = this.get('firstName'),
- lastName = this.get('lastName');
- if (firstName && lastName) {
- return firstName + ' ' + lastName;
- }
- return firstName || lastName;
- }.property('firstName', 'lastName')
- });
-
- proxy = ProxyWithComputedProperty.create();
-
- proxy.get('fullName'); // undefined
- proxy.set('content', {
- firstName: 'Tom', lastName: 'Dale'
- }); // triggers property change for fullName on proxy
-
- proxy.get('fullName'); // 'Tom Dale'
- ```
-
- @class ObjectProxy
- @namespace Ember
- @extends Ember.Object
- @extends Ember._ProxyMixin
- */
-
- __exports__["default"] = EmberObject.extend(_ProxyMixin);
- });
-enifed("ember-runtime/system/service",
- ["ember-runtime/system/object","ember-runtime/inject","exports"],
- function(__dependency1__, __dependency2__, __exports__) {
- "use strict";
- var Object = __dependency1__["default"];
- var createInjectionHelper = __dependency2__.createInjectionHelper;
-
- var Service;
-
-
- __exports__["default"] = Service;
- });
-enifed("ember-runtime/system/set",
- ["ember-metal/core","ember-metal/property_get","ember-metal/property_set","ember-metal/utils","ember-metal/is_none","ember-runtime/system/string","ember-runtime/system/core_object","ember-runtime/mixins/mutable_enumerable","ember-runtime/mixins/enumerable","ember-runtime/mixins/copyable","ember-runtime/mixins/freezable","ember-metal/error","ember-metal/property_events","ember-metal/mixin","ember-metal/computed","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __dependency15__, __exports__) {
- "use strict";
- /**
- @module ember
- @submodule ember-runtime
- */
- var Ember = __dependency1__["default"];
- // Ember.isNone, Ember.A
-
- var get = __dependency2__.get;
- var set = __dependency3__.set;
- var guidFor = __dependency4__.guidFor;
- var isNone = __dependency5__["default"];
- var fmt = __dependency6__.fmt;
- var CoreObject = __dependency7__["default"];
- var MutableEnumerable = __dependency8__["default"];
- var Enumerable = __dependency9__["default"];
- var Copyable = __dependency10__["default"];
- var Freezable = __dependency11__.Freezable;
- var FROZEN_ERROR = __dependency11__.FROZEN_ERROR;
- var EmberError = __dependency12__["default"];
- var propertyWillChange = __dependency13__.propertyWillChange;
- var propertyDidChange = __dependency13__.propertyDidChange;
- var aliasMethod = __dependency14__.aliasMethod;
- var computed = __dependency15__.computed;
-
- /**
- An unordered collection of objects.
-
- A Set works a bit like an array except that its items are not ordered. You
- can create a set to efficiently test for membership for an object. You can
- also iterate through a set just like an array, even accessing objects by
- index, however there is no guarantee as to their order.
-
- All Sets are observable via the Enumerable Observer API - which works
- on any enumerable object including both Sets and Arrays.
-
- ## Creating a Set
-
- You can create a set like you would most objects using
- `new Ember.Set()`. Most new sets you create will be empty, but you can
- also initialize the set with some content by passing an array or other
- enumerable of objects to the constructor.
-
- Finally, you can pass in an existing set and the set will be copied. You
- can also create a copy of a set by calling `Ember.Set#copy()`.
-
- ```javascript
- // creates a new empty set
- var foundNames = new Ember.Set();
-
- // creates a set with four names in it.
- var names = new Ember.Set(["Charles", "Tom", "Juan", "Alex"]); // :P
-
- // creates a copy of the names set.
- var namesCopy = new Ember.Set(names);
-
- // same as above.
- var anotherNamesCopy = names.copy();
- ```
-
- ## Adding/Removing Objects
-
- You generally add or remove objects from a set using `add()` or
- `remove()`. You can add any type of object including primitives such as
- numbers, strings, and booleans.
-
- Unlike arrays, objects can only exist one time in a set. If you call `add()`
- on a set with the same object multiple times, the object will only be added
- once. Likewise, calling `remove()` with the same object multiple times will
- remove the object the first time and have no effect on future calls until
- you add the object to the set again.
-
- NOTE: You cannot add/remove `null` or `undefined` to a set. Any attempt to do
- so will be ignored.
-
- In addition to add/remove you can also call `push()`/`pop()`. Push behaves
- just like `add()` but `pop()`, unlike `remove()` will pick an arbitrary
- object, remove it and return it. This is a good way to use a set as a job
- queue when you don't care which order the jobs are executed in.
-
- ## Testing for an Object
-
- To test for an object's presence in a set you simply call
- `Ember.Set#contains()`.
-
- ## Observing changes
-
- When using `Ember.Set`, you can observe the `"[]"` property to be
- alerted whenever the content changes. You can also add an enumerable
- observer to the set to be notified of specific objects that are added and
- removed from the set. See [Ember.Enumerable](/api/classes/Ember.Enumerable.html)
- for more information on enumerables.
-
- This is often unhelpful. If you are filtering sets of objects, for instance,
- it is very inefficient to re-filter all of the items each time the set
- changes. It would be better if you could just adjust the filtered set based
- on what was changed on the original set. The same issue applies to merging
- sets, as well.
-
- ## Other Methods
-
- `Ember.Set` primary implements other mixin APIs. For a complete reference
- on the methods you will use with `Ember.Set`, please consult these mixins.
- The most useful ones will be `Ember.Enumerable` and
- `Ember.MutableEnumerable` which implement most of the common iterator
- methods you are used to on Array.
-
- Note that you can also use the `Ember.Copyable` and `Ember.Freezable`
- APIs on `Ember.Set` as well. Once a set is frozen it can no longer be
- modified. The benefit of this is that when you call `frozenCopy()` on it,
- Ember will avoid making copies of the set. This allows you to write
- code that can know with certainty when the underlying set data will or
- will not be modified.
-
- @class Set
- @namespace Ember
- @extends Ember.CoreObject
- @uses Ember.MutableEnumerable
- @uses Ember.Copyable
- @uses Ember.Freezable
- @since Ember 0.9
- @deprecated
- */
- __exports__["default"] = CoreObject.extend(MutableEnumerable, Copyable, Freezable, {
-
- // ..........................................................
- // IMPLEMENT ENUMERABLE APIS
- //
-
- /**
- This property will change as the number of objects in the set changes.
-
- @property length
- @type number
- @default 0
- */
- length: 0,
-
- /**
- Clears the set. This is useful if you want to reuse an existing set
- without having to recreate it.
-
- ```javascript
- var colors = new Ember.Set(["red", "green", "blue"]);
- colors.length; // 3
- colors.clear();
- colors.length; // 0
- ```
-
- @method clear
- @return {Ember.Set} An empty Set
- */
- clear: function() {
- if (this.isFrozen) { throw new EmberError(FROZEN_ERROR); }
-
- var len = get(this, 'length');
- if (len === 0) { return this; }
-
- var guid;
-
- this.enumerableContentWillChange(len, 0);
- propertyWillChange(this, 'firstObject');
- propertyWillChange(this, 'lastObject');
-
- for (var i=0; i < len; i++) {
- guid = guidFor(this[i]);
- delete this[guid];
- delete this[i];
- }
-
- set(this, 'length', 0);
-
- propertyDidChange(this, 'firstObject');
- propertyDidChange(this, 'lastObject');
- this.enumerableContentDidChange(len, 0);
-
- return this;
- },
-
- /**
- Returns true if the passed object is also an enumerable that contains the
- same objects as the receiver.
-
- ```javascript
- var colors = ["red", "green", "blue"],
- same_colors = new Ember.Set(colors);
-
- same_colors.isEqual(colors); // true
- same_colors.isEqual(["purple", "brown"]); // false
- ```
-
- @method isEqual
- @param {Ember.Set} obj the other object.
- @return {Boolean}
- */
- isEqual: function(obj) {
- // fail fast
- if (!Enumerable.detect(obj)) return false;
-
- var loc = get(this, 'length');
- if (get(obj, 'length') !== loc) return false;
-
- while(--loc >= 0) {
- if (!obj.contains(this[loc])) return false;
- }
-
- return true;
- },
-
- /**
- Adds an object to the set. Only non-`null` objects can be added to a set
- and those can only be added once. If the object is already in the set or
- the passed value is null this method will have no effect.
-
- This is an alias for `Ember.MutableEnumerable.addObject()`.
-
- ```javascript
- var colors = new Ember.Set();
- colors.add("blue"); // ["blue"]
- colors.add("blue"); // ["blue"]
- colors.add("red"); // ["blue", "red"]
- colors.add(null); // ["blue", "red"]
- colors.add(undefined); // ["blue", "red"]
- ```
-
- @method add
- @param {Object} obj The object to add.
- @return {Ember.Set} The set itself.
- */
- add: aliasMethod('addObject'),
-
- /**
- Removes the object from the set if it is found. If you pass a `null` value
- or an object that is already not in the set, this method will have no
- effect. This is an alias for `Ember.MutableEnumerable.removeObject()`.
-
- ```javascript
- var colors = new Ember.Set(["red", "green", "blue"]);
- colors.remove("red"); // ["blue", "green"]
- colors.remove("purple"); // ["blue", "green"]
- colors.remove(null); // ["blue", "green"]
- ```
-
- @method remove
- @param {Object} obj The object to remove
- @return {Ember.Set} The set itself.
- */
- remove: aliasMethod('removeObject'),
-
- /**
- Removes the last element from the set and returns it, or `null` if it's empty.
-
- ```javascript
- var colors = new Ember.Set(["green", "blue"]);
- colors.pop(); // "blue"
- colors.pop(); // "green"
- colors.pop(); // null
- ```
-
- @method pop
- @return {Object} The removed object from the set or null.
- */
- pop: function() {
- if (get(this, 'isFrozen')) throw new EmberError(FROZEN_ERROR);
- var obj = this.length > 0 ? this[this.length-1] : null;
- this.remove(obj);
- return obj;
- },
-
- /**
- Inserts the given object on to the end of the set. It returns
- the set itself.
-
- This is an alias for `Ember.MutableEnumerable.addObject()`.
-
- ```javascript
- var colors = new Ember.Set();
- colors.push("red"); // ["red"]
- colors.push("green"); // ["red", "green"]
- colors.push("blue"); // ["red", "green", "blue"]
- ```
-
- @method push
- @return {Ember.Set} The set itself.
- */
- push: aliasMethod('addObject'),
-
- /**
- Removes the last element from the set and returns it, or `null` if it's empty.
-
- This is an alias for `Ember.Set.pop()`.
-
- ```javascript
- var colors = new Ember.Set(["green", "blue"]);
- colors.shift(); // "blue"
- colors.shift(); // "green"
- colors.shift(); // null
- ```
-
- @method shift
- @return {Object} The removed object from the set or null.
- */
- shift: aliasMethod('pop'),
-
- /**
- Inserts the given object on to the end of the set. It returns
- the set itself.
-
- This is an alias of `Ember.Set.push()`
-
- ```javascript
- var colors = new Ember.Set();
- colors.unshift("red"); // ["red"]
- colors.unshift("green"); // ["red", "green"]
- colors.unshift("blue"); // ["red", "green", "blue"]
- ```
-
- @method unshift
- @return {Ember.Set} The set itself.
- */
- unshift: aliasMethod('push'),
-
- /**
- Adds each object in the passed enumerable to the set.
-
- This is an alias of `Ember.MutableEnumerable.addObjects()`
-
- ```javascript
- var colors = new Ember.Set();
- colors.addEach(["red", "green", "blue"]); // ["red", "green", "blue"]
- ```
-
- @method addEach
- @param {Ember.Enumerable} objects the objects to add.
- @return {Ember.Set} The set itself.
- */
- addEach: aliasMethod('addObjects'),
-
- /**
- Removes each object in the passed enumerable to the set.
-
- This is an alias of `Ember.MutableEnumerable.removeObjects()`
-
- ```javascript
- var colors = new Ember.Set(["red", "green", "blue"]);
- colors.removeEach(["red", "blue"]); // ["green"]
- ```
-
- @method removeEach
- @param {Ember.Enumerable} objects the objects to remove.
- @return {Ember.Set} The set itself.
- */
- removeEach: aliasMethod('removeObjects'),
-
- // ..........................................................
- // PRIVATE ENUMERABLE SUPPORT
- //
-
- init: function(items) {
- Ember.deprecate('Ember.Set is deprecated and will be removed in a future release.');
- this._super();
- if (items) this.addObjects(items);
- },
-
- // implement Ember.Enumerable
- nextObject: function(idx) {
- return this[idx];
- },
-
- // more optimized version
- firstObject: computed(function() {
- return this.length > 0 ? this[0] : undefined;
- }),
-
- // more optimized version
- lastObject: computed(function() {
- return this.length > 0 ? this[this.length-1] : undefined;
- }),
-
- // implements Ember.MutableEnumerable
- addObject: function(obj) {
- if (get(this, 'isFrozen')) throw new EmberError(FROZEN_ERROR);
- if (isNone(obj)) return this; // nothing to do
-
- var guid = guidFor(obj);
- var idx = this[guid];
- var len = get(this, 'length');
- var added;
-
- if (idx>=0 && idx<len && (this[idx] === obj)) return this; // added
-
- added = [obj];
-
- this.enumerableContentWillChange(null, added);
- propertyWillChange(this, 'lastObject');
-
- len = get(this, 'length');
- this[guid] = len;
- this[len] = obj;
- set(this, 'length', len+1);
-
- propertyDidChange(this, 'lastObject');
- this.enumerableContentDidChange(null, added);
-
- return this;
- },
-
- // implements Ember.MutableEnumerable
- removeObject: function(obj) {
- if (get(this, 'isFrozen')) throw new EmberError(FROZEN_ERROR);
- if (isNone(obj)) return this; // nothing to do
-
- var guid = guidFor(obj);
- var idx = this[guid];
- var len = get(this, 'length');
- var isFirst = idx === 0;
- var isLast = idx === len-1;
- var last, removed;
-
-
- if (idx>=0 && idx<len && (this[idx] === obj)) {
- removed = [obj];
-
- this.enumerableContentWillChange(removed, null);
- if (isFirst) { propertyWillChange(this, 'firstObject'); }
- if (isLast) { propertyWillChange(this, 'lastObject'); }
-
- // swap items - basically move the item to the end so it can be removed
- if (idx < len-1) {
- last = this[len-1];
- this[idx] = last;
- this[guidFor(last)] = idx;
- }
-
- delete this[guid];
- delete this[len-1];
- set(this, 'length', len-1);
-
- if (isFirst) { propertyDidChange(this, 'firstObject'); }
- if (isLast) { propertyDidChange(this, 'lastObject'); }
- this.enumerableContentDidChange(removed, null);
- }
-
- return this;
- },
-
- // optimized version
- contains: function(obj) {
- return this[guidFor(obj)]>=0;
- },
-
- copy: function() {
- var C = this.constructor, ret = new C(), loc = get(this, 'length');
- set(ret, 'length', loc);
- while(--loc>=0) {
- ret[loc] = this[loc];
- ret[guidFor(this[loc])] = loc;
- }
- return ret;
- },
-
- toString: function() {
- var len = this.length, idx, array = [];
- for(idx = 0; idx < len; idx++) {
- array[idx] = this[idx];
- }
- return fmt("Ember.Set<%@>", [array.join(',')]);
- }
- });
- });
-enifed("ember-runtime/system/string",
- ["ember-metal/core","ember-metal/utils","ember-metal/cache","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
- "use strict";
- /**
- @module ember
- @submodule ember-runtime
- */
- var Ember = __dependency1__["default"];
- // Ember.STRINGS, Ember.FEATURES
- var isArray = __dependency2__.isArray;
- var emberInspect = __dependency2__.inspect;
-
- var Cache = __dependency3__["default"];
-
- var STRING_DASHERIZE_REGEXP = (/[ _]/g);
-
- var STRING_DASHERIZE_CACHE = new Cache(1000, function(key) {
- return decamelize(key).replace(STRING_DASHERIZE_REGEXP, '-');
- });
-
- var CAMELIZE_CACHE = new Cache(1000, function(key) {
- return key.replace(STRING_CAMELIZE_REGEXP, function(match, separator, chr) {
- return chr ? chr.toUpperCase() : '';
- }).replace(/^([A-Z])/, function(match, separator, chr) {
- return match.toLowerCase();
- });
- });
-
- var CLASSIFY_CACHE = new Cache(1000, function(str) {
- var parts = str.split(".");
- var out = [];
-
- for (var i=0, l=parts.length; i<l; i++) {
- var camelized = camelize(parts[i]);
- out.push(camelized.charAt(0).toUpperCase() + camelized.substr(1));
- }
-
- return out.join(".");
- });
-
- var UNDERSCORE_CACHE = new Cache(1000, function(str) {
- return str.replace(STRING_UNDERSCORE_REGEXP_1, '$1_$2').
- replace(STRING_UNDERSCORE_REGEXP_2, '_').toLowerCase();
- });
-
- var CAPITALIZE_CACHE = new Cache(1000, function(str) {
- return str.charAt(0).toUpperCase() + str.substr(1);
- });
-
- var DECAMELIZE_CACHE = new Cache(1000, function(str) {
- return str.replace(STRING_DECAMELIZE_REGEXP, '$1_$2').toLowerCase();
- });
-
- var STRING_DECAMELIZE_REGEXP = (/([a-z\d])([A-Z])/g);
- var STRING_CAMELIZE_REGEXP = (/(\-|_|\.|\s)+(.)?/g);
- var STRING_UNDERSCORE_REGEXP_1 = (/([a-z\d])([A-Z]+)/g);
- var STRING_UNDERSCORE_REGEXP_2 = (/\-|\s+/g);
-
- function fmt(str, formats) {
- var cachedFormats = formats;
-
- if (!isArray(cachedFormats) || arguments.length > 2) {
- cachedFormats = new Array(arguments.length - 1);
-
- for (var i = 1, l = arguments.length; i < l; i++) {
- cachedFormats[i - 1] = arguments[i];
- }
- }
-
- // first, replace any ORDERED replacements.
- var idx = 0; // the current index for non-numerical replacements
- return str.replace(/%@([0-9]+)?/g, function(s, argIndex) {
- argIndex = (argIndex) ? parseInt(argIndex, 10) - 1 : idx++;
- s = cachedFormats[argIndex];
- return (s === null) ? '(null)' : (s === undefined) ? '' : emberInspect(s);
- });
- }
-
- function loc(str, formats) {
- if (!isArray(formats) || arguments.length > 2) {
- formats = Array.prototype.slice.call(arguments, 1);
- }
-
- str = Ember.STRINGS[str] || str;
- return fmt(str, formats);
- }
-
- function w(str) {
- return str.split(/\s+/);
- }
-
- function decamelize(str) {
- return DECAMELIZE_CACHE.get(str);
- }
-
- function dasherize(str) {
- return STRING_DASHERIZE_CACHE.get(str);
- }
-
- function camelize(str) {
- return CAMELIZE_CACHE.get(str);
- }
-
- function classify(str) {
- return CLASSIFY_CACHE.get(str);
- }
-
- function underscore(str) {
- return UNDERSCORE_CACHE.get(str);
- }
-
- function capitalize(str) {
- return CAPITALIZE_CACHE.get(str);
- }
-
- /**
- Defines the hash of localized strings for the current language. Used by
- the `Ember.String.loc()` helper. To localize, add string values to this
- hash.
-
- @property STRINGS
- @for Ember
- @type Hash
- */
- Ember.STRINGS = {};
-
- /**
- Defines string helper methods including string formatting and localization.
- Unless `Ember.EXTEND_PROTOTYPES.String` is `false` these methods will also be
- added to the `String.prototype` as well.
-
- @class String
- @namespace Ember
- @static
- */
- __exports__["default"] = {
- /**
- Apply formatting options to the string. This will look for occurrences
- of "%@" in your string and substitute them with the arguments you pass into
- this method. If you want to control the specific order of replacement,
- you can add a number after the key as well to indicate which argument
- you want to insert.
-
- Ordered insertions are most useful when building loc strings where values
- you need to insert may appear in different orders.
-
- ```javascript
- "Hello %@ %@".fmt('John', 'Doe'); // "Hello John Doe"
- "Hello %@2, %@1".fmt('John', 'Doe'); // "Hello Doe, John"
- ```
-
- @method fmt
- @param {String} str The string to format
- @param {Array} formats An array of parameters to interpolate into string.
- @return {String} formatted string
- */
- fmt: fmt,
-
- /**
- Formats the passed string, but first looks up the string in the localized
- strings hash. This is a convenient way to localize text. See
- `Ember.String.fmt()` for more information on formatting.
-
- Note that it is traditional but not required to prefix localized string
- keys with an underscore or other character so you can easily identify
- localized strings.
-
- ```javascript
- Ember.STRINGS = {
- '_Hello World': 'Bonjour le monde',
- '_Hello %@ %@': 'Bonjour %@ %@'
- };
-
- Ember.String.loc("_Hello World"); // 'Bonjour le monde';
- Ember.String.loc("_Hello %@ %@", ["John", "Smith"]); // "Bonjour John Smith";
- ```
-
- @method loc
- @param {String} str The string to format
- @param {Array} formats Optional array of parameters to interpolate into string.
- @return {String} formatted string
- */
- loc: loc,
-
- /**
- Splits a string into separate units separated by spaces, eliminating any
- empty strings in the process. This is a convenience method for split that
- is mostly useful when applied to the `String.prototype`.
-
- ```javascript
- Ember.String.w("alpha beta gamma").forEach(function(key) {
- console.log(key);
- });
-
- // > alpha
- // > beta
- // > gamma
- ```
-
- @method w
- @param {String} str The string to split
- @return {Array} array containing the split strings
- */
- w: w,
-
- /**
- Converts a camelized string into all lower case separated by underscores.
-
- ```javascript
- 'innerHTML'.decamelize(); // 'inner_html'
- 'action_name'.decamelize(); // 'action_name'
- 'css-class-name'.decamelize(); // 'css-class-name'
- 'my favorite items'.decamelize(); // 'my favorite items'
- ```
-
- @method decamelize
- @param {String} str The string to decamelize.
- @return {String} the decamelized string.
- */
- decamelize: decamelize,
-
- /**
- Replaces underscores, spaces, or camelCase with dashes.
-
- ```javascript
- 'innerHTML'.dasherize(); // 'inner-html'
- 'action_name'.dasherize(); // 'action-name'
- 'css-class-name'.dasherize(); // 'css-class-name'
- 'my favorite items'.dasherize(); // 'my-favorite-items'
- ```
-
- @method dasherize
- @param {String} str The string to dasherize.
- @return {String} the dasherized string.
- */
- dasherize: dasherize,
-
- /**
- Returns the lowerCamelCase form of a string.
-
- ```javascript
- 'innerHTML'.camelize(); // 'innerHTML'
- 'action_name'.camelize(); // 'actionName'
- 'css-class-name'.camelize(); // 'cssClassName'
- 'my favorite items'.camelize(); // 'myFavoriteItems'
- 'My Favorite Items'.camelize(); // 'myFavoriteItems'
- ```
-
- @method camelize
- @param {String} str The string to camelize.
- @return {String} the camelized string.
- */
- camelize: camelize,
-
- /**
- Returns the UpperCamelCase form of a string.
-
- ```javascript
- 'innerHTML'.classify(); // 'InnerHTML'
- 'action_name'.classify(); // 'ActionName'
- 'css-class-name'.classify(); // 'CssClassName'
- 'my favorite items'.classify(); // 'MyFavoriteItems'
- ```
-
- @method classify
- @param {String} str the string to classify
- @return {String} the classified string
- */
- classify: classify,
-
- /**
- More general than decamelize. Returns the lower\_case\_and\_underscored
- form of a string.
-
- ```javascript
- 'innerHTML'.underscore(); // 'inner_html'
- 'action_name'.underscore(); // 'action_name'
- 'css-class-name'.underscore(); // 'css_class_name'
- 'my favorite items'.underscore(); // 'my_favorite_items'
- ```
-
- @method underscore
- @param {String} str The string to underscore.
- @return {String} the underscored string.
- */
- underscore: underscore,
-
- /**
- Returns the Capitalized form of a string
-
- ```javascript
- 'innerHTML'.capitalize() // 'InnerHTML'
- 'action_name'.capitalize() // 'Action_name'
- 'css-class-name'.capitalize() // 'Css-class-name'
- 'my favorite items'.capitalize() // 'My favorite items'
- ```
-
- @method capitalize
- @param {String} str The string to capitalize.
- @return {String} The capitalized string.
- */
- capitalize: capitalize
- };
-
- __exports__.fmt = fmt;
- __exports__.loc = loc;
- __exports__.w = w;
- __exports__.decamelize = decamelize;
- __exports__.dasherize = dasherize;
- __exports__.camelize = camelize;
- __exports__.classify = classify;
- __exports__.underscore = underscore;
- __exports__.capitalize = capitalize;
- });
-enifed("ember-runtime/system/subarray",
- ["ember-metal/error","ember-metal/enumerable_utils","exports"],
- function(__dependency1__, __dependency2__, __exports__) {
- "use strict";
- var EmberError = __dependency1__["default"];
- var EnumerableUtils = __dependency2__["default"];
-
- var RETAIN = 'r';
- var FILTER = 'f';
-
- function Operation(type, count) {
- this.type = type;
- this.count = count;
- }
-
- __exports__["default"] = SubArray;
-
- /**
- An `Ember.SubArray` tracks an array in a way similar to, but more specialized
- than, `Ember.TrackedArray`. It is useful for keeping track of the indexes of
- items within a filtered array.
-
- @class SubArray
- @namespace Ember
- */
- function SubArray (length) {
- if (arguments.length < 1) { length = 0; }
-
- if (length > 0) {
- this._operations = [new Operation(RETAIN, length)];
- } else {
- this._operations = [];
- }
- }
-
-
- SubArray.prototype = {
- /**
- Track that an item was added to the tracked array.
-
- @method addItem
-
- @param {Number} index The index of the item in the tracked array.
- @param {Boolean} match `true` iff the item is included in the subarray.
-
- @return {number} The index of the item in the subarray.
- */
- addItem: function(index, match) {
- var returnValue = -1;
- var itemType = match ? RETAIN : FILTER;
- var self = this;
-
- this._findOperation(index, function(operation, operationIndex, rangeStart, rangeEnd, seenInSubArray) {
- var newOperation, splitOperation;
-
- if (itemType === operation.type) {
- ++operation.count;
- } else if (index === rangeStart) {
- // insert to the left of `operation`
- self._operations.splice(operationIndex, 0, new Operation(itemType, 1));
- } else {
- newOperation = new Operation(itemType, 1);
- splitOperation = new Operation(operation.type, rangeEnd - index + 1);
- operation.count = index - rangeStart;
-
- self._operations.splice(operationIndex + 1, 0, newOperation, splitOperation);
- }
-
- if (match) {
- if (operation.type === RETAIN) {
- returnValue = seenInSubArray + (index - rangeStart);
- } else {
- returnValue = seenInSubArray;
- }
- }
-
- self._composeAt(operationIndex);
- }, function(seenInSubArray) {
- self._operations.push(new Operation(itemType, 1));
-
- if (match) {
- returnValue = seenInSubArray;
- }
-
- self._composeAt(self._operations.length-1);
- });
-
- return returnValue;
- },
-
- /**
- Track that an item was removed from the tracked array.
-
- @method removeItem
-
- @param {Number} index The index of the item in the tracked array.
-
- @return {number} The index of the item in the subarray, or `-1` if the item
- was not in the subarray.
- */
- removeItem: function(index) {
- var returnValue = -1;
- var self = this;
-
- this._findOperation(index, function (operation, operationIndex, rangeStart, rangeEnd, seenInSubArray) {
- if (operation.type === RETAIN) {
- returnValue = seenInSubArray + (index - rangeStart);
- }
-
- if (operation.count > 1) {
- --operation.count;
- } else {
- self._operations.splice(operationIndex, 1);
- self._composeAt(operationIndex);
- }
- }, function() {
- throw new EmberError("Can't remove an item that has never been added.");
- });
-
- return returnValue;
- },
-
-
- _findOperation: function (index, foundCallback, notFoundCallback) {
- var seenInSubArray = 0;
- var operationIndex, len, operation, rangeStart, rangeEnd;
-
- // OPTIMIZE: change to balanced tree
- // find leftmost operation to the right of `index`
- for (operationIndex = rangeStart = 0, len = this._operations.length; operationIndex < len; rangeStart = rangeEnd + 1, ++operationIndex) {
- operation = this._operations[operationIndex];
- rangeEnd = rangeStart + operation.count - 1;
-
- if (index >= rangeStart && index <= rangeEnd) {
- foundCallback(operation, operationIndex, rangeStart, rangeEnd, seenInSubArray);
- return;
- } else if (operation.type === RETAIN) {
- seenInSubArray += operation.count;
- }
- }
-
- notFoundCallback(seenInSubArray);
- },
-
- _composeAt: function(index) {
- var op = this._operations[index];
- var otherOp;
-
- if (!op) {
- // Composing out of bounds is a no-op, as when removing the last operation
- // in the list.
- return;
- }
-
- if (index > 0) {
- otherOp = this._operations[index-1];
- if (otherOp.type === op.type) {
- op.count += otherOp.count;
- this._operations.splice(index-1, 1);
- --index;
- }
- }
-
- if (index < this._operations.length-1) {
- otherOp = this._operations[index+1];
- if (otherOp.type === op.type) {
- op.count += otherOp.count;
- this._operations.splice(index+1, 1);
- }
- }
- },
-
- toString: function () {
- var str = "";
- EnumerableUtils.forEach(this._operations, function (operation) {
- str += " " + operation.type + ":" + operation.count;
- });
- return str.substring(1);
- }
- };
- });
-enifed("ember-runtime/system/tracked_array",
- ["ember-metal/property_get","ember-metal/enumerable_utils","exports"],
- function(__dependency1__, __dependency2__, __exports__) {
- "use strict";
- var get = __dependency1__.get;
- var forEach = __dependency2__.forEach;
-
- var RETAIN = 'r';
- var INSERT = 'i';
- var DELETE = 'd';
-
- __exports__["default"] = TrackedArray;
-
- /**
- An `Ember.TrackedArray` tracks array operations. It's useful when you want to
- lazily compute the indexes of items in an array after they've been shifted by
- subsequent operations.
-
- @class TrackedArray
- @namespace Ember
- @param {Array} [items=[]] The array to be tracked. This is used just to get
- the initial items for the starting state of retain:n.
- */
- function TrackedArray(items) {
- if (arguments.length < 1) { items = []; }
-
- var length = get(items, 'length');
-
- if (length) {
- this._operations = [new ArrayOperation(RETAIN, length, items)];
- } else {
- this._operations = [];
- }
- }
-
- TrackedArray.RETAIN = RETAIN;
- TrackedArray.INSERT = INSERT;
- TrackedArray.DELETE = DELETE;
-
- TrackedArray.prototype = {
-
- /**
- Track that `newItems` were added to the tracked array at `index`.
-
- @method addItems
- @param index
- @param newItems
- */
- addItems: function (index, newItems) {
- var count = get(newItems, 'length');
- if (count < 1) { return; }
-
- var match = this._findArrayOperation(index);
- var arrayOperation = match.operation;
- var arrayOperationIndex = match.index;
- var arrayOperationRangeStart = match.rangeStart;
- var composeIndex, newArrayOperation;
-
- newArrayOperation = new ArrayOperation(INSERT, count, newItems);
-
- if (arrayOperation) {
- if (!match.split) {
- // insert left of arrayOperation
- this._operations.splice(arrayOperationIndex, 0, newArrayOperation);
- composeIndex = arrayOperationIndex;
- } else {
- this._split(arrayOperationIndex, index - arrayOperationRangeStart, newArrayOperation);
- composeIndex = arrayOperationIndex + 1;
- }
- } else {
- // insert at end
- this._operations.push(newArrayOperation);
- composeIndex = arrayOperationIndex;
- }
-
- this._composeInsert(composeIndex);
- },
-
- /**
- Track that `count` items were removed at `index`.
-
- @method removeItems
- @param index
- @param count
- */
- removeItems: function (index, count) {
- if (count < 1) { return; }
-
- var match = this._findArrayOperation(index);
- var arrayOperationIndex = match.index;
- var arrayOperationRangeStart = match.rangeStart;
- var newArrayOperation, composeIndex;
-
- newArrayOperation = new ArrayOperation(DELETE, count);
- if (!match.split) {
- // insert left of arrayOperation
- this._operations.splice(arrayOperationIndex, 0, newArrayOperation);
- composeIndex = arrayOperationIndex;
- } else {
- this._split(arrayOperationIndex, index - arrayOperationRangeStart, newArrayOperation);
- composeIndex = arrayOperationIndex + 1;
- }
-
- return this._composeDelete(composeIndex);
- },
-
- /**
- Apply all operations, reducing them to retain:n, for `n`, the number of
- items in the array.
-
- `callback` will be called for each operation and will be passed the following arguments:
-
- * {array} items The items for the given operation
- * {number} offset The computed offset of the items, ie the index in the
- array of the first item for this operation.
- * {string} operation The type of the operation. One of
- `Ember.TrackedArray.{RETAIN, DELETE, INSERT}`
-
- @method apply
- @param {Function} callback
- */
- apply: function (callback) {
- var items = [];
- var offset = 0;
-
- forEach(this._operations, function (arrayOperation, operationIndex) {
- callback(arrayOperation.items, offset, arrayOperation.type, operationIndex);
-
- if (arrayOperation.type !== DELETE) {
- offset += arrayOperation.count;
- items = items.concat(arrayOperation.items);
- }
- });
-
- this._operations = [new ArrayOperation(RETAIN, items.length, items)];
- },
-
- /**
- Return an `ArrayOperationMatch` for the operation that contains the item at `index`.
-
- @method _findArrayOperation
-
- @param {Number} index the index of the item whose operation information
- should be returned.
- @private
- */
- _findArrayOperation: function (index) {
- var split = false;
- var arrayOperationIndex, arrayOperation,
- arrayOperationRangeStart, arrayOperationRangeEnd,
- len;
-
- // OPTIMIZE: we could search these faster if we kept a balanced tree.
- // find leftmost arrayOperation to the right of `index`
- for (arrayOperationIndex = arrayOperationRangeStart = 0, len = this._operations.length; arrayOperationIndex < len; ++arrayOperationIndex) {
- arrayOperation = this._operations[arrayOperationIndex];
-
- if (arrayOperation.type === DELETE) { continue; }
-
- arrayOperationRangeEnd = arrayOperationRangeStart + arrayOperation.count - 1;
-
- if (index === arrayOperationRangeStart) {
- break;
- } else if (index > arrayOperationRangeStart && index <= arrayOperationRangeEnd) {
- split = true;
- break;
- } else {
- arrayOperationRangeStart = arrayOperationRangeEnd + 1;
- }
- }
-
- return new ArrayOperationMatch(arrayOperation, arrayOperationIndex, split, arrayOperationRangeStart);
- },
-
- _split: function (arrayOperationIndex, splitIndex, newArrayOperation) {
- var arrayOperation = this._operations[arrayOperationIndex];
- var splitItems = arrayOperation.items.slice(splitIndex);
- var splitArrayOperation = new ArrayOperation(arrayOperation.type, splitItems.length, splitItems);
-
- // truncate LHS
- arrayOperation.count = splitIndex;
- arrayOperation.items = arrayOperation.items.slice(0, splitIndex);
-
- this._operations.splice(arrayOperationIndex + 1, 0, newArrayOperation, splitArrayOperation);
- },
-
- // see SubArray for a better implementation.
- _composeInsert: function (index) {
- var newArrayOperation = this._operations[index];
- var leftArrayOperation = this._operations[index-1]; // may be undefined
- var rightArrayOperation = this._operations[index+1]; // may be undefined
- var leftOp = leftArrayOperation && leftArrayOperation.type;
- var rightOp = rightArrayOperation && rightArrayOperation.type;
-
- if (leftOp === INSERT) {
- // merge left
- leftArrayOperation.count += newArrayOperation.count;
- leftArrayOperation.items = leftArrayOperation.items.concat(newArrayOperation.items);
-
- if (rightOp === INSERT) {
- // also merge right (we have split an insert with an insert)
- leftArrayOperation.count += rightArrayOperation.count;
- leftArrayOperation.items = leftArrayOperation.items.concat(rightArrayOperation.items);
- this._operations.splice(index, 2);
- } else {
- // only merge left
- this._operations.splice(index, 1);
- }
- } else if (rightOp === INSERT) {
- // merge right
- newArrayOperation.count += rightArrayOperation.count;
- newArrayOperation.items = newArrayOperation.items.concat(rightArrayOperation.items);
- this._operations.splice(index + 1, 1);
- }
- },
-
- _composeDelete: function (index) {
- var arrayOperation = this._operations[index];
- var deletesToGo = arrayOperation.count;
- var leftArrayOperation = this._operations[index-1]; // may be undefined
- var leftOp = leftArrayOperation && leftArrayOperation.type;
- var nextArrayOperation;
- var nextOp;
- var nextCount;
- var removeNewAndNextOp = false;
- var removedItems = [];
-
- if (leftOp === DELETE) {
- arrayOperation = leftArrayOperation;
- index -= 1;
- }
-
- for (var i = index + 1; deletesToGo > 0; ++i) {
- nextArrayOperation = this._operations[i];
- nextOp = nextArrayOperation.type;
- nextCount = nextArrayOperation.count;
-
- if (nextOp === DELETE) {
- arrayOperation.count += nextCount;
- continue;
- }
-
- if (nextCount > deletesToGo) {
- // d:2 {r,i}:5 we reduce the retain or insert, but it stays
- removedItems = removedItems.concat(nextArrayOperation.items.splice(0, deletesToGo));
- nextArrayOperation.count -= deletesToGo;
-
- // In the case where we truncate the last arrayOperation, we don't need to
- // remove it; also the deletesToGo reduction is not the entirety of
- // nextCount
- i -= 1;
- nextCount = deletesToGo;
-
- deletesToGo = 0;
- } else {
- if (nextCount === deletesToGo) {
- // Handle edge case of d:2 i:2 in which case both operations go away
- // during composition.
- removeNewAndNextOp = true;
- }
- removedItems = removedItems.concat(nextArrayOperation.items);
- deletesToGo -= nextCount;
- }
-
- if (nextOp === INSERT) {
- // d:2 i:3 will result in delete going away
- arrayOperation.count -= nextCount;
- }
- }
-
- if (arrayOperation.count > 0) {
- // compose our new delete with possibly several operations to the right of
- // disparate types
- this._operations.splice(index+1, i-1-index);
- } else {
- // The delete operation can go away; it has merely reduced some other
- // operation, as in d:3 i:4; it may also have eliminated that operation,
- // as in d:3 i:3.
- this._operations.splice(index, removeNewAndNextOp ? 2 : 1);
- }
-
- return removedItems;
- },
-
- toString: function () {
- var str = "";
- forEach(this._operations, function (operation) {
- str += " " + operation.type + ":" + operation.count;
- });
- return str.substring(1);
- }
- };
-
- /**
- Internal data structure to represent an array operation.
-
- @method ArrayOperation
- @private
- @param {String} type The type of the operation. One of
- `Ember.TrackedArray.{RETAIN, INSERT, DELETE}`
- @param {Number} count The number of items in this operation.
- @param {Array} items The items of the operation, if included. RETAIN and
- INSERT include their items, DELETE does not.
- */
- function ArrayOperation (operation, count, items) {
- this.type = operation; // RETAIN | INSERT | DELETE
- this.count = count;
- this.items = items;
- }
-
- /**
- Internal data structure used to include information when looking up operations
- by item index.
-
- @method ArrayOperationMatch
- @private
- @param {ArrayOperation} operation
- @param {Number} index The index of `operation` in the array of operations.
- @param {Boolean} split Whether or not the item index searched for would
- require a split for a new operation type.
- @param {Number} rangeStart The index of the first item in the operation,
- with respect to the tracked array. The index of the last item can be computed
- from `rangeStart` and `operation.count`.
- */
- function ArrayOperationMatch(operation, index, split, rangeStart) {
- this.operation = operation;
- this.index = index;
- this.split = split;
- this.rangeStart = rangeStart;
- }
- });
-enifed("ember-testing",
- ["ember-metal/core","ember-testing/initializers","ember-testing/support","ember-testing/setup_for_testing","ember-testing/test","ember-testing/adapters/adapter","ember-testing/adapters/qunit","ember-testing/helpers"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__) {
- "use strict";
- var Ember = __dependency1__["default"];
-
- // to setup initializer
- // to handle various edge cases
-
- var setupForTesting = __dependency4__["default"];
- var Test = __dependency5__["default"];
- var Adapter = __dependency6__["default"];
- var QUnitAdapter = __dependency7__["default"];
- // adds helpers to helpers object in Test
-
- /**
- Ember Testing
-
- @module ember
- @submodule ember-testing
- @requires ember-application
- */
-
- Ember.Test = Test;
- Ember.Test.Adapter = Adapter;
- Ember.Test.QUnitAdapter = QUnitAdapter;
- Ember.setupForTesting = setupForTesting;
- });
-enifed("ember-testing/adapters/adapter",
- ["ember-metal/core","ember-runtime/system/object","exports"],
- function(__dependency1__, __dependency2__, __exports__) {
- "use strict";
- var Ember = __dependency1__["default"];
- // Ember.K
- var EmberObject = __dependency2__["default"];
-
- /**
- @module ember
- @submodule ember-testing
- */
-
- /**
- The primary purpose of this class is to create hooks that can be implemented
- by an adapter for various test frameworks.
-
- @class Adapter
- @namespace Ember.Test
- */
- var Adapter = EmberObject.extend({
- /**
- This callback will be called whenever an async operation is about to start.
-
- Override this to call your framework's methods that handle async
- operations.
-
- @public
- @method asyncStart
- */
- asyncStart: Ember.K,
-
- /**
- This callback will be called whenever an async operation has completed.
-
- @public
- @method asyncEnd
- */
- asyncEnd: Ember.K,
-
- /**
- Override this method with your testing framework's false assertion.
- This function is called whenever an exception occurs causing the testing
- promise to fail.
-
- QUnit example:
-
- ```javascript
- exception: function(error) {
- ok(false, error);
- };
- ```
-
- @public
- @method exception
- @param {String} error The exception to be raised.
- */
- exception: function(error) {
- throw error;
- }
- });
-
- __exports__["default"] = Adapter;
- });
-enifed("ember-testing/adapters/qunit",
- ["ember-testing/adapters/adapter","ember-metal/utils","exports"],
- function(__dependency1__, __dependency2__, __exports__) {
- "use strict";
- var Adapter = __dependency1__["default"];
- var inspect = __dependency2__.inspect;
-
- /**
- This class implements the methods defined by Ember.Test.Adapter for the
- QUnit testing framework.
-
- @class QUnitAdapter
- @namespace Ember.Test
- @extends Ember.Test.Adapter
- */
- __exports__["default"] = Adapter.extend({
- asyncStart: function() {
- QUnit.stop();
- },
- asyncEnd: function() {
- QUnit.start();
- },
- exception: function(error) {
- ok(false, inspect(error));
- }
- });
- });
-enifed("ember-testing/helpers",
- ["ember-metal/property_get","ember-metal/error","ember-metal/run_loop","ember-views/system/jquery","ember-testing/test"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__) {
- "use strict";
- var get = __dependency1__.get;
- var EmberError = __dependency2__["default"];
- var run = __dependency3__["default"];
- var jQuery = __dependency4__["default"];
- var Test = __dependency5__["default"];
-
- /**
- * @module ember
- * @submodule ember-testing
- */
-
- var helper = Test.registerHelper;
- var asyncHelper = Test.registerAsyncHelper;
- var countAsync = 0;
-
- function currentRouteName(app){
- var appController = app.__container__.lookup('controller:application');
-
- return get(appController, 'currentRouteName');
- }
-
- function currentPath(app){
- var appController = app.__container__.lookup('controller:application');
-
- return get(appController, 'currentPath');
- }
-
- function currentURL(app){
- var router = app.__container__.lookup('router:main');
-
- return get(router, 'location').getURL();
- }
-
- function pauseTest(){
- Test.adapter.asyncStart();
- return new Ember.RSVP.Promise(function(){ }, 'TestAdapter paused promise');
- }
-
- function visit(app, url) {
- var router = app.__container__.lookup('router:main');
- router.location.setURL(url);
-
- if (app._readinessDeferrals > 0) {
- router['initialURL'] = url;
- run(app, 'advanceReadiness');
- delete router['initialURL'];
- } else {
- run(app, app.handleURL, url);
- }
-
- return app.testHelpers.wait();
- }
-
- function click(app, selector, context) {
- var $el = app.testHelpers.findWithAssert(selector, context);
- run($el, 'mousedown');
-
- if ($el.is(':input')) {
- var type = $el.prop('type');
- if (type !== 'checkbox' && type !== 'radio' && type !== 'hidden') {
- run($el, function(){
- // Firefox does not trigger the `focusin` event if the window
- // does not have focus. If the document doesn't have focus just
- // use trigger('focusin') instead.
- if (!document.hasFocus || document.hasFocus()) {
- this.focus();
- } else {
- this.trigger('focusin');
- }
- });
- }
- }
-
- run($el, 'mouseup');
- run($el, 'click');
-
- return app.testHelpers.wait();
- }
-
- function triggerEvent(app, selector, contextOrType, typeOrOptions, possibleOptions){
- var arity = arguments.length;
- var context, type, options;
-
- if (arity === 3) {
- // context and options are optional, so this is
- // app, selector, type
- context = null;
- type = contextOrType;
- options = {};
- } else if (arity === 4) {
- // context and options are optional, so this is
- if (typeof typeOrOptions === "object") { // either
- // app, selector, type, options
- context = null;
- type = contextOrType;
- options = typeOrOptions;
- } else { // or
- // app, selector, context, type
- context = contextOrType;
- type = typeOrOptions;
- options = {};
- }
- } else {
- context = contextOrType;
- type = typeOrOptions;
- options = possibleOptions;
- }
-
- var $el = app.testHelpers.findWithAssert(selector, context);
-
- var event = jQuery.Event(type, options);
-
- run($el, 'trigger', event);
-
- return app.testHelpers.wait();
- }
-
- function keyEvent(app, selector, contextOrType, typeOrKeyCode, keyCode) {
- var context, type;
-
- if (typeof keyCode === 'undefined') {
- context = null;
- keyCode = typeOrKeyCode;
- type = contextOrType;
- } else {
- context = contextOrType;
- type = typeOrKeyCode;
- }
-
- return app.testHelpers.triggerEvent(selector, context, type, { keyCode: keyCode, which: keyCode });
- }
-
- function fillIn(app, selector, contextOrText, text) {
- var $el, context;
- if (typeof text === 'undefined') {
- text = contextOrText;
- } else {
- context = contextOrText;
- }
- $el = app.testHelpers.findWithAssert(selector, context);
- run(function() {
- $el.val(text).change();
- });
- return app.testHelpers.wait();
- }
-
- function findWithAssert(app, selector, context) {
- var $el = app.testHelpers.find(selector, context);
- if ($el.length === 0) {
- throw new EmberError("Element " + selector + " not found.");
- }
- return $el;
- }
-
- function find(app, selector, context) {
- var $el;
- context = context || get(app, 'rootElement');
- $el = app.$(selector, context);
-
- return $el;
- }
-
- function andThen(app, callback) {
- return app.testHelpers.wait(callback(app));
- }
-
- function wait(app, value) {
- return Test.promise(function(resolve) {
- // If this is the first async promise, kick off the async test
- if (++countAsync === 1) {
- Test.adapter.asyncStart();
- }
-
- // Every 10ms, poll for the async thing to have finished
- var watcher = setInterval(function() {
- // 1. If the router is loading, keep polling
- var routerIsLoading = !!app.__container__.lookup('router:main').router.activeTransition;
- if (routerIsLoading) { return; }
-
- // 2. If there are pending Ajax requests, keep polling
- if (Test.pendingAjaxRequests) { return; }
-
- // 3. If there are scheduled timers or we are inside of a run loop, keep polling
- if (run.hasScheduledTimers() || run.currentRunLoop) { return; }
- if (Test.waiters && Test.waiters.any(function(waiter) {
- var context = waiter[0];
- var callback = waiter[1];
- return !callback.call(context);
- })) { return; }
- // Stop polling
- clearInterval(watcher);
-
- // If this is the last async promise, end the async test
- if (--countAsync === 0) {
- Test.adapter.asyncEnd();
- }
-
- // Synchronously resolve the promise
- run(null, resolve, value);
- }, 10);
- });
-
- }
-
-
- /**
- * Loads a route, sets up any controllers, and renders any templates associated
- * with the route as though a real user had triggered the route change while
- * using your app.
- *
- * Example:
- *
- * ```javascript
- * visit('posts/index').then(function() {
- * // assert something
- * });
- * ```
- *
- * @method visit
- * @param {String} url the name of the route
- * @return {RSVP.Promise}
- */
- asyncHelper('visit', visit);
-
- /**
- * Clicks an element and triggers any actions triggered by the element's `click`
- * event.
- *
- * Example:
- *
- * ```javascript
- * click('.some-jQuery-selector').then(function() {
- * // assert something
- * });
- * ```
- *
- * @method click
- * @param {String} selector jQuery selector for finding element on the DOM
- * @return {RSVP.Promise}
- */
- asyncHelper('click', click);
-
- /**
- * Simulates a key event, e.g. `keypress`, `keydown`, `keyup` with the desired keyCode
- *
- * Example:
- *
- * ```javascript
- * keyEvent('.some-jQuery-selector', 'keypress', 13).then(function() {
- * // assert something
- * });
- * ```
- *
- * @method keyEvent
- * @param {String} selector jQuery selector for finding element on the DOM
- * @param {String} type the type of key event, e.g. `keypress`, `keydown`, `keyup`
- * @param {Number} keyCode the keyCode of the simulated key event
- * @return {RSVP.Promise}
- * @since 1.5.0
- */
- asyncHelper('keyEvent', keyEvent);
-
- /**
- * Fills in an input element with some text.
- *
- * Example:
- *
- * ```javascript
- * fillIn('#email', 'you@example.com').then(function() {
- * // assert something
- * });
- * ```
- *
- * @method fillIn
- * @param {String} selector jQuery selector finding an input element on the DOM
- * to fill text with
- * @param {String} text text to place inside the input element
- * @return {RSVP.Promise}
- */
- asyncHelper('fillIn', fillIn);
-
- /**
- * Finds an element in the context of the app's container element. A simple alias
- * for `app.$(selector)`.
- *
- * Example:
- *
- * ```javascript
- * var $el = find('.my-selector');
- * ```
- *
- * @method find
- * @param {String} selector jQuery string selector for element lookup
- * @return {Object} jQuery object representing the results of the query
- */
- helper('find', find);
-
- /**
- * Like `find`, but throws an error if the element selector returns no results.
- *
- * Example:
- *
- * ```javascript
- * var $el = findWithAssert('.doesnt-exist'); // throws error
- * ```
- *
- * @method findWithAssert
- * @param {String} selector jQuery selector string for finding an element within
- * the DOM
- * @return {Object} jQuery object representing the results of the query
- * @throws {Error} throws error if jQuery object returned has a length of 0
- */
- helper('findWithAssert', findWithAssert);
-
- /**
- Causes the run loop to process any pending events. This is used to ensure that
- any async operations from other helpers (or your assertions) have been processed.
-
- This is most often used as the return value for the helper functions (see 'click',
- 'fillIn','visit',etc).
-
- Example:
-
- ```javascript
- Ember.Test.registerAsyncHelper('loginUser', function(app, username, password) {
- visit('secured/path/here')
- .fillIn('#username', username)
- .fillIn('#password', password)
- .click('.submit')
-
- return app.testHelpers.wait();
- });
-
- @method wait
- @param {Object} value The value to be returned.
- @return {RSVP.Promise}
- */
- asyncHelper('wait', wait);
- asyncHelper('andThen', andThen);
-
-
- /**
- Returns the currently active route name.
-
- Example:
-
- ```javascript
- function validateRouteName(){
- equal(currentRouteName(), 'some.path', "correct route was transitioned into.");
- }
-
- visit('/some/path').then(validateRouteName)
- ```
-
- @method currentRouteName
- @return {Object} The name of the currently active route.
- @since 1.5.0
- */
- helper('currentRouteName', currentRouteName);
-
- /**
- Returns the current path.
-
- Example:
-
- ```javascript
- function validateURL(){
- equal(currentPath(), 'some.path.index', "correct path was transitioned into.");
- }
-
- click('#some-link-id').then(validateURL);
- ```
-
- @method currentPath
- @return {Object} The currently active path.
- @since 1.5.0
- */
- helper('currentPath', currentPath);
-
- /**
- Returns the current URL.
-
- Example:
-
- ```javascript
- function validateURL(){
- equal(currentURL(), '/some/path', "correct URL was transitioned into.");
- }
-
- click('#some-link-id').then(validateURL);
- ```
-
- @method currentURL
- @return {Object} The currently active URL.
- @since 1.5.0
- */
- helper('currentURL', currentURL);
-
-
- /**
- Pauses the current test - this is useful for debugging while testing or for test-driving.
- It allows you to inspect the state of your application at any point.
-
- Example (The test will pause before clicking the button):
-
- ```javascript
- visit('/')
- return pauseTest();
-
- click('.btn');
- ```
-
- @method pauseTest
- @return {Object} A promise that will never resolve
- */
- helper('pauseTest', pauseTest);
-
-
- /**
- Triggers the given DOM event on the element identified by the provided selector.
-
- Example:
-
- ```javascript
- triggerEvent('#some-elem-id', 'blur');
- ```
-
- This is actually used internally by the `keyEvent` helper like so:
-
- ```javascript
- triggerEvent('#some-elem-id', 'keypress', { keyCode: 13 });
- ```
-
- @method triggerEvent
- @param {String} selector jQuery selector for finding element on the DOM
- @param {String} [context] jQuery selector that will limit the selector
- argument to find only within the context's children
- @param {String} type The event type to be triggered.
- @param {Object} [options] The options to be passed to jQuery.Event.
- @return {RSVP.Promise}
- @since 1.5.0
- */
- asyncHelper('triggerEvent', triggerEvent);
- });
-enifed("ember-testing/initializers",
- ["ember-runtime/system/lazy_load"],
- function(__dependency1__) {
- "use strict";
- var onLoad = __dependency1__.onLoad;
-
- var name = 'deferReadiness in `testing` mode';
-
- onLoad('Ember.Application', function(Application) {
- if (!Application.initializers[name]) {
- Application.initializer({
- name: name,
-
- initialize: function(container, application){
- if (application.testing) {
- application.deferReadiness();
- }
- }
- });
- }
- });
- });
-enifed("ember-testing/setup_for_testing",
- ["ember-metal/core","ember-testing/adapters/qunit","ember-views/system/jquery","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
- "use strict";
- var Ember = __dependency1__["default"];
- // import Test from "ember-testing/test"; // ES6TODO: fix when cycles are supported
- var QUnitAdapter = __dependency2__["default"];
- var jQuery = __dependency3__["default"];
-
- var Test, requests;
-
- function incrementAjaxPendingRequests(_, xhr){
- requests.push(xhr);
- Test.pendingAjaxRequests = requests.length;
- }
-
- function decrementAjaxPendingRequests(_, xhr){
- for (var i=0;i<requests.length;i++) {
- if (xhr === requests[i]) {
- requests.splice(i, 1);
- }
- }
- Test.pendingAjaxRequests = requests.length;
- }
-
- /**
- Sets Ember up for testing. This is useful to perform
- basic setup steps in order to unit test.
-
- Use `App.setupForTesting` to perform integration tests (full
- application testing).
-
- @method setupForTesting
- @namespace Ember
- @since 1.5.0
- */
- __exports__["default"] = function setupForTesting() {
- if (!Test) { Test = requireModule('ember-testing/test')['default']; }
-
- Ember.testing = true;
-
- // if adapter is not manually set default to QUnit
- if (!Test.adapter) {
- Test.adapter = QUnitAdapter.create();
- }
-
- requests = [];
- Test.pendingAjaxRequests = requests.length;
-
- jQuery(document).off('ajaxSend', incrementAjaxPendingRequests);
- jQuery(document).off('ajaxComplete', decrementAjaxPendingRequests);
- jQuery(document).on('ajaxSend', incrementAjaxPendingRequests);
- jQuery(document).on('ajaxComplete', decrementAjaxPendingRequests);
- }
- });
-enifed("ember-testing/support",
- ["ember-metal/core","ember-views/system/jquery"],
- function(__dependency1__, __dependency2__) {
- "use strict";
- var Ember = __dependency1__["default"];
- var jQuery = __dependency2__["default"];
-
- /**
- @module ember
- @submodule ember-testing
- */
-
- var $ = jQuery;
-
- /**
- This method creates a checkbox and triggers the click event to fire the
- passed in handler. It is used to correct for a bug in older versions
- of jQuery (e.g 1.8.3).
-
- @private
- @method testCheckboxClick
- */
- function testCheckboxClick(handler) {
- $('<input type="checkbox">')
- .css({ position: 'absolute', left: '-1000px', top: '-1000px' })
- .appendTo('body')
- .on('click', handler)
- .trigger('click')
- .remove();
- }
-
- $(function() {
- /*
- Determine whether a checkbox checked using jQuery's "click" method will have
- the correct value for its checked property.
-
- If we determine that the current jQuery version exhibits this behavior,
- patch it to work correctly as in the commit for the actual fix:
- https://github.com/jquery/jquery/commit/1fb2f92.
- */
- testCheckboxClick(function() {
- if (!this.checked && !$.event.special.click) {
- $.event.special.click = {
- // For checkbox, fire native event so checked state will be right
- trigger: function() {
- if ($.nodeName( this, "input" ) && this.type === "checkbox" && this.click) {
- this.click();
- return false;
- }
- }
- };
- }
- });
-
- // Try again to verify that the patch took effect or blow up.
- testCheckboxClick(function() {
- Ember.warn("clicked checkboxes should be checked! the jQuery patch didn't work", this.checked);
- });
- });
- });
-enifed("ember-testing/test",
- ["ember-metal/core","ember-metal/run_loop","ember-metal/platform","ember-runtime/compare","ember-runtime/ext/rsvp","ember-testing/setup_for_testing","ember-application/system/application","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __exports__) {
- "use strict";
- var Ember = __dependency1__["default"];
- var emberRun = __dependency2__["default"];
- var create = __dependency3__.create;
- var compare = __dependency4__["default"];
- var RSVP = __dependency5__["default"];
- var setupForTesting = __dependency6__["default"];
- var EmberApplication = __dependency7__["default"];
-
- /**
- @module ember
- @submodule ember-testing
- */
- var slice = [].slice;
- var helpers = {};
- var injectHelpersCallbacks = [];
-
- /**
- This is a container for an assortment of testing related functionality:
-
- * Choose your default test adapter (for your framework of choice).
- * Register/Unregister additional test helpers.
- * Setup callbacks to be fired when the test helpers are injected into
- your application.
-
- @class Test
- @namespace Ember
- */
- var Test = {
- /**
- Hash containing all known test helpers.
-
- @property _helpers
- @private
- @since 1.7.0
- */
- _helpers: helpers,
-
- /**
- `registerHelper` is used to register a test helper that will be injected
- when `App.injectTestHelpers` is called.
-
- The helper method will always be called with the current Application as
- the first parameter.
-
- For example:
-
- ```javascript
- Ember.Test.registerHelper('boot', function(app) {
- Ember.run(app, app.advanceReadiness);
- });
- ```
-
- This helper can later be called without arguments because it will be
- called with `app` as the first parameter.
-
- ```javascript
- App = Ember.Application.create();
- App.injectTestHelpers();
- boot();
- ```
-
- @public
- @method registerHelper
- @param {String} name The name of the helper method to add.
- @param {Function} helperMethod
- @param options {Object}
- */
- registerHelper: function(name, helperMethod) {
- helpers[name] = {
- method: helperMethod,
- meta: { wait: false }
- };
- },
-
- /**
- `registerAsyncHelper` is used to register an async test helper that will be injected
- when `App.injectTestHelpers` is called.
-
- The helper method will always be called with the current Application as
- the first parameter.
-
- For example:
-
- ```javascript
- Ember.Test.registerAsyncHelper('boot', function(app) {
- Ember.run(app, app.advanceReadiness);
- });
- ```
-
- The advantage of an async helper is that it will not run
- until the last async helper has completed. All async helpers
- after it will wait for it complete before running.
-
-
- For example:
-
- ```javascript
- Ember.Test.registerAsyncHelper('deletePost', function(app, postId) {
- click('.delete-' + postId);
- });
-
- // ... in your test
- visit('/post/2');
- deletePost(2);
- visit('/post/3');
- deletePost(3);
- ```
-
- @public
- @method registerAsyncHelper
- @param {String} name The name of the helper method to add.
- @param {Function} helperMethod
- @since 1.2.0
- */
- registerAsyncHelper: function(name, helperMethod) {
- helpers[name] = {
- method: helperMethod,
- meta: { wait: true }
- };
- },
-
- /**
- Remove a previously added helper method.
-
- Example:
-
- ```javascript
- Ember.Test.unregisterHelper('wait');
- ```
-
- @public
- @method unregisterHelper
- @param {String} name The helper to remove.
- */
- unregisterHelper: function(name) {
- delete helpers[name];
- delete Test.Promise.prototype[name];
- },
-
- /**
- Used to register callbacks to be fired whenever `App.injectTestHelpers`
- is called.
-
- The callback will receive the current application as an argument.
-
- Example:
-
- ```javascript
- Ember.Test.onInjectHelpers(function() {
- Ember.$(document).ajaxSend(function() {
- Test.pendingAjaxRequests++;
- });
-
- Ember.$(document).ajaxComplete(function() {
- Test.pendingAjaxRequests--;
- });
- });
- ```
-
- @public
- @method onInjectHelpers
- @param {Function} callback The function to be called.
- */
- onInjectHelpers: function(callback) {
- injectHelpersCallbacks.push(callback);
- },
-
- /**
- This returns a thenable tailored for testing. It catches failed
- `onSuccess` callbacks and invokes the `Ember.Test.adapter.exception`
- callback in the last chained then.
-
- This method should be returned by async helpers such as `wait`.
-
- @public
- @method promise
- @param {Function} resolver The function used to resolve the promise.
- */
- promise: function(resolver) {
- return new Test.Promise(resolver);
- },
-
- /**
- Used to allow ember-testing to communicate with a specific testing
- framework.
-
- You can manually set it before calling `App.setupForTesting()`.
-
- Example:
-
- ```javascript
- Ember.Test.adapter = MyCustomAdapter.create()
- ```
-
- If you do not set it, ember-testing will default to `Ember.Test.QUnitAdapter`.
-
- @public
- @property adapter
- @type {Class} The adapter to be used.
- @default Ember.Test.QUnitAdapter
- */
- adapter: null,
-
- /**
- Replacement for `Ember.RSVP.resolve`
- The only difference is this uses
- an instance of `Ember.Test.Promise`
-
- @public
- @method resolve
- @param {Mixed} The value to resolve
- @since 1.2.0
- */
- resolve: function(val) {
- return Test.promise(function(resolve) {
- return resolve(val);
- });
- },
-
- /**
- This allows ember-testing to play nicely with other asynchronous
- events, such as an application that is waiting for a CSS3
- transition or an IndexDB transaction.
-
- For example:
-
- ```javascript
- Ember.Test.registerWaiter(function() {
- return myPendingTransactions() == 0;
- });
- ```
- The `context` argument allows you to optionally specify the `this`
- with which your callback will be invoked.
-
- For example:
-
- ```javascript
- Ember.Test.registerWaiter(MyDB, MyDB.hasPendingTransactions);
- ```
-
- @public
- @method registerWaiter
- @param {Object} context (optional)
- @param {Function} callback
- @since 1.2.0
- */
- registerWaiter: function(context, callback) {
- if (arguments.length === 1) {
- callback = context;
- context = null;
- }
- if (!this.waiters) {
- this.waiters = Ember.A();
- }
- this.waiters.push([context, callback]);
- },
- /**
- `unregisterWaiter` is used to unregister a callback that was
- registered with `registerWaiter`.
-
- @public
- @method unregisterWaiter
- @param {Object} context (optional)
- @param {Function} callback
- @since 1.2.0
- */
- unregisterWaiter: function(context, callback) {
- var pair;
- if (!this.waiters) { return; }
- if (arguments.length === 1) {
- callback = context;
- context = null;
- }
- pair = [context, callback];
- this.waiters = Ember.A(this.waiters.filter(function(elt) {
- return compare(elt, pair)!==0;
- }));
- }
- };
-
- function helper(app, name) {
- var fn = helpers[name].method;
- var meta = helpers[name].meta;
-
- return function() {
- var args = slice.call(arguments);
- var lastPromise = Test.lastPromise;
-
- args.unshift(app);
-
- // some helpers are not async and
- // need to return a value immediately.
- // example: `find`
- if (!meta.wait) {
- return fn.apply(app, args);
- }
-
- if (!lastPromise) {
- // It's the first async helper in current context
- lastPromise = fn.apply(app, args);
- } else {
- // wait for last helper's promise to resolve
- // and then execute
- run(function() {
- lastPromise = Test.resolve(lastPromise).then(function() {
- return fn.apply(app, args);
- });
- });
- }
-
- return lastPromise;
- };
- }
-
- function run(fn) {
- if (!emberRun.currentRunLoop) {
- emberRun(fn);
- } else {
- fn();
- }
- }
-
- EmberApplication.reopen({
- /**
- This property contains the testing helpers for the current application. These
- are created once you call `injectTestHelpers` on your `Ember.Application`
- instance. The included helpers are also available on the `window` object by
- default, but can be used from this object on the individual application also.
-
- @property testHelpers
- @type {Object}
- @default {}
- */
- testHelpers: {},
-
- /**
- This property will contain the original methods that were registered
- on the `helperContainer` before `injectTestHelpers` is called.
-
- When `removeTestHelpers` is called, these methods are restored to the
- `helperContainer`.
-
- @property originalMethods
- @type {Object}
- @default {}
- @private
- @since 1.3.0
- */
- originalMethods: {},
-
-
- /**
- This property indicates whether or not this application is currently in
- testing mode. This is set when `setupForTesting` is called on the current
- application.
-
- @property testing
- @type {Boolean}
- @default false
- @since 1.3.0
- */
- testing: false,
-
- /**
- This hook defers the readiness of the application, so that you can start
- the app when your tests are ready to run. It also sets the router's
- location to 'none', so that the window's location will not be modified
- (preventing both accidental leaking of state between tests and interference
- with your testing framework).
-
- Example:
-
- ```
- App.setupForTesting();
- ```
-
- @method setupForTesting
- */
- setupForTesting: function() {
- setupForTesting();
-
- this.testing = true;
-
- this.Router.reopen({
- location: 'none'
- });
- },
-
- /**
- This will be used as the container to inject the test helpers into. By
- default the helpers are injected into `window`.
-
- @property helperContainer
- @type {Object} The object to be used for test helpers.
- @default window
- @since 1.2.0
- */
- helperContainer: window,
-
- /**
- This injects the test helpers into the `helperContainer` object. If an object is provided
- it will be used as the helperContainer. If `helperContainer` is not set it will default
- to `window`. If a function of the same name has already been defined it will be cached
- (so that it can be reset if the helper is removed with `unregisterHelper` or
- `removeTestHelpers`).
-
- Any callbacks registered with `onInjectHelpers` will be called once the
- helpers have been injected.
-
- Example:
- ```
- App.injectTestHelpers();
- ```
-
- @method injectTestHelpers
- */
- injectTestHelpers: function(helperContainer) {
- if (helperContainer) { this.helperContainer = helperContainer; }
-
- this.testHelpers = {};
- for (var name in helpers) {
- this.originalMethods[name] = this.helperContainer[name];
- this.testHelpers[name] = this.helperContainer[name] = helper(this, name);
- protoWrap(Test.Promise.prototype, name, helper(this, name), helpers[name].meta.wait);
- }
-
- for(var i = 0, l = injectHelpersCallbacks.length; i < l; i++) {
- injectHelpersCallbacks[i](this);
- }
- },
-
- /**
- This removes all helpers that have been registered, and resets and functions
- that were overridden by the helpers.
-
- Example:
-
- ```javascript
- App.removeTestHelpers();
- ```
-
- @public
- @method removeTestHelpers
- */
- removeTestHelpers: function() {
- for (var name in helpers) {
- this.helperContainer[name] = this.originalMethods[name];
- delete this.testHelpers[name];
- delete this.originalMethods[name];
- }
- }
- });
-
- // This method is no longer needed
- // But still here for backwards compatibility
- // of helper chaining
- function protoWrap(proto, name, callback, isAsync) {
- proto[name] = function() {
- var args = arguments;
- if (isAsync) {
- return callback.apply(this, args);
- } else {
- return this.then(function() {
- return callback.apply(this, args);
- });
- }
- };
- }
-
- Test.Promise = function() {
- RSVP.Promise.apply(this, arguments);
- Test.lastPromise = this;
- };
-
- Test.Promise.prototype = create(RSVP.Promise.prototype);
- Test.Promise.prototype.constructor = Test.Promise;
-
- // Patch `then` to isolate async methods
- // specifically `Ember.Test.lastPromise`
- var originalThen = RSVP.Promise.prototype.then;
- Test.Promise.prototype.then = function(onSuccess, onFailure) {
- return originalThen.call(this, function(val) {
- return isolate(onSuccess, val);
- }, onFailure);
- };
-
- // This method isolates nested async methods
- // so that they don't conflict with other last promises.
- //
- // 1. Set `Ember.Test.lastPromise` to null
- // 2. Invoke method
- // 3. Return the last promise created during method
- // 4. Restore `Ember.Test.lastPromise` to original value
- function isolate(fn, val) {
- var value, lastPromise;
-
- // Reset lastPromise for nested helpers
- Test.lastPromise = null;
-
- value = fn(val);
-
- lastPromise = Test.lastPromise;
-
- // If the method returned a promise
- // return that promise. If not,
- // return the last async helper's promise
- if ((value && (value instanceof Test.Promise)) || !lastPromise) {
- return value;
- } else {
- run(function() {
- lastPromise = Test.resolve(lastPromise).then(function() {
- return value;
- });
- });
- return lastPromise;
- }
- }
-
- __exports__["default"] = Test;
- });
-enifed("ember-views",
- ["ember-runtime","ember-views/system/jquery","ember-views/system/utils","ember-views/system/render_buffer","ember-views/system/ext","ember-views/views/states","ember-views/views/core_view","ember-views/views/view","ember-views/views/container_view","ember-views/views/collection_view","ember-views/views/component","ember-views/system/event_dispatcher","ember-views/mixins/view_target_action_support","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __exports__) {
- "use strict";
- /**
- Ember Views
-
- @module ember
- @submodule ember-views
- @requires ember-runtime
- @main ember-views
- */
-
- // BEGIN IMPORTS
- var Ember = __dependency1__["default"];
- var jQuery = __dependency2__["default"];
- var isSimpleClick = __dependency3__.isSimpleClick;
- var getViewClientRects = __dependency3__.getViewClientRects;
- var getViewBoundingClientRect = __dependency3__.getViewBoundingClientRect;
- var RenderBuffer = __dependency4__["default"];
- // for the side effect of extending Ember.run.queues
- var cloneStates = __dependency6__.cloneStates;
- var states = __dependency6__.states;
-
- var CoreView = __dependency7__["default"];
- var View = __dependency8__["default"];
- var ContainerView = __dependency9__["default"];
- var CollectionView = __dependency10__["default"];
- var Component = __dependency11__["default"];
-
- var EventDispatcher = __dependency12__["default"];
- var ViewTargetActionSupport = __dependency13__["default"];
- // END IMPORTS
-
- /**
- Alias for jQuery
-
- @method $
- @for Ember
- */
-
- // BEGIN EXPORTS
- Ember.$ = jQuery;
-
- Ember.ViewTargetActionSupport = ViewTargetActionSupport;
- Ember.RenderBuffer = RenderBuffer;
-
- var ViewUtils = Ember.ViewUtils = {};
- ViewUtils.isSimpleClick = isSimpleClick;
- ViewUtils.getViewClientRects = getViewClientRects;
- ViewUtils.getViewBoundingClientRect = getViewBoundingClientRect;
-
- Ember.CoreView = CoreView;
- Ember.View = View;
- Ember.View.states = states;
- Ember.View.cloneStates = cloneStates;
-
- Ember.ContainerView = ContainerView;
- Ember.CollectionView = CollectionView;
- Ember.Component = Component;
- Ember.EventDispatcher = EventDispatcher;
- // END EXPORTS
-
- __exports__["default"] = Ember;
- });
-enifed("ember-views/mixins/component_template_deprecation",
- ["ember-metal/core","ember-metal/property_get","ember-metal/mixin","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
- "use strict";
- var Ember = __dependency1__["default"];
- // Ember.deprecate
- var get = __dependency2__.get;
- var Mixin = __dependency3__.Mixin;
-
- /**
- The ComponentTemplateDeprecation mixin is used to provide a useful
- deprecation warning when using either `template` or `templateName` with
- a component. The `template` and `templateName` properties specified at
- extend time are moved to `layout` and `layoutName` respectively.
-
- `Ember.ComponentTemplateDeprecation` is used internally by Ember in
- `Ember.Component`.
-
- @class ComponentTemplateDeprecation
- @namespace Ember
- */
- __exports__["default"] = Mixin.create({
- /**
- @private
-
- Moves `templateName` to `layoutName` and `template` to `layout` at extend
- time if a layout is not also specified.
-
- Note that this currently modifies the mixin themselves, which is technically
- dubious but is practically of little consequence. This may change in the
- future.
-
- @method willMergeMixin
- @since 1.4.0
- */
- willMergeMixin: function(props) {
- // must call _super here to ensure that the ActionHandler
- // mixin is setup properly (moves actions -> _actions)
- //
- // Calling super is only OK here since we KNOW that
- // there is another Mixin loaded first.
- this._super.apply(this, arguments);
-
- var deprecatedProperty, replacementProperty;
- var layoutSpecified = (props.layoutName || props.layout || get(this, 'layoutName'));
-
- if (props.templateName && !layoutSpecified) {
- deprecatedProperty = 'templateName';
- replacementProperty = 'layoutName';
-
- props.layoutName = props.templateName;
- delete props['templateName'];
- }
-
- if (props.template && !layoutSpecified) {
- deprecatedProperty = 'template';
- replacementProperty = 'layout';
-
- props.layout = props.template;
- delete props['template'];
- }
-
- if (deprecatedProperty) {
- Ember.deprecate('Do not specify ' + deprecatedProperty + ' on a Component, use ' + replacementProperty + ' instead.', false);
- }
- }
- });
- });
-enifed("ember-views/mixins/view_target_action_support",
- ["ember-metal/mixin","ember-runtime/mixins/target_action_support","ember-metal/alias","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
- "use strict";
- var Mixin = __dependency1__.Mixin;
- var TargetActionSupport = __dependency2__["default"];
- var alias = __dependency3__["default"];
-
- /**
- `Ember.ViewTargetActionSupport` is a mixin that can be included in a
- view class to add a `triggerAction` method with semantics similar to
- the Handlebars `{{action}}` helper. It provides intelligent defaults
- for the action's target: the view's controller; and the context that is
- sent with the action: the view's context.
-
- Note: In normal Ember usage, the `{{action}}` helper is usually the best
- choice. This mixin is most often useful when you are doing more complex
- event handling in custom View subclasses.
-
- For example:
-
- ```javascript
- App.SaveButtonView = Ember.View.extend(Ember.ViewTargetActionSupport, {
- action: 'save',
- click: function() {
- this.triggerAction(); // Sends the `save` action, along with the current context
- // to the current controller
- }
- });
- ```
-
- The `action` can be provided as properties of an optional object argument
- to `triggerAction` as well.
-
- ```javascript
- App.SaveButtonView = Ember.View.extend(Ember.ViewTargetActionSupport, {
- click: function() {
- this.triggerAction({
- action: 'save'
- }); // Sends the `save` action, along with the current context
- // to the current controller
- }
- });
- ```
-
- @class ViewTargetActionSupport
- @namespace Ember
- @extends Ember.TargetActionSupport
- */
- __exports__["default"] = Mixin.create(TargetActionSupport, {
- /**
- @property target
- */
- target: alias('controller'),
- /**
- @property actionContext
- */
- actionContext: alias('context')
- });
- });
-enifed("ember-views/streams/context_stream",
- ["ember-metal/core","ember-metal/merge","ember-metal/platform","ember-metal/path_cache","ember-metal/streams/stream","ember-metal/streams/simple","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __exports__) {
- "use strict";
- var Ember = __dependency1__["default"];
-
- var merge = __dependency2__["default"];
- var create = __dependency3__.create;
- var isGlobal = __dependency4__.isGlobal;
- var Stream = __dependency5__["default"];
- var SimpleStream = __dependency6__["default"];
-
- function ContextStream(view) {
- Ember.assert("ContextStream error: the argument is not a view", view && view.isView);
- this.view = view;
- }
-
- ContextStream.prototype = create(Stream.prototype);
-
- merge(ContextStream.prototype, {
- value: function() {},
-
- _makeChildStream: function(key, _fullPath) {
- var stream;
-
- if (key === '' || key === 'this') {
- stream = this.view._baseContext;
- } else if (isGlobal(key) && Ember.lookup[key]) {
- Ember.deprecate("Global lookup of " + _fullPath + " from a Handlebars template is deprecated.");
- stream = new SimpleStream(Ember.lookup[key]);
- stream._isGlobal = true;
- } else if (key in this.view._keywords) {
- stream = new SimpleStream(this.view._keywords[key]);
- } else {
- stream = new SimpleStream(this.view._baseContext.get(key));
- }
-
- stream._isRoot = true;
-
- if (key === 'controller') {
- stream._isController = true;
- }
-
- return stream;
- }
- });
-
- __exports__["default"] = ContextStream;
- });
-enifed("ember-views/streams/key_stream",
- ["ember-metal/core","ember-metal/merge","ember-metal/platform","ember-metal/property_get","ember-metal/property_set","ember-metal/observer","ember-metal/streams/stream","ember-metal/streams/read","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __exports__) {
- "use strict";
- var Ember = __dependency1__["default"];
-
- var merge = __dependency2__["default"];
- var create = __dependency3__.create;
- var get = __dependency4__.get;
- var set = __dependency5__.set;
- var addObserver = __dependency6__.addObserver;
- var removeObserver = __dependency6__.removeObserver;
- var Stream = __dependency7__["default"];
- var read = __dependency8__.read;
-
- function KeyStream(source, key) {
- Ember.assert("KeyStream error: key must be a non-empty string", typeof key === 'string' && key.length > 0);
- Ember.assert("KeyStream error: key must not have a '.'", key.indexOf('.') === -1);
-
- this.source = source;
- this.obj = undefined;
- this.key = key;
-
- if (source && source.isStream) {
- source.subscribe(this._didChange, this);
- }
- }
-
- KeyStream.prototype = create(Stream.prototype);
-
- merge(KeyStream.prototype, {
- valueFn: function() {
- var prevObj = this.obj;
- var nextObj = read(this.source);
-
- if (nextObj !== prevObj) {
- if (prevObj && typeof prevObj === 'object') {
- removeObserver(prevObj, this.key, this, this._didChange);
- }
-
- if (nextObj && typeof nextObj === 'object') {
- addObserver(nextObj, this.key, this, this._didChange);
- }
-
- this.obj = nextObj;
- }
-
- if (nextObj) {
- return get(nextObj, this.key);
- }
- },
-
- setValue: function(value) {
- if (this.obj) {
- set(this.obj, this.key, value);
- }
- },
-
- setSource: function(nextSource) {
- Ember.assert("KeyStream error: source must be an object", typeof nextSource === 'object');
-
- var prevSource = this.source;
-
- if (nextSource !== prevSource) {
- if (prevSource && prevSource.isStream) {
- prevSource.unsubscribe(this._didChange, this);
- }
-
- if (nextSource && nextSource.isStream) {
- nextSource.subscribe(this._didChange, this);
- }
-
- this.source = nextSource;
- this.notify();
- }
- },
-
- _didChange: function() {
- this.notify();
- },
-
- destroy: function() {
- if (this.source && this.source.isStream) {
- this.source.unsubscribe(this._didChange, this);
- }
-
- if (this.obj && typeof this.obj === 'object') {
- removeObserver(this.obj, this.key, this, this._didChange);
- }
-
- this.source = undefined;
- this.obj = undefined;
-
- Stream.prototype.destroy.call(this);
- }
- });
-
- __exports__["default"] = KeyStream;
-
- // The transpiler does not resolve cycles, so we export
- // the `_makeChildStream` method onto `Stream` here.
-
- Stream.prototype._makeChildStream = function(key) {
- return new KeyStream(this, key);
- };
- });
-enifed("ember-views/streams/read",
- ["ember-metal/core","ember-metal/property_get","ember-metal/path_cache","ember-runtime/system/string","ember-metal/streams/read","ember-views/views/view","ember-runtime/mixins/controller","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __exports__) {
- "use strict";
- var Ember = __dependency1__["default"];
- var get = __dependency2__.get;
- var isGlobal = __dependency3__.isGlobal;
- var fmt = __dependency4__.fmt;
- var read = __dependency5__.read;
- var View = __dependency6__["default"];
- var ControllerMixin = __dependency7__["default"];
-
- function readViewFactory(object, container) {
- var value = read(object);
- var viewClass;
-
- if (typeof value === 'string') {
- if (isGlobal(value)) {
- viewClass = get(null, value);
- Ember.deprecate('Resolved the view "'+value+'" on the global context. Pass a view name to be looked up on the container instead, such as {{view "select"}}. http://emberjs.com/guides/deprecations#toc_global-lookup-of-views', !viewClass);
- } else {
- Ember.assert("View requires a container to resolve views not passed in through the context", !!container);
- viewClass = container.lookupFactory('view:'+value);
- }
- } else {
- viewClass = value;
- }
-
- Ember.assert(fmt(value+" must be a subclass of Ember.View, not %@", [viewClass]), View.detect(viewClass));
-
- return viewClass;
- }
-
- __exports__.readViewFactory = readViewFactory;function readUnwrappedModel(object) {
- if (object && object.isStream) {
- var result = object.value();
-
- // If the path is exactly `controller` then we don't unwrap it.
- if (!object._isController) {
- while (ControllerMixin.detect(result)) {
- result = get(result, 'model');
- }
- }
-
- return result;
- } else {
- return object;
- }
- }
-
- __exports__.readUnwrappedModel = readUnwrappedModel;
- });
-enifed("ember-views/system/action_manager",
- ["exports"],
- function(__exports__) {
- "use strict";
- /**
- @module ember
- @submodule ember-views
- */
-
- function ActionManager() {}
-
- /**
- Global action id hash.
-
- @private
- @property registeredActions
- @type Object
- */
- ActionManager.registeredActions = {};
-
- __exports__["default"] = ActionManager;
- });
-enifed("ember-views/system/event_dispatcher",
- ["ember-metal/core","ember-metal/property_get","ember-metal/property_set","ember-metal/is_none","ember-metal/run_loop","ember-metal/utils","ember-runtime/system/string","ember-runtime/system/object","ember-views/system/jquery","ember-views/system/action_manager","ember-views/views/view","ember-metal/merge","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __exports__) {
- "use strict";
- /**
- @module ember
- @submodule ember-views
- */
- var Ember = __dependency1__["default"];
- // Ember.assert
-
- var get = __dependency2__.get;
- var set = __dependency3__.set;
- var isNone = __dependency4__["default"];
- var run = __dependency5__["default"];
- var typeOf = __dependency6__.typeOf;
- var fmt = __dependency7__.fmt;
- var EmberObject = __dependency8__["default"];
- var jQuery = __dependency9__["default"];
- var ActionManager = __dependency10__["default"];
- var View = __dependency11__["default"];
- var merge = __dependency12__["default"];
-
- //ES6TODO:
- // find a better way to do Ember.View.views without global state
-
- /**
- `Ember.EventDispatcher` handles delegating browser events to their
- corresponding `Ember.Views.` For example, when you click on a view,
- `Ember.EventDispatcher` ensures that that view's `mouseDown` method gets
- called.
-
- @class EventDispatcher
- @namespace Ember
- @private
- @extends Ember.Object
- */
- __exports__["default"] = EmberObject.extend({
-
- /**
- The set of events names (and associated handler function names) to be setup
- and dispatched by the `EventDispatcher`. Custom events can added to this list at setup
- time, generally via the `Ember.Application.customEvents` hash. Only override this
- default set to prevent the EventDispatcher from listening on some events all together.
-
- This set will be modified by `setup` to also include any events added at that time.
-
- @property events
- @type Object
- */
- events: {
- touchstart : 'touchStart',
- touchmove : 'touchMove',
- touchend : 'touchEnd',
- touchcancel : 'touchCancel',
- keydown : 'keyDown',
- keyup : 'keyUp',
- keypress : 'keyPress',
- mousedown : 'mouseDown',
- mouseup : 'mouseUp',
- contextmenu : 'contextMenu',
- click : 'click',
- dblclick : 'doubleClick',
- mousemove : 'mouseMove',
- focusin : 'focusIn',
- focusout : 'focusOut',
- mouseenter : 'mouseEnter',
- mouseleave : 'mouseLeave',
- submit : 'submit',
- input : 'input',
- change : 'change',
- dragstart : 'dragStart',
- drag : 'drag',
- dragenter : 'dragEnter',
- dragleave : 'dragLeave',
- dragover : 'dragOver',
- drop : 'drop',
- dragend : 'dragEnd'
- },
-
- /**
- The root DOM element to which event listeners should be attached. Event
- listeners will be attached to the document unless this is overridden.
-
- Can be specified as a DOMElement or a selector string.
-
- The default body is a string since this may be evaluated before document.body
- exists in the DOM.
-
- @private
- @property rootElement
- @type DOMElement
- @default 'body'
- */
- rootElement: 'body',
-
- /**
- It enables events to be dispatched to the view's `eventManager.` When present,
- this object takes precedence over handling of events on the view itself.
-
- Note that most Ember applications do not use this feature. If your app also
- does not use it, consider setting this property to false to gain some performance
- improvement by allowing the EventDispatcher to skip the search for the
- `eventManager` on the view tree.
-
- ```javascript
- var EventDispatcher = Em.EventDispatcher.extend({
- events: {
- click : 'click',
- focusin : 'focusIn',
- focusout : 'focusOut',
- change : 'change'
- },
- canDispatchToEventManager: false
- });
- container.register('event_dispatcher:main', EventDispatcher);
- ```
-
- @property canDispatchToEventManager
- @type boolean
- @default 'true'
- @since 1.7.0
- */
- canDispatchToEventManager: true,
-
- /**
- Sets up event listeners for standard browser events.
-
- This will be called after the browser sends a `DOMContentReady` event. By
- default, it will set up all of the listeners on the document body. If you
- would like to register the listeners on a different element, set the event
- dispatcher's `root` property.
-
- @private
- @method setup
- @param addedEvents {Hash}
- */
- setup: function(addedEvents, rootElement) {
- var event, events = get(this, 'events');
-
- merge(events, addedEvents || {});
-
- if (!isNone(rootElement)) {
- set(this, 'rootElement', rootElement);
- }
-
- rootElement = jQuery(get(this, 'rootElement'));
-
- Ember.assert(fmt('You cannot use the same root element (%@) multiple times in an Ember.Application', [rootElement.selector || rootElement[0].tagName]), !rootElement.is('.ember-application'));
- Ember.assert('You cannot make a new Ember.Application using a root element that is a descendent of an existing Ember.Application', !rootElement.closest('.ember-application').length);
- Ember.assert('You cannot make a new Ember.Application using a root element that is an ancestor of an existing Ember.Application', !rootElement.find('.ember-application').length);
-
- rootElement.addClass('ember-application');
-
- Ember.assert('Unable to add "ember-application" class to rootElement. Make sure you set rootElement to the body or an element in the body.', rootElement.is('.ember-application'));
-
- for (event in events) {
- if (events.hasOwnProperty(event)) {
- this.setupHandler(rootElement, event, events[event]);
- }
- }
- },
-
- /**
- Registers an event listener on the rootElement. If the given event is
- triggered, the provided event handler will be triggered on the target view.
-
- If the target view does not implement the event handler, or if the handler
- returns `false`, the parent view will be called. The event will continue to
- bubble to each successive parent view until it reaches the top.
-
- @private
- @method setupHandler
- @param {Element} rootElement
- @param {String} event the browser-originated event to listen to
- @param {String} eventName the name of the method to call on the view
- */
- setupHandler: function(rootElement, event, eventName) {
- var self = this;
-
- rootElement.on(event + '.ember', '.ember-view', function(evt, triggeringManager) {
- var view = View.views[this.id];
- var result = true;
-
- var manager = self.canDispatchToEventManager ? self._findNearestEventManager(view, eventName) : null;
-
- if (manager && manager !== triggeringManager) {
- result = self._dispatchEvent(manager, evt, eventName, view);
- } else if (view) {
- result = self._bubbleEvent(view, evt, eventName);
- }
-
- return result;
- });
-
- rootElement.on(event + '.ember', '[data-ember-action]', function(evt) {
- var actionId = jQuery(evt.currentTarget).attr('data-ember-action');
- var action = ActionManager.registeredActions[actionId];
-
- // We have to check for action here since in some cases, jQuery will trigger
- // an event on `removeChild` (i.e. focusout) after we've already torn down the
- // action handlers for the view.
- if (action && action.eventName === eventName) {
- return action.handler(evt);
- }
- });
- },
-
- _findNearestEventManager: function(view, eventName) {
- var manager = null;
-
- while (view) {
- manager = get(view, 'eventManager');
- if (manager && manager[eventName]) { break; }
-
- view = get(view, 'parentView');
- }
-
- return manager;
- },
-
- _dispatchEvent: function(object, evt, eventName, view) {
- var result = true;
-
- var handler = object[eventName];
- if (typeOf(handler) === 'function') {
- result = run(object, handler, evt, view);
- // Do not preventDefault in eventManagers.
- evt.stopPropagation();
- }
- else {
- result = this._bubbleEvent(view, evt, eventName);
- }
-
- return result;
- },
-
- _bubbleEvent: function(view, evt, eventName) {
- return run.join(view, view.handleEvent, eventName, evt);
- },
-
- destroy: function() {
- var rootElement = get(this, 'rootElement');
- jQuery(rootElement).off('.ember', '**').removeClass('ember-application');
- return this._super();
- },
-
- toString: function() {
- return '(EventDispatcher)';
- }
- });
- });
-enifed("ember-views/system/ext",
- ["ember-metal/run_loop"],
- function(__dependency1__) {
- "use strict";
- /**
- @module ember
- @submodule ember-views
- */
-
- var run = __dependency1__["default"];
-
- // Add a new named queue for rendering views that happens
- // after bindings have synced, and a queue for scheduling actions
- // that that should occur after view rendering.
- run._addQueue('render', 'actions');
- run._addQueue('afterRender', 'render');
- });
-enifed("ember-views/system/jquery",
- ["ember-metal/core","ember-metal/enumerable_utils","exports"],
- function(__dependency1__, __dependency2__, __exports__) {
- "use strict";
- var Ember = __dependency1__["default"];
- // Ember.assert
-
- // ES6TODO: the functions on EnumerableUtils need their own exports
- var forEach = __dependency2__.forEach;
-
- /**
- Ember Views
-
- @module ember
- @submodule ember-views
- @requires ember-runtime
- @main ember-views
- */
-
- var jQuery = (Ember.imports && Ember.imports.jQuery) || (this && this.jQuery);
- if (!jQuery && typeof eriuqer === 'function') {
- jQuery = eriuqer('jquery');
- }
-
- Ember.assert("Ember Views require jQuery between 1.7 and 2.1", jQuery &&
- (jQuery().jquery.match(/^((1\.(7|8|9|10|11))|(2\.(0|1)))(\.\d+)?(pre|rc\d?)?/) ||
- Ember.ENV.FORCE_JQUERY));
-
- /**
- @module ember
- @submodule ember-views
- */
- if (jQuery) {
- // http://www.whatwg.org/specs/web-apps/current-work/multipage/dnd.html#dndevents
- var dragEvents = [
- 'dragstart',
- 'drag',
- 'dragenter',
- 'dragleave',
- 'dragover',
- 'drop',
- 'dragend'
- ];
-
- // Copies the `dataTransfer` property from a browser event object onto the
- // jQuery event object for the specified events
- forEach(dragEvents, function(eventName) {
- jQuery.event.fixHooks[eventName] = {
- props: ['dataTransfer']
- };
- });
- }
-
- __exports__["default"] = jQuery;
- });
-enifed("ember-views/system/render_buffer",
- ["ember-views/system/jquery","morph","ember-metal/core","ember-metal/platform","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
- "use strict";
- /**
- @module ember
- @submodule ember-views
- */
-
- var jQuery = __dependency1__["default"];
- var DOMHelper = __dependency2__.DOMHelper;
- var Ember = __dependency3__["default"];
- var create = __dependency4__.create;
-
- // The HTML spec allows for "omitted start tags". These tags are optional
- // when their intended child is the first thing in the parent tag. For
- // example, this is a tbody start tag:
- //
- // <table>
- // <tbody>
- // <tr>
- //
- // The tbody may be omitted, and the browser will accept and render:
- //
- // <table>
- // <tr>
- //
- // However, the omitted start tag will still be added to the DOM. Here
- // we test the string and context to see if the browser is about to
- // perform this cleanup, but with a special allowance for disregarding
- // <script tags. This disregarding of <script being the first child item
- // may bend the offical spec a bit, and is only needed for Handlebars
- // templates.
- //
- // http://www.whatwg.org/specs/web-apps/current-work/multipage/syntax.html#optional-tags
- // describes which tags are omittable. The spec for tbody and colgroup
- // explains this behavior:
- //
- // http://www.whatwg.org/specs/web-apps/current-work/multipage/tables.html#the-tbody-element
- // http://www.whatwg.org/specs/web-apps/current-work/multipage/tables.html#the-colgroup-element
- //
- var omittedStartTagChildren = {
- tr: document.createElement('tbody'),
- col: document.createElement('colgroup')
- };
-
- var omittedStartTagChildTest = /(?:<script)*.*?<([\w:]+)/i;
-
- function detectOmittedStartTag(string, contextualElement){
- // Omitted start tags are only inside table tags.
- if (contextualElement.tagName === 'TABLE') {
- var omittedStartTagChildMatch = omittedStartTagChildTest.exec(string);
- if (omittedStartTagChildMatch) {
- // It is already asserted that the contextual element is a table
- // and not the proper start tag. Just look up the start tag.
- return omittedStartTagChildren[omittedStartTagChildMatch[1].toLowerCase()];
- }
- }
- }
-
- function ClassSet() {
- this.seen = create(null);
- this.list = [];
- }
-
- ClassSet.prototype = {
- add: function(string) {
- if (this.seen[string] === true) { return; }
- this.seen[string] = true;
-
- this.list.push(string);
- }
- };
-
- var BAD_TAG_NAME_TEST_REGEXP = /[^a-zA-Z0-9\-]/;
- var BAD_TAG_NAME_REPLACE_REGEXP = /[^a-zA-Z0-9\-]/g;
-
- function stripTagName(tagName) {
- if (!tagName) {
- return tagName;
- }
-
- if (!BAD_TAG_NAME_TEST_REGEXP.test(tagName)) {
- return tagName;
- }
-
- return tagName.replace(BAD_TAG_NAME_REPLACE_REGEXP, '');
- }
-
- var BAD_CHARS_REGEXP = /&(?!\w+;)|[<>"'`]/g;
- var POSSIBLE_CHARS_REGEXP = /[&<>"'`]/;
-
- function escapeAttribute(value) {
- // Stolen shamelessly from Handlebars
-
- var escape = {
- "<": "&lt;",
- ">": "&gt;",
- '"': "&quot;",
- "'": "&#x27;",
- "`": "&#x60;"
- };
-
- var escapeChar = function(chr) {
- return escape[chr] || "&amp;";
- };
-
- var string = value.toString();
-
- if(!POSSIBLE_CHARS_REGEXP.test(string)) { return string; }
- return string.replace(BAD_CHARS_REGEXP, escapeChar);
- }
-
- // IE 6/7 have bugs around setting names on inputs during creation.
- // From http://msdn.microsoft.com/en-us/library/ie/ms536389(v=vs.85).aspx:
- // "To include the NAME attribute at run time on objects created with the createElement method, use the eTag."
- var canSetNameOnInputs = (function() {
- var div = document.createElement('div');
- var el = document.createElement('input');
-
- el.setAttribute('name', 'foo');
- div.appendChild(el);
-
- return !!div.innerHTML.match('foo');
- })();
-
- /**
- `Ember.renderBuffer` gathers information regarding the view and generates the
- final representation. `Ember.renderBuffer` will generate HTML which can be pushed
- to the DOM.
-
- ```javascript
- var buffer = Ember.renderBuffer('div', contextualElement);
- ```
-
- @method renderBuffer
- @namespace Ember
- @param {String} tagName tag name (such as 'div' or 'p') used for the buffer
- */
- __exports__["default"] = function renderBuffer(tagName, contextualElement) {
- return new _RenderBuffer(tagName, contextualElement); // jshint ignore:line
- }
-
- function _RenderBuffer(tagName, contextualElement) {
- this.tagName = tagName;
- this._outerContextualElement = contextualElement;
- this.buffer = null;
- this.childViews = [];
- this.dom = new DOMHelper();
- }
-
- _RenderBuffer.prototype = {
-
- reset: function(tagName, contextualElement) {
- this.tagName = tagName;
- this.buffer = null;
- this._element = null;
- this._outerContextualElement = contextualElement;
- this.elementClasses = null;
- this.elementId = null;
- this.elementAttributes = null;
- this.elementProperties = null;
- this.elementTag = null;
- this.elementStyle = null;
- this.childViews.length = 0;
- },
-
- // The root view's element
- _element: null,
-
- // The root view's contextualElement
- _outerContextualElement: null,
-
- /**
- An internal set used to de-dupe class names when `addClass()` is
- used. After each call to `addClass()`, the `classes` property
- will be updated.
-
- @private
- @property elementClasses
- @type Array
- @default null
- */
- elementClasses: null,
-
- /**
- Array of class names which will be applied in the class attribute.
-
- You can use `setClasses()` to set this property directly. If you
- use `addClass()`, it will be maintained for you.
-
- @property classes
- @type Array
- @default null
- */
- classes: null,
-
- /**
- The id in of the element, to be applied in the id attribute.
-
- You should not set this property yourself, rather, you should use
- the `id()` method of `Ember.RenderBuffer`.
-
- @property elementId
- @type String
- @default null
- */
- elementId: null,
-
- /**
- A hash keyed on the name of the attribute and whose value will be
- applied to that attribute. For example, if you wanted to apply a
- `data-view="Foo.bar"` property to an element, you would set the
- elementAttributes hash to `{'data-view':'Foo.bar'}`.
-
- You should not maintain this hash yourself, rather, you should use
- the `attr()` method of `Ember.RenderBuffer`.
-
- @property elementAttributes
- @type Hash
- @default {}
- */
- elementAttributes: null,
-
- /**
- A hash keyed on the name of the properties and whose value will be
- applied to that property. For example, if you wanted to apply a
- `checked=true` property to an element, you would set the
- elementProperties hash to `{'checked':true}`.
-
- You should not maintain this hash yourself, rather, you should use
- the `prop()` method of `Ember.RenderBuffer`.
-
- @property elementProperties
- @type Hash
- @default {}
- */
- elementProperties: null,
-
- /**
- The tagname of the element an instance of `Ember.RenderBuffer` represents.
-
- Usually, this gets set as the first parameter to `Ember.RenderBuffer`. For
- example, if you wanted to create a `p` tag, then you would call
-
- ```javascript
- Ember.RenderBuffer('p', contextualElement)
- ```
-
- @property elementTag
- @type String
- @default null
- */
- elementTag: null,
-
- /**
- A hash keyed on the name of the style attribute and whose value will
- be applied to that attribute. For example, if you wanted to apply a
- `background-color:black;` style to an element, you would set the
- elementStyle hash to `{'background-color':'black'}`.
-
- You should not maintain this hash yourself, rather, you should use
- the `style()` method of `Ember.RenderBuffer`.
-
- @property elementStyle
- @type Hash
- @default {}
- */
- elementStyle: null,
-
- pushChildView: function (view) {
- var index = this.childViews.length;
- this.childViews[index] = view;
- this.push("<script id='morph-"+index+"' type='text/x-placeholder'>\x3C/script>");
- },
-
- hydrateMorphs: function (contextualElement) {
- var childViews = this.childViews;
- var el = this._element;
- for (var i=0,l=childViews.length; i<l; i++) {
- var childView = childViews[i];
- var ref = el.querySelector('#morph-'+i);
-
- Ember.assert('An error occured while setting up template bindings. Please check ' +
- (childView && childView._parentView && childView._parentView._debugTemplateName ?
- '"' + childView._parentView._debugTemplateName + '" template ' :
- ''
- ) + 'for invalid markup or bindings within HTML comments.',
- ref);
-
- var parent = ref.parentNode;
-
- childView._morph = this.dom.insertMorphBefore(
- parent,
- ref,
- parent.nodeType === 1 ? parent : contextualElement
- );
- parent.removeChild(ref);
- }
- },
-
- /**
- Adds a string of HTML to the `RenderBuffer`.
-
- @method push
- @param {String} string HTML to push into the buffer
- @chainable
- */
- push: function(content) {
- if (this.buffer === null) {
- this.buffer = '';
- }
- this.buffer += content;
- return this;
- },
-
- /**
- Adds a class to the buffer, which will be rendered to the class attribute.
-
- @method addClass
- @param {String} className Class name to add to the buffer
- @chainable
- */
- addClass: function(className) {
- // lazily create elementClasses
- this.elementClasses = (this.elementClasses || new ClassSet());
- this.elementClasses.add(className);
- this.classes = this.elementClasses.list;
-
- return this;
- },
-
- setClasses: function(classNames) {
- this.elementClasses = null;
- var len = classNames.length;
- var i;
- for (i = 0; i < len; i++) {
- this.addClass(classNames[i]);
- }
- },
-
- /**
- Sets the elementID to be used for the element.
-
- @method id
- @param {String} id
- @chainable
- */
- id: function(id) {
- this.elementId = id;
- return this;
- },
-
- // duck type attribute functionality like jQuery so a render buffer
- // can be used like a jQuery object in attribute binding scenarios.
-
- /**
- Adds an attribute which will be rendered to the element.
-
- @method attr
- @param {String} name The name of the attribute
- @param {String} value The value to add to the attribute
- @chainable
- @return {Ember.RenderBuffer|String} this or the current attribute value
- */
- attr: function(name, value) {
- var attributes = this.elementAttributes = (this.elementAttributes || {});
-
- if (arguments.length === 1) {
- return attributes[name];
- } else {
- attributes[name] = value;
- }
-
- return this;
- },
-
- /**
- Remove an attribute from the list of attributes to render.
-
- @method removeAttr
- @param {String} name The name of the attribute
- @chainable
- */
- removeAttr: function(name) {
- var attributes = this.elementAttributes;
- if (attributes) { delete attributes[name]; }
-
- return this;
- },
-
- /**
- Adds a property which will be rendered to the element.
-
- @method prop
- @param {String} name The name of the property
- @param {String} value The value to add to the property
- @chainable
- @return {Ember.RenderBuffer|String} this or the current property value
- */
- prop: function(name, value) {
- var properties = this.elementProperties = (this.elementProperties || {});
-
- if (arguments.length === 1) {
- return properties[name];
- } else {
- properties[name] = value;
- }
-
- return this;
- },
-
- /**
- Remove an property from the list of properties to render.
-
- @method removeProp
- @param {String} name The name of the property
- @chainable
- */
- removeProp: function(name) {
- var properties = this.elementProperties;
- if (properties) { delete properties[name]; }
-
- return this;
- },
-
- /**
- Adds a style to the style attribute which will be rendered to the element.
-
- @method style
- @param {String} name Name of the style
- @param {String} value
- @chainable
- */
- style: function(name, value) {
- this.elementStyle = (this.elementStyle || {});
-
- this.elementStyle[name] = value;
- return this;
- },
-
- generateElement: function() {
- var tagName = this.tagName;
- var id = this.elementId;
- var classes = this.classes;
- var attrs = this.elementAttributes;
- var props = this.elementProperties;
- var style = this.elementStyle;
- var styleBuffer = '';
- var attr, prop, tagString;
-
- if (attrs && attrs.name && !canSetNameOnInputs) {
- // IE allows passing a tag to createElement. See note on `canSetNameOnInputs` above as well.
- tagString = '<'+stripTagName(tagName)+' name="'+escapeAttribute(attrs.name)+'">';
- } else {
- tagString = tagName;
- }
-
- var element = this.dom.createElement(tagString, this.outerContextualElement());
- var $element = jQuery(element);
-
- if (id) {
- this.dom.setAttribute(element, 'id', id);
- this.elementId = null;
- }
- if (classes) {
- this.dom.setAttribute(element, 'class', classes.join(' '));
- this.classes = null;
- this.elementClasses = null;
- }
-
- if (style) {
- for (prop in style) {
- if (style.hasOwnProperty(prop)) {
- styleBuffer += (prop + ':' + style[prop] + ';');
- }
- }
-
- this.dom.setAttribute(element, 'style', styleBuffer);
-
- this.elementStyle = null;
- }
-
- if (attrs) {
- for (attr in attrs) {
- if (attrs.hasOwnProperty(attr)) {
- this.dom.setAttribute(element, attr, attrs[attr]);
- }
- }
-
- this.elementAttributes = null;
- }
-
- if (props) {
- for (prop in props) {
- if (props.hasOwnProperty(prop)) {
- $element.prop(prop, props[prop]);
- }
- }
-
- this.elementProperties = null;
- }
-
- this._element = element;
- },
-
- /**
- @method element
- @return {DOMElement} The element corresponding to the generated HTML
- of this buffer
- */
- element: function() {
- var content = this.innerContent();
- // No content means a text node buffer, with the content
- // in _element. HandlebarsBoundView is an example.
- if (content === null) {
- return this._element;
- }
-
- var contextualElement = this.innerContextualElement(content);
- this.dom.detectNamespace(contextualElement);
-
- if (!this._element) {
- this._element = document.createDocumentFragment();
- }
-
- var nodes = this.dom.parseHTML(content, contextualElement);
- while (nodes[0]) {
- this._element.appendChild(nodes[0]);
- }
- this.hydrateMorphs(contextualElement);
-
- return this._element;
- },
-
- /**
- Generates the HTML content for this buffer.
-
- @method string
- @return {String} The generated HTML
- */
- string: function() {
- if (this._element) {
- // Firefox versions < 11 do not have support for element.outerHTML.
- var thisElement = this.element();
- var outerHTML = thisElement.outerHTML;
- if (typeof outerHTML === 'undefined') {
- return jQuery('<div/>').append(thisElement).html();
- }
- return outerHTML;
- } else {
- return this.innerString();
- }
- },
-
- outerContextualElement: function() {
- if (!this._outerContextualElement) {
- Ember.deprecate("The render buffer expects an outer contextualElement to exist." +
- " This ensures DOM that requires context is correctly generated (tr, SVG tags)." +
- " Defaulting to document.body, but this will be removed in the future");
- this.outerContextualElement = document.body;
- }
- return this._outerContextualElement;
- },
-
- innerContextualElement: function(html) {
- var innerContextualElement;
- if (this._element && this._element.nodeType === 1) {
- innerContextualElement = this._element;
- } else {
- innerContextualElement = this.outerContextualElement();
- }
-
- var omittedStartTag;
- if (html) {
- omittedStartTag = detectOmittedStartTag(html, innerContextualElement);
- }
- return omittedStartTag || innerContextualElement;
- },
-
- innerString: function() {
- var content = this.innerContent();
- if (content && !content.nodeType) {
- return content;
- }
- },
-
- innerContent: function() {
- return this.buffer;
- }
- };
- });
-enifed("ember-views/system/renderer",
- ["ember-metal/core","ember-metal-views/renderer","ember-metal/platform","ember-views/system/render_buffer","ember-metal/run_loop","ember-metal/property_set","ember-metal/instrumentation","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __exports__) {
- "use strict";
- var Ember = __dependency1__["default"];
- var Renderer = __dependency2__["default"];
- var create = __dependency3__.create;
- var renderBuffer = __dependency4__["default"];
- var run = __dependency5__["default"];
- var set = __dependency6__.set;
- var _instrumentStart = __dependency7__._instrumentStart;
- var subscribers = __dependency7__.subscribers;
-
- function EmberRenderer() {
- this.buffer = renderBuffer();
- this._super$constructor();
- }
-
- EmberRenderer.prototype = create(Renderer.prototype);
- EmberRenderer.prototype.constructor = EmberRenderer;
- EmberRenderer.prototype._super$constructor = Renderer;
-
- EmberRenderer.prototype.scheduleRender =
- function EmberRenderer_scheduleRender(ctx, fn) {
- return run.scheduleOnce('render', ctx, fn);
- };
-
- EmberRenderer.prototype.cancelRender =
- function EmberRenderer_cancelRender(id) {
- run.cancel(id);
- };
-
- EmberRenderer.prototype.createElement =
- function EmberRenderer_createElement(view, contextualElement) {
- // If this is the top-most view, start a new buffer. Otherwise,
- // create a new buffer relative to the original using the
- // provided buffer operation (for example, `insertAfter` will
- // insert a new buffer after the "parent buffer").
- var tagName = view.tagName;
- var classNameBindings = view.classNameBindings;
- var taglessViewWithClassBindings = tagName === '' && classNameBindings.length > 0;
-
- if (tagName === null || tagName === undefined) {
- tagName = 'div';
- }
-
- Ember.assert('You cannot use `classNameBindings` on a tag-less view: ' + view.toString(), !taglessViewWithClassBindings);
-
- var buffer = view.buffer = this.buffer;
- buffer.reset(tagName, contextualElement);
-
- if (view.beforeRender) {
- view.beforeRender(buffer);
- }
-
- if (tagName !== '') {
- if (view.applyAttributesToBuffer) {
- view.applyAttributesToBuffer(buffer);
- }
- buffer.generateElement();
- }
-
- if (view.render) {
- view.render(buffer);
- }
-
- if (view.afterRender) {
- view.afterRender(buffer);
- }
-
- var element = buffer.element();
-
- view.buffer = null;
- if (element && element.nodeType === 1) {
- // We have hooks, we shouldn't make element observable
- // consider just doing view.element = element
- set(view, 'element', element);
- }
- return element;
- };
-
- EmberRenderer.prototype.destroyView = function destroyView(view) {
- view.removedFromDOM = true;
- view.destroy();
- };
-
- EmberRenderer.prototype.childViews = function childViews(view) {
- return view._childViews;
- };
-
- Renderer.prototype.willCreateElement = function (view) {
- if (subscribers.length && view.instrumentDetails) {
- view._instrumentEnd = _instrumentStart('render.'+view.instrumentName, function viewInstrumentDetails() {
- var details = {};
- view.instrumentDetails(details);
- return details;
- });
- }
- if (view._transitionTo) {
- view._transitionTo('inBuffer');
- }
- }; // inBuffer
- Renderer.prototype.didCreateElement = function (view) {
- if (view._transitionTo) {
- view._transitionTo('hasElement');
- }
- if (view._instrumentEnd) {
- view._instrumentEnd();
- }
- }; // hasElement
- Renderer.prototype.willInsertElement = function (view) {
- if (view.trigger) { view.trigger('willInsertElement'); }
- }; // will place into DOM
- Renderer.prototype.didInsertElement = function (view) {
- if (view._transitionTo) {
- view._transitionTo('inDOM');
- }
- if (view.trigger) { view.trigger('didInsertElement'); }
- }; // inDOM // placed into DOM
-
- Renderer.prototype.willRemoveElement = function (view) {};
-
- Renderer.prototype.willDestroyElement = function (view) {
- if (view.trigger) { view.trigger('willDestroyElement'); }
- if (view.trigger) { view.trigger('willClearRender'); }
- };
-
- Renderer.prototype.didDestroyElement = function (view) {
- set(view, 'element', null);
- if (view._transitionTo) {
- view._transitionTo('preRender');
- }
- }; // element destroyed so view.destroy shouldn't try to remove it removedFromDOM
-
- __exports__["default"] = EmberRenderer;
- });
-enifed("ember-views/system/utils",
- ["exports"],
- function(__exports__) {
- "use strict";
- /**
- @module ember
- @submodule ember-views
- */
-
- function isSimpleClick(event) {
- var modifier = event.shiftKey || event.metaKey || event.altKey || event.ctrlKey;
- var secondaryClick = event.which > 1; // IE9 may return undefined
-
- return !modifier && !secondaryClick;
- }
-
- __exports__.isSimpleClick = isSimpleClick;/**
- @private
- @method getViewRange
- @param {Ember.View} view
- */
- function getViewRange(view) {
- var range = document.createRange();
- range.setStartAfter(view._morph.start);
- range.setEndBefore(view._morph.end);
- return range;
- }
-
- /**
- `getViewClientRects` provides information about the position of the border
- box edges of a view relative to the viewport.
-
- It is only intended to be used by development tools like the Ember Inpsector
- and may not work on older browsers.
-
- @private
- @method getViewClientRects
- @param {Ember.View} view
- */
- function getViewClientRects(view) {
- var range = getViewRange(view);
- return range.getClientRects();
- }
-
- __exports__.getViewClientRects = getViewClientRects;/**
- `getViewBoundingClientRect` provides information about the position of the
- bounding border box edges of a view relative to the viewport.
-
- It is only intended to be used by development tools like the Ember Inpsector
- and may not work on older browsers.
-
- @private
- @method getViewBoundingClientRect
- @param {Ember.View} view
- */
- function getViewBoundingClientRect(view) {
- var range = getViewRange(view);
- return range.getBoundingClientRect();
- }
-
- __exports__.getViewBoundingClientRect = getViewBoundingClientRect;
- });
-enifed("ember-views/views/collection_view",
- ["ember-metal/core","ember-metal/binding","ember-metal/property_get","ember-metal/property_set","ember-runtime/system/string","ember-views/views/container_view","ember-views/views/core_view","ember-views/views/view","ember-metal/mixin","ember-views/streams/read","ember-runtime/mixins/array","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __exports__) {
- "use strict";
-
- /**
- @module ember
- @submodule ember-views
- */
-
- var Ember = __dependency1__["default"];
- // Ember.assert
- var isGlobalPath = __dependency2__.isGlobalPath;
- var get = __dependency3__.get;
- var set = __dependency4__.set;
- var fmt = __dependency5__.fmt;
- var ContainerView = __dependency6__["default"];
- var CoreView = __dependency7__["default"];
- var View = __dependency8__["default"];
- var observer = __dependency9__.observer;
- var beforeObserver = __dependency9__.beforeObserver;
- var readViewFactory = __dependency10__.readViewFactory;
- var EmberArray = __dependency11__["default"];
-
- /**
- `Ember.CollectionView` is an `Ember.View` descendent responsible for managing
- a collection (an array or array-like object) by maintaining a child view object
- and associated DOM representation for each item in the array and ensuring
- that child views and their associated rendered HTML are updated when items in
- the array are added, removed, or replaced.
-
- ## Setting content
-
- The managed collection of objects is referenced as the `Ember.CollectionView`
- instance's `content` property.
-
- ```javascript
- someItemsView = Ember.CollectionView.create({
- content: ['A', 'B','C']
- })
- ```
-
- The view for each item in the collection will have its `content` property set
- to the item.
-
- ## Specifying `itemViewClass`
-
- By default the view class for each item in the managed collection will be an
- instance of `Ember.View`. You can supply a different class by setting the
- `CollectionView`'s `itemViewClass` property.
-
- Given the following application code:
-
- ```javascript
- var App = Ember.Application.create();
- App.ItemListView = Ember.CollectionView.extend({
- classNames: ['a-collection'],
- content: ['A','B','C'],
- itemViewClass: Ember.View.extend({
- template: Ember.Handlebars.compile("the letter: {{view.content}}")
- })
- });
- ```
-
- And a simple application template:
-
- ```handlebars
- {{view 'item-list'}}
- ```
-
- The following HTML will result:
-
- ```html
- <div class="ember-view a-collection">
- <div class="ember-view">the letter: A</div>
- <div class="ember-view">the letter: B</div>
- <div class="ember-view">the letter: C</div>
- </div>
- ```
-
- ## Automatic matching of parent/child tagNames
-
- Setting the `tagName` property of a `CollectionView` to any of
- "ul", "ol", "table", "thead", "tbody", "tfoot", "tr", or "select" will result
- in the item views receiving an appropriately matched `tagName` property.
-
- Given the following application code:
-
- ```javascript
- var App = Ember.Application.create();
- App.UnorderedListView = Ember.CollectionView.create({
- tagName: 'ul',
- content: ['A','B','C'],
- itemViewClass: Ember.View.extend({
- template: Ember.Handlebars.compile("the letter: {{view.content}}")
- })
- });
- ```
-
- And a simple application template:
-
- ```handlebars
- {{view 'unordered-list-view'}}
- ```
-
- The following HTML will result:
-
- ```html
- <ul class="ember-view a-collection">
- <li class="ember-view">the letter: A</li>
- <li class="ember-view">the letter: B</li>
- <li class="ember-view">the letter: C</li>
- </ul>
- ```
-
- Additional `tagName` pairs can be provided by adding to
- `Ember.CollectionView.CONTAINER_MAP`. For example:
-
- ```javascript
- Ember.CollectionView.CONTAINER_MAP['article'] = 'section'
- ```
-
- ## Programmatic creation of child views
-
- For cases where additional customization beyond the use of a single
- `itemViewClass` or `tagName` matching is required CollectionView's
- `createChildView` method can be overidden:
-
- ```javascript
- App.CustomCollectionView = Ember.CollectionView.extend({
- createChildView: function(viewClass, attrs) {
- if (attrs.content.kind == 'album') {
- viewClass = App.AlbumView;
- } else {
- viewClass = App.SongView;
- }
- return this._super(viewClass, attrs);
- }
- });
- ```
-
- ## Empty View
-
- You can provide an `Ember.View` subclass to the `Ember.CollectionView`
- instance as its `emptyView` property. If the `content` property of a
- `CollectionView` is set to `null` or an empty array, an instance of this view
- will be the `CollectionView`s only child.
-
- ```javascript
- var App = Ember.Application.create();
- App.ListWithNothing = Ember.CollectionView.create({
- classNames: ['nothing'],
- content: null,
- emptyView: Ember.View.extend({
- template: Ember.Handlebars.compile("The collection is empty")
- })
- });
- ```
-
- And a simple application template:
-
- ```handlebars
- {{view 'list-with-nothing'}}
- ```
-
- The following HTML will result:
-
- ```html
- <div class="ember-view nothing">
- <div class="ember-view">
- The collection is empty
- </div>
- </div>
- ```
-
- ## Adding and Removing items
-
- The `childViews` property of a `CollectionView` should not be directly
- manipulated. Instead, add, remove, replace items from its `content` property.
- This will trigger appropriate changes to its rendered HTML.
-
-
- @class CollectionView
- @namespace Ember
- @extends Ember.ContainerView
- @since Ember 0.9
- */
- var CollectionView = ContainerView.extend({
-
- /**
- A list of items to be displayed by the `Ember.CollectionView`.
-
- @property content
- @type Ember.Array
- @default null
- */
- content: null,
-
- /**
- This provides metadata about what kind of empty view class this
- collection would like if it is being instantiated from another
- system (like Handlebars)
-
- @private
- @property emptyViewClass
- */
- emptyViewClass: View,
-
- /**
- An optional view to display if content is set to an empty array.
-
- @property emptyView
- @type Ember.View
- @default null
- */
- emptyView: null,
-
- /**
- @property itemViewClass
- @type Ember.View
- @default Ember.View
- */
- itemViewClass: View,
-
- /**
- Setup a CollectionView
-
- @method init
- */
- init: function() {
- var ret = this._super();
- this._contentDidChange();
- return ret;
- },
-
- /**
- Invoked when the content property is about to change. Notifies observers that the
- entire array content will change.
-
- @private
- @method _contentWillChange
- */
- _contentWillChange: beforeObserver('content', function() {
- var content = this.get('content');
-
- if (content) { content.removeArrayObserver(this); }
- var len = content ? get(content, 'length') : 0;
- this.arrayWillChange(content, 0, len);
- }),
-
- /**
- Check to make sure that the content has changed, and if so,
- update the children directly. This is always scheduled
- asynchronously, to allow the element to be created before
- bindings have synchronized and vice versa.
-
- @private
- @method _contentDidChange
- */
- _contentDidChange: observer('content', function() {
- var content = get(this, 'content');
-
- if (content) {
- this._assertArrayLike(content);
- content.addArrayObserver(this);
- }
-
- var len = content ? get(content, 'length') : 0;
- this.arrayDidChange(content, 0, null, len);
- }),
-
- /**
- Ensure that the content implements Ember.Array
-
- @private
- @method _assertArrayLike
- */
- _assertArrayLike: function(content) {
- Ember.assert(fmt("an Ember.CollectionView's content must implement Ember.Array. You passed %@", [content]), EmberArray.detect(content));
- },
-
- /**
- Removes the content and content observers.
-
- @method destroy
- */
- destroy: function() {
- if (!this._super()) { return; }
-
- var content = get(this, 'content');
- if (content) { content.removeArrayObserver(this); }
-
- if (this._createdEmptyView) {
- this._createdEmptyView.destroy();
- }
-
- return this;
- },
-
- /**
- Called when a mutation to the underlying content array will occur.
-
- This method will remove any views that are no longer in the underlying
- content array.
-
- Invokes whenever the content array itself will change.
-
- @method arrayWillChange
- @param {Array} content the managed collection of objects
- @param {Number} start the index at which the changes will occurr
- @param {Number} removed number of object to be removed from content
- */
- arrayWillChange: function(content, start, removedCount) {
- // If the contents were empty before and this template collection has an
- // empty view remove it now.
- var emptyView = get(this, 'emptyView');
- if (emptyView && emptyView instanceof View) {
- emptyView.removeFromParent();
- }
-
- // Loop through child views that correspond with the removed items.
- // Note that we loop from the end of the array to the beginning because
- // we are mutating it as we go.
- var childViews = this._childViews;
- var childView, idx;
-
- for (idx = start + removedCount - 1; idx >= start; idx--) {
- childView = childViews[idx];
- childView.destroy();
- }
- },
-
- /**
- Called when a mutation to the underlying content array occurs.
-
- This method will replay that mutation against the views that compose the
- `Ember.CollectionView`, ensuring that the view reflects the model.
-
- This array observer is added in `contentDidChange`.
-
- @method arrayDidChange
- @param {Array} content the managed collection of objects
- @param {Number} start the index at which the changes occurred
- @param {Number} removed number of object removed from content
- @param {Number} added number of object added to content
- */
- arrayDidChange: function(content, start, removed, added) {
- var addedViews = [];
- var view, item, idx, len, itemViewClass, emptyView, itemViewProps;
-
- len = content ? get(content, 'length') : 0;
-
- if (len) {
- itemViewProps = this._itemViewProps || {};
- itemViewClass = get(this, 'itemViewClass');
-
- itemViewClass = readViewFactory(itemViewClass, this.container);
-
- for (idx = start; idx < start+added; idx++) {
- item = content.objectAt(idx);
-
- itemViewProps.content = item;
- itemViewProps.contentIndex = idx;
-
- view = this.createChildView(itemViewClass, itemViewProps);
-
- addedViews.push(view);
- }
- } else {
- emptyView = get(this, 'emptyView');
-
- if (!emptyView) { return; }
-
- if ('string' === typeof emptyView && isGlobalPath(emptyView)) {
- emptyView = get(emptyView) || emptyView;
- }
-
- emptyView = this.createChildView(emptyView);
-
- addedViews.push(emptyView);
- set(this, 'emptyView', emptyView);
-
- if (CoreView.detect(emptyView)) {
- this._createdEmptyView = emptyView;
- }
- }
-
- this.replace(start, 0, addedViews);
- },
-
- /**
- Instantiates a view to be added to the childViews array during view
- initialization. You generally will not call this method directly unless
- you are overriding `createChildViews()`. Note that this method will
- automatically configure the correct settings on the new view instance to
- act as a child of the parent.
-
- The tag name for the view will be set to the tagName of the viewClass
- passed in.
-
- @method createChildView
- @param {Class} viewClass
- @param {Hash} [attrs] Attributes to add
- @return {Ember.View} new instance
- */
- createChildView: function(view, attrs) {
- view = this._super(view, attrs);
-
- var itemTagName = get(view, 'tagName');
-
- if (itemTagName === null || itemTagName === undefined) {
- itemTagName = CollectionView.CONTAINER_MAP[get(this, 'tagName')];
- set(view, 'tagName', itemTagName);
- }
-
- return view;
- }
- });
-
- /**
- A map of parent tags to their default child tags. You can add
- additional parent tags if you want collection views that use
- a particular parent tag to default to a child tag.
-
- @property CONTAINER_MAP
- @type Hash
- @static
- @final
- */
- CollectionView.CONTAINER_MAP = {
- ul: 'li',
- ol: 'li',
- table: 'tr',
- thead: 'tr',
- tbody: 'tr',
- tfoot: 'tr',
- tr: 'td',
- select: 'option'
- };
-
- __exports__["default"] = CollectionView;
- });
-enifed("ember-views/views/component",
- ["ember-metal/core","ember-views/mixins/component_template_deprecation","ember-runtime/mixins/target_action_support","ember-views/views/view","ember-metal/property_get","ember-metal/property_set","ember-metal/is_none","ember-metal/computed","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __exports__) {
- "use strict";
- var Ember = __dependency1__["default"];
- // Ember.assert, Ember.Handlebars
-
- var ComponentTemplateDeprecation = __dependency2__["default"];
- var TargetActionSupport = __dependency3__["default"];
- var View = __dependency4__["default"];
-
- var get = __dependency5__.get;
- var set = __dependency6__.set;
- var isNone = __dependency7__["default"];
-
- var computed = __dependency8__.computed;
-
- var a_slice = Array.prototype.slice;
-
- /**
- @module ember
- @submodule ember-views
- */
-
- /**
- An `Ember.Component` is a view that is completely
- isolated. Property access in its templates go
- to the view object and actions are targeted at
- the view object. There is no access to the
- surrounding context or outer controller; all
- contextual information must be passed in.
-
- The easiest way to create an `Ember.Component` is via
- a template. If you name a template
- `components/my-foo`, you will be able to use
- `{{my-foo}}` in other templates, which will make
- an instance of the isolated component.
-
- ```handlebars
- {{app-profile person=currentUser}}
- ```
-
- ```handlebars
- <!-- app-profile template -->
- <h1>{{person.title}}</h1>
- <img {{bind-attr src=person.avatar}}>
- <p class='signature'>{{person.signature}}</p>
- ```
-
- You can use `yield` inside a template to
- include the **contents** of any block attached to
- the component. The block will be executed in the
- context of the surrounding context or outer controller:
-
- ```handlebars
- {{#app-profile person=currentUser}}
- <p>Admin mode</p>
- {{! Executed in the controller's context. }}
- {{/app-profile}}
- ```
-
- ```handlebars
- <!-- app-profile template -->
- <h1>{{person.title}}</h1>
- {{! Executed in the components context. }}
- {{yield}} {{! block contents }}
- ```
-
- If you want to customize the component, in order to
- handle events or actions, you implement a subclass
- of `Ember.Component` named after the name of the
- component. Note that `Component` needs to be appended to the name of
- your subclass like `AppProfileComponent`.
-
- For example, you could implement the action
- `hello` for the `app-profile` component:
-
- ```javascript
- App.AppProfileComponent = Ember.Component.extend({
- actions: {
- hello: function(name) {
- console.log("Hello", name);
- }
- }
- });
- ```
-
- And then use it in the component's template:
-
- ```handlebars
- <!-- app-profile template -->
-
- <h1>{{person.title}}</h1>
- {{yield}} <!-- block contents -->
-
- <button {{action 'hello' person.name}}>
- Say Hello to {{person.name}}
- </button>
- ```
-
- Components must have a `-` in their name to avoid
- conflicts with built-in controls that wrap HTML
- elements. This is consistent with the same
- requirement in web components.
-
- @class Component
- @namespace Ember
- @extends Ember.View
- */
- var Component = View.extend(TargetActionSupport, ComponentTemplateDeprecation, {
- instrumentName: 'component',
- instrumentDisplay: computed(function() {
- if (this._debugContainerKey) {
- return '{{' + this._debugContainerKey.split(':')[1] + '}}';
- }
- }),
-
- init: function() {
- this._super();
- set(this, 'context', this);
- set(this, 'controller', this);
- },
-
- defaultLayout: function(context, options){
- Ember.Handlebars.helpers['yield'].call(context, options);
- },
-
- /**
- A components template property is set by passing a block
- during its invocation. It is executed within the parent context.
-
- Example:
-
- ```handlebars
- {{#my-component}}
- // something that is run in the context
- // of the parent context
- {{/my-component}}
- ```
-
- Specifying a template directly to a component is deprecated without
- also specifying the layout property.
-
- @deprecated
- @property template
- */
- template: computed(function(key, value) {
- if (value !== undefined) { return value; }
-
- var templateName = get(this, 'templateName');
- var template = this.templateForName(templateName, 'template');
-
- Ember.assert("You specified the templateName " + templateName + " for " + this + ", but it did not exist.", !templateName || template);
-
- return template || get(this, 'defaultTemplate');
- }).property('templateName'),
-
- /**
- Specifying a components `templateName` is deprecated without also
- providing the `layout` or `layoutName` properties.
-
- @deprecated
- @property templateName
- */
- templateName: null,
-
- _setupKeywords: function() {
- this._keywords.view.setSource(this);
- },
-
- _yield: function(context, options) {
- var view = options.data.view;
- var parentView = this._parentView;
- var template = get(this, 'template');
-
- if (template) {
- Ember.assert("A Component must have a parent view in order to yield.", parentView);
-
- view.appendChild(View, {
- isVirtual: true,
- tagName: '',
- _contextView: parentView,
- template: template,
- context: get(parentView, 'context'),
- controller: get(parentView, 'controller'),
- templateData: { keywords: {} }
- });
- }
- },
-
- /**
- If the component is currently inserted into the DOM of a parent view, this
- property will point to the controller of the parent view.
-
- @property targetObject
- @type Ember.Controller
- @default null
- */
- targetObject: computed(function(key) {
- var parentView = get(this, '_parentView');
- return parentView ? get(parentView, 'controller') : null;
- }).property('_parentView'),
-
- /**
- Triggers a named action on the controller context where the component is used if
- this controller has registered for notifications of the action.
-
- For example a component for playing or pausing music may translate click events
- into action notifications of "play" or "stop" depending on some internal state
- of the component:
-
-
- ```javascript
- App.PlayButtonComponent = Ember.Component.extend({
- click: function(){
- if (this.get('isPlaying')) {
- this.sendAction('play');
- } else {
- this.sendAction('stop');
- }
- }
- });
- ```
-
- When used inside a template these component actions are configured to
- trigger actions in the outer application context:
-
- ```handlebars
- {{! application.hbs }}
- {{play-button play="musicStarted" stop="musicStopped"}}
- ```
-
- When the component receives a browser `click` event it translate this
- interaction into application-specific semantics ("play" or "stop") and
- triggers the specified action name on the controller for the template
- where the component is used:
-
-
- ```javascript
- App.ApplicationController = Ember.Controller.extend({
- actions: {
- musicStarted: function(){
- // called when the play button is clicked
- // and the music started playing
- },
- musicStopped: function(){
- // called when the play button is clicked
- // and the music stopped playing
- }
- }
- });
- ```
-
- If no action name is passed to `sendAction` a default name of "action"
- is assumed.
-
- ```javascript
- App.NextButtonComponent = Ember.Component.extend({
- click: function(){
- this.sendAction();
- }
- });
- ```
-
- ```handlebars
- {{! application.hbs }}
- {{next-button action="playNextSongInAlbum"}}
- ```
-
- ```javascript
- App.ApplicationController = Ember.Controller.extend({
- actions: {
- playNextSongInAlbum: function(){
- ...
- }
- }
- });
- ```
-
- @method sendAction
- @param [action] {String} the action to trigger
- @param [context] {*} a context to send with the action
- */
- sendAction: function(action) {
- var actionName;
- var contexts = a_slice.call(arguments, 1);
-
- // Send the default action
- if (action === undefined) {
- actionName = get(this, 'action');
- Ember.assert("The default action was triggered on the component " + this.toString() +
- ", but the action name (" + actionName + ") was not a string.",
- isNone(actionName) || typeof actionName === 'string');
- } else {
- actionName = get(this, action);
- Ember.assert("The " + action + " action was triggered on the component " +
- this.toString() + ", but the action name (" + actionName +
- ") was not a string.",
- isNone(actionName) || typeof actionName === 'string');
- }
-
- // If no action name for that action could be found, just abort.
- if (actionName === undefined) { return; }
-
- this.triggerAction({
- action: actionName,
- actionContext: contexts
- });
- },
-
- send: function(actionName) {
- var args = [].slice.call(arguments, 1);
- var target;
- var hasAction = this._actions && this._actions[actionName];
-
- if (hasAction) {
- if (this._actions[actionName].apply(this, args) === true) {
- // handler returned true, so this action will bubble
- } else {
- return;
- }
- }
-
- if (target = get(this, 'target')) {
- Ember.assert("The `target` for " + this + " (" + target +
- ") does not have a `send` method", typeof target.send === 'function');
- target.send.apply(target, arguments);
- } else {
- if (!hasAction) {
- throw new Error(Ember.inspect(this) + ' had no action handler for: ' + actionName);
- }
- }
- }
- });
-
- __exports__["default"] = Component;
- });
-enifed("ember-views/views/container_view",
- ["ember-metal/core","ember-metal/merge","ember-runtime/mixins/mutable_array","ember-metal/property_get","ember-metal/property_set","ember-views/views/view","ember-views/views/states","ember-metal/error","ember-metal/enumerable_utils","ember-metal/computed","ember-metal/run_loop","ember-metal/properties","ember-metal/mixin","ember-runtime/system/native_array","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __exports__) {
- "use strict";
- var Ember = __dependency1__["default"];
- // Ember.assert, Ember.K
-
- var merge = __dependency2__["default"];
- var MutableArray = __dependency3__["default"];
- var get = __dependency4__.get;
- var set = __dependency5__.set;
-
- var View = __dependency6__["default"];
-
- var cloneStates = __dependency7__.cloneStates;
- var EmberViewStates = __dependency7__.states;
-
- var EmberError = __dependency8__["default"];
-
- var forEach = __dependency9__.forEach;
-
- var computed = __dependency10__.computed;
- var run = __dependency11__["default"];
- var defineProperty = __dependency12__.defineProperty;
- var observer = __dependency13__.observer;
- var beforeObserver = __dependency13__.beforeObserver;
- var emberA = __dependency14__.A;
-
- /**
- @module ember
- @submodule ember-views
- */
-
- var states = cloneStates(EmberViewStates);
-
- /**
- A `ContainerView` is an `Ember.View` subclass that implements `Ember.MutableArray`
- allowing programmatic management of its child views.
-
- ## Setting Initial Child Views
-
- The initial array of child views can be set in one of two ways. You can
- provide a `childViews` property at creation time that contains instance of
- `Ember.View`:
-
- ```javascript
- aContainer = Ember.ContainerView.create({
- childViews: [Ember.View.create(), Ember.View.create()]
- });
- ```
-
- You can also provide a list of property names whose values are instances of
- `Ember.View`:
-
- ```javascript
- aContainer = Ember.ContainerView.create({
- childViews: ['aView', 'bView', 'cView'],
- aView: Ember.View.create(),
- bView: Ember.View.create(),
- cView: Ember.View.create()
- });
- ```
-
- The two strategies can be combined:
-
- ```javascript
- aContainer = Ember.ContainerView.create({
- childViews: ['aView', Ember.View.create()],
- aView: Ember.View.create()
- });
- ```
-
- Each child view's rendering will be inserted into the container's rendered
- HTML in the same order as its position in the `childViews` property.
-
- ## Adding and Removing Child Views
-
- The container view implements `Ember.MutableArray` allowing programmatic management of its child views.
-
- To remove a view, pass that view into a `removeObject` call on the container view.
-
- Given an empty `<body>` the following code
-
- ```javascript
- aContainer = Ember.ContainerView.create({
- classNames: ['the-container'],
- childViews: ['aView', 'bView'],
- aView: Ember.View.create({
- template: Ember.Handlebars.compile("A")
- }),
- bView: Ember.View.create({
- template: Ember.Handlebars.compile("B")
- })
- });
-
- aContainer.appendTo('body');
- ```
-
- Results in the HTML
-
- ```html
- <div class="ember-view the-container">
- <div class="ember-view">A</div>
- <div class="ember-view">B</div>
- </div>
- ```
-
- Removing a view
-
- ```javascript
- aContainer.toArray(); // [aContainer.aView, aContainer.bView]
- aContainer.removeObject(aContainer.get('bView'));
- aContainer.toArray(); // [aContainer.aView]
- ```
-
- Will result in the following HTML
-
- ```html
- <div class="ember-view the-container">
- <div class="ember-view">A</div>
- </div>
- ```
-
- Similarly, adding a child view is accomplished by adding `Ember.View` instances to the
- container view.
-
- Given an empty `<body>` the following code
-
- ```javascript
- aContainer = Ember.ContainerView.create({
- classNames: ['the-container'],
- childViews: ['aView', 'bView'],
- aView: Ember.View.create({
- template: Ember.Handlebars.compile("A")
- }),
- bView: Ember.View.create({
- template: Ember.Handlebars.compile("B")
- })
- });
-
- aContainer.appendTo('body');
- ```
-
- Results in the HTML
-
- ```html
- <div class="ember-view the-container">
- <div class="ember-view">A</div>
- <div class="ember-view">B</div>
- </div>
- ```
-
- Adding a view
-
- ```javascript
- AnotherViewClass = Ember.View.extend({
- template: Ember.Handlebars.compile("Another view")
- });
-
- aContainer.toArray(); // [aContainer.aView, aContainer.bView]
- aContainer.pushObject(AnotherViewClass.create());
- aContainer.toArray(); // [aContainer.aView, aContainer.bView, <AnotherViewClass instance>]
- ```
-
- Will result in the following HTML
-
- ```html
- <div class="ember-view the-container">
- <div class="ember-view">A</div>
- <div class="ember-view">B</div>
- <div class="ember-view">Another view</div>
- </div>
- ```
-
- ## Templates and Layout
-
- A `template`, `templateName`, `defaultTemplate`, `layout`, `layoutName` or
- `defaultLayout` property on a container view will not result in the template
- or layout being rendered. The HTML contents of a `Ember.ContainerView`'s DOM
- representation will only be the rendered HTML of its child views.
-
- @class ContainerView
- @namespace Ember
- @extends Ember.View
- */
- var ContainerView = View.extend(MutableArray, {
- _states: states,
-
- willWatchProperty: function(prop){
- Ember.deprecate(
- "ContainerViews should not be observed as arrays. This behavior will change in future implementations of ContainerView.",
- !prop.match(/\[]/) && prop.indexOf('@') !== 0
- );
- },
-
- init: function() {
- this._super();
-
- var childViews = get(this, 'childViews');
- Ember.deprecate('Setting `childViews` on a Container is deprecated.', Ember.isEmpty(childViews));
-
- // redefine view's childViews property that was obliterated
- defineProperty(this, 'childViews', View.childViewsProperty);
-
- var _childViews = this._childViews;
-
- forEach(childViews, function(viewName, idx) {
- var view;
-
- if ('string' === typeof viewName) {
- view = get(this, viewName);
- view = this.createChildView(view);
- set(this, viewName, view);
- } else {
- view = this.createChildView(viewName);
- }
-
- _childViews[idx] = view;
- }, this);
-
- var currentView = get(this, 'currentView');
- if (currentView) {
- if (!_childViews.length) { _childViews = this._childViews = this._childViews.slice(); }
- _childViews.push(this.createChildView(currentView));
- }
- },
-
- replace: function(idx, removedCount, addedViews) {
- var addedCount = addedViews ? get(addedViews, 'length') : 0;
- var self = this;
- Ember.assert("You can't add a child to a container - the child is already a child of another view", emberA(addedViews).every(function(item) { return !get(item, '_parentView') || get(item, '_parentView') === self; }));
-
- this.arrayContentWillChange(idx, removedCount, addedCount);
- this.childViewsWillChange(this._childViews, idx, removedCount);
-
- if (addedCount === 0) {
- this._childViews.splice(idx, removedCount) ;
- } else {
- var args = [idx, removedCount].concat(addedViews);
- if (addedViews.length && !this._childViews.length) { this._childViews = this._childViews.slice(); }
- this._childViews.splice.apply(this._childViews, args);
- }
-
- this.arrayContentDidChange(idx, removedCount, addedCount);
- this.childViewsDidChange(this._childViews, idx, removedCount, addedCount);
-
- return this;
- },
-
- objectAt: function(idx) {
- return this._childViews[idx];
- },
-
- length: computed(function () {
- return this._childViews.length;
- })["volatile"](),
-
- /**
- Instructs each child view to render to the passed render buffer.
-
- @private
- @method render
- @param {Ember.RenderBuffer} buffer the buffer to render to
- */
- render: function(buffer) {
- var element = buffer.element();
- var dom = buffer.dom;
-
- if (this.tagName === '') {
- element = dom.createDocumentFragment();
- buffer._element = element;
- this._childViewsMorph = dom.appendMorph(element, this._morph.contextualElement);
- } else {
- this._childViewsMorph = dom.createMorph(element, element.lastChild, null);
- }
-
- return element;
- },
-
- instrumentName: 'container',
-
- /**
- When a child view is removed, destroy its element so that
- it is removed from the DOM.
-
- The array observer that triggers this action is set up in the
- `renderToBuffer` method.
-
- @private
- @method childViewsWillChange
- @param {Ember.Array} views the child views array before mutation
- @param {Number} start the start position of the mutation
- @param {Number} removed the number of child views removed
- **/
- childViewsWillChange: function(views, start, removed) {
- this.propertyWillChange('childViews');
-
- if (removed > 0) {
- var changedViews = views.slice(start, start+removed);
- // transition to preRender before clearing parentView
- this.currentState.childViewsWillChange(this, views, start, removed);
- this.initializeViews(changedViews, null, null);
- }
- },
-
- removeChild: function(child) {
- this.removeObject(child);
- return this;
- },
-
- /**
- When a child view is added, make sure the DOM gets updated appropriately.
-
- If the view has already rendered an element, we tell the child view to
- create an element and insert it into the DOM. If the enclosing container
- view has already written to a buffer, but not yet converted that buffer
- into an element, we insert the string representation of the child into the
- appropriate place in the buffer.
-
- @private
- @method childViewsDidChange
- @param {Ember.Array} views the array of child views after the mutation has occurred
- @param {Number} start the start position of the mutation
- @param {Number} removed the number of child views removed
- @param {Number} added the number of child views added
- */
- childViewsDidChange: function(views, start, removed, added) {
- if (added > 0) {
- var changedViews = views.slice(start, start+added);
- this.initializeViews(changedViews, this, get(this, 'templateData'));
- this.currentState.childViewsDidChange(this, views, start, added);
- }
- this.propertyDidChange('childViews');
- },
-
- initializeViews: function(views, parentView, templateData) {
- forEach(views, function(view) {
- set(view, '_parentView', parentView);
-
- if (!view.container && parentView) {
- set(view, 'container', parentView.container);
- }
-
- if (!get(view, 'templateData')) {
- set(view, 'templateData', templateData);
- }
- });
- },
-
- currentView: null,
-
- _currentViewWillChange: beforeObserver('currentView', function() {
- var currentView = get(this, 'currentView');
- if (currentView) {
- currentView.destroy();
- }
- }),
-
- _currentViewDidChange: observer('currentView', function() {
- var currentView = get(this, 'currentView');
- if (currentView) {
- Ember.assert("You tried to set a current view that already has a parent. Make sure you don't have multiple outlets in the same view.", !get(currentView, '_parentView'));
- this.pushObject(currentView);
- }
- }),
-
- _ensureChildrenAreInDOM: function () {
- this.currentState.ensureChildrenAreInDOM(this);
- }
- });
-
- merge(states._default, {
- childViewsWillChange: Ember.K,
- childViewsDidChange: Ember.K,
- ensureChildrenAreInDOM: Ember.K
- });
-
- merge(states.inBuffer, {
- childViewsDidChange: function(parentView, views, start, added) {
- throw new EmberError('You cannot modify child views while in the inBuffer state');
- }
- });
-
- merge(states.hasElement, {
- childViewsWillChange: function(view, views, start, removed) {
- for (var i=start; i<start+removed; i++) {
- var _view = views[i];
- _view._unsubscribeFromStreamBindings();
- _view.remove();
- }
- },
-
- childViewsDidChange: function(view, views, start, added) {
- run.scheduleOnce('render', view, '_ensureChildrenAreInDOM');
- },
-
- ensureChildrenAreInDOM: function(view) {
- var childViews = view._childViews;
- var renderer = view._renderer;
-
- var i, len, childView;
- for (i = 0, len = childViews.length; i < len; i++) {
- childView = childViews[i];
- if (!childView._elementCreated) {
- renderer.renderTree(childView, view, i);
- }
- }
- }
- });
-
- __exports__["default"] = ContainerView;
- });
-enifed("ember-views/views/core_view",
- ["ember-views/system/renderer","ember-views/views/states","ember-runtime/system/object","ember-runtime/mixins/evented","ember-runtime/mixins/action_handler","ember-metal/property_get","ember-metal/computed","ember-metal/utils","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __exports__) {
- "use strict";
- var Rerender = __dependency1__["default"];
-
- var cloneStates = __dependency2__.cloneStates;
- var states = __dependency2__.states;
- var EmberObject = __dependency3__["default"];
- var Evented = __dependency4__["default"];
- var ActionHandler = __dependency5__["default"];
-
- var get = __dependency6__.get;
- var computed = __dependency7__.computed;
-
- var typeOf = __dependency8__.typeOf;
- /**
- `Ember.CoreView` is an abstract class that exists to give view-like behavior
- to both Ember's main view class `Ember.View` and other classes like
- `Ember._SimpleMetamorphView` that don't need the fully functionaltiy of
- `Ember.View`.
-
- Unless you have specific needs for `CoreView`, you will use `Ember.View`
- in your applications.
-
- @class CoreView
- @namespace Ember
- @extends Ember.Object
- @uses Ember.Evented
- @uses Ember.ActionHandler
- */
- var CoreView = EmberObject.extend(Evented, ActionHandler, {
- isView: true,
- isVirtual: false,
-
- _states: cloneStates(states),
-
- init: function() {
- this._super();
- this._transitionTo('preRender');
- this._isVisible = get(this, 'isVisible');
- },
-
- /**
- If the view is currently inserted into the DOM of a parent view, this
- property will point to the parent of the view.
-
- @property parentView
- @type Ember.View
- @default null
- */
- parentView: computed('_parentView', function() {
- var parent = this._parentView;
-
- if (parent && parent.isVirtual) {
- return get(parent, 'parentView');
- } else {
- return parent;
- }
- }),
-
- _state: null,
-
- _parentView: null,
-
- // return the current view, not including virtual views
- concreteView: computed('parentView', function() {
- if (!this.isVirtual) { return this; }
- else { return get(this, 'parentView.concreteView'); }
- }),
-
- instrumentName: 'core_view',
-
- instrumentDetails: function(hash) {
- hash.object = this.toString();
- hash.containerKey = this._debugContainerKey;
- hash.view = this;
- },
-
- /**
- Override the default event firing from `Ember.Evented` to
- also call methods with the given name.
-
- @method trigger
- @param name {String}
- @private
- */
- trigger: function() {
- this._super.apply(this, arguments);
- var name = arguments[0];
- var method = this[name];
- if (method) {
- var length = arguments.length;
- var args = new Array(length - 1);
- for (var i = 1; i < length; i++) {
- args[i - 1] = arguments[i];
- }
- return method.apply(this, args);
- }
- },
-
- has: function(name) {
- return typeOf(this[name]) === 'function' || this._super(name);
- },
-
- destroy: function() {
- var parent = this._parentView;
-
- if (!this._super()) { return; }
-
-
- // destroy the element -- this will avoid each child view destroying
- // the element over and over again...
- if (!this.removedFromDOM && this._renderer) {
- this._renderer.remove(this, true);
- }
-
- // remove from parent if found. Don't call removeFromParent,
- // as removeFromParent will try to remove the element from
- // the DOM again.
- if (parent) { parent.removeChild(this); }
-
- this._transitionTo('destroying', false);
-
- return this;
- },
-
- clearRenderedChildren: Ember.K,
- _transitionTo: Ember.K,
- destroyElement: Ember.K
- });
-
- CoreView.reopenClass({
- renderer: new Rerender()
- });
-
- __exports__["default"] = CoreView;
- });
-enifed("ember-views/views/states",
- ["ember-metal/platform","ember-metal/merge","ember-views/views/states/default","ember-views/views/states/pre_render","ember-views/views/states/in_buffer","ember-views/views/states/has_element","ember-views/views/states/in_dom","ember-views/views/states/destroying","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __exports__) {
- "use strict";
- var create = __dependency1__.create;
- var merge = __dependency2__["default"];
- var _default = __dependency3__["default"];
- var preRender = __dependency4__["default"];
- var inBuffer = __dependency5__["default"];
- var hasElement = __dependency6__["default"];
- var inDOM = __dependency7__["default"];
- var destroying = __dependency8__["default"];
-
- function cloneStates(from) {
- var into = {};
-
- into._default = {};
- into.preRender = create(into._default);
- into.destroying = create(into._default);
- into.inBuffer = create(into._default);
- into.hasElement = create(into._default);
- into.inDOM = create(into.hasElement);
-
- for (var stateName in from) {
- if (!from.hasOwnProperty(stateName)) { continue; }
- merge(into[stateName], from[stateName]);
- }
-
- return into;
- }
-
- __exports__.cloneStates = cloneStates;var states = {
- _default: _default,
- preRender: preRender,
- inDOM: inDOM,
- inBuffer: inBuffer,
- hasElement: hasElement,
- destroying: destroying
- };
- __exports__.states = states;
- });
-enifed("ember-views/views/states/default",
- ["ember-metal/core","ember-metal/error","exports"],
- function(__dependency1__, __dependency2__, __exports__) {
- "use strict";
- var Ember = __dependency1__["default"];
- // Ember.K
- var EmberError = __dependency2__["default"];
-
- /**
- @module ember
- @submodule ember-views
- */
- __exports__["default"] = {
- // appendChild is only legal while rendering the buffer.
- appendChild: function() {
- throw new EmberError("You can't use appendChild outside of the rendering process");
- },
-
- $: function() {
- return undefined;
- },
-
- getElement: function() {
- return null;
- },
-
- // Handle events from `Ember.EventDispatcher`
- handleEvent: function() {
- return true; // continue event propagation
- },
-
- destroyElement: function(view) {
- if (view._renderer)
- view._renderer.remove(view, false);
- return view;
- },
-
- rerender: Ember.K,
- invokeObserver: Ember.K
- };
- });
-enifed("ember-views/views/states/destroying",
- ["ember-metal/merge","ember-metal/platform","ember-runtime/system/string","ember-views/views/states/default","ember-metal/error","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) {
- "use strict";
- var merge = __dependency1__["default"];
- var create = __dependency2__.create;
- var fmt = __dependency3__.fmt;
- var _default = __dependency4__["default"];
- var EmberError = __dependency5__["default"];
- /**
- @module ember
- @submodule ember-views
- */
-
- var destroyingError = "You can't call %@ on a view being destroyed";
-
- var destroying = create(_default);
-
- merge(destroying, {
- appendChild: function() {
- throw new EmberError(fmt(destroyingError, ['appendChild']));
- },
- rerender: function() {
- throw new EmberError(fmt(destroyingError, ['rerender']));
- },
- destroyElement: function() {
- throw new EmberError(fmt(destroyingError, ['destroyElement']));
- }
- });
-
- __exports__["default"] = destroying;
- });
-enifed("ember-views/views/states/has_element",
- ["ember-views/views/states/default","ember-metal/run_loop","ember-metal/merge","ember-metal/platform","ember-views/system/jquery","ember-metal/error","ember-metal/property_get","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __exports__) {
- "use strict";
- var _default = __dependency1__["default"];
- var run = __dependency2__["default"];
- var merge = __dependency3__["default"];
- var create = __dependency4__.create;
- var jQuery = __dependency5__["default"];
- var EmberError = __dependency6__["default"];
-
- /**
- @module ember
- @submodule ember-views
- */
-
- var get = __dependency7__.get;
-
- var hasElement = create(_default);
-
- merge(hasElement, {
- $: function(view, sel) {
- var elem = view.get('concreteView').element;
- return sel ? jQuery(sel, elem) : jQuery(elem);
- },
-
- getElement: function(view) {
- var parent = get(view, 'parentView');
- if (parent) { parent = get(parent, 'element'); }
- if (parent) { return view.findElementInParentElement(parent); }
- return jQuery("#" + get(view, 'elementId'))[0];
- },
-
- // once the view has been inserted into the DOM, rerendering is
- // deferred to allow bindings to synchronize.
- rerender: function(view) {
- if (view._root._morph && !view._elementInserted) {
- throw new EmberError("Something you did caused a view to re-render after it rendered but before it was inserted into the DOM.");
- }
- // TODO: should be scheduled with renderer
- run.scheduleOnce('render', function () {
- if (view.isDestroying) return;
- view._renderer.renderTree(view, view._parentView);
- });
- },
-
- // once the view is already in the DOM, destroying it removes it
- // from the DOM, nukes its element, and puts it back into the
- // preRender state if inDOM.
-
- destroyElement: function(view) {
- view._renderer.remove(view, false);
- return view;
- },
-
- // Handle events from `Ember.EventDispatcher`
- handleEvent: function(view, eventName, evt) {
- if (view.has(eventName)) {
- // Handler should be able to re-dispatch events, so we don't
- // preventDefault or stopPropagation.
- return view.trigger(eventName, evt);
- } else {
- return true; // continue event propagation
- }
- },
-
- invokeObserver: function(target, observer) {
- observer.call(target);
- }
- });
-
- __exports__["default"] = hasElement;
- });
-enifed("ember-views/views/states/in_buffer",
- ["ember-views/views/states/default","ember-metal/error","ember-metal/core","ember-metal/platform","ember-metal/merge","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) {
- "use strict";
- var _default = __dependency1__["default"];
- var EmberError = __dependency2__["default"];
-
- var Ember = __dependency3__["default"];
- // Ember.assert
- var create = __dependency4__.create;
- var merge = __dependency5__["default"];
-
- /**
- @module ember
- @submodule ember-views
- */
-
- var inBuffer = create(_default);
-
- merge(inBuffer, {
- $: function(view, sel) {
- // if we don't have an element yet, someone calling this.$() is
- // trying to update an element that isn't in the DOM. Instead,
- // rerender the view to allow the render method to reflect the
- // changes.
- view.rerender();
- return Ember.$();
- },
-
- // when a view is rendered in a buffer, rerendering it simply
- // replaces the existing buffer with a new one
- rerender: function(view) {
- throw new EmberError("Something you did caused a view to re-render after it rendered but before it was inserted into the DOM.");
- },
-
- // when a view is rendered in a buffer, appending a child
- // view will render that view and append the resulting
- // buffer into its buffer.
- appendChild: function(view, childView, options) {
- var buffer = view.buffer;
- var _childViews = view._childViews;
-
- childView = view.createChildView(childView, options);
- if (!_childViews.length) { _childViews = view._childViews = _childViews.slice(); }
- _childViews.push(childView);
-
- if (!childView._morph) {
- buffer.pushChildView(childView);
- }
-
- view.propertyDidChange('childViews');
-
- return childView;
- },
-
- invokeObserver: function(target, observer) {
- observer.call(target);
- }
- });
-
- __exports__["default"] = inBuffer;
- });
-enifed("ember-views/views/states/in_dom",
- ["ember-metal/core","ember-metal/platform","ember-metal/merge","ember-metal/error","ember-views/views/states/has_element","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) {
- "use strict";
- var Ember = __dependency1__["default"];
- // Ember.assert
- var create = __dependency2__.create;
- var merge = __dependency3__["default"];
- var EmberError = __dependency4__["default"];
-
- var hasElement = __dependency5__["default"];
- /**
- @module ember
- @submodule ember-views
- */
-
- var inDOM = create(hasElement);
-
- var View;
-
- merge(inDOM, {
- enter: function(view) {
- if (!View) { View = requireModule('ember-views/views/view')["default"]; } // ES6TODO: this sucks. Have to avoid cycles...
-
- // Register the view for event handling. This hash is used by
- // Ember.EventDispatcher to dispatch incoming events.
- if (!view.isVirtual) {
- Ember.assert("Attempted to register a view with an id already in use: "+view.elementId, !View.views[view.elementId]);
- View.views[view.elementId] = view;
- }
-
- view.addBeforeObserver('elementId', function() {
- throw new EmberError("Changing a view's elementId after creation is not allowed");
- });
- },
-
- exit: function(view) {
- if (!View) { View = requireModule('ember-views/views/view')["default"]; } // ES6TODO: this sucks. Have to avoid cycles...
-
- if (!this.isVirtual) delete View.views[view.elementId];
- }
- });
-
- __exports__["default"] = inDOM;
- });
-enifed("ember-views/views/states/pre_render",
- ["ember-views/views/states/default","ember-metal/platform","exports"],
- function(__dependency1__, __dependency2__, __exports__) {
- "use strict";
- var _default = __dependency1__["default"];
- var create = __dependency2__.create;
-
- /**
- @module ember
- @submodule ember-views
- */
- var preRender = create(_default);
-
- __exports__["default"] = preRender;
- });
-enifed("ember-views/views/view",
- ["ember-metal/core","ember-metal/platform","ember-runtime/mixins/evented","ember-runtime/system/object","ember-metal/error","ember-metal/property_get","ember-metal/property_set","ember-metal/set_properties","ember-metal/run_loop","ember-metal/observer","ember-metal/properties","ember-metal/utils","ember-metal/computed","ember-metal/mixin","ember-metal/streams/simple","ember-views/streams/key_stream","ember-metal/streams/stream_binding","ember-views/streams/context_stream","ember-metal/is_none","ember-metal/deprecate_property","ember-runtime/system/native_array","ember-runtime/system/string","ember-metal/enumerable_utils","ember-metal/property_events","ember-views/system/jquery","ember-views/system/ext","ember-views/views/core_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__, __dependency27__, __exports__) {
- "use strict";
- // Ember.assert, Ember.deprecate, Ember.warn, Ember.TEMPLATES,
- // Ember.K, jQuery, Ember.lookup,
- // Ember.ContainerView circular dependency
- // Ember.ENV
- var Ember = __dependency1__["default"];
- var create = __dependency2__.create;
-
- var Evented = __dependency3__["default"];
- var EmberObject = __dependency4__["default"];
- var EmberError = __dependency5__["default"];
- var get = __dependency6__.get;
- var set = __dependency7__.set;
- var setProperties = __dependency8__["default"];
- var run = __dependency9__["default"];
- var addObserver = __dependency10__.addObserver;
- var removeObserver = __dependency10__.removeObserver;
- var defineProperty = __dependency11__.defineProperty;
- var guidFor = __dependency12__.guidFor;
- var computed = __dependency13__.computed;
- var observer = __dependency14__.observer;
- var SimpleStream = __dependency15__["default"];
- var KeyStream = __dependency16__["default"];
- var StreamBinding = __dependency17__["default"];
- var ContextStream = __dependency18__["default"];
-
- var typeOf = __dependency12__.typeOf;
- var isArray = __dependency12__.isArray;
- var isNone = __dependency19__["default"];
- var Mixin = __dependency14__.Mixin;
- var deprecateProperty = __dependency20__.deprecateProperty;
- var emberA = __dependency21__.A;
-
- var dasherize = __dependency22__.dasherize;
-
- // ES6TODO: functions on EnumerableUtils should get their own export
- var forEach = __dependency23__.forEach;
- var addObject = __dependency23__.addObject;
- var removeObject = __dependency23__.removeObject;
-
- var beforeObserver = __dependency14__.beforeObserver;
-
- var propertyWillChange = __dependency24__.propertyWillChange;
- var propertyDidChange = __dependency24__.propertyDidChange;
-
- var jQuery = __dependency25__["default"];
- // for the side effect of extending Ember.run.queues
-
- var CoreView = __dependency27__["default"];
-
-
- /**
- @module ember
- @submodule ember-views
- */
- var childViewsProperty = computed(function() {
- var childViews = this._childViews;
- var ret = emberA();
-
- forEach(childViews, function(view) {
- var currentChildViews;
- if (view.isVirtual) {
- if (currentChildViews = get(view, 'childViews')) {
- ret.pushObjects(currentChildViews);
- }
- } else {
- ret.push(view);
- }
- });
-
- ret.replace = function (idx, removedCount, addedViews) {
- throw new EmberError("childViews is immutable");
- };
-
- return ret;
- });
-
- Ember.warn("The VIEW_PRESERVES_CONTEXT flag has been removed and the functionality can no longer be disabled.", Ember.ENV.VIEW_PRESERVES_CONTEXT !== false);
-
- /**
- Global hash of shared templates. This will automatically be populated
- by the build tools so that you can store your Handlebars templates in
- separate files that get loaded into JavaScript at buildtime.
-
- @property TEMPLATES
- @for Ember
- @type Hash
- */
- Ember.TEMPLATES = {};
-
- var EMPTY_ARRAY = [];
-
- /**
- `Ember.View` is the class in Ember responsible for encapsulating templates of
- HTML content, combining templates with data to render as sections of a page's
- DOM, and registering and responding to user-initiated events.
-
- ## HTML Tag
-
- The default HTML tag name used for a view's DOM representation is `div`. This
- can be customized by setting the `tagName` property. The following view
- class:
-
- ```javascript
- ParagraphView = Ember.View.extend({
- tagName: 'em'
- });
- ```
-
- Would result in instances with the following HTML:
-
- ```html
- <em id="ember1" class="ember-view"></em>
- ```
-
- ## HTML `class` Attribute
-
- The HTML `class` attribute of a view's tag can be set by providing a
- `classNames` property that is set to an array of strings:
-
- ```javascript
- MyView = Ember.View.extend({
- classNames: ['my-class', 'my-other-class']
- });
- ```
-
- Will result in view instances with an HTML representation of:
-
- ```html
- <div id="ember1" class="ember-view my-class my-other-class"></div>
- ```
-
- `class` attribute values can also be set by providing a `classNameBindings`
- property set to an array of properties names for the view. The return value
- of these properties will be added as part of the value for the view's `class`
- attribute. These properties can be computed properties:
-
- ```javascript
- MyView = Ember.View.extend({
- classNameBindings: ['propertyA', 'propertyB'],
- propertyA: 'from-a',
- propertyB: function() {
- if (someLogic) { return 'from-b'; }
- }.property()
- });
- ```
-
- Will result in view instances with an HTML representation of:
-
- ```html
- <div id="ember1" class="ember-view from-a from-b"></div>
- ```
-
- If the value of a class name binding returns a boolean the property name
- itself will be used as the class name if the property is true. The class name
- will not be added if the value is `false` or `undefined`.
-
- ```javascript
- MyView = Ember.View.extend({
- classNameBindings: ['hovered'],
- hovered: true
- });
- ```
-
- Will result in view instances with an HTML representation of:
-
- ```html
- <div id="ember1" class="ember-view hovered"></div>
- ```
-
- When using boolean class name bindings you can supply a string value other
- than the property name for use as the `class` HTML attribute by appending the
- preferred value after a ":" character when defining the binding:
-
- ```javascript
- MyView = Ember.View.extend({
- classNameBindings: ['awesome:so-very-cool'],
- awesome: true
- });
- ```
-
- Will result in view instances with an HTML representation of:
-
- ```html
- <div id="ember1" class="ember-view so-very-cool"></div>
- ```
-
- Boolean value class name bindings whose property names are in a
- camelCase-style format will be converted to a dasherized format:
-
- ```javascript
- MyView = Ember.View.extend({
- classNameBindings: ['isUrgent'],
- isUrgent: true
- });
- ```
-
- Will result in view instances with an HTML representation of:
-
- ```html
- <div id="ember1" class="ember-view is-urgent"></div>
- ```
-
- Class name bindings can also refer to object values that are found by
- traversing a path relative to the view itself:
-
- ```javascript
- MyView = Ember.View.extend({
- classNameBindings: ['messages.empty']
- messages: Ember.Object.create({
- empty: true
- })
- });
- ```
-
- Will result in view instances with an HTML representation of:
-
- ```html
- <div id="ember1" class="ember-view empty"></div>
- ```
-
- If you want to add a class name for a property which evaluates to true and
- and a different class name if it evaluates to false, you can pass a binding
- like this:
-
- ```javascript
- // Applies 'enabled' class when isEnabled is true and 'disabled' when isEnabled is false
- Ember.View.extend({
- classNameBindings: ['isEnabled:enabled:disabled']
- isEnabled: true
- });
- ```
-
- Will result in view instances with an HTML representation of:
-
- ```html
- <div id="ember1" class="ember-view enabled"></div>
- ```
-
- When isEnabled is `false`, the resulting HTML reprensentation looks like
- this:
-
- ```html
- <div id="ember1" class="ember-view disabled"></div>
- ```
-
- This syntax offers the convenience to add a class if a property is `false`:
-
- ```javascript
- // Applies no class when isEnabled is true and class 'disabled' when isEnabled is false
- Ember.View.extend({
- classNameBindings: ['isEnabled::disabled']
- isEnabled: true
- });
- ```
-
- Will result in view instances with an HTML representation of:
-
- ```html
- <div id="ember1" class="ember-view"></div>
- ```
-
- When the `isEnabled` property on the view is set to `false`, it will result
- in view instances with an HTML representation of:
-
- ```html
- <div id="ember1" class="ember-view disabled"></div>
- ```
-
- Updates to the the value of a class name binding will result in automatic
- update of the HTML `class` attribute in the view's rendered HTML
- representation. If the value becomes `false` or `undefined` the class name
- will be removed.
-
- Both `classNames` and `classNameBindings` are concatenated properties. See
- [Ember.Object](/api/classes/Ember.Object.html) documentation for more
- information about concatenated properties.
-
- ## HTML Attributes
-
- The HTML attribute section of a view's tag can be set by providing an
- `attributeBindings` property set to an array of property names on the view.
- The return value of these properties will be used as the value of the view's
- HTML associated attribute:
-
- ```javascript
- AnchorView = Ember.View.extend({
- tagName: 'a',
- attributeBindings: ['href'],
- href: 'http://google.com'
- });
- ```
-
- Will result in view instances with an HTML representation of:
-
- ```html
- <a id="ember1" class="ember-view" href="http://google.com"></a>
- ```
-
- One property can be mapped on to another by placing a ":" between
- the source property and the destination property:
-
- ```javascript
- AnchorView = Ember.View.extend({
- tagName: 'a',
- attributeBindings: ['url:href'],
- url: 'http://google.com'
- });
- ```
-
- Will result in view instances with an HTML representation of:
-
- ```html
- <a id="ember1" class="ember-view" href="http://google.com"></a>
- ```
-
- If the return value of an `attributeBindings` monitored property is a boolean
- the property will follow HTML's pattern of repeating the attribute's name as
- its value:
-
- ```javascript
- MyTextInput = Ember.View.extend({
- tagName: 'input',
- attributeBindings: ['disabled'],
- disabled: true
- });
- ```
-
- Will result in view instances with an HTML representation of:
-
- ```html
- <input id="ember1" class="ember-view" disabled="disabled" />
- ```
-
- `attributeBindings` can refer to computed properties:
-
- ```javascript
- MyTextInput = Ember.View.extend({
- tagName: 'input',
- attributeBindings: ['disabled'],
- disabled: function() {
- if (someLogic) {
- return true;
- } else {
- return false;
- }
- }.property()
- });
- ```
-
- Updates to the the property of an attribute binding will result in automatic
- update of the HTML attribute in the view's rendered HTML representation.
-
- `attributeBindings` is a concatenated property. See [Ember.Object](/api/classes/Ember.Object.html)
- documentation for more information about concatenated properties.
-
- ## Templates
-
- The HTML contents of a view's rendered representation are determined by its
- template. Templates can be any function that accepts an optional context
- parameter and returns a string of HTML that will be inserted within the
- view's tag. Most typically in Ember this function will be a compiled
- `Ember.Handlebars` template.
-
- ```javascript
- AView = Ember.View.extend({
- template: Ember.Handlebars.compile('I am the template')
- });
- ```
-
- Will result in view instances with an HTML representation of:
-
- ```html
- <div id="ember1" class="ember-view">I am the template</div>
- ```
-
- Within an Ember application is more common to define a Handlebars templates as
- part of a page:
-
- ```html
- <script type='text/x-handlebars' data-template-name='some-template'>
- Hello
- </script>
- ```
-
- And associate it by name using a view's `templateName` property:
-
- ```javascript
- AView = Ember.View.extend({
- templateName: 'some-template'
- });
- ```
-
- If you have nested resources, your Handlebars template will look like this:
-
- ```html
- <script type='text/x-handlebars' data-template-name='posts/new'>
- <h1>New Post</h1>
- </script>
- ```
-
- And `templateName` property:
-
- ```javascript
- AView = Ember.View.extend({
- templateName: 'posts/new'
- });
- ```
-
- Using a value for `templateName` that does not have a Handlebars template
- with a matching `data-template-name` attribute will throw an error.
-
- For views classes that may have a template later defined (e.g. as the block
- portion of a `{{view}}` Handlebars helper call in another template or in
- a subclass), you can provide a `defaultTemplate` property set to compiled
- template function. If a template is not later provided for the view instance
- the `defaultTemplate` value will be used:
-
- ```javascript
- AView = Ember.View.extend({
- defaultTemplate: Ember.Handlebars.compile('I was the default'),
- template: null,
- templateName: null
- });
- ```
-
- Will result in instances with an HTML representation of:
-
- ```html
- <div id="ember1" class="ember-view">I was the default</div>
- ```
-
- If a `template` or `templateName` is provided it will take precedence over
- `defaultTemplate`:
-
- ```javascript
- AView = Ember.View.extend({
- defaultTemplate: Ember.Handlebars.compile('I was the default')
- });
-
- aView = AView.create({
- template: Ember.Handlebars.compile('I was the template, not default')
- });
- ```
-
- Will result in the following HTML representation when rendered:
-
- ```html
- <div id="ember1" class="ember-view">I was the template, not default</div>
- ```
-
- ## View Context
-
- The default context of the compiled template is the view's controller:
-
- ```javascript
- AView = Ember.View.extend({
- template: Ember.Handlebars.compile('Hello {{excitedGreeting}}')
- });
-
- aController = Ember.Object.create({
- firstName: 'Barry',
- excitedGreeting: function() {
- return this.get("content.firstName") + "!!!"
- }.property()
- });
-
- aView = AView.create({
- controller: aController
- });
- ```
-
- Will result in an HTML representation of:
-
- ```html
- <div id="ember1" class="ember-view">Hello Barry!!!</div>
- ```
-
- A context can also be explicitly supplied through the view's `context`
- property. If the view has neither `context` nor `controller` properties, the
- `parentView`'s context will be used.
-
- ## Layouts
-
- Views can have a secondary template that wraps their main template. Like
- primary templates, layouts can be any function that accepts an optional
- context parameter and returns a string of HTML that will be inserted inside
- view's tag. Views whose HTML element is self closing (e.g. `<input />`)
- cannot have a layout and this property will be ignored.
-
- Most typically in Ember a layout will be a compiled `Ember.Handlebars`
- template.
-
- A view's layout can be set directly with the `layout` property or reference
- an existing Handlebars template by name with the `layoutName` property.
-
- A template used as a layout must contain a single use of the Handlebars
- `{{yield}}` helper. The HTML contents of a view's rendered `template` will be
- inserted at this location:
-
- ```javascript
- AViewWithLayout = Ember.View.extend({
- layout: Ember.Handlebars.compile("<div class='my-decorative-class'>{{yield}}</div>"),
- template: Ember.Handlebars.compile("I got wrapped")
- });
- ```
-
- Will result in view instances with an HTML representation of:
-
- ```html
- <div id="ember1" class="ember-view">
- <div class="my-decorative-class">
- I got wrapped
- </div>
- </div>
- ```
-
- See [Ember.Handlebars.helpers.yield](/api/classes/Ember.Handlebars.helpers.html#method_yield)
- for more information.
-
- ## Responding to Browser Events
-
- Views can respond to user-initiated events in one of three ways: method
- implementation, through an event manager, and through `{{action}}` helper use
- in their template or layout.
-
- ### Method Implementation
-
- Views can respond to user-initiated events by implementing a method that
- matches the event name. A `jQuery.Event` object will be passed as the
- argument to this method.
-
- ```javascript
- AView = Ember.View.extend({
- click: function(event) {
- // will be called when when an instance's
- // rendered element is clicked
- }
- });
- ```
-
- ### Event Managers
-
- Views can define an object as their `eventManager` property. This object can
- then implement methods that match the desired event names. Matching events
- that occur on the view's rendered HTML or the rendered HTML of any of its DOM
- descendants will trigger this method. A `jQuery.Event` object will be passed
- as the first argument to the method and an `Ember.View` object as the
- second. The `Ember.View` will be the view whose rendered HTML was interacted
- with. This may be the view with the `eventManager` property or one of its
- descendent views.
-
- ```javascript
- AView = Ember.View.extend({
- eventManager: Ember.Object.create({
- doubleClick: function(event, view) {
- // will be called when when an instance's
- // rendered element or any rendering
- // of this views's descendent
- // elements is clicked
- }
- })
- });
- ```
-
- An event defined for an event manager takes precedence over events of the
- same name handled through methods on the view.
-
- ```javascript
- AView = Ember.View.extend({
- mouseEnter: function(event) {
- // will never trigger.
- },
- eventManager: Ember.Object.create({
- mouseEnter: function(event, view) {
- // takes precedence over AView#mouseEnter
- }
- })
- });
- ```
-
- Similarly a view's event manager will take precedence for events of any views
- rendered as a descendent. A method name that matches an event name will not
- be called if the view instance was rendered inside the HTML representation of
- a view that has an `eventManager` property defined that handles events of the
- name. Events not handled by the event manager will still trigger method calls
- on the descendent.
-
- ```javascript
- var App = Ember.Application.create();
- App.OuterView = Ember.View.extend({
- template: Ember.Handlebars.compile("outer {{#view 'inner'}}inner{{/view}} outer"),
- eventManager: Ember.Object.create({
- mouseEnter: function(event, view) {
- // view might be instance of either
- // OuterView or InnerView depending on
- // where on the page the user interaction occured
- }
- })
- });
-
- App.InnerView = Ember.View.extend({
- click: function(event) {
- // will be called if rendered inside
- // an OuterView because OuterView's
- // eventManager doesn't handle click events
- },
- mouseEnter: function(event) {
- // will never be called if rendered inside
- // an OuterView.
- }
- });
- ```
-
- ### Handlebars `{{action}}` Helper
-
- See [Handlebars.helpers.action](/api/classes/Ember.Handlebars.helpers.html#method_action).
-
- ### Event Names
-
- All of the event handling approaches described above respond to the same set
- of events. The names of the built-in events are listed below. (The hash of
- built-in events exists in `Ember.EventDispatcher`.) Additional, custom events
- can be registered by using `Ember.Application.customEvents`.
-
- Touch events:
-
- * `touchStart`
- * `touchMove`
- * `touchEnd`
- * `touchCancel`
-
- Keyboard events
-
- * `keyDown`
- * `keyUp`
- * `keyPress`
-
- Mouse events
-
- * `mouseDown`
- * `mouseUp`
- * `contextMenu`
- * `click`
- * `doubleClick`
- * `mouseMove`
- * `focusIn`
- * `focusOut`
- * `mouseEnter`
- * `mouseLeave`
-
- Form events:
-
- * `submit`
- * `change`
- * `focusIn`
- * `focusOut`
- * `input`
-
- HTML5 drag and drop events:
-
- * `dragStart`
- * `drag`
- * `dragEnter`
- * `dragLeave`
- * `dragOver`
- * `dragEnd`
- * `drop`
-
- ## Handlebars `{{view}}` Helper
-
- Other `Ember.View` instances can be included as part of a view's template by
- using the `{{view}}` Handlebars helper. See [Ember.Handlebars.helpers.view](/api/classes/Ember.Handlebars.helpers.html#method_view)
- for additional information.
-
- @class View
- @namespace Ember
- @extends Ember.CoreView
- */
- var View = CoreView.extend({
-
- concatenatedProperties: ['classNames', 'classNameBindings', 'attributeBindings'],
-
- /**
- @property isView
- @type Boolean
- @default true
- @static
- */
- isView: true,
-
- // ..........................................................
- // TEMPLATE SUPPORT
- //
-
- /**
- The name of the template to lookup if no template is provided.
-
- By default `Ember.View` will lookup a template with this name in
- `Ember.TEMPLATES` (a shared global object).
-
- @property templateName
- @type String
- @default null
- */
- templateName: null,
-
- /**
- The name of the layout to lookup if no layout is provided.
-
- By default `Ember.View` will lookup a template with this name in
- `Ember.TEMPLATES` (a shared global object).
-
- @property layoutName
- @type String
- @default null
- */
- layoutName: null,
-
- /**
- Used to identify this view during debugging
-
- @property instrumentDisplay
- @type String
- */
- instrumentDisplay: computed(function() {
- if (this.helperName) {
- return '{{' + this.helperName + '}}';
- }
- }),
-
- /**
- The template used to render the view. This should be a function that
- accepts an optional context parameter and returns a string of HTML that
- will be inserted into the DOM relative to its parent view.
-
- In general, you should set the `templateName` property instead of setting
- the template yourself.
-
- @property template
- @type Function
- */
- template: computed('templateName', function(key, value) {
- if (value !== undefined) { return value; }
-
- var templateName = get(this, 'templateName');
- var template = this.templateForName(templateName, 'template');
-
- Ember.assert("You specified the templateName " + templateName + " for " + this + ", but it did not exist.", !templateName || template);
-
- return template || get(this, 'defaultTemplate');
- }),
-
- /**
- The controller managing this view. If this property is set, it will be
- made available for use by the template.
-
- @property controller
- @type Object
- */
- controller: computed('_parentView', function(key) {
- var parentView = get(this, '_parentView');
- return parentView ? get(parentView, 'controller') : null;
- }),
-
- /**
- A view may contain a layout. A layout is a regular template but
- supersedes the `template` property during rendering. It is the
- responsibility of the layout template to retrieve the `template`
- property from the view (or alternatively, call `Handlebars.helpers.yield`,
- `{{yield}}`) to render it in the correct location.
-
- This is useful for a view that has a shared wrapper, but which delegates
- the rendering of the contents of the wrapper to the `template` property
- on a subclass.
-
- @property layout
- @type Function
- */
- layout: computed(function(key) {
- var layoutName = get(this, 'layoutName');
- var layout = this.templateForName(layoutName, 'layout');
-
- Ember.assert("You specified the layoutName " + layoutName + " for " + this + ", but it did not exist.", !layoutName || layout);
-
- return layout || get(this, 'defaultLayout');
- }).property('layoutName'),
-
- _yield: function(context, options) {
- var template = get(this, 'template');
- if (template) { template(context, options); }
- },
-
- templateForName: function(name, type) {
- if (!name) { return; }
- Ember.assert("templateNames are not allowed to contain periods: "+name, name.indexOf('.') === -1);
-
- if (!this.container) {
- throw new EmberError('Container was not found when looking up a views template. ' +
- 'This is most likely due to manually instantiating an Ember.View. ' +
- 'See: http://git.io/EKPpnA');
- }
-
- return this.container.lookup('template:' + name);
- },
-
- /**
- The object from which templates should access properties.
-
- This object will be passed to the template function each time the render
- method is called, but it is up to the individual function to decide what
- to do with it.
-
- By default, this will be the view's controller.
-
- @property context
- @type Object
- */
- context: computed(function(key, value) {
- if (arguments.length === 2) {
- set(this, '_context', value);
- return value;
- } else {
- return get(this, '_context');
- }
- })["volatile"](),
-
- /**
- Private copy of the view's template context. This can be set directly
- by Handlebars without triggering the observer that causes the view
- to be re-rendered.
-
- The context of a view is looked up as follows:
-
- 1. Supplied context (usually by Handlebars)
- 2. Specified controller
- 3. `parentView`'s context (for a child of a ContainerView)
-
- The code in Handlebars that overrides the `_context` property first
- checks to see whether the view has a specified controller. This is
- something of a hack and should be revisited.
-
- @property _context
- @private
- */
- _context: computed(function(key) {
- var parentView, controller;
-
- if (controller = get(this, 'controller')) {
- return controller;
- }
-
- parentView = this._parentView;
- if (parentView) {
- return get(parentView, '_context');
- }
-
- return null;
- }),
-
- /**
- If a value that affects template rendering changes, the view should be
- re-rendered to reflect the new value.
-
- @method _contextDidChange
- @private
- */
- _contextDidChange: observer('context', function() {
- this.rerender();
- }),
-
- /**
- If `false`, the view will appear hidden in DOM.
-
- @property isVisible
- @type Boolean
- @default null
- */
- isVisible: true,
-
- /**
- Array of child views. You should never edit this array directly.
- Instead, use `appendChild` and `removeFromParent`.
-
- @property childViews
- @type Array
- @default []
- @private
- */
- childViews: childViewsProperty,
-
- _childViews: EMPTY_ARRAY,
-
- // When it's a virtual view, we need to notify the parent that their
- // childViews will change.
- _childViewsWillChange: beforeObserver('childViews', function() {
- if (this.isVirtual) {
- var parentView = get(this, 'parentView');
- if (parentView) { propertyWillChange(parentView, 'childViews'); }
- }
- }),
-
- // When it's a virtual view, we need to notify the parent that their
- // childViews did change.
- _childViewsDidChange: observer('childViews', function() {
- if (this.isVirtual) {
- var parentView = get(this, 'parentView');
- if (parentView) { propertyDidChange(parentView, 'childViews'); }
- }
- }),
-
- /**
- Return the nearest ancestor that is an instance of the provided
- class.
-
- @method nearestInstanceOf
- @param {Class} klass Subclass of Ember.View (or Ember.View itself)
- @return Ember.View
- @deprecated
- */
- nearestInstanceOf: function(klass) {
- Ember.deprecate("nearestInstanceOf is deprecated and will be removed from future releases. Use nearestOfType.");
- var view = get(this, 'parentView');
-
- while (view) {
- if (view instanceof klass) { return view; }
- view = get(view, 'parentView');
- }
- },
-
- /**
- Return the nearest ancestor that is an instance of the provided
- class or mixin.
-
- @method nearestOfType
- @param {Class,Mixin} klass Subclass of Ember.View (or Ember.View itself),
- or an instance of Ember.Mixin.
- @return Ember.View
- */
- nearestOfType: function(klass) {
- var view = get(this, 'parentView');
- var isOfType = klass instanceof Mixin ?
- function(view) { return klass.detect(view); } :
- function(view) { return klass.detect(view.constructor); };
-
- while (view) {
- if (isOfType(view)) { return view; }
- view = get(view, 'parentView');
- }
- },
-
- /**
- Return the nearest ancestor that has a given property.
-
- @method nearestWithProperty
- @param {String} property A property name
- @return Ember.View
- */
- nearestWithProperty: function(property) {
- var view = get(this, 'parentView');
-
- while (view) {
- if (property in view) { return view; }
- view = get(view, 'parentView');
- }
- },
-
- /**
- Return the nearest ancestor whose parent is an instance of
- `klass`.
-
- @method nearestChildOf
- @param {Class} klass Subclass of Ember.View (or Ember.View itself)
- @return Ember.View
- */
- nearestChildOf: function(klass) {
- var view = get(this, 'parentView');
-
- while (view) {
- if (get(view, 'parentView') instanceof klass) { return view; }
- view = get(view, 'parentView');
- }
- },
-
- /**
- When the parent view changes, recursively invalidate `controller`
-
- @method _parentViewDidChange
- @private
- */
- _parentViewDidChange: observer('_parentView', function() {
- if (this.isDestroying) { return; }
-
- this._setupKeywords();
- this.trigger('parentViewDidChange');
-
- if (get(this, 'parentView.controller') && !get(this, 'controller')) {
- this.notifyPropertyChange('controller');
- }
- }),
-
- _controllerDidChange: observer('controller', function() {
- if (this.isDestroying) { return; }
-
- this.rerender();
-
- this.forEachChildView(function(view) {
- view.propertyDidChange('controller');
- });
- }),
-
- _setupKeywords: function() {
- var keywords = this._keywords;
- var contextView = this._contextView || this._parentView;
-
- if (contextView) {
- var parentKeywords = contextView._keywords;
-
- keywords.view.setSource(this.isVirtual ? parentKeywords.view : this);
-
- for (var name in parentKeywords) {
- if (keywords[name]) continue;
- keywords[name] = parentKeywords[name];
- }
- } else {
- keywords.view.setSource(this.isVirtual ? null : this);
- }
- },
-
- /**
- Called on your view when it should push strings of HTML into a
- `Ember.RenderBuffer`. Most users will want to override the `template`
- or `templateName` properties instead of this method.
-
- By default, `Ember.View` will look for a function in the `template`
- property and invoke it with the value of `context`. The value of
- `context` will be the view's controller unless you override it.
-
- @method render
- @param {Ember.RenderBuffer} buffer The render buffer
- */
- render: function(buffer) {
- // If this view has a layout, it is the responsibility of the
- // the layout to render the view's template. Otherwise, render the template
- // directly.
- var template = get(this, 'layout') || get(this, 'template');
-
- if (template) {
- var context = get(this, 'context');
- var output;
-
- var data = {
- view: this,
- buffer: buffer,
- isRenderData: true
- };
-
- // Invoke the template with the provided template context, which
- // is the view's controller by default. A hash of data is also passed that provides
- // the template with access to the view and render buffer.
-
- Ember.assert('template must be a function. Did you mean to call Ember.Handlebars.compile("...") or specify templateName instead?', typeof template === 'function');
- // The template should write directly to the render buffer instead
- // of returning a string.
- output = template(context, { data: data });
-
- // If the template returned a string instead of writing to the buffer,
- // push the string onto the buffer.
- if (output !== undefined) { buffer.push(output); }
- }
- },
-
- /**
- Renders the view again. This will work regardless of whether the
- view is already in the DOM or not. If the view is in the DOM, the
- rendering process will be deferred to give bindings a chance
- to synchronize.
-
- If children were added during the rendering process using `appendChild`,
- `rerender` will remove them, because they will be added again
- if needed by the next `render`.
-
- In general, if the display of your view changes, you should modify
- the DOM element directly instead of manually calling `rerender`, which can
- be slow.
-
- @method rerender
- */
- rerender: function() {
- return this.currentState.rerender(this);
- },
-
- /**
- Iterates over the view's `classNameBindings` array, inserts the value
- of the specified property into the `classNames` array, then creates an
- observer to update the view's element if the bound property ever changes
- in the future.
-
- @method _applyClassNameBindings
- @private
- */
- _applyClassNameBindings: function(classBindings) {
- var classNames = this.classNames;
- var elem, newClass, dasherizedClass;
-
- // Loop through all of the configured bindings. These will be either
- // property names ('isUrgent') or property paths relative to the view
- // ('content.isUrgent')
- forEach(classBindings, function(binding) {
-
- var parsedPath;
-
- if (typeof binding === 'string') {
- Ember.assert("classNameBindings must not have spaces in them. Multiple class name bindings can be provided as elements of an array, e.g. ['foo', ':bar']", binding.indexOf(' ') === -1);
- parsedPath = View._parsePropertyPath(binding);
- if (parsedPath.path === '') {
- parsedPath.stream = new SimpleStream(true);
- } else {
- parsedPath.stream = this.getStream('_view.' + parsedPath.path);
- }
- } else {
- parsedPath = binding;
- }
-
- // Variable in which the old class value is saved. The observer function
- // closes over this variable, so it knows which string to remove when
- // the property changes.
- var oldClass;
-
- // Set up an observer on the context. If the property changes, toggle the
- // class name.
- var observer = this._wrapAsScheduled(function() {
- // Get the current value of the property
- newClass = this._classStringForProperty(parsedPath);
- elem = this.$();
-
- // If we had previously added a class to the element, remove it.
- if (oldClass) {
- elem.removeClass(oldClass);
- // Also remove from classNames so that if the view gets rerendered,
- // the class doesn't get added back to the DOM.
- classNames.removeObject(oldClass);
- }
-
- // If necessary, add a new class. Make sure we keep track of it so
- // it can be removed in the future.
- if (newClass) {
- elem.addClass(newClass);
- oldClass = newClass;
- } else {
- oldClass = null;
- }
- });
-
- // Get the class name for the property at its current value
- dasherizedClass = this._classStringForProperty(parsedPath);
-
- if (dasherizedClass) {
- // Ensure that it gets into the classNames array
- // so it is displayed when we render.
- addObject(classNames, dasherizedClass);
-
- // Save a reference to the class name so we can remove it
- // if the observer fires. Remember that this variable has
- // been closed over by the observer.
- oldClass = dasherizedClass;
- }
-
- parsedPath.stream.subscribe(observer, this);
- // Remove className so when the view is rerendered,
- // the className is added based on binding reevaluation
- this.one('willClearRender', function() {
- if (oldClass) {
- classNames.removeObject(oldClass);
- oldClass = null;
- }
- });
-
- }, this);
- },
-
- _unspecifiedAttributeBindings: null,
-
- /**
- Iterates through the view's attribute bindings, sets up observers for each,
- then applies the current value of the attributes to the passed render buffer.
-
- @method _applyAttributeBindings
- @param {Ember.RenderBuffer} buffer
- @private
- */
- _applyAttributeBindings: function(buffer, attributeBindings) {
- var attributeValue;
- var unspecifiedAttributeBindings = this._unspecifiedAttributeBindings = this._unspecifiedAttributeBindings || {};
-
- forEach(attributeBindings, function(binding) {
- var split = binding.split(':');
- var property = split[0];
- var attributeName = split[1] || property;
-
- Ember.assert('You cannot use class as an attributeBinding, use classNameBindings instead.', attributeName !== 'class');
-
- if (property in this) {
- this._setupAttributeBindingObservation(property, attributeName);
-
- // Determine the current value and add it to the render buffer
- // if necessary.
- attributeValue = get(this, property);
- View.applyAttributeBindings(buffer, attributeName, attributeValue);
- } else {
- unspecifiedAttributeBindings[property] = attributeName;
- }
- }, this);
-
- // Lazily setup setUnknownProperty after attributeBindings are initially applied
- this.setUnknownProperty = this._setUnknownProperty;
- },
-
- _setupAttributeBindingObservation: function(property, attributeName) {
- var attributeValue, elem;
-
- // Create an observer to add/remove/change the attribute if the
- // JavaScript property changes.
- var observer = function() {
- elem = this.$();
-
- attributeValue = get(this, property);
-
- View.applyAttributeBindings(elem, attributeName, attributeValue);
- };
-
- this.registerObserver(this, property, observer);
- },
-
- /**
- We're using setUnknownProperty as a hook to setup attributeBinding observers for
- properties that aren't defined on a view at initialization time.
-
- Note: setUnknownProperty will only be called once for each property.
-
- @method setUnknownProperty
- @param key
- @param value
- @private
- */
- setUnknownProperty: null, // Gets defined after initialization by _applyAttributeBindings
-
- _setUnknownProperty: function(key, value) {
- var attributeName = this._unspecifiedAttributeBindings && this._unspecifiedAttributeBindings[key];
- if (attributeName) {
- this._setupAttributeBindingObservation(key, attributeName);
- }
-
- defineProperty(this, key);
- return set(this, key, value);
- },
-
- /**
- Given a property name, returns a dasherized version of that
- property name if the property evaluates to a non-falsy value.
-
- For example, if the view has property `isUrgent` that evaluates to true,
- passing `isUrgent` to this method will return `"is-urgent"`.
-
- @method _classStringForProperty
- @param property
- @private
- */
- _classStringForProperty: function(parsedPath) {
- return View._classStringForValue(parsedPath.path, parsedPath.stream.value(), parsedPath.className, parsedPath.falsyClassName);
- },
-
- // ..........................................................
- // ELEMENT SUPPORT
- //
-
- /**
- Returns the current DOM element for the view.
-
- @property element
- @type DOMElement
- */
- element: null,
-
- /**
- Returns a jQuery object for this view's element. If you pass in a selector
- string, this method will return a jQuery object, using the current element
- as its buffer.
-
- For example, calling `view.$('li')` will return a jQuery object containing
- all of the `li` elements inside the DOM element of this view.
-
- @method $
- @param {String} [selector] a jQuery-compatible selector string
- @return {jQuery} the jQuery object for the DOM node
- */
- $: function(sel) {
- return this.currentState.$(this, sel);
- },
-
- mutateChildViews: function(callback) {
- var childViews = this._childViews;
- var idx = childViews.length;
- var view;
-
- while(--idx >= 0) {
- view = childViews[idx];
- callback(this, view, idx);
- }
-
- return this;
- },
-
- forEachChildView: function(callback) {
- var childViews = this._childViews;
-
- if (!childViews) { return this; }
-
- var len = childViews.length;
- var view, idx;
-
- for (idx = 0; idx < len; idx++) {
- view = childViews[idx];
- callback(view);
- }
-
- return this;
- },
-
- /**
- Appends the view's element to the specified parent element.
-
- If the view does not have an HTML representation yet, `createElement()`
- will be called automatically.
-
- Note that this method just schedules the view to be appended; the DOM
- element will not be appended to the given element until all bindings have
- finished synchronizing.
-
- This is not typically a function that you will need to call directly when
- building your application. You might consider using `Ember.ContainerView`
- instead. If you do need to use `appendTo`, be sure that the target element
- you are providing is associated with an `Ember.Application` and does not
- have an ancestor element that is associated with an Ember view.
-
- @method appendTo
- @param {String|DOMElement|jQuery} A selector, element, HTML string, or jQuery object
- @return {Ember.View} receiver
- */
- appendTo: function(selector) {
- var target = jQuery(selector);
-
- Ember.assert("You tried to append to (" + selector + ") but that isn't in the DOM", target.length > 0);
- Ember.assert("You cannot append to an existing Ember.View. Consider using Ember.ContainerView instead.", !target.is('.ember-view') && !target.parents().is('.ember-view'));
-
- this.constructor.renderer.appendTo(this, target[0]);
-
- return this;
- },
-
- /**
- Replaces the content of the specified parent element with this view's
- element. If the view does not have an HTML representation yet,
- `createElement()` will be called automatically.
-
- Note that this method just schedules the view to be appended; the DOM
- element will not be appended to the given element until all bindings have
- finished synchronizing
-
- @method replaceIn
- @param {String|DOMElement|jQuery} target A selector, element, HTML string, or jQuery object
- @return {Ember.View} received
- */
- replaceIn: function(selector) {
- var target = jQuery(selector);
-
- Ember.assert("You tried to replace in (" + selector + ") but that isn't in the DOM", target.length > 0);
- Ember.assert("You cannot replace an existing Ember.View. Consider using Ember.ContainerView instead.", !target.is('.ember-view') && !target.parents().is('.ember-view'));
-
- this.constructor.renderer.replaceIn(this, target[0]);
-
- return this;
- },
-
- /**
- Appends the view's element to the document body. If the view does
- not have an HTML representation yet, `createElement()` will be called
- automatically.
-
- If your application uses the `rootElement` property, you must append
- the view within that element. Rendering views outside of the `rootElement`
- is not supported.
-
- Note that this method just schedules the view to be appended; the DOM
- element will not be appended to the document body until all bindings have
- finished synchronizing.
-
- @method append
- @return {Ember.View} receiver
- */
- append: function() {
- return this.appendTo(document.body);
- },
-
- /**
- Removes the view's element from the element to which it is attached.
-
- @method remove
- @return {Ember.View} receiver
- */
- remove: function() {
- // What we should really do here is wait until the end of the run loop
- // to determine if the element has been re-appended to a different
- // element.
- // In the interim, we will just re-render if that happens. It is more
- // important than elements get garbage collected.
- if (!this.removedFromDOM) { this.destroyElement(); }
- },
-
- elementId: null,
-
- /**
- Attempts to discover the element in the parent element. The default
- implementation looks for an element with an ID of `elementId` (or the
- view's guid if `elementId` is null). You can override this method to
- provide your own form of lookup. For example, if you want to discover your
- element using a CSS class name instead of an ID.
-
- @method findElementInParentElement
- @param {DOMElement} parentElement The parent's DOM element
- @return {DOMElement} The discovered element
- */
- findElementInParentElement: function(parentElem) {
- var id = "#" + this.elementId;
- return jQuery(id)[0] || jQuery(id, parentElem)[0];
- },
-
- /**
- Creates a DOM representation of the view and all of its child views by
- recursively calling the `render()` method.
-
- After the element has been inserted into the DOM, `didInsertElement` will
- be called on this view and all of its child views.
-
- @method createElement
- @return {Ember.View} receiver
- */
- createElement: function() {
- if (this.element) { return this; }
-
- this._didCreateElementWithoutMorph = true;
- this.constructor.renderer.renderTree(this);
-
- return this;
- },
-
- /**
- Called when a view is going to insert an element into the DOM.
-
- @event willInsertElement
- */
- willInsertElement: Ember.K,
-
- /**
- Called when the element of the view has been inserted into the DOM
- or after the view was re-rendered. Override this function to do any
- set up that requires an element in the document body.
-
- When a view has children, didInsertElement will be called on the
- child view(s) first, bubbling upwards through the hierarchy.
-
- @event didInsertElement
- */
- didInsertElement: Ember.K,
-
- /**
- Called when the view is about to rerender, but before anything has
- been torn down. This is a good opportunity to tear down any manual
- observers you have installed based on the DOM state
-
- @event willClearRender
- */
- willClearRender: Ember.K,
-
- /**
- Destroys any existing element along with the element for any child views
- as well. If the view does not currently have a element, then this method
- will do nothing.
-
- If you implement `willDestroyElement()` on your view, then this method will
- be invoked on your view before your element is destroyed to give you a
- chance to clean up any event handlers, etc.
-
- If you write a `willDestroyElement()` handler, you can assume that your
- `didInsertElement()` handler was called earlier for the same element.
-
- You should not call or override this method yourself, but you may
- want to implement the above callbacks.
-
- @method destroyElement
- @return {Ember.View} receiver
- */
- destroyElement: function() {
- return this.currentState.destroyElement(this);
- },
-
- /**
- Called when the element of the view is going to be destroyed. Override
- this function to do any teardown that requires an element, like removing
- event listeners.
-
- Please note: any property changes made during this event will have no
- effect on object observers.
-
- @event willDestroyElement
- */
- willDestroyElement: Ember.K,
-
- /**
- Called when the parentView property has changed.
-
- @event parentViewDidChange
- */
- parentViewDidChange: Ember.K,
-
- instrumentName: 'view',
-
- instrumentDetails: function(hash) {
- hash.template = get(this, 'templateName');
- this._super(hash);
- },
-
- beforeRender: function(buffer) {},
-
- afterRender: function(buffer) {},
-
- applyAttributesToBuffer: function(buffer) {
- // Creates observers for all registered class name and attribute bindings,
- // then adds them to the element.
- var classNameBindings = get(this, 'classNameBindings');
- if (classNameBindings.length) {
- this._applyClassNameBindings(classNameBindings);
- }
-
- // Pass the render buffer so the method can apply attributes directly.
- // This isn't needed for class name bindings because they use the
- // existing classNames infrastructure.
- var attributeBindings = get(this, 'attributeBindings');
- if (attributeBindings.length) {
- this._applyAttributeBindings(buffer, attributeBindings);
- }
-
- buffer.setClasses(this.classNames);
- buffer.id(this.elementId);
-
- var role = get(this, 'ariaRole');
- if (role) {
- buffer.attr('role', role);
- }
-
- if (get(this, 'isVisible') === false) {
- buffer.style('display', 'none');
- }
- },
-
- // ..........................................................
- // STANDARD RENDER PROPERTIES
- //
-
- /**
- Tag name for the view's outer element. The tag name is only used when an
- element is first created. If you change the `tagName` for an element, you
- must destroy and recreate the view element.
-
- By default, the render buffer will use a `<div>` tag for views.
-
- @property tagName
- @type String
- @default null
- */
-
- // We leave this null by default so we can tell the difference between
- // the default case and a user-specified tag.
- tagName: null,
-
- /**
- The WAI-ARIA role of the control represented by this view. For example, a
- button may have a role of type 'button', or a pane may have a role of
- type 'alertdialog'. This property is used by assistive software to help
- visually challenged users navigate rich web applications.
-
- The full list of valid WAI-ARIA roles is available at:
- [http://www.w3.org/TR/wai-aria/roles#roles_categorization](http://www.w3.org/TR/wai-aria/roles#roles_categorization)
-
- @property ariaRole
- @type String
- @default null
- */
- ariaRole: null,
-
- /**
- Standard CSS class names to apply to the view's outer element. This
- property automatically inherits any class names defined by the view's
- superclasses as well.
-
- @property classNames
- @type Array
- @default ['ember-view']
- */
- classNames: ['ember-view'],
-
- /**
- A list of properties of the view to apply as class names. If the property
- is a string value, the value of that string will be applied as a class
- name.
-
- ```javascript
- // Applies the 'high' class to the view element
- Ember.View.extend({
- classNameBindings: ['priority']
- priority: 'high'
- });
- ```
-
- If the value of the property is a Boolean, the name of that property is
- added as a dasherized class name.
-
- ```javascript
- // Applies the 'is-urgent' class to the view element
- Ember.View.extend({
- classNameBindings: ['isUrgent']
- isUrgent: true
- });
- ```
-
- If you would prefer to use a custom value instead of the dasherized
- property name, you can pass a binding like this:
-
- ```javascript
- // Applies the 'urgent' class to the view element
- Ember.View.extend({
- classNameBindings: ['isUrgent:urgent']
- isUrgent: true
- });
- ```
-
- This list of properties is inherited from the view's superclasses as well.
-
- @property classNameBindings
- @type Array
- @default []
- */
- classNameBindings: EMPTY_ARRAY,
-
- /**
- A list of properties of the view to apply as attributes. If the property is
- a string value, the value of that string will be applied as the attribute.
-
- ```javascript
- // Applies the type attribute to the element
- // with the value "button", like <div type="button">
- Ember.View.extend({
- attributeBindings: ['type'],
- type: 'button'
- });
- ```
-
- If the value of the property is a Boolean, the name of that property is
- added as an attribute.
-
- ```javascript
- // Renders something like <div enabled="enabled">
- Ember.View.extend({
- attributeBindings: ['enabled'],
- enabled: true
- });
- ```
-
- @property attributeBindings
- */
- attributeBindings: EMPTY_ARRAY,
-
- // .......................................................
- // CORE DISPLAY METHODS
- //
-
- /**
- Setup a view, but do not finish waking it up.
-
- * configure `childViews`
- * register the view with the global views hash, which is used for event
- dispatch
-
- @method init
- @private
- */
- init: function() {
- if (!this.isVirtual && !this.elementId) {
- this.elementId = guidFor(this);
- }
-
- this._super();
-
- // setup child views. be sure to clone the child views array first
- this._childViews = this._childViews.slice();
- this._baseContext = undefined;
- this._contextStream = undefined;
- this._streamBindings = undefined;
-
- if (!this._keywords) {
- this._keywords = create(null);
- }
- this._keywords.view = new SimpleStream();
- this._keywords._view = this;
- this._keywords.controller = new KeyStream(this, 'controller');
- this._setupKeywords();
-
- Ember.assert("Only arrays are allowed for 'classNameBindings'", typeOf(this.classNameBindings) === 'array');
- this.classNameBindings = emberA(this.classNameBindings.slice());
-
- Ember.assert("Only arrays are allowed for 'classNames'", typeOf(this.classNames) === 'array');
- this.classNames = emberA(this.classNames.slice());
- },
-
- appendChild: function(view, options) {
- return this.currentState.appendChild(this, view, options);
- },
-
- /**
- Removes the child view from the parent view.
-
- @method removeChild
- @param {Ember.View} view
- @return {Ember.View} receiver
- */
- removeChild: function(view) {
- // If we're destroying, the entire subtree will be
- // freed, and the DOM will be handled separately,
- // so no need to mess with childViews.
- if (this.isDestroying) { return; }
-
- // update parent node
- set(view, '_parentView', null);
-
- // remove view from childViews array.
- var childViews = this._childViews;
-
- removeObject(childViews, view);
-
- this.propertyDidChange('childViews'); // HUH?! what happened to will change?
-
- return this;
- },
-
- /**
- Removes all children from the `parentView`.
-
- @method removeAllChildren
- @return {Ember.View} receiver
- */
- removeAllChildren: function() {
- return this.mutateChildViews(function(parentView, view) {
- parentView.removeChild(view);
- });
- },
-
- destroyAllChildren: function() {
- return this.mutateChildViews(function(parentView, view) {
- view.destroy();
- });
- },
-
- /**
- Removes the view from its `parentView`, if one is found. Otherwise
- does nothing.
-
- @method removeFromParent
- @return {Ember.View} receiver
- */
- removeFromParent: function() {
- var parent = this._parentView;
-
- // Remove DOM element from parent
- this.remove();
-
- if (parent) { parent.removeChild(this); }
- return this;
- },
-
- /**
- You must call `destroy` on a view to destroy the view (and all of its
- child views). This will remove the view from any parent node, then make
- sure that the DOM element managed by the view can be released by the
- memory manager.
-
- @method destroy
- */
- destroy: function() {
- // get parentView before calling super because it'll be destroyed
- var nonVirtualParentView = get(this, 'parentView');
- var viewName = this.viewName;
-
- if (!this._super()) { return; }
-
- // remove from non-virtual parent view if viewName was specified
- if (viewName && nonVirtualParentView) {
- nonVirtualParentView.set(viewName, null);
- }
-
- return this;
- },
-
- /**
- Instantiates a view to be added to the childViews array during view
- initialization. You generally will not call this method directly unless
- you are overriding `createChildViews()`. Note that this method will
- automatically configure the correct settings on the new view instance to
- act as a child of the parent.
-
- @method createChildView
- @param {Class|String} viewClass
- @param {Hash} [attrs] Attributes to add
- @return {Ember.View} new instance
- */
- createChildView: function(view, attrs) {
- if (!view) {
- throw new TypeError("createChildViews first argument must exist");
- }
-
- if (view.isView && view._parentView === this && view.container === this.container) {
- return view;
- }
-
- attrs = attrs || {};
- attrs._parentView = this;
-
- if (CoreView.detect(view)) {
- attrs.templateData = attrs.templateData || get(this, 'templateData');
-
- attrs.container = this.container;
- view = view.create(attrs);
-
- // don't set the property on a virtual view, as they are invisible to
- // consumers of the view API
- if (view.viewName) {
- set(get(this, 'concreteView'), view.viewName, view);
- }
- } else if ('string' === typeof view) {
- var fullName = 'view:' + view;
- var ViewKlass = this.container.lookupFactory(fullName);
-
- Ember.assert("Could not find view: '" + fullName + "'", !!ViewKlass);
-
- attrs.templateData = get(this, 'templateData');
- view = ViewKlass.create(attrs);
- } else {
- Ember.assert('You must pass instance or subclass of View', view.isView);
- attrs.container = this.container;
-
- if (!get(view, 'templateData')) {
- attrs.templateData = get(this, 'templateData');
- }
-
- setProperties(view, attrs);
-
- }
-
- return view;
- },
-
- becameVisible: Ember.K,
- becameHidden: Ember.K,
-
- /**
- When the view's `isVisible` property changes, toggle the visibility
- element of the actual DOM element.
-
- @method _isVisibleDidChange
- @private
- */
- _isVisibleDidChange: observer('isVisible', function() {
- if (this._isVisible === get(this, 'isVisible')) { return ; }
- run.scheduleOnce('render', this, this._toggleVisibility);
- }),
-
- _toggleVisibility: function() {
- var $el = this.$();
- var isVisible = get(this, 'isVisible');
-
- if (this._isVisible === isVisible) { return ; }
-
- // It's important to keep these in sync, even if we don't yet have
- // an element in the DOM to manipulate:
- this._isVisible = isVisible;
-
- if (!$el) { return; }
-
- $el.toggle(isVisible);
-
- if (this._isAncestorHidden()) { return; }
-
- if (isVisible) {
- this._notifyBecameVisible();
- } else {
- this._notifyBecameHidden();
- }
- },
-
- _notifyBecameVisible: function() {
- this.trigger('becameVisible');
-
- this.forEachChildView(function(view) {
- var isVisible = get(view, 'isVisible');
-
- if (isVisible || isVisible === null) {
- view._notifyBecameVisible();
- }
- });
- },
-
- _notifyBecameHidden: function() {
- this.trigger('becameHidden');
- this.forEachChildView(function(view) {
- var isVisible = get(view, 'isVisible');
-
- if (isVisible || isVisible === null) {
- view._notifyBecameHidden();
- }
- });
- },
-
- _isAncestorHidden: function() {
- var parent = get(this, 'parentView');
-
- while (parent) {
- if (get(parent, 'isVisible') === false) { return true; }
-
- parent = get(parent, 'parentView');
- }
-
- return false;
- },
- transitionTo: function(state, children) {
- Ember.deprecate("Ember.View#transitionTo has been deprecated, it is for internal use only");
- this._transitionTo(state, children);
- },
- _transitionTo: function(state, children) {
- var priorState = this.currentState;
- var currentState = this.currentState = this._states[state];
- this._state = state;
-
- if (priorState && priorState.exit) { priorState.exit(this); }
- if (currentState.enter) { currentState.enter(this); }
- },
-
- // .......................................................
- // EVENT HANDLING
- //
-
- /**
- Handle events from `Ember.EventDispatcher`
-
- @method handleEvent
- @param eventName {String}
- @param evt {Event}
- @private
- */
- handleEvent: function(eventName, evt) {
- return this.currentState.handleEvent(this, eventName, evt);
- },
-
- registerObserver: function(root, path, target, observer) {
- if (!observer && 'function' === typeof target) {
- observer = target;
- target = null;
- }
-
- if (!root || typeof root !== 'object') {
- return;
- }
-
- var scheduledObserver = this._wrapAsScheduled(observer);
-
- addObserver(root, path, target, scheduledObserver);
-
- this.one('willClearRender', function() {
- removeObserver(root, path, target, scheduledObserver);
- });
- },
-
- _wrapAsScheduled: function(fn) {
- var view = this;
- var stateCheckedFn = function() {
- view.currentState.invokeObserver(this, fn);
- };
- var scheduledFn = function() {
- run.scheduleOnce('render', this, stateCheckedFn);
- };
- return scheduledFn;
- },
-
- getStream: function(path) {
- return this._getContextStream().get(path);
- },
-
- _getBindingForStream: function(path) {
- if (this._streamBindings === undefined) {
- this._streamBindings = create(null);
- this.one('willDestroyElement', this, this._destroyStreamBindings);
- }
-
- if (this._streamBindings[path] !== undefined) {
- return this._streamBindings[path];
- } else {
- var stream = this._getContextStream().get(path);
- return this._streamBindings[path] = new StreamBinding(stream);
- }
- },
-
- _destroyStreamBindings: function() {
- var streamBindings = this._streamBindings;
- for (var path in streamBindings) {
- streamBindings[path].destroy();
- }
- this._streamBindings = undefined;
- },
-
- _getContextStream: function() {
- if (this._contextStream === undefined) {
- this._baseContext = new KeyStream(this, 'context');
- this._contextStream = new ContextStream(this);
- this.one('willDestroyElement', this, this._destroyContextStream);
- }
-
- return this._contextStream;
- },
-
- _destroyContextStream: function() {
- this._baseContext.destroy();
- this._baseContext = undefined;
- this._contextStream.destroy();
- this._contextStream = undefined;
- },
-
- _unsubscribeFromStreamBindings: function() {
- for (var key in this._streamBindingSubscriptions) {
- var streamBinding = this[key + 'Binding'];
- var callback = this._streamBindingSubscriptions[key];
- streamBinding.unsubscribe(callback);
- }
- }
- });
-
- deprecateProperty(View.prototype, 'state', '_state');
- deprecateProperty(View.prototype, 'states', '_states');
-
- /*
- Describe how the specified actions should behave in the various
- states that a view can exist in. Possible states:
-
- * preRender: when a view is first instantiated, and after its
- element was destroyed, it is in the preRender state
- * inBuffer: once a view has been rendered, but before it has
- been inserted into the DOM, it is in the inBuffer state
- * hasElement: the DOM representation of the view is created,
- and is ready to be inserted
- * inDOM: once a view has been inserted into the DOM it is in
- the inDOM state. A view spends the vast majority of its
- existence in this state.
- * destroyed: once a view has been destroyed (using the destroy
- method), it is in this state. No further actions can be invoked
- on a destroyed view.
- */
-
- // in the destroyed state, everything is illegal
-
- // before rendering has begun, all legal manipulations are noops.
-
- // inside the buffer, legal manipulations are done on the buffer
-
- // once the view has been inserted into the DOM, legal manipulations
- // are done on the DOM element.
-
- View.reopenClass({
-
- /**
- Parse a path and return an object which holds the parsed properties.
-
- For example a path like "content.isEnabled:enabled:disabled" will return the
- following object:
-
- ```javascript
- {
- path: "content.isEnabled",
- className: "enabled",
- falsyClassName: "disabled",
- classNames: ":enabled:disabled"
- }
- ```
-
- @method _parsePropertyPath
- @static
- @private
- */
- _parsePropertyPath: function(path) {
- var split = path.split(':');
- var propertyPath = split[0];
- var classNames = "";
- var className, falsyClassName;
-
- // check if the property is defined as prop:class or prop:trueClass:falseClass
- if (split.length > 1) {
- className = split[1];
- if (split.length === 3) { falsyClassName = split[2]; }
-
- classNames = ':' + className;
- if (falsyClassName) { classNames += ":" + falsyClassName; }
- }
-
- return {
- stream: undefined,
- path: propertyPath,
- classNames: classNames,
- className: (className === '') ? undefined : className,
- falsyClassName: falsyClassName
- };
- },
-
- /**
- Get the class name for a given value, based on the path, optional
- `className` and optional `falsyClassName`.
-
- - if a `className` or `falsyClassName` has been specified:
- - if the value is truthy and `className` has been specified,
- `className` is returned
- - if the value is falsy and `falsyClassName` has been specified,
- `falsyClassName` is returned
- - otherwise `null` is returned
- - if the value is `true`, the dasherized last part of the supplied path
- is returned
- - if the value is not `false`, `undefined` or `null`, the `value`
- is returned
- - if none of the above rules apply, `null` is returned
-
- @method _classStringForValue
- @param path
- @param val
- @param className
- @param falsyClassName
- @static
- @private
- */
- _classStringForValue: function(path, val, className, falsyClassName) {
- if(isArray(val)) {
- val = get(val, 'length') !== 0;
- }
-
- // When using the colon syntax, evaluate the truthiness or falsiness
- // of the value to determine which className to return
- if (className || falsyClassName) {
- if (className && !!val) {
- return className;
-
- } else if (falsyClassName && !val) {
- return falsyClassName;
-
- } else {
- return null;
- }
-
- // If value is a Boolean and true, return the dasherized property
- // name.
- } else if (val === true) {
- // Normalize property path to be suitable for use
- // as a class name. For exaple, content.foo.barBaz
- // becomes bar-baz.
- var parts = path.split('.');
- return dasherize(parts[parts.length-1]);
-
- // If the value is not false, undefined, or null, return the current
- // value of the property.
- } else if (val !== false && val != null) {
- return val;
-
- // Nothing to display. Return null so that the old class is removed
- // but no new class is added.
- } else {
- return null;
- }
- }
- });
-
- var mutation = EmberObject.extend(Evented).create();
- // TODO MOVE TO RENDERER HOOKS
- View.addMutationListener = function(callback) {
- mutation.on('change', callback);
- };
-
- View.removeMutationListener = function(callback) {
- mutation.off('change', callback);
- };
-
- View.notifyMutationListeners = function() {
- mutation.trigger('change');
- };
-
- /**
- Global views hash
-
- @property views
- @static
- @type Hash
- */
- View.views = {};
-
- // If someone overrides the child views computed property when
- // defining their class, we want to be able to process the user's
- // supplied childViews and then restore the original computed property
- // at view initialization time. This happens in Ember.ContainerView's init
- // method.
- View.childViewsProperty = childViewsProperty;
-
- View.applyAttributeBindings = function(elem, name, value) {
- var type = typeOf(value);
-
- // if this changes, also change the logic in ember-handlebars/lib/helpers/binding.js
- if (name !== 'value' && (type === 'string' || (type === 'number' && !isNaN(value)))) {
- if (value !== elem.attr(name)) {
- elem.attr(name, value);
- }
- } else if (name === 'value' || type === 'boolean') {
- if (isNone(value) || value === false) {
- // `null`, `undefined` or `false` should remove attribute
- elem.removeAttr(name);
- // In IE8 `prop` couldn't remove attribute when name is `required`.
- if (name === 'required') {
- elem.removeProp(name);
- } else {
- elem.prop(name, '');
- }
- } else if (value !== elem.prop(name)) {
- // value should always be properties
- elem.prop(name, value);
- }
- } else if (!value) {
- elem.removeAttr(name);
- }
- };
-
- __exports__["default"] = View;
- });
-enifed("ember",
- ["ember-metal","ember-runtime","ember-handlebars","ember-views","ember-routing","ember-routing-handlebars","ember-application","ember-extension-support"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__) {
- "use strict";
- /* global navigator */
- // require the main entry points for each of these packages
- // this is so that the global exports occur properly
-
- // do this to ensure that Ember.Test is defined properly on the global
- // if it is present.
- if (Ember.__loader.registry['ember-testing']) {
- requireModule('ember-testing');
- }
-
- /**
- Ember
-
- @module ember
- */
-
- Ember.deprecate('Usage of Ember is deprecated for Internet Explorer 6 and 7, support will be removed in the next major version.', !navigator.userAgent.match(/MSIE [67]/));
- });
-enifed("morph",
- ["./morph/morph","./morph/dom-helper","exports"],
- function(__dependency1__, __dependency2__, __exports__) {
- "use strict";
- var Morph = __dependency1__["default"];
- var Morph;
- __exports__.Morph = Morph;
- var DOMHelper = __dependency2__["default"];
- var DOMHelper;
- __exports__.DOMHelper = DOMHelper;
- });
-enifed("morph/dom-helper",
- ["../morph/morph","./dom-helper/build-html-dom","exports"],
- function(__dependency1__, __dependency2__, __exports__) {
- "use strict";
- var Morph = __dependency1__["default"];
- var buildHTMLDOM = __dependency2__.buildHTMLDOM;
- var svgNamespace = __dependency2__.svgNamespace;
- var svgHTMLIntegrationPoints = __dependency2__.svgHTMLIntegrationPoints;
-
- var deletesBlankTextNodes = (function(){
- var element = document.createElement('div');
- element.appendChild( document.createTextNode('') );
- var clonedElement = element.cloneNode(true);
- return clonedElement.childNodes.length === 0;
- })();
-
- var ignoresCheckedAttribute = (function(){
- var element = document.createElement('input');
- element.setAttribute('checked', 'checked');
- var clonedElement = element.cloneNode(false);
- return !clonedElement.checked;
- })();
-
- function isSVG(ns){
- return ns === svgNamespace;
- }
-
- // This is not the namespace of the element, but of
- // the elements inside that elements.
- function interiorNamespace(element){
- if (
- element &&
- element.namespaceURI === svgNamespace &&
- !svgHTMLIntegrationPoints[element.tagName]
- ) {
- return svgNamespace;
- } else {
- return null;
- }
- }
-
- // The HTML spec allows for "omitted start tags". These tags are optional
- // when their intended child is the first thing in the parent tag. For
- // example, this is a tbody start tag:
- //
- // <table>
- // <tbody>
- // <tr>
- //
- // The tbody may be omitted, and the browser will accept and render:
- //
- // <table>
- // <tr>
- //
- // However, the omitted start tag will still be added to the DOM. Here
- // we test the string and context to see if the browser is about to
- // perform this cleanup.
- //
- // http://www.whatwg.org/specs/web-apps/current-work/multipage/syntax.html#optional-tags
- // describes which tags are omittable. The spec for tbody and colgroup
- // explains this behavior:
- //
- // http://www.whatwg.org/specs/web-apps/current-work/multipage/tables.html#the-tbody-element
- // http://www.whatwg.org/specs/web-apps/current-work/multipage/tables.html#the-colgroup-element
- //
-
- var omittedStartTagChildTest = /<([\w:]+)/;
- function detectOmittedStartTag(string, contextualElement){
- // Omitted start tags are only inside table tags.
- if (contextualElement.tagName === 'TABLE') {
- var omittedStartTagChildMatch = omittedStartTagChildTest.exec(string);
- if (omittedStartTagChildMatch) {
- var omittedStartTagChild = omittedStartTagChildMatch[1];
- // It is already asserted that the contextual element is a table
- // and not the proper start tag. Just see if a tag was omitted.
- return omittedStartTagChild === 'tr' ||
- omittedStartTagChild === 'col';
- }
- }
- }
-
- function buildSVGDOM(html, dom){
- var div = dom.document.createElement('div');
- div.innerHTML = '<svg>'+html+'</svg>';
- return div.firstChild.childNodes;
- }
-
- /*
- * A class wrapping DOM functions to address environment compatibility,
- * namespaces, contextual elements for morph un-escaped content
- * insertion.
- *
- * When entering a template, a DOMHelper should be passed:
- *
- * template(context, { hooks: hooks, dom: new DOMHelper() });
- *
- * TODO: support foreignObject as a passed contextual element. It has
- * a namespace (svg) that does not match its internal namespace
- * (xhtml).
- *
- * @class DOMHelper
- * @constructor
- * @param {HTMLDocument} _document The document DOM methods are proxied to
- */
- function DOMHelper(_document){
- this.document = _document || window.document;
- this.namespace = null;
- }
-
- var prototype = DOMHelper.prototype;
- prototype.constructor = DOMHelper;
-
- prototype.insertBefore = function(element, childElement, referenceChild) {
- return element.insertBefore(childElement, referenceChild);
- };
-
- prototype.appendChild = function(element, childElement) {
- return element.appendChild(childElement);
- };
-
- prototype.appendText = function(element, text) {
- return element.appendChild(this.document.createTextNode(text));
- };
-
- prototype.setAttribute = function(element, name, value) {
- element.setAttribute(name, value);
- };
-
- if (document.createElementNS) {
- // Only opt into namespace detection if a contextualElement
- // is passed.
- prototype.createElement = function(tagName, contextualElement) {
- var namespace = this.namespace;
- if (contextualElement) {
- if (tagName === 'svg') {
- namespace = svgNamespace;
- } else {
- namespace = interiorNamespace(contextualElement);
- }
- }
- if (namespace) {
- return this.document.createElementNS(namespace, tagName);
- } else {
- return this.document.createElement(tagName);
- }
- };
- } else {
- prototype.createElement = function(tagName) {
- return this.document.createElement(tagName);
- };
- }
-
- prototype.setNamespace = function(ns) {
- this.namespace = ns;
- };
-
- prototype.detectNamespace = function(element) {
- this.namespace = interiorNamespace(element);
- };
-
- prototype.createDocumentFragment = function(){
- return this.document.createDocumentFragment();
- };
-
- prototype.createTextNode = function(text){
- return this.document.createTextNode(text);
- };
-
- prototype.repairClonedNode = function(element, blankChildTextNodes, isChecked){
- if (deletesBlankTextNodes && blankChildTextNodes.length > 0) {
- for (var i=0, len=blankChildTextNodes.length;i<len;i++){
- var textNode = this.document.createTextNode(''),
- offset = blankChildTextNodes[i],
- before = element.childNodes[offset];
- if (before) {
- element.insertBefore(textNode, before);
- } else {
- element.appendChild(textNode);
- }
- }
- }
- if (ignoresCheckedAttribute && isChecked) {
- element.setAttribute('checked', 'checked');
- }
- };
-
- prototype.cloneNode = function(element, deep){
- var clone = element.cloneNode(!!deep);
- return clone;
- };
-
- prototype.createMorph = function(parent, start, end, contextualElement){
- if (!contextualElement && parent.nodeType === 1) {
- contextualElement = parent;
- }
- return new Morph(parent, start, end, this, contextualElement);
- };
-
- // This helper is just to keep the templates good looking,
- // passing integers instead of element references.
- prototype.createMorphAt = function(parent, startIndex, endIndex, contextualElement){
- var childNodes = parent.childNodes,
- start = startIndex === -1 ? null : childNodes[startIndex],
- end = endIndex === -1 ? null : childNodes[endIndex];
- return this.createMorph(parent, start, end, contextualElement);
- };
-
- prototype.insertMorphBefore = function(element, referenceChild, contextualElement) {
- var start = this.document.createTextNode('');
- var end = this.document.createTextNode('');
- element.insertBefore(start, referenceChild);
- element.insertBefore(end, referenceChild);
- return this.createMorph(element, start, end, contextualElement);
- };
-
- prototype.appendMorph = function(element, contextualElement) {
- var start = this.document.createTextNode('');
- var end = this.document.createTextNode('');
- element.appendChild(start);
- element.appendChild(end);
- return this.createMorph(element, start, end, contextualElement);
- };
-
- prototype.parseHTML = function(html, contextualElement) {
- var isSVGContent = (
- isSVG(this.namespace) &&
- !svgHTMLIntegrationPoints[contextualElement.tagName]
- );
-
- if (isSVGContent) {
- return buildSVGDOM(html, this);
- } else {
- var nodes = buildHTMLDOM(html, contextualElement, this);
- if (detectOmittedStartTag(html, contextualElement)) {
- var node = nodes[0];
- while (node && node.nodeType !== 1) {
- node = node.nextSibling;
- }
- return node.childNodes;
- } else {
- return nodes;
- }
- }
- };
-
- __exports__["default"] = DOMHelper;
- });
-enifed("morph/dom-helper/build-html-dom",
- ["exports"],
- function(__exports__) {
- "use strict";
- var svgHTMLIntegrationPoints = {foreignObject: 1, desc: 1, title: 1};
- __exports__.svgHTMLIntegrationPoints = svgHTMLIntegrationPoints;var svgNamespace = 'http://www.w3.org/2000/svg';
- __exports__.svgNamespace = svgNamespace;
- // Safari does not like using innerHTML on SVG HTML integration
- // points (desc/title/foreignObject).
- var needsIntegrationPointFix = document && document.createElementNS && (function() {
- // In FF title will not accept innerHTML.
- var testEl = document.createElementNS(svgNamespace, 'title');
- testEl.innerHTML = "<div></div>";
- return testEl.childNodes.length === 0 || testEl.childNodes[0].nodeType !== 1;
- })();
-
- // Internet Explorer prior to 9 does not allow setting innerHTML if the first element
- // is a "zero-scope" element. This problem can be worked around by making
- // the first node an invisible text node. We, like Modernizr, use &shy;
- var needsShy = document && (function() {
- var testEl = document.createElement('div');
- testEl.innerHTML = "<div></div>";
- testEl.firstChild.innerHTML = "<script><\/script>";
- return testEl.firstChild.innerHTML === '';
- })();
-
- // IE 8 (and likely earlier) likes to move whitespace preceeding
- // a script tag to appear after it. This means that we can
- // accidentally remove whitespace when updating a morph.
- var movesWhitespace = document && (function() {
- var testEl = document.createElement('div');
- testEl.innerHTML = "Test: <script type='text/x-placeholder'><\/script>Value";
- return testEl.childNodes[0].nodeValue === 'Test:' &&
- testEl.childNodes[2].nodeValue === ' Value';
- })();
-
- // IE8 create a selected attribute where they should only
- // create a property
- var createsSelectedAttribute = document && (function() {
- var testEl = document.createElement('div');
- testEl.innerHTML = "<select><option></option></select>";
- return testEl.childNodes[0].childNodes[0].getAttribute('selected') === 'selected';
- })();
-
- var detectAutoSelectedOption;
- if (createsSelectedAttribute) {
- var detectAutoSelectedOptionRegex = /<option[^>]*selected/;
- detectAutoSelectedOption = function detectAutoSelectedOption(select, option, html) { //jshint ignore:line
- return select.selectedIndex === 0 &&
- !detectAutoSelectedOptionRegex.test(html);
- };
- } else {
- detectAutoSelectedOption = function detectAutoSelectedOption(select, option, html) { //jshint ignore:line
- var selectedAttribute = option.getAttribute('selected');
- return select.selectedIndex === 0 && (
- selectedAttribute === null ||
- ( selectedAttribute !== '' && selectedAttribute.toLowerCase() !== 'selected' )
- );
- };
- }
-
- // IE 9 and earlier don't allow us to set innerHTML on col, colgroup, frameset,
- // html, style, table, tbody, tfoot, thead, title, tr. Detect this and add
- // them to an initial list of corrected tags.
- //
- // Here we are only dealing with the ones which can have child nodes.
- //
- var tagNamesRequiringInnerHTMLFix, tableNeedsInnerHTMLFix;
- var tableInnerHTMLTestElement = document.createElement('table');
- try {
- tableInnerHTMLTestElement.innerHTML = '<tbody></tbody>';
- } catch (e) {
- } finally {
- tableNeedsInnerHTMLFix = (tableInnerHTMLTestElement.childNodes.length === 0);
- }
- if (tableNeedsInnerHTMLFix) {
- tagNamesRequiringInnerHTMLFix = {
- colgroup: ['table'],
- table: [],
- tbody: ['table'],
- tfoot: ['table'],
- thead: ['table'],
- tr: ['table', 'tbody']
- };
- }
-
- // IE 8 doesn't allow setting innerHTML on a select tag. Detect this and
- // add it to the list of corrected tags.
- //
- var selectInnerHTMLTestElement = document.createElement('select');
- selectInnerHTMLTestElement.innerHTML = '<option></option>';
- if (selectInnerHTMLTestElement) {
- tagNamesRequiringInnerHTMLFix = tagNamesRequiringInnerHTMLFix || {};
- tagNamesRequiringInnerHTMLFix.select = [];
- }
-
- function scriptSafeInnerHTML(element, html) {
- // without a leading text node, IE will drop a leading script tag.
- html = '&shy;'+html;
-
- element.innerHTML = html;
-
- var nodes = element.childNodes;
-
- // Look for &shy; to remove it.
- var shyElement = nodes[0];
- while (shyElement.nodeType === 1 && !shyElement.nodeName) {
- shyElement = shyElement.firstChild;
- }
- // At this point it's the actual unicode character.
- if (shyElement.nodeType === 3 && shyElement.nodeValue.charAt(0) === "\u00AD") {
- var newValue = shyElement.nodeValue.slice(1);
- if (newValue.length) {
- shyElement.nodeValue = shyElement.nodeValue.slice(1);
- } else {
- shyElement.parentNode.removeChild(shyElement);
- }
- }
-
- return nodes;
- }
-
- function buildDOMWithFix(html, contextualElement){
- var tagName = contextualElement.tagName;
-
- // Firefox versions < 11 do not have support for element.outerHTML.
- var outerHTML = contextualElement.outerHTML || new XMLSerializer().serializeToString(contextualElement);
- if (!outerHTML) {
- throw "Can't set innerHTML on "+tagName+" in this browser";
- }
-
- var wrappingTags = tagNamesRequiringInnerHTMLFix[tagName.toLowerCase()];
- var startTag = outerHTML.match(new RegExp("<"+tagName+"([^>]*)>", 'i'))[0];
- var endTag = '</'+tagName+'>';
-
- var wrappedHTML = [startTag, html, endTag];
-
- var i = wrappingTags.length;
- var wrappedDepth = 1 + i;
- while(i--) {
- wrappedHTML.unshift('<'+wrappingTags[i]+'>');
- wrappedHTML.push('</'+wrappingTags[i]+'>');
- }
-
- var wrapper = document.createElement('div');
- scriptSafeInnerHTML(wrapper, wrappedHTML.join(''));
- var element = wrapper;
- while (wrappedDepth--) {
- element = element.firstChild;
- while (element && element.nodeType !== 1) {
- element = element.nextSibling;
- }
- }
- while (element && element.tagName !== tagName) {
- element = element.nextSibling;
- }
- return element ? element.childNodes : [];
- }
-
- var buildDOM;
- if (needsShy) {
- buildDOM = function buildDOM(html, contextualElement, dom){
- contextualElement = dom.cloneNode(contextualElement, false);
- scriptSafeInnerHTML(contextualElement, html);
- return contextualElement.childNodes;
- };
- } else {
- buildDOM = function buildDOM(html, contextualElement, dom){
- contextualElement = dom.cloneNode(contextualElement, false);
- contextualElement.innerHTML = html;
- return contextualElement.childNodes;
- };
- }
-
- var buildIESafeDOM;
- if (tagNamesRequiringInnerHTMLFix || movesWhitespace) {
- buildIESafeDOM = function buildIESafeDOM(html, contextualElement, dom) {
- // Make a list of the leading text on script nodes. Include
- // script tags without any whitespace for easier processing later.
- var spacesBefore = [];
- var spacesAfter = [];
- html = html.replace(/(\s*)(<script)/g, function(match, spaces, tag) {
- spacesBefore.push(spaces);
- return tag;
- });
-
- html = html.replace(/(<\/script>)(\s*)/g, function(match, tag, spaces) {
- spacesAfter.push(spaces);
- return tag;
- });
-
- // Fetch nodes
- var nodes;
- if (tagNamesRequiringInnerHTMLFix[contextualElement.tagName.toLowerCase()]) {
- // buildDOMWithFix uses string wrappers for problematic innerHTML.
- nodes = buildDOMWithFix(html, contextualElement);
- } else {
- nodes = buildDOM(html, contextualElement, dom);
- }
-
- // Build a list of script tags, the nodes themselves will be
- // mutated as we add test nodes.
- var i, j, node, nodeScriptNodes;
- var scriptNodes = [];
- for (i=0;node=nodes[i];i++) {
- if (node.nodeType !== 1) {
- continue;
- }
- if (node.tagName === 'SCRIPT') {
- scriptNodes.push(node);
- } else {
- nodeScriptNodes = node.getElementsByTagName('script');
- for (j=0;j<nodeScriptNodes.length;j++) {
- scriptNodes.push(nodeScriptNodes[j]);
- }
- }
- }
-
- // Walk the script tags and put back their leading text nodes.
- var scriptNode, textNode, spaceBefore, spaceAfter;
- for (i=0;scriptNode=scriptNodes[i];i++) {
- spaceBefore = spacesBefore[i];
- if (spaceBefore && spaceBefore.length > 0) {
- textNode = dom.document.createTextNode(spaceBefore);
- scriptNode.parentNode.insertBefore(textNode, scriptNode);
- }
-
- spaceAfter = spacesAfter[i];
- if (spaceAfter && spaceAfter.length > 0) {
- textNode = dom.document.createTextNode(spaceAfter);
- scriptNode.parentNode.insertBefore(textNode, scriptNode.nextSibling);
- }
- }
-
- return nodes;
- };
- } else {
- buildIESafeDOM = buildDOM;
- }
-
- // When parsing innerHTML, the browser may set up DOM with some things
- // not desired. For example, with a select element context and option
- // innerHTML the first option will be marked selected.
- //
- // This method cleans up some of that, resetting those values back to
- // their defaults.
- //
- function buildSafeDOM(html, contextualElement, dom) {
- var childNodes = buildIESafeDOM(html, contextualElement, dom);
-
- if (contextualElement.tagName === 'SELECT') {
- // Walk child nodes
- for (var i = 0; childNodes[i]; i++) {
- // Find and process the first option child node
- if (childNodes[i].tagName === 'OPTION') {
- if (detectAutoSelectedOption(childNodes[i].parentNode, childNodes[i], html)) {
- // If the first node is selected but does not have an attribute,
- // presume it is not really selected.
- childNodes[i].parentNode.selectedIndex = -1;
- }
- break;
- }
- }
- }
-
- return childNodes;
- }
-
- var buildHTMLDOM;
- if (needsIntegrationPointFix) {
- buildHTMLDOM = function buildHTMLDOM(html, contextualElement, dom){
- if (svgHTMLIntegrationPoints[contextualElement.tagName]) {
- return buildSafeDOM(html, document.createElement('div'), dom);
- } else {
- return buildSafeDOM(html, contextualElement, dom);
- }
- };
- } else {
- buildHTMLDOM = buildSafeDOM;
- }
-
- __exports__.buildHTMLDOM = buildHTMLDOM;
- });
-enifed("morph/morph",
- ["exports"],
- function(__exports__) {
- "use strict";
- var splice = Array.prototype.splice;
-
- function ensureStartEnd(start, end) {
- if (start === null || end === null) {
- throw new Error('a fragment parent must have boundary nodes in order to detect insertion');
- }
- }
-
- function ensureContext(contextualElement) {
- if (!contextualElement || contextualElement.nodeType !== 1) {
- throw new Error('An element node must be provided for a contextualElement, you provided ' +
- (contextualElement ? 'nodeType ' + contextualElement.nodeType : 'nothing'));
- }
- }
-
- // TODO: this is an internal API, this should be an assert
- function Morph(parent, start, end, domHelper, contextualElement) {
- if (parent.nodeType === 11) {
- ensureStartEnd(start, end);
- this.element = null;
- } else {
- this.element = parent;
- }
- this._parent = parent;
- this.start = start;
- this.end = end;
- this.domHelper = domHelper;
- ensureContext(contextualElement);
- this.contextualElement = contextualElement;
- this.reset();
- }
-
- Morph.prototype.reset = function() {
- this.text = null;
- this.owner = null;
- this.morphs = null;
- this.before = null;
- this.after = null;
- this.escaped = true;
- };
-
- Morph.prototype.parent = function () {
- if (!this.element) {
- var parent = this.start.parentNode;
- if (this._parent !== parent) {
- this.element = this._parent = parent;
- }
- }
- return this._parent;
- };
-
- Morph.prototype.destroy = function () {
- if (this.owner) {
- this.owner.removeMorph(this);
- } else {
- clear(this.element || this.parent(), this.start, this.end);
- }
- };
-
- Morph.prototype.removeMorph = function (morph) {
- var morphs = this.morphs;
- for (var i=0, l=morphs.length; i<l; i++) {
- if (morphs[i] === morph) {
- this.replace(i, 1);
- break;
- }
- }
- };
-
- Morph.prototype.update = function (nodeOrString) {
- this._update(this.element || this.parent(), nodeOrString);
- };
-
- Morph.prototype.updateNode = function (node) {
- var parent = this.element || this.parent();
- if (!node) return this._updateText(parent, '');
- this._updateNode(parent, node);
- };
-
- Morph.prototype.updateText = function (text) {
- this._updateText(this.element || this.parent(), text);
- };
-
- Morph.prototype.updateHTML = function (html) {
- var parent = this.element || this.parent();
- if (!html) return this._updateText(parent, '');
- this._updateHTML(parent, html);
- };
-
- Morph.prototype._update = function (parent, nodeOrString) {
- if (nodeOrString === null || nodeOrString === undefined) {
- this._updateText(parent, '');
- } else if (typeof nodeOrString === 'string') {
- if (this.escaped) {
- this._updateText(parent, nodeOrString);
- } else {
- this._updateHTML(parent, nodeOrString);
- }
- } else if (nodeOrString.nodeType) {
- this._updateNode(parent, nodeOrString);
- } else if (nodeOrString.string) { // duck typed SafeString
- this._updateHTML(parent, nodeOrString.string);
- } else {
- this._updateText(parent, nodeOrString.toString());
- }
- };
-
- Morph.prototype._updateNode = function (parent, node) {
- if (this.text) {
- if (node.nodeType === 3) {
- this.text.nodeValue = node.nodeValue;
- return;
- } else {
- this.text = null;
- }
- }
- var start = this.start, end = this.end;
- clear(parent, start, end);
- parent.insertBefore(node, end);
- if (this.before !== null) {
- this.before.end = start.nextSibling;
- }
- if (this.after !== null) {
- this.after.start = end.previousSibling;
- }
- };
-
- Morph.prototype._updateText = function (parent, text) {
- if (this.text) {
- this.text.nodeValue = text;
- return;
- }
- var node = this.domHelper.createTextNode(text);
- this.text = node;
- clear(parent, this.start, this.end);
- parent.insertBefore(node, this.end);
- if (this.before !== null) {
- this.before.end = node;
- }
- if (this.after !== null) {
- this.after.start = node;
- }
- };
-
- Morph.prototype._updateHTML = function (parent, html) {
- var start = this.start, end = this.end;
- clear(parent, start, end);
- this.text = null;
- var childNodes = this.domHelper.parseHTML(html, this.contextualElement);
- appendChildren(parent, end, childNodes);
- if (this.before !== null) {
- this.before.end = start.nextSibling;
- }
- if (this.after !== null) {
- this.after.start = end.previousSibling;
- }
- };
-
- Morph.prototype.append = function (node) {
- if (this.morphs === null) this.morphs = [];
- var index = this.morphs.length;
- return this.insert(index, node);
- };
-
- Morph.prototype.insert = function (index, node) {
- if (this.morphs === null) this.morphs = [];
- var parent = this.element || this.parent();
- var morphs = this.morphs;
- var before = index > 0 ? morphs[index-1] : null;
- var after = index < morphs.length ? morphs[index] : null;
- var start = before === null ? this.start : (before.end === null ? parent.lastChild : before.end.previousSibling);
- var end = after === null ? this.end : (after.start === null ? parent.firstChild : after.start.nextSibling);
- var morph = new Morph(parent, start, end, this.domHelper, this.contextualElement);
-
- morph.owner = this;
- morph._update(parent, node);
-
- if (before !== null) {
- morph.before = before;
- before.end = start.nextSibling;
- before.after = morph;
- }
-
- if (after !== null) {
- morph.after = after;
- after.before = morph;
- after.start = end.previousSibling;
- }
-
- this.morphs.splice(index, 0, morph);
- return morph;
- };
-
- Morph.prototype.replace = function (index, removedLength, addedNodes) {
- if (this.morphs === null) this.morphs = [];
- var parent = this.element || this.parent();
- var morphs = this.morphs;
- var before = index > 0 ? morphs[index-1] : null;
- var after = index+removedLength < morphs.length ? morphs[index+removedLength] : null;
- var start = before === null ? this.start : (before.end === null ? parent.lastChild : before.end.previousSibling);
- var end = after === null ? this.end : (after.start === null ? parent.firstChild : after.start.nextSibling);
- var addedLength = addedNodes === undefined ? 0 : addedNodes.length;
- var args, i, current;
-
- if (removedLength > 0) {
- clear(parent, start, end);
- }
-
- if (addedLength === 0) {
- if (before !== null) {
- before.after = after;
- before.end = end;
- }
- if (after !== null) {
- after.before = before;
- after.start = start;
- }
- morphs.splice(index, removedLength);
- return;
- }
-
- args = new Array(addedLength+2);
- if (addedLength > 0) {
- for (i=0; i<addedLength; i++) {
- args[i+2] = current = new Morph(parent, start, end, this.domHelper, this.contextualElement);
- current._update(parent, addedNodes[i]);
- current.owner = this;
- if (before !== null) {
- current.before = before;
- before.end = start.nextSibling;
- before.after = current;
- }
- before = current;
- start = end === null ? parent.lastChild : end.previousSibling;
- }
- if (after !== null) {
- current.after = after;
- after.before = current;
- after.start = end.previousSibling;
- }
- }
-
- args[0] = index;
- args[1] = removedLength;
-
- splice.apply(morphs, args);
- };
-
- function appendChildren(parent, end, nodeList) {
- var ref = end;
- var i = nodeList.length;
- var node;
-
- while (i--) {
- node = nodeList[i];
- parent.insertBefore(node, ref);
- ref = node;
- }
- }
-
- function clear(parent, start, end) {
- var current, previous;
- if (end === null) {
- current = parent.lastChild;
- } else {
- current = end.previousSibling;
- }
-
- while (current !== null && current !== start) {
- previous = current.previousSibling;
- parent.removeChild(current);
- current = previous;
- }
- }
-
- __exports__["default"] = Morph;
- });
-enifed("route-recognizer",
- ["route-recognizer/dsl","exports"],
- function(__dependency1__, __exports__) {
- "use strict";
- var map = __dependency1__["default"];
-
- var specials = [
- '/', '.', '*', '+', '?', '|',
- '(', ')', '[', ']', '{', '}', '\\'
- ];
-
- var escapeRegex = new RegExp('(\\' + specials.join('|\\') + ')', 'g');
-
- function isArray(test) {
- return Object.prototype.toString.call(test) === "[object Array]";
- }
-
- // A Segment represents a segment in the original route description.
- // Each Segment type provides an `eachChar` and `regex` method.
- //
- // The `eachChar` method invokes the callback with one or more character
- // specifications. A character specification consumes one or more input
- // characters.
- //
- // The `regex` method returns a regex fragment for the segment. If the
- // segment is a dynamic of star segment, the regex fragment also includes
- // a capture.
- //
- // A character specification contains:
- //
- // * `validChars`: a String with a list of all valid characters, or
- // * `invalidChars`: a String with a list of all invalid characters
- // * `repeat`: true if the character specification can repeat
-
- function StaticSegment(string) { this.string = string; }
- StaticSegment.prototype = {
- eachChar: function(callback) {
- var string = this.string, ch;
-
- for (var i=0, l=string.length; i<l; i++) {
- ch = string.charAt(i);
- callback({ validChars: ch });
- }
- },
-
- regex: function() {
- return this.string.replace(escapeRegex, '\\$1');
- },
-
- generate: function() {
- return this.string;
- }
- };
-
- function DynamicSegment(name) { this.name = name; }
- DynamicSegment.prototype = {
- eachChar: function(callback) {
- callback({ invalidChars: "/", repeat: true });
- },
-
- regex: function() {
- return "([^/]+)";
- },
-
- generate: function(params) {
- return params[this.name];
- }
- };
-
- function StarSegment(name) { this.name = name; }
- StarSegment.prototype = {
- eachChar: function(callback) {
- callback({ invalidChars: "", repeat: true });
- },
-
- regex: function() {
- return "(.+)";
- },
-
- generate: function(params) {
- return params[this.name];
- }
- };
-
- function EpsilonSegment() {}
- EpsilonSegment.prototype = {
- eachChar: function() {},
- regex: function() { return ""; },
- generate: function() { return ""; }
- };
-
- function parse(route, names, types) {
- // normalize route as not starting with a "/". Recognition will
- // also normalize.
- if (route.charAt(0) === "/") { route = route.substr(1); }
-
- var segments = route.split("/"), results = [];
-
- for (var i=0, l=segments.length; i<l; i++) {
- var segment = segments[i], match;
-
- if (match = segment.match(/^:([^\/]+)$/)) {
- results.push(new DynamicSegment(match[1]));
- names.push(match[1]);
- types.dynamics++;
- } else if (match = segment.match(/^\*([^\/]+)$/)) {
- results.push(new StarSegment(match[1]));
- names.push(match[1]);
- types.stars++;
- } else if(segment === "") {
- results.push(new EpsilonSegment());
- } else {
- results.push(new StaticSegment(segment));
- types.statics++;
- }
- }
-
- return results;
- }
-
- // A State has a character specification and (`charSpec`) and a list of possible
- // subsequent states (`nextStates`).
- //
- // If a State is an accepting state, it will also have several additional
- // properties:
- //
- // * `regex`: A regular expression that is used to extract parameters from paths
- // that reached this accepting state.
- // * `handlers`: Information on how to convert the list of captures into calls
- // to registered handlers with the specified parameters
- // * `types`: How many static, dynamic or star segments in this route. Used to
- // decide which route to use if multiple registered routes match a path.
- //
- // Currently, State is implemented naively by looping over `nextStates` and
- // comparing a character specification against a character. A more efficient
- // implementation would use a hash of keys pointing at one or more next states.
-
- function State(charSpec) {
- this.charSpec = charSpec;
- this.nextStates = [];
- }
-
- State.prototype = {
- get: function(charSpec) {
- var nextStates = this.nextStates;
-
- for (var i=0, l=nextStates.length; i<l; i++) {
- var child = nextStates[i];
-
- var isEqual = child.charSpec.validChars === charSpec.validChars;
- isEqual = isEqual && child.charSpec.invalidChars === charSpec.invalidChars;
-
- if (isEqual) { return child; }
- }
- },
-
- put: function(charSpec) {
- var state;
-
- // If the character specification already exists in a child of the current
- // state, just return that state.
- if (state = this.get(charSpec)) { return state; }
-
- // Make a new state for the character spec
- state = new State(charSpec);
-
- // Insert the new state as a child of the current state
- this.nextStates.push(state);
-
- // If this character specification repeats, insert the new state as a child
- // of itself. Note that this will not trigger an infinite loop because each
- // transition during recognition consumes a character.
- if (charSpec.repeat) {
- state.nextStates.push(state);
- }
-
- // Return the new state
- return state;
- },
-
- // Find a list of child states matching the next character
- match: function(ch) {
- // DEBUG "Processing `" + ch + "`:"
- var nextStates = this.nextStates,
- child, charSpec, chars;
-
- // DEBUG " " + debugState(this)
- var returned = [];
-
- for (var i=0, l=nextStates.length; i<l; i++) {
- child = nextStates[i];
-
- charSpec = child.charSpec;
-
- if (typeof (chars = charSpec.validChars) !== 'undefined') {
- if (chars.indexOf(ch) !== -1) { returned.push(child); }
- } else if (typeof (chars = charSpec.invalidChars) !== 'undefined') {
- if (chars.indexOf(ch) === -1) { returned.push(child); }
- }
- }
-
- return returned;
- }
-
- /** IF DEBUG
- , debug: function() {
- var charSpec = this.charSpec,
- debug = "[",
- chars = charSpec.validChars || charSpec.invalidChars;
-
- if (charSpec.invalidChars) { debug += "^"; }
- debug += chars;
- debug += "]";
-
- if (charSpec.repeat) { debug += "+"; }
-
- return debug;
- }
- END IF **/
- };
-
- /** IF DEBUG
- function debug(log) {
- console.log(log);
- }
-
- function debugState(state) {
- return state.nextStates.map(function(n) {
- if (n.nextStates.length === 0) { return "( " + n.debug() + " [accepting] )"; }
- return "( " + n.debug() + " <then> " + n.nextStates.map(function(s) { return s.debug() }).join(" or ") + " )";
- }).join(", ")
- }
- END IF **/
-
- // This is a somewhat naive strategy, but should work in a lot of cases
- // A better strategy would properly resolve /posts/:id/new and /posts/edit/:id.
- //
- // This strategy generally prefers more static and less dynamic matching.
- // Specifically, it
- //
- // * prefers fewer stars to more, then
- // * prefers using stars for less of the match to more, then
- // * prefers fewer dynamic segments to more, then
- // * prefers more static segments to more
- function sortSolutions(states) {
- return states.sort(function(a, b) {
- if (a.types.stars !== b.types.stars) { return a.types.stars - b.types.stars; }
-
- if (a.types.stars) {
- if (a.types.statics !== b.types.statics) { return b.types.statics - a.types.statics; }
- if (a.types.dynamics !== b.types.dynamics) { return b.types.dynamics - a.types.dynamics; }
- }
-
- if (a.types.dynamics !== b.types.dynamics) { return a.types.dynamics - b.types.dynamics; }
- if (a.types.statics !== b.types.statics) { return b.types.statics - a.types.statics; }
-
- return 0;
- });
- }
-
- function recognizeChar(states, ch) {
- var nextStates = [];
-
- for (var i=0, l=states.length; i<l; i++) {
- var state = states[i];
-
- nextStates = nextStates.concat(state.match(ch));
- }
-
- return nextStates;
- }
-
- var oCreate = Object.create || function(proto) {
- function F() {}
- F.prototype = proto;
- return new F();
- };
-
- function RecognizeResults(queryParams) {
- this.queryParams = queryParams || {};
- }
- RecognizeResults.prototype = oCreate({
- splice: Array.prototype.splice,
- slice: Array.prototype.slice,
- push: Array.prototype.push,
- length: 0,
- queryParams: null
- });
-
- function findHandler(state, path, queryParams) {
- var handlers = state.handlers, regex = state.regex;
- var captures = path.match(regex), currentCapture = 1;
- var result = new RecognizeResults(queryParams);
-
- for (var i=0, l=handlers.length; i<l; i++) {
- var handler = handlers[i], names = handler.names, params = {};
-
- for (var j=0, m=names.length; j<m; j++) {
- params[names[j]] = captures[currentCapture++];
- }
-
- result.push({ handler: handler.handler, params: params, isDynamic: !!names.length });
- }
-
- return result;
- }
-
- function addSegment(currentState, segment) {
- segment.eachChar(function(ch) {
- var state;
-
- currentState = currentState.put(ch);
- });
-
- return currentState;
- }
-
- // The main interface
-
- var RouteRecognizer = function() {
- this.rootState = new State();
- this.names = {};
- };
-
-
- RouteRecognizer.prototype = {
- add: function(routes, options) {
- var currentState = this.rootState, regex = "^",
- types = { statics: 0, dynamics: 0, stars: 0 },
- handlers = [], allSegments = [], name;
-
- var isEmpty = true;
-
- for (var i=0, l=routes.length; i<l; i++) {
- var route = routes[i], names = [];
-
- var segments = parse(route.path, names, types);
-
- allSegments = allSegments.concat(segments);
-
- for (var j=0, m=segments.length; j<m; j++) {
- var segment = segments[j];
-
- if (segment instanceof EpsilonSegment) { continue; }
-
- isEmpty = false;
-
- // Add a "/" for the new segment
- currentState = currentState.put({ validChars: "/" });
- regex += "/";
-
- // Add a representation of the segment to the NFA and regex
- currentState = addSegment(currentState, segment);
- regex += segment.regex();
- }
-
- var handler = { handler: route.handler, names: names };
- handlers.push(handler);
- }
-
- if (isEmpty) {
- currentState = currentState.put({ validChars: "/" });
- regex += "/";
- }
-
- currentState.handlers = handlers;
- currentState.regex = new RegExp(regex + "$");
- currentState.types = types;
-
- if (name = options && options.as) {
- this.names[name] = {
- segments: allSegments,
- handlers: handlers
- };
- }
- },
-
- handlersFor: function(name) {
- var route = this.names[name], result = [];
- if (!route) { throw new Error("There is no route named " + name); }
-
- for (var i=0, l=route.handlers.length; i<l; i++) {
- result.push(route.handlers[i]);
- }
-
- return result;
- },
-
- hasRoute: function(name) {
- return !!this.names[name];
- },
-
- generate: function(name, params) {
- var route = this.names[name], output = "";
- if (!route) { throw new Error("There is no route named " + name); }
-
- var segments = route.segments;
-
- for (var i=0, l=segments.length; i<l; i++) {
- var segment = segments[i];
-
- if (segment instanceof EpsilonSegment) { continue; }
-
- output += "/";
- output += segment.generate(params);
- }
-
- if (output.charAt(0) !== '/') { output = '/' + output; }
-
- if (params && params.queryParams) {
- output += this.generateQueryString(params.queryParams, route.handlers);
- }
-
- return output;
- },
-
- generateQueryString: function(params, handlers) {
- var pairs = [];
- var keys = [];
- for(var key in params) {
- if (params.hasOwnProperty(key)) {
- keys.push(key);
- }
- }
- keys.sort();
- for (var i = 0, len = keys.length; i < len; i++) {
- key = keys[i];
- var value = params[key];
- if (value == null) {
- continue;
- }
- var pair = encodeURIComponent(key);
- if (isArray(value)) {
- for (var j = 0, l = value.length; j < l; j++) {
- var arrayPair = key + '[]' + '=' + encodeURIComponent(value[j]);
- pairs.push(arrayPair);
- }
- } else {
- pair += "=" + encodeURIComponent(value);
- pairs.push(pair);
- }
- }
-
- if (pairs.length === 0) { return ''; }
-
- return "?" + pairs.join("&");
- },
-
- parseQueryString: function(queryString) {
- var pairs = queryString.split("&"), queryParams = {};
- for(var i=0; i < pairs.length; i++) {
- var pair = pairs[i].split('='),
- key = decodeURIComponent(pair[0]),
- keyLength = key.length,
- isArray = false,
- value;
- if (pair.length === 1) {
- value = 'true';
- } else {
- //Handle arrays
- if (keyLength > 2 && key.slice(keyLength -2) === '[]') {
- isArray = true;
- key = key.slice(0, keyLength - 2);
- if(!queryParams[key]) {
- queryParams[key] = [];
- }
- }
- value = pair[1] ? decodeURIComponent(pair[1]) : '';
- }
- if (isArray) {
- queryParams[key].push(value);
- } else {
- queryParams[key] = value;
- }
- }
- return queryParams;
- },
-
- recognize: function(path) {
- var states = [ this.rootState ],
- pathLen, i, l, queryStart, queryParams = {},
- isSlashDropped = false;
-
- queryStart = path.indexOf('?');
- if (queryStart !== -1) {
- var queryString = path.substr(queryStart + 1, path.length);
- path = path.substr(0, queryStart);
- queryParams = this.parseQueryString(queryString);
- }
-
- path = decodeURI(path);
-
- // DEBUG GROUP path
-
- if (path.charAt(0) !== "/") { path = "/" + path; }
-
- pathLen = path.length;
- if (pathLen > 1 && path.charAt(pathLen - 1) === "/") {
- path = path.substr(0, pathLen - 1);
- isSlashDropped = true;
- }
-
- for (i=0, l=path.length; i<l; i++) {
- states = recognizeChar(states, path.charAt(i));
- if (!states.length) { break; }
- }
-
- // END DEBUG GROUP
-
- var solutions = [];
- for (i=0, l=states.length; i<l; i++) {
- if (states[i].handlers) { solutions.push(states[i]); }
- }
-
- states = sortSolutions(solutions);
-
- var state = solutions[0];
-
- if (state && state.handlers) {
- // if a trailing slash was dropped and a star segment is the last segment
- // specified, put the trailing slash back
- if (isSlashDropped && state.regex.source.slice(-5) === "(.+)$") {
- path = path + "/";
- }
- return findHandler(state, path, queryParams);
- }
- }
- };
-
- RouteRecognizer.prototype.map = map;
-
- __exports__["default"] = RouteRecognizer;
- });
-enifed("route-recognizer/dsl",
- ["exports"],
- function(__exports__) {
- "use strict";
- function Target(path, matcher, delegate) {
- this.path = path;
- this.matcher = matcher;
- this.delegate = delegate;
- }
-
- Target.prototype = {
- to: function(target, callback) {
- var delegate = this.delegate;
-
- if (delegate && delegate.willAddRoute) {
- target = delegate.willAddRoute(this.matcher.target, target);
- }
-
- this.matcher.add(this.path, target);
-
- if (callback) {
- if (callback.length === 0) { throw new Error("You must have an argument in the function passed to `to`"); }
- this.matcher.addChild(this.path, target, callback, this.delegate);
- }
- return this;
- }
- };
-
- function Matcher(target) {
- this.routes = {};
- this.children = {};
- this.target = target;
- }
-
- Matcher.prototype = {
- add: function(path, handler) {
- this.routes[path] = handler;
- },
-
- addChild: function(path, target, callback, delegate) {
- var matcher = new Matcher(target);
- this.children[path] = matcher;
-
- var match = generateMatch(path, matcher, delegate);
-
- if (delegate && delegate.contextEntered) {
- delegate.contextEntered(target, match);
- }
-
- callback(match);
- }
- };
-
- function generateMatch(startingPath, matcher, delegate) {
- return function(path, nestedCallback) {
- var fullPath = startingPath + path;
-
- if (nestedCallback) {
- nestedCallback(generateMatch(fullPath, matcher, delegate));
- } else {
- return new Target(startingPath + path, matcher, delegate);
- }
- };
- }
-
- function addRoute(routeArray, path, handler) {
- var len = 0;
- for (var i=0, l=routeArray.length; i<l; i++) {
- len += routeArray[i].path.length;
- }
-
- path = path.substr(len);
- var route = { path: path, handler: handler };
- routeArray.push(route);
- }
-
- function eachRoute(baseRoute, matcher, callback, binding) {
- var routes = matcher.routes;
-
- for (var path in routes) {
- if (routes.hasOwnProperty(path)) {
- var routeArray = baseRoute.slice();
- addRoute(routeArray, path, routes[path]);
-
- if (matcher.children[path]) {
- eachRoute(routeArray, matcher.children[path], callback, binding);
- } else {
- callback.call(binding, routeArray);
- }
- }
- }
- }
-
- __exports__["default"] = function(callback, addRouteCallback) {
- var matcher = new Matcher();
-
- callback(generateMatch("", matcher, this.delegate));
-
- eachRoute([], matcher, function(route) {
- if (addRouteCallback) { addRouteCallback(this, route); }
- else { this.add(route); }
- }, this);
- }
- });
-enifed("router",
- ["./router/router","exports"],
- function(__dependency1__, __exports__) {
- "use strict";
- var Router = __dependency1__["default"];
-
- __exports__["default"] = Router;
- });
-enifed("router/handler-info",
- ["./utils","rsvp/promise","exports"],
- function(__dependency1__, __dependency2__, __exports__) {
- "use strict";
- var bind = __dependency1__.bind;
- var merge = __dependency1__.merge;
- var serialize = __dependency1__.serialize;
- var promiseLabel = __dependency1__.promiseLabel;
- var applyHook = __dependency1__.applyHook;
- var Promise = __dependency2__["default"];
-
- function HandlerInfo(_props) {
- var props = _props || {};
- merge(this, props);
- this.initialize(props);
- }
-
- HandlerInfo.prototype = {
- name: null,
- handler: null,
- params: null,
- context: null,
-
- // Injected by the handler info factory.
- factory: null,
-
- initialize: function() {},
-
- log: function(payload, message) {
- if (payload.log) {
- payload.log(this.name + ': ' + message);
- }
- },
-
- promiseLabel: function(label) {
- return promiseLabel("'" + this.name + "' " + label);
- },
-
- getUnresolved: function() {
- return this;
- },
-
- serialize: function() {
- return this.params || {};
- },
-
- resolve: function(shouldContinue, payload) {
- var checkForAbort = bind(this, this.checkForAbort, shouldContinue),
- beforeModel = bind(this, this.runBeforeModelHook, payload),
- model = bind(this, this.getModel, payload),
- afterModel = bind(this, this.runAfterModelHook, payload),
- becomeResolved = bind(this, this.becomeResolved, payload);
-
- return Promise.resolve(undefined, this.promiseLabel("Start handler"))
- .then(checkForAbort, null, this.promiseLabel("Check for abort"))
- .then(beforeModel, null, this.promiseLabel("Before model"))
- .then(checkForAbort, null, this.promiseLabel("Check if aborted during 'beforeModel' hook"))
- .then(model, null, this.promiseLabel("Model"))
- .then(checkForAbort, null, this.promiseLabel("Check if aborted in 'model' hook"))
- .then(afterModel, null, this.promiseLabel("After model"))
- .then(checkForAbort, null, this.promiseLabel("Check if aborted in 'afterModel' hook"))
- .then(becomeResolved, null, this.promiseLabel("Become resolved"));
- },
-
- runBeforeModelHook: function(payload) {
- if (payload.trigger) {
- payload.trigger(true, 'willResolveModel', payload, this.handler);
- }
- return this.runSharedModelHook(payload, 'beforeModel', []);
- },
-
- runAfterModelHook: function(payload, resolvedModel) {
- // Stash the resolved model on the payload.
- // This makes it possible for users to swap out
- // the resolved model in afterModel.
- var name = this.name;
- this.stashResolvedModel(payload, resolvedModel);
-
- return this.runSharedModelHook(payload, 'afterModel', [resolvedModel])
- .then(function() {
- // Ignore the fulfilled value returned from afterModel.
- // Return the value stashed in resolvedModels, which
- // might have been swapped out in afterModel.
- return payload.resolvedModels[name];
- }, null, this.promiseLabel("Ignore fulfillment value and return model value"));
- },
-
- runSharedModelHook: function(payload, hookName, args) {
- this.log(payload, "calling " + hookName + " hook");
-
- if (this.queryParams) {
- args.push(this.queryParams);
- }
- args.push(payload);
-
- var result = applyHook(this.handler, hookName, args);
-
- if (result && result.isTransition) {
- result = null;
- }
-
- return Promise.resolve(result, this.promiseLabel("Resolve value returned from one of the model hooks"));
- },
-
- // overridden by subclasses
- getModel: null,
-
- checkForAbort: function(shouldContinue, promiseValue) {
- return Promise.resolve(shouldContinue(), this.promiseLabel("Check for abort")).then(function() {
- // We don't care about shouldContinue's resolve value;
- // pass along the original value passed to this fn.
- return promiseValue;
- }, null, this.promiseLabel("Ignore fulfillment value and continue"));
- },
-
- stashResolvedModel: function(payload, resolvedModel) {
- payload.resolvedModels = payload.resolvedModels || {};
- payload.resolvedModels[this.name] = resolvedModel;
- },
-
- becomeResolved: function(payload, resolvedContext) {
- var params = this.serialize(resolvedContext);
-
- if (payload) {
- this.stashResolvedModel(payload, resolvedContext);
- payload.params = payload.params || {};
- payload.params[this.name] = params;
- }
-
- return this.factory('resolved', {
- context: resolvedContext,
- name: this.name,
- handler: this.handler,
- params: params
- });
- },
-
- shouldSupercede: function(other) {
- // Prefer this newer handlerInfo over `other` if:
- // 1) The other one doesn't exist
- // 2) The names don't match
- // 3) This handler has a context that doesn't match
- // the other one (or the other one doesn't have one).
- // 4) This handler has parameters that don't match the other.
- if (!other) { return true; }
-
- var contextsMatch = (other.context === this.context);
- return other.name !== this.name ||
- (this.hasOwnProperty('context') && !contextsMatch) ||
- (this.hasOwnProperty('params') && !paramsMatch(this.params, other.params));
- }
- };
-
- function paramsMatch(a, b) {
- if ((!a) ^ (!b)) {
- // Only one is null.
- return false;
- }
-
- if (!a) {
- // Both must be null.
- return true;
- }
-
- // Note: this assumes that both params have the same
- // number of keys, but since we're comparing the
- // same handlers, they should.
- for (var k in a) {
- if (a.hasOwnProperty(k) && a[k] !== b[k]) {
- return false;
- }
- }
- return true;
- }
-
- __exports__["default"] = HandlerInfo;
- });
-enifed("router/handler-info/factory",
- ["router/handler-info/resolved-handler-info","router/handler-info/unresolved-handler-info-by-object","router/handler-info/unresolved-handler-info-by-param","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
- "use strict";
- var ResolvedHandlerInfo = __dependency1__["default"];
- var UnresolvedHandlerInfoByObject = __dependency2__["default"];
- var UnresolvedHandlerInfoByParam = __dependency3__["default"];
-
- handlerInfoFactory.klasses = {
- resolved: ResolvedHandlerInfo,
- param: UnresolvedHandlerInfoByParam,
- object: UnresolvedHandlerInfoByObject
- };
-
- function handlerInfoFactory(name, props) {
- var Ctor = handlerInfoFactory.klasses[name],
- handlerInfo = new Ctor(props || {});
- handlerInfo.factory = handlerInfoFactory;
- return handlerInfo;
- }
-
- __exports__["default"] = handlerInfoFactory;
- });
-enifed("router/handler-info/resolved-handler-info",
- ["../handler-info","router/utils","rsvp/promise","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
- "use strict";
- var HandlerInfo = __dependency1__["default"];
- var subclass = __dependency2__.subclass;
- var promiseLabel = __dependency2__.promiseLabel;
- var Promise = __dependency3__["default"];
-
- var ResolvedHandlerInfo = subclass(HandlerInfo, {
- resolve: function(shouldContinue, payload) {
- // A ResolvedHandlerInfo just resolved with itself.
- if (payload && payload.resolvedModels) {
- payload.resolvedModels[this.name] = this.context;
- }
- return Promise.resolve(this, this.promiseLabel("Resolve"));
- },
-
- getUnresolved: function() {
- return this.factory('param', {
- name: this.name,
- handler: this.handler,
- params: this.params
- });
- },
-
- isResolved: true
- });
-
- __exports__["default"] = ResolvedHandlerInfo;
- });
-enifed("router/handler-info/unresolved-handler-info-by-object",
- ["../handler-info","router/utils","rsvp/promise","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
- "use strict";
- var HandlerInfo = __dependency1__["default"];
- var merge = __dependency2__.merge;
- var subclass = __dependency2__.subclass;
- var promiseLabel = __dependency2__.promiseLabel;
- var isParam = __dependency2__.isParam;
- var Promise = __dependency3__["default"];
-
- var UnresolvedHandlerInfoByObject = subclass(HandlerInfo, {
- getModel: function(payload) {
- this.log(payload, this.name + ": resolving provided model");
- return Promise.resolve(this.context);
- },
-
- initialize: function(props) {
- this.names = props.names || [];
- this.context = props.context;
- },
-
- /**
- @private
-
- Serializes a handler using its custom `serialize` method or
- by a default that looks up the expected property name from
- the dynamic segment.
-
- @param {Object} model the model to be serialized for this handler
- */
- serialize: function(_model) {
- var model = _model || this.context,
- names = this.names,
- handler = this.handler;
-
- var object = {};
- if (isParam(model)) {
- object[names[0]] = model;
- return object;
- }
-
- // Use custom serialize if it exists.
- if (handler.serialize) {
- return handler.serialize(model, names);
- }
-
- if (names.length !== 1) { return; }
-
- var name = names[0];
-
- if (/_id$/.test(name)) {
- object[name] = model.id;
- } else {
- object[name] = model;
- }
- return object;
- }
- });
-
- __exports__["default"] = UnresolvedHandlerInfoByObject;
- });
-enifed("router/handler-info/unresolved-handler-info-by-param",
- ["../handler-info","router/utils","exports"],
- function(__dependency1__, __dependency2__, __exports__) {
- "use strict";
- var HandlerInfo = __dependency1__["default"];
- var resolveHook = __dependency2__.resolveHook;
- var merge = __dependency2__.merge;
- var subclass = __dependency2__.subclass;
- var promiseLabel = __dependency2__.promiseLabel;
-
- // Generated by URL transitions and non-dynamic route segments in named Transitions.
- var UnresolvedHandlerInfoByParam = subclass (HandlerInfo, {
- initialize: function(props) {
- this.params = props.params || {};
- },
-
- getModel: function(payload) {
- var fullParams = this.params;
- if (payload && payload.queryParams) {
- fullParams = {};
- merge(fullParams, this.params);
- fullParams.queryParams = payload.queryParams;
- }
-
- var handler = this.handler;
- var hookName = resolveHook(handler, 'deserialize') ||
- resolveHook(handler, 'model');
-
- return this.runSharedModelHook(payload, hookName, [fullParams]);
- }
- });
-
- __exports__["default"] = UnresolvedHandlerInfoByParam;
- });
-enifed("router/router",
- ["route-recognizer","rsvp/promise","./utils","./transition-state","./transition","./transition-intent/named-transition-intent","./transition-intent/url-transition-intent","./handler-info","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __exports__) {
- "use strict";
- var RouteRecognizer = __dependency1__["default"];
- var Promise = __dependency2__["default"];
- var trigger = __dependency3__.trigger;
- var log = __dependency3__.log;
- var slice = __dependency3__.slice;
- var forEach = __dependency3__.forEach;
- var merge = __dependency3__.merge;
- var serialize = __dependency3__.serialize;
- var extractQueryParams = __dependency3__.extractQueryParams;
- var getChangelist = __dependency3__.getChangelist;
- var promiseLabel = __dependency3__.promiseLabel;
- var callHook = __dependency3__.callHook;
- var TransitionState = __dependency4__["default"];
- var logAbort = __dependency5__.logAbort;
- var Transition = __dependency5__.Transition;
- var TransitionAborted = __dependency5__.TransitionAborted;
- var NamedTransitionIntent = __dependency6__["default"];
- var URLTransitionIntent = __dependency7__["default"];
- var ResolvedHandlerInfo = __dependency8__.ResolvedHandlerInfo;
-
- var pop = Array.prototype.pop;
-
- function Router() {
- this.recognizer = new RouteRecognizer();
- this.reset();
- }
-
- function getTransitionByIntent(intent, isIntermediate) {
- var wasTransitioning = !!this.activeTransition;
- var oldState = wasTransitioning ? this.activeTransition.state : this.state;
- var newTransition;
-
- var newState = intent.applyToState(oldState, this.recognizer, this.getHandler, isIntermediate);
- var queryParamChangelist = getChangelist(oldState.queryParams, newState.queryParams);
-
- if (handlerInfosEqual(newState.handlerInfos, oldState.handlerInfos)) {
-
- // This is a no-op transition. See if query params changed.
- if (queryParamChangelist) {
- newTransition = this.queryParamsTransition(queryParamChangelist, wasTransitioning, oldState, newState);
- if (newTransition) {
- return newTransition;
- }
- }
-
- // No-op. No need to create a new transition.
- return new Transition(this);
- }
-
- if (isIntermediate) {
- setupContexts(this, newState);
- return;
- }
-
- // Create a new transition to the destination route.
- newTransition = new Transition(this, intent, newState);
-
- // Abort and usurp any previously active transition.
- if (this.activeTransition) {
- this.activeTransition.abort();
- }
- this.activeTransition = newTransition;
-
- // Transition promises by default resolve with resolved state.
- // For our purposes, swap out the promise to resolve
- // after the transition has been finalized.
- newTransition.promise = newTransition.promise.then(function(result) {
- return finalizeTransition(newTransition, result.state);
- }, null, promiseLabel("Settle transition promise when transition is finalized"));
-
- if (!wasTransitioning) {
- notifyExistingHandlers(this, newState, newTransition);
- }
-
- fireQueryParamDidChange(this, newState, queryParamChangelist);
-
- return newTransition;
- }
-
- Router.prototype = {
-
- /**
- The main entry point into the router. The API is essentially
- the same as the `map` method in `route-recognizer`.
-
- This method extracts the String handler at the last `.to()`
- call and uses it as the name of the whole route.
-
- @param {Function} callback
- */
- map: function(callback) {
- this.recognizer.delegate = this.delegate;
-
- this.recognizer.map(callback, function(recognizer, routes) {
- for (var i = routes.length - 1, proceed = true; i >= 0 && proceed; --i) {
- var route = routes[i];
- recognizer.add(routes, { as: route.handler });
- proceed = route.path === '/' || route.path === '' || route.handler.slice(-6) === '.index';
- }
- });
- },
-
- hasRoute: function(route) {
- return this.recognizer.hasRoute(route);
- },
-
- queryParamsTransition: function(changelist, wasTransitioning, oldState, newState) {
- var router = this;
-
- fireQueryParamDidChange(this, newState, changelist);
-
- if (!wasTransitioning && this.activeTransition) {
- // One of the handlers in queryParamsDidChange
- // caused a transition. Just return that transition.
- return this.activeTransition;
- } else {
- // Running queryParamsDidChange didn't change anything.
- // Just update query params and be on our way.
-
- // We have to return a noop transition that will
- // perform a URL update at the end. This gives
- // the user the ability to set the url update
- // method (default is replaceState).
- var newTransition = new Transition(this);
- newTransition.queryParamsOnly = true;
-
- oldState.queryParams = finalizeQueryParamChange(this, newState.handlerInfos, newState.queryParams, newTransition);
-
- newTransition.promise = newTransition.promise.then(function(result) {
- updateURL(newTransition, oldState, true);
- if (router.didTransition) {
- router.didTransition(router.currentHandlerInfos);
- }
- return result;
- }, null, promiseLabel("Transition complete"));
- return newTransition;
- }
- },
-
- // NOTE: this doesn't really belong here, but here
- // it shall remain until our ES6 transpiler can
- // handle cyclical deps.
- transitionByIntent: function(intent, isIntermediate) {
- try {
- return getTransitionByIntent.apply(this, arguments);
- } catch(e) {
- return new Transition(this, intent, null, e);
- }
- },
-
- /**
- Clears the current and target route handlers and triggers exit
- on each of them starting at the leaf and traversing up through
- its ancestors.
- */
- reset: function() {
- if (this.state) {
- forEach(this.state.handlerInfos.slice().reverse(), function(handlerInfo) {
- var handler = handlerInfo.handler;
- callHook(handler, 'exit');
- });
- }
-
- this.state = new TransitionState();
- this.currentHandlerInfos = null;
- },
-
- activeTransition: null,
-
- /**
- var handler = handlerInfo.handler;
- The entry point for handling a change to the URL (usually
- via the back and forward button).
-
- Returns an Array of handlers and the parameters associated
- with those parameters.
-
- @param {String} url a URL to process
-
- @return {Array} an Array of `[handler, parameter]` tuples
- */
- handleURL: function(url) {
- // Perform a URL-based transition, but don't change
- // the URL afterward, since it already happened.
- var args = slice.call(arguments);
- if (url.charAt(0) !== '/') { args[0] = '/' + url; }
-
- return doTransition(this, args).method(null);
- },
-
- /**
- Hook point for updating the URL.
-
- @param {String} url a URL to update to
- */
- updateURL: function() {
- throw new Error("updateURL is not implemented");
- },
-
- /**
- Hook point for replacing the current URL, i.e. with replaceState
-
- By default this behaves the same as `updateURL`
-
- @param {String} url a URL to update to
- */
- replaceURL: function(url) {
- this.updateURL(url);
- },
-
- /**
- Transition into the specified named route.
-
- If necessary, trigger the exit callback on any handlers
- that are no longer represented by the target route.
-
- @param {String} name the name of the route
- */
- transitionTo: function(name) {
- return doTransition(this, arguments);
- },
-
- intermediateTransitionTo: function(name) {
- return doTransition(this, arguments, true);
- },
-
- refresh: function(pivotHandler) {
- var state = this.activeTransition ? this.activeTransition.state : this.state;
- var handlerInfos = state.handlerInfos;
- var params = {};
- for (var i = 0, len = handlerInfos.length; i < len; ++i) {
- var handlerInfo = handlerInfos[i];
- params[handlerInfo.name] = handlerInfo.params || {};
- }
-
- log(this, "Starting a refresh transition");
- var intent = new NamedTransitionIntent({
- name: handlerInfos[handlerInfos.length - 1].name,
- pivotHandler: pivotHandler || handlerInfos[0].handler,
- contexts: [], // TODO collect contexts...?
- queryParams: this._changedQueryParams || state.queryParams || {}
- });
-
- return this.transitionByIntent(intent, false);
- },
-
- /**
- Identical to `transitionTo` except that the current URL will be replaced
- if possible.
-
- This method is intended primarily for use with `replaceState`.
-
- @param {String} name the name of the route
- */
- replaceWith: function(name) {
- return doTransition(this, arguments).method('replace');
- },
-
- /**
- Take a named route and context objects and generate a
- URL.
-
- @param {String} name the name of the route to generate
- a URL for
- @param {...Object} objects a list of objects to serialize
-
- @return {String} a URL
- */
- generate: function(handlerName) {
-
- var partitionedArgs = extractQueryParams(slice.call(arguments, 1)),
- suppliedParams = partitionedArgs[0],
- queryParams = partitionedArgs[1];
-
- // Construct a TransitionIntent with the provided params
- // and apply it to the present state of the router.
- var intent = new NamedTransitionIntent({ name: handlerName, contexts: suppliedParams });
- var state = intent.applyToState(this.state, this.recognizer, this.getHandler);
- var params = {};
-
- for (var i = 0, len = state.handlerInfos.length; i < len; ++i) {
- var handlerInfo = state.handlerInfos[i];
- var handlerParams = handlerInfo.serialize();
- merge(params, handlerParams);
- }
- params.queryParams = queryParams;
-
- return this.recognizer.generate(handlerName, params);
- },
-
- applyIntent: function(handlerName, contexts) {
- var intent = new NamedTransitionIntent({
- name: handlerName,
- contexts: contexts
- });
-
- var state = this.activeTransition && this.activeTransition.state || this.state;
- return intent.applyToState(state, this.recognizer, this.getHandler);
- },
-
- isActiveIntent: function(handlerName, contexts, queryParams) {
- var targetHandlerInfos = this.state.handlerInfos,
- found = false, names, object, handlerInfo, handlerObj, i, len;
-
- if (!targetHandlerInfos.length) { return false; }
-
- var targetHandler = targetHandlerInfos[targetHandlerInfos.length - 1].name;
- var recogHandlers = this.recognizer.handlersFor(targetHandler);
-
- var index = 0;
- for (len = recogHandlers.length; index < len; ++index) {
- handlerInfo = targetHandlerInfos[index];
- if (handlerInfo.name === handlerName) { break; }
- }
-
- if (index === recogHandlers.length) {
- // The provided route name isn't even in the route hierarchy.
- return false;
- }
-
- var state = new TransitionState();
- state.handlerInfos = targetHandlerInfos.slice(0, index + 1);
- recogHandlers = recogHandlers.slice(0, index + 1);
-
- var intent = new NamedTransitionIntent({
- name: targetHandler,
- contexts: contexts
- });
-
- var newState = intent.applyToHandlers(state, recogHandlers, this.getHandler, targetHandler, true, true);
-
- var handlersEqual = handlerInfosEqual(newState.handlerInfos, state.handlerInfos);
- if (!queryParams || !handlersEqual) {
- return handlersEqual;
- }
-
- // Get a hash of QPs that will still be active on new route
- var activeQPsOnNewHandler = {};
- merge(activeQPsOnNewHandler, queryParams);
-
- var activeQueryParams = this.state.queryParams;
- for (var key in activeQueryParams) {
- if (activeQueryParams.hasOwnProperty(key) &&
- activeQPsOnNewHandler.hasOwnProperty(key)) {
- activeQPsOnNewHandler[key] = activeQueryParams[key];
- }
- }
-
- return handlersEqual && !getChangelist(activeQPsOnNewHandler, queryParams);
- },
-
- isActive: function(handlerName) {
- var partitionedArgs = extractQueryParams(slice.call(arguments, 1));
- return this.isActiveIntent(handlerName, partitionedArgs[0], partitionedArgs[1]);
- },
-
- trigger: function(name) {
- var args = slice.call(arguments);
- trigger(this, this.currentHandlerInfos, false, args);
- },
-
- /**
- Hook point for logging transition status updates.
-
- @param {String} message The message to log.
- */
- log: null,
-
- _willChangeContextEvent: 'willChangeContext',
- _triggerWillChangeContext: function(handlerInfos, newTransition) {
- trigger(this, handlerInfos, true, [this._willChangeContextEvent, newTransition]);
- },
-
- _triggerWillLeave: function(handlerInfos, newTransition, leavingChecker) {
- trigger(this, handlerInfos, true, ['willLeave', newTransition, leavingChecker]);
- }
- };
-
- /**
- @private
-
- Fires queryParamsDidChange event
- */
- function fireQueryParamDidChange(router, newState, queryParamChangelist) {
- // If queryParams changed trigger event
- if (queryParamChangelist) {
-
- // This is a little hacky but we need some way of storing
- // changed query params given that no activeTransition
- // is guaranteed to have occurred.
- router._changedQueryParams = queryParamChangelist.all;
- trigger(router, newState.handlerInfos, true, ['queryParamsDidChange', queryParamChangelist.changed, queryParamChangelist.all, queryParamChangelist.removed]);
- router._changedQueryParams = null;
- }
- }
-
- /**
- @private
-
- Takes an Array of `HandlerInfo`s, figures out which ones are
- exiting, entering, or changing contexts, and calls the
- proper handler hooks.
-
- For example, consider the following tree of handlers. Each handler is
- followed by the URL segment it handles.
-
- ```
- |~index ("/")
- | |~posts ("/posts")
- | | |-showPost ("/:id")
- | | |-newPost ("/new")
- | | |-editPost ("/edit")
- | |~about ("/about/:id")
- ```
-
- Consider the following transitions:
-
- 1. A URL transition to `/posts/1`.
- 1. Triggers the `*model` callbacks on the
- `index`, `posts`, and `showPost` handlers
- 2. Triggers the `enter` callback on the same
- 3. Triggers the `setup` callback on the same
- 2. A direct transition to `newPost`
- 1. Triggers the `exit` callback on `showPost`
- 2. Triggers the `enter` callback on `newPost`
- 3. Triggers the `setup` callback on `newPost`
- 3. A direct transition to `about` with a specified
- context object
- 1. Triggers the `exit` callback on `newPost`
- and `posts`
- 2. Triggers the `serialize` callback on `about`
- 3. Triggers the `enter` callback on `about`
- 4. Triggers the `setup` callback on `about`
-
- @param {Router} transition
- @param {TransitionState} newState
- */
- function setupContexts(router, newState, transition) {
- var partition = partitionHandlers(router.state, newState);
-
- forEach(partition.exited, function(handlerInfo) {
- var handler = handlerInfo.handler;
- delete handler.context;
-
- callHook(handler, 'reset', true, transition);
- callHook(handler, 'exit', transition);
- });
-
- var oldState = router.oldState = router.state;
- router.state = newState;
- var currentHandlerInfos = router.currentHandlerInfos = partition.unchanged.slice();
-
- try {
- forEach(partition.reset, function(handlerInfo) {
- var handler = handlerInfo.handler;
- callHook(handler, 'reset', false, transition);
- });
-
- forEach(partition.updatedContext, function(handlerInfo) {
- return handlerEnteredOrUpdated(currentHandlerInfos, handlerInfo, false, transition);
- });
-
- forEach(partition.entered, function(handlerInfo) {
- return handlerEnteredOrUpdated(currentHandlerInfos, handlerInfo, true, transition);
- });
- } catch(e) {
- router.state = oldState;
- router.currentHandlerInfos = oldState.handlerInfos;
- throw e;
- }
-
- router.state.queryParams = finalizeQueryParamChange(router, currentHandlerInfos, newState.queryParams, transition);
- }
-
-
- /**
- @private
-
- Helper method used by setupContexts. Handles errors or redirects
- that may happen in enter/setup.
- */
- function handlerEnteredOrUpdated(currentHandlerInfos, handlerInfo, enter, transition) {
-
- var handler = handlerInfo.handler,
- context = handlerInfo.context;
-
- if (enter) {
- callHook(handler, 'enter', transition);
- }
- if (transition && transition.isAborted) {
- throw new TransitionAborted();
- }
-
- handler.context = context;
- callHook(handler, 'contextDidChange');
-
- callHook(handler, 'setup', context, transition);
- if (transition && transition.isAborted) {
- throw new TransitionAborted();
- }
-
- currentHandlerInfos.push(handlerInfo);
-
- return true;
- }
-
-
- /**
- @private
-
- This function is called when transitioning from one URL to
- another to determine which handlers are no longer active,
- which handlers are newly active, and which handlers remain
- active but have their context changed.
-
- Take a list of old handlers and new handlers and partition
- them into four buckets:
-
- * unchanged: the handler was active in both the old and
- new URL, and its context remains the same
- * updated context: the handler was active in both the
- old and new URL, but its context changed. The handler's
- `setup` method, if any, will be called with the new
- context.
- * exited: the handler was active in the old URL, but is
- no longer active.
- * entered: the handler was not active in the old URL, but
- is now active.
-
- The PartitionedHandlers structure has four fields:
-
- * `updatedContext`: a list of `HandlerInfo` objects that
- represent handlers that remain active but have a changed
- context
- * `entered`: a list of `HandlerInfo` objects that represent
- handlers that are newly active
- * `exited`: a list of `HandlerInfo` objects that are no
- longer active.
- * `unchanged`: a list of `HanderInfo` objects that remain active.
-
- @param {Array[HandlerInfo]} oldHandlers a list of the handler
- information for the previous URL (or `[]` if this is the
- first handled transition)
- @param {Array[HandlerInfo]} newHandlers a list of the handler
- information for the new URL
-
- @return {Partition}
- */
- function partitionHandlers(oldState, newState) {
- var oldHandlers = oldState.handlerInfos;
- var newHandlers = newState.handlerInfos;
-
- var handlers = {
- updatedContext: [],
- exited: [],
- entered: [],
- unchanged: []
- };
-
- var handlerChanged, contextChanged = false, i, l;
-
- for (i=0, l=newHandlers.length; i<l; i++) {
- var oldHandler = oldHandlers[i], newHandler = newHandlers[i];
-
- if (!oldHandler || oldHandler.handler !== newHandler.handler) {
- handlerChanged = true;
- }
-
- if (handlerChanged) {
- handlers.entered.push(newHandler);
- if (oldHandler) { handlers.exited.unshift(oldHandler); }
- } else if (contextChanged || oldHandler.context !== newHandler.context) {
- contextChanged = true;
- handlers.updatedContext.push(newHandler);
- } else {
- handlers.unchanged.push(oldHandler);
- }
- }
-
- for (i=newHandlers.length, l=oldHandlers.length; i<l; i++) {
- handlers.exited.unshift(oldHandlers[i]);
- }
-
- handlers.reset = handlers.updatedContext.slice();
- handlers.reset.reverse();
-
- return handlers;
- }
-
- function updateURL(transition, state, inputUrl) {
- var urlMethod = transition.urlMethod;
-
- if (!urlMethod) {
- return;
- }
-
- var router = transition.router,
- handlerInfos = state.handlerInfos,
- handlerName = handlerInfos[handlerInfos.length - 1].name,
- params = {};
-
- for (var i = handlerInfos.length - 1; i >= 0; --i) {
- var handlerInfo = handlerInfos[i];
- merge(params, handlerInfo.params);
- if (handlerInfo.handler.inaccessibleByURL) {
- urlMethod = null;
- }
- }
-
- if (urlMethod) {
- params.queryParams = transition._visibleQueryParams || state.queryParams;
- var url = router.recognizer.generate(handlerName, params);
-
- if (urlMethod === 'replace') {
- router.replaceURL(url);
- } else {
- router.updateURL(url);
- }
- }
- }
-
- /**
- @private
-
- Updates the URL (if necessary) and calls `setupContexts`
- to update the router's array of `currentHandlerInfos`.
- */
- function finalizeTransition(transition, newState) {
-
- try {
- log(transition.router, transition.sequence, "Resolved all models on destination route; finalizing transition.");
-
- var router = transition.router,
- handlerInfos = newState.handlerInfos,
- seq = transition.sequence;
-
- // Run all the necessary enter/setup/exit hooks
- setupContexts(router, newState, transition);
-
- // Check if a redirect occurred in enter/setup
- if (transition.isAborted) {
- // TODO: cleaner way? distinguish b/w targetHandlerInfos?
- router.state.handlerInfos = router.currentHandlerInfos;
- return Promise.reject(logAbort(transition));
- }
-
- updateURL(transition, newState, transition.intent.url);
-
- transition.isActive = false;
- router.activeTransition = null;
-
- trigger(router, router.currentHandlerInfos, true, ['didTransition']);
-
- if (router.didTransition) {
- router.didTransition(router.currentHandlerInfos);
- }
-
- log(router, transition.sequence, "TRANSITION COMPLETE.");
-
- // Resolve with the final handler.
- return handlerInfos[handlerInfos.length - 1].handler;
- } catch(e) {
- if (!((e instanceof TransitionAborted))) {
- //var erroneousHandler = handlerInfos.pop();
- var infos = transition.state.handlerInfos;
- transition.trigger(true, 'error', e, transition, infos[infos.length-1].handler);
- transition.abort();
- }
-
- throw e;
- }
- }
-
- /**
- @private
-
- Begins and returns a Transition based on the provided
- arguments. Accepts arguments in the form of both URL
- transitions and named transitions.
-
- @param {Router} router
- @param {Array[Object]} args arguments passed to transitionTo,
- replaceWith, or handleURL
- */
- function doTransition(router, args, isIntermediate) {
- // Normalize blank transitions to root URL transitions.
- var name = args[0] || '/';
-
- var lastArg = args[args.length-1];
- var queryParams = {};
- if (lastArg && lastArg.hasOwnProperty('queryParams')) {
- queryParams = pop.call(args).queryParams;
- }
-
- var intent;
- if (args.length === 0) {
-
- log(router, "Updating query params");
-
- // A query param update is really just a transition
- // into the route you're already on.
- var handlerInfos = router.state.handlerInfos;
- intent = new NamedTransitionIntent({
- name: handlerInfos[handlerInfos.length - 1].name,
- contexts: [],
- queryParams: queryParams
- });
-
- } else if (name.charAt(0) === '/') {
-
- log(router, "Attempting URL transition to " + name);
- intent = new URLTransitionIntent({ url: name });
-
- } else {
-
- log(router, "Attempting transition to " + name);
- intent = new NamedTransitionIntent({
- name: args[0],
- contexts: slice.call(args, 1),
- queryParams: queryParams
- });
- }
-
- return router.transitionByIntent(intent, isIntermediate);
- }
-
- function handlerInfosEqual(handlerInfos, otherHandlerInfos) {
- if (handlerInfos.length !== otherHandlerInfos.length) {
- return false;
- }
-
- for (var i = 0, len = handlerInfos.length; i < len; ++i) {
- if (handlerInfos[i] !== otherHandlerInfos[i]) {
- return false;
- }
- }
- return true;
- }
-
- function finalizeQueryParamChange(router, resolvedHandlers, newQueryParams, transition) {
- // We fire a finalizeQueryParamChange event which
- // gives the new route hierarchy a chance to tell
- // us which query params it's consuming and what
- // their final values are. If a query param is
- // no longer consumed in the final route hierarchy,
- // its serialized segment will be removed
- // from the URL.
-
- for (var k in newQueryParams) {
- if (newQueryParams.hasOwnProperty(k) &&
- newQueryParams[k] === null) {
- delete newQueryParams[k];
- }
- }
-
- var finalQueryParamsArray = [];
- trigger(router, resolvedHandlers, true, ['finalizeQueryParamChange', newQueryParams, finalQueryParamsArray, transition]);
-
- if (transition) {
- transition._visibleQueryParams = {};
- }
-
- var finalQueryParams = {};
- for (var i = 0, len = finalQueryParamsArray.length; i < len; ++i) {
- var qp = finalQueryParamsArray[i];
- finalQueryParams[qp.key] = qp.value;
- if (transition && qp.visible !== false) {
- transition._visibleQueryParams[qp.key] = qp.value;
- }
- }
- return finalQueryParams;
- }
-
- function notifyExistingHandlers(router, newState, newTransition) {
- var oldHandlers = router.state.handlerInfos,
- changing = [],
- leavingIndex = null,
- leaving, leavingChecker, i, oldHandlerLen, oldHandler, newHandler;
-
- oldHandlerLen = oldHandlers.length;
- for (i = 0; i < oldHandlerLen; i++) {
- oldHandler = oldHandlers[i];
- newHandler = newState.handlerInfos[i];
-
- if (!newHandler || oldHandler.name !== newHandler.name) {
- leavingIndex = i;
- break;
- }
-
- if (!newHandler.isResolved) {
- changing.push(oldHandler);
- }
- }
-
- if (leavingIndex !== null) {
- leaving = oldHandlers.slice(leavingIndex, oldHandlerLen);
- leavingChecker = function(name) {
- for (var h = 0, len = leaving.length; h < len; h++) {
- if (leaving[h].name === name) {
- return true;
- }
- }
- return false;
- };
-
- router._triggerWillLeave(leaving, newTransition, leavingChecker);
- }
-
- if (changing.length > 0) {
- router._triggerWillChangeContext(changing, newTransition);
- }
-
- trigger(router, oldHandlers, true, ['willTransition', newTransition]);
- }
-
- __exports__["default"] = Router;
- });
-enifed("router/transition-intent",
- ["./utils","exports"],
- function(__dependency1__, __exports__) {
- "use strict";
- var merge = __dependency1__.merge;
-
- function TransitionIntent(props) {
- this.initialize(props);
-
- // TODO: wat
- this.data = this.data || {};
- }
-
- TransitionIntent.prototype = {
- initialize: null,
- applyToState: null
- };
-
- __exports__["default"] = TransitionIntent;
- });
-enifed("router/transition-intent/named-transition-intent",
- ["../transition-intent","../transition-state","../handler-info/factory","../utils","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
- "use strict";
- var TransitionIntent = __dependency1__["default"];
- var TransitionState = __dependency2__["default"];
- var handlerInfoFactory = __dependency3__["default"];
- var isParam = __dependency4__.isParam;
- var extractQueryParams = __dependency4__.extractQueryParams;
- var merge = __dependency4__.merge;
- var subclass = __dependency4__.subclass;
-
- __exports__["default"] = subclass(TransitionIntent, {
- name: null,
- pivotHandler: null,
- contexts: null,
- queryParams: null,
-
- initialize: function(props) {
- this.name = props.name;
- this.pivotHandler = props.pivotHandler;
- this.contexts = props.contexts || [];
- this.queryParams = props.queryParams;
- },
-
- applyToState: function(oldState, recognizer, getHandler, isIntermediate) {
-
- var partitionedArgs = extractQueryParams([this.name].concat(this.contexts)),
- pureArgs = partitionedArgs[0],
- queryParams = partitionedArgs[1],
- handlers = recognizer.handlersFor(pureArgs[0]);
-
- var targetRouteName = handlers[handlers.length-1].handler;
-
- return this.applyToHandlers(oldState, handlers, getHandler, targetRouteName, isIntermediate);
- },
-
- applyToHandlers: function(oldState, handlers, getHandler, targetRouteName, isIntermediate, checkingIfActive) {
-
- var i, len;
- var newState = new TransitionState();
- var objects = this.contexts.slice(0);
-
- var invalidateIndex = handlers.length;
-
- // Pivot handlers are provided for refresh transitions
- if (this.pivotHandler) {
- for (i = 0, len = handlers.length; i < len; ++i) {
- if (getHandler(handlers[i].handler) === this.pivotHandler) {
- invalidateIndex = i;
- break;
- }
- }
- }
-
- var pivotHandlerFound = !this.pivotHandler;
-
- for (i = handlers.length - 1; i >= 0; --i) {
- var result = handlers[i];
- var name = result.handler;
- var handler = getHandler(name);
-
- var oldHandlerInfo = oldState.handlerInfos[i];
- var newHandlerInfo = null;
-
- if (result.names.length > 0) {
- if (i >= invalidateIndex) {
- newHandlerInfo = this.createParamHandlerInfo(name, handler, result.names, objects, oldHandlerInfo);
- } else {
- newHandlerInfo = this.getHandlerInfoForDynamicSegment(name, handler, result.names, objects, oldHandlerInfo, targetRouteName, i);
- }
- } else {
- // This route has no dynamic segment.
- // Therefore treat as a param-based handlerInfo
- // with empty params. This will cause the `model`
- // hook to be called with empty params, which is desirable.
- newHandlerInfo = this.createParamHandlerInfo(name, handler, result.names, objects, oldHandlerInfo);
- }
-
- if (checkingIfActive) {
- // If we're performing an isActive check, we want to
- // serialize URL params with the provided context, but
- // ignore mismatches between old and new context.
- newHandlerInfo = newHandlerInfo.becomeResolved(null, newHandlerInfo.context);
- var oldContext = oldHandlerInfo && oldHandlerInfo.context;
- if (result.names.length > 0 && newHandlerInfo.context === oldContext) {
- // If contexts match in isActive test, assume params also match.
- // This allows for flexibility in not requiring that every last
- // handler provide a `serialize` method
- newHandlerInfo.params = oldHandlerInfo && oldHandlerInfo.params;
- }
- newHandlerInfo.context = oldContext;
- }
-
- var handlerToUse = oldHandlerInfo;
- if (i >= invalidateIndex || newHandlerInfo.shouldSupercede(oldHandlerInfo)) {
- invalidateIndex = Math.min(i, invalidateIndex);
- handlerToUse = newHandlerInfo;
- }
-
- if (isIntermediate && !checkingIfActive) {
- handlerToUse = handlerToUse.becomeResolved(null, handlerToUse.context);
- }
-
- newState.handlerInfos.unshift(handlerToUse);
- }
-
- if (objects.length > 0) {
- throw new Error("More context objects were passed than there are dynamic segments for the route: " + targetRouteName);
- }
-
- if (!isIntermediate) {
- this.invalidateChildren(newState.handlerInfos, invalidateIndex);
- }
-
- merge(newState.queryParams, this.queryParams || {});
-
- return newState;
- },
-
- invalidateChildren: function(handlerInfos, invalidateIndex) {
- for (var i = invalidateIndex, l = handlerInfos.length; i < l; ++i) {
- var handlerInfo = handlerInfos[i];
- handlerInfos[i] = handlerInfos[i].getUnresolved();
- }
- },
-
- getHandlerInfoForDynamicSegment: function(name, handler, names, objects, oldHandlerInfo, targetRouteName, i) {
-
- var numNames = names.length;
- var objectToUse;
- if (objects.length > 0) {
-
- // Use the objects provided for this transition.
- objectToUse = objects[objects.length - 1];
- if (isParam(objectToUse)) {
- return this.createParamHandlerInfo(name, handler, names, objects, oldHandlerInfo);
- } else {
- objects.pop();
- }
- } else if (oldHandlerInfo && oldHandlerInfo.name === name) {
- // Reuse the matching oldHandlerInfo
- return oldHandlerInfo;
- } else {
- if (this.preTransitionState) {
- var preTransitionHandlerInfo = this.preTransitionState.handlerInfos[i];
- objectToUse = preTransitionHandlerInfo && preTransitionHandlerInfo.context;
- } else {
- // Ideally we should throw this error to provide maximal
- // information to the user that not enough context objects
- // were provided, but this proves too cumbersome in Ember
- // in cases where inner template helpers are evaluated
- // before parent helpers un-render, in which cases this
- // error somewhat prematurely fires.
- //throw new Error("Not enough context objects were provided to complete a transition to " + targetRouteName + ". Specifically, the " + name + " route needs an object that can be serialized into its dynamic URL segments [" + names.join(', ') + "]");
- return oldHandlerInfo;
- }
- }
-
- return handlerInfoFactory('object', {
- name: name,
- handler: handler,
- context: objectToUse,
- names: names
- });
- },
-
- createParamHandlerInfo: function(name, handler, names, objects, oldHandlerInfo) {
- var params = {};
-
- // Soak up all the provided string/numbers
- var numNames = names.length;
- while (numNames--) {
-
- // Only use old params if the names match with the new handler
- var oldParams = (oldHandlerInfo && name === oldHandlerInfo.name && oldHandlerInfo.params) || {};
-
- var peek = objects[objects.length - 1];
- var paramName = names[numNames];
- if (isParam(peek)) {
- params[paramName] = "" + objects.pop();
- } else {
- // If we're here, this means only some of the params
- // were string/number params, so try and use a param
- // value from a previous handler.
- if (oldParams.hasOwnProperty(paramName)) {
- params[paramName] = oldParams[paramName];
- } else {
- throw new Error("You didn't provide enough string/numeric parameters to satisfy all of the dynamic segments for route " + name);
- }
- }
- }
-
- return handlerInfoFactory('param', {
- name: name,
- handler: handler,
- params: params
- });
- }
- });
- });
-enifed("router/transition-intent/url-transition-intent",
- ["../transition-intent","../transition-state","../handler-info/factory","../utils","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
- "use strict";
- var TransitionIntent = __dependency1__["default"];
- var TransitionState = __dependency2__["default"];
- var handlerInfoFactory = __dependency3__["default"];
- var oCreate = __dependency4__.oCreate;
- var merge = __dependency4__.merge;
- var subclass = __dependency4__.subclass;
-
- __exports__["default"] = subclass(TransitionIntent, {
- url: null,
-
- initialize: function(props) {
- this.url = props.url;
- },
-
- applyToState: function(oldState, recognizer, getHandler) {
- var newState = new TransitionState();
-
- var results = recognizer.recognize(this.url),
- queryParams = {},
- i, len;
-
- if (!results) {
- throw new UnrecognizedURLError(this.url);
- }
-
- var statesDiffer = false;
-
- for (i = 0, len = results.length; i < len; ++i) {
- var result = results[i];
- var name = result.handler;
- var handler = getHandler(name);
-
- if (handler.inaccessibleByURL) {
- throw new UnrecognizedURLError(this.url);
- }
-
- var newHandlerInfo = handlerInfoFactory('param', {
- name: name,
- handler: handler,
- params: result.params
- });
-
- var oldHandlerInfo = oldState.handlerInfos[i];
- if (statesDiffer || newHandlerInfo.shouldSupercede(oldHandlerInfo)) {
- statesDiffer = true;
- newState.handlerInfos[i] = newHandlerInfo;
- } else {
- newState.handlerInfos[i] = oldHandlerInfo;
- }
- }
-
- merge(newState.queryParams, results.queryParams);
-
- return newState;
- }
- });
-
- /**
- Promise reject reasons passed to promise rejection
- handlers for failed transitions.
- */
- function UnrecognizedURLError(message) {
- this.message = (message || "UnrecognizedURLError");
- this.name = "UnrecognizedURLError";
- }
- });
-enifed("router/transition-state",
- ["./handler-info","./utils","rsvp/promise","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
- "use strict";
- var ResolvedHandlerInfo = __dependency1__.ResolvedHandlerInfo;
- var forEach = __dependency2__.forEach;
- var promiseLabel = __dependency2__.promiseLabel;
- var callHook = __dependency2__.callHook;
- var Promise = __dependency3__["default"];
-
- function TransitionState(other) {
- this.handlerInfos = [];
- this.queryParams = {};
- this.params = {};
- }
-
- TransitionState.prototype = {
- handlerInfos: null,
- queryParams: null,
- params: null,
-
- promiseLabel: function(label) {
- var targetName = '';
- forEach(this.handlerInfos, function(handlerInfo) {
- if (targetName !== '') {
- targetName += '.';
- }
- targetName += handlerInfo.name;
- });
- return promiseLabel("'" + targetName + "': " + label);
- },
-
- resolve: function(shouldContinue, payload) {
- var self = this;
- // First, calculate params for this state. This is useful
- // information to provide to the various route hooks.
- var params = this.params;
- forEach(this.handlerInfos, function(handlerInfo) {
- params[handlerInfo.name] = handlerInfo.params || {};
- });
-
- payload = payload || {};
- payload.resolveIndex = 0;
-
- var currentState = this;
- var wasAborted = false;
-
- // The prelude RSVP.resolve() asyncs us into the promise land.
- return Promise.resolve(null, this.promiseLabel("Start transition"))
- .then(resolveOneHandlerInfo, null, this.promiseLabel('Resolve handler'))['catch'](handleError, this.promiseLabel('Handle error'));
-
- function innerShouldContinue() {
- return Promise.resolve(shouldContinue(), currentState.promiseLabel("Check if should continue"))['catch'](function(reason) {
- // We distinguish between errors that occurred
- // during resolution (e.g. beforeModel/model/afterModel),
- // and aborts due to a rejecting promise from shouldContinue().
- wasAborted = true;
- return Promise.reject(reason);
- }, currentState.promiseLabel("Handle abort"));
- }
-
- function handleError(error) {
- // This is the only possible
- // reject value of TransitionState#resolve
- var handlerInfos = currentState.handlerInfos;
- var errorHandlerIndex = payload.resolveIndex >= handlerInfos.length ?
- handlerInfos.length - 1 : payload.resolveIndex;
- return Promise.reject({
- error: error,
- handlerWithError: currentState.handlerInfos[errorHandlerIndex].handler,
- wasAborted: wasAborted,
- state: currentState
- });
- }
-
- function proceed(resolvedHandlerInfo) {
- var wasAlreadyResolved = currentState.handlerInfos[payload.resolveIndex].isResolved;
-
- // Swap the previously unresolved handlerInfo with
- // the resolved handlerInfo
- currentState.handlerInfos[payload.resolveIndex++] = resolvedHandlerInfo;
-
- if (!wasAlreadyResolved) {
- // Call the redirect hook. The reason we call it here
- // vs. afterModel is so that redirects into child
- // routes don't re-run the model hooks for this
- // already-resolved route.
- var handler = resolvedHandlerInfo.handler;
- callHook(handler, 'redirect', resolvedHandlerInfo.context, payload);
- }
-
- // Proceed after ensuring that the redirect hook
- // didn't abort this transition by transitioning elsewhere.
- return innerShouldContinue().then(resolveOneHandlerInfo, null, currentState.promiseLabel('Resolve handler'));
- }
-
- function resolveOneHandlerInfo() {
- if (payload.resolveIndex === currentState.handlerInfos.length) {
- // This is is the only possible
- // fulfill value of TransitionState#resolve
- return {
- error: null,
- state: currentState
- };
- }
-
- var handlerInfo = currentState.handlerInfos[payload.resolveIndex];
-
- return handlerInfo.resolve(innerShouldContinue, payload)
- .then(proceed, null, currentState.promiseLabel('Proceed'));
- }
- }
- };
-
- __exports__["default"] = TransitionState;
- });
-enifed("router/transition",
- ["rsvp/promise","./handler-info","./utils","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
- "use strict";
- var Promise = __dependency1__["default"];
- var ResolvedHandlerInfo = __dependency2__.ResolvedHandlerInfo;
- var trigger = __dependency3__.trigger;
- var slice = __dependency3__.slice;
- var log = __dependency3__.log;
- var promiseLabel = __dependency3__.promiseLabel;
-
- /**
- @private
-
- A Transition is a thennable (a promise-like object) that represents
- an attempt to transition to another route. It can be aborted, either
- explicitly via `abort` or by attempting another transition while a
- previous one is still underway. An aborted transition can also
- be `retry()`d later.
- */
- function Transition(router, intent, state, error) {
- var transition = this;
- this.state = state || router.state;
- this.intent = intent;
- this.router = router;
- this.data = this.intent && this.intent.data || {};
- this.resolvedModels = {};
- this.queryParams = {};
-
- if (error) {
- this.promise = Promise.reject(error);
- this.error = error;
- return;
- }
-
- if (state) {
- this.params = state.params;
- this.queryParams = state.queryParams;
- this.handlerInfos = state.handlerInfos;
-
- var len = state.handlerInfos.length;
- if (len) {
- this.targetName = state.handlerInfos[len-1].name;
- }
-
- for (var i = 0; i < len; ++i) {
- var handlerInfo = state.handlerInfos[i];
-
- // TODO: this all seems hacky
- if (!handlerInfo.isResolved) { break; }
- this.pivotHandler = handlerInfo.handler;
- }
-
- this.sequence = Transition.currentSequence++;
- this.promise = state.resolve(checkForAbort, this)['catch'](function(result) {
- if (result.wasAborted || transition.isAborted) {
- return Promise.reject(logAbort(transition));
- } else {
- transition.trigger('error', result.error, transition, result.handlerWithError);
- transition.abort();
- return Promise.reject(result.error);
- }
- }, promiseLabel('Handle Abort'));
- } else {
- this.promise = Promise.resolve(this.state);
- this.params = {};
- }
-
- function checkForAbort() {
- if (transition.isAborted) {
- return Promise.reject(undefined, promiseLabel("Transition aborted - reject"));
- }
- }
- }
-
- Transition.currentSequence = 0;
-
- Transition.prototype = {
- targetName: null,
- urlMethod: 'update',
- intent: null,
- params: null,
- pivotHandler: null,
- resolveIndex: 0,
- handlerInfos: null,
- resolvedModels: null,
- isActive: true,
- state: null,
- queryParamsOnly: false,
-
- isTransition: true,
-
- isExiting: function(handler) {
- var handlerInfos = this.handlerInfos;
- for (var i = 0, len = handlerInfos.length; i < len; ++i) {
- var handlerInfo = handlerInfos[i];
- if (handlerInfo.name === handler || handlerInfo.handler === handler) {
- return false;
- }
- }
- return true;
- },
-
- /**
- @public
-
- The Transition's internal promise. Calling `.then` on this property
- is that same as calling `.then` on the Transition object itself, but
- this property is exposed for when you want to pass around a
- Transition's promise, but not the Transition object itself, since
- Transition object can be externally `abort`ed, while the promise
- cannot.
- */
- promise: null,
-
- /**
- @public
-
- Custom state can be stored on a Transition's `data` object.
- This can be useful for decorating a Transition within an earlier
- hook and shared with a later hook. Properties set on `data` will
- be copied to new transitions generated by calling `retry` on this
- transition.
- */
- data: null,
-
- /**
- @public
-
- A standard promise hook that resolves if the transition
- succeeds and rejects if it fails/redirects/aborts.
-
- Forwards to the internal `promise` property which you can
- use in situations where you want to pass around a thennable,
- but not the Transition itself.
-
- @param {Function} onFulfilled
- @param {Function} onRejected
- @param {String} label optional string for labeling the promise.
- Useful for tooling.
- @return {Promise}
- */
- then: function(onFulfilled, onRejected, label) {
- return this.promise.then(onFulfilled, onRejected, label);
- },
-
- /**
- @public
-
- Forwards to the internal `promise` property which you can
- use in situations where you want to pass around a thennable,
- but not the Transition itself.
-
- @method catch
- @param {Function} onRejection
- @param {String} label optional string for labeling the promise.
- Useful for tooling.
- @return {Promise}
- */
- "catch": function(onRejection, label) {
- return this.promise["catch"](onRejection, label);
- },
-
- /**
- @public
-
- Forwards to the internal `promise` property which you can
- use in situations where you want to pass around a thennable,
- but not the Transition itself.
-
- @method finally
- @param {Function} callback
- @param {String} label optional string for labeling the promise.
- Useful for tooling.
- @return {Promise}
- */
- "finally": function(callback, label) {
- return this.promise["finally"](callback, label);
- },
-
- /**
- @public
-
- Aborts the Transition. Note you can also implicitly abort a transition
- by initiating another transition while a previous one is underway.
- */
- abort: function() {
- if (this.isAborted) { return this; }
- log(this.router, this.sequence, this.targetName + ": transition was aborted");
- this.intent.preTransitionState = this.router.state;
- this.isAborted = true;
- this.isActive = false;
- this.router.activeTransition = null;
- return this;
- },
-
- /**
- @public
-
- Retries a previously-aborted transition (making sure to abort the
- transition if it's still active). Returns a new transition that
- represents the new attempt to transition.
- */
- retry: function() {
- // TODO: add tests for merged state retry()s
- this.abort();
- return this.router.transitionByIntent(this.intent, false);
- },
-
- /**
- @public
-
- Sets the URL-changing method to be employed at the end of a
- successful transition. By default, a new Transition will just
- use `updateURL`, but passing 'replace' to this method will
- cause the URL to update using 'replaceWith' instead. Omitting
- a parameter will disable the URL change, allowing for transitions
- that don't update the URL at completion (this is also used for
- handleURL, since the URL has already changed before the
- transition took place).
-
- @param {String} method the type of URL-changing method to use
- at the end of a transition. Accepted values are 'replace',
- falsy values, or any other non-falsy value (which is
- interpreted as an updateURL transition).
-
- @return {Transition} this transition
- */
- method: function(method) {
- this.urlMethod = method;
- return this;
- },
-
- /**
- @public
-
- Fires an event on the current list of resolved/resolving
- handlers within this transition. Useful for firing events
- on route hierarchies that haven't fully been entered yet.
-
- Note: This method is also aliased as `send`
-
- @param {Boolean} [ignoreFailure=false] a boolean specifying whether unhandled events throw an error
- @param {String} name the name of the event to fire
- */
- trigger: function (ignoreFailure) {
- var args = slice.call(arguments);
- if (typeof ignoreFailure === 'boolean') {
- args.shift();
- } else {
- // Throw errors on unhandled trigger events by default
- ignoreFailure = false;
- }
- trigger(this.router, this.state.handlerInfos.slice(0, this.resolveIndex + 1), ignoreFailure, args);
- },
-
- /**
- @public
-
- Transitions are aborted and their promises rejected
- when redirects occur; this method returns a promise
- that will follow any redirects that occur and fulfill
- with the value fulfilled by any redirecting transitions
- that occur.
-
- @return {Promise} a promise that fulfills with the same
- value that the final redirecting transition fulfills with
- */
- followRedirects: function() {
- var router = this.router;
- return this.promise['catch'](function(reason) {
- if (router.activeTransition) {
- return router.activeTransition.followRedirects();
- }
- return Promise.reject(reason);
- });
- },
-
- toString: function() {
- return "Transition (sequence " + this.sequence + ")";
- },
-
- /**
- @private
- */
- log: function(message) {
- log(this.router, this.sequence, message);
- }
- };
-
- // Alias 'trigger' as 'send'
- Transition.prototype.send = Transition.prototype.trigger;
-
- /**
- @private
-
- Logs and returns a TransitionAborted error.
- */
- function logAbort(transition) {
- log(transition.router, transition.sequence, "detected abort.");
- return new TransitionAborted();
- }
-
- function TransitionAborted(message) {
- this.message = (message || "TransitionAborted");
- this.name = "TransitionAborted";
- }
-
- __exports__.Transition = Transition;
- __exports__.logAbort = logAbort;
- __exports__.TransitionAborted = TransitionAborted;
- });
-enifed("router/utils",
- ["exports"],
- function(__exports__) {
- "use strict";
- var slice = Array.prototype.slice;
-
- var _isArray;
- if (!Array.isArray) {
- _isArray = function (x) {
- return Object.prototype.toString.call(x) === "[object Array]";
- };
- } else {
- _isArray = Array.isArray;
- }
-
- var isArray = _isArray;
- __exports__.isArray = isArray;
- function merge(hash, other) {
- for (var prop in other) {
- if (other.hasOwnProperty(prop)) { hash[prop] = other[prop]; }
- }
- }
-
- var oCreate = Object.create || function(proto) {
- function F() {}
- F.prototype = proto;
- return new F();
- };
- __exports__.oCreate = oCreate;
- /**
- @private
-
- Extracts query params from the end of an array
- **/
- function extractQueryParams(array) {
- var len = (array && array.length), head, queryParams;
-
- if(len && len > 0 && array[len - 1] && array[len - 1].hasOwnProperty('queryParams')) {
- queryParams = array[len - 1].queryParams;
- head = slice.call(array, 0, len - 1);
- return [head, queryParams];
- } else {
- return [array, null];
- }
- }
-
- __exports__.extractQueryParams = extractQueryParams;/**
- @private
-
- Coerces query param properties and array elements into strings.
- **/
- function coerceQueryParamsToString(queryParams) {
- for (var key in queryParams) {
- if (typeof queryParams[key] === 'number') {
- queryParams[key] = '' + queryParams[key];
- } else if (isArray(queryParams[key])) {
- for (var i = 0, l = queryParams[key].length; i < l; i++) {
- queryParams[key][i] = '' + queryParams[key][i];
- }
- }
- }
- }
- /**
- @private
- */
- function log(router, sequence, msg) {
- if (!router.log) { return; }
-
- if (arguments.length === 3) {
- router.log("Transition #" + sequence + ": " + msg);
- } else {
- msg = sequence;
- router.log(msg);
- }
- }
-
- __exports__.log = log;function bind(context, fn) {
- var boundArgs = arguments;
- return function(value) {
- var args = slice.call(boundArgs, 2);
- args.push(value);
- return fn.apply(context, args);
- };
- }
-
- __exports__.bind = bind;function isParam(object) {
- return (typeof object === "string" || object instanceof String || typeof object === "number" || object instanceof Number);
- }
-
-
- function forEach(array, callback) {
- for (var i=0, l=array.length; i<l && false !== callback(array[i]); i++) { }
- }
-
- __exports__.forEach = forEach;function trigger(router, handlerInfos, ignoreFailure, args) {
- if (router.triggerEvent) {
- router.triggerEvent(handlerInfos, ignoreFailure, args);
- return;
- }
-
- var name = args.shift();
-
- if (!handlerInfos) {
- if (ignoreFailure) { return; }
- throw new Error("Could not trigger event '" + name + "'. There are no active handlers");
- }
-
- var eventWasHandled = false;
-
- for (var i=handlerInfos.length-1; i>=0; i--) {
- var handlerInfo = handlerInfos[i],
- handler = handlerInfo.handler;
-
- if (handler.events && handler.events[name]) {
- if (handler.events[name].apply(handler, args) === true) {
- eventWasHandled = true;
- } else {
- return;
- }
- }
- }
-
- if (!eventWasHandled && !ignoreFailure) {
- throw new Error("Nothing handled the event '" + name + "'.");
- }
- }
-
- __exports__.trigger = trigger;function getChangelist(oldObject, newObject) {
- var key;
- var results = {
- all: {},
- changed: {},
- removed: {}
- };
-
- merge(results.all, newObject);
-
- var didChange = false;
- coerceQueryParamsToString(oldObject);
- coerceQueryParamsToString(newObject);
-
- // Calculate removals
- for (key in oldObject) {
- if (oldObject.hasOwnProperty(key)) {
- if (!newObject.hasOwnProperty(key)) {
- didChange = true;
- results.removed[key] = oldObject[key];
- }
- }
- }
-
- // Calculate changes
- for (key in newObject) {
- if (newObject.hasOwnProperty(key)) {
- if (isArray(oldObject[key]) && isArray(newObject[key])) {
- if (oldObject[key].length !== newObject[key].length) {
- results.changed[key] = newObject[key];
- didChange = true;
- } else {
- for (var i = 0, l = oldObject[key].length; i < l; i++) {
- if (oldObject[key][i] !== newObject[key][i]) {
- results.changed[key] = newObject[key];
- didChange = true;
- }
- }
- }
- }
- else {
- if (oldObject[key] !== newObject[key]) {
- results.changed[key] = newObject[key];
- didChange = true;
- }
- }
- }
- }
-
- return didChange && results;
- }
-
- __exports__.getChangelist = getChangelist;function promiseLabel(label) {
- return 'Router: ' + label;
- }
-
- __exports__.promiseLabel = promiseLabel;function subclass(parentConstructor, proto) {
- function C(props) {
- parentConstructor.call(this, props || {});
- }
- C.prototype = oCreate(parentConstructor.prototype);
- merge(C.prototype, proto);
- return C;
- }
-
- __exports__.subclass = subclass;function resolveHook(obj, hookName) {
- if (!obj) { return; }
- var underscored = "_" + hookName;
- return obj[underscored] && underscored ||
- obj[hookName] && hookName;
- }
-
- function callHook(obj, hookName) {
- var args = slice.call(arguments, 2);
- return applyHook(obj, hookName, args);
- }
-
- function applyHook(obj, _hookName, args) {
- var hookName = resolveHook(obj, _hookName);
- if (hookName) {
- return obj[hookName].apply(obj, args);
- }
- }
-
- __exports__.merge = merge;
- __exports__.slice = slice;
- __exports__.isParam = isParam;
- __exports__.coerceQueryParamsToString = coerceQueryParamsToString;
- __exports__.callHook = callHook;
- __exports__.resolveHook = resolveHook;
- __exports__.applyHook = applyHook;
- });
-enifed("rsvp",
- ["./rsvp/promise","./rsvp/events","./rsvp/node","./rsvp/all","./rsvp/all-settled","./rsvp/race","./rsvp/hash","./rsvp/hash-settled","./rsvp/rethrow","./rsvp/defer","./rsvp/config","./rsvp/map","./rsvp/resolve","./rsvp/reject","./rsvp/filter","./rsvp/asap","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __dependency15__, __dependency16__, __exports__) {
- "use strict";
- var Promise = __dependency1__["default"];
- var EventTarget = __dependency2__["default"];
- var denodeify = __dependency3__["default"];
- var all = __dependency4__["default"];
- var allSettled = __dependency5__["default"];
- var race = __dependency6__["default"];
- var hash = __dependency7__["default"];
- var hashSettled = __dependency8__["default"];
- var rethrow = __dependency9__["default"];
- var defer = __dependency10__["default"];
- var config = __dependency11__.config;
- var configure = __dependency11__.configure;
- var map = __dependency12__["default"];
- var resolve = __dependency13__["default"];
- var reject = __dependency14__["default"];
- var filter = __dependency15__["default"];
- var asap = __dependency16__["default"];
-
- config.async = asap; // default async is asap;
- var cast = resolve;
- function async(callback, arg) {
- config.async(callback, arg);
- }
-
- function on() {
- config.on.apply(config, arguments);
- }
-
- function off() {
- config.off.apply(config, arguments);
- }
-
- // Set up instrumentation through `window.__PROMISE_INTRUMENTATION__`
- if (typeof window !== 'undefined' && typeof window['__PROMISE_INSTRUMENTATION__'] === 'object') {
- var callbacks = window['__PROMISE_INSTRUMENTATION__'];
- configure('instrument', true);
- for (var eventName in callbacks) {
- if (callbacks.hasOwnProperty(eventName)) {
- on(eventName, callbacks[eventName]);
- }
- }
- }
-
- __exports__.cast = cast;
- __exports__.Promise = Promise;
- __exports__.EventTarget = EventTarget;
- __exports__.all = all;
- __exports__.allSettled = allSettled;
- __exports__.race = race;
- __exports__.hash = hash;
- __exports__.hashSettled = hashSettled;
- __exports__.rethrow = rethrow;
- __exports__.defer = defer;
- __exports__.denodeify = denodeify;
- __exports__.configure = configure;
- __exports__.on = on;
- __exports__.off = off;
- __exports__.resolve = resolve;
- __exports__.reject = reject;
- __exports__.async = async;
- __exports__.map = map;
- __exports__.filter = filter;
- });
-enifed("rsvp.umd",
- ["./rsvp"],
- function(__dependency1__) {
- "use strict";
- var Promise = __dependency1__.Promise;
- var allSettled = __dependency1__.allSettled;
- var hash = __dependency1__.hash;
- var hashSettled = __dependency1__.hashSettled;
- var denodeify = __dependency1__.denodeify;
- var on = __dependency1__.on;
- var off = __dependency1__.off;
- var map = __dependency1__.map;
- var filter = __dependency1__.filter;
- var resolve = __dependency1__.resolve;
- var reject = __dependency1__.reject;
- var rethrow = __dependency1__.rethrow;
- var all = __dependency1__.all;
- var defer = __dependency1__.defer;
- var EventTarget = __dependency1__.EventTarget;
- var configure = __dependency1__.configure;
- var race = __dependency1__.race;
- var async = __dependency1__.async;
-
- var RSVP = {
- 'race': race,
- 'Promise': Promise,
- 'allSettled': allSettled,
- 'hash': hash,
- 'hashSettled': hashSettled,
- 'denodeify': denodeify,
- 'on': on,
- 'off': off,
- 'map': map,
- 'filter': filter,
- 'resolve': resolve,
- 'reject': reject,
- 'all': all,
- 'rethrow': rethrow,
- 'defer': defer,
- 'EventTarget': EventTarget,
- 'configure': configure,
- 'async': async
- };
-
- /* global define:true module:true window: true */
- if (typeof enifed === 'function' && enifed['amd']) {
- enifed(function() { return RSVP; });
- } else if (typeof module !== 'undefined' && module['exports']) {
- module['exports'] = RSVP;
- } else if (typeof this !== 'undefined') {
- this['RSVP'] = RSVP;
- }
- });
-enifed("rsvp/-internal",
- ["./utils","./instrument","./config","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
- "use strict";
- var objectOrFunction = __dependency1__.objectOrFunction;
- var isFunction = __dependency1__.isFunction;
-
- var instrument = __dependency2__["default"];
-
- var config = __dependency3__.config;
-
- function withOwnPromise() {
- return new TypeError('A promises callback cannot return that same promise.');
- }
-
- function noop() {}
-
- var PENDING = void 0;
- var FULFILLED = 1;
- var REJECTED = 2;
-
- var GET_THEN_ERROR = new ErrorObject();
-
- function getThen(promise) {
- try {
- return promise.then;
- } catch(error) {
- GET_THEN_ERROR.error = error;
- return GET_THEN_ERROR;
- }
- }
-
- function tryThen(then, value, fulfillmentHandler, rejectionHandler) {
- try {
- then.call(value, fulfillmentHandler, rejectionHandler);
- } catch(e) {
- return e;
- }
- }
-
- function handleForeignThenable(promise, thenable, then) {
- config.async(function(promise) {
- var sealed = false;
- var error = tryThen(then, thenable, function(value) {
- if (sealed) { return; }
- sealed = true;
- if (thenable !== value) {
- resolve(promise, value);
- } else {
- fulfill(promise, value);
- }
- }, function(reason) {
- if (sealed) { return; }
- sealed = true;
-
- reject(promise, reason);
- }, 'Settle: ' + (promise._label || ' unknown promise'));
-
- if (!sealed && error) {
- sealed = true;
- reject(promise, error);
- }
- }, promise);
- }
-
- function handleOwnThenable(promise, thenable) {
- if (thenable._state === FULFILLED) {
- fulfill(promise, thenable._result);
- } else if (promise._state === REJECTED) {
- reject(promise, thenable._result);
- } else {
- subscribe(thenable, undefined, function(value) {
- if (thenable !== value) {
- resolve(promise, value);
- } else {
- fulfill(promise, value);
- }
- }, function(reason) {
- reject(promise, reason);
- });
- }
- }
-
- function handleMaybeThenable(promise, maybeThenable) {
- if (maybeThenable.constructor === promise.constructor) {
- handleOwnThenable(promise, maybeThenable);
- } else {
- var then = getThen(maybeThenable);
-
- if (then === GET_THEN_ERROR) {
- reject(promise, GET_THEN_ERROR.error);
- } else if (then === undefined) {
- fulfill(promise, maybeThenable);
- } else if (isFunction(then)) {
- handleForeignThenable(promise, maybeThenable, then);
- } else {
- fulfill(promise, maybeThenable);
- }
- }
- }
-
- function resolve(promise, value) {
- if (promise === value) {
- fulfill(promise, value);
- } else if (objectOrFunction(value)) {
- handleMaybeThenable(promise, value);
- } else {
- fulfill(promise, value);
- }
- }
-
- function publishRejection(promise) {
- if (promise._onerror) {
- promise._onerror(promise._result);
- }
-
- publish(promise);
- }
-
- function fulfill(promise, value) {
- if (promise._state !== PENDING) { return; }
-
- promise._result = value;
- promise._state = FULFILLED;
-
- if (promise._subscribers.length === 0) {
- if (config.instrument) {
- instrument('fulfilled', promise);
- }
- } else {
- config.async(publish, promise);
- }
- }
-
- function reject(promise, reason) {
- if (promise._state !== PENDING) { return; }
- promise._state = REJECTED;
- promise._result = reason;
-
- config.async(publishRejection, promise);
- }
-
- function subscribe(parent, child, onFulfillment, onRejection) {
- var subscribers = parent._subscribers;
- var length = subscribers.length;
-
- parent._onerror = null;
-
- subscribers[length] = child;
- subscribers[length + FULFILLED] = onFulfillment;
- subscribers[length + REJECTED] = onRejection;
-
- if (length === 0 && parent._state) {
- config.async(publish, parent);
- }
- }
-
- function publish(promise) {
- var subscribers = promise._subscribers;
- var settled = promise._state;
-
- if (config.instrument) {
- instrument(settled === FULFILLED ? 'fulfilled' : 'rejected', promise);
- }
-
- if (subscribers.length === 0) { return; }
-
- var child, callback, detail = promise._result;
-
- for (var i = 0; i < subscribers.length; i += 3) {
- child = subscribers[i];
- callback = subscribers[i + settled];
-
- if (child) {
- invokeCallback(settled, child, callback, detail);
- } else {
- callback(detail);
- }
- }
-
- promise._subscribers.length = 0;
- }
-
- function ErrorObject() {
- this.error = null;
- }
-
- var TRY_CATCH_ERROR = new ErrorObject();
-
- function tryCatch(callback, detail) {
- try {
- return callback(detail);
- } catch(e) {
- TRY_CATCH_ERROR.error = e;
- return TRY_CATCH_ERROR;
- }
- }
-
- function invokeCallback(settled, promise, callback, detail) {
- var hasCallback = isFunction(callback),
- value, error, succeeded, failed;
-
- if (hasCallback) {
- value = tryCatch(callback, detail);
-
- if (value === TRY_CATCH_ERROR) {
- failed = true;
- error = value.error;
- value = null;
- } else {
- succeeded = true;
- }
-
- if (promise === value) {
- reject(promise, withOwnPromise());
- return;
- }
-
- } else {
- value = detail;
- succeeded = true;
- }
-
- if (promise._state !== PENDING) {
- // noop
- } else if (hasCallback && succeeded) {
- resolve(promise, value);
- } else if (failed) {
- reject(promise, error);
- } else if (settled === FULFILLED) {
- fulfill(promise, value);
- } else if (settled === REJECTED) {
- reject(promise, value);
- }
- }
-
- function initializePromise(promise, resolver) {
- try {
- resolver(function resolvePromise(value){
- resolve(promise, value);
- }, function rejectPromise(reason) {
- reject(promise, reason);
- });
- } catch(e) {
- reject(promise, e);
- }
- }
-
- __exports__.noop = noop;
- __exports__.resolve = resolve;
- __exports__.reject = reject;
- __exports__.fulfill = fulfill;
- __exports__.subscribe = subscribe;
- __exports__.publish = publish;
- __exports__.publishRejection = publishRejection;
- __exports__.initializePromise = initializePromise;
- __exports__.invokeCallback = invokeCallback;
- __exports__.FULFILLED = FULFILLED;
- __exports__.REJECTED = REJECTED;
- __exports__.PENDING = PENDING;
- });
-enifed("rsvp/all-settled",
- ["./enumerator","./promise","./utils","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
- "use strict";
- var Enumerator = __dependency1__["default"];
- var makeSettledResult = __dependency1__.makeSettledResult;
- var Promise = __dependency2__["default"];
- var o_create = __dependency3__.o_create;
-
- function AllSettled(Constructor, entries, label) {
- this._superConstructor(Constructor, entries, false /* don't abort on reject */, label);
- }
-
- AllSettled.prototype = o_create(Enumerator.prototype);
- AllSettled.prototype._superConstructor = Enumerator;
- AllSettled.prototype._makeResult = makeSettledResult;
- AllSettled.prototype._validationError = function() {
- return new Error('allSettled must be called with an array');
- };
-
- /**
- `RSVP.allSettled` is similar to `RSVP.all`, but instead of implementing
- a fail-fast method, it waits until all the promises have returned and
- shows you all the results. This is useful if you want to handle multiple
- promises' failure states together as a set.
-
- Returns a promise that is fulfilled when all the given promises have been
- settled. The return promise is fulfilled with an array of the states of
- the promises passed into the `promises` array argument.
-
- Each state object will either indicate fulfillment or rejection, and
- provide the corresponding value or reason. The states will take one of
- the following formats:
-
- ```javascript
- { state: 'fulfilled', value: value }
- or
- { state: 'rejected', reason: reason }
- ```
-
- Example:
-
- ```javascript
- var promise1 = RSVP.Promise.resolve(1);
- var promise2 = RSVP.Promise.reject(new Error('2'));
- var promise3 = RSVP.Promise.reject(new Error('3'));
- var promises = [ promise1, promise2, promise3 ];
-
- RSVP.allSettled(promises).then(function(array){
- // array == [
- // { state: 'fulfilled', value: 1 },
- // { state: 'rejected', reason: Error },
- // { state: 'rejected', reason: Error }
- // ]
- // Note that for the second item, reason.message will be '2', and for the
- // third item, reason.message will be '3'.
- }, function(error) {
- // Not run. (This block would only be called if allSettled had failed,
- // for instance if passed an incorrect argument type.)
- });
- ```
-
- @method allSettled
- @static
- @for RSVP
- @param {Array} promises
- @param {String} label - optional string that describes the promise.
- Useful for tooling.
- @return {Promise} promise that is fulfilled with an array of the settled
- states of the constituent promises.
- */
-
- __exports__["default"] = function allSettled(entries, label) {
- return new AllSettled(Promise, entries, label).promise;
- }
- });
-enifed("rsvp/all",
- ["./promise","exports"],
- function(__dependency1__, __exports__) {
- "use strict";
- var Promise = __dependency1__["default"];
-
- /**
- This is a convenient alias for `RSVP.Promise.all`.
-
- @method all
- @static
- @for RSVP
- @param {Array} array Array of promises.
- @param {String} label An optional label. This is useful
- for tooling.
- */
- __exports__["default"] = function all(array, label) {
- return Promise.all(array, label);
- }
- });
-enifed("rsvp/asap",
- ["exports"],
- function(__exports__) {
- "use strict";
- var len = 0;
-
- __exports__["default"] = function asap(callback, arg) {
- queue[len] = callback;
- queue[len + 1] = arg;
- len += 2;
- if (len === 2) {
- // If len is 1, that means that we need to schedule an async flush.
- // If additional callbacks are queued before the queue is flushed, they
- // will be processed by this flush that we are scheduling.
- scheduleFlush();
- }
- }
-
- var browserWindow = (typeof window !== 'undefined') ? window : undefined
- var browserGlobal = browserWindow || {};
- var BrowserMutationObserver = browserGlobal.MutationObserver || browserGlobal.WebKitMutationObserver;
-
- // test for web worker but not in IE10
- var isWorker = typeof Uint8ClampedArray !== 'undefined' &&
- typeof importScripts !== 'undefined' &&
- typeof MessageChannel !== 'undefined';
-
- // node
- function useNextTick() {
- return function() {
- process.nextTick(flush);
- };
- }
-
- // vertx
- function useVertxTimer() {
- return function() {
- vertxNext(flush);
- };
- }
-
- function useMutationObserver() {
- var iterations = 0;
- var observer = new BrowserMutationObserver(flush);
- var node = document.createTextNode('');
- observer.observe(node, { characterData: true });
-
- return function() {
- node.data = (iterations = ++iterations % 2);
- };
- }
-
- // web worker
- function useMessageChannel() {
- var channel = new MessageChannel();
- channel.port1.onmessage = flush;
- return function () {
- channel.port2.postMessage(0);
- };
- }
-
- function useSetTimeout() {
- return function() {
- setTimeout(flush, 1);
- };
- }
-
- var queue = new Array(1000);
- function flush() {
- for (var i = 0; i < len; i+=2) {
- var callback = queue[i];
- var arg = queue[i+1];
-
- callback(arg);
-
- queue[i] = undefined;
- queue[i+1] = undefined;
- }
-
- len = 0;
- }
-
- function attemptVertex() {
- try {
- var vertx = eriuqer('vertx');
- var vertxNext = vertx.runOnLoop || vertx.runOnContext;
- return useVertxTimer();
- } catch(e) {
- return useSetTimeout();
- }
- }
-
- var scheduleFlush;
- // Decide what async method to use to triggering processing of queued callbacks:
- if (typeof process !== 'undefined' && {}.toString.call(process) === '[object process]') {
- scheduleFlush = useNextTick();
- } else if (BrowserMutationObserver) {
- scheduleFlush = useMutationObserver();
- } else if (isWorker) {
- scheduleFlush = useMessageChannel();
- } else if (browserWindow === undefined && typeof eriuqer === 'function') {
- scheduleFlush = attemptVertex();
- } else {
- scheduleFlush = useSetTimeout();
- }
- });
-enifed("rsvp/config",
- ["./events","exports"],
- function(__dependency1__, __exports__) {
- "use strict";
- var EventTarget = __dependency1__["default"];
-
- var config = {
- instrument: false
- };
-
- EventTarget.mixin(config);
-
- function configure(name, value) {
- if (name === 'onerror') {
- // handle for legacy users that expect the actual
- // error to be passed to their function added via
- // `RSVP.configure('onerror', someFunctionHere);`
- config.on('error', value);
- return;
- }
-
- if (arguments.length === 2) {
- config[name] = value;
- } else {
- return config[name];
- }
- }
-
- __exports__.config = config;
- __exports__.configure = configure;
- });
-enifed("rsvp/defer",
- ["./promise","exports"],
- function(__dependency1__, __exports__) {
- "use strict";
- var Promise = __dependency1__["default"];
-
- /**
- `RSVP.defer` returns an object similar to jQuery's `$.Deferred`.
- `RSVP.defer` should be used when porting over code reliant on `$.Deferred`'s
- interface. New code should use the `RSVP.Promise` constructor instead.
-
- The object returned from `RSVP.defer` is a plain object with three properties:
-
- * promise - an `RSVP.Promise`.
- * reject - a function that causes the `promise` property on this object to
- become rejected
- * resolve - a function that causes the `promise` property on this object to
- become fulfilled.
-
- Example:
-
- ```javascript
- var deferred = RSVP.defer();
-
- deferred.resolve("Success!");
-
- defered.promise.then(function(value){
- // value here is "Success!"
- });
- ```
-
- @method defer
- @static
- @for RSVP
- @param {String} label optional string for labeling the promise.
- Useful for tooling.
- @return {Object}
- */
-
- __exports__["default"] = function defer(label) {
- var deferred = { };
-
- deferred['promise'] = new Promise(function(resolve, reject) {
- deferred['resolve'] = resolve;
- deferred['reject'] = reject;
- }, label);
-
- return deferred;
- }
- });
-enifed("rsvp/enumerator",
- ["./utils","./-internal","exports"],
- function(__dependency1__, __dependency2__, __exports__) {
- "use strict";
- var isArray = __dependency1__.isArray;
- var isMaybeThenable = __dependency1__.isMaybeThenable;
-
- var noop = __dependency2__.noop;
- var reject = __dependency2__.reject;
- var fulfill = __dependency2__.fulfill;
- var subscribe = __dependency2__.subscribe;
- var FULFILLED = __dependency2__.FULFILLED;
- var REJECTED = __dependency2__.REJECTED;
- var PENDING = __dependency2__.PENDING;
-
- function makeSettledResult(state, position, value) {
- if (state === FULFILLED) {
- return {
- state: 'fulfilled',
- value: value
- };
- } else {
- return {
- state: 'rejected',
- reason: value
- };
- }
- }
-
- __exports__.makeSettledResult = makeSettledResult;function Enumerator(Constructor, input, abortOnReject, label) {
- this._instanceConstructor = Constructor;
- this.promise = new Constructor(noop, label);
- this._abortOnReject = abortOnReject;
-
- if (this._validateInput(input)) {
- this._input = input;
- this.length = input.length;
- this._remaining = input.length;
-
- this._init();
-
- if (this.length === 0) {
- fulfill(this.promise, this._result);
- } else {
- this.length = this.length || 0;
- this._enumerate();
- if (this._remaining === 0) {
- fulfill(this.promise, this._result);
- }
- }
- } else {
- reject(this.promise, this._validationError());
- }
- }
-
- Enumerator.prototype._validateInput = function(input) {
- return isArray(input);
- };
-
- Enumerator.prototype._validationError = function() {
- return new Error('Array Methods must be provided an Array');
- };
-
- Enumerator.prototype._init = function() {
- this._result = new Array(this.length);
- };
-
- __exports__["default"] = Enumerator;
-
- Enumerator.prototype._enumerate = function() {
- var length = this.length;
- var promise = this.promise;
- var input = this._input;
-
- for (var i = 0; promise._state === PENDING && i < length; i++) {
- this._eachEntry(input[i], i);
- }
- };
-
- Enumerator.prototype._eachEntry = function(entry, i) {
- var c = this._instanceConstructor;
- if (isMaybeThenable(entry)) {
- if (entry.constructor === c && entry._state !== PENDING) {
- entry._onerror = null;
- this._settledAt(entry._state, i, entry._result);
- } else {
- this._willSettleAt(c.resolve(entry), i);
- }
- } else {
- this._remaining--;
- this._result[i] = this._makeResult(FULFILLED, i, entry);
- }
- };
-
- Enumerator.prototype._settledAt = function(state, i, value) {
- var promise = this.promise;
-
- if (promise._state === PENDING) {
- this._remaining--;
-
- if (this._abortOnReject && state === REJECTED) {
- reject(promise, value);
- } else {
- this._result[i] = this._makeResult(state, i, value);
- }
- }
-
- if (this._remaining === 0) {
- fulfill(promise, this._result);
- }
- };
-
- Enumerator.prototype._makeResult = function(state, i, value) {
- return value;
- };
-
- Enumerator.prototype._willSettleAt = function(promise, i) {
- var enumerator = this;
-
- subscribe(promise, undefined, function(value) {
- enumerator._settledAt(FULFILLED, i, value);
- }, function(reason) {
- enumerator._settledAt(REJECTED, i, reason);
- });
- };
- });
-enifed("rsvp/events",
- ["exports"],
- function(__exports__) {
- "use strict";
- function indexOf(callbacks, callback) {
- for (var i=0, l=callbacks.length; i<l; i++) {
- if (callbacks[i] === callback) { return i; }
- }
-
- return -1;
- }
-
- function callbacksFor(object) {
- var callbacks = object._promiseCallbacks;
-
- if (!callbacks) {
- callbacks = object._promiseCallbacks = {};
- }
-
- return callbacks;
- }
-
- /**
- @class RSVP.EventTarget
- */
- __exports__["default"] = {
-
- /**
- `RSVP.EventTarget.mixin` extends an object with EventTarget methods. For
- Example:
-
- ```javascript
- var object = {};
-
- RSVP.EventTarget.mixin(object);
-
- object.on('finished', function(event) {
- // handle event
- });
-
- object.trigger('finished', { detail: value });
- ```
-
- `EventTarget.mixin` also works with prototypes:
-
- ```javascript
- var Person = function() {};
- RSVP.EventTarget.mixin(Person.prototype);
-
- var yehuda = new Person();
- var tom = new Person();
-
- yehuda.on('poke', function(event) {
- console.log('Yehuda says OW');
- });
-
- tom.on('poke', function(event) {
- console.log('Tom says OW');
- });
-
- yehuda.trigger('poke');
- tom.trigger('poke');
- ```
-
- @method mixin
- @for RSVP.EventTarget
- @private
- @param {Object} object object to extend with EventTarget methods
- */
- mixin: function(object) {
- object.on = this.on;
- object.off = this.off;
- object.trigger = this.trigger;
- object._promiseCallbacks = undefined;
- return object;
- },
-
- /**
- Registers a callback to be executed when `eventName` is triggered
-
- ```javascript
- object.on('event', function(eventInfo){
- // handle the event
- });
-
- object.trigger('event');
- ```
-
- @method on
- @for RSVP.EventTarget
- @private
- @param {String} eventName name of the event to listen for
- @param {Function} callback function to be called when the event is triggered.
- */
- on: function(eventName, callback) {
- var allCallbacks = callbacksFor(this), callbacks;
-
- callbacks = allCallbacks[eventName];
-
- if (!callbacks) {
- callbacks = allCallbacks[eventName] = [];
- }
-
- if (indexOf(callbacks, callback) === -1) {
- callbacks.push(callback);
- }
- },
-
- /**
- You can use `off` to stop firing a particular callback for an event:
-
- ```javascript
- function doStuff() { // do stuff! }
- object.on('stuff', doStuff);
-
- object.trigger('stuff'); // doStuff will be called
-
- // Unregister ONLY the doStuff callback
- object.off('stuff', doStuff);
- object.trigger('stuff'); // doStuff will NOT be called
- ```
-
- If you don't pass a `callback` argument to `off`, ALL callbacks for the
- event will not be executed when the event fires. For example:
-
- ```javascript
- var callback1 = function(){};
- var callback2 = function(){};
-
- object.on('stuff', callback1);
- object.on('stuff', callback2);
-
- object.trigger('stuff'); // callback1 and callback2 will be executed.
-
- object.off('stuff');
- object.trigger('stuff'); // callback1 and callback2 will not be executed!
- ```
-
- @method off
- @for RSVP.EventTarget
- @private
- @param {String} eventName event to stop listening to
- @param {Function} callback optional argument. If given, only the function
- given will be removed from the event's callback queue. If no `callback`
- argument is given, all callbacks will be removed from the event's callback
- queue.
- */
- off: function(eventName, callback) {
- var allCallbacks = callbacksFor(this), callbacks, index;
-
- if (!callback) {
- allCallbacks[eventName] = [];
- return;
- }
-
- callbacks = allCallbacks[eventName];
-
- index = indexOf(callbacks, callback);
-
- if (index !== -1) { callbacks.splice(index, 1); }
- },
-
- /**
- Use `trigger` to fire custom events. For example:
-
- ```javascript
- object.on('foo', function(){
- console.log('foo event happened!');
- });
- object.trigger('foo');
- // 'foo event happened!' logged to the console
- ```
-
- You can also pass a value as a second argument to `trigger` that will be
- passed as an argument to all event listeners for the event:
-
- ```javascript
- object.on('foo', function(value){
- console.log(value.name);
- });
-
- object.trigger('foo', { name: 'bar' });
- // 'bar' logged to the console
- ```
-
- @method trigger
- @for RSVP.EventTarget
- @private
- @param {String} eventName name of the event to be triggered
- @param {Any} options optional value to be passed to any event handlers for
- the given `eventName`
- */
- trigger: function(eventName, options) {
- var allCallbacks = callbacksFor(this), callbacks, callback;
-
- if (callbacks = allCallbacks[eventName]) {
- // Don't cache the callbacks.length since it may grow
- for (var i=0; i<callbacks.length; i++) {
- callback = callbacks[i];
-
- callback(options);
- }
- }
- }
- };
- });
-enifed("rsvp/filter",
- ["./promise","./utils","exports"],
- function(__dependency1__, __dependency2__, __exports__) {
- "use strict";
- var Promise = __dependency1__["default"];
- var isFunction = __dependency2__.isFunction;
-
- /**
- `RSVP.filter` is similar to JavaScript's native `filter` method, except that it
- waits for all promises to become fulfilled before running the `filterFn` on
- each item in given to `promises`. `RSVP.filter` returns a promise that will
- become fulfilled with the result of running `filterFn` on the values the
- promises become fulfilled with.
-
- For example:
-
- ```javascript
-
- var promise1 = RSVP.resolve(1);
- var promise2 = RSVP.resolve(2);
- var promise3 = RSVP.resolve(3);
-
- var promises = [promise1, promise2, promise3];
-
- var filterFn = function(item){
- return item > 1;
- };
-
- RSVP.filter(promises, filterFn).then(function(result){
- // result is [ 2, 3 ]
- });
- ```
-
- If any of the `promises` given to `RSVP.filter` are rejected, the first promise
- that is rejected will be given as an argument to the returned promise's
- rejection handler. For example:
-
- ```javascript
- var promise1 = RSVP.resolve(1);
- var promise2 = RSVP.reject(new Error('2'));
- var promise3 = RSVP.reject(new Error('3'));
- var promises = [ promise1, promise2, promise3 ];
-
- var filterFn = function(item){
- return item > 1;
- };
-
- RSVP.filter(promises, filterFn).then(function(array){
- // Code here never runs because there are rejected promises!
- }, function(reason) {
- // reason.message === '2'
- });
- ```
-
- `RSVP.filter` will also wait for any promises returned from `filterFn`.
- For instance, you may want to fetch a list of users then return a subset
- of those users based on some asynchronous operation:
-
- ```javascript
-
- var alice = { name: 'alice' };
- var bob = { name: 'bob' };
- var users = [ alice, bob ];
-
- var promises = users.map(function(user){
- return RSVP.resolve(user);
- });
-
- var filterFn = function(user){
- // Here, Alice has permissions to create a blog post, but Bob does not.
- return getPrivilegesForUser(user).then(function(privs){
- return privs.can_create_blog_post === true;
- });
- };
- RSVP.filter(promises, filterFn).then(function(users){
- // true, because the server told us only Alice can create a blog post.
- users.length === 1;
- // false, because Alice is the only user present in `users`
- users[0] === bob;
- });
- ```
-
- @method filter
- @static
- @for RSVP
- @param {Array} promises
- @param {Function} filterFn - function to be called on each resolved value to
- filter the final results.
- @param {String} label optional string describing the promise. Useful for
- tooling.
- @return {Promise}
- */
- __exports__["default"] = function filter(promises, filterFn, label) {
- return Promise.all(promises, label).then(function(values) {
- if (!isFunction(filterFn)) {
- throw new TypeError("You must pass a function as filter's second argument.");
- }
-
- var length = values.length;
- var filtered = new Array(length);
-
- for (var i = 0; i < length; i++) {
- filtered[i] = filterFn(values[i]);
- }
-
- return Promise.all(filtered, label).then(function(filtered) {
- var results = new Array(length);
- var newLength = 0;
-
- for (var i = 0; i < length; i++) {
- if (filtered[i]) {
- results[newLength] = values[i];
- newLength++;
- }
- }
-
- results.length = newLength;
-
- return results;
- });
- });
- }
- });
-enifed("rsvp/hash-settled",
- ["./promise","./enumerator","./promise-hash","./utils","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
- "use strict";
- var Promise = __dependency1__["default"];
- var makeSettledResult = __dependency2__.makeSettledResult;
- var PromiseHash = __dependency3__["default"];
- var Enumerator = __dependency2__["default"];
- var o_create = __dependency4__.o_create;
-
- function HashSettled(Constructor, object, label) {
- this._superConstructor(Constructor, object, false, label);
- }
-
- HashSettled.prototype = o_create(PromiseHash.prototype);
- HashSettled.prototype._superConstructor = Enumerator;
- HashSettled.prototype._makeResult = makeSettledResult;
-
- HashSettled.prototype._validationError = function() {
- return new Error('hashSettled must be called with an object');
- };
-
- /**
- `RSVP.hashSettled` is similar to `RSVP.allSettled`, but takes an object
- instead of an array for its `promises` argument.
-
- Unlike `RSVP.all` or `RSVP.hash`, which implement a fail-fast method,
- but like `RSVP.allSettled`, `hashSettled` waits until all the
- constituent promises have returned and then shows you all the results
- with their states and values/reasons. This is useful if you want to
- handle multiple promises' failure states together as a set.
-
- Returns a promise that is fulfilled when all the given promises have been
- settled, or rejected if the passed parameters are invalid.
-
- The returned promise is fulfilled with a hash that has the same key names as
- the `promises` object argument. If any of the values in the object are not
- promises, they will be copied over to the fulfilled object and marked with state
- 'fulfilled'.
-
- Example:
-
- ```javascript
- var promises = {
- myPromise: RSVP.Promise.resolve(1),
- yourPromise: RSVP.Promise.resolve(2),
- theirPromise: RSVP.Promise.resolve(3),
- notAPromise: 4
- };
-
- RSVP.hashSettled(promises).then(function(hash){
- // hash here is an object that looks like:
- // {
- // myPromise: { state: 'fulfilled', value: 1 },
- // yourPromise: { state: 'fulfilled', value: 2 },
- // theirPromise: { state: 'fulfilled', value: 3 },
- // notAPromise: { state: 'fulfilled', value: 4 }
- // }
- });
- ```
-
- If any of the `promises` given to `RSVP.hash` are rejected, the state will
- be set to 'rejected' and the reason for rejection provided.
-
- Example:
-
- ```javascript
- var promises = {
- myPromise: RSVP.Promise.resolve(1),
- rejectedPromise: RSVP.Promise.reject(new Error('rejection')),
- anotherRejectedPromise: RSVP.Promise.reject(new Error('more rejection')),
- };
-
- RSVP.hashSettled(promises).then(function(hash){
- // hash here is an object that looks like:
- // {
- // myPromise: { state: 'fulfilled', value: 1 },
- // rejectedPromise: { state: 'rejected', reason: Error },
- // anotherRejectedPromise: { state: 'rejected', reason: Error },
- // }
- // Note that for rejectedPromise, reason.message == 'rejection',
- // and for anotherRejectedPromise, reason.message == 'more rejection'.
- });
- ```
-
- An important note: `RSVP.hashSettled` is intended for plain JavaScript objects that
- are just a set of keys and values. `RSVP.hashSettled` will NOT preserve prototype
- chains.
-
- Example:
-
- ```javascript
- function MyConstructor(){
- this.example = RSVP.Promise.resolve('Example');
- }
-
- MyConstructor.prototype = {
- protoProperty: RSVP.Promise.resolve('Proto Property')
- };
-
- var myObject = new MyConstructor();
-
- RSVP.hashSettled(myObject).then(function(hash){
- // protoProperty will not be present, instead you will just have an
- // object that looks like:
- // {
- // example: { state: 'fulfilled', value: 'Example' }
- // }
- //
- // hash.hasOwnProperty('protoProperty'); // false
- // 'undefined' === typeof hash.protoProperty
- });
- ```
-
- @method hashSettled
- @for RSVP
- @param {Object} promises
- @param {String} label optional string that describes the promise.
- Useful for tooling.
- @return {Promise} promise that is fulfilled when when all properties of `promises`
- have been settled.
- @static
- */
- __exports__["default"] = function hashSettled(object, label) {
- return new HashSettled(Promise, object, label).promise;
- }
- });
-enifed("rsvp/hash",
- ["./promise","./promise-hash","exports"],
- function(__dependency1__, __dependency2__, __exports__) {
- "use strict";
- var Promise = __dependency1__["default"];
- var PromiseHash = __dependency2__["default"];
-
- /**
- `RSVP.hash` is similar to `RSVP.all`, but takes an object instead of an array
- for its `promises` argument.
-
- Returns a promise that is fulfilled when all the given promises have been
- fulfilled, or rejected if any of them become rejected. The returned promise
- is fulfilled with a hash that has the same key names as the `promises` object
- argument. If any of the values in the object are not promises, they will
- simply be copied over to the fulfilled object.
-
- Example:
-
- ```javascript
- var promises = {
- myPromise: RSVP.resolve(1),
- yourPromise: RSVP.resolve(2),
- theirPromise: RSVP.resolve(3),
- notAPromise: 4
- };
-
- RSVP.hash(promises).then(function(hash){
- // hash here is an object that looks like:
- // {
- // myPromise: 1,
- // yourPromise: 2,
- // theirPromise: 3,
- // notAPromise: 4
- // }
- });
- ````
-
- If any of the `promises` given to `RSVP.hash` are rejected, the first promise
- that is rejected will be given as the reason to the rejection handler.
-
- Example:
-
- ```javascript
- var promises = {
- myPromise: RSVP.resolve(1),
- rejectedPromise: RSVP.reject(new Error('rejectedPromise')),
- anotherRejectedPromise: RSVP.reject(new Error('anotherRejectedPromise')),
- };
-
- RSVP.hash(promises).then(function(hash){
- // Code here never runs because there are rejected promises!
- }, function(reason) {
- // reason.message === 'rejectedPromise'
- });
- ```
-
- An important note: `RSVP.hash` is intended for plain JavaScript objects that
- are just a set of keys and values. `RSVP.hash` will NOT preserve prototype
- chains.
-
- Example:
-
- ```javascript
- function MyConstructor(){
- this.example = RSVP.resolve('Example');
- }
-
- MyConstructor.prototype = {
- protoProperty: RSVP.resolve('Proto Property')
- };
-
- var myObject = new MyConstructor();
-
- RSVP.hash(myObject).then(function(hash){
- // protoProperty will not be present, instead you will just have an
- // object that looks like:
- // {
- // example: 'Example'
- // }
- //
- // hash.hasOwnProperty('protoProperty'); // false
- // 'undefined' === typeof hash.protoProperty
- });
- ```
-
- @method hash
- @static
- @for RSVP
- @param {Object} promises
- @param {String} label optional string that describes the promise.
- Useful for tooling.
- @return {Promise} promise that is fulfilled when all properties of `promises`
- have been fulfilled, or rejected if any of them become rejected.
- */
- __exports__["default"] = function hash(object, label) {
- return new PromiseHash(Promise, object, label).promise;
- }
- });
-enifed("rsvp/instrument",
- ["./config","./utils","exports"],
- function(__dependency1__, __dependency2__, __exports__) {
- "use strict";
- var config = __dependency1__.config;
- var now = __dependency2__.now;
-
- var queue = [];
-
- function scheduleFlush() {
- setTimeout(function() {
- var entry;
- for (var i = 0; i < queue.length; i++) {
- entry = queue[i];
-
- var payload = entry.payload;
-
- payload.guid = payload.key + payload.id;
- payload.childGuid = payload.key + payload.childId;
- if (payload.error) {
- payload.stack = payload.error.stack;
- }
-
- config.trigger(entry.name, entry.payload);
- }
- queue.length = 0;
- }, 50);
- }
-
- __exports__["default"] = function instrument(eventName, promise, child) {
- if (1 === queue.push({
- name: eventName,
- payload: {
- key: promise._guidKey,
- id: promise._id,
- eventName: eventName,
- detail: promise._result,
- childId: child && child._id,
- label: promise._label,
- timeStamp: now(),
- error: config["instrument-with-stack"] ? new Error(promise._label) : null
- }})) {
- scheduleFlush();
- }
- }
- });
-enifed("rsvp/map",
- ["./promise","./utils","exports"],
- function(__dependency1__, __dependency2__, __exports__) {
- "use strict";
- var Promise = __dependency1__["default"];
- var isFunction = __dependency2__.isFunction;
-
- /**
- `RSVP.map` is similar to JavaScript's native `map` method, except that it
- waits for all promises to become fulfilled before running the `mapFn` on
- each item in given to `promises`. `RSVP.map` returns a promise that will
- become fulfilled with the result of running `mapFn` on the values the promises
- become fulfilled with.
-
- For example:
-
- ```javascript
-
- var promise1 = RSVP.resolve(1);
- var promise2 = RSVP.resolve(2);
- var promise3 = RSVP.resolve(3);
- var promises = [ promise1, promise2, promise3 ];
-
- var mapFn = function(item){
- return item + 1;
- };
-
- RSVP.map(promises, mapFn).then(function(result){
- // result is [ 2, 3, 4 ]
- });
- ```
-
- If any of the `promises` given to `RSVP.map` are rejected, the first promise
- that is rejected will be given as an argument to the returned promise's
- rejection handler. For example:
-
- ```javascript
- var promise1 = RSVP.resolve(1);
- var promise2 = RSVP.reject(new Error('2'));
- var promise3 = RSVP.reject(new Error('3'));
- var promises = [ promise1, promise2, promise3 ];
-
- var mapFn = function(item){
- return item + 1;
- };
-
- RSVP.map(promises, mapFn).then(function(array){
- // Code here never runs because there are rejected promises!
- }, function(reason) {
- // reason.message === '2'
- });
- ```
-
- `RSVP.map` will also wait if a promise is returned from `mapFn`. For example,
- say you want to get all comments from a set of blog posts, but you need
- the blog posts first because they contain a url to those comments.
-
- ```javscript
-
- var mapFn = function(blogPost){
- // getComments does some ajax and returns an RSVP.Promise that is fulfilled
- // with some comments data
- return getComments(blogPost.comments_url);
- };
-
- // getBlogPosts does some ajax and returns an RSVP.Promise that is fulfilled
- // with some blog post data
- RSVP.map(getBlogPosts(), mapFn).then(function(comments){
- // comments is the result of asking the server for the comments
- // of all blog posts returned from getBlogPosts()
- });
- ```
-
- @method map
- @static
- @for RSVP
- @param {Array} promises
- @param {Function} mapFn function to be called on each fulfilled promise.
- @param {String} label optional string for labeling the promise.
- Useful for tooling.
- @return {Promise} promise that is fulfilled with the result of calling
- `mapFn` on each fulfilled promise or value when they become fulfilled.
- The promise will be rejected if any of the given `promises` become rejected.
- @static
- */
- __exports__["default"] = function map(promises, mapFn, label) {
- return Promise.all(promises, label).then(function(values) {
- if (!isFunction(mapFn)) {
- throw new TypeError("You must pass a function as map's second argument.");
- }
-
- var length = values.length;
- var results = new Array(length);
-
- for (var i = 0; i < length; i++) {
- results[i] = mapFn(values[i]);
- }
-
- return Promise.all(results, label);
- });
- }
- });
-enifed("rsvp/node",
- ["./promise","./-internal","./utils","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
- "use strict";
- var Promise = __dependency1__["default"];
- var noop = __dependency2__.noop;
- var resolve = __dependency2__.resolve;
- var reject = __dependency2__.reject;
- var isArray = __dependency3__.isArray;
-
- function Result() {
- this.value = undefined;
- }
-
- var ERROR = new Result();
- var GET_THEN_ERROR = new Result();
-
- function getThen(obj) {
- try {
- return obj.then;
- } catch(error) {
- ERROR.value= error;
- return ERROR;
- }
- }
-
-
- function tryApply(f, s, a) {
- try {
- f.apply(s, a);
- } catch(error) {
- ERROR.value = error;
- return ERROR;
- }
- }
-
- function makeObject(_, argumentNames) {
- var obj = {};
- var name;
- var i;
- var length = _.length;
- var args = new Array(length);
-
- for (var x = 0; x < length; x++) {
- args[x] = _[x];
- }
-
- for (i = 0; i < argumentNames.length; i++) {
- name = argumentNames[i];
- obj[name] = args[i + 1];
- }
-
- return obj;
- }
-
- function arrayResult(_) {
- var length = _.length;
- var args = new Array(length - 1);
-
- for (var i = 1; i < length; i++) {
- args[i - 1] = _[i];
- }
-
- return args;
- }
-
- function wrapThenable(then, promise) {
- return {
- then: function(onFulFillment, onRejection) {
- return then.call(promise, onFulFillment, onRejection);
- }
- };
- }
-
- /**
- `RSVP.denodeify` takes a 'node-style' function and returns a function that
- will return an `RSVP.Promise`. You can use `denodeify` in Node.js or the
- browser when you'd prefer to use promises over using callbacks. For example,
- `denodeify` transforms the following:
-
- ```javascript
- var fs = require('fs');
-
- fs.readFile('myfile.txt', function(err, data){
- if (err) return handleError(err);
- handleData(data);
- });
- ```
-
- into:
-
- ```javascript
- var fs = require('fs');
- var readFile = RSVP.denodeify(fs.readFile);
-
- readFile('myfile.txt').then(handleData, handleError);
- ```
-
- If the node function has multiple success parameters, then `denodeify`
- just returns the first one:
-
- ```javascript
- var request = RSVP.denodeify(require('request'));
-
- request('http://example.com').then(function(res) {
- // ...
- });
- ```
-
- However, if you need all success parameters, setting `denodeify`'s
- second parameter to `true` causes it to return all success parameters
- as an array:
-
- ```javascript
- var request = RSVP.denodeify(require('request'), true);
-
- request('http://example.com').then(function(result) {
- // result[0] -> res
- // result[1] -> body
- });
- ```
-
- Or if you pass it an array with names it returns the parameters as a hash:
-
- ```javascript
- var request = RSVP.denodeify(require('request'), ['res', 'body']);
-
- request('http://example.com').then(function(result) {
- // result.res
- // result.body
- });
- ```
-
- Sometimes you need to retain the `this`:
-
- ```javascript
- var app = require('express')();
- var render = RSVP.denodeify(app.render.bind(app));
- ```
-
- The denodified function inherits from the original function. It works in all
- environments, except IE 10 and below. Consequently all properties of the original
- function are available to you. However, any properties you change on the
- denodeified function won't be changed on the original function. Example:
-
- ```javascript
- var request = RSVP.denodeify(require('request')),
- cookieJar = request.jar(); // <- Inheritance is used here
-
- request('http://example.com', {jar: cookieJar}).then(function(res) {
- // cookieJar.cookies holds now the cookies returned by example.com
- });
- ```
-
- Using `denodeify` makes it easier to compose asynchronous operations instead
- of using callbacks. For example, instead of:
-
- ```javascript
- var fs = require('fs');
-
- fs.readFile('myfile.txt', function(err, data){
- if (err) { ... } // Handle error
- fs.writeFile('myfile2.txt', data, function(err){
- if (err) { ... } // Handle error
- console.log('done')
- });
- });
- ```
-
- you can chain the operations together using `then` from the returned promise:
-
- ```javascript
- var fs = require('fs');
- var readFile = RSVP.denodeify(fs.readFile);
- var writeFile = RSVP.denodeify(fs.writeFile);
-
- readFile('myfile.txt').then(function(data){
- return writeFile('myfile2.txt', data);
- }).then(function(){
- console.log('done')
- }).catch(function(error){
- // Handle error
- });
- ```
-
- @method denodeify
- @static
- @for RSVP
- @param {Function} nodeFunc a 'node-style' function that takes a callback as
- its last argument. The callback expects an error to be passed as its first
- argument (if an error occurred, otherwise null), and the value from the
- operation as its second argument ('function(err, value){ }').
- @param {Boolean|Array} argumentNames An optional paramter that if set
- to `true` causes the promise to fulfill with the callback's success arguments
- as an array. This is useful if the node function has multiple success
- paramters. If you set this paramter to an array with names, the promise will
- fulfill with a hash with these names as keys and the success parameters as
- values.
- @return {Function} a function that wraps `nodeFunc` to return an
- `RSVP.Promise`
- @static
- */
- __exports__["default"] = function denodeify(nodeFunc, options) {
- var fn = function() {
- var self = this;
- var l = arguments.length;
- var args = new Array(l + 1);
- var arg;
- var promiseInput = false;
-
- for (var i = 0; i < l; ++i) {
- arg = arguments[i];
-
- if (!promiseInput) {
- // TODO: clean this up
- promiseInput = needsPromiseInput(arg);
- if (promiseInput === GET_THEN_ERROR) {
- var p = new Promise(noop);
- reject(p, GET_THEN_ERROR.value);
- return p;
- } else if (promiseInput && promiseInput !== true) {
- arg = wrapThenable(promiseInput, arg);
- }
- }
- args[i] = arg;
- }
-
- var promise = new Promise(noop);
-
- args[l] = function(err, val) {
- if (err)
- reject(promise, err);
- else if (options === undefined)
- resolve(promise, val);
- else if (options === true)
- resolve(promise, arrayResult(arguments));
- else if (isArray(options))
- resolve(promise, makeObject(arguments, options));
- else
- resolve(promise, val);
- };
-
- if (promiseInput) {
- return handlePromiseInput(promise, args, nodeFunc, self);
- } else {
- return handleValueInput(promise, args, nodeFunc, self);
- }
- };
-
- fn.__proto__ = nodeFunc;
-
- return fn;
- }
-
- function handleValueInput(promise, args, nodeFunc, self) {
- var result = tryApply(nodeFunc, self, args);
- if (result === ERROR) {
- reject(promise, result.value);
- }
- return promise;
- }
-
- function handlePromiseInput(promise, args, nodeFunc, self){
- return Promise.all(args).then(function(args){
- var result = tryApply(nodeFunc, self, args);
- if (result === ERROR) {
- reject(promise, result.value);
- }
- return promise;
- });
- }
-
- function needsPromiseInput(arg) {
- if (arg && typeof arg === 'object') {
- if (arg.constructor === Promise) {
- return true;
- } else {
- return getThen(arg);
- }
- } else {
- return false;
- }
- }
- });
-enifed("rsvp/promise-hash",
- ["./enumerator","./-internal","./utils","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
- "use strict";
- var Enumerator = __dependency1__["default"];
- var PENDING = __dependency2__.PENDING;
- var o_create = __dependency3__.o_create;
-
- function PromiseHash(Constructor, object, label) {
- this._superConstructor(Constructor, object, true, label);
- }
-
- __exports__["default"] = PromiseHash;
-
- PromiseHash.prototype = o_create(Enumerator.prototype);
- PromiseHash.prototype._superConstructor = Enumerator;
- PromiseHash.prototype._init = function() {
- this._result = {};
- };
-
- PromiseHash.prototype._validateInput = function(input) {
- return input && typeof input === 'object';
- };
-
- PromiseHash.prototype._validationError = function() {
- return new Error('Promise.hash must be called with an object');
- };
-
- PromiseHash.prototype._enumerate = function() {
- var promise = this.promise;
- var input = this._input;
- var results = [];
-
- for (var key in input) {
- if (promise._state === PENDING && input.hasOwnProperty(key)) {
- results.push({
- position: key,
- entry: input[key]
- });
- }
- }
-
- var length = results.length;
- this._remaining = length;
- var result;
-
- for (var i = 0; promise._state === PENDING && i < length; i++) {
- result = results[i];
- this._eachEntry(result.entry, result.position);
- }
- };
- });
-enifed("rsvp/promise",
- ["./config","./instrument","./utils","./-internal","./promise/all","./promise/race","./promise/resolve","./promise/reject","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __exports__) {
- "use strict";
- var config = __dependency1__.config;
- var instrument = __dependency2__["default"];
-
- var isFunction = __dependency3__.isFunction;
- var now = __dependency3__.now;
-
- var noop = __dependency4__.noop;
- var subscribe = __dependency4__.subscribe;
- var initializePromise = __dependency4__.initializePromise;
- var invokeCallback = __dependency4__.invokeCallback;
- var FULFILLED = __dependency4__.FULFILLED;
- var REJECTED = __dependency4__.REJECTED;
-
- var all = __dependency5__["default"];
- var race = __dependency6__["default"];
- var Resolve = __dependency7__["default"];
- var Reject = __dependency8__["default"];
-
- var guidKey = 'rsvp_' + now() + '-';
- var counter = 0;
-
- function needsResolver() {
- throw new TypeError('You must pass a resolver function as the first argument to the promise constructor');
- }
-
- function needsNew() {
- throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.");
- }
- __exports__["default"] = Promise;
- /**
- Promise objects represent the eventual result of an asynchronous operation. The
- primary way of interacting with a promise is through its `then` method, which
- registers callbacks to receive either a promise’s eventual value or the reason
- why the promise cannot be fulfilled.
-
- Terminology
- -----------
-
- - `promise` is an object or function with a `then` method whose behavior conforms to this specification.
- - `thenable` is an object or function that defines a `then` method.
- - `value` is any legal JavaScript value (including undefined, a thenable, or a promise).
- - `exception` is a value that is thrown using the throw statement.
- - `reason` is a value that indicates why a promise was rejected.
- - `settled` the final resting state of a promise, fulfilled or rejected.
-
- A promise can be in one of three states: pending, fulfilled, or rejected.
-
- Promises that are fulfilled have a fulfillment value and are in the fulfilled
- state. Promises that are rejected have a rejection reason and are in the
- rejected state. A fulfillment value is never a thenable.
-
- Promises can also be said to *resolve* a value. If this value is also a
- promise, then the original promise's settled state will match the value's
- settled state. So a promise that *resolves* a promise that rejects will
- itself reject, and a promise that *resolves* a promise that fulfills will
- itself fulfill.
-
-
- Basic Usage:
- ------------
-
- ```js
- var promise = new Promise(function(resolve, reject) {
- // on success
- resolve(value);
-
- // on failure
- reject(reason);
- });
-
- promise.then(function(value) {
- // on fulfillment
- }, function(reason) {
- // on rejection
- });
- ```
-
- Advanced Usage:
- ---------------
-
- Promises shine when abstracting away asynchronous interactions such as
- `XMLHttpRequest`s.
-
- ```js
- function getJSON(url) {
- return new Promise(function(resolve, reject){
- var xhr = new XMLHttpRequest();
-
- xhr.open('GET', url);
- xhr.onreadystatechange = handler;
- xhr.responseType = 'json';
- xhr.setRequestHeader('Accept', 'application/json');
- xhr.send();
-
- function handler() {
- if (this.readyState === this.DONE) {
- if (this.status === 200) {
- resolve(this.response);
- } else {
- reject(new Error('getJSON: `' + url + '` failed with status: [' + this.status + ']'));
- }
- }
- };
- });
- }
-
- getJSON('/posts.json').then(function(json) {
- // on fulfillment
- }, function(reason) {
- // on rejection
- });
- ```
-
- Unlike callbacks, promises are great composable primitives.
-
- ```js
- Promise.all([
- getJSON('/posts'),
- getJSON('/comments')
- ]).then(function(values){
- values[0] // => postsJSON
- values[1] // => commentsJSON
-
- return values;
- });
- ```
-
- @class RSVP.Promise
- @param {function} resolver
- @param {String} label optional string for labeling the promise.
- Useful for tooling.
- @constructor
- */
- function Promise(resolver, label) {
- this._id = counter++;
- this._label = label;
- this._state = undefined;
- this._result = undefined;
- this._subscribers = [];
-
- if (config.instrument) {
- instrument('created', this);
- }
-
- if (noop !== resolver) {
- if (!isFunction(resolver)) {
- needsResolver();
- }
-
- if (!(this instanceof Promise)) {
- needsNew();
- }
-
- initializePromise(this, resolver);
- }
- }
-
- Promise.cast = Resolve; // deprecated
- Promise.all = all;
- Promise.race = race;
- Promise.resolve = Resolve;
- Promise.reject = Reject;
-
- Promise.prototype = {
- constructor: Promise,
-
- _guidKey: guidKey,
-
- _onerror: function (reason) {
- config.trigger('error', reason);
- },
-
- /**
- The primary way of interacting with a promise is through its `then` method,
- which registers callbacks to receive either a promise's eventual value or the
- reason why the promise cannot be fulfilled.
-
- ```js
- findUser().then(function(user){
- // user is available
- }, function(reason){
- // user is unavailable, and you are given the reason why
- });
- ```
-
- Chaining
- --------
-
- The return value of `then` is itself a promise. This second, 'downstream'
- promise is resolved with the return value of the first promise's fulfillment
- or rejection handler, or rejected if the handler throws an exception.
-
- ```js
- findUser().then(function (user) {
- return user.name;
- }, function (reason) {
- return 'default name';
- }).then(function (userName) {
- // If `findUser` fulfilled, `userName` will be the user's name, otherwise it
- // will be `'default name'`
- });
-
- findUser().then(function (user) {
- throw new Error('Found user, but still unhappy');
- }, function (reason) {
- throw new Error('`findUser` rejected and we're unhappy');
- }).then(function (value) {
- // never reached
- }, function (reason) {
- // if `findUser` fulfilled, `reason` will be 'Found user, but still unhappy'.
- // If `findUser` rejected, `reason` will be '`findUser` rejected and we're unhappy'.
- });
- ```
- If the downstream promise does not specify a rejection handler, rejection reasons will be propagated further downstream.
-
- ```js
- findUser().then(function (user) {
- throw new PedagogicalException('Upstream error');
- }).then(function (value) {
- // never reached
- }).then(function (value) {
- // never reached
- }, function (reason) {
- // The `PedgagocialException` is propagated all the way down to here
- });
- ```
-
- Assimilation
- ------------
-
- Sometimes the value you want to propagate to a downstream promise can only be
- retrieved asynchronously. This can be achieved by returning a promise in the
- fulfillment or rejection handler. The downstream promise will then be pending
- until the returned promise is settled. This is called *assimilation*.
-
- ```js
- findUser().then(function (user) {
- return findCommentsByAuthor(user);
- }).then(function (comments) {
- // The user's comments are now available
- });
- ```
-
- If the assimliated promise rejects, then the downstream promise will also reject.
-
- ```js
- findUser().then(function (user) {
- return findCommentsByAuthor(user);
- }).then(function (comments) {
- // If `findCommentsByAuthor` fulfills, we'll have the value here
- }, function (reason) {
- // If `findCommentsByAuthor` rejects, we'll have the reason here
- });
- ```
-
- Simple Example
- --------------
-
- Synchronous Example
-
- ```javascript
- var result;
-
- try {
- result = findResult();
- // success
- } catch(reason) {
- // failure
- }
- ```
-
- Errback Example
-
- ```js
- findResult(function(result, err){
- if (err) {
- // failure
- } else {
- // success
- }
- });
- ```
-
- Promise Example;
-
- ```javascript
- findResult().then(function(result){
- // success
- }, function(reason){
- // failure
- });
- ```
-
- Advanced Example
- --------------
-
- Synchronous Example
-
- ```javascript
- var author, books;
-
- try {
- author = findAuthor();
- books = findBooksByAuthor(author);
- // success
- } catch(reason) {
- // failure
- }
- ```
-
- Errback Example
-
- ```js
-
- function foundBooks(books) {
-
- }
-
- function failure(reason) {
-
- }
-
- findAuthor(function(author, err){
- if (err) {
- failure(err);
- // failure
- } else {
- try {
- findBoooksByAuthor(author, function(books, err) {
- if (err) {
- failure(err);
- } else {
- try {
- foundBooks(books);
- } catch(reason) {
- failure(reason);
- }
- }
- });
- } catch(error) {
- failure(err);
- }
- // success
- }
- });
- ```
-
- Promise Example;
-
- ```javascript
- findAuthor().
- then(findBooksByAuthor).
- then(function(books){
- // found books
- }).catch(function(reason){
- // something went wrong
- });
- ```
-
- @method then
- @param {Function} onFulfilled
- @param {Function} onRejected
- @param {String} label optional string for labeling the promise.
- Useful for tooling.
- @return {Promise}
- */
- then: function(onFulfillment, onRejection, label) {
- var parent = this;
- var state = parent._state;
-
- if (state === FULFILLED && !onFulfillment || state === REJECTED && !onRejection) {
- if (config.instrument) {
- instrument('chained', this, this);
- }
- return this;
- }
-
- parent._onerror = null;
-
- var child = new this.constructor(noop, label);
- var result = parent._result;
-
- if (config.instrument) {
- instrument('chained', parent, child);
- }
-
- if (state) {
- var callback = arguments[state - 1];
- config.async(function(){
- invokeCallback(state, child, callback, result);
- });
- } else {
- subscribe(parent, child, onFulfillment, onRejection);
- }
-
- return child;
- },
-
- /**
- `catch` is simply sugar for `then(undefined, onRejection)` which makes it the same
- as the catch block of a try/catch statement.
-
- ```js
- function findAuthor(){
- throw new Error('couldn't find that author');
- }
-
- // synchronous
- try {
- findAuthor();
- } catch(reason) {
- // something went wrong
- }
-
- // async with promises
- findAuthor().catch(function(reason){
- // something went wrong
- });
- ```
-
- @method catch
- @param {Function} onRejection
- @param {String} label optional string for labeling the promise.
- Useful for tooling.
- @return {Promise}
- */
- 'catch': function(onRejection, label) {
- return this.then(null, onRejection, label);
- },
-
- /**
- `finally` will be invoked regardless of the promise's fate just as native
- try/catch/finally behaves
-
- Synchronous example:
-
- ```js
- findAuthor() {
- if (Math.random() > 0.5) {
- throw new Error();
- }
- return new Author();
- }
-
- try {
- return findAuthor(); // succeed or fail
- } catch(error) {
- return findOtherAuther();
- } finally {
- // always runs
- // doesn't affect the return value
- }
- ```
-
- Asynchronous example:
-
- ```js
- findAuthor().catch(function(reason){
- return findOtherAuther();
- }).finally(function(){
- // author was either found, or not
- });
- ```
-
- @method finally
- @param {Function} callback
- @param {String} label optional string for labeling the promise.
- Useful for tooling.
- @return {Promise}
- */
- 'finally': function(callback, label) {
- var constructor = this.constructor;
-
- return this.then(function(value) {
- return constructor.resolve(callback()).then(function(){
- return value;
- });
- }, function(reason) {
- return constructor.resolve(callback()).then(function(){
- throw reason;
- });
- }, label);
- }
- };
- });
-enifed("rsvp/promise/all",
- ["../enumerator","exports"],
- function(__dependency1__, __exports__) {
- "use strict";
- var Enumerator = __dependency1__["default"];
-
- /**
- `RSVP.Promise.all` accepts an array of promises, and returns a new promise which
- is fulfilled with an array of fulfillment values for the passed promises, or
- rejected with the reason of the first passed promise to be rejected. It casts all
- elements of the passed iterable to promises as it runs this algorithm.
-
- Example:
-
- ```javascript
- var promise1 = RSVP.resolve(1);
- var promise2 = RSVP.resolve(2);
- var promise3 = RSVP.resolve(3);
- var promises = [ promise1, promise2, promise3 ];
-
- RSVP.Promise.all(promises).then(function(array){
- // The array here would be [ 1, 2, 3 ];
- });
- ```
-
- If any of the `promises` given to `RSVP.all` are rejected, the first promise
- that is rejected will be given as an argument to the returned promises's
- rejection handler. For example:
-
- Example:
-
- ```javascript
- var promise1 = RSVP.resolve(1);
- var promise2 = RSVP.reject(new Error("2"));
- var promise3 = RSVP.reject(new Error("3"));
- var promises = [ promise1, promise2, promise3 ];
-
- RSVP.Promise.all(promises).then(function(array){
- // Code here never runs because there are rejected promises!
- }, function(error) {
- // error.message === "2"
- });
- ```
-
- @method all
- @static
- @param {Array} entries array of promises
- @param {String} label optional string for labeling the promise.
- Useful for tooling.
- @return {Promise} promise that is fulfilled when all `promises` have been
- fulfilled, or rejected if any of them become rejected.
- @static
- */
- __exports__["default"] = function all(entries, label) {
- return new Enumerator(this, entries, true /* abort on reject */, label).promise;
- }
- });
-enifed("rsvp/promise/race",
- ["../utils","../-internal","exports"],
- function(__dependency1__, __dependency2__, __exports__) {
- "use strict";
- var isArray = __dependency1__.isArray;
-
- var noop = __dependency2__.noop;
- var resolve = __dependency2__.resolve;
- var reject = __dependency2__.reject;
- var subscribe = __dependency2__.subscribe;
- var PENDING = __dependency2__.PENDING;
-
- /**
- `RSVP.Promise.race` returns a new promise which is settled in the same way as the
- first passed promise to settle.
-
- Example:
-
- ```javascript
- var promise1 = new RSVP.Promise(function(resolve, reject){
- setTimeout(function(){
- resolve('promise 1');
- }, 200);
- });
-
- var promise2 = new RSVP.Promise(function(resolve, reject){
- setTimeout(function(){
- resolve('promise 2');
- }, 100);
- });
-
- RSVP.Promise.race([promise1, promise2]).then(function(result){
- // result === 'promise 2' because it was resolved before promise1
- // was resolved.
- });
- ```
-
- `RSVP.Promise.race` is deterministic in that only the state of the first
- settled promise matters. For example, even if other promises given to the
- `promises` array argument are resolved, but the first settled promise has
- become rejected before the other promises became fulfilled, the returned
- promise will become rejected:
-
- ```javascript
- var promise1 = new RSVP.Promise(function(resolve, reject){
- setTimeout(function(){
- resolve('promise 1');
- }, 200);
- });
-
- var promise2 = new RSVP.Promise(function(resolve, reject){
- setTimeout(function(){
- reject(new Error('promise 2'));
- }, 100);
- });
-
- RSVP.Promise.race([promise1, promise2]).then(function(result){
- // Code here never runs
- }, function(reason){
- // reason.message === 'promise 2' because promise 2 became rejected before
- // promise 1 became fulfilled
- });
- ```
-
- An example real-world use case is implementing timeouts:
-
- ```javascript
- RSVP.Promise.race([ajax('foo.json'), timeout(5000)])
- ```
-
- @method race
- @static
- @param {Array} promises array of promises to observe
- @param {String} label optional string for describing the promise returned.
- Useful for tooling.
- @return {Promise} a promise which settles in the same way as the first passed
- promise to settle.
- */
- __exports__["default"] = function race(entries, label) {
- /*jshint validthis:true */
- var Constructor = this;
-
- var promise = new Constructor(noop, label);
-
- if (!isArray(entries)) {
- reject(promise, new TypeError('You must pass an array to race.'));
- return promise;
- }
-
- var length = entries.length;
-
- function onFulfillment(value) {
- resolve(promise, value);
- }
-
- function onRejection(reason) {
- reject(promise, reason);
- }
-
- for (var i = 0; promise._state === PENDING && i < length; i++) {
- subscribe(Constructor.resolve(entries[i]), undefined, onFulfillment, onRejection);
- }
-
- return promise;
- }
- });
-enifed("rsvp/promise/reject",
- ["../-internal","exports"],
- function(__dependency1__, __exports__) {
- "use strict";
- var noop = __dependency1__.noop;
- var _reject = __dependency1__.reject;
-
- /**
- `RSVP.Promise.reject` returns a promise rejected with the passed `reason`.
- It is shorthand for the following:
-
- ```javascript
- var promise = new RSVP.Promise(function(resolve, reject){
- reject(new Error('WHOOPS'));
- });
-
- promise.then(function(value){
- // Code here doesn't run because the promise is rejected!
- }, function(reason){
- // reason.message === 'WHOOPS'
- });
- ```
-
- Instead of writing the above, your code now simply becomes the following:
-
- ```javascript
- var promise = RSVP.Promise.reject(new Error('WHOOPS'));
-
- promise.then(function(value){
- // Code here doesn't run because the promise is rejected!
- }, function(reason){
- // reason.message === 'WHOOPS'
- });
- ```
-
- @method reject
- @static
- @param {Any} reason value that the returned promise will be rejected with.
- @param {String} label optional string for identifying the returned promise.
- Useful for tooling.
- @return {Promise} a promise rejected with the given `reason`.
- */
- __exports__["default"] = function reject(reason, label) {
- /*jshint validthis:true */
- var Constructor = this;
- var promise = new Constructor(noop, label);
- _reject(promise, reason);
- return promise;
- }
- });
-enifed("rsvp/promise/resolve",
- ["../-internal","exports"],
- function(__dependency1__, __exports__) {
- "use strict";
- var noop = __dependency1__.noop;
- var _resolve = __dependency1__.resolve;
-
- /**
- `RSVP.Promise.resolve` returns a promise that will become resolved with the
- passed `value`. It is shorthand for the following:
-
- ```javascript
- var promise = new RSVP.Promise(function(resolve, reject){
- resolve(1);
- });
-
- promise.then(function(value){
- // value === 1
- });
- ```
-
- Instead of writing the above, your code now simply becomes the following:
-
- ```javascript
- var promise = RSVP.Promise.resolve(1);
-
- promise.then(function(value){
- // value === 1
- });
- ```
-
- @method resolve
- @static
- @param {Any} value value that the returned promise will be resolved with
- @param {String} label optional string for identifying the returned promise.
- Useful for tooling.
- @return {Promise} a promise that will become fulfilled with the given
- `value`
- */
- __exports__["default"] = function resolve(object, label) {
- /*jshint validthis:true */
- var Constructor = this;
-
- if (object && typeof object === 'object' && object.constructor === Constructor) {
- return object;
- }
-
- var promise = new Constructor(noop, label);
- _resolve(promise, object);
- return promise;
- }
- });
-enifed("rsvp/race",
- ["./promise","exports"],
- function(__dependency1__, __exports__) {
- "use strict";
- var Promise = __dependency1__["default"];
-
- /**
- This is a convenient alias for `RSVP.Promise.race`.
-
- @method race
- @static
- @for RSVP
- @param {Array} array Array of promises.
- @param {String} label An optional label. This is useful
- for tooling.
- */
- __exports__["default"] = function race(array, label) {
- return Promise.race(array, label);
- }
- });
-enifed("rsvp/reject",
- ["./promise","exports"],
- function(__dependency1__, __exports__) {
- "use strict";
- var Promise = __dependency1__["default"];
-
- /**
- This is a convenient alias for `RSVP.Promise.reject`.
-
- @method reject
- @static
- @for RSVP
- @param {Any} reason value that the returned promise will be rejected with.
- @param {String} label optional string for identifying the returned promise.
- Useful for tooling.
- @return {Promise} a promise rejected with the given `reason`.
- */
- __exports__["default"] = function reject(reason, label) {
- return Promise.reject(reason, label);
- }
- });
-enifed("rsvp/resolve",
- ["./promise","exports"],
- function(__dependency1__, __exports__) {
- "use strict";
- var Promise = __dependency1__["default"];
-
- /**
- This is a convenient alias for `RSVP.Promise.resolve`.
-
- @method resolve
- @static
- @for RSVP
- @param {Any} value value that the returned promise will be resolved with
- @param {String} label optional string for identifying the returned promise.
- Useful for tooling.
- @return {Promise} a promise that will become fulfilled with the given
- `value`
- */
- __exports__["default"] = function resolve(value, label) {
- return Promise.resolve(value, label);
- }
- });
-enifed("rsvp/rethrow",
- ["exports"],
- function(__exports__) {
- "use strict";
- /**
- `RSVP.rethrow` will rethrow an error on the next turn of the JavaScript event
- loop in order to aid debugging.
-
- Promises A+ specifies that any exceptions that occur with a promise must be
- caught by the promises implementation and bubbled to the last handler. For
- this reason, it is recommended that you always specify a second rejection
- handler function to `then`. However, `RSVP.rethrow` will throw the exception
- outside of the promise, so it bubbles up to your console if in the browser,
- or domain/cause uncaught exception in Node. `rethrow` will also throw the
- error again so the error can be handled by the promise per the spec.
-
- ```javascript
- function throws(){
- throw new Error('Whoops!');
- }
-
- var promise = new RSVP.Promise(function(resolve, reject){
- throws();
- });
-
- promise.catch(RSVP.rethrow).then(function(){
- // Code here doesn't run because the promise became rejected due to an
- // error!
- }, function (err){
- // handle the error here
- });
- ```
-
- The 'Whoops' error will be thrown on the next turn of the event loop
- and you can watch for it in your console. You can also handle it using a
- rejection handler given to `.then` or `.catch` on the returned promise.
-
- @method rethrow
- @static
- @for RSVP
- @param {Error} reason reason the promise became rejected.
- @throws Error
- @static
- */
- __exports__["default"] = function rethrow(reason) {
- setTimeout(function() {
- throw reason;
- });
- throw reason;
- }
- });
-enifed("rsvp/utils",
- ["exports"],
- function(__exports__) {
- "use strict";
- function objectOrFunction(x) {
- return typeof x === 'function' || (typeof x === 'object' && x !== null);
- }
-
- __exports__.objectOrFunction = objectOrFunction;function isFunction(x) {
- return typeof x === 'function';
- }
-
- __exports__.isFunction = isFunction;function isMaybeThenable(x) {
- return typeof x === 'object' && x !== null;
- }
-
- __exports__.isMaybeThenable = isMaybeThenable;var _isArray;
- if (!Array.isArray) {
- _isArray = function (x) {
- return Object.prototype.toString.call(x) === '[object Array]';
- };
- } else {
- _isArray = Array.isArray;
- }
-
- var isArray = _isArray;
- __exports__.isArray = isArray;
- // Date.now is not available in browsers < IE9
- // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/now#Compatibility
- var now = Date.now || function() { return new Date().getTime(); };
- __exports__.now = now;
- function F() { }
-
- var o_create = (Object.create || function (o) {
- if (arguments.length > 1) {
- throw new Error('Second argument not supported');
- }
- if (typeof o !== 'object') {
- throw new TypeError('Argument must be an object');
- }
- F.prototype = o;
- return new F();
- });
- __exports__.o_create = o_create;
- });
-requireModule("ember");
-
-})(); \ No newline at end of file