diff --git a/app/assets/javascripts/discourse/helpers/application_helpers.js b/app/assets/javascripts/discourse/helpers/application_helpers.js
index c3c3dfb1c70..ca48aa47bf8 100644
--- a/app/assets/javascripts/discourse/helpers/application_helpers.js
+++ b/app/assets/javascripts/discourse/helpers/application_helpers.js
@@ -6,16 +6,14 @@
@method breakUp
@for Handlebars
**/
-Handlebars.registerHelper('breakUp', function(property, options) {
+Ember.Handlebars.registerHelper('breakUp', function(property, options) {
var prop, result, tokens;
prop = Ember.Handlebars.get(this, property, options);
- if (!prop) {
- return "";
- }
+ if (!prop) return "";
+
tokens = prop.match(new RegExp(".{1,14}", 'g'));
- if (tokens.length === 1) {
- return prop;
- }
+ if (tokens.length === 1) return prop;
+
result = "";
tokens.each(function(token, index) {
result += token;
@@ -32,7 +30,7 @@ Handlebars.registerHelper('breakUp', function(property, options) {
@method shorten
@for Handlebars
**/
-Handlebars.registerHelper('shorten', function(property, options) {
+Ember.Handlebars.registerHelper('shorten', function(property, options) {
return Ember.Handlebars.get(this, property, options).truncate(35);
});
@@ -42,7 +40,7 @@ Handlebars.registerHelper('shorten', function(property, options) {
@method topicLink
@for Handlebars
**/
-Handlebars.registerHelper('topicLink', function(property, options) {
+Ember.Handlebars.registerHelper('topicLink', function(property, options) {
var title, topic;
topic = Ember.Handlebars.get(this, property, options);
title = topic.get('fancy_title') || topic.get('title');
@@ -55,9 +53,18 @@ Handlebars.registerHelper('topicLink', function(property, options) {
@method categoryLink
@for Handlebars
**/
-Handlebars.registerHelper('categoryLink', function(property, options) {
- var category;
- category = Ember.Handlebars.get(this, property, options);
+Ember.Handlebars.registerHelper('categoryLink', function(property, options) {
+ var category = Ember.Handlebars.get(this, property, options);
+ return new Handlebars.SafeString(Discourse.Utilities.categoryLink(category));
+});
+
+/**
+ Produces a bound link to a category
+
+ @method boundCategoryLink
+ @for Handlebars
+**/
+Ember.Handlebars.registerBoundHelper('boundCategoryLink', function(category) {
return new Handlebars.SafeString(Discourse.Utilities.categoryLink(category));
});
@@ -67,7 +74,7 @@ Handlebars.registerHelper('categoryLink', function(property, options) {
@method titledLinkTo
@for Handlebars
**/
-Handlebars.registerHelper('titledLinkTo', function(name, object) {
+Ember.Handlebars.registerHelper('titledLinkTo', function(name, object) {
var options;
options = [].slice.call(arguments, -1)[0];
if (options.hash.titleKey) {
@@ -86,7 +93,7 @@ Handlebars.registerHelper('titledLinkTo', function(name, object) {
@method shortenUrl
@for Handlebars
**/
-Handlebars.registerHelper('shortenUrl', function(property, options) {
+Ember.Handlebars.registerHelper('shortenUrl', function(property, options) {
var url;
url = Ember.Handlebars.get(this, property, options);
// Remove trailing slash if it's a top level URL
@@ -104,7 +111,7 @@ Handlebars.registerHelper('shortenUrl', function(property, options) {
@method lower
@for Handlebars
**/
-Handlebars.registerHelper('lower', function(property, options) {
+Ember.Handlebars.registerHelper('lower', function(property, options) {
var o;
o = Ember.Handlebars.get(this, property, options);
if (o && typeof o === 'string') {
@@ -120,7 +127,7 @@ Handlebars.registerHelper('lower', function(property, options) {
@method avatar
@for Handlebars
**/
-Handlebars.registerHelper('avatar', function(user, options) {
+Ember.Handlebars.registerHelper('avatar', function(user, options) {
if (typeof user === 'string') {
user = Ember.Handlebars.get(this, user, options);
@@ -152,7 +159,7 @@ Handlebars.registerHelper('avatar', function(user, options) {
@method unboundDate
@for Handlebars
**/
-Handlebars.registerHelper('unboundDate', function(property, options) {
+Ember.Handlebars.registerHelper('unboundDate', function(property, options) {
var dt;
dt = new Date(Ember.Handlebars.get(this, property, options));
return dt.format("{d} {Mon}, {yyyy} {hh}:{mm}");
@@ -164,7 +171,7 @@ Handlebars.registerHelper('unboundDate', function(property, options) {
@method editDate
@for Handlebars
**/
-Handlebars.registerHelper('editDate', function(property, options) {
+Ember.Handlebars.registerHelper('editDate', function(property, options) {
var dt, yesterday;
dt = Date.create(Ember.Handlebars.get(this, property, options));
yesterday = new Date() - (60 * 60 * 24 * 1000);
@@ -181,7 +188,7 @@ Handlebars.registerHelper('editDate', function(property, options) {
@method number
@for Handlebars
**/
-Handlebars.registerHelper('number', function(property, options) {
+Ember.Handlebars.registerHelper('number', function(property, options) {
var n, orig, title;
orig = parseInt(Ember.Handlebars.get(this, property, options), 10);
if (isNaN(orig)) {
@@ -207,7 +214,7 @@ Handlebars.registerHelper('number', function(property, options) {
@method date
@for Handlebars
**/
-Handlebars.registerHelper('date', function(property, options) {
+Ember.Handlebars.registerHelper('date', function(property, options) {
var displayDate, dt, fiveDaysAgo, fullReadable, humanized, leaveAgo, val;
if (property.hash) {
if (property.hash.leaveAgo) {
@@ -250,7 +257,7 @@ Handlebars.registerHelper('date', function(property, options) {
@method personalizedName
@for Handlebars
**/
-Handlebars.registerHelper('personalizedName', function(property, options) {
+Ember.Handlebars.registerHelper('personalizedName', function(property, options) {
var name, username;
name = Ember.Handlebars.get(this, property, options);
if (options.hash.usernamePath) {
diff --git a/app/assets/javascripts/discourse/templates/topic.js.handlebars b/app/assets/javascripts/discourse/templates/topic.js.handlebars
index 6d9e1cc47ee..7e10adc5e1e 100644
--- a/app/assets/javascripts/discourse/templates/topic.js.handlebars
+++ b/app/assets/javascripts/discourse/templates/topic.js.handlebars
@@ -25,7 +25,7 @@
{{i18n topic.loading}}
{{/if}}
{{/if}}
- {{#bind view.topic.category}}{{categoryLink this}}{{/bind}}
+ {{boundCategoryLink category}}
{{#if view.topic.can_edit}}
diff --git a/app/assets/javascripts/external/ember.js b/app/assets/javascripts/external/ember.js
index 87b273b78be..790d298094a 100644
--- a/app/assets/javascripts/external/ember.js
+++ b/app/assets/javascripts/external/ember.js
@@ -1,5 +1,5 @@
-// Version: v1.0.0-pre.2-756-gb26f1f0
-// Last commit: b26f1f0 (2013-02-26 09:03:26 -0800)
+// Version: v1.0.0-pre.2-790-ge26f105
+// Last commit: e26f105 (2013-03-04 09:58:40 -0800)
(function() {
@@ -150,8 +150,8 @@ Ember.deprecateFunc = function(message, func) {
})();
-// Version: v1.0.0-pre.2-756-gb26f1f0
-// Last commit: b26f1f0 (2013-02-26 09:03:26 -0800)
+// Version: v1.0.0-pre.2-790-ge26f105
+// Last commit: e26f105 (2013-03-04 09:58:40 -0800)
(function() {
@@ -4273,7 +4273,7 @@ var run = Ember.run;
/**
Begins a new RunLoop. Any deferred actions invoked after the begin will
be buffered until you invoke a matching call to `Ember.run.end()`. This is
- an lower-level way to use a RunLoop instead of using `Ember.run()`.
+ a lower-level way to use a RunLoop instead of using `Ember.run()`.
```javascript
Ember.run.begin();
@@ -4319,9 +4319,9 @@ Ember.run.end = function() {
@property queues
@type Array
- @default ['sync', 'actions', 'destroy', 'timers']
+ @default ['sync', 'actions', 'destroy']
*/
-Ember.run.queues = ['sync', 'actions', 'destroy', 'timers'];
+Ember.run.queues = ['sync', 'actions', 'destroy'];
/**
Adds the passed target/method and any optional arguments to the named
@@ -4334,19 +4334,19 @@ Ember.run.queues = ['sync', 'actions', 'destroy', 'timers'];
the `run.queues` property.
```javascript
- Ember.run.schedule('timers', this, function(){
- // this will be executed at the end of the RunLoop, when timers are run
- console.log("scheduled on timers queue");
+ Ember.run.schedule('sync', this, function(){
+ // this will be executed in the first RunLoop queue, when bindings are synced
+ console.log("scheduled on sync queue");
});
- Ember.run.schedule('sync', this, function(){
- // this will be executed at the end of the RunLoop, when bindings are synced
- console.log("scheduled on sync queue");
+ Ember.run.schedule('actions', this, function(){
+ // this will be executed in the 'actions' queue, after bindings have synced.
+ console.log("scheduled on actions queue");
});
// Note the functions will be run in order based on the run queues order. Output would be:
// scheduled on sync queue
- // scheduled on timers queue
+ // scheduled on actions queue
```
@method schedule
@@ -4372,7 +4372,7 @@ function autorun() {
// Used by global test teardown
Ember.run.hasScheduledTimers = function() {
- return !!(scheduledAutorun || scheduledLater || scheduledNext);
+ return !!(scheduledAutorun || scheduledLater);
};
// Used by global test teardown
@@ -4385,10 +4385,6 @@ Ember.run.cancelTimers = function () {
clearTimeout(scheduledLater);
scheduledLater = null;
}
- if (scheduledNext) {
- clearTimeout(scheduledNext);
- scheduledNext = null;
- }
timers = {};
};
@@ -4423,7 +4419,8 @@ Ember.run.autorun = function() {
bindings in the application to sync.
You should call this method anytime you need any changed state to propagate
- throughout the app immediately without repainting the UI.
+ throughout the app immediately without repainting the UI (which happens
+ in the later 'render' queue added by the `ember-views` package).
```javascript
Ember.run.sync();
@@ -4443,25 +4440,30 @@ Ember.run.sync = function() {
var timers = {}; // active timers...
-var scheduledLater;
+var scheduledLater, scheduledLaterExpires;
function invokeLaterTimers() {
scheduledLater = null;
- var now = (+ new Date()), earliest = -1;
- for (var key in timers) {
- if (!timers.hasOwnProperty(key)) { continue; }
- var timer = timers[key];
- if (timer && timer.expires) {
- if (now >= timer.expires) {
- delete timers[key];
- invoke(timer.target, timer.method, timer.args, 2);
- } else {
- if (earliest<0 || (timer.expires < earliest)) earliest=timer.expires;
+ run(function() {
+ var now = (+ new Date()), earliest = -1;
+ for (var key in timers) {
+ if (!timers.hasOwnProperty(key)) { continue; }
+ var timer = timers[key];
+ if (timer && timer.expires) {
+ if (now >= timer.expires) {
+ delete timers[key];
+ invoke(timer.target, timer.method, timer.args, 2);
+ } else {
+ if (earliest < 0 || (timer.expires < earliest)) { earliest = timer.expires; }
+ }
}
}
- }
- // schedule next timeout to fire...
- if (earliest > 0) { scheduledLater = setTimeout(invokeLaterTimers, earliest-(+ new Date())); }
+ // schedule next timeout to fire when the earliest timer expires
+ if (earliest > 0) {
+ scheduledLater = setTimeout(invokeLaterTimers, earliest - now);
+ scheduledLaterExpires = earliest;
+ }
+ });
}
/**
@@ -4509,7 +4511,19 @@ Ember.run.later = function(target, method) {
timer = { target: target, method: method, expires: expires, args: args };
guid = Ember.guidFor(timer);
timers[guid] = timer;
- run.once(timers, invokeLaterTimers);
+
+ if(scheduledLater && expires < scheduledLaterExpires) {
+ // Cancel later timer (then reschedule earlier timer below)
+ clearTimeout(scheduledLater);
+ scheduledLater = null;
+ }
+
+ if (!scheduledLater) {
+ // Schedule later timers to be run.
+ scheduledLater = setTimeout(invokeLaterTimers, wait);
+ scheduledLaterExpires = expires;
+ }
+
return guid;
};
@@ -4564,6 +4578,21 @@ function scheduleOnce(queue, target, method, args) {
// doFoo will only be executed once at the end of the RunLoop
});
```
+
+ Also note that passing an anonymous function to `Ember.run.once` will
+ not prevent additional calls with an identical anonymous function from
+ scheduling the items multiple times, e.g.:
+
+ ```javascript
+ function scheduleIt() {
+ Ember.run.once(myContext, function() { console.log("Closure"); });
+ }
+ scheduleIt();
+ scheduleIt();
+ // "Closure" will print twice, even though we're using `Ember.run.once`,
+ // because the function we pass to it is anonymous and won't match the
+ // previously scheduled operation.
+ ```
@method once
@param {Object} [target] target of method to invoke
@@ -4581,22 +4610,9 @@ Ember.run.scheduleOnce = function(queue, target, method, args) {
return scheduleOnce(queue, target, method, slice.call(arguments, 3));
};
-var scheduledNext;
-function invokeNextTimers() {
- scheduledNext = null;
- for(var key in timers) {
- if (!timers.hasOwnProperty(key)) { continue; }
- var timer = timers[key];
- if (timer.next) {
- delete timers[key];
- invoke(timer.target, timer.method, timer.args, 2);
- }
- }
-}
-
/**
Schedules an item to run after control has been returned to the system.
- This is often equivalent to calling `setTimeout(function() {}, 1)`.
+ This is equivalent to calling `Ember.run.later` with a wait time of 1ms.
```javascript
Ember.run.next(myContext, function(){
@@ -4612,20 +4628,10 @@ function invokeNextTimers() {
@param {Object} [args*] Optional arguments to pass to the timeout.
@return {Object} timer
*/
-Ember.run.next = function(target, method) {
- var guid,
- timer = {
- target: target,
- method: method,
- args: slice.call(arguments),
- next: true
- };
-
- guid = Ember.guidFor(timer);
- timers[guid] = timer;
-
- if (!scheduledNext) { scheduledNext = setTimeout(invokeNextTimers, 1); }
- return guid;
+Ember.run.next = function() {
+ var args = slice.call(arguments);
+ args.push(1); // 1 millisecond wait
+ return run.later.apply(this, args);
};
/**
@@ -5499,6 +5505,38 @@ Mixin.finishPartial = finishPartial;
Ember.anyUnprocessedMixins = false;
/**
+ Creates an instance of a class. Accepts either no arguments, or an object
+ containing values to initialize the newly instantiated object with.
+
+ ```javascript
+ App.Person = Ember.Object.extend({
+ helloWorld: function() {
+ alert("Hi, my name is " + this.get('name'));
+ }
+ });
+
+ var tom = App.Person.create({
+ name: 'Tom Dale'
+ });
+
+ tom.helloWorld(); // alerts "Hi, my name is Tom Dale".
+ ```
+
+ `create` will call the `init` function if defined during
+ `Ember.AnyObject.extend`
+
+ If no arguments are passed to `create`, it will not set values to the new
+ instance during initialization:
+
+ ```javascript
+ var noName = App.Person.create();
+ noName.helloWorld(); // alerts undefined
+ ```
+
+ NOTE: For performance reasons, you cannot declare methods or computed
+ properties during `create`. You should instead declare methods and computed
+ properties when using `extend`.
+
@method create
@static
@param arguments*
@@ -6924,10 +6962,11 @@ Ember.String = {
*/
dasherize: function(str) {
var cache = STRING_DASHERIZE_CACHE,
- ret = cache[str];
+ hit = cache.hasOwnProperty(str),
+ ret;
- if (ret) {
- return ret;
+ if (hit) {
+ return cache[str];
} else {
ret = Ember.String.decamelize(str).replace(STRING_DASHERIZE_REGEXP,'-');
cache[str] = ret;
@@ -6937,7 +6976,7 @@ Ember.String = {
},
/**
- Returns the lowerCaseCamel form of a string.
+ Returns the lowerCamelCase form of a string.
```javascript
'innerHTML'.camelize(); // 'innerHTML'
@@ -7008,10 +7047,10 @@ Ember.String = {
/**
Returns the Capitalized form of a string
- 'innerHTML'.capitalize() => 'InnerHTML'
- 'action_name'.capitalize() => 'Action_name'
- 'css-class-name'.capitalize() => 'Css-class-name'
- 'my favorite items'.capitalize() => 'My favorite items'
+ 'innerHTML'.capitalize() // 'InnerHTML'
+ 'action_name'.capitalize() // 'Action_name'
+ 'css-class-name'.capitalize() // 'Css-class-name'
+ 'my favorite items'.capitalize() // 'My favorite items'
@method capitalize
@param {String} str
@@ -7408,10 +7447,10 @@ Ember.Enumerable = Ember.Mixin.create(
```javascript
var arr = ["a", "b", "c"];
- arr.firstObject(); // "a"
+ arr.get('firstObject'); // "a"
var arr = [];
- arr.firstObject(); // undefined
+ arr.get('firstObject'); // undefined
```
@property firstObject
@@ -7434,10 +7473,10 @@ Ember.Enumerable = Ember.Mixin.create(
```javascript
var arr = ["a", "b", "c"];
- arr.lastObject(); // "c"
+ arr.get('lastObject'); // "c"
var arr = [];
- arr.lastObject(); // undefined
+ arr.get('lastObject'); // undefined
```
@property lastObject
@@ -7570,7 +7609,7 @@ Ember.Enumerable = Ember.Mixin.create(
@return {Array} The mapped array.
*/
map: function(callback, target) {
- var ret = [];
+ var ret = Ember.A([]);
this.forEach(function(x, idx, i) {
ret[idx] = callback.call(target, x, idx,i);
});
@@ -7620,7 +7659,7 @@ Ember.Enumerable = Ember.Mixin.create(
@return {Array} A filtered array.
*/
filter: function(callback, target) {
- var ret = [];
+ var ret = Ember.A([]);
this.forEach(function(x, idx, i) {
if (callback.call(target, x, idx, i)) ret.push(x);
});
@@ -7909,7 +7948,7 @@ Ember.Enumerable = Ember.Mixin.create(
@return {Array} return values from calling invoke.
*/
invoke: function(methodName) {
- var args, ret = [];
+ var args, ret = Ember.A([]);
if (arguments.length>1) args = a_slice.call(arguments, 1);
this.forEach(function(x, idx) {
@@ -7930,7 +7969,7 @@ Ember.Enumerable = Ember.Mixin.create(
@return {Array} the enumerable as an array.
*/
toArray: function() {
- var ret = [];
+ var ret = Ember.A([]);
this.forEach(function(o, idx) { ret[idx] = o; });
return ret ;
},
@@ -7964,7 +8003,7 @@ Ember.Enumerable = Ember.Mixin.create(
*/
without: function(value) {
if (!this.contains(value)) return this; // nothing to do
- var ret = [] ;
+ var ret = Ember.A([]);
this.forEach(function(k) {
if (k !== value) ret[ret.length] = k;
}) ;
@@ -7984,7 +8023,7 @@ Ember.Enumerable = Ember.Mixin.create(
@return {Ember.Enumerable}
*/
uniq: function() {
- var ret = [];
+ var ret = Ember.A([]);
this.forEach(function(k){
if (a_indexOf(ret, k)<0) ret.push(k);
});
@@ -8016,7 +8055,7 @@ Ember.Enumerable = Ember.Mixin.create(
@method addEnumerableObserver
@param {Object} target
- @param {Hash} opts
+ @param {Hash} [opts]
*/
addEnumerableObserver: function(target, opts) {
var willChange = (opts && opts.willChange) || 'enumerableWillChange',
@@ -8152,7 +8191,7 @@ Ember.Enumerable = Ember.Mixin.create(
// HELPERS
//
-var get = Ember.get, set = Ember.set, meta = Ember.meta, map = Ember.EnumerableUtils.map, cacheFor = Ember.cacheFor;
+var get = Ember.get, set = Ember.set, map = Ember.EnumerableUtils.map, cacheFor = Ember.cacheFor;
function none(obj) { return obj===null || obj===undefined; }
@@ -8294,12 +8333,12 @@ Ember.Array = Ember.Mixin.create(Ember.Enumerable, /** @scope Ember.Array.protot
```
@method slice
- @param beginIndex {Integer} (Optional) index to begin slicing from.
- @param endIndex {Integer} (Optional) index to end the slice at.
+ @param {Integer} beginIndex (Optional) index to begin slicing from.
+ @param {Integer} endIndex (Optional) index to end the slice at.
@return {Array} New array with specified slice
*/
slice: function(beginIndex, endIndex) {
- var ret = [];
+ var ret = Ember.A([]);
var length = get(this, 'length') ;
if (none(beginIndex)) beginIndex = 0 ;
if (none(endIndex) || (endIndex > length)) endIndex = length ;
@@ -9201,7 +9240,7 @@ Ember.MutableArray = Ember.Mixin.create(Ember.Array, Ember.MutableEnumerable,
@submodule ember-runtime
*/
-var get = Ember.get, set = Ember.set, defineProperty = Ember.defineProperty;
+var get = Ember.get, set = Ember.set;
/**
## Overview
@@ -10147,6 +10186,37 @@ CoreObject.PrototypeMixin = Mixin.create({
isInstance: true,
+ /**
+ An overridable method called when objects are instantiated. By default,
+ does nothing unless it is overridden during class definition.
+
+ Example:
+
+ ```javascript
+ App.Person = Ember.Object.extend({
+ init: function() {
+ this._super();
+ alert('Name is ' + this.get('name'));
+ }
+ });
+
+ var steve = App.Person.create({
+ name: "Steve"
+ });
+
+ // alerts 'Name is Steve'.
+ ```
+
+ NOTE: If you do override `init` for a framework class like `Ember.View` or
+ `Ember.ArrayController`, be sure to call `this._super()` in your
+ `init` declaration! If you don't, Ember may not have an opportunity to
+ do important setup work, and you'll see strange behavior in your
+ application.
+
+ ```
+
+ @method init
+ */
init: function() {},
/**
@@ -10297,7 +10367,7 @@ CoreObject.PrototypeMixin = Mixin.create({
}
});
teacher = App.Teacher.create()
- teacher.toString(); // #=> ""
+ teacher.toString(); //=> ""
@method toString
@return {String} string representation
@@ -14825,7 +14895,6 @@ Ember.View = Ember.CoreView.extend(
// JavaScript property changes.
var observer = function() {
elem = this.$();
- if (!elem) { return; }
attributeValue = get(this, property);
@@ -15693,10 +15762,18 @@ Ember.View = Ember.CoreView.extend(
},
registerObserver: function(root, path, target, observer) {
- Ember.addObserver(root, path, target, observer);
+ if (!observer && 'function' === typeof target) {
+ observer = target;
+ target = null;
+ }
+ var view = this,
+ stateCheckedObserver = function(){
+ view.currentState.invokeObserver(this, observer);
+ };
+ Ember.addObserver(root, path, target, stateCheckedObserver);
this.one('willClearRender', function() {
- Ember.removeObserver(root, path, target, observer);
+ Ember.removeObserver(root, path, target, stateCheckedObserver);
});
}
@@ -15974,7 +16051,8 @@ Ember.View.states._default = {
return false;
},
- rerender: Ember.K
+ rerender: Ember.K,
+ invokeObserver: Ember.K
};
})();
@@ -16095,6 +16173,10 @@ Ember.merge(inBuffer, {
}
return value;
+ },
+
+ invokeObserver: function(target, observer) {
+ observer.call(target);
}
});
@@ -16182,6 +16264,10 @@ Ember.merge(hasElement, {
} else {
return true; // continue event propagation
}
+ },
+
+ invokeObserver: function(target, observer) {
+ observer.call(target);
}
});
@@ -23862,10 +23948,10 @@ Ember.onLoad('Ember.Handlebars', function(Handlebars) {
The default target for `{{action}}`s in the rendered template is the
named controller.
- @method action
+ @method render
@for Ember.Handlebars.helpers
- @param {String} actionName
- @param {Object?} model
+ @param {String} name
+ @param {Object?} contextString
@param {Hash} options
*/
Ember.Handlebars.registerHelper('render', function(name, contextString, options) {
@@ -24668,6 +24754,7 @@ Ember.HistoryLocation = Ember.Object.extend({
if (this.getState() && this.getState().path !== path) {
popstateReady = true;
+ console.log('pushin');
this.pushState(path);
}
},
@@ -24698,7 +24785,7 @@ Ember.HistoryLocation = Ember.Object.extend({
@method getState
*/
getState: function() {
- return get(this, 'history').state;
+ return window.history.state;
},
/**
@@ -25141,6 +25228,7 @@ var Application = Ember.Application = Ember.Namespace.extend({
}
if ( Ember.LOG_VERSION ) {
+ Ember.LOG_VERSION = false; // we only need to see this once per Application#init
Ember.debug('-------------------------------');
Ember.debug('Ember.VERSION : ' + Ember.VERSION);
Ember.debug('Handlebars.VERSION : ' + Ember.Handlebars.VERSION);
@@ -26947,8 +27035,8 @@ Ember States
})();
-// Version: v1.0.0-pre.2-756-gb26f1f0
-// Last commit: b26f1f0 (2013-02-26 09:03:26 -0800)
+// Version: v1.0.0-pre.2-790-ge26f105
+// Last commit: e26f105 (2013-03-04 09:58:40 -0800)
(function() {
diff --git a/app/assets/javascripts/external_production/ember.js b/app/assets/javascripts/external_production/ember.js
index 14f1f8e4330..b6f7847f8e1 100644
--- a/app/assets/javascripts/external_production/ember.js
+++ b/app/assets/javascripts/external_production/ember.js
@@ -4113,7 +4113,7 @@ var run = Ember.run;
/**
Begins a new RunLoop. Any deferred actions invoked after the begin will
be buffered until you invoke a matching call to `Ember.run.end()`. This is
- an lower-level way to use a RunLoop instead of using `Ember.run()`.
+ a lower-level way to use a RunLoop instead of using `Ember.run()`.
```javascript
Ember.run.begin();
@@ -4159,9 +4159,9 @@ Ember.run.end = function() {
@property queues
@type Array
- @default ['sync', 'actions', 'destroy', 'timers']
+ @default ['sync', 'actions', 'destroy']
*/
-Ember.run.queues = ['sync', 'actions', 'destroy', 'timers'];
+Ember.run.queues = ['sync', 'actions', 'destroy'];
/**
Adds the passed target/method and any optional arguments to the named
@@ -4174,19 +4174,19 @@ Ember.run.queues = ['sync', 'actions', 'destroy', 'timers'];
the `run.queues` property.
```javascript
- Ember.run.schedule('timers', this, function(){
- // this will be executed at the end of the RunLoop, when timers are run
- console.log("scheduled on timers queue");
+ Ember.run.schedule('sync', this, function(){
+ // this will be executed in the first RunLoop queue, when bindings are synced
+ console.log("scheduled on sync queue");
});
- Ember.run.schedule('sync', this, function(){
- // this will be executed at the end of the RunLoop, when bindings are synced
- console.log("scheduled on sync queue");
+ Ember.run.schedule('actions', this, function(){
+ // this will be executed in the 'actions' queue, after bindings have synced.
+ console.log("scheduled on actions queue");
});
// Note the functions will be run in order based on the run queues order. Output would be:
// scheduled on sync queue
- // scheduled on timers queue
+ // scheduled on actions queue
```
@method schedule
@@ -4212,7 +4212,7 @@ function autorun() {
// Used by global test teardown
Ember.run.hasScheduledTimers = function() {
- return !!(scheduledAutorun || scheduledLater || scheduledNext);
+ return !!(scheduledAutorun || scheduledLater);
};
// Used by global test teardown
@@ -4225,10 +4225,6 @@ Ember.run.cancelTimers = function () {
clearTimeout(scheduledLater);
scheduledLater = null;
}
- if (scheduledNext) {
- clearTimeout(scheduledNext);
- scheduledNext = null;
- }
timers = {};
};
@@ -4263,7 +4259,8 @@ Ember.run.autorun = function() {
bindings in the application to sync.
You should call this method anytime you need any changed state to propagate
- throughout the app immediately without repainting the UI.
+ throughout the app immediately without repainting the UI (which happens
+ in the later 'render' queue added by the `ember-views` package).
```javascript
Ember.run.sync();
@@ -4283,25 +4280,30 @@ Ember.run.sync = function() {
var timers = {}; // active timers...
-var scheduledLater;
+var scheduledLater, scheduledLaterExpires;
function invokeLaterTimers() {
scheduledLater = null;
- var now = (+ new Date()), earliest = -1;
- for (var key in timers) {
- if (!timers.hasOwnProperty(key)) { continue; }
- var timer = timers[key];
- if (timer && timer.expires) {
- if (now >= timer.expires) {
- delete timers[key];
- invoke(timer.target, timer.method, timer.args, 2);
- } else {
- if (earliest<0 || (timer.expires < earliest)) earliest=timer.expires;
+ run(function() {
+ var now = (+ new Date()), earliest = -1;
+ for (var key in timers) {
+ if (!timers.hasOwnProperty(key)) { continue; }
+ var timer = timers[key];
+ if (timer && timer.expires) {
+ if (now >= timer.expires) {
+ delete timers[key];
+ invoke(timer.target, timer.method, timer.args, 2);
+ } else {
+ if (earliest < 0 || (timer.expires < earliest)) { earliest = timer.expires; }
+ }
}
}
- }
- // schedule next timeout to fire...
- if (earliest > 0) { scheduledLater = setTimeout(invokeLaterTimers, earliest-(+ new Date())); }
+ // schedule next timeout to fire when the earliest timer expires
+ if (earliest > 0) {
+ scheduledLater = setTimeout(invokeLaterTimers, earliest - now);
+ scheduledLaterExpires = earliest;
+ }
+ });
}
/**
@@ -4349,7 +4351,19 @@ Ember.run.later = function(target, method) {
timer = { target: target, method: method, expires: expires, args: args };
guid = Ember.guidFor(timer);
timers[guid] = timer;
- run.once(timers, invokeLaterTimers);
+
+ if(scheduledLater && expires < scheduledLaterExpires) {
+ // Cancel later timer (then reschedule earlier timer below)
+ clearTimeout(scheduledLater);
+ scheduledLater = null;
+ }
+
+ if (!scheduledLater) {
+ // Schedule later timers to be run.
+ scheduledLater = setTimeout(invokeLaterTimers, wait);
+ scheduledLaterExpires = expires;
+ }
+
return guid;
};
@@ -4404,6 +4418,21 @@ function scheduleOnce(queue, target, method, args) {
// doFoo will only be executed once at the end of the RunLoop
});
```
+
+ Also note that passing an anonymous function to `Ember.run.once` will
+ not prevent additional calls with an identical anonymous function from
+ scheduling the items multiple times, e.g.:
+
+ ```javascript
+ function scheduleIt() {
+ Ember.run.once(myContext, function() { console.log("Closure"); });
+ }
+ scheduleIt();
+ scheduleIt();
+ // "Closure" will print twice, even though we're using `Ember.run.once`,
+ // because the function we pass to it is anonymous and won't match the
+ // previously scheduled operation.
+ ```
@method once
@param {Object} [target] target of method to invoke
@@ -4421,22 +4450,9 @@ Ember.run.scheduleOnce = function(queue, target, method, args) {
return scheduleOnce(queue, target, method, slice.call(arguments, 3));
};
-var scheduledNext;
-function invokeNextTimers() {
- scheduledNext = null;
- for(var key in timers) {
- if (!timers.hasOwnProperty(key)) { continue; }
- var timer = timers[key];
- if (timer.next) {
- delete timers[key];
- invoke(timer.target, timer.method, timer.args, 2);
- }
- }
-}
-
/**
Schedules an item to run after control has been returned to the system.
- This is often equivalent to calling `setTimeout(function() {}, 1)`.
+ This is equivalent to calling `Ember.run.later` with a wait time of 1ms.
```javascript
Ember.run.next(myContext, function(){
@@ -4452,20 +4468,10 @@ function invokeNextTimers() {
@param {Object} [args*] Optional arguments to pass to the timeout.
@return {Object} timer
*/
-Ember.run.next = function(target, method) {
- var guid,
- timer = {
- target: target,
- method: method,
- args: slice.call(arguments),
- next: true
- };
-
- guid = Ember.guidFor(timer);
- timers[guid] = timer;
-
- if (!scheduledNext) { scheduledNext = setTimeout(invokeNextTimers, 1); }
- return guid;
+Ember.run.next = function() {
+ var args = slice.call(arguments);
+ args.push(1); // 1 millisecond wait
+ return run.later.apply(this, args);
};
/**
@@ -5339,6 +5345,38 @@ Mixin.finishPartial = finishPartial;
Ember.anyUnprocessedMixins = false;
/**
+ Creates an instance of a class. Accepts either no arguments, or an object
+ containing values to initialize the newly instantiated object with.
+
+ ```javascript
+ App.Person = Ember.Object.extend({
+ helloWorld: function() {
+ alert("Hi, my name is " + this.get('name'));
+ }
+ });
+
+ var tom = App.Person.create({
+ name: 'Tom Dale'
+ });
+
+ tom.helloWorld(); // alerts "Hi, my name is Tom Dale".
+ ```
+
+ `create` will call the `init` function if defined during
+ `Ember.AnyObject.extend`
+
+ If no arguments are passed to `create`, it will not set values to the new
+ instance during initialization:
+
+ ```javascript
+ var noName = App.Person.create();
+ noName.helloWorld(); // alerts undefined
+ ```
+
+ NOTE: For performance reasons, you cannot declare methods or computed
+ properties during `create`. You should instead declare methods and computed
+ properties when using `extend`.
+
@method create
@static
@param arguments*
@@ -6763,10 +6801,11 @@ Ember.String = {
*/
dasherize: function(str) {
var cache = STRING_DASHERIZE_CACHE,
- ret = cache[str];
+ hit = cache.hasOwnProperty(str),
+ ret;
- if (ret) {
- return ret;
+ if (hit) {
+ return cache[str];
} else {
ret = Ember.String.decamelize(str).replace(STRING_DASHERIZE_REGEXP,'-');
cache[str] = ret;
@@ -6776,7 +6815,7 @@ Ember.String = {
},
/**
- Returns the lowerCaseCamel form of a string.
+ Returns the lowerCamelCase form of a string.
```javascript
'innerHTML'.camelize(); // 'innerHTML'
@@ -6847,10 +6886,10 @@ Ember.String = {
/**
Returns the Capitalized form of a string
- 'innerHTML'.capitalize() => 'InnerHTML'
- 'action_name'.capitalize() => 'Action_name'
- 'css-class-name'.capitalize() => 'Css-class-name'
- 'my favorite items'.capitalize() => 'My favorite items'
+ 'innerHTML'.capitalize() // 'InnerHTML'
+ 'action_name'.capitalize() // 'Action_name'
+ 'css-class-name'.capitalize() // 'Css-class-name'
+ 'my favorite items'.capitalize() // 'My favorite items'
@method capitalize
@param {String} str
@@ -7247,10 +7286,10 @@ Ember.Enumerable = Ember.Mixin.create(
```javascript
var arr = ["a", "b", "c"];
- arr.firstObject(); // "a"
+ arr.get('firstObject'); // "a"
var arr = [];
- arr.firstObject(); // undefined
+ arr.get('firstObject'); // undefined
```
@property firstObject
@@ -7273,10 +7312,10 @@ Ember.Enumerable = Ember.Mixin.create(
```javascript
var arr = ["a", "b", "c"];
- arr.lastObject(); // "c"
+ arr.get('lastObject'); // "c"
var arr = [];
- arr.lastObject(); // undefined
+ arr.get('lastObject'); // undefined
```
@property lastObject
@@ -7409,7 +7448,7 @@ Ember.Enumerable = Ember.Mixin.create(
@return {Array} The mapped array.
*/
map: function(callback, target) {
- var ret = [];
+ var ret = Ember.A([]);
this.forEach(function(x, idx, i) {
ret[idx] = callback.call(target, x, idx,i);
});
@@ -7459,7 +7498,7 @@ Ember.Enumerable = Ember.Mixin.create(
@return {Array} A filtered array.
*/
filter: function(callback, target) {
- var ret = [];
+ var ret = Ember.A([]);
this.forEach(function(x, idx, i) {
if (callback.call(target, x, idx, i)) ret.push(x);
});
@@ -7748,7 +7787,7 @@ Ember.Enumerable = Ember.Mixin.create(
@return {Array} return values from calling invoke.
*/
invoke: function(methodName) {
- var args, ret = [];
+ var args, ret = Ember.A([]);
if (arguments.length>1) args = a_slice.call(arguments, 1);
this.forEach(function(x, idx) {
@@ -7769,7 +7808,7 @@ Ember.Enumerable = Ember.Mixin.create(
@return {Array} the enumerable as an array.
*/
toArray: function() {
- var ret = [];
+ var ret = Ember.A([]);
this.forEach(function(o, idx) { ret[idx] = o; });
return ret ;
},
@@ -7803,7 +7842,7 @@ Ember.Enumerable = Ember.Mixin.create(
*/
without: function(value) {
if (!this.contains(value)) return this; // nothing to do
- var ret = [] ;
+ var ret = Ember.A([]);
this.forEach(function(k) {
if (k !== value) ret[ret.length] = k;
}) ;
@@ -7823,7 +7862,7 @@ Ember.Enumerable = Ember.Mixin.create(
@return {Ember.Enumerable}
*/
uniq: function() {
- var ret = [];
+ var ret = Ember.A([]);
this.forEach(function(k){
if (a_indexOf(ret, k)<0) ret.push(k);
});
@@ -7855,7 +7894,7 @@ Ember.Enumerable = Ember.Mixin.create(
@method addEnumerableObserver
@param {Object} target
- @param {Hash} opts
+ @param {Hash} [opts]
*/
addEnumerableObserver: function(target, opts) {
var willChange = (opts && opts.willChange) || 'enumerableWillChange',
@@ -7991,7 +8030,7 @@ Ember.Enumerable = Ember.Mixin.create(
// HELPERS
//
-var get = Ember.get, set = Ember.set, meta = Ember.meta, map = Ember.EnumerableUtils.map, cacheFor = Ember.cacheFor;
+var get = Ember.get, set = Ember.set, map = Ember.EnumerableUtils.map, cacheFor = Ember.cacheFor;
function none(obj) { return obj===null || obj===undefined; }
@@ -8133,12 +8172,12 @@ Ember.Array = Ember.Mixin.create(Ember.Enumerable, /** @scope Ember.Array.protot
```
@method slice
- @param beginIndex {Integer} (Optional) index to begin slicing from.
- @param endIndex {Integer} (Optional) index to end the slice at.
+ @param {Integer} beginIndex (Optional) index to begin slicing from.
+ @param {Integer} endIndex (Optional) index to end the slice at.
@return {Array} New array with specified slice
*/
slice: function(beginIndex, endIndex) {
- var ret = [];
+ var ret = Ember.A([]);
var length = get(this, 'length') ;
if (none(beginIndex)) beginIndex = 0 ;
if (none(endIndex) || (endIndex > length)) endIndex = length ;
@@ -9040,7 +9079,7 @@ Ember.MutableArray = Ember.Mixin.create(Ember.Array, Ember.MutableEnumerable,
@submodule ember-runtime
*/
-var get = Ember.get, set = Ember.set, defineProperty = Ember.defineProperty;
+var get = Ember.get, set = Ember.set;
/**
## Overview
@@ -9985,6 +10024,37 @@ CoreObject.PrototypeMixin = Mixin.create({
isInstance: true,
+ /**
+ An overridable method called when objects are instantiated. By default,
+ does nothing unless it is overridden during class definition.
+
+ Example:
+
+ ```javascript
+ App.Person = Ember.Object.extend({
+ init: function() {
+ this._super();
+ alert('Name is ' + this.get('name'));
+ }
+ });
+
+ var steve = App.Person.create({
+ name: "Steve"
+ });
+
+ // alerts 'Name is Steve'.
+ ```
+
+ NOTE: If you do override `init` for a framework class like `Ember.View` or
+ `Ember.ArrayController`, be sure to call `this._super()` in your
+ `init` declaration! If you don't, Ember may not have an opportunity to
+ do important setup work, and you'll see strange behavior in your
+ application.
+
+ ```
+
+ @method init
+ */
init: function() {},
/**
@@ -10135,7 +10205,7 @@ CoreObject.PrototypeMixin = Mixin.create({
}
});
teacher = App.Teacher.create()
- teacher.toString(); // #=> ""
+ teacher.toString(); //=> ""
@method toString
@return {String} string representation
@@ -14652,7 +14722,6 @@ Ember.View = Ember.CoreView.extend(
// JavaScript property changes.
var observer = function() {
elem = this.$();
- if (!elem) { return; }
attributeValue = get(this, property);
@@ -15518,10 +15587,18 @@ Ember.View = Ember.CoreView.extend(
},
registerObserver: function(root, path, target, observer) {
- Ember.addObserver(root, path, target, observer);
+ if (!observer && 'function' === typeof target) {
+ observer = target;
+ target = null;
+ }
+ var view = this,
+ stateCheckedObserver = function(){
+ view.currentState.invokeObserver(this, observer);
+ };
+ Ember.addObserver(root, path, target, stateCheckedObserver);
this.one('willClearRender', function() {
- Ember.removeObserver(root, path, target, observer);
+ Ember.removeObserver(root, path, target, stateCheckedObserver);
});
}
@@ -15799,7 +15876,8 @@ Ember.View.states._default = {
return false;
},
- rerender: Ember.K
+ rerender: Ember.K,
+ invokeObserver: Ember.K
};
})();
@@ -15920,6 +15998,10 @@ Ember.merge(inBuffer, {
}
return value;
+ },
+
+ invokeObserver: function(target, observer) {
+ observer.call(target);
}
});
@@ -16007,6 +16089,10 @@ Ember.merge(hasElement, {
} else {
return true; // continue event propagation
}
+ },
+
+ invokeObserver: function(target, observer) {
+ observer.call(target);
}
});
@@ -23668,10 +23754,10 @@ Ember.onLoad('Ember.Handlebars', function(Handlebars) {
The default target for `{{action}}`s in the rendered template is the
named controller.
- @method action
+ @method render
@for Ember.Handlebars.helpers
- @param {String} actionName
- @param {Object?} model
+ @param {String} name
+ @param {Object?} contextString
@param {Hash} options
*/
Ember.Handlebars.registerHelper('render', function(name, contextString, options) {
@@ -24472,6 +24558,7 @@ Ember.HistoryLocation = Ember.Object.extend({
if (this.getState() && this.getState().path !== path) {
popstateReady = true;
+ console.log('pushin');
this.pushState(path);
}
},
@@ -24502,7 +24589,7 @@ Ember.HistoryLocation = Ember.Object.extend({
@method getState
*/
getState: function() {
- return get(this, 'history').state;
+ return window.history.state;
},
/**
@@ -24945,6 +25032,7 @@ var Application = Ember.Application = Ember.Namespace.extend({
}
if ( Ember.LOG_VERSION ) {
+ Ember.LOG_VERSION = false; // we only need to see this once per Application#init