dist/ember.prod.js in ember-source-1.0.0.rc4.1 vs dist/ember.prod.js in ember-source-1.0.0.rc5
- old
+ new
@@ -60,11 +60,11 @@
The core Runtime framework is based on the jQuery API with a number of
performance optimizations.
@class Ember
@static
- @version 1.0.0-rc.4
+ @version 1.0.0-rc.5
*/
if ('undefined' === typeof Ember) {
// Create core object. Make it act like an instance of Ember.Namespace so that
// objects assigned to it are given a sane string representation.
@@ -87,14 +87,14 @@
/**
@property VERSION
@type String
- @default '1.0.0-rc.4'
+ @default '1.0.0-rc.5'
@final
*/
-Ember.VERSION = '1.0.0-rc.4';
+Ember.VERSION = '1.0.0-rc.5';
/**
Standard environmental variables. You can define these in a global `ENV`
variable before loading Ember to control various configuration
settings.
@@ -4468,11 +4468,11 @@
if (typeof method === 'string') {
method = target[method];
}
- var stack = new Error().stack,
+ var stack = this.DEBUG ? new Error().stack : undefined,
args = arguments.length > 3 ? slice.call(arguments, 3) : undefined;
if (!this.currentInstance) { createAutorun(this); }
return this.currentInstance.schedule(queueName, target, method, args, false, stack);
},
@@ -4484,11 +4484,11 @@
if (typeof method === 'string') {
method = target[method];
}
- var stack = new Error().stack,
+ var stack = this.DEBUG ? new Error().stack : undefined,
args = arguments.length > 3 ? slice.call(arguments, 3) : undefined;
if (!this.currentInstance) { createAutorun(this); }
return this.currentInstance.schedule(queueName, target, method, args, true, stack);
},
@@ -4533,11 +4533,11 @@
if (laterTimer) {
clearTimeout(laterTimer);
laterTimer = null;
}
- laterTimer = setTimeout(function() {
+ laterTimer = window.setTimeout(function() {
executeTimers(self);
laterTimer = null;
laterTimerExpiresAt = null;
}, wait);
laterTimerExpiresAt = executeAt;
@@ -4554,11 +4554,11 @@
for (var i = 0, l = debouncees.length; i < l; i++) {
debouncee = debouncees[i];
if (debouncee[0] === target && debouncee[1] === method) { return; } // do nothing
}
- var timer = setTimeout(function() {
+ var timer = window.setTimeout(function() {
self.run.apply(self, args);
// remove debouncee
var index = -1;
for (var i = 0, l = debouncees.length; i < l; i++) {
@@ -4615,11 +4615,11 @@
Backburner.prototype.scheduleOnce = Backburner.prototype.deferOnce;
Backburner.prototype.later = Backburner.prototype.setTimeout;
function createAutorun(backburner) {
backburner.begin();
- autorun = setTimeout(function() {
+ autorun = window.setTimeout(function() {
backburner.end();
autorun = null;
});
}
@@ -4640,11 +4640,11 @@
self.schedule(self.options.defaultQueue, null, fns[i]);
}
});
if (timers.length) {
- laterTimer = setTimeout(function() {
+ laterTimer = window.setTimeout(function() {
executeTimers(self);
laterTimer = null;
laterTimerExpiresAt = null;
}, timers[0] - now);
laterTimerExpiresAt = timers[0];
@@ -6418,10 +6418,33 @@
return Ember.observer.apply(this, arguments);
};
/**
+ When observers fire, they are called with the arguments `obj`, `keyName`
+ and `value`. In a typical observer, value is the new, post-change value.
+
+ A `beforeObserver` fires before a property changes. The `value` argument contains
+ the pre-change value.
+
+ A `beforeObserver` is an alternative form of `.observesBefore()`.
+
+ ```javascript
+ App.PersonView = Ember.View.extend({
+ valueWillChange: function (obj, keyName, value) {
+ this.changingFrom = value;
+ }.observesBefore('content.value'),
+ valueDidChange: function(obj, keyName, value) {
+ // only run if updating a value already in the DOM
+ if(this.get('state') === 'inDOM') {
+ var color = value > this.changingFrom ? 'green' : 'red';
+ // logic
+ }
+ }.observes('content.value')
+ });
+ ```
+
@method beforeObserver
@for Ember
@param {Function} func
@param {String} propertyNames*
@return func
@@ -13922,49 +13945,10 @@
toDOM: function() {
return this.list.join(" ");
}
};
-var BAD_TAG_NAME_TEST_REGEXP = /[^a-zA-Z\-]/;
-var BAD_TAG_NAME_REPLACE_REGEXP = /[^a-zA-Z\-]/g;
-
-function stripTagName(tagName) {
- if (!tagName) {
- return tagName;
- }
-
- if (!BAD_TAG_NAME_TEST_REGEXP.test(tagName)) {
- return tagName;
- }
-
- return tagName.replace(BAD_TAG_NAME_REPLACE_REGEXP, '');
-}
-
-var BAD_CHARS_REGEXP = /&(?!\w+;)|[<>"'`]/g;
-var POSSIBLE_CHARS_REGEXP = /[&<>"'`]/;
-
-function escapeAttribute(value) {
- // Stolen shamelessly from Handlebars
-
- var escape = {
- "<": "<",
- ">": ">",
- '"': """,
- "'": "'",
- "`": "`"
- };
-
- var escapeChar = function(chr) {
- return escape[chr] || "&";
- };
-
- var string = value.toString();
-
- if(!POSSIBLE_CHARS_REGEXP.test(string)) { return string; }
- return string.replace(BAD_CHARS_REGEXP, escapeChar);
-}
-
/**
`Ember.RenderBuffer` gathers information regarding the a view and generates the
final representation. `Ember.RenderBuffer` will generate HTML which can be pushed
to the DOM.
@@ -14248,27 +14232,27 @@
attrs = this.elementAttributes,
props = this.elementProperties,
style = this.elementStyle,
attr, prop;
- buffer += '<' + stripTagName(tagName);
+ buffer += '<' + tagName;
if (id) {
- buffer += ' id="' + escapeAttribute(id) + '"';
+ buffer += ' id="' + this._escapeAttribute(id) + '"';
this.elementId = null;
}
if (classes) {
- buffer += ' class="' + escapeAttribute(classes.join(' ')) + '"';
+ buffer += ' class="' + this._escapeAttribute(classes.join(' ')) + '"';
this.classes = null;
}
if (style) {
buffer += ' style="';
for (prop in style) {
if (style.hasOwnProperty(prop)) {
- buffer += prop + ':' + escapeAttribute(style[prop]) + ';';
+ buffer += prop + ':' + this._escapeAttribute(style[prop]) + ';';
}
}
buffer += '"';
@@ -14276,11 +14260,11 @@
}
if (attrs) {
for (attr in attrs) {
if (attrs.hasOwnProperty(attr)) {
- buffer += ' ' + attr + '="' + escapeAttribute(attrs[attr]) + '"';
+ buffer += ' ' + attr + '="' + this._escapeAttribute(attrs[attr]) + '"';
}
}
this.elementAttributes = null;
}
@@ -14291,11 +14275,11 @@
var value = props[prop];
if (value || typeof(value) === 'number') {
if (value === true) {
buffer += ' ' + prop + '="' + prop + '"';
} else {
- buffer += ' ' + prop + '="' + escapeAttribute(props[prop]) + '"';
+ buffer += ' ' + prop + '="' + this._escapeAttribute(props[prop]) + '"';
}
}
}
}
@@ -14306,11 +14290,11 @@
this.buffer = buffer;
},
pushClosingTag: function() {
var tagName = this.tagNames.pop();
- if (tagName) { this.buffer += '</' + stripTagName(tagName) + '>'; }
+ if (tagName) { this.buffer += '</' + tagName + '>'; }
},
currentTagName: function() {
return this.tagNames[this.tagNames.length-1];
},
@@ -14404,11 +14388,36 @@
}
},
innerString: function() {
return this.buffer;
+ },
+
+ _escapeAttribute: function(value) {
+ // Stolen shamelessly from Handlebars
+
+ var escape = {
+ "<": "<",
+ ">": ">",
+ '"': """,
+ "'": "'",
+ "`": "`"
+ };
+
+ var badChars = /&(?!\w+;)|[<>"'`]/g;
+ var possible = /[&<>"'`]/;
+
+ var escapeChar = function(chr) {
+ return escape[chr] || "&";
+ };
+
+ var string = value.toString();
+
+ if(!possible.test(string)) { return string; }
+ return string.replace(badChars, escapeChar);
}
+
};
})();
@@ -23588,11 +23597,11 @@
Clears the current and target route handlers and triggers exit
on each of them starting at the leaf and traversing up through
its ancestors.
*/
reset: function() {
- eachHandler(this.currentHandlerInfos, function(handler) {
+ eachHandler(this.currentHandlerInfos || [], function(handler) {
if (handler.exit) {
handler.exit();
}
});
this.currentHandlerInfos = null;
@@ -24729,10 +24738,13 @@
/**
Transition into another route while replacing the current URL if
possible. Identical to `transitionTo` in all other respects.
+ Of the bundled location types, only `history` currently supports
+ this behavior.
+
@method replaceWith
@param {String} name the name of the route
@param {...Object} models the
*/
replaceWith: function() {
@@ -25169,10 +25181,12 @@
});
function parentRoute(route) {
var handlerInfos = route.router.router.targetHandlerInfos;
+ if (!handlerInfos) { return; }
+
var parent, current;
for (var i=0, l=handlerInfos.length; i<l; i++) {
current = handlerInfos[i].handler;
if (current === route) { return parent; }
@@ -26079,11 +26093,11 @@
`{{outlet}}` helper, actions will bubble to the current controller, then
to the current route, and then up the route hierarchy.
Alternatively, a `target` option can be provided to the helper to change
which object will receive the method call. This option must be a path
- path to an object, accessible in the current context:
+ to an object, accessible in the current context:
```handlebars
<script type="text/x-handlebars" data-template-name='a-template'>
<div {{action anActionName target="MyApplication.someObject"}}>
click me
@@ -27896,11 +27910,11 @@
return resolver.resolve(fullName);
};
}
function normalize(fullName) {
- var split = fullName.split(':'),
+ var split = fullName.split(':', 2),
type = split[0],
name = split[1];
if (type !== 'template') {
@@ -29304,424 +29318,9 @@
@module ember
@submodule ember-states
@requires ember-runtime
*/
-
-})();
-
-(function() {
-var slice = [].slice,
- helpers = {},
- originalMethods = {},
- injectHelpersCallbacks = [];
-
-/**
- @class Test
- @namespace Ember
-*/
-Ember.Test = {
-
- /**
- @public
-
- `registerHelper` is used to register a
- test helper that will be injected when
- `App.injectTestHelpers` is called.
-
- The helper method will always be called
- with the current Application as the first
- parameter.
-
- For example:
- ```javascript
- Ember.Test.registerHelper('boot', function(app)) {
- Ember.run(app, app.deferReadiness);
- }
- ```
-
- This helper can later be called without arguments
- because it will be called with `app` as the
- first parameter.
-
- ```javascript
- App = Ember.Application.create();
- App.injectTestHelpers();
- boot();
- ```
-
- Whenever you register a helper that
- performs async operations,
- make sure you `return wait();` at the
- end of the helper.
-
- If an async helper also needs to return a value,
- pass it to the `wait` helper as a first argument:
- `return wait(val);`
-
- @method registerHelper
- @param name {String}
- @param helperMethod {Function}
- */
- registerHelper: function(name, helperMethod) {
- helpers[name] = helperMethod;
- },
- /**
- @public
- @method unregisterHelper
- @param name {String}
- */
- unregisterHelper: function(name) {
- delete helpers[name];
- if (originalMethods[name]) {
- window[name] = originalMethods[name];
- }
- delete originalMethods[name];
- },
-
- /**
- @public
-
- Used to register callbacks to be fired
- whenever `App.injectTestHelpers` is called
-
- The callback will receive the current application
- as an argument.
-
- @method unregisterHelper
- @param name {String}
- */
- onInjectHelpers: function(callback) {
- injectHelpersCallbacks.push(callback);
- },
-
- /**
- @public
-
- This returns a thenable tailored
- for testing. It catches failed
- `onSuccess` callbacks and invokes
- the `Ember.Test.adapter.exception`
- callback in the last chained then.
-
- This method should be returned
- by async helpers such as `wait`.
-
- @method promise
- @param resolver {Function}
- */
- promise: function(resolver) {
- var promise = new Ember.RSVP.Promise(resolver);
- var thenable = {
- chained: false
- };
- thenable.then = function(onSuccess, onFailure) {
- var self = this, thenPromise, nextPromise;
- thenable.chained = true;
- thenPromise = promise.then(onSuccess, onFailure);
- // this is to ensure all downstream fulfillment
- // handlers are wrapped in the error handling
- nextPromise = Ember.Test.promise(function(resolve) {
- resolve(thenPromise);
- });
- thenPromise.then(null, function(reason) {
- // ensure this is the last promise in the chain
- // if not, ignore and the exception will propagate
- // this prevents the same error from being fired multiple times
- if (!nextPromise.chained) {
- Ember.Test.adapter.exception(reason);
- }
- });
- return nextPromise;
- };
- return thenable;
- },
-
- /**
- @public
-
- Used to allow ember-testing
- to communicate with a specific
- testing framework.
-
- You can manually set it before calling
- `App.setupForTesting()`.
-
- Example:
- 'Ember.Test.adapter = MyCustomAdapter.create()'
-
- If you do not set it, ember-testing
- will default to `Ember.Test.QUnitAdapter`.
- */
- adapter: null
-};
-
-function curry(app, fn) {
- return function() {
- var args = slice.call(arguments);
- args.unshift(app);
- return fn.apply(app, args);
- };
-}
-
-Ember.Application.reopen({
- testHelpers: {},
-
- setupForTesting: function() {
- this.deferReadiness();
-
- this.Router.reopen({
- location: 'none'
- });
-
- // if adapter is not manually set
- // default to QUnit
- if (!Ember.Test.adapter) {
- Ember.Test.adapter = Ember.Test.QUnitAdapter.create();
- }
- },
-
- injectTestHelpers: function() {
- this.testHelpers = {};
- for (var name in helpers) {
- originalMethods[name] = window[name];
- this.testHelpers[name] = window[name] = curry(this, helpers[name]);
- }
-
- for(var i = 0, l = injectHelpersCallbacks.length; i < l; i++) {
- injectHelpersCallbacks[i](this);
- }
- },
-
- removeTestHelpers: function() {
- for (var name in helpers) {
- window[name] = originalMethods[name];
- delete this.testHelpers[name];
- delete originalMethods[name];
- }
- }
-});
-
-})();
-
-
-
-(function() {
-var Test = Ember.Test;
-
-/**
- @class Adapter
- @namespace Ember.Test
-*/
-Test.Adapter = Ember.Object.extend({
- /**
- @public
-
- This callback will be called
- whenever an async operation
- is about to start.
-
- Override this to call your
- framework's methods
- that handle async operations
-
- @method asyncStart
- */
- asyncStart: Ember.K,
-
- /**
- @public
-
- This callback will be called
- whenever an async operation
- has completed.
-
- @method asyncEnd
- */
- asyncEnd: Ember.K,
-
- /**
- @public
-
- Override this method with your
- testing framework's false assertion
- This function is called whenever
- an exception occurs causing the testing
- promise to fail.
-
- QUnit example:
-
- ```javascript
- exception: function(error) {
- ok(false, error);
- }
- ```
-
- @method exception
- @param reason {String}
- */
- exception: function(error) {
- setTimeout(function() {
- throw error;
- });
- }
-});
-
-/**
- @class QUnitAdapter
- @namespace Ember.Test
-*/
-Test.QUnitAdapter = Test.Adapter.extend({
- asyncStart: function() {
- stop();
- },
- asyncEnd: function() {
- start();
- },
- exception: function(error) {
- ok(false, error);
- }
-});
-
-})();
-
-
-
-(function() {
-var get = Ember.get,
- helper = Ember.Test.registerHelper,
- pendingAjaxRequests = 0,
- countAsync = 0;
-
-
-Ember.Test.onInjectHelpers(function() {
- Ember.$(document).ajaxStart(function() {
- pendingAjaxRequests++;
- });
-
- Ember.$(document).ajaxStop(function() {
- pendingAjaxRequests--;
- });
-});
-
-
-function visit(app, url) {
- Ember.run(app, app.handleURL, url);
- app.__container__.lookup('router:main').location.setURL(url);
- return wait(app);
-}
-
-function click(app, selector, context) {
- var $el = find(app, selector, context);
- Ember.run(function() {
- $el.click();
- });
- return wait(app);
-}
-
-function fillIn(app, selector, context, text) {
- var $el;
- if (typeof text === 'undefined') {
- text = context;
- context = null;
- }
- $el = find(app, selector, context);
- Ember.run(function() {
- $el.val(text).change();
- });
- return wait(app);
-}
-
-function find(app, selector, context) {
- var $el;
- context = context || get(app, 'rootElement');
- $el = app.$(selector, context);
- if ($el.length === 0) {
- throw("Element " + selector + " not found.");
- }
- return $el;
-}
-
-function wait(app, value) {
- var promise, obj = {}, helperName;
-
- promise = Ember.Test.promise(function(resolve) {
- if (++countAsync === 1) {
- Ember.Test.adapter.asyncStart();
- }
- var watcher = setInterval(function() {
- var routerIsLoading = app.__container__.lookup('router:main').router.isLoading;
- if (routerIsLoading) { return; }
- if (pendingAjaxRequests) { return; }
- if (Ember.run.hasScheduledTimers() || Ember.run.currentRunLoop) { return; }
- clearInterval(watcher);
- if (--countAsync === 0) {
- Ember.Test.adapter.asyncEnd();
- }
- Ember.run(function() {
- resolve(value);
- });
- }, 10);
- });
-
- return buildChainObject(app, promise);
-}
-
-/**
- Builds an object that contains
- all helper methods. This object will be
- returned by helpers and then-promises.
-
- This allows us to chain helpers:
-
- ```javascript
- visit('posts/new')
- .click('.add-btn')
- .fillIn('.title', 'Post')
- .click('.submit')
- .then(function() {
- equal('.post-title', 'Post');
- })
- .visit('comments')
- .then(function() {
- equal(find('.comments'),length, 0);
- });
- ```
-*/
-function buildChainObject(app, promise) {
- var helperName, obj = {};
- for(helperName in app.testHelpers) {
- obj[helperName] = chain(app, promise, app.testHelpers[helperName]);
- }
- obj.then = function(fn) {
- var thenPromise = promise.then(fn);
- return buildChainObject(app, thenPromise);
- };
- return obj;
-}
-
-function chain(app, promise, fn) {
- return function() {
- var args = arguments, chainedPromise;
- chainedPromise = promise.then(function() {
- return fn.apply(null, args);
- });
- return buildChainObject(app, chainedPromise);
- };
-}
-
-// expose these methods as test helpers
-helper('visit', visit);
-helper('click', click);
-helper('fillIn', fillIn);
-helper('find', find);
-helper('wait', wait);
-
-})();
-
-
-
-(function() {
})();
})();