style: make jshint happy

This commit is contained in:
Vojta Jina 2013-10-22 14:41:21 -07:00
parent 934a95d3ef
commit f2fab49830
304 changed files with 1938 additions and 1174 deletions

View file

@ -159,6 +159,7 @@ function outputLocale(localeInfo, localeID) {
localeObj.id = correctedLocaleId(localeID); localeObj.id = correctedLocaleId(localeID);
var prefix = var prefix =
"'use strict';\n" +
'angular.module("ngLocale", [], ["$provide", function($provide) {\n' + 'angular.module("ngLocale", [], ["$provide", function($provide) {\n' +
'var PLURAL_CATEGORY = {' + 'var PLURAL_CATEGORY = {' +
'ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"' + 'ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"' +

View file

@ -1,5 +1,88 @@
'use strict'; 'use strict';
/* We need to tell jshint what variables are being exported */
/* global
-angular,
-msie,
-jqLite,
-jQuery,
-slice,
-push,
-toString,
-ngMinErr,
-_angular,
-angularModule,
-nodeName_,
-uid,
-lowercase,
-uppercase,
-manualLowercase,
-manualUppercase,
-nodeName_,
-isArrayLike,
-forEach,
-sortedKeys,
-forEachSorted,
-reverseParams,
-nextUid,
-setHashKey,
-extend,
-int,
-inherit,
-noop,
-identity,
-valueFn,
-isUndefined,
-isDefined,
-isObject,
-isString,
-isNumber,
-isDate,
-isArray,
-isFunction,
-isRegExp,
-isWindow,
-isScope,
-isFile,
-isBoolean,
-trim,
-isElement,
-makeMap,
-map,
-size,
-includes,
-indexOf,
-arrayRemove,
-isLeafNode,
-copy,
-shallowCopy,
-equals,
-csp,
-concat,
-sliceArgs,
-bind,
-toJsonReplacer,
-toJson,
-fromJson,
-toBoolean,
-startingTag,
-tryDecodeURIComponent,
-parseKeyValue,
-toKeyValue,
-encodeUriSegment,
-encodeUriQuery,
-angularInit,
-bootstrap,
-snake_case,
-bindJQuery,
-assertArg,
-assertArgFn,
-assertNotHasOwnProperty,
-getter
*/
//////////////////////////////////// ////////////////////////////////////
/** /**
@ -27,11 +110,13 @@ var uppercase = function(string){return isString(string) ? string.toUpperCase()
var manualLowercase = function(s) { var manualLowercase = function(s) {
/* jshint bitwise: false */
return isString(s) return isString(s)
? s.replace(/[A-Z]/g, function(ch) {return String.fromCharCode(ch.charCodeAt(0) | 32);}) ? s.replace(/[A-Z]/g, function(ch) {return String.fromCharCode(ch.charCodeAt(0) | 32);})
: s; : s;
}; };
var manualUppercase = function(s) { var manualUppercase = function(s) {
/* jshint bitwise: false */
return isString(s) return isString(s)
? s.replace(/[a-z]/g, function(ch) {return String.fromCharCode(ch.charCodeAt(0) & ~32);}) ? s.replace(/[a-z]/g, function(ch) {return String.fromCharCode(ch.charCodeAt(0) & ~32);})
: s; : s;
@ -77,7 +162,8 @@ if (isNaN(msie)) {
/** /**
* @private * @private
* @param {*} obj * @param {*} obj
* @return {boolean} Returns true if `obj` is an array or array-like object (NodeList, Arguments, String ...) * @return {boolean} Returns true if `obj` is an array or array-like object (NodeList, Arguments,
* String ...)
*/ */
function isArrayLike(obj) { function isArrayLike(obj) {
if (obj == null || isWindow(obj)) { if (obj == null || isWindow(obj)) {
@ -171,7 +257,7 @@ function forEachSorted(obj, iterator, context) {
* @returns {function(*, string)} * @returns {function(*, string)}
*/ */
function reverseParams(iteratorFn) { function reverseParams(iteratorFn) {
return function(value, key) { iteratorFn(key, value) }; return function(value, key) { iteratorFn(key, value); };
} }
/** /**
@ -530,17 +616,17 @@ function map(obj, iterator, context) {
* @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array. * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.
*/ */
function size(obj, ownPropsOnly) { function size(obj, ownPropsOnly) {
var size = 0, key; var count = 0, key;
if (isArray(obj) || isString(obj)) { if (isArray(obj) || isString(obj)) {
return obj.length; return obj.length;
} else if (isObject(obj)){ } else if (isObject(obj)){
for (key in obj) for (key in obj)
if (!ownPropsOnly || obj.hasOwnProperty(key)) if (!ownPropsOnly || obj.hasOwnProperty(key))
size++; count++;
} }
return size; return count;
} }
@ -637,7 +723,8 @@ function isLeafNode (node) {
*/ */
function copy(source, destination){ function copy(source, destination){
if (isWindow(source) || isScope(source)) { if (isWindow(source) || isScope(source)) {
throw ngMinErr('cpws', "Can't copy! Making copies of Window or Scope instances is not supported."); throw ngMinErr('cpws',
"Can't copy! Making copies of Window or Scope instances is not supported.");
} }
if (!destination) { if (!destination) {
@ -654,7 +741,8 @@ function copy(source, destination){
} }
} }
} else { } else {
if (source === destination) throw ngMinErr('cpi', "Can't copy! Source and destination are identical."); if (source === destination) throw ngMinErr('cpi',
"Can't copy! Source and destination are identical.");
if (isArray(source)) { if (isArray(source)) {
destination.length = 0; destination.length = 0;
for ( var i = 0; i < source.length; i++) { for ( var i = 0; i < source.length; i++) {
@ -698,8 +786,8 @@ function shallowCopy(src, dst) {
* @function * @function
* *
* @description * @description
* Determines if two objects or two values are equivalent. Supports value types, regular expressions, arrays and * Determines if two objects or two values are equivalent. Supports value types, regular
* objects. * expressions, arrays and objects.
* *
* Two objects or values are considered equivalent if at least one of the following is true: * Two objects or values are considered equivalent if at least one of the following is true:
* *
@ -776,6 +864,7 @@ function sliceArgs(args, startIndex) {
} }
/* jshint -W101 */
/** /**
* @ngdoc function * @ngdoc function
* @name angular.bind * @name angular.bind
@ -784,14 +873,15 @@ function sliceArgs(args, startIndex) {
* @description * @description
* Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for
* `fn`). You can supply optional `args` that are prebound to the function. This feature is also * `fn`). You can supply optional `args` that are prebound to the function. This feature is also
* known as [partial application](http://en.wikipedia.org/wiki/Partial_application), as distinguished * known as [partial application](http://en.wikipedia.org/wiki/Partial_application), as
* from [function currying](http://en.wikipedia.org/wiki/Currying#Contrast_with_partial_function_application). * distinguished from [function currying](http://en.wikipedia.org/wiki/Currying#Contrast_with_partial_function_application).
* *
* @param {Object} self Context which `fn` should be evaluated in. * @param {Object} self Context which `fn` should be evaluated in.
* @param {function()} fn Function to be bound. * @param {function()} fn Function to be bound.
* @param {...*} args Optional arguments to be prebound to the `fn` function call. * @param {...*} args Optional arguments to be prebound to the `fn` function call.
* @returns {function()} Function that wraps the `fn` with all the specified bindings. * @returns {function()} Function that wraps the `fn` with all the specified bindings.
*/ */
/* jshint +W101 */
function bind(self, fn) { function bind(self, fn) {
var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : []; var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];
if (isFunction(fn) && !(fn instanceof RegExp)) { if (isFunction(fn) && !(fn instanceof RegExp)) {
@ -951,10 +1041,12 @@ function toKeyValue(obj) {
forEach(obj, function(value, key) { forEach(obj, function(value, key) {
if (isArray(value)) { if (isArray(value)) {
forEach(value, function(arrayValue) { forEach(value, function(arrayValue) {
parts.push(encodeUriQuery(key, true) + (arrayValue === true ? '' : '=' + encodeUriQuery(arrayValue, true))); parts.push(encodeUriQuery(key, true) +
(arrayValue === true ? '' : '=' + encodeUriQuery(arrayValue, true)));
}); });
} else { } else {
parts.push(encodeUriQuery(key, true) + (value === true ? '' : '=' + encodeUriQuery(value, true))); parts.push(encodeUriQuery(key, true) +
(value === true ? '' : '=' + encodeUriQuery(value, true)));
} }
}); });
return parts.length ? parts.join('&') : ''; return parts.length ? parts.join('&') : '';
@ -1016,8 +1108,8 @@ function encodeUriQuery(val, pctEncodeSpaces) {
* designates the root of the application and is typically placed * designates the root of the application and is typically placed
* at the root of the page. * at the root of the page.
* *
* The first ngApp found in the document will be auto-bootstrapped. To use multiple applications in an * The first ngApp found in the document will be auto-bootstrapped. To use multiple applications in
* HTML document you must manually bootstrap them using {@link angular.bootstrap}. * an HTML document you must manually bootstrap them using {@link angular.bootstrap}.
* Applications cannot be nested. * Applications cannot be nested.
* *
* In the example below if the `ngApp` directive were not placed * In the example below if the `ngApp` directive were not placed
@ -1091,7 +1183,8 @@ function angularInit(element, bootstrap) {
* @param {Element} element DOM element which is the root of angular application. * @param {Element} element DOM element which is the root of angular application.
* @param {Array<String|Function|Array>=} modules an array of modules to load into the application. * @param {Array<String|Function|Array>=} modules an array of modules to load into the application.
* Each item in the array should be the name of a predefined module or a (DI annotated) * Each item in the array should be the name of a predefined module or a (DI annotated)
* function that will be invoked by the injector as a run block. See: {@link angular.module modules} * function that will be invoked by the injector as a run block.
* See: {@link angular.module modules}
* @returns {AUTO.$injector} Returns the newly created injector for this app. * @returns {AUTO.$injector} Returns the newly created injector for this app.
*/ */
function bootstrap(element, modules) { function bootstrap(element, modules) {
@ -1156,10 +1249,11 @@ function bindJQuery() {
injector: JQLitePrototype.injector, injector: JQLitePrototype.injector,
inheritedData: JQLitePrototype.inheritedData inheritedData: JQLitePrototype.inheritedData
}); });
// Method signature: JQLitePatchJQueryRemove(name, dispatchThis, filterElems, getterIfNoArguments) // Method signature:
JQLitePatchJQueryRemove('remove', true, true, false); // jqLitePatchJQueryRemove(name, dispatchThis, filterElems, getterIfNoArguments)
JQLitePatchJQueryRemove('empty', false, false, false); jqLitePatchJQueryRemove('remove', true, true, false);
JQLitePatchJQueryRemove('html', false, false, true); jqLitePatchJQueryRemove('empty', false, false, false);
jqLitePatchJQueryRemove('html', false, false, true);
} else { } else {
jqLite = JQLite; jqLite = JQLite;
} }

74
src/AngularPublic.js Executable file → Normal file
View file

@ -1,5 +1,79 @@
'use strict'; 'use strict';
/* global
angularModule: true,
version: true,
$LocaleProvider,
$CompileProvider,
htmlAnchorDirective,
inputDirective,
inputDirective,
formDirective,
scriptDirective,
selectDirective,
styleDirective,
optionDirective,
ngBindDirective,
ngBindHtmlDirective,
ngBindTemplateDirective,
ngClassDirective,
ngClassEvenDirective,
ngClassOddDirective,
ngCspDirective,
ngCloakDirective,
ngControllerDirective,
ngFormDirective,
ngHideDirective,
ngIfDirective,
ngIncludeDirective,
ngInitDirective,
ngNonBindableDirective,
ngPluralizeDirective,
ngRepeatDirective,
ngShowDirective,
ngStyleDirective,
ngSwitchDirective,
ngSwitchWhenDirective,
ngSwitchDefaultDirective,
ngOptionsDirective,
ngTranscludeDirective,
ngModelDirective,
ngListDirective,
ngChangeDirective,
requiredDirective,
requiredDirective,
ngValueDirective,
ngAttributeAliasDirectives,
ngEventDirectives,
$AnchorScrollProvider,
$AnimateProvider,
$BrowserProvider,
$CacheFactoryProvider,
$ControllerProvider,
$DocumentProvider,
$ExceptionHandlerProvider,
$FilterProvider,
$InterpolateProvider,
$IntervalProvider,
$HttpProvider,
$HttpBackendProvider,
$LocationProvider,
$LogProvider,
$ParseProvider,
$RootScopeProvider,
$QProvider,
$SceProvider,
$SceDelegateProvider,
$SnifferProvider,
$TemplateCacheProvider,
$TimeoutProvider,
$WindowProvider
*/
/** /**
* @ngdoc property * @ngdoc property
* @name angular.version * @name angular.version

View file

@ -116,9 +116,9 @@ function annotate(fn) {
* *
* ## Inference * ## Inference
* *
* In JavaScript calling `toString()` on a function returns the function definition. The definition can then be * In JavaScript calling `toString()` on a function returns the function definition. The definition
* parsed and the function arguments can be extracted. *NOTE:* This does not work with minification, and obfuscation * can then be parsed and the function arguments can be extracted. *NOTE:* This does not work with
* tools since these tools change the argument names. * minification, and obfuscation tools since these tools change the argument names.
* *
* ## `$inject` Annotation * ## `$inject` Annotation
* By adding a `$inject` property onto a function the injection parameters can be specified. * By adding a `$inject` property onto a function the injection parameters can be specified.
@ -150,8 +150,8 @@ function annotate(fn) {
* @param {!function} fn The function to invoke. Function parameters are injected according to the * @param {!function} fn The function to invoke. Function parameters are injected according to the
* {@link guide/di $inject Annotation} rules. * {@link guide/di $inject Annotation} rules.
* @param {Object=} self The `this` for the invoked method. * @param {Object=} self The `this` for the invoked method.
* @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before * @param {Object=} locals Optional object. If preset then any argument names are read from this
* the `$injector` is consulted. * object first, before the `$injector` is consulted.
* @returns {*} the value returned by the invoked `fn` function. * @returns {*} the value returned by the invoked `fn` function.
*/ */
@ -172,12 +172,13 @@ function annotate(fn) {
* @name AUTO.$injector#instantiate * @name AUTO.$injector#instantiate
* @methodOf AUTO.$injector * @methodOf AUTO.$injector
* @description * @description
* Create a new instance of JS type. The method takes a constructor function invokes the new operator and supplies * Create a new instance of JS type. The method takes a constructor function invokes the new
* all of the arguments to the constructor function as specified by the constructor annotation. * operator and supplies all of the arguments to the constructor function as specified by the
* constructor annotation.
* *
* @param {function} Type Annotated constructor function. * @param {function} Type Annotated constructor function.
* @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before * @param {Object=} locals Optional object. If preset then any argument names are read from this
* the `$injector` is consulted. * object first, before the `$injector` is consulted.
* @returns {Object} new instance of `Type`. * @returns {Object} new instance of `Type`.
*/ */
@ -187,14 +188,16 @@ function annotate(fn) {
* @methodOf AUTO.$injector * @methodOf AUTO.$injector
* *
* @description * @description
* Returns an array of service names which the function is requesting for injection. This API is used by the injector * Returns an array of service names which the function is requesting for injection. This API is
* to determine which services need to be injected into the function when the function is invoked. There are three * used by the injector to determine which services need to be injected into the function when the
* ways in which the function can be annotated with the needed dependencies. * function is invoked. There are three ways in which the function can be annotated with the needed
* dependencies.
* *
* # Argument names * # Argument names
* *
* The simplest form is to extract the dependencies from the arguments of the function. This is done by converting * The simplest form is to extract the dependencies from the arguments of the function. This is done
* the function into a string using `toString()` method and extracting the argument names. * by converting the function into a string using `toString()` method and extracting the argument
* names.
* <pre> * <pre>
* // Given * // Given
* function MyController($scope, $route) { * function MyController($scope, $route) {
@ -205,13 +208,13 @@ function annotate(fn) {
* expect(injector.annotate(MyController)).toEqual(['$scope', '$route']); * expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);
* </pre> * </pre>
* *
* This method does not work with code minification / obfuscation. For this reason the following annotation strategies * This method does not work with code minification / obfuscation. For this reason the following
* are supported. * annotation strategies are supported.
* *
* # The `$inject` property * # The `$inject` property
* *
* If a function has an `$inject` property and its value is an array of strings, then the strings represent names of * If a function has an `$inject` property and its value is an array of strings, then the strings
* services to be injected into the function. * represent names of services to be injected into the function.
* <pre> * <pre>
* // Given * // Given
* var MyController = function(obfuscatedScope, obfuscatedRoute) { * var MyController = function(obfuscatedScope, obfuscatedRoute) {
@ -226,9 +229,9 @@ function annotate(fn) {
* *
* # The array notation * # The array notation
* *
* It is often desirable to inline Injected functions and that's when setting the `$inject` property is very * It is often desirable to inline Injected functions and that's when setting the `$inject` property
* inconvenient. In these situations using the array notation to specify the dependencies in a way that survives * is very inconvenient. In these situations using the array notation to specify the dependencies in
* minification is a better choice: * a way that survives minification is a better choice:
* *
* <pre> * <pre>
* // We wish to write this (not minification / obfuscation safe) * // We wish to write this (not minification / obfuscation safe)
@ -254,8 +257,8 @@ function annotate(fn) {
* ).toEqual(['$compile', '$rootScope']); * ).toEqual(['$compile', '$rootScope']);
* </pre> * </pre>
* *
* @param {function|Array.<string|Function>} fn Function for which dependent service names need to be retrieved as described * @param {function|Array.<string|Function>} fn Function for which dependent service names need to
* above. * be retrieved as described above.
* *
* @returns {Array.<string>} The names of the services which the function requires. * @returns {Array.<string>} The names of the services which the function requires.
*/ */
@ -269,13 +272,14 @@ function annotate(fn) {
* *
* @description * @description
* *
* The {@link AUTO.$provide $provide} service has a number of methods for registering components with * The {@link AUTO.$provide $provide} service has a number of methods for registering components
* the {@link AUTO.$injector $injector}. Many of these functions are also exposed on {@link angular.Module}. * 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 * An Angular **service** is a singleton object created by a **service factory**. These **service
* factories** are functions which, in turn, are created by a **service provider**. * factories** are functions which, in turn, are created by a **service provider**.
* The **service providers** are constructor functions. When instantiated they must contain a property * The **service providers** are constructor functions. When instantiated they must contain a
* called `$get`, which holds the **service factory** function. * 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** * correct **service provider**, instantiating it and then calling its `$get` **service factory**
@ -292,12 +296,12 @@ function annotate(fn) {
* providers and services. * providers and services.
* * {@link AUTO.$provide#methods_value value(obj)} - registers a value/object that can only be accessed by * * {@link AUTO.$provide#methods_value value(obj)} - registers a value/object that can only be accessed by
* services, not providers. * services, not providers.
* * {@link AUTO.$provide#methods_factory factory(fn)} - registers a service **factory function**, `fn`, that * * {@link AUTO.$provide#factory factory(fn)} - registers a service **factory function**, `fn`,
* will be wrapped in a **service provider** object, whose `$get` property will contain the given * that will be wrapped in a **service provider** object, whose `$get` property will contain the
* factory function. * given factory function.
* * {@link AUTO.$provide#methods_service service(class)} - registers a **constructor function**, `class` that * * {@link AUTO.$provide#methods_service service(class)} - registers a **constructor function**, `class` that
* will be wrapped in a **service provider** object, whose `$get` property will instantiate a new * that will be wrapped in a **service provider** object, whose `$get` property will instantiate
* object using the given constructor function. * a new object using the given constructor function.
* *
* See the individual methods for more information and examples. * See the individual methods for more information and examples.
*/ */
@ -308,26 +312,31 @@ function annotate(fn) {
* @methodOf AUTO.$provide * @methodOf AUTO.$provide
* @description * @description
* *
* Register a **provider function** with the {@link AUTO.$injector $injector}. Provider functions are * Register a **provider function** with the {@link AUTO.$injector $injector}. Provider functions
* constructor functions, whose instances are responsible for "providing" a factory for a service. * are constructor functions, whose instances are responsible for "providing" a factory for a
* service.
* *
* Service provider names start with the name of the service they provide followed by `Provider`. * Service provider names start with the name of the service they provide followed by `Provider`.
* For example, the {@link ng.$log $log} service has a provider called {@link ng.$logProvider $logProvider}. * For example, the {@link ng.$log $log} service has a provider called
* {@link ng.$logProvider $logProvider}.
* *
* Service provider objects can have additional methods which allow configuration of the provider and * Service provider objects can have additional methods which allow configuration of the provider
* its service. Importantly, you can configure what kind of service is created by the `$get` method, * and its service. Importantly, you can configure what kind of service is created by the `$get`
* or how that service will act. For example, the {@link ng.$logProvider $logProvider} has a method * method, or how that service will act. For example, the {@link ng.$logProvider $logProvider} has a
* {@link ng.$logProvider#debugEnabled debugEnabled} * method {@link ng.$logProvider#debugEnabled debugEnabled}
* which lets you specify whether the {@link ng.$log $log} service will log debug messages to the * which lets you specify whether the {@link ng.$log $log} service will log debug messages to the
* console or not. * console or not.
* *
* @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provider'` key. * @param {string} name The name of the instance. NOTE: the provider will be available under `name +
'Provider'` key.
* @param {(Object|function())} provider If the provider is: * @param {(Object|function())} provider If the provider is:
* *
* - `Object`: then it should have a `$get` method. The `$get` method will be invoked using * - `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 * - `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 * @returns {Object} registered provider instance
@ -405,12 +414,12 @@ function annotate(fn) {
* Register a **service factory**, which will be called to return the service instance. * 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, * This is short for registering a service where its provider consists of only a `$get` property,
* which is the given service factory function. * which is the given service factory function.
* You should use {@link AUTO.$provide#factory $provide.factor(getFn)} if you do not need to configure * You should use {@link AUTO.$provide#factory $provide.factor(getFn)} if you do not need to
* your service in a provider. * configure your service in a provider.
* *
* @param {string} name The name of the instance. * @param {string} name The name of the instance.
* @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand for * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand
* `$provide.provider(name, {$get: $getFn})`. * for `$provide.provider(name, {$get: $getFn})`.
* @returns {Object} registered provider instance * @returns {Object} registered provider instance
* *
* @example * @example
@ -437,7 +446,8 @@ function annotate(fn) {
* @methodOf AUTO.$provide * @methodOf AUTO.$provide
* @description * @description
* *
* Register a **service constructor**, which will be invoked with `new` to create the service instance. * Register a **service constructor**, which will be invoked with `new` to create the service
* instance.
* This is short for registering a service where its provider's `$get` property is the service * 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. * constructor function that will be used to instantiate the service instance.
* *
@ -449,8 +459,8 @@ function annotate(fn) {
* @returns {Object} registered provider instance * @returns {Object} registered provider instance
* *
* @example * @example
* Here is an example of registering a service using {@link AUTO.$provide#methods_service $provide.service(class)} * Here is an example of registering a service using
* that is defined as a CoffeeScript class. * {@link AUTO.$provide#methods_service $provide.service(class)} that is defined as a CoffeeScript class.
* <pre> * <pre>
* class Ping * class Ping
* constructor: (@$http)-> * constructor: (@$http)->
@ -474,12 +484,14 @@ function annotate(fn) {
* @methodOf AUTO.$provide * @methodOf AUTO.$provide
* @description * @description
* *
* Register a **value service** with the {@link AUTO.$injector $injector}, such as a string, a number, * Register a **value service** with the {@link AUTO.$injector $injector}, such as a string, a
* an array, an object or a function. This is short for registering a service where its provider's * number, an array, an object or a function. This is short for registering a service where its
* `$get` property is a factory function that takes no arguments and returns the **value service**. * provider's `$get` property is a factory function that takes no arguments and returns the **value
* service**.
* *
* Value services are similar to constant services, except that they cannot be injected into a module * Value services are similar to constant services, except that they cannot be injected into a
* configuration function (see {@link angular.Module#config}) but they can be overridden by an Angular * 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 {string} name The name of the instance.
@ -506,10 +518,10 @@ function annotate(fn) {
* @methodOf AUTO.$provide * @methodOf AUTO.$provide
* @description * @description
* *
* Register a **constant service**, such as a string, a number, an array, an object or a function, with * Register a **constant service**, such as a string, a number, an array, an object or a function,
* the {@link AUTO.$injector $injector}. Unlike {@link AUTO.$provide#value value} it can be injected * with the {@link AUTO.$injector $injector}. Unlike {@link AUTO.$provide#value value} it can be
* into a module configuration function (see {@link angular.Module#config}) and it cannot be * injected into a module configuration function (see {@link angular.Module#config}) and it cannot
* 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 {string} name The name of the constant.
* @param {*} value The constant value. * @param {*} value The constant value.
@ -537,8 +549,8 @@ function annotate(fn) {
* *
* 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 * 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 * service. The object returned by the decorator may be the original service, or a new service
* which replaces or wraps and delegates to the original service. * object which replaces or wraps and delegates to the original service.
* *
* @param {string} name The name of the service to decorate. * @param {string} name The name of the service to decorate.
* @param {function()} decorator This function will be invoked when the service needs to be * @param {function()} decorator This function will be invoked when the service needs to be
@ -603,7 +615,7 @@ function createInjector(modulesToLoad) {
} else { } else {
return delegate(key, value); return delegate(key, value);
} }
} };
} }
function provider(name, provider_) { function provider(name, provider_) {
@ -625,7 +637,7 @@ function createInjector(modulesToLoad) {
}]); }]);
} }
function value(name, value) { return factory(name, valueFn(value)); } function value(name, val) { return factory(name, valueFn(val)); }
function constant(name, value) { function constant(name, value) {
assertNotHasOwnProperty(name, 'constant'); assertNotHasOwnProperty(name, 'constant');
@ -647,17 +659,17 @@ function createInjector(modulesToLoad) {
// Module Loading // Module Loading
//////////////////////////////////// ////////////////////////////////////
function loadModules(modulesToLoad){ function loadModules(modulesToLoad){
var runBlocks = []; var runBlocks = [], moduleFn, invokeQueue, i, ii;
forEach(modulesToLoad, function(module) { forEach(modulesToLoad, function(module) {
if (loadedModules.get(module)) return; if (loadedModules.get(module)) return;
loadedModules.put(module, true); loadedModules.put(module, true);
try { try {
if (isString(module)) { if (isString(module)) {
var moduleFn = angularModule(module); moduleFn = angularModule(module);
runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks); runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);
for(var invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) { for(invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {
var invokeArgs = invokeQueue[i], var invokeArgs = invokeQueue[i],
provider = providerInjector.get(invokeArgs[0]); provider = providerInjector.get(invokeArgs[0]);
@ -675,12 +687,15 @@ function createInjector(modulesToLoad) {
module = module[module.length - 1]; module = module[module.length - 1];
} }
if (e.message && e.stack && e.stack.indexOf(e.message) == -1) { if (e.message && e.stack && e.stack.indexOf(e.message) == -1) {
// Safari & FF's stack traces don't contain error.message content unlike those of Chrome and IE // Safari & FF's stack traces don't contain error.message content
// unlike those of Chrome and IE
// So if stack doesn't contain message, we create a new string that contains both. // So if stack doesn't contain message, we create a new string that contains both.
// Since error.stack is read-only in Safari, I'm overriding e and not e.stack here. // Since error.stack is read-only in Safari, I'm overriding e and not e.stack here.
/* jshint -W022 */
e = e.message + '\n' + e.stack; e = e.message + '\n' + e.stack;
} }
throw $injectorMinErr('modulerr', "Failed to instantiate module {0} due to:\n{1}", module, e.stack || e.message || e); throw $injectorMinErr('modulerr', "Failed to instantiate module {0} due to:\n{1}",
module, e.stack || e.message || e);
} }
}); });
return runBlocks; return runBlocks;
@ -718,7 +733,8 @@ function createInjector(modulesToLoad) {
for(i = 0, length = $inject.length; i < length; i++) { for(i = 0, length = $inject.length; i < length; i++) {
key = $inject[i]; key = $inject[i];
if (typeof key !== 'string') { if (typeof key !== 'string') {
throw $injectorMinErr('itkn', 'Incorrect injection token! Expected service name as string, got {0}', key); throw $injectorMinErr('itkn',
'Incorrect injection token! Expected service name as string, got {0}', key);
} }
args.push( args.push(
locals && locals.hasOwnProperty(key) locals && locals.hasOwnProperty(key)
@ -743,8 +759,10 @@ function createInjector(modulesToLoad) {
case 6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]); 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 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 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 9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7],
case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]); 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); default: return fn.apply(self, args);
} }
} }

View file

@ -1,5 +1,13 @@
'use strict'; 'use strict';
/* global
-JQLitePrototype,
-addEventListenerFn,
-removeEventListenerFn,
-BOOLEAN_ATTR
*/
////////////////////////////////// //////////////////////////////////
//JQLite //JQLite
////////////////////////////////// //////////////////////////////////
@ -122,13 +130,14 @@ function camelCase(name) {
// //
///////////////////////////////////////////// /////////////////////////////////////////////
function JQLitePatchJQueryRemove(name, dispatchThis, filterElems, getterIfNoArguments) { function jqLitePatchJQueryRemove(name, dispatchThis, filterElems, getterIfNoArguments) {
var originalJqFn = jQuery.fn[name]; var originalJqFn = jQuery.fn[name];
originalJqFn = originalJqFn.$original || originalJqFn; originalJqFn = originalJqFn.$original || originalJqFn;
removePatch.$original = originalJqFn; removePatch.$original = originalJqFn;
jQuery.fn[name] = removePatch; jQuery.fn[name] = removePatch;
function removePatch(param) { function removePatch(param) {
// jshint -W040
var list = filterElems && param ? [this.filter(param)] : [this], var list = filterElems && param ? [this.filter(param)] : [this],
fireEvent = dispatchThis, fireEvent = dispatchThis,
set, setIndex, setLength, set, setIndex, setLength,
@ -174,30 +183,30 @@ function JQLite(element) {
// http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx // http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx
div.innerHTML = '<div>&#160;</div>' + element; // IE insanity to make NoScope elements work! div.innerHTML = '<div>&#160;</div>' + element; // IE insanity to make NoScope elements work!
div.removeChild(div.firstChild); // remove the superfluous div div.removeChild(div.firstChild); // remove the superfluous div
JQLiteAddNodes(this, div.childNodes); jqLiteAddNodes(this, div.childNodes);
var fragment = jqLite(document.createDocumentFragment()); var fragment = jqLite(document.createDocumentFragment());
fragment.append(this); // detach the elements from the temporary DOM div. fragment.append(this); // detach the elements from the temporary DOM div.
} else { } else {
JQLiteAddNodes(this, element); jqLiteAddNodes(this, element);
} }
} }
function JQLiteClone(element) { function jqLiteClone(element) {
return element.cloneNode(true); return element.cloneNode(true);
} }
function JQLiteDealoc(element){ function jqLiteDealoc(element){
JQLiteRemoveData(element); jqLiteRemoveData(element);
for ( var i = 0, children = element.childNodes || []; i < children.length; i++) { for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {
JQLiteDealoc(children[i]); jqLiteDealoc(children[i]);
} }
} }
function JQLiteOff(element, type, fn, unsupported) { function jqLiteOff(element, type, fn, unsupported) {
if (isDefined(unsupported)) throw jqLiteMinErr('offargs', 'jqLite#off() does not support the `selector` argument'); if (isDefined(unsupported)) throw jqLiteMinErr('offargs', 'jqLite#off() does not support the `selector` argument');
var events = JQLiteExpandoStore(element, 'events'), var events = jqLiteExpandoStore(element, 'events'),
handle = JQLiteExpandoStore(element, 'handle'); handle = jqLiteExpandoStore(element, 'handle');
if (!handle) return; //no listeners registered if (!handle) return; //no listeners registered
@ -218,7 +227,7 @@ function JQLiteOff(element, type, fn, unsupported) {
} }
} }
function JQLiteRemoveData(element, name) { function jqLiteRemoveData(element, name) {
var expandoId = element[jqName], var expandoId = element[jqName],
expandoStore = jqCache[expandoId]; expandoStore = jqCache[expandoId];
@ -230,14 +239,14 @@ function JQLiteRemoveData(element, name) {
if (expandoStore.handle) { if (expandoStore.handle) {
expandoStore.events.$destroy && expandoStore.handle({}, '$destroy'); expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');
JQLiteOff(element); jqLiteOff(element);
} }
delete jqCache[expandoId]; delete jqCache[expandoId];
element[jqName] = undefined; // ie does not allow deletion of attributes on elements. element[jqName] = undefined; // ie does not allow deletion of attributes on elements.
} }
} }
function JQLiteExpandoStore(element, key, value) { function jqLiteExpandoStore(element, key, value) {
var expandoId = element[jqName], var expandoId = element[jqName],
expandoStore = jqCache[expandoId || -1]; expandoStore = jqCache[expandoId || -1];
@ -252,14 +261,14 @@ function JQLiteExpandoStore(element, key, value) {
} }
} }
function JQLiteData(element, key, value) { function jqLiteData(element, key, value) {
var data = JQLiteExpandoStore(element, 'data'), var data = jqLiteExpandoStore(element, 'data'),
isSetter = isDefined(value), isSetter = isDefined(value),
keyDefined = !isSetter && isDefined(key), keyDefined = !isSetter && isDefined(key),
isSimpleGetter = keyDefined && !isObject(key); isSimpleGetter = keyDefined && !isObject(key);
if (!data && !isSimpleGetter) { if (!data && !isSimpleGetter) {
JQLiteExpandoStore(element, 'data', data = {}); jqLiteExpandoStore(element, 'data', data = {});
} }
if (isSetter) { if (isSetter) {
@ -278,13 +287,13 @@ function JQLiteData(element, key, value) {
} }
} }
function JQLiteHasClass(element, selector) { function jqLiteHasClass(element, selector) {
if (!element.getAttribute) return false; if (!element.getAttribute) return false;
return ((" " + (element.getAttribute('class') || '') + " ").replace(/[\n\t]/g, " "). return ((" " + (element.getAttribute('class') || '') + " ").replace(/[\n\t]/g, " ").
indexOf( " " + selector + " " ) > -1); indexOf( " " + selector + " " ) > -1);
} }
function JQLiteRemoveClass(element, cssClasses) { function jqLiteRemoveClass(element, cssClasses) {
if (cssClasses && element.setAttribute) { if (cssClasses && element.setAttribute) {
forEach(cssClasses.split(' '), function(cssClass) { forEach(cssClasses.split(' '), function(cssClass) {
element.setAttribute('class', trim( element.setAttribute('class', trim(
@ -296,7 +305,7 @@ function JQLiteRemoveClass(element, cssClasses) {
} }
} }
function JQLiteAddClass(element, cssClasses) { function jqLiteAddClass(element, cssClasses) {
if (cssClasses && element.setAttribute) { if (cssClasses && element.setAttribute) {
var existingClasses = (' ' + (element.getAttribute('class') || '') + ' ') var existingClasses = (' ' + (element.getAttribute('class') || '') + ' ')
.replace(/[\n\t]/g, " "); .replace(/[\n\t]/g, " ");
@ -312,7 +321,7 @@ function JQLiteAddClass(element, cssClasses) {
} }
} }
function JQLiteAddNodes(root, elements) { function jqLiteAddNodes(root, elements) {
if (elements) { if (elements) {
elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements)) elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))
? elements ? elements
@ -323,11 +332,11 @@ function JQLiteAddNodes(root, elements) {
} }
} }
function JQLiteController(element, name) { function jqLiteController(element, name) {
return JQLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller'); return jqLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');
} }
function JQLiteInheritedData(element, name, value) { function jqLiteInheritedData(element, name, value) {
element = jqLite(element); element = jqLite(element);
// if element is the document object work with the html element instead // if element is the document object work with the html element instead
@ -361,7 +370,9 @@ var JQLitePrototype = JQLite.prototype = {
} else { } else {
this.on('DOMContentLoaded', trigger); // works for modern browsers and IE9 this.on('DOMContentLoaded', trigger); // works for modern browsers and IE9
// we can not use jqLite since we are not done loading and jQuery could be loaded later. // we can not use jqLite since we are not done loading and jQuery could be loaded later.
// jshint -W064
JQLite(window).on('load', trigger); // fallback to window.onload for others JQLite(window).on('load', trigger); // fallback to window.onload for others
// jshint +W064
} }
}, },
toString: function() { toString: function() {
@ -403,24 +414,24 @@ function getBooleanAttrName(element, name) {
} }
forEach({ forEach({
data: JQLiteData, data: jqLiteData,
inheritedData: JQLiteInheritedData, inheritedData: jqLiteInheritedData,
scope: function(element) { scope: function(element) {
return JQLiteInheritedData(element, '$scope'); return jqLiteInheritedData(element, '$scope');
}, },
controller: JQLiteController , controller: jqLiteController ,
injector: function(element) { injector: function(element) {
return JQLiteInheritedData(element, '$injector'); return jqLiteInheritedData(element, '$injector');
}, },
removeAttr: function(element,name) { removeAttr: function(element,name) {
element.removeAttribute(name); element.removeAttribute(name);
}, },
hasClass: JQLiteHasClass, hasClass: jqLiteHasClass,
css: function(element, name, value) { css: function(element, name, value) {
name = camelCase(name); name = camelCase(name);
@ -496,7 +507,7 @@ forEach({
return getText; return getText;
function getText(element, value) { function getText(element, value) {
var textProp = NODE_TYPE_TEXT_PROPERTY[element.nodeType] var textProp = NODE_TYPE_TEXT_PROPERTY[element.nodeType];
if (isUndefined(value)) { if (isUndefined(value)) {
return textProp ? element[textProp] : ''; return textProp ? element[textProp] : '';
} }
@ -525,7 +536,7 @@ forEach({
return element.innerHTML; return element.innerHTML;
} }
for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) { for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {
JQLiteDealoc(childNodes[i]); jqLiteDealoc(childNodes[i]);
} }
element.innerHTML = value; element.innerHTML = value;
} }
@ -536,14 +547,14 @@ forEach({
JQLite.prototype[name] = function(arg1, arg2) { JQLite.prototype[name] = function(arg1, arg2) {
var i, key; var i, key;
// JQLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it // jqLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it
// in a way that survives minification. // in a way that survives minification.
if (((fn.length == 2 && (fn !== JQLiteHasClass && fn !== JQLiteController)) ? arg1 : arg2) === undefined) { if (((fn.length == 2 && (fn !== jqLiteHasClass && fn !== jqLiteController)) ? arg1 : arg2) === undefined) {
if (isObject(arg1)) { if (isObject(arg1)) {
// we are a write, but the object properties are the key/values // we are a write, but the object properties are the key/values
for(i=0; i < this.length; i++) { for(i=0; i < this.length; i++) {
if (fn === JQLiteData) { if (fn === jqLiteData) {
// data() takes the whole object in jQuery // data() takes the whole object in jQuery
fn(this[i], arg1); fn(this[i], arg1);
} else { } else {
@ -558,7 +569,7 @@ forEach({
// we are a read, so read the first child. // we are a read, so read the first child.
var value = fn.$dv; var value = fn.$dv;
// Only if we have $dv do we iterate over all, otherwise it is just the first element. // Only if we have $dv do we iterate over all, otherwise it is just the first element.
var jj = value == undefined ? Math.min(this.length, 1) : this.length; var jj = (value === undefined) ? Math.min(this.length, 1) : this.length;
for (var j = 0; j < jj; j++) { for (var j = 0; j < jj; j++) {
var nodeValue = fn(this[j], arg1, arg2); var nodeValue = fn(this[j], arg1, arg2);
value = value ? value + nodeValue : nodeValue; value = value ? value + nodeValue : nodeValue;
@ -604,7 +615,7 @@ function createEventHandler(element, events) {
} }
event.isDefaultPrevented = function() { event.isDefaultPrevented = function() {
return event.defaultPrevented || event.returnValue == false; return event.defaultPrevented || event.returnValue === false;
}; };
forEach(events[type || event.type], function(fn) { forEach(events[type || event.type], function(fn) {
@ -635,18 +646,18 @@ function createEventHandler(element, events) {
// selector. // selector.
////////////////////////////////////////// //////////////////////////////////////////
forEach({ forEach({
removeData: JQLiteRemoveData, removeData: jqLiteRemoveData,
dealoc: JQLiteDealoc, dealoc: jqLiteDealoc,
on: function onFn(element, type, fn, unsupported){ on: function onFn(element, type, fn, unsupported){
if (isDefined(unsupported)) throw jqLiteMinErr('onargs', 'jqLite#on() does not support the `selector` or `eventData` parameters'); if (isDefined(unsupported)) throw jqLiteMinErr('onargs', 'jqLite#on() does not support the `selector` or `eventData` parameters');
var events = JQLiteExpandoStore(element, 'events'), var events = jqLiteExpandoStore(element, 'events'),
handle = JQLiteExpandoStore(element, 'handle'); handle = jqLiteExpandoStore(element, 'handle');
if (!events) JQLiteExpandoStore(element, 'events', events = {}); if (!events) jqLiteExpandoStore(element, 'events', events = {});
if (!handle) JQLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events)); if (!handle) jqLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));
forEach(type.split(' '), function(type){ forEach(type.split(' '), function(type){
var eventFns = events[type]; var eventFns = events[type];
@ -655,6 +666,7 @@ forEach({
if (type == 'mouseenter' || type == 'mouseleave') { if (type == 'mouseenter' || type == 'mouseleave') {
var contains = document.body.contains || document.body.compareDocumentPosition ? var contains = document.body.contains || document.body.compareDocumentPosition ?
function( a, b ) { function( a, b ) {
// jshint bitwise: false
var adown = a.nodeType === 9 ? a.documentElement : a, var adown = a.nodeType === 9 ? a.documentElement : a,
bup = b && b.parentNode; bup = b && b.parentNode;
return a === bup || !!( bup && bup.nodeType === 1 && ( return a === bup || !!( bup && bup.nodeType === 1 && (
@ -694,17 +706,17 @@ forEach({
addEventListenerFn(element, type, handle); addEventListenerFn(element, type, handle);
events[type] = []; events[type] = [];
} }
eventFns = events[type] eventFns = events[type];
} }
eventFns.push(fn); eventFns.push(fn);
}); });
}, },
off: JQLiteOff, off: jqLiteOff,
replaceWith: function(element, replaceNode) { replaceWith: function(element, replaceNode) {
var index, parent = element.parentNode; var index, parent = element.parentNode;
JQLiteDealoc(element); jqLiteDealoc(element);
forEach(new JQLite(replaceNode), function(node){ forEach(new JQLite(replaceNode), function(node){
if (index) { if (index) {
parent.insertBefore(node, index.nextSibling); parent.insertBefore(node, index.nextSibling);
@ -755,7 +767,7 @@ forEach({
}, },
remove: function(element) { remove: function(element) {
JQLiteDealoc(element); jqLiteDealoc(element);
var parent = element.parentNode; var parent = element.parentNode;
if (parent) parent.removeChild(element); if (parent) parent.removeChild(element);
}, },
@ -768,14 +780,14 @@ forEach({
}); });
}, },
addClass: JQLiteAddClass, addClass: jqLiteAddClass,
removeClass: JQLiteRemoveClass, removeClass: jqLiteRemoveClass,
toggleClass: function(element, selector, condition) { toggleClass: function(element, selector, condition) {
if (isUndefined(condition)) { if (isUndefined(condition)) {
condition = !JQLiteHasClass(element, selector); condition = !jqLiteHasClass(element, selector);
} }
(condition ? JQLiteAddClass : JQLiteRemoveClass)(element, selector); (condition ? jqLiteAddClass : jqLiteRemoveClass)(element, selector);
}, },
parent: function(element) { parent: function(element) {
@ -800,10 +812,10 @@ forEach({
return element.getElementsByTagName(selector); return element.getElementsByTagName(selector);
}, },
clone: JQLiteClone, clone: jqLiteClone,
triggerHandler: function(element, eventName, eventData) { triggerHandler: function(element, eventName, eventData) {
var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName]; var eventFns = (jqLiteExpandoStore(element, 'events') || {})[eventName];
eventData = eventData || []; eventData = eventData || [];
@ -823,17 +835,17 @@ forEach({
JQLite.prototype[name] = function(arg1, arg2, arg3) { JQLite.prototype[name] = function(arg1, arg2, arg3) {
var value; var value;
for(var i=0; i < this.length; i++) { for(var i=0; i < this.length; i++) {
if (value == undefined) { if (isUndefined(value)) {
value = fn(this[i], arg1, arg2, arg3); value = fn(this[i], arg1, arg2, arg3);
if (value !== undefined) { if (isDefined(value)) {
// any function which returns a value needs to be wrapped // any function which returns a value needs to be wrapped
value = jqLite(value); value = jqLite(value);
} }
} else { } else {
JQLiteAddNodes(value, fn(this[i], arg1, arg2, arg3)); jqLiteAddNodes(value, fn(this[i], arg1, arg2, arg3));
} }
} }
return value == undefined ? this : value; return isDefined(value) ? value : this;
}; };
// bind legacy bind/unbind to on/off // bind legacy bind/unbind to on/off

View file

@ -25,7 +25,8 @@ function setupModuleLoader(window) {
* @name angular.module * @name angular.module
* @description * @description
* *
* The `angular.module` is a global place for creating, registering and retrieving Angular modules. * The `angular.module` is a global place for creating, registering and retrieving Angular
* modules.
* All modules (angular core or 3rd party) that should be available to an application must be * All modules (angular core or 3rd party) that should be available to an application must be
* registered using this mechanism. * registered using this mechanism.
* *
@ -63,8 +64,8 @@ function setupModuleLoader(window) {
* {@link angular.bootstrap} to simplify this process for you. * {@link angular.bootstrap} to simplify this process for you.
* *
* @param {!string} name The name of the module to create or retrieve. * @param {!string} name The name of the module to create or retrieve.
* @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the * @param {Array.<string>=} requires If specified then new module is being created. If
* the module is being retrieved for further configuration. * unspecified then the the module is being retrieved for further configuration.
* @param {Function} configFn Optional configuration function for the module. Same as * @param {Function} configFn Optional configuration function for the module. Same as
* {@link angular.Module#methods_config Module#config()}. * {@link angular.Module#methods_config Module#config()}.
* @returns {module} new module with the {@link angular.Module} api. * @returns {module} new module with the {@link angular.Module} api.
@ -76,9 +77,9 @@ function setupModuleLoader(window) {
} }
return ensure(modules, name, function() { return ensure(modules, name, function() {
if (!requires) { if (!requires) {
throw $injectorMinErr('nomod', "Module '{0}' is not available! You either misspelled the module name " + throw $injectorMinErr('nomod', "Module '{0}' is not available! You either misspelled " +
"or forgot to load it. If registering a module ensure that you specify the dependencies as the second " + "the module name or forgot to load it. If registering a module ensure that you " +
"argument.", name); "specify the dependencies as the second argument.", name);
} }
/** @type {!Array.<Array.<*>>} */ /** @type {!Array.<Array.<*>>} */
@ -101,7 +102,8 @@ function setupModuleLoader(window) {
* @propertyOf angular.Module * @propertyOf angular.Module
* @returns {Array.<string>} List of module names which must be loaded before this module. * @returns {Array.<string>} List of module names which must be loaded before this module.
* @description * @description
* Holds the list of modules which the injector will load before the current module is loaded. * Holds the list of modules which the injector will load before the current module is
* loaded.
*/ */
requires: requires, requires: requires,
@ -120,7 +122,8 @@ function setupModuleLoader(window) {
* @name angular.Module#provider * @name angular.Module#provider
* @methodOf angular.Module * @methodOf angular.Module
* @param {string} name service name * @param {string} name service name
* @param {Function} providerType Construction function for creating new instance of the service. * @param {Function} providerType Construction function for creating new instance of the
* service.
* @description * @description
* See {@link AUTO.$provide#provider $provide.provider()}. * See {@link AUTO.$provide#provider $provide.provider()}.
*/ */
@ -176,14 +179,15 @@ function setupModuleLoader(window) {
* @name angular.Module#animation * @name angular.Module#animation
* @methodOf angular.Module * @methodOf angular.Module
* @param {string} name animation name * @param {string} name animation name
* @param {Function} animationFactory Factory function for creating new instance of an animation. * @param {Function} animationFactory Factory function for creating new instance of an
* animation.
* @description * @description
* *
* **NOTE**: animations take effect only if the **ngAnimate** module is loaded. * **NOTE**: animations take effect only if the **ngAnimate** module is loaded.
* *
* *
* Defines an animation hook that can be later used with {@link ngAnimate.$animate $animate} service and * Defines an animation hook that can be later used with
* directives that use this service. * {@link ngAnimate.$animate $animate} service and directives that use this service.
* *
* <pre> * <pre>
* module.animation('.animation-name', function($inject1, $inject2) { * module.animation('.animation-name', function($inject1, $inject2) {
@ -283,7 +287,7 @@ function setupModuleLoader(window) {
return function() { return function() {
invokeQueue[insertMethod || 'push']([provider, method, arguments]); invokeQueue[insertMethod || 'push']([provider, method, arguments]);
return moduleInstance; return moduleInstance;
} };
} }
}); });
}; };

View file

@ -1,3 +1,5 @@
'use strict';
/** /**
* @ngdoc function * @ngdoc function
* @name ng.$anchorScroll * @name ng.$anchorScroll

View file

@ -7,7 +7,8 @@ var $animateMinErr = minErr('$animate');
* @name ng.$animateProvider * @name ng.$animateProvider
* *
* @description * @description
* Default implementation of $animate that doesn't perform any animations, instead just synchronously performs DOM * Default implementation of $animate that doesn't perform any animations, instead just
* synchronously performs DOM
* updates and calls done() callbacks. * updates and calls done() callbacks.
* *
* In order to enable animations the ngAnimate module has to be loaded. * In order to enable animations the ngAnimate module has to be loaded.
@ -16,6 +17,7 @@ var $animateMinErr = minErr('$animate');
*/ */
var $AnimateProvider = ['$provide', function($provide) { var $AnimateProvider = ['$provide', function($provide) {
this.$$selectors = {}; this.$$selectors = {};
@ -25,12 +27,14 @@ var $AnimateProvider = ['$provide', function($provide) {
* @methodOf ng.$animateProvider * @methodOf ng.$animateProvider
* *
* @description * @description
* Registers a new injectable animation factory function. The factory function produces the animation object which * Registers a new injectable animation factory function. The factory function produces the
* contains callback functions for each event that is expected to be animated. * animation object which contains callback functions for each event that is expected to be
* animated.
* *
* * `eventFn`: `function(Element, doneFunction)` The element to animate, the `doneFunction` must be called once the * * `eventFn`: `function(Element, doneFunction)` The element to animate, the `doneFunction`
* element animation is complete. If a function is returned then the animation service will use this function to * must be called once the element animation is complete. If a function is returned then the
* cancel the animation whenever a cancel event is triggered. * animation service will use this function to cancel the animation whenever a cancel event is
* triggered.
* *
* *
*<pre> *<pre>
@ -46,7 +50,8 @@ var $AnimateProvider = ['$provide', function($provide) {
*</pre> *</pre>
* *
* @param {string} name The name of the animation. * @param {string} name The name of the animation.
* @param {function} factory The factory function that will be executed to return the animation object. * @param {function} factory The factory function that will be executed to return the animation
* object.
*/ */
this.register = function(name, factory) { this.register = function(name, factory) {
var key = name + '-animation'; var key = name + '-animation';
@ -59,36 +64,39 @@ var $AnimateProvider = ['$provide', function($provide) {
this.$get = ['$timeout', function($timeout) { this.$get = ['$timeout', function($timeout) {
/** /**
*
* @ngdoc object * @ngdoc object
* @name ng.$animate * @name ng.$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
* high-level animation hooks for CSS and JavaScript.
* *
* @description * $animate is available in the AngularJS core, however, the ngAnimate module must be included
* The $animate service provides rudimentary DOM manipulation functions to insert, remove and move elements within * to enable full out animation support. Otherwise, $animate will only perform simple DOM
* the DOM, as well as adding and removing classes. This service is the core service used by the ngAnimate $animator * manipulation operations.
* service which provides high-level animation hooks for CSS and JavaScript.
* *
* $animate is available in the AngularJS core, however, the ngAnimate module must be included to enable full out * To learn more about enabling animation support, click here to visit the {@link ngAnimate
* animation support. Otherwise, $animate will only perform simple DOM manipulation operations. * ngAnimate module page} as well as the {@link ngAnimate.$animate ngAnimate $animate service
* * page}.
* To learn more about enabling animation support, click here to visit the {@link ngAnimate ngAnimate module page}
* as well as the {@link ngAnimate.$animate ngAnimate $animate service page}.
*/ */
return { return {
/** /**
*
* @ngdoc function * @ngdoc function
* @name ng.$animate#enter * @name ng.$animate#enter
* @methodOf ng.$animate * @methodOf ng.$animate
* @function * @function
* * @description Inserts the element into the DOM either after the `after` element or within
* @description * the `parent` element. Once complete, the done() callback will be fired (if provided).
* 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} element the element which will be inserted into the DOM
* @param {jQuery/jqLite element} parent the parent element which will append the element as a child (if the after element is not present) * @param {jQuery/jqLite element} parent the parent element which will append the element as
* @param {jQuery/jqLite element} after the sibling element which will append the element after itself * a child (if the after element is not present)
* @param {function=} done callback function that will be called after the element has been inserted into the DOM * @param {jQuery/jqLite element} 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
* inserted into the DOM
*/ */
enter : function(element, parent, after, done) { enter : function(element, parent, after, done) {
var afterNode = after && after[after.length - 1]; var afterNode = after && after[after.length - 1];
@ -102,16 +110,16 @@ var $AnimateProvider = ['$provide', function($provide) {
}, },
/** /**
*
* @ngdoc function * @ngdoc function
* @name ng.$animate#leave * @name ng.$animate#leave
* @methodOf ng.$animate * @methodOf ng.$animate
* @function * @function
* * @description Removes the element from the DOM. Once complete, the done() callback will be
* @description * fired (if provided).
* 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 {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 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) { leave : function(element, done) {
element.remove(); element.remove();
@ -119,19 +127,23 @@ var $AnimateProvider = ['$provide', function($provide) {
}, },
/** /**
*
* @ngdoc function * @ngdoc function
* @name ng.$animate#move * @name ng.$animate#move
* @methodOf ng.$animate * @methodOf ng.$animate
* @function * @function
* * @description Moves the position of the provided element within the DOM to be placed
* @description * either after the `after` element or inside of the `parent` element. Once complete, the
* Moves the position of the provided element within the DOM to be placed either after the `after` element or inside of the `parent` element. * done() callback will be fired (if provided).
* 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 {jQuery/jqLite element} element the element which will be moved around within the DOM * DOM
* @param {jQuery/jqLite element} parent the parent element where the element will be inserted into (if the after element is not present) * @param {jQuery/jqLite element} parent the parent element where the element will be
* @param {jQuery/jqLite element} after the sibling element where the element will be positioned next to * inserted into (if the after element is not present)
* @param {function=} done the callback function (if provided) that will be fired after the element has been moved to its new position * @param {jQuery/jqLite element} 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
* element has been moved to its new position
*/ */
move : function(element, parent, after, done) { move : function(element, parent, after, done) {
// Do not remove element before insert. Removing will cause data associated with the // Do not remove element before insert. Removing will cause data associated with the
@ -140,47 +152,49 @@ var $AnimateProvider = ['$provide', function($provide) {
}, },
/** /**
*
* @ngdoc function * @ngdoc function
* @name ng.$animate#addClass * @name ng.$animate#addClass
* @methodOf ng.$animate * @methodOf ng.$animate
* @function * @function
* * @description Adds the provided className CSS class value to the provided element. Once
* @description * complete, the done() callback will be fired (if provided).
* 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
* * added to it
* @param {jQuery/jqLite element} 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 {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 className value has been added to the element * @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) { addClass : function(element, className, done) {
className = isString(className) ? className = isString(className) ?
className : className :
isArray(className) ? className.join(' ') : ''; isArray(className) ? className.join(' ') : '';
forEach(element, function (element) { forEach(element, function (element) {
JQLiteAddClass(element, className); jqLiteAddClass(element, className);
}); });
done && $timeout(done, 0, false); done && $timeout(done, 0, false);
}, },
/** /**
*
* @ngdoc function * @ngdoc function
* @name ng.$animate#removeClass * @name ng.$animate#removeClass
* @methodOf ng.$animate * @methodOf ng.$animate
* @function * @function
* * @description Removes the provided className CSS class value from the provided element.
* @description * Once complete, the done() callback will be fired (if provided).
* 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
* * removed from it
* @param {jQuery/jqLite element} 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 {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 className value has been removed from the element * @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) { removeClass : function(element, className, done) {
className = isString(className) ? className = isString(className) ?
className : className :
isArray(className) ? className.join(' ') : ''; isArray(className) ? className.join(' ') : '';
forEach(element, function (element) { forEach(element, function (element) {
JQLiteRemoveClass(element, className); jqLiteRemoveClass(element, className);
}); });
done && $timeout(done, 0, false); done && $timeout(done, 0, false);
}, },

View file

@ -274,30 +274,35 @@ function Browser(window, document, $log, $sniffer) {
* It is not meant to be used directly, use the $cookie service instead. * 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: * The return values vary depending on the arguments that the method was called with as follows:
* <ul> *
* <li>cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify it</li> * - cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify
* <li>cookies(name, value) -> set name to value, if value is undefined delete the cookie</li> * it
* <li>cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that way)</li> * - cookies(name, value) -> set name to value, if value is undefined delete the cookie
* </ul> * - 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) * @returns {Object} Hash of all cookies (if called without any parameter)
*/ */
self.cookies = function(name, value) { self.cookies = function(name, value) {
/* global escape: false, unescape: false */
var cookieLength, cookieArray, cookie, i, index; var cookieLength, cookieArray, cookie, i, index;
if (name) { if (name) {
if (value === undefined) { if (value === undefined) {
rawDocument.cookie = escape(name) + "=;path=" + cookiePath + ";expires=Thu, 01 Jan 1970 00:00:00 GMT"; rawDocument.cookie = escape(name) + "=;path=" + cookiePath +
";expires=Thu, 01 Jan 1970 00:00:00 GMT";
} else { } else {
if (isString(value)) { if (isString(value)) {
cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) + ';path=' + cookiePath).length + 1; cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) +
';path=' + cookiePath).length + 1;
// per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum: // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:
// - 300 cookies // - 300 cookies
// - 20 cookies per unique domain // - 20 cookies per unique domain
// - 4096 bytes per cookie // - 4096 bytes per cookie
if (cookieLength > 4096) { if (cookieLength > 4096) {
$log.warn("Cookie '"+ name +"' possibly not set or overflowed because it was too large ("+ $log.warn("Cookie '"+ name +
"' possibly not set or overflowed because it was too large ("+
cookieLength + " > 4096 bytes)!"); cookieLength + " > 4096 bytes)!");
} }
} }
@ -312,7 +317,7 @@ function Browser(window, document, $log, $sniffer) {
cookie = cookieArray[i]; cookie = cookieArray[i];
index = cookie.indexOf('='); index = cookie.indexOf('=');
if (index > 0) { //ignore nameless cookies if (index > 0) { //ignore nameless cookies
var name = unescape(cookie.substring(0, index)); name = unescape(cookie.substring(0, index));
// the first value that is seen for a cookie is the most // the first value that is seen for a cookie is the most
// specific one. values for the same cookie name that // specific one. values for the same cookie name that
// follow are for less specific paths. // follow are for less specific paths.
@ -362,7 +367,8 @@ function Browser(window, document, $log, $sniffer) {
* Cancels a deferred task identified with `deferId`. * Cancels a deferred task identified with `deferId`.
* *
* @param {*} deferId Token returned by the `$browser.defer` function. * @param {*} deferId Token returned by the `$browser.defer` function.
* @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully canceled. * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully
* canceled.
*/ */
self.defer.cancel = function(deferId) { self.defer.cancel = function(deferId) {
if (pendingDeferIds[deferId]) { if (pendingDeferIds[deferId]) {

View file

@ -1,3 +1,5 @@
'use strict';
/** /**
* @ngdoc object * @ngdoc object
* @name ng.$cacheFactory * @name ng.$cacheFactory
@ -13,8 +15,9 @@
* *
* cache.put("key", "value"); * cache.put("key", "value");
* cache.put("another key", "another value"); * cache.put("another key", "another value");
* *
* expect(cache.info()).toEqual({id: 'cacheId', size: 2}); // Since we've specified no options on creation * // We've specified no options on creation
* expect(cache.info()).toEqual({id: 'cacheId', size: 2});
* *
* </pre> * </pre>
* *
@ -27,7 +30,8 @@
* @returns {object} Newly created cache object with the following set of methods: * @returns {object} Newly created cache object with the following set of methods:
* *
* - `{object}` `info()` Returns id, size, and options of cache. * - `{object}` `info()` Returns id, size, and options of cache.
* - `{{*}}` `put({string} key, {*} value)` Puts a new key-value pair into the cache and returns it. * - `{{*}}` `put({string} key, {*} value)` Puts a new key-value pair into the cache and returns
* it.
* - `{{*}}` `get({string} key)` Returns cached value for `key` or undefined for cache miss. * - `{{*}}` `get({string} key)` Returns cached value for `key` or undefined for cache miss.
* - `{void}` `remove({string} key)` Removes a key-value pair from the cache. * - `{void}` `remove({string} key)` Removes a key-value pair from the cache.
* - `{void}` `removeAll()` Removes all cached values. * - `{void}` `removeAll()` Removes all cached values.
@ -194,9 +198,9 @@ function $CacheFactoryProvider() {
* @name ng.$templateCache * @name ng.$templateCache
* *
* @description * @description
* The first time a template is used, it is loaded in the template cache for quick retrieval. You can * The first time a template is used, it is loaded in the template cache for quick retrieval. You
* load templates directly into the cache in a `script` tag, or by consuming the `$templateCache` * can load templates directly into the cache in a `script` tag, or by consuming the
* service directly. * `$templateCache` service directly.
* *
* Adding via the `script` tag: * Adding via the `script` tag:
* <pre> * <pre>
@ -210,8 +214,8 @@ function $CacheFactoryProvider() {
* </html> * </html>
* </pre> * </pre>
* *
* **Note:** the `script` tag containing the template does not need to be included in the `head` of the document, but * **Note:** the `script` tag containing the template does not need to be included in the `head` of
* it must be below the `ng-app` definition. * the document, but it must be below the `ng-app` definition.
* *
* Adding via the $templateCache service: * Adding via the $templateCache service:
* *

View file

@ -97,16 +97,16 @@
* (a DOM element/tree) to a scope. Where: * (a DOM element/tree) to a scope. Where:
* *
* * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to. * * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.
* * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the `template` * * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the
* and call the `cloneAttachFn` function allowing the caller to attach the * `template` and call the `cloneAttachFn` function allowing the caller to attach the
* cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is * cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is
* called as: <br> `cloneAttachFn(clonedElement, scope)` where: * called as: <br> `cloneAttachFn(clonedElement, scope)` where:
* *
* * `clonedElement` - is a clone of the original `element` passed into the compiler. * * `clonedElement` - is a clone of the original `element` passed into the compiler.
* * `scope` - is the current scope with which the linking function is working with. * * `scope` - is the current scope with which the linking function is working with.
* *
* Calling the linking function returns the element of the template. It is either the original element * Calling the linking function returns the element of the template. It is either the original
* passed in, or the clone of the element if the `cloneAttachFn` is provided. * element passed in, or the clone of the element if the `cloneAttachFn` is provided.
* *
* After linking the view is not updated until after a call to $digest which typically is done by * After linking the view is not updated until after a call to $digest which typically is done by
* Angular automatically. * Angular automatically.
@ -257,10 +257,10 @@ function $CompileProvider($provide) {
* *
* The sanitization is a security measure aimed at prevent XSS attacks via html links. * The sanitization is a security measure aimed at prevent XSS attacks via html links.
* *
* Any url about to be assigned to img[src] via data-binding is first normalized and turned into an * Any url about to be assigned to img[src] via data-binding is first normalized and turned into
* absolute url. Afterwards, the url is matched against the `imgSrcSanitizationWhitelist` regular * an absolute url. Afterwards, the url is matched against the `imgSrcSanitizationWhitelist`
* expression. If a match is found, the original url is written into the dom. Otherwise, the * regular expression. If a match is found, the original url is written into the dom. Otherwise,
* absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM. * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.
* *
* @param {RegExp=} regexp New regexp to whitelist urls with. * @param {RegExp=} regexp New regexp to whitelist urls with.
* @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for
@ -315,8 +315,8 @@ function $CompileProvider($provide) {
* @function * @function
* *
* @description * @description
* Removes the CSS class value specified by the classVal parameter from the element. If animations * Removes the CSS class value specified by the classVal parameter from the element. If
* are enabled then an animation will be triggered for the class removal. * animations are enabled then an animation will be triggered for the class removal.
* *
* @param {string} classVal The className value that will be removed from the element * @param {string} classVal The className value that will be removed from the element
*/ */
@ -416,7 +416,7 @@ function $CompileProvider($provide) {
values.push(token); values.push(token);
} }
return values; return values;
}; }
}, },
@ -469,9 +469,11 @@ function $CompileProvider($provide) {
//================================ //================================
function compile($compileNodes, transcludeFn, maxPriority, ignoreDirective, previousCompileContext) { function compile($compileNodes, transcludeFn, maxPriority, ignoreDirective,
previousCompileContext) {
if (!($compileNodes instanceof jqLite)) { if (!($compileNodes instanceof jqLite)) {
// jquery always rewraps, whereas we need to preserve the original selector so that we can modify it. // jquery always rewraps, whereas we need to preserve the original selector so that we can
// modify it.
$compileNodes = jqLite($compileNodes); $compileNodes = jqLite($compileNodes);
} }
// We can not compile top level text elements since text nodes can be merged and we will // We can not compile top level text elements since text nodes can be merged and we will
@ -481,7 +483,9 @@ function $CompileProvider($provide) {
$compileNodes[index] = node = jqLite(node).wrap('<span></span>').parent()[0]; $compileNodes[index] = node = jqLite(node).wrap('<span></span>').parent()[0];
} }
}); });
var compositeLinkFn = compileNodes($compileNodes, transcludeFn, $compileNodes, maxPriority, ignoreDirective, previousCompileContext); var compositeLinkFn =
compileNodes($compileNodes, transcludeFn, $compileNodes,
maxPriority, ignoreDirective, previousCompileContext);
return function publicLinkFn(scope, cloneConnectFn){ return function publicLinkFn(scope, cloneConnectFn){
assertArg(scope, 'scope'); assertArg(scope, 'scope');
// important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart
@ -522,13 +526,14 @@ function $CompileProvider($provide) {
* @param {NodeList} nodeList an array of nodes or NodeList to compile * @param {NodeList} nodeList an array of nodes or NodeList to compile
* @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the
* scope argument is auto-generated to the new child of the transcluded parent scope. * scope argument is auto-generated to the new child of the transcluded parent scope.
* @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then the * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then
* rootElement must be set the jqLite collection of the compile root. This is * the rootElement must be set the jqLite collection of the compile root. This is
* needed so that the jqLite collection items can be replaced with widgets. * needed so that the jqLite collection items can be replaced with widgets.
* @param {number=} max directive priority * @param {number=} max directive priority
* @returns {?function} A composite linking function of all of the matched directives or null. * @returns {?function} A composite linking function of all of the matched directives or null.
*/ */
function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority, ignoreDirective, previousCompileContext) { function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority, ignoreDirective,
previousCompileContext) {
var linkFns = [], var linkFns = [],
nodeLinkFn, childLinkFn, directives, attrs, linkFnFound; nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;
@ -536,13 +541,17 @@ function $CompileProvider($provide) {
attrs = new Attributes(); attrs = new Attributes();
// we must always refer to nodeList[i] since the nodes can be replaced underneath us. // we must always refer to nodeList[i] since the nodes can be replaced underneath us.
directives = collectDirectives(nodeList[i], [], attrs, i == 0 ? maxPriority : undefined, ignoreDirective); directives = collectDirectives(nodeList[i], [], attrs, i === 0 ? maxPriority : undefined,
ignoreDirective);
nodeLinkFn = (directives.length) nodeLinkFn = (directives.length)
? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement, null, [], [], previousCompileContext) ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement,
null, [], [], previousCompileContext)
: null; : null;
childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes || !nodeList[i].childNodes.length) childLinkFn = (nodeLinkFn && nodeLinkFn.terminal ||
!nodeList[i].childNodes ||
!nodeList[i].childNodes.length)
? null ? null
: compileNodes(nodeList[i].childNodes, : compileNodes(nodeList[i].childNodes,
nodeLinkFn ? nodeLinkFn.transclude : transcludeFn); nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);
@ -550,7 +559,8 @@ function $CompileProvider($provide) {
linkFns.push(nodeLinkFn); linkFns.push(nodeLinkFn);
linkFns.push(childLinkFn); linkFns.push(childLinkFn);
linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn); linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);
previousCompileContext = null; //use the previous context only for the first element in the virtual group //use the previous context only for the first element in the virtual group
previousCompileContext = null;
} }
// return a linking function if we have found anything, null otherwise // return a linking function if we have found anything, null otherwise
@ -654,7 +664,8 @@ function $CompileProvider($provide) {
attrs[nName] = true; // presence means true attrs[nName] = true; // presence means true
} }
addAttrInterpolateDirective(node, directives, value, nName); addAttrInterpolateDirective(node, directives, value, nName);
addDirective(directives, nName, 'A', maxPriority, ignoreDirective, attrStartName, attrEndName); addDirective(directives, nName, 'A', maxPriority, ignoreDirective, attrStartName,
attrEndName);
} }
} }
@ -683,7 +694,8 @@ function $CompileProvider($provide) {
} }
} }
} catch (e) { } catch (e) {
// turns out that under some circumstances IE9 throws errors when one attempts to read comment's node value. // turns out that under some circumstances IE9 throws errors when one attempts to read
// comment's node value.
// Just ignore it and continue. (Can't seem to reproduce in test case.) // Just ignore it and continue. (Can't seem to reproduce in test case.)
} }
break; break;
@ -694,7 +706,8 @@ function $CompileProvider($provide) {
} }
/** /**
* Given a node with an directive-start it collects all of the siblings until it find directive-end. * Given a node with an directive-start it collects all of the siblings until it finds
* directive-end.
* @param node * @param node
* @param attrStart * @param attrStart
* @param attrEnd * @param attrEnd
@ -707,7 +720,9 @@ function $CompileProvider($provide) {
var startNode = node; var startNode = node;
do { do {
if (!node) { if (!node) {
throw $compileMinErr('uterdir', "Unterminated attribute, found '{0}' but no matching '{1}' found.", attrStart, attrEnd); throw $compileMinErr('uterdir',
"Unterminated attribute, found '{0}' but no matching '{1}' found.",
attrStart, attrEnd);
} }
if (node.nodeType == 1 /** Element **/) { if (node.nodeType == 1 /** Element **/) {
if (node.hasAttribute(attrStart)) depth++; if (node.hasAttribute(attrStart)) depth++;
@ -735,7 +750,7 @@ function $CompileProvider($provide) {
return function(scope, element, attrs, controllers) { return function(scope, element, attrs, controllers) {
element = groupScan(element[0], attrStart, attrEnd); element = groupScan(element[0], attrStart, attrEnd);
return linkFn(scope, element, attrs, controllers); return linkFn(scope, element, attrs, controllers);
} };
} }
/** /**
@ -748,18 +763,22 @@ function $CompileProvider($provide) {
* @param {Node} compileNode The raw DOM node to apply the compile functions to * @param {Node} compileNode The raw DOM node to apply the compile functions to
* @param {Object} templateAttrs The shared attribute function * @param {Object} templateAttrs The shared attribute function
* @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the
* scope argument is auto-generated to the new child of the transcluded parent scope. * scope argument is auto-generated to the new
* child of the transcluded parent scope.
* @param {JQLite} jqCollection If we are working on the root of the compile tree then this * @param {JQLite} jqCollection If we are working on the root of the compile tree then this
* argument has the root jqLite array so that we can replace nodes on it. * argument has the root jqLite array so that we can replace nodes
* @param {Object=} originalReplaceDirective An optional directive that will be ignored when compiling * on it.
* the transclusion. * @param {Object=} originalReplaceDirective An optional directive that will be ignored when
* compiling the transclusion.
* @param {Array.<Function>} preLinkFns * @param {Array.<Function>} preLinkFns
* @param {Array.<Function>} postLinkFns * @param {Array.<Function>} postLinkFns
* @param {Object} previousCompileContext Context used for previous compilation of the current node * @param {Object} previousCompileContext Context used for previous compilation of the current
* node
* @returns linkFn * @returns linkFn
*/ */
function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, jqCollection, function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn,
originalReplaceDirective, preLinkFns, postLinkFns, previousCompileContext) { jqCollection, originalReplaceDirective, preLinkFns, postLinkFns,
previousCompileContext) {
previousCompileContext = previousCompileContext || {}; previousCompileContext = previousCompileContext || {};
var terminalPriority = -Number.MAX_VALUE, var terminalPriority = -Number.MAX_VALUE,
@ -785,7 +804,7 @@ function $CompileProvider($provide) {
// collect multiblock sections // collect multiblock sections
if (attrStart) { if (attrStart) {
$compileNode = groupScan(compileNode, attrStart, attrEnd) $compileNode = groupScan(compileNode, attrStart, attrEnd);
} }
$template = undefined; $template = undefined;
@ -796,10 +815,11 @@ function $CompileProvider($provide) {
if (directiveValue = directive.scope) { if (directiveValue = directive.scope) {
newScopeDirective = newScopeDirective || directive; newScopeDirective = newScopeDirective || directive;
// skip the check for directives with async templates, we'll check the derived sync directive when // skip the check for directives with async templates, we'll check the derived sync
// the template arrives // directive when the template arrives
if (!directive.templateUrl) { if (!directive.templateUrl) {
assertNoDuplicate('new/isolated scope', newIsolateScopeDirective, directive, $compileNode); assertNoDuplicate('new/isolated scope', newIsolateScopeDirective, directive,
$compileNode);
if (isObject(directiveValue)) { if (isObject(directiveValue)) {
safeAddClass($compileNode, 'ng-isolate-scope'); safeAddClass($compileNode, 'ng-isolate-scope');
newIsolateScopeDirective = directive; newIsolateScopeDirective = directive;
@ -819,8 +839,8 @@ function $CompileProvider($provide) {
} }
if (directiveValue = directive.transclude) { if (directiveValue = directive.transclude) {
// Special case ngRepeat so that we don't complain about duplicate transclusion, ngRepeat knows how to handle // Special case ngRepeat so that we don't complain about duplicate transclusion, ngRepeat
// this on its own. // knows how to handle this on its own.
if (directiveName !== 'ngRepeat') { if (directiveName !== 'ngRepeat') {
assertNoDuplicate('transclusion', transcludeDirective, directive, $compileNode); assertNoDuplicate('transclusion', transcludeDirective, directive, $compileNode);
transcludeDirective = directive; transcludeDirective = directive;
@ -830,7 +850,8 @@ function $CompileProvider($provide) {
terminalPriority = directive.priority; terminalPriority = directive.priority;
$template = groupScan(compileNode, attrStart, attrEnd); $template = groupScan(compileNode, attrStart, attrEnd);
$compileNode = templateAttrs.$$element = $compileNode = templateAttrs.$$element =
jqLite(document.createComment(' ' + directiveName + ': ' + templateAttrs[directiveName] + ' ')); jqLite(document.createComment(' ' + directiveName + ': ' +
templateAttrs[directiveName] + ' '));
compileNode = $compileNode[0]; compileNode = $compileNode[0];
replaceWith(jqCollection, jqLite(sliceArgs($template)), compileNode); replaceWith(jqCollection, jqLite(sliceArgs($template)), compileNode);
@ -841,7 +862,7 @@ function $CompileProvider($provide) {
templateDirective: templateDirective templateDirective: templateDirective
}); });
} else { } else {
$template = jqLite(JQLiteClone(compileNode)).contents(); $template = jqLite(jqLiteClone(compileNode)).contents();
$compileNode.html(''); // clear contents $compileNode.html(''); // clear contents
childTranscludeFn = compile($template, transcludeFn); childTranscludeFn = compile($template, transcludeFn);
} }
@ -865,7 +886,9 @@ function $CompileProvider($provide) {
compileNode = $template[0]; compileNode = $template[0];
if ($template.length != 1 || compileNode.nodeType !== 1) { if ($template.length != 1 || compileNode.nodeType !== 1) {
throw $compileMinErr('tplrt', "Template for directive '{0}' must have exactly one root element. {1}", directiveName, ''); throw $compileMinErr('tplrt',
"Template for directive '{0}' must have exactly one root element. {1}",
directiveName, '');
} }
replaceWith(jqCollection, $compileNode, compileNode); replaceWith(jqCollection, $compileNode, compileNode);
@ -968,7 +991,9 @@ function $CompileProvider($provide) {
} }
if (!value && !optional) { if (!value && !optional) {
throw $compileMinErr('ctreq', "Controller '{0}', required by directive '{1}', can't be found!", require, directiveName); throw $compileMinErr('ctreq',
"Controller '{0}', required by directive '{1}', can't be found!",
require, directiveName);
} }
return value; return value;
} else if (isArray(require)) { } else if (isArray(require)) {
@ -1008,19 +1033,19 @@ function $CompileProvider($provide) {
switch (mode) { switch (mode) {
case '@': { case '@':
attrs.$observe(attrName, function(value) { attrs.$observe(attrName, function(value) {
scope[scopeName] = value; scope[scopeName] = value;
}); });
attrs.$$observers[attrName].$$scope = parentScope; attrs.$$observers[attrName].$$scope = parentScope;
if( attrs[attrName] ) { if( attrs[attrName] ) {
// If the attribute has been provided then we trigger an interpolation to ensure the value is there for use in the link fn // If the attribute has been provided then we trigger an interpolation to ensure
// the value is there for use in the link fn
scope[scopeName] = $interpolate(attrs[attrName])(parentScope); scope[scopeName] = $interpolate(attrs[attrName])(parentScope);
} }
break; break;
}
case '=': { case '=':
if (optional && !attrs[attrName]) { if (optional && !attrs[attrName]) {
return; return;
} }
@ -1028,7 +1053,8 @@ function $CompileProvider($provide) {
parentSet = parentGet.assign || function() { parentSet = parentGet.assign || function() {
// reset the change, or we will throw this exception on every $digest // reset the change, or we will throw this exception on every $digest
lastValue = scope[scopeName] = parentGet(parentScope); lastValue = scope[scopeName] = parentGet(parentScope);
throw $compileMinErr('nonassign', "Expression '{0}' used with directive '{1}' is non-assignable!", throw $compileMinErr('nonassign',
"Expression '{0}' used with directive '{1}' is non-assignable!",
attrs[attrName], newIsolateScopeDirective.name); attrs[attrName], newIsolateScopeDirective.name);
}; };
lastValue = scope[scopeName] = parentGet(parentScope); lastValue = scope[scopeName] = parentGet(parentScope);
@ -1048,20 +1074,19 @@ function $CompileProvider($provide) {
return parentValue; return parentValue;
}); });
break; break;
}
case '&': { case '&':
parentGet = $parse(attrs[attrName]); parentGet = $parse(attrs[attrName]);
scope[scopeName] = function(locals) { scope[scopeName] = function(locals) {
return parentGet(parentScope, locals); return parentGet(parentScope, locals);
}; };
break; break;
}
default:
default: { throw $compileMinErr('iscp',
throw $compileMinErr('iscp', "Invalid isolate scope definition for directive '{0}'. Definition: {... {1}: '{2}' ...}", "Invalid isolate scope definition for directive '{0}'." +
" Definition: {... {1}: '{2}' ...}",
newIsolateScopeDirective.name, scopeName, definition); newIsolateScopeDirective.name, scopeName, definition);
}
} }
}); });
} }
@ -1139,7 +1164,8 @@ function $CompileProvider($provide) {
* * `M`: comment * * `M`: comment
* @returns true if directive was added. * @returns true if directive was added.
*/ */
function addDirective(tDirectives, name, location, maxPriority, ignoreDirective, startAttrName, endAttrName) { function addDirective(tDirectives, name, location, maxPriority, ignoreDirective, startAttrName,
endAttrName) {
if (name === ignoreDirective) return null; if (name === ignoreDirective) return null;
var match = null; var match = null;
if (hasDirectives.hasOwnProperty(name)) { if (hasDirectives.hasOwnProperty(name)) {
@ -1231,7 +1257,8 @@ function $CompileProvider($provide) {
compileNode = $template[0]; compileNode = $template[0];
if ($template.length != 1 || compileNode.nodeType !== 1) { if ($template.length != 1 || compileNode.nodeType !== 1) {
throw $compileMinErr('tplrt', "Template for directive '{0}' must have exactly one root element. {1}", throw $compileMinErr('tplrt',
"Template for directive '{0}' must have exactly one root element. {1}",
origAsyncDirective.name, templateUrl); origAsyncDirective.name, templateUrl);
} }
@ -1247,7 +1274,8 @@ function $CompileProvider($provide) {
directives.unshift(derivedSyncDirective); directives.unshift(derivedSyncDirective);
afterTemplateNodeLinkFn = applyDirectivesToNode(directives, compileNode, tAttrs, afterTemplateNodeLinkFn = applyDirectivesToNode(directives, compileNode, tAttrs,
childTranscludeFn, $compileNode, origAsyncDirective, preLinkFns, postLinkFns, previousCompileContext); childTranscludeFn, $compileNode, origAsyncDirective, preLinkFns, postLinkFns,
previousCompileContext);
forEach($rootElement, function(node, i) { forEach($rootElement, function(node, i) {
if (node == compileNode) { if (node == compileNode) {
$rootElement[i] = $compileNode[0]; $rootElement[i] = $compileNode[0];
@ -1265,11 +1293,12 @@ function $CompileProvider($provide) {
if (beforeTemplateLinkNode !== beforeTemplateCompileNode) { if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {
// it was cloned therefore we have to clone as well. // it was cloned therefore we have to clone as well.
linkNode = JQLiteClone(compileNode); linkNode = jqLiteClone(compileNode);
replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode); replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);
} }
afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, controller); afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement,
controller);
} }
linkQueue = null; linkQueue = null;
}). }).
@ -1346,7 +1375,8 @@ function $CompileProvider($provide) {
if (name === "multiple" && nodeName_(node) === "SELECT") { if (name === "multiple" && nodeName_(node) === "SELECT") {
throw $compileMinErr("selmulti", "Binding to the 'multiple' attribute is not supported. Element: {0}", throw $compileMinErr("selmulti",
"Binding to the 'multiple' attribute is not supported. Element: {0}",
startingTag(node)); startingTag(node));
} }
@ -1357,8 +1387,8 @@ function $CompileProvider($provide) {
if (EVENT_HANDLER_ATTR_REGEXP.test(name)) { if (EVENT_HANDLER_ATTR_REGEXP.test(name)) {
throw $compileMinErr('nodomevents', throw $compileMinErr('nodomevents',
"Interpolations for HTML DOM event attributes are disallowed. Please use the ng- " + "Interpolations for HTML DOM event attributes are disallowed. Please use the " +
"versions (such as ng-click instead of onclick) instead."); "ng- versions (such as ng-click instead of onclick) instead.");
} }
// we need to interpolate again, in case the attribute value has been updated // we need to interpolate again, in case the attribute value has been updated
@ -1369,7 +1399,8 @@ function $CompileProvider($provide) {
// register any observers // register any observers
if (!interpolateFn) return; if (!interpolateFn) return;
// TODO(i): this should likely be attr.$set(name, iterpolateFn(scope) so that we reset the actual attr value // TODO(i): this should likely be attr.$set(name, iterpolateFn(scope) so that we reset the
// actual attr value
attr[name] = interpolateFn(scope); attr[name] = interpolateFn(scope);
($$observers[name] || ($$observers[name] = [])).$$inter = true; ($$observers[name] || ($$observers[name] = [])).$$inter = true;
(attr.$$observers && attr.$$observers[name].$$scope || scope). (attr.$$observers && attr.$$observers[name].$$scope || scope).
@ -1386,9 +1417,9 @@ function $CompileProvider($provide) {
* have no parents, provided that the containing jqLite collection is provided. * have no parents, provided that the containing jqLite collection is provided.
* *
* @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes
* in the root of the tree. * in the root of the tree.
* @param {JqLite} elementsToRemove The jqLite element which we are going to replace. We keep the shell, * @param {JqLite} elementsToRemove The jqLite element which we are going to replace. We keep
* but replace its DOM node reference. * the shell, but replace its DOM node reference.
* @param {Node} newNode The new DOM node. * @param {Node} newNode The new DOM node.
*/ */
function replaceWith($rootElement, elementsToRemove, newNode) { function replaceWith($rootElement, elementsToRemove, newNode) {
@ -1430,7 +1461,7 @@ function $CompileProvider($provide) {
} }
elementsToRemove[0] = newNode; elementsToRemove[0] = newNode;
elementsToRemove.length = 1 elementsToRemove.length = 1;
} }
}]; }];
} }
@ -1454,13 +1485,13 @@ function directiveNormalize(name) {
/** /**
* @ngdoc object * @ngdoc object
* @name ng.$compile.directive.Attributes * @name ng.$compile.directive.Attributes
*
* @description * @description
* A shared object between directive compile / linking functions which contains normalized DOM
* element attributes. The the values reflect current binding state `{{ }}`. The normalization is
* needed since all of these are treated as equivalent in Angular:
* *
* A shared object between directive compile / linking functions which contains normalized DOM element * <span ng:bind="a" ng-bind="a" data-ng-bind="a" x-ng-bind="a">
* attributes. The the values reflect current binding state `{{ }}`. The normalization is needed
* since all of these are treated as equivalent in Angular:
*
* <span ng:bind="a" ng-bind="a" data-ng-bind="a" x-ng-bind="a">
*/ */
/** /**
@ -1468,7 +1499,7 @@ function directiveNormalize(name) {
* @name ng.$compile.directive.Attributes#$attr * @name ng.$compile.directive.Attributes#$attr
* @propertyOf ng.$compile.directive.Attributes * @propertyOf ng.$compile.directive.Attributes
* @returns {object} A map of DOM element attribute names to the normalized name. This is * @returns {object} A map of DOM element attribute names to the normalized name. This is
* needed to do reverse lookup from normalized name back to actual name. * needed to do reverse lookup from normalized name back to actual name.
*/ */

View file

@ -27,7 +27,7 @@ function $ControllerProvider() {
this.register = function(name, constructor) { this.register = function(name, constructor) {
assertNotHasOwnProperty(name, 'controller'); assertNotHasOwnProperty(name, 'controller');
if (isObject(name)) { if (isObject(name)) {
extend(controllers, name) extend(controllers, name);
} else { } else {
controllers[name] = constructor; controllers[name] = constructor;
} }
@ -77,7 +77,9 @@ function $ControllerProvider() {
if (identifier) { if (identifier) {
if (!(locals && typeof locals.$scope == 'object')) { if (!(locals && typeof locals.$scope == 'object')) {
throw minErr('$controller')('noscp', "Cannot export controller '{0}' as '{1}'! No $scope object provided via `locals`.", constructor || expression.name, identifier); throw minErr('$controller')('noscp',
"Cannot export controller '{0}' as '{1}'! No $scope object provided via `locals`.",
constructor || expression.name, identifier);
} }
locals.$scope[identifier] = instance; locals.$scope[identifier] = instance;

View file

@ -39,6 +39,6 @@ var htmlAnchorDirective = valueFn({
event.preventDefault(); event.preventDefault();
} }
}); });
} };
} }
}); });

View file

@ -4,7 +4,7 @@ function ngDirective(directive) {
if (isFunction(directive)) { if (isFunction(directive)) {
directive = { directive = {
link: directive link: directive
} };
} }
directive.restrict = directive.restrict || 'AC'; directive.restrict = directive.restrict || 'AC';
return valueFn(directive); return valueFn(directive);

View file

@ -1,6 +1,6 @@
'use strict'; 'use strict';
/* global -nullFormCtrl */
var nullFormCtrl = { var nullFormCtrl = {
$addControl: noop, $addControl: noop,
$removeControl: noop, $removeControl: noop,

View file

@ -1,5 +1,13 @@
'use strict'; 'use strict';
/* global
-VALID_CLASS,
-INVALID_CLASS,
-PRISTINE_CLASS,
-DIRTY_CLASS
*/
var URL_REGEXP = /^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/; 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-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,6}$/;
var NUMBER_REGEXP = /^\s*(\-|\+)?(\d+|(\d*(\.\d*)))\s*$/; var NUMBER_REGEXP = /^\s*(\-|\+)?(\d+|(\d*(\.\d*)))\s*$/;
@ -939,22 +947,22 @@ var VALID_CLASS = 'ng-valid',
* <example module="badIsolatedDirective"> * <example module="badIsolatedDirective">
<file name="script.js"> <file name="script.js">
angular.module('badIsolatedDirective', []).directive('bad', function() { angular.module('badIsolatedDirective', []).directive('bad', function() {
return { return {
require: 'ngModel', require: 'ngModel',
scope: { }, scope: { },
template: '<input ng-model="innerModel">', template: '<input ng-model="innerModel">',
link: function(scope, element, attrs, ngModel) { link: function(scope, element, attrs, ngModel) {
scope.$watch('innerModel', function(value) { scope.$watch('innerModel', function(value) {
console.log(value); console.log(value);
ngModel.$setViewValue(value); ngModel.$setViewValue(value);
}); });
} }
}; };
}); });
</file> </file>
<file name="index.html"> <file name="index.html">
<input ng-model="someModel"> <input ng-model="someModel">
<div bad ng-model="someModel"></div> <div bad ng-model="someModel"></div>
</file> </file>
* </example> * </example>
* *
@ -1047,7 +1055,10 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
* @param {boolean} isValid Whether the current state is valid (true) or invalid (false). * @param {boolean} isValid Whether the current state is valid (true) or invalid (false).
*/ */
this.$setValidity = function(validationErrorKey, isValid) { this.$setValidity = function(validationErrorKey, isValid) {
// Purposeful use of ! here to cast isValid to boolean in case it is undefined
// jshint -W018
if ($error[validationErrorKey] === !isValid) return; if ($error[validationErrorKey] === !isValid) return;
// jshint +W018
if (isValid) { if (isValid) {
if ($error[validationErrorKey]) invalidCount--; if ($error[validationErrorKey]) invalidCount--;
@ -1127,7 +1138,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
} catch(e) { } catch(e) {
$exceptionHandler(e); $exceptionHandler(e);
} }
}) });
} }
}; };

View file

@ -50,6 +50,9 @@
var ngBindDirective = ngDirective(function(scope, element, attr) { var ngBindDirective = ngDirective(function(scope, element, attr) {
element.addClass('ng-binding').data('$binding', attr.ngBind); element.addClass('ng-binding').data('$binding', attr.ngBind);
scope.$watch(attr.ngBind, function ngBindWatchAction(value) { scope.$watch(attr.ngBind, function ngBindWatchAction(value) {
// We are purposefully using == here rather than === because we want to
// catch when value is "null or undefined"
// jshint -W041
element.text(value == undefined ? '' : value); element.text(value == undefined ? '' : value);
}); });
}); });
@ -111,7 +114,7 @@ var ngBindTemplateDirective = ['$interpolate', function($interpolate) {
attr.$observe('ngBindTemplate', function(value) { attr.$observe('ngBindTemplate', function(value) {
element.text(value); element.text(value);
}); });
} };
}]; }];

View file

@ -6,7 +6,7 @@ function classDirective(name, selector) {
return { return {
restrict: 'AC', restrict: 'AC',
link: function(scope, element, attr) { link: function(scope, element, attr) {
var oldVal = undefined; var oldVal;
scope.$watch(attr[name], ngClassWatchAction, true); scope.$watch(attr[name], ngClassWatchAction, true);
@ -17,6 +17,7 @@ function classDirective(name, selector) {
if (name !== 'ngClass') { if (name !== 'ngClass') {
scope.$watch('$index', function($index, old$index) { scope.$watch('$index', function($index, old$index) {
// jshint bitwise: false
var mod = $index & 1; var mod = $index & 1;
if (mod !== old$index & 1) { if (mod !== old$index & 1) {
if (mod === selector) { if (mod === selector) {
@ -63,7 +64,7 @@ function classDirective(name, selector) {
} }
return classVal; return classVal;
}; }
} }
}; };
}; };

4
src/ng/directive/ngIf.js Executable file → Normal file
View file

@ -104,7 +104,7 @@ var ngIfDirective = ['$animate', function($animate) {
}); });
} }
}); });
} };
} }
} };
}]; }];

View file

@ -52,6 +52,6 @@ var ngInitDirective = ngDirective({
pre: function(scope, element, attrs) { pre: function(scope, element, attrs) {
scope.$eval(attrs.ngInit); scope.$eval(attrs.ngInit);
} }
} };
} }
}); });

View file

@ -243,10 +243,10 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
} else { } else {
trackByIdArrayFn = function(key, value) { trackByIdArrayFn = function(key, value) {
return hashKey(value); return hashKey(value);
} };
trackByIdObjFn = function(key) { trackByIdObjFn = function(key) {
return key; return key;
} };
} }
match = lhs.match(/^(?:([\$\w]+)|\(([\$\w]+)\s*,\s*([\$\w]+)\))$/); match = lhs.match(/^(?:([\$\w]+)|\(([\$\w]+)\s*,\s*([\$\w]+)\))$/);
@ -308,7 +308,7 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
trackById = trackByIdFn(key, value, index); trackById = trackByIdFn(key, value, index);
assertNotHasOwnProperty(trackById, '`track by` id'); assertNotHasOwnProperty(trackById, '`track by` id');
if(lastBlockMap.hasOwnProperty(trackById)) { if(lastBlockMap.hasOwnProperty(trackById)) {
block = lastBlockMap[trackById] block = lastBlockMap[trackById];
delete lastBlockMap[trackById]; delete lastBlockMap[trackById];
nextBlockMap[trackById] = block; nextBlockMap[trackById] = block;
nextBlockOrder[index] = block; nextBlockOrder[index] = block;
@ -356,9 +356,7 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
nextNode = nextNode.nextSibling; nextNode = nextNode.nextSibling;
} while(nextNode && nextNode[NG_REMOVED]); } while(nextNode && nextNode[NG_REMOVED]);
if (block.startNode == nextNode) { if (block.startNode != nextNode) {
// do nothing
} else {
// existing item which got moved // existing item which got moved
$animate.move(getBlockElements(block), null, jqLite(previousNode)); $animate.move(getBlockElements(block), null, jqLite(previousNode));
} }
@ -374,7 +372,9 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
childScope.$first = (index === 0); childScope.$first = (index === 0);
childScope.$last = (index === (arrayLength - 1)); childScope.$last = (index === (arrayLength - 1));
childScope.$middle = !(childScope.$first || childScope.$last); childScope.$middle = !(childScope.$first || childScope.$last);
childScope.$odd = !(childScope.$even = index%2==0); // jshint bitwise: false
childScope.$odd = !(childScope.$even = (index&1) === 0);
// jshint bitwise: true
if (!block.startNode) { if (!block.startNode) {
linker(childScope, function(clone) { linker(childScope, function(clone) {

View file

@ -161,7 +161,7 @@ var ngSwitchDirective = ['$animate', function($animate) {
} }
}); });
} }
} };
}]; }];
var ngSwitchWhenDirective = ngDirective({ var ngSwitchWhenDirective = ngDirective({

View file

@ -126,10 +126,12 @@ var ngOptionsMinErr = minErr('ngOptions');
*/ */
var ngOptionsDirective = valueFn({ terminal: true }); var ngOptionsDirective = valueFn({ terminal: true });
// jshint maxlen: false
var selectDirective = ['$compile', '$parse', function($compile, $parse) { var selectDirective = ['$compile', '$parse', function($compile, $parse) {
//0000111110000000000022220000000000000000000000333300000000000000444444444444444000000000555555555555555000000066666666666666600000000000000007777000000000000000000088888 //0000111110000000000022220000000000000000000000333300000000000000444444444444444000000000555555555555555000000066666666666666600000000000000007777000000000000000000088888
var NG_OPTIONS_REGEXP = /^\s*(.*?)(?:\s+as\s+(.*?))?(?:\s+group\s+by\s+(.*))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+(.*?)(?:\s+track\s+by\s+(.*?))?$/, var NG_OPTIONS_REGEXP = /^\s*(.*?)(?:\s+as\s+(.*?))?(?:\s+group\s+by\s+(.*))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+(.*?)(?:\s+track\s+by\s+(.*?))?$/,
nullModelCtrl = {$setViewValue: noop}; nullModelCtrl = {$setViewValue: noop};
// jshint maxlen: 100
return { return {
restrict: 'E', restrict: 'E',
@ -210,7 +212,7 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
// find "null" option // find "null" option
for(var i = 0, children = element.children(), ii = children.length; i < ii; i++) { for(var i = 0, children = element.children(), ii = children.length; i < ii; i++) {
if (children[i].value == '') { if (children[i].value === '') {
emptyOption = nullOption = children.eq(i); emptyOption = nullOption = children.eq(i);
break; break;
} }
@ -233,16 +235,16 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
}); });
} }
if (optionsExp) Options(scope, element, ngModelCtrl); if (optionsExp) setupAsOptions(scope, element, ngModelCtrl);
else if (multiple) Multiple(scope, element, ngModelCtrl); else if (multiple) setupAsMultiple(scope, element, ngModelCtrl);
else Single(scope, element, ngModelCtrl, selectCtrl); else setupAsSingle(scope, element, ngModelCtrl, selectCtrl);
//////////////////////////// ////////////////////////////
function Single(scope, selectElement, ngModelCtrl, selectCtrl) { function setupAsSingle(scope, selectElement, ngModelCtrl, selectCtrl) {
ngModelCtrl.$render = function() { ngModelCtrl.$render = function() {
var viewValue = ngModelCtrl.$viewValue; var viewValue = ngModelCtrl.$viewValue;
@ -267,7 +269,7 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
}); });
} }
function Multiple(scope, selectElement, ctrl) { function setupAsMultiple(scope, selectElement, ctrl) {
var lastView; var lastView;
ctrl.$render = function() { ctrl.$render = function() {
var items = new HashMap(ctrl.$viewValue); var items = new HashMap(ctrl.$viewValue);
@ -298,12 +300,14 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
}); });
} }
function Options(scope, selectElement, ctrl) { function setupAsOptions(scope, selectElement, ctrl) {
var match; var match;
if (! (match = optionsExp.match(NG_OPTIONS_REGEXP))) { if (! (match = optionsExp.match(NG_OPTIONS_REGEXP))) {
throw ngOptionsMinErr('iexp', throw ngOptionsMinErr('iexp',
"Expected expression in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_' but got '{0}'. Element: {1}", "Expected expression in form of " +
"'_select_ (as _label_)? for (_key_,)?_value_ in _collection_'" +
" but got '{0}'. Element: {1}",
optionsExp, startingTag(selectElement)); optionsExp, startingTag(selectElement));
} }
@ -315,9 +319,10 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
valuesFn = $parse(match[7]), valuesFn = $parse(match[7]),
track = match[8], track = match[8],
trackFn = track ? $parse(match[8]) : null, trackFn = track ? $parse(match[8]) : null,
// This is an array of array of existing option groups in DOM. We try to reuse these if possible // This is an array of array of existing option groups in DOM.
// optionGroupsCache[0] is the options with no option group // We try to reuse these if possible
// optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element // - optionGroupsCache[0] is the options with no option group
// - optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element
optionGroupsCache = [[{element: selectElement, label:''}]]; optionGroupsCache = [[{element: selectElement, label:''}]];
if (nullOption) { if (nullOption) {
@ -371,7 +376,7 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
key = selectElement.val(); key = selectElement.val();
if (key == '?') { if (key == '?') {
value = undefined; value = undefined;
} else if (key == ''){ } else if (key === ''){
value = null; value = null;
} else { } else {
if (trackFn) { if (trackFn) {
@ -399,7 +404,8 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
scope.$watch(render); scope.$watch(render);
function render() { function render() {
var optionGroups = {'':[]}, // Temporary location for the option groups before we render them // Temporary location for the option groups before we render them
var optionGroups = {'':[]},
optionGroupNames = [''], optionGroupNames = [''],
optionGroupName, optionGroupName,
optionGroup, optionGroup,
@ -448,7 +454,9 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
optionGroupNames.push(optionGroupName); optionGroupNames.push(optionGroupName);
} }
if (multiple) { if (multiple) {
selected = selectedSet.remove(trackFn ? trackFn(scope, locals) : valueFn(scope, locals)) !== undefined; selected = isDefined(
selectedSet.remove(trackFn ? trackFn(scope, locals) : valueFn(scope, locals))
);
} else { } else {
if (trackFn) { if (trackFn) {
var modelCast = {}; var modelCast = {};
@ -460,9 +468,12 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
selectedSet = selectedSet || selected; // see if at least one item is selected selectedSet = selectedSet || selected; // see if at least one item is selected
} }
label = displayFn(scope, locals); // what will be seen by the user label = displayFn(scope, locals); // what will be seen by the user
label = label === undefined ? '' : label; // doing displayFn(scope, locals) || '' overwrites zero values
// doing displayFn(scope, locals) || '' overwrites zero values
label = isDefined(label) ? label : '';
optionGroup.push({ optionGroup.push({
id: trackFn ? trackFn(scope, locals) : (keyName ? keys[index] : index), // either the index into array or key from object // either the index into array or key from object
id: trackFn ? trackFn(scope, locals) : (keyName ? keys[index] : index),
label: label, label: label,
selected: selected // determine if we should be selected selected: selected // determine if we should be selected
}); });

View file

@ -5,9 +5,9 @@
* @name ng.$filterProvider * @name ng.$filterProvider
* @description * @description
* *
* Filters are just functions which transform input to an output. However filters need to be Dependency Injected. To * Filters are just functions which transform input to an output. However filters need to be
* achieve this a filter definition consists of a factory function which is annotated with dependencies and is * Dependency Injected. To achieve this a filter definition consists of a factory function which is
* responsible for creating a filter function. * annotated with dependencies and is responsible for creating a filter function.
* *
* <pre> * <pre>
* // Filter registration * // Filter registration
@ -30,7 +30,9 @@
* } * }
* </pre> * </pre>
* *
* The filter function is registered with the `$injector` under the filter name suffix with `Filter`. * The filter function is registered with the `$injector` under the filter name suffix with
* `Filter`.
*
* <pre> * <pre>
* it('should be the same instance', inject( * it('should be the same instance', inject(
* function($filterProvider) { * function($filterProvider) {
@ -107,6 +109,18 @@ function $FilterProvider($provide) {
}]; }];
//////////////////////////////////////// ////////////////////////////////////////
/* global
currencyFilter: false,
dateFilter: false,
filterFilter: false,
jsonFilter: false,
limitToFilter: false,
lowercaseFilter: false,
numberFilter: false,
orderByFilter: false,
uppercaseFilter: false,
*/
register('currency', currencyFilter); register('currency', currencyFilter);
register('date', dateFilter); register('date', dateFilter);

View file

@ -105,9 +105,12 @@
</doc:example> </doc:example>
*/ */
function filterFilter() { function filterFilter() {
return function(array, expression, comperator) { return function(array, expression, comparator) {
if (!isArray(array)) return array; if (!isArray(array)) return array;
var predicates = [];
var comparatorType = typeof(comparator),
predicates = [];
predicates.check = function(value) { predicates.check = function(value) {
for (var j = 0; j < predicates.length; j++) { for (var j = 0; j < predicates.length; j++) {
if(!predicates[j](value)) { if(!predicates[j](value)) {
@ -116,22 +119,20 @@ function filterFilter() {
} }
return true; return true;
}; };
switch(typeof comperator) {
case "function": if (comparatorType !== 'function') {
break; if (comparatorType === 'boolean' && comparator) {
case "boolean": comparator = function(obj, text) {
if(comperator == true) { return angular.equals(obj, text);
comperator = function(obj, text) { };
return angular.equals(obj, text); } else {
} comparator = function(obj, text) {
break;
}
default:
comperator = function(obj, text) {
text = (''+text).toLowerCase(); text = (''+text).toLowerCase();
return (''+obj).toLowerCase().indexOf(text) > -1; return (''+obj).toLowerCase().indexOf(text) > -1;
}; };
}
} }
var search = function(obj, text){ var search = function(obj, text){
if (typeof text == 'string' && text.charAt(0) === '!') { if (typeof text == 'string' && text.charAt(0) === '!') {
return !search(obj, text.substr(1)); return !search(obj, text.substr(1));
@ -140,12 +141,11 @@ function filterFilter() {
case "boolean": case "boolean":
case "number": case "number":
case "string": case "string":
return comperator(obj, text); return comparator(obj, text);
case "object": case "object":
switch (typeof text) { switch (typeof text) {
case "object": case "object":
return comperator(obj, text); return comparator(obj, text);
break;
default: default:
for ( var objKey in obj) { for ( var objKey in obj) {
if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) { if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {
@ -170,13 +170,16 @@ function filterFilter() {
case "boolean": case "boolean":
case "number": case "number":
case "string": case "string":
// Set up expression object and fall through
expression = {$:expression}; expression = {$:expression};
// jshint -W086
case "object": case "object":
// jshint +W086
for (var key in expression) { for (var key in expression) {
if (key == '$') { if (key == '$') {
(function() { (function() {
if (!expression[key]) return; if (!expression[key]) return;
var path = key var path = key;
predicates.push(function(value) { predicates.push(function(value) {
return search(value, expression[path]); return search(value, expression[path]);
}); });
@ -206,5 +209,5 @@ function filterFilter() {
} }
} }
return filtered; return filtered;
} };
} }

View file

@ -144,13 +144,13 @@ function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {
var whole = fraction[0]; var whole = fraction[0];
fraction = fraction[1] || ''; fraction = fraction[1] || '';
var pos = 0, var i, pos = 0,
lgroup = pattern.lgSize, lgroup = pattern.lgSize,
group = pattern.gSize; group = pattern.gSize;
if (whole.length >= (lgroup + group)) { if (whole.length >= (lgroup + group)) {
pos = whole.length - lgroup; pos = whole.length - lgroup;
for (var i = 0; i < pos; i++) { for (i = 0; i < pos; i++) {
if ((pos - i)%group === 0 && i !== 0) { if ((pos - i)%group === 0 && i !== 0) {
formatedText += groupSep; formatedText += groupSep;
} }
@ -364,7 +364,7 @@ function dateFilter($locale) {
} }
dateSetter.call(date, int(match[1]), int(match[2]) - 1, int(match[3])); dateSetter.call(date, int(match[1]), int(match[2]) - 1, int(match[3]));
var h = int(match[4]||0) - tzHour; var h = int(match[4]||0) - tzHour;
var m = int(match[5]||0) - tzMin var m = int(match[5]||0) - tzMin;
var s = int(match[6]||0); var s = int(match[6]||0);
var ms = Math.round(parseFloat('0.' + (match[7]||0)) * 1000); var ms = Math.round(parseFloat('0.' + (match[7]||0)) * 1000);
timeSetter.call(date, h, m, s, ms); timeSetter.call(date, h, m, s, ms);

View file

@ -100,5 +100,5 @@ function limitToFilter(){
} }
return out; return out;
} };
} }

View file

@ -135,5 +135,5 @@ function orderByFilter($parse){
return t1 < t2 ? -1 : 1; return t1 < t2 ? -1 : 1;
} }
} }
} };
} }

View file

@ -224,11 +224,11 @@ function $HttpProvider() {
* called for such responses. * called for such responses.
* *
* # Calling $http from outside AngularJS * # Calling $http from outside AngularJS
* The `$http` service will not actually send the request until the next `$digest()` is executed. * The `$http` service will not actually send the request until the next `$digest()` is
* Normally this is not an issue, since almost all the time your call to `$http` will be from within * executed. Normally this is not an issue, since almost all the time your call to `$http` will
* a `$apply()` block. * be from within a `$apply()` block.
* If you are calling `$http` from outside Angular, then you should wrap it in a call to `$apply` * If you are calling `$http` from outside Angular, then you should wrap it in a call to
* to cause a $digest to occur and also to handle errors in the block correctly. * `$apply` to cause a $digest to occur and also to handle errors in the block correctly.
* *
* ``` * ```
* $scope.$apply(function() { * $scope.$apply(function() {
@ -237,10 +237,11 @@ function $HttpProvider() {
* ``` * ```
* *
* # Writing Unit Tests that use $http * # Writing Unit Tests that use $http
* When unit testing you are mostly responsible for scheduling the `$digest` cycle. If you do not * When unit testing you are mostly responsible for scheduling the `$digest` cycle. If you do
* trigger a `$digest` before calling `$httpBackend.flush()` then the request will not have been * not trigger a `$digest` before calling `$httpBackend.flush()` then the request will not have
* made and `$httpBackend.expect(...)` expectations will fail. The solution is to run the code * been made and `$httpBackend.expect(...)` expectations will fail. The solution is to run the
* that calls the `$http()` method inside a $apply block as explained in the previous section. * code that calls the `$http()` method inside a $apply block as explained in the previous
* section.
* *
* ``` * ```
* $httpBackend.expectGET(...); * $httpBackend.expectGET(...);
@ -300,22 +301,24 @@ function $HttpProvider() {
* *
* Request transformations: * Request transformations:
* *
* - If the `data` property of the request configuration object contains an object, serialize it into * - If the `data` property of the request configuration object contains an object, serialize it
* JSON format. * into JSON format.
* *
* Response transformations: * Response transformations:
* *
* - If XSRF prefix is detected, strip it (see Security Considerations section below). * - If XSRF prefix is detected, strip it (see Security Considerations section below).
* - If JSON response is detected, deserialize it using a JSON parser. * - If JSON response is detected, deserialize it using a JSON parser.
* *
* To globally augment or override the default transforms, modify the `$httpProvider.defaults.transformRequest` and * To globally augment or override the default transforms, modify the
* `$httpProvider.defaults.transformResponse` properties. These properties are by default an * `$httpProvider.defaults.transformRequest` and `$httpProvider.defaults.transformResponse`
* array of transform functions, which allows you to `push` or `unshift` a new transformation function into the * properties. These properties are by default an array of transform functions, which allows you
* transformation chain. You can also decide to completely override any default transformations by assigning your * to `push` or `unshift` a new transformation function into the transformation chain. You can
* also decide to completely override any default transformations by assigning your
* transformation functions to these properties directly without the array wrapper. * transformation functions to these properties directly without the array wrapper.
* *
* Similarly, to locally override the request/response transforms, augment the `transformRequest` and/or * Similarly, to locally override the request/response transforms, augment the
* `transformResponse` properties of the configuration object passed into `$http`. * `transformRequest` and/or `transformResponse` properties of the configuration object passed
* into `$http`.
* *
* *
* # Caching * # Caching
@ -353,16 +356,16 @@ function $HttpProvider() {
* *
* There are two kinds of interceptors (and two kinds of rejection interceptors): * There are two kinds of interceptors (and two kinds of rejection interceptors):
* *
* * `request`: interceptors get called with http `config` object. The function is free to modify * * `request`: interceptors get called with http `config` object. The function is free to
* the `config` or create a new one. The function needs to return the `config` directly or as a * modify the `config` or create a new one. The function needs to return the `config`
* promise. * directly or as a promise.
* * `requestError`: interceptor gets called when a previous interceptor threw an error or resolved * * `requestError`: interceptor gets called when a previous interceptor threw an error or
* with a rejection. * resolved with a rejection.
* * `response`: interceptors get called with http `response` object. The function is free to modify * * `response`: interceptors get called with http `response` object. The function is free to
* the `response` or create a new one. The function needs to return the `response` directly or as a * modify the `response` or create a new one. The function needs to return the `response`
* promise. * directly or as a promise.
* * `responseError`: interceptor gets called when a previous interceptor threw an error or resolved * * `responseError`: interceptor gets called when a previous interceptor threw an error or
* with a rejection. * resolved with a rejection.
* *
* *
* <pre> * <pre>
@ -511,9 +514,10 @@ function $HttpProvider() {
* cookie called `XSRF-TOKEN` on the first HTTP GET request. On subsequent XHR requests the * cookie called `XSRF-TOKEN` on the first HTTP GET request. On subsequent XHR requests the
* server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure
* that only JavaScript running on your domain could have sent the request. The token must be * that only JavaScript running on your domain could have sent the request. The token must be
* unique for each user and must be verifiable by the server (to prevent the JavaScript from making * unique for each user and must be verifiable by the server (to prevent the JavaScript from
* up its own tokens). We recommend that the token is a digest of your site's authentication * making up its own tokens). We recommend that the token is a digest of your site's
* cookie with a {@link https://en.wikipedia.org/wiki/Salt_(cryptography) salt} for added security. * authentication cookie with a {@link https://en.wikipedia.org/wiki/Salt_(cryptography) salt}
* for added security.
* *
* The name of the headers can be specified using the xsrfHeaderName and xsrfCookieName * The name of the headers can be specified using the xsrfHeaderName and xsrfCookieName
* properties of either $httpProvider.defaults, or the per-request config object. * properties of either $httpProvider.defaults, or the per-request config object.
@ -524,18 +528,21 @@ function $HttpProvider() {
* *
* - **method** `{string}` HTTP method (e.g. 'GET', 'POST', etc) * - **method** `{string}` HTTP method (e.g. 'GET', 'POST', etc)
* - **url** `{string}` Absolute or relative URL of the resource that is being requested. * - **url** `{string}` Absolute or relative URL of the resource that is being requested.
* - **params** `{Object.<string|Object>}` Map of strings or objects which will be turned to * - **params** `{Object.<string|Object>}` Map of strings or objects which will be turned
* `?key1=value1&key2=value2` after the url. If the value is not a string, it will be JSONified. * to `?key1=value1&key2=value2` after the url. If the value is not a string, it will be
* JSONified.
* - **data** `{string|Object}` Data to be sent as the request message data. * - **data** `{string|Object}` Data to be sent as the request message data.
* - **headers** `{Object}` Map of strings or functions which return strings representing * - **headers** `{Object}` Map of strings or functions which return strings representing
* HTTP headers to send to the server. If the return value of a function is null, the header will * HTTP headers to send to the server. If the return value of a function is null, the
* not be sent. * header will not be sent.
* - **xsrfHeaderName** `{string}` Name of HTTP header to populate with the XSRF token. * - **xsrfHeaderName** `{string}` Name of HTTP header to populate with the XSRF token.
* - **xsrfCookieName** `{string}` Name of cookie containing the XSRF token. * - **xsrfCookieName** `{string}` Name of cookie containing the XSRF token.
* - **transformRequest** `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` * - **transformRequest**
* `{function(data, headersGetter)|Array.<function(data, headersGetter)>}`
* transform function or an array of such functions. The transform function takes the http * transform function or an array of such functions. The transform function takes the http
* request body and headers and returns its transformed (typically serialized) version. * request body and headers and returns its transformed (typically serialized) version.
* - **transformResponse** `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` * - **transformResponse**
* `{function(data, headersGetter)|Array.<function(data, headersGetter)>}`
* transform function or an array of such functions. The transform function takes the http * transform function or an array of such functions. The transform function takes the http
* response body and headers and returns its transformed (typically deserialized) version. * response body and headers and returns its transformed (typically deserialized) version.
* - **cache** `{boolean|Cache}` If true, a default $http cache will be used to cache the * - **cache** `{boolean|Cache}` If true, a default $http cache will be used to cache the
@ -558,7 +565,8 @@ function $HttpProvider() {
* these functions are destructured representation of the response object passed into the * these functions are destructured representation of the response object passed into the
* `then` method. The response object has these properties: * `then` method. The response object has these properties:
* *
* - **data** `{string|Object}` The response body transformed with the transform functions. * - **data** `{string|Object}` The response body transformed with the transform
* functions.
* - **status** `{number}` HTTP status code of the response. * - **status** `{number}` HTTP status code of the response.
* - **headers** `{function([headerName])}` Header getter function. * - **headers** `{function([headerName])}` Header getter function.
* - **config** `{Object}` The configuration object that was used to generate the request. * - **config** `{Object}` The configuration object that was used to generate the request.
@ -568,75 +576,82 @@ function $HttpProvider() {
* *
* *
* @example * @example
<example> <example>
<file name="index.html"> <file name="index.html">
<div ng-controller="FetchCtrl"> <div ng-controller="FetchCtrl">
<select ng-model="method"> <select ng-model="method">
<option>GET</option> <option>GET</option>
<option>JSONP</option> <option>JSONP</option>
</select> </select>
<input type="text" ng-model="url" size="80"/> <input type="text" ng-model="url" size="80"/>
<button ng-click="fetch()">fetch</button><br> <button ng-click="fetch()">fetch</button><br>
<button ng-click="updateModel('GET', 'http-hello.html')">Sample GET</button> <button ng-click="updateModel('GET', 'http-hello.html')">Sample GET</button>
<button ng-click="updateModel('JSONP', 'http://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')">Sample JSONP</button> <button
<button ng-click="updateModel('JSONP', 'http://angularjs.org/doesntexist&callback=JSON_CALLBACK')">Invalid JSONP</button> ng-click="updateModel('JSONP',
<pre>http status code: {{status}}</pre> 'http://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')">
<pre>http response data: {{data}}</pre> Sample JSONP
</div> </button>
</file> <button
<file name="script.js"> ng-click="updateModel('JSONP', 'http://angularjs.org/doesntexist&callback=JSON_CALLBACK')">
function FetchCtrl($scope, $http, $templateCache) { Invalid JSONP
$scope.method = 'GET'; </button>
$scope.url = 'http-hello.html'; <pre>http status code: {{status}}</pre>
<pre>http response data: {{data}}</pre>
</div>
</file>
<file name="script.js">
function FetchCtrl($scope, $http, $templateCache) {
$scope.method = 'GET';
$scope.url = 'http-hello.html';
$scope.fetch = function() { $scope.fetch = function() {
$scope.code = null; $scope.code = null;
$scope.response = null; $scope.response = null;
$http({method: $scope.method, url: $scope.url, cache: $templateCache}). $http({method: $scope.method, url: $scope.url, cache: $templateCache}).
success(function(data, status) { success(function(data, status) {
$scope.status = status; $scope.status = status;
$scope.data = data; $scope.data = data;
}). }).
error(function(data, status) { error(function(data, status) {
$scope.data = data || "Request failed"; $scope.data = data || "Request failed";
$scope.status = status; $scope.status = status;
}); });
}; };
$scope.updateModel = function(method, url) { $scope.updateModel = function(method, url) {
$scope.method = method; $scope.method = method;
$scope.url = url; $scope.url = url;
}; };
} }
</file> </file>
<file name="http-hello.html"> <file name="http-hello.html">
Hello, $http! Hello, $http!
</file> </file>
<file name="scenario.js"> <file name="scenario.js">
it('should make an xhr GET request', function() { it('should make an xhr GET request', function() {
element(':button:contains("Sample GET")').click(); element(':button:contains("Sample GET")').click();
element(':button:contains("fetch")').click(); element(':button:contains("fetch")').click();
expect(binding('status')).toBe('200'); expect(binding('status')).toBe('200');
expect(binding('data')).toMatch(/Hello, \$http!/); expect(binding('data')).toMatch(/Hello, \$http!/);
}); });
it('should make a JSONP request to angularjs.org', function() { it('should make a JSONP request to angularjs.org', function() {
element(':button:contains("Sample JSONP")').click(); element(':button:contains("Sample JSONP")').click();
element(':button:contains("fetch")').click(); element(':button:contains("fetch")').click();
expect(binding('status')).toBe('200'); expect(binding('status')).toBe('200');
expect(binding('data')).toMatch(/Super Hero!/); expect(binding('data')).toMatch(/Super Hero!/);
}); });
it('should make JSONP request to invalid URL and invoke the error handler', it('should make JSONP request to invalid URL and invoke the error handler',
function() { function() {
element(':button:contains("Invalid JSONP")').click(); element(':button:contains("Invalid JSONP")').click();
element(':button:contains("fetch")').click(); element(':button:contains("fetch")').click();
expect(binding('status')).toBe('0'); expect(binding('status')).toBe('0');
expect(binding('data')).toBe('Request failed'); expect(binding('data')).toBe('Request failed');
}); });
</file> </file>
</example> </example>
*/ */
function $http(requestConfig) { function $http(requestConfig) {
var config = { var config = {
@ -996,7 +1011,7 @@ function $HttpProvider() {
if (!params) return url; if (!params) return url;
var parts = []; var parts = [];
forEachSorted(params, function(value, key) { forEachSorted(params, function(value, key) {
if (value == null || value == undefined) return; if (value === null || isUndefined(value)) return;
if (!isArray(value)) value = [value]; if (!isArray(value)) value = [value];
forEach(value, function(v) { forEach(value, function(v) {

View file

@ -1,4 +1,7 @@
'use strict';
var XHR = window.XMLHttpRequest || function() { var XHR = window.XMLHttpRequest || function() {
/* global ActiveXObject */
try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); } catch (e1) {} try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); } catch (e1) {}
try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); } catch (e2) {} try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); } catch (e2) {}
try { return new ActiveXObject("Msxml2.XMLHTTP"); } catch (e3) {} try { return new ActiveXObject("Msxml2.XMLHTTP"); } catch (e3) {}
@ -69,7 +72,7 @@ function createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument,
var responseHeaders = xhr.getAllResponseHeaders(); var responseHeaders = xhr.getAllResponseHeaders();
// responseText is the old-school way of retrieving response (supported by IE8 & 9) // responseText is the old-school way of retrieving response (supported by IE8 & 9)
// response and responseType properties were introduced in XHR Level2 spec (supported by IE10) // response/responseType properties were introduced in XHR Level2 spec (supported by IE10)
completeRequest(callback, completeRequest(callback,
status || xhr.status, status || xhr.status,
(xhr.responseType ? xhr.response : xhr.responseText), (xhr.responseType ? xhr.response : xhr.responseText),

View file

@ -12,31 +12,31 @@ var $interpolateMinErr = minErr('$interpolate');
* Used for configuring the interpolation markup. Defaults to `{{` and `}}`. * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.
* *
* @example * @example
<doc:example module="customInterpolationApp"> <doc:example module="customInterpolationApp">
<doc:source> <doc:source>
<script> <script>
var customInterpolationApp = angular.module('customInterpolationApp', []); var customInterpolationApp = angular.module('customInterpolationApp', []);
customInterpolationApp.config(function($interpolateProvider) { customInterpolationApp.config(function($interpolateProvider) {
$interpolateProvider.startSymbol('//'); $interpolateProvider.startSymbol('//');
$interpolateProvider.endSymbol('//'); $interpolateProvider.endSymbol('//');
}); });
customInterpolationApp.controller('DemoController', function DemoController() { customInterpolationApp.controller('DemoController', function DemoController() {
this.label = "This bindings is brought you you by // interpolation symbols."; this.label = "This binding is brought you by // interpolation symbols.";
}); });
</script> </script>
<div ng-app="App" ng-controller="DemoController as demo"> <div ng-app="App" ng-controller="DemoController as demo">
//demo.label// //demo.label//
</div> </div>
</doc:source> </doc:source>
<doc:scenario> <doc:scenario>
it('should interpolate binding with custom symbols', function() { it('should interpolate binding with custom symbols', function() {
expect(binding('demo.label')).toBe('This bindings is brought you you by // interpolation symbols.'); expect(binding('demo.label')).toBe('This binding is brought you by // interpolation symbols.');
}); });
</doc:scenario> </doc:scenario>
</doc:example> </doc:example>
*/ */
function $InterpolateProvider() { function $InterpolateProvider() {
var startSymbol = '{{'; var startSymbol = '{{';
@ -116,8 +116,8 @@ function $InterpolateProvider() {
* result through {@link ng.$sce#methods_getTrusted $sce.getTrusted(interpolatedResult, * result through {@link ng.$sce#methods_getTrusted $sce.getTrusted(interpolatedResult,
* trustedContext)} before returning it. Refer to the {@link ng.$sce $sce} service that * trustedContext)} before returning it. Refer to the {@link ng.$sce $sce} service that
* provides Strict Contextual Escaping for details. * provides Strict Contextual Escaping for details.
* @returns {function(context)} an interpolation function which is used to compute the interpolated * @returns {function(context)} an interpolation function which is used to compute the
* string. The function has these parameters: * interpolated string. The function has these parameters:
* *
* * `context`: an object against which any expressions embedded in the strings are evaluated * * `context`: an object against which any expressions embedded in the strings are evaluated
* against. * against.
@ -155,12 +155,12 @@ function $InterpolateProvider() {
length = 1; length = 1;
} }
// Concatenating expressions makes it hard to reason about whether some combination of concatenated // Concatenating expressions makes it hard to reason about whether some combination of
// values are unsafe to use and could easily lead to XSS. By requiring that a single // concatenated values are unsafe to use and could easily lead to XSS. By requiring that a
// expression be used for iframe[src], object[src], etc., we ensure that the value that's used // single expression be used for iframe[src], object[src], etc., we ensure that the value
// is assigned or constructed by some JS code somewhere that is more testable or make it // that's used is assigned or constructed by some JS code somewhere that is more testable or
// obvious that you bound the value to some user controlled value. This helps reduce the load // make it obvious that you bound the value to some user controlled value. This helps reduce
// when auditing for XSS issues. // the load when auditing for XSS issues.
if (trustedContext && parts.length > 1) { if (trustedContext && parts.length > 1) {
throw $interpolateMinErr('noconcat', throw $interpolateMinErr('noconcat',
"Error while interpolating: {0}\nStrict Contextual Escaping disallows " + "Error while interpolating: {0}\nStrict Contextual Escaping disallows " +
@ -180,7 +180,7 @@ function $InterpolateProvider() {
} else { } else {
part = $sce.valueOf(part); part = $sce.valueOf(part);
} }
if (part == null || part == undefined) { if (part === null || isUndefined(part)) {
part = ''; part = '';
} else if (typeof part != 'string') { } else if (typeof part != 'string') {
part = toJson(part); part = toJson(part);
@ -191,7 +191,8 @@ function $InterpolateProvider() {
return concat.join(''); return concat.join('');
} }
catch(err) { catch(err) {
var newErr = $interpolateMinErr('interr', "Can't interpolate: {0}\n{1}", text, err.toString()); var newErr = $interpolateMinErr('interr', "Can't interpolate: {0}\n{1}", text,
err.toString());
$exceptionHandler(newErr); $exceptionHandler(newErr);
} }
}; };
@ -216,7 +217,7 @@ function $InterpolateProvider() {
*/ */
$interpolate.startSymbol = function() { $interpolate.startSymbol = function() {
return startSymbol; return startSymbol;
} };
/** /**
@ -233,7 +234,7 @@ function $InterpolateProvider() {
*/ */
$interpolate.endSymbol = function() { $interpolate.endSymbol = function() {
return endSymbol; return endSymbol;
} };
return $interpolate; return $interpolate;
}]; }];

View file

@ -35,13 +35,13 @@ function $IntervalProvider() {
*/ */
function interval(fn, delay, count, invokeApply) { function interval(fn, delay, count, invokeApply) {
var setInterval = $window.setInterval, var setInterval = $window.setInterval,
clearInterval = $window.clearInterval; clearInterval = $window.clearInterval,
deferred = $q.defer(),
var deferred = $q.defer(),
promise = deferred.promise, promise = deferred.promise,
count = (isDefined(count)) ? count : 0,
iteration = 0, iteration = 0,
skipApply = (isDefined(invokeApply) && !invokeApply); skipApply = (isDefined(invokeApply) && !invokeApply);
count = isDefined(count) ? count : 0,
promise.then(null, null, fn); promise.then(null, null, fn);

View file

@ -45,8 +45,9 @@ function $LocaleProvider(){
}, },
DATETIME_FORMATS: { DATETIME_FORMATS: {
MONTH: 'January,February,March,April,May,June,July,August,September,October,November,December' MONTH:
.split(','), 'January,February,March,April,May,June,July,August,September,October,November,December'
.split(','),
SHORTMONTH: 'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','), SHORTMONTH: 'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),
DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','), DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),
SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','), SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),

View file

@ -37,12 +37,15 @@ function parseAppUrl(relativeUrl, locationObj) {
relativeUrl = '/' + relativeUrl; relativeUrl = '/' + relativeUrl;
} }
var match = urlResolve(relativeUrl); var match = urlResolve(relativeUrl);
locationObj.$$path = decodeURIComponent(prefixed && match.pathname.charAt(0) === '/' ? match.pathname.substring(1) : match.pathname); locationObj.$$path = decodeURIComponent(prefixed && match.pathname.charAt(0) === '/' ?
match.pathname.substring(1) : match.pathname);
locationObj.$$search = parseKeyValue(match.search); locationObj.$$search = parseKeyValue(match.search);
locationObj.$$hash = decodeURIComponent(match.hash); locationObj.$$hash = decodeURIComponent(match.hash);
// make sure path starts with '/'; // make sure path starts with '/';
if (locationObj.$$path && locationObj.$$path.charAt(0) != '/') locationObj.$$path = '/' + locationObj.$$path; if (locationObj.$$path && locationObj.$$path.charAt(0) != '/') {
locationObj.$$path = '/' + locationObj.$$path;
}
} }
@ -50,10 +53,11 @@ function parseAppUrl(relativeUrl, locationObj) {
* *
* @param {string} begin * @param {string} begin
* @param {string} whole * @param {string} whole
* @returns {string} returns text from whole after begin or undefined if it does not begin with expected string. * @returns {string} returns text from whole after begin or undefined if it does not begin with
* expected string.
*/ */
function beginsWith(begin, whole) { function beginsWith(begin, whole) {
if (whole.indexOf(begin) == 0) { if (whole.indexOf(begin) === 0) {
return whole.substr(begin.length); return whole.substr(begin.length);
} }
} }
@ -98,7 +102,8 @@ function LocationHtml5Url(appBase, basePrefix) {
this.$$parse = function(url) { this.$$parse = function(url) {
var pathUrl = beginsWith(appBaseNoFile, url); var pathUrl = beginsWith(appBaseNoFile, url);
if (!isString(pathUrl)) { if (!isString(pathUrl)) {
throw $locationMinErr('ipthprfx', 'Invalid url "{0}", missing path prefix "{1}".', url, appBaseNoFile); throw $locationMinErr('ipthprfx', 'Invalid url "{0}", missing path prefix "{1}".', url,
appBaseNoFile);
} }
parseAppUrl(pathUrl, this); parseAppUrl(pathUrl, this);
@ -137,7 +142,7 @@ function LocationHtml5Url(appBase, basePrefix) {
} else if (appBaseNoFile == url + '/') { } else if (appBaseNoFile == url + '/') {
return appBaseNoFile; return appBaseNoFile;
} }
} };
} }
@ -170,7 +175,8 @@ function LocationHashbangUrl(appBase, hashPrefix) {
: ''; : '';
if (!isString(withoutHashUrl)) { if (!isString(withoutHashUrl)) {
throw $locationMinErr('ihshprfx', 'Invalid url "{0}", missing hash prefix "{1}".', url, hashPrefix); throw $locationMinErr('ihshprfx', 'Invalid url "{0}", missing hash prefix "{1}".', url,
hashPrefix);
} }
parseAppUrl(withoutHashUrl, this); parseAppUrl(withoutHashUrl, this);
this.$$compose(); this.$$compose();
@ -192,7 +198,7 @@ function LocationHashbangUrl(appBase, hashPrefix) {
if(stripHash(appBase) == stripHash(url)) { if(stripHash(appBase) == stripHash(url)) {
return url; return url;
} }
} };
} }
@ -221,7 +227,7 @@ function LocationHashbangInHtml5Url(appBase, hashPrefix) {
} else if ( appBaseNoFile === url + '/') { } else if ( appBaseNoFile === url + '/') {
return appBaseNoFile; return appBaseNoFile;
} }
} };
} }
@ -360,10 +366,12 @@ LocationHashbangInHtml5Url.prototype =
* *
* Change search part when called with parameter and return `$location`. * Change search part when called with parameter and return `$location`.
* *
* @param {string|Object.<string>|Object.<Array.<string>>} search New search params - string or hash object. Hash object * @param {string|Object.<string>|Object.<Array.<string>>} search New search params - string or
* may contain an array of values, which will be decoded as duplicates in the url. * hash object. Hash object may contain an array of values, which will be decoded as duplicates in
* the url.
*
* @param {string=} paramValue If `search` is a string, then `paramValue` will override only a * @param {string=} paramValue If `search` is a string, then `paramValue` will override only a
* single search parameter. If the value is `null`, the parameter will be deleted. * single search parameter. If the value is `null`, the parameter will be deleted.
* *
* @return {string} search * @return {string} search
*/ */
@ -377,11 +385,12 @@ LocationHashbangInHtml5Url.prototype =
} else if (isObject(search)) { } else if (isObject(search)) {
this.$$search = search; this.$$search = search;
} else { } else {
throw $locationMinErr('isrcharg', 'The first argument of the `$location#search()` call must be a string or an object.'); throw $locationMinErr('isrcharg',
'The first argument of the `$location#search()` call must be a string or an object.');
} }
break; break;
default: default:
if (paramValue == undefined || paramValue == null) { if (isUndefined(paramValue) || paramValue === null) {
delete this.$$search[search]; delete this.$$search[search];
} else { } else {
this.$$search[search] = paramValue; this.$$search[search] = paramValue;
@ -573,7 +582,8 @@ function $LocationProvider(){
// update $location when $browser url changes // update $location when $browser url changes
$browser.onUrlChange(function(newUrl) { $browser.onUrlChange(function(newUrl) {
if ($location.absUrl() != newUrl) { if ($location.absUrl() != newUrl) {
if ($rootScope.$broadcast('$locationChangeStart', newUrl, $location.absUrl()).defaultPrevented) { if ($rootScope.$broadcast('$locationChangeStart', newUrl,
$location.absUrl()).defaultPrevented) {
$browser.url($location.absUrl()); $browser.url($location.absUrl());
return; return;
} }

View file

@ -55,12 +55,12 @@ function $LogProvider(){
* @returns {*} current value if used as getter or itself (chaining) if used as setter * @returns {*} current value if used as getter or itself (chaining) if used as setter
*/ */
this.debugEnabled = function(flag) { this.debugEnabled = function(flag) {
if (isDefined(flag)) { if (isDefined(flag)) {
debug = flag; debug = flag;
return this; return this;
} else { } else {
return debug; return debug;
} }
}; };
this.$get = ['$window', function($window){ this.$get = ['$window', function($window){
@ -114,13 +114,13 @@ function $LogProvider(){
* Write a debug message * Write a debug message
*/ */
debug: (function () { debug: (function () {
var fn = consoleLog('debug'); var fn = consoleLog('debug');
return function() { return function() {
if (debug) { if (debug) {
fn.apply(self, arguments); fn.apply(self, arguments);
} }
} };
}()) }())
}; };
@ -155,7 +155,7 @@ function $LogProvider(){
// or we are IE where console.log doesn't have apply so we log at least first 2 args // or we are IE where console.log doesn't have apply so we log at least first 2 args
return function(arg1, arg2) { return function(arg1, arg2) {
logFn(arg1, arg2 == null ? '' : arg2); logFn(arg1, arg2 == null ? '' : arg2);
} };
} }
}]; }];
} }

View file

@ -6,58 +6,65 @@ var promiseWarning;
// Sandboxing Angular Expressions // Sandboxing Angular Expressions
// ------------------------------ // ------------------------------
// Angular expressions are generally considered safe because these expressions only have direct access to $scope and // Angular expressions are generally considered safe because these expressions only have direct
// locals. However, one can obtain the ability to execute arbitrary JS code by obtaining a reference to native JS // access to $scope and locals. However, one can obtain the ability to execute arbitrary JS code by
// functions such as the Function constructor. // obtaining a reference to native JS functions such as the Function constructor.
// //
// As an example, consider the following Angular expression: // As an example, consider the following Angular expression:
// //
// {}.toString.constructor(alert("evil JS code")) // {}.toString.constructor(alert("evil JS code"))
// //
// We want to prevent this type of access. For the sake of performance, during the lexing phase we disallow any "dotted" // We want to prevent this type of access. For the sake of performance, during the lexing phase we
// access to any member named "constructor". // disallow any "dotted" access to any member named "constructor".
// //
// For reflective calls (a[b]) we check that the value of the lookup is not the Function constructor while evaluating // For reflective calls (a[b]) we check that the value of the lookup is not the Function constructor
// the expression, which is a stronger but more expensive test. Since reflective calls are expensive anyway, this is not // while evaluating the expression, which is a stronger but more expensive test. Since reflective
// such a big deal compared to static dereferencing. // calls are expensive anyway, this is not such a big deal compared to static dereferencing.
// //
// This sandboxing technique is not perfect and doesn't aim to be. The goal is to prevent exploits against the // This sandboxing technique is not perfect and doesn't aim to be. The goal is to prevent exploits
// expression language, but not to prevent exploits that were enabled by exposing sensitive JavaScript or browser apis // against the expression language, but not to prevent exploits that were enabled by exposing
// on Scope. Exposing such objects on a Scope is never a good practice and therefore we are not even trying to protect // sensitive JavaScript or browser apis on Scope. Exposing such objects on a Scope is never a good
// against interaction with an object explicitly exposed in this way. // practice and therefore we are not even trying to protect against interaction with an object
// explicitly exposed in this way.
// //
// A developer could foil the name check by aliasing the Function constructor under a different name on the scope. // A developer could foil the name check by aliasing the Function constructor under a different
// name on the scope.
// //
// In general, it is not possible to access a Window object from an angular expression unless a window or some DOM // In general, it is not possible to access a Window object from an angular expression unless a
// object that has a reference to window is published onto a Scope. // window or some DOM object that has a reference to window is published onto a Scope.
function ensureSafeMemberName(name, fullExpression) { function ensureSafeMemberName(name, fullExpression) {
if (name === "constructor") { if (name === "constructor") {
throw $parseMinErr('isecfld', throw $parseMinErr('isecfld',
'Referencing "constructor" field in Angular expressions is disallowed! Expression: {0}', fullExpression); 'Referencing "constructor" field in Angular expressions is disallowed! Expression: {0}',
fullExpression);
} }
return name; return name;
}; }
function ensureSafeObject(obj, fullExpression) { function ensureSafeObject(obj, fullExpression) {
// nifty check if obj is Function that is fast and works across iframes and other contexts // nifty check if obj is Function that is fast and works across iframes and other contexts
if (obj && obj.constructor === obj) { if (obj && obj.constructor === obj) {
throw $parseMinErr('isecfn', throw $parseMinErr('isecfn',
'Referencing Function in Angular expressions is disallowed! Expression: {0}', fullExpression); 'Referencing Function in Angular expressions is disallowed! Expression: {0}',
fullExpression);
} else if (// isWindow(obj) } else if (// isWindow(obj)
obj && obj.document && obj.location && obj.alert && obj.setInterval) { obj && obj.document && obj.location && obj.alert && obj.setInterval) {
throw $parseMinErr('isecwindow', throw $parseMinErr('isecwindow',
'Referencing the Window in Angular expressions is disallowed! Expression: {0}', fullExpression); 'Referencing the Window in Angular expressions is disallowed! Expression: {0}',
fullExpression);
} else if (// isElement(obj) } else if (// isElement(obj)
obj && (obj.nodeName || (obj.on && obj.find))) { obj && (obj.nodeName || (obj.on && obj.find))) {
throw $parseMinErr('isecdom', throw $parseMinErr('isecdom',
'Referencing DOM nodes in Angular expressions is disallowed! Expression: {0}', fullExpression); 'Referencing DOM nodes in Angular expressions is disallowed! Expression: {0}',
fullExpression);
} else { } else {
return obj; return obj;
} }
} }
var OPERATORS = { var OPERATORS = {
/* jshint bitwise : false */
'null':function(){return null;}, 'null':function(){return null;},
'true':function(){return true;}, 'true':function(){return true;},
'false':function(){return false;}, 'false':function(){return false;},
@ -71,7 +78,10 @@ var OPERATORS = {
return a; return a;
} }
return isDefined(b)?b:undefined;}, return isDefined(b)?b:undefined;},
'-':function(self, locals, a,b){a=a(self, locals); b=b(self, locals); return (isDefined(a)?a:0)-(isDefined(b)?b:0);}, '-':function(self, locals, a,b){
a=a(self, locals); b=b(self, locals);
return (isDefined(a)?a:0)-(isDefined(b)?b:0);
},
'*':function(self, locals, a,b){return a(self, locals)*b(self, locals);}, '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);},
'/':function(self, locals, a,b){return a(self, locals)/b(self, locals);}, '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);},
'%':function(self, locals, a,b){return a(self, locals)%b(self, locals);}, '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},
@ -92,6 +102,7 @@ var OPERATORS = {
'|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));}, '|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));},
'!':function(self, locals, a){return !a(self, locals);} '!':function(self, locals, a){return !a(self, locals);}
}; };
/* jshint bitwise: true */
var ESCAPE = {"n":"\n", "f":"\f", "r":"\r", "t":"\t", "v":"\v", "'":"'", '"':'"'}; var ESCAPE = {"n":"\n", "f":"\f", "r":"\r", "t":"\t", "v":"\v", "'":"'", '"':'"'};
@ -192,8 +203,9 @@ Lexer.prototype = {
}, },
isWhitespace: function(ch) { isWhitespace: function(ch) {
// IE treats non-breaking space as \u00A0
return (ch === ' ' || ch === '\r' || ch === '\t' || return (ch === ' ' || ch === '\r' || ch === '\t' ||
ch === '\n' || ch === '\v' || ch === '\u00A0'); // IE treats non-breaking space as \u00A0 ch === '\n' || ch === '\v' || ch === '\u00A0');
}, },
isIdent: function(ch) { isIdent: function(ch) {
@ -960,7 +972,7 @@ function cspSafeGetterFn(key0, key1, key2, key3, key4, fullExp, options) {
pathVal = pathVal.$$v; pathVal = pathVal.$$v;
} }
return pathVal; return pathVal;
} };
} }
function getterFn(path, options, fullExp) { function getterFn(path, options, fullExp) {
@ -976,20 +988,22 @@ function getterFn(path, options, fullExp) {
fn; fn;
if (options.csp) { if (options.csp) {
fn = (pathKeysLength < 6) if (pathKeysLength < 6) {
? cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4], fullExp, options) fn = cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4], fullExp,
: function(scope, locals) { options);
var i = 0, val; } else {
do { fn = function(scope, locals) {
val = cspSafeGetterFn( var i = 0, val;
pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], fullExp, options do {
)(scope, locals); val = cspSafeGetterFn(pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++],
pathKeys[i++], fullExp, options)(scope, locals);
locals = undefined; // clear after first iteration locals = undefined; // clear after first iteration
scope = val; scope = val;
} while (i < pathKeysLength); } while (i < pathKeysLength);
return val; return val;
} };
}
} else { } else {
var code = 'var l, fn, p;\n'; var code = 'var l, fn, p;\n';
forEach(pathKeys, function(key, index) { forEach(pathKeys, function(key, index) {
@ -1015,7 +1029,9 @@ function getterFn(path, options, fullExp) {
}); });
code += 'return s;'; code += 'return s;';
var evaledFnGetter = Function('s', 'k', 'pw', code); // s=scope, k=locals, pw=promiseWarning /* jshint -W054 */
var evaledFnGetter = new Function('s', 'k', 'pw', code); // s=scope, k=locals, pw=promiseWarning
/* jshint +W054 */
evaledFnGetter.toString = function() { return code; }; evaledFnGetter.toString = function() { return code; };
fn = function(scope, locals) { fn = function(scope, locals) {
return evaledFnGetter(scope, locals, promiseWarning); return evaledFnGetter(scope, locals, promiseWarning);
@ -1079,7 +1095,8 @@ function getterFn(path, options, fullExp) {
* @function * @function
* *
* @description * @description
* `$parseProvider` can be used for configuring the default behavior of the {@link ng.$parse $parse} service. * `$parseProvider` can be used for configuring the default behavior of the {@link ng.$parse $parse}
* service.
*/ */
function $ParseProvider() { function $ParseProvider() {
var cache = {}; var cache = {};
@ -1101,35 +1118,40 @@ function $ParseProvider() {
* *
* **This feature is deprecated, see deprecation notes below for more info** * **This feature is deprecated, see deprecation notes below for more info**
* *
* If set to true (default is false), $parse will unwrap promises automatically when a promise is found at any part of * If set to true (default is false), $parse will unwrap promises automatically when a promise is
* the expression. In other words, if set to true, the expression will always result in a non-promise value. * found at any part of the expression. In other words, if set to true, the expression will always
* result in a non-promise value.
* *
* While the promise is unresolved, it's treated as undefined, but once resolved and fulfilled, the fulfillment value * While the promise is unresolved, it's treated as undefined, but once resolved and fulfilled,
* is used in place of the promise while evaluating the expression. * the fulfillment value is used in place of the promise while evaluating the expression.
* *
* **Deprecation notice** * **Deprecation notice**
* *
* This is a feature that didn't prove to be wildly useful or popular, primarily because of the dichotomy between data * This is a feature that didn't prove to be wildly useful or popular, primarily because of the
* access in templates (accessed as raw values) and controller code (accessed as promises). * dichotomy between data access in templates (accessed as raw values) and controller code
* (accessed as promises).
* *
* In most code we ended up resolving promises manually in controllers anyway and thus unifying the model access there. * In most code we ended up resolving promises manually in controllers anyway and thus unifying
* the model access there.
* *
* Other downsides of automatic promise unwrapping: * Other downsides of automatic promise unwrapping:
* *
* - when building components it's often desirable to receive the raw promises * - when building components it's often desirable to receive the raw promises
* - adds complexity and slows down expression evaluation * - adds complexity and slows down expression evaluation
* - makes expression code pre-generation unattractive due to the amount of code that needs to be generated * - makes expression code pre-generation unattractive due to the amount of code that needs to be
* generated
* - makes IDE auto-completion and tool support hard * - makes IDE auto-completion and tool support hard
* *
* **Warning Logs** * **Warning Logs**
* *
* If the unwrapping is enabled, Angular will log a warning about each expression that unwraps a promise (to reduce * If the unwrapping is enabled, Angular will log a warning about each expression that unwraps a
* the noise, each expression is logged only once). To disable this logging use * promise (to reduce the noise, each expression is logged only once). To disable this logging use
* `$parseProvider.logPromiseWarnings(false)` api. * `$parseProvider.logPromiseWarnings(false)` api.
* *
* *
* @param {boolean=} value New value. * @param {boolean=} value New value.
* @returns {boolean|self} Returns the current setting when used as getter and self if used as setter. * @returns {boolean|self} Returns the current setting when used as getter and self if used as
* setter.
*/ */
this.unwrapPromises = function(value) { this.unwrapPromises = function(value) {
if (isDefined(value)) { if (isDefined(value)) {
@ -1156,7 +1178,8 @@ function $ParseProvider() {
* This setting applies only if `$parseProvider.unwrapPromises` setting is set to true as well. * This setting applies only if `$parseProvider.unwrapPromises` setting is set to true as well.
* *
* @param {boolean=} value New value. * @param {boolean=} value New value.
* @returns {boolean|self} Returns the current setting when used as getter and self if used as setter. * @returns {boolean|self} Returns the current setting when used as getter and self if used as
* setter.
*/ */
this.logPromiseWarnings = function(value) { this.logPromiseWarnings = function(value) {
if (isDefined(value)) { if (isDefined(value)) {

View file

@ -50,8 +50,8 @@
* </pre> * </pre>
* *
* At first it might not be obvious why this extra complexity is worth the trouble. The payoff * At first it might not be obvious why this extra complexity is worth the trouble. The payoff
* comes in the way of * comes in the way of guarantees that promise and deferred APIs make, see
* [guarantees that promise and deferred APIs make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md). * https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md.
* *
* Additionally the promise api allows for composition that is very hard to do with the * Additionally the promise api allows for composition that is very hard to do with the
* traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach. * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.
@ -98,8 +98,9 @@
* provide a progress indication, before the promise is resolved or rejected. * provide a progress indication, before the promise is resolved or rejected.
* *
* This method *returns a new promise* which is resolved or rejected via the return value of the * This method *returns a new promise* which is resolved or rejected via the return value of the
* `successCallback`, `errorCallback`. It also notifies via the return value of the `notifyCallback` * `successCallback`, `errorCallback`. It also notifies via the return value of the
* method. The promise can not be resolved or rejected from the notifyCallback method. * `notifyCallback` method. The promise can not be resolved or rejected from the notifyCallback
* method.
* *
* - `catch(errorCallback)` shorthand for `promise.then(null, errorCallback)` * - `catch(errorCallback)` shorthand for `promise.then(null, errorCallback)`
* *
@ -115,8 +116,8 @@
* *
* # Chaining promises * # Chaining promises
* *
* Because calling the `then` method of a promise returns a new derived promise, it is easily possible * Because calling the `then` method of a promise returns a new derived promise, it is easily
* to create a chain of promises: * possible to create a chain of promises:
* *
* <pre> * <pre>
* promiseB = promiseA.then(function(result) { * promiseB = promiseA.then(function(result) {
@ -479,9 +480,9 @@ function qFactory(nextTick, exceptionHandler) {
* *
* @param {Array.<Promise>|Object.<Promise>} promises An array or hash of promises. * @param {Array.<Promise>|Object.<Promise>} promises An array or hash of promises.
* @returns {Promise} Returns a single promise that will be resolved with an array/hash of values, * @returns {Promise} Returns a single promise that will be resolved with an array/hash of values,
* each value corresponding to the promise at the same index/key in the `promises` array/hash. If any of * each value corresponding to the promise at the same index/key in the `promises` array/hash.
* the promises is resolved with a rejection, this resulting promise will be rejected with the * If any of the promises is resolved with a rejection, this resulting promise will be rejected
* same rejection value. * with the same rejection value.
*/ */
function all(promises) { function all(promises) {
var deferred = defer(), var deferred = defer(),

View file

@ -40,14 +40,18 @@
* @methodOf ng.$rootScopeProvider * @methodOf ng.$rootScopeProvider
* @description * @description
* *
* Sets the number of `$digest` iterations the scope should attempt to execute before giving up and assuming that the model is unstable. * Sets the number of `$digest` iterations the scope should attempt to execute before giving up and
* assuming that the model is unstable.
* *
* The current default is 10 iterations. * The current default is 10 iterations.
* *
* In complex applications it's possible that the dependencies between `$watch`s will result in several digest iterations. * In complex applications it's possible that the dependencies between `$watch`s will result in
* However if an application needs more than the default 10 digest iterations for its model to stabilize then you should investigate what is causing the model to continuously change during the digest. * several digest iterations. However if an application needs more than the default 10 digest
* iterations for its model to stabilize then you should investigate what is causing the model to
* continuously change during the digest.
* *
* Increasing the TTL could have performance implications, so you should not change it without proper justification. * Increasing the TTL could have performance implications, so you should not change it without
* proper justification.
* *
* @param {number} limit The number of digest iterations. * @param {number} limit The number of digest iterations.
*/ */
@ -109,11 +113,12 @@ function $RootScopeProvider(){
* </pre> * </pre>
* *
* *
* @param {Object.<string, function()>=} providers Map of service factory which need to be provided * @param {Object.<string, function()>=} providers Map of service factory which need to be
* for the current scope. Defaults to {@link ng}. * provided for the current scope. Defaults to {@link ng}.
* @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should
* append/override services provided by `providers`. This is handy when unit-testing and having * append/override services provided by `providers`. This is handy
* the need to override a default service. * when unit-testing and having the need to override a default
* service.
* @returns {Object} Newly created scope. * @returns {Object} Newly created scope.
* *
*/ */
@ -151,12 +156,12 @@ function $RootScopeProvider(){
* Creates a new child {@link ng.$rootScope.Scope scope}. * Creates a new child {@link ng.$rootScope.Scope scope}.
* *
* The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} and * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} and
* {@link ng.$rootScope.Scope#$digest $digest()} events. The scope can be removed from the scope * {@link ng.$rootScope.Scope#$digest $digest()} events. The scope can be removed from the
* hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}. * scope hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.
* *
* {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is desired for * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is
* the scope and its child scopes to be permanently detached from the parent and thus stop * desired for the scope and its child scopes to be permanently detached from the parent and
* participating in model change detection and listener notification by invoking. * thus stop participating in model change detection and listener notification by invoking.
* *
* @param {boolean} isolate If true, then the scope does not prototypically inherit from the * @param {boolean} isolate If true, then the scope does not prototypically inherit from the
* parent scope. The scope is isolated, as it can not see parent scope properties. * parent scope. The scope is isolated, as it can not see parent scope properties.
@ -207,25 +212,26 @@ function $RootScopeProvider(){
* @description * @description
* Registers a `listener` callback to be executed whenever the `watchExpression` changes. * Registers a `listener` callback to be executed whenever the `watchExpression` changes.
* *
* - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest $digest()} and * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest
* should return the value that will be watched. (Since {@link ng.$rootScope.Scope#$digest $digest()} * $digest()} and should return the value that will be watched. (Since
* reruns when it detects changes the `watchExpression` can execute multiple times per * {@link ng.$rootScope.Scope#$digest $digest()} reruns when it detects changes the
* `watchExpression` can execute multiple times per
* {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.) * {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)
* - The `listener` is called only when the value from the current `watchExpression` and the * - The `listener` is called only when the value from the current `watchExpression` and the
* previous call to `watchExpression` are not equal (with the exception of the initial run, * previous call to `watchExpression` are not equal (with the exception of the initial run,
* see below). The inequality is determined according to * see below). The inequality is determined according to
* {@link angular.equals} function. To save the value of the object for later comparison, the * {@link angular.equals} function. To save the value of the object for later comparison,
* {@link angular.copy} function is used. It also means that watching complex options will * the {@link angular.copy} function is used. It also means that watching complex options
* have adverse memory and performance implications. * will have adverse memory and performance implications.
* - The watch `listener` may change the model, which may trigger other `listener`s to fire. This * - The watch `listener` may change the model, which may trigger other `listener`s to fire.
* is achieved by rerunning the watchers until no changes are detected. The rerun iteration * This is achieved by rerunning the watchers until no changes are detected. The rerun
* limit is 10 to prevent an infinite loop deadlock. * iteration limit is 10 to prevent an infinite loop deadlock.
* *
* *
* If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called, * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,
* you can register a `watchExpression` function with no `listener`. (Since `watchExpression` * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`
* can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a change is * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a
* detected, be prepared for multiple calls to your listener.) * change is detected, be prepared for multiple calls to your listener.)
* *
* After a watcher is registered with the scope, the `listener` fn is called asynchronously * After a watcher is registered with the scope, the `listener` fn is called asynchronously
* (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the
@ -243,7 +249,9 @@ function $RootScopeProvider(){
scope.counter = 0; scope.counter = 0;
expect(scope.counter).toEqual(0); expect(scope.counter).toEqual(0);
scope.$watch('name', function(newValue, oldValue) { scope.counter = scope.counter + 1; }); scope.$watch('name', function(newValue, oldValue) {
scope.counter = scope.counter + 1;
});
expect(scope.counter).toEqual(0); expect(scope.counter).toEqual(0);
scope.$digest(); scope.$digest();
@ -258,8 +266,8 @@ function $RootScopeProvider(){
* *
* *
* @param {(function()|string)} watchExpression Expression that is evaluated on each * @param {(function()|string)} watchExpression Expression that is evaluated on each
* {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers a * {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers
* call to the `listener`. * a call to the `listener`.
* *
* - `string`: Evaluated as {@link guide/expression expression} * - `string`: Evaluated as {@link guide/expression expression}
* - `function(scope)`: called with current `scope` as a parameter. * - `function(scope)`: called with current `scope` as a parameter.
@ -267,7 +275,8 @@ function $RootScopeProvider(){
* the `watchExpression` changes. * the `watchExpression` changes.
* *
* - `string`: Evaluated as {@link guide/expression expression} * - `string`: Evaluated as {@link guide/expression expression}
* - `function(newValue, oldValue, scope)`: called with current and previous values as parameters. * - `function(newValue, oldValue, scope)`: called with current and previous values as
* parameters.
* *
* @param {boolean=} objectEquality Compare object for equality rather than for reference. * @param {boolean=} objectEquality Compare object for equality rather than for reference.
* @returns {function()} Returns a deregistration function for this listener. * @returns {function()} Returns a deregistration function for this listener.
@ -319,13 +328,13 @@ function $RootScopeProvider(){
* *
* @description * @description
* Shallow watches the properties of an object and fires whenever any of the properties change * Shallow watches the properties of an object and fires whenever any of the properties change
* (for arrays, this implies watching the array items; for object maps, this implies watching the properties). * (for arrays, this implies watching the array items; for object maps, this implies watching
* If a change is detected, the `listener` callback is fired. * the properties). If a change is detected, the `listener` callback is fired.
* *
* - The `obj` collection is observed via standard $watch operation and is examined on every call to $digest() to * - The `obj` collection is observed via standard $watch operation and is examined on every
* see if any items have been added, removed, or moved. * call to $digest() to see if any items have been added, removed, or moved.
* - The `listener` is called whenever anything within the `obj` has changed. Examples include adding, removing, * - The `listener` is called whenever anything within the `obj` has changed. Examples include
* and moving items belonging to an object or array. * adding, removing, and moving items belonging to an object or array.
* *
* *
* # Example * # Example
@ -351,19 +360,19 @@ function $RootScopeProvider(){
* </pre> * </pre>
* *
* *
* @param {string|Function(scope)} obj Evaluated as {@link guide/expression expression}. The expression value * @param {string|Function(scope)} obj Evaluated as {@link guide/expression expression}. The
* should evaluate to an object or an array which is observed on each * 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 * {@link ng.$rootScope.Scope#$digest $digest} cycle. Any shallow change within the
* a call to the `listener`. * collection will trigger a call to the `listener`.
* *
* @param {function(newCollection, oldCollection, scope)} listener a callback function that is fired with both * @param {function(newCollection, oldCollection, scope)} listener a callback function that is
* the `newCollection` and `oldCollection` as parameters. * fired with both the `newCollection` and `oldCollection` as parameters.
* The `newCollection` object is the newly modified data obtained from the `obj` expression and the * The `newCollection` object is the newly modified data obtained from the `obj` expression
* `oldCollection` object is a copy of the former collection data. * and the `oldCollection` object is a copy of the former collection data.
* The `scope` refers to the current scope. * The `scope` refers to the current scope.
* *
* @returns {function()} Returns a de-registration function for this listener. When the de-registration function * @returns {function()} Returns a de-registration function for this listener. When the
* is executed, the internal watch operation is terminated. * de-registration function is executed, the internal watch operation is terminated.
*/ */
$watchCollection: function(obj, listener) { $watchCollection: function(obj, listener) {
var self = this; var self = this;
@ -458,21 +467,22 @@ function $RootScopeProvider(){
* @function * @function
* *
* @description * @description
* Processes all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and its children. * Processes all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and
* Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change the model, the * its children. Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change
* `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} until no more listeners are * the model, the `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers}
* firing. This means that it is possible to get into an infinite loop. This function will throw * until no more listeners are firing. This means that it is possible to get into an infinite
* `'Maximum iteration limit exceeded.'` if the number of iterations exceeds 10. * loop. This function will throw `'Maximum iteration limit exceeded.'` if the number of
* iterations exceeds 10.
* *
* Usually, you don't call `$digest()` directly in * Usually, you don't call `$digest()` directly in
* {@link ng.directive:ngController controllers} or in * {@link ng.directive:ngController controllers} or in
* {@link ng.$compileProvider#methods_directive directives}. * {@link ng.$compileProvider#methods_directive directives}.
* Instead, you should call {@link ng.$rootScope.Scope#$apply $apply()} (typically from within a * Instead, you should call {@link ng.$rootScope.Scope#$apply $apply()} (typically from within
* {@link ng.$compileProvider#methods_directive directives}), which will force a `$digest()`. * a {@link ng.$compileProvider#methods_directive directives}), which will force a `$digest()`.
* *
* If you want to be notified whenever `$digest()` is called, * If you want to be notified whenever `$digest()` is called,
* you can register a `watchExpression` function with {@link ng.$rootScope.Scope#$watch $watch()} * you can register a `watchExpression` function with
* with no `listener`. * {@link ng.$rootScope.Scope#$watch $watch()} with no `listener`.
* *
* In unit tests, you may need to call `$digest()` to simulate the scope life cycle. * In unit tests, you may need to call `$digest()` to simulate the scope life cycle.
* *
@ -570,7 +580,8 @@ function $RootScopeProvider(){
if(dirty && !(ttl--)) { if(dirty && !(ttl--)) {
clearPhase(); clearPhase();
throw $rootScopeMinErr('infdig', throw $rootScopeMinErr('infdig',
'{0} $digest() iterations reached. Aborting!\nWatchers fired in the last 5 iterations: {1}', '{0} $digest() iterations reached. Aborting!\n' +
'Watchers fired in the last 5 iterations: {1}',
TTL, toJson(watchLog)); TTL, toJson(watchLog));
} }
} while (dirty || asyncQueue.length); } while (dirty || asyncQueue.length);
@ -649,8 +660,9 @@ function $RootScopeProvider(){
* @function * @function
* *
* @description * @description
* Executes the `expression` on the current scope and returns the result. Any exceptions in the * Executes the `expression` on the current scope and returns the result. Any exceptions in
* expression are propagated (uncaught). This is useful when evaluating Angular expressions. * the expression are propagated (uncaught). This is useful when evaluating Angular
* expressions.
* *
* # Example * # Example
* <pre> * <pre>
@ -682,17 +694,20 @@ function $RootScopeProvider(){
* @description * @description
* Executes the expression on the current scope at a later point in time. * Executes the expression on the current scope at a later point in time.
* *
* The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only that: * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only
* that:
* *
* - it will execute after the function that scheduled the evaluation (preferably before DOM rendering). * - it will execute after the function that scheduled the evaluation (preferably before DOM
* - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after `expression` execution. * rendering).
* - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after
* `expression` execution.
* *
* Any exceptions from the execution of the expression are forwarded to the * Any exceptions from the execution of the expression are forwarded to the
* {@link ng.$exceptionHandler $exceptionHandler} service. * {@link ng.$exceptionHandler $exceptionHandler} service.
* *
* __Note:__ if this function is called outside of a `$digest` cycle, a new `$digest` cycle will be scheduled. * __Note:__ if this function is called outside of a `$digest` cycle, a new `$digest` cycle
* However, it is encouraged to always call code that changes the model from within an `$apply` call. * will be scheduled. However, it is encouraged to always call code that changes the model
* That includes code evaluated via `$evalAsync`. * from within an `$apply` call. That includes code evaluated via `$evalAsync`.
* *
* @param {(string|function())=} expression An angular expression to be executed. * @param {(string|function())=} expression An angular expression to be executed.
* *
@ -701,8 +716,8 @@ function $RootScopeProvider(){
* *
*/ */
$evalAsync: function(expr) { $evalAsync: function(expr) {
// if we are outside of an $digest loop and this is the first time we are scheduling async task also schedule // if we are outside of an $digest loop and this is the first time we are scheduling async
// async auto-flush // task also schedule async auto-flush
if (!$rootScope.$$phase && !$rootScope.$$asyncQueue.length) { if (!$rootScope.$$phase && !$rootScope.$$asyncQueue.length) {
$browser.defer(function() { $browser.defer(function() {
if ($rootScope.$$asyncQueue.length) { if ($rootScope.$$asyncQueue.length) {
@ -725,10 +740,10 @@ function $RootScopeProvider(){
* @function * @function
* *
* @description * @description
* `$apply()` is used to execute an expression in angular from outside of the angular framework. * `$apply()` is used to execute an expression in angular from outside of the angular
* (For example from browser DOM events, setTimeout, XHR or third party libraries). * framework. (For example from browser DOM events, setTimeout, XHR or third party libraries).
* Because we are calling into the angular framework we need to perform proper scope life cycle * Because we are calling into the angular framework we need to perform proper scope life
* of {@link ng.$exceptionHandler exception handling}, * cycle of {@link ng.$exceptionHandler exception handling},
* {@link ng.$rootScope.Scope#$digest executing watches}. * {@link ng.$rootScope.Scope#$digest executing watches}.
* *
* ## Life cycle * ## Life cycle
@ -753,8 +768,8 @@ function $RootScopeProvider(){
* {@link ng.$rootScope.Scope#$eval $eval()} method. * {@link ng.$rootScope.Scope#$eval $eval()} method.
* 2. Any exceptions from the execution of the expression are forwarded to the * 2. Any exceptions from the execution of the expression are forwarded to the
* {@link ng.$exceptionHandler $exceptionHandler} service. * {@link ng.$exceptionHandler $exceptionHandler} service.
* 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the expression * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the
* was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method. * expression was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.
* *
* *
* @param {(string|function())=} exp An angular expression to be executed. * @param {(string|function())=} exp An angular expression to be executed.
@ -788,18 +803,20 @@ function $RootScopeProvider(){
* @function * @function
* *
* @description * @description
* Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for discussion of * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for
* event life cycle. * discussion of event life cycle.
* *
* The event listener function format is: `function(event, args...)`. The `event` object * The event listener function format is: `function(event, args...)`. The `event` object
* passed into the listener has the following attributes: * passed into the listener has the following attributes:
* *
* - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or `$broadcast`-ed. * - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or
* `$broadcast`-ed.
* - `currentScope` - `{Scope}`: the current scope which is handling the event. * - `currentScope` - `{Scope}`: the current scope which is handling the event.
* - `name` - `{string}`: name of the event. * - `name` - `{string}`: name of the event.
* - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel further event * - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel
* propagation (available only for events that were `$emit`-ed). * further event propagation (available only for events that were `$emit`-ed).
* - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag to true. * - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag
* to true.
* - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called. * - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.
* *
* @param {string} name Event name to listen on. * @param {string} name Event name to listen on.
@ -830,9 +847,10 @@ function $RootScopeProvider(){
* registered {@link ng.$rootScope.Scope#$on} listeners. * registered {@link ng.$rootScope.Scope#$on} listeners.
* *
* The event life cycle starts at the scope on which `$emit` was called. All * The event life cycle starts at the scope on which `$emit` was called. All
* {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified. * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get
* Afterwards, the event traverses upwards toward the root scope and calls all registered * notified. Afterwards, the event traverses upwards toward the root scope and calls all
* listeners along the way. The event will stop propagating if one of the listeners cancels it. * registered listeners along the way. The event will stop propagating if one of the listeners
* cancels it.
* *
* Any exception emitted from the {@link ng.$rootScope.Scope#$on listeners} will be passed * Any exception emitted from the {@link ng.$rootScope.Scope#$on listeners} will be passed
* onto the {@link ng.$exceptionHandler $exceptionHandler} service. * onto the {@link ng.$exceptionHandler $exceptionHandler} service.
@ -898,9 +916,9 @@ function $RootScopeProvider(){
* registered {@link ng.$rootScope.Scope#$on} listeners. * registered {@link ng.$rootScope.Scope#$on} listeners.
* *
* The event life cycle starts at the scope on which `$broadcast` was called. All * The event life cycle starts at the scope on which `$broadcast` was called. All
* {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified. * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get
* Afterwards, the event propagates to all direct and indirect scopes of the current scope and * notified. Afterwards, the event propagates to all direct and indirect scopes of the current
* calls all registered listeners along the way. The event cannot be canceled. * scope and calls all registered listeners along the way. The event cannot be canceled.
* *
* Any exception emitted from the {@link ng.$rootScope.Scope#$on listeners} will be passed * Any exception emitted from the {@link ng.$rootScope.Scope#$on listeners} will be passed
* onto the {@link ng.$exceptionHandler $exceptionHandler} service. * onto the {@link ng.$exceptionHandler $exceptionHandler} service.

View file

@ -20,7 +20,7 @@ var SCE_CONTEXTS = {
function escapeForRegexp(s) { function escapeForRegexp(s) {
return s.replace(/([-()\[\]{}+?*.$\^|,:#<!\\])/g, '\\$1'). return s.replace(/([-()\[\]{}+?*.$\^|,:#<!\\])/g, '\\$1').
replace(/\x08/g, '\\x08'); replace(/\x08/g, '\\x08');
}; }
function adjustMatcher(matcher) { function adjustMatcher(matcher) {
@ -144,8 +144,8 @@ function $SceDelegateProvider() {
* provided. This must be an array or null. A snapshot of this array is used so further * provided. This must be an array or null. A snapshot of this array is used so further
* changes to the array are ignored. * changes to the array are ignored.
* *
* Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items allowed in * Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items
* this array. * allowed in this array.
* *
* Note: **an empty whitelist array will block all URLs**! * Note: **an empty whitelist array will block all URLs**!
* *
@ -174,19 +174,19 @@ function $SceDelegateProvider() {
* provided. This must be an array or null. A snapshot of this array is used so further * provided. This must be an array or null. A snapshot of this array is used so further
* changes to the array are ignored. * changes to the array are ignored.
* *
* Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items allowed in * Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items
* this array. * allowed in this array.
* *
* The typical usage for the blacklist is to **block [open redirects](http://cwe.mitre.org/data/definitions/601.html)** * The typical usage for the blacklist is to **block
* served by your domain as these would otherwise be trusted but actually return content from the redirected * [open redirects](http://cwe.mitre.org/data/definitions/601.html)** served by your domain as
* domain. * these would otherwise be trusted but actually return content from the redirected domain.
* *
* Finally, **the blacklist overrides the whitelist** and has the final say. * Finally, **the blacklist overrides the whitelist** and has the final say.
* *
* @return {Array} the currently set blacklist array. * @return {Array} the currently set blacklist array.
* *
* The **default value** when no whitelist has been explicitly set is the empty array (i.e. there is * The **default value** when no whitelist has been explicitly set is the empty array (i.e. there
* no blacklist.) * is no blacklist.)
* *
* @description * @description
* Sets/Gets the blacklist of trusted resource URLs. * Sets/Gets the blacklist of trusted resource URLs.
@ -242,21 +242,21 @@ function $SceDelegateProvider() {
return allowed; return allowed;
} }
function generateHolderType(base) { function generateHolderType(Base) {
var holderType = function TrustedValueHolderType(trustedValue) { var holderType = function TrustedValueHolderType(trustedValue) {
this.$$unwrapTrustedValue = function() { this.$$unwrapTrustedValue = function() {
return trustedValue; return trustedValue;
}; };
}; };
if (base) { if (Base) {
holderType.prototype = new base(); holderType.prototype = new Base();
} }
holderType.prototype.valueOf = function sceValueOf() { holderType.prototype.valueOf = function sceValueOf() {
return this.$$unwrapTrustedValue(); return this.$$unwrapTrustedValue();
} };
holderType.prototype.toString = function sceToString() { holderType.prototype.toString = function sceToString() {
return this.$$unwrapTrustedValue().toString(); return this.$$unwrapTrustedValue().toString();
} };
return holderType; return holderType;
} }
@ -288,9 +288,10 @@ function $SceDelegateProvider() {
* where Angular expects a $sce.trustAs() return value. * where Angular expects a $sce.trustAs() return value.
*/ */
function trustAs(type, trustedValue) { function trustAs(type, trustedValue) {
var constructor = (byType.hasOwnProperty(type) ? byType[type] : null); var Constructor = (byType.hasOwnProperty(type) ? byType[type] : null);
if (!constructor) { if (!Constructor) {
throw $sceMinErr('icontext', 'Attempted to trust a value in invalid context. Context: {0}; Value: {1}', throw $sceMinErr('icontext',
'Attempted to trust a value in invalid context. Context: {0}; Value: {1}',
type, trustedValue); type, trustedValue);
} }
if (trustedValue === null || trustedValue === undefined || trustedValue === '') { if (trustedValue === null || trustedValue === undefined || trustedValue === '') {
@ -303,7 +304,7 @@ function $SceDelegateProvider() {
'Attempted to trust a non-string value in a content requiring a string: Context: {0}', 'Attempted to trust a non-string value in a content requiring a string: Context: {0}',
type); type);
} }
return new constructor(trustedValue); return new Constructor(trustedValue);
} }
/** /**
@ -322,8 +323,8 @@ function $SceDelegateProvider() {
* @param {*} value The result of a prior {@link ng.$sceDelegate#methods_trustAs `$sceDelegate.trustAs`} * @param {*} value The result of a prior {@link ng.$sceDelegate#methods_trustAs `$sceDelegate.trustAs`}
* call or anything else. * call or anything else.
* @returns {*} The value the was originally provided to {@link ng.$sceDelegate#methods_trustAs * @returns {*} The value the was originally provided to {@link ng.$sceDelegate#methods_trustAs
* `$sceDelegate.trustAs`} if `value` is the result of such a call. Otherwise, returns `value` * `$sceDelegate.trustAs`} if `value` is the result of such a call. Otherwise, returns
* unchanged. * `value` unchanged.
*/ */
function valueOf(maybeTrusted) { function valueOf(maybeTrusted) {
if (maybeTrusted instanceof trustedValueHolderBase) { if (maybeTrusted instanceof trustedValueHolderBase) {
@ -339,13 +340,13 @@ function $SceDelegateProvider() {
* @methodOf ng.$sceDelegate * @methodOf ng.$sceDelegate
* *
* @description * @description
* Takes the result of a {@link ng.$sceDelegate#methods_trustAs `$sceDelegate.trustAs`} call and returns the * Takes the result of a {@link ng.$sceDelegate#methods_trustAs `$sceDelegate.trustAs`} call and
* originally supplied value if the queried context type is a supertype of the created type. If * returns the originally supplied value if the queried context type is a supertype of the
* this condition isn't satisfied, throws an exception. * 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 {string} type The kind of context in which this value is to be used.
* @param {*} maybeTrusted The result of a prior {@link ng.$sceDelegate#methods_trustAs * @param {*} maybeTrusted The result of a prior {@link ng.$sceDelegate#methods_trustAs
* `$sceDelegate.trustAs`} call. * `$sceDelegate.trustAs`} call.
* @returns {*} The value the was originally provided to {@link ng.$sceDelegate#methods_trustAs * @returns {*} The value the was originally provided to {@link ng.$sceDelegate#methods_trustAs
* `$sceDelegate.trustAs`} if valid in this context. Otherwise, throws an exception. * `$sceDelegate.trustAs`} if valid in this context. Otherwise, throws an exception.
*/ */
@ -365,7 +366,8 @@ function $SceDelegateProvider() {
return maybeTrusted; return maybeTrusted;
} else { } else {
throw $sceMinErr('insecurl', throw $sceMinErr('insecurl',
'Blocked loading resource from url not allowed by $sceDelegate policy. URL: {0}', maybeTrusted.toString()); 'Blocked loading resource from url not allowed by $sceDelegate policy. URL: {0}',
maybeTrusted.toString());
} }
} else if (type === SCE_CONTEXTS.HTML) { } else if (type === SCE_CONTEXTS.HTML) {
return htmlSanitizer(maybeTrusted); return htmlSanitizer(maybeTrusted);
@ -392,6 +394,8 @@ function $SceDelegateProvider() {
* Read more about {@link ng.$sce Strict Contextual Escaping (SCE)}. * Read more about {@link ng.$sce Strict Contextual Escaping (SCE)}.
*/ */
/* jshint maxlen: false*/
/** /**
* @ngdoc service * @ngdoc service
* @name ng.$sce * @name ng.$sce
@ -448,9 +452,9 @@ function $SceDelegateProvider() {
* allowing only the files in a specific directory to do this. Ensuring that the internal API * allowing only the files in a specific directory to do this. Ensuring that the internal API
* exposed by that code doesn't markup arbitrary values as safe then becomes a more manageable task. * exposed by that code doesn't markup arbitrary values as safe then becomes a more manageable task.
* *
* In the case of AngularJS' SCE service, one uses {@link ng.$sce#methods_trustAs $sce.trustAs} (and shorthand * In the case of AngularJS' SCE service, one uses {@link ng.$sce#methods_trustAs $sce.trustAs}
* methods such as {@link ng.$sce#methods_trustAsHtml $sce.trustAsHtml}, etc.) to obtain values that will be * (and shorthand methods such as {@link ng.$sce#methods_trustAsHtml $sce.trustAsHtml}, etc.) to
* accepted by SCE / privileged contexts. * obtain values that will be accepted by SCE / privileged contexts.
* *
* *
* ## How does it work? * ## How does it work?
@ -577,60 +581,63 @@ function $SceDelegateProvider() {
* ## Show me an example using SCE. * ## Show me an example using SCE.
* *
* @example * @example
<example module="mySceApp"> <example module="mySceApp">
<file name="index.html"> <file name="index.html">
<div ng-controller="myAppController as myCtrl"> <div ng-controller="myAppController as myCtrl">
<i ng-bind-html="myCtrl.explicitlyTrustedHtml" id="explicitlyTrustedHtml"></i><br><br> <i ng-bind-html="myCtrl.explicitlyTrustedHtml" id="explicitlyTrustedHtml"></i><br><br>
<b>User comments</b><br> <b>User comments</b><br>
By default, HTML that isn't explicitly trusted (e.g. Alice's comment) is sanitized when $sanitize is available. If $sanitize isn't available, this results in an error instead of an exploit. By default, HTML that isn't explicitly trusted (e.g. Alice's comment) is sanitized when
<div class="well"> $sanitize is available. If $sanitize isn't available, this results in an error instead of an
<div ng-repeat="userComment in myCtrl.userComments"> exploit.
<b>{{userComment.name}}</b>: <div class="well">
<span ng-bind-html="userComment.htmlComment" class="htmlComment"></span> <div ng-repeat="userComment in myCtrl.userComments">
<br> <b>{{userComment.name}}</b>:
</div> <span ng-bind-html="userComment.htmlComment" class="htmlComment"></span>
<br>
</div> </div>
</div> </div>
</file> </div>
</file>
<file name="script.js"> <file name="script.js">
var mySceApp = angular.module('mySceApp', ['ngSanitize']); var mySceApp = angular.module('mySceApp', ['ngSanitize']);
mySceApp.controller("myAppController", function myAppController($http, $templateCache, $sce) { mySceApp.controller("myAppController", function myAppController($http, $templateCache, $sce) {
var self = this; var self = this;
$http.get("test_data.json", {cache: $templateCache}).success(function(userComments) { $http.get("test_data.json", {cache: $templateCache}).success(function(userComments) {
self.userComments = userComments; self.userComments = userComments;
}); });
self.explicitlyTrustedHtml = $sce.trustAsHtml( self.explicitlyTrustedHtml = $sce.trustAsHtml(
'<span onmouseover="this.textContent=&quot;Explicitly trusted HTML bypasses ' +
'sanitization.&quot;">Hover over this text.</span>');
});
</file>
<file name="test_data.json">
[
{ "name": "Alice",
"htmlComment":
"<span onmouseover='this.textContent=\"PWN3D!\"'>Is <i>anyone</i> reading this?</span>"
},
{ "name": "Bob",
"htmlComment": "<i>Yes!</i> Am I the only other one?"
}
]
</file>
<file name="scenario.js">
describe('SCE doc demo', function() {
it('should sanitize untrusted values', function() {
expect(element('.htmlComment').html()).toBe('<span>Is <i>anyone</i> reading this?</span>');
});
it('should NOT sanitize explicitly trusted values', function() {
expect(element('#explicitlyTrustedHtml').html()).toBe(
'<span onmouseover="this.textContent=&quot;Explicitly trusted HTML bypasses ' + '<span onmouseover="this.textContent=&quot;Explicitly trusted HTML bypasses ' +
'sanitization.&quot;">Hover over this text.</span>'); 'sanitization.&quot;">Hover over this text.</span>');
}); });
</file> });
</file>
<file name="test_data.json"> </example>
[
{ "name": "Alice",
"htmlComment": "<span onmouseover='this.textContent=\"PWN3D!\"'>Is <i>anyone</i> reading this?</span>"
},
{ "name": "Bob",
"htmlComment": "<i>Yes!</i> Am I the only other one?"
}
]
</file>
<file name="scenario.js">
describe('SCE doc demo', function() {
it('should sanitize untrusted values', function() {
expect(element('.htmlComment').html()).toBe('<span>Is <i>anyone</i> reading this?</span>');
});
it('should NOT sanitize explicitly trusted values', function() {
expect(element('#explicitlyTrustedHtml').html()).toBe(
'<span onmouseover="this.textContent=&quot;Explicitly trusted HTML bypasses ' +
'sanitization.&quot;">Hover over this text.</span>');
});
});
</file>
</example>
* *
* *
* *
@ -653,6 +660,7 @@ function $SceDelegateProvider() {
* </pre> * </pre>
* *
*/ */
/* jshint maxlen: 100 */
function $SceProvider() { function $SceProvider() {
var enabled = true; var enabled = true;
@ -698,13 +706,13 @@ function $SceProvider() {
* This function should return the a value that is safe to use in the context specified by * This function should return the a value that is safe to use in the context specified by
* contextEnum or throw and exception otherwise. * contextEnum or throw and exception otherwise.
* *
* NOTE: This contract deliberately does NOT state that values returned by trustAs() must be opaque * NOTE: This contract deliberately does NOT state that values returned by trustAs() must be
* or wrapped in some holder object. That happens to be an implementation detail. For instance, * opaque or wrapped in some holder object. That happens to be an implementation detail. For
* an implementation could maintain a registry of all trusted objects by context. In such a case, * instance, an implementation could maintain a registry of all trusted objects by context. In
* trustAs() would return the same object that was passed in. getTrusted() would return the same * such a case, trustAs() would return the same object that was passed in. getTrusted() would
* object passed in if it was found in the registry under a compatible context or throw an * return the same object passed in if it was found in the registry under a compatible context or
* exception otherwise. An implementation might only wrap values some of the time based on * throw an exception otherwise. An implementation might only wrap values some of the time based
* some criteria. getTrusted() might return a value and not throw an exception for special * on some criteria. getTrusted() might return a value and not throw an exception for special
* constants or objects even if not wrapped. All such implementations fulfill this contract. * constants or objects even if not wrapped. All such implementations fulfill this contract.
* *
* *
@ -759,8 +767,8 @@ function $SceProvider() {
sce.valueOf = $sceDelegate.valueOf; sce.valueOf = $sceDelegate.valueOf;
if (!enabled) { if (!enabled) {
sce.trustAs = sce.getTrusted = function(type, value) { return value; }, sce.trustAs = sce.getTrusted = function(type, value) { return value; };
sce.valueOf = identity sce.valueOf = identity;
} }
/** /**
@ -790,7 +798,7 @@ function $SceProvider() {
} else { } else {
return function sceParseAsTrusted(self, locals) { return function sceParseAsTrusted(self, locals) {
return sce.getTrusted(type, parsed(self, locals)); return sce.getTrusted(type, parsed(self, locals));
} };
} }
}; };
@ -800,11 +808,12 @@ function $SceProvider() {
* @methodOf ng.$sce * @methodOf ng.$sce
* *
* @description * @description
* Delegates to {@link ng.$sceDelegate#methods_trustAs `$sceDelegate.trustAs`}. As such, returns an object * Delegates to {@link ng.$sceDelegate#methods_trustAs `$sceDelegate.trustAs`}. As such,
* that is trusted by angular for use in specified strict contextual escaping contexts (such as * returns an objectthat is trusted by angular for use in specified strict contextual
* ng-html-bind-unsafe, ng-include, any src attribute interpolation, any dom event binding * escaping contexts (such as ng-html-bind-unsafe, ng-include, any src attribute
* attribute interpolation such as for onclick, etc.) that uses the provided value. See * * interpolation, any dom event binding attribute interpolation such as for onclick, etc.)
* {@link ng.$sce $sce} for enabling strict contextual escaping. * that uses the provided value. See * {@link ng.$sce $sce} for enabling strict contextual
* escaping.
* *
* @param {string} type The kind of context in which this value is safe for use. e.g. url, * @param {string} type The kind of context in which this value is safe for use. e.g. url,
* resource_url, html, js and css. * resource_url, html, js and css.
@ -819,7 +828,8 @@ function $SceProvider() {
* @methodOf ng.$sce * @methodOf ng.$sce
* *
* @description * @description
* Shorthand method. `$sce.trustAsHtml(value)` {@link ng.$sceDelegate#methods_trustAs `$sceDelegate.trustAs($sce.HTML, value)`} * Shorthand method. `$sce.trustAsHtml(value)`
* {@link ng.$sceDelegate#methods_trustAs `$sceDelegate.trustAs($sce.HTML, value)`}
* *
* @param {*} value The value to trustAs. * @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#methods_getTrustedHtml
@ -834,7 +844,8 @@ function $SceProvider() {
* @methodOf ng.$sce * @methodOf ng.$sce
* *
* @description * @description
* Shorthand method. `$sce.trustAsUrl(value)` {@link ng.$sceDelegate#methods_trustAs `$sceDelegate.trustAs($sce.URL, value)`} * Shorthand method. `$sce.trustAsUrl(value)`
* {@link ng.$sceDelegate#methods_trustAs `$sceDelegate.trustAs($sce.URL, value)`}
* *
* @param {*} value The value to trustAs. * @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#methods_getTrustedUrl
@ -849,7 +860,8 @@ function $SceProvider() {
* @methodOf ng.$sce * @methodOf ng.$sce
* *
* @description * @description
* Shorthand method. `$sce.trustAsResourceUrl(value)` {@link ng.$sceDelegate#methods_trustAs `$sceDelegate.trustAs($sce.RESOURCE_URL, value)`} * Shorthand method. `$sce.trustAsResourceUrl(value)`
* {@link ng.$sceDelegate#methods_trustAs `$sceDelegate.trustAs($sce.RESOURCE_URL, value)`}
* *
* @param {*} value The value to trustAs. * @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#methods_getTrustedResourceUrl
@ -864,7 +876,8 @@ function $SceProvider() {
* @methodOf ng.$sce * @methodOf ng.$sce
* *
* @description * @description
* Shorthand method. `$sce.trustAsJs(value)` {@link ng.$sceDelegate#methods_trustAs `$sceDelegate.trustAs($sce.JS, value)`} * Shorthand method. `$sce.trustAsJs(value)`
* {@link ng.$sceDelegate#methods_trustAs `$sceDelegate.trustAs($sce.JS, value)`}
* *
* @param {*} value The value to trustAs. * @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#methods_getTrustedJs
@ -879,15 +892,17 @@ function $SceProvider() {
* @methodOf ng.$sce * @methodOf ng.$sce
* *
* @description * @description
* Delegates to {@link ng.$sceDelegate#methods_getTrusted `$sceDelegate.getTrusted`}. As such, takes * Delegates to {@link ng.$sceDelegate#methods_getTrusted `$sceDelegate.getTrusted`}. As such,
* the result of a {@link ng.$sce#methods_trustAs `$sce.trustAs`}() call and returns the originally supplied * takes the result of a {@link ng.$sce#methods_trustAs `$sce.trustAs`}() call and returns the
* value if the queried context type is a supertype of the created type. If this condition * originally supplied value if the queried context type is a supertype of the created type.
* isn't satisfied, throws an exception. * 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 {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`} call. * @param {*} maybeTrusted The result of a prior {@link ng.$sce#methods_trustAs `$sce.trustAs`}
* @returns {*} The value the was originally provided to {@link ng.$sce#methods_trustAs `$sce.trustAs`} if * call.
* valid in this context. Otherwise, throws an exception. * @returns {*} The value the was originally provided to
* {@link ng.$sce#methods_trustAs `$sce.trustAs`} if valid in this context.
* Otherwise, throws an exception.
*/ */
/** /**
@ -896,7 +911,8 @@ function $SceProvider() {
* @methodOf ng.$sce * @methodOf ng.$sce
* *
* @description * @description
* Shorthand method. `$sce.getTrustedHtml(value)` {@link ng.$sceDelegate#methods_getTrusted `$sceDelegate.getTrusted($sce.HTML, value)`} * Shorthand method. `$sce.getTrustedHtml(value)`
* {@link ng.$sceDelegate#methods_getTrusted `$sceDelegate.getTrusted($sce.HTML, value)`}
* *
* @param {*} value The value to pass to `$sce.getTrusted`. * @param {*} value The value to pass to `$sce.getTrusted`.
* @returns {*} The return value of `$sce.getTrusted($sce.HTML, value)` * @returns {*} The return value of `$sce.getTrusted($sce.HTML, value)`
@ -908,7 +924,8 @@ function $SceProvider() {
* @methodOf ng.$sce * @methodOf ng.$sce
* *
* @description * @description
* Shorthand method. `$sce.getTrustedCss(value)` {@link ng.$sceDelegate#methods_getTrusted `$sceDelegate.getTrusted($sce.CSS, value)`} * Shorthand method. `$sce.getTrustedCss(value)`
* {@link ng.$sceDelegate#methods_getTrusted `$sceDelegate.getTrusted($sce.CSS, value)`}
* *
* @param {*} value The value to pass to `$sce.getTrusted`. * @param {*} value The value to pass to `$sce.getTrusted`.
* @returns {*} The return value of `$sce.getTrusted($sce.CSS, value)` * @returns {*} The return value of `$sce.getTrusted($sce.CSS, value)`
@ -920,7 +937,8 @@ function $SceProvider() {
* @methodOf ng.$sce * @methodOf ng.$sce
* *
* @description * @description
* Shorthand method. `$sce.getTrustedUrl(value)` {@link ng.$sceDelegate#methods_getTrusted `$sceDelegate.getTrusted($sce.URL, value)`} * Shorthand method. `$sce.getTrustedUrl(value)`
* {@link ng.$sceDelegate#methods_getTrusted `$sceDelegate.getTrusted($sce.URL, value)`}
* *
* @param {*} value The value to pass to `$sce.getTrusted`. * @param {*} value The value to pass to `$sce.getTrusted`.
* @returns {*} The return value of `$sce.getTrusted($sce.URL, value)` * @returns {*} The return value of `$sce.getTrusted($sce.URL, value)`
@ -932,7 +950,8 @@ function $SceProvider() {
* @methodOf ng.$sce * @methodOf ng.$sce
* *
* @description * @description
* Shorthand method. `$sce.getTrustedResourceUrl(value)` {@link ng.$sceDelegate#methods_getTrusted `$sceDelegate.getTrusted($sce.RESOURCE_URL, value)`} * Shorthand method. `$sce.getTrustedResourceUrl(value)`
* {@link ng.$sceDelegate#methods_getTrusted `$sceDelegate.getTrusted($sce.RESOURCE_URL, value)`}
* *
* @param {*} value The value to pass to `$sceDelegate.getTrusted`. * @param {*} value The value to pass to `$sceDelegate.getTrusted`.
* @returns {*} The return value of `$sce.getTrusted($sce.RESOURCE_URL, value)` * @returns {*} The return value of `$sce.getTrusted($sce.RESOURCE_URL, value)`
@ -944,7 +963,8 @@ function $SceProvider() {
* @methodOf ng.$sce * @methodOf ng.$sce
* *
* @description * @description
* Shorthand method. `$sce.getTrustedJs(value)` {@link ng.$sceDelegate#methods_getTrusted `$sceDelegate.getTrusted($sce.JS, value)`} * Shorthand method. `$sce.getTrustedJs(value)`
* {@link ng.$sceDelegate#methods_getTrusted `$sceDelegate.getTrusted($sce.JS, value)`}
* *
* @param {*} value The value to pass to `$sce.getTrusted`. * @param {*} value The value to pass to `$sce.getTrusted`.
* @returns {*} The return value of `$sce.getTrusted($sce.JS, value)` * @returns {*} The return value of `$sce.getTrusted($sce.JS, value)`
@ -956,7 +976,8 @@ function $SceProvider() {
* @methodOf ng.$sce * @methodOf ng.$sce
* *
* @description * @description
* Shorthand method. `$sce.parseAsHtml(expression string)` {@link ng.$sce#methods_parse `$sce.parseAs($sce.HTML, value)`} * Shorthand method. `$sce.parseAsHtml(expression string)`
* {@link ng.$sce#methods_parse `$sce.parseAs($sce.HTML, value)`}
* *
* @param {string} expression String expression to compile. * @param {string} expression String expression to compile.
* @returns {function(context, locals)} a function which represents the compiled expression: * @returns {function(context, locals)} a function which represents the compiled expression:
@ -973,7 +994,8 @@ function $SceProvider() {
* @methodOf ng.$sce * @methodOf ng.$sce
* *
* @description * @description
* Shorthand method. `$sce.parseAsCss(value)` {@link ng.$sce#methods_parse `$sce.parseAs($sce.CSS, value)`} * Shorthand method. `$sce.parseAsCss(value)`
* {@link ng.$sce#methods_parse `$sce.parseAs($sce.CSS, value)`}
* *
* @param {string} expression String expression to compile. * @param {string} expression String expression to compile.
* @returns {function(context, locals)} a function which represents the compiled expression: * @returns {function(context, locals)} a function which represents the compiled expression:
@ -990,7 +1012,8 @@ function $SceProvider() {
* @methodOf ng.$sce * @methodOf ng.$sce
* *
* @description * @description
* Shorthand method. `$sce.parseAsUrl(value)` {@link ng.$sce#methods_parse `$sce.parseAs($sce.URL, value)`} * Shorthand method. `$sce.parseAsUrl(value)`
* {@link ng.$sce#methods_parse `$sce.parseAs($sce.URL, value)`}
* *
* @param {string} expression String expression to compile. * @param {string} expression String expression to compile.
* @returns {function(context, locals)} a function which represents the compiled expression: * @returns {function(context, locals)} a function which represents the compiled expression:
@ -1007,7 +1030,8 @@ function $SceProvider() {
* @methodOf ng.$sce * @methodOf ng.$sce
* *
* @description * @description
* Shorthand method. `$sce.parseAsResourceUrl(value)` {@link ng.$sce#methods_parse `$sce.parseAs($sce.RESOURCE_URL, value)`} * Shorthand method. `$sce.parseAsResourceUrl(value)`
* {@link ng.$sce#methods_parse `$sce.parseAs($sce.RESOURCE_URL, value)`}
* *
* @param {string} expression String expression to compile. * @param {string} expression String expression to compile.
* @returns {function(context, locals)} a function which represents the compiled expression: * @returns {function(context, locals)} a function which represents the compiled expression:
@ -1024,7 +1048,8 @@ function $SceProvider() {
* @methodOf ng.$sce * @methodOf ng.$sce
* *
* @description * @description
* Shorthand method. `$sce.parseAsJs(value)` {@link ng.$sce#methods_parse `$sce.parseAs($sce.JS, value)`} * Shorthand method. `$sce.parseAsJs(value)`
* {@link ng.$sce#methods_parse `$sce.parseAs($sce.JS, value)`}
* *
* @param {string} expression String expression to compile. * @param {string} expression String expression to compile.
* @returns {function(context, locals)} a function which represents the compiled expression: * @returns {function(context, locals)} a function which represents the compiled expression:
@ -1044,13 +1069,13 @@ function $SceProvider() {
var lName = lowercase(name); var lName = lowercase(name);
sce[camelCase("parse_as_" + lName)] = function (expr) { sce[camelCase("parse_as_" + lName)] = function (expr) {
return parse(enumValue, expr); return parse(enumValue, expr);
} };
sce[camelCase("get_trusted_" + lName)] = function (value) { sce[camelCase("get_trusted_" + lName)] = function (value) {
return getTrusted(enumValue, value); return getTrusted(enumValue, value);
} };
sce[camelCase("trust_as_" + lName)] = function (value) { sce[camelCase("trust_as_" + lName)] = function (value) {
return trustAs(enumValue, value); return trustAs(enumValue, value);
} };
}); });
return sce; return sce;

View file

@ -18,7 +18,8 @@
function $SnifferProvider() { function $SnifferProvider() {
this.$get = ['$window', '$document', function($window, $document) { this.$get = ['$window', '$document', function($window, $document) {
var eventSupport = {}, var eventSupport = {},
android = int((/android (\d+)/.exec(lowercase(($window.navigator || {}).userAgent)) || [])[1]), android =
int((/android (\d+)/.exec(lowercase(($window.navigator || {}).userAgent)) || [])[1]),
boxee = /Boxee/i.test(($window.navigator || {}).userAgent), boxee = /Boxee/i.test(($window.navigator || {}).userAgent),
document = $document[0] || {}, document = $document[0] || {},
vendorPrefix, vendorPrefix,
@ -59,7 +60,10 @@ function $SnifferProvider() {
// older webit browser (533.9) on Boxee box has exactly the same problem as Android has // older webit browser (533.9) on Boxee box has exactly the same problem as Android has
// so let's not use the history API also // 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
history: !!($window.history && $window.history.pushState && !(android < 4) && !boxee), history: !!($window.history && $window.history.pushState && !(android < 4) && !boxee),
// jshint +W018
hashchange: 'onhashchange' in $window && hashchange: 'onhashchange' in $window &&
// IE8 compatible mode lies // IE8 compatible mode lies
(!document.documentMode || document.documentMode > 7), (!document.documentMode || document.documentMode > 7),

View file

@ -81,7 +81,8 @@ function urlResolve(url) {
hash: urlParsingNode.hash ? urlParsingNode.hash.replace(/^#/, '') : '', hash: urlParsingNode.hash ? urlParsingNode.hash.replace(/^#/, '') : '',
hostname: urlParsingNode.hostname, hostname: urlParsingNode.hostname,
port: urlParsingNode.port, port: urlParsingNode.port,
pathname: urlParsingNode.pathname && urlParsingNode.pathname.charAt(0) === '/' ? urlParsingNode.pathname : '/' + urlParsingNode.pathname pathname: urlParsingNode.pathname && urlParsingNode.pathname.charAt(0) === '/' ?
urlParsingNode.pathname : '/' + urlParsingNode.pathname
}; };
} }

View file

@ -1,3 +1,6 @@
'use strict';
/* jshint maxlen: false */
/** /**
* @ngdoc overview * @ngdoc overview
* @name ngAnimate * @name ngAnimate
@ -474,7 +477,7 @@ angular.module('ngAnimate', ['ng'])
break; break;
default: default:
value = !rootAnimateState.running value = !rootAnimateState.running;
break; break;
} }
return !!value; return !!value;
@ -505,7 +508,7 @@ angular.module('ngAnimate', ['ng'])
//skip the animation if animations are disabled, a parent is already being animated //skip the animation if animations are disabled, a parent is already being animated
//or the element is not currently attached to the document body. //or the element is not currently attached to the document body.
if ((parent.inheritedData(NG_ANIMATE_STATE) || disabledAnimation).running || animations.length == 0) { if ((parent.inheritedData(NG_ANIMATE_STATE) || disabledAnimation).running || animations.length === 0) {
done(); done();
return; return;
} }
@ -686,7 +689,7 @@ angular.module('ngAnimate', ['ng'])
var aDuration = parseMaxTime(elementStyles[animationProp + durationKey]); var aDuration = parseMaxTime(elementStyles[animationProp + durationKey]);
if(aDuration > 0) { if(aDuration > 0) {
aDuration *= parseInt(elementStyles[animationProp + animationIterationCountKey]) || 1; aDuration *= parseInt(elementStyles[animationProp + animationIterationCountKey], 10) || 1;
} }
animationDuration = Math.max(aDuration, animationDuration); animationDuration = Math.max(aDuration, animationDuration);
@ -782,7 +785,7 @@ angular.module('ngAnimate', ['ng'])
if(cancelled) { if(cancelled) {
done(); done();
} }
} };
} }
else { else {
element.removeClass(className); element.removeClass(className);

View file

@ -75,7 +75,8 @@ angular.module('ngCookies', ['ng']).
/** /**
* Pushes all the cookies from the service to the browser and verifies if all cookies were stored. * Pushes all the cookies from the service to the browser and verifies if all cookies were
* stored.
*/ */
function push() { function push() {
var name, var name,

View file

@ -1,3 +1,4 @@
'use strict';
angular.module("ngLocale", [], ["$provide", function($provide) { angular.module("ngLocale", [], ["$provide", function($provide) {
var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"}; var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
$provide.value("$locale", { $provide.value("$locale", {

View file

@ -1,3 +1,4 @@
'use strict';
angular.module("ngLocale", [], ["$provide", function($provide) { angular.module("ngLocale", [], ["$provide", function($provide) {
var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"}; var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
$provide.value("$locale", { $provide.value("$locale", {

View file

@ -1,3 +1,4 @@
'use strict';
angular.module("ngLocale", [], ["$provide", function($provide) { angular.module("ngLocale", [], ["$provide", function($provide) {
var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"}; var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
$provide.value("$locale", { $provide.value("$locale", {

View file

@ -1,3 +1,4 @@
'use strict';
angular.module("ngLocale", [], ["$provide", function($provide) { angular.module("ngLocale", [], ["$provide", function($provide) {
var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"}; var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
$provide.value("$locale", { $provide.value("$locale", {

View file

@ -1,3 +1,4 @@
'use strict';
angular.module("ngLocale", [], ["$provide", function($provide) { angular.module("ngLocale", [], ["$provide", function($provide) {
var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"}; var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
$provide.value("$locale", { $provide.value("$locale", {

View file

@ -1,3 +1,4 @@
'use strict';
angular.module("ngLocale", [], ["$provide", function($provide) { angular.module("ngLocale", [], ["$provide", function($provide) {
var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"}; var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
$provide.value("$locale", { $provide.value("$locale", {

View file

@ -1,3 +1,4 @@
'use strict';
angular.module("ngLocale", [], ["$provide", function($provide) { angular.module("ngLocale", [], ["$provide", function($provide) {
var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"}; var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
$provide.value("$locale", { $provide.value("$locale", {

View file

@ -1,3 +1,4 @@
'use strict';
angular.module("ngLocale", [], ["$provide", function($provide) { angular.module("ngLocale", [], ["$provide", function($provide) {
var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"}; var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
$provide.value("$locale", { $provide.value("$locale", {

View file

@ -1,3 +1,4 @@
'use strict';
angular.module("ngLocale", [], ["$provide", function($provide) { angular.module("ngLocale", [], ["$provide", function($provide) {
var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"}; var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
$provide.value("$locale", { $provide.value("$locale", {

View file

@ -1,3 +1,4 @@
'use strict';
angular.module("ngLocale", [], ["$provide", function($provide) { angular.module("ngLocale", [], ["$provide", function($provide) {
var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"}; var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
$provide.value("$locale", { $provide.value("$locale", {

View file

@ -1,3 +1,4 @@
'use strict';
angular.module("ngLocale", [], ["$provide", function($provide) { angular.module("ngLocale", [], ["$provide", function($provide) {
var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"}; var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
$provide.value("$locale", { $provide.value("$locale", {

View file

@ -1,3 +1,4 @@
'use strict';
angular.module("ngLocale", [], ["$provide", function($provide) { angular.module("ngLocale", [], ["$provide", function($provide) {
var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"}; var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
$provide.value("$locale", { $provide.value("$locale", {

View file

@ -1,3 +1,4 @@
'use strict';
angular.module("ngLocale", [], ["$provide", function($provide) { angular.module("ngLocale", [], ["$provide", function($provide) {
var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"}; var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
$provide.value("$locale", { $provide.value("$locale", {

View file

@ -1,3 +1,4 @@
'use strict';
angular.module("ngLocale", [], ["$provide", function($provide) { angular.module("ngLocale", [], ["$provide", function($provide) {
var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"}; var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
$provide.value("$locale", { $provide.value("$locale", {

View file

@ -1,3 +1,4 @@
'use strict';
angular.module("ngLocale", [], ["$provide", function($provide) { angular.module("ngLocale", [], ["$provide", function($provide) {
var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"}; var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
$provide.value("$locale", { $provide.value("$locale", {

View file

@ -1,3 +1,4 @@
'use strict';
angular.module("ngLocale", [], ["$provide", function($provide) { angular.module("ngLocale", [], ["$provide", function($provide) {
var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"}; var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
$provide.value("$locale", { $provide.value("$locale", {

View file

@ -1,3 +1,4 @@
'use strict';
angular.module("ngLocale", [], ["$provide", function($provide) { angular.module("ngLocale", [], ["$provide", function($provide) {
var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"}; var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
$provide.value("$locale", { $provide.value("$locale", {

View file

@ -1,3 +1,4 @@
'use strict';
angular.module("ngLocale", [], ["$provide", function($provide) { angular.module("ngLocale", [], ["$provide", function($provide) {
var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"}; var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
$provide.value("$locale", { $provide.value("$locale", {

View file

@ -1,3 +1,4 @@
'use strict';
angular.module("ngLocale", [], ["$provide", function($provide) { angular.module("ngLocale", [], ["$provide", function($provide) {
var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"}; var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
$provide.value("$locale", { $provide.value("$locale", {

View file

@ -1,3 +1,4 @@
'use strict';
angular.module("ngLocale", [], ["$provide", function($provide) { angular.module("ngLocale", [], ["$provide", function($provide) {
var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"}; var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
$provide.value("$locale", { $provide.value("$locale", {

View file

@ -1,3 +1,4 @@
'use strict';
angular.module("ngLocale", [], ["$provide", function($provide) { angular.module("ngLocale", [], ["$provide", function($provide) {
var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"}; var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
$provide.value("$locale", { $provide.value("$locale", {

View file

@ -1,3 +1,4 @@
'use strict';
angular.module("ngLocale", [], ["$provide", function($provide) { angular.module("ngLocale", [], ["$provide", function($provide) {
var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"}; var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
$provide.value("$locale", { $provide.value("$locale", {

View file

@ -1,3 +1,4 @@
'use strict';
angular.module("ngLocale", [], ["$provide", function($provide) { angular.module("ngLocale", [], ["$provide", function($provide) {
var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"}; var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
$provide.value("$locale", { $provide.value("$locale", {

View file

@ -1,3 +1,4 @@
'use strict';
angular.module("ngLocale", [], ["$provide", function($provide) { angular.module("ngLocale", [], ["$provide", function($provide) {
var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"}; var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
$provide.value("$locale", { $provide.value("$locale", {

View file

@ -1,3 +1,4 @@
'use strict';
angular.module("ngLocale", [], ["$provide", function($provide) { angular.module("ngLocale", [], ["$provide", function($provide) {
var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"}; var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
$provide.value("$locale", { $provide.value("$locale", {

View file

@ -1,3 +1,4 @@
'use strict';
angular.module("ngLocale", [], ["$provide", function($provide) { angular.module("ngLocale", [], ["$provide", function($provide) {
var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"}; var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
$provide.value("$locale", { $provide.value("$locale", {

View file

@ -1,3 +1,4 @@
'use strict';
angular.module("ngLocale", [], ["$provide", function($provide) { angular.module("ngLocale", [], ["$provide", function($provide) {
var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"}; var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
$provide.value("$locale", { $provide.value("$locale", {

View file

@ -1,3 +1,4 @@
'use strict';
angular.module("ngLocale", [], ["$provide", function($provide) { angular.module("ngLocale", [], ["$provide", function($provide) {
var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"}; var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
$provide.value("$locale", { $provide.value("$locale", {

View file

@ -1,3 +1,4 @@
'use strict';
angular.module("ngLocale", [], ["$provide", function($provide) { angular.module("ngLocale", [], ["$provide", function($provide) {
var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"}; var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
$provide.value("$locale", { $provide.value("$locale", {

View file

@ -1,3 +1,4 @@
'use strict';
angular.module("ngLocale", [], ["$provide", function($provide) { angular.module("ngLocale", [], ["$provide", function($provide) {
var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"}; var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
$provide.value("$locale", { $provide.value("$locale", {

View file

@ -1,3 +1,4 @@
'use strict';
angular.module("ngLocale", [], ["$provide", function($provide) { angular.module("ngLocale", [], ["$provide", function($provide) {
var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"}; var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
$provide.value("$locale", { $provide.value("$locale", {

View file

@ -1,3 +1,4 @@
'use strict';
angular.module("ngLocale", [], ["$provide", function($provide) { angular.module("ngLocale", [], ["$provide", function($provide) {
var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"}; var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
$provide.value("$locale", { $provide.value("$locale", {

View file

@ -1,3 +1,4 @@
'use strict';
angular.module("ngLocale", [], ["$provide", function($provide) { angular.module("ngLocale", [], ["$provide", function($provide) {
var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"}; var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
$provide.value("$locale", { $provide.value("$locale", {

View file

@ -1,3 +1,4 @@
'use strict';
angular.module("ngLocale", [], ["$provide", function($provide) { angular.module("ngLocale", [], ["$provide", function($provide) {
var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"}; var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
$provide.value("$locale", { $provide.value("$locale", {

View file

@ -1,3 +1,4 @@
'use strict';
angular.module("ngLocale", [], ["$provide", function($provide) { angular.module("ngLocale", [], ["$provide", function($provide) {
var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"}; var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
$provide.value("$locale", { $provide.value("$locale", {

View file

@ -1,3 +1,4 @@
'use strict';
angular.module("ngLocale", [], ["$provide", function($provide) { angular.module("ngLocale", [], ["$provide", function($provide) {
var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"}; var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
$provide.value("$locale", { $provide.value("$locale", {

View file

@ -1,3 +1,4 @@
'use strict';
angular.module("ngLocale", [], ["$provide", function($provide) { angular.module("ngLocale", [], ["$provide", function($provide) {
var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"}; var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
$provide.value("$locale", { $provide.value("$locale", {

View file

@ -1,3 +1,4 @@
'use strict';
angular.module("ngLocale", [], ["$provide", function($provide) { angular.module("ngLocale", [], ["$provide", function($provide) {
var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"}; var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
$provide.value("$locale", { $provide.value("$locale", {

View file

@ -1,3 +1,4 @@
'use strict';
angular.module("ngLocale", [], ["$provide", function($provide) { angular.module("ngLocale", [], ["$provide", function($provide) {
var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"}; var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
$provide.value("$locale", { $provide.value("$locale", {

View file

@ -1,3 +1,4 @@
'use strict';
angular.module("ngLocale", [], ["$provide", function($provide) { angular.module("ngLocale", [], ["$provide", function($provide) {
var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"}; var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
$provide.value("$locale", { $provide.value("$locale", {

View file

@ -1,3 +1,4 @@
'use strict';
angular.module("ngLocale", [], ["$provide", function($provide) { angular.module("ngLocale", [], ["$provide", function($provide) {
var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"}; var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
$provide.value("$locale", { $provide.value("$locale", {

View file

@ -1,3 +1,4 @@
'use strict';
angular.module("ngLocale", [], ["$provide", function($provide) { angular.module("ngLocale", [], ["$provide", function($provide) {
var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"}; var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
$provide.value("$locale", { $provide.value("$locale", {

View file

@ -1,3 +1,4 @@
'use strict';
angular.module("ngLocale", [], ["$provide", function($provide) { angular.module("ngLocale", [], ["$provide", function($provide) {
var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"}; var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
$provide.value("$locale", { $provide.value("$locale", {

View file

@ -1,3 +1,4 @@
'use strict';
angular.module("ngLocale", [], ["$provide", function($provide) { angular.module("ngLocale", [], ["$provide", function($provide) {
var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"}; var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
$provide.value("$locale", { $provide.value("$locale", {

View file

@ -1,3 +1,4 @@
'use strict';
angular.module("ngLocale", [], ["$provide", function($provide) { angular.module("ngLocale", [], ["$provide", function($provide) {
var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"}; var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
$provide.value("$locale", { $provide.value("$locale", {

View file

@ -1,3 +1,4 @@
'use strict';
angular.module("ngLocale", [], ["$provide", function($provide) { angular.module("ngLocale", [], ["$provide", function($provide) {
var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"}; var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
$provide.value("$locale", { $provide.value("$locale", {

View file

@ -1,3 +1,4 @@
'use strict';
angular.module("ngLocale", [], ["$provide", function($provide) { angular.module("ngLocale", [], ["$provide", function($provide) {
var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"}; var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
$provide.value("$locale", { $provide.value("$locale", {

View file

@ -1,3 +1,4 @@
'use strict';
angular.module("ngLocale", [], ["$provide", function($provide) { angular.module("ngLocale", [], ["$provide", function($provide) {
var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"}; var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
$provide.value("$locale", { $provide.value("$locale", {

View file

@ -1,3 +1,4 @@
'use strict';
angular.module("ngLocale", [], ["$provide", function($provide) { angular.module("ngLocale", [], ["$provide", function($provide) {
var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"}; var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
$provide.value("$locale", { $provide.value("$locale", {

View file

@ -1,3 +1,4 @@
'use strict';
angular.module("ngLocale", [], ["$provide", function($provide) { angular.module("ngLocale", [], ["$provide", function($provide) {
var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"}; var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
$provide.value("$locale", { $provide.value("$locale", {

View file

@ -1,3 +1,4 @@
'use strict';
angular.module("ngLocale", [], ["$provide", function($provide) { angular.module("ngLocale", [], ["$provide", function($provide) {
var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"}; var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
$provide.value("$locale", { $provide.value("$locale", {

View file

@ -1,3 +1,4 @@
'use strict';
angular.module("ngLocale", [], ["$provide", function($provide) { angular.module("ngLocale", [], ["$provide", function($provide) {
var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"}; var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
$provide.value("$locale", { $provide.value("$locale", {

View file

@ -1,3 +1,4 @@
'use strict';
angular.module("ngLocale", [], ["$provide", function($provide) { angular.module("ngLocale", [], ["$provide", function($provide) {
var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"}; var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
$provide.value("$locale", { $provide.value("$locale", {

View file

@ -1,3 +1,4 @@
'use strict';
angular.module("ngLocale", [], ["$provide", function($provide) { angular.module("ngLocale", [], ["$provide", function($provide) {
var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"}; var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
$provide.value("$locale", { $provide.value("$locale", {

View file

@ -1,3 +1,4 @@
'use strict';
angular.module("ngLocale", [], ["$provide", function($provide) { angular.module("ngLocale", [], ["$provide", function($provide) {
var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"}; var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
$provide.value("$locale", { $provide.value("$locale", {

View file

@ -1,3 +1,4 @@
'use strict';
angular.module("ngLocale", [], ["$provide", function($provide) { angular.module("ngLocale", [], ["$provide", function($provide) {
var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"}; var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
$provide.value("$locale", { $provide.value("$locale", {

View file

@ -1,3 +1,4 @@
'use strict';
angular.module("ngLocale", [], ["$provide", function($provide) { angular.module("ngLocale", [], ["$provide", function($provide) {
var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"}; var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
$provide.value("$locale", { $provide.value("$locale", {

Some files were not shown because too many files have changed in this diff Show more