Update ember and ember-data
This commit is contained in:
parent
3eb8e17daa
commit
cd26fc103e
22
assets/javascripts/vendor/ember-data.js
vendored
22
assets/javascripts/vendor/ember-data.js
vendored
|
@ -248,7 +248,7 @@ DS.ManyArrayStateManager = Ember.StateManager.extend({
|
||||||
|
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
var get = Ember.get, set = Ember.set, set = Ember.set;
|
var get = Ember.get, set = Ember.set;
|
||||||
|
|
||||||
DS.ManyArray = DS.RecordArray.extend({
|
DS.ManyArray = DS.RecordArray.extend({
|
||||||
init: function() {
|
init: function() {
|
||||||
|
@ -3743,31 +3743,35 @@ DS.FixtureAdapter = DS.Adapter.extend({
|
||||||
find: function(store, type, id) {
|
find: function(store, type, id) {
|
||||||
var fixtures = this.fixturesForType(type);
|
var fixtures = this.fixturesForType(type);
|
||||||
|
|
||||||
|
Ember.assert("Unable to find fixtures for model type "+type.toString(), !!fixtures);
|
||||||
|
|
||||||
if (fixtures) {
|
if (fixtures) {
|
||||||
fixtures = fixtures.findProperty('id', id);
|
fixtures = fixtures.findProperty('id', id);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ember.assert("Unable to find fixtures for model type "+type.toString(), !!fixtures);
|
if (fixtures) {
|
||||||
|
|
||||||
this.simulateRemoteCall(function() {
|
this.simulateRemoteCall(function() {
|
||||||
store.load(type, fixtures);
|
store.load(type, fixtures);
|
||||||
}, store, type);
|
}, store, type);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
findMany: function(store, type, ids) {
|
findMany: function(store, type, ids) {
|
||||||
var fixtures = this.fixturesForType(type);
|
var fixtures = this.fixturesForType(type);
|
||||||
|
|
||||||
|
Ember.assert("Unable to find fixtures for model type "+type.toString(), !!fixtures);
|
||||||
|
|
||||||
if (fixtures) {
|
if (fixtures) {
|
||||||
fixtures = fixtures.filter(function(item) {
|
fixtures = fixtures.filter(function(item) {
|
||||||
return ids.indexOf(item.id) !== -1;
|
return ids.indexOf(item.id) !== -1;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Ember.assert("Unable to find fixtures for model type "+type.toString(), !!fixtures);
|
if (fixtures) {
|
||||||
|
|
||||||
this.simulateRemoteCall(function() {
|
this.simulateRemoteCall(function() {
|
||||||
store.loadMany(type, fixtures);
|
store.loadMany(type, fixtures);
|
||||||
}, store, type);
|
}, store, type);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
findAll: function(store, type) {
|
findAll: function(store, type) {
|
||||||
|
@ -3783,13 +3787,15 @@ DS.FixtureAdapter = DS.Adapter.extend({
|
||||||
findQuery: function(store, type, query, array) {
|
findQuery: function(store, type, query, array) {
|
||||||
var fixtures = this.fixturesForType(type);
|
var fixtures = this.fixturesForType(type);
|
||||||
|
|
||||||
fixtures = this.queryFixtures(fixtures, query);
|
|
||||||
|
|
||||||
Ember.assert("Unable to find fixtures for model type "+type.toString(), !!fixtures);
|
Ember.assert("Unable to find fixtures for model type "+type.toString(), !!fixtures);
|
||||||
|
|
||||||
|
fixtures = this.queryFixtures(fixtures, query);
|
||||||
|
|
||||||
|
if (fixtures) {
|
||||||
this.simulateRemoteCall(function() {
|
this.simulateRemoteCall(function() {
|
||||||
array.load(fixtures);
|
array.load(fixtures);
|
||||||
}, store, type);
|
}, store, type);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
createRecord: function(store, type, record) {
|
createRecord: function(store, type, record) {
|
||||||
|
@ -4030,7 +4036,9 @@ DS.RESTAdapter = DS.Adapter.extend({
|
||||||
data: query,
|
data: query,
|
||||||
success: function(json) {
|
success: function(json) {
|
||||||
this.sideload(store, type, json, plural);
|
this.sideload(store, type, json, plural);
|
||||||
|
setTimeout(function() {
|
||||||
recordArray.load(json[plural]);
|
recordArray.load(json[plural]);
|
||||||
|
}, 10);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
597
assets/javascripts/vendor/ember.js
vendored
597
assets/javascripts/vendor/ember.js
vendored
|
@ -1,5 +1,5 @@
|
||||||
// Version: v0.9.8.1-617-g2b213df
|
// Version: v0.9.8.1-672-gd7e24ac
|
||||||
// Last commit: 2b213df (2012-07-14 16:44:53 -0700)
|
// Last commit: d7e24ac (2012-07-26 09:35:30 -0700)
|
||||||
|
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
@ -142,8 +142,8 @@ window.ember_deprecateFunc = Ember.deprecateFunc("ember_deprecateFunc is deprec
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
|
||||||
// Version: v0.9.8.1-658-gd4a9e46
|
// Version: v0.9.8.1-672-gd7e24ac
|
||||||
// Last commit: d4a9e46 (2012-07-21 19:16:48 -0700)
|
// Last commit: d7e24ac (2012-07-26 09:35:30 -0700)
|
||||||
|
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
@ -1406,7 +1406,11 @@ set = function set(obj, keyName, value, tolerant) {
|
||||||
if (value !== currentValue) {
|
if (value !== currentValue) {
|
||||||
Ember.propertyWillChange(obj, keyName);
|
Ember.propertyWillChange(obj, keyName);
|
||||||
if (MANDATORY_SETTER) {
|
if (MANDATORY_SETTER) {
|
||||||
|
if (currentValue === undefined && !(keyName in obj)) {
|
||||||
|
Ember.defineProperty(obj, keyName, null, value); // setup mandatory setter
|
||||||
|
} else {
|
||||||
meta.values[keyName] = value;
|
meta.values[keyName] = value;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
obj[keyName] = value;
|
obj[keyName] = value;
|
||||||
}
|
}
|
||||||
|
@ -11377,6 +11381,28 @@ Ember.ControllerMixin.reopen({
|
||||||
set(this, outletName, view);
|
set(this, outletName, view);
|
||||||
|
|
||||||
return view;
|
return view;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
Convenience method to connect controllers. This method makes other controllers
|
||||||
|
available on the controller the method was invoked on.
|
||||||
|
|
||||||
|
For example, to make the `personController` and the `postController` available
|
||||||
|
on the `overviewController`, you would call:
|
||||||
|
|
||||||
|
overviewController.connectControllers('person', 'post');
|
||||||
|
|
||||||
|
@param {String...} controllerNames the controllers to make available
|
||||||
|
*/
|
||||||
|
connectControllers: function() {
|
||||||
|
var controllers = get(this, 'controllers'),
|
||||||
|
controllerNames = Array.prototype.slice.apply(arguments),
|
||||||
|
controllerName;
|
||||||
|
|
||||||
|
for (var i=0, l=controllerNames.length; i<l; i++) {
|
||||||
|
controllerName = controllerNames[i] + 'Controller';
|
||||||
|
set(this, controllerName, get(controllers, controllerName));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -14199,6 +14225,7 @@ Ember.ContainerView = Ember.View.extend({
|
||||||
|
|
||||||
if (currentView) {
|
if (currentView) {
|
||||||
childViews.removeObject(currentView);
|
childViews.removeObject(currentView);
|
||||||
|
currentView.destroy();
|
||||||
}
|
}
|
||||||
}, 'currentView'),
|
}, 'currentView'),
|
||||||
|
|
||||||
|
@ -14823,7 +14850,14 @@ Ember.State.reopenClass(
|
||||||
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) {
|
||||||
|
if (context.hasOwnProperty('context')) {
|
||||||
context = context.context;
|
context = context.context;
|
||||||
|
} else {
|
||||||
|
// If we received an event and it doesn't contain
|
||||||
|
// a context, don't pass along a superfluous
|
||||||
|
// context to the target of the event.
|
||||||
|
return stateManager.transitionTo(target);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stateManager.transitionTo(target, context);
|
stateManager.transitionTo(target, context);
|
||||||
|
@ -14842,6 +14876,167 @@ Ember.State.reopenClass(
|
||||||
(function() {
|
(function() {
|
||||||
var get = Ember.get, set = Ember.set, fmt = Ember.String.fmt;
|
var get = Ember.get, set = Ember.set, fmt = Ember.String.fmt;
|
||||||
var arrayForEach = Ember.ArrayPolyfills.forEach;
|
var arrayForEach = Ember.ArrayPolyfills.forEach;
|
||||||
|
/**
|
||||||
|
@private
|
||||||
|
|
||||||
|
A Transition takes the enter, exit and resolve states and normalizes
|
||||||
|
them:
|
||||||
|
|
||||||
|
* takes any passed in contexts into consideration
|
||||||
|
* adds in `initialState`s
|
||||||
|
*/
|
||||||
|
var Transition = function(raw) {
|
||||||
|
this.enterStates = raw.enterStates.slice();
|
||||||
|
this.exitStates = raw.exitStates.slice();
|
||||||
|
this.resolveState = raw.resolveState;
|
||||||
|
|
||||||
|
this.finalState = raw.enterStates[raw.enterStates.length - 1] || raw.resolveState;
|
||||||
|
};
|
||||||
|
|
||||||
|
Transition.prototype = {
|
||||||
|
/**
|
||||||
|
@private
|
||||||
|
|
||||||
|
Normalize the passed in enter, exit and resolve states.
|
||||||
|
|
||||||
|
This process also adds `finalState` and `contexts` to the Transition object.
|
||||||
|
|
||||||
|
@param {Ember.StateManager} manager the state manager running the transition
|
||||||
|
@param {Array} contexts a list of contexts passed into `transitionTo`
|
||||||
|
*/
|
||||||
|
normalize: function(manager, contexts) {
|
||||||
|
this.matchContextsToStates(contexts);
|
||||||
|
this.addInitialStates();
|
||||||
|
this.removeUnchangedContexts(manager);
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
@private
|
||||||
|
|
||||||
|
Match each of the contexts passed to `transitionTo` to a state.
|
||||||
|
This process may also require adding additional enter and exit
|
||||||
|
states if there are more contexts than enter states.
|
||||||
|
|
||||||
|
@param {Array} contexts a list of contexts passed into `transitionTo`
|
||||||
|
*/
|
||||||
|
matchContextsToStates: function(contexts) {
|
||||||
|
var stateIdx = this.enterStates.length - 1,
|
||||||
|
matchedContexts = [],
|
||||||
|
state,
|
||||||
|
context;
|
||||||
|
|
||||||
|
// Next, we will match the passed in contexts to the states they
|
||||||
|
// represent.
|
||||||
|
//
|
||||||
|
// First, assign a context to each enter state in reverse order. If
|
||||||
|
// any contexts are left, add a parent state to the list of states
|
||||||
|
// to enter and exit, and assign a context to the parent state.
|
||||||
|
//
|
||||||
|
// If there are still contexts left when the state manager is
|
||||||
|
// reached, raise an exception.
|
||||||
|
//
|
||||||
|
// This allows the following:
|
||||||
|
//
|
||||||
|
// |- root
|
||||||
|
// | |- post
|
||||||
|
// | | |- comments
|
||||||
|
// | |- about (* current state)
|
||||||
|
//
|
||||||
|
// For `transitionTo('post.comments', post, post.get('comments')`,
|
||||||
|
// the first context (`post`) will be assigned to `root.post`, and
|
||||||
|
// the second context (`post.get('comments')`) will be assigned
|
||||||
|
// to `root.post.comments`.
|
||||||
|
//
|
||||||
|
// For the following:
|
||||||
|
//
|
||||||
|
// |- root
|
||||||
|
// | |- post
|
||||||
|
// | | |- index (* current state)
|
||||||
|
// | | |- comments
|
||||||
|
//
|
||||||
|
// For `transitionTo('post.comments', otherPost, otherPost.get('comments')`,
|
||||||
|
// the `<root.post>` state will be added to the list of enter and exit
|
||||||
|
// states because its context has changed.
|
||||||
|
|
||||||
|
while (contexts.length > 0) {
|
||||||
|
if (stateIdx >= 0) {
|
||||||
|
state = this.enterStates[stateIdx--];
|
||||||
|
} else {
|
||||||
|
if (this.enterStates.length) {
|
||||||
|
state = get(this.enterStates[0], 'parentState');
|
||||||
|
if (!state) { throw "Cannot match all contexts to states"; }
|
||||||
|
} else {
|
||||||
|
// If re-entering the current state with a context, the resolve
|
||||||
|
// state will be the current state.
|
||||||
|
state = this.resolveState;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.enterStates.unshift(state);
|
||||||
|
this.exitStates.unshift(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
// in routers, only states with dynamic segments have a context
|
||||||
|
if (get(state, 'hasContext')) {
|
||||||
|
context = contexts.pop();
|
||||||
|
} else {
|
||||||
|
context = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
matchedContexts.unshift(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.contexts = matchedContexts;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
@private
|
||||||
|
|
||||||
|
Add any `initialState`s to the list of enter states.
|
||||||
|
*/
|
||||||
|
addInitialStates: function() {
|
||||||
|
var finalState = this.finalState, initialState;
|
||||||
|
|
||||||
|
while(true) {
|
||||||
|
initialState = get(finalState, 'initialState') || 'start';
|
||||||
|
finalState = get(finalState, 'states.' + initialState);
|
||||||
|
|
||||||
|
if (!finalState) { break; }
|
||||||
|
|
||||||
|
this.finalState = finalState;
|
||||||
|
this.enterStates.push(finalState);
|
||||||
|
this.contexts.push(undefined);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
@private
|
||||||
|
|
||||||
|
Remove any states that were added because the number of contexts
|
||||||
|
exceeded the number of explicit enter states, but the context has
|
||||||
|
not changed since the last time the state was entered.
|
||||||
|
|
||||||
|
@param {Ember.StateManager} manager passed in to look up the last
|
||||||
|
context for a states
|
||||||
|
*/
|
||||||
|
removeUnchangedContexts: function(manager) {
|
||||||
|
// Start from the beginning of the enter states. If the state was added
|
||||||
|
// to the list during the context matching phase, make sure the context
|
||||||
|
// has actually changed since the last time the state was entered.
|
||||||
|
while (this.enterStates.length > 0) {
|
||||||
|
if (this.enterStates[0] !== this.exitStates[0]) { break; }
|
||||||
|
|
||||||
|
if (this.enterStates.length === this.contexts.length) {
|
||||||
|
if (manager.getStateMeta(this.enterStates[0], 'context') !== this.contexts[0]) { break; }
|
||||||
|
this.contexts.shift();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.resolveState = this.enterStates.shift();
|
||||||
|
this.exitStates.shift();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@class
|
@class
|
||||||
|
|
||||||
|
@ -15351,18 +15546,29 @@ Ember.StateManager = Ember.State.extend(
|
||||||
return possible;
|
return possible;
|
||||||
},
|
},
|
||||||
|
|
||||||
findStatesByPath: function(state, path) {
|
/**
|
||||||
|
@private
|
||||||
|
|
||||||
|
A state stores its child states in its `states` hash.
|
||||||
|
This code takes a path like `posts.show` and looks
|
||||||
|
up `origin.states.posts.states.show`.
|
||||||
|
|
||||||
|
It returns a list of all of the states from the
|
||||||
|
origin, which is the list of states to call `enter`
|
||||||
|
on.
|
||||||
|
*/
|
||||||
|
findStatesByPath: function(origin, path) {
|
||||||
if (!path || path === "") { return undefined; }
|
if (!path || path === "") { return undefined; }
|
||||||
var r = path.split('.'),
|
var r = path.split('.'),
|
||||||
ret = [];
|
ret = [];
|
||||||
|
|
||||||
for (var i=0, len = r.length; i < len; i++) {
|
for (var i=0, len = r.length; i < len; i++) {
|
||||||
var states = get(state, 'states');
|
var states = get(origin, 'states');
|
||||||
|
|
||||||
if (!states) { return undefined; }
|
if (!states) { return undefined; }
|
||||||
|
|
||||||
var s = get(states, r[i]);
|
var s = get(states, r[i]);
|
||||||
if (s) { state = s; ret.push(s); }
|
if (s) { origin = s; ret.push(s); }
|
||||||
else { return undefined; }
|
else { return undefined; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15376,45 +15582,65 @@ Ember.StateManager = Ember.State.extend(
|
||||||
},
|
},
|
||||||
|
|
||||||
transitionTo: function(path, context) {
|
transitionTo: function(path, context) {
|
||||||
// 1. Normalize arguments
|
// XXX When is transitionTo called with no path
|
||||||
// 2. Ensure that we are in the correct state
|
|
||||||
// 3. Map provided path to context objects and send
|
|
||||||
// appropriate transitionEvent events
|
|
||||||
|
|
||||||
if (Ember.empty(path)) { return; }
|
if (Ember.empty(path)) { return; }
|
||||||
|
|
||||||
|
// The ES6 signature of this function is `path, ...contexts`
|
||||||
var contexts = context ? Array.prototype.slice.call(arguments, 1) : [],
|
var contexts = context ? Array.prototype.slice.call(arguments, 1) : [],
|
||||||
currentState = get(this, 'currentState') || this,
|
currentState = get(this, 'currentState') || this;
|
||||||
resolveState = currentState,
|
|
||||||
|
// First, get the enter, exit and resolve states for the current state
|
||||||
|
// and specified path. If possible, use an existing cache.
|
||||||
|
var hash = this.contextFreeTransition(currentState, path);
|
||||||
|
|
||||||
|
// Next, process the raw state information for the contexts passed in.
|
||||||
|
var transition = new Transition(hash).normalize(this, contexts);
|
||||||
|
|
||||||
|
this.enterState(transition);
|
||||||
|
this.triggerSetupContext(transition);
|
||||||
|
},
|
||||||
|
|
||||||
|
contextFreeTransition: function(currentState, path) {
|
||||||
|
var cache = currentState.pathsCache[path];
|
||||||
|
if (cache) { return cache; }
|
||||||
|
|
||||||
|
var enterStates = this.findStatesByPath(currentState, path),
|
||||||
exitStates = [],
|
exitStates = [],
|
||||||
matchedContexts = [],
|
resolveState = currentState;
|
||||||
cachedPath,
|
|
||||||
enterStates,
|
|
||||||
state,
|
|
||||||
initialState,
|
|
||||||
stateIdx,
|
|
||||||
useContext;
|
|
||||||
|
|
||||||
if (!context && (cachedPath = currentState.pathsCacheNoContext[path])) {
|
|
||||||
// fast path
|
|
||||||
|
|
||||||
exitStates = cachedPath.exitStates;
|
|
||||||
enterStates = cachedPath.enterStates;
|
|
||||||
resolveState = cachedPath.resolveState;
|
|
||||||
} else {
|
|
||||||
// normal path
|
|
||||||
|
|
||||||
if ((cachedPath = currentState.pathsCache[path])) {
|
|
||||||
// cache hit
|
|
||||||
|
|
||||||
exitStates = cachedPath.exitStates;
|
|
||||||
enterStates = cachedPath.enterStates;
|
|
||||||
resolveState = cachedPath.resolveState;
|
|
||||||
} else {
|
|
||||||
// cache miss
|
|
||||||
|
|
||||||
enterStates = this.findStatesByPath(currentState, path);
|
|
||||||
|
|
||||||
|
// Walk up the states. For each state, check whether a state matching
|
||||||
|
// the `path` is nested underneath. This will find the closest
|
||||||
|
// parent state containing `path`.
|
||||||
|
//
|
||||||
|
// This allows the user to pass in a relative path. For example, for
|
||||||
|
// the following state hierarchy:
|
||||||
|
//
|
||||||
|
// | |root
|
||||||
|
// | |- posts
|
||||||
|
// | | |- show (* current)
|
||||||
|
// | |- comments
|
||||||
|
// | | |- show
|
||||||
|
//
|
||||||
|
// If the current state is `<root.posts.show>`, an attempt to
|
||||||
|
// transition to `comments.show` will match `<root.comments.show>`.
|
||||||
|
//
|
||||||
|
// First, this code will look for root.posts.show.comments.show.
|
||||||
|
// Next, it will look for root.posts.comments.show. Finally,
|
||||||
|
// it will look for `root.comments.show`, and find the state.
|
||||||
|
//
|
||||||
|
// After this process, the following variables will exist:
|
||||||
|
//
|
||||||
|
// * resolveState: a common parent state between the current
|
||||||
|
// and target state. In the above example, `<root>` is the
|
||||||
|
// `resolveState`.
|
||||||
|
// * enterStates: a list of all of the states represented
|
||||||
|
// by the path from the `resolveState`. For example, for
|
||||||
|
// the path `root.comments.show`, `enterStates` would have
|
||||||
|
// `[<root.comments>, <root.comments.show>]`
|
||||||
|
// * exitStates: a list of all of the states from the
|
||||||
|
// `resolveState` to the `currentState`. In the above
|
||||||
|
// example, `exitStates` would have
|
||||||
|
// `[<root.posts>`, `<root.posts.show>]`.
|
||||||
while (resolveState && !enterStates) {
|
while (resolveState && !enterStates) {
|
||||||
exitStates.unshift(resolveState);
|
exitStates.unshift(resolveState);
|
||||||
|
|
||||||
|
@ -15429,69 +15655,57 @@ Ember.StateManager = Ember.State.extend(
|
||||||
enterStates = this.findStatesByPath(resolveState, path);
|
enterStates = this.findStatesByPath(resolveState, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the path contains some states that are parents of both the
|
||||||
|
// current state and the target state, remove them.
|
||||||
|
//
|
||||||
|
// For example, in the following hierarchy:
|
||||||
|
//
|
||||||
|
// |- root
|
||||||
|
// | |- post
|
||||||
|
// | | |- index (* current)
|
||||||
|
// | | |- show
|
||||||
|
//
|
||||||
|
// If the `path` is `root.post.show`, the three variables will
|
||||||
|
// be:
|
||||||
|
//
|
||||||
|
// * resolveState: `<state manager>`
|
||||||
|
// * enterStates: `[<root>, <root.post>, <root.post.show>]`
|
||||||
|
// * exitStates: `[<root>, <root.post>, <root.post.index>]`
|
||||||
|
//
|
||||||
|
// The goal of this code is to remove the common states, so we
|
||||||
|
// have:
|
||||||
|
//
|
||||||
|
// * resolveState: `<root.post>`
|
||||||
|
// * enterStates: `[<root.post.show>]`
|
||||||
|
// * exitStates: `[<root.post.index>]`
|
||||||
|
//
|
||||||
|
// This avoid unnecessary calls to the enter and exit transitions.
|
||||||
while (enterStates.length > 0 && enterStates[0] === exitStates[0]) {
|
while (enterStates.length > 0 && enterStates[0] === exitStates[0]) {
|
||||||
resolveState = enterStates.shift();
|
resolveState = enterStates.shift();
|
||||||
exitStates.shift();
|
exitStates.shift();
|
||||||
}
|
}
|
||||||
|
|
||||||
currentState.pathsCache[path] = {
|
// Cache the enterStates, exitStates, and resolveState for the
|
||||||
|
// current state and the `path`.
|
||||||
|
var transitions = currentState.pathsCache[path] = {
|
||||||
exitStates: exitStates,
|
exitStates: exitStates,
|
||||||
enterStates: enterStates,
|
enterStates: enterStates,
|
||||||
resolveState: resolveState
|
resolveState: resolveState
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
|
||||||
// Don't modify the cached versions
|
return transitions;
|
||||||
enterStates = enterStates.slice();
|
|
||||||
exitStates = exitStates.slice();
|
|
||||||
|
|
||||||
stateIdx = enterStates.length-1;
|
|
||||||
while (contexts.length > 0) {
|
|
||||||
if (stateIdx >= 0) {
|
|
||||||
state = enterStates[stateIdx--];
|
|
||||||
} else {
|
|
||||||
state = enterStates[0] ? get(enterStates[0], 'parentState') : resolveState;
|
|
||||||
if (!state) { throw "Cannot match all contexts to states"; }
|
|
||||||
enterStates.unshift(state);
|
|
||||||
exitStates.unshift(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
useContext = context && get(state, 'hasContext');
|
|
||||||
matchedContexts.unshift(useContext ? contexts.pop() : null);
|
|
||||||
}
|
|
||||||
|
|
||||||
state = enterStates[enterStates.length - 1] || resolveState;
|
|
||||||
while(true) {
|
|
||||||
initialState = get(state, 'initialState') || 'start';
|
|
||||||
state = get(state, 'states.'+initialState);
|
|
||||||
if (!state) { break; }
|
|
||||||
enterStates.push(state);
|
|
||||||
matchedContexts.push(undefined);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (enterStates.length > 0) {
|
|
||||||
if (enterStates[0] !== exitStates[0]) { break; }
|
|
||||||
|
|
||||||
if (enterStates.length === matchedContexts.length) {
|
|
||||||
if (this.getStateMeta(enterStates[0], 'context') !== matchedContexts[0]) { break; }
|
|
||||||
matchedContexts.shift();
|
|
||||||
}
|
|
||||||
|
|
||||||
resolveState = enterStates.shift();
|
|
||||||
exitStates.shift();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.enterState(exitStates, enterStates, enterStates[enterStates.length-1] || resolveState);
|
|
||||||
this.triggerSetupContext(enterStates, matchedContexts);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
triggerSetupContext: function(enterStates, contexts) {
|
triggerSetupContext: function(transitions) {
|
||||||
var offset = enterStates.length - contexts.length;
|
var contexts = transitions.contexts,
|
||||||
|
offset = transitions.enterStates.length - contexts.length,
|
||||||
|
enterStates = transitions.enterStates,
|
||||||
|
transitionEvent = get(this, 'transitionEvent');
|
||||||
|
|
||||||
Ember.assert("More contexts provided than states", offset >= 0);
|
Ember.assert("More contexts provided than states", offset >= 0);
|
||||||
|
|
||||||
arrayForEach.call(enterStates, function(state, idx) {
|
arrayForEach.call(enterStates, function(state, idx) {
|
||||||
state.trigger(get(this, 'transitionEvent'), this, contexts[idx-offset]);
|
state.trigger(transitionEvent, this, contexts[idx-offset]);
|
||||||
}, this);
|
}, this);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -15506,21 +15720,20 @@ Ember.StateManager = Ember.State.extend(
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
enterState: function(exitStates, enterStates, state) {
|
enterState: function(transition) {
|
||||||
var log = this.enableLogging,
|
var log = this.enableLogging;
|
||||||
stateManager = this;
|
|
||||||
|
|
||||||
exitStates = exitStates.slice(0).reverse();
|
var exitStates = transition.exitStates.slice(0).reverse();
|
||||||
arrayForEach.call(exitStates, function(state) {
|
arrayForEach.call(exitStates, function(state) {
|
||||||
state.trigger('exit', stateManager);
|
state.trigger('exit', this);
|
||||||
});
|
}, this);
|
||||||
|
|
||||||
arrayForEach.call(enterStates, function(state) {
|
arrayForEach.call(transition.enterStates, function(state) {
|
||||||
if (log) { Ember.Logger.log("STATEMANAGER: Entering " + get(state, 'path')); }
|
if (log) { Ember.Logger.log("STATEMANAGER: Entering " + get(state, 'path')); }
|
||||||
state.trigger('enter', stateManager);
|
state.trigger('enter', this);
|
||||||
});
|
}, this);
|
||||||
|
|
||||||
set(this, 'currentState', state);
|
set(this, 'currentState', transition.finalState);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -16109,9 +16322,9 @@ var get = Ember.get, set = Ember.set;
|
||||||
|
|
||||||
## Adding Routes to a Router
|
## Adding Routes to a Router
|
||||||
The `initialState` property of Ember.Router instances is named `root`. The state stored in this
|
The `initialState` property of Ember.Router instances is named `root`. The state stored in this
|
||||||
property should be a subclass of Ember.Route. The `root` route should itself have states that are
|
property must be a subclass of Ember.Route. The `root` route acts as the container for the
|
||||||
also subclasses of Ember.Route and have `route` properties describing the URL pattern you would
|
set of routable states but is not routable itself. It should have states that are also subclasses
|
||||||
like to detect.
|
of Ember.Route which each have a `route` property describing the URL pattern you would like to detect.
|
||||||
|
|
||||||
App = Ember.Application.create({
|
App = Ember.Application.create({
|
||||||
Router: Ember.Router.extend({
|
Router: Ember.Router.extend({
|
||||||
|
@ -16153,6 +16366,46 @@ var get = Ember.get, set = Ember.set;
|
||||||
'root.bRoute' ('/alphabeta') and transition the router first to the state named 'root' and
|
'root.bRoute' ('/alphabeta') and transition the router first to the state named 'root' and
|
||||||
then to the substate 'bRoute'.
|
then to the substate 'bRoute'.
|
||||||
|
|
||||||
|
## Adding Nested Routes to a Router
|
||||||
|
Routes can contain nested subroutes each with their own `route` property describing the nested
|
||||||
|
portion of the URL they would like to detect and handle. Router, like all instances of StateManager,
|
||||||
|
cannot call `transitonTo` with an intermediary state. To avoid transitioning the Router into an
|
||||||
|
intermediary state when detecting URLs, a Route with nested routes must define both a base `route`
|
||||||
|
property for itself and a child Route with a `route` property of `'/'` which will be transitioned
|
||||||
|
to when the base route is detected in the URL:
|
||||||
|
|
||||||
|
Given the following application code:
|
||||||
|
|
||||||
|
App = Ember.Application.create({
|
||||||
|
Router: Ember.Router.extend({
|
||||||
|
root: Ember.Route.extend({
|
||||||
|
aRoute: Ember.Route.extend({
|
||||||
|
route: '/theBaseRouteForThisSet',
|
||||||
|
|
||||||
|
indexSubRoute: Ember.Route.extend({
|
||||||
|
route: '/',
|
||||||
|
}),
|
||||||
|
|
||||||
|
subRouteOne: Ember.Route.extend({
|
||||||
|
route: '/subroute1
|
||||||
|
}),
|
||||||
|
|
||||||
|
subRouteTwo: Ember.Route.extend({
|
||||||
|
route: '/subRoute2'
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
});
|
||||||
|
App.initialize();
|
||||||
|
|
||||||
|
When the application is loaded at '/theBaseRouteForThisSet' the Router will transition to the route
|
||||||
|
at path 'root.aRoute' and then transition to state 'indexSubRoute'.
|
||||||
|
|
||||||
|
When the application is loaded at '/theBaseRouteForThisSet/subRoute1' the Router will transition to
|
||||||
|
the route at path 'root.aRoute' and then transition to state 'subRouteOne'.
|
||||||
|
|
||||||
## Route Transition Events
|
## Route Transition Events
|
||||||
Transitioning between Ember.Route instances (including the transition into the detected
|
Transitioning between Ember.Route instances (including the transition into the detected
|
||||||
route when loading the application) triggers the same transition events as state transitions for
|
route when loading the application) triggers the same transition events as state transitions for
|
||||||
|
@ -16383,7 +16636,7 @@ var get = Ember.get, set = Ember.set;
|
||||||
|
|
||||||
<script type="text/x-handlebars" data-template-name="photos">
|
<script type="text/x-handlebars" data-template-name="photos">
|
||||||
{{#each photo in controller}}
|
{{#each photo in controller}}
|
||||||
<h1><a {{action showPhoto context="photo"}}>{{title}}</a></h1>
|
<h1><a {{action showPhoto photo}}>{{title}}</a></h1>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -19050,27 +19303,39 @@ Ember.Handlebars.registerHelper('template', function(name, options) {
|
||||||
|
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
var EmberHandlebars = Ember.Handlebars, getPath = EmberHandlebars.getPath, get = Ember.get;
|
var EmberHandlebars = Ember.Handlebars,
|
||||||
|
getPath = EmberHandlebars.getPath,
|
||||||
|
get = Ember.get,
|
||||||
|
a_slice = Array.prototype.slice;
|
||||||
|
|
||||||
var ActionHelper = EmberHandlebars.ActionHelper = {
|
var ActionHelper = EmberHandlebars.ActionHelper = {
|
||||||
registeredActions: {}
|
registeredActions: {}
|
||||||
};
|
};
|
||||||
|
|
||||||
ActionHelper.registerAction = function(actionName, eventName, target, view, context, link) {
|
ActionHelper.registerAction = function(actionName, options) {
|
||||||
var actionId = (++Ember.$.uuid).toString();
|
var actionId = (++Ember.$.uuid).toString();
|
||||||
|
|
||||||
ActionHelper.registeredActions[actionId] = {
|
ActionHelper.registeredActions[actionId] = {
|
||||||
eventName: eventName,
|
eventName: options.eventName,
|
||||||
handler: function(event) {
|
handler: function(event) {
|
||||||
if (link && (event.button !== 0 || event.shiftKey || event.metaKey || event.altKey || event.ctrlKey)) {
|
var modifier = event.shiftKey || event.metaKey || event.altKey || event.ctrlKey,
|
||||||
|
secondaryClick = event.which > 1, // IE9 may return undefined
|
||||||
|
nonStandard = modifier || secondaryClick;
|
||||||
|
|
||||||
|
if (options.link && nonStandard) {
|
||||||
// Allow the browser to handle special link clicks normally
|
// Allow the browser to handle special link clicks normally
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
event.view = view;
|
event.view = options.view;
|
||||||
event.context = context;
|
|
||||||
|
if (options.hasOwnProperty('context')) {
|
||||||
|
event.context = options.context;
|
||||||
|
}
|
||||||
|
|
||||||
|
var target = options.target;
|
||||||
|
|
||||||
// Check for StateManager (or compatible object)
|
// Check for StateManager (or compatible object)
|
||||||
if (target.isState && typeof target.send === 'function') {
|
if (target.isState && typeof target.send === 'function') {
|
||||||
|
@ -19082,7 +19347,7 @@ ActionHelper.registerAction = function(actionName, eventName, target, view, cont
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
view.on('willRerender', function() {
|
options.view.on('willRerender', function() {
|
||||||
delete ActionHelper.registeredActions[actionId];
|
delete ActionHelper.registeredActions[actionId];
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -19091,14 +19356,16 @@ ActionHelper.registerAction = function(actionName, eventName, target, view, cont
|
||||||
|
|
||||||
/**
|
/**
|
||||||
The `{{action}}` helper registers an HTML element within a template for
|
The `{{action}}` helper registers an HTML element within a template for
|
||||||
DOM event handling. User interaction with that element will call the method
|
DOM event handling and forwards that interaction to the Application's router,
|
||||||
on the template's associated `Ember.View` instance that has the same name
|
the template's `Ember.View` instance, or supplied `target` option (see 'Specifiying a Target').
|
||||||
as the first provided argument to `{{action}}`:
|
|
||||||
|
User interaction with that element will invoke the supplied action name on
|
||||||
|
the appropriate target.
|
||||||
|
|
||||||
Given the following Handlebars template on the page
|
Given the following Handlebars template on the page
|
||||||
|
|
||||||
<script type="text/x-handlebars" data-template-name='a-template'>
|
<script type="text/x-handlebars" data-template-name='a-template'>
|
||||||
<div {{action "anActionName"}}>
|
<div {{action anActionName}}>
|
||||||
click me
|
click me
|
||||||
</div>
|
</div>
|
||||||
</script>
|
</script>
|
||||||
|
@ -19134,15 +19401,51 @@ ActionHelper.registerAction = function(actionName, eventName, target, view, cont
|
||||||
handler.
|
handler.
|
||||||
|
|
||||||
If you need the default handler to trigger you should either register your
|
If you need the default handler to trigger you should either register your
|
||||||
own event handler, or use event methods on your view class.
|
own event handler, or use event methods on your view class. See Ember.View
|
||||||
|
'Responding to Browser Events' for more information.
|
||||||
|
|
||||||
### Specifying an Action Target
|
### Specifying DOM event type
|
||||||
|
|
||||||
A `target` option can be provided to change which object will receive the
|
By default the `{{action}}` helper registers for DOM `click` events. You can
|
||||||
method call. This option must be a string representing a path to an object:
|
supply an `on` option to the helper to specify a different DOM event name:
|
||||||
|
|
||||||
<script type="text/x-handlebars" data-template-name='a-template'>
|
<script type="text/x-handlebars" data-template-name='a-template'>
|
||||||
<div {{action "anActionName" target="MyApplication.someObject"}}>
|
<div {{action anActionName on="doubleClick"}}>
|
||||||
|
click me
|
||||||
|
</div>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
See Ember.View 'Responding to Browser Events' for a list of
|
||||||
|
acceptable DOM event names.
|
||||||
|
|
||||||
|
Because `{{action}}` depends on Ember's event dispatch system it will only
|
||||||
|
function if an `Ember.EventDispatcher` instance is available. An
|
||||||
|
`Ember.EventDispatcher` instance will be created when a new
|
||||||
|
`Ember.Application` is created. Having an instance of `Ember.Application`
|
||||||
|
will satisfy this requirement.
|
||||||
|
|
||||||
|
|
||||||
|
### Specifying a Target
|
||||||
|
There are several possible target objects for `{{action}}` helpers:
|
||||||
|
|
||||||
|
In a typical `Ember.Router`-backed Application where views are managed
|
||||||
|
through use of the `{{outlet}}` helper, actions will be forwarded to the
|
||||||
|
current state of the Applications's Router. See Ember.Router 'Responding
|
||||||
|
to User-initiated Events' for more information.
|
||||||
|
|
||||||
|
If you manaully set the `target` property on the controller of a template's
|
||||||
|
`Ember.View` instance, the specifed `controller.target` will become the target
|
||||||
|
for any actions. Likely custom values for a controller's `target` are the
|
||||||
|
controller itself or a StateManager other than the Application's Router.
|
||||||
|
|
||||||
|
If the templates's view lacks a controller property the view itself is the target.
|
||||||
|
|
||||||
|
Finally, a `target` option can be provided to the helper to change which object
|
||||||
|
will receive the method call. This option must be a string representing a
|
||||||
|
path to an object:
|
||||||
|
|
||||||
|
<script type="text/x-handlebars" data-template-name='a-template'>
|
||||||
|
<div {{action anActionName target="MyApplication.someObject"}}>
|
||||||
click me
|
click me
|
||||||
</div>
|
</div>
|
||||||
</script>
|
</script>
|
||||||
|
@ -19156,7 +19459,7 @@ ActionHelper.registerAction = function(actionName, eventName, target, view, cont
|
||||||
a target:
|
a target:
|
||||||
|
|
||||||
<script type="text/x-handlebars" data-template-name='a-template'>
|
<script type="text/x-handlebars" data-template-name='a-template'>
|
||||||
<div {{action "anActionName" target="parentView"}}>
|
<div {{action anActionName target="parentView"}}>
|
||||||
click me
|
click me
|
||||||
</div>
|
</div>
|
||||||
</script>
|
</script>
|
||||||
|
@ -19173,7 +19476,7 @@ ActionHelper.registerAction = function(actionName, eventName, target, view, cont
|
||||||
action name an error will be thrown.
|
action name an error will be thrown.
|
||||||
|
|
||||||
<script type="text/x-handlebars" data-template-name='a-template'>
|
<script type="text/x-handlebars" data-template-name='a-template'>
|
||||||
<div {{action "aMethodNameThatIsMissing"}}>
|
<div {{action aMethodNameThatIsMissing}}>
|
||||||
click me
|
click me
|
||||||
</div>
|
</div>
|
||||||
</script>
|
</script>
|
||||||
|
@ -19192,34 +19495,15 @@ ActionHelper.registerAction = function(actionName, eventName, target, view, cont
|
||||||
Will throw `Uncaught TypeError: Cannot call method 'call' of undefined` when
|
Will throw `Uncaught TypeError: Cannot call method 'call' of undefined` when
|
||||||
"click me" is clicked.
|
"click me" is clicked.
|
||||||
|
|
||||||
### Specifying DOM event type
|
|
||||||
|
|
||||||
By default the `{{action}}` helper registers for DOM `click` events. You can
|
|
||||||
supply an `on` option to the helper to specify a different DOM event name:
|
|
||||||
|
|
||||||
<script type="text/x-handlebars" data-template-name='a-template'>
|
|
||||||
<div {{action "aMethodNameThatIsMissing" on="doubleClick"}}>
|
|
||||||
click me
|
|
||||||
</div>
|
|
||||||
</script>
|
|
||||||
|
|
||||||
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 an `Ember.EventDispatcher` instance is available. An
|
|
||||||
`Ember.EventDispatcher` instance will be created when a new
|
|
||||||
`Ember.Application` is created. Having an instance of `Ember.Application`
|
|
||||||
will satisfy this requirement.
|
|
||||||
|
|
||||||
### Specifying a context
|
### Specifying a context
|
||||||
|
|
||||||
By default the `{{action}}` helper passes the current Handlebars context
|
By default the `{{action}}` helper passes the current Handlebars context
|
||||||
along in the `jQuery.Event` object. You may specify an alternative object to
|
along in the `jQuery.Event` object. You may specify an alternate object to
|
||||||
pass as the context by providing a property path:
|
pass as the context by providing a property path:
|
||||||
|
|
||||||
<script type="text/x-handlebars" data-template-name='a-template'>
|
<script type="text/x-handlebars" data-template-name='a-template'>
|
||||||
{{#each person in people}}
|
{{#each person in people}}
|
||||||
<div {{action "edit" context="person"}}>
|
<div {{action edit person}}>
|
||||||
click me
|
click me
|
||||||
</div>
|
</div>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
|
@ -19227,15 +19511,23 @@ ActionHelper.registerAction = function(actionName, eventName, target, view, cont
|
||||||
|
|
||||||
@name Handlebars.helpers.action
|
@name Handlebars.helpers.action
|
||||||
@param {String} actionName
|
@param {String} actionName
|
||||||
|
@param {Object...} contexts
|
||||||
@param {Hash} options
|
@param {Hash} options
|
||||||
*/
|
*/
|
||||||
EmberHandlebars.registerHelper('action', function(actionName, options) {
|
EmberHandlebars.registerHelper('action', function(actionName) {
|
||||||
|
var options = arguments[arguments.length - 1],
|
||||||
|
contexts = a_slice.call(arguments, 1, -1);
|
||||||
|
|
||||||
var hash = options.hash,
|
var hash = options.hash,
|
||||||
eventName = hash.on || "click",
|
|
||||||
view = options.data.view,
|
view = options.data.view,
|
||||||
target, context, controller, link;
|
target, context, controller, link;
|
||||||
|
|
||||||
view = get(view, 'concreteView');
|
// create a hash to pass along to registerAction
|
||||||
|
var action = {
|
||||||
|
eventName: hash.on || "click"
|
||||||
|
};
|
||||||
|
|
||||||
|
action.view = view = get(view, 'concreteView');
|
||||||
|
|
||||||
if (hash.target) {
|
if (hash.target) {
|
||||||
target = getPath(this, hash.target, options);
|
target = getPath(this, hash.target, options);
|
||||||
|
@ -19243,19 +19535,22 @@ EmberHandlebars.registerHelper('action', function(actionName, options) {
|
||||||
target = get(controller, 'target');
|
target = get(controller, 'target');
|
||||||
}
|
}
|
||||||
|
|
||||||
target = target || view;
|
action.target = target = target || view;
|
||||||
|
|
||||||
context = hash.context ? getPath(this, hash.context, options) : options.contexts[0];
|
// TODO: Support multiple contexts
|
||||||
|
if (contexts.length) {
|
||||||
|
action.context = context = getPath(this, contexts[0], options);
|
||||||
|
}
|
||||||
|
|
||||||
var output = [], url;
|
var output = [], url;
|
||||||
|
|
||||||
if (hash.href && target.urlForEvent) {
|
if (hash.href && target.urlForEvent) {
|
||||||
url = target.urlForEvent(actionName, context);
|
url = target.urlForEvent(actionName, context);
|
||||||
output.push('href="' + url + '"');
|
output.push('href="' + url + '"');
|
||||||
link = true;
|
action.link = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
var actionId = ActionHelper.registerAction(actionName, eventName, target, view, context, link);
|
var actionId = ActionHelper.registerAction(actionName, action);
|
||||||
output.push('data-ember-action="' + actionId + '"');
|
output.push('data-ember-action="' + actionId + '"');
|
||||||
|
|
||||||
return new EmberHandlebars.SafeString(output.join(" "));
|
return new EmberHandlebars.SafeString(output.join(" "));
|
||||||
|
@ -20275,8 +20570,8 @@ Ember.onLoad('application', bootstrap);
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
|
||||||
// Version: v0.9.8.1-658-gd4a9e46
|
// Version: v0.9.8.1-672-gd7e24ac
|
||||||
// Last commit: d4a9e46 (2012-07-21 19:16:48 -0700)
|
// Last commit: d7e24ac (2012-07-26 09:35:30 -0700)
|
||||||
|
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
|
|
@ -1952,8 +1952,8 @@ Handlebars.VM = {
|
||||||
|
|
||||||
Handlebars.template = Handlebars.VM.template;
|
Handlebars.template = Handlebars.VM.template;
|
||||||
;
|
;
|
||||||
// Version: v0.9.8.1-617-g2b213df
|
// Version: v0.9.8.1-672-gd7e24ac
|
||||||
// Last commit: 2b213df (2012-07-14 16:44:53 -0700)
|
// Last commit: d7e24ac (2012-07-26 09:35:30 -0700)
|
||||||
|
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
@ -2096,8 +2096,8 @@ window.ember_deprecateFunc = Ember.deprecateFunc("ember_deprecateFunc is deprec
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
|
||||||
// Version: v0.9.8.1-658-gd4a9e46
|
// Version: v0.9.8.1-672-gd7e24ac
|
||||||
// Last commit: d4a9e46 (2012-07-21 19:16:48 -0700)
|
// Last commit: d7e24ac (2012-07-26 09:35:30 -0700)
|
||||||
|
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
@ -3360,7 +3360,11 @@ set = function set(obj, keyName, value, tolerant) {
|
||||||
if (value !== currentValue) {
|
if (value !== currentValue) {
|
||||||
Ember.propertyWillChange(obj, keyName);
|
Ember.propertyWillChange(obj, keyName);
|
||||||
if (MANDATORY_SETTER) {
|
if (MANDATORY_SETTER) {
|
||||||
|
if (currentValue === undefined && !(keyName in obj)) {
|
||||||
|
Ember.defineProperty(obj, keyName, null, value); // setup mandatory setter
|
||||||
|
} else {
|
||||||
meta.values[keyName] = value;
|
meta.values[keyName] = value;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
obj[keyName] = value;
|
obj[keyName] = value;
|
||||||
}
|
}
|
||||||
|
@ -13331,6 +13335,28 @@ Ember.ControllerMixin.reopen({
|
||||||
set(this, outletName, view);
|
set(this, outletName, view);
|
||||||
|
|
||||||
return view;
|
return view;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
Convenience method to connect controllers. This method makes other controllers
|
||||||
|
available on the controller the method was invoked on.
|
||||||
|
|
||||||
|
For example, to make the `personController` and the `postController` available
|
||||||
|
on the `overviewController`, you would call:
|
||||||
|
|
||||||
|
overviewController.connectControllers('person', 'post');
|
||||||
|
|
||||||
|
@param {String...} controllerNames the controllers to make available
|
||||||
|
*/
|
||||||
|
connectControllers: function() {
|
||||||
|
var controllers = get(this, 'controllers'),
|
||||||
|
controllerNames = Array.prototype.slice.apply(arguments),
|
||||||
|
controllerName;
|
||||||
|
|
||||||
|
for (var i=0, l=controllerNames.length; i<l; i++) {
|
||||||
|
controllerName = controllerNames[i] + 'Controller';
|
||||||
|
set(this, controllerName, get(controllers, controllerName));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -16153,6 +16179,7 @@ Ember.ContainerView = Ember.View.extend({
|
||||||
|
|
||||||
if (currentView) {
|
if (currentView) {
|
||||||
childViews.removeObject(currentView);
|
childViews.removeObject(currentView);
|
||||||
|
currentView.destroy();
|
||||||
}
|
}
|
||||||
}, 'currentView'),
|
}, 'currentView'),
|
||||||
|
|
||||||
|
@ -16777,7 +16804,14 @@ Ember.State.reopenClass(
|
||||||
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) {
|
||||||
|
if (context.hasOwnProperty('context')) {
|
||||||
context = context.context;
|
context = context.context;
|
||||||
|
} else {
|
||||||
|
// If we received an event and it doesn't contain
|
||||||
|
// a context, don't pass along a superfluous
|
||||||
|
// context to the target of the event.
|
||||||
|
return stateManager.transitionTo(target);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stateManager.transitionTo(target, context);
|
stateManager.transitionTo(target, context);
|
||||||
|
@ -16796,6 +16830,167 @@ Ember.State.reopenClass(
|
||||||
(function() {
|
(function() {
|
||||||
var get = Ember.get, set = Ember.set, fmt = Ember.String.fmt;
|
var get = Ember.get, set = Ember.set, fmt = Ember.String.fmt;
|
||||||
var arrayForEach = Ember.ArrayPolyfills.forEach;
|
var arrayForEach = Ember.ArrayPolyfills.forEach;
|
||||||
|
/**
|
||||||
|
@private
|
||||||
|
|
||||||
|
A Transition takes the enter, exit and resolve states and normalizes
|
||||||
|
them:
|
||||||
|
|
||||||
|
* takes any passed in contexts into consideration
|
||||||
|
* adds in `initialState`s
|
||||||
|
*/
|
||||||
|
var Transition = function(raw) {
|
||||||
|
this.enterStates = raw.enterStates.slice();
|
||||||
|
this.exitStates = raw.exitStates.slice();
|
||||||
|
this.resolveState = raw.resolveState;
|
||||||
|
|
||||||
|
this.finalState = raw.enterStates[raw.enterStates.length - 1] || raw.resolveState;
|
||||||
|
};
|
||||||
|
|
||||||
|
Transition.prototype = {
|
||||||
|
/**
|
||||||
|
@private
|
||||||
|
|
||||||
|
Normalize the passed in enter, exit and resolve states.
|
||||||
|
|
||||||
|
This process also adds `finalState` and `contexts` to the Transition object.
|
||||||
|
|
||||||
|
@param {Ember.StateManager} manager the state manager running the transition
|
||||||
|
@param {Array} contexts a list of contexts passed into `transitionTo`
|
||||||
|
*/
|
||||||
|
normalize: function(manager, contexts) {
|
||||||
|
this.matchContextsToStates(contexts);
|
||||||
|
this.addInitialStates();
|
||||||
|
this.removeUnchangedContexts(manager);
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
@private
|
||||||
|
|
||||||
|
Match each of the contexts passed to `transitionTo` to a state.
|
||||||
|
This process may also require adding additional enter and exit
|
||||||
|
states if there are more contexts than enter states.
|
||||||
|
|
||||||
|
@param {Array} contexts a list of contexts passed into `transitionTo`
|
||||||
|
*/
|
||||||
|
matchContextsToStates: function(contexts) {
|
||||||
|
var stateIdx = this.enterStates.length - 1,
|
||||||
|
matchedContexts = [],
|
||||||
|
state,
|
||||||
|
context;
|
||||||
|
|
||||||
|
// Next, we will match the passed in contexts to the states they
|
||||||
|
// represent.
|
||||||
|
//
|
||||||
|
// First, assign a context to each enter state in reverse order. If
|
||||||
|
// any contexts are left, add a parent state to the list of states
|
||||||
|
// to enter and exit, and assign a context to the parent state.
|
||||||
|
//
|
||||||
|
// If there are still contexts left when the state manager is
|
||||||
|
// reached, raise an exception.
|
||||||
|
//
|
||||||
|
// This allows the following:
|
||||||
|
//
|
||||||
|
// |- root
|
||||||
|
// | |- post
|
||||||
|
// | | |- comments
|
||||||
|
// | |- about (* current state)
|
||||||
|
//
|
||||||
|
// For `transitionTo('post.comments', post, post.get('comments')`,
|
||||||
|
// the first context (`post`) will be assigned to `root.post`, and
|
||||||
|
// the second context (`post.get('comments')`) will be assigned
|
||||||
|
// to `root.post.comments`.
|
||||||
|
//
|
||||||
|
// For the following:
|
||||||
|
//
|
||||||
|
// |- root
|
||||||
|
// | |- post
|
||||||
|
// | | |- index (* current state)
|
||||||
|
// | | |- comments
|
||||||
|
//
|
||||||
|
// For `transitionTo('post.comments', otherPost, otherPost.get('comments')`,
|
||||||
|
// the `<root.post>` state will be added to the list of enter and exit
|
||||||
|
// states because its context has changed.
|
||||||
|
|
||||||
|
while (contexts.length > 0) {
|
||||||
|
if (stateIdx >= 0) {
|
||||||
|
state = this.enterStates[stateIdx--];
|
||||||
|
} else {
|
||||||
|
if (this.enterStates.length) {
|
||||||
|
state = get(this.enterStates[0], 'parentState');
|
||||||
|
if (!state) { throw "Cannot match all contexts to states"; }
|
||||||
|
} else {
|
||||||
|
// If re-entering the current state with a context, the resolve
|
||||||
|
// state will be the current state.
|
||||||
|
state = this.resolveState;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.enterStates.unshift(state);
|
||||||
|
this.exitStates.unshift(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
// in routers, only states with dynamic segments have a context
|
||||||
|
if (get(state, 'hasContext')) {
|
||||||
|
context = contexts.pop();
|
||||||
|
} else {
|
||||||
|
context = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
matchedContexts.unshift(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.contexts = matchedContexts;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
@private
|
||||||
|
|
||||||
|
Add any `initialState`s to the list of enter states.
|
||||||
|
*/
|
||||||
|
addInitialStates: function() {
|
||||||
|
var finalState = this.finalState, initialState;
|
||||||
|
|
||||||
|
while(true) {
|
||||||
|
initialState = get(finalState, 'initialState') || 'start';
|
||||||
|
finalState = get(finalState, 'states.' + initialState);
|
||||||
|
|
||||||
|
if (!finalState) { break; }
|
||||||
|
|
||||||
|
this.finalState = finalState;
|
||||||
|
this.enterStates.push(finalState);
|
||||||
|
this.contexts.push(undefined);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
@private
|
||||||
|
|
||||||
|
Remove any states that were added because the number of contexts
|
||||||
|
exceeded the number of explicit enter states, but the context has
|
||||||
|
not changed since the last time the state was entered.
|
||||||
|
|
||||||
|
@param {Ember.StateManager} manager passed in to look up the last
|
||||||
|
context for a states
|
||||||
|
*/
|
||||||
|
removeUnchangedContexts: function(manager) {
|
||||||
|
// Start from the beginning of the enter states. If the state was added
|
||||||
|
// to the list during the context matching phase, make sure the context
|
||||||
|
// has actually changed since the last time the state was entered.
|
||||||
|
while (this.enterStates.length > 0) {
|
||||||
|
if (this.enterStates[0] !== this.exitStates[0]) { break; }
|
||||||
|
|
||||||
|
if (this.enterStates.length === this.contexts.length) {
|
||||||
|
if (manager.getStateMeta(this.enterStates[0], 'context') !== this.contexts[0]) { break; }
|
||||||
|
this.contexts.shift();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.resolveState = this.enterStates.shift();
|
||||||
|
this.exitStates.shift();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@class
|
@class
|
||||||
|
|
||||||
|
@ -17305,18 +17500,29 @@ Ember.StateManager = Ember.State.extend(
|
||||||
return possible;
|
return possible;
|
||||||
},
|
},
|
||||||
|
|
||||||
findStatesByPath: function(state, path) {
|
/**
|
||||||
|
@private
|
||||||
|
|
||||||
|
A state stores its child states in its `states` hash.
|
||||||
|
This code takes a path like `posts.show` and looks
|
||||||
|
up `origin.states.posts.states.show`.
|
||||||
|
|
||||||
|
It returns a list of all of the states from the
|
||||||
|
origin, which is the list of states to call `enter`
|
||||||
|
on.
|
||||||
|
*/
|
||||||
|
findStatesByPath: function(origin, path) {
|
||||||
if (!path || path === "") { return undefined; }
|
if (!path || path === "") { return undefined; }
|
||||||
var r = path.split('.'),
|
var r = path.split('.'),
|
||||||
ret = [];
|
ret = [];
|
||||||
|
|
||||||
for (var i=0, len = r.length; i < len; i++) {
|
for (var i=0, len = r.length; i < len; i++) {
|
||||||
var states = get(state, 'states');
|
var states = get(origin, 'states');
|
||||||
|
|
||||||
if (!states) { return undefined; }
|
if (!states) { return undefined; }
|
||||||
|
|
||||||
var s = get(states, r[i]);
|
var s = get(states, r[i]);
|
||||||
if (s) { state = s; ret.push(s); }
|
if (s) { origin = s; ret.push(s); }
|
||||||
else { return undefined; }
|
else { return undefined; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17330,45 +17536,65 @@ Ember.StateManager = Ember.State.extend(
|
||||||
},
|
},
|
||||||
|
|
||||||
transitionTo: function(path, context) {
|
transitionTo: function(path, context) {
|
||||||
// 1. Normalize arguments
|
// XXX When is transitionTo called with no path
|
||||||
// 2. Ensure that we are in the correct state
|
|
||||||
// 3. Map provided path to context objects and send
|
|
||||||
// appropriate transitionEvent events
|
|
||||||
|
|
||||||
if (Ember.empty(path)) { return; }
|
if (Ember.empty(path)) { return; }
|
||||||
|
|
||||||
|
// The ES6 signature of this function is `path, ...contexts`
|
||||||
var contexts = context ? Array.prototype.slice.call(arguments, 1) : [],
|
var contexts = context ? Array.prototype.slice.call(arguments, 1) : [],
|
||||||
currentState = get(this, 'currentState') || this,
|
currentState = get(this, 'currentState') || this;
|
||||||
resolveState = currentState,
|
|
||||||
|
// First, get the enter, exit and resolve states for the current state
|
||||||
|
// and specified path. If possible, use an existing cache.
|
||||||
|
var hash = this.contextFreeTransition(currentState, path);
|
||||||
|
|
||||||
|
// Next, process the raw state information for the contexts passed in.
|
||||||
|
var transition = new Transition(hash).normalize(this, contexts);
|
||||||
|
|
||||||
|
this.enterState(transition);
|
||||||
|
this.triggerSetupContext(transition);
|
||||||
|
},
|
||||||
|
|
||||||
|
contextFreeTransition: function(currentState, path) {
|
||||||
|
var cache = currentState.pathsCache[path];
|
||||||
|
if (cache) { return cache; }
|
||||||
|
|
||||||
|
var enterStates = this.findStatesByPath(currentState, path),
|
||||||
exitStates = [],
|
exitStates = [],
|
||||||
matchedContexts = [],
|
resolveState = currentState;
|
||||||
cachedPath,
|
|
||||||
enterStates,
|
|
||||||
state,
|
|
||||||
initialState,
|
|
||||||
stateIdx,
|
|
||||||
useContext;
|
|
||||||
|
|
||||||
if (!context && (cachedPath = currentState.pathsCacheNoContext[path])) {
|
|
||||||
// fast path
|
|
||||||
|
|
||||||
exitStates = cachedPath.exitStates;
|
|
||||||
enterStates = cachedPath.enterStates;
|
|
||||||
resolveState = cachedPath.resolveState;
|
|
||||||
} else {
|
|
||||||
// normal path
|
|
||||||
|
|
||||||
if ((cachedPath = currentState.pathsCache[path])) {
|
|
||||||
// cache hit
|
|
||||||
|
|
||||||
exitStates = cachedPath.exitStates;
|
|
||||||
enterStates = cachedPath.enterStates;
|
|
||||||
resolveState = cachedPath.resolveState;
|
|
||||||
} else {
|
|
||||||
// cache miss
|
|
||||||
|
|
||||||
enterStates = this.findStatesByPath(currentState, path);
|
|
||||||
|
|
||||||
|
// Walk up the states. For each state, check whether a state matching
|
||||||
|
// the `path` is nested underneath. This will find the closest
|
||||||
|
// parent state containing `path`.
|
||||||
|
//
|
||||||
|
// This allows the user to pass in a relative path. For example, for
|
||||||
|
// the following state hierarchy:
|
||||||
|
//
|
||||||
|
// | |root
|
||||||
|
// | |- posts
|
||||||
|
// | | |- show (* current)
|
||||||
|
// | |- comments
|
||||||
|
// | | |- show
|
||||||
|
//
|
||||||
|
// If the current state is `<root.posts.show>`, an attempt to
|
||||||
|
// transition to `comments.show` will match `<root.comments.show>`.
|
||||||
|
//
|
||||||
|
// First, this code will look for root.posts.show.comments.show.
|
||||||
|
// Next, it will look for root.posts.comments.show. Finally,
|
||||||
|
// it will look for `root.comments.show`, and find the state.
|
||||||
|
//
|
||||||
|
// After this process, the following variables will exist:
|
||||||
|
//
|
||||||
|
// * resolveState: a common parent state between the current
|
||||||
|
// and target state. In the above example, `<root>` is the
|
||||||
|
// `resolveState`.
|
||||||
|
// * enterStates: a list of all of the states represented
|
||||||
|
// by the path from the `resolveState`. For example, for
|
||||||
|
// the path `root.comments.show`, `enterStates` would have
|
||||||
|
// `[<root.comments>, <root.comments.show>]`
|
||||||
|
// * exitStates: a list of all of the states from the
|
||||||
|
// `resolveState` to the `currentState`. In the above
|
||||||
|
// example, `exitStates` would have
|
||||||
|
// `[<root.posts>`, `<root.posts.show>]`.
|
||||||
while (resolveState && !enterStates) {
|
while (resolveState && !enterStates) {
|
||||||
exitStates.unshift(resolveState);
|
exitStates.unshift(resolveState);
|
||||||
|
|
||||||
|
@ -17383,69 +17609,57 @@ Ember.StateManager = Ember.State.extend(
|
||||||
enterStates = this.findStatesByPath(resolveState, path);
|
enterStates = this.findStatesByPath(resolveState, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the path contains some states that are parents of both the
|
||||||
|
// current state and the target state, remove them.
|
||||||
|
//
|
||||||
|
// For example, in the following hierarchy:
|
||||||
|
//
|
||||||
|
// |- root
|
||||||
|
// | |- post
|
||||||
|
// | | |- index (* current)
|
||||||
|
// | | |- show
|
||||||
|
//
|
||||||
|
// If the `path` is `root.post.show`, the three variables will
|
||||||
|
// be:
|
||||||
|
//
|
||||||
|
// * resolveState: `<state manager>`
|
||||||
|
// * enterStates: `[<root>, <root.post>, <root.post.show>]`
|
||||||
|
// * exitStates: `[<root>, <root.post>, <root.post.index>]`
|
||||||
|
//
|
||||||
|
// The goal of this code is to remove the common states, so we
|
||||||
|
// have:
|
||||||
|
//
|
||||||
|
// * resolveState: `<root.post>`
|
||||||
|
// * enterStates: `[<root.post.show>]`
|
||||||
|
// * exitStates: `[<root.post.index>]`
|
||||||
|
//
|
||||||
|
// This avoid unnecessary calls to the enter and exit transitions.
|
||||||
while (enterStates.length > 0 && enterStates[0] === exitStates[0]) {
|
while (enterStates.length > 0 && enterStates[0] === exitStates[0]) {
|
||||||
resolveState = enterStates.shift();
|
resolveState = enterStates.shift();
|
||||||
exitStates.shift();
|
exitStates.shift();
|
||||||
}
|
}
|
||||||
|
|
||||||
currentState.pathsCache[path] = {
|
// Cache the enterStates, exitStates, and resolveState for the
|
||||||
|
// current state and the `path`.
|
||||||
|
var transitions = currentState.pathsCache[path] = {
|
||||||
exitStates: exitStates,
|
exitStates: exitStates,
|
||||||
enterStates: enterStates,
|
enterStates: enterStates,
|
||||||
resolveState: resolveState
|
resolveState: resolveState
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
|
||||||
// Don't modify the cached versions
|
return transitions;
|
||||||
enterStates = enterStates.slice();
|
|
||||||
exitStates = exitStates.slice();
|
|
||||||
|
|
||||||
stateIdx = enterStates.length-1;
|
|
||||||
while (contexts.length > 0) {
|
|
||||||
if (stateIdx >= 0) {
|
|
||||||
state = enterStates[stateIdx--];
|
|
||||||
} else {
|
|
||||||
state = enterStates[0] ? get(enterStates[0], 'parentState') : resolveState;
|
|
||||||
if (!state) { throw "Cannot match all contexts to states"; }
|
|
||||||
enterStates.unshift(state);
|
|
||||||
exitStates.unshift(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
useContext = context && get(state, 'hasContext');
|
|
||||||
matchedContexts.unshift(useContext ? contexts.pop() : null);
|
|
||||||
}
|
|
||||||
|
|
||||||
state = enterStates[enterStates.length - 1] || resolveState;
|
|
||||||
while(true) {
|
|
||||||
initialState = get(state, 'initialState') || 'start';
|
|
||||||
state = get(state, 'states.'+initialState);
|
|
||||||
if (!state) { break; }
|
|
||||||
enterStates.push(state);
|
|
||||||
matchedContexts.push(undefined);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (enterStates.length > 0) {
|
|
||||||
if (enterStates[0] !== exitStates[0]) { break; }
|
|
||||||
|
|
||||||
if (enterStates.length === matchedContexts.length) {
|
|
||||||
if (this.getStateMeta(enterStates[0], 'context') !== matchedContexts[0]) { break; }
|
|
||||||
matchedContexts.shift();
|
|
||||||
}
|
|
||||||
|
|
||||||
resolveState = enterStates.shift();
|
|
||||||
exitStates.shift();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.enterState(exitStates, enterStates, enterStates[enterStates.length-1] || resolveState);
|
|
||||||
this.triggerSetupContext(enterStates, matchedContexts);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
triggerSetupContext: function(enterStates, contexts) {
|
triggerSetupContext: function(transitions) {
|
||||||
var offset = enterStates.length - contexts.length;
|
var contexts = transitions.contexts,
|
||||||
|
offset = transitions.enterStates.length - contexts.length,
|
||||||
|
enterStates = transitions.enterStates,
|
||||||
|
transitionEvent = get(this, 'transitionEvent');
|
||||||
|
|
||||||
Ember.assert("More contexts provided than states", offset >= 0);
|
Ember.assert("More contexts provided than states", offset >= 0);
|
||||||
|
|
||||||
arrayForEach.call(enterStates, function(state, idx) {
|
arrayForEach.call(enterStates, function(state, idx) {
|
||||||
state.trigger(get(this, 'transitionEvent'), this, contexts[idx-offset]);
|
state.trigger(transitionEvent, this, contexts[idx-offset]);
|
||||||
}, this);
|
}, this);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -17460,21 +17674,20 @@ Ember.StateManager = Ember.State.extend(
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
enterState: function(exitStates, enterStates, state) {
|
enterState: function(transition) {
|
||||||
var log = this.enableLogging,
|
var log = this.enableLogging;
|
||||||
stateManager = this;
|
|
||||||
|
|
||||||
exitStates = exitStates.slice(0).reverse();
|
var exitStates = transition.exitStates.slice(0).reverse();
|
||||||
arrayForEach.call(exitStates, function(state) {
|
arrayForEach.call(exitStates, function(state) {
|
||||||
state.trigger('exit', stateManager);
|
state.trigger('exit', this);
|
||||||
});
|
}, this);
|
||||||
|
|
||||||
arrayForEach.call(enterStates, function(state) {
|
arrayForEach.call(transition.enterStates, function(state) {
|
||||||
if (log) { Ember.Logger.log("STATEMANAGER: Entering " + get(state, 'path')); }
|
if (log) { Ember.Logger.log("STATEMANAGER: Entering " + get(state, 'path')); }
|
||||||
state.trigger('enter', stateManager);
|
state.trigger('enter', this);
|
||||||
});
|
}, this);
|
||||||
|
|
||||||
set(this, 'currentState', state);
|
set(this, 'currentState', transition.finalState);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -18063,9 +18276,9 @@ var get = Ember.get, set = Ember.set;
|
||||||
|
|
||||||
## Adding Routes to a Router
|
## Adding Routes to a Router
|
||||||
The `initialState` property of Ember.Router instances is named `root`. The state stored in this
|
The `initialState` property of Ember.Router instances is named `root`. The state stored in this
|
||||||
property should be a subclass of Ember.Route. The `root` route should itself have states that are
|
property must be a subclass of Ember.Route. The `root` route acts as the container for the
|
||||||
also subclasses of Ember.Route and have `route` properties describing the URL pattern you would
|
set of routable states but is not routable itself. It should have states that are also subclasses
|
||||||
like to detect.
|
of Ember.Route which each have a `route` property describing the URL pattern you would like to detect.
|
||||||
|
|
||||||
App = Ember.Application.create({
|
App = Ember.Application.create({
|
||||||
Router: Ember.Router.extend({
|
Router: Ember.Router.extend({
|
||||||
|
@ -18107,6 +18320,46 @@ var get = Ember.get, set = Ember.set;
|
||||||
'root.bRoute' ('/alphabeta') and transition the router first to the state named 'root' and
|
'root.bRoute' ('/alphabeta') and transition the router first to the state named 'root' and
|
||||||
then to the substate 'bRoute'.
|
then to the substate 'bRoute'.
|
||||||
|
|
||||||
|
## Adding Nested Routes to a Router
|
||||||
|
Routes can contain nested subroutes each with their own `route` property describing the nested
|
||||||
|
portion of the URL they would like to detect and handle. Router, like all instances of StateManager,
|
||||||
|
cannot call `transitonTo` with an intermediary state. To avoid transitioning the Router into an
|
||||||
|
intermediary state when detecting URLs, a Route with nested routes must define both a base `route`
|
||||||
|
property for itself and a child Route with a `route` property of `'/'` which will be transitioned
|
||||||
|
to when the base route is detected in the URL:
|
||||||
|
|
||||||
|
Given the following application code:
|
||||||
|
|
||||||
|
App = Ember.Application.create({
|
||||||
|
Router: Ember.Router.extend({
|
||||||
|
root: Ember.Route.extend({
|
||||||
|
aRoute: Ember.Route.extend({
|
||||||
|
route: '/theBaseRouteForThisSet',
|
||||||
|
|
||||||
|
indexSubRoute: Ember.Route.extend({
|
||||||
|
route: '/',
|
||||||
|
}),
|
||||||
|
|
||||||
|
subRouteOne: Ember.Route.extend({
|
||||||
|
route: '/subroute1
|
||||||
|
}),
|
||||||
|
|
||||||
|
subRouteTwo: Ember.Route.extend({
|
||||||
|
route: '/subRoute2'
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
});
|
||||||
|
App.initialize();
|
||||||
|
|
||||||
|
When the application is loaded at '/theBaseRouteForThisSet' the Router will transition to the route
|
||||||
|
at path 'root.aRoute' and then transition to state 'indexSubRoute'.
|
||||||
|
|
||||||
|
When the application is loaded at '/theBaseRouteForThisSet/subRoute1' the Router will transition to
|
||||||
|
the route at path 'root.aRoute' and then transition to state 'subRouteOne'.
|
||||||
|
|
||||||
## Route Transition Events
|
## Route Transition Events
|
||||||
Transitioning between Ember.Route instances (including the transition into the detected
|
Transitioning between Ember.Route instances (including the transition into the detected
|
||||||
route when loading the application) triggers the same transition events as state transitions for
|
route when loading the application) triggers the same transition events as state transitions for
|
||||||
|
@ -18337,7 +18590,7 @@ var get = Ember.get, set = Ember.set;
|
||||||
|
|
||||||
<script type="text/x-handlebars" data-template-name="photos">
|
<script type="text/x-handlebars" data-template-name="photos">
|
||||||
{{#each photo in controller}}
|
{{#each photo in controller}}
|
||||||
<h1><a {{action showPhoto context="photo"}}>{{title}}</a></h1>
|
<h1><a {{action showPhoto photo}}>{{title}}</a></h1>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -21004,27 +21257,39 @@ Ember.Handlebars.registerHelper('template', function(name, options) {
|
||||||
|
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
var EmberHandlebars = Ember.Handlebars, getPath = EmberHandlebars.getPath, get = Ember.get;
|
var EmberHandlebars = Ember.Handlebars,
|
||||||
|
getPath = EmberHandlebars.getPath,
|
||||||
|
get = Ember.get,
|
||||||
|
a_slice = Array.prototype.slice;
|
||||||
|
|
||||||
var ActionHelper = EmberHandlebars.ActionHelper = {
|
var ActionHelper = EmberHandlebars.ActionHelper = {
|
||||||
registeredActions: {}
|
registeredActions: {}
|
||||||
};
|
};
|
||||||
|
|
||||||
ActionHelper.registerAction = function(actionName, eventName, target, view, context, link) {
|
ActionHelper.registerAction = function(actionName, options) {
|
||||||
var actionId = (++Ember.$.uuid).toString();
|
var actionId = (++Ember.$.uuid).toString();
|
||||||
|
|
||||||
ActionHelper.registeredActions[actionId] = {
|
ActionHelper.registeredActions[actionId] = {
|
||||||
eventName: eventName,
|
eventName: options.eventName,
|
||||||
handler: function(event) {
|
handler: function(event) {
|
||||||
if (link && (event.button !== 0 || event.shiftKey || event.metaKey || event.altKey || event.ctrlKey)) {
|
var modifier = event.shiftKey || event.metaKey || event.altKey || event.ctrlKey,
|
||||||
|
secondaryClick = event.which > 1, // IE9 may return undefined
|
||||||
|
nonStandard = modifier || secondaryClick;
|
||||||
|
|
||||||
|
if (options.link && nonStandard) {
|
||||||
// Allow the browser to handle special link clicks normally
|
// Allow the browser to handle special link clicks normally
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
event.view = view;
|
event.view = options.view;
|
||||||
event.context = context;
|
|
||||||
|
if (options.hasOwnProperty('context')) {
|
||||||
|
event.context = options.context;
|
||||||
|
}
|
||||||
|
|
||||||
|
var target = options.target;
|
||||||
|
|
||||||
// Check for StateManager (or compatible object)
|
// Check for StateManager (or compatible object)
|
||||||
if (target.isState && typeof target.send === 'function') {
|
if (target.isState && typeof target.send === 'function') {
|
||||||
|
@ -21036,7 +21301,7 @@ ActionHelper.registerAction = function(actionName, eventName, target, view, cont
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
view.on('willRerender', function() {
|
options.view.on('willRerender', function() {
|
||||||
delete ActionHelper.registeredActions[actionId];
|
delete ActionHelper.registeredActions[actionId];
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -21045,14 +21310,16 @@ ActionHelper.registerAction = function(actionName, eventName, target, view, cont
|
||||||
|
|
||||||
/**
|
/**
|
||||||
The `{{action}}` helper registers an HTML element within a template for
|
The `{{action}}` helper registers an HTML element within a template for
|
||||||
DOM event handling. User interaction with that element will call the method
|
DOM event handling and forwards that interaction to the Application's router,
|
||||||
on the template's associated `Ember.View` instance that has the same name
|
the template's `Ember.View` instance, or supplied `target` option (see 'Specifiying a Target').
|
||||||
as the first provided argument to `{{action}}`:
|
|
||||||
|
User interaction with that element will invoke the supplied action name on
|
||||||
|
the appropriate target.
|
||||||
|
|
||||||
Given the following Handlebars template on the page
|
Given the following Handlebars template on the page
|
||||||
|
|
||||||
<script type="text/x-handlebars" data-template-name='a-template'>
|
<script type="text/x-handlebars" data-template-name='a-template'>
|
||||||
<div {{action "anActionName"}}>
|
<div {{action anActionName}}>
|
||||||
click me
|
click me
|
||||||
</div>
|
</div>
|
||||||
</script>
|
</script>
|
||||||
|
@ -21088,15 +21355,51 @@ ActionHelper.registerAction = function(actionName, eventName, target, view, cont
|
||||||
handler.
|
handler.
|
||||||
|
|
||||||
If you need the default handler to trigger you should either register your
|
If you need the default handler to trigger you should either register your
|
||||||
own event handler, or use event methods on your view class.
|
own event handler, or use event methods on your view class. See Ember.View
|
||||||
|
'Responding to Browser Events' for more information.
|
||||||
|
|
||||||
### Specifying an Action Target
|
### Specifying DOM event type
|
||||||
|
|
||||||
A `target` option can be provided to change which object will receive the
|
By default the `{{action}}` helper registers for DOM `click` events. You can
|
||||||
method call. This option must be a string representing a path to an object:
|
supply an `on` option to the helper to specify a different DOM event name:
|
||||||
|
|
||||||
<script type="text/x-handlebars" data-template-name='a-template'>
|
<script type="text/x-handlebars" data-template-name='a-template'>
|
||||||
<div {{action "anActionName" target="MyApplication.someObject"}}>
|
<div {{action anActionName on="doubleClick"}}>
|
||||||
|
click me
|
||||||
|
</div>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
See Ember.View 'Responding to Browser Events' for a list of
|
||||||
|
acceptable DOM event names.
|
||||||
|
|
||||||
|
Because `{{action}}` depends on Ember's event dispatch system it will only
|
||||||
|
function if an `Ember.EventDispatcher` instance is available. An
|
||||||
|
`Ember.EventDispatcher` instance will be created when a new
|
||||||
|
`Ember.Application` is created. Having an instance of `Ember.Application`
|
||||||
|
will satisfy this requirement.
|
||||||
|
|
||||||
|
|
||||||
|
### Specifying a Target
|
||||||
|
There are several possible target objects for `{{action}}` helpers:
|
||||||
|
|
||||||
|
In a typical `Ember.Router`-backed Application where views are managed
|
||||||
|
through use of the `{{outlet}}` helper, actions will be forwarded to the
|
||||||
|
current state of the Applications's Router. See Ember.Router 'Responding
|
||||||
|
to User-initiated Events' for more information.
|
||||||
|
|
||||||
|
If you manaully set the `target` property on the controller of a template's
|
||||||
|
`Ember.View` instance, the specifed `controller.target` will become the target
|
||||||
|
for any actions. Likely custom values for a controller's `target` are the
|
||||||
|
controller itself or a StateManager other than the Application's Router.
|
||||||
|
|
||||||
|
If the templates's view lacks a controller property the view itself is the target.
|
||||||
|
|
||||||
|
Finally, a `target` option can be provided to the helper to change which object
|
||||||
|
will receive the method call. This option must be a string representing a
|
||||||
|
path to an object:
|
||||||
|
|
||||||
|
<script type="text/x-handlebars" data-template-name='a-template'>
|
||||||
|
<div {{action anActionName target="MyApplication.someObject"}}>
|
||||||
click me
|
click me
|
||||||
</div>
|
</div>
|
||||||
</script>
|
</script>
|
||||||
|
@ -21110,7 +21413,7 @@ ActionHelper.registerAction = function(actionName, eventName, target, view, cont
|
||||||
a target:
|
a target:
|
||||||
|
|
||||||
<script type="text/x-handlebars" data-template-name='a-template'>
|
<script type="text/x-handlebars" data-template-name='a-template'>
|
||||||
<div {{action "anActionName" target="parentView"}}>
|
<div {{action anActionName target="parentView"}}>
|
||||||
click me
|
click me
|
||||||
</div>
|
</div>
|
||||||
</script>
|
</script>
|
||||||
|
@ -21127,7 +21430,7 @@ ActionHelper.registerAction = function(actionName, eventName, target, view, cont
|
||||||
action name an error will be thrown.
|
action name an error will be thrown.
|
||||||
|
|
||||||
<script type="text/x-handlebars" data-template-name='a-template'>
|
<script type="text/x-handlebars" data-template-name='a-template'>
|
||||||
<div {{action "aMethodNameThatIsMissing"}}>
|
<div {{action aMethodNameThatIsMissing}}>
|
||||||
click me
|
click me
|
||||||
</div>
|
</div>
|
||||||
</script>
|
</script>
|
||||||
|
@ -21146,34 +21449,15 @@ ActionHelper.registerAction = function(actionName, eventName, target, view, cont
|
||||||
Will throw `Uncaught TypeError: Cannot call method 'call' of undefined` when
|
Will throw `Uncaught TypeError: Cannot call method 'call' of undefined` when
|
||||||
"click me" is clicked.
|
"click me" is clicked.
|
||||||
|
|
||||||
### Specifying DOM event type
|
|
||||||
|
|
||||||
By default the `{{action}}` helper registers for DOM `click` events. You can
|
|
||||||
supply an `on` option to the helper to specify a different DOM event name:
|
|
||||||
|
|
||||||
<script type="text/x-handlebars" data-template-name='a-template'>
|
|
||||||
<div {{action "aMethodNameThatIsMissing" on="doubleClick"}}>
|
|
||||||
click me
|
|
||||||
</div>
|
|
||||||
</script>
|
|
||||||
|
|
||||||
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 an `Ember.EventDispatcher` instance is available. An
|
|
||||||
`Ember.EventDispatcher` instance will be created when a new
|
|
||||||
`Ember.Application` is created. Having an instance of `Ember.Application`
|
|
||||||
will satisfy this requirement.
|
|
||||||
|
|
||||||
### Specifying a context
|
### Specifying a context
|
||||||
|
|
||||||
By default the `{{action}}` helper passes the current Handlebars context
|
By default the `{{action}}` helper passes the current Handlebars context
|
||||||
along in the `jQuery.Event` object. You may specify an alternative object to
|
along in the `jQuery.Event` object. You may specify an alternate object to
|
||||||
pass as the context by providing a property path:
|
pass as the context by providing a property path:
|
||||||
|
|
||||||
<script type="text/x-handlebars" data-template-name='a-template'>
|
<script type="text/x-handlebars" data-template-name='a-template'>
|
||||||
{{#each person in people}}
|
{{#each person in people}}
|
||||||
<div {{action "edit" context="person"}}>
|
<div {{action edit person}}>
|
||||||
click me
|
click me
|
||||||
</div>
|
</div>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
|
@ -21181,15 +21465,23 @@ ActionHelper.registerAction = function(actionName, eventName, target, view, cont
|
||||||
|
|
||||||
@name Handlebars.helpers.action
|
@name Handlebars.helpers.action
|
||||||
@param {String} actionName
|
@param {String} actionName
|
||||||
|
@param {Object...} contexts
|
||||||
@param {Hash} options
|
@param {Hash} options
|
||||||
*/
|
*/
|
||||||
EmberHandlebars.registerHelper('action', function(actionName, options) {
|
EmberHandlebars.registerHelper('action', function(actionName) {
|
||||||
|
var options = arguments[arguments.length - 1],
|
||||||
|
contexts = a_slice.call(arguments, 1, -1);
|
||||||
|
|
||||||
var hash = options.hash,
|
var hash = options.hash,
|
||||||
eventName = hash.on || "click",
|
|
||||||
view = options.data.view,
|
view = options.data.view,
|
||||||
target, context, controller, link;
|
target, context, controller, link;
|
||||||
|
|
||||||
view = get(view, 'concreteView');
|
// create a hash to pass along to registerAction
|
||||||
|
var action = {
|
||||||
|
eventName: hash.on || "click"
|
||||||
|
};
|
||||||
|
|
||||||
|
action.view = view = get(view, 'concreteView');
|
||||||
|
|
||||||
if (hash.target) {
|
if (hash.target) {
|
||||||
target = getPath(this, hash.target, options);
|
target = getPath(this, hash.target, options);
|
||||||
|
@ -21197,19 +21489,22 @@ EmberHandlebars.registerHelper('action', function(actionName, options) {
|
||||||
target = get(controller, 'target');
|
target = get(controller, 'target');
|
||||||
}
|
}
|
||||||
|
|
||||||
target = target || view;
|
action.target = target = target || view;
|
||||||
|
|
||||||
context = hash.context ? getPath(this, hash.context, options) : options.contexts[0];
|
// TODO: Support multiple contexts
|
||||||
|
if (contexts.length) {
|
||||||
|
action.context = context = getPath(this, contexts[0], options);
|
||||||
|
}
|
||||||
|
|
||||||
var output = [], url;
|
var output = [], url;
|
||||||
|
|
||||||
if (hash.href && target.urlForEvent) {
|
if (hash.href && target.urlForEvent) {
|
||||||
url = target.urlForEvent(actionName, context);
|
url = target.urlForEvent(actionName, context);
|
||||||
output.push('href="' + url + '"');
|
output.push('href="' + url + '"');
|
||||||
link = true;
|
action.link = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
var actionId = ActionHelper.registerAction(actionName, eventName, target, view, context, link);
|
var actionId = ActionHelper.registerAction(actionName, action);
|
||||||
output.push('data-ember-action="' + actionId + '"');
|
output.push('data-ember-action="' + actionId + '"');
|
||||||
|
|
||||||
return new EmberHandlebars.SafeString(output.join(" "));
|
return new EmberHandlebars.SafeString(output.join(" "));
|
||||||
|
@ -22229,8 +22524,8 @@ Ember.onLoad('application', bootstrap);
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
|
||||||
// Version: v0.9.8.1-658-gd4a9e46
|
// Version: v0.9.8.1-672-gd7e24ac
|
||||||
// Last commit: d4a9e46 (2012-07-21 19:16:48 -0700)
|
// Last commit: d7e24ac (2012-07-26 09:35:30 -0700)
|
||||||
|
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
@ -22492,7 +22787,7 @@ DS.ManyArrayStateManager = Ember.StateManager.extend({
|
||||||
|
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
var get = Ember.get, set = Ember.set, set = Ember.set;
|
var get = Ember.get, set = Ember.set;
|
||||||
|
|
||||||
DS.ManyArray = DS.RecordArray.extend({
|
DS.ManyArray = DS.RecordArray.extend({
|
||||||
init: function() {
|
init: function() {
|
||||||
|
@ -25987,31 +26282,35 @@ DS.FixtureAdapter = DS.Adapter.extend({
|
||||||
find: function(store, type, id) {
|
find: function(store, type, id) {
|
||||||
var fixtures = this.fixturesForType(type);
|
var fixtures = this.fixturesForType(type);
|
||||||
|
|
||||||
|
Ember.assert("Unable to find fixtures for model type "+type.toString(), !!fixtures);
|
||||||
|
|
||||||
if (fixtures) {
|
if (fixtures) {
|
||||||
fixtures = fixtures.findProperty('id', id);
|
fixtures = fixtures.findProperty('id', id);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ember.assert("Unable to find fixtures for model type "+type.toString(), !!fixtures);
|
if (fixtures) {
|
||||||
|
|
||||||
this.simulateRemoteCall(function() {
|
this.simulateRemoteCall(function() {
|
||||||
store.load(type, fixtures);
|
store.load(type, fixtures);
|
||||||
}, store, type);
|
}, store, type);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
findMany: function(store, type, ids) {
|
findMany: function(store, type, ids) {
|
||||||
var fixtures = this.fixturesForType(type);
|
var fixtures = this.fixturesForType(type);
|
||||||
|
|
||||||
|
Ember.assert("Unable to find fixtures for model type "+type.toString(), !!fixtures);
|
||||||
|
|
||||||
if (fixtures) {
|
if (fixtures) {
|
||||||
fixtures = fixtures.filter(function(item) {
|
fixtures = fixtures.filter(function(item) {
|
||||||
return ids.indexOf(item.id) !== -1;
|
return ids.indexOf(item.id) !== -1;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Ember.assert("Unable to find fixtures for model type "+type.toString(), !!fixtures);
|
if (fixtures) {
|
||||||
|
|
||||||
this.simulateRemoteCall(function() {
|
this.simulateRemoteCall(function() {
|
||||||
store.loadMany(type, fixtures);
|
store.loadMany(type, fixtures);
|
||||||
}, store, type);
|
}, store, type);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
findAll: function(store, type) {
|
findAll: function(store, type) {
|
||||||
|
@ -26027,13 +26326,15 @@ DS.FixtureAdapter = DS.Adapter.extend({
|
||||||
findQuery: function(store, type, query, array) {
|
findQuery: function(store, type, query, array) {
|
||||||
var fixtures = this.fixturesForType(type);
|
var fixtures = this.fixturesForType(type);
|
||||||
|
|
||||||
fixtures = this.queryFixtures(fixtures, query);
|
|
||||||
|
|
||||||
Ember.assert("Unable to find fixtures for model type "+type.toString(), !!fixtures);
|
Ember.assert("Unable to find fixtures for model type "+type.toString(), !!fixtures);
|
||||||
|
|
||||||
|
fixtures = this.queryFixtures(fixtures, query);
|
||||||
|
|
||||||
|
if (fixtures) {
|
||||||
this.simulateRemoteCall(function() {
|
this.simulateRemoteCall(function() {
|
||||||
array.load(fixtures);
|
array.load(fixtures);
|
||||||
}, store, type);
|
}, store, type);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
createRecord: function(store, type, record) {
|
createRecord: function(store, type, record) {
|
||||||
|
@ -26274,7 +26575,9 @@ DS.RESTAdapter = DS.Adapter.extend({
|
||||||
data: query,
|
data: query,
|
||||||
success: function(json) {
|
success: function(json) {
|
||||||
this.sideload(store, type, json, plural);
|
this.sideload(store, type, json, plural);
|
||||||
|
setTimeout(function() {
|
||||||
recordArray.load(json[plural]);
|
recordArray.load(json[plural]);
|
||||||
|
}, 10);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue
Block a user