} The names of the services which the function requires.
@@ -3154,12 +3277,12 @@ function annotate(fn) {
/**
* @ngdoc object
- * @name AUTO.$provide
+ * @name $provide
*
* @description
*
- * The {@link AUTO.$provide $provide} service has a number of methods for registering components
- * with the {@link AUTO.$injector $injector}. Many of these functions are also exposed on
+ * The {@link auto.$provide $provide} service has a number of methods for registering components
+ * with the {@link auto.$injector $injector}. Many of these functions are also exposed on
* {@link angular.Module}.
*
* An Angular **service** is a singleton object created by a **service factory**. These **service
@@ -3167,25 +3290,25 @@ function annotate(fn) {
* The **service providers** are constructor functions. When instantiated they must contain a
* property called `$get`, which holds the **service factory** function.
*
- * When you request a service, the {@link AUTO.$injector $injector} is responsible for finding the
+ * When you request a service, the {@link auto.$injector $injector} is responsible for finding the
* correct **service provider**, instantiating it and then calling its `$get` **service factory**
* function to get the instance of the **service**.
*
* Often services have no configuration options and there is no need to add methods to the service
* provider. The provider will be no more than a constructor function with a `$get` property. For
- * these cases the {@link AUTO.$provide $provide} service has additional helper methods to register
+ * these cases the {@link auto.$provide $provide} service has additional helper methods to register
* services without specifying a provider.
*
- * * {@link AUTO.$provide#methods_provider provider(provider)} - registers a **service provider** with the
- * {@link AUTO.$injector $injector}
- * * {@link AUTO.$provide#methods_constant constant(obj)} - registers a value/object that can be accessed by
+ * * {@link auto.$provide#provider provider(provider)} - registers a **service provider** with the
+ * {@link auto.$injector $injector}
+ * * {@link auto.$provide#constant constant(obj)} - registers a value/object that can be accessed by
* providers and services.
- * * {@link AUTO.$provide#methods_value value(obj)} - registers a value/object that can only be accessed by
+ * * {@link auto.$provide#value value(obj)} - registers a value/object that can only be accessed by
* services, not providers.
- * * {@link AUTO.$provide#methods_factory factory(fn)} - registers a service **factory function**, `fn`,
+ * * {@link auto.$provide#factory factory(fn)} - registers a service **factory function**, `fn`,
* that will be wrapped in a **service provider** object, whose `$get` property will contain the
* given factory function.
- * * {@link AUTO.$provide#methods_service service(class)} - registers a **constructor function**, `class` that
+ * * {@link auto.$provide#service service(class)} - registers a **constructor function**, `class`
* that will be wrapped in a **service provider** object, whose `$get` property will instantiate
* a new object using the given constructor function.
*
@@ -3194,11 +3317,10 @@ function annotate(fn) {
/**
* @ngdoc method
- * @name AUTO.$provide#provider
- * @methodOf AUTO.$provide
+ * @name $provide#provider
* @description
*
- * Register a **provider function** with the {@link AUTO.$injector $injector}. Provider functions
+ * Register a **provider function** with the {@link auto.$injector $injector}. Provider functions
* are constructor functions, whose instances are responsible for "providing" a factory for a
* service.
*
@@ -3218,20 +3340,18 @@ function annotate(fn) {
* @param {(Object|function())} provider If the provider is:
*
* - `Object`: then it should have a `$get` method. The `$get` method will be invoked using
- * {@link AUTO.$injector#invoke $injector.invoke()} when an instance needs to be
- * created.
+ * {@link auto.$injector#invoke $injector.invoke()} when an instance needs to be created.
* - `Constructor`: a new instance of the provider will be created using
- * {@link AUTO.$injector#instantiate $injector.instantiate()}, then treated as
- * `object`.
+ * {@link auto.$injector#instantiate $injector.instantiate()}, then treated as `object`.
*
* @returns {Object} registered provider instance
* @example
*
* The following example shows how to create a simple event tracking service and register it using
- * {@link AUTO.$provide#methods_provider $provide.provider()}.
+ * {@link auto.$provide#provider $provide.provider()}.
*
- *
+ * ```js
* // Define the eventTracker provider
* function EventTrackerProvider() {
* var trackingUrl = '/track';
@@ -3288,19 +3408,18 @@ function annotate(fn) {
* expect(postSpy.mostRecentCall.args[1]).toEqual({ 'login': 1 });
* }));
* });
- *
+ * ```
*/
/**
* @ngdoc method
- * @name AUTO.$provide#factory
- * @methodOf AUTO.$provide
+ * @name $provide#factory
* @description
*
* Register a **service factory**, which will be called to return the service instance.
* This is short for registering a service where its provider consists of only a `$get` property,
* which is the given service factory function.
- * You should use {@link AUTO.$provide#factory $provide.factory(getFn)} if you do not need to
+ * You should use {@link auto.$provide#factory $provide.factory(getFn)} if you do not need to
* configure your service in a provider.
*
* @param {string} name The name of the instance.
@@ -3310,26 +3429,25 @@ function annotate(fn) {
*
* @example
* Here is an example of registering a service
- *
+ * ```js
* $provide.factory('ping', ['$http', function($http) {
* return function ping() {
* return $http.send('/ping');
* };
* }]);
- *
+ * ```
* You would then inject and use this service like this:
- *
+ * ```js
* someModule.controller('Ctrl', ['ping', function(ping) {
* ping();
* }]);
- *
+ * ```
*/
/**
* @ngdoc method
- * @name AUTO.$provide#service
- * @methodOf AUTO.$provide
+ * @name $provide#service
* @description
*
* Register a **service constructor**, which will be invoked with `new` to create the service
@@ -3337,8 +3455,8 @@ function annotate(fn) {
* This is short for registering a service where its provider's `$get` property is the service
* constructor function that will be used to instantiate the service instance.
*
- * You should use {@link AUTO.$provide#methods_service $provide.service(class)} if you define your service
- * as a type/class. This is common when using {@link http://coffeescript.org CoffeeScript}.
+ * You should use {@link auto.$provide#service $provide.service(class)} if you define your service
+ * as a type/class.
*
* @param {string} name The name of the instance.
* @param {Function} constructor A class (constructor function) that will be instantiated.
@@ -3346,31 +3464,34 @@ function annotate(fn) {
*
* @example
* Here is an example of registering a service using
- * {@link AUTO.$provide#methods_service $provide.service(class)} that is defined as a CoffeeScript class.
- *
- * class Ping
- * constructor: (@$http)->
- * send: ()=>
- * @$http.get('/ping')
+ * {@link auto.$provide#service $provide.service(class)}.
+ * ```js
+ * var Ping = function($http) {
+ * this.$http = $http;
+ * };
*
- * $provide.service('ping', ['$http', Ping])
- *
+ * Ping.$inject = ['$http'];
+ *
+ * Ping.prototype.send = function() {
+ * return this.$http.get('/ping');
+ * };
+ * $provide.service('ping', Ping);
+ * ```
* You would then inject and use this service like this:
- *
- * someModule.controller 'Ctrl', ['ping', (ping)->
- * ping.send()
- * ]
- *
+ * ```js
+ * someModule.controller('Ctrl', ['ping', function(ping) {
+ * ping.send();
+ * }]);
+ * ```
*/
/**
* @ngdoc method
- * @name AUTO.$provide#value
- * @methodOf AUTO.$provide
+ * @name $provide#value
* @description
*
- * Register a **value service** with the {@link AUTO.$injector $injector}, such as a string, a
+ * Register a **value service** with the {@link auto.$injector $injector}, such as a string, a
* number, an array, an object or a function. This is short for registering a service where its
* provider's `$get` property is a factory function that takes no arguments and returns the **value
* service**.
@@ -3378,7 +3499,7 @@ function annotate(fn) {
* Value services are similar to constant services, except that they cannot be injected into a
* module configuration function (see {@link angular.Module#config}) but they can be overridden by
* an Angular
- * {@link AUTO.$provide#decorator decorator}.
+ * {@link auto.$provide#decorator decorator}.
*
* @param {string} name The name of the instance.
* @param {*} value The value.
@@ -3386,7 +3507,7 @@ function annotate(fn) {
*
* @example
* Here are some examples of creating value services.
- *
+ * ```js
* $provide.value('ADMIN_USER', 'admin');
*
* $provide.value('RoleLookup', { admin: 0, writer: 1, reader: 2 });
@@ -3394,20 +3515,19 @@ function annotate(fn) {
* $provide.value('halfOf', function(value) {
* return value / 2;
* });
- *
+ * ```
*/
/**
* @ngdoc method
- * @name AUTO.$provide#constant
- * @methodOf AUTO.$provide
+ * @name $provide#constant
* @description
*
* Register a **constant service**, such as a string, a number, an array, an object or a function,
- * with the {@link AUTO.$injector $injector}. Unlike {@link AUTO.$provide#value value} it can be
+ * with the {@link auto.$injector $injector}. Unlike {@link auto.$provide#value value} it can be
* injected into a module configuration function (see {@link angular.Module#config}) and it cannot
- * be overridden by an Angular {@link AUTO.$provide#decorator decorator}.
+ * be overridden by an Angular {@link auto.$provide#decorator decorator}.
*
* @param {string} name The name of the constant.
* @param {*} value The constant value.
@@ -3415,7 +3535,7 @@ function annotate(fn) {
*
* @example
* Here a some examples of creating constants:
- *
+ * ```js
* $provide.constant('SHARD_HEIGHT', 306);
*
* $provide.constant('MY_COLOURS', ['red', 'blue', 'grey']);
@@ -3423,17 +3543,16 @@ function annotate(fn) {
* $provide.constant('double', function(value) {
* return value * 2;
* });
- *
+ * ```
*/
/**
* @ngdoc method
- * @name AUTO.$provide#decorator
- * @methodOf AUTO.$provide
+ * @name $provide#decorator
* @description
*
- * Register a **service decorator** with the {@link AUTO.$injector $injector}. A service decorator
+ * Register a **service decorator** with the {@link auto.$injector $injector}. A service decorator
* intercepts the creation of a service, allowing it to override or modify the behaviour of the
* service. The object returned by the decorator may be the original service, or a new service
* object which replaces or wraps and delegates to the original service.
@@ -3441,7 +3560,7 @@ function annotate(fn) {
* @param {string} name The name of the service to decorate.
* @param {function()} decorator This function will be invoked when the service needs to be
* instantiated and should return the decorated service instance. The function is called using
- * the {@link AUTO.$injector#invoke injector.invoke} method and is therefore fully injectable.
+ * the {@link auto.$injector#invoke injector.invoke} method and is therefore fully injectable.
* Local injection arguments:
*
* * `$delegate` - The original service instance, which can be monkey patched, configured,
@@ -3450,12 +3569,12 @@ function annotate(fn) {
* @example
* Here we decorate the {@link ng.$log $log} service to convert warnings to errors by intercepting
* calls to {@link ng.$log#error $log.warn()}.
- *
- * $provider.decorator('$log', ['$delegate', function($delegate) {
+ * ```js
+ * $provide.decorator('$log', ['$delegate', function($delegate) {
* $delegate.warn = $delegate.error;
* return $delegate;
* }]);
- *
+ * ```
*/
@@ -3604,6 +3723,11 @@ function createInjector(modulesToLoad) {
path.unshift(serviceName);
cache[serviceName] = INSTANTIATING;
return cache[serviceName] = factory(serviceName);
+ } catch (err) {
+ if (cache[serviceName] === INSTANTIATING) {
+ delete cache[serviceName];
+ }
+ throw err;
} finally {
path.shift();
}
@@ -3633,24 +3757,9 @@ function createInjector(modulesToLoad) {
fn = fn[length];
}
-
- // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke
- switch (self ? -1 : args.length) {
- case 0: return fn();
- case 1: return fn(args[0]);
- case 2: return fn(args[0], args[1]);
- case 3: return fn(args[0], args[1], args[2]);
- case 4: return fn(args[0], args[1], args[2], args[3]);
- case 5: return fn(args[0], args[1], args[2], args[3], args[4]);
- case 6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]);
- case 7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
- case 8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);
- case 9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7],
- args[8]);
- case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7],
- args[8], args[9]);
- default: return fn.apply(self, args);
- }
+ // http://jsperf.com/angularjs-invoke-apply-vs-switch
+ // #5388
+ return fn.apply(self, args);
}
function instantiate(Type, locals) {
@@ -3679,8 +3788,9 @@ function createInjector(modulesToLoad) {
}
/**
- * @ngdoc function
- * @name ng.$anchorScroll
+ * @ngdoc service
+ * @name $anchorScroll
+ * @kind function
* @requires $window
* @requires $location
* @requires $rootScope
@@ -3688,11 +3798,11 @@ function createInjector(modulesToLoad) {
* @description
* When called, it checks current value of `$location.hash()` and scroll to related element,
* according to rules specified in
- * {@link http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document Html5 spec}.
+ * [Html5 spec](http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document).
*
* It also watches the `$location.hash()` and scrolls whenever it changes to match any anchor.
* This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.
- *
+ *
* @example
@@ -3707,10 +3817,10 @@ function createInjector(modulesToLoad) {
// set the location.hash to the id of
// the element you wish to scroll to.
$location.hash('bottom');
-
+
// call $anchorScroll()
$anchorScroll();
- }
+ };
}
@@ -3781,8 +3891,8 @@ function $AnchorScrollProvider() {
var $animateMinErr = minErr('$animate');
/**
- * @ngdoc object
- * @name ng.$animateProvider
+ * @ngdoc provider
+ * @name $animateProvider
*
* @description
* Default implementation of $animate that doesn't perform any animations, instead just
@@ -3795,14 +3905,13 @@ var $animateMinErr = minErr('$animate');
*/
var $AnimateProvider = ['$provide', function($provide) {
-
+
this.$$selectors = {};
/**
- * @ngdoc function
- * @name ng.$animateProvider#register
- * @methodOf ng.$animateProvider
+ * @ngdoc method
+ * @name $animateProvider#register
*
* @description
* Registers a new injectable animation factory function. The factory function produces the
@@ -3815,7 +3924,7 @@ var $AnimateProvider = ['$provide', function($provide) {
* triggered.
*
*
- *
+ * ```js
* return {
* eventFn : function(element, done) {
* //code to run the animation
@@ -3825,10 +3934,10 @@ var $AnimateProvider = ['$provide', function($provide) {
* }
* }
* }
- *
+ * ```
*
* @param {string} name The name of the animation.
- * @param {function} factory The factory function that will be executed to return the animation
+ * @param {Function} factory The factory function that will be executed to return the animation
* object.
*/
this.register = function(name, factory) {
@@ -3839,12 +3948,37 @@ var $AnimateProvider = ['$provide', function($provide) {
$provide.factory(key, factory);
};
- this.$get = ['$timeout', function($timeout) {
+ /**
+ * @ngdoc method
+ * @name $animateProvider#classNameFilter
+ *
+ * @description
+ * Sets and/or returns the CSS class regular expression that is checked when performing
+ * an animation. Upon bootstrap the classNameFilter value is not set at all and will
+ * therefore enable $animate to attempt to perform an animation on any element.
+ * When setting the classNameFilter value, animations will only be performed on elements
+ * that successfully match the filter expression. This in turn can boost performance
+ * for low-powered devices as well as applications containing a lot of structural operations.
+ * @param {RegExp=} expression The className expression which will be checked against all animations
+ * @return {RegExp} The current CSS className expression value. If null then there is no expression value
+ */
+ this.classNameFilter = function(expression) {
+ if(arguments.length === 1) {
+ this.$$classNameFilter = (expression instanceof RegExp) ? expression : null;
+ }
+ return this.$$classNameFilter;
+ };
+
+ this.$get = ['$timeout', '$$asyncCallback', function($timeout, $$asyncCallback) {
+
+ function async(fn) {
+ fn && $$asyncCallback(fn);
+ }
/**
*
- * @ngdoc object
- * @name ng.$animate
+ * @ngdoc service
+ * @name $animate
* @description The $animate service provides rudimentary DOM manipulation functions to
* insert, remove and move elements within the DOM, as well as adding and removing classes.
* This service is the core service used by the ngAnimate $animator service which provides
@@ -3862,18 +3996,17 @@ var $AnimateProvider = ['$provide', function($provide) {
/**
*
- * @ngdoc function
- * @name ng.$animate#enter
- * @methodOf ng.$animate
+ * @ngdoc method
+ * @name $animate#enter
* @function
* @description Inserts the element into the DOM either after the `after` element or within
* the `parent` element. Once complete, the done() callback will be fired (if provided).
- * @param {jQuery/jqLite element} element the element which will be inserted into the DOM
- * @param {jQuery/jqLite element} parent the parent element which will append the element as
+ * @param {DOMElement} element the element which will be inserted into the DOM
+ * @param {DOMElement} parent the parent element which will append the element as
* a child (if the after element is not present)
- * @param {jQuery/jqLite element} after the sibling element which will append the element
+ * @param {DOMElement} after the sibling element which will append the element
* after itself
- * @param {function=} done callback function that will be called after the element has been
+ * @param {Function=} done callback function that will be called after the element has been
* inserted into the DOM
*/
enter : function(element, parent, after, done) {
@@ -3885,43 +4018,41 @@ var $AnimateProvider = ['$provide', function($provide) {
}
parent.append(element);
}
- done && $timeout(done, 0, false);
+ async(done);
},
/**
*
- * @ngdoc function
- * @name ng.$animate#leave
- * @methodOf ng.$animate
+ * @ngdoc method
+ * @name $animate#leave
* @function
* @description Removes the element from the DOM. Once complete, the done() callback will be
* fired (if provided).
- * @param {jQuery/jqLite element} element the element which will be removed from the DOM
- * @param {function=} done callback function that will be called after the element has been
+ * @param {DOMElement} element the element which will be removed from the DOM
+ * @param {Function=} done callback function that will be called after the element has been
* removed from the DOM
*/
leave : function(element, done) {
element.remove();
- done && $timeout(done, 0, false);
+ async(done);
},
/**
*
- * @ngdoc function
- * @name ng.$animate#move
- * @methodOf ng.$animate
+ * @ngdoc method
+ * @name $animate#move
* @function
* @description Moves the position of the provided element within the DOM to be placed
* either after the `after` element or inside of the `parent` element. Once complete, the
* done() callback will be fired (if provided).
- *
- * @param {jQuery/jqLite element} element the element which will be moved around within the
+ *
+ * @param {DOMElement} element the element which will be moved around within the
* DOM
- * @param {jQuery/jqLite element} parent the parent element where the element will be
+ * @param {DOMElement} parent the parent element where the element will be
* inserted into (if the after element is not present)
- * @param {jQuery/jqLite element} after the sibling element where the element will be
+ * @param {DOMElement} after the sibling element where the element will be
* positioned next to
- * @param {function=} done the callback function (if provided) that will be fired after the
+ * @param {Function=} done the callback function (if provided) that will be fired after the
* element has been moved to its new position
*/
move : function(element, parent, after, done) {
@@ -3932,16 +4063,15 @@ var $AnimateProvider = ['$provide', function($provide) {
/**
*
- * @ngdoc function
- * @name ng.$animate#addClass
- * @methodOf ng.$animate
+ * @ngdoc method
+ * @name $animate#addClass
* @function
* @description Adds the provided className CSS class value to the provided element. Once
* complete, the done() callback will be fired (if provided).
- * @param {jQuery/jqLite element} element the element which will have the className value
+ * @param {DOMElement} element the element which will have the className value
* added to it
* @param {string} className the CSS class which will be added to the element
- * @param {function=} done the callback function (if provided) that will be fired after the
+ * @param {Function=} done the callback function (if provided) that will be fired after the
* className value has been added to the element
*/
addClass : function(element, className, done) {
@@ -3951,21 +4081,20 @@ var $AnimateProvider = ['$provide', function($provide) {
forEach(element, function (element) {
jqLiteAddClass(element, className);
});
- done && $timeout(done, 0, false);
+ async(done);
},
/**
*
- * @ngdoc function
- * @name ng.$animate#removeClass
- * @methodOf ng.$animate
+ * @ngdoc method
+ * @name $animate#removeClass
* @function
* @description Removes the provided className CSS class value from the provided element.
* Once complete, the done() callback will be fired (if provided).
- * @param {jQuery/jqLite element} element the element which will have the className value
+ * @param {DOMElement} element the element which will have the className value
* removed from it
* @param {string} className the CSS class which will be removed from the element
- * @param {function=} done the callback function (if provided) that will be fired after the
+ * @param {Function=} done the callback function (if provided) that will be fired after the
* className value has been removed from the element
*/
removeClass : function(element, className, done) {
@@ -3975,7 +4104,29 @@ var $AnimateProvider = ['$provide', function($provide) {
forEach(element, function (element) {
jqLiteRemoveClass(element, className);
});
- done && $timeout(done, 0, false);
+ async(done);
+ },
+
+ /**
+ *
+ * @ngdoc method
+ * @name $animate#setClass
+ * @function
+ * @description Adds and/or removes the given CSS classes to and from the element.
+ * Once complete, the done() callback will be fired (if provided).
+ * @param {DOMElement} element the element which will it's CSS classes changed
+ * removed from it
+ * @param {string} add the CSS classes which will be added to the element
+ * @param {string} remove the CSS class which will be removed from the element
+ * @param {Function=} done the callback function (if provided) that will be fired after the
+ * CSS classes have been set on the element
+ */
+ setClass : function(element, add, remove, done) {
+ forEach(element, function (element) {
+ jqLiteAddClass(element, add);
+ jqLiteRemoveClass(element, remove);
+ });
+ async(done);
},
enabled : noop
@@ -3983,10 +4134,20 @@ var $AnimateProvider = ['$provide', function($provide) {
}];
}];
+function $$AsyncCallbackProvider(){
+ this.$get = ['$$rAF', '$timeout', function($$rAF, $timeout) {
+ return $$rAF.supported
+ ? function(fn) { return $$rAF(fn); }
+ : function(fn) {
+ return $timeout(fn, 0, false);
+ };
+ }];
+}
+
/**
* ! This is a private undocumented service !
*
- * @name ng.$browser
+ * @name $browser
* @requires $log
* @description
* This object has two goals:
@@ -4070,8 +4231,7 @@ function Browser(window, document, $log, $sniffer) {
pollTimeout;
/**
- * @name ng.$browser#addPollFn
- * @methodOf ng.$browser
+ * @name $browser#addPollFn
*
* @param {function()} fn Poll function to add
*
@@ -4111,8 +4271,7 @@ function Browser(window, document, $log, $sniffer) {
newLocation = null;
/**
- * @name ng.$browser#url
- * @methodOf ng.$browser
+ * @name $browser#url
*
* @description
* GETTER:
@@ -4131,8 +4290,9 @@ function Browser(window, document, $log, $sniffer) {
* @param {boolean=} replace Should new url replace current history record ?
*/
self.url = function(url, replace) {
- // Android Browser BFCache causes location reference to become stale.
+ // Android Browser BFCache causes location, history reference to become stale.
if (location !== window.location) location = window.location;
+ if (history !== window.history) history = window.history;
// setter
if (url) {
@@ -4177,14 +4337,13 @@ function Browser(window, document, $log, $sniffer) {
}
/**
- * @name ng.$browser#onUrlChange
- * @methodOf ng.$browser
+ * @name $browser#onUrlChange
* @TODO(vojta): refactor to use node's syntax for events
*
* @description
* Register callback function that will be called, when url changes.
*
- * It's only called when the url is changed by outside of angular:
+ * It's only called when the url is changed from outside of angular:
* - user types different url into address bar
* - user clicks on history (forward/back) button
* - user clicks on a link
@@ -4224,18 +4383,17 @@ function Browser(window, document, $log, $sniffer) {
//////////////////////////////////////////////////////////////
/**
- * @name ng.$browser#baseHref
- * @methodOf ng.$browser
- *
+ * @name $browser#baseHref
+ *
* @description
* Returns current
* (always relative - without domain)
*
- * @returns {string=} current
+ * @returns {string} The current base href
*/
self.baseHref = function() {
var href = baseElement.attr('href');
- return href ? href.replace(/^https?\:\/\/[^\/]*/, '') : '';
+ return href ? href.replace(/^(https?\:)?\/\/[^\/]*/, '') : '';
};
//////////////////////////////////////////////////////////////
@@ -4246,8 +4404,7 @@ function Browser(window, document, $log, $sniffer) {
var cookiePath = self.baseHref();
/**
- * @name ng.$browser#cookies
- * @methodOf ng.$browser
+ * @name $browser#cookies
*
* @param {string=} name Cookie name
* @param {string=} value Cookie value
@@ -4257,13 +4414,13 @@ function Browser(window, document, $log, $sniffer) {
* It is not meant to be used directly, use the $cookie service instead.
*
* The return values vary depending on the arguments that the method was called with as follows:
- *
+ *
* - cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify
* it
* - cookies(name, value) -> set name to value, if value is undefined delete the cookie
* - cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that
* way)
- *
+ *
* @returns {Object} Hash of all cookies (if called without any parameter)
*/
self.cookies = function(name, value) {
@@ -4316,8 +4473,7 @@ function Browser(window, document, $log, $sniffer) {
/**
- * @name ng.$browser#defer
- * @methodOf ng.$browser
+ * @name $browser#defer
* @param {function()} fn A function, who's execution should be deferred.
* @param {number=} [delay=0] of milliseconds to defer the function execution.
* @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.
@@ -4343,8 +4499,7 @@ function Browser(window, document, $log, $sniffer) {
/**
- * @name ng.$browser#defer.cancel
- * @methodOf ng.$browser.defer
+ * @name $browser#defer.cancel
*
* @description
* Cancels a deferred task identified with `deferId`.
@@ -4373,14 +4528,14 @@ function $BrowserProvider(){
}
/**
- * @ngdoc object
- * @name ng.$cacheFactory
+ * @ngdoc service
+ * @name $cacheFactory
*
* @description
* Factory that constructs cache objects and gives access to them.
- *
- *
- *
+ *
+ * ```js
+ *
* var cache = $cacheFactory('cacheId');
* expect($cacheFactory.get('cacheId')).toBe(cache);
* expect($cacheFactory.get('noSuchCacheId')).not.toBeDefined();
@@ -4389,9 +4544,9 @@ function $BrowserProvider(){
* cache.put("another key", "another value");
*
* // We've specified no options on creation
- * expect(cache.info()).toEqual({id: 'cacheId', size: 2});
- *
- *
+ * expect(cache.info()).toEqual({id: 'cacheId', size: 2});
+ *
+ * ```
*
*
* @param {string} cacheId Name or id of the newly created cache.
@@ -4431,9 +4586,11 @@ function $CacheFactoryProvider() {
return caches[cacheId] = {
put: function(key, value) {
- var lruEntry = lruHash[key] || (lruHash[key] = {key: key});
+ if (capacity < Number.MAX_VALUE) {
+ var lruEntry = lruHash[key] || (lruHash[key] = {key: key});
- refresh(lruEntry);
+ refresh(lruEntry);
+ }
if (isUndefined(value)) return;
if (!(key in data)) size++;
@@ -4448,26 +4605,31 @@ function $CacheFactoryProvider() {
get: function(key) {
- var lruEntry = lruHash[key];
+ if (capacity < Number.MAX_VALUE) {
+ var lruEntry = lruHash[key];
- if (!lruEntry) return;
+ if (!lruEntry) return;
- refresh(lruEntry);
+ refresh(lruEntry);
+ }
return data[key];
},
remove: function(key) {
- var lruEntry = lruHash[key];
+ if (capacity < Number.MAX_VALUE) {
+ var lruEntry = lruHash[key];
+
+ if (!lruEntry) return;
- if (!lruEntry) return;
+ if (lruEntry == freshEnd) freshEnd = lruEntry.p;
+ if (lruEntry == staleEnd) staleEnd = lruEntry.n;
+ link(lruEntry.n,lruEntry.p);
- if (lruEntry == freshEnd) freshEnd = lruEntry.p;
- if (lruEntry == staleEnd) staleEnd = lruEntry.n;
- link(lruEntry.n,lruEntry.p);
+ delete lruHash[key];
+ }
- delete lruHash[key];
delete data[key];
size--;
},
@@ -4528,8 +4690,7 @@ function $CacheFactoryProvider() {
/**
* @ngdoc method
- * @name ng.$cacheFactory#info
- * @methodOf ng.$cacheFactory
+ * @name $cacheFactory#info
*
* @description
* Get information about all the of the caches that have been created
@@ -4547,8 +4708,7 @@ function $CacheFactoryProvider() {
/**
* @ngdoc method
- * @name ng.$cacheFactory#get
- * @methodOf ng.$cacheFactory
+ * @name $cacheFactory#get
*
* @description
* Get access to a cache object by the `cacheId` used when it was created.
@@ -4566,16 +4726,16 @@ function $CacheFactoryProvider() {
}
/**
- * @ngdoc object
- * @name ng.$templateCache
+ * @ngdoc service
+ * @name $templateCache
*
* @description
* The first time a template is used, it is loaded in the template cache for quick retrieval. You
* can load templates directly into the cache in a `script` tag, or by consuming the
* `$templateCache` service directly.
- *
+ *
* Adding via the `script` tag:
- *
+ * ```html
*
*
*
+ *
+ *
+ *
+ * Date format:
+ * Current time is:
+ *
+ * Blood 1 : {{blood_1}}
+ * Blood 2 : {{blood_2}}
+ * Fight
+ * StopFight
+ * resetFight
+ *
+ *
+ *
+ *
+ *
*/
function interval(fn, delay, count, invokeApply) {
var setInterval = $window.setInterval,
@@ -8230,8 +8547,8 @@ function $IntervalProvider() {
promise = deferred.promise,
iteration = 0,
skipApply = (isDefined(invokeApply) && !invokeApply);
-
- count = isDefined(count) ? count : 0,
+
+ count = isDefined(count) ? count : 0;
promise.then(null, null, fn);
@@ -8255,9 +8572,8 @@ function $IntervalProvider() {
/**
- * @ngdoc function
- * @name ng.$interval#cancel
- * @methodOf ng.$interval
+ * @ngdoc method
+ * @name $interval#cancel
*
* @description
* Cancels a task associated with the `promise`.
@@ -8280,8 +8596,8 @@ function $IntervalProvider() {
}
/**
- * @ngdoc object
- * @name ng.$locale
+ * @ngdoc service
+ * @name $locale
*
* @description
* $locale service provides localization rules for various Angular components. As of right now the
@@ -8640,14 +8956,13 @@ LocationHashbangInHtml5Url.prototype =
/**
* @ngdoc method
- * @name ng.$location#absUrl
- * @methodOf ng.$location
+ * @name $location#absUrl
*
* @description
* This method is getter only.
*
* Return full url representation with all segments encoded according to rules specified in
- * {@link http://www.ietf.org/rfc/rfc3986.txt RFC 3986}.
+ * [RFC 3986](http://www.ietf.org/rfc/rfc3986.txt).
*
* @return {string} full url
*/
@@ -8655,8 +8970,7 @@ LocationHashbangInHtml5Url.prototype =
/**
* @ngdoc method
- * @name ng.$location#url
- * @methodOf ng.$location
+ * @name $location#url
*
* @description
* This method is getter / setter.
@@ -8683,8 +8997,7 @@ LocationHashbangInHtml5Url.prototype =
/**
* @ngdoc method
- * @name ng.$location#protocol
- * @methodOf ng.$location
+ * @name $location#protocol
*
* @description
* This method is getter only.
@@ -8697,8 +9010,7 @@ LocationHashbangInHtml5Url.prototype =
/**
* @ngdoc method
- * @name ng.$location#host
- * @methodOf ng.$location
+ * @name $location#host
*
* @description
* This method is getter only.
@@ -8711,8 +9023,7 @@ LocationHashbangInHtml5Url.prototype =
/**
* @ngdoc method
- * @name ng.$location#port
- * @methodOf ng.$location
+ * @name $location#port
*
* @description
* This method is getter only.
@@ -8725,8 +9036,7 @@ LocationHashbangInHtml5Url.prototype =
/**
* @ngdoc method
- * @name ng.$location#path
- * @methodOf ng.$location
+ * @name $location#path
*
* @description
* This method is getter / setter.
@@ -8747,8 +9057,7 @@ LocationHashbangInHtml5Url.prototype =
/**
* @ngdoc method
- * @name ng.$location#search
- * @methodOf ng.$location
+ * @name $location#search
*
* @description
* This method is getter / setter.
@@ -8795,8 +9104,7 @@ LocationHashbangInHtml5Url.prototype =
/**
* @ngdoc method
- * @name ng.$location#hash
- * @methodOf ng.$location
+ * @name $location#hash
*
* @description
* This method is getter / setter.
@@ -8812,8 +9120,7 @@ LocationHashbangInHtml5Url.prototype =
/**
* @ngdoc method
- * @name ng.$location#replace
- * @methodOf ng.$location
+ * @name $location#replace
*
* @description
* If called, all changes to $location during current `$digest` will be replacing current history
@@ -8846,16 +9153,14 @@ function locationGetterSetter(property, preprocess) {
/**
- * @ngdoc object
- * @name ng.$location
+ * @ngdoc service
+ * @name $location
*
- * @requires $browser
- * @requires $sniffer
* @requires $rootElement
*
* @description
* The $location service parses the URL in the browser address bar (based on the
- * {@link https://developer.mozilla.org/en/window.location window.location}) and makes the URL
+ * [window.location](https://developer.mozilla.org/en/window.location)) and makes the URL
* available to your application. Changes to the URL in the address bar are reflected into
* $location service and changes to $location are reflected into the browser address bar.
*
@@ -8875,8 +9180,8 @@ function locationGetterSetter(property, preprocess) {
*/
/**
- * @ngdoc object
- * @name ng.$locationProvider
+ * @ngdoc provider
+ * @name $locationProvider
* @description
* Use the `$locationProvider` to configure how the application deep linking paths are stored.
*/
@@ -8886,8 +9191,7 @@ function $LocationProvider(){
/**
* @ngdoc property
- * @name ng.$locationProvider#hashPrefix
- * @methodOf ng.$locationProvider
+ * @name $locationProvider#hashPrefix
* @description
* @param {string=} prefix Prefix for hash part (containing path and search)
* @returns {*} current value if used as getter or itself (chaining) if used as setter
@@ -8903,8 +9207,7 @@ function $LocationProvider(){
/**
* @ngdoc property
- * @name ng.$locationProvider#html5Mode
- * @methodOf ng.$locationProvider
+ * @name $locationProvider#html5Mode
* @description
* @param {boolean=} mode Use HTML5 strategy if available.
* @returns {*} current value if used as getter or itself (chaining) if used as setter
@@ -8920,14 +9223,13 @@ function $LocationProvider(){
/**
* @ngdoc event
- * @name ng.$location#$locationChangeStart
- * @eventOf ng.$location
+ * @name $location#$locationChangeStart
* @eventType broadcast on root scope
* @description
* Broadcasted before a URL will change. This change can be prevented by calling
* `preventDefault` method of the event. See {@link ng.$rootScope.Scope#$on} for more
* details about event object. Upon successful change
- * {@link ng.$location#$locationChangeSuccess $locationChangeSuccess} is fired.
+ * {@link ng.$location#events_$locationChangeSuccess $locationChangeSuccess} is fired.
*
* @param {Object} angularEvent Synthetic event object.
* @param {string} newUrl New URL
@@ -8936,8 +9238,7 @@ function $LocationProvider(){
/**
* @ngdoc event
- * @name ng.$location#$locationChangeSuccess
- * @eventOf ng.$location
+ * @name $location#$locationChangeSuccess
* @eventType broadcast on root scope
* @description
* Broadcasted after a URL was changed.
@@ -8980,6 +9281,13 @@ function $LocationProvider(){
}
var absHref = elm.prop('href');
+
+ if (isObject(absHref) && absHref.toString() === '[object SVGAnimatedString]') {
+ // SVGAnimatedString.animVal should be identical to SVGAnimatedString.baseVal, unless during
+ // an animation.
+ absHref = urlResolve(absHref.animVal).href;
+ }
+
var rewrittenUrl = $location.$$rewrite(absHref);
if (absHref && !elm.attr('target') && rewrittenUrl && !event.isDefaultPrevented()) {
@@ -9003,16 +9311,17 @@ function $LocationProvider(){
// update $location when $browser url changes
$browser.onUrlChange(function(newUrl) {
if ($location.absUrl() != newUrl) {
- if ($rootScope.$broadcast('$locationChangeStart', newUrl,
- $location.absUrl()).defaultPrevented) {
- $browser.url($location.absUrl());
- return;
- }
$rootScope.$evalAsync(function() {
var oldUrl = $location.absUrl();
$location.$$parse(newUrl);
- afterLocationChange(oldUrl);
+ if ($rootScope.$broadcast('$locationChangeStart', newUrl,
+ oldUrl).defaultPrevented) {
+ $location.$$parse(oldUrl);
+ $browser.url(oldUrl);
+ } else {
+ afterLocationChange(oldUrl);
+ }
});
if (!$rootScope.$$phase) $rootScope.$digest();
}
@@ -9050,14 +9359,14 @@ function $LocationProvider(){
}
/**
- * @ngdoc object
- * @name ng.$log
+ * @ngdoc service
+ * @name $log
* @requires $window
*
* @description
* Simple service for logging. Default implementation safely writes the message
* into the browser's console (if present).
- *
+ *
* The main purpose of this service is to simplify debugging and troubleshooting.
*
* The default is to log `debug` messages. You can use
@@ -9086,21 +9395,20 @@ function $LocationProvider(){
*/
/**
- * @ngdoc object
- * @name ng.$logProvider
+ * @ngdoc provider
+ * @name $logProvider
* @description
* Use the `$logProvider` to configure how the application logs messages
*/
function $LogProvider(){
var debug = true,
self = this;
-
+
/**
* @ngdoc property
- * @name ng.$logProvider#debugEnabled
- * @methodOf ng.$logProvider
+ * @name $logProvider#debugEnabled
* @description
- * @param {string=} flag enable or disable debug level messages
+ * @param {boolean=} flag enable or disable debug level messages
* @returns {*} current value if used as getter or itself (chaining) if used as setter
*/
this.debugEnabled = function(flag) {
@@ -9111,13 +9419,12 @@ function $LogProvider(){
return debug;
}
};
-
+
this.$get = ['$window', function($window){
return {
/**
* @ngdoc method
- * @name ng.$log#log
- * @methodOf ng.$log
+ * @name $log#log
*
* @description
* Write a log message
@@ -9126,8 +9433,7 @@ function $LogProvider(){
/**
* @ngdoc method
- * @name ng.$log#info
- * @methodOf ng.$log
+ * @name $log#info
*
* @description
* Write an information message
@@ -9136,8 +9442,7 @@ function $LogProvider(){
/**
* @ngdoc method
- * @name ng.$log#warn
- * @methodOf ng.$log
+ * @name $log#warn
*
* @description
* Write a warning message
@@ -9146,19 +9451,17 @@ function $LogProvider(){
/**
* @ngdoc method
- * @name ng.$log#error
- * @methodOf ng.$log
+ * @name $log#error
*
* @description
* Write an error message
*/
error: consoleLog('error'),
-
+
/**
* @ngdoc method
- * @name ng.$log#debug
- * @methodOf ng.$log
- *
+ * @name $log#debug
+ *
* @description
* Write a debug message
*/
@@ -9188,9 +9491,16 @@ function $LogProvider(){
function consoleLog(type) {
var console = $window.console || {},
- logFn = console[type] || console.log || noop;
+ logFn = console[type] || console.log || noop,
+ hasApply = false;
- if (logFn.apply) {
+ // Note: reading logFn.apply throws an error in IE11 in IE8 document mode.
+ // The reason behind this is that console.log has type "object" in IE8...
+ try {
+ hasApply = !!logFn.apply;
+ } catch (e) {}
+
+ if (hasApply) {
return function() {
var args = [];
forEach(arguments, function(arg) {
@@ -9264,7 +9574,7 @@ function ensureSafeObject(obj, fullExpression) {
'Referencing the Window in Angular expressions is disallowed! Expression: {0}',
fullExpression);
} else if (// isElement(obj)
- obj.children && (obj.nodeName || (obj.on && obj.find))) {
+ obj.children && (obj.nodeName || (obj.prop && obj.attr && obj.find))) {
throw $parseMinErr('isecdom',
'Referencing DOM nodes in Angular expressions is disallowed! Expression: {0}',
fullExpression);
@@ -9916,7 +10226,7 @@ Parser.prototype = {
var getter = getterFn(field, this.options, this.text);
return extend(function(scope, locals, self) {
- return getter(self || object(scope, locals), locals);
+ return getter(self || object(scope, locals));
}, {
assign: function(scope, value, locals) {
return setter(object(scope, locals), field, value, parser.text, parser.options);
@@ -9994,6 +10304,10 @@ Parser.prototype = {
var allConstant = true;
if (this.peekToken().text !== ']') {
do {
+ if (this.peek(']')) {
+ // Support trailing commas per ES5.1.
+ break;
+ }
var elementFn = this.expression();
elementFns.push(elementFn);
if (!elementFn.constant) {
@@ -10020,6 +10334,10 @@ Parser.prototype = {
var allConstant = true;
if (this.peekToken().text !== '}') {
do {
+ if (this.peek('}')) {
+ // Support trailing commas per ES5.1.
+ break;
+ }
var token = this.expect(),
key = token.string || token.text;
this.consume(':');
@@ -10100,19 +10418,23 @@ function cspSafeGetterFn(key0, key1, key2, key3, key4, fullExp, options) {
? function cspSafeGetter(scope, locals) {
var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope;
- if (pathVal === null || pathVal === undefined) return pathVal;
+ if (pathVal == null) return pathVal;
pathVal = pathVal[key0];
- if (!key1 || pathVal === null || pathVal === undefined) return pathVal;
+ if (!key1) return pathVal;
+ if (pathVal == null) return undefined;
pathVal = pathVal[key1];
- if (!key2 || pathVal === null || pathVal === undefined) return pathVal;
+ if (!key2) return pathVal;
+ if (pathVal == null) return undefined;
pathVal = pathVal[key2];
- if (!key3 || pathVal === null || pathVal === undefined) return pathVal;
+ if (!key3) return pathVal;
+ if (pathVal == null) return undefined;
pathVal = pathVal[key3];
- if (!key4 || pathVal === null || pathVal === undefined) return pathVal;
+ if (!key4) return pathVal;
+ if (pathVal == null) return undefined;
pathVal = pathVal[key4];
return pathVal;
@@ -10121,7 +10443,7 @@ function cspSafeGetterFn(key0, key1, key2, key3, key4, fullExp, options) {
var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope,
promise;
- if (pathVal === null || pathVal === undefined) return pathVal;
+ if (pathVal == null) return pathVal;
pathVal = pathVal[key0];
if (pathVal && pathVal.then) {
@@ -10133,8 +10455,9 @@ function cspSafeGetterFn(key0, key1, key2, key3, key4, fullExp, options) {
}
pathVal = pathVal.$$v;
}
- if (!key1 || pathVal === null || pathVal === undefined) return pathVal;
+ if (!key1) return pathVal;
+ if (pathVal == null) return undefined;
pathVal = pathVal[key1];
if (pathVal && pathVal.then) {
promiseWarning(fullExp);
@@ -10145,8 +10468,9 @@ function cspSafeGetterFn(key0, key1, key2, key3, key4, fullExp, options) {
}
pathVal = pathVal.$$v;
}
- if (!key2 || pathVal === null || pathVal === undefined) return pathVal;
+ if (!key2) return pathVal;
+ if (pathVal == null) return undefined;
pathVal = pathVal[key2];
if (pathVal && pathVal.then) {
promiseWarning(fullExp);
@@ -10157,8 +10481,9 @@ function cspSafeGetterFn(key0, key1, key2, key3, key4, fullExp, options) {
}
pathVal = pathVal.$$v;
}
- if (!key3 || pathVal === null || pathVal === undefined) return pathVal;
+ if (!key3) return pathVal;
+ if (pathVal == null) return undefined;
pathVal = pathVal[key3];
if (pathVal && pathVal.then) {
promiseWarning(fullExp);
@@ -10169,8 +10494,9 @@ function cspSafeGetterFn(key0, key1, key2, key3, key4, fullExp, options) {
}
pathVal = pathVal.$$v;
}
- if (!key4 || pathVal === null || pathVal === undefined) return pathVal;
+ if (!key4) return pathVal;
+ if (pathVal == null) return undefined;
pathVal = pathVal[key4];
if (pathVal && pathVal.then) {
promiseWarning(fullExp);
@@ -10185,6 +10511,26 @@ function cspSafeGetterFn(key0, key1, key2, key3, key4, fullExp, options) {
};
}
+function simpleGetterFn1(key0, fullExp) {
+ ensureSafeMemberName(key0, fullExp);
+
+ return function simpleGetterFn1(scope, locals) {
+ if (scope == null) return undefined;
+ return ((locals && locals.hasOwnProperty(key0)) ? locals : scope)[key0];
+ };
+}
+
+function simpleGetterFn2(key0, key1, fullExp) {
+ ensureSafeMemberName(key0, fullExp);
+ ensureSafeMemberName(key1, fullExp);
+
+ return function simpleGetterFn2(scope, locals) {
+ if (scope == null) return undefined;
+ scope = ((locals && locals.hasOwnProperty(key0)) ? locals : scope)[key0];
+ return scope == null ? undefined : scope[key1];
+ };
+}
+
function getterFn(path, options, fullExp) {
// Check whether the cache has this getter already.
// We can use hasOwnProperty directly on the cache because we ensure,
@@ -10197,7 +10543,13 @@ function getterFn(path, options, fullExp) {
pathKeysLength = pathKeys.length,
fn;
- if (options.csp) {
+ // When we have only 1 or 2 tokens, use optimized special case closures.
+ // http://jsperf.com/angularjs-parse-getter/6
+ if (!options.unwrapPromises && pathKeysLength === 1) {
+ fn = simpleGetterFn1(pathKeys[0], fullExp);
+ } else if (!options.unwrapPromises && pathKeysLength === 2) {
+ fn = simpleGetterFn2(pathKeys[0], pathKeys[1], fullExp);
+ } else if (options.csp) {
if (pathKeysLength < 6) {
fn = cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4], fullExp,
options);
@@ -10215,11 +10567,10 @@ function getterFn(path, options, fullExp) {
};
}
} else {
- var code = 'var l, fn, p;\n';
+ var code = 'var p;\n';
forEach(pathKeys, function(key, index) {
ensureSafeMemberName(key, fullExp);
- code += 'if(s === null || s === undefined) return s;\n' +
- 'l=s;\n' +
+ code += 'if(s == null) return undefined;\n' +
's='+ (index
// we simply dereference 's' on any .dot notation
? 's'
@@ -10242,10 +10593,10 @@ function getterFn(path, options, fullExp) {
/* jshint -W054 */
var evaledFnGetter = new Function('s', 'k', 'pw', code); // s=scope, k=locals, pw=promiseWarning
/* jshint +W054 */
- evaledFnGetter.toString = function() { return code; };
- fn = function(scope, locals) {
+ evaledFnGetter.toString = valueFn(code);
+ fn = options.unwrapPromises ? function(scope, locals) {
return evaledFnGetter(scope, locals, promiseWarning);
- };
+ } : evaledFnGetter;
}
// Only cache the value if it's not going to mess up the cache object
@@ -10259,15 +10610,15 @@ function getterFn(path, options, fullExp) {
///////////////////////////////////
/**
- * @ngdoc function
- * @name ng.$parse
- * @function
+ * @ngdoc service
+ * @name $parse
+ * @kind function
*
* @description
*
* Converts Angular {@link guide/expression expression} into a function.
*
- *
+ * ```js
* var getter = $parse('user.name');
* var setter = getter.assign;
* var context = {user:{name:'angular'}};
@@ -10277,7 +10628,7 @@ function getterFn(path, options, fullExp) {
* setter(context, 'newValue');
* expect(context.user.name).toEqual('newValue');
* expect(getter(context, locals)).toEqual('local');
- *
+ * ```
*
*
* @param {string} expression String expression to compile.
@@ -10300,8 +10651,8 @@ function getterFn(path, options, fullExp) {
/**
- * @ngdoc object
- * @name ng.$parseProvider
+ * @ngdoc provider
+ * @name $parseProvider
* @function
*
* @description
@@ -10322,8 +10673,7 @@ function $ParseProvider() {
* @deprecated Promise unwrapping via $parse is deprecated and will be removed in the future.
*
* @ngdoc method
- * @name ng.$parseProvider#unwrapPromises
- * @methodOf ng.$parseProvider
+ * @name $parseProvider#unwrapPromises
* @description
*
* **This feature is deprecated, see deprecation notes below for more info**
@@ -10377,8 +10727,7 @@ function $ParseProvider() {
* @deprecated Promise unwrapping via $parse is deprecated and will be removed in the future.
*
* @ngdoc method
- * @name ng.$parseProvider#logPromiseWarnings
- * @methodOf ng.$parseProvider
+ * @name $parseProvider#logPromiseWarnings
* @description
*
* Controls whether Angular should log a warning on any encounter of a promise in an expression.
@@ -10445,7 +10794,7 @@ function $ParseProvider() {
/**
* @ngdoc service
- * @name ng.$q
+ * @name $q
* @requires $rootScope
*
* @description
@@ -10458,9 +10807,9 @@ function $ParseProvider() {
* From the perspective of dealing with error handling, deferred and promise APIs are to
* asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.
*
- *
- * // for the purpose of this example let's assume that variables `$q` and `scope` are
- * // available in the current lexical scope (they could have been injected or passed in).
+ * ```js
+ * // for the purpose of this example let's assume that variables `$q`, `scope` and `okToGreet`
+ * // are available in the current lexical scope (they could have been injected or passed in).
*
* function asyncGreet(name) {
* var deferred = $q.defer();
@@ -10490,7 +10839,7 @@ function $ParseProvider() {
* }, function(update) {
* alert('Got notification: ' + update);
* });
- *
+ * ```
*
* At first it might not be obvious why this extra complexity is worth the trouble. The payoff
* comes in the way of guarantees that promise and deferred APIs make, see
@@ -10516,7 +10865,7 @@ function $ParseProvider() {
* constructed via `$q.reject`, the promise will be rejected instead.
* - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to
* resolving it with a rejection constructed via `$q.reject`.
- * - `notify(value)` - provides updates on the status of the promises execution. This may be called
+ * - `notify(value)` - provides updates on the status of the promise's execution. This may be called
* multiple times before the promise is either resolved or rejected.
*
* **Properties**
@@ -10562,14 +10911,14 @@ function $ParseProvider() {
* Because calling the `then` method of a promise returns a new derived promise, it is easily
* possible to create a chain of promises:
*
- *
+ * ```js
* promiseB = promiseA.then(function(result) {
* return result + 1;
* });
*
* // promiseB will be resolved immediately after promiseA is resolved and its value
* // will be the result of promiseA incremented by 1
- *
+ * ```
*
* It is possible to create chains of any length and since a promise can be resolved with another
* promise (which will defer its resolution further), it is possible to pause/defer resolution of
@@ -10579,7 +10928,7 @@ function $ParseProvider() {
*
* # Differences between Kris Kowal's Q and $q
*
- * There are three main differences:
+ * There are two main differences:
*
* - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation
* mechanism in angular, which means faster propagation of resolution or rejection into your
@@ -10589,7 +10938,7 @@ function $ParseProvider() {
*
* # Testing
*
- *
+ * ```js
* it('should simulate promise', inject(function($q, $rootScope) {
* var deferred = $q.defer();
* var promise = deferred.promise;
@@ -10609,7 +10958,7 @@ function $ParseProvider() {
* $rootScope.$apply();
* expect(resolvedValue).toEqual(123);
* }));
- *
+ * ```
*/
function $QProvider() {
@@ -10624,7 +10973,7 @@ function $QProvider() {
/**
* Constructs a promise manager.
*
- * @param {function(function)} nextTick Function for executing functions in the next turn.
+ * @param {function(Function)} nextTick Function for executing functions in the next turn.
* @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for
* debugging purposes.
* @returns {object} Promise manager.
@@ -10632,9 +10981,10 @@ function $QProvider() {
function qFactory(nextTick, exceptionHandler) {
/**
- * @ngdoc
- * @name ng.$q#defer
- * @methodOf ng.$q
+ * @ngdoc method
+ * @name $q#defer
+ * @function
+ *
* @description
* Creates a `Deferred` object which represents a task which will finish in the future.
*
@@ -10666,7 +11016,7 @@ function qFactory(nextTick, exceptionHandler) {
reject: function(reason) {
- deferred.resolve(reject(reason));
+ deferred.resolve(createInternalRejectedPromise(reason));
},
@@ -10788,9 +11138,10 @@ function qFactory(nextTick, exceptionHandler) {
/**
- * @ngdoc
- * @name ng.$q#reject
- * @methodOf ng.$q
+ * @ngdoc method
+ * @name $q#reject
+ * @function
+ *
* @description
* Creates a promise that is resolved as rejected with the specified `reason`. This api should be
* used to forward rejection in a chain of promises. If you are dealing with the last promise in
@@ -10802,7 +11153,7 @@ function qFactory(nextTick, exceptionHandler) {
* current promise, you have to "rethrow" the error by returning a rejection constructed via
* `reject`.
*
- *
+ * ```js
* promiseB = promiseA.then(function(result) {
* // success: do something and resolve promiseB
* // with the old or a new result
@@ -10817,12 +11168,18 @@ function qFactory(nextTick, exceptionHandler) {
* }
* return $q.reject(reason);
* });
- *
+ * ```
*
* @param {*} reason Constant, message, exception or an object representing the rejection reason.
* @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.
*/
var reject = function(reason) {
+ var result = defer();
+ result.reject(reason);
+ return result.promise;
+ };
+
+ var createInternalRejectedPromise = function(reason) {
return {
then: function(callback, errback) {
var result = defer();
@@ -10841,9 +11198,10 @@ function qFactory(nextTick, exceptionHandler) {
/**
- * @ngdoc
- * @name ng.$q#when
- * @methodOf ng.$q
+ * @ngdoc method
+ * @name $q#when
+ * @function
+ *
* @description
* Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.
* This is useful when you are dealing with an object that might or might not be a promise, or if
@@ -10912,9 +11270,10 @@ function qFactory(nextTick, exceptionHandler) {
/**
- * @ngdoc
- * @name ng.$q#all
- * @methodOf ng.$q
+ * @ngdoc method
+ * @name $q#all
+ * @function
+ *
* @description
* Combines multiple promises into a single promise that is resolved when all of the input
* promises are resolved.
@@ -10957,6 +11316,27 @@ function qFactory(nextTick, exceptionHandler) {
};
}
+function $$RAFProvider(){ //rAF
+ this.$get = ['$window', function($window) {
+ var requestAnimationFrame = $window.requestAnimationFrame ||
+ $window.webkitRequestAnimationFrame;
+
+ var cancelAnimationFrame = $window.cancelAnimationFrame ||
+ $window.webkitCancelAnimationFrame;
+
+ var raf = function(fn) {
+ var id = requestAnimationFrame(fn);
+ return function() {
+ cancelAnimationFrame(id);
+ };
+ };
+
+ raf.supported = !!requestAnimationFrame;
+
+ return raf;
+ }];
+}
+
/**
* DESIGN NOTES
*
@@ -10984,17 +11364,16 @@ function qFactory(nextTick, exceptionHandler) {
/**
- * @ngdoc object
- * @name ng.$rootScopeProvider
+ * @ngdoc provider
+ * @name $rootScopeProvider
* @description
*
* Provider for the $rootScope service.
*/
/**
- * @ngdoc function
- * @name ng.$rootScopeProvider#digestTtl
- * @methodOf ng.$rootScopeProvider
+ * @ngdoc method
+ * @name $rootScopeProvider#digestTtl
* @description
*
* Sets the number of `$digest` iterations the scope should attempt to execute before giving up and
@@ -11015,8 +11394,8 @@ function qFactory(nextTick, exceptionHandler) {
/**
- * @ngdoc object
- * @name ng.$rootScope
+ * @ngdoc service
+ * @name $rootScope
* @description
*
* Every application has a single root {@link ng.$rootScope.Scope scope}.
@@ -11041,23 +11420,23 @@ function $RootScopeProvider(){
function( $injector, $exceptionHandler, $parse, $browser) {
/**
- * @ngdoc function
- * @name ng.$rootScope.Scope
+ * @ngdoc type
+ * @name $rootScope.Scope
*
* @description
* A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the
- * {@link AUTO.$injector $injector}. Child scopes are created using the
- * {@link ng.$rootScope.Scope#methods_$new $new()} method. (Most scopes are created automatically when
+ * {@link auto.$injector $injector}. Child scopes are created using the
+ * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when
* compiled HTML template is executed.)
*
* Here is a simple scope snippet to show how you can interact with the scope.
- *
+ * ```html
*
- *
+ * ```
*
* # Inheritance
* A scope can inherit from a parent scope, as in this example:
- *
+ * ```js
var parent = $rootScope;
var child = parent.$new();
@@ -11068,7 +11447,7 @@ function $RootScopeProvider(){
child.salutation = "Welcome";
expect(child.salutation).toEqual('Welcome');
expect(parent.salutation).toEqual('Hello');
- *
+ * ```
*
*
* @param {Object.=} providers Map of service factory which need to be
@@ -11090,12 +11469,13 @@ function $RootScopeProvider(){
this.$$asyncQueue = [];
this.$$postDigestQueue = [];
this.$$listeners = {};
+ this.$$listenerCount = {};
this.$$isolateBindings = {};
}
/**
* @ngdoc property
- * @name ng.$rootScope.Scope#$id
+ * @name $rootScope.Scope#$id
* @propertyOf ng.$rootScope.Scope
* @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for
* debugging.
@@ -11105,9 +11485,8 @@ function $RootScopeProvider(){
Scope.prototype = {
constructor: Scope,
/**
- * @ngdoc function
- * @name ng.$rootScope.Scope#$new
- * @methodOf ng.$rootScope.Scope
+ * @ngdoc method
+ * @name $rootScope.Scope#$new
* @function
*
* @description
@@ -11142,13 +11521,14 @@ function $RootScopeProvider(){
} else {
ChildScope = function() {}; // should be anonymous; This is so that when the minifier munges
// the name it does not become random set of chars. This will then show up as class
- // name in the debugger.
+ // name in the web inspector.
ChildScope.prototype = this;
child = new ChildScope();
child.$id = nextUid();
}
child['this'] = child;
child.$$listeners = {};
+ child.$$listenerCount = {};
child.$parent = this;
child.$$watchers = child.$$nextSibling = child.$$childHead = child.$$childTail = null;
child.$$prevSibling = this.$$childTail;
@@ -11162,9 +11542,8 @@ function $RootScopeProvider(){
},
/**
- * @ngdoc function
- * @name ng.$rootScope.Scope#$watch
- * @methodOf ng.$rootScope.Scope
+ * @ngdoc method
+ * @name $rootScope.Scope#$watch
* @function
*
* @description
@@ -11202,7 +11581,7 @@ function $RootScopeProvider(){
*
*
* # Example
- *
+ * ```js
// let's assume that scope was dependency injected as the $rootScope
var scope = $rootScope;
scope.name = 'misko';
@@ -11242,7 +11621,7 @@ function $RootScopeProvider(){
// No digest has been run so the counter will be zero
expect(scope.foodCounter).toEqual(0);
- // Run the digest but since food has not changed cout will still be zero
+ // Run the digest but since food has not changed count will still be zero
scope.$digest();
expect(scope.foodCounter).toEqual(0);
@@ -11251,7 +11630,7 @@ function $RootScopeProvider(){
scope.$digest();
expect(scope.foodCounter).toEqual(1);
- *
+ * ```
*
*
*
@@ -11308,14 +11687,14 @@ function $RootScopeProvider(){
return function() {
arrayRemove(array, watcher);
+ lastDirtyWatch = null;
};
},
/**
- * @ngdoc function
- * @name ng.$rootScope.Scope#$watchCollection
- * @methodOf ng.$rootScope.Scope
+ * @ngdoc method
+ * @name $rootScope.Scope#$watchCollection
* @function
*
* @description
@@ -11330,7 +11709,7 @@ function $RootScopeProvider(){
*
*
* # Example
- *
+ * ```js
$scope.names = ['igor', 'matias', 'misko', 'james'];
$scope.dataCount = 4;
@@ -11349,10 +11728,10 @@ function $RootScopeProvider(){
//now there's been a change
expect($scope.dataCount).toEqual(3);
- *
+ * ```
*
*
- * @param {string|Function(scope)} obj Evaluated as {@link guide/expression expression}. The
+ * @param {string|function(scope)} obj Evaluated as {@link guide/expression expression}. The
* expression value should evaluate to an object or an array which is observed on each
* {@link ng.$rootScope.Scope#$digest $digest} cycle. Any shallow change within the
* collection will trigger a call to the `listener`.
@@ -11453,9 +11832,8 @@ function $RootScopeProvider(){
},
/**
- * @ngdoc function
- * @name ng.$rootScope.Scope#$digest
- * @methodOf ng.$rootScope.Scope
+ * @ngdoc method
+ * @name $rootScope.Scope#$digest
* @function
*
* @description
@@ -11468,9 +11846,9 @@ function $RootScopeProvider(){
*
* Usually, you don't call `$digest()` directly in
* {@link ng.directive:ngController controllers} or in
- * {@link ng.$compileProvider#methods_directive directives}.
+ * {@link ng.$compileProvider#directive directives}.
* Instead, you should call {@link ng.$rootScope.Scope#$apply $apply()} (typically from within
- * a {@link ng.$compileProvider#methods_directive directives}), which will force a `$digest()`.
+ * a {@link ng.$compileProvider#directive directives}), which will force a `$digest()`.
*
* If you want to be notified whenever `$digest()` is called,
* you can register a `watchExpression` function with
@@ -11479,7 +11857,7 @@ function $RootScopeProvider(){
* In unit tests, you may need to call `$digest()` to simulate the scope life cycle.
*
* # Example
- *
+ * ```js
var scope = ...;
scope.name = 'misko';
scope.counter = 0;
@@ -11497,7 +11875,7 @@ function $RootScopeProvider(){
scope.name = 'adam';
scope.$digest();
expect(scope.counter).toEqual(1);
- *
+ * ```
*
*/
$digest: function() {
@@ -11586,7 +11964,7 @@ function $RootScopeProvider(){
// `break traverseScopesLoop;` takes us to here
- if(dirty && !(ttl--)) {
+ if((dirty || asyncQueue.length) && !(ttl--)) {
clearPhase();
throw $rootScopeMinErr('infdig',
'{0} $digest() iterations reached. Aborting!\n' +
@@ -11610,7 +11988,7 @@ function $RootScopeProvider(){
/**
* @ngdoc event
- * @name ng.$rootScope.Scope#$destroy
+ * @name $rootScope.Scope#$destroy
* @eventOf ng.$rootScope.Scope
* @eventType broadcast on scope being destroyed
*
@@ -11622,9 +12000,8 @@ function $RootScopeProvider(){
*/
/**
- * @ngdoc function
- * @name ng.$rootScope.Scope#$destroy
- * @methodOf ng.$rootScope.Scope
+ * @ngdoc method
+ * @name $rootScope.Scope#$destroy
* @function
*
* @description
@@ -11653,6 +12030,8 @@ function $RootScopeProvider(){
this.$$destroyed = true;
if (this === $rootScope) return;
+ forEach(this.$$listenerCount, bind(null, decrementListenerCount, this));
+
if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;
if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;
if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;
@@ -11665,9 +12044,8 @@ function $RootScopeProvider(){
},
/**
- * @ngdoc function
- * @name ng.$rootScope.Scope#$eval
- * @methodOf ng.$rootScope.Scope
+ * @ngdoc method
+ * @name $rootScope.Scope#$eval
* @function
*
* @description
@@ -11676,14 +12054,14 @@ function $RootScopeProvider(){
* expressions.
*
* # Example
- *
+ * ```js
var scope = ng.$rootScope.Scope();
scope.a = 1;
scope.b = 2;
expect(scope.$eval('a+b')).toEqual(3);
expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);
- *
+ * ```
*
* @param {(string|function())=} expression An angular expression to be executed.
*
@@ -11698,9 +12076,8 @@ function $RootScopeProvider(){
},
/**
- * @ngdoc function
- * @name ng.$rootScope.Scope#$evalAsync
- * @methodOf ng.$rootScope.Scope
+ * @ngdoc method
+ * @name $rootScope.Scope#$evalAsync
* @function
*
* @description
@@ -11746,9 +12123,8 @@ function $RootScopeProvider(){
},
/**
- * @ngdoc function
- * @name ng.$rootScope.Scope#$apply
- * @methodOf ng.$rootScope.Scope
+ * @ngdoc method
+ * @name $rootScope.Scope#$apply
* @function
*
* @description
@@ -11761,7 +12137,7 @@ function $RootScopeProvider(){
* ## Life cycle
*
* # Pseudo-Code of `$apply()`
- *
+ * ```js
function $apply(expr) {
try {
return $eval(expr);
@@ -11771,7 +12147,7 @@ function $RootScopeProvider(){
$root.$digest();
}
}
- *
+ * ```
*
*
* Scope's `$apply()` method transitions through the following stages:
@@ -11809,9 +12185,8 @@ function $RootScopeProvider(){
},
/**
- * @ngdoc function
- * @name ng.$rootScope.Scope#$on
- * @methodOf ng.$rootScope.Scope
+ * @ngdoc method
+ * @name $rootScope.Scope#$on
* @function
*
* @description
@@ -11842,16 +12217,25 @@ function $RootScopeProvider(){
}
namedListeners.push(listener);
+ var current = this;
+ do {
+ if (!current.$$listenerCount[name]) {
+ current.$$listenerCount[name] = 0;
+ }
+ current.$$listenerCount[name]++;
+ } while ((current = current.$parent));
+
+ var self = this;
return function() {
namedListeners[indexOf(namedListeners, listener)] = null;
+ decrementListenerCount(self, 1, name);
};
},
/**
- * @ngdoc function
- * @name ng.$rootScope.Scope#$emit
- * @methodOf ng.$rootScope.Scope
+ * @ngdoc method
+ * @name $rootScope.Scope#$emit
* @function
*
* @description
@@ -11868,7 +12252,7 @@ function $RootScopeProvider(){
* onto the {@link ng.$exceptionHandler $exceptionHandler} service.
*
* @param {string} name Event name to emit.
- * @param {...*} args Optional set of arguments which will be passed onto the event listeners.
+ * @param {...*} args Optional one or more arguments which will be passed onto the event listeners.
* @return {Object} Event object (see {@link ng.$rootScope.Scope#$on}).
*/
$emit: function(name, args) {
@@ -11918,9 +12302,8 @@ function $RootScopeProvider(){
/**
- * @ngdoc function
- * @name ng.$rootScope.Scope#$broadcast
- * @methodOf ng.$rootScope.Scope
+ * @ngdoc method
+ * @name $rootScope.Scope#$broadcast
* @function
*
* @description
@@ -11936,7 +12319,7 @@ function $RootScopeProvider(){
* onto the {@link ng.$exceptionHandler $exceptionHandler} service.
*
* @param {string} name Event name to broadcast.
- * @param {...*} args Optional set of arguments which will be passed onto the event listeners.
+ * @param {...*} args Optional one or more arguments which will be passed onto the event listeners.
* @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}
*/
$broadcast: function(name, args) {
@@ -11955,8 +12338,7 @@ function $RootScopeProvider(){
listeners, i, length;
//down while you can, then up and next sibling or up and next sibling until back at root
- do {
- current = next;
+ while ((current = next)) {
event.currentScope = current;
listeners = current.$$listeners[name] || [];
for (i=0, length = listeners.length; i
@@ -12576,15 +12965,15 @@ function $SceDelegateProvider() {
* `templateUrl`'s specified by {@link guide/directive directives}.
*
* By default, Angular only loads templates from the same domain and protocol as the application
- * document. This is done by calling {@link ng.$sce#methods_getTrustedResourceUrl
+ * document. This is done by calling {@link ng.$sce#getTrustedResourceUrl
* $sce.getTrustedResourceUrl} on the template URL. To load templates from other domains and/or
- * protocols, you may either either {@link ng.$sceDelegateProvider#methods_resourceUrlWhitelist whitelist
- * them} or {@link ng.$sce#methods_trustAsResourceUrl wrap it} into a trusted value.
+ * protocols, you may either either {@link ng.$sceDelegateProvider#resourceUrlWhitelist whitelist
+ * them} or {@link ng.$sce#trustAsResourceUrl wrap it} into a trusted value.
*
* *Please note*:
* The browser's
- * {@link https://code.google.com/p/browsersec/wiki/Part2#Same-origin_policy_for_XMLHttpRequest
- * Same Origin Policy} and {@link http://www.w3.org/TR/cors/ Cross-Origin Resource Sharing (CORS)}
+ * [Same Origin Policy](https://code.google.com/p/browsersec/wiki/Part2#Same-origin_policy_for_XMLHttpRequest)
+ * and [Cross-Origin Resource Sharing (CORS)](http://www.w3.org/TR/cors/)
* policy apply in addition to this and may further restrict whether the template is successfully
* loaded. This means that without the right CORS policy, loading templates from a different domain
* won't work on all browsers. Also, loading templates from `file://` URL does not work on some
@@ -12595,18 +12984,18 @@ function $SceDelegateProvider() {
* It's important to remember that SCE only applies to interpolation expressions.
*
* If your expressions are constant literals, they're automatically trusted and you don't need to
- * call `$sce.trustAs` on them. (e.g.
- * `
`) just works.
+ * call `$sce.trustAs` on them (remember to include the `ngSanitize` module) (e.g.
+ * `
`) just works.
*
* Additionally, `a[href]` and `img[src]` automatically sanitize their URLs and do not pass them
- * through {@link ng.$sce#methods_getTrusted $sce.getTrusted}. SCE doesn't play a role here.
+ * through {@link ng.$sce#getTrusted $sce.getTrusted}. SCE doesn't play a role here.
*
* The included {@link ng.$sceDelegate $sceDelegate} comes with sane defaults to allow you to load
* templates in `ng-include` from your application's domain without having to even know about SCE.
* It blocks loading templates from other domains or loading templates over http from an https
* served document. You can change these by setting your own custom {@link
- * ng.$sceDelegateProvider#methods_resourceUrlWhitelist whitelists} and {@link
- * ng.$sceDelegateProvider#methods_resourceUrlBlacklist blacklists} for matching such URLs.
+ * ng.$sceDelegateProvider#resourceUrlWhitelist whitelists} and {@link
+ * ng.$sceDelegateProvider#resourceUrlBlacklist blacklists} for matching such URLs.
*
* This significantly reduces the overhead. It is far easier to pay the small overhead and have an
* application that's secure and can be audited to verify that with much more ease than bolting
@@ -12623,7 +13012,7 @@ function $SceDelegateProvider() {
* | `$sce.RESOURCE_URL` | For URLs that are not only safe to follow as links, but whose contens are also safe to include in your application. Examples include `ng-include`, `src` / `ngSrc` bindings for tags other than `IMG` (e.g. `IFRAME`, `OBJECT`, etc.) Note that `$sce.RESOURCE_URL` makes a stronger statement about the URL than `$sce.URL` does and therefore contexts requiring values trusted for `$sce.RESOURCE_URL` can be used anywhere that values trusted for `$sce.URL` are required. |
* | `$sce.JS` | For JavaScript that is safe to execute in your application's context. Currently unused. Feel free to use it in your own directives. |
*
- * ## Format of items in {@link ng.$sceDelegateProvider#methods_resourceUrlWhitelist resourceUrlWhitelist}/{@link ng.$sceDelegateProvider#methods_resourceUrlBlacklist Blacklist}
+ * ## Format of items in {@link ng.$sceDelegateProvider#resourceUrlWhitelist resourceUrlWhitelist}/{@link ng.$sceDelegateProvider#resourceUrlBlacklist Blacklist}
*
* Each element in these arrays must be one of the following:
*
@@ -12635,10 +13024,10 @@ function $SceDelegateProvider() {
* being tested (substring matches are not good enough.)
* - There are exactly **two wildcard sequences** - `*` and `**`. All other characters
* match themselves.
- * - `*`: matches zero or more occurances of any character other than one of the following 6
+ * - `*`: matches zero or more occurrences of any character other than one of the following 6
* characters: '`:`', '`/`', '`.`', '`?`', '`&`' and ';'. It's a useful wildcard for use
* in a whitelist.
- * - `**`: matches zero or more occurances of *any* character. As such, it's not
+ * - `**`: matches zero or more occurrences of *any* character. As such, it's not
* not appropriate to use in for a scheme, domain, etc. as it would match too much. (e.g.
* http://**.example.com/ would match http://evil.com/?ignore=.example.com/ and that might
* not have been the intention.) It's usage at the very end of the path is ok. (e.g.
@@ -12656,7 +13045,7 @@ function $SceDelegateProvider() {
* matched against the **entire** *normalized / absolute URL* of the resource being tested
* (even when the RegExp did not have the `^` and `$` codes.) In addition, any flags
* present on the RegExp (such as multiline, global, ignoreCase) are ignored.
- * - If you are generating your Javascript from some other templating engine (not
+ * - If you are generating your JavaScript from some other templating engine (not
* recommended, e.g. in issue [#4006](https://github.com/angular/angular.js/issues/4006)),
* remember to escape your regular expression (and be aware that you might need more than
* one level of escaping depending on your templating engine and the way you interpolated
@@ -12673,7 +13062,7 @@ function $SceDelegateProvider() {
* ## Show me an example using SCE.
*
* @example
-
+
@@ -12717,13 +13106,15 @@ function $SceDelegateProvider() {
]
-
+
describe('SCE doc demo', function() {
it('should sanitize untrusted values', function() {
- expect(element('.htmlComment').html()).toBe('Is anyone reading this? ');
+ expect(element(by.css('.htmlComment')).getInnerHtml())
+ .toBe('Is anyone reading this? ');
});
+
it('should NOT sanitize explicitly trusted values', function() {
- expect(element('#explicitlyTrustedHtml').html()).toBe(
+ expect(element(by.id('explicitlyTrustedHtml')).getInnerHtml()).toBe(
'Hover over this text. ');
});
@@ -12758,9 +13149,8 @@ function $SceProvider() {
var enabled = true;
/**
- * @ngdoc function
- * @name ng.sceProvider#enabled
- * @methodOf ng.$sceProvider
+ * @ngdoc method
+ * @name $sceProvider#enabled
* @function
*
* @param {boolean=} value If provided, then enables/disables SCE.
@@ -12837,9 +13227,8 @@ function $SceProvider() {
var sce = copy(SCE_CONTEXTS);
/**
- * @ngdoc function
- * @name ng.sce#isEnabled
- * @methodOf ng.$sce
+ * @ngdoc method
+ * @name $sce#isEnabled
* @function
*
* @return {Boolean} true if SCE is enabled, false otherwise. If you want to set the value, you
@@ -12862,13 +13251,12 @@ function $SceProvider() {
/**
* @ngdoc method
- * @name ng.$sce#parse
- * @methodOf ng.$sce
+ * @name $sce#parse
*
* @description
* Converts Angular {@link guide/expression expression} into a function. This is like {@link
* ng.$parse $parse} and is identical when the expression is a literal constant. Otherwise, it
- * wraps the expression in a call to {@link ng.$sce#methods_getTrusted $sce.getTrusted(*type*,
+ * wraps the expression in a call to {@link ng.$sce#getTrusted $sce.getTrusted(*type*,
* *result*)}
*
* @param {string} type The kind of SCE context in which this result will be used.
@@ -12893,13 +13281,12 @@ function $SceProvider() {
/**
* @ngdoc method
- * @name ng.$sce#trustAs
- * @methodOf ng.$sce
+ * @name $sce#trustAs
*
* @description
- * Delegates to {@link ng.$sceDelegate#methods_trustAs `$sceDelegate.trustAs`}. As such,
- * returns an objectthat is trusted by angular for use in specified strict contextual
- * escaping contexts (such as ng-html-bind-unsafe, ng-include, any src attribute
+ * Delegates to {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}. As such,
+ * returns an object that is trusted by angular for use in specified strict contextual
+ * escaping contexts (such as ng-bind-html, ng-include, any src attribute
* interpolation, any dom event binding attribute interpolation such as for onclick, etc.)
* that uses the provided value. See * {@link ng.$sce $sce} for enabling strict contextual
* escaping.
@@ -12913,95 +13300,89 @@ function $SceProvider() {
/**
* @ngdoc method
- * @name ng.$sce#trustAsHtml
- * @methodOf ng.$sce
+ * @name $sce#trustAsHtml
*
* @description
* Shorthand method. `$sce.trustAsHtml(value)` →
- * {@link ng.$sceDelegate#methods_trustAs `$sceDelegate.trustAs($sce.HTML, value)`}
+ * {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.HTML, value)`}
*
* @param {*} value The value to trustAs.
- * @returns {*} An object that can be passed to {@link ng.$sce#methods_getTrustedHtml
+ * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedHtml
* $sce.getTrustedHtml(value)} to obtain the original value. (privileged directives
* only accept expressions that are either literal constants or are the
- * return value of {@link ng.$sce#methods_trustAs $sce.trustAs}.)
+ * return value of {@link ng.$sce#trustAs $sce.trustAs}.)
*/
/**
* @ngdoc method
- * @name ng.$sce#trustAsUrl
- * @methodOf ng.$sce
+ * @name $sce#trustAsUrl
*
* @description
* Shorthand method. `$sce.trustAsUrl(value)` →
- * {@link ng.$sceDelegate#methods_trustAs `$sceDelegate.trustAs($sce.URL, value)`}
+ * {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.URL, value)`}
*
* @param {*} value The value to trustAs.
- * @returns {*} An object that can be passed to {@link ng.$sce#methods_getTrustedUrl
+ * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedUrl
* $sce.getTrustedUrl(value)} to obtain the original value. (privileged directives
* only accept expressions that are either literal constants or are the
- * return value of {@link ng.$sce#methods_trustAs $sce.trustAs}.)
+ * return value of {@link ng.$sce#trustAs $sce.trustAs}.)
*/
/**
* @ngdoc method
- * @name ng.$sce#trustAsResourceUrl
- * @methodOf ng.$sce
+ * @name $sce#trustAsResourceUrl
*
* @description
* Shorthand method. `$sce.trustAsResourceUrl(value)` →
- * {@link ng.$sceDelegate#methods_trustAs `$sceDelegate.trustAs($sce.RESOURCE_URL, value)`}
+ * {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.RESOURCE_URL, value)`}
*
* @param {*} value The value to trustAs.
- * @returns {*} An object that can be passed to {@link ng.$sce#methods_getTrustedResourceUrl
+ * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedResourceUrl
* $sce.getTrustedResourceUrl(value)} to obtain the original value. (privileged directives
* only accept expressions that are either literal constants or are the return
- * value of {@link ng.$sce#methods_trustAs $sce.trustAs}.)
+ * value of {@link ng.$sce#trustAs $sce.trustAs}.)
*/
/**
* @ngdoc method
- * @name ng.$sce#trustAsJs
- * @methodOf ng.$sce
+ * @name $sce#trustAsJs
*
* @description
* Shorthand method. `$sce.trustAsJs(value)` →
- * {@link ng.$sceDelegate#methods_trustAs `$sceDelegate.trustAs($sce.JS, value)`}
+ * {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.JS, value)`}
*
* @param {*} value The value to trustAs.
- * @returns {*} An object that can be passed to {@link ng.$sce#methods_getTrustedJs
+ * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedJs
* $sce.getTrustedJs(value)} to obtain the original value. (privileged directives
* only accept expressions that are either literal constants or are the
- * return value of {@link ng.$sce#methods_trustAs $sce.trustAs}.)
+ * return value of {@link ng.$sce#trustAs $sce.trustAs}.)
*/
/**
* @ngdoc method
- * @name ng.$sce#getTrusted
- * @methodOf ng.$sce
+ * @name $sce#getTrusted
*
* @description
- * Delegates to {@link ng.$sceDelegate#methods_getTrusted `$sceDelegate.getTrusted`}. As such,
- * takes the result of a {@link ng.$sce#methods_trustAs `$sce.trustAs`}() call and returns the
+ * Delegates to {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted`}. As such,
+ * takes the result of a {@link ng.$sce#trustAs `$sce.trustAs`}() call and returns the
* originally supplied value if the queried context type is a supertype of the created type.
* If this condition isn't satisfied, throws an exception.
*
* @param {string} type The kind of context in which this value is to be used.
- * @param {*} maybeTrusted The result of a prior {@link ng.$sce#methods_trustAs `$sce.trustAs`}
+ * @param {*} maybeTrusted The result of a prior {@link ng.$sce#trustAs `$sce.trustAs`}
* call.
* @returns {*} The value the was originally provided to
- * {@link ng.$sce#methods_trustAs `$sce.trustAs`} if valid in this context.
+ * {@link ng.$sce#trustAs `$sce.trustAs`} if valid in this context.
* Otherwise, throws an exception.
*/
/**
* @ngdoc method
- * @name ng.$sce#getTrustedHtml
- * @methodOf ng.$sce
+ * @name $sce#getTrustedHtml
*
* @description
* Shorthand method. `$sce.getTrustedHtml(value)` →
- * {@link ng.$sceDelegate#methods_getTrusted `$sceDelegate.getTrusted($sce.HTML, value)`}
+ * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.HTML, value)`}
*
* @param {*} value The value to pass to `$sce.getTrusted`.
* @returns {*} The return value of `$sce.getTrusted($sce.HTML, value)`
@@ -13009,12 +13390,11 @@ function $SceProvider() {
/**
* @ngdoc method
- * @name ng.$sce#getTrustedCss
- * @methodOf ng.$sce
+ * @name $sce#getTrustedCss
*
* @description
* Shorthand method. `$sce.getTrustedCss(value)` →
- * {@link ng.$sceDelegate#methods_getTrusted `$sceDelegate.getTrusted($sce.CSS, value)`}
+ * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.CSS, value)`}
*
* @param {*} value The value to pass to `$sce.getTrusted`.
* @returns {*} The return value of `$sce.getTrusted($sce.CSS, value)`
@@ -13022,12 +13402,11 @@ function $SceProvider() {
/**
* @ngdoc method
- * @name ng.$sce#getTrustedUrl
- * @methodOf ng.$sce
+ * @name $sce#getTrustedUrl
*
* @description
* Shorthand method. `$sce.getTrustedUrl(value)` →
- * {@link ng.$sceDelegate#methods_getTrusted `$sceDelegate.getTrusted($sce.URL, value)`}
+ * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.URL, value)`}
*
* @param {*} value The value to pass to `$sce.getTrusted`.
* @returns {*} The return value of `$sce.getTrusted($sce.URL, value)`
@@ -13035,12 +13414,11 @@ function $SceProvider() {
/**
* @ngdoc method
- * @name ng.$sce#getTrustedResourceUrl
- * @methodOf ng.$sce
+ * @name $sce#getTrustedResourceUrl
*
* @description
* Shorthand method. `$sce.getTrustedResourceUrl(value)` →
- * {@link ng.$sceDelegate#methods_getTrusted `$sceDelegate.getTrusted($sce.RESOURCE_URL, value)`}
+ * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.RESOURCE_URL, value)`}
*
* @param {*} value The value to pass to `$sceDelegate.getTrusted`.
* @returns {*} The return value of `$sce.getTrusted($sce.RESOURCE_URL, value)`
@@ -13048,12 +13426,11 @@ function $SceProvider() {
/**
* @ngdoc method
- * @name ng.$sce#getTrustedJs
- * @methodOf ng.$sce
+ * @name $sce#getTrustedJs
*
* @description
* Shorthand method. `$sce.getTrustedJs(value)` →
- * {@link ng.$sceDelegate#methods_getTrusted `$sceDelegate.getTrusted($sce.JS, value)`}
+ * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.JS, value)`}
*
* @param {*} value The value to pass to `$sce.getTrusted`.
* @returns {*} The return value of `$sce.getTrusted($sce.JS, value)`
@@ -13061,12 +13438,11 @@ function $SceProvider() {
/**
* @ngdoc method
- * @name ng.$sce#parseAsHtml
- * @methodOf ng.$sce
+ * @name $sce#parseAsHtml
*
* @description
* Shorthand method. `$sce.parseAsHtml(expression string)` →
- * {@link ng.$sce#methods_parse `$sce.parseAs($sce.HTML, value)`}
+ * {@link ng.$sce#parse `$sce.parseAs($sce.HTML, value)`}
*
* @param {string} expression String expression to compile.
* @returns {function(context, locals)} a function which represents the compiled expression:
@@ -13079,12 +13455,11 @@ function $SceProvider() {
/**
* @ngdoc method
- * @name ng.$sce#parseAsCss
- * @methodOf ng.$sce
+ * @name $sce#parseAsCss
*
* @description
* Shorthand method. `$sce.parseAsCss(value)` →
- * {@link ng.$sce#methods_parse `$sce.parseAs($sce.CSS, value)`}
+ * {@link ng.$sce#parse `$sce.parseAs($sce.CSS, value)`}
*
* @param {string} expression String expression to compile.
* @returns {function(context, locals)} a function which represents the compiled expression:
@@ -13097,12 +13472,11 @@ function $SceProvider() {
/**
* @ngdoc method
- * @name ng.$sce#parseAsUrl
- * @methodOf ng.$sce
+ * @name $sce#parseAsUrl
*
* @description
* Shorthand method. `$sce.parseAsUrl(value)` →
- * {@link ng.$sce#methods_parse `$sce.parseAs($sce.URL, value)`}
+ * {@link ng.$sce#parse `$sce.parseAs($sce.URL, value)`}
*
* @param {string} expression String expression to compile.
* @returns {function(context, locals)} a function which represents the compiled expression:
@@ -13115,12 +13489,11 @@ function $SceProvider() {
/**
* @ngdoc method
- * @name ng.$sce#parseAsResourceUrl
- * @methodOf ng.$sce
+ * @name $sce#parseAsResourceUrl
*
* @description
* Shorthand method. `$sce.parseAsResourceUrl(value)` →
- * {@link ng.$sce#methods_parse `$sce.parseAs($sce.RESOURCE_URL, value)`}
+ * {@link ng.$sce#parse `$sce.parseAs($sce.RESOURCE_URL, value)`}
*
* @param {string} expression String expression to compile.
* @returns {function(context, locals)} a function which represents the compiled expression:
@@ -13133,12 +13506,11 @@ function $SceProvider() {
/**
* @ngdoc method
- * @name ng.$sce#parseAsJs
- * @methodOf ng.$sce
+ * @name $sce#parseAsJs
*
* @description
* Shorthand method. `$sce.parseAsJs(value)` →
- * {@link ng.$sce#methods_parse `$sce.parseAs($sce.JS, value)`}
+ * {@link ng.$sce#parse `$sce.parseAs($sce.JS, value)`}
*
* @param {string} expression String expression to compile.
* @returns {function(context, locals)} a function which represents the compiled expression:
@@ -13174,7 +13546,7 @@ function $SceProvider() {
/**
* !!! This is an undocumented "private" service !!!
*
- * @name ng.$sniffer
+ * @name $sniffer
* @requires $window
* @requires $document
*
@@ -13230,7 +13602,7 @@ function $SnifferProvider() {
// http://code.google.com/p/android/issues/detail?id=17471
// https://github.com/angular/angular.js/issues/904
- // older webit browser (533.9) on Boxee box has exactly the same problem as Android has
+ // older webkit browser (533.9) on Boxee box has exactly the same problem as Android has
// so let's not use the history API also
// We are purposefully using `!(android < 4)` to cover the case when `android` is undefined
// jshint -W018
@@ -13256,6 +13628,7 @@ function $SnifferProvider() {
vendorPrefix: vendorPrefix,
transitions : transitions,
animations : animations,
+ android: android,
msie : msie,
msieDocumentMode: documentMode
};
@@ -13269,9 +13642,8 @@ function $TimeoutProvider() {
/**
- * @ngdoc function
- * @name ng.$timeout
- * @requires $browser
+ * @ngdoc service
+ * @name $timeout
*
* @description
* Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch
@@ -13289,97 +13661,10 @@ function $TimeoutProvider() {
* @param {function()} fn A function, whose execution should be delayed.
* @param {number=} [delay=0] Delay in milliseconds.
* @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise
- * will invoke `fn` within the {@link ng.$rootScope.Scope#methods_$apply $apply} block.
+ * will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.
* @returns {Promise} Promise that will be resolved when the timeout is reached. The value this
* promise will be resolved with is the return value of the `fn` function.
- *
- * @example
-
-
-
-
-
-
- Date format:
- Current time is:
-
- Blood 1 : {{blood_1}}
- Blood 2 : {{blood_2}}
- Fight
- StopFight
- resetFight
-
-
-
-
-
+ *
*/
function timeout(fn, delay, invokeApply) {
var deferred = $q.defer(),
@@ -13409,9 +13694,8 @@ function $TimeoutProvider() {
/**
- * @ngdoc function
- * @name ng.$timeout#cancel
- * @methodOf ng.$timeout
+ * @ngdoc method
+ * @name $timeout#cancel
*
* @description
* Cancels a task associated with the `promise`. As a result of this, the promise will be
@@ -13538,8 +13822,8 @@ function urlIsSameOrigin(requestUrl) {
}
/**
- * @ngdoc object
- * @name ng.$window
+ * @ngdoc service
+ * @name $window
*
* @description
* A reference to the browser's `window` object. While `window`
@@ -13553,8 +13837,8 @@ function urlIsSameOrigin(requestUrl) {
* expression.
*
* @example
-
-
+
+
- default currency symbol ($): {{amount | currency}}
- custom currency identifier (USD$): {{amount | currency:"USD$"}}
+ default currency symbol ($): {{amount | currency}}
+ custom currency identifier (USD$): {{amount | currency:"USD$"}}
-
-
+
+
it('should init with 1234.56', function() {
- expect(binding('amount | currency')).toBe('$1,234.56');
- expect(binding('amount | currency:"USD$"')).toBe('USD$1,234.56');
+ expect(element(by.id('currency-default')).getText()).toBe('$1,234.56');
+ expect(element(by.binding('amount | currency:"USD$"')).getText()).toBe('USD$1,234.56');
});
it('should update', function() {
- input('amount').enter('-1234');
- expect(binding('amount | currency')).toBe('($1,234.00)');
- expect(binding('amount | currency:"USD$"')).toBe('(USD$1,234.00)');
+ if (browser.params.browser == 'safari') {
+ // Safari does not understand the minus key. See
+ // https://github.com/angular/protractor/issues/481
+ return;
+ }
+ element(by.model('amount')).clear();
+ element(by.model('amount')).sendKeys('-1234');
+ expect(element(by.id('currency-default')).getText()).toBe('($1,234.00)');
+ expect(element(by.binding('amount | currency:"USD$"')).getText()).toBe('(USD$1,234.00)');
});
-
-
+
+
*/
currencyFilter.$inject = ['$locale'];
function currencyFilter($locale) {
@@ -13975,7 +14273,7 @@ function currencyFilter($locale) {
/**
* @ngdoc filter
- * @name ng.filter:number
+ * @name number
* @function
*
* @description
@@ -13990,8 +14288,8 @@ function currencyFilter($locale) {
* @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.
*
* @example
-
-
+
+
Enter number:
- Default formatting: {{val | number}}
- No fractions: {{val | number:0}}
- Negative number: {{-val | number:4}}
+ Default formatting: {{val | number}}
+ No fractions: {{val | number:0}}
+ Negative number: {{-val | number:4}}
-
-
+
+
it('should format numbers', function() {
- expect(binding('val | number')).toBe('1,234.568');
- expect(binding('val | number:0')).toBe('1,235');
- expect(binding('-val | number:4')).toBe('-1,234.5679');
+ expect(element(by.id('number-default')).getText()).toBe('1,234.568');
+ expect(element(by.binding('val | number:0')).getText()).toBe('1,235');
+ expect(element(by.binding('-val | number:4')).getText()).toBe('-1,234.5679');
});
it('should update', function() {
- input('val').enter('3374.333');
- expect(binding('val | number')).toBe('3,374.333');
- expect(binding('val | number:0')).toBe('3,374');
- expect(binding('-val | number:4')).toBe('-3,374.3330');
- });
-
-
+ element(by.model('val')).clear();
+ element(by.model('val')).sendKeys('3374.333');
+ expect(element(by.id('number-default')).getText()).toBe('3,374.333');
+ expect(element(by.binding('val | number:0')).getText()).toBe('3,374');
+ expect(element(by.binding('-val | number:4')).getText()).toBe('-3,374.3330');
+ });
+
+
*/
@@ -14033,7 +14332,7 @@ function numberFilter($locale) {
var DECIMAL_SEP = '.';
function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {
- if (isNaN(number) || !isFinite(number)) return '';
+ if (number == null || !isFinite(number) || isObject(number)) return '';
var isNegative = number < 0;
number = Math.abs(number);
@@ -14186,7 +14485,7 @@ var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+
/**
* @ngdoc filter
- * @name ng.filter:date
+ * @name date
* @function
*
* @description
@@ -14244,26 +14543,26 @@ var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+
* @returns {string} Formatted string or the input if input is not recognized as date/millis.
*
* @example
-
-
+
+
{{1288323623006 | date:'medium'}} :
- {{1288323623006 | date:'medium'}}
+ {{1288323623006 | date:'medium'}}
{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}} :
- {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}
+ {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}
{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}} :
- {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}
-
-
+ {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}
+
+
it('should format date', function() {
- expect(binding("1288323623006 | date:'medium'")).
+ expect(element(by.binding("1288323623006 | date:'medium'")).getText()).
toMatch(/Oct 2\d, 2010 \d{1,2}:\d{2}:\d{2} (AM|PM)/);
- expect(binding("1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'")).
+ expect(element(by.binding("1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'")).getText()).
toMatch(/2010\-10\-2\d \d{2}:\d{2}:\d{2} (\-|\+)?\d{4}/);
- expect(binding("'1288323623006' | date:'MM/dd/yyyy @ h:mma'")).
+ expect(element(by.binding("'1288323623006' | date:'MM/dd/yyyy @ h:mma'")).getText()).
toMatch(/10\/2\d\/2010 @ \d{1,2}:\d{2}(AM|PM)/);
});
-
-
+
+
*/
dateFilter.$inject = ['$locale'];
function dateFilter($locale) {
@@ -14343,7 +14642,7 @@ function dateFilter($locale) {
/**
* @ngdoc filter
- * @name ng.filter:json
+ * @name json
* @function
*
* @description
@@ -14357,16 +14656,16 @@ function dateFilter($locale) {
*
*
* @example:
-
-
+
+
{{ {'name':'value'} | json }}
-
-
+
+
it('should jsonify filtered objects', function() {
- expect(binding("{'name':'value'}")).toMatch(/\{\n "name": ?"value"\n}/);
+ expect(element(by.binding("{'name':'value'}")).getText()).toMatch(/\{\n "name": ?"value"\n}/);
});
-
-
+
+
*
*/
function jsonFilter() {
@@ -14378,7 +14677,7 @@ function jsonFilter() {
/**
* @ngdoc filter
- * @name ng.filter:lowercase
+ * @name lowercase
* @function
* @description
* Converts string to lowercase.
@@ -14389,7 +14688,7 @@ var lowercaseFilter = valueFn(lowercase);
/**
* @ngdoc filter
- * @name ng.filter:uppercase
+ * @name uppercase
* @function
* @description
* Converts string to uppercase.
@@ -14398,8 +14697,8 @@ var lowercaseFilter = valueFn(lowercase);
var uppercaseFilter = valueFn(uppercase);
/**
- * @ngdoc function
- * @name ng.filter:limitTo
+ * @ngdoc filter
+ * @name limitTo
* @function
*
* @description
@@ -14408,16 +14707,16 @@ var uppercaseFilter = valueFn(uppercase);
* the value and sign (positive or negative) of `limit`.
*
* @param {Array|string} input Source array or string to be limited.
- * @param {string|number} limit The length of the returned array or string. If the `limit` number
+ * @param {string|number} limit The length of the returned array or string. If the `limit` number
* is positive, `limit` number of items from the beginning of the source array/string are copied.
- * If the number is negative, `limit` number of items from the end of the source array/string
+ * If the number is negative, `limit` number of items from the end of the source array/string
* are copied. The `limit` will be trimmed if it exceeds `array.length`
* @returns {Array|string} A new sub-array or substring of length `limit` or less if input array
* had less than `limit` elements.
*
* @example
-
-
+
+
-
-
-
+
+
it('should initialize to model', function() {
- expect(binding('userType')).toEqual('guest');
- expect(binding('myForm.input.$valid')).toEqual('true');
+ var userType = element(by.binding('userType'));
+ var valid = element(by.binding('myForm.input.$valid'));
+
+ expect(userType.getText()).toContain('guest');
+ expect(valid.getText()).toContain('true');
});
it('should be invalid if empty', function() {
- input('userType').enter('');
- expect(binding('userType')).toEqual('');
- expect(binding('myForm.input.$valid')).toEqual('false');
+ var userType = element(by.binding('userType'));
+ var valid = element(by.binding('myForm.input.$valid'));
+ var userInput = element(by.model('userType'));
+
+ userInput.clear();
+ userInput.sendKeys('');
+
+ expect(userType.getText()).toEqual('userType =');
+ expect(valid.getText()).toContain('false');
});
-
-
+
+
+ *
+ * @param {string=} name Name of the form. If specified, the form controller will be published into
+ * related scope, under this name.
*/
var formDirectiveFactory = function(isNgForm) {
return ['$timeout', function($timeout) {
@@ -15439,14 +15803,14 @@ var ngFormDirective = formDirectiveFactory(true);
*/
var URL_REGEXP = /^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/;
-var EMAIL_REGEXP = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,6}$/;
+var EMAIL_REGEXP = /^[a-z0-9!#$%&'*+/=?^_`{|}~.-]+@[a-z0-9-]+(\.[a-z0-9-]+)*$/i;
var NUMBER_REGEXP = /^\s*(\-|\+)?(\d+|(\d*(\.\d*)))\s*$/;
var inputType = {
/**
- * @ngdoc inputType
- * @name ng.directive:input.text
+ * @ngdoc input
+ * @name input[text]
*
* @description
* Standard HTML text input with angular data binding.
@@ -15469,8 +15833,8 @@ var inputType = {
* @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input.
*
* @example
-
-
+
+
-
-
+ Note that `ng-value="specialValue"` sets radio item's value to be the value of `$scope.specialValue`.
+
+
it('should change state', function() {
- expect(binding('color')).toEqual('blue');
+ var color = element(by.binding('color'));
+
+ expect(color.getText()).toContain('blue');
- input('color').select('red');
- expect(binding('color')).toEqual('red');
+ element.all(by.model('color')).get(0).click();
+
+ expect(color.getText()).toContain('red');
});
-
-
+
+
*/
'radio': radioInputType,
/**
- * @ngdoc inputType
- * @name ng.directive:input.checkbox
+ * @ngdoc input
+ * @name input[checkbox]
*
* @description
* HTML checkbox.
@@ -15783,8 +16180,8 @@ var inputType = {
* interaction with the input element.
*
* @example
-
-
+
+
+
+ Update input to see transitions when valid/invalid.
+ Integer is a valid value.
+
+
+ *
*/
var ngModelDirective = function() {
return {
@@ -16653,10 +17128,13 @@ var ngModelDirective = function() {
/**
* @ngdoc directive
- * @name ng.directive:ngChange
+ * @name ngChange
*
* @description
- * Evaluate given expression when user changes the input.
+ * Evaluate the given expression when the user changes the input.
+ * The expression is evaluated immediately, unlike the JavaScript onchange event
+ * which only triggers at the end of a change (usually, when the user leaves the
+ * form element or presses the return key).
* The expression is not evaluated when the value change is coming from the model.
*
* Note, this directive requires `ngModel` to be present.
@@ -16666,8 +17144,8 @@ var ngModelDirective = function() {
* in input value.
*
* @example
- *
- *
+ *
+ *
*
Load inlined template
-
-
+
+
it('should load template defined inside script tag', function() {
- element('#tpl-link').click();
- expect(element('#tpl-content').text()).toMatch(/Content of the template/);
+ element(by.css('#tpl-link')).click();
+ expect(element(by.css('#tpl-content')).getText()).toMatch(/Content of the template/);
});
-
-
+
+
*/
var scriptDirective = ['$templateCache', function($templateCache) {
return {
@@ -19665,7 +20406,7 @@ var scriptDirective = ['$templateCache', function($templateCache) {
var ngOptionsMinErr = minErr('ngOptions');
/**
* @ngdoc directive
- * @name ng.directive:select
+ * @name select
* @restrict E
*
* @description
@@ -19681,14 +20422,21 @@ var ngOptionsMinErr = minErr('ngOptions');
* represented by the selected option will be bound to the model identified by the `ngModel`
* directive.
*
+ *
+ * **Note:** `ngModel` compares by reference, not value. This is important when binding to an
+ * array of objects. See an example [in this jsfiddle](http://jsfiddle.net/qWzTb/).
+ *
+ *
* Optionally, a single hard-coded `` element, with the value set to an empty string, can
* be nested into the `` element. This element will then represent the `null` or "not selected"
* option. See example below for demonstration.
*
- * Note: `ngOptions` provides iterator facility for `` element which should be used instead
+ *
+ * **Note:** `ngOptions` provides an iterator facility for the `` element which should be used instead
* of {@link ng.directive:ngRepeat ngRepeat} when you want the
* `select` model to be bound to a non-string value. This is because an option element can only
* be bound to string values at present.
+ *
*
* @param {string} ngModel Assignable angular expression to data-bind to.
* @param {string=} name Property name of the form under which the control is published.
@@ -19727,8 +20475,8 @@ var ngOptionsMinErr = minErr('ngOptions');
* `value` variable (e.g. `value.propertyName`).
*
* @example
-
-
+
+
-
+
+
diff --git a/src/state.js b/src/state.js
index c49932935..9089cb3d2 100644
--- a/src/state.js
+++ b/src/state.js
@@ -1178,6 +1178,7 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
}
// Provide access to the state itself for internal use
result.$$state = state;
+ result.$$controllerAs = view.controllerAs;
dst[name] = result;
}));
});
diff --git a/src/viewDirective.js b/src/viewDirective.js
index 4f2e2c169..7b7e0f187 100644
--- a/src/viewDirective.js
+++ b/src/viewDirective.js
@@ -115,8 +115,8 @@
*
*
*/
-$ViewDirective.$inject = ['$state', '$compile', '$controller', '$injector', '$uiViewScroll', '$document'];
-function $ViewDirective( $state, $compile, $controller, $injector, $uiViewScroll, $document) {
+$ViewDirective.$inject = ['$state', '$injector', '$uiViewScroll'];
+function $ViewDirective( $state, $injector, $uiViewScroll) {
function getService() {
return ($injector.has) ? function(service) {
@@ -130,141 +130,101 @@ function $ViewDirective( $state, $compile, $controller, $injector, $ui
};
}
- var viewIsUpdating = false,
- service = getService(),
+ var service = getService(),
$animator = service('$animator'),
$animate = service('$animate');
- // Returns a set of DOM manipulation functions based on whether animation
- // should be performed
- function getRenderer(element, attrs, scope) {
+ // Returns a set of DOM manipulation functions based on which Angular version
+ // it should use
+ function getRenderer(attrs, scope) {
var statics = function() {
return {
- leave: function (element) { element.remove(); },
- enter: function (element, parent, anchor) { anchor.after(element); }
+ enter: function (element, target, cb) { target.after(element); cb(); },
+ leave: function (element, cb) { element.remove(); cb(); }
};
};
if ($animate) {
- return function(shouldAnimate) {
- return !shouldAnimate ? statics() : {
- enter: function(element, parent, anchor) { $animate.enter(element, null, anchor); },
- leave: function(element) { $animate.leave(element, function() { element.remove(); }); }
- };
+ return {
+ enter: function(element, target, cb) { $animate.enter(element, null, target, cb); },
+ leave: function(element, cb) { $animate.leave(element, cb); }
};
}
if ($animator) {
var animate = $animator && $animator(scope, attrs);
- return function(shouldAnimate) {
- return !shouldAnimate ? statics() : {
- enter: function(element, parent, anchor) { animate.enter(element, parent); },
- leave: function(element) { animate.leave(element.contents(), element); }
- };
+ return {
+ enter: function(element, target, cb) {animate.enter(element, null, target); cb(); },
+ leave: function(element, cb) { animate.leave(element); cb(); }
};
}
- return statics;
+ return statics();
}
var directive = {
restrict: 'ECA',
- compile: function (element, attrs) {
- var initial = element.html(),
- isDefault = true,
- anchor = angular.element($document[0].createComment(' ui-view-anchor ')),
- parentEl = element.parent();
-
- element.prepend(anchor);
-
- return function ($scope) {
- var inherited = parentEl.inheritedData('$uiView');
-
- var currentScope, currentEl, viewLocals,
- name = attrs[directive.name] || attrs.name || '',
- onloadExp = attrs.onload || '',
- autoscrollExp = attrs.autoscroll,
- renderer = getRenderer(element, attrs, $scope);
-
- if (name.indexOf('@') < 0) name = name + '@' + (inherited ? inherited.state.name : '');
- var view = { name: name, state: null };
-
- var eventHook = function () {
- if (viewIsUpdating) return;
- viewIsUpdating = true;
-
- try { updateView(true); } catch (e) {
- viewIsUpdating = false;
- throw e;
- }
- viewIsUpdating = false;
- };
-
- $scope.$on('$stateChangeSuccess', eventHook);
- $scope.$on('$viewContentLoading', eventHook);
-
- updateView(false);
+ terminal: true,
+ priority: 400,
+ transclude: 'element',
+ compile: function (tElement, tAttrs, $transclude) {
+ return function (scope, $element, attrs) {
+ var previousEl, currentEl, currentScope, latestLocals,
+ onloadExp = attrs.onload || '',
+ autoScrollExp = attrs.autoscroll,
+ renderer = getRenderer(attrs, scope);
+
+ scope.$on('$stateChangeSuccess', function() {
+ updateView(false);
+ });
+ scope.$on('$viewContentLoading', function() {
+ updateView(false);
+ });
+
+ updateView(true);
function cleanupLastView() {
- if (currentEl) {
- renderer(true).leave(currentEl);
- currentEl = null;
+ if (previousEl) {
+ previousEl.remove();
+ previousEl = null;
}
if (currentScope) {
currentScope.$destroy();
currentScope = null;
}
- }
-
- function updateView(shouldAnimate) {
- var locals = $state.$current && $state.$current.locals[name];
-
- if (isDefault) {
- isDefault = false;
- element.replaceWith(anchor);
- }
- if (!locals) {
- cleanupLastView();
- currentEl = element.clone();
- currentEl.html(initial);
- renderer(shouldAnimate).enter(currentEl, parentEl, anchor);
+ if (currentEl) {
+ renderer.leave(currentEl, function() {
+ previousEl = null;
+ });
- currentScope = $scope.$new();
- $compile(currentEl.contents())(currentScope);
- return;
+ previousEl = currentEl;
+ currentEl = null;
}
+ }
- if (locals === viewLocals) return; // nothing to do
-
- cleanupLastView();
-
- currentEl = element.clone();
- currentEl.html(locals.$template ? locals.$template : initial);
- renderer(true).enter(currentEl, parentEl, anchor);
-
- currentEl.data('$uiView', view);
-
- viewLocals = locals;
- view.state = locals.$$state;
-
- var link = $compile(currentEl.contents());
+ function updateView(firstTime) {
+ var newScope = scope.$new(),
+ name = currentEl && currentEl.data('$uiViewName'),
+ previousLocals = name && $state.$current && $state.$current.locals[name];
- currentScope = $scope.$new();
+ if (!firstTime && previousLocals === latestLocals) return; // nothing to do
- if (locals.$$controller) {
- locals.$scope = currentScope;
- var controller = $controller(locals.$$controller, locals);
- if ($state.$current.controllerAs) {
- currentScope[$state.$current.controllerAs] = controller;
- }
- currentEl.children().data('$ngControllerController', controller);
- }
+ var clone = $transclude(newScope, function(clone) {
+ renderer.enter(clone, $element, function onUiViewEnter() {
+ if (!angular.isDefined(autoScrollExp) || !autoScrollExp || scope.$eval(autoScrollExp)) {
+ $uiViewScroll(clone);
+ }
+ });
+ cleanupLastView();
+ });
- link(currentScope);
+ latestLocals = $state.$current.locals[clone.data('$uiViewName')];
+ currentEl = clone;
+ currentScope = newScope;
/**
* @ngdoc event
* @name ui.router.state.directive:ui-view#$viewContentLoaded
@@ -276,11 +236,7 @@ function $ViewDirective( $state, $compile, $controller, $injector, $ui
* @param {Object} event Event object.
*/
currentScope.$emit('$viewContentLoaded');
- if (onloadExp) currentScope.$eval(onloadExp);
-
- if (!angular.isDefined(autoscrollExp) || !autoscrollExp || $scope.$eval(autoscrollExp)) {
- $uiViewScroll(currentEl);
- }
+ currentScope.$eval(onloadExp);
}
};
}
@@ -289,4 +245,50 @@ function $ViewDirective( $state, $compile, $controller, $injector, $ui
return directive;
}
+$ViewDirectiveFill.$inject = ['$compile', '$controller', '$state'];
+function $ViewDirectiveFill ($compile, $controller, $state) {
+ return {
+ restrict: 'ECA',
+ priority: -400,
+ compile: function (tElement) {
+ var initial = tElement.html();
+ return function (scope, $element, attrs) {
+ var name = attrs.uiView || attrs.name || '',
+ inherited = $element.inheritedData('$uiView');
+
+ if (name.indexOf('@') < 0) {
+ name = name + '@' + (inherited ? inherited.state.name : '');
+ }
+
+ $element.data('$uiViewName', name);
+
+ var current = $state.$current,
+ locals = current && current.locals[name];
+
+ if (! locals) {
+ return;
+ }
+
+ $element.data('$uiView', { name: name, state: locals.$$state });
+ $element.html(locals.$template ? locals.$template : initial);
+
+ var link = $compile($element.contents());
+
+ if (locals.$$controller) {
+ locals.$scope = scope;
+ var controller = $controller(locals.$$controller, locals);
+ if (locals.$$controllerAs) {
+ scope[locals.$$controllerAs] = controller;
+ }
+ $element.data('$ngControllerController', controller);
+ $element.children().data('$ngControllerController', controller);
+ }
+
+ link(scope);
+ };
+ }
+ };
+}
+
angular.module('ui.router.state').directive('uiView', $ViewDirective);
+angular.module('ui.router.state').directive('uiView', $ViewDirectiveFill);
diff --git a/test/viewDirectiveSpec.js b/test/viewDirectiveSpec.js
index 8e1cf17a7..2c184d86c 100644
--- a/test/viewDirectiveSpec.js
+++ b/test/viewDirectiveSpec.js
@@ -10,19 +10,19 @@ describe('uiView', function () {
var depends = ['ui.router'];
try {
- angular.module('ngAnimate');
- depends.push('ngAnimate');
+ angular.module('ngAnimateMock');
+ depends.push('ngAnimateMock');
} catch(e) {
angular.module('mock.animate', []).value('$animate', null);
+ module('mock.animate');
}
angular.module('ui.router.test', depends);
module('ui.router.test');
- module('mock.animate');
});
beforeEach(module(function ($provide) {
- $provide.decorator('$uiViewScroll', function ($delegate) {
+ $provide.decorator('$uiViewScroll', function () {
return jasmine.createSpy('$uiViewScroll');
});
}));
@@ -61,7 +61,7 @@ describe('uiView', function () {
}
},
gState = {
- template: '{{content}}
'
+ template: '{{content}}
'
},
hState = {
views: {
@@ -76,13 +76,13 @@ describe('uiView', function () {
' '
},
jState = {
- template: 'jState '
+ template: 'jState'
},
kState = {
controller: function() {
this.someProperty = "value"
},
- controllerAs: "vm",
+ controllerAs: "vm"
};
beforeEach(module(function ($stateProvider) {
@@ -108,136 +108,95 @@ describe('uiView', function () {
describe('linking ui-directive', function () {
- it('anonymous ui-view should be replaced with the template of the current $state', inject(function ($state, $q, $animate) {
+ it('anonymous ui-view should be replaced with the template of the current $state', inject(function ($state, $q) {
elem.append($compile('
')(scope));
+ expect(elem.find('ui-view').text()).toBe('');
+
$state.transitionTo(aState);
$q.flush();
- if ($animate) {
- expect($animate.flushNext('leave').element.text()).toBe('');
- expect($animate.flushNext('enter').element.text()).toBe(aState.template);
- }
+ expect(elem.find('ui-view').text()).toBe(aState.template);
}));
- it('named ui-view should be replaced with the template of the current $state', inject(function ($state, $q, $animate) {
+ it('named ui-view should be replaced with the template of the current $state', inject(function ($state, $q) {
elem.append($compile('
')(scope));
$state.transitionTo(cState);
$q.flush();
- if ($animate) {
- expect($animate.flushNext('leave').element.text()).toBe('');
- expect($animate.flushNext('enter').element.text()).toBe(cState.views.cview.template);
- }
+ expect(elem.find('ui-view').text()).toBe(cState.views.cview.template);
}));
- it('ui-view should be updated after transition to another state', inject(function ($state, $q, $animate) {
+ it('ui-view should be updated after transition to another state', inject(function ($state, $q) {
elem.append($compile('
')(scope));
+ expect(elem.find('ui-view').text()).toBe('');
$state.transitionTo(aState);
$q.flush();
- if ($animate) {
- expect($animate.flushNext('leave').element.text()).toBe('');
- expect($animate.flushNext('enter').element.text()).toBe(aState.template);
- }
+ expect(elem.find('ui-view').text()).toBe(aState.template);
$state.transitionTo(bState);
$q.flush();
- if ($animate) {
- expect($animate.flushNext('leave').element.text()).toBe(aState.template);
- expect($animate.flushNext('enter').element.text()).toBe(bState.template);
- }
+ expect(elem.find('ui-view').text()).toBe(bState.template);
}));
- it('should handle NOT nested ui-views', inject(function ($state, $q, $animate) {
- elem.append($compile('')(scope));
+ it('should handle NOT nested ui-views', inject(function ($state, $q) {
+ elem.append($compile('
')(scope));
+ expect(elem.find('ui-view').eq(0).text()).toBe('');
+ expect(elem.find('ui-view').eq(1).text()).toBe('');
$state.transitionTo(dState);
$q.flush();
- if ($animate) {
- expect($animate.flushNext('leave').element.html()).toBe('');
- expect($animate.flushNext('enter').element.text()).toBe(dState.views.dview1.template);
- expect($animate.flushNext('leave').element.html()).toBe('');
- expect($animate.flushNext('enter').element.text()).toBe(dState.views.dview2.template);
- }
+ expect(elem.find('ui-view').eq(0).text()).toBe(dState.views.dview1.template);
+ expect(elem.find('ui-view').eq(1).text()).toBe(dState.views.dview2.template);
}));
- it('should handle nested ui-views (testing two levels deep)', inject(function ($state, $q, $animate) {
- $compile(elem.append('
'))(scope);
+ it('should handle nested ui-views (testing two levels deep)', inject(function ($state, $q) {
+ $compile(elem.append('
'))(scope);
+ expect(elem.find('ui-view').text()).toBe('');
$state.transitionTo(fState);
$q.flush();
- if ($animate) {
- expect($animate.flushNext('leave').element.text()).toBe('');
- expect($animate.flushNext('enter').element.parent().find('.view')).toMatchText('');
-
- var target = $animate.flushNext('enter').element;
- expect(target).toHaveClass('eview');
- expect(target).toMatchText(fState.views.eview.template);
- }
+ expect(elem.find('ui-view').text()).toBe(fState.views.eview.template);
}));
});
describe('handling initial view', function () {
- it('initial view should be compiled if the view is empty', inject(function ($state, $q, $animate) {
+ it('initial view should be compiled if the view is empty', inject(function ($state, $q) {
var content = 'inner content';
- elem.append($compile('
')(scope));
$state.transitionTo(gState);
$q.flush();
- if ($animate) {
- var target = $animate.flushNext('leave').element;
- expect(target.text()).toBe("");
-
- $animate.flushNext('enter');
- $animate.flushNext('leave');
- $animate.flushNext('enter');
- $animate.flushNext('addClass');
- $animate.flushNext('addClass');
-
- target = $animate.flushNext('addClass').element;
- expect(target).toHaveClass('test');
- expect(target.text()).toBe(content);
- }
+ expect(elem.find('ui-view').text()).toBe(content);
}));
- it('initial view should be put back after removal of the view', inject(function ($state, $q, $animate) {
+ it('initial view should be put back after removal of the view', inject(function ($state, $q) {
var content = 'inner content';
-
+ scope.content = content;
elem.append($compile('
')(scope));
- scope.$apply('content = "' + content + '"');
- $state.transitionTo(hState);
+ $state.go(hState);
$q.flush();
- if ($animate) {
- expect($animate.flushNext('leave').element.text()).toBe('');
- expect($animate.flushNext('enter').element.text()).toBe('');
- expect($animate.flushNext('enter').element.text()).toBe(hState.views.inner.template);
- expect($animate.flushNext('addClass').element.text()).toBe(content);
-
- // going to the parent state which makes the inner view empty
- $state.transitionTo(gState);
- $q.flush();
+ expect(elem.find('ui-view').text()).toBe(hState.views.inner.template);
- expect($animate.flushNext('leave').element).toMatchText(hState.views.inner.template);
- $animate.flushNext('enter');
+ // going to the parent state which makes the inner view empty
+ $state.go(gState);
+ $q.flush();
- var target = $animate.flushNext('addClass').element;
- expect(target).toHaveClass('test');
- expect(target).toMatchText(content);
- }
+ expect(elem.find('ui-view').text()).toBe(content);
}));
// related to issue #435
- it('initial view should be transcluded once to prevent breaking other directives', inject(function ($state, $q, $animate) {
+ it('initial view should be transcluded once to prevent breaking other directives', inject(function ($state, $q) {
scope.items = ["I", "am", "a", "list", "of", "items"];
elem.append($compile('
')(scope));
@@ -245,7 +204,6 @@ describe('uiView', function () {
// transition to state that has an initial view
$state.transitionTo(iState);
$q.flush();
- if ($animate) $animate.flush();
// verify if ng-repeat has been compiled
expect(elem.find('li').length).toBe(scope.items.length);
@@ -253,14 +211,12 @@ describe('uiView', function () {
// transition to another state that replace the initial content
$state.transitionTo(jState);
$q.flush();
- if ($animate) $animate.flush();
- expect(elem.find('ui-view').find('span').text()).toBe('jState');
+ expect(elem.find('ui-view').text()).toBe(jState.template);
// transition back to the state with empty subview and the initial view
$state.transitionTo(iState);
$q.flush();
- if ($animate) $animate.flush();
// verify if the initial view is correct
expect(elem.find('li').length).toBe(scope.items.length);
@@ -270,19 +226,56 @@ describe('uiView', function () {
scope.items.push(".", "Working?");
});
- if ($animate) $animate.flush();
-
// verify if the initial view has been updated
expect(elem.find('li').length).toBe(scope.items.length);
}));
+
+ // related to issue #857
+ it('should handle ui-view inside ng-if', inject(function ($state, $q, $compile) {
+ // ngIf does not exist in 1.0.8
+ if (angular.version.full === '1.0.8') return;
+
+ scope.someBoolean = false;
+ elem.append($compile('
')(scope));
+
+ $state.transitionTo(aState);
+ $q.flush();
+
+ // Verify there is no ui-view in the DOM
+ expect(elem.find('ui-view').length).toBe(0);
+
+ // Turn on the div that holds the ui-view
+ scope.someBoolean = true;
+ scope.$digest();
+
+ // Verify that the ui-view is there and it has the correct content
+ expect(elem.find('ui-view').text()).toBe(aState.template);
+
+ // Turn off the ui-view
+ scope.someBoolean = false;
+ scope.$digest();
+
+ // Verify there is no ui-view in the DOM
+ expect(elem.find('ui-view').length).toBe(0);
+
+ // Turn on the div that holds the ui-view once again
+ scope.someBoolean = true;
+ scope.$digest();
+
+ // Verify that the ui-view is there and it has the correct content
+ expect(elem.find('ui-view').text()).toBe(aState.template);
+ }));
});
describe('autoscroll attribute', function () {
it('should autoscroll when unspecified', inject(function ($state, $q, $uiViewScroll, $animate) {
elem.append($compile('
')(scope));
+
$state.transitionTo(aState);
$q.flush();
- if ($animate) $animate.flush();
+
+ if ($animate) $animate.triggerCallbacks();
+
expect($uiViewScroll).toHaveBeenCalledWith(elem.find('span').parent());
}));
@@ -290,39 +283,48 @@ describe('uiView', function () {
elem.append($compile('
')(scope));
$state.transitionTo(aState);
$q.flush();
- if ($animate) $animate.flush();
+
+ if ($animate) $animate.triggerCallbacks();
+
expect($uiViewScroll).toHaveBeenCalledWith(elem.find('span').parent());
}));
it('should autoscroll based on expression', inject(function ($state, $q, $uiViewScroll, $animate) {
+ scope.doScroll = false;
+
elem.append($compile('
')(scope));
- scope.doScroll = false;
$state.transitionTo(aState);
$q.flush();
+
+ if ($animate) $animate.triggerCallbacks();
+
expect($uiViewScroll).not.toHaveBeenCalled();
scope.doScroll = true;
$state.transitionTo(bState);
$q.flush();
- if ($animate) $animate.flush();
- var target;
- angular.forEach(elem.find('ui-view'), function(view) {
- if (angular.element(view).text() === bState.template) target = angular.element(view);
- });
+ if ($animate) $animate.triggerCallbacks();
+
+ var target,
+ index = -1,
+ uiViews = elem.find('ui-view');
+
+ while (index++ < uiViews.length) {
+ var uiView = angular.element(uiViews[index]);
+ if (uiView.text() === bState.template) target = uiView;
+ }
expect($uiViewScroll).toHaveBeenCalledWith(target);
}));
-
- it('should instantiate a controller with controllerAs', inject(function($state, $q) {
- elem.append($compile('{{vm.someProperty}}
')(scope));
- $state.transitionTo(kState);
- $q.flush();
- var innerScope = scope.$$childHead
- expect(innerScope.vm).not.toBeUndefined()
- expect(innerScope.vm.someProperty).toBe("value")
- }))
});
-});
\ No newline at end of file
+ it('should instantiate a controller with controllerAs', inject(function($state, $q) {
+ elem.append($compile('{{vm.someProperty}}
')(scope));
+ $state.transitionTo(kState);
+ $q.flush();
+
+ expect(elem.text()).toBe('value');
+ }));
+});