');
return new TestPromise(resolver, fullLabel);
}
/**
Replacement for `Ember.RSVP.resolve`
The only difference is this uses
an instance of `Ember.Test.Promise`
@public
@for Ember.Test
@method resolve
@param {Mixed} The value to resolve
@since 1.2.0
*/
function resolve(result, label) {
return TestPromise.resolve(result, label);
}
function getLastPromise() {
return lastPromise;
}
// 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
function isolate(onFulfillment, result) {
// Reset lastPromise for nested helpers
lastPromise = null;
var value = onFulfillment(result);
var promise = lastPromise;
lastPromise = null;
// If the method returned a promise
// return that promise. If not,
// return the last async helper's promise
if (value && value instanceof TestPromise || !promise) {
return value;
} else {
return (0, _run.default)(function () {
return resolve(promise).then(function () {
return value;
});
});
}
}
});
enifed('ember-testing/lib/test/run', ['exports', '@ember/runloop'], function (exports, _runloop) {
'use strict';
exports.default = run;
function run(fn) {
if (!(0, _runloop.getCurrentRunLoop)()) {
return (0, _runloop.run)(fn);
} else {
return fn();
}
}
});
enifed("ember-testing/lib/test/waiters", ["exports"], function (exports) {
"use strict";
exports.registerWaiter = registerWaiter;
exports.unregisterWaiter = unregisterWaiter;
exports.checkWaiters = checkWaiters;
/**
@module @ember/test
*/
var contexts = [];
var callbacks = [];
/**
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. The waiter runs periodically
after each async helper (i.e. `click`, `andThen`, `visit`, etc) has executed,
until the returning result is truthy. After the waiters finish, the next async helper
is executed and the process repeats.
For example:
```javascript
import { registerWaiter } from '@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
import { registerWaiter } from '@ember/test';
registerWaiter(MyDB, MyDB.hasPendingTransactions);
```
@public
@for @ember/test
@static
@method registerWaiter
@param {Object} context (optional)
@param {Function} callback
@since 1.2.0
*/
function registerWaiter(context, callback) {
if (arguments.length === 1) {
callback = context;
context = null;
}
if (indexOf(context, callback) > -1) {
return;
}
contexts.push(context);
callbacks.push(callback);
}
/**
`unregisterWaiter` is used to unregister a callback that was
registered with `registerWaiter`.
@public
@for @ember/test
@static
@method unregisterWaiter
@param {Object} context (optional)
@param {Function} callback
@since 1.2.0
*/
function unregisterWaiter(context, callback) {
if (!callbacks.length) {
return;
}
if (arguments.length === 1) {
callback = context;
context = null;
}
var i = indexOf(context, callback);
if (i === -1) {
return;
}
contexts.splice(i, 1);
callbacks.splice(i, 1);
}
/**
Iterates through each registered test waiter, and invokes
its callback. If any waiter returns false, this method will return
true indicating that the waiters have not settled yet.
This is generally used internally from the acceptance/integration test
infrastructure.
@public
@for @ember/test
@static
@method checkWaiters
*/
function checkWaiters() {
if (!callbacks.length) {
return false;
}
for (var i = 0; i < callbacks.length; i++) {
var context = contexts[i];
var callback = callbacks[i];
if (!callback.call(context)) {
return true;
}
}
return false;
}
function indexOf(context, callback) {
for (var i = 0; i < callbacks.length; i++) {
if (callbacks[i] === callback && contexts[i] === context) {
return i;
}
}
return -1;
}
});
enifed('ember-utils', ['exports', 'ember-babel'], function (exports, _emberBabel) {
'use strict';
exports.Cache = exports.setProxy = exports.isProxy = exports.WeakSet = exports.HAS_NATIVE_PROXY = exports.HAS_NATIVE_SYMBOL = exports.toString = exports.setName = exports.getName = exports.makeArray = exports.tryInvoke = exports.canInvoke = exports.lookupDescriptor = exports.inspect = exports.setListeners = exports.setObservers = exports.getListeners = exports.getObservers = exports.wrap = exports.ROOT = exports.checkHasSuper = exports.intern = exports.guidFor = exports.generateGuid = exports.GUID_KEY = exports.uuid = exports.dictionary = exports.isInternalSymbol = exports.symbol = exports.NAME_KEY = undefined;
/**
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 algorithms. These
algorithms 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
comparison.
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 comparisons 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;
}
/**
Returns whether Type(value) is Object.
Useful for checking whether a value is a valid WeakMap key.
Refs: https://tc39.github.io/ecma262/#sec-typeof-operator-runtime-semantics-evaluation
https://tc39.github.io/ecma262/#sec-weakmap.prototype.set
@private
@function isObject
*/
function isObject(value) {
return value !== null && (typeof value === 'object' || typeof value === 'function');
}
/**
@module @ember/object
*/
/**
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.
@public
@return {Number} [description]
*/
function uuid() {
return ++_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 OBJECT_GUIDS = new WeakMap();
var NON_OBJECT_GUIDS = new Map();
/**
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());
/**
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 `guidFor(obj)`, which return an existing guid if available.
@private
@method generateGuid
@static
@for @ember/object/internals
@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) {
var prefix = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : GUID_PREFIX;
var guid = prefix + uuid();
if (isObject(obj)) {
OBJECT_GUIDS.set(obj, guid);
}
return guid;
}
/**
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,
`EmberObject`-based or not.
You can also use this method on DOM Element objects.
@public
@static
@method guidFor
@for @ember/object/internals
@param {Object} obj any object, string, number, Element, or primitive
@return {String} the unique guid for this instance.
*/
function guidFor(value) {
var guid = void 0;
if (isObject(value)) {
guid = OBJECT_GUIDS.get(value);
if (guid === undefined) {
guid = GUID_PREFIX + uuid();
OBJECT_GUIDS.set(value, guid);
}
} else {
guid = NON_OBJECT_GUIDS.get(value);
if (guid === undefined) {
var type = typeof value;
if (type === 'string') {
guid = 'st' + uuid();
} else if (type === 'number') {
guid = 'nu' + uuid();
} else if (type === 'symbol') {
guid = 'sy' + uuid();
} else {
guid = '(' + value + ')';
}
NON_OBJECT_GUIDS.set(value, guid);
}
}
return guid;
}
var GENERATED_SYMBOLS = [];
function isInternalSymbol(possibleSymbol) {
return GENERATED_SYMBOLS.indexOf(possibleSymbol) !== -1;
}
function symbol(debugName) {
// TODO: Investigate using platform symbols, but we do not
// want to require non-enumerability for this API, which
// would introduce a large cost.
var id = GUID_KEY + Math.floor(Math.random() * +new Date());
var symbol = intern('__' + debugName + id + '__');
GENERATED_SYMBOLS.push(symbol);
return symbol;
}
// 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 worthwhile 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.
function makeDictionary(parent) {
var dict = Object.create(parent);
dict['_dict'] = null;
delete dict['_dict'];
return dict;
}
/* globals WeakSet */
var WeakSet$1 = typeof WeakSet === 'function' ? WeakSet : function () {
function WeakSetPolyFill() {
(0, _emberBabel.classCallCheck)(this, WeakSetPolyFill);
this._map = new WeakMap();
}
WeakSetPolyFill.prototype.add = function add(val) {
this._map.set(val, true);
return this;
};
WeakSetPolyFill.prototype.delete = function _delete(val) {
return this._map.delete(val);
};
WeakSetPolyFill.prototype.has = function has(val) {
return this._map.has(val);
};
return WeakSetPolyFill;
}();
var HAS_SUPER_PATTERN = /\.(_super|call\(this|apply\(this)/;
var fnToString = Function.prototype.toString;
var checkHasSuper = function () {
var sourceAvailable = fnToString.call(function () {
return this;
}).indexOf('return this') > -1;
if (sourceAvailable) {
return function checkHasSuper(func) {
return HAS_SUPER_PATTERN.test(fnToString.call(func));
};
}
return function checkHasSuper() {
return true;
};
}();
var HAS_SUPER_MAP = new WeakMap();
var ROOT = Object.freeze(function () {});
HAS_SUPER_MAP.set(ROOT, false);
function hasSuper(func) {
var hasSuper = HAS_SUPER_MAP.get(func);
if (hasSuper === undefined) {
hasSuper = checkHasSuper(func);
HAS_SUPER_MAP.set(func, hasSuper);
}
return hasSuper;
}
var OBSERVERS_MAP = new WeakMap();
function setObservers(func, observers) {
if (observers) {
OBSERVERS_MAP.set(func, observers);
}
}
function getObservers(func) {
return OBSERVERS_MAP.get(func);
}
var LISTENERS_MAP = new WeakMap();
function setListeners(func, listeners) {
if (listeners) {
LISTENERS_MAP.set(func, listeners);
}
}
function getListeners(func) {
return LISTENERS_MAP.get(func);
}
var IS_WRAPPED_FUNCTION_SET = new WeakSet$1();
/**
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) {
if (!hasSuper(func)) {
return func;
}
// ensure an unwrapped super that calls _super is wrapped with a terminal _super
if (!IS_WRAPPED_FUNCTION_SET.has(superFunc) && hasSuper(superFunc)) {
return _wrap(func, _wrap(superFunc, ROOT));
}
return _wrap(func, superFunc);
}
function _wrap(func, superFunc) {
function superWrapper() {
var orig = this._super;
this._super = superFunc;
var ret = func.apply(this, arguments);
this._super = orig;
return ret;
}
IS_WRAPPED_FUNCTION_SET.add(superWrapper);
setObservers(superWrapper, getObservers(func));
setListeners(superWrapper, getListeners(func));
return superWrapper;
}
var objectToString = Object.prototype.toString;
var functionToString = Function.prototype.toString;
var isArray = Array.isArray;
var objectKeys = Object.keys;
var stringify = JSON.stringify;
var LIST_LIMIT = 100;
var DEPTH_LIMIT = 4;
var SAFE_KEY = /^[\w$]+$/;
/**
@module @ember/debug
*/
/**
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
@static
@param {Object} obj The object you want to inspect.
@return {String} A description of the object
@since 1.4.0
@private
*/
function inspect(obj) {
// detect Node util.inspect call inspect(depth: number, opts: object)
if (typeof obj === 'number' && arguments.length === 2) {
return this;
}
return inspectValue(obj, 0);
}
function inspectValue(value, depth, seen) {
var valueIsArray = false;
switch (typeof value) {
case 'undefined':
return 'undefined';
case 'object':
if (value === null) return 'null';
if (isArray(value)) {
valueIsArray = true;
break;
}
// is toString Object.prototype.toString or undefined then traverse
if (value.toString === objectToString || value.toString === undefined) {
break;
}
// custom toString
return value.toString();
case 'function':
return value.toString === functionToString ? value.name ? '[Function:' + value.name + ']' : '[Function]' : value.toString();
case 'string':
return stringify(value);
case 'symbol':
case 'boolean':
case 'number':
default:
return value.toString();
}
if (seen === undefined) {
seen = new WeakSet$1();
} else {
if (seen.has(value)) return '[Circular]';
}
seen.add(value);
return valueIsArray ? inspectArray(value, depth + 1, seen) : inspectObject(value, depth + 1, seen);
}
function inspectKey(key) {
return SAFE_KEY.test(key) ? key : stringify(key);
}
function inspectObject(obj, depth, seen) {
if (depth > DEPTH_LIMIT) {
return '[Object]';
}
var s = '{';
var keys = objectKeys(obj);
for (var i = 0; i < keys.length; i++) {
s += i === 0 ? ' ' : ', ';
if (i >= LIST_LIMIT) {
s += '... ' + (keys.length - LIST_LIMIT) + ' more keys';
break;
}
var key = keys[i];
s += inspectKey(key) + ': ' + inspectValue(obj[key], depth, seen);
}
s += ' }';
return s;
}
function inspectArray(arr, depth, seen) {
if (depth > DEPTH_LIMIT) {
return '[Array]';
}
var s = '[';
for (var i = 0; i < arr.length; i++) {
s += i === 0 ? ' ' : ', ';
if (i >= LIST_LIMIT) {
s += '... ' + (arr.length - LIST_LIMIT) + ' more items';
break;
}
s += inspectValue(arr[i], depth, seen);
}
s += ' ]';
return s;
}
function lookupDescriptor(obj, keyName) {
var current = obj;
do {
var descriptor = Object.getOwnPropertyDescriptor(current, keyName);
if (descriptor !== undefined) {
return descriptor;
}
current = Object.getPrototypeOf(current);
} while (current !== null);
return null;
}
/**
Checks to see if the `methodName` exists on the `obj`.
```javascript
let foo = { bar: function() { return 'bar'; }, 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}
@private
*/
function canInvoke(obj, methodName) {
return obj !== null && obj !== undefined && typeof obj[methodName] === 'function';
}
/**
@module @ember/utils
*/
/**
Checks to see if the `methodName` exists on the `obj`,
and if it does, invokes it with the arguments passed.
```javascript
import { tryInvoke } from '@ember/utils';
let d = new Date('03/15/2013');
tryInvoke(d, 'getTime'); // 1363320000000
tryInvoke(d, 'setFullYear', [2014]); // 1394856000000
tryInvoke(d, 'noSuchMethod', [2014]); // undefined
```
@method tryInvoke
@for @ember/utils
@static
@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
@public
*/
function tryInvoke(obj, methodName, args) {
if (canInvoke(obj, methodName)) {
var method = obj[methodName];
return method.apply(obj, args);
}
}
var isArray$1 = Array.isArray;
function makeArray(obj) {
if (obj === null || obj === undefined) {
return [];
}
return isArray$1(obj) ? obj : [obj];
}
var NAMES = new WeakMap();
function setName(obj, name) {
if (isObject(obj)) NAMES.set(obj, name);
}
function getName(obj) {
return NAMES.get(obj);
}
var objectToString$1 = Object.prototype.toString;
function isNone(obj) {
return obj === null || obj === undefined;
}
/*
A `toString` util function that supports objects without a `toString`
method, e.g. an object created with `Object.create(null)`.
*/
function toString(obj) {
if (typeof obj === 'string') {
return obj;
}
if (null === obj) return 'null';
if (undefined === obj) return 'undefined';
if (Array.isArray(obj)) {
// Reimplement Array.prototype.join according to spec (22.1.3.13)
// Changing ToString(element) with this safe version of ToString.
var r = '';
for (var k = 0; k < obj.length; k++) {
if (k > 0) {
r += ',';
}
if (!isNone(obj[k])) {
r += toString(obj[k]);
}
}
return r;
}
if (typeof obj.toString === 'function') {
return obj.toString();
}
return objectToString$1.call(obj);
}
var HAS_NATIVE_SYMBOL = function () {
if (typeof Symbol !== 'function') {
return false;
}
// use `Object`'s `.toString` directly to prevent us from detecting
// polyfills as native
return Object.prototype.toString.call(Symbol()) === '[object Symbol]';
}();
var HAS_NATIVE_PROXY = typeof Proxy === 'function';
var PROXIES = new WeakSet$1();
function isProxy(object) {
if (isObject(object)) {
return PROXIES.has(object);
}
return false;
}
function setProxy(object) {
if (isObject(object)) {
PROXIES.add(object);
}
}
var Cache = function () {
function Cache(limit, func, store) {
(0, _emberBabel.classCallCheck)(this, Cache);
this.limit = limit;
this.func = func;
this.store = store;
this.size = 0;
this.misses = 0;
this.hits = 0;
this.store = store || new Map();
}
Cache.prototype.get = function get(key) {
var value = this.store.get(key);
if (this.store.has(key)) {
this.hits++;
return this.store.get(key);
} else {
this.misses++;
value = this.set(key, this.func(key));
}
return value;
};
Cache.prototype.set = function set(key, value) {
if (this.limit > this.size) {
this.size++;
this.store.set(key, value);
}
return value;
};
Cache.prototype.purge = function purge() {
this.store.clear();
this.size = 0;
this.hits = 0;
this.misses = 0;
};
return Cache;
}();
/*
This package will be eagerly parsed and should have no dependencies on external
packages.
It is intended to be used to share utility methods that will be needed
by every Ember application (and is **not** a dumping ground of useful utilities).
Utility methods that are needed in < 80% of cases should be placed
elsewhere (so they can be lazily evaluated / parsed).
*/
var NAME_KEY = symbol('NAME_KEY');
exports.NAME_KEY = NAME_KEY;
exports.symbol = symbol;
exports.isInternalSymbol = isInternalSymbol;
exports.dictionary = makeDictionary;
exports.uuid = uuid;
exports.GUID_KEY = GUID_KEY;
exports.generateGuid = generateGuid;
exports.guidFor = guidFor;
exports.intern = intern;
exports.checkHasSuper = checkHasSuper;
exports.ROOT = ROOT;
exports.wrap = wrap;
exports.getObservers = getObservers;
exports.getListeners = getListeners;
exports.setObservers = setObservers;
exports.setListeners = setListeners;
exports.inspect = inspect;
exports.lookupDescriptor = lookupDescriptor;
exports.canInvoke = canInvoke;
exports.tryInvoke = tryInvoke;
exports.makeArray = makeArray;
exports.getName = getName;
exports.setName = setName;
exports.toString = toString;
exports.HAS_NATIVE_SYMBOL = HAS_NATIVE_SYMBOL;
exports.HAS_NATIVE_PROXY = HAS_NATIVE_PROXY;
exports.WeakSet = WeakSet$1;
exports.isProxy = isProxy;
exports.setProxy = setProxy;
exports.Cache = Cache;
});
enifed('ember-views/index', ['exports', 'ember-views/lib/system/jquery', 'ember-views/lib/system/utils', 'ember-views/lib/system/event_dispatcher', 'ember-views/lib/component_lookup', 'ember-views/lib/mixins/text_support', 'ember-views/lib/views/core_view', 'ember-views/lib/mixins/class_names_support', 'ember-views/lib/mixins/child_views_support', 'ember-views/lib/mixins/view_state_support', 'ember-views/lib/mixins/view_support', 'ember-views/lib/mixins/action_support', 'ember-views/lib/compat/attrs', 'ember-views/lib/system/lookup_partial', 'ember-views/lib/utils/lookup-component', 'ember-views/lib/system/action_manager', 'ember-views/lib/compat/fallback-view-registry'], function (exports, _jquery, _utils, _event_dispatcher, _component_lookup, _text_support, _core_view, _class_names_support, _child_views_support, _view_state_support, _view_support, _action_support, _attrs, _lookup_partial, _lookupComponent, _action_manager, _fallbackViewRegistry) {
'use strict';
Object.defineProperty(exports, 'jQuery', {
enumerable: true,
get: function () {
return _jquery.default;
}
});
Object.defineProperty(exports, 'jQueryDisabled', {
enumerable: true,
get: function () {
return _jquery.jQueryDisabled;
}
});
Object.defineProperty(exports, 'addChildView', {
enumerable: true,
get: function () {
return _utils.addChildView;
}
});
Object.defineProperty(exports, 'isSimpleClick', {
enumerable: true,
get: function () {
return _utils.isSimpleClick;
}
});
Object.defineProperty(exports, 'getViewBounds', {
enumerable: true,
get: function () {
return _utils.getViewBounds;
}
});
Object.defineProperty(exports, 'getViewClientRects', {
enumerable: true,
get: function () {
return _utils.getViewClientRects;
}
});
Object.defineProperty(exports, 'getViewBoundingClientRect', {
enumerable: true,
get: function () {
return _utils.getViewBoundingClientRect;
}
});
Object.defineProperty(exports, 'getRootViews', {
enumerable: true,
get: function () {
return _utils.getRootViews;
}
});
Object.defineProperty(exports, 'getChildViews', {
enumerable: true,
get: function () {
return _utils.getChildViews;
}
});
Object.defineProperty(exports, 'getViewId', {
enumerable: true,
get: function () {
return _utils.getViewId;
}
});
Object.defineProperty(exports, 'getViewElement', {
enumerable: true,
get: function () {
return _utils.getViewElement;
}
});
Object.defineProperty(exports, 'setViewElement', {
enumerable: true,
get: function () {
return _utils.setViewElement;
}
});
Object.defineProperty(exports, 'constructStyleDeprecationMessage', {
enumerable: true,
get: function () {
return _utils.constructStyleDeprecationMessage;
}
});
Object.defineProperty(exports, 'EventDispatcher', {
enumerable: true,
get: function () {
return _event_dispatcher.default;
}
});
Object.defineProperty(exports, 'ComponentLookup', {
enumerable: true,
get: function () {
return _component_lookup.default;
}
});
Object.defineProperty(exports, 'TextSupport', {
enumerable: true,
get: function () {
return _text_support.default;
}
});
Object.defineProperty(exports, 'CoreView', {
enumerable: true,
get: function () {
return _core_view.default;
}
});
Object.defineProperty(exports, 'ClassNamesSupport', {
enumerable: true,
get: function () {
return _class_names_support.default;
}
});
Object.defineProperty(exports, 'ChildViewsSupport', {
enumerable: true,
get: function () {
return _child_views_support.default;
}
});
Object.defineProperty(exports, 'ViewStateSupport', {
enumerable: true,
get: function () {
return _view_state_support.default;
}
});
Object.defineProperty(exports, 'ViewMixin', {
enumerable: true,
get: function () {
return _view_support.default;
}
});
Object.defineProperty(exports, 'ActionSupport', {
enumerable: true,
get: function () {
return _action_support.default;
}
});
Object.defineProperty(exports, 'MUTABLE_CELL', {
enumerable: true,
get: function () {
return _attrs.MUTABLE_CELL;
}
});
Object.defineProperty(exports, 'lookupPartial', {
enumerable: true,
get: function () {
return _lookup_partial.default;
}
});
Object.defineProperty(exports, 'hasPartial', {
enumerable: true,
get: function () {
return _lookup_partial.hasPartial;
}
});
Object.defineProperty(exports, 'lookupComponent', {
enumerable: true,
get: function () {
return _lookupComponent.default;
}
});
Object.defineProperty(exports, 'ActionManager', {
enumerable: true,
get: function () {
return _action_manager.default;
}
});
Object.defineProperty(exports, 'fallbackViewRegistry', {
enumerable: true,
get: function () {
return _fallbackViewRegistry.default;
}
});
});
enifed('ember-views/lib/compat/attrs', ['exports', 'ember-utils'], function (exports, _emberUtils) {
'use strict';
exports.MUTABLE_CELL = undefined;
var MUTABLE_CELL = exports.MUTABLE_CELL = (0, _emberUtils.symbol)('MUTABLE_CELL');
});
enifed('ember-views/lib/compat/fallback-view-registry', ['exports', 'ember-utils'], function (exports, _emberUtils) {
'use strict';
exports.default = (0, _emberUtils.dictionary)(null);
});
enifed('ember-views/lib/component_lookup', ['exports', '@ember/debug', 'ember-runtime'], function (exports, _debug, _emberRuntime) {
'use strict';
exports.default = _emberRuntime.Object.extend({
componentFor: function (name, owner, options) {
(true && !(name.indexOf('-') > -1 || true /* EMBER_GLIMMER_ANGLE_BRACKET_INVOCATION */) && (0, _debug.assert)('You cannot use \'' + name + '\' as a component name. Component names must contain a hyphen' + (true /* EMBER_GLIMMER_ANGLE_BRACKET_INVOCATION */ ? ' or start with a capital letter' : '') + '.', name.indexOf('-') > -1 || true));
var fullName = 'component:' + name;
return owner.factoryFor(fullName, options);
},
layoutFor: function (name, owner, options) {
(true && !(name.indexOf('-') > -1 || true /* EMBER_GLIMMER_ANGLE_BRACKET_INVOCATION */) && (0, _debug.assert)('You cannot use \'' + name + '\' as a component name. Component names must contain a hyphen.', name.indexOf('-') > -1 || true));
var templateFullName = 'template:components/' + name;
return owner.lookup(templateFullName, options);
}
});
});
enifed('ember-views/lib/mixins/action_support', ['exports', 'ember-utils', 'ember-metal', '@ember/debug', 'ember-views/lib/compat/attrs', '@ember/deprecated-features'], function (exports, _emberUtils, _emberMetal, _debug, _attrs, _deprecatedFeatures) {
'use strict';
var mixinObj = {
send: function (actionName) {
for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
args[_key - 1] = arguments[_key];
}
(true && !(!this.isDestroying && !this.isDestroyed) && (0, _debug.assert)('Attempted to call .send() with the action \'' + actionName + '\' on the destroyed object \'' + this + '\'.', !this.isDestroying && !this.isDestroyed));
var action = this.actions && this.actions[actionName];
if (action) {
var shouldBubble = action.apply(this, args) === true;
if (!shouldBubble) {
return;
}
}
var target = (0, _emberMetal.get)(this, 'target');
if (target) {
(true && !(typeof target.send === 'function') && (0, _debug.assert)('The `target` for ' + this + ' (' + target + ') does not have a `send` method', typeof target.send === 'function'));
target.send.apply(target, arguments);
} else {
(true && !(action) && (0, _debug.assert)((0, _emberUtils.inspect)(this) + ' had no action handler for: ' + actionName, action));
}
}
}; /**
@module ember
*/
if (_deprecatedFeatures.SEND_ACTION) {
/**
Calls an action passed to a component.
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:
```app/components/play-button.js
import Component from '@ember/component';
export default Component.extend({
click() {
if (this.get('isPlaying')) {
this.sendAction('play');
} else {
this.sendAction('stop');
}
}
});
```
The actions "play" and "stop" must be passed to this `play-button` component:
```handlebars
{{! app/templates/application.hbs }}
{{play-button play=(action "musicStarted") stop=(action "musicStopped")}}
```
When the component receives a browser `click` event it translate this
interaction into application-specific semantics ("play" or "stop") and
calls the specified action.
```app/controller/application.js
import Controller from '@ember/controller';
export default Controller.extend({
actions: {
musicStarted() {
// called when the play button is clicked
// and the music started playing
},
musicStopped() {
// called when the play button is clicked
// and the music stopped playing
}
}
});
```
If no action is passed to `sendAction` a default name of "action"
is assumed.
```app/components/next-button.js
import Component from '@ember/component';
export default Component.extend({
click() {
this.sendAction();
}
});
```
```handlebars
{{! app/templates/application.hbs }}
{{next-button action=(action "playNextSongInAlbum")}}
```
```app/controllers/application.js
import Controller from '@ember/controller';
export default Controller.extend({
actions: {
playNextSongInAlbum() {
...
}
}
});
```
@method sendAction
@param [action] {String} the action to call
@param [params] {*} arguments for the action
@public
@deprecated
*/
var sendAction = function sendAction(action) {
for (var _len2 = arguments.length, contexts = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
contexts[_key2 - 1] = arguments[_key2];
}
(true && !(!this.isDestroying && !this.isDestroyed) && (0, _debug.assert)('Attempted to call .sendAction() with the action \'' + action + '\' on the destroyed object \'' + this + '\'.', !this.isDestroying && !this.isDestroyed));
(true && !(false) && (0, _debug.deprecate)('You called ' + (0, _emberUtils.inspect)(this) + '.sendAction(' + (typeof action === 'string' ? '"' + action + '"' : '') + ') but Component#sendAction is deprecated. Please use closure actions instead.', false, {
id: 'ember-component.send-action',
until: '4.0.0',
url: 'https://emberjs.com/deprecations/v3.x#toc_ember-component-send-action'
}));
var actionName = void 0;
// Send the default action
if (action === undefined) {
action = 'action';
}
actionName = (0, _emberMetal.get)(this, 'attrs.' + action) || (0, _emberMetal.get)(this, action);
actionName = validateAction(this, actionName);
// If no action name for that action could be found, just abort.
if (actionName === undefined) {
return;
}
if (typeof actionName === 'function') {
actionName.apply(undefined, contexts);
} else {
this.triggerAction({
action: actionName,
actionContext: contexts
});
}
};
var validateAction = function validateAction(component, actionName) {
if (actionName && actionName[_attrs.MUTABLE_CELL]) {
actionName = actionName.value;
}
(true && !(actionName === null || actionName === undefined || typeof actionName === 'string' || typeof actionName === 'function') && (0, _debug.assert)('The default action was triggered on the component ' + component.toString() + ', but the action name (' + actionName + ') was not a string.', actionName === null || actionName === undefined || typeof actionName === 'string' || typeof actionName === 'function'));
return actionName;
};
mixinObj.sendAction = sendAction;
}
/**
@class ActionSupport
@namespace Ember
@private
*/
exports.default = _emberMetal.Mixin.create(mixinObj);
});
enifed('ember-views/lib/mixins/child_views_support', ['exports', 'ember-metal', 'ember-views/lib/system/utils'], function (exports, _emberMetal, _utils) {
'use strict';
exports.default = _emberMetal.Mixin.create({
/**
Array of child views. You should never edit this array directly.
@property childViews
@type Array
@default []
@private
*/
childViews: (0, _emberMetal.descriptor)({
configurable: false,
enumerable: false,
get: function () {
return (0, _utils.getChildViews)(this);
}
}),
appendChild: function (view) {
(0, _utils.addChildView)(this, view);
}
});
});
enifed('ember-views/lib/mixins/class_names_support', ['exports', 'ember-meta', 'ember-metal', '@ember/debug'], function (exports, _emberMeta, _emberMetal, _debug) {
'use strict';
var EMPTY_ARRAY = Object.freeze([]);
/**
@class ClassNamesSupport
@namespace Ember
@private
*/
/**
@module ember
*/
exports.default = _emberMetal.Mixin.create({
concatenatedProperties: ['classNames', 'classNameBindings'],
init: function () {
this._super.apply(this, arguments);
(true && !((0, _emberMeta.descriptorFor)(this, 'classNameBindings') === undefined && Array.isArray(this.classNameBindings)) && (0, _debug.assert)('Only arrays are allowed for \'classNameBindings\'', (0, _emberMeta.descriptorFor)(this, 'classNameBindings') === undefined && Array.isArray(this.classNameBindings)));
(true && !((0, _emberMeta.descriptorFor)(this, 'classNames') === undefined && Array.isArray(this.classNames)) && (0, _debug.assert)('Only arrays of static class strings are allowed for \'classNames\'. For dynamic classes, use \'classNameBindings\'.', (0, _emberMeta.descriptorFor)(this, 'classNames') === undefined && Array.isArray(this.classNames)));
},
/**
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']
@public
*/
classNames: EMPTY_ARRAY,
/**
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
import Component from '@ember/component';
Component.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
import Component from '@ember/component';
Component.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
import Component from '@ember/component';
Component.extend({
classNameBindings: ['isUrgent:urgent'],
isUrgent: true
});
```
If you would like to specify a class that should only be added when the
property is false, you can declare a binding like this:
```javascript
// Applies the 'disabled' class to the view element
import Component from '@ember/component';
Component.extend({
classNameBindings: ['isEnabled::disabled'],
isEnabled: false
});
```
This list of properties is inherited from the component's superclasses as well.
@property classNameBindings
@type Array
@default []
@public
*/
classNameBindings: EMPTY_ARRAY
});
});
enifed('ember-views/lib/mixins/text_support', ['exports', 'ember-metal', 'ember-runtime', '@ember/debug', '@ember/deprecated-features'], function (exports, _emberMetal, _emberRuntime, _debug, _deprecatedFeatures) {
'use strict';
/**
@module ember
*/
var KEY_EVENTS = {
13: 'insertNewline',
27: 'cancel'
};
/**
`TextSupport` is a shared mixin used by both `TextField` and
`TextArea`. `TextSupport` adds a number of methods that allow you to
specify a controller action to invoke when a certain event is fired on your
text field or textarea. The specified controller action would get the current
value of the field passed in as the only argument unless the value of
the field is empty. In that case, the instance of the field itself is passed
in as the only argument.
Let's use the pressing of the escape key as an example. If you wanted to
invoke a controller action when a user presses the escape key while on your
field, you would use the `escape-press` attribute on your field like so:
```handlebars
{{! application.hbs}}
{{input escape-press='alertUser'}}
```
```javascript
import Application from '@ember/application';
import Controller from '@ember/controller';
App = Application.create();
App.ApplicationController = Controller.extend({
actions: {
alertUser: function ( currentValue ) {
alert( 'escape pressed, current value: ' + currentValue );
}
}
});
```
The following chart is a visual representation of what takes place when the
escape key is pressed in this scenario:
```
The Template
+---------------------------+
| |
| escape-press='alertUser' |
| | TextSupport Mixin
+----+----------------------+ +-------------------------------+
| | cancel method |
| escape button pressed | |
+-------------------------------> | checks for the `escape-press` |
| attribute and pulls out the |
+-------------------------------+ | `alertUser` value |
| action name 'alertUser' +-------------------------------+
| sent to controller
v
Controller
+------------------------------------------ +
| |
| actions: { |
| alertUser: function( currentValue ){ |
| alert( 'the esc key was pressed!' ) |
| } |
| } |
| |
+-------------------------------------------+
```
Here are the events that we currently support along with the name of the
attribute you would need to use on your field. To reiterate, you would use the
attribute name like so:
```handlebars
{{input attribute-name='controllerAction'}}
```
```
+--------------------+----------------+
| | |
| event | attribute name |
+--------------------+----------------+
| new line inserted | insert-newline |
| | |
| enter key pressed | enter |
| | |
| cancel key pressed | escape-press |
| | |
| focusin | focus-in |
| | |
| focusout | focus-out |
| | |
| keypress | key-press |
| | |
| keyup | key-up |
| | |
| keydown | key-down |
+--------------------+----------------+
```
@class TextSupport
@namespace Ember
@uses Ember.TargetActionSupport
@extends Mixin
@private
*/
exports.default = _emberMetal.Mixin.create(_emberRuntime.TargetActionSupport, {
value: '',
attributeBindings: ['autocapitalize', 'autocorrect', 'autofocus', 'disabled', 'form', 'maxlength', 'minlength', 'placeholder', 'readonly', 'required', 'selectionDirection', 'spellcheck', 'tabindex', 'title'],
placeholder: null,
disabled: false,
maxlength: null,
init: function () {
this._super.apply(this, arguments);
this.on('paste', this, this._elementValueDidChange);
this.on('cut', this, this._elementValueDidChange);
this.on('input', this, this._elementValueDidChange);
},
/**
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
@private
*/
bubbles: false,
interpretKeyEvents: function (event) {
var map = KEY_EVENTS;
var method = map[event.keyCode];
this._elementValueDidChange();
if (method) {
return this[method](event);
}
},
_elementValueDidChange: function () {
(0, _emberMetal.set)(this, 'value', this.element.value);
},
change: function (event) {
this._elementValueDidChange(event);
},
/**
Allows you to specify a controller action to invoke when either the `enter`
key is pressed or, in the case of the field being a textarea, when a newline
is inserted. To use this method, give your field an `insert-newline`
attribute. The value of that attribute should be the name of the action
in your controller that you wish to invoke.
For an example on how to use the `insert-newline` attribute, please
reference the example near the top of this file.
@method insertNewline
@param {Event} event
@private
*/
insertNewline: function (event) {
sendAction('enter', this, event);
sendAction('insert-newline', this, event);
},
/**
Allows you to specify a controller action to invoke when the escape button
is pressed. To use this method, give your field an `escape-press`
attribute. The value of that attribute should be the name of the action
in your controller that you wish to invoke.
For an example on how to use the `escape-press` attribute, please reference
the example near the top of this file.
@method cancel
@param {Event} event
@private
*/
cancel: function (event) {
sendAction('escape-press', this, event);
},
/**
Allows you to specify a controller action to invoke when a field receives
focus. To use this method, give your field a `focus-in` attribute. The value
of that attribute should be the name of the action in your controller
that you wish to invoke.
For an example on how to use the `focus-in` attribute, please reference the
example near the top of this file.
@method focusIn
@param {Event} event
@private
*/
focusIn: function (event) {
sendAction('focus-in', this, event);
},
/**
Allows you to specify a controller action to invoke when a field loses
focus. To use this method, give your field a `focus-out` attribute. The value
of that attribute should be the name of the action in your controller
that you wish to invoke.
For an example on how to use the `focus-out` attribute, please reference the
example near the top of this file.
@method focusOut
@param {Event} event
@private
*/
focusOut: function (event) {
this._elementValueDidChange(event);
sendAction('focus-out', this, event);
},
/**
Allows you to specify a controller action to invoke when a key is pressed.
To use this method, give your field a `key-press` attribute. The value of
that attribute should be the name of the action in your controller you
that wish to invoke.
For an example on how to use the `key-press` attribute, please reference the
example near the top of this file.
@method keyPress
@param {Event} event
@private
*/
keyPress: function (event) {
sendAction('key-press', this, event);
},
/**
Allows you to specify a controller action to invoke when a key-up event is
fired. To use this method, give your field a `key-up` attribute. The value
of that attribute should be the name of the action in your controller
that you wish to invoke.
For an example on how to use the `key-up` attribute, please reference the
example near the top of this file.
@method keyUp
@param {Event} event
@private
*/
keyUp: function (event) {
this.interpretKeyEvents(event);
sendAction('key-up', this, event);
},
/**
Allows you to specify a controller action to invoke when a key-down event is
fired. To use this method, give your field a `key-down` attribute. The value
of that attribute should be the name of the action in your controller that
you wish to invoke.
For an example on how to use the `key-down` attribute, please reference the
example near the top of this file.
@method keyDown
@param {Event} event
@private
*/
keyDown: function (event) {
sendAction('key-down', this, event);
}
});
// 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 actionName = (0, _emberMetal.get)(view, 'attrs.' + eventName) || (0, _emberMetal.get)(view, eventName);
var value = (0, _emberMetal.get)(view, 'value');
if (_deprecatedFeatures.SEND_ACTION && typeof actionName === 'string') {
(true && !(false) && (0, _debug.deprecate)('Passing actions to components as strings (like {{input ' + eventName + '="' + actionName + '"}}) is deprecated. Please use closure actions instead ({{input ' + eventName + '=(action "' + actionName + '")}})', false, {
id: 'ember-component.send-action',
until: '4.0.0',
url: 'https://emberjs.com/deprecations/v3.x#toc_ember-component-send-action'
}));
view.triggerAction({
action: actionName,
actionContext: [value, event]
});
} else if (typeof actionName === 'function') {
actionName(value, event);
}
if (actionName && !(0, _emberMetal.get)(view, 'bubbles')) {
event.stopPropagation();
}
}
});
enifed('ember-views/lib/mixins/view_state_support', ['exports', 'ember-metal'], function (exports, _emberMetal) {
'use strict';
exports.default = _emberMetal.Mixin.create({
_transitionTo: function (state) {
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);
}
}
});
});
enifed('ember-views/lib/mixins/view_support', ['exports', 'ember-utils', 'ember-meta', 'ember-metal', '@ember/debug', 'ember-browser-environment', 'ember-views/lib/system/utils', 'ember-views/lib/system/jquery'], function (exports, _emberUtils, _emberMeta, _emberMetal, _debug, _emberBrowserEnvironment, _utils, _jquery) {
'use strict';
function K() {
return this;
}
/**
@class ViewMixin
@namespace Ember
@private
*/
exports.default = _emberMetal.Mixin.create({
/**
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 value
for an attribute of the property's name.
The following example creates a tag like ``.
```app/components/my-component.js
import Component from '@ember/component';
export default Component.extend({
attributeBindings: ['priority'],
priority: 'high'
});
```
If the value of the property is a Boolean, the attribute is treated as
an HTML Boolean attribute. It will be present if the property is `true`
and omitted if the property is `false`.
The following example creates markup like ``.
```app/components/my-component.js
import Component from '@ember/component';
export default Component.extend({
attributeBindings: ['visible'],
visible: true
});
```
If you would prefer to use a custom value instead of the property name,
you can create the same markup as the last example with a binding like
this:
```app/components/my-component.js
import Component from '@ember/component';
export default Component.extend({
attributeBindings: ['isVisible:visible'],
isVisible: true
});
```
This list of attributes is inherited from the component's superclasses,
as well.
@property attributeBindings
@type Array
@default []
@public
*/
concatenatedProperties: ['attributeBindings'],
// ..........................................................
// TEMPLATE SUPPORT
//
/**
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 Mixin.
@return Ember.View
@deprecated use `yield` and contextual components for composition instead.
@private
*/
nearestOfType: function (klass) {
var view = this.parentView;
var isOfType = klass instanceof _emberMetal.Mixin ? function (view) {
return klass.detect(view);
} : function (view) {
return klass.detect(view.constructor);
};
while (view) {
if (isOfType(view)) {
return view;
}
view = view.parentView;
}
},
/**
Return the nearest ancestor that has a given property.
@method nearestWithProperty
@param {String} property A property name
@return Ember.View
@deprecated use `yield` and contextual components for composition instead.
@private
*/
nearestWithProperty: function (property) {
var view = this.parentView;
while (view) {
if (property in view) {
return view;
}
view = view.parentView;
}
},
/**
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
@public
*/
rerender: function () {
return this._currentState.rerender(this);
},
// ..........................................................
// ELEMENT SUPPORT
//
/**
Returns the current DOM element for the view.
@property element
@type DOMElement
@public
*/
element: (0, _emberMetal.descriptor)({
configurable: false,
enumerable: false,
get: function () {
return this.renderer.getElement(this);
}
}),
/**
Returns a jQuery object for this view's element. If you pass in a selector
string, this method will return a jQuery object, using the current element
as its buffer.
For example, calling `view.$('li')` will return a jQuery object containing
all of the `li` elements inside the DOM element of this view.
@method $
@param {String} [selector] a jQuery-compatible selector string
@return {jQuery} the jQuery object for the DOM node
@public
*/
$: function (sel) {
(true && !(this.tagName !== '') && (0, _debug.assert)("You cannot access this.$() on a component with `tagName: ''` specified.", this.tagName !== ''));
(true && !(!_jquery.jQueryDisabled) && (0, _debug.assert)('You cannot access this.$() with `jQuery` disabled.', !_jquery.jQueryDisabled));
if (this.element) {
return sel ? (0, _jquery.default)(sel, this.element) : (0, _jquery.default)(this.element);
}
},
/**
Appends the view's element to the specified parent element.
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. If you do need to use `appendTo`, be sure that
the target element you are providing is associated with an `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
@private
*/
appendTo: function (selector) {
var target = void 0;
if (_emberBrowserEnvironment.hasDOM) {
target = typeof selector === 'string' ? document.querySelector(selector) : selector;
(true && !(target) && (0, _debug.assert)('You tried to append to (' + selector + ') but that isn\'t in the DOM', target));
(true && !(!(0, _utils.matches)(target, '.ember-view')) && (0, _debug.assert)('You cannot append to an existing Ember.View.', !(0, _utils.matches)(target, '.ember-view')));
(true && !(function () {
var node = target.parentNode;
while (node) {
if (node.nodeType !== 9 && (0, _utils.matches)(node, '.ember-view')) {
return false;
}
node = node.parentNode;
}
return true;
}()) && (0, _debug.assert)('You cannot append to an existing Ember.View.', function () {
var node = target.parentNode;while (node) {
if (node.nodeType !== 9 && (0, _utils.matches)(node, '.ember-view')) {
return false;
}node = node.parentNode;
}return true;
}()));
} else {
target = selector;
(true && !(typeof target !== 'string') && (0, _debug.assert)('You tried to append to a selector string (' + selector + ') in an environment without jQuery', typeof target !== 'string'));
(true && !(typeof selector.appendChild === 'function') && (0, _debug.assert)('You tried to append to a non-Element (' + selector + ') in an environment without jQuery', typeof selector.appendChild === 'function'));
}
this.renderer.appendTo(this, target);
return this;
},
/**
Appends the view's element to the document body. If the view does
not have an HTML representation yet
the element will be generated 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
@private
*/
append: function () {
return this.appendTo(document.body);
},
/**
The HTML `id` of the view's element in the DOM. You can provide this
value yourself but it must be unique (just as in HTML):
```handlebars
{{my-component elementId="a-really-cool-id"}}
```
If not manually set a default value will be provided by the framework.
Once rendered an element's `elementId` is considered immutable and you
should never change it. If you need to compute a dynamic value for the
`elementId`, you should do this when the component or element is being
instantiated:
```app/components/my-component.js
import Component from '@ember/component';
export default Component.extend({
init() {
this._super(...arguments);
let index = this.get('index');
this.set('elementId', 'component-id' + index);
}
});
```
@property elementId
@type String
@public
*/
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
@private
*/
findElementInParentElement: function (parentElem) {
var id = '#' + this.elementId;
return (0, _jquery.default)(id)[0] || (0, _jquery.default)(id, parentElem)[0];
},
/**
Called when a view is going to insert an element into the DOM.
@event willInsertElement
@public
*/
willInsertElement: K,
/**
Called when the element of the view has been inserted into the DOM.
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 and on itself afterwards.
@event didInsertElement
@public
*/
didInsertElement: 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
@public
*/
willClearRender: K,
/**
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
@private
*/
destroy: function () {
this._super.apply(this, arguments);
this._currentState.destroy(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
@public
*/
willDestroyElement: K,
/**
Called when the parentView property has changed.
@event parentViewDidChange
@private
*/
parentViewDidChange: K,
// ..........................................................
// 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 `` tag for views.
@property tagName
@type String
@default null
@public
*/
// We leave this null by default so we can tell the difference between
// the default case and a user-specified tag.
tagName: null,
// .......................................................
// CORE DISPLAY METHODS
//
/**
Setup a view, but do not finish waking it up.
* configure `childViews`
* register the view with the global views hash, which is used for event
dispatch
@method init
@private
*/
init: function () {
this._super.apply(this, arguments);
// tslint:disable-next-line:max-line-length
(true && !((0, _emberMeta.descriptorFor)(this, 'elementId') === undefined) && (0, _debug.assert)('You cannot use a computed property for the component\'s `elementId` (' + this + ').', (0, _emberMeta.descriptorFor)(this, 'elementId') === undefined));
// tslint:disable-next-line:max-line-length
(true && !((0, _emberMeta.descriptorFor)(this, 'tagName') === undefined) && (0, _debug.assert)('You cannot use a computed property for the component\'s `tagName` (' + this + ').', (0, _emberMeta.descriptorFor)(this, 'tagName') === undefined));
if (!this.elementId && this.tagName !== '') {
this.elementId = (0, _emberUtils.guidFor)(this);
}
(true && !(!this.render) && (0, _debug.assert)('Using a custom `.render` function is no longer supported.', !this.render));
},
// .......................................................
// EVENT HANDLING
//
/**
Handle events from `EventDispatcher`
@method handleEvent
@param eventName {String}
@param evt {Event}
@private
*/
handleEvent: function (eventName, evt) {
return this._currentState.handleEvent(this, eventName, evt);
}
});
});
enifed("ember-views/lib/system/action_manager", ["exports"], function (exports) {
"use strict";
exports.default = ActionManager;
/**
@module ember
*/
function ActionManager() {}
/**
Global action id hash.
@private
@property registeredActions
@type Object
*/
ActionManager.registeredActions = {};
});
enifed('ember-views/lib/system/event_dispatcher', ['exports', 'ember-owner', '@ember/polyfills', '@ember/debug', 'ember-metal', 'ember-runtime', 'ember-views/lib/system/jquery', 'ember-views/lib/system/action_manager', 'ember-views/lib/compat/fallback-view-registry', 'ember-views/lib/system/jquery_event_deprecation'], function (exports, _emberOwner, _polyfills, _debug, _emberMetal, _emberRuntime, _jquery, _action_manager, _fallbackViewRegistry, _jquery_event_deprecation) {
'use strict';
/**
@module ember
*/
var ROOT_ELEMENT_CLASS = 'ember-application';
var ROOT_ELEMENT_SELECTOR = '.' + ROOT_ELEMENT_CLASS;
var EVENT_MAP = {
mouseenter: 'mouseover',
mouseleave: 'mouseout'
};
/**
`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 = _emberRuntime.Object.extend({
/**
The set of events names (and associated handler function names) to be setup
and dispatched by the `EventDispatcher`. Modifications to this list can be done
at setup time, generally via the `Application.customEvents` hash.
To add new events to be listened to:
```javascript
import Application from '@ember/application';
let App = Application.create({
customEvents: {
paste: 'paste'
}
});
```
To prevent default events from being listened to:
```javascript
import Application from '@ember/application';
let App = Application.create({
customEvents: {
mouseenter: null,
mouseleave: null
}
});
```
@property events
@type Object
@private
*/
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',
init: function () {
var _this = this;
this._super();
(true && !(function () {
var owner = (0, _emberOwner.getOwner)(_this);
var environment = owner.lookup('-environment:main');
return environment.isInteractive;
}()) && (0, _debug.assert)('EventDispatcher should never be instantiated in fastboot mode. Please report this as an Ember bug.', function () {
var owner = (0, _emberOwner.getOwner)(_this);var environment = owner.lookup('-environment:main');return environment.isInteractive;
}()));
this._eventHandlers = Object.create(null);
},
/**
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 {Object}
*/
setup: function (addedEvents, _rootElement) {
var events = this._finalEvents = (0, _polyfills.assign)({}, (0, _emberMetal.get)(this, 'events'), addedEvents);
if (_rootElement !== undefined && _rootElement !== null) {
(0, _emberMetal.set)(this, 'rootElement', _rootElement);
}
var rootElementSelector = (0, _emberMetal.get)(this, 'rootElement');
var rootElement = void 0;
if (_jquery.jQueryDisabled) {
if (typeof rootElementSelector !== 'string') {
rootElement = rootElementSelector;
} else {
rootElement = document.querySelector(rootElementSelector);
}
(true && !(!rootElement.classList.contains(ROOT_ELEMENT_CLASS)) && (0, _debug.assert)('You cannot use the same root element (' + ((0, _emberMetal.get)(this, 'rootElement') || rootElement.tagName) + ') multiple times in an Ember.Application', !rootElement.classList.contains(ROOT_ELEMENT_CLASS)));
(true && !(function () {
var target = rootElement.parentNode;
do {
if (target.classList.contains(ROOT_ELEMENT_CLASS)) {
return false;
}
target = target.parentNode;
} while (target && target.nodeType === 1);
return true;
}()) && (0, _debug.assert)('You cannot make a new Ember.Application using a root element that is a descendent of an existing Ember.Application', function () {
var target = rootElement.parentNode;do {
if (target.classList.contains(ROOT_ELEMENT_CLASS)) {
return false;
}target = target.parentNode;
} while (target && target.nodeType === 1);return true;
}()));
(true && !(!rootElement.querySelector(ROOT_ELEMENT_SELECTOR)) && (0, _debug.assert)('You cannot make a new Ember.Application using a root element that is an ancestor of an existing Ember.Application', !rootElement.querySelector(ROOT_ELEMENT_SELECTOR)));
rootElement.classList.add(ROOT_ELEMENT_CLASS);
(true && !(rootElement.classList.contains(ROOT_ELEMENT_CLASS)) && (0, _debug.assert)('Unable to add \'' + ROOT_ELEMENT_CLASS + '\' class to root element (' + ((0, _emberMetal.get)(this, 'rootElement') || rootElement.tagName) + '). Make sure you set rootElement to the body or an element in the body.', rootElement.classList.contains(ROOT_ELEMENT_CLASS)));
} else {
rootElement = (0, _jquery.default)(rootElementSelector);
(true && !(!rootElement.is(ROOT_ELEMENT_SELECTOR)) && (0, _debug.assert)('You cannot use the same root element (' + (rootElement.selector || rootElement[0].tagName) + ') multiple times in an Ember.Application', !rootElement.is(ROOT_ELEMENT_SELECTOR)));
(true && !(!rootElement.closest(ROOT_ELEMENT_SELECTOR).length) && (0, _debug.assert)('You cannot make a new Ember.Application using a root element that is a descendent of an existing Ember.Application', !rootElement.closest(ROOT_ELEMENT_SELECTOR).length));
(true && !(!rootElement.find(ROOT_ELEMENT_SELECTOR).length) && (0, _debug.assert)('You cannot make a new Ember.Application using a root element that is an ancestor of an existing Ember.Application', !rootElement.find(ROOT_ELEMENT_SELECTOR).length));
rootElement.addClass(ROOT_ELEMENT_CLASS);
if (!rootElement.is(ROOT_ELEMENT_SELECTOR)) {
throw new TypeError('Unable to add \'' + ROOT_ELEMENT_CLASS + '\' class to root element (' + (rootElement.selector || rootElement[0].tagName) + '). Make sure you set rootElement to the body or an element in the body.');
}
}
var viewRegistry = this._getViewRegistry();
for (var event in events) {
if (events.hasOwnProperty(event)) {
this.setupHandler(rootElement, event, events[event], viewRegistry);
}
}
},
/**
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
@param {Object} viewRegistry
*/
setupHandler: function (rootElement, event, eventName, viewRegistry) {
if (eventName === null) {
return;
}
if (_jquery.jQueryDisabled) {
var viewHandler = function (target, event) {
var view = viewRegistry[target.id];
var result = true;
if (view) {
result = view.handleEvent(eventName, event);
}
return result;
};
var actionHandler = function (target, event) {
var actionId = target.getAttribute('data-ember-action');
var actions = _action_manager.default.registeredActions[actionId];
// In Glimmer2 this attribute is set to an empty string and an additional
// attribute it set for each action on a given element. In this case, the
// attributes need to be read so that a proper set of action handlers can
// be coalesced.
if (actionId === '') {
var attributes = target.attributes;
var attributeCount = attributes.length;
actions = [];
for (var i = 0; i < attributeCount; i++) {
var attr = attributes.item(i);
var attrName = attr.name;
if (attrName.indexOf('data-ember-action-') === 0) {
actions = actions.concat(_action_manager.default.registeredActions[attr.value]);
}
}
}
// We have to check for actions 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 (!actions) {
return;
}
for (var index = 0; index < actions.length; index++) {
var action = actions[index];
if (action && action.eventName === eventName) {
return action.handler(event);
}
}
};
// Special handling of events that don't bubble (event delegation does not work).
// Mimics the way this is handled in jQuery,
// see https://github.com/jquery/jquery/blob/899c56f6ada26821e8af12d9f35fa039100e838e/src/event.js#L666-L700
if (EVENT_MAP[event] !== undefined) {
var mappedEventType = EVENT_MAP[event];
var origEventType = event;
var createFakeEvent = function (eventType, event) {
var fakeEvent = document.createEvent('MouseEvent');
fakeEvent.initMouseEvent(eventType, false, false, event.view, event.detail, event.screenX, event.screenY, event.clientX, event.clientY, event.ctrlKey, event.altKey, event.shiftKey, event.metaKey, event.button, event.relatedTarget);
// fake event.target as we don't dispatch the event
Object.defineProperty(fakeEvent, 'target', { value: event.target, enumerable: true });
return fakeEvent;
};
var handleMappedEvent = this._eventHandlers[mappedEventType] = function (event) {
var target = event.target;
var related = event.relatedTarget;
while (target && target.nodeType === 1 && (!related || related !== target && !target.contains(related))) {
// mouseEnter/Leave don't bubble, so there is no logic to prevent it as with other events
if (viewRegistry[target.id]) {
viewHandler(target, createFakeEvent(origEventType, event));
} else if (target.hasAttribute('data-ember-action')) {
actionHandler(target, createFakeEvent(origEventType, event));
}
// separate mouseEnter/Leave events are dispatched for each listening element
// until the element (related) has been reached that the pointing device exited from/to
target = target.parentNode;
}
};
rootElement.addEventListener(mappedEventType, handleMappedEvent);
} else {
var handleEvent = this._eventHandlers[event] = function (event) {
var target = event.target;
do {
if (viewRegistry[target.id]) {
if (viewHandler(target, event) === false) {
event.preventDefault();
event.stopPropagation();
break;
}
} else if (target.hasAttribute('data-ember-action')) {
if (actionHandler(target, event) === false) {
break;
}
}
target = target.parentNode;
} while (target && target.nodeType === 1);
};
rootElement.addEventListener(event, handleEvent);
}
} else {
rootElement.on(event + '.ember', '.ember-view', function (evt) {
var view = viewRegistry[this.id];
var result = true;
if (view) {
result = view.handleEvent(eventName, (0, _jquery_event_deprecation.default)(evt));
}
return result;
});
rootElement.on(event + '.ember', '[data-ember-action]', function (evt) {
var attributes = evt.currentTarget.attributes;
var handledActions = [];
evt = (0, _jquery_event_deprecation.default)(evt);
for (var i = 0; i < attributes.length; i++) {
var attr = attributes.item(i);
var attrName = attr.name;
if (attrName.lastIndexOf('data-ember-action-', 0) !== -1) {
var action = _action_manager.default.registeredActions[attr.value];
// 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 && handledActions.indexOf(action) === -1) {
action.handler(evt);
// Action handlers can mutate state which in turn creates new attributes on the element.
// This effect could cause the `data-ember-action` attribute to shift down and be invoked twice.
// To avoid this, we keep track of which actions have been handled.
handledActions.push(action);
}
}
}
});
}
},
_getViewRegistry: function () {
var owner = (0, _emberOwner.getOwner)(this);
var viewRegistry = owner && owner.lookup('-view-registry:main') || _fallbackViewRegistry.default;
return viewRegistry;
},
destroy: function () {
var rootElementSelector = (0, _emberMetal.get)(this, 'rootElement');
var rootElement = void 0;
if (rootElementSelector.nodeType) {
rootElement = rootElementSelector;
} else {
rootElement = document.querySelector(rootElementSelector);
}
if (!rootElement) {
return;
}
if (_jquery.jQueryDisabled) {
for (var event in this._eventHandlers) {
rootElement.removeEventListener(event, this._eventHandlers[event]);
}
} else {
(0, _jquery.default)(rootElementSelector).off('.ember', '**');
}
rootElement.classList.remove(ROOT_ELEMENT_CLASS);
return this._super.apply(this, arguments);
},
toString: function () {
return '(EventDispatcher)';
}
});
});
enifed('ember-views/lib/system/jquery', ['exports', 'ember-environment', 'ember-browser-environment'], function (exports, _emberEnvironment, _emberBrowserEnvironment) {
'use strict';
exports.jQueryDisabled = undefined;
var jQuery = void 0;
var jQueryDisabled = exports.jQueryDisabled = _emberEnvironment.ENV._JQUERY_INTEGRATION === false;
if (_emberBrowserEnvironment.hasDOM) {
jQuery = _emberEnvironment.context.imports.jQuery;
if (!jQueryDisabled && jQuery) {
if (jQuery.event.addProp) {
jQuery.event.addProp('dataTransfer');
} else {
// http://www.whatwg.org/specs/web-apps/current-work/multipage/dnd.html#dndevents
['dragstart', 'drag', 'dragenter', 'dragleave', 'dragover', 'drop', 'dragend'].forEach(function (eventName) {
jQuery.event.fixHooks[eventName] = {
props: ['dataTransfer']
};
});
}
} else {
exports.jQueryDisabled = jQueryDisabled = true;
}
}
exports.default = jQueryDisabled ? undefined : jQuery;
});
enifed('ember-views/lib/system/jquery_event_deprecation', ['exports', '@ember/debug', 'ember-environment', 'ember-utils'], function (exports, _debug, _emberEnvironment, _emberUtils) {
'use strict';
exports.default = addJQueryEventDeprecation;
function addJQueryEventDeprecation(jqEvent) {
if (!true || !_emberUtils.HAS_NATIVE_PROXY) {
return jqEvent;
}
var boundFunctions = new Map();
// wrap the jQuery event in a Proxy to add the deprecation message for originalEvent, according to RFC#294
// we need a native Proxy here, so we can make sure that the internal use of originalEvent in jQuery itself does
// not trigger a deprecation
return new Proxy(jqEvent, {
get: function (target, name) {
switch (name) {
case 'originalEvent':
(true && !(function (EmberENV) {
// this deprecation is intentionally checking `global.EmberENV` /
// `global.ENV` so that we can ensure we _only_ deprecate in the
// case where jQuery integration is enabled implicitly (e.g.
// "defaulted" to enabled) as opposed to when the user explicitly
// opts in to using jQuery
if (typeof EmberENV !== 'object' || EmberENV === null) return false;
return EmberENV._JQUERY_INTEGRATION === true;
}(_emberEnvironment.global.EmberENV || _emberEnvironment.global.ENV)) && (0, _debug.deprecate)('Accessing jQuery.Event specific properties is deprecated. Either use the ember-jquery-legacy addon to normalize events to native events, or explicitly opt into jQuery integration using @ember/optional-features.', function (EmberENV) {
if (typeof EmberENV !== 'object' || EmberENV === null) return false;return EmberENV._JQUERY_INTEGRATION === true;
}(_emberEnvironment.global.EmberENV || _emberEnvironment.global.ENV), {
id: 'ember-views.event-dispatcher.jquery-event',
until: '4.0.0',
url: 'https://emberjs.com/deprecations/v3.x#toc_jquery-event'
}));
return target[name];
// provide an escape hatch for ember-jquery-legacy to access originalEvent without a deprecation
case '__originalEvent':
return target.originalEvent;
default:
if (typeof target[name] === 'function') {
// cache functions for reuse
if (!boundFunctions.has(name)) {
// for jQuery.Event methods call them with `target` as the `this` context, so they will access
// `originalEvent` from the original jQuery event, not our proxy, thus not trigger the deprecation
boundFunctions.set(name, target[name].bind(target));
}
return boundFunctions.get(name);
}
// same for jQuery's getter functions for simple properties
return target[name];
}
}
});
} /* global Proxy */
});
enifed('ember-views/lib/system/lookup_partial', ['exports', '@ember/debug', '@ember/error'], function (exports, _debug, _error) {
'use strict';
exports.default = lookupPartial;
exports.hasPartial = hasPartial;
function parseUnderscoredName(templateName) {
var nameParts = templateName.split('/');
var lastPart = nameParts[nameParts.length - 1];
nameParts[nameParts.length - 1] = '_' + lastPart;
return nameParts.join('/');
}
function lookupPartial(templateName, owner) {
if (templateName == null) {
return;
}
var template = templateFor(owner, parseUnderscoredName(templateName), templateName);
(true && !(!!template) && (0, _debug.assert)('Unable to find partial with name "' + templateName + '"', !!template));
return template;
}
function hasPartial(name, owner) {
if (!owner) {
throw new _error.default('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 owner.hasRegistration('template:' + parseUnderscoredName(name)) || owner.hasRegistration('template:' + name);
}
function templateFor(owner, underscored, name) {
if (!name) {
return;
}
(true && !(name.indexOf('.') === -1) && (0, _debug.assert)('templateNames are not allowed to contain periods: ' + name, name.indexOf('.') === -1));
if (!owner) {
throw new _error.default('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 owner.lookup('template:' + underscored) || owner.lookup('template:' + name);
}
});
enifed('ember-views/lib/system/utils', ['exports', 'ember-owner', 'ember-utils'], function (exports, _emberOwner, _emberUtils) {
'use strict';
exports.elMatches = undefined;
exports.isSimpleClick = isSimpleClick;
exports.constructStyleDeprecationMessage = constructStyleDeprecationMessage;
exports.getRootViews = getRootViews;
exports.getViewId = getViewId;
exports.getViewElement = getViewElement;
exports.initViewElement = initViewElement;
exports.setViewElement = setViewElement;
exports.getChildViews = getChildViews;
exports.initChildViews = initChildViews;
exports.addChildView = addChildView;
exports.collectChildViews = collectChildViews;
exports.getViewBounds = getViewBounds;
exports.getViewRange = getViewRange;
exports.getViewClientRects = getViewClientRects;
exports.getViewBoundingClientRect = getViewBoundingClientRect;
exports.matches = matches;
/**
@module ember
*/
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;
}
/* globals Element */
function constructStyleDeprecationMessage(affectedStyle) {
return '' + 'Binding style attributes may introduce cross-site scripting vulnerabilities; ' + 'please ensure that values being bound are properly escaped. For more information, ' + 'including how to disable this warning, see ' + 'https://emberjs.com/deprecations/v1.x/#toc_binding-style-attributes. ' + 'Style affected: "' + affectedStyle + '"';
}
/**
@private
@method getRootViews
@param {Object} owner
*/
function getRootViews(owner) {
var registry = owner.lookup('-view-registry:main');
var rootViews = [];
Object.keys(registry).forEach(function (id) {
var view = registry[id];
if (view.parentView === null) {
rootViews.push(view);
}
});
return rootViews;
}
/**
@private
@method getViewId
@param {Ember.View} view
*/
function getViewId(view) {
if (view.tagName !== '' && view.elementId) {
return view.elementId;
} else {
return (0, _emberUtils.guidFor)(view);
}
}
var VIEW_ELEMENT = (0, _emberUtils.symbol)('VIEW_ELEMENT');
/**
@private
@method getViewElement
@param {Ember.View} view
*/
function getViewElement(view) {
return view[VIEW_ELEMENT];
}
function initViewElement(view) {
view[VIEW_ELEMENT] = null;
}
function setViewElement(view, element) {
return view[VIEW_ELEMENT] = element;
}
var CHILD_VIEW_IDS = new WeakMap();
/**
@private
@method getChildViews
@param {Ember.View} view
*/
function getChildViews(view) {
var owner = (0, _emberOwner.getOwner)(view);
var registry = owner.lookup('-view-registry:main');
return collectChildViews(view, registry);
}
function initChildViews(view) {
var childViews = new Set();
CHILD_VIEW_IDS.set(view, childViews);
return childViews;
}
function addChildView(parent, child) {
var childViews = CHILD_VIEW_IDS.get(parent);
if (childViews === undefined) {
childViews = initChildViews(parent);
}
childViews.add(getViewId(child));
}
function collectChildViews(view, registry) {
var views = [];
var childViews = CHILD_VIEW_IDS.get(view);
if (childViews !== undefined) {
childViews.forEach(function (id) {
var view = registry[id];
if (view && !view.isDestroying && !view.isDestroyed) {
views.push(view);
}
});
}
return views;
}
/**
@private
@method getViewBounds
@param {Ember.View} view
*/
function getViewBounds(view) {
return view.renderer.getBounds(view);
}
/**
@private
@method getViewRange
@param {Ember.View} view
*/
function getViewRange(view) {
var bounds = getViewBounds(view);
var range = document.createRange();
range.setStartBefore(bounds.firstNode);
range.setEndAfter(bounds.lastNode);
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 Inspector
and may not work on older browsers.
@private
@method getViewClientRects
@param {Ember.View} view
*/
function getViewClientRects(view) {
var range = getViewRange(view);
return range.getClientRects();
}
/**
`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 Inspector
and may not work on older browsers.
@private
@method getViewBoundingClientRect
@param {Ember.View} view
*/
function getViewBoundingClientRect(view) {
var range = getViewRange(view);
return range.getBoundingClientRect();
}
/**
Determines if the element matches the specified selector.
@private
@method matches
@param {DOMElement} el
@param {String} selector
*/
var elMatches = exports.elMatches = typeof Element !== 'undefined' && (Element.prototype.matches || Element.prototype.matchesSelector || Element.prototype.mozMatchesSelector || Element.prototype.msMatchesSelector || Element.prototype.oMatchesSelector || Element.prototype.webkitMatchesSelector);
function matches(el, selector) {
return elMatches.call(el, selector);
}
});
enifed('ember-views/lib/utils/lookup-component', ['exports'], function (exports) {
'use strict';
exports.default = lookupComponent;
function lookupModuleUnificationComponentPair(componentLookup, owner, name, options) {
var localComponent = componentLookup.componentFor(name, owner, options);
var localLayout = componentLookup.layoutFor(name, owner, options);
var globalComponent = componentLookup.componentFor(name, owner);
var globalLayout = componentLookup.layoutFor(name, owner);
// TODO: we shouldn't have to recheck fallback, we should have a lookup that doesn't fallback
if (localComponent !== undefined && globalComponent !== undefined && globalComponent.class === localComponent.class) {
localComponent = undefined;
}
if (localLayout !== undefined && globalLayout !== undefined && localLayout.referrer.moduleName === globalLayout.referrer.moduleName) {
localLayout = undefined;
}
if (localLayout !== undefined || localComponent !== undefined) {
return { layout: localLayout, component: localComponent };
}
return { layout: globalLayout, component: globalComponent };
}
function lookupComponentPair(componentLookup, owner, name, options) {
if (false) {
return lookupModuleUnificationComponentPair(componentLookup, owner, name, options);
}
var component = componentLookup.componentFor(name, owner, options);
var layout = componentLookup.layoutFor(name, owner, options);
var result = { layout: layout, component: component };
return result;
}
function lookupComponent(owner, name, options) {
var componentLookup = owner.lookup('component-lookup:main');
if (options && (options.source || options.namespace)) {
var localResult = lookupComponentPair(componentLookup, owner, name, options);
if (localResult.component || localResult.layout) {
return localResult;
}
}
return lookupComponentPair(componentLookup, owner, name);
}
});
enifed('ember-views/lib/views/core_view', ['exports', 'ember-runtime', 'ember-views/lib/system/utils', 'ember-views/lib/views/states'], function (exports, _emberRuntime, _utils, _states) {
'use strict';
/**
`Ember.CoreView` is an abstract class that exists to give view-like behavior
to both Ember's main view class `Component` and other classes that don't need
the full functionality of `Component`.
Unless you have specific needs for `CoreView`, you will use `Component`
in your applications.
@class CoreView
@namespace Ember
@extends EmberObject
@deprecated Use `Component` instead.
@uses Evented
@uses Ember.ActionHandler
@private
*/
var CoreView = _emberRuntime.FrameworkObject.extend(_emberRuntime.Evented, _emberRuntime.ActionHandler, {
isView: true,
_states: (0, _states.cloneStates)(_states.states),
init: function () {
this._super.apply(this, arguments);
this._state = 'preRender';
this._currentState = this._states.preRender;
(0, _utils.initViewElement)(this);
if (!this.renderer) {
throw new Error('Cannot instantiate a component without a renderer. Please ensure that you are creating ' + this + ' with a proper container/registry.');
}
},
/**
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
@private
*/
parentView: null,
instrumentDetails: function (hash) {
hash.object = this.toString();
hash.containerKey = this._debugContainerKey;
hash.view = this;
return hash;
},
trigger: function (name) {
for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
args[_key - 1] = arguments[_key];
}
this._super.apply(this, arguments);
var method = this[name];
if (typeof method === 'function') {
return method.apply(this, args);
}
},
has: function (name) {
return typeof this[name] === 'function' || this._super(name);
}
});
CoreView.reopenClass({
isViewFactory: true
});
exports.default = CoreView;
});
enifed('ember-views/lib/views/states', ['exports', '@ember/polyfills', 'ember-views/lib/views/states/default', 'ember-views/lib/views/states/pre_render', 'ember-views/lib/views/states/has_element', 'ember-views/lib/views/states/in_dom', 'ember-views/lib/views/states/destroying'], function (exports, _polyfills, _default2, _pre_render, _has_element, _in_dom, _destroying) {
'use strict';
exports.states = undefined;
exports.cloneStates = cloneStates;
function cloneStates(from) {
var into = {};
into._default = {};
into.preRender = Object.create(into._default);
into.destroying = Object.create(into._default);
into.hasElement = Object.create(into._default);
into.inDOM = Object.create(into.hasElement);
for (var stateName in from) {
if (!from.hasOwnProperty(stateName)) {
continue;
}
(0, _polyfills.assign)(into[stateName], from[stateName]);
}
return into;
}
/*
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
* 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.
*/
var states = exports.states = {
_default: _default2.default,
preRender: _pre_render.default,
inDOM: _in_dom.default,
hasElement: _has_element.default,
destroying: _destroying.default
};
});
enifed("ember-views/lib/views/states/default", ["exports", "@ember/error"], function (exports, _error) {
"use strict";
exports.default = {
// appendChild is only legal while rendering the buffer.
appendChild: function () {
throw new _error.default("You can't use appendChild outside of the rendering process");
},
// Handle events from `Ember.EventDispatcher`
handleEvent: function () {
return true; // continue event propagation
},
rerender: function () {},
destroy: function () {}
};
});
enifed('ember-views/lib/views/states/destroying', ['exports', '@ember/polyfills', '@ember/error', 'ember-views/lib/views/states/default'], function (exports, _polyfills, _error, _default2) {
'use strict';
var destroying = Object.create(_default2.default);
(0, _polyfills.assign)(destroying, {
appendChild: function () {
throw new _error.default("You can't call appendChild on a view being destroyed");
},
rerender: function () {
throw new _error.default("You can't call rerender on a view being destroyed");
}
});
exports.default = destroying;
});
enifed('ember-views/lib/views/states/has_element', ['exports', '@ember/polyfills', 'ember-views/lib/views/states/default', '@ember/runloop', '@ember/instrumentation'], function (exports, _polyfills, _default2, _runloop, _instrumentation) {
'use strict';
var hasElement = Object.create(_default2.default);
(0, _polyfills.assign)(hasElement, {
rerender: function (view) {
view.renderer.rerender(view);
},
destroy: function (view) {
view.renderer.remove(view);
},
handleEvent: function (view, eventName, event) {
if (view.has(eventName)) {
// Handler should be able to re-dispatch events, so we don't
// preventDefault or stopPropagation.
return (0, _instrumentation.flaggedInstrument)('interaction.' + eventName, { event: event, view: view }, function () {
return (0, _runloop.join)(view, view.trigger, eventName, event);
});
} else {
return true; // continue event propagation
}
}
});
exports.default = hasElement;
});
enifed('ember-views/lib/views/states/in_dom', ['exports', '@ember/polyfills', 'ember-metal', '@ember/error', 'ember-views/lib/views/states/has_element'], function (exports, _polyfills, _emberMetal, _error, _has_element) {
'use strict';
var inDOM = Object.create(_has_element.default);
(0, _polyfills.assign)(inDOM, {
enter: function (view) {
// Register the view for event handling. This hash is used by
// Ember.EventDispatcher to dispatch incoming events.
view.renderer.register(view);
if (true) {
(0, _emberMetal.addObserver)(view, 'elementId', function () {
throw new _error.default("Changing a view's elementId after creation is not allowed");
});
}
},
exit: function (view) {
view.renderer.unregister(view);
}
});
exports.default = inDOM;
});
enifed('ember-views/lib/views/states/pre_render', ['exports', 'ember-views/lib/views/states/default'], function (exports, _default2) {
'use strict';
exports.default = Object.create(_default2.default);
});
enifed('ember/index', ['exports', 'require', 'ember-environment', 'node-module', 'ember-utils', 'container', '@ember/instrumentation', 'ember-meta', 'ember-metal', '@ember/canary-features', '@ember/debug', 'backburner', 'ember-console', '@ember/controller', '@ember/controller/lib/controller_mixin', '@ember/string', '@ember/service', '@ember/object/computed', 'ember-runtime', 'ember-glimmer', 'ember/version', 'ember-views', 'ember-routing', 'ember-extension-support', '@ember/error', '@ember/runloop', 'ember-error-handling', 'ember-owner', '@ember/application', '@ember/application/globals-resolver', '@ember/application/instance', '@ember/engine', '@ember/engine/instance', '@ember/map', '@ember/map/with-default', '@ember/map/lib/ordered-set', '@ember/polyfills', '@ember/deprecated-features'], function (exports, _require2, _emberEnvironment, _nodeModule, _emberUtils, _container, _instrumentation, _emberMeta, _emberMetal, _canaryFeatures, _debug, _backburner, _emberConsole, _controller, _controller_mixin, _string, _service, _computed, _emberRuntime, _emberGlimmer, _version, _emberViews, _emberRouting, _emberExtensionSupport, _error, _runloop, _emberErrorHandling, _emberOwner, _application, _globalsResolver, _instance, _engine, _instance2, _map, _withDefault, _orderedSet, _polyfills, _deprecatedFeatures) {
'use strict';
// ****ember-environment****
// eslint-disable-next-line import/no-unresolved
var Ember = typeof _emberEnvironment.context.imports.Ember === 'object' && _emberEnvironment.context.imports.Ember || {};
Ember.isNamespace = true;
Ember.toString = function () {
return 'Ember';
};
Object.defineProperty(Ember, 'ENV', {
get: _emberEnvironment.getENV,
enumerable: false
});
Object.defineProperty(Ember, 'lookup', {
get: _emberEnvironment.getLookup,
set: _emberEnvironment.setLookup,
enumerable: false
});
if (_deprecatedFeatures.EMBER_EXTEND_PROTOTYPES) {
Object.defineProperty(Ember, 'EXTEND_PROTOTYPES', {
enumerable: false,
get: function () {
(true && !(false) && (0, _debug.deprecate)('Accessing Ember.EXTEND_PROTOTYPES is deprecated, please migrate to Ember.ENV.EXTEND_PROTOTYPES', false, {
id: 'ember-env.old-extend-prototypes',
until: '4.0.0'
}));
return _emberEnvironment.ENV.EXTEND_PROTOTYPES;
}
});
}
// ****@ember/application****
Ember.getOwner = _emberOwner.getOwner;
Ember.setOwner = _emberOwner.setOwner;
Ember.Application = _application.default;
Ember.DefaultResolver = Ember.Resolver = _globalsResolver.default;
Ember.ApplicationInstance = _instance.default;
// ****@ember/engine****
Ember.Engine = _engine.default;
Ember.EngineInstance = _instance2.default;
// ****@ember/map****
Ember.OrderedSet = _orderedSet.default;
Ember.__OrderedSet__ = _orderedSet.__OrderedSet__;
Ember.Map = _map.default;
Ember.MapWithDefault = _withDefault.default;
// ****@ember/polyfills****
Ember.assign = _polyfills.assign;
Ember.merge = _polyfills.merge;
// ****ember-utils****
Ember.generateGuid = _emberUtils.generateGuid;
Ember.GUID_KEY = _emberUtils.GUID_KEY;
Ember.guidFor = _emberUtils.guidFor;
Ember.inspect = _emberUtils.inspect;
Ember.makeArray = _emberUtils.makeArray;
Ember.canInvoke = _emberUtils.canInvoke;
Ember.tryInvoke = _emberUtils.tryInvoke;
Ember.wrap = _emberUtils.wrap;
Ember.uuid = _emberUtils.uuid;
Ember.NAME_KEY = _emberUtils.NAME_KEY;
Ember._Cache = _emberUtils.Cache;
// ****container****
Ember.Container = _container.Container;
Ember.Registry = _container.Registry;
// ****@ember/debug****
Ember.assert = _debug.assert;
Ember.warn = _debug.warn;
Ember.debug = _debug.debug;
Ember.deprecate = _debug.deprecate;
Ember.deprecateFunc = _debug.deprecateFunc;
Ember.runInDebug = _debug.runInDebug;
// ****@ember/error****
Ember.Error = _error.default;
/**
@public
@class Ember.Debug
*/
Ember.Debug = {
registerDeprecationHandler: _debug.registerDeprecationHandler,
registerWarnHandler: _debug.registerWarnHandler
};
// ****@ember/instrumentation****
Ember.instrument = _instrumentation.instrument;
Ember.subscribe = _instrumentation.subscribe;
Ember.Instrumentation = {
instrument: _instrumentation.instrument,
subscribe: _instrumentation.subscribe,
unsubscribe: _instrumentation.unsubscribe,
reset: _instrumentation.reset
};
// ****@ember/runloop****
// Using _globalsRun here so that mutating the function (adding
// `next`, `later`, etc to it) is only available in globals builds
Ember.run = _runloop._globalsRun;
Ember.run.backburner = _runloop.backburner;
Ember.run.begin = _runloop.begin;
Ember.run.bind = _runloop.bind;
Ember.run.cancel = _runloop.cancel;
Ember.run.debounce = _runloop.debounce;
Ember.run.end = _runloop.end;
Ember.run.hasScheduledTimers = _runloop.hasScheduledTimers;
Ember.run.join = _runloop.join;
Ember.run.later = _runloop.later;
Ember.run.next = _runloop.next;
Ember.run.once = _runloop.once;
Ember.run.schedule = _runloop.schedule;
Ember.run.scheduleOnce = _runloop.scheduleOnce;
Ember.run.throttle = _runloop.throttle;
Ember.run.cancelTimers = _runloop.cancelTimers;
Object.defineProperty(Ember.run, 'currentRunLoop', {
get: _runloop.getCurrentRunLoop,
enumerable: false
});
// ****ember-metal****
// Using _globalsComputed here so that mutating the function is only available
// in globals builds
var computed = _emberMetal._globalsComputed;
Ember.computed = computed;
computed.alias = _emberMetal.alias;
Ember.ComputedProperty = _emberMetal.ComputedProperty;
Ember.cacheFor = _emberMetal.getCachedValueFor;
Ember.meta = _emberMeta.meta;
Ember.get = _emberMetal.get;
Ember.getWithDefault = _emberMetal.getWithDefault;
Ember._getPath = _emberMetal._getPath;
Ember.set = _emberMetal.set;
Ember.trySet = _emberMetal.trySet;
Ember.FEATURES = (0, _polyfills.assign)({ isEnabled: _canaryFeatures.isEnabled }, _canaryFeatures.FEATURES);
Ember._Cache = _emberUtils.Cache;
Ember.on = _emberMetal.on;
Ember.addListener = _emberMetal.addListener;
Ember.removeListener = _emberMetal.removeListener;
Ember.sendEvent = _emberMetal.sendEvent;
Ember.hasListeners = _emberMetal.hasListeners;
Ember.isNone = _emberMetal.isNone;
Ember.isEmpty = _emberMetal.isEmpty;
Ember.isBlank = _emberMetal.isBlank;
Ember.isPresent = _emberMetal.isPresent;
if (_deprecatedFeatures.PROPERTY_WILL_CHANGE) {
Ember.propertyWillChange = _emberMetal.propertyWillChange;
}
if (_deprecatedFeatures.PROPERTY_DID_CHANGE) {
Ember.propertyDidChange = _emberMetal.propertyDidChange;
}
Ember.notifyPropertyChange = _emberMetal.notifyPropertyChange;
Ember.overrideChains = _emberMetal.overrideChains;
Ember.beginPropertyChanges = _emberMetal.beginPropertyChanges;
Ember.endPropertyChanges = _emberMetal.endPropertyChanges;
Ember.changeProperties = _emberMetal.changeProperties;
Ember.platform = {
defineProperty: true,
hasPropertyAccessors: true
};
Ember.defineProperty = _emberMetal.defineProperty;
Ember.watchKey = _emberMetal.watchKey;
Ember.unwatchKey = _emberMetal.unwatchKey;
Ember.removeChainWatcher = _emberMetal.removeChainWatcher;
Ember._ChainNode = _emberMetal.ChainNode;
Ember.finishChains = _emberMetal.finishChains;
Ember.watchPath = _emberMetal.watchPath;
Ember.unwatchPath = _emberMetal.unwatchPath;
Ember.watch = _emberMetal.watch;
Ember.isWatching = _emberMetal.isWatching;
Ember.unwatch = _emberMetal.unwatch;
Ember.destroy = _emberMeta.deleteMeta;
Ember.libraries = _emberMetal.libraries;
Ember.getProperties = _emberMetal.getProperties;
Ember.setProperties = _emberMetal.setProperties;
Ember.expandProperties = _emberMetal.expandProperties;
Ember.addObserver = _emberMetal.addObserver;
Ember.removeObserver = _emberMetal.removeObserver;
Ember.aliasMethod = _emberMetal.aliasMethod;
Ember.observer = _emberMetal.observer;
Ember.mixin = _emberMetal.mixin;
Ember.Mixin = _emberMetal.Mixin;
/**
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
import $ from 'jquery';
Ember.onerror = function(error) {
$.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
@public
*/
Object.defineProperty(Ember, 'onerror', {
get: _emberErrorHandling.getOnerror,
set: _emberErrorHandling.setOnerror,
enumerable: false
});
Object.defineProperty(Ember, 'testing', {
get: _debug.isTesting,
set: _debug.setTesting,
enumerable: false
});
Ember._Backburner = _backburner.default;
// ****ember-console****
if (_deprecatedFeatures.LOGGER) {
Ember.Logger = _emberConsole.default;
}
// ****ember-runtime****
Ember.A = _emberRuntime.A;
Ember.String = {
loc: _string.loc,
w: _string.w,
dasherize: _string.dasherize,
decamelize: _string.decamelize,
camelize: _string.camelize,
classify: _string.classify,
underscore: _string.underscore,
capitalize: _string.capitalize
};
Ember.Object = _emberRuntime.Object;
Ember._RegistryProxyMixin = _emberRuntime.RegistryProxyMixin;
Ember._ContainerProxyMixin = _emberRuntime.ContainerProxyMixin;
Ember.compare = _emberRuntime.compare;
Ember.copy = _emberRuntime.copy;
Ember.isEqual = _emberRuntime.isEqual;
/**
@module ember
*/
/**
Namespace for injection helper methods.
@class inject
@namespace Ember
@static
@public
*/
Ember.inject = function inject() {
(true && !(false) && (0, _debug.assert)('Injected properties must be created through helpers, see \'' + Object.keys(inject).map(function (k) {
return '\'inject.' + k + '\'';
}).join(' or ') + '\''));
};
Ember.inject.service = _service.inject;
Ember.inject.controller = _controller.inject;
Ember.Array = _emberRuntime.Array;
Ember.Comparable = _emberRuntime.Comparable;
Ember.Enumerable = _emberRuntime.Enumerable;
Ember.ArrayProxy = _emberRuntime.ArrayProxy;
Ember.ObjectProxy = _emberRuntime.ObjectProxy;
Ember.ActionHandler = _emberRuntime.ActionHandler;
Ember.CoreObject = _emberRuntime.CoreObject;
Ember.NativeArray = _emberRuntime.NativeArray;
Ember.Copyable = _emberRuntime.Copyable;
Ember.MutableEnumerable = _emberRuntime.MutableEnumerable;
Ember.MutableArray = _emberRuntime.MutableArray;
Ember.TargetActionSupport = _emberRuntime.TargetActionSupport;
Ember.Evented = _emberRuntime.Evented;
Ember.PromiseProxyMixin = _emberRuntime.PromiseProxyMixin;
Ember.Observable = _emberRuntime.Observable;
Ember.typeOf = _emberRuntime.typeOf;
Ember.isArray = _emberRuntime.isArray;
Ember.Object = _emberRuntime.Object;
Ember.onLoad = _application.onLoad;
Ember.runLoadHooks = _application.runLoadHooks;
Ember.Controller = _controller.default;
Ember.ControllerMixin = _controller_mixin.default;
Ember.Service = _service.default;
Ember._ProxyMixin = _emberRuntime._ProxyMixin;
Ember.RSVP = _emberRuntime.RSVP;
Ember.Namespace = _emberRuntime.Namespace;
computed.empty = _computed.empty;
computed.notEmpty = _computed.notEmpty;
computed.none = _computed.none;
computed.not = _computed.not;
computed.bool = _computed.bool;
computed.match = _computed.match;
computed.equal = _computed.equal;
computed.gt = _computed.gt;
computed.gte = _computed.gte;
computed.lt = _computed.lt;
computed.lte = _computed.lte;
computed.oneWay = _computed.oneWay;
computed.reads = _computed.oneWay;
computed.readOnly = _computed.readOnly;
computed.deprecatingAlias = _computed.deprecatingAlias;
computed.and = _computed.and;
computed.or = _computed.or;
computed.sum = _computed.sum;
computed.min = _computed.min;
computed.max = _computed.max;
computed.map = _computed.map;
computed.sort = _computed.sort;
computed.setDiff = _computed.setDiff;
computed.mapBy = _computed.mapBy;
computed.filter = _computed.filter;
computed.filterBy = _computed.filterBy;
computed.uniq = _computed.uniq;
computed.uniqBy = _computed.uniqBy;
computed.union = _computed.union;
computed.intersect = _computed.intersect;
computed.collect = _computed.collect;
/**
Defines the hash of localized strings for the current language. Used by
the `String.loc` helper. To localize, add string values to this
hash.
@property STRINGS
@for Ember
@type Object
@private
*/
Object.defineProperty(Ember, 'STRINGS', {
configurable: false,
get: _string._getStrings,
set: _string._setStrings
});
/**
Whether searching on the global for new Namespace instances is enabled.
This is only exported here as to not break any addons. Given the new
visit API, you will have issues if you treat this as a indicator of
booted.
Internally this is only exposing a flag in Namespace.
@property BOOTED
@for Ember
@type Boolean
@private
*/
Object.defineProperty(Ember, 'BOOTED', {
configurable: false,
enumerable: false,
get: _emberMetal.isNamespaceSearchDisabled,
set: _emberMetal.setNamespaceSearchDisabled
});
// ****ember-glimmer****
Ember.Component = _emberGlimmer.Component;
_emberGlimmer.Helper.helper = _emberGlimmer.helper;
Ember.Helper = _emberGlimmer.Helper;
Ember.Checkbox = _emberGlimmer.Checkbox;
Ember.TextField = _emberGlimmer.TextField;
Ember.TextArea = _emberGlimmer.TextArea;
Ember.LinkComponent = _emberGlimmer.LinkComponent;
Ember._setComponentManager = _emberGlimmer.setComponentManager;
Ember._componentManagerCapabilities = _emberGlimmer.capabilities;
Ember.Handlebars = {
template: _emberGlimmer.template,
Utils: {
escapeExpression: _emberGlimmer.escapeExpression
}
};
Ember.HTMLBars = {
template: _emberGlimmer.template
};
if (_emberEnvironment.ENV.EXTEND_PROTOTYPES.String) {
String.prototype.htmlSafe = function () {
return (0, _emberGlimmer.htmlSafe)(this);
};
}
Ember.String.htmlSafe = _emberGlimmer.htmlSafe;
Ember.String.isHTMLSafe = _emberGlimmer.isHTMLSafe;
/**
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 Object
@private
*/
Object.defineProperty(Ember, 'TEMPLATES', {
get: _emberGlimmer.getTemplates,
set: _emberGlimmer.setTemplates,
configurable: false,
enumerable: false
});
/**
The semantic version
@property VERSION
@type String
@public
*/
Ember.VERSION = _version.default;
// ****ember-views****
if (!_emberViews.jQueryDisabled) {
Ember.$ = _emberViews.jQuery;
}
Ember.ViewUtils = {
isSimpleClick: _emberViews.isSimpleClick,
getViewElement: _emberViews.getViewElement,
getViewBounds: _emberViews.getViewBounds,
getViewClientRects: _emberViews.getViewClientRects,
getViewBoundingClientRect: _emberViews.getViewBoundingClientRect,
getRootViews: _emberViews.getRootViews,
getChildViews: _emberViews.getChildViews,
isSerializationFirstNode: _emberGlimmer.isSerializationFirstNode
};
Ember.TextSupport = _emberViews.TextSupport;
Ember.ComponentLookup = _emberViews.ComponentLookup;
Ember.EventDispatcher = _emberViews.EventDispatcher;
// ****ember-routing****
Ember.Location = _emberRouting.Location;
Ember.AutoLocation = _emberRouting.AutoLocation;
Ember.HashLocation = _emberRouting.HashLocation;
Ember.HistoryLocation = _emberRouting.HistoryLocation;
Ember.NoneLocation = _emberRouting.NoneLocation;
Ember.controllerFor = _emberRouting.controllerFor;
Ember.generateControllerFactory = _emberRouting.generateControllerFactory;
Ember.generateController = _emberRouting.generateController;
Ember.RouterDSL = _emberRouting.RouterDSL;
Ember.Router = _emberRouting.Router;
Ember.Route = _emberRouting.Route;
(0, _application.runLoadHooks)('Ember.Application', _application.default);
Ember.DataAdapter = _emberExtensionSupport.DataAdapter;
Ember.ContainerDebugAdapter = _emberExtensionSupport.ContainerDebugAdapter;
if ((0, _require2.has)('ember-template-compiler')) {
(0, _require2.default)('ember-template-compiler');
}
// do this to ensure that Ember.Test is defined properly on the global
// if it is present.
if ((0, _require2.has)('ember-testing')) {
var testing = (0, _require2.default)('ember-testing');
Ember.Test = testing.Test;
Ember.Test.Adapter = testing.Adapter;
Ember.Test.QUnitAdapter = testing.QUnitAdapter;
Ember.setupForTesting = testing.setupForTesting;
}
(0, _application.runLoadHooks)('Ember');
exports.default = Ember;
if (_nodeModule.IS_NODE) {
_nodeModule.module.exports = Ember;
} else {
_emberEnvironment.context.exports.Ember = _emberEnvironment.context.exports.Em = Ember;
}
/**
@module jquery
@public
*/
/**
@class jquery
@public
@static
*/
/**
Alias for jQuery
@for jquery
@method $
@static
@public
*/
});
enifed("ember/version", ["exports"], function (exports) {
"use strict";
exports.default = "3.5.1";
});
/*global enifed, module */
enifed('node-module', ['exports'], function(_exports) {
var IS_NODE = typeof module === 'object' && typeof module.require === 'function';
if (IS_NODE) {
_exports.require = module.require;
_exports.module = module;
_exports.IS_NODE = IS_NODE;
} else {
_exports.require = null;
_exports.module = null;
_exports.IS_NODE = IS_NODE;
}
});
enifed("route-recognizer", ["exports"], function (exports) {
"use strict";
var createObject = Object.create;
function createMap() {
var map = createObject(null);
map["__"] = undefined;
delete map["__"];
return map;
}
var Target = function Target(path, matcher, delegate) {
this.path = path;
this.matcher = matcher;
this.delegate = delegate;
};
Target.prototype.to = function to(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);
}
};
var Matcher = function Matcher(target) {
this.routes = createMap();
this.children = createMap();
this.target = target;
};
Matcher.prototype.add = function add(path, target) {
this.routes[path] = target;
};
Matcher.prototype.addChild = function addChild(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) {
function match(path, callback) {
var fullPath = startingPath + path;
if (callback) {
callback(generateMatch(fullPath, matcher, delegate));
} else {
return new Target(fullPath, matcher, delegate);
}
}
return match;
}
function addRoute(routeArray, path, handler) {
var len = 0;
for (var i = 0; i < routeArray.length; 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;
var paths = Object.keys(routes);
for (var i = 0; i < paths.length; i++) {
var path = paths[i];
var routeArray = baseRoute.slice();
addRoute(routeArray, path, routes[path]);
var nested = matcher.children[path];
if (nested) {
eachRoute(routeArray, nested, callback, binding);
} else {
callback.call(binding, routeArray);
}
}
}
var map = function (callback, addRouteCallback) {
var matcher = new Matcher();
callback(generateMatch("", matcher, this.delegate));
eachRoute([], matcher, function (routes) {
if (addRouteCallback) {
addRouteCallback(this, routes);
} else {
this.add(routes);
}
}, this);
};
// Normalizes percent-encoded values in `path` to upper-case and decodes percent-encoded
// values that are not reserved (i.e., unicode characters, emoji, etc). The reserved
// chars are "/" and "%".
// Safe to call multiple times on the same path.
// Normalizes percent-encoded values in `path` to upper-case and decodes percent-encoded
function normalizePath(path) {
return path.split("/").map(normalizeSegment).join("/");
}
// We want to ensure the characters "%" and "/" remain in percent-encoded
// form when normalizing paths, so replace them with their encoded form after
// decoding the rest of the path
var SEGMENT_RESERVED_CHARS = /%|\//g;
function normalizeSegment(segment) {
if (segment.length < 3 || segment.indexOf("%") === -1) {
return segment;
}
return decodeURIComponent(segment).replace(SEGMENT_RESERVED_CHARS, encodeURIComponent);
}
// We do not want to encode these characters when generating dynamic path segments
// See https://tools.ietf.org/html/rfc3986#section-3.3
// sub-delims: "!", "$", "&", "'", "(", ")", "*", "+", ",", ";", "="
// others allowed by RFC 3986: ":", "@"
//
// First encode the entire path segment, then decode any of the encoded special chars.
//
// The chars "!", "'", "(", ")", "*" do not get changed by `encodeURIComponent`,
// so the possible encoded chars are:
// ['%24', '%26', '%2B', '%2C', '%3B', '%3D', '%3A', '%40'].
var PATH_SEGMENT_ENCODINGS = /%(?:2(?:4|6|B|C)|3(?:B|D|A)|40)/g;
function encodePathSegment(str) {
return encodeURIComponent(str).replace(PATH_SEGMENT_ENCODINGS, decodeURIComponent);
}
var escapeRegex = /(\/|\.|\*|\+|\?|\||\(|\)|\[|\]|\{|\}|\\)/g;
var isArray = Array.isArray;
var hasOwnProperty = Object.prototype.hasOwnProperty;
function getParam(params, key) {
if (typeof params !== "object" || params === null) {
throw new Error("You must pass an object as the second argument to `generate`.");
}
if (!hasOwnProperty.call(params, key)) {
throw new Error("You must provide param `" + key + "` to `generate`.");
}
var value = params[key];
var str = typeof value === "string" ? value : "" + value;
if (str.length === 0) {
throw new Error("You must provide a param `" + key + "`.");
}
return str;
}
var eachChar = [];
eachChar[0 /* Static */] = function (segment, currentState) {
var state = currentState;
var value = segment.value;
for (var i = 0; i < value.length; i++) {
var ch = value.charCodeAt(i);
state = state.put(ch, false, false);
}
return state;
};
eachChar[1 /* Dynamic */] = function (_, currentState) {
return currentState.put(47 /* SLASH */, true, true);
};
eachChar[2 /* Star */] = function (_, currentState) {
return currentState.put(-1 /* ANY */, false, true);
};
eachChar[4 /* Epsilon */] = function (_, currentState) {
return currentState;
};
var regex = [];
regex[0 /* Static */] = function (segment) {
return segment.value.replace(escapeRegex, "\\$1");
};
regex[1 /* Dynamic */] = function () {
return "([^/]+)";
};
regex[2 /* Star */] = function () {
return "(.+)";
};
regex[4 /* Epsilon */] = function () {
return "";
};
var generate = [];
generate[0 /* Static */] = function (segment) {
return segment.value;
};
generate[1 /* Dynamic */] = function (segment, params) {
var value = getParam(params, segment.value);
if (RouteRecognizer.ENCODE_AND_DECODE_PATH_SEGMENTS) {
return encodePathSegment(value);
} else {
return value;
}
};
generate[2 /* Star */] = function (segment, params) {
return getParam(params, segment.value);
};
generate[4 /* Epsilon */] = function () {
return "";
};
var EmptyObject = Object.freeze({});
var EmptyArray = Object.freeze([]);
// The `names` will be populated with the paramter name for each dynamic/star
// segment. `shouldDecodes` will be populated with a boolean for each dyanamic/star
// segment, indicating whether it should be decoded during recognition.
function parse(segments, route, types) {
// normalize route as not starting with a "/". Recognition will
// also normalize.
if (route.length > 0 && route.charCodeAt(0) === 47 /* SLASH */) {
route = route.substr(1);
}
var parts = route.split("/");
var names = undefined;
var shouldDecodes = undefined;
for (var i = 0; i < parts.length; i++) {
var part = parts[i];
var flags = 0;
var type = 0;
if (part === "") {
type = 4 /* Epsilon */;
} else if (part.charCodeAt(0) === 58 /* COLON */) {
type = 1 /* Dynamic */;
} else if (part.charCodeAt(0) === 42 /* STAR */) {
type = 2 /* Star */;
} else {
type = 0 /* Static */;
}
flags = 2 << type;
if (flags & 12 /* Named */) {
part = part.slice(1);
names = names || [];
names.push(part);
shouldDecodes = shouldDecodes || [];
shouldDecodes.push((flags & 4 /* Decoded */) !== 0);
}
if (flags & 14 /* Counted */) {
types[type]++;
}
segments.push({
type: type,
value: normalizeSegment(part)
});
}
return {
names: names || EmptyArray,
shouldDecodes: shouldDecodes || EmptyArray
};
}
function isEqualCharSpec(spec, char, negate) {
return spec.char === char && spec.negate === negate;
}
// 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.
var State = function State(states, id, char, negate, repeat) {
this.states = states;
this.id = id;
this.char = char;
this.negate = negate;
this.nextStates = repeat ? id : null;
this.pattern = "";
this._regex = undefined;
this.handlers = undefined;
this.types = undefined;
};
State.prototype.regex = function regex$1() {
if (!this._regex) {
this._regex = new RegExp(this.pattern);
}
return this._regex;
};
State.prototype.get = function get(char, negate) {
var this$1 = this;
var nextStates = this.nextStates;
if (nextStates === null) {
return;
}
if (isArray(nextStates)) {
for (var i = 0; i < nextStates.length; i++) {
var child = this$1.states[nextStates[i]];
if (isEqualCharSpec(child, char, negate)) {
return child;
}
}
} else {
var child$1 = this.states[nextStates];
if (isEqualCharSpec(child$1, char, negate)) {
return child$1;
}
}
};
State.prototype.put = function put(char, negate, repeat) {
var state;
// If the character specification already exists in a child of the current
// state, just return that state.
if (state = this.get(char, negate)) {
return state;
}
// Make a new state for the character spec
var states = this.states;
state = new State(states, states.length, char, negate, repeat);
states[states.length] = state;
// Insert the new state as a child of the current state
if (this.nextStates == null) {
this.nextStates = state.id;
} else if (isArray(this.nextStates)) {
this.nextStates.push(state.id);
} else {
this.nextStates = [this.nextStates, state.id];
}
// Return the new state
return state;
};
// Find a list of child states matching the next character
State.prototype.match = function match(ch) {
var this$1 = this;
var nextStates = this.nextStates;
if (!nextStates) {
return [];
}
var returned = [];
if (isArray(nextStates)) {
for (var i = 0; i < nextStates.length; i++) {
var child = this$1.states[nextStates[i]];
if (isMatch(child, ch)) {
returned.push(child);
}
}
} else {
var child$1 = this.states[nextStates];
if (isMatch(child$1, ch)) {
returned.push(child$1);
}
}
return returned;
};
function isMatch(spec, char) {
return spec.negate ? spec.char !== char && spec.char !== -1 /* ANY */ : spec.char === char || spec.char === -1 /* ANY */;
}
// 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) {
var ref = a.types || [0, 0, 0];
var astatics = ref[0];
var adynamics = ref[1];
var astars = ref[2];
var ref$1 = b.types || [0, 0, 0];
var bstatics = ref$1[0];
var bdynamics = ref$1[1];
var bstars = ref$1[2];
if (astars !== bstars) {
return astars - bstars;
}
if (astars) {
if (astatics !== bstatics) {
return bstatics - astatics;
}
if (adynamics !== bdynamics) {
return bdynamics - adynamics;
}
}
if (adynamics !== bdynamics) {
return adynamics - bdynamics;
}
if (astatics !== bstatics) {
return bstatics - astatics;
}
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 RecognizeResults = function RecognizeResults(queryParams) {
this.length = 0;
this.queryParams = queryParams || {};
};
RecognizeResults.prototype.splice = Array.prototype.splice;
RecognizeResults.prototype.slice = Array.prototype.slice;
RecognizeResults.prototype.push = Array.prototype.push;
function findHandler(state, originalPath, queryParams) {
var handlers = state.handlers;
var regex = state.regex();
if (!regex || !handlers) {
throw new Error("state not initialized");
}
var captures = originalPath.match(regex);
var currentCapture = 1;
var result = new RecognizeResults(queryParams);
result.length = handlers.length;
for (var i = 0; i < handlers.length; i++) {
var handler = handlers[i];
var names = handler.names;
var shouldDecodes = handler.shouldDecodes;
var params = EmptyObject;
var isDynamic = false;
if (names !== EmptyArray && shouldDecodes !== EmptyArray) {
for (var j = 0; j < names.length; j++) {
isDynamic = true;
var name = names[j];
var capture = captures && captures[currentCapture++];
if (params === EmptyObject) {
params = {};
}
if (RouteRecognizer.ENCODE_AND_DECODE_PATH_SEGMENTS && shouldDecodes[j]) {
params[name] = capture && decodeURIComponent(capture);
} else {
params[name] = capture;
}
}
}
result[i] = {
handler: handler.handler,
params: params,
isDynamic: isDynamic
};
}
return result;
}
function decodeQueryParamPart(part) {
// http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.1
part = part.replace(/\+/gm, "%20");
var result;
try {
result = decodeURIComponent(part);
} catch (error) {
result = "";
}
return result;
}
var RouteRecognizer = function RouteRecognizer() {
this.names = createMap();
var states = [];
var state = new State(states, 0, -1 /* ANY */, true, false);
states[0] = state;
this.states = states;
this.rootState = state;
};
RouteRecognizer.prototype.add = function add(routes, options) {
var currentState = this.rootState;
var pattern = "^";
var types = [0, 0, 0];
var handlers = new Array(routes.length);
var allSegments = [];
var isEmpty = true;
var j = 0;
for (var i = 0; i < routes.length; i++) {
var route = routes[i];
var ref = parse(allSegments, route.path, types);
var names = ref.names;
var shouldDecodes = ref.shouldDecodes;
// preserve j so it points to the start of newly added segments
for (; j < allSegments.length; j++) {
var segment = allSegments[j];
if (segment.type === 4 /* Epsilon */) {
continue;
}
isEmpty = false;
// Add a "/" for the new segment
currentState = currentState.put(47 /* SLASH */, false, false);
pattern += "/";
// Add a representation of the segment to the NFA and regex
currentState = eachChar[segment.type](segment, currentState);
pattern += regex[segment.type](segment);
}
handlers[i] = {
handler: route.handler,
names: names,
shouldDecodes: shouldDecodes
};
}
if (isEmpty) {
currentState = currentState.put(47 /* SLASH */, false, false);
pattern += "/";
}
currentState.handlers = handlers;
currentState.pattern = pattern + "$";
currentState.types = types;
var name;
if (typeof options === "object" && options !== null && options.as) {
name = options.as;
}
if (name) {
// if (this.names[name]) {
// throw new Error("You may not add a duplicate route named `" + name + "`.");
// }
this.names[name] = {
segments: allSegments,
handlers: handlers
};
}
};
RouteRecognizer.prototype.handlersFor = function handlersFor(name) {
var route = this.names[name];
if (!route) {
throw new Error("There is no route named " + name);
}
var result = new Array(route.handlers.length);
for (var i = 0; i < route.handlers.length; i++) {
var handler = route.handlers[i];
result[i] = handler;
}
return result;
};
RouteRecognizer.prototype.hasRoute = function hasRoute(name) {
return !!this.names[name];
};
RouteRecognizer.prototype.generate = function generate$1(name, params) {
var route = this.names[name];
var output = "";
if (!route) {
throw new Error("There is no route named " + name);
}
var segments = route.segments;
for (var i = 0; i < segments.length; i++) {
var segment = segments[i];
if (segment.type === 4 /* Epsilon */) {
continue;
}
output += "/";
output += generate[segment.type](segment, params);
}
if (output.charAt(0) !== "/") {
output = "/" + output;
}
if (params && params.queryParams) {
output += this.generateQueryString(params.queryParams);
}
return output;
};
RouteRecognizer.prototype.generateQueryString = function generateQueryString(params) {
var pairs = [];
var keys = Object.keys(params);
keys.sort();
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
var value = params[key];
if (value == null) {
continue;
}
var pair = encodeURIComponent(key);
if (isArray(value)) {
for (var j = 0; j < value.length; 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("&");
};
RouteRecognizer.prototype.parseQueryString = function parseQueryString(queryString) {
var pairs = queryString.split("&");
var queryParams = {};
for (var i = 0; i < pairs.length; i++) {
var pair = pairs[i].split("="),
key = decodeQueryParamPart(pair[0]),
keyLength = key.length,
isArray = false,
value = void 0;
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] ? decodeQueryParamPart(pair[1]) : "";
}
if (isArray) {
queryParams[key].push(value);
} else {
queryParams[key] = value;
}
}
return queryParams;
};
RouteRecognizer.prototype.recognize = function recognize(path) {
var results;
var states = [this.rootState];
var queryParams = {};
var isSlashDropped = false;
var hashStart = path.indexOf("#");
if (hashStart !== -1) {
path = path.substr(0, hashStart);
}
var queryStart = path.indexOf("?");
if (queryStart !== -1) {
var queryString = path.substr(queryStart + 1, path.length);
path = path.substr(0, queryStart);
queryParams = this.parseQueryString(queryString);
}
if (path.charAt(0) !== "/") {
path = "/" + path;
}
var originalPath = path;
if (RouteRecognizer.ENCODE_AND_DECODE_PATH_SEGMENTS) {
path = normalizePath(path);
} else {
path = decodeURI(path);
originalPath = decodeURI(originalPath);
}
var pathLen = path.length;
if (pathLen > 1 && path.charAt(pathLen - 1) === "/") {
path = path.substr(0, pathLen - 1);
originalPath = originalPath.substr(0, originalPath.length - 1);
isSlashDropped = true;
}
for (var i = 0; i < path.length; i++) {
states = recognizeChar(states, path.charCodeAt(i));
if (!states.length) {
break;
}
}
var solutions = [];
for (var i$1 = 0; i$1 < states.length; i$1++) {
if (states[i$1].handlers) {
solutions.push(states[i$1]);
}
}
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.pattern && state.pattern.slice(-5) === "(.+)$") {
originalPath = originalPath + "/";
}
results = findHandler(state, originalPath, queryParams);
}
return results;
};
RouteRecognizer.VERSION = "0.3.3";
// Set to false to opt-out of encoding and decoding path segments.
// See https://github.com/tildeio/route-recognizer/pull/55
RouteRecognizer.ENCODE_AND_DECODE_PATH_SEGMENTS = true;
RouteRecognizer.Normalizer = {
normalizeSegment: normalizeSegment, normalizePath: normalizePath, encodePathSegment: encodePathSegment
};
RouteRecognizer.prototype.map = map;
exports.default = RouteRecognizer;
});
enifed('router', ['exports', 'ember-babel', 'rsvp', 'route-recognizer'], function (exports, _emberBabel, _rsvp, _routeRecognizer) {
'use strict';
exports.Transition = undefined;
var slice = Array.prototype.slice;
var hasOwnProperty = Object.prototype.hasOwnProperty;
/**
Determines if an object is Promise by checking if it is "thenable".
**/
function isPromise(obj) {
return (typeof obj === 'object' && obj !== null || typeof obj === 'function') && typeof obj.then === 'function';
}
function merge(hash, other) {
for (var prop in other) {
if (hasOwnProperty.call(other, prop)) {
hash[prop] = other[prop];
}
}
}
/**
@private
Extracts query params from the end of an array
**/
function extractQueryParams(array) {
var len = array && array.length,
head = void 0,
queryParams = void 0;
if (len && len > 0 && array[len - 1] && hasOwnProperty.call(array[len - 1], 'queryParams')) {
queryParams = array[len - 1].queryParams;
head = slice.call(array, 0, len - 1);
return [head, queryParams];
} else {
return [array, null];
}
}
/**
@private
Coerces query param properties and array elements into strings.
**/
function coerceQueryParamsToString(queryParams) {
for (var key in queryParams) {
var val = queryParams[key];
if (typeof val === 'number') {
queryParams[key] = '' + val;
} else if (Array.isArray(val)) {
for (var i = 0, l = val.length; i < l; i++) {
val[i] = '' + val[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);
}
}
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++) {
// empty intentionally
}
}
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;
function delayedEvent(name, args, handler) {
handler.events[name].apply(handler, args);
}
for (var i = handlerInfos.length - 1; i >= 0; i--) {
var handlerInfo = handlerInfos[i],
handler = handlerInfo.handler;
// If there is no handler, it means the handler hasn't resolved yet which
// means that we should trigger the event later when the handler is available
if (!handler) {
handlerInfo.handlerPromise.then(delayedEvent.bind(null, name, args));
continue;
}
if (handler.events && handler.events[name]) {
if (handler.events[name].apply(handler, args) === true) {
eventWasHandled = true;
} else {
return;
}
}
}
// In the case that we got an UnrecognizedURLError as an event with no handler,
// let it bubble up
if (name === 'error' && args[0].name === 'UnrecognizedURLError') {
throw args[0];
} else if (!eventWasHandled && !ignoreFailure) {
throw new Error("Nothing handled the event '" + name + "'.");
}
}
function getChangelist(oldObject, newObject) {
var key = void 0;
var results = {
all: {},
changed: {},
removed: {}
};
merge(results.all, newObject);
var didChange = false;
coerceQueryParamsToString(oldObject);
coerceQueryParamsToString(newObject);
// Calculate removals
for (key in oldObject) {
if (hasOwnProperty.call(oldObject, key)) {
if (!hasOwnProperty.call(newObject, key)) {
didChange = true;
results.removed[key] = oldObject[key];
}
}
}
// Calculate changes
for (key in newObject) {
if (hasOwnProperty.call(newObject, key)) {
if (Array.isArray(oldObject[key]) && Array.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 : undefined;
}
function _promiseLabel(label) {
return 'Router: ' + label;
}
function resolveHook(obj, hookName) {
if (!obj) {
return;
}
var underscored = '_' + hookName;
return obj[underscored] && underscored || obj[hookName] && hookName;
}
function callHook(obj, _hookName, arg1, arg2) {
var hookName = resolveHook(obj, _hookName);
return hookName && obj[hookName].call(obj, arg1, arg2);
}
function applyHook(obj, _hookName, args) {
var hookName = resolveHook(obj, _hookName);
if (hookName) {
if (args.length === 0) {
return obj[hookName].call(obj);
} else if (args.length === 1) {
return obj[hookName].call(obj, args[0]);
} else if (args.length === 2) {
return obj[hookName].call(obj, args[0], args[1]);
} else {
return obj[hookName].apply(obj, args);
}
}
}
var TransitionState = function () {
function TransitionState() {
(0, _emberBabel.classCallCheck)(this, TransitionState);
this.handlerInfos = [];
this.queryParams = {};
this.params = {};
}
TransitionState.prototype.promiseLabel = function promiseLabel(label) {
var targetName = '';
forEach(this.handlerInfos, function (handlerInfo) {
if (targetName !== '') {
targetName += '.';
}
targetName += handlerInfo.name;
});
return _promiseLabel("'" + targetName + "': " + label);
};
TransitionState.prototype.resolve = function resolve(shouldContinue) {
var payload = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
// 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.resolveIndex = 0;
var currentState = this;
var wasAborted = false;
// The prelude RSVP.resolve() asyncs us into the promise land.
return _rsvp.Promise.resolve(null, this.promiseLabel('Start transition')).then(resolveOneHandlerInfo, null, this.promiseLabel('Resolve handler')).catch(handleError, this.promiseLabel('Handle error'));
function innerShouldContinue() {
return _rsvp.Promise.resolve(shouldContinue(), currentState.promiseLabel('Check if should continue')).catch(function (reason) {
// We distinguish between errors that occurred
// during resolution (e.g. before"Model/model/afterModel),
// and aborts due to a rejecting promise from shouldContinue().
wasAborted = true;
return _rsvp.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 _rsvp.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'));
}
};
return TransitionState;
}();
function TransitionAbortedError(message) {
if (!(this instanceof TransitionAbortedError)) {
return new TransitionAbortedError(message);
}
var error = Error.call(this, message);
if (Error.captureStackTrace) {
Error.captureStackTrace(this, TransitionAbortedError);
} else {
this.stack = error.stack;
}
this.description = error.description;
this.fileName = error.fileName;
this.lineNumber = error.lineNumber;
this.message = error.message || 'TransitionAborted';
this.name = 'TransitionAborted';
this.number = error.number;
this.code = error.code;
}
TransitionAbortedError.prototype = Object.create(Error.prototype);
/**
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.
@class Transition
@constructor
@param {Object} router
@param {Object} intent
@param {Object} state
@param {Object} error
@private
*/
var Transition = function () {
function Transition(router, intent, state, error, previousTransition) {
var _this = this;
(0, _emberBabel.classCallCheck)(this, Transition);
this.state = state || router.state;
this.intent = intent;
this.router = router;
this.data = this.intent && this.intent.data || {};
this.resolvedModels = {};
this.queryParams = {};
this.promise = undefined;
this.error = undefined;
this.params = undefined;
this.handlerInfos = undefined;
this.targetName = undefined;
this.pivotHandler = undefined;
this.sequence = undefined;
this.isAborted = false;
this.isActive = true;
this.urlMethod = 'update';
this.resolveIndex = 0;
this.queryParamsOnly = false;
this.isTransition = true;
if (error) {
this.promise = _rsvp.Promise.reject(error);
this.error = error;
return;
}
// if you're doing multiple redirects, need the new transition to know if it
// is actually part of the first transition or not. Any further redirects
// in the initial transition also need to know if they are part of the
// initial transition
this.isCausedByAbortingTransition = !!previousTransition;
this.isCausedByInitialTransition = previousTransition && (previousTransition.isCausedByInitialTransition || previousTransition.sequence === 0);
// Every transition in the chain is a replace
this.isCausedByAbortingReplaceTransition = previousTransition && previousTransition.urlMethod == 'replace' && (!previousTransition.isCausedByAbortingTransition || previousTransition.isCausedByAbortingReplaceTransition);
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 = router.currentSequence++;
this.promise = state.resolve(function () {
if (_this.isAborted) {
return _rsvp.Promise.reject(undefined, _promiseLabel('Transition aborted - reject'));
}
}, this).catch(function (result) {
if (result.wasAborted || _this.isAborted) {
return _rsvp.Promise.reject(logAbort(_this));
} else {
_this.trigger('error', result.error, _this, result.handlerWithError);
_this.abort();
return _rsvp.Promise.reject(result.error);
}
}, _promiseLabel('Handle Abort'));
} else {
this.promise = _rsvp.Promise.resolve(this.state);
this.params = {};
}
}
Transition.prototype.isExiting = function isExiting(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;
};
Transition.prototype.then = function then(onFulfilled, onRejected, label) {
return this.promise.then(onFulfilled, onRejected, label);
};
Transition.prototype.catch = function _catch(onRejection, label) {
return this.promise.catch(onRejection, label);
};
Transition.prototype.finally = function _finally(callback, label) {
return this.promise.finally(callback, label);
};
Transition.prototype.abort = function abort() {
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;
};
Transition.prototype.retry = function retry() {
// TODO: add tests for merged state retry()s
this.abort();
var newTransition = this.router.transitionByIntent(this.intent, false);
// inheriting a `null` urlMethod is not valid
// the urlMethod is only set to `null` when
// the transition is initiated *after* the url
// has been updated (i.e. `router.handleURL`)
//
// in that scenario, the url method cannot be
// inherited for a new transition because then
// the url would not update even though it should
if (this.urlMethod !== null) {
newTransition.method(this.urlMethod);
}
return newTransition;
};
Transition.prototype.method = function method(_method) {
this.urlMethod = _method;
return this;
};
Transition.prototype.trigger = function trigger(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);
};
Transition.prototype.followRedirects = function followRedirects() {
var router = this.router;
return this.promise.catch(function (reason) {
if (router.activeTransition) {
return router.activeTransition.followRedirects();
}
return _rsvp.Promise.reject(reason);
});
};
Transition.prototype.toString = function toString() {
return 'Transition (sequence ' + this.sequence + ')';
};
Transition.prototype.log = function log(message) {
_log(this.router, this.sequence, message);
};
return Transition;
}();
// Alias 'trigger' as 'send'
Transition.prototype.send = Transition.prototype.trigger;
/**
@private
Logs and returns an instance of TransitionAborted.
*/
function logAbort(transition) {
_log(transition.router, transition.sequence, 'detected abort.');
return new TransitionAbortedError();
}
var TransitionIntent = function TransitionIntent() {
(0, _emberBabel.classCallCheck)(this, TransitionIntent);
this.data = this.data || {};
};
var DEFAULT_HANDLER = Object.freeze({});
var HandlerInfo = function () {
function HandlerInfo() {
var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
(0, _emberBabel.classCallCheck)(this, HandlerInfo);
// initialize local properties to ensure consistent object shape
this._handler = DEFAULT_HANDLER;
this._handlerPromise = null;
this.factory = null; // Injected by the handler info factory
this.name = props.name;
for (var prop in props) {
if (prop === 'handler') {
this._processHandler(props.handler);
} else {
this[prop] = props[prop];
}
}
}
HandlerInfo.prototype.getHandler = function getHandler() {};
HandlerInfo.prototype.fetchHandler = function fetchHandler() {
var handler = this.getHandler(this.name);
return this._processHandler(handler);
};
HandlerInfo.prototype._processHandler = function _processHandler(handler) {
var _this2 = this;
// Setup a handlerPromise so that we can wait for asynchronously loaded handlers
this.handlerPromise = _rsvp.Promise.resolve(handler);
// Wait until the 'handler' property has been updated when chaining to a handler
// that is a promise
if (isPromise(handler)) {
this.handlerPromise = this.handlerPromise.then(function (h) {
return _this2.updateHandler(h);
});
// set to undefined to avoid recursive loop in the handler getter
return this.handler = undefined;
} else if (handler) {
return this.updateHandler(handler);
}
};
HandlerInfo.prototype.log = function log(payload, message) {
if (payload.log) {
payload.log(this.name + ': ' + message);
}
};
HandlerInfo.prototype.promiseLabel = function promiseLabel(label) {
return _promiseLabel("'" + this.name + "' " + label);
};
HandlerInfo.prototype.getUnresolved = function getUnresolved() {
return this;
};
HandlerInfo.prototype.serialize = function serialize() {
return this.params || {};
};
HandlerInfo.prototype.updateHandler = function updateHandler(handler) {
// Store the name of the handler on the handler for easy checks later
handler._handlerName = this.name;
return this.handler = handler;
};
HandlerInfo.prototype.resolve = function resolve(shouldContinue, payload) {
var checkForAbort = this.checkForAbort.bind(this, shouldContinue);
var beforeModel = this.runBeforeModelHook.bind(this, payload);
var model = this.getModel.bind(this, payload);
var afterModel = this.runAfterModelHook.bind(this, payload);
var becomeResolved = this.becomeResolved.bind(this, payload);
return _rsvp.Promise.resolve(this.handlerPromise, 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'));
};
HandlerInfo.prototype.runBeforeModelHook = function runBeforeModelHook(payload) {
if (payload.trigger) {
payload.trigger(true, 'willResolveModel', payload, this.handler);
}
return this.runSharedModelHook(payload, 'beforeModel', []);
};
HandlerInfo.prototype.runAfterModelHook = function runAfterModelHook(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'));
};
HandlerInfo.prototype.runSharedModelHook = function runSharedModelHook(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 _rsvp.Promise.resolve(result, this.promiseLabel('Resolve value returned from one of the model hooks'));
};
HandlerInfo.prototype.getModel = function getModel() {};
HandlerInfo.prototype.checkForAbort = function checkForAbort(shouldContinue, promiseValue) {
return _rsvp.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'));
};
HandlerInfo.prototype.stashResolvedModel = function stashResolvedModel(payload, resolvedModel) {
payload.resolvedModels = payload.resolvedModels || {};
payload.resolvedModels[this.name] = resolvedModel;
};
HandlerInfo.prototype.becomeResolved = function becomeResolved(payload, resolvedContext) {
var params = this.serialize(resolvedContext);
if (payload) {
this.stashResolvedModel(payload, resolvedContext);
payload.params = payload.params || {};
payload.params[this.name] = params;
}
var resolution = {
name: this.name,
handler: this.handler,
params: params
};
// Don't set a context on the resolution unless we actually have one.
var contextsMatch = resolvedContext === this.context;
if ('context' in this || !contextsMatch) {
resolution.context = resolvedContext;
}
return this.factory('resolved', resolution);
};
HandlerInfo.prototype.shouldSupercede = function shouldSupercede(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 || 'context' in this && !contextsMatch || this.hasOwnProperty('params') && !paramsMatch(this.params, other.params);
};
(0, _emberBabel.createClass)(HandlerInfo, [{
key: 'handler',
get: function () {
// _handler could be set to either a handler object or undefined, so we
// compare against a default reference to know when it's been set
if (this._handler !== DEFAULT_HANDLER) {
return this._handler;
}
return this.fetchHandler();
},
set: function (handler) {
return this._handler = handler;
}
}, {
key: 'handlerPromise',
get: function () {
if (this._handlerPromise !== null) {
return this._handlerPromise;
}
this.fetchHandler();
return this._handlerPromise;
},
set: function (handlerPromise) {
this._handlerPromise = handlerPromise;
return handlerPromise;
}
}]);
return HandlerInfo;
}();
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;
}
var ResolvedHandlerInfo = function (_HandlerInfo) {
(0, _emberBabel.inherits)(ResolvedHandlerInfo, _HandlerInfo);
function ResolvedHandlerInfo(props) {
(0, _emberBabel.classCallCheck)(this, ResolvedHandlerInfo);
var _this3 = (0, _emberBabel.possibleConstructorReturn)(this, _HandlerInfo.call(this, props));
_this3.isResolved = true;
return _this3;
}
ResolvedHandlerInfo.prototype.resolve = function resolve(shouldContinue, payload) {
// A ResolvedHandlerInfo just resolved with itself.
if (payload && payload.resolvedModels) {
payload.resolvedModels[this.name] = this.context;
}
return _rsvp.Promise.resolve(this, this.promiseLabel('Resolve'));
};
ResolvedHandlerInfo.prototype.getUnresolved = function getUnresolved() {
return this.factory('param', {
name: this.name,
handler: this.handler,
params: this.params
});
};
return ResolvedHandlerInfo;
}(HandlerInfo);
var UnresolvedHandlerInfoByObject = function (_HandlerInfo2) {
(0, _emberBabel.inherits)(UnresolvedHandlerInfoByObject, _HandlerInfo2);
function UnresolvedHandlerInfoByObject(props) {
(0, _emberBabel.classCallCheck)(this, UnresolvedHandlerInfoByObject);
var _this4 = (0, _emberBabel.possibleConstructorReturn)(this, _HandlerInfo2.call(this, props));
_this4.names = _this4.names || [];
return _this4;
}
UnresolvedHandlerInfoByObject.prototype.getModel = function getModel(payload) {
this.log(payload, this.name + ': resolving provided model');
return _rsvp.Promise.resolve(this.context);
};
UnresolvedHandlerInfoByObject.prototype.serialize = function serialize(_model) {
var model = _model || this.context,
names = this.names;
var object = {};
if (isParam(model)) {
object[names[0]] = model;
return object;
}
// Use custom serialize if it exists.
if (this.serializer) {
// invoke this.serializer unbound (getSerializer returns a stateless function)
return this.serializer.call(null, model, names);
} else if (this.handler && this.handler.serialize) {
return this.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;
};
return UnresolvedHandlerInfoByObject;
}(HandlerInfo);
var UnresolvedHandlerInfoByParam = function (_HandlerInfo3) {
(0, _emberBabel.inherits)(UnresolvedHandlerInfoByParam, _HandlerInfo3);
function UnresolvedHandlerInfoByParam(props) {
(0, _emberBabel.classCallCheck)(this, UnresolvedHandlerInfoByParam);
var _this5 = (0, _emberBabel.possibleConstructorReturn)(this, _HandlerInfo3.call(this, props));
_this5.params = _this5.params || {};
return _this5;
}
UnresolvedHandlerInfoByParam.prototype.getModel = function getModel(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]);
};
return UnresolvedHandlerInfoByParam;
}(HandlerInfo);
handlerInfoFactory.klasses = {
resolved: ResolvedHandlerInfo,
param: UnresolvedHandlerInfoByParam,
object: UnresolvedHandlerInfoByObject
};
function handlerInfoFactory(name, props) {
var klass = handlerInfoFactory.klasses[name];
var handlerInfo = new klass(props || {});
handlerInfo.factory = handlerInfoFactory;
return handlerInfo;
}
var NamedTransitionIntent = function (_TransitionIntent) {
(0, _emberBabel.inherits)(NamedTransitionIntent, _TransitionIntent);
function NamedTransitionIntent(props) {
(0, _emberBabel.classCallCheck)(this, NamedTransitionIntent);
var _this6 = (0, _emberBabel.possibleConstructorReturn)(this, _TransitionIntent.call(this, props));
_this6.name = props.name;
_this6.pivotHandler = props.pivotHandler;
_this6.contexts = props.contexts || [];
_this6.queryParams = props.queryParams;
return _this6;
}
NamedTransitionIntent.prototype.applyToState = function applyToState(oldState, recognizer, getHandler, isIntermediate, getSerializer) {
var partitionedArgs = extractQueryParams([this.name].concat(this.contexts)),
pureArgs = partitionedArgs[0],
handlers = recognizer.handlersFor(pureArgs[0]);
var targetRouteName = handlers[handlers.length - 1].handler;
return this.applyToHandlers(oldState, handlers, getHandler, targetRouteName, isIntermediate, null, getSerializer);
};
NamedTransitionIntent.prototype.applyToHandlers = function applyToHandlers(oldState, handlers, getHandler, targetRouteName, isIntermediate, checkingIfActive, getSerializer) {
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 (handlers[i].handler === this.pivotHandler._handlerName) {
invalidateIndex = i;
break;
}
}
}
for (i = handlers.length - 1; i >= 0; --i) {
var result = handlers[i];
var name = result.handler;
var oldHandlerInfo = oldState.handlerInfos[i];
var newHandlerInfo = null;
if (result.names.length > 0) {
if (i >= invalidateIndex) {
newHandlerInfo = this.createParamHandlerInfo(name, getHandler, result.names, objects, oldHandlerInfo);
} else {
var serializer = getSerializer(name);
newHandlerInfo = this.getHandlerInfoForDynamicSegment(name, getHandler, result.names, objects, oldHandlerInfo, targetRouteName, i, serializer);
}
} 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, getHandler, 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 && 'context' in oldHandlerInfo && 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;
};
NamedTransitionIntent.prototype.invalidateChildren = function invalidateChildren(handlerInfos, invalidateIndex) {
for (var i = invalidateIndex, l = handlerInfos.length; i < l; ++i) {
var handlerInfo = handlerInfos[i];
handlerInfos[i] = handlerInfo.getUnresolved();
}
};
NamedTransitionIntent.prototype.getHandlerInfoForDynamicSegment = function getHandlerInfoForDynamicSegment(name, getHandler, names, objects, oldHandlerInfo, targetRouteName, i, serializer) {
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, getHandler, 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,
getHandler: getHandler,
serializer: serializer,
context: objectToUse,
names: names
});
};
NamedTransitionIntent.prototype.createParamHandlerInfo = function createParamHandlerInfo(name, getHandler, 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,
getHandler: getHandler,
params: params
});
};
return NamedTransitionIntent;
}(TransitionIntent);
function UnrecognizedURLError(message) {
if (!(this instanceof UnrecognizedURLError)) {
return new UnrecognizedURLError(message);
}
var error = Error.call(this, message);
if (Error.captureStackTrace) {
Error.captureStackTrace(this, UnrecognizedURLError);
} else {
this.stack = error.stack;
}
this.description = error.description;
this.fileName = error.fileName;
this.lineNumber = error.lineNumber;
this.message = error.message || 'UnrecognizedURL';
this.name = 'UnrecognizedURLError';
this.number = error.number;
this.code = error.code;
}
UnrecognizedURLError.prototype = Object.create(Error.prototype);
var URLTransitionIntent = function (_TransitionIntent2) {
(0, _emberBabel.inherits)(URLTransitionIntent, _TransitionIntent2);
function URLTransitionIntent(props) {
(0, _emberBabel.classCallCheck)(this, URLTransitionIntent);
var _this7 = (0, _emberBabel.possibleConstructorReturn)(this, _TransitionIntent2.call(this, props));
_this7.url = props.url;
return _this7;
}
URLTransitionIntent.prototype.applyToState = function applyToState(oldState, recognizer, getHandler) {
var newState = new TransitionState();
var results = recognizer.recognize(this.url),
i,
len;
if (!results) {
throw new UnrecognizedURLError(this.url);
}
var statesDiffer = false;
var url = this.url;
// Checks if a handler is accessible by URL. If it is not, an error is thrown.
// For the case where the handler is loaded asynchronously, the error will be
// thrown once it is loaded.
function checkHandlerAccessibility(handler) {
if (handler && handler.inaccessibleByURL) {
throw new UnrecognizedURLError(url);
}
return handler;
}
for (i = 0, len = results.length; i < len; ++i) {
var result = results[i];
var name = result.handler;
var newHandlerInfo = handlerInfoFactory('param', {
name: name,
getHandler: getHandler,
params: result.params
});
var handler = newHandlerInfo.handler;
if (handler) {
checkHandlerAccessibility(handler);
} else {
// If the hanlder is being loaded asynchronously, check if we can
// access it after it has resolved
newHandlerInfo.handlerPromise = newHandlerInfo.handlerPromise.then(checkHandlerAccessibility);
}
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;
};
return URLTransitionIntent;
}(TransitionIntent);
var pop = Array.prototype.pop;
var Router = function () {
function Router() {
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
(0, _emberBabel.classCallCheck)(this, Router);
this.getHandler = options.getHandler || this.getHandler;
this.getSerializer = options.getSerializer || this.getSerializer;
this.updateURL = options.updateURL || this.updateURL;
this.replaceURL = options.replaceURL || this.replaceURL;
this.didTransition = options.didTransition || this.didTransition;
this.willTransition = options.willTransition || this.willTransition;
this.delegate = options.delegate || this.delegate;
this.triggerEvent = options.triggerEvent || this.triggerEvent;
this.log = options.log || this.log;
this.dslCallBacks = []; // NOTE: set by Ember
this.state = undefined;
this.activeTransition = undefined;
this._changedQueryParams = undefined;
this.oldState = undefined;
this.currentHandlerInfos = undefined;
this.currentSequence = 0;
this.recognizer = new _routeRecognizer.default();
this.reset();
}
/**
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
*/
Router.prototype.map = function map(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';
}
});
};
Router.prototype.hasRoute = function hasRoute(route) {
return this.recognizer.hasRoute(route);
};
Router.prototype.getHandler = function getHandler() {};
Router.prototype.getSerializer = function getSerializer() {};
Router.prototype.queryParamsTransition = function queryParamsTransition(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;
}
};
Router.prototype.transitionByIntent = function transitionByIntent(intent /*, isIntermediate*/) {
try {
return getTransitionByIntent.apply(this, arguments);
} catch (e) {
return new Transition(this, intent, null, e);
}
};
Router.prototype.reset = function reset() {
if (this.state) {
forEach(this.state.handlerInfos.slice().reverse(), function (handlerInfo) {
var handler = handlerInfo.handler;
callHook(handler, 'exit');
});
}
this.oldState = undefined;
this.state = new TransitionState();
this.currentHandlerInfos = null;
};
Router.prototype.handleURL = function handleURL() {
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
// Perform a URL-based transition, but don't change
// the URL afterward, since it already happened.
var url = args[0];
if (url.charAt(0) !== '/') {
args[0] = '/' + url;
}
return doTransition(this, args).method(null);
};
Router.prototype.updateURL = function updateURL() {
throw new Error('updateURL is not implemented');
};
Router.prototype.replaceURL = function replaceURL(url) {
this.updateURL(url);
};
Router.prototype.transitionTo = function transitionTo() /*name*/{
return doTransition(this, arguments);
};
Router.prototype.intermediateTransitionTo = function intermediateTransitionTo() /*name*/{
return doTransition(this, arguments, true);
};
Router.prototype.refresh = function refresh(pivotHandler) {
var previousTransition = this.activeTransition;
var state = previousTransition ? previousTransition.state : this.state;
var handlerInfos = state.handlerInfos;
_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 || {}
});
var newTransition = this.transitionByIntent(intent, false);
// if the previous transition is a replace transition, that needs to be preserved
if (previousTransition && previousTransition.urlMethod === 'replace') {
newTransition.method(previousTransition.urlMethod);
}
return newTransition;
};
Router.prototype.replaceWith = function replaceWith() /*name*/{
return doTransition(this, arguments).method('replace');
};
Router.prototype.generate = function generate(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, null, this.getSerializer);
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);
};
Router.prototype.applyIntent = function applyIntent(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, null, this.getSerializer);
};
Router.prototype.isActiveIntent = function isActiveIntent(handlerName, contexts, queryParams, _state) {
var state = _state || this.state,
targetHandlerInfos = state.handlerInfos,
handlerInfo = void 0,
len = void 0;
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 testState = new TransitionState();
testState.handlerInfos = targetHandlerInfos.slice(0, index + 1);
recogHandlers = recogHandlers.slice(0, index + 1);
var intent = new NamedTransitionIntent({
name: targetHandler,
contexts: contexts
});
var newState = intent.applyToHandlers(testState, recogHandlers, this.getHandler, targetHandler, true, true, this.getSerializer);
var handlersEqual = handlerInfosEqual(newState.handlerInfos, testState.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 = state.queryParams;
for (var key in activeQueryParams) {
if (activeQueryParams.hasOwnProperty(key) && activeQPsOnNewHandler.hasOwnProperty(key)) {
activeQPsOnNewHandler[key] = activeQueryParams[key];
}
}
return handlersEqual && !getChangelist(activeQPsOnNewHandler, queryParams);
};
Router.prototype.isActive = function isActive(handlerName) {
for (var _len2 = arguments.length, args = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
args[_key2 - 1] = arguments[_key2];
}
var partitionedArgs = extractQueryParams(args);
return this.isActiveIntent(handlerName, partitionedArgs[0], partitionedArgs[1]);
};
Router.prototype.trigger = function trigger() {
for (var _len3 = arguments.length, args = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
args[_key3] = arguments[_key3];
}
_trigger(this, this.currentHandlerInfos, false, args);
};
return Router;
}();
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, this.getSerializer);
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) {
newTransition.queryParamsOnly = true;
return newTransition;
}
}
// No-op. No need to create a new transition.
return this.activeTransition || new Transition(this);
}
if (isIntermediate) {
setupContexts(this, newState);
return;
}
// Create a new transition to the destination route.
newTransition = new Transition(this, intent, newState, undefined, this.activeTransition);
// transition is to same route with same params, only query params differ.
// not caught above probably because refresh() has been used
if (handlerInfosSameExceptQueryParams(newState.handlerInfos, oldState.handlerInfos)) {
newTransition.queryParamsOnly = true;
}
// 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;
}
/**
@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);
var i, l, handler;
for (i = 0, l = partition.exited.length; i < l; i++) {
handler = partition.exited[i].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 {
for (i = 0, l = partition.reset.length; i < l; i++) {
handler = partition.reset[i].handler;
callHook(handler, 'reset', false, transition);
}
for (i = 0, l = partition.updatedContext.length; i < l; i++) {
handlerEnteredOrUpdated(currentHandlerInfos, partition.updatedContext[i], false, transition);
}
for (i = 0, l = partition.entered.length; i < l; i++) {
handlerEnteredOrUpdated(currentHandlerInfos, partition.entered[i], 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;
function _handlerEnteredOrUpdated(handler) {
if (enter) {
callHook(handler, 'enter', transition);
}
if (transition && transition.isAborted) {
throw new TransitionAbortedError();
}
handler.context = context;
callHook(handler, 'contextDidChange');
callHook(handler, 'setup', context, transition);
if (transition && transition.isAborted) {
throw new TransitionAbortedError();
}
currentHandlerInfos.push(handlerInfo);
}
// If the handler doesn't exist, it means we haven't resolved the handler promise yet
if (!handler) {
handlerInfo.handlerPromise = handlerInfo.handlerPromise.then(_handlerEnteredOrUpdated);
} else {
_handlerEnteredOrUpdated(handler);
}
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: [],
reset: undefined
};
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);
// transitions during the initial transition must always use replaceURL.
// When the app boots, you are at a url, e.g. /foo. If some handler
// redirects to bar as part of the initial transition, you don't want to
// add a history entry for /foo. If you do, pressing back will immediately
// hit the redirect again and take you back to /bar, thus killing the back
// button
var initial = transition.isCausedByInitialTransition;
// say you are at / and you click a link to route /foo. In /foo's
// handler, the transition is aborted using replacewith('/bar').
// Because the current url is still /, the history entry for / is
// removed from the history. Clicking back will take you to the page
// you were on before /, which is often not even the app, thus killing
// the back button. That's why updateURL is always correct for an
// aborting transition that's not the initial transition
var replaceAndNotAborting = urlMethod === 'replace' && !transition.isCausedByAbortingTransition;
// because calling refresh causes an aborted transition, this needs to be
// special cased - if the initial transition is a replace transition, the
// urlMethod should be honored here.
var isQueryParamsRefreshTransition = transition.queryParamsOnly && urlMethod === 'replace';
// say you are at / and you a `replaceWith(/foo)` is called. Then, that
// transition is aborted with `replaceWith(/bar)`. At the end, we should
// end up with /bar replacing /. We are replacing the replace. We only
// will replace the initial route if all subsequent aborts are also
// replaces. However, there is some ambiguity around the correct behavior
// here.
var replacingReplace = urlMethod === 'replace' && transition.isCausedByAbortingReplaceTransition;
if (initial || replaceAndNotAborting || isQueryParamsRefreshTransition || replacingReplace) {
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;
// 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 _rsvp.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 TransitionAbortedError)) {
//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 handlerInfosSameExceptQueryParams(handlerInfos, otherHandlerInfos) {
if (handlerInfos.length !== otherHandlerInfos.length) {
return false;
}
for (var i = 0, len = handlerInfos.length; i < len; ++i) {
if (handlerInfos[i].name !== otherHandlerInfos[i].name) {
return false;
}
if (!paramsEqual(handlerInfos[i].params, otherHandlerInfos[i].params)) {
return false;
}
}
return true;
}
function paramsEqual(params, otherParams) {
if (!params && !otherParams) {
return true;
} else if (!params && !!otherParams || !!params && !otherParams) {
// one is falsy but other is not;
return false;
}
var keys = Object.keys(params);
var otherKeys = Object.keys(otherParams);
if (keys.length !== otherKeys.length) {
return false;
}
for (var i = 0, len = keys.length; i < len; ++i) {
var key = keys[i];
if (params[key] !== otherParams[key]) {
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,
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) {
break;
}
if (!newHandler.isResolved) {}
}
_trigger(router, oldHandlers, true, ['willTransition', newTransition]);
if (router.willTransition) {
router.willTransition(oldHandlers, newState.handlerInfos, newTransition);
}
}
exports.default = Router;
exports.Transition = Transition;
});
enifed('rsvp', ['exports', 'ember-babel', 'node-module'], function (exports, _emberBabel, _nodeModule) {
'use strict';
exports.filter = exports.async = exports.map = exports.reject = exports.resolve = exports.off = exports.on = exports.configure = exports.denodeify = exports.defer = exports.rethrow = exports.hashSettled = exports.hash = exports.race = exports.allSettled = exports.all = exports.EventTarget = exports.Promise = exports.cast = exports.asap = undefined;
function callbacksFor(object) {
var callbacks = object._promiseCallbacks;
if (!callbacks) {
callbacks = object._promiseCallbacks = {};
}
return callbacks;
}
/**
@class RSVP.EventTarget
*/
var EventTarget = {
mixin: function (object) {
object.on = this.on;
object.off = this.off;
object.trigger = this.trigger;
object._promiseCallbacks = undefined;
return object;
},
on: function (eventName, callback) {
if (typeof callback !== 'function') {
throw new TypeError('Callback must be a function');
}
var allCallbacks = callbacksFor(this);
var callbacks = allCallbacks[eventName];
if (!callbacks) {
callbacks = allCallbacks[eventName] = [];
}
if (callbacks.indexOf(callback) === -1) {
callbacks.push(callback);
}
},
off: function (eventName, callback) {
var allCallbacks = callbacksFor(this);
if (!callback) {
allCallbacks[eventName] = [];
return;
}
var callbacks = allCallbacks[eventName];
var index = callbacks.indexOf(callback);
if (index !== -1) {
callbacks.splice(index, 1);
}
},
trigger: function (eventName, options, label) {
var allCallbacks = callbacksFor(this);
var callbacks = allCallbacks[eventName];
if (callbacks) {
// Don't cache the callbacks.length since it may grow
var callback = void 0;
for (var i = 0; i < callbacks.length; i++) {
callback = callbacks[i];
callback(options, label);
}
}
}
};
var config = {
instrument: false
};
EventTarget['mixin'](config);
function configure(name, value) {
if (arguments.length === 2) {
config[name] = value;
} else {
return config[name];
}
}
var queue = [];
function scheduleFlush() {
setTimeout(function () {
for (var i = 0; i < queue.length; i++) {
var 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);
}
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: Date.now(),
error: config["instrument-with-stack"] ? new Error(promise._label) : null
} })) {
scheduleFlush();
}
}
/**
`RSVP.Promise.resolve` returns a promise that will become resolved with the
passed `value`. It is shorthand for the following:
```javascript
let 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
let promise = RSVP.Promise.resolve(1);
promise.then(function(value){
// value === 1
});
```
@method resolve
@static
@param {*} object 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`
*/
function resolve$$1(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$1(promise, object);
return promise;
}
function withOwnPromise() {
return new TypeError('A promises callback cannot return that same promise.');
}
function objectOrFunction(x) {
var type = typeof x;
return x !== null && (type === 'object' || type === 'function');
}
function noop() {}
var PENDING = void 0;
var FULFILLED = 1;
var REJECTED = 2;
var TRY_CATCH_ERROR = { error: null };
function getThen(promise) {
try {
return promise.then;
} catch (error) {
TRY_CATCH_ERROR.error = error;
return TRY_CATCH_ERROR;
}
}
var tryCatchCallback = void 0;
function tryCatcher() {
try {
var target = tryCatchCallback;
tryCatchCallback = null;
return target.apply(this, arguments);
} catch (e) {
TRY_CATCH_ERROR.error = e;
return TRY_CATCH_ERROR;
}
}
function tryCatch(fn) {
tryCatchCallback = fn;
return tryCatcher;
}
function handleForeignThenable(promise, thenable, then$$1) {
config.async(function (promise) {
var sealed = false;
var result = tryCatch(then$$1).call(thenable, function (value) {
if (sealed) {
return;
}
sealed = true;
if (thenable === value) {
fulfill(promise, value);
} else {
resolve$1(promise, value);
}
}, function (reason) {
if (sealed) {
return;
}
sealed = true;
reject(promise, reason);
}, 'Settle: ' + (promise._label || ' unknown promise'));
if (!sealed && result === TRY_CATCH_ERROR) {
sealed = true;
var error = TRY_CATCH_ERROR.error;
TRY_CATCH_ERROR.error = null;
reject(promise, error);
}
}, promise);
}
function handleOwnThenable(promise, thenable) {
if (thenable._state === FULFILLED) {
fulfill(promise, thenable._result);
} else if (thenable._state === REJECTED) {
thenable._onError = null;
reject(promise, thenable._result);
} else {
subscribe(thenable, undefined, function (value) {
if (thenable === value) {
fulfill(promise, value);
} else {
resolve$1(promise, value);
}
}, function (reason) {
return reject(promise, reason);
});
}
}
function handleMaybeThenable(promise, maybeThenable, then$$1) {
var isOwnThenable = maybeThenable.constructor === promise.constructor && then$$1 === then && promise.constructor.resolve === resolve$$1;
if (isOwnThenable) {
handleOwnThenable(promise, maybeThenable);
} else if (then$$1 === TRY_CATCH_ERROR) {
var error = TRY_CATCH_ERROR.error;
TRY_CATCH_ERROR.error = null;
reject(promise, error);
} else if (typeof then$$1 === 'function') {
handleForeignThenable(promise, maybeThenable, then$$1);
} else {
fulfill(promise, maybeThenable);
}
}
function resolve$1(promise, value) {
if (promise === value) {
fulfill(promise, value);
} else if (objectOrFunction(value)) {
handleMaybeThenable(promise, value, getThen(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 = void 0,
callback = void 0,
result = promise._result;
for (var i = 0; i < subscribers.length; i += 3) {
child = subscribers[i];
callback = subscribers[i + settled];
if (child) {
invokeCallback(settled, child, callback, result);
} else {
callback(result);
}
}
promise._subscribers.length = 0;
}
function invokeCallback(state, promise, callback, result) {
var hasCallback = typeof callback === 'function';
var value = void 0;
if (hasCallback) {
value = tryCatch(callback)(result);
} else {
value = result;
}
if (promise._state !== PENDING) {
// noop
} else if (value === promise) {
reject(promise, withOwnPromise());
} else if (value === TRY_CATCH_ERROR) {
var error = TRY_CATCH_ERROR.error;
TRY_CATCH_ERROR.error = null; // release
reject(promise, error);
} else if (hasCallback) {
resolve$1(promise, value);
} else if (state === FULFILLED) {
fulfill(promise, value);
} else if (state === REJECTED) {
reject(promise, value);
}
}
function initializePromise(promise, resolver) {
var resolved = false;
try {
resolver(function (value) {
if (resolved) {
return;
}
resolved = true;
resolve$1(promise, value);
}, function (reason) {
if (resolved) {
return;
}
resolved = true;
reject(promise, reason);
});
} catch (e) {
reject(promise, e);
}
}
function then(onFulfillment, onRejection, label) {
var parent = this;
var state = parent._state;
if (state === FULFILLED && !onFulfillment || state === REJECTED && !onRejection) {
config.instrument && instrument('chained', parent, parent);
return parent;
}
parent._onError = null;
var child = new parent.constructor(noop, label);
var result = parent._result;
config.instrument && instrument('chained', parent, child);
if (state === PENDING) {
subscribe(parent, child, onFulfillment, onRejection);
} else {
var callback = state === FULFILLED ? onFulfillment : onRejection;
config.async(function () {
return invokeCallback(state, child, callback, result);
});
}
return child;
}
var Enumerator = function () {
function Enumerator(Constructor, input, abortOnReject, label) {
(0, _emberBabel.classCallCheck)(this, Enumerator);
this._instanceConstructor = Constructor;
this.promise = new Constructor(noop, label);
this._abortOnReject = abortOnReject;
this._isUsingOwnPromise = Constructor === Promise;
this._isUsingOwnResolve = Constructor.resolve === resolve$$1;
this._init.apply(this, arguments);
}
Enumerator.prototype._init = function _init(Constructor, input) {
var len = input.length || 0;
this.length = len;
this._remaining = len;
this._result = new Array(len);
this._enumerate(input);
};
Enumerator.prototype._enumerate = function _enumerate(input) {
var length = this.length;
var promise = this.promise;
for (var i = 0; promise._state === PENDING && i < length; i++) {
this._eachEntry(input[i], i, true);
}
this._checkFullfillment();
};
Enumerator.prototype._checkFullfillment = function _checkFullfillment() {
if (this._remaining === 0) {
var result = this._result;
fulfill(this.promise, result);
this._result = null;
}
};
Enumerator.prototype._settleMaybeThenable = function _settleMaybeThenable(entry, i, firstPass) {
var c = this._instanceConstructor;
if (this._isUsingOwnResolve) {
var then$$1 = getThen(entry);
if (then$$1 === then && entry._state !== PENDING) {
entry._onError = null;
this._settledAt(entry._state, i, entry._result, firstPass);
} else if (typeof then$$1 !== 'function') {
this._settledAt(FULFILLED, i, entry, firstPass);
} else if (this._isUsingOwnPromise) {
var promise = new c(noop);
handleMaybeThenable(promise, entry, then$$1);
this._willSettleAt(promise, i, firstPass);
} else {
this._willSettleAt(new c(function (resolve) {
return resolve(entry);
}), i, firstPass);
}
} else {
this._willSettleAt(c.resolve(entry), i, firstPass);
}
};
Enumerator.prototype._eachEntry = function _eachEntry(entry, i, firstPass) {
if (entry !== null && typeof entry === 'object') {
this._settleMaybeThenable(entry, i, firstPass);
} else {
this._setResultAt(FULFILLED, i, entry, firstPass);
}
};
Enumerator.prototype._settledAt = function _settledAt(state, i, value, firstPass) {
var promise = this.promise;
if (promise._state === PENDING) {
if (this._abortOnReject && state === REJECTED) {
reject(promise, value);
} else {
this._setResultAt(state, i, value, firstPass);
this._checkFullfillment();
}
}
};
Enumerator.prototype._setResultAt = function _setResultAt(state, i, value, firstPass) {
this._remaining--;
this._result[i] = value;
};
Enumerator.prototype._willSettleAt = function _willSettleAt(promise, i, firstPass) {
var _this = this;
subscribe(promise, undefined, function (value) {
return _this._settledAt(FULFILLED, i, value, firstPass);
}, function (reason) {
return _this._settledAt(REJECTED, i, reason, firstPass);
});
};
return Enumerator;
}();
function setSettledResult(state, i, value) {
this._remaining--;
if (state === FULFILLED) {
this._result[i] = {
state: 'fulfilled',
value: value
};
} else {
this._result[i] = {
state: 'rejected',
reason: value
};
}
}
/**
`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
let promise1 = RSVP.resolve(1);
let promise2 = RSVP.resolve(2);
let promise3 = RSVP.resolve(3);
let 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
let promise1 = RSVP.resolve(1);
let promise2 = RSVP.reject(new Error("2"));
let promise3 = RSVP.reject(new Error("3"));
let 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
*/
function all(entries, label) {
if (!Array.isArray(entries)) {
return this.reject(new TypeError("Promise.all must be called with an array"), label);
}
return new Enumerator(this, entries, true /* abort on reject */, label).promise;
}
/**
`RSVP.Promise.race` returns a new promise which is settled in the same way as the
first passed promise to settle.
Example:
```javascript
let promise1 = new RSVP.Promise(function(resolve, reject){
setTimeout(function(){
resolve('promise 1');
}, 200);
});
let 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
let promise1 = new RSVP.Promise(function(resolve, reject){
setTimeout(function(){
resolve('promise 1');
}, 200);
});
let 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} entries 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.
*/
function race(entries, label) {
/*jshint validthis:true */
var Constructor = this;
var promise = new Constructor(noop, label);
if (!Array.isArray(entries)) {
reject(promise, new TypeError('Promise.race must be called with an array'));
return promise;
}
for (var i = 0; promise._state === PENDING && i < entries.length; i++) {
subscribe(Constructor.resolve(entries[i]), undefined, function (value) {
return resolve$1(promise, value);
}, function (reason) {
return reject(promise, reason);
});
}
return promise;
}
/**
`RSVP.Promise.reject` returns a promise rejected with the passed `reason`.
It is shorthand for the following:
```javascript
let 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
let 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 {*} 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`.
*/
function reject$1(reason, label) {
/*jshint validthis:true */
var Constructor = this;
var promise = new Constructor(noop, label);
reject(promise, reason);
return promise;
}
var guidKey = 'rsvp_' + Date.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.");
}
/**
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
let 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){
let 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
*/
var Promise = function () {
function Promise(resolver, label) {
(0, _emberBabel.classCallCheck)(this, Promise);
this._id = counter++;
this._label = label;
this._state = undefined;
this._result = undefined;
this._subscribers = [];
config.instrument && instrument('created', this);
if (noop !== resolver) {
typeof resolver !== 'function' && needsResolver();
this instanceof Promise ? initializePromise(this, resolver) : needsNew();
}
}
Promise.prototype._onError = function _onError(reason) {
var _this2 = this;
config.after(function () {
if (_this2._onError) {
config.trigger('error', reason, _this2._label);
}
});
};
Promise.prototype.catch = function _catch(onRejection, label) {
return this.then(undefined, onRejection, label);
};
Promise.prototype.finally = function _finally(callback, label) {
var promise = this;
var constructor = promise.constructor;
return promise.then(function (value) {
return constructor.resolve(callback()).then(function () {
return value;
});
}, function (reason) {
return constructor.resolve(callback()).then(function () {
throw reason;
});
}, label);
};
return Promise;
}();
Promise.cast = resolve$$1; // deprecated
Promise.all = all;
Promise.race = race;
Promise.resolve = resolve$$1;
Promise.reject = reject$1;
Promise.prototype._guidKey = guidKey;
/**
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
let 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
let 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} onFulfillment
@param {Function} onRejection
@param {String} label optional string for labeling the promise.
Useful for tooling.
@return {Promise}
*/
Promise.prototype.then = then;
function makeObject(_, argumentNames) {
var obj = {};
var length = _.length;
var args = new Array(length);
for (var x = 0; x < length; x++) {
args[x] = _[x];
}
for (var i = 0; i < argumentNames.length; i++) {
var 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
let fs = require('fs');
fs.readFile('myfile.txt', function(err, data){
if (err) return handleError(err);
handleData(data);
});
```
into:
```javascript
let fs = require('fs');
let 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
let 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
let 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
let 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
let app = require('express')();
let 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
let 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
let 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
let fs = require('fs');
let readFile = RSVP.denodeify(fs.readFile);
let 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} [options] 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
*/
function denodeify(nodeFunc, options) {
var fn = function () {
var l = arguments.length;
var args = new Array(l + 1);
var promiseInput = false;
for (var i = 0; i < l; ++i) {
var arg = arguments[i];
if (!promiseInput) {
// TODO: clean this up
promiseInput = needsPromiseInput(arg);
if (promiseInput === TRY_CATCH_ERROR) {
var error = TRY_CATCH_ERROR.error;
TRY_CATCH_ERROR.error = null;
var p = new Promise(noop);
reject(p, error);
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$1(promise, val);
} else if (options === true) {
resolve$1(promise, arrayResult(arguments));
} else if (Array.isArray(options)) {
resolve$1(promise, makeObject(arguments, options));
} else {
resolve$1(promise, val);
}
};
if (promiseInput) {
return handlePromiseInput(promise, args, nodeFunc, this);
} else {
return handleValueInput(promise, args, nodeFunc, this);
}
};
fn.__proto__ = nodeFunc;
return fn;
}
function handleValueInput(promise, args, nodeFunc, self) {
var result = tryCatch(nodeFunc).apply(self, args);
if (result === TRY_CATCH_ERROR) {
var error = TRY_CATCH_ERROR.error;
TRY_CATCH_ERROR.error = null;
reject(promise, error);
}
return promise;
}
function handlePromiseInput(promise, args, nodeFunc, self) {
return Promise.all(args).then(function (args) {
return handleValueInput(promise, args, nodeFunc, self);
});
}
function needsPromiseInput(arg) {
if (arg !== null && typeof arg === 'object') {
if (arg.constructor === Promise) {
return true;
} else {
return getThen(arg);
}
} else {
return false;
}
}
/**
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.
*/
function all$1(array, label) {
return Promise.all(array, label);
}
var AllSettled = function (_Enumerator) {
(0, _emberBabel.inherits)(AllSettled, _Enumerator);
function AllSettled(Constructor, entries, label) {
(0, _emberBabel.classCallCheck)(this, AllSettled);
return (0, _emberBabel.possibleConstructorReturn)(this, _Enumerator.call(this, Constructor, entries, false /* don't abort on reject */, label));
}
return AllSettled;
}(Enumerator);
AllSettled.prototype._setResultAt = setSettledResult;
/**
`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
let promise1 = RSVP.Promise.resolve(1);
let promise2 = RSVP.Promise.reject(new Error('2'));
let promise3 = RSVP.Promise.reject(new Error('3'));
let 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} entries
@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.
*/
function allSettled(entries, label) {
if (!Array.isArray(entries)) {
return Promise.reject(new TypeError("Promise.allSettled must be called with an array"), label);
}
return new AllSettled(Promise, entries, label).promise;
}
/**
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.
*/
function race$1(array, label) {
return Promise.race(array, label);
}
var PromiseHash = function (_Enumerator2) {
(0, _emberBabel.inherits)(PromiseHash, _Enumerator2);
function PromiseHash(Constructor, object) {
var abortOnReject = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
var label = arguments[3];
(0, _emberBabel.classCallCheck)(this, PromiseHash);
return (0, _emberBabel.possibleConstructorReturn)(this, _Enumerator2.call(this, Constructor, object, abortOnReject, label));
}
PromiseHash.prototype._init = function _init(Constructor, object) {
this._result = {};
this._enumerate(object);
};
PromiseHash.prototype._enumerate = function _enumerate(input) {
var keys = Object.keys(input);
var length = keys.length;
var promise = this.promise;
this._remaining = length;
var key = void 0,
val = void 0;
for (var i = 0; promise._state === PENDING && i < length; i++) {
key = keys[i];
val = input[key];
this._eachEntry(val, key, true);
}
this._checkFullfillment();
};
return PromiseHash;
}(Enumerator);
/**
`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
let 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
let 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')
};
let 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} object
@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.
*/
function hash(object, label) {
if (object === null || typeof object !== 'object') {
return Promise.reject(new TypeError("Promise.hash must be called with an object"), label);
}
return new PromiseHash(Promise, object, label).promise;
}
var HashSettled = function (_PromiseHash) {
(0, _emberBabel.inherits)(HashSettled, _PromiseHash);
function HashSettled(Constructor, object, label) {
(0, _emberBabel.classCallCheck)(this, HashSettled);
return (0, _emberBabel.possibleConstructorReturn)(this, _PromiseHash.call(this, Constructor, object, false, label));
}
return HashSettled;
}(PromiseHash);
HashSettled.prototype._setResultAt = setSettledResult;
/**
`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
let 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
let 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')
};
let 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} object
@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
*/
function hashSettled(object, label) {
if (object === null || typeof object !== 'object') {
return Promise.reject(new TypeError("RSVP.hashSettled must be called with an object"), label);
}
return new HashSettled(Promise, object, false, label).promise;
}
/**
`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!');
}
let 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
*/
function rethrow(reason) {
setTimeout(function () {
throw reason;
});
throw reason;
}
/**
`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
let deferred = RSVP.defer();
deferred.resolve("Success!");
deferred.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}
*/
function defer(label) {
var deferred = { resolve: undefined, reject: undefined };
deferred.promise = new Promise(function (resolve, reject) {
deferred.resolve = resolve;
deferred.reject = reject;
}, label);
return deferred;
}
var MapEnumerator = function (_Enumerator3) {
(0, _emberBabel.inherits)(MapEnumerator, _Enumerator3);
function MapEnumerator(Constructor, entries, mapFn, label) {
(0, _emberBabel.classCallCheck)(this, MapEnumerator);
return (0, _emberBabel.possibleConstructorReturn)(this, _Enumerator3.call(this, Constructor, entries, true, label, mapFn));
}
MapEnumerator.prototype._init = function _init(Constructor, input, bool, label, mapFn) {
var len = input.length || 0;
this.length = len;
this._remaining = len;
this._result = new Array(len);
this._mapFn = mapFn;
this._enumerate(input);
};
MapEnumerator.prototype._setResultAt = function _setResultAt(state, i, value, firstPass) {
if (firstPass) {
var val = tryCatch(this._mapFn)(value, i);
if (val === TRY_CATCH_ERROR) {
this._settledAt(REJECTED, i, val.error, false);
} else {
this._eachEntry(val, i, false);
}
} else {
this._remaining--;
this._result[i] = value;
}
};
return MapEnumerator;
}(Enumerator);
/**
`RSVP.map` is similar to JavaScript's native `map` method. `mapFn` is eagerly called
meaning that as soon as any promise resolves its value will be passed to `mapFn`.
`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
let promise1 = RSVP.resolve(1);
let promise2 = RSVP.resolve(2);
let promise3 = RSVP.resolve(3);
let promises = [ promise1, promise2, promise3 ];
let 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
let promise1 = RSVP.resolve(1);
let promise2 = RSVP.reject(new Error('2'));
let promise3 = RSVP.reject(new Error('3'));
let promises = [ promise1, promise2, promise3 ];
let 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
let 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
*/
function map(promises, mapFn, label) {
if (!Array.isArray(promises)) {
return Promise.reject(new TypeError("RSVP.map must be called with an array"), label);
}
if (typeof mapFn !== 'function') {
return Promise.reject(new TypeError("RSVP.map expects a function as a second argument"), label);
}
return new MapEnumerator(Promise, promises, mapFn, label).promise;
}
/**
This is a convenient alias for `RSVP.Promise.resolve`.
@method resolve
@static
@for RSVP
@param {*} 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`
*/
function resolve$2(value, label) {
return Promise.resolve(value, label);
}
/**
This is a convenient alias for `RSVP.Promise.reject`.
@method reject
@static
@for RSVP
@param {*} 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`.
*/
function reject$2(reason, label) {
return Promise.reject(reason, label);
}
var EMPTY_OBJECT = {};
var FilterEnumerator = function (_MapEnumerator) {
(0, _emberBabel.inherits)(FilterEnumerator, _MapEnumerator);
function FilterEnumerator() {
(0, _emberBabel.classCallCheck)(this, FilterEnumerator);
return (0, _emberBabel.possibleConstructorReturn)(this, _MapEnumerator.apply(this, arguments));
}
FilterEnumerator.prototype._checkFullfillment = function _checkFullfillment() {
if (this._remaining === 0 && this._result !== null) {
var result = this._result.filter(function (val) {
return val !== EMPTY_OBJECT;
});
fulfill(this.promise, result);
this._result = null;
}
};
FilterEnumerator.prototype._setResultAt = function _setResultAt(state, i, value, firstPass) {
if (firstPass) {
this._result[i] = value;
var val = tryCatch(this._mapFn)(value, i);
if (val === TRY_CATCH_ERROR) {
this._settledAt(REJECTED, i, val.error, false);
} else {
this._eachEntry(val, i, false);
}
} else {
this._remaining--;
if (!value) {
this._result[i] = EMPTY_OBJECT;
}
}
};
return FilterEnumerator;
}(MapEnumerator);
/**
`RSVP.filter` is similar to JavaScript's native `filter` method.
`filterFn` is eagerly called meaning that as soon as any promise
resolves its value will be passed to `filterFn`. `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
let promise1 = RSVP.resolve(1);
let promise2 = RSVP.resolve(2);
let promise3 = RSVP.resolve(3);
let promises = [promise1, promise2, promise3];
let 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
let promise1 = RSVP.resolve(1);
let promise2 = RSVP.reject(new Error('2'));
let promise3 = RSVP.reject(new Error('3'));
let promises = [ promise1, promise2, promise3 ];
let 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
let alice = { name: 'alice' };
let bob = { name: 'bob' };
let users = [ alice, bob ];
let promises = users.map(function(user){
return RSVP.resolve(user);
});
let 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}
*/
function filter(promises, filterFn, label) {
if (typeof filterFn !== 'function') {
return Promise.reject(new TypeError("RSVP.filter expects function as a second argument"), label);
}
return Promise.resolve(promises, label).then(function (promises) {
if (!Array.isArray(promises)) {
throw new TypeError("RSVP.filter must be called with an array");
}
return new FilterEnumerator(Promise, promises, filterFn, label).promise;
});
}
var len = 0;
var vertxNext = void 0;
function asap(callback, arg) {
queue$1[len] = callback;
queue$1[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$1();
}
}
var browserWindow = typeof window !== 'undefined' ? window : undefined;
var browserGlobal = browserWindow || {};
var BrowserMutationObserver = browserGlobal.MutationObserver || browserGlobal.WebKitMutationObserver;
var isNode = typeof self === 'undefined' && typeof process !== 'undefined' && {}.toString.call(process) === '[object process]';
// test for web worker but not in IE10
var isWorker = typeof Uint8ClampedArray !== 'undefined' && typeof importScripts !== 'undefined' && typeof MessageChannel !== 'undefined';
// node
function useNextTick() {
var nextTick = process.nextTick;
// node version 0.10.x displays a deprecation warning when nextTick is used recursively
// setImmediate should be used instead instead
var version = process.versions.node.match(/^(?:(\d+)\.)?(?:(\d+)\.)?(\*|\d+)$/);
if (Array.isArray(version) && version[1] === '0' && version[2] === '10') {
nextTick = setImmediate;
}
return function () {
return nextTick(flush);
};
}
// vertx
function useVertxTimer() {
if (typeof vertxNext !== 'undefined') {
return function () {
vertxNext(flush);
};
}
return useSetTimeout();
}
function useMutationObserver() {
var iterations = 0;
var observer = new BrowserMutationObserver(flush);
var node = document.createTextNode('');
observer.observe(node, { characterData: true });
return function () {
return node.data = iterations = ++iterations % 2;
};
}
// web worker
function useMessageChannel() {
var channel = new MessageChannel();
channel.port1.onmessage = flush;
return function () {
return channel.port2.postMessage(0);
};
}
function useSetTimeout() {
return function () {
return setTimeout(flush, 1);
};
}
var queue$1 = new Array(1000);
function flush() {
for (var i = 0; i < len; i += 2) {
var callback = queue$1[i];
var arg = queue$1[i + 1];
callback(arg);
queue$1[i] = undefined;
queue$1[i + 1] = undefined;
}
len = 0;
}
function attemptVertex() {
try {
var vertx = Function('return this')().require('vertx');
vertxNext = vertx.runOnLoop || vertx.runOnContext;
return useVertxTimer();
} catch (e) {
return useSetTimeout();
}
}
var scheduleFlush$1 = void 0;
// Decide what async method to use to triggering processing of queued callbacks:
if (isNode) {
scheduleFlush$1 = useNextTick();
} else if (BrowserMutationObserver) {
scheduleFlush$1 = useMutationObserver();
} else if (isWorker) {
scheduleFlush$1 = useMessageChannel();
} else if (browserWindow === undefined && typeof _nodeModule.require === 'function') {
scheduleFlush$1 = attemptVertex();
} else {
scheduleFlush$1 = useSetTimeout();
}
// defaults
config.async = asap;
config.after = function (cb) {
return setTimeout(cb, 0);
};
var cast = resolve$2;
var async = function (callback, arg) {
return 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]);
}
}
}
// the default export here is for backwards compat:
// https://github.com/tildeio/rsvp.js/issues/434
var rsvp = {
asap: asap,
cast: cast,
Promise: Promise,
EventTarget: EventTarget,
all: all$1,
allSettled: allSettled,
race: race$1,
hash: hash,
hashSettled: hashSettled,
rethrow: rethrow,
defer: defer,
denodeify: denodeify,
configure: configure,
on: on,
off: off,
resolve: resolve$2,
reject: reject$2,
map: map,
async: async,
filter: filter
};
exports.default = rsvp;
exports.asap = asap;
exports.cast = cast;
exports.Promise = Promise;
exports.EventTarget = EventTarget;
exports.all = all$1;
exports.allSettled = allSettled;
exports.race = race$1;
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$2;
exports.reject = reject$2;
exports.map = map;
exports.async = async;
exports.filter = filter;
});
requireModule('ember')
}());
//# sourceMappingURL=ember.debug.map