upgrade ember.js master

This commit is contained in:
Sven Fuchs 2012-06-19 11:47:55 +02:00
parent 5aa55f2064
commit 3121aa551a
5 changed files with 207 additions and 121 deletions

View File

@ -5,32 +5,36 @@ App = Em.Application.create();
App.Store = DS.Store.extend({ revision: 4, adapter: DS.fixtureAdapter }); App.Store = DS.Store.extend({ revision: 4, adapter: DS.fixtureAdapter });
App.Repository = DS.Model.extend({ App.Repository = DS.Model.extend({
slug: DS.attr('string'),
ownerName: DS.attr('string'), ownerName: DS.attr('string'),
name: DS.attr('string'), name: DS.attr('string'),
builds: DS.hasMany('App.Build', { key: 'build_ids' }),
lastBuild: function() {
return this.getPath('builds.firstObject');
}.property()
}); });
App.Build = DS.Model.extend({ App.Build = DS.Model.extend({
repositoryId: DS.attr('number'),
number: DS.attr('number'), number: DS.attr('number'),
repository: DS.belongsTo('App.Repository') repository: DS.belongsTo('App.Repository')
}); });
App.Repository.FIXTURES = [ App.Build.FIXTURES = [
{ id: 1, slug: 'travis-ci/travis-core', owner_name: 'travis-ci', name: 'travis-core' }, { id: 1, repositoryId: 1, repository_id: 1, number: 1 },
{ id: 2, slug: 'travis-ci/travis-assets', owner_name: 'travis-ci', name: 'travis-assets' }, { id: 2, repositoryId: 1, repository_id: 1, number: 2 },
{ id: 3, slug: 'travis-ci/travis-hub', owner_name: 'travis-ci', name: 'travis-hub' }, { id: 3, repositoryId: 2, repository_id: 2, number: 3 },
{ id: 4, repositoryId: 3, repository_id: 3, number: 4 }
]; ];
App.Build.FIXTURES = [ App.Repository.FIXTURES = [
{ id: 1, repository_id: 1, number: 1 }, { id: 1, owner_name: 'travis-ci', name: 'travis-core', build_ids: [1, 2] },
{ id: 2, repository_id: 1, number: 2 }, { id: 2, owner_name: 'travis-ci', name: 'travis-assets', build_ids: [3] },
{ id: 3, repository_id: 2, number: 3 }, { id: 3, owner_name: 'travis-ci', name: 'travis-hub', build_ids: [4] },
{ id: 4, repository_id: 3, number: 4 }
]; ];
App.ApplicationController = Em.Controller.extend(); App.ApplicationController = Em.Controller.extend();
App.RepositoriesController = Em.Controller.extend(); App.RepositoriesController = Em.ArrayController.extend();
App.RepositoryController = Em.Controller.extend(); App.RepositoryController = Em.Controller.extend();
App.TabsController = Em.Controller.extend(); App.TabsController = Em.Controller.extend();
App.CurrentController = Em.Controller.extend(); App.CurrentController = Em.Controller.extend();
@ -80,7 +84,7 @@ App.Router = Em.Router.extend({
connectOutlets: function(router) { connectOutlets: function(router) {
router.connectLayout({}, function(repository) { router.connectLayout({}, function(repository) {
router.connectCurrent(App.Build.find(1)) // should use repository.lastBuild() router.connectCurrent(repository.get('lastBuild'));
}); });
}, },
@ -99,7 +103,7 @@ App.Router = Em.Router.extend({
connectOutlets: function(router, repository) { connectOutlets: function(router, repository) {
var params = router.serializeRepository(repository); var params = router.serializeRepository(repository);
router.connectLayout(params, function(repository) { router.connectLayout(params, function(repository) {
router.connectCurrent(App.Build.find(1)) // should use repository.lastBuild() router.connectCurrent(repository.get('lastBuild'));
}); });
} }
}), }),
@ -115,7 +119,7 @@ App.Router = Em.Router.extend({
connectOutlets: function(router, repository) { connectOutlets: function(router, repository) {
var params = router.serializeRepository(repository); var params = router.serializeRepository(repository);
router.connectLayout(params, function(repository) { router.connectLayout(params, function(repository) {
router.connectHistory(App.Build.find()) router.connectHistory(repository.get('builds'))
}); });
} }
}), }),
@ -148,8 +152,8 @@ App.Router = Em.Router.extend({
serializeBuild: function(build) { serializeBuild: function(build) {
if(build instanceof DS.Model) { if(build instanceof DS.Model) {
// var repository = build.get('repository') var repository = build.get('repository')
var repository = App.Repository.find(build.get('repositoryId')); // wat. // var repository = App.Repository.find(build.get('repositoryId')); // wat.
var params = this.serializeRepository(repository); var params = this.serializeRepository(repository);
return $.extend(params, { id: build.get('id') }); return $.extend(params, { id: build.get('id') });
} else { } else {

View File

@ -1,2 +1,3 @@
current repo current build {{content.id}}

View File

@ -1,5 +1,5 @@
<ul class="tabs"> <ul class="tabs">
<li><a {{action viewCurrent href=true context="repository"}}>Current</a></li> <li><a {{action viewCurrent href=true context="repository"}} class="current">Current</a></li>
<li><a {{action viewHistory href=true context="repository"}}>History</a></li> <li><a {{action viewHistory href=true context="repository"}} class="history">History</a></li>
<li><a {{action viewBuild href=true context="build"}}>Build</a></li> <li><a {{action viewBuild href=true context="build"}} class="build">Build #{{build.number}}</a></li>
</ul> </ul>

View File

@ -2162,7 +2162,7 @@ var DirtyState = DS.State.extend({
invokeLifecycleCallbacks: function(manager) { invokeLifecycleCallbacks: function(manager) {
var record = get(manager, 'record'); var record = get(manager, 'record');
record.fire('becameInvalid', record); record.trigger('becameInvalid', record);
} }
}) })
}); });
@ -2252,7 +2252,7 @@ var states = {
// TRANSITIONS // TRANSITIONS
exit: function(manager) { exit: function(manager) {
var record = get(manager, 'record'); var record = get(manager, 'record');
record.fire('didLoad'); record.trigger('didLoad');
}, },
// EVENTS // EVENTS
@ -2306,9 +2306,9 @@ var states = {
invokeLifecycleCallbacks: function(manager, dirtyType) { invokeLifecycleCallbacks: function(manager, dirtyType) {
var record = get(manager, 'record'); var record = get(manager, 'record');
if (dirtyType === 'created') { if (dirtyType === 'created') {
record.fire('didCreate', record); record.trigger('didCreate', record);
} else { } else {
record.fire('didUpdate', record); record.trigger('didUpdate', record);
} }
} }
}), }),
@ -2411,7 +2411,7 @@ var states = {
invokeLifecycleCallbacks: function(manager) { invokeLifecycleCallbacks: function(manager) {
var record = get(manager, 'record'); var record = get(manager, 'record');
record.fire('didDelete', record); record.trigger('didDelete', record);
} }
}) })
}), }),
@ -2426,7 +2426,7 @@ var states = {
invokeLifecycleCallbacks: function(manager) { invokeLifecycleCallbacks: function(manager) {
var record = get(manager, 'record'); var record = get(manager, 'record');
record.fire('becameError', record); record.trigger('becameError', record);
} }
}) })
}) })
@ -2902,7 +2902,7 @@ DS.Model = Ember.Object.extend(Ember.Evented, {
Override the default event firing from Ember.Evented to Override the default event firing from Ember.Evented to
also call methods with the given name. also call methods with the given name.
*/ */
fire: function(name) { trigger: function(name) {
this[name].apply(this, [].slice.call(arguments, 1)); this[name].apply(this, [].slice.call(arguments, 1));
this._super.apply(this, arguments); this._super.apply(this, arguments);
} }

View File

@ -955,7 +955,7 @@ Ember.isArray = function(obj) {
Ember.makeArray(); => [] Ember.makeArray(); => []
Ember.makeArray(null); => [] Ember.makeArray(null); => []
Ember.makeArray(undefined); => [] Ember.makeArray(undefined); => []
Ember.makeArray('lindsay'); => ['lindsay'] Ember.makeArray('lindsay'); => ['lindsay']
Ember.makeArray([1,2,42]); => [1,2,42] Ember.makeArray([1,2,42]); => [1,2,42]
var controller = Ember.ArrayProxy.create({ content: [] }); var controller = Ember.ArrayProxy.create({ content: [] });
@ -3344,6 +3344,8 @@ function deferEvent(obj, eventName) {
}); });
return function() { return function() {
if (obj.isDestroyed) { return; }
if (obj !== Ember && 'function' === typeof obj.sendEvent) { if (obj !== Ember && 'function' === typeof obj.sendEvent) {
obj.sendEvent.apply(obj, a_slice.call(params, 1)); obj.sendEvent.apply(obj, a_slice.call(params, 1));
} }
@ -3584,7 +3586,7 @@ Ember.RunLoop = RunLoop;
call. call.
Ember.run(function(){ Ember.run(function(){
// code to be execute within a RunLoop // code to be execute within a RunLoop
}); });
@name run @name run
@ -3622,7 +3624,7 @@ var run = Ember.run;
an lower-level way to use a RunLoop instead of using Ember.run(). an lower-level way to use a RunLoop instead of using Ember.run().
Ember.run.begin(); Ember.run.begin();
// code to be execute within a RunLoop // code to be execute within a RunLoop
Ember.run.end(); Ember.run.end();
@ -3638,7 +3640,7 @@ Ember.run.begin = function() {
instead of using Ember.run(). instead of using Ember.run().
Ember.run.begin(); Ember.run.begin();
// code to be execute within a RunLoop // code to be execute within a RunLoop
Ember.run.end(); Ember.run.end();
@returns {void} @returns {void}
@ -5386,7 +5388,7 @@ Ember.inspect = function(obj) {
/** /**
Compares two objects, returning true if they are logically equal. This is Compares two objects, returning true if they are logically equal. This is
a deeper comparison than a simple triple equal. For sets it will compare the a deeper comparison than a simple triple equal. For sets it will compare the
internal objects. For any other object that implements `isEqual()` it will internal objects. For any other object that implements `isEqual()` it will
respect that method. respect that method.
Ember.isEqual('hello', 'hello'); => true Ember.isEqual('hello', 'hello'); => true
@ -5568,7 +5570,7 @@ Ember.String = {
> beta > beta
> gamma > gamma
@param {String} str @param {String} str
The string to split The string to split
@returns {String} split string @returns {String} split string
@ -5577,7 +5579,7 @@ Ember.String = {
/** /**
Converts a camelized string into all lower case separated by underscores. Converts a camelized string into all lower case separated by underscores.
'innerHTML'.decamelize() => 'inner_html' 'innerHTML'.decamelize() => 'inner_html'
'action_name'.decamelize() => 'action_name' 'action_name'.decamelize() => 'action_name'
'css-class-name'.decamelize() => 'css-class-name' 'css-class-name'.decamelize() => 'css-class-name'
@ -5594,7 +5596,7 @@ Ember.String = {
/** /**
Replaces underscores or spaces with dashes. Replaces underscores or spaces with dashes.
'innerHTML'.dasherize() => 'inner-html' 'innerHTML'.dasherize() => 'inner-html'
'action_name'.dasherize() => 'action-name' 'action_name'.dasherize() => 'action-name'
'css-class-name'.dasherize() => 'css-class-name' 'css-class-name'.dasherize() => 'css-class-name'
@ -5761,7 +5763,7 @@ if (Ember.EXTEND_PROTOTYPES) {
/** /**
The `property` extension of Javascript's Function prototype is available The `property` extension of Javascript's Function prototype is available
when Ember.EXTEND_PROTOTYPES is true, which is the default. when Ember.EXTEND_PROTOTYPES is true, which is the default.
Computed properties allow you to treat a function like a property: Computed properties allow you to treat a function like a property:
@ -5816,7 +5818,7 @@ if (Ember.EXTEND_PROTOTYPES) {
/** /**
The `observes` extension of Javascript's Function prototype is available The `observes` extension of Javascript's Function prototype is available
when Ember.EXTEND_PROTOTYPES is true, which is the default. when Ember.EXTEND_PROTOTYPES is true, which is the default.
You can observe property changes simply by adding the `observes` You can observe property changes simply by adding the `observes`
call to the end of your method declarations in classes that you write. call to the end of your method declarations in classes that you write.
@ -5827,7 +5829,7 @@ if (Ember.EXTEND_PROTOTYPES) {
// Executes whenever the "value" property changes // Executes whenever the "value" property changes
}.observes('value') }.observes('value')
}); });
@see Ember.Observable @see Ember.Observable
*/ */
Function.prototype.observes = function() { Function.prototype.observes = function() {
@ -5837,7 +5839,7 @@ if (Ember.EXTEND_PROTOTYPES) {
/** /**
The `observesBefore` extension of Javascript's Function prototype is The `observesBefore` extension of Javascript's Function prototype is
available when Ember.EXTEND_PROTOTYPES is true, which is the default. available when Ember.EXTEND_PROTOTYPES is true, which is the default.
You can get notified when a property changes is about to happen by You can get notified when a property changes is about to happen by
by adding the `observesBefore` call to the end of your method by adding the `observesBefore` call to the end of your method
@ -5848,7 +5850,7 @@ if (Ember.EXTEND_PROTOTYPES) {
// Executes whenever the "value" property is about to change // Executes whenever the "value" property is about to change
}.observesBefore('value') }.observesBefore('value')
}); });
@see Ember.Observable @see Ember.Observable
*/ */
Function.prototype.observesBefore = function() { Function.prototype.observesBefore = function() {
@ -6445,9 +6447,9 @@ Ember.Enumerable = Ember.Mixin.create( /** @lends Ember.Enumerable */ {
/** /**
Returns a copy of the array with all null elements removed. Returns a copy of the array with all null elements removed.
var arr = ["a", null, "c", null]; var arr = ["a", null, "c", null];
arr.compact(); => ["a", "c"] arr.compact(); => ["a", "c"]
@returns {Array} the array without null elements. @returns {Array} the array without null elements.
*/ */
@ -6970,6 +6972,9 @@ Ember.Array = Ember.Mixin.create(Ember.Enumerable, /** @scope Ember.Array.protot
if (addAmt === undefined) addAmt=-1; if (addAmt === undefined) addAmt=-1;
} }
// Make sure the @each proxy is set up if anyone is observing @each
if (Ember.isWatching(this, '@each')) { get(this, '@each'); }
Ember.sendEvent(this, '@array:before', startIdx, removeAmt, addAmt); Ember.sendEvent(this, '@array:before', startIdx, removeAmt, addAmt);
var removing, lim; var removing, lim;
@ -6983,9 +6988,6 @@ Ember.Array = Ember.Mixin.create(Ember.Enumerable, /** @scope Ember.Array.protot
this.enumerableContentWillChange(removing, addAmt); this.enumerableContentWillChange(removing, addAmt);
// Make sure the @each proxy is set up if anyone is observing @each
if (Ember.isWatching(this, '@each')) { get(this, '@each'); }
return this; return this;
}, },
@ -7447,7 +7449,7 @@ Ember.MutableArray = Ember.Mixin.create(Ember.Array, Ember.MutableEnumerable,
colors.clear(); => [] colors.clear(); => []
colors.length(); => 0 colors.length(); => 0
@returns {Ember.Array} An empty Array. @returns {Ember.Array} An empty Array.
*/ */
clear: function () { clear: function () {
var len = get(this, 'length'); var len = get(this, 'length');
@ -7641,15 +7643,15 @@ var get = Ember.get, set = Ember.set;
@class @class
## Overview ## Overview
This mixin provides properties and property observing functionality, core This mixin provides properties and property observing functionality, core
features of the Ember object model. features of the Ember object model.
Properties and observers allow one object to observe changes to a Properties and observers allow one object to observe changes to a
property on another object. This is one of the fundamental ways that property on another object. This is one of the fundamental ways that
models, controllers and views communicate with each other in an Ember models, controllers and views communicate with each other in an Ember
application. application.
Any object that has this mixin applied can be used in observer Any object that has this mixin applied can be used in observer
operations. That includes Ember.Object and most objects you will operations. That includes Ember.Object and most objects you will
interact with as you write your Ember application. interact with as you write your Ember application.
@ -7657,16 +7659,16 @@ var get = Ember.get, set = Ember.set;
Note that you will not generally apply this mixin to classes yourself, Note that you will not generally apply this mixin to classes yourself,
but you will use the features provided by this module frequently, so it but you will use the features provided by this module frequently, so it
is important to understand how to use it. is important to understand how to use it.
## Using get() and set() ## Using get() and set()
Because of Ember's support for bindings and observers, you will always Because of Ember's support for bindings and observers, you will always
access properties using the get method, and set properties using the access properties using the get method, and set properties using the
set method. This allows the observing objects to be notified and set method. This allows the observing objects to be notified and
computed properties to be handled properly. computed properties to be handled properly.
More documentation about `get` and `set` are below. More documentation about `get` and `set` are below.
## Observing Property Changes ## Observing Property Changes
You typically observe property changes simply by adding the `observes` You typically observe property changes simply by adding the `observes`
@ -7678,7 +7680,7 @@ var get = Ember.get, set = Ember.set;
// Executes whenever the "value" property changes // Executes whenever the "value" property changes
}.observes('value') }.observes('value')
}); });
Although this is the most common way to add an observer, this capability Although this is the most common way to add an observer, this capability
is actually built into the Ember.Object class on top of two methods is actually built into the Ember.Object class on top of two methods
defined in this mixin: `addObserver` and `removeObserver`. You can use defined in this mixin: `addObserver` and `removeObserver`. You can use
@ -7691,12 +7693,12 @@ var get = Ember.get, set = Ember.set;
This will call the `targetAction` method on the `targetObject` to be called This will call the `targetAction` method on the `targetObject` to be called
whenever the value of the `propertyKey` changes. whenever the value of the `propertyKey` changes.
Note that if `propertyKey` is a computed property, the observer will be Note that if `propertyKey` is a computed property, the observer will be
called when any of the property dependencies are changed, even if the called when any of the property dependencies are changed, even if the
resulting value of the computed property is unchanged. This is necessary resulting value of the computed property is unchanged. This is necessary
because computed properties are not computed until `get` is called. because computed properties are not computed until `get` is called.
@extends Ember.Mixin @extends Ember.Mixin
*/ */
Ember.Observable = Ember.Mixin.create(/** @scope Ember.Observable.prototype */ { Ember.Observable = Ember.Mixin.create(/** @scope Ember.Observable.prototype */ {
@ -7710,7 +7712,7 @@ Ember.Observable = Ember.Mixin.create(/** @scope Ember.Observable.prototype */ {
This method is usually similar to using object[keyName] or object.keyName, This method is usually similar to using object[keyName] or object.keyName,
however it supports both computed properties and the unknownProperty however it supports both computed properties and the unknownProperty
handler. handler.
Because `get` unifies the syntax for accessing all these kinds Because `get` unifies the syntax for accessing all these kinds
of properties, it can make many refactorings easier, such as replacing a of properties, it can make many refactorings easier, such as replacing a
simple property with a computed property, or vice versa. simple property with a computed property, or vice versa.
@ -7906,11 +7908,11 @@ Ember.Observable = Ember.Mixin.create(/** @scope Ember.Observable.prototype */ {
Ember.propertyDidChange(this, keyName); Ember.propertyDidChange(this, keyName);
return this; return this;
}, },
/** /**
Convenience method to call `propertyWillChange` and `propertyDidChange` in Convenience method to call `propertyWillChange` and `propertyDidChange` in
succession. succession.
@param {String} keyName The property key to be notified about. @param {String} keyName The property key to be notified about.
@returns {Ember.Observable} @returns {Ember.Observable}
*/ */
@ -7920,6 +7922,10 @@ Ember.Observable = Ember.Mixin.create(/** @scope Ember.Observable.prototype */ {
return this; return this;
}, },
addBeforeObserver: function(key, target, method) {
Ember.addBeforeObserver(this, key, target, method);
},
/** /**
Adds an observer on a property. Adds an observer on a property.
@ -7998,7 +8004,7 @@ Ember.Observable = Ember.Mixin.create(/** @scope Ember.Observable.prototype */ {
This method will be called when a client attempts to get the value of a This method will be called when a client attempts to get the value of a
property that has not been defined in one of the typical ways. Override property that has not been defined in one of the typical ways. Override
this method to create "virtual" properties. this method to create "virtual" properties.
@param {String} key The name of the unknown property that was requested. @param {String} key The name of the unknown property that was requested.
@returns {Object} The property value or undefined. Default is undefined. @returns {Object} The property value or undefined. Default is undefined.
*/ */
@ -8010,7 +8016,7 @@ Ember.Observable = Ember.Mixin.create(/** @scope Ember.Observable.prototype */ {
This method will be called when a client attempts to set the value of a This method will be called when a client attempts to set the value of a
property that has not been defined in one of the typical ways. Override property that has not been defined in one of the typical ways. Override
this method to create "virtual" properties. this method to create "virtual" properties.
@param {String} key The name of the unknown property to be set. @param {String} key The name of the unknown property to be set.
@param {Object} value The value the unknown property is to be set to. @param {Object} value The value the unknown property is to be set to.
*/ */
@ -8021,7 +8027,7 @@ Ember.Observable = Ember.Mixin.create(/** @scope Ember.Observable.prototype */ {
/** /**
This is like `get`, but allows you to pass in a dot-separated property This is like `get`, but allows you to pass in a dot-separated property
path. path.
person.getPath('address.zip'); // return the zip person.getPath('address.zip'); // return the zip
person.getPath('children.firstObject.age'); // return the first kid's age person.getPath('children.firstObject.age'); // return the first kid's age
@ -8037,7 +8043,7 @@ Ember.Observable = Ember.Mixin.create(/** @scope Ember.Observable.prototype */ {
/** /**
This is like `set`, but allows you to specify the property you want to This is like `set`, but allows you to specify the property you want to
set as a dot-separated property path. set as a dot-separated property path.
person.setPath('address.zip', 10011); // set the zip to 10011 person.setPath('address.zip', 10011); // set the zip to 10011
person.setPath('children.firstObject.age', 6); // set the first kid's age to 6 person.setPath('children.firstObject.age', 6); // set the first kid's age to 6
@ -8055,9 +8061,9 @@ Ember.Observable = Ember.Mixin.create(/** @scope Ember.Observable.prototype */ {
/** /**
Retrieves the value of a property, or a default value in the case that the property Retrieves the value of a property, or a default value in the case that the property
returns undefined. returns undefined.
person.getWithDefault('lastName', 'Doe'); person.getWithDefault('lastName', 'Doe');
@param {String} keyName The name of the property to retrieve @param {String} keyName The name of the property to retrieve
@param {Object} defaultValue The value to return if the property value is undefined @param {Object} defaultValue The value to return if the property value is undefined
@returns {Object} The property value or the defaultValue. @returns {Object} The property value or the defaultValue.
@ -8068,10 +8074,10 @@ Ember.Observable = Ember.Mixin.create(/** @scope Ember.Observable.prototype */ {
/** /**
Set the value of a property to the current value plus some amount. Set the value of a property to the current value plus some amount.
person.incrementProperty('age'); person.incrementProperty('age');
team.incrementProperty('score', 2); team.incrementProperty('score', 2);
@param {String} keyName The name of the property to increment @param {String} keyName The name of the property to increment
@param {Object} increment The amount to increment by. Defaults to 1 @param {Object} increment The amount to increment by. Defaults to 1
@returns {Object} The new property value @returns {Object} The new property value
@ -8081,13 +8087,13 @@ Ember.Observable = Ember.Mixin.create(/** @scope Ember.Observable.prototype */ {
set(this, keyName, (get(this, keyName) || 0)+increment); set(this, keyName, (get(this, keyName) || 0)+increment);
return get(this, keyName); return get(this, keyName);
}, },
/** /**
Set the value of a property to the current value minus some amount. Set the value of a property to the current value minus some amount.
player.decrementProperty('lives'); player.decrementProperty('lives');
orc.decrementProperty('health', 5); orc.decrementProperty('health', 5);
@param {String} keyName The name of the property to decrement @param {String} keyName The name of the property to decrement
@param {Object} increment The amount to decrement by. Defaults to 1 @param {Object} increment The amount to decrement by. Defaults to 1
@returns {Object} The new property value @returns {Object} The new property value
@ -8101,9 +8107,9 @@ Ember.Observable = Ember.Mixin.create(/** @scope Ember.Observable.prototype */ {
/** /**
Set the value of a boolean property to the opposite of it's Set the value of a boolean property to the opposite of it's
current value. current value.
starship.toggleProperty('warpDriveEnaged'); starship.toggleProperty('warpDriveEnaged');
@param {String} keyName The name of the property to toggle @param {String} keyName The name of the property to toggle
@returns {Object} The new property value @returns {Object} The new property value
*/ */
@ -8204,8 +8210,32 @@ Ember.Evented = Ember.Mixin.create({
Ember.addListener(this, name, target, method, xform); Ember.addListener(this, name, target, method, xform);
}, },
one: function(name, target, method) {
if (!method) {
method = target;
target = null;
}
var wrapped = function() {
Ember.removeListener(this, name, target, wrapped);
// Internally, a `null` target means that the target is
// the first parameter to addListener. That means that
// the `this` passed into this function is the target
// determined by the event system.
method.apply(this, arguments);
};
this.on(name, target, wrapped);
},
trigger: function(name) {
Ember.sendEvent.apply(null, [this, name].concat(a_slice.call(arguments, 1)));
},
fire: function(name) { fire: function(name) {
Ember.sendEvent.apply(null, [this, name].concat(a_slice.call(arguments, 1))); Ember.deprecate("Ember.Evented#fire() has been deprecated in favor of trigger() for compatibility with jQuery. It will be removed in 1.0. Please update your code to call trigger() instead.");
this.trigger.apply(this, arguments);
}, },
off: function(name, target, method) { off: function(name, target, method) {
@ -11466,7 +11496,7 @@ var invokeForState = {
`Ember.View` is the class in Ember responsible for encapsulating templates of HTML `Ember.View` is the class in Ember responsible for encapsulating templates of HTML
content, combining templates with data to render as sections of a page's DOM, and content, combining templates with data to render as sections of a page's DOM, and
registering and responding to user-initiated events. registering and responding to user-initiated events.
## HTML Tag ## HTML Tag
The default HTML tag name used for a view's DOM representation is `div`. This can be The default HTML tag name used for a view's DOM representation is `div`. This can be
customized by setting the `tagName` property. The following view class: customized by setting the `tagName` property. The following view class:
@ -11492,7 +11522,7 @@ var invokeForState = {
<div id="ember1" class="ember-view my-class my-other-class"></div> <div id="ember1" class="ember-view my-class my-other-class"></div>
`class` attribute values can also be set by providing a `classNameBindings` property `class` attribute values can also be set by providing a `classNameBindings` property
set to an array of properties names for the view. The return value of these properties set to an array of properties names for the view. The return value of these properties
will be added as part of the value for the view's `class` attribute. These properties will be added as part of the value for the view's `class` attribute. These properties
can be computed properties: can be computed properties:
@ -11521,7 +11551,7 @@ var invokeForState = {
<div id="ember1" class="ember-view hovered"></div> <div id="ember1" class="ember-view hovered"></div>
When using boolean class name bindings you can supply a string value other than the When using boolean class name bindings you can supply a string value other than the
property name for use as the `class` HTML attribute by appending the preferred value after property name for use as the `class` HTML attribute by appending the preferred value after
a ":" character when defining the binding: a ":" character when defining the binding:
@ -11562,11 +11592,11 @@ var invokeForState = {
<div id="ember1" class="ember-view empty"></div> <div id="ember1" class="ember-view empty"></div>
Updates to the the value of a class name binding will result in automatic update Updates to the the value of a class name binding will result in automatic update
of the HTML `class` attribute in the view's rendered HTML representation. of the HTML `class` attribute in the view's rendered HTML representation.
If the value becomes `false` or `undefined` the class name will be removed. If the value becomes `false` or `undefined` the class name will be removed.
Both `classNames` and `classNameBindings` are concatenated properties. Both `classNames` and `classNameBindings` are concatenated properties.
See `Ember.Object` documentation for more information about concatenated properties. See `Ember.Object` documentation for more information about concatenated properties.
## HTML Attributes ## HTML Attributes
@ -11612,7 +11642,7 @@ var invokeForState = {
}.property() }.property()
}) })
Updates to the the property of an attribute binding will result in automatic update Updates to the the property of an attribute binding will result in automatic update
of the HTML attribute in the view's rendered HTML representation. of the HTML attribute in the view's rendered HTML representation.
`attributeBindings` is a concatenated property. See `Ember.Object` documentation `attributeBindings` is a concatenated property. See `Ember.Object` documentation
@ -11703,7 +11733,7 @@ var invokeForState = {
primary templates, layouts can be any function that accepts an optional context primary templates, layouts can be any function that accepts an optional context
parameter and returns a string of HTML that will be inserted inside view's tag. Views whose HTML parameter and returns a string of HTML that will be inserted inside view's tag. Views whose HTML
element is self closing (e.g. `<input />`) cannot have a layout and this property will be ignored. element is self closing (e.g. `<input />`) cannot have a layout and this property will be ignored.
Most typically in Ember a layout will be a compiled Ember.Handlebars template. Most typically in Ember a layout will be a compiled Ember.Handlebars template.
A view's layout can be set directly with the `layout` property or reference an A view's layout can be set directly with the `layout` property or reference an
@ -11728,7 +11758,7 @@ var invokeForState = {
See `Handlebars.helpers.yield` for more information. See `Handlebars.helpers.yield` for more information.
## Responding to Browser Events ## Responding to Browser Events
Views can respond to user-initiated events in one of three ways: method implementation, Views can respond to user-initiated events in one of three ways: method implementation,
through an event manager, and through `{{action}}` helper use in their template or layout. through an event manager, and through `{{action}}` helper use in their template or layout.
### Method Implementation ### Method Implementation
@ -11745,8 +11775,8 @@ var invokeForState = {
### Event Managers ### Event Managers
Views can define an object as their `eventManager` property. This object can then Views can define an object as their `eventManager` property. This object can then
implement methods that match the desired event names. Matching events that occur implement methods that match the desired event names. Matching events that occur
on the view's rendered HTML or the rendered HTML of any of its DOM descendants on the view's rendered HTML or the rendered HTML of any of its DOM descendants
will trigger this method. A `jQuery.Event` object will be passed as the first will trigger this method. A `jQuery.Event` object will be passed as the first
argument to the method and an `Ember.View` object as the second. The `Ember.View` argument to the method and an `Ember.View` object as the second. The `Ember.View`
will be the view whose rendered HTML was interacted with. This may be the view with will be the view whose rendered HTML was interacted with. This may be the view with
the `eventManager` property or one of its descendent views. the `eventManager` property or one of its descendent views.
@ -11780,7 +11810,7 @@ var invokeForState = {
Similarly a view's event manager will take precedence for events of any views Similarly a view's event manager will take precedence for events of any views
rendered as a descendent. A method name that matches an event name will not be called rendered as a descendent. A method name that matches an event name will not be called
if the view instance was rendered inside the HTML representation of a view that has if the view instance was rendered inside the HTML representation of a view that has
an `eventManager` property defined that handles events of the name. Events not handled an `eventManager` property defined that handles events of the name. Events not handled
by the event manager will still trigger method calls on the descendent. by the event manager will still trigger method calls on the descendent.
@ -11802,7 +11832,7 @@ var invokeForState = {
// eventManager doesn't handle click events // eventManager doesn't handle click events
}, },
mouseEnter: function(event){ mouseEnter: function(event){
// will never be called if rendered inside // will never be called if rendered inside
// an OuterView. // an OuterView.
} }
}) })
@ -11823,7 +11853,7 @@ var invokeForState = {
Form events: 'submit', 'change', 'focusIn', 'focusOut', 'input' Form events: 'submit', 'change', 'focusIn', 'focusOut', 'input'
HTML5 drag and drop events: 'dragStart', 'drag', 'dragEnter', 'dragLeave', 'drop', 'dragEnd' HTML5 drag and drop events: 'dragStart', 'drag', 'dragEnter', 'dragLeave', 'drop', 'dragEnd'
## Handlebars `{{view}}` Helper ## Handlebars `{{view}}` Helper
Other `Ember.View` instances can be included as part of a view's template by using the `{{view}}` Other `Ember.View` instances can be included as part of a view's template by using the `{{view}}`
Handlebars helper. See `Handlebars.helpers.view` for additional information. Handlebars helper. See `Handlebars.helpers.view` for additional information.
@ -12755,7 +12785,7 @@ Ember.View = Ember.Object.extend(Ember.Evented,
*/ */
_notifyWillInsertElement: function() { _notifyWillInsertElement: function() {
this.invokeRecursively(function(view) { this.invokeRecursively(function(view) {
view.fire('willInsertElement'); view.trigger('willInsertElement');
}); });
}, },
@ -12767,7 +12797,7 @@ Ember.View = Ember.Object.extend(Ember.Evented,
*/ */
_notifyDidInsertElement: function() { _notifyDidInsertElement: function() {
this.invokeRecursively(function(view) { this.invokeRecursively(function(view) {
view.fire('didInsertElement'); view.trigger('didInsertElement');
}); });
}, },
@ -12779,7 +12809,7 @@ Ember.View = Ember.Object.extend(Ember.Evented,
*/ */
_notifyWillRerender: function() { _notifyWillRerender: function() {
this.invokeRecursively(function(view) { this.invokeRecursively(function(view) {
view.fire('willRerender'); view.trigger('willRerender');
}); });
}, },
@ -12818,7 +12848,7 @@ Ember.View = Ember.Object.extend(Ember.Evented,
*/ */
_notifyWillDestroyElement: function() { _notifyWillDestroyElement: function() {
this.invokeRecursively(function(view) { this.invokeRecursively(function(view) {
view.fire('willDestroyElement'); view.trigger('willDestroyElement');
}); });
}, },
@ -13248,7 +13278,7 @@ Ember.View = Ember.Object.extend(Ember.Evented,
}, 'isVisible'), }, 'isVisible'),
_notifyBecameVisible: function() { _notifyBecameVisible: function() {
this.fire('becameVisible'); this.trigger('becameVisible');
this.forEachChildView(function(view) { this.forEachChildView(function(view) {
var isVisible = get(view, 'isVisible'); var isVisible = get(view, 'isVisible');
@ -13260,7 +13290,7 @@ Ember.View = Ember.Object.extend(Ember.Evented,
}, },
_notifyBecameHidden: function() { _notifyBecameHidden: function() {
this.fire('becameHidden'); this.trigger('becameHidden');
this.forEachChildView(function(view) { this.forEachChildView(function(view) {
var isVisible = get(view, 'isVisible'); var isVisible = get(view, 'isVisible');
@ -13304,7 +13334,7 @@ Ember.View = Ember.Object.extend(Ember.Evented,
Override the default event firing from Ember.Evented to Override the default event firing from Ember.Evented to
also call methods with the given name. also call methods with the given name.
*/ */
fire: function(name) { trigger: function(name) {
this._super.apply(this, arguments); this._super.apply(this, arguments);
if (this[name]) { if (this[name]) {
return this[name].apply(this, [].slice.call(arguments, 1)); return this[name].apply(this, [].slice.call(arguments, 1));
@ -13678,7 +13708,7 @@ Ember.View.states.hasElement = {
if (view.has(eventName)) { if (view.has(eventName)) {
// Handler should be able to re-dispatch events, so we don't // Handler should be able to re-dispatch events, so we don't
// preventDefault or stopPropagation. // preventDefault or stopPropagation.
return view.fire(eventName, evt); return view.trigger(eventName, evt);
} else { } else {
return true; // continue event propagation return true; // continue event propagation
} }
@ -14200,7 +14230,7 @@ var get = Ember.get, set = Ember.set, fmt = Ember.String.fmt;
@class @class
`Ember.CollectionView` is an `Ember.View` descendent responsible for managing a `Ember.CollectionView` is an `Ember.View` descendent responsible for managing a
collection (an array or array-like object) by maintaing a child view object and collection (an array or array-like object) by maintaing a child view object and
associated DOM representation for each item in the array and ensuring that child associated DOM representation for each item in the array and ensuring that child
views and their associated rendered HTML are updated when items in the array views and their associated rendered HTML are updated when items in the array
are added, removed, or replaced. are added, removed, or replaced.
@ -14244,7 +14274,7 @@ var get = Ember.get, set = Ember.set, fmt = Ember.String.fmt;
## Automatic matching of parent/child tagNames ## Automatic matching of parent/child tagNames
Setting the `tagName` property of a `CollectionView` to any of Setting the `tagName` property of a `CollectionView` to any of
"ul", "ol", "table", "thead", "tbody", "tfoot", "tr", or "select" will result "ul", "ol", "table", "thead", "tbody", "tfoot", "tr", or "select" will result
in the item views receiving an appropriately matched `tagName` property. in the item views receiving an appropriately matched `tagName` property.
@ -14573,7 +14603,7 @@ Ember.State = Ember.Object.extend(Ember.Evented,
Override the default event firing from Ember.Evented to Override the default event firing from Ember.Evented to
also call methods with the given name. also call methods with the given name.
*/ */
fire: function(name) { trigger: function(name) {
if (this[name]) { if (this[name]) {
this[name].apply(this, [].slice.call(arguments, 1)); this[name].apply(this, [].slice.call(arguments, 1));
} }
@ -14689,7 +14719,34 @@ Ember.State = Ember.Object.extend(Ember.Evented,
var Event = Ember.$ && Ember.$.Event; var Event = Ember.$ && Ember.$.Event;
Ember.State.reopenClass({ Ember.State.reopenClass(
/** @scope Ember.State */{
/**
@static
Creates an action function for transitioning to the named state while preserving context.
The following example StateManagers are equivalent:
aManager = Ember.StateManager.create({
stateOne: Ember.State.create({
changeToStateTwo: Ember.State.transitionTo('stateTwo')
}),
stateTwo: Ember.State.create({})
})
bManager = Ember.StateManager.create({
stateOne: Ember.State.create({
changeToStateTwo: function(manager, context){
manager.transitionTo('stateTwo', context)
}
}),
stateTwo: Ember.State.create({})
})
@param {String} target
*/
transitionTo: function(target) { transitionTo: function(target) {
var event = function(stateManager, context) { var event = function(stateManager, context) {
if (Event && context instanceof Event) { if (Event && context instanceof Event) {
@ -15060,6 +15117,24 @@ var arrayForEach = Ember.ArrayPolyfills.forEach;
robotManager.send('beginExtermination', allHumans) robotManager.send('beginExtermination', allHumans)
robotManager.getPath('currentState.name') // 'rampaging' robotManager.getPath('currentState.name') // 'rampaging'
Transition actions can also be created using the `transitionTo` method of the Ember.State class. The
following example StateManagers are equivalent:
aManager = Ember.StateManager.create({
stateOne: Ember.State.create({
changeToStateTwo: Ember.State.transitionTo('stateTwo')
}),
stateTwo: Ember.State.create({})
})
bManager = Ember.StateManager.create({
stateOne: Ember.State.create({
changeToStateTwo: function(manager, context){
manager.transitionTo('stateTwo', context)
}
}),
stateTwo: Ember.State.create({})
})
**/ **/
Ember.StateManager = Ember.State.extend( Ember.StateManager = Ember.State.extend(
/** @scope Ember.StateManager.prototype */ { /** @scope Ember.StateManager.prototype */ {
@ -15132,7 +15207,7 @@ Ember.StateManager = Ember.State.extend(
@default true @default true
*/ */
errorOnUnhandledEvent: true, errorOnUnhandledEvent: true,
send: function(event, context) { send: function(event, context) {
Ember.assert('Cannot send event "' + event + '" while currentState is ' + get(this, 'currentState'), get(this, 'currentState')); Ember.assert('Cannot send event "' + event + '" while currentState is ' + get(this, 'currentState'), get(this, 'currentState'));
if (arguments.length === 1) { context = {}; } if (arguments.length === 1) { context = {}; }
@ -15326,7 +15401,7 @@ Ember.StateManager = Ember.State.extend(
state = this.findStatesByRoute(state, path); state = this.findStatesByRoute(state, path);
state = state[state.length-1]; state = state[state.length-1];
state.fire(get(this, 'transitionEvent'), this, context); state.trigger(get(this, 'transitionEvent'), this, context);
}, this); }, this);
}, },
@ -15347,12 +15422,12 @@ Ember.StateManager = Ember.State.extend(
exitStates = exitStates.slice(0).reverse(); exitStates = exitStates.slice(0).reverse();
arrayForEach.call(exitStates, function(state) { arrayForEach.call(exitStates, function(state) {
state.fire('exit', stateManager); state.trigger('exit', stateManager);
}); });
arrayForEach.call(enterStates, function(state) { arrayForEach.call(enterStates, function(state) {
if (log) { Ember.Logger.log("STATEMANAGER: Entering " + get(state, 'path')); } if (log) { Ember.Logger.log("STATEMANAGER: Entering " + get(state, 'path')); }
state.fire('enter', stateManager); state.trigger('enter', stateManager);
}); });
var startState = state, var startState = state,
@ -15367,7 +15442,7 @@ Ember.StateManager = Ember.State.extend(
enteredState = startState; enteredState = startState;
if (log) { Ember.Logger.log("STATEMANAGER: Entering " + get(startState, 'path')); } if (log) { Ember.Logger.log("STATEMANAGER: Entering " + get(startState, 'path')); }
startState.fire('enter', stateManager); startState.trigger('enter', stateManager);
initialState = get(startState, 'initialState'); initialState = get(startState, 'initialState');
@ -15455,6 +15530,7 @@ Ember.Routable = Ember.Mixin.create({
*/ */
stashContext: function(manager, context) { stashContext: function(manager, context) {
var serialized = this.serialize(manager, context); var serialized = this.serialize(manager, context);
manager.setStateMeta(this, 'serialized', serialized); manager.setStateMeta(this, 'serialized', serialized);
if (get(this, 'isRoutable') && !get(manager, 'isRouting')) { if (get(this, 'isRoutable') && !get(manager, 'isRouting')) {
@ -16217,6 +16293,11 @@ Ember.ViewState = Ember.State.extend(
/** @scope Ember.ViewState.prototype */ { /** @scope Ember.ViewState.prototype */ {
isViewState: true, isViewState: true,
init: function() {
Ember.deprecate("Ember.ViewState is deprecated and will be removed from future releases. Consider using the outlet pattern to display nested views instead. For more information, see http://emberjs.com/guides/outlets/.");
return this._super();
},
enter: function(stateManager) { enter: function(stateManager) {
var view = get(this, 'view'), root, childViews; var view = get(this, 'view'), root, childViews;
@ -17744,7 +17825,7 @@ EmberHandlebars.ViewHelper = Ember.Object.create({
if (!hash.hasOwnProperty(prop)) { continue; } if (!hash.hasOwnProperty(prop)) { continue; }
// Test if the property ends in "Binding" // Test if the property ends in "Binding"
if (Ember.IS_BINDING.test(prop)) { if (Ember.IS_BINDING.test(prop) && typeof hash[prop] === 'string') {
path = hash[prop]; path = hash[prop];
normalized = Ember.Handlebars.normalizePath(null, path, data); normalized = Ember.Handlebars.normalizePath(null, path, data);
@ -17813,7 +17894,7 @@ EmberHandlebars.ViewHelper = Ember.Object.create({
Will result in HTML structure: Will result in HTML structure:
<body> <body>
<!-- Note: the handlebars template script <!-- Note: the handlebars template script
also results in a rendered Ember.View also results in a rendered Ember.View
which is the outer <div> here --> which is the outer <div> here -->
@ -17835,7 +17916,7 @@ EmberHandlebars.ViewHelper = Ember.Object.create({
}) })
aView.appendTo('body') aView.appendTo('body')
Will result in HTML structure: Will result in HTML structure:
<div id="ember1" class="ember-view"> <div id="ember1" class="ember-view">
@ -17909,7 +17990,7 @@ EmberHandlebars.ViewHelper = Ember.Object.create({
Will result in the following HTML: Will result in the following HTML:
<div id="ember1" class="ember-view"> <div id="ember1" class="ember-view">
<div id="ember2" class="ember-view a-custom-view-class-as-property"> <div id="ember2" class="ember-view a-custom-view-class-as-property">
hi hi
</div> </div>
</div> </div>
@ -18069,7 +18150,7 @@ var get = Ember.get, getPath = Ember.Handlebars.getPath, fmt = Ember.String.fmt;
<p class="ember-view greeting">Howdy Mary</p> <p class="ember-view greeting">Howdy Mary</p>
<p class="ember-view greeting">Howdy Sara</p> <p class="ember-view greeting">Howdy Sara</p>
</div> </div>
@name Handlebars.helpers.collection @name Handlebars.helpers.collection
@param {String} path @param {String} path
@param {Hash} options @param {Hash} options
@ -18398,7 +18479,7 @@ ActionHelper.registerAction = function(actionName, eventName, target, view, cont
</div> </div>
</div> </div>
Clicking "click me" will trigger the `anActionName` method of the `aView` object with a Clicking "click me" will trigger the `anActionName` method of the `aView` object with a
`jQuery.Event` object as its argument. The `jQuery.Event` object will be extended to include `jQuery.Event` object as its argument. The `jQuery.Event` object will be extended to include
a `view` property that is set to the original view interacted with (in this case the `aView` object). a `view` property that is set to the original view interacted with (in this case the `aView` object).
@ -18423,9 +18504,9 @@ ActionHelper.registerAction = function(actionName, eventName, target, view, cont
</div> </div>
</script> </script>
Clicking "click me" in the rendered HTML of the above template will trigger the Clicking "click me" in the rendered HTML of the above template will trigger the
`anActionName` method of the object at `MyApplication.someObject`. The first argument `anActionName` method of the object at `MyApplication.someObject`. The first argument
to this method will be a `jQuery.Event` extended to include a `view` property that is to this method will be a `jQuery.Event` extended to include a `view` property that is
set to the original view interacted with. set to the original view interacted with.
A path relative to the template's `Ember.View` instance can also be used as a target: A path relative to the template's `Ember.View` instance can also be used as a target:
@ -18436,7 +18517,7 @@ ActionHelper.registerAction = function(actionName, eventName, target, view, cont
</div> </div>
</script> </script>
Clicking "click me" in the rendered HTML of the above template will trigger the Clicking "click me" in the rendered HTML of the above template will trigger the
`anActionName` method of the view's parent view. `anActionName` method of the view's parent view.
The `{{action}}` helper is `Ember.StateManager` aware. If the target of The `{{action}}` helper is `Ember.StateManager` aware. If the target of
@ -18480,7 +18561,7 @@ ActionHelper.registerAction = function(actionName, eventName, target, view, cont
See `Ember.EventDispatcher` for a list of acceptable DOM event names. See `Ember.EventDispatcher` for a list of acceptable DOM event names.
Because `{{action}}` depends on Ember's event dispatch system it will only function if Because `{{action}}` depends on Ember's event dispatch system it will only function if
an `Ember.EventDispatcher` instance is available. An `Ember.EventDispatcher` instance an `Ember.EventDispatcher` instance is available. An `Ember.EventDispatcher` instance
will be created when a new `Ember.Application` is created. Having an instance of will be created when a new `Ember.Application` is created. Having an instance of
`Ember.Application` will satisfy this requirement. `Ember.Application` will satisfy this requirement.
@ -18678,7 +18759,7 @@ var set = Ember.set, get = Ember.get;
/** /**
@class @class
Creates an HTML input of type 'checkbox' with HTML related properties Creates an HTML input of type 'checkbox' with HTML related properties
applied directly to the input. applied directly to the input.
{{view Ember.Checkbox classNames="applicaton-specific-checkbox"}} {{view Ember.Checkbox classNames="applicaton-specific-checkbox"}}
@ -18697,7 +18778,7 @@ var set = Ember.set, get = Ember.get;
through the Ember object or by interacting with its rendered element representation through the Ember object or by interacting with its rendered element representation
via the mouse, keyboard, or touch. Updating the value of the checkbox via jQuery will via the mouse, keyboard, or touch. Updating the value of the checkbox via jQuery will
result in the checked value of the object and its element losing synchronization. result in the checked value of the object and its element losing synchronization.
## Layout and LayoutName properties ## Layout and LayoutName properties
Because HTML `input` elements are self closing `layout` and `layoutName` properties will Because HTML `input` elements are self closing `layout` and `layoutName` properties will
not be applied. See `Ember.View`'s layout section for more information. not be applied. See `Ember.View`'s layout section for more information.
@ -18809,7 +18890,7 @@ var get = Ember.get, set = Ember.set;
## Layout and LayoutName properties ## Layout and LayoutName properties
Because HTML `input` elements are self closing `layout` and `layoutName` properties will Because HTML `input` elements are self closing `layout` and `layoutName` properties will
not be applied. See `Ember.View`'s layout section for more information. not be applied. See `Ember.View`'s layout section for more information.
@extends Ember.TextSupport @extends Ember.TextSupport
*/ */
Ember.TextField = Ember.View.extend(Ember.TextSupport, Ember.TextField = Ember.View.extend(Ember.TextSupport,
@ -18986,7 +19067,7 @@ var get = Ember.get, set = Ember.set;
## Layout and LayoutName properties ## Layout and LayoutName properties
Because HTML `textarea` elements do not contain inner HTML the `layout` and `layoutName` Because HTML `textarea` elements do not contain inner HTML the `layout` and `layoutName`
properties will not be applied. See `Ember.View`'s layout section for more information. properties will not be applied. See `Ember.View`'s layout section for more information.
@extends Ember.TextSupport @extends Ember.TextSupport