dist/ember.js in ember-source-1.9.0.beta.1.1 vs dist/ember.js in ember-source-1.9.0.beta.3
- old
+ new
@@ -3,11 +3,11 @@
* @copyright Copyright 2011-2014 Tilde Inc. and contributors
* Portions Copyright 2006-2011 Strobe Inc.
* Portions Copyright 2008-2011 Apple Inc. All rights reserved.
* @license Licensed under MIT license
* See https://raw.github.com/emberjs/ember.js/master/LICENSE
- * @version 1.9.0-beta.1
+ * @version 1.9.0-beta.3
*/
(function() {
var enifed, requireModule, eriuqer, requirejs, Ember;
@@ -191,10 +191,27 @@
}
}
}
},
+ join: function(target, method /*, args */) {
+ if (this.currentInstance) {
+ if (!method) {
+ method = target;
+ target = null;
+ }
+
+ if (isString(method)) {
+ method = target[method];
+ }
+
+ return method.apply(target, slice.call(arguments, 2));
+ } else {
+ return this.run.apply(this, arguments);
+ }
+ },
+
defer: function(queueName, target, method /* , args */) {
if (!method) {
method = target;
target = null;
}
@@ -1177,24 +1194,10 @@
this.children.push(container);
return container;
},
/**
- Sets a key-value pair on the current container. If a parent container,
- has the same key, once set on a child, the parent and child will diverge
- as expected.
-
- @method set
- @param {Object} object
- @param {String} key
- @param {any} value
- */
- set: function(object, key, value) {
- object[key] = value;
- },
-
- /**
Registers a factory for later injection.
Example:
```javascript
@@ -1445,15 +1448,17 @@
this._typeOptions[type] = options;
},
/**
@method options
- @param {String} type
+ @param {String} fullName
@param {Object} options
*/
- options: function(type, options) {
- this.optionsForType(type, options);
+ options: function(fullName, options) {
+ options = options || {};
+ var normalizedName = this.normalize(fullName);
+ this._options[normalizedName] = options;
},
/**
Used only via `injection`.
@@ -2489,14 +2494,14 @@
If there is a bubbling browser event that Ember does not listen for by
default, you can specify custom events and their corresponding view method
names by setting the application's `customEvents` property:
```javascript
- App = Ember.Application.create({
+ var App = Ember.Application.create({
customEvents: {
// add support for the paste event
- paste: "paste"
+ paste: 'paste'
}
});
```
By default, the application sets up these event listeners on the document
@@ -2506,11 +2511,11 @@
For example, if only events inside a DOM element with the ID of `ember-app`
should be delegated, set your application's `rootElement` property:
```javascript
- window.App = Ember.Application.create({
+ var App = Ember.Application.create({
rootElement: '#ember-app'
});
```
The `rootElement` can be either a DOM element or a jQuery-compatible selector
@@ -2549,11 +2554,11 @@
between routes can be logged with the `LOG_TRANSITIONS` flag, and more
detailed intra-transition logging can be logged with
the `LOG_TRANSITIONS_INTERNAL` flag:
```javascript
- window.App = Ember.Application.create({
+ var App = Ember.Application.create({
LOG_TRANSITIONS: true, // basic logging of successful transitions
LOG_TRANSITIONS_INTERNAL: true // detailed logging of all routing steps
});
```
@@ -2618,14 +2623,14 @@
views, set your `Ember.Application`'s `customEvents` property
to a hash containing the DOM event name as the key and the
corresponding view method name as the value. For example:
```javascript
- App = Ember.Application.create({
+ var App = Ember.Application.create({
customEvents: {
// add support for the paste event
- paste: "paste"
+ paste: 'paste'
}
});
```
@property customEvents
@@ -2751,14 +2756,15 @@
Use this to defer readiness until some condition is true.
Example:
```javascript
- App = Ember.Application.create();
+ var App = Ember.Application.create();
+
App.deferReadiness();
-
- jQuery.getJSON("/auth-token", function(token) {
+ // Ember.$ is a reference to the jQuery object/function
+ Ember.$.getJSON('/auth-token', function(token) {
App.token = token;
App.advanceReadiness();
});
```
@@ -2800,23 +2806,24 @@
A simple example:
```javascript
var App = Ember.Application.create();
- App.Orange = Ember.Object.extend();
+
+ App.Orange = Ember.Object.extend();
App.register('fruit:favorite', App.Orange);
```
Ember will resolve factories from the `App` namespace automatically.
For example `App.CarsController` will be discovered and returned if
an application requests `controller:cars`.
An example of registering a controller with a non-standard name:
```javascript
- var App = Ember.Application.create(),
- Session = Ember.Controller.extend();
+ var App = Ember.Application.create();
+ var Session = Ember.Controller.extend();
App.register('controller:session', Session);
// The Session controller can now be treated like a normal controller,
// despite its non-standard name.
@@ -2837,14 +2844,14 @@
App.Person = Ember.Object.extend();
App.Orange = Ember.Object.extend();
App.Email = Ember.Object.extend();
App.session = Ember.Object.create();
- App.register('model:user', App.Person, {singleton: false });
+ App.register('model:user', App.Person, { singleton: false });
App.register('fruit:favorite', App.Orange);
- App.register('communication:main', App.Email, {singleton: false});
- App.register('session', App.session, {instantiate: false});
+ App.register('communication:main', App.Email, { singleton: false });
+ App.register('session', App.session, { instantiate: false });
```
@method register
@param fullName {String} type:name (e.g., 'model:user')
@param factory {Function} (e.g., App.Person)
@@ -2864,12 +2871,12 @@
provide services to a set of framework components.
An example of providing a session object to all controllers:
```javascript
- var App = Ember.Application.create(),
- Session = Ember.Object.extend({ isAuthenticated: false });
+ var App = Ember.Application.create();
+ var Session = Ember.Object.extend({ isAuthenticated: false });
// A factory must be registered before it can be injected
App.register('session:main', Session);
// Inject 'session:main' onto all factories of the type 'controller'
@@ -2892,11 +2899,11 @@
It is important to note that injections can only be performed on
classes that are instantiated by Ember itself. Instantiating a class
directly (via `create` or `new`) bypasses the dependency injection
system.
- Ember-Data instantiates its models in a unique manner, and consequently
+ **Note:** Ember-Data instantiates its models in a unique manner, and consequently
injections onto models (or all models) will not work as expected. Injections
on models can be enabled by setting `Ember.MODEL_FACTORY_INJECTIONS`
to `true`.
@method inject
@@ -2964,28 +2971,27 @@
4. Re-route to the existing url
Typical Example:
```javascript
-
var App;
run(function() {
App = Ember.Application.create();
});
- module("acceptance test", {
+ module('acceptance test', {
setup: function() {
App.reset();
}
});
- test("first test", function() {
+ test('first test', function() {
// App is freshly reset
});
- test("first test", function() {
+ test('second test', function() {
// App is again freshly reset
});
```
Advanced Example:
@@ -2993,32 +2999,32 @@
Occasionally you may want to prevent the app from initializing during
setup. This could enable extra configuration, or enable asserting prior
to the app becoming ready.
```javascript
-
var App;
run(function() {
App = Ember.Application.create();
});
- module("acceptance test", {
+ module('acceptance test', {
setup: function() {
run(function() {
App.reset();
App.deferReadiness();
});
}
});
- test("first test", function() {
+ test('first test', function() {
ok(true, 'something before app is initialized');
run(function() {
App.advanceReadiness();
});
+
ok(true, 'something after app is initialized');
});
```
@method reset
@@ -3183,12 +3189,13 @@
same name will result in an error.
```javascript
Ember.Application.initializer({
name: 'namedInitializer',
+
initialize: function(container, application) {
- Ember.debug("Running namedInitializer!");
+ Ember.debug('Running namedInitializer!');
}
});
```
* `before` and `after` are used to ensure that this initializer is ran prior
@@ -3198,12 +3205,13 @@
An example of ordering initializers, we create an initializer named `first`:
```javascript
Ember.Application.initializer({
name: 'first',
+
initialize: function(container, application) {
- Ember.debug("First initializer!");
+ Ember.debug('First initializer!');
}
});
// DEBUG: First initializer!
```
@@ -3215,11 +3223,11 @@
Ember.Application.initializer({
name: 'second',
after: 'first',
initialize: function(container, application) {
- Ember.debug("Second initializer!");
+ Ember.debug('Second initializer!');
}
});
// DEBUG: First initializer!
// DEBUG: Second initializer!
@@ -3232,11 +3240,11 @@
Ember.Application.initializer({
name: 'pre',
before: 'first',
initialize: function(container, application) {
- Ember.debug("Pre initializer!");
+ Ember.debug('Pre initializer!');
}
});
// DEBUG: Pre initializer!
// DEBUG: First initializer!
@@ -3250,11 +3258,11 @@
Ember.Application.initializer({
name: 'post',
after: ['first', 'second'],
initialize: function(container, application) {
- Ember.debug("Post initializer!");
+ Ember.debug('Post initializer!');
}
});
// DEBUG: Pre initializer!
// DEBUG: First initializer!
@@ -3267,14 +3275,15 @@
Example of using `container` to preload data into the store:
```javascript
Ember.Application.initializer({
- name: "preload-data",
+ name: 'preload-data',
initialize: function(container, application) {
var store = container.lookup('store:main');
+
store.pushPayload(preloadedData);
}
});
```
@@ -3304,10 +3313,11 @@
});
}
Ember.assert("The initializer '" + initializer.name + "' has already been registered", !this.initializers[initializer.name]);
Ember.assert("An initializer cannot be registered without an initialize function", canInvoke(initializer, 'initialize'));
+ Ember.assert("An initializer cannot be registered without a name property", initializer.name !== undefined);
this.initializers[initializer.name] = initializer;
},
/**
@@ -5999,28 +6009,28 @@
if (stack1 != null) { data.buffer.push(stack1); }
data.buffer.push("</option>");
return buffer;
},"3":function(depth0,helpers,partials,data) {
var stack1;
- stack1 = helpers.each.call(depth0, "view.groupedContent", {"name":"each","hash":{},"hashTypes":{},"hashContexts":{},"fn":this.program(4, data),"inverse":this.noop,"types":["ID"],"contexts":[depth0],"data":data});
+ stack1 = helpers.each.call(depth0, "group", "in", "view.groupedContent", {"name":"each","hash":{},"hashTypes":{},"hashContexts":{},"fn":this.program(4, data),"inverse":this.noop,"types":["ID","ID","ID"],"contexts":[depth0,depth0,depth0],"data":data});
if (stack1 != null) { data.buffer.push(stack1); }
else { data.buffer.push(''); }
},"4":function(depth0,helpers,partials,data) {
var escapeExpression=this.escapeExpression;
data.buffer.push(escapeExpression(helpers.view.call(depth0, "view.groupView", {"name":"view","hash":{
- 'label': ("label"),
- 'content': ("content")
+ 'label': ("group.label"),
+ 'content': ("group.content")
},"hashTypes":{'label': "ID",'content': "ID"},"hashContexts":{'label': depth0,'content': depth0},"types":["ID"],"contexts":[depth0],"data":data})));
},"6":function(depth0,helpers,partials,data) {
var stack1;
- stack1 = helpers.each.call(depth0, "view.content", {"name":"each","hash":{},"hashTypes":{},"hashContexts":{},"fn":this.program(7, data),"inverse":this.noop,"types":["ID"],"contexts":[depth0],"data":data});
+ stack1 = helpers.each.call(depth0, "item", "in", "view.content", {"name":"each","hash":{},"hashTypes":{},"hashContexts":{},"fn":this.program(7, data),"inverse":this.noop,"types":["ID","ID","ID"],"contexts":[depth0,depth0,depth0],"data":data});
if (stack1 != null) { data.buffer.push(stack1); }
else { data.buffer.push(''); }
},"7":function(depth0,helpers,partials,data) {
var escapeExpression=this.escapeExpression;
data.buffer.push(escapeExpression(helpers.view.call(depth0, "view.optionView", {"name":"view","hash":{
- 'content': ("")
+ 'content': ("item")
},"hashTypes":{'content': "ID"},"hashContexts":{'content': depth0},"types":["ID"],"contexts":[depth0],"data":data})));
},"compiler":[6,">= 2.0.0-beta.1"],"main":function(depth0,helpers,partials,data) {
var stack1, buffer = '';
stack1 = helpers['if'].call(depth0, "view.prompt", {"name":"if","hash":{},"hashTypes":{},"hashContexts":{},"fn":this.program(1, data),"inverse":this.noop,"types":["ID"],"contexts":[depth0],"data":data});
if (stack1 != null) { data.buffer.push(stack1); }
@@ -6885,25 +6895,33 @@
function helperMissingHelper(path) {
if (!resolveHelper) {
resolveHelper = requireModule('ember-handlebars/helpers/binding')['resolveHelper'];
} // ES6TODO: stupid circular dep
- var error, view = "";
+ var error, fmtError, view = "";
var options = arguments[arguments.length - 1];
var helper = resolveHelper(options.data.view.container, options.name);
if (helper) {
return helper.apply(this, arguments);
}
- error = "%@ Handlebars error: Could not find property '%@' on object %@.";
if (options.data) {
view = options.data.view;
}
- throw new EmberError(fmt(error, [view, options.name, this]));
+
+ if (options.name.match(/-/)) {
+ error = "%@ Handlebars error: Could not find component or helper named '%@'";
+ fmtError = fmt(error, [view, options.name]);
+ } else {
+ error = "%@ Handlebars error: Could not find property '%@' on object %@.";
+ fmtError = fmt(error, [view, options.name, this]);
+ }
+
+ throw new EmberError(fmtError);
}
__exports__.helperMissingHelper = helperMissingHelper;/**
@private
@method blockHelperMissingHelper
@@ -8219,27 +8237,17 @@
/**
The `{{#each}}` helper loops over elements in a collection. It is an extension
of the base Handlebars `{{#each}}` helper.
The default behavior of `{{#each}}` is to yield its inner block once for every
- item in an array. Each yield will provide the item as the context of the block.
+ item in an array.
```javascript
var developers = [{name: 'Yehuda'},{name: 'Tom'}, {name: 'Paul'}];
```
```handlebars
- {{#each developers}}
- {{name}}
- {{! `this` is each developer }}
- {{/each}}
- ```
-
- `{{#each}}` supports an alternative syntax with element naming. This preserves
- context of the yielded block:
-
- ```handlebars
{{#each person in developers}}
{{person.name}}
{{! `this` is whatever it was outside the #each }}
{{/each}}
```
@@ -8250,12 +8258,12 @@
```javascript
var developerNames = ['Yehuda', 'Tom', 'Paul']
```
```handlebars
- {{#each developerNames}}
- {{this}}
+ {{#each name in developerNames}}
+ {{name}}
{{/each}}
```
### {{else}} condition
@@ -8277,12 +8285,12 @@
The following template:
```handlebars
<ul>
- {{#each developers itemViewClass="person"}}
- {{name}}
+ {{#each developer in developers itemViewClass="person"}}
+ {{developer.name}}
{{/each}}
</ul>
```
Will use the following view for each item
@@ -8309,17 +8317,17 @@
as the previous one:
```javascript
App.PersonView = Ember.View.extend({
tagName: 'li',
- template: '{{name}}'
+ template: '{{developer.name}}'
});
```
```handlebars
<ul>
- {{each developers itemViewClass="person"}}
+ {{each developer in developers itemViewClass="person"}}
</ul>
```
### Specifying an alternative view for no items (else)
@@ -8333,12 +8341,12 @@
});
```
```handlebars
<ul>
- {{#each developers emptyViewClass="no-people"}}
- <li>{{name}}</li>
+ {{#each developer in developers emptyViewClass="no-people"}}
+ <li>{{developer.name}}</li>
{{/each}}
</ul>
```
### Wrapping each item in a controller
@@ -8377,16 +8385,17 @@
@param [options.itemController] {String} name of a controller to be created for each item
*/
function eachHelper(path) {
var options = arguments[arguments.length - 1];
var helperName = 'each';
+ var keywordName;
if (arguments.length === 4) {
Ember.assert("If you pass more than one argument to the each helper," +
" it must be in the form #each foo in bar", arguments[1] === "in");
- var keywordName = arguments[0];
+ keywordName = arguments[0];
path = arguments[2];
helperName += ' ' + keywordName + ' in ' + path;
options.hash.keyword = keywordName;
@@ -8394,10 +8403,12 @@
path = '';
} else {
helperName += ' ' + path;
}
+ Ember.deprecate('Using the context switching form of {{each}} is deprecated. Please use the keyword form (`{{#each foo in bar}}`) instead. See http://emberjs.com/guides/deprecations/#toc_more-consistent-handlebars-scope for more details.', keywordName);
+
options.hash.emptyViewClass = Ember._MetamorphView;
options.hash.dataSourceBinding = path;
options.hashTypes.dataSourceBinding = 'STRING';
options.helperName = options.helperName || helperName;
@@ -8652,21 +8663,11 @@
value as the name of the template to render. If the resolved
value is falsy, nothing will be rendered. If `someTemplateName`
changes, the partial will be re-rendered using the new template
name.
- ## Setting the partial's context with `with`
- The `partial` helper can be used in conjunction with the `with`
- helper to set a context that will be used by the partial:
-
- ```handlebars
- {{#with currentUser}}
- {{partial "user_info"}}
- {{/with}}
- ```
-
@method partial
@for Ember.Handlebars.helpers
@param {String} partialName the name of the template to render minus the leading underscore
*/
@@ -9280,46 +9281,15 @@
}
}
});
/**
- Use the `{{with}}` helper when you want to scope context. Take the following code as an example:
+ Use the `{{with}}` helper when you want to aliases the to a new name. It's helpful
+ for semantic clarity and to retain default scope or to reference from another
+ `{{with}}` block.
```handlebars
- <h5>{{user.name}}</h5>
-
- <div class="role">
- <h6>{{user.role.label}}</h6>
- <span class="role-id">{{user.role.id}}</span>
-
- <p class="role-desc">{{user.role.description}}</p>
- </div>
- ```
-
- `{{with}}` can be our best friend in these cases,
- instead of writing `user.role.*` over and over, we use `{{#with user.role}}`.
- Now the context within the `{{#with}} .. {{/with}}` block is `user.role` so you can do the following:
-
- ```handlebars
- <h5>{{user.name}}</h5>
-
- <div class="role">
- {{#with user.role}}
- <h6>{{label}}</h6>
- <span class="role-id">{{id}}</span>
-
- <p class="role-desc">{{description}}</p>
- {{/with}}
- </div>
- ```
-
- ### `as` operator
-
- This operator aliases the scope to a new name. It's helpful for semantic clarity and to retain
- default scope or to reference from another `{{with}}` block.
-
- ```handlebars
// posts might not be
{{#with user.posts as blogPosts}}
<div class="notice">
There are {{blogPosts.length}} blog posts written by {{user.name}}.
</div>
@@ -9337,22 +9307,22 @@
the first part of the property path, `foo`. Instead, use `{{#with foo.bar as baz}}`.
### `controller` option
Adding `controller='something'` instructs the `{{with}}` helper to create and use an instance of
- the specified controller with the new context as its content.
+ the specified controller wrapping the aliased keyword.
This is very similar to using an `itemController` option with the `{{each}}` helper.
```handlebars
- {{#with users.posts controller='userBlogPosts'}}
- {{!- The current context is wrapped in our controller instance }}
+ {{#with users.posts as posts controller='userBlogPosts'}}
+ {{!- `posts` is wrapped in our controller instance }}
{{/with}}
```
- In the above example, the template provided to the `{{with}}` block is now wrapped in the
- `userBlogPost` controller, which provides a very elegant way to decorate the context with custom
+ In the above example, the `posts` keyword is now wrapped in the `userBlogPost` controller,
+ which provides an elegant way to decorate the context with custom
functions/properties.
@method with
@for Ember.Handlebars.helpers
@param {Function} context
@@ -9387,10 +9357,12 @@
bindContext = this;
options = localizedOptions;
preserveContext = true;
} else {
+ Ember.deprecate('Using the context switching form of `{{with}}` is deprecated. Please use the keyword form (`{{with foo as bar}}`) instead. See http://emberjs.com/guides/deprecations/#toc_more-consistent-handlebars-scope for more details.');
+
Ember.assert("You must pass exactly one argument to the with helper", arguments.length === 2);
Ember.assert("You must pass a block to the with helper", options.fn && options.fn !== Handlebars.VM.noop);
helperName += ' ' + contextPath;
bindContext = options.contexts[0];
@@ -11014,11 +10986,13 @@
// add an observer on the object to be notified when the binding should be updated
addObserver(obj, fromPath, this, this.fromDidChange);
// if the binding is a two-way binding, also set up an observer on the target
- if (!this._oneWay) { addObserver(obj, toPath, this, this.toDidChange); }
+ if (!this._oneWay) {
+ addObserver(obj, toPath, this, this.toDidChange);
+ }
this._readyToSync = true;
return this;
},
@@ -11039,11 +11013,13 @@
// remove an observer on the object so we're no longer notified of
// changes that should update bindings.
removeObserver(obj, this._from, this, this.fromDidChange);
// if the binding is two-way, remove the observer from the target as well
- if (twoWay) { removeObserver(obj, this._to, this, this.toDidChange); }
+ if (twoWay) {
+ removeObserver(obj, this._to, this, this.toDidChange);
+ }
this._readyToSync = false; // disable scheduled syncs...
return this;
},
@@ -11425,11 +11401,13 @@
if (pendingQueue.length === 0) { return; } // nothing to do
var queue = pendingQueue;
pendingQueue = [];
- forEach.call(queue, function(q) { q[0].add(q[1]); });
+ forEach.call(queue, function(q) {
+ q[0].add(q[1]);
+ });
warn('Watching an undefined global, Ember expects watched globals to be' +
' setup by the time the run loop is flushed, check for typos', pendingQueue.length === 0);
}
@@ -11441,11 +11419,13 @@
if (!m.hasOwnProperty('chainWatchers')) {
nodes = m.chainWatchers = {};
}
- if (!nodes[keyName]) { nodes[keyName] = []; }
+ if (!nodes[keyName]) {
+ nodes[keyName] = [];
+ }
nodes[keyName].push(node);
watchKey(obj, keyName, m);
}
function removeChainWatcher(obj, keyName, node) {
@@ -11485,11 +11465,13 @@
this._value = value;
this._paths = {};
if (this._watching) {
this._object = parent.value();
- if (this._object) { addChainWatcher(this._object, this._key, this); }
+ if (this._object) {
+ addChainWatcher(this._object, this._key, this);
+ }
}
// Special-case: the EachProxy relies on immediate evaluation to
// establish its observers.
//
@@ -11505,13 +11487,17 @@
function lazyGet(obj, key) {
if (!obj) return undefined;
var meta = obj['__ember_meta__'];
// check if object meant only to be a prototype
- if (meta && meta.proto === obj) return undefined;
+ if (meta && meta.proto === obj) {
+ return undefined;
+ }
- if (key === "@each") return get(obj, key);
+ if (key === "@each") {
+ return get(obj, key);
+ }
// if a CP only return cached value
var desc = meta && meta.descs[key];
if (desc && desc._cacheable) {
if (key in meta.cache) {
@@ -11533,11 +11519,13 @@
};
ChainNodePrototype.destroy = function() {
if (this._watching) {
var obj = this._object;
- if (obj) { removeChainWatcher(obj, this._key, this); }
+ if (obj) {
+ removeChainWatcher(obj, this._key, this);
+ }
this._watching = false; // so future calls do nothing
}
};
// copies a top level object only
@@ -11545,11 +11533,14 @@
var ret = new ChainNode(null, null, obj);
var paths = this._paths;
var path;
for (path in paths) {
- if (paths[path] <= 0) { continue; } // this check will also catch non-number vals.
+ // this check will also catch non-number vals.
+ if (paths[path] <= 0) {
+ continue;
+ }
ret.add(path);
}
return ret;
};
@@ -11592,11 +11583,13 @@
// path
ChainNodePrototype.remove = function(path) {
var obj, tuple, key, src, paths;
paths = this._paths;
- if (paths[path] > 0) { paths[path]--; }
+ if (paths[path] > 0) {
+ paths[path]--;
+ }
obj = this.value();
tuple = normalizeTuple(obj, path);
if (tuple[0] === obj) {
path = tuple[1];
@@ -11615,14 +11608,18 @@
ChainNodePrototype.count = 0;
ChainNodePrototype.chain = function(key, path, src) {
var chains = this._chains;
var node;
- if (!chains) { chains = this._chains = {}; }
+ if (!chains) {
+ chains = this._chains = {};
+ }
node = chains[key];
- if (!node) { node = chains[key] = new ChainNode(this, key, src); }
+ if (!node) {
+ node = chains[key] = new ChainNode(this, key, src);
+ }
node.count++; // count chains...
// chain rest of path if there is one
if (path) {
key = firstKey(path);
@@ -11634,14 +11631,14 @@
ChainNodePrototype.unchain = function(key, path) {
var chains = this._chains;
var node = chains[key];
// unchain rest of path first...
- if (path && path.length>1) {
- key = firstKey(path);
- path = path.slice(key.length+1);
- node.unchain(key, path);
+ if (path && path.length > 1) {
+ var nextKey = firstKey(path);
+ var nextPath = path.slice(nextKey.length + 1);
+ node.unchain(nextKey, nextPath);
}
// delete node if needed.
node.count--;
if (node.count<=0) {
@@ -11653,20 +11650,26 @@
ChainNodePrototype.willChange = function(events) {
var chains = this._chains;
if (chains) {
for(var key in chains) {
- if (!chains.hasOwnProperty(key)) { continue; }
+ if (!chains.hasOwnProperty(key)) {
+ continue;
+ }
chains[key].willChange(events);
}
}
- if (this._parent) { this._parent.chainWillChange(this, this._key, 1, events); }
+ if (this._parent) {
+ this._parent.chainWillChange(this, this._key, 1, events);
+ }
};
ChainNodePrototype.chainWillChange = function(chain, path, depth, events) {
- if (this._key) { path = this._key + '.' + path; }
+ if (this._key) {
+ path = this._key + '.' + path;
+ }
if (this._parent) {
this._parent.chainWillChange(this, path, depth+1, events);
} else {
if (depth > 1) {
@@ -11678,11 +11681,14 @@
}
}
};
ChainNodePrototype.chainDidChange = function(chain, path, depth, events) {
- if (this._key) { path = this._key + '.' + path; }
+ if (this._key) {
+ path = this._key + '.' + path;
+ }
+
if (this._parent) {
this._parent.chainDidChange(this, path, depth+1, events);
} else {
if (depth > 1) {
events.push(this.value(), path);
@@ -11705,12 +11711,13 @@
}
this._value = undefined;
// Special-case: the EachProxy relies on immediate evaluation to
// establish its observers.
- if (this._parent && this._parent._key === '@each')
+ if (this._parent && this._parent._key === '@each') {
this.value();
+ }
}
// then notify chains...
var chains = this._chains;
if (chains) {
@@ -11719,26 +11726,34 @@
chains[key].didChange(events);
}
}
// if no events are passed in then we only care about the above wiring update
- if (events === null) { return; }
+ if (events === null) {
+ return;
+ }
// and finally tell parent about my path changing...
- if (this._parent) { this._parent.chainDidChange(this, this._key, 1, events); }
+ if (this._parent) {
+ this._parent.chainDidChange(this, this._key, 1, events);
+ }
};
function finishChains(obj) {
// We only create meta if we really have to
- var m = obj['__ember_meta__'],
- chains, chainWatchers, chainNodes;
+ var m = obj['__ember_meta__'];
+ var chains, chainWatchers, chainNodes;
+
if (m) {
// finish any current chains node watchers that reference obj
chainWatchers = m.chainWatchers;
if (chainWatchers) {
for(var key in chainWatchers) {
- if (!chainWatchers.hasOwnProperty(key)) { continue; }
+ if (!chainWatchers.hasOwnProperty(key)) {
+ continue;
+ }
+
chainNodes = chainWatchers[key];
if (chainNodes) {
for (var i=0,l=chainNodes.length;i<l;i++) {
chainNodes[i].didChange(null);
}
@@ -11787,22 +11802,22 @@
// ..........................................................
// COMPUTED PROPERTY
//
/**
- A computed property transforms an objects function into a property.
+ A computed property transforms an object's function into a property.
By default the function backing the computed property will only be called
once and the result will be cached. You can specify various properties
- that your computed property is dependent on. This will force the cached
+ that your computed property depends on. This will force the cached
result to be recomputed if the dependencies are modified.
In the following example we declare a computed property (by calling
- `.property()` on the fullName function) and setup the properties
+ `.property()` on the fullName function) and setup the property
dependencies (depending on firstName and lastName). The fullName function
will be called once (regardless of how many times it is accessed) as long
- as it's dependencies have not been changed. Once firstName or lastName are updated
+ as its dependencies have not changed. Once firstName or lastName are updated
any future calls (or anything bound) to fullName will incorporate the new
values.
```javascript
var Person = Ember.Object.extend({
@@ -12094,11 +12109,13 @@
} else {
cache[keyName] = ret;
}
chainNodes = meta.chainWatchers && meta.chainWatchers[keyName];
- if (chainNodes) { finishChains(chainNodes); }
+ if (chainNodes) {
+ finishChains(chainNodes);
+ }
addDependentKeys(this, obj, keyName, meta);
} else {
ret = this.func.call(obj, keyName);
}
return ret;
@@ -12336,11 +12353,13 @@
function cacheFor(obj, key) {
var meta = obj['__ember_meta__'];
var cache = meta && meta.cache;
var ret = cache && cache[key];
- if (ret === UNDEFINED) { return undefined; }
+ if (ret === UNDEFINED) {
+ return undefined;
+ }
return ret;
}
cacheFor.set = function(cache, key, value) {
if (value === undefined) {
@@ -12350,11 +12369,13 @@
}
};
cacheFor.get = function(cache, key) {
var ret = cache[key];
- if (ret === UNDEFINED) { return undefined; }
+ if (ret === UNDEFINED) {
+ return undefined;
+ }
return ret;
};
cacheFor.remove = function(cache, key) {
cache[key] = undefined;
@@ -13095,11 +13116,11 @@
The core Runtime framework is based on the jQuery API with a number of
performance optimizations.
@class Ember
@static
- @version 1.9.0-beta.1
+ @version 1.9.0-beta.3
*/
if ('undefined' === typeof Ember) {
// Create core object. Make it act like an instance of Ember.Namespace so that
// objects assigned to it are given a sane string representation.
@@ -13122,14 +13143,14 @@
/**
@property VERSION
@type String
- @default '1.9.0-beta.1'
+ @default '1.9.0-beta.3'
@static
*/
- Ember.VERSION = '1.9.0-beta.1';
+ Ember.VERSION = '1.9.0-beta.3';
/**
Standard environmental variables. You can define these in a global `EmberENV`
variable before loading Ember to control various configuration settings.
@@ -13240,11 +13261,11 @@
@default true
*/
Ember.LOG_STACKTRACE_ON_DEPRECATION = (Ember.ENV.LOG_STACKTRACE_ON_DEPRECATION !== false);
/**
- Determines whether Ember should add ECMAScript 5 shims to older browsers.
+ Determines whether Ember should add ECMAScript 5 Array shims to older browsers.
@property SHIM_ES5
@type Boolean
@default Ember.EXTEND_PROTOTYPES
*/
@@ -14773,11 +14794,12 @@
return function keys(obj) {
if (typeof obj !== 'object' && (typeof obj !== 'function' || obj === null)) {
throw new TypeError('Object.keys called on non-object');
}
- var result = [], prop, i;
+ var result = [];
+ var prop, i;
for (prop in obj) {
if (prop !== '_super' &&
prop.lastIndexOf('__',0) !== 0 &&
hasOwnProperty.call(obj, prop)) {
@@ -14863,12 +14885,16 @@
}
var method = typeof consoleObj === 'object' ? consoleObj[name] : null;
if (method) {
- // Older IE doesn't support apply, but Chrome needs it
- if (typeof method.apply === 'function') {
+ // Older IE doesn't support bind, but Chrome needs it
+ if (typeof method.bind === 'function') {
+ logToConsole = method.bind(consoleObj);
+ logToConsole.displayName = 'console.' + name;
+ return logToConsole;
+ } else if (typeof method.apply === 'function') {
logToConsole = function() {
method.apply(consoleObj, arguments);
};
logToConsole.displayName = 'console.' + name;
return logToConsole;
@@ -15557,11 +15583,10 @@
*/
var Ember = __dependency1__["default"];
// warn, assert, wrap, et;
var merge = __dependency2__["default"];
- var a_map = __dependency3__.map;
var a_indexOf = __dependency3__.indexOf;
var a_forEach = __dependency3__.forEach;
var o_create = __dependency4__.create;
var get = __dependency5__.get;
var set = __dependency6__.set;
@@ -15612,26 +15637,10 @@
ret = m.mixins = o_create(ret);
}
return ret;
}
- function initMixin(mixin, args) {
- if (args && args.length > 0) {
- mixin.mixins = a_map.call(args, function(x) {
- if (x instanceof Mixin) { return x; }
-
- // Note: Manually setup a primitive mixin here. This is the only
- // way to actually get a primitive mixin. This way normal creation
- // of mixins will give you combined mixins...
- var mixin = new Mixin();
- mixin.properties = x;
- return mixin;
- });
- }
- return mixin;
- }
-
function isMethod(obj) {
return 'function' === typeof obj &&
obj.isMethod !== false &&
obj !== Boolean &&
obj !== Object &&
@@ -16074,17 +16083,34 @@
@class Mixin
@namespace Ember
*/
__exports__["default"] = Mixin;
- function Mixin() { return initMixin(this, arguments); }
- Mixin.prototype = {
- properties: null,
- mixins: null,
- ownerConstructor: null
- };
+ function Mixin(args, properties) {
+ this.properties = properties;
+ var length = args && args.length;
+
+ if (length > 0) {
+ var m = new Array(length);
+
+ for (var i = 0; i < length; i++) {
+ var x = args[i];
+ if (x instanceof Mixin) {
+ m[i] = x;
+ } else {
+ m[i] = new Mixin(undefined, x);
+ }
+ }
+
+ this.mixins = m;
+ } else {
+ this.mixins = undefined;
+ }
+ this.ownerConstructor = undefined;
+ }
+
Mixin._apply = applyMixin;
Mixin.applyPartial = function(obj) {
var args = a_slice.call(arguments, 1);
return applyMixin(obj, args, true);
@@ -16102,26 +16128,30 @@
*/
Mixin.create = function() {
// ES6TODO: this relies on a global state?
Ember.anyUnprocessedMixins = true;
var M = this;
- return initMixin(new M(), arguments);
+ var length = arguments.length;
+ var args = new Array(length);
+ for (var i = 0; i < length; i++) {
+ args[i] = arguments[i];
+ }
+ return new M(args, undefined);
};
var MixinPrototype = Mixin.prototype;
/**
@method reopen
@param arguments*
*/
MixinPrototype.reopen = function() {
- var mixin, tmp;
+ var mixin;
if (this.properties) {
- mixin = Mixin.create();
- mixin.properties = this.properties;
- delete this.properties;
+ mixin = new Mixin(undefined, this.properties);
+ this.properties = undefined;
this.mixins = [mixin];
} else if (!this.mixins) {
this.mixins = [];
}
@@ -16136,13 +16166,11 @@
Object.prototype.toString.call(mixin) !== '[object Array]');
if (mixin instanceof Mixin) {
mixins.push(mixin);
} else {
- tmp = Mixin.create();
- tmp.properties = mixin;
- mixins.push(tmp);
+ mixins.push(new Mixin(undefined, mixin));
}
}
return this;
};
@@ -16190,11 +16218,11 @@
}
return false;
};
MixinPrototype.without = function() {
- var ret = new Mixin(this);
+ var ret = new Mixin([this]);
ret._without = a_slice.call(arguments);
return ret;
};
function _keys(ret, mixin, seen) {
@@ -16215,11 +16243,13 @@
var keys = {};
var seen = {};
var ret = [];
_keys(keys, this, seen);
for(var key in keys) {
- if (keys.hasOwnProperty(key)) { ret.push(key); }
+ if (keys.hasOwnProperty(key)) {
+ ret.push(key);
+ }
}
return ret;
};
// returns the mixins currently applied to the specified object
@@ -17173,13 +17203,22 @@
var m = obj['__ember_meta__'];
var watching = (m && m.watching[keyName] > 0) || keyName === 'length';
var proto = m && m.proto;
var desc = m && m.descs[keyName];
- if (!watching) { return; }
- if (proto === obj) { return; }
- if (desc && desc.willChange) { desc.willChange(obj, keyName); }
+ if (!watching) {
+ return;
+ }
+
+ if (proto === obj) {
+ return;
+ }
+
+ if (desc && desc.willChange) {
+ desc.willChange(obj, keyName);
+ }
+
dependentKeysWillChange(obj, keyName, m);
chainsWillChange(obj, keyName, m);
notifyBeforeObservers(obj, keyName);
}
@@ -17202,16 +17241,23 @@
var m = obj['__ember_meta__'];
var watching = (m && m.watching[keyName] > 0) || keyName === 'length';
var proto = m && m.proto;
var desc = m && m.descs[keyName];
- if (proto === obj) { return; }
+ if (proto === obj) {
+ return;
+ }
// shouldn't this mean that we're watching this key?
- if (desc && desc.didChange) { desc.didChange(obj, keyName); }
- if (!watching && keyName !== 'length') { return; }
+ if (desc && desc.didChange) {
+ desc.didChange(obj, keyName);
+ }
+ if (!watching && keyName !== 'length') {
+ return;
+ }
+
if (m && m.deps && m.deps[keyName]) {
dependentKeysDidChange(obj, keyName, m);
}
chainsDidChange(obj, keyName, m, false);
@@ -17225,13 +17271,20 @@
var deps;
if (meta && meta.deps && (deps = meta.deps[depKey])) {
var seen = WILL_SEEN;
var top = !seen;
- if (top) { seen = WILL_SEEN = {}; }
+
+ if (top) {
+ seen = WILL_SEEN = {};
+ }
+
iterDeps(propertyWillChange, obj, deps, depKey, seen, meta);
- if (top) { WILL_SEEN = null; }
+
+ if (top) {
+ WILL_SEEN = null;
+ }
}
}
// called whenever a property has just changed to update dependent keys
function dependentKeysDidChange(obj, depKey, meta) {
@@ -17239,37 +17292,59 @@
var deps;
if (meta && meta.deps && (deps = meta.deps[depKey])) {
var seen = DID_SEEN;
var top = !seen;
- if (top) { seen = DID_SEEN = {}; }
+
+ if (top) {
+ seen = DID_SEEN = {};
+ }
+
iterDeps(propertyDidChange, obj, deps, depKey, seen, meta);
- if (top) { DID_SEEN = null; }
+
+ if (top) {
+ DID_SEEN = null;
+ }
}
}
function keysOf(obj) {
var keys = [];
- for (var key in obj) keys.push(key);
+
+ for (var key in obj) {
+ keys.push(key);
+ }
+
return keys;
}
function iterDeps(method, obj, deps, depKey, seen, meta) {
var keys, key, i, desc;
var guid = guidFor(obj);
var current = seen[guid];
- if (!current) current = seen[guid] = {};
- if (current[depKey]) return;
+
+ if (!current) {
+ current = seen[guid] = {};
+ }
+
+ if (current[depKey]) {
+ return;
+ }
+
current[depKey] = true;
if (deps) {
keys = keysOf(deps);
var descs = meta.descs;
for (i=0; i<keys.length; i++) {
key = keys[i];
desc = descs[key];
- if (desc && desc._suspended === obj) continue;
+
+ if (desc && desc._suspended === obj) {
+ continue;
+ }
+
method(obj, key);
}
}
}
@@ -17838,18 +17913,12 @@
then it will be looked up on the passed target.
@param {Object} [args*] Any additional arguments you wish to pass to the method.
@return {Object} Return value from invoking the passed function. Please note,
when called within an existing loop, no return value is possible.
*/
- run.join = function(target, method /* args */) {
- if (!run.currentRunLoop) {
- return Ember.run.apply(Ember, arguments);
- }
-
- var args = slice.call(arguments);
- args.unshift('actions');
- run.schedule.apply(run, args);
+ run.join = function() {
+ return backburner.join.apply(backburner, arguments);
};
/**
Provides a useful utility for when integrating with non-Ember libraries
that provide asynchronous callbacks.
@@ -19652,11 +19721,12 @@
}
};
function unwatchKey(obj, keyName, meta) {
- var m = meta || metaFor(obj), watching = m.watching;
+ var m = meta || metaFor(obj);
+ var watching = m.watching;
if (watching[keyName] === 1) {
watching[keyName] = 0;
var desc = m.descs[keyName];
@@ -25427,15 +25497,19 @@
view.appendTo(rootElement);
}
}
function generateTopLevelTeardown(view) {
- return function() { view.destroy(); };
+ return function() {
+ view.destroy();
+ };
}
function generateOutletTeardown(parentView, outlet) {
- return function() { parentView.disconnectOutlet(outlet); };
+ return function() {
+ parentView.disconnectOutlet(outlet);
+ };
}
function getFullQueryParams(router, state) {
if (state.fullQueryParams) { return state.fullQueryParams; }
@@ -28631,12 +28705,12 @@
```
Then, create a view that binds to your new controller:
```handlebars
- {{#each MyApp.listController}}
- {{firstName}} {{lastName}}
+ {{#each person in MyApp.listController}}
+ {{person.firstName}} {{person.lastName}}
{{/each}}
```
Although you are binding to the controller, the behavior of this controller
is to pass through any methods or properties to the underlying array. This
@@ -39118,11 +39192,11 @@
return result;
},
_bubbleEvent: function(view, evt, eventName) {
- return run(view, view.handleEvent, eventName, evt);
+ return run.join(view, view.handleEvent, eventName, evt);
},
destroy: function() {
var rootElement = get(this, 'rootElement');
jQuery(rootElement).off('.ember', '**').removeClass('ember-application');
@@ -40741,9 +40815,33 @@
this.triggerAction({
action: actionName,
actionContext: contexts
});
+ },
+
+ send: function(actionName) {
+ var args = [].slice.call(arguments, 1);
+ var target;
+ var hasAction = this._actions && this._actions[actionName];
+
+ if (hasAction) {
+ if (this._actions[actionName].apply(this, args) === true) {
+ // handler returned true, so this action will bubble
+ } else {
+ return;
+ }
+ }
+
+ if (target = get(this, 'target')) {
+ Ember.assert("The `target` for " + this + " (" + target +
+ ") does not have a `send` method", typeof target.send === 'function');
+ target.send.apply(target, arguments);
+ } else {
+ if (!hasAction) {
+ throw new Error(Ember.inspect(this) + ' had no action handler for: ' + actionName);
+ }
+ }
}
});
__exports__["default"] = Component;
});
\ No newline at end of file