)
App.inject('route', 'source', 'source:main')
App.inject('route:application', 'email', 'model:email')
```
It is important to note that injections can only be performed on
classes that are instantiated by Ember itself. Instantiating a class
directly (via `create` or `new`) bypasses the dependency injection
system.
@public
@method inject
@param factoryNameOrType {String}
@param property {String}
@param injectionName {String}
**/
inject: registryAlias('injection')
});
function registryAlias(name) {
return function () {
var _registry__;
return (_registry__ = this.__registry__)[name].apply(_registry__, arguments);
};
}
});
enifed('ember-runtime/lib/mixins/target_action_support', ['exports', 'ember-environment', 'ember-metal', '@ember/debug', '@ember/deprecated-features'], function (exports, _emberEnvironment, _emberMetal, _debug, _deprecatedFeatures) {
'use strict';
exports.default = _emberMetal.Mixin.create({
target: null,
targetObject: _deprecatedFeatures.TARGET_OBJECT ? (0, _emberMetal.descriptor)({
configurable: true,
enumerable: false,
get: function () {
var message = this + ' Usage of `targetObject` is deprecated. Please use `target` instead.';
false && !false && (0, _debug.deprecate)(message, false, { id: 'ember-runtime.using-targetObject', until: '3.5.0' });
return this._targetObject;
},
set: function (value) {
var message = this + ' Usage of `targetObject` is deprecated. Please use `target` instead.';
false && !false && (0, _debug.deprecate)(message, false, { id: 'ember-runtime.using-targetObject', until: '3.5.0' });
this._targetObject = value;
}
}) : undefined,
action: null,
actionContext: null,
actionContextObject: (0, _emberMetal.computed)('actionContext', function () {
var actionContext = (0, _emberMetal.get)(this, 'actionContext'),
value;
if (typeof actionContext === 'string') {
value = (0, _emberMetal.get)(this, actionContext);
if (value === undefined) {
value = (0, _emberMetal.get)(_emberEnvironment.context.lookup, actionContext);
}
return value;
} else {
return actionContext;
}
}),
/**
Send an `action` with an `actionContext` to a `target`. The action, actionContext
and target will be retrieved from properties of the object. For example:
```javascript
import { alias } from '@ember/object/computed';
App.SaveButtonView = Ember.View.extend(Ember.TargetActionSupport, {
target: alias('controller'),
action: 'save',
actionContext: alias('context'),
click() {
this.triggerAction(); // Sends the `save` action, along with the current context
// to the current controller
}
});
```
The `target`, `action`, and `actionContext` can be provided as properties of
an optional object argument to `triggerAction` as well.
```javascript
App.SaveButtonView = Ember.View.extend(Ember.TargetActionSupport, {
click() {
this.triggerAction({
action: 'save',
target: this.get('controller'),
actionContext: this.get('context')
}); // Sends the `save` action, along with the current context
// to the current controller
}
});
```
The `actionContext` defaults to the object you are mixing `TargetActionSupport` into.
But `target` and `action` must be specified either as properties or with the argument
to `triggerAction`, or a combination:
```javascript
import { alias } from '@ember/object/computed';
App.SaveButtonView = Ember.View.extend(Ember.TargetActionSupport, {
target: alias('controller'),
click() {
this.triggerAction({
action: 'save'
}); // Sends the `save` action, along with a reference to `this`,
// to the current controller
}
});
```
@method triggerAction
@param opts {Object} (optional, with the optional keys action, target and/or actionContext)
@return {Boolean} true if the action was sent successfully and did not return false
@private
*/
triggerAction: function () {
var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
ret,
_target,
_target2;
var action = opts.action,
target = opts.target,
actionContext = opts.actionContext;
action = action || (0, _emberMetal.get)(this, 'action');
target = target || getTarget(this);
if (actionContext === undefined) {
actionContext = (0, _emberMetal.get)(this, 'actionContextObject') || this;
}
if (target && action) {
ret = void 0;
if (target.send) {
ret = (_target = target).send.apply(_target, [action].concat(actionContext));
} else {
false && !(typeof target[action] === 'function') && (0, _debug.assert)('The action \'' + action + '\' did not exist on ' + target, typeof target[action] === 'function');
ret = (_target2 = target)[action].apply(_target2, [].concat(actionContext));
}
if (ret !== false) {
return true;
}
}
return false;
}
});
function getTarget(instance) {
var target = (0, _emberMetal.get)(instance, 'target'),
value;
if (target) {
if (typeof target === 'string') {
value = (0, _emberMetal.get)(instance, target);
if (value === undefined) {
value = (0, _emberMetal.get)(_emberEnvironment.context.lookup, target);
}
return value;
} else {
return target;
}
}
// if a `targetObject` CP was provided, use it
if (target) {
return target;
}
// if _targetObject use it
if (_deprecatedFeatures.TARGET_OBJECT && instance._targetObject) {
return instance._targetObject;
}
return null;
}
});
enifed('ember-runtime/lib/system/array_proxy', ['exports', 'ember-babel', 'ember-metal', 'ember-runtime/lib/system/object', 'ember-runtime/lib/mixins/array', '@ember/debug'], function (exports, _emberBabel, _emberMetal, _object, _array, _debug) {
'use strict';
/**
@module @ember/array
*/
var ARRAY_OBSERVER_MAPPING = {
willChange: '_arrangedContentArrayWillChange',
didChange: '_arrangedContentArrayDidChange'
};
/**
An ArrayProxy wraps any other object that implements `Array` and/or
`MutableArray,` forwarding all requests. This makes it very useful for
a number of binding use cases or other cases where being able to swap
out the underlying array is useful.
A simple example of usage:
```javascript
import { A } from '@ember/array';
import ArrayProxy from '@ember/array/proxy';
let pets = ['dog', 'cat', 'fish'];
let ap = ArrayProxy.create({ content: A(pets) });
ap.get('firstObject'); // 'dog'
ap.set('content', ['amoeba', 'paramecium']);
ap.get('firstObject'); // 'amoeba'
```
This class can also be useful as a layer to transform the contents of
an array, as they are accessed. This can be done by overriding
`objectAtContent`:
```javascript
import { A } from '@ember/array';
import ArrayProxy from '@ember/array/proxy';
let pets = ['dog', 'cat', 'fish'];
let ap = ArrayProxy.create({
content: A(pets),
objectAtContent: function(idx) {
return this.get('content').objectAt(idx).toUpperCase();
}
});
ap.get('firstObject'); // . 'DOG'
```
When overriding this class, it is important to place the call to
`_super` *after* setting `content` so the internal observers have
a chance to fire properly:
```javascript
import { A } from '@ember/array';
import ArrayProxy from '@ember/array/proxy';
export default ArrayProxy.extend({
init() {
this.set('content', A(['dog', 'cat', 'fish']));
this._super(...arguments);
}
});
```
@class ArrayProxy
@extends EmberObject
@uses MutableArray
@public
*/
var ArrayProxy = function (_EmberObject) {
(0, _emberBabel.inherits)(ArrayProxy, _EmberObject);
function ArrayProxy() {
return (0, _emberBabel.possibleConstructorReturn)(this, _EmberObject.apply(this, arguments));
}
ArrayProxy.prototype.init = function () {
var _EmberObject$prototyp;
(_EmberObject$prototyp = _EmberObject.prototype.init).call.apply(_EmberObject$prototyp, [this].concat(Array.prototype.slice.call(arguments)));
/*
`this._objectsDirtyIndex` determines which indexes in the `this._objects`
cache are dirty.
If `this._objectsDirtyIndex === -1` then no indexes are dirty.
Otherwise, an index `i` is dirty if `i >= this._objectsDirtyIndex`.
Calling `objectAt` with a dirty index will cause the `this._objects`
cache to be recomputed.
*/
this._objectsDirtyIndex = 0;
this._objects = null;
this._lengthDirty = true;
this._length = 0;
this._arrangedContent = null;
this._addArrangedContentArrayObsever();
};
ArrayProxy.prototype.willDestroy = function () {
this._removeArrangedContentArrayObsever();
};
ArrayProxy.prototype.objectAtContent = function (idx) {
return (0, _emberMetal.objectAt)((0, _emberMetal.get)(this, 'arrangedContent'), idx);
};
ArrayProxy.prototype.replace = function (idx, amt, objects) {
false && !((0, _emberMetal.get)(this, 'arrangedContent') === (0, _emberMetal.get)(this, 'content')) && (0, _debug.assert)('Mutating an arranged ArrayProxy is not allowed', (0, _emberMetal.get)(this, 'arrangedContent') === (0, _emberMetal.get)(this, 'content'));
this.replaceContent(idx, amt, objects);
};
ArrayProxy.prototype.replaceContent = function (idx, amt, objects) {
(0, _emberMetal.get)(this, 'content').replace(idx, amt, objects);
};
ArrayProxy.prototype.objectAt = function (idx) {
var arrangedContent, length, i;
if (this._objects === null) {
this._objects = [];
}
if (this._objectsDirtyIndex !== -1 && idx >= this._objectsDirtyIndex) {
arrangedContent = (0, _emberMetal.get)(this, 'arrangedContent');
if (arrangedContent) {
length = this._objects.length = (0, _emberMetal.get)(arrangedContent, 'length');
for (i = this._objectsDirtyIndex; i < length; i++) {
this._objects[i] = this.objectAtContent(i);
}
} else {
this._objects.length = 0;
}
this._objectsDirtyIndex = -1;
}
return this._objects[idx];
};
ArrayProxy.prototype[_emberMetal.PROPERTY_DID_CHANGE] = function (key) {
var oldLength, arrangedContent, newLength;
if (key === 'arrangedContent') {
oldLength = this._objects === null ? 0 : this._objects.length;
arrangedContent = (0, _emberMetal.get)(this, 'arrangedContent');
newLength = arrangedContent ? (0, _emberMetal.get)(arrangedContent, 'length') : 0;
this._removeArrangedContentArrayObsever();
this.arrayContentWillChange(0, oldLength, newLength);
this._invalidate();
this.arrayContentDidChange(0, oldLength, newLength);
this._addArrangedContentArrayObsever();
} else if (key === 'content') {
this._invalidate();
}
};
ArrayProxy.prototype._addArrangedContentArrayObsever = function () {
var arrangedContent = (0, _emberMetal.get)(this, 'arrangedContent');
if (arrangedContent) {
false && !(arrangedContent !== this) && (0, _debug.assert)("Can't set ArrayProxy's content to itself", arrangedContent !== this);
false && !((0, _array.isArray)(arrangedContent) || arrangedContent.isDestroyed) && (0, _debug.assert)('ArrayProxy expects an Array or ArrayProxy, but you passed ' + typeof arrangedContent, (0, _array.isArray)(arrangedContent) || arrangedContent.isDestroyed);
(0, _emberMetal.addArrayObserver)(arrangedContent, this, ARRAY_OBSERVER_MAPPING);
this._arrangedContent = arrangedContent;
}
};
ArrayProxy.prototype._removeArrangedContentArrayObsever = function () {
if (this._arrangedContent) {
(0, _emberMetal.removeArrayObserver)(this._arrangedContent, this, ARRAY_OBSERVER_MAPPING);
}
};
ArrayProxy.prototype._arrangedContentArrayWillChange = function () {};
ArrayProxy.prototype._arrangedContentArrayDidChange = function (proxy, idx, removedCnt, addedCnt) {
this.arrayContentWillChange(idx, removedCnt, addedCnt);
var dirtyIndex = idx,
length;
if (dirtyIndex < 0) {
length = (0, _emberMetal.get)(this._arrangedContent, 'length');
dirtyIndex += length + removedCnt - addedCnt;
}
if (this._objectsDirtyIndex === -1) {
this._objectsDirtyIndex = dirtyIndex;
} else {
if (this._objectsDirtyIndex > dirtyIndex) {
this._objectsDirtyIndex = dirtyIndex;
}
}
this._lengthDirty = true;
this.arrayContentDidChange(idx, removedCnt, addedCnt);
};
ArrayProxy.prototype._invalidate = function () {
this._objectsDirtyIndex = 0;
this._lengthDirty = true;
};
(0, _emberBabel.createClass)(ArrayProxy, [{
key: 'length',
get: function () {
var arrangedContent;
if (this._lengthDirty) {
arrangedContent = (0, _emberMetal.get)(this, 'arrangedContent');
this._length = arrangedContent ? (0, _emberMetal.get)(arrangedContent, 'length') : 0;
this._lengthDirty = false;
}
return this._length;
},
set: function (value) {
var length = this.length;
var removedCount = length - value;
var added = void 0;
if (removedCount === 0) {
return;
} else if (removedCount < 0) {
added = new Array(-removedCount);
removedCount = 0;
}
var content = (0, _emberMetal.get)(this, 'content');
if (content) {
(0, _emberMetal.replace)(content, value, removedCount, added);
this._invalidate();
}
}
}]);
return ArrayProxy;
}(_object.default);
exports.default = ArrayProxy;
ArrayProxy.reopen(_array.MutableArray, {
/**
The array that the proxy pretends to be. In the default `ArrayProxy`
implementation, this and `content` are the same. Subclasses of `ArrayProxy`
can override this property to provide things like sorting and filtering.
@property arrangedContent
@public
*/
arrangedContent: (0, _emberMetal.alias)('content')
});
});
enifed('ember-runtime/lib/system/core_object', ['exports', 'ember-babel', 'container', '@ember/deprecated-features', '@ember/polyfills', 'ember-utils', '@ember/runloop', 'ember-meta', 'ember-metal', 'ember-runtime/lib/mixins/action_handler', '@ember/debug', 'ember-environment'], function (exports, _emberBabel, _container, _deprecatedFeatures, _polyfills, _emberUtils, _runloop, _emberMeta, _emberMetal, _action_handler, _debug, _emberEnvironment) {
'use strict';
/**
@module @ember/object
*/
var _reopen = _emberMetal.Mixin.prototype.reopen;
var wasApplied = new _emberUtils.WeakSet();
var factoryMap = new WeakMap();
var prototypeMixinMap = new WeakMap();
/**
@class CoreObject
@public
*/
var CoreObject = function () {
CoreObject._initFactory = function (factory) {
factoryMap.set(this, factory);
};
function CoreObject(properties) {
var _self, concatenatedProperties, mergedProperties, hasConcatenatedProps, hasMergedProps, keyNames, i, keyName, value, possibleDesc, isDescriptor, baseValue;
// pluck off factory
var initFactory = factoryMap.get(this.constructor);
if (initFactory !== undefined) {
factoryMap.delete(this.constructor);
_container.FACTORY_FOR.set(this, initFactory);
}
// prepare prototype...
this.constructor.proto();
var self = this; // only used in debug builds to enable the proxy trap
// using DEBUG here to avoid the extraneous variable when not needed
var m = (0, _emberMeta.meta)(self);
var proto = m.proto;
m.proto = self;
if (properties !== undefined) {
false && !(typeof properties === 'object' && properties !== null) && (0, _debug.assert)('EmberObject.create only accepts objects.', typeof properties === 'object' && properties !== null);
false && !!(properties instanceof _emberMetal.Mixin) && (0, _debug.assert)('EmberObject.create no longer supports mixing in other ' + 'definitions, use .extend & .create separately instead.', !(properties instanceof _emberMetal.Mixin));
concatenatedProperties = self.concatenatedProperties;
mergedProperties = self.mergedProperties;
hasConcatenatedProps = concatenatedProperties !== undefined && concatenatedProperties.length > 0;
hasMergedProps = mergedProperties !== undefined && mergedProperties.length > 0;
keyNames = Object.keys(properties);
for (i = 0; i < keyNames.length; i++) {
keyName = keyNames[i];
value = properties[keyName];
if (_deprecatedFeatures.BINDING_SUPPORT && _emberEnvironment.ENV._ENABLE_BINDING_SUPPORT && _emberMetal.Mixin.detectBinding(keyName)) {
m.writeBindings(keyName, value);
}
false && !!(value instanceof _emberMetal.ComputedProperty) && (0, _debug.assert)('EmberObject.create no longer supports defining computed ' + 'properties. Define computed properties using extend() or reopen() ' + 'before calling create().', !(value instanceof _emberMetal.ComputedProperty));
false && !!(typeof value === 'function' && value.toString().indexOf('._super') !== -1) && (0, _debug.assert)('EmberObject.create no longer supports defining methods that call _super.', !(typeof value === 'function' && value.toString().indexOf('._super') !== -1));
false && !!(keyName === 'actions' && _action_handler.default.detect(this)) && (0, _debug.assert)('`actions` must be provided at extend time, not at create time, ' + 'when Ember.ActionHandler is used (i.e. views, controllers & routes).', !(keyName === 'actions' && _action_handler.default.detect(this)));
possibleDesc = (0, _emberMeta.descriptorFor)(self, keyName, m);
isDescriptor = possibleDesc !== undefined;
if (!isDescriptor) {
baseValue = self[keyName];
if (hasConcatenatedProps && concatenatedProperties.indexOf(keyName) > -1) {
if (baseValue) {
value = (0, _emberUtils.makeArray)(baseValue).concat(value);
} else {
value = (0, _emberUtils.makeArray)(value);
}
}
if (hasMergedProps && mergedProperties.indexOf(keyName) > -1) {
value = (0, _polyfills.assign)({}, baseValue, value);
}
}
if (isDescriptor) {
possibleDesc.set(self, keyName, value);
} else if (typeof self.setUnknownProperty === 'function' && !(keyName in self)) {
self.setUnknownProperty(keyName, value);
} else {
self[keyName] = value;
}
}
}
if (_deprecatedFeatures.BINDING_SUPPORT && _emberEnvironment.ENV._ENABLE_BINDING_SUPPORT) {
_emberMetal.Mixin.finishPartial(self, m);
}
// using DEBUG here to avoid the extraneous variable when not needed
(_self = self).init.apply(_self, arguments);
m.proto = proto;
(0, _emberMetal.finishChains)(m);
(0, _emberMetal.sendEvent)(self, 'init', undefined, undefined, undefined, m);
// only return when in debug builds and `self` is the proxy created above
}
CoreObject.prototype.reopen = function () {
var _len, args, _key;
for (_len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
(0, _emberMetal.applyMixin)(this, args, true);
return this;
};
CoreObject.prototype.init = function () {};
CoreObject.prototype.destroy = function () {
var m = (0, _emberMeta.peekMeta)(this);
if (m.isSourceDestroying()) {
return;
}
m.setSourceDestroying();
(0, _runloop.schedule)('actions', this, this.willDestroy);
(0, _runloop.schedule)('destroy', this, this._scheduledDestroy, m);
return this;
};
CoreObject.prototype.willDestroy = function () {};
CoreObject.prototype._scheduledDestroy = function (m) {
if (m.isSourceDestroyed()) {
return;
}
(0, _emberMeta.deleteMeta)(this);
m.setSourceDestroyed();
};
CoreObject.prototype.toString = function () {
var hasToStringExtension = typeof this.toStringExtension === 'function';
var extension = hasToStringExtension ? ':' + this.toStringExtension() : '';
var ret = '<' + ((0, _emberUtils.getName)(this) || _container.FACTORY_FOR.get(this) || this.constructor.toString()) + ':' + (0, _emberUtils.guidFor)(this) + extension + '>';
return ret;
};
CoreObject.extend = function () {
var Class = function (_ref) {
(0, _emberBabel.inherits)(Class, _ref);
function Class() {
return (0, _emberBabel.possibleConstructorReturn)(this, _ref.apply(this, arguments));
}
return Class;
}(this);
_reopen.apply(Class.PrototypeMixin, arguments);
return Class;
};
CoreObject.create = function (props, extra) {
var C = this;
if (extra === undefined) {
return new C(props);
} else {
return new C(flattenProps.apply(this, arguments));
}
};
CoreObject.reopen = function () {
this.willReopen();
_reopen.apply(this.PrototypeMixin, arguments);
return this;
};
CoreObject.willReopen = function () {
var p = this.prototype;
if (wasApplied.has(p)) {
wasApplied.delete(p);
// If the base mixin already exists and was applied, create a new mixin to
// make sure that it gets properly applied. Reusing the same mixin after
// the first `proto` call will cause it to get skipped.
if (prototypeMixinMap.has(this)) {
prototypeMixinMap.set(this, _emberMetal.Mixin.create(this.PrototypeMixin));
}
}
};
CoreObject.reopenClass = function () {
(0, _emberMetal.applyMixin)(this, arguments, false);
return this;
};
CoreObject.detect = function (obj) {
if ('function' !== typeof obj) {
return false;
}
while (obj) {
if (obj === this) {
return true;
}
obj = obj.superclass;
}
return false;
};
CoreObject.detectInstance = function (obj) {
return obj instanceof this;
};
CoreObject.metaForProperty = function (key) {
var proto = this.proto(); // ensure prototype is initialized
var possibleDesc = (0, _emberMeta.descriptorFor)(proto, key);
false && !(possibleDesc !== undefined) && (0, _debug.assert)('metaForProperty() could not find a computed property with key \'' + key + '\'.', possibleDesc !== undefined);
return possibleDesc._meta || {};
};
CoreObject.eachComputedProperty = function (callback) {
var binding = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this;
this.proto(); // ensure prototype is initialized
var empty = {};
(0, _emberMeta.meta)(this.prototype).forEachDescriptors(function (name, descriptor) {
var _meta;
if (descriptor.enumerable) {
_meta = descriptor._meta || empty;
callback.call(binding, name, _meta);
}
});
};
CoreObject.proto = function () {
var p = this.prototype,
parent;
if (!wasApplied.has(p)) {
wasApplied.add(p);
parent = this.superclass;
if (parent) {
parent.proto();
}
// If the prototype mixin exists, apply it. In the case of native classes,
// it will not exist (unless the class has been reopened).
if (prototypeMixinMap.has(this)) {
this.PrototypeMixin.apply(p);
}
}
return p;
};
(0, _emberBabel.createClass)(CoreObject, [{
key: 'isDestroyed',
get: function () {
return (0, _emberMeta.peekMeta)(this).isSourceDestroyed();
},
set: function () {
false && !false && (0, _debug.assert)('You cannot set `' + this + '.isDestroyed` directly, please use `.destroy()`.', false);
}
}, {
key: 'isDestroying',
get: function () {
return (0, _emberMeta.peekMeta)(this).isSourceDestroying();
},
set: function () {
false && !false && (0, _debug.assert)('You cannot set `' + this + '.isDestroying` directly, please use `.destroy()`.', false);
}
}], [{
key: 'PrototypeMixin',
get: function () {
var prototypeMixin = prototypeMixinMap.get(this);
if (prototypeMixin === undefined) {
prototypeMixin = _emberMetal.Mixin.create();
prototypeMixin.ownerConstructor = this;
prototypeMixinMap.set(this, prototypeMixin);
}
return prototypeMixin;
}
}, {
key: 'superclass',
get: function () {
var c = Object.getPrototypeOf(this);
if (c !== Function.prototype) return c;
}
}]);
return CoreObject;
}();
CoreObject.toString = _emberMetal.classToString;
(0, _emberUtils.setName)(CoreObject, 'Ember.CoreObject');
CoreObject.isClass = true;
CoreObject.isMethod = false;
function flattenProps() {
var concatenatedProperties = this.concatenatedProperties,
mergedProperties = this.mergedProperties,
_len2,
props,
_key2,
i,
properties,
keyNames,
j,
k,
keyName,
value,
baseValue,
_baseValue;
var hasConcatenatedProps = concatenatedProperties !== undefined && concatenatedProperties.length > 0;
var hasMergedProps = mergedProperties !== undefined && mergedProperties.length > 0;
var initProperties = {};
for (_len2 = arguments.length, props = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
props[_key2] = arguments[_key2];
}
for (i = 0; i < props.length; i++) {
properties = props[i];
false && !!(properties instanceof _emberMetal.Mixin) && (0, _debug.assert)('EmberObject.create no longer supports mixing in other ' + 'definitions, use .extend & .create separately instead.', !(properties instanceof _emberMetal.Mixin));
keyNames = Object.keys(properties);
for (j = 0, k = keyNames.length; j < k; j++) {
keyName = keyNames[j];
value = properties[keyName];
if (hasConcatenatedProps && concatenatedProperties.indexOf(keyName) > -1) {
baseValue = initProperties[keyName];
if (baseValue) {
value = (0, _emberUtils.makeArray)(baseValue).concat(value);
} else {
value = (0, _emberUtils.makeArray)(value);
}
}
if (hasMergedProps && mergedProperties.indexOf(keyName) > -1) {
_baseValue = initProperties[keyName];
value = (0, _polyfills.assign)({}, _baseValue, value);
}
initProperties[keyName] = value;
}
}
return initProperties;
}
exports.default = CoreObject;
});
enifed('ember-runtime/lib/system/namespace', ['exports', 'ember-babel', 'ember-metal', 'ember-utils', 'ember-runtime/lib/system/object'], function (exports, _emberBabel, _emberMetal, _emberUtils, _object) {
'use strict';
var Namespace = function (_EmberObject) {
(0, _emberBabel.inherits)(Namespace, _EmberObject);
function Namespace() {
return (0, _emberBabel.possibleConstructorReturn)(this, _EmberObject.apply(this, arguments));
}
Namespace.prototype.init = function () {
(0, _emberMetal.addNamespace)(this);
};
Namespace.prototype.toString = function () {
var name = (0, _emberMetal.get)(this, 'name') || (0, _emberMetal.get)(this, 'modulePrefix');
if (name) {
return name;
}
(0, _emberMetal.findNamespaces)();
name = (0, _emberUtils.getName)(this);
if (name === undefined) {
name = (0, _emberUtils.guidFor)(this);
(0, _emberUtils.setName)(this, name);
}
return name;
};
Namespace.prototype.nameClasses = function () {
(0, _emberMetal.processNamespace)(this);
};
Namespace.prototype.destroy = function () {
(0, _emberMetal.removeNamespace)(this);
_EmberObject.prototype.destroy.call(this);
};
return Namespace;
}(_object.default);
exports.default = Namespace;
Namespace.prototype.isNamespace = true;
Namespace.NAMESPACES = _emberMetal.NAMESPACES;
Namespace.NAMESPACES_BY_ID = _emberMetal.NAMESPACES_BY_ID;
Namespace.processAll = _emberMetal.processAllNamespaces;
Namespace.byName = _emberMetal.findNamespace;
});
enifed('ember-runtime/lib/system/object', ['exports', 'ember-babel', 'container', 'ember-owner', 'ember-utils', 'ember-metal', 'ember-runtime/lib/system/core_object', 'ember-runtime/lib/mixins/observable', '@ember/debug'], function (exports, _emberBabel, _container, _emberOwner, _emberUtils, _emberMetal, _core_object, _observable) {
'use strict';
exports.FrameworkObject = undefined;
var OVERRIDE_OWNER = (0, _emberUtils.symbol)('OVERRIDE_OWNER');
/**
`EmberObject` is the main base class for all Ember objects. It is a subclass
of `CoreObject` with the `Observable` mixin applied. For details,
see the documentation for each of these.
@class EmberObject
@extends CoreObject
@uses Observable
@public
*/
/**
@module @ember/object
*/
var EmberObject = function (_CoreObject) {
(0, _emberBabel.inherits)(EmberObject, _CoreObject);
function EmberObject() {
return (0, _emberBabel.possibleConstructorReturn)(this, _CoreObject.apply(this, arguments));
}
(0, _emberBabel.createClass)(EmberObject, [{
key: '_debugContainerKey',
get: function () {
var factory = _container.FACTORY_FOR.get(this);
return factory !== undefined && factory.fullName;
}
}, {
key: _emberOwner.OWNER,
get: function () {
if (this[OVERRIDE_OWNER]) {
return this[OVERRIDE_OWNER];
}
var factory = _container.FACTORY_FOR.get(this);
return factory !== undefined && factory.owner;
},
set: function (value) {
this[OVERRIDE_OWNER] = value;
}
}]);
return EmberObject;
}(_core_object.default);
exports.default = EmberObject;
(0, _emberUtils.setName)(EmberObject, 'Ember.Object');
_observable.default.apply(EmberObject.prototype);
exports.FrameworkObject = EmberObject;
});
enifed('ember-runtime/lib/system/object_proxy', ['exports', 'ember-babel', 'ember-runtime/lib/system/object', 'ember-runtime/lib/mixins/-proxy'], function (exports, _emberBabel, _object, _proxy) {
'use strict';
var ObjectProxy = function (_FrameworkObject) {
(0, _emberBabel.inherits)(ObjectProxy, _FrameworkObject);
function ObjectProxy() {
return (0, _emberBabel.possibleConstructorReturn)(this, _FrameworkObject.apply(this, arguments));
}
return ObjectProxy;
}(_object.default);
exports.default = ObjectProxy;
ObjectProxy.PrototypeMixin.reopen(_proxy.default);
});
enifed('ember-runtime/lib/type-of', ['exports', 'ember-runtime/lib/system/object'], function (exports, _object) {
'use strict';
exports.typeOf =
/**
@module @ember/utils
*/
/**
Returns a consistent type for the passed object.
Use this instead of the built-in `typeof` to get the type of an item.
It will return the same result across all browsers and includes a bit
more detail. Here is what will be returned:
| Return Value | Meaning |
|---------------|------------------------------------------------------|
| 'string' | String primitive or String object. |
| 'number' | Number primitive or Number object. |
| 'boolean' | Boolean primitive or Boolean object. |
| 'null' | Null value |
| 'undefined' | Undefined value |
| 'function' | A function |
| 'array' | An instance of Array |
| 'regexp' | An instance of RegExp |
| 'date' | An instance of Date |
| 'filelist' | An instance of FileList |
| 'class' | An Ember class (created using EmberObject.extend()) |
| 'instance' | An Ember object instance |
| 'error' | An instance of the Error object |
| 'object' | A JavaScript object not inheriting from EmberObject |
Examples:
```javascript
import { A } from '@ember/array';
import { typeOf } from '@ember/utils';
import EmberObject from '@ember/object';
typeOf(); // 'undefined'
typeOf(null); // 'null'
typeOf(undefined); // 'undefined'
typeOf('michael'); // 'string'
typeOf(new String('michael')); // 'string'
typeOf(101); // 'number'
typeOf(new Number(101)); // 'number'
typeOf(true); // 'boolean'
typeOf(new Boolean(true)); // 'boolean'
typeOf(A); // 'function'
typeOf([1, 2, 90]); // 'array'
typeOf(/abc/); // 'regexp'
typeOf(new Date()); // 'date'
typeOf(event.target.files); // 'filelist'
typeOf(EmberObject.extend()); // 'class'
typeOf(EmberObject.create()); // 'instance'
typeOf(new Error('teamocil')); // 'error'
// 'normal' JavaScript object
typeOf({ a: 'b' }); // 'object'
```
@method typeOf
@for @ember/utils
@param {Object} item the item to check
@return {String} the type
@public
@static
*/
function (item) {
if (item === null) {
return 'null';
}
if (item === undefined) {
return 'undefined';
}
var ret = TYPE_MAP[toString.call(item)] || 'object';
if (ret === 'function') {
if (_object.default.detect(item)) {
ret = 'class';
}
} else if (ret === 'object') {
if (item instanceof Error) {
ret = 'error';
} else if (item instanceof _object.default) {
ret = 'instance';
} else if (item instanceof Date) {
ret = 'date';
}
}
return ret;
};
// ........................................
// TYPING & ARRAY MESSAGING
//
var TYPE_MAP = {
'[object Boolean]': 'boolean',
'[object Number]': 'number',
'[object String]': 'string',
'[object Function]': 'function',
'[object Array]': 'array',
'[object Date]': 'date',
'[object RegExp]': 'regexp',
'[object Object]': 'object',
'[object FileList]': 'filelist'
};
var toString = Object.prototype.toString;
});
enifed('ember-utils', ['exports'], function (exports) {
'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
*/
/**
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.
*/
var GENERATED_SYMBOLS = [];
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.
/* globals WeakSet */
var WeakSet$1 = typeof WeakSet === 'function' ? WeakSet : function () {
function WeakSetPolyFill() {
this._map = new WeakMap();
}
WeakSetPolyFill.prototype.add = function (val) {
this._map.set(val, true);
return this;
};
WeakSetPolyFill.prototype.delete = function (val) {
return this._map.delete(val);
};
WeakSetPolyFill.prototype.has = function (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 (func) {
return HAS_SUPER_PATTERN.test(fnToString.call(func));
};
}
return function () {
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) {
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 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 = '{',
i,
key;
var keys = objectKeys(obj);
for (i = 0; i < keys.length; i++) {
s += i === 0 ? ' ' : ', ';
if (i >= LIST_LIMIT) {
s += '... ' + (keys.length - LIST_LIMIT) + ' more keys';
break;
}
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 = '[',
i;
for (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;
}
/**
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
*/
var isArray$1 = Array.isArray;
var NAMES = new WeakMap();
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) {
var r, k;
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.
r = '';
for (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();
var Cache = function () {
function Cache(limit, func, store) {
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 (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 (key, value) {
if (this.limit > this.size) {
this.size++;
this.store.set(key, value);
}
return value;
};
Cache.prototype.purge = function () {
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 = function (possibleSymbol) {
return GENERATED_SYMBOLS.indexOf(possibleSymbol) !== -1;
};
exports.dictionary = function (parent) {
var dict = Object.create(parent);
dict['_dict'] = null;
delete dict['_dict'];
return dict;
};
exports.uuid = uuid;
exports.GUID_KEY = GUID_KEY;
exports.generateGuid = function (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;
};
exports.guidFor = function (value) {
var guid = void 0,
type;
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) {
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;
};
exports.intern = intern;
exports.checkHasSuper = checkHasSuper;
exports.ROOT = ROOT;
exports.wrap = function (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);
};
exports.getObservers = getObservers;
exports.getListeners = getListeners;
exports.setObservers = setObservers;
exports.setListeners = setListeners;
exports.inspect = function (obj) {
// detect Node util.inspect call inspect(depth: number, opts: object)
if (typeof obj === 'number' && arguments.length === 2) {
return this;
}
return inspectValue(obj, 0);
};
exports.lookupDescriptor = function (obj, keyName) {
var current = obj,
descriptor;
do {
descriptor = Object.getOwnPropertyDescriptor(current, keyName);
if (descriptor !== undefined) {
return descriptor;
}
current = Object.getPrototypeOf(current);
} while (current !== null);
return null;
};
exports.canInvoke = canInvoke;
exports.tryInvoke = function (obj, methodName, args) {
var method;
if (canInvoke(obj, methodName)) {
method = obj[methodName];
return method.apply(obj, args);
}
};
exports.makeArray = function (obj) {
if (obj === null || obj === undefined) {
return [];
}
return isArray$1(obj) ? obj : [obj];
};
exports.getName = function (obj) {
return NAMES.get(obj);
};
exports.setName = function (obj, name) {
if (isObject(obj)) NAMES.set(obj, name);
};
exports.toString = toString;
exports.HAS_NATIVE_SYMBOL = HAS_NATIVE_SYMBOL;
exports.HAS_NATIVE_PROXY = HAS_NATIVE_PROXY;
exports.WeakSet = WeakSet$1;
exports.isProxy = function (object) {
if (isObject(object)) {
return PROXIES.has(object);
}
return false;
};
exports.setProxy = function (object) {
if (isObject(object)) {
PROXIES.add(object);
}
};
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;
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) {
false && !(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' + /* EMBER_GLIMMER_ANGLE_BRACKET_INVOCATION */' or start with a capital letter' + '.', name.indexOf('-') > -1 || true);
return owner.factoryFor('component:' + name, options);
},
layoutFor: function (name, owner, options) {
false && !(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);
return owner.lookup('template:components/' + name, 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 (_len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
args[_key - 1] = arguments[_key];
}
false && !(!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],
_len,
args,
_key,
shouldBubble;
if (action) {
shouldBubble = action.apply(this, args) === true;
if (!shouldBubble) {
return;
}
}
var target = (0, _emberMetal.get)(this, 'target');
if (target) {
false && !(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 {
false && !action && (0, _debug.assert)((0, _emberUtils.inspect)(this) + ' had no action handler for: ' + actionName, action);
}
}
},
sendAction,
validateAction; /**
@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
*/
sendAction = function (action) {
for (_len2 = arguments.length, contexts = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
contexts[_key2 - 1] = arguments[_key2];
}
false && !(!this.isDestroying && !this.isDestroyed) && (0, _debug.assert)('Attempted to call .sendAction() with the action \'' + action + '\' on the destroyed object \'' + this + '\'.', !this.isDestroying && !this.isDestroyed);
false && !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,
_len2,
contexts,
_key2;
// 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
});
}
};
validateAction = function (component, actionName) {
if (actionName && actionName[_attrs.MUTABLE_CELL]) {
actionName = actionName.value;
}
false && !(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);
false && !((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));
false && !((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 method = KEY_EVENTS[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') {
false && !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) {
false && !(this.tagName !== '') && (0, _debug.assert)("You cannot access this.$() on a component with `tagName: ''` specified.", this.tagName !== '');
false && !!_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;
false && !target && (0, _debug.assert)('You tried to append to (' + selector + ') but that isn\'t in the DOM', target);
false && !!(0, _utils.matches)(target, '.ember-view') && (0, _debug.assert)('You cannot append to an existing Ember.View.', !(0, _utils.matches)(target, '.ember-view'));
false && !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;
false && !(typeof target !== 'string') && (0, _debug.assert)('You tried to append to a selector string (' + selector + ') in an environment without jQuery', typeof target !== 'string');
false && !(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
false && !((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
false && !((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);
}
false && !!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();
false && !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);
}
false && !!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));
false && !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;
}());
false && !!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);
false && !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);
false && !!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));
false && !!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);
false && !!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) {
var viewHandler, actionHandler, mappedEventType, origEventType, createFakeEvent, handleMappedEvent, handleEvent;
if (eventName === null) {
return;
}
if (_jquery.jQueryDisabled) {
viewHandler = function (target, event) {
var view = viewRegistry[target.id];
var result = true;
if (view) {
result = view.handleEvent(eventName, event);
}
return result;
};
actionHandler = function (target, event) {
var actionId = target.getAttribute('data-ember-action'),
attributes,
attributeCount,
i,
attr,
attrName,
index,
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 === '') {
attributes = target.attributes;
attributeCount = attributes.length;
actions = [];
for (i = 0; i < attributeCount; i++) {
attr = attributes.item(i);
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 (index = 0; index < actions.length; index++) {
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) {
mappedEventType = EVENT_MAP[event];
origEventType = event;
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;
};
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 {
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,
i,
attr,
attrName,
action;
var handledActions = [];
evt = (0, _jquery_event_deprecation.default)(evt);
for (i = 0; i < attributes.length; i++) {
attr = attributes.item(i);
attrName = attr.name;
if (attrName.lastIndexOf('data-ember-action-', 0) !== -1) {
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) {
'use strict';
/* global Proxy */
exports.default = function (jqEvent) {
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
};
});
enifed('ember-views/lib/system/lookup_partial', ['exports', '@ember/debug', '@ember/error'], function (exports, _debug, _error) {
'use strict';
exports.default = function (templateName, owner) {
if (templateName == null) {
return;
}
var template = templateFor(owner, parseUnderscoredName(templateName), templateName);
false && !!!template && (0, _debug.assert)('Unable to find partial with name "' + templateName + '"', !!template);
return template;
};
exports.hasPartial = function (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 parseUnderscoredName(templateName) {
var nameParts = templateName.split('/');
var lastPart = nameParts[nameParts.length - 1];
nameParts[nameParts.length - 1] = '_' + lastPart;
return nameParts.join('/');
}
function templateFor(owner, underscored, name) {
if (!name) {
return;
}
false && !(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 =
/**
@module ember
*/
function (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 */
;
exports.constructStyleDeprecationMessage = function (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
*/
;
exports.getRootViews = function (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
*/
;
exports.getViewId = getViewId;
exports.getViewElement =
/**
@private
@method getViewElement
@param {Ember.View} view
*/
function (view) {
return view[VIEW_ELEMENT];
};
exports.initViewElement = function (view) {
view[VIEW_ELEMENT] = null;
};
exports.setViewElement = function (view, element) {
return view[VIEW_ELEMENT] = element;
};
exports.getChildViews =
/**
@private
@method getChildViews
@param {Ember.View} view
*/
function (view) {
var owner = (0, _emberOwner.getOwner)(view);
var registry = owner.lookup('-view-registry:main');
return collectChildViews(view, registry);
};
exports.initChildViews = initChildViews;
exports.addChildView = function (parent, child) {
var childViews = CHILD_VIEW_IDS.get(parent);
if (childViews === undefined) {
childViews = initChildViews(parent);
}
childViews.add(getViewId(child));
};
exports.collectChildViews = collectChildViews;
exports.getViewBounds = getViewBounds;
exports.getViewRange = getViewRange;
exports.getViewClientRects =
/**
`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 (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
*/
;
exports.getViewBoundingClientRect = function (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
*/
;
exports.matches = function (el, selector) {
return elMatches.call(el, selector);
};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');
var CHILD_VIEW_IDS = new WeakMap();
function initChildViews(view) {
var childViews = new Set();
CHILD_VIEW_IDS.set(view, childViews);
return childViews;
}
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;
}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);
});
enifed('ember-views/lib/utils/lookup-component', ['exports'], function (exports) {
'use strict';
exports.default = function (owner, name, options) {
var componentLookup = owner.lookup('component-lookup:main'),
localResult;
if (options && (options.source || options.namespace)) {
localResult = lookupComponentPair(componentLookup, owner, name, options);
if (localResult.component || localResult.layout) {
return localResult;
}
}
return lookupComponentPair(componentLookup, owner, name);
};
function lookupComponentPair(componentLookup, owner, name, options) {
var component = componentLookup.componentFor(name, owner, options);
var layout = componentLookup.layoutFor(name, owner, options);
return { layout: layout, component: component };
}
});
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 (_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],
_len,
args,
_key;
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 = function (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.
*/
;
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);
},
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 || {},
testing;
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 () {
false && !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() {
false && !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')) {
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 (path, matcher, delegate) {
this.path = path;
this.matcher = matcher;
this.delegate = delegate;
};
Target.prototype.to = function (target, callback) {
var delegate = this.delegate;
if (delegate && delegate.willAddRoute) {
target = delegate.willAddRoute(this.matcher.target, target);
}
this.matcher.add(this.path, target);
if (callback) {
if (callback.length === 0) {
throw new Error("You must have an argument in the function passed to `to`");
}
this.matcher.addChild(this.path, target, callback, this.delegate);
}
};
var Matcher = function (target) {
this.routes = createMap();
this.children = createMap();
this.target = target;
};
Matcher.prototype.add = function (path, target) {
this.routes[path] = target;
};
Matcher.prototype.addChild = function (path, target, callback, delegate) {
var matcher = new Matcher(target);
this.children[path] = matcher;
var match = generateMatch(path, matcher, delegate);
if (delegate && delegate.contextEntered) {
delegate.contextEntered(target, match);
}
callback(match);
};
function generateMatch(startingPath, matcher, delegate) {
return function (path, callback) {
var fullPath = startingPath + path;
if (callback) {
callback(generateMatch(fullPath, matcher, delegate));
} else {
return new Target(fullPath, matcher, delegate);
}
};
}
function addRoute(routeArray, path, handler) {
var len = 0,
i;
for (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,
i,
path,
routeArray,
nested;
var paths = Object.keys(routes);
for (i = 0; i < paths.length; i++) {
path = paths[i];
routeArray = baseRoute.slice();
addRoute(routeArray, path, routes[path]);
nested = matcher.children[path];
if (nested) {
eachRoute(routeArray, nested, callback, binding);
} else {
callback.call(binding, routeArray);
}
}
}
// 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,
i,
ch;
var value = segment.value;
for (i = 0; i < value.length; i++) {
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("/"),
i,
part,
flags,
type;
var names = undefined;
var shouldDecodes = undefined;
for (i = 0; i < parts.length; i++) {
part = parts[i];
flags = 0;
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 (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 () {
if (!this._regex) {
this._regex = new RegExp(this.pattern);
}
return this._regex;
};
State.prototype.get = function (char, negate) {
var this$1 = this,
i,
child,
child$1;
var nextStates = this.nextStates;
if (nextStates === null) {
return;
}
if (isArray(nextStates)) {
for (i = 0; i < nextStates.length; i++) {
child = this$1.states[nextStates[i]];
if (isEqualCharSpec(child, char, negate)) {
return child;
}
}
} else {
child$1 = this.states[nextStates];
if (isEqualCharSpec(child$1, char, negate)) {
return child$1;
}
}
};
State.prototype.put = function (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 (ch) {
var this$1 = this,
i,
child,
child$1;
var nextStates = this.nextStates;
if (!nextStates) {
return [];
}
var returned = [];
if (isArray(nextStates)) {
for (i = 0; i < nextStates.length; i++) {
child = this$1.states[nextStates[i]];
if (isMatch(child, ch)) {
returned.push(child);
}
}
} else {
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 = [],
i,
l,
state;
for (i = 0, l = states.length; i < l; i++) {
state = states[i];
nextStates = nextStates.concat(state.match(ch));
}
return nextStates;
}
var RecognizeResults = function (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,
i,
handler,
names,
shouldDecodes,
params,
isDynamic,
j,
name,
capture;
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 (i = 0; i < handlers.length; i++) {
handler = handlers[i];
names = handler.names;
shouldDecodes = handler.shouldDecodes;
params = EmptyObject;
isDynamic = false;
if (names !== EmptyArray && shouldDecodes !== EmptyArray) {
for (j = 0; j < names.length; j++) {
isDynamic = true;
name = names[j];
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 () {
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 (routes, options) {
var currentState = this.rootState,
i,
route,
ref,
names,
shouldDecodes,
segment;
var pattern = "^";
var types = [0, 0, 0];
var handlers = new Array(routes.length);
var allSegments = [];
var isEmpty = true;
var j = 0;
for (i = 0; i < routes.length; i++) {
route = routes[i];
ref = parse(allSegments, route.path, types);
names = ref.names;
shouldDecodes = ref.shouldDecodes;
// preserve j so it points to the start of newly added segments
for (; j < allSegments.length; j++) {
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 (name) {
var route = this.names[name],
i,
handler;
if (!route) {
throw new Error("There is no route named " + name);
}
var result = new Array(route.handlers.length);
for (i = 0; i < route.handlers.length; i++) {
handler = route.handlers[i];
result[i] = handler;
}
return result;
};
RouteRecognizer.prototype.hasRoute = function (name) {
return !!this.names[name];
};
RouteRecognizer.prototype.generate = function (name, params) {
var route = this.names[name],
i,
segment;
var output = "";
if (!route) {
throw new Error("There is no route named " + name);
}
var segments = route.segments;
for (i = 0; i < segments.length; i++) {
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 (params) {
var pairs = [],
i,
key,
value,
pair,
j,
arrayPair;
var keys = Object.keys(params);
keys.sort();
for (i = 0; i < keys.length; i++) {
key = keys[i];
value = params[key];
if (value == null) {
continue;
}
pair = encodeURIComponent(key);
if (isArray(value)) {
for (j = 0; j < value.length; j++) {
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 (queryString) {
var pairs = queryString.split("&"),
i,
pair,
key,
keyLength,
isArray,
value;
var queryParams = {};
for (i = 0; i < pairs.length; i++) {
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 (path) {
var results, queryString, i, i$1;
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) {
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 (i = 0; i < path.length; i++) {
states = recognizeChar(states, path.charCodeAt(i));
if (!states.length) {
break;
}
}
var solutions = [];
for (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 = 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);
};
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) {
var val, i, l;
for (var key in queryParams) {
val = queryParams[key];
if (typeof val === 'number') {
queryParams[key] = '' + val;
} else if (Array.isArray(val)) {
for (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) {
var i, l;
for (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(),
i,
handlerInfo,
handler;
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 (i = handlerInfos.length - 1; i >= 0; i--) {
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,
i,
l;
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 (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() {
this.handlerInfos = [];
this.queryParams = {};
this.params = {};
}
TransitionState.prototype.promiseLabel = function (label) {
var targetName = '';
forEach(this.handlerInfos, function (handlerInfo) {
if (targetName !== '') {
targetName += '.';
}
targetName += handlerInfo.name;
});
return _promiseLabel("'" + targetName + "': " + label);
};
TransitionState.prototype.resolve = function (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,
handler;
// 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.
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,
len,
i,
handlerInfo;
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;
len = state.handlerInfos.length;
if (len) {
this.targetName = state.handlerInfos[len - 1].name;
}
for (i = 0; i < len; ++i) {
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 (handler) {
var handlerInfos = this.handlerInfos,
i,
len,
handlerInfo;
for (i = 0, len = handlerInfos.length; i < len; ++i) {
handlerInfo = handlerInfos[i];
if (handlerInfo.name === handler || handlerInfo.handler === handler) {
return false;
}
}
return true;
};
Transition.prototype.then = function (onFulfilled, onRejected, label) {
return this.promise.then(onFulfilled, onRejected, label);
};
Transition.prototype.catch = function (onRejection, label) {
return this.promise.catch(onRejection, label);
};
Transition.prototype.finally = function (callback, label) {
return this.promise.finally(callback, label);
};
Transition.prototype.abort = function () {
if (this.isAborted) {
return this;
}
_log(this.router, this.sequence, this.targetName + ': transition was aborted');
this.intent.preTransitionState = this.router.state;
this.isAborted = true;
this.isActive = false;
this.router.activeTransition = null;
return this;
};
Transition.prototype.retry = function () {
// 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) {
this.urlMethod = _method;
return this;
};
Transition.prototype.trigger = function (ignoreFailure) {
var args = slice.call(arguments);
if (typeof ignoreFailure === 'boolean') {
args.shift();
} else {
// Throw errors on unhandled trigger events by default
ignoreFailure = false;
}
_trigger(this.router, this.state.handlerInfos.slice(0, this.resolveIndex + 1), ignoreFailure, args);
};
Transition.prototype.followRedirects = function () {
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 () {
return 'Transition (sequence ' + this.sequence + ')';
};
Transition.prototype.log = function (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 () {
this.data = this.data || {};
};
var DEFAULT_HANDLER = Object.freeze({});
var HandlerInfo = function () {
function HandlerInfo() {
var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
// 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 () {};
HandlerInfo.prototype.fetchHandler = function () {
var handler = this.getHandler(this.name);
return this._processHandler(handler);
};
HandlerInfo.prototype._processHandler = function (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 (payload, message) {
if (payload.log) {
payload.log(this.name + ': ' + message);
}
};
HandlerInfo.prototype.promiseLabel = function (label) {
return _promiseLabel("'" + this.name + "' " + label);
};
HandlerInfo.prototype.getUnresolved = function () {
return this;
};
HandlerInfo.prototype.serialize = function () {
return this.params || {};
};
HandlerInfo.prototype.updateHandler = function (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 (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 (payload) {
if (payload.trigger) {
payload.trigger(true, 'willResolveModel', payload, this.handler);
}
return this.runSharedModelHook(payload, 'beforeModel', []);
};
HandlerInfo.prototype.runAfterModelHook = function (payload, resolvedModel) {
// Stash the resolved model on the payload.
// This makes it possible for users to swap out
// the resolved model in afterModel.
var name = this.name;
this.stashResolvedModel(payload, resolvedModel);
return this.runSharedModelHook(payload, 'afterModel', [resolvedModel]).then(function () {
// Ignore the fulfilled value returned from afterModel.
// Return the value stashed in resolvedModels, which
// might have been swapped out in afterModel.
return payload.resolvedModels[name];
}, null, this.promiseLabel('Ignore fulfillment value and return model value'));
};
HandlerInfo.prototype.runSharedModelHook = function (payload, hookName, args) {
this.log(payload, 'calling ' + hookName + ' hook');
if (this.queryParams) {
args.push(this.queryParams);
}
args.push(payload);
var result = applyHook(this.handler, hookName, args);
if (result && result.isTransition) {
result = null;
}
return _rsvp.Promise.resolve(result, this.promiseLabel('Resolve value returned from one of the model hooks'));
};
HandlerInfo.prototype.getModel = function () {};
HandlerInfo.prototype.checkForAbort = function (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 (payload, resolvedModel) {
payload.resolvedModels = payload.resolvedModels || {};
payload.resolvedModels[this.name] = resolvedModel;
};
HandlerInfo.prototype.becomeResolved = function (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 (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) {
var _this3 = (0, _emberBabel.possibleConstructorReturn)(this, _HandlerInfo.call(this, props));
_this3.isResolved = true;
return _this3;
}
ResolvedHandlerInfo.prototype.resolve = function (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 () {
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) {
var _this4 = (0, _emberBabel.possibleConstructorReturn)(this, _HandlerInfo2.call(this, props));
_this4.names = _this4.names || [];
return _this4;
}
UnresolvedHandlerInfoByObject.prototype.getModel = function (payload) {
this.log(payload, this.name + ': resolving provided model');
return _rsvp.Promise.resolve(this.context);
};
UnresolvedHandlerInfoByObject.prototype.serialize = function (_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) {
var _this5 = (0, _emberBabel.possibleConstructorReturn)(this, _HandlerInfo3.call(this, props));
_this5.params = _this5.params || {};
return _this5;
}
UnresolvedHandlerInfoByParam.prototype.getModel = function (payload) {
var fullParams = this.params;
if (payload && payload.queryParams) {
fullParams = {};
merge(fullParams, this.params);
fullParams.queryParams = payload.queryParams;
}
var handler = this.handler;
var hookName = resolveHook(handler, 'deserialize') || resolveHook(handler, 'model');
return this.runSharedModelHook(payload, hookName, [fullParams]);
};
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) {
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 (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 (oldState, handlers, getHandler, targetRouteName, isIntermediate, checkingIfActive, getSerializer) {
var i, len, result, name, oldHandlerInfo, newHandlerInfo, serializer, oldContext, handlerToUse;
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) {
result = handlers[i];
name = result.handler;
oldHandlerInfo = oldState.handlerInfos[i];
newHandlerInfo = null;
if (result.names.length > 0) {
if (i >= invalidateIndex) {
newHandlerInfo = this.createParamHandlerInfo(name, getHandler, result.names, objects, oldHandlerInfo);
} else {
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);
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;
}
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 (handlerInfos, invalidateIndex) {
var i, l, handlerInfo;
for (i = invalidateIndex, l = handlerInfos.length; i < l; ++i) {
handlerInfo = handlerInfos[i];
handlerInfos[i] = handlerInfo.getUnresolved();
}
};
NamedTransitionIntent.prototype.getHandlerInfoForDynamicSegment = function (name, getHandler, names, objects, oldHandlerInfo, targetRouteName, i, serializer) {
var objectToUse, preTransitionHandlerInfo;
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) {
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 (name, getHandler, names, objects, oldHandlerInfo) {
var params = {},
oldParams,
peek,
paramName;
// 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
oldParams = oldHandlerInfo && name === oldHandlerInfo.name && oldHandlerInfo.params || {};
peek = objects[objects.length - 1];
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) {
var _this7 = (0, _emberBabel.possibleConstructorReturn)(this, _TransitionIntent2.call(this, props));
_this7.url = props.url;
return _this7;
}
URLTransitionIntent.prototype.applyToState = function (oldState, recognizer, getHandler) {
var newState = new TransitionState(),
result,
name,
newHandlerInfo,
handler,
oldHandlerInfo;
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) {
result = results[i];
name = result.handler;
newHandlerInfo = handlerInfoFactory('param', {
name: name,
getHandler: getHandler,
params: result.params
});
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);
}
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] : {};
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 (callback) {
this.recognizer.delegate = this.delegate;
this.recognizer.map(callback, function (recognizer, routes) {
var i, proceed, route;
for (i = routes.length - 1, proceed = true; i >= 0 && proceed; --i) {
route = routes[i];
recognizer.add(routes, { as: route.handler });
proceed = route.path === '/' || route.path === '' || route.handler.slice(-6) === '.index';
}
});
};
Router.prototype.hasRoute = function (route) {
return this.recognizer.hasRoute(route);
};
Router.prototype.getHandler = function () {};
Router.prototype.getSerializer = function () {};
Router.prototype.queryParamsTransition = function (changelist, wasTransitioning, oldState, newState) {
var router = this,
newTransition;
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).
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 (intent /*, isIntermediate*/) {
try {
return getTransitionByIntent.apply(this, arguments);
} catch (e) {
return new Transition(this, intent, null, e);
}
};
Router.prototype.reset = function () {
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 () {
for (_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],
_len,
args,
_key;
if (url.charAt(0) !== '/') {
args[0] = '/' + url;
}
return doTransition(this, args).method(null);
};
Router.prototype.updateURL = function () {
throw new Error('updateURL is not implemented');
};
Router.prototype.replaceURL = function (url) {
this.updateURL(url);
};
Router.prototype.transitionTo = function () /*name*/{
return doTransition(this, arguments);
};
Router.prototype.intermediateTransitionTo = function () /*name*/{
return doTransition(this, arguments, true);
};
Router.prototype.refresh = function (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 () /*name*/{
return doTransition(this, arguments).method('replace');
};
Router.prototype.generate = function (handlerName) {
var partitionedArgs = extractQueryParams(slice.call(arguments, 1)),
suppliedParams = partitionedArgs[0],
queryParams = partitionedArgs[1],
i,
len,
handlerInfo,
handlerParams;
// 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 (i = 0, len = state.handlerInfos.length; i < len; ++i) {
handlerInfo = state.handlerInfos[i];
handlerParams = handlerInfo.serialize();
merge(params, handlerParams);
}
params.queryParams = queryParams;
return this.recognizer.generate(handlerName, params);
};
Router.prototype.applyIntent = function (handlerName, contexts) {
var intent = new NamedTransitionIntent({
name: handlerName,
contexts: contexts
});
var state = this.activeTransition && this.activeTransition.state || this.state;
return intent.applyToState(state, this.recognizer, this.getHandler, null, this.getSerializer);
};
Router.prototype.isActiveIntent = function (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 (handlerName) {
for (_len2 = arguments.length, args = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
args[_key2 - 1] = arguments[_key2];
}
var partitionedArgs = extractQueryParams(args),
_len2,
args,
_key2;
return this.isActiveIntent(handlerName, partitionedArgs[0], partitionedArgs[1]);
};
Router.prototype.trigger = function () {
var _len3, args, _key3;
for (_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,
oldHandler,
newHandler;
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++) {
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,
i,
handlerInfo,
url,
initial,
replaceAndNotAborting,
isQueryParamsRefreshTransition,
replacingReplace;
if (!urlMethod) {
return;
}
var router = transition.router,
handlerInfos = state.handlerInfos,
handlerName = handlerInfos[handlerInfos.length - 1].name,
params = {};
for (i = handlerInfos.length - 1; i >= 0; --i) {
handlerInfo = handlerInfos[i];
merge(params, handlerInfo.params);
if (handlerInfo.handler.inaccessibleByURL) {
urlMethod = null;
}
}
if (urlMethod) {
params.queryParams = transition._visibleQueryParams || state.queryParams;
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
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
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.
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.
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) {
var router, handlerInfos, infos;
try {
_log(transition.router, transition.sequence, 'Resolved all models on destination route; finalizing transition.');
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();
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] || '/',
handlerInfos;
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.
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) {
var i, len;
if (handlerInfos.length !== otherHandlerInfos.length) {
return false;
}
for (i = 0, len = handlerInfos.length; i < len; ++i) {
if (handlerInfos[i] !== otherHandlerInfos[i]) {
return false;
}
}
return true;
}
function handlerInfosSameExceptQueryParams(handlerInfos, otherHandlerInfos) {
var i, len;
if (handlerInfos.length !== otherHandlerInfos.length) {
return false;
}
for (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),
i,
len,
key;
var otherKeys = Object.keys(otherParams);
if (keys.length !== otherKeys.length) {
return false;
}
for (i = 0, len = keys.length; i < len; ++i) {
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 = [],
i,
len,
qp;
_trigger(router, resolvedHandlers, true, ['finalizeQueryParamChange', newQueryParams, finalQueryParamsArray, transition]);
if (transition) {
transition._visibleQueryParams = {};
}
var finalQueryParams = {};
for (i = 0, len = finalQueryParamsArray.length; i < len; ++i) {
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),
callback,
i;
var callbacks = allCallbacks[eventName];
if (callbacks) {
// Don't cache the callbacks.length since it may grow
callback = void 0;
for (i = 0; i < callbacks.length; i++) {
callback = callbacks[i];
callback(options, label);
}
}
}
},
callbacks;
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 () {
var i, entry, payload;
for (i = 0; i < queue.length; i++) {
entry = queue[i];
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() {
var target;
try {
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,
error;
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;
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,
error;
if (isOwnThenable) {
handleOwnThenable(promise, maybeThenable);
} else if (then$$1 === TRY_CATCH_ERROR) {
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,
i;
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 (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',
error;
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) {
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,
callback;
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 {
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) {
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 (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 (input) {
var length = this.length,
i;
var promise = this.promise;
for (i = 0; promise._state === PENDING && i < length; i++) {
this._eachEntry(input[i], i, true);
}
this._checkFullfillment();
};
Enumerator.prototype._checkFullfillment = function () {
var result;
if (this._remaining === 0) {
result = this._result;
fulfill(this.promise, result);
this._result = null;
}
};
Enumerator.prototype._settleMaybeThenable = function (entry, i, firstPass) {
var c = this._instanceConstructor,
then$$1,
promise;
if (this._isUsingOwnResolve) {
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) {
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 (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 (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 (state, i, value) {
this._remaining--;
this._result[i] = value;
};
Enumerator.prototype._willSettleAt = function (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
*/
/**
`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.
*/
/**
`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`.
*/
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) {
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 (reason) {
var _this2 = this;
config.after(function () {
if (_this2._onError) {
config.trigger('error', reason, _this2._label);
}
});
};
Promise.prototype.catch = function (onRejection, label) {
return this.then(undefined, onRejection, label);
};
Promise.prototype.finally = function (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 = function (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;
};
Promise.race = function (entries, label) {
/*jshint validthis:true */
var Constructor = this,
i;
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 (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;
};
Promise.resolve = resolve$$1;
Promise.reject = function (reason, label) {
/*jshint validthis:true */
var Constructor = this;
var promise = new Constructor(noop, label);
reject(promise, reason);
return promise;
};
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 = {},
x,
i,
name;
var length = _.length;
var args = new Array(length);
for (x = 0; x < length; x++) {
args[x] = _[x];
}
for (i = 0; i < argumentNames.length; i++) {
name = argumentNames[i];
obj[name] = args[i + 1];
}
return obj;
}
function arrayResult(_) {
var length = _.length,
i;
var args = new Array(length - 1);
for (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,
i,
arg,
error,
p;
var args = new Array(l + 1);
var promiseInput = false;
for (i = 0; i < l; ++i) {
arg = arguments[i];
if (!promiseInput) {
// TODO: clean this up
promiseInput = needsPromiseInput(arg);
if (promiseInput === TRY_CATCH_ERROR) {
error = TRY_CATCH_ERROR.error;
TRY_CATCH_ERROR.error = null;
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),
error;
if (result === TRY_CATCH_ERROR) {
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) {
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];
return (0, _emberBabel.possibleConstructorReturn)(this, _Enumerator2.call(this, Constructor, object, abortOnReject, label));
}
PromiseHash.prototype._init = function (Constructor, object) {
this._result = {};
this._enumerate(object);
};
PromiseHash.prototype._enumerate = function (input) {
var keys = Object.keys(input),
i;
var length = keys.length;
var promise = this.promise;
this._remaining = length;
var key = void 0,
val = void 0;
for (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) {
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) {
return (0, _emberBabel.possibleConstructorReturn)(this, _Enumerator3.call(this, Constructor, entries, true, label, mapFn));
}
MapEnumerator.prototype._init = function (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 (state, i, value, firstPass) {
var val;
if (firstPass) {
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() {
return (0, _emberBabel.possibleConstructorReturn)(this, _MapEnumerator.apply(this, arguments));
}
FilterEnumerator.prototype._checkFullfillment = function () {
var result;
if (this._remaining === 0 && this._result !== null) {
result = this._result.filter(function (val) {
return val !== EMPTY_OBJECT;
});
fulfill(this.promise, result);
this._result = null;
}
};
FilterEnumerator.prototype._setResultAt = function (state, i, value, firstPass) {
var val;
if (firstPass) {
this._result[i] = value;
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() {
var i, callback, arg;
for (i = 0; i < len; i += 2) {
callback = queue$1[i];
arg = queue$1[i + 1];
callback(arg);
queue$1[i] = undefined;
queue$1[i + 1] = undefined;
}
len = 0;
}
function attemptVertex() {
var vertx;
try {
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') {
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
exports.default = {
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.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.prod.map