template_app/vendor/assets/javascripts/angular.js in deano-1.2.0 vs template_app/vendor/assets/javascripts/angular.js in deano-1.2.1
- old
+ new
@@ -1,7 +1,7 @@
/**
- * @license AngularJS v1.0.5
+ * @license AngularJS v1.0.7
* (c) 2010-2012 Google, Inc. http://angularjs.org
* License: MIT
*/
(function(window, document, undefined) {
'use strict';
@@ -32,16 +32,16 @@
var uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};
var manualLowercase = function(s) {
return isString(s)
- ? s.replace(/[A-Z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) | 32);})
+ ? s.replace(/[A-Z]/g, function(ch) {return String.fromCharCode(ch.charCodeAt(0) | 32);})
: s;
};
var manualUppercase = function(s) {
return isString(s)
- ? s.replace(/[a-z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) & ~32);})
+ ? s.replace(/[a-z]/g, function(ch) {return String.fromCharCode(ch.charCodeAt(0) & ~32);})
: s;
};
// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish
@@ -50,13 +50,11 @@
if ('i' !== 'I'.toLowerCase()) {
lowercase = manualLowercase;
uppercase = manualUppercase;
}
-function fromCharCode(code) {return String.fromCharCode(code);}
-
var /** holds major version number for IE or NaN for real browsers */
msie = int((/msie (\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]),
jqLite, // delay binding since jQuery could be loaded after us.
jQuery, // delay binding
slice = [].slice,
@@ -67,11 +65,34 @@
angular = window.angular || (window.angular = {}),
angularModule,
nodeName_,
uid = ['0', '0', '0'];
+
/**
+ * @private
+ * @param {*} obj
+ * @return {boolean} Returns true if `obj` is an array or array-like object (NodeList, Arguments, ...)
+ */
+function isArrayLike(obj) {
+ if (!obj || (typeof obj.length !== 'number')) return false;
+
+ // We have on object which has length property. Should we treat it as array?
+ if (typeof obj.hasOwnProperty != 'function' &&
+ typeof obj.constructor != 'function') {
+ // This is here for IE8: it is a bogus object treat it as array;
+ return true;
+ } else {
+ return obj instanceof JQLite || // JQLite
+ (jQuery && obj instanceof jQuery) || // jQuery
+ toString.call(obj) !== '[object Object]' || // some browser native object
+ typeof obj.callee === 'function'; // arguments (on IE8 looks like regular obj)
+ }
+}
+
+
+/**
* @ngdoc function
* @name angular.forEach
* @function
*
* @description
@@ -94,34 +115,10 @@
* @param {Object|Array} obj Object to iterate over.
* @param {Function} iterator Iterator function.
* @param {Object=} context Object to become context (`this`) for the iterator function.
* @returns {Object|Array} Reference to `obj`.
*/
-
-
-/**
- * @private
- * @param {*} obj
- * @return {boolean} Returns true if `obj` is an array or array-like object (NodeList, Arguments, ...)
- */
-function isArrayLike(obj) {
- if (!obj || (typeof obj.length !== 'number')) return false;
-
- // We have on object which has length property. Should we treat it as array?
- if (typeof obj.hasOwnProperty != 'function' &&
- typeof obj.constructor != 'function') {
- // This is here for IE8: it is a bogus object treat it as array;
- return true;
- } else {
- return obj instanceof JQLite || // JQLite
- (jQuery && obj instanceof jQuery) || // jQuery
- toString.call(obj) !== '[object Object]' || // some browser native object
- typeof obj.callee === 'function'; // arguments (on IE8 looks like regular obj)
- }
-}
-
-
function forEach(obj, iterator, context) {
var key;
if (obj) {
if (isFunction(obj)){
for (key in obj) {
@@ -201,30 +198,49 @@
}
uid.unshift('0');
return uid.join('');
}
+
/**
+ * Set or clear the hashkey for an object.
+ * @param obj object
+ * @param h the hashkey (!truthy to delete the hashkey)
+ */
+function setHashKey(obj, h) {
+ if (h) {
+ obj.$$hashKey = h;
+ }
+ else {
+ delete obj.$$hashKey;
+ }
+}
+
+/**
* @ngdoc function
* @name angular.extend
* @function
*
* @description
* Extends the destination object `dst` by copying all of the properties from the `src` object(s)
* to `dst`. You can specify multiple `src` objects.
*
* @param {Object} dst Destination object.
* @param {...Object} src Source object(s).
+ * @returns {Object} Reference to `dst`.
*/
function extend(dst) {
+ var h = dst.$$hashKey;
forEach(arguments, function(obj){
if (obj !== dst) {
forEach(obj, function(value, key){
dst[key] = value;
});
}
});
+
+ setHashKey(dst,h);
return dst;
}
function int(str) {
return parseInt(str, 10);
@@ -575,16 +591,18 @@
destination.length = 0;
for ( var i = 0; i < source.length; i++) {
destination.push(copy(source[i]));
}
} else {
+ var h = destination.$$hashKey;
forEach(destination, function(value, key){
delete destination[key];
});
for ( var key in source) {
destination[key] = copy(source[key]);
}
+ setHashKey(destination,h);
}
}
return destination;
}
@@ -620,11 +638,11 @@
* * Both values are NaN. (In JavasScript, NaN == NaN => false. But we consider two NaN as equal)
*
* During a property comparision, properties of `function` type and properties with names
* that begin with `$` are ignored.
*
- * Scope and DOMWindow objects are being compared only be identify (`===`).
+ * Scope and DOMWindow objects are being compared only by identify (`===`).
*
* @param {*} o1 Object or value to compare.
* @param {*} o2 Object or value to compare.
* @returns {boolean} True if arguments are equal.
*/
@@ -680,11 +698,11 @@
* @name angular.bind
* @function
*
* @description
* Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for
- * `fn`). You can supply optional `args` that are 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 [function currying](http://en.wikipedia.org/wiki/Currying).
*
* @param {Object} self Context which `fn` should be evaluated in.
* @param {function()} fn Function to be bound.
* @param {...*} args Optional arguments to be prebound to the `fn` function call.
@@ -859,11 +877,11 @@
return encodeURIComponent(val).
replace(/%40/gi, '@').
replace(/%3A/gi, ':').
replace(/%24/g, '$').
replace(/%2C/gi, ',').
- replace((pctEncodeSpaces ? null : /%20/g), '+');
+ replace(/%20/g, (pctEncodeSpaces ? '%20' : '+'));
}
/**
* @ngdoc directive
@@ -873,11 +891,11 @@
* @param {angular.Module} ngApp an optional application
* {@link angular.module module} name to load.
*
* @description
*
- * Use this directive to auto-bootstrap on application. Only
+ * Use this directive to auto-bootstrap an application. Only
* one directive can be used per HTML document. The directive
* designates the root of the application and is typically placed
* at the root of the page.
*
* In the example below if the `ngApp` directive would not be placed
@@ -948,26 +966,42 @@
* @param {Element} element DOM element which is the root of angular application.
* @param {Array<String|Function>=} modules an array of module declarations. See: {@link angular.module modules}
* @returns {AUTO.$injector} Returns the newly created injector for this app.
*/
function bootstrap(element, modules) {
- element = jqLite(element);
- modules = modules || [];
- modules.unshift(['$provide', function($provide) {
- $provide.value('$rootElement', element);
- }]);
- modules.unshift('ng');
- var injector = createInjector(modules);
- injector.invoke(
- ['$rootScope', '$rootElement', '$compile', '$injector', function(scope, element, compile, injector){
- scope.$apply(function() {
- element.data('$injector', injector);
- compile(element)(scope);
- });
- }]
- );
- return injector;
+ var resumeBootstrapInternal = function() {
+ element = jqLite(element);
+ modules = modules || [];
+ modules.unshift(['$provide', function($provide) {
+ $provide.value('$rootElement', element);
+ }]);
+ modules.unshift('ng');
+ var injector = createInjector(modules);
+ injector.invoke(['$rootScope', '$rootElement', '$compile', '$injector',
+ function(scope, element, compile, injector) {
+ scope.$apply(function() {
+ element.data('$injector', injector);
+ compile(element)(scope);
+ });
+ }]
+ );
+ return injector;
+ };
+
+ var NG_DEFER_BOOTSTRAP = /^NG_DEFER_BOOTSTRAP!/;
+
+ if (window && !NG_DEFER_BOOTSTRAP.test(window.name)) {
+ return resumeBootstrapInternal();
+ }
+
+ window.name = window.name.replace(NG_DEFER_BOOTSTRAP, '');
+ angular.resumeBootstrap = function(extraModules) {
+ forEach(extraModules, function(module) {
+ modules.push(module);
+ });
+ resumeBootstrapInternal();
+ };
}
var SNAKE_CASE_REGEXP = /[A-Z]/g;
function snake_case(name, separator){
separator = separator || '_';
@@ -996,11 +1030,11 @@
}
angular.element = jqLite;
}
/**
- * throw error of the argument is falsy.
+ * throw error if the argument is falsy.
*/
function assertArg(arg, name, reason) {
if (!arg) {
throw new Error("Argument '" + (name || '?') + "' is " + (reason || "required"));
}
@@ -1270,22 +1304,22 @@
* @name angular.version
* @description
* An object that contains information about the current AngularJS version. This object has the
* following properties:
*
- * - `full` – `{string}` – Full version string, such as "0.9.18".
- * - `major` – `{number}` – Major version number, such as "0".
- * - `minor` – `{number}` – Minor version number, such as "9".
- * - `dot` – `{number}` – Dot version number, such as "18".
- * - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat".
+ * - `full` – `{string}` – Full version string, such as "0.9.18".
+ * - `major` – `{number}` – Major version number, such as "0".
+ * - `minor` – `{number}` – Minor version number, such as "9".
+ * - `dot` – `{number}` – Dot version number, such as "18".
+ * - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat".
*/
var version = {
- full: '1.0.5', // all of these placeholder strings will be replaced by rake's
- major: 1, // compile task
+ full: '1.0.7', // all of these placeholder strings will be replaced by grunt's
+ major: 1, // package task
minor: 0,
- dot: 5,
- codeName: 'flatulent-propulsion'
+ dot: 7,
+ codeName: 'monochromatic-rainbow'
};
function publishExternalAPI(angular){
extend(angular, {
@@ -1426,22 +1460,22 @@
*
* - [addClass()](http://api.jquery.com/addClass/)
* - [after()](http://api.jquery.com/after/)
* - [append()](http://api.jquery.com/append/)
* - [attr()](http://api.jquery.com/attr/)
- * - [bind()](http://api.jquery.com/bind/)
- * - [children()](http://api.jquery.com/children/)
+ * - [bind()](http://api.jquery.com/bind/) - Does not support namespaces
+ * - [children()](http://api.jquery.com/children/) - Does not support selectors
* - [clone()](http://api.jquery.com/clone/)
* - [contents()](http://api.jquery.com/contents/)
* - [css()](http://api.jquery.com/css/)
* - [data()](http://api.jquery.com/data/)
* - [eq()](http://api.jquery.com/eq/)
- * - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name.
+ * - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name
* - [hasClass()](http://api.jquery.com/hasClass/)
* - [html()](http://api.jquery.com/html/)
- * - [next()](http://api.jquery.com/next/)
- * - [parent()](http://api.jquery.com/parent/)
+ * - [next()](http://api.jquery.com/next/) - Does not support selectors
+ * - [parent()](http://api.jquery.com/parent/) - Does not support selectors
* - [prepend()](http://api.jquery.com/prepend/)
* - [prop()](http://api.jquery.com/prop/)
* - [ready()](http://api.jquery.com/ready/)
* - [remove()](http://api.jquery.com/remove/)
* - [removeAttr()](http://api.jquery.com/removeAttr/)
@@ -1449,11 +1483,11 @@
* - [removeData()](http://api.jquery.com/removeData/)
* - [replaceWith()](http://api.jquery.com/replaceWith/)
* - [text()](http://api.jquery.com/text/)
* - [toggleClass()](http://api.jquery.com/toggleClass/)
* - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Doesn't pass native event objects to handlers.
- * - [unbind()](http://api.jquery.com/unbind/)
+ * - [unbind()](http://api.jquery.com/unbind/) - Does not support namespaces
* - [val()](http://api.jquery.com/val/)
* - [wrap()](http://api.jquery.com/wrap/)
*
* ## In addtion to the above, Angular provides additional methods to both jQuery and jQuery lite:
*
@@ -1996,27 +2030,47 @@
forEach(type.split(' '), function(type){
var eventFns = events[type];
if (!eventFns) {
if (type == 'mouseenter' || type == 'mouseleave') {
- var counter = 0;
+ var contains = document.body.contains || document.body.compareDocumentPosition ?
+ function( a, b ) {
+ var adown = a.nodeType === 9 ? a.documentElement : a,
+ bup = b && b.parentNode;
+ return a === bup || !!( bup && bup.nodeType === 1 && (
+ adown.contains ?
+ adown.contains( bup ) :
+ a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
+ ));
+ } :
+ function( a, b ) {
+ if ( b ) {
+ while ( (b = b.parentNode) ) {
+ if ( b === a ) {
+ return true;
+ }
+ }
+ }
+ return false;
+ };
- events.mouseenter = [];
- events.mouseleave = [];
+ events[type] = [];
- bindFn(element, 'mouseover', function(event) {
- counter++;
- if (counter == 1) {
- handle(event, 'mouseenter');
+ // Refer to jQuery's implementation of mouseenter & mouseleave
+ // Read about mouseenter and mouseleave:
+ // http://www.quirksmode.org/js/events_mouse.html#link8
+ var eventmap = { mouseleave : "mouseout", mouseenter : "mouseover"}
+ bindFn(element, eventmap[type], function(event) {
+ var ret, target = this, related = event.relatedTarget;
+ // For mousenter/leave call the handler if related is outside the target.
+ // NB: No relatedTarget if the mouse left/entered the browser window
+ if ( !related || (related !== target && !contains(target, related)) ){
+ handle(event, type);
}
+
});
- bindFn(element, 'mouseout', function(event) {
- counter --;
- if (counter == 0) {
- handle(event, 'mouseleave');
- }
- });
+
} else {
addEventListenerFn(element, type, handle);
events[type] = [];
}
eventFns = events[type]
@@ -2328,11 +2382,11 @@
});
fn.$inject = $inject;
}
} else if (isArray(fn)) {
last = fn.length - 1;
- assertArgFn(fn[last], 'fn')
+ assertArgFn(fn[last], 'fn');
$inject = fn.slice(0, last);
} else {
assertArgFn(fn, 'fn', true);
}
return $inject;
@@ -2362,23 +2416,23 @@
* </pre>
*
* # Injection Function Annotation
*
* JavaScript does not have annotations, and annotations are needed for dependency injection. The
- * following ways are all valid way of annotating function with injection arguments and are equivalent.
+ * following are all valid ways of annotating function with injection arguments and are equivalent.
*
* <pre>
* // inferred (only works if code not minified/obfuscated)
- * $inject.invoke(function(serviceA){});
+ * $injector.invoke(function(serviceA){});
*
* // annotated
* function explicit(serviceA) {};
* explicit.$inject = ['serviceA'];
- * $inject.invoke(explicit);
+ * $injector.invoke(explicit);
*
* // inline
- * $inject.invoke(['serviceA', function(serviceA){}]);
+ * $injector.invoke(['serviceA', function(serviceA){}]);
* </pre>
*
* ## Inference
*
* In JavaScript calling `toString()` on a function returns the function definition. The definition can then be
@@ -2491,11 +2545,11 @@
* // We are forced to write break inlining
* var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {
* // ...
* };
* tmpFn.$inject = ['$compile', '$rootScope'];
- * injector.invoke(tempFn);
+ * injector.invoke(tmpFn);
*
* // To better support inline function the inline annotation is supported
* injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {
* // ...
* }]);
@@ -2520,11 +2574,11 @@
* @name AUTO.$provide
*
* @description
*
* Use `$provide` to register new providers with the `$injector`. The providers are the factories for the instance.
- * The providers share the same name as the instance they create with the `Provider` suffixed to them.
+ * The providers share the same name as the instance they create with `Provider` suffixed to them.
*
* A provider is an object with a `$get()` method. The injector calls the `$get` method to create a new instance of
* a service. The Provider can have additional methods which would allow for configuration of the provider.
*
* <pre>
@@ -2544,11 +2598,11 @@
*
* describe('Greeter', function(){
*
* beforeEach(module(function($provide) {
* $provide.provider('greet', GreetProvider);
- * });
+ * }));
*
* it('should greet', inject(function(greet) {
* expect(greet('angular')).toEqual('Hello angular!');
* }));
*
@@ -2557,13 +2611,11 @@
* greetProvider.salutation('Ahoj');
* });
* inject(function(greet) {
* expect(greet('angular')).toEqual('Ahoj angular!');
* });
- * )};
- *
- * });
+ * });
* </pre>
*/
/**
* @ngdoc method
@@ -2653,11 +2705,11 @@
* returned instance may be the original instance, or a new instance which delegates to the
* original instance.
*
* @param {string} name The name of the service to decorate.
* @param {function()} decorator This function will be invoked when the service needs to be
- * instanciated. The function is called using the {@link AUTO.$injector#invoke
+ * instantiated. The function is called using the {@link AUTO.$injector#invoke
* injector.invoke} method and is therefore fully injectable. Local injection arguments:
*
* * `$delegate` - The original service instance, which can be monkey patched, configured,
* decorated or delegated to.
*/
@@ -2853,10 +2905,12 @@
function instantiate(Type, locals) {
var Constructor = function() {},
instance, returnedValue;
+ // Check if Type is annotated and use just the given function at n-1 as parameter
+ // e.g. someModule.factory('greeter', ['$window', function(renamed$window) {}]);
Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;
instance = new Constructor();
returnedValue = invoke(Type, instance, locals);
return isObject(returnedValue) ? returnedValue : instance;
@@ -2868,10 +2922,11 @@
get: getService,
annotate: annotate
};
}
}
+
/**
* @ngdoc function
* @name ng.$anchorScroll
* @requires $window
* @requires $location
@@ -3232,11 +3287,17 @@
for (i = 0; i < cookieArray.length; i++) {
cookie = cookieArray[i];
index = cookie.indexOf('=');
if (index > 0) { //ignore nameless cookies
- lastCookies[unescape(cookie.substring(0, index))] = unescape(cookie.substring(index + 1));
+ var name = unescape(cookie.substring(0, index));
+ // the first value that is seen for a cookie is the most
+ // specific one. values for the same cookie name that
+ // follow are for less specific paths.
+ if (lastCookies[name] === undefined) {
+ lastCookies[name] = unescape(cookie.substring(index + 1));
+ }
}
}
}
return lastCookies;
}
@@ -3296,10 +3357,11 @@
this.$get = ['$window', '$log', '$sniffer', '$document',
function( $window, $log, $sniffer, $document){
return new Browser($window, $document, $log, $sniffer);
}];
}
+
/**
* @ngdoc object
* @name ng.$cacheFactory
*
* @description
@@ -3307,20 +3369,20 @@
*
*
* @param {string} cacheId Name or id of the newly created cache.
* @param {object=} options Options object that specifies the cache behavior. Properties:
*
- * - `{number=}` `capacity` — turns the cache into LRU cache.
+ * - `{number=}` `capacity` — turns the cache into LRU cache.
*
* @returns {object} Newly created cache object with the following set of methods:
*
- * - `{object}` `info()` — Returns id, size, and options of cache.
- * - `{void}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache.
- * - `{{*}}` `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}` `removeAll()` — Removes all cached values.
- * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.
+ * - `{object}` `info()` — Returns id, size, and options of cache.
+ * - `{void}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache.
+ * - `{{*}}` `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}` `removeAll()` — Removes all cached values.
+ * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.
*
*/
function $CacheFactoryProvider() {
this.$get = function() {
@@ -3623,11 +3685,11 @@
var hasDirectives = {},
Suffix = 'Directive',
COMMENT_DIRECTIVE_REGEXP = /^\s*directive\:\s*([\d\w\-_]+)\s+(.*)$/,
CLASS_DIRECTIVE_REGEXP = /(([\d\w\-_]+)(?:\:([^;]+))?;?)/,
MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ',
- urlSanitizationWhitelist = /^\s*(https?|ftp|mailto):/;
+ urlSanitizationWhitelist = /^\s*(https?|ftp|mailto|file):/;
/**
* @ngdoc function
* @name ng.$compileProvider#directive
@@ -3825,11 +3887,11 @@
//================================
function compile($compileNodes, transcludeFn, maxPriority) {
if (!($compileNodes instanceof jqLite)) {
- // jquery always rewraps, where as 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);
}
// We can not compile top level text elements since text nodes can be merged and we will
// not be able to attach scope data to them, so we will wrap them in <span>
forEach($compileNodes, function(node, index){
@@ -3877,11 +3939,11 @@
* Compile function matches each node in nodeList against the directives. Once all directives
* for a particular node are collected their compile functions are executed. The compile
* functions return values - the linking functions - are combined into a composite linking
* function, which is the a linking function for the node.
*
- * @param {NodeList} nodeList an array of nodes to compile
+ * @param {NodeList} nodeList an array of nodes or NodeList to compile
* @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.
* @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then 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.
@@ -3900,11 +3962,11 @@
nodeLinkFn = (directives.length)
? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)
: null;
- childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes.length)
+ childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes || !nodeList[i].childNodes.length)
? null
: compileNodes(nodeList[i].childNodes,
nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);
linkFns.push(nodeLinkFn);
@@ -4036,25 +4098,25 @@
return directives;
}
/**
- * Once the directives have been collected their compile functions is executed. This method
+ * Once the directives have been collected, their compile functions are executed. This method
* is responsible for inlining directive templates as well as terminating the application
- * of the directives if the terminal directive has been reached..
+ * of the directives if the terminal directive has been reached.
*
* @param {Array} directives Array of collected directives to execute their compile function.
* this needs to be pre-sorted by priority order.
* @param {Node} compileNode The raw DOM node to apply the compile functions to
* @param {Object} templateAttrs The shared attribute function
* @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.
- * @param {DOMElement} $rootElement If we are working on the root of the compile tree then this
- * argument has the root jqLite array so that we can replace widgets on it.
+ * @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.
* @returns linkFn
*/
- function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, $rootElement) {
+ function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, jqCollection) {
var terminalPriority = -Number.MAX_VALUE,
preLinkFns = [],
postLinkFns = [],
newScopeDirective = null,
newIsolateScopeDirective = null,
@@ -4104,11 +4166,11 @@
if (directiveValue == 'element') {
$template = jqLite(compileNode);
$compileNode = templateAttrs.$$element =
jqLite(document.createComment(' ' + directiveName + ': ' + templateAttrs[directiveName] + ' '));
compileNode = $compileNode[0];
- replaceWith($rootElement, jqLite($template[0]), compileNode);
+ replaceWith(jqCollection, jqLite($template[0]), compileNode);
childTranscludeFn = compile($template, transcludeFn, terminalPriority);
} else {
$template = jqLite(JQLiteClone(compileNode)).contents();
$compileNode.html(''); // clear contents
childTranscludeFn = compile($template, transcludeFn);
@@ -4128,11 +4190,11 @@
if ($template.length != 1 || compileNode.nodeType !== 1) {
throw new Error(MULTI_ROOT_TEMPLATE_ERROR + directiveValue);
}
- replaceWith($rootElement, $compileNode, compileNode);
+ replaceWith(jqCollection, $compileNode, compileNode);
var newTemplateAttrs = {$attr: {}};
// combine directives from the original node and from the template:
// - take the array of directives for this element
@@ -4156,11 +4218,11 @@
if (directive.templateUrl) {
assertNoDuplicate('template', templateDirective, directive, $compileNode);
templateDirective = directive;
nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i),
- nodeLinkFn, $compileNode, templateAttrs, $rootElement, directive.replace,
+ nodeLinkFn, $compileNode, templateAttrs, jqCollection, directive.replace,
childTranscludeFn);
ii = directives.length;
} else if (directive.compile) {
try {
linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);
@@ -4289,11 +4351,11 @@
case '&': {
parentGet = $parse(attrs[attrName]);
scope[scopeName] = function(locals) {
return parentGet(parentScope, locals);
- }
+ };
break;
}
default: {
throw Error('Invalid isolate scope definition for directive ' +
@@ -4459,11 +4521,11 @@
$compileNode.html(content);
}
directives.unshift(derivedSyncDirective);
afterTemplateNodeLinkFn = applyDirectivesToNode(directives, compileNode, tAttrs, childTranscludeFn);
- afterTemplateChildLinkFn = compileNodes($compileNode.contents(), childTranscludeFn);
+ afterTemplateChildLinkFn = compileNodes($compileNode[0].childNodes, childTranscludeFn);
while(linkQueue.length) {
var controller = linkQueue.pop(),
linkRootElement = linkQueue.pop(),
@@ -4724,11 +4786,11 @@
* @return {Object} Instance of given controller.
*
* @description
* `$controller` service is responsible for instantiating controllers.
*
- * It's just simple call to {@link AUTO.$injector $injector}, but extracted into
+ * It's just a simple call to {@link AUTO.$injector $injector}, but extracted into
* a service, so that one can override this service with {@link https://gist.github.com/1649788
* BC version}.
*/
return function(constructor, locals) {
if(isString(constructor)) {
@@ -4777,11 +4839,11 @@
* @param {string=} cause optional information about the context in which
* the error was thrown.
*
*/
function $ExceptionHandlerProvider() {
- this.$get = ['$log', function($log){
+ this.$get = ['$log', function($log) {
return function(exception, cause) {
$log.error.apply($log, arguments);
};
}];
}
@@ -4965,11 +5027,11 @@
return $interpolate;
}];
}
-var URL_MATCH = /^([^:]+):\/\/(\w+:{0,1}\w*@)?([\w\.-]*)(:([0-9]+))?(\/[^\?#]*)?(\?([^#]*))?(#(.*))?$/,
+var URL_MATCH = /^([^:]+):\/\/(\w+:{0,1}\w*@)?(\{?[\w\.-]*\}?)(:([0-9]+))?(\/[^\?#]*)?(\?([^#]*))?(#(.*))?$/,
PATH_MATCH = /^([^\?#]*)?(\?([^#]*))?(#(.*))?$/,
HASH_MATCH = PATH_MATCH,
DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};
@@ -5044,11 +5106,12 @@
function convertToHashbangUrl(url, basePath, hashPrefix) {
var match = matchUrl(url);
// already hashbang url
- if (decodeURIComponent(match.path) == basePath) {
+ if (decodeURIComponent(match.path) == basePath && !isUndefined(match.hash) &&
+ match.hash.indexOf(hashPrefix) === 0) {
return url;
// convert html5 url -> hashbang url
} else {
var search = match.search && '?' + match.search || '',
hash = match.hash && '#' + match.hash || '',
@@ -5541,10 +5604,14 @@
}
// update $location when $browser url changes
$browser.onUrlChange(function(newUrl) {
if ($location.absUrl() != newUrl) {
+ if ($rootScope.$broadcast('$locationChangeStart', newUrl, $location.absUrl()).defaultPrevented) {
+ $browser.url($location.absUrl());
+ return;
+ }
$rootScope.$evalAsync(function() {
var oldUrl = $location.absUrl();
$location.$$parse(newUrl);
afterLocationChange(oldUrl);
@@ -5849,14 +5916,14 @@
fn:function() {return number;}});
}
function readIdent() {
var ident = "",
start = index,
- lastDot, peekIndex, methodName;
+ lastDot, peekIndex, methodName, ch;
while (index < text.length) {
- var ch = text.charAt(index);
+ ch = text.charAt(index);
if (ch == '.' || isIdent(ch) || isNumber(ch)) {
if (ch == '.') lastDot = index;
ident += ch;
} else {
break;
@@ -5866,11 +5933,11 @@
//check if this is not a method invocation and if it is back out to last dot
if (lastDot) {
peekIndex = index;
while(peekIndex < text.length) {
- var ch = text.charAt(peekIndex);
+ ch = text.charAt(peekIndex);
if (ch == '(') {
methodName = ident.substr(lastDot - start + 1);
ident = ident.substr(0, lastDot - start);
index = peekIndex;
break;
@@ -6119,12 +6186,12 @@
if (!left.assign) {
throwError("implies assignment but [" +
text.substring(0, token.index) + "] can not be assigned to", token);
}
right = logicalOR();
- return function(self, locals){
- return left.assign(self, right(self, locals), locals);
+ return function(scope, locals){
+ return left.assign(scope, right(scope, locals), locals);
};
} else {
return left;
}
}
@@ -6237,16 +6304,16 @@
function _fieldAccess(object) {
var field = expect().text;
var getter = getterFn(field, csp);
return extend(
- function(self, locals) {
- return getter(object(self, locals), locals);
+ function(scope, locals, self) {
+ return getter(self || object(scope, locals), locals);
},
{
- assign:function(self, value, locals) {
- return setter(object(self, locals), field, value);
+ assign:function(scope, value, locals) {
+ return setter(object(scope, locals), field, value);
}
}
);
}
@@ -6283,18 +6350,18 @@
do {
argsFn.push(expression());
} while (expect(','));
}
consume(')');
- return function(self, locals){
+ return function(scope, locals){
var args = [],
- context = contextGetter ? contextGetter(self, locals) : self;
+ context = contextGetter ? contextGetter(scope, locals) : scope;
for ( var i = 0; i < argsFn.length; i++) {
- args.push(argsFn[i](self, locals));
+ args.push(argsFn[i](scope, locals));
}
- var fnPtr = fn(self, locals) || noop;
+ var fnPtr = fn(scope, locals, context) || noop;
// IE stupidity!
return fnPtr.apply
? fnPtr.apply(context, args)
: fnPtr(args[0], args[1], args[2], args[3], args[4]);
};
@@ -6332,12 +6399,11 @@
consume('}');
return function(self, locals){
var object = {};
for ( var i = 0; i < keyValues.length; i++) {
var keyValue = keyValues[i];
- var value = keyValue.value(self, locals);
- object[keyValue.key] = value;
+ object[keyValue.key] = keyValue.value(self, locals);
}
return object;
};
}
}
@@ -6455,11 +6521,11 @@
}
pathVal = pathVal.$$v;
}
return pathVal;
};
-};
+}
function getterFn(path, csp) {
if (getterFnCache.hasOwnProperty(path)) {
return getterFnCache[path];
}
@@ -6470,11 +6536,11 @@
if (csp) {
fn = (pathKeysLength < 6)
? cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4])
: function(scope, locals) {
- var i = 0, val
+ var i = 0, val;
do {
val = cspSafeGetterFn(
pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++]
)(scope, locals);
@@ -6535,13 +6601,13 @@
*
*
* @param {string} expression String expression to compile.
* @returns {function(context, locals)} a function which represents the compiled expression:
*
- * * `context` – `{object}` – an object against which any expressions embedded in the strings
+ * * `context` – `{object}` – an object against which any expressions embedded in the strings
* are evaluated against (tipically a scope object).
- * * `locals` – `{object=}` – local variables context object, useful for overriding values in
+ * * `locals` – `{object=}` – local variables context object, useful for overriding values in
* `context`.
*
* The return function also has an `assign` property, if the expression is assignable, which
* allows one to set values to expressions.
*
@@ -6626,18 +6692,18 @@
* The purpose of the deferred object is to expose the associated Promise instance as well as APIs
* that can be used for signaling the successful or unsuccessful completion of the task.
*
* **Methods**
*
- * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection
+ * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection
* constructed via `$q.reject`, the promise will be rejected instead.
- * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to
+ * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to
* resolving it with a rejection constructed via `$q.reject`.
*
* **Properties**
*
- * - promise – `{Promise}` – promise object associated with this deferred.
+ * - promise – `{Promise}` – promise object associated with this deferred.
*
*
* # The Promise API
*
* A new promise instance is created when a deferred instance is created and can be retrieved by
@@ -6646,11 +6712,11 @@
* The purpose of the promise object is to allow for interested parties to get access to the result
* of the deferred task when it completes.
*
* **Methods**
*
- * - `then(successCallback, errorCallback)` – regardless of when the promise was or will be resolved
+ * - `then(successCallback, errorCallback)` – regardless of when the promise was or will be resolved
* or rejected calls one of the success or error callbacks asynchronously as soon as the result
* is available. The callbacks are called with a single argument the result or rejection reason.
*
* This method *returns a new promise* which is resolved or rejected via the return value of the
* `successCallback` or `errorCallback`.
@@ -6683,31 +6749,31 @@
* - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation
* mechanism in angular, which means faster propagation of resolution or rejection into your
* models and avoiding unnecessary browser repaints, which would result in flickering UI.
* - $q promises are recognized by the templating engine in angular, which means that in templates
* you can treat promises attached to a scope as if they were the resulting values.
- * - Q has many more features that $q, but that comes at a cost of bytes. $q is tiny, but contains
+ * - Q has many more features than $q, but that comes at a cost of bytes. $q is tiny, but contains
* all the important functionality needed for common async tasks.
- *
+ *
* # Testing
- *
+ *
* <pre>
* it('should simulate promise', inject(function($q, $rootScope) {
* var deferred = $q.defer();
* var promise = deferred.promise;
* var resolvedValue;
- *
+ *
* promise.then(function(value) { resolvedValue = value; });
* expect(resolvedValue).toBeUndefined();
- *
+ *
* // Simulate resolving of promise
* deferred.resolve(123);
* // Note that the 'then' function does not get called synchronously.
* // This is because we want the promise API to always be async, whether or not
* // it got called synchronously or asynchronously.
* expect(resolvedValue).toBeUndefined();
- *
+ *
* // Propagate promise resolution to 'then' functions using $apply().
* $rootScope.$apply();
* expect(resolvedValue).toEqual(123);
* });
* </pre>
@@ -6878,14 +6944,11 @@
* Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.
* This is useful when you are dealing with an object that might or might not be a promise, or if
* the promise comes from a source that can't be trusted.
*
* @param {*} value Value or a promise
- * @returns {Promise} Returns a single promise that will be resolved with an array of values,
- * each value corresponding to the promise at the same index in the `promises` array. If any of
- * the promises is resolved with a rejection, this resulting promise will be resolved with the
- * same rejection.
+ * @returns {Promise} Returns a promise of the passed value or promise
*/
var when = function(value, callback, errback) {
var result = defer(),
done;
@@ -7007,31 +7070,31 @@
* @param {Object} route Mapping information to be assigned to `$route.current` on route
* match.
*
* Object properties:
*
- * - `controller` – `{(string|function()=}` – Controller fn that should be associated with newly
+ * - `controller` – `{(string|function()=}` – Controller fn that should be associated with newly
* created scope or the name of a {@link angular.Module#controller registered controller}
* if passed as a string.
- * - `template` – `{string=}` – html template as a string that should be used by
+ * - `template` – `{string=}` – html template as a string that should be used by
* {@link ng.directive:ngView ngView} or
* {@link ng.directive:ngInclude ngInclude} directives.
* this property takes precedence over `templateUrl`.
- * - `templateUrl` – `{string=}` – path to an html template that should be used by
+ * - `templateUrl` – `{string=}` – path to an html template that should be used by
* {@link ng.directive:ngView ngView}.
* - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should
* be injected into the controller. If any of these dependencies are promises, they will be
* resolved and converted to a value before the controller is instantiated and the
* `$routeChangeSuccess` event is fired. The map object is:
*
- * - `key` – `{string}`: a name of a dependency to be injected into the controller.
+ * - `key` – `{string}`: a name of a dependency to be injected into the controller.
* - `factory` - `{string|function}`: If `string` then it is an alias for a service.
* Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected}
* and the return value is treated as the dependency. If the result is a promise, it is resolved
* before its value is injected into the controller.
*
- * - `redirectTo` – {(string|function())=} – value to update
+ * - `redirectTo` – {(string|function())=} – value to update
* {@link ng.$location $location} path with and trigger route redirection.
*
* If `redirectTo` is a function, it will be called with the following parameters:
*
* - `{Object.<string>}` - route parameters extracted from the current
@@ -7238,12 +7301,13 @@
* @description
* Broadcasted after a route dependencies are resolved.
* {@link ng.directive:ngView ngView} listens for the directive
* to instantiate the controller and render the view.
*
+ * @param {Object} angularEvent Synthetic event object.
* @param {Route} current Current route information.
- * @param {Route} previous Previous route information.
+ * @param {Route|Undefined} previous Previous route information, or undefined if current is first route entered.
*/
/**
* @ngdoc event
* @name ng.$route#$routeChangeError
@@ -7337,11 +7401,11 @@
function updateRoute() {
var next = parseRoute(),
last = $route.current;
- if (next && last && next.$route === last.$route
+ if (next && last && next.$$route === last.$$route
&& equals(next.pathParams, last.pathParams) && !next.reloadOnSearch && !forceReload) {
last.params = next.params;
copy(last.params, $routeParams);
$rootScope.$broadcast('$routeUpdate', last);
} else if (next || last) {
@@ -7416,11 +7480,11 @@
forEach(routes, function(route, path) {
if (!match && (params = switchRouteMatcher($location.path(), path))) {
match = inherit(route, {
params: extend({}, $location.search(), params),
pathParams: params});
- match.$route = route;
+ match.$$route = route;
}
});
// No route matched; fallback to "otherwise" route
return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});
}
@@ -7476,26 +7540,26 @@
}
/**
* DESIGN NOTES
*
- * The design decisions behind the scope ware heavily favored for speed and memory consumption.
+ * The design decisions behind the scope are heavily favored for speed and memory consumption.
*
* The typical use of scope is to watch the expressions, which most of the time return the same
* value as last time so we optimize the operation.
*
- * Closures construction is expensive from speed as well as memory:
- * - no closures, instead ups prototypical inheritance for API
+ * Closures construction is expensive in terms of speed as well as memory:
+ * - No closures, instead use prototypical inheritance for API
* - Internal state needs to be stored on scope directly, which means that private state is
* exposed as $$____ properties
*
* Loop operations are optimized by using while(count--) { ... }
* - this means that in order to keep the same order of execution as addition we have to add
- * items to the array at the begging (shift) instead of at the end (push)
+ * items to the array at the beginning (shift) instead of at the end (push)
*
* Child scopes are created and removed often
- * - Using array would be slow since inserts in meddle are expensive so we use linked list
+ * - Using an array would be slow since inserts in middle are expensive so we use linked list
*
* There are few watches then a lot of observers. This is why you don't want the observer to be
* implemented in the same way as watch. Watch requires return of initialization function which
* are expensive to construct.
*/
@@ -7513,11 +7577,11 @@
* @ngdoc function
* @name ng.$rootScopeProvider#digestTtl
* @methodOf ng.$rootScopeProvider
* @description
*
- * Sets the number of digest iteration the scope should attempt to execute before giving up and
+ * 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.
*
* @param {number} limit The number of digest iterations.
@@ -7793,11 +7857,11 @@
* @name ng.$rootScope.Scope#$digest
* @methodOf ng.$rootScope.Scope
* @function
*
* @description
- * Process 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 its children.
* Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change the model, the
* `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} until no more listeners are
* firing. This means that it is possible to get into an infinite loop. This function will throw
* `'Maximum iteration limit exceeded.'` if the number of iterations exceeds 10.
*
@@ -8135,11 +8199,11 @@
* 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.
* Afterwards, the event traverses upwards toward the root scope and calls all registered
* listeners along the way. The event will stop propagating if one of the listeners cancels it.
*
- * Any exception emmited 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.
*
* @param {string} name Event name to emit.
* @param {...*} args Optional set of arguments which will be passed onto the event listeners.
* @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}
@@ -8204,11 +8268,11 @@
* calls all registered listeners along the way. The event cannot be canceled.
*
* Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed
* onto the {@link ng.$exceptionHandler $exceptionHandler} service.
*
- * @param {string} name Event name to emit.
+ * @param {string} name Event name to broadcast.
* @param {...*} args Optional set of arguments which will be passed onto the event listeners.
* @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}
*/
$broadcast: function(name, args) {
var target = this,
@@ -8350,14 +8414,27 @@
* suffer from window globality.
*
* @example
<doc:example>
<doc:source>
- <input ng-init="$window = $service('$window'); greeting='Hello World!'" type="text" ng-model="greeting" />
- <button ng-click="$window.alert(greeting)">ALERT</button>
+ <script>
+ function Ctrl($scope, $window) {
+ $scope.$window = $window;
+ $scope.greeting = 'Hello, World!';
+ }
+ </script>
+ <div ng-controller="Ctrl">
+ <input type="text" ng-model="greeting" />
+ <button ng-click="$window.alert(greeting)">ALERT</button>
+ </div>
</doc:source>
<doc:scenario>
+ it('should display the greeting in the input box', function() {
+ input('greeting').enter('Hello, E2E Tests');
+ // If we click the button it will block the test runner
+ // element(':button').click();
+ });
</doc:scenario>
</doc:example>
*/
function $WindowProvider(){
this.$get = valueFn(window);
@@ -8506,27 +8583,27 @@
* @requires $q
* @requires $injector
*
* @description
* The `$http` service is a core Angular service that facilitates communication with the remote
- * HTTP servers via browser's {@link https://developer.mozilla.org/en/xmlhttprequest
+ * HTTP servers via the browser's {@link https://developer.mozilla.org/en/xmlhttprequest
* XMLHttpRequest} object or via {@link http://en.wikipedia.org/wiki/JSONP JSONP}.
*
* For unit testing applications that use `$http` service, see
* {@link ngMock.$httpBackend $httpBackend mock}.
*
* For a higher level of abstraction, please check out the {@link ngResource.$resource
* $resource} service.
*
* The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by
- * the $q service. While for simple usage patters this doesn't matter much, for advanced usage,
- * it is important to familiarize yourself with these apis and guarantees they provide.
+ * the $q service. While for simple usage patterns this doesn't matter much, for advanced usage
+ * it is important to familiarize yourself with these APIs and the guarantees they provide.
*
*
* # General usage
- * The `$http` service is a function which takes a single argument — a configuration object —
- * that is used to generate an http request and returns a {@link ng.$q promise}
+ * The `$http` service is a function which takes a single argument — a configuration object —
+ * that is used to generate an HTTP request and returns a {@link ng.$q promise}
* with two $http specific methods: `success` and `error`.
*
* <pre>
* $http({method: 'GET', url: '/someUrl'}).
* success(function(data, status, headers, config) {
@@ -8537,25 +8614,25 @@
* // called asynchronously if an error occurs
* // or server returns response with an error status.
* });
* </pre>
*
- * Since the returned value of calling the $http function is a Promise object, you can also use
- * the `then` method to register callbacks, and these callbacks will receive a single argument –
- * an object representing the response. See the api signature and type info below for more
+ * Since the returned value of calling the $http function is a `promise`, you can also use
+ * the `then` method to register callbacks, and these callbacks will receive a single argument –
+ * an object representing the response. See the API signature and type info below for more
* details.
*
- * A response status code that falls in the [200, 300) range is considered a success status and
+ * A response status code between 200 and 299 is considered a success status and
* will result in the success callback being called. Note that if the response is a redirect,
* XMLHttpRequest will transparently follow it, meaning that the error callback will not be
* called for such responses.
*
* # Shortcut methods
*
- * Since all invocation of the $http service require definition of the http method and url and
- * POST and PUT requests require response body/data to be provided as well, shortcut methods
- * were created to simplify using the api:
+ * Since all invocations of the $http service require passing in an HTTP method and URL, and
+ * POST/PUT requests require request data to be provided as well, shortcut methods
+ * were created:
*
* <pre>
* $http.get('/someUrl').success(successCallback);
* $http.post('/someUrl', data).success(successCallback);
* </pre>
@@ -8570,64 +8647,68 @@
* - {@link ng.$http#jsonp $http.jsonp}
*
*
* # Setting HTTP Headers
*
- * The $http service will automatically add certain http headers to all requests. These defaults
+ * The $http service will automatically add certain HTTP headers to all requests. These defaults
* can be fully configured by accessing the `$httpProvider.defaults.headers` configuration
* object, which currently contains this default configuration:
*
* - `$httpProvider.defaults.headers.common` (headers that are common for all requests):
* - `Accept: application/json, text/plain, * / *`
* - `X-Requested-With: XMLHttpRequest`
- * - `$httpProvider.defaults.headers.post`: (header defaults for HTTP POST requests)
+ * - `$httpProvider.defaults.headers.post`: (header defaults for POST requests)
* - `Content-Type: application/json`
- * - `$httpProvider.defaults.headers.put` (header defaults for HTTP PUT requests)
+ * - `$httpProvider.defaults.headers.put` (header defaults for PUT requests)
* - `Content-Type: application/json`
*
- * To add or overwrite these defaults, simply add or remove a property from this configuration
+ * To add or overwrite these defaults, simply add or remove a property from these configuration
* objects. To add headers for an HTTP method other than POST or PUT, simply add a new object
- * with name equal to the lower-cased http method name, e.g.
+ * with the lowercased HTTP method name as the key, e.g.
* `$httpProvider.defaults.headers.get['My-Header']='value'`.
*
- * Additionally, the defaults can be set at runtime via the `$http.defaults` object in a similar
- * fassion as described above.
+ * Additionally, the defaults can be set at runtime via the `$http.defaults` object in the same
+ * fashion.
*
*
* # Transforming Requests and Responses
*
* Both requests and responses can be transformed using transform functions. By default, Angular
* applies these transformations:
*
* Request transformations:
*
- * - if the `data` property of the request config object contains an object, serialize it into
+ * - If the `data` property of the request configuration object contains an object, serialize it into
* JSON format.
*
* Response transformations:
*
- * - if XSRF prefix is detected, strip it (see Security Considerations section below)
- * - if json response is detected, deserialize it using a JSON parser
+ * - If XSRF prefix is detected, strip it (see Security Considerations section below).
+ * - If JSON response is detected, deserialize it using a JSON parser.
*
- * To override these transformation locally, specify transform functions as `transformRequest`
- * and/or `transformResponse` properties of the config object. To globally override the default
- * transforms, override the `$httpProvider.defaults.transformRequest` and
- * `$httpProvider.defaults.transformResponse` properties of the `$httpProvider`.
+ * To globally augment or override the default transforms, modify the `$httpProvider.defaults.transformRequest` and
+ * `$httpProvider.defaults.transformResponse` properties. These properties are by default an
+ * array of transform functions, which allows you 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.
*
+ * Similarly, to locally override the request/response transforms, augment the `transformRequest` and/or
+ * `transformResponse` properties of the configuration object passed into `$http`.
*
+ *
* # Caching
*
- * To enable caching set the configuration property `cache` to `true`. When the cache is
+ * To enable caching, set the configuration property `cache` to `true`. When the cache is
* enabled, `$http` stores the response from the server in local cache. Next time the
* response is served from the cache without sending a request to the server.
*
* Note that even if the response is served from cache, delivery of the data is asynchronous in
* the same way that real requests are.
*
- * If there are multiple GET requests for the same url that should be cached using the same
+ * If there are multiple GET requests for the same URL that should be cached using the same
* cache, but the cache is not populated yet, only one request to the server will be made and
- * the remaining requests will be fulfilled using the response for the first request.
+ * the remaining requests will be fulfilled using the response from the first request.
*
*
* # Response interceptors
*
* Before you start creating interceptors, be sure to understand the
@@ -8639,11 +8720,11 @@
* initiated these requests. The response interceptors leverage the {@link ng.$q
* promise apis} to fulfil this need for both synchronous and asynchronous preprocessing.
*
* The interceptors are service factories that are registered with the $httpProvider by
* adding them to the `$httpProvider.responseInterceptors` array. The factory is called and
- * injected with dependencies (if specified) and returns the interceptor — a function that
+ * injected with dependencies (if specified) and returns the interceptor — a function that
* takes a {@link ng.$q promise} and returns the original or a new promise.
*
* <pre>
* // register the interceptor as a service
* $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {
@@ -8675,22 +8756,22 @@
* # Security Considerations
*
* When designing web applications, consider security threats from:
*
* - {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx
- * JSON Vulnerability}
+ * JSON vulnerability}
* - {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF}
*
* Both server and the client must cooperate in order to eliminate these threats. Angular comes
* pre-configured with strategies that address these issues, but for this to work backend server
* cooperation is required.
*
* ## JSON Vulnerability Protection
*
* A {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx
- * JSON Vulnerability} allows third party web-site to turn your JSON resource URL into
- * {@link http://en.wikipedia.org/wiki/JSON#JSONP JSONP} request under some conditions. To
+ * JSON vulnerability} allows third party website to turn your JSON resource URL into
+ * {@link http://en.wikipedia.org/wiki/JSONP JSONP} request under some conditions. To
* counter this your server can prefix all JSON requests with following string `")]}',\n"`.
* Angular will automatically strip the prefix before processing it as JSON.
*
* For example if your server needs to return:
* <pre>
@@ -8707,45 +8788,45 @@
*
*
* ## Cross Site Request Forgery (XSRF) Protection
*
* {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} is a technique by which
- * an unauthorized site can gain your user's private data. Angular provides following mechanism
+ * an unauthorized site can gain your user's private data. Angular provides a mechanism
* to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie
* called `XSRF-TOKEN` and sets it as the HTTP header `X-XSRF-TOKEN`. Since only JavaScript that
* runs on your domain could read the cookie, your server can be assured that the XHR came from
* JavaScript running on your domain.
*
* To take advantage of this, your server needs to set a token in a JavaScript readable session
- * cookie called `XSRF-TOKEN` on first HTTP GET request. On subsequent non-GET 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
- * that only JavaScript running on your domain could have read the token. The token must be
- * unique for each user and must be verifiable by the server (to prevent the JavaScript making
+ * 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
* up its own tokens). We recommend that the token is a digest of your site's authentication
- * cookie with {@link http://en.wikipedia.org/wiki/Rainbow_table salt for added security}.
+ * cookie with a {@link https://en.wikipedia.org/wiki/Salt_(cryptography) salt} for added security.
*
*
* @param {object} config Object describing the request to be made and how it should be
* processed. The object has following properties:
*
- * - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)
- * - **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
+ * - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)
+ * - **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
* `?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.
- * - **headers** – `{Object}` – Map of strings representing HTTP headers to send to the server.
- * - **transformRequest** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –
+ * - **data** – `{string|Object}` – Data to be sent as the request message data.
+ * - **headers** – `{Object}` – Map of strings representing HTTP headers to send to the server.
+ * - **transformRequest** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –
* 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.
- * - **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
* 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
* GET request, otherwise if a cache instance built with
* {@link ng.$cacheFactory $cacheFactory}, this cache will be used for
* caching.
- * - **timeout** – `{number}` – timeout in milliseconds.
+ * - **timeout** – `{number}` – timeout in milliseconds.
* - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the
* XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5
* requests with credentials} for more information.
*
* @returns {HttpPromise} Returns a {@link ng.$q promise} object with the
@@ -8754,14 +8835,14 @@
* response object. The `success` and `error` methods take a single argument - a function that
* will be called when the request succeeds or fails respectively. The arguments passed into
* these functions are destructured representation of the response object passed into the
* `then` method. The response object has these properties:
*
- * - **data** – `{string|Object}` – The response body transformed with the transform functions.
- * - **status** – `{number}` – HTTP status code of the response.
- * - **headers** – `{function([headerName])}` – Header getter function.
- * - **config** – `{Object}` – The configuration object that was used to generate the request.
+ * - **data** – `{string|Object}` – The response body transformed with the transform functions.
+ * - **status** – `{number}` – HTTP status code of the response.
+ * - **headers** – `{function([headerName])}` – Header getter function.
+ * - **config** – `{Object}` – The configuration object that was used to generate the request.
*
* @property {Array.<Object>} pendingRequests Array of config objects for currently pending
* requests. This is primarily meant to be used for debugging purposes.
*
*
@@ -8897,11 +8978,11 @@
* @ngdoc method
* @name ng.$http#get
* @methodOf ng.$http
*
* @description
- * Shortcut method to perform `GET` request
+ * Shortcut method to perform `GET` request.
*
* @param {string} url Relative or absolute URL specifying the destination of the request
* @param {Object=} config Optional configuration object
* @returns {HttpPromise} Future object
*/
@@ -8910,11 +8991,11 @@
* @ngdoc method
* @name ng.$http#delete
* @methodOf ng.$http
*
* @description
- * Shortcut method to perform `DELETE` request
+ * Shortcut method to perform `DELETE` request.
*
* @param {string} url Relative or absolute URL specifying the destination of the request
* @param {Object=} config Optional configuration object
* @returns {HttpPromise} Future object
*/
@@ -8923,11 +9004,11 @@
* @ngdoc method
* @name ng.$http#head
* @methodOf ng.$http
*
* @description
- * Shortcut method to perform `HEAD` request
+ * Shortcut method to perform `HEAD` request.
*
* @param {string} url Relative or absolute URL specifying the destination of the request
* @param {Object=} config Optional configuration object
* @returns {HttpPromise} Future object
*/
@@ -8936,11 +9017,11 @@
* @ngdoc method
* @name ng.$http#jsonp
* @methodOf ng.$http
*
* @description
- * Shortcut method to perform `JSONP` request
+ * Shortcut method to perform `JSONP` request.
*
* @param {string} url Relative or absolute URL specifying the destination of the request.
* Should contain `JSON_CALLBACK` string.
* @param {Object=} config Optional configuration object
* @returns {HttpPromise} Future object
@@ -8951,11 +9032,11 @@
* @ngdoc method
* @name ng.$http#post
* @methodOf ng.$http
*
* @description
- * Shortcut method to perform `POST` request
+ * Shortcut method to perform `POST` request.
*
* @param {string} url Relative or absolute URL specifying the destination of the request
* @param {*} data Request content
* @param {Object=} config Optional configuration object
* @returns {HttpPromise} Future object
@@ -8965,11 +9046,11 @@
* @ngdoc method
* @name ng.$http#put
* @methodOf ng.$http
*
* @description
- * Shortcut method to perform `PUT` request
+ * Shortcut method to perform `PUT` request.
*
* @param {string} url Relative or absolute URL specifying the destination of the request
* @param {*} data Request content
* @param {Object=} config Optional configuration object
* @returns {HttpPromise} Future object
@@ -9017,11 +9098,11 @@
});
}
/**
- * Makes the request
+ * Makes the request.
*
* !!! ACCESSES CLOSURE VARS:
* $httpBackend, $config, $log, $rootScope, defaultCache, $http.pendingRequests
*/
function sendReq(config, reqData, reqHeaders) {
@@ -9127,10 +9208,11 @@
}
}];
}
+
var XHR = window.XMLHttpRequest || function() {
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"); } catch (e3) {}
throw new Error("This browser does not support XMLHttpRequest.");
@@ -9284,11 +9366,11 @@
*
* @description
* $locale service provides localization rules for various Angular components. As of right now the
* only public api is:
*
- * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)
+ * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)
*/
function $LocaleProvider(){
this.$get = function() {
return {
id: 'en-us',
@@ -9363,21 +9445,21 @@
* @description
* Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch
* block and delegates any exceptions to
* {@link ng.$exceptionHandler $exceptionHandler} service.
*
- * The return value of registering a timeout function is a promise which will be resolved when
+ * The return value of registering a timeout function is a promise, which will be resolved when
* the timeout is reached and the timeout function is executed.
*
- * To cancel a the timeout request, call `$timeout.cancel(promise)`.
+ * To cancel a timeout request, call `$timeout.cancel(promise)`.
*
* In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to
* synchronously flush the queue of deferred functions.
*
- * @param {function()} fn A function, who's execution should be delayed.
+ * @param {function()} fn A function, whose execution should be delayed.
* @param {number=} [delay=0] Delay in milliseconds.
- * @param {boolean=} [invokeApply=true] If set to false skips model dirty checking, otherwise
+ * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise
* will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.
* @returns {Promise} Promise that will be resolved when the timeout is reached. The value this
* promise will be resolved with is the return value of the `fn` function.
*/
function timeout(fn, delay, invokeApply) {
@@ -9413,11 +9495,11 @@
* @ngdoc function
* @name ng.$timeout#cancel
* @methodOf ng.$timeout
*
* @description
- * Cancels a task associated with the `promise`. As a result of this the promise will be
+ * Cancels a task associated with the `promise`. As a result of this, the promise will be
* resolved with a rejection.
*
* @param {Promise=} promise Promise returned by the `$timeout` function.
* @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully
* canceled.
@@ -9439,11 +9521,11 @@
* @name ng.$filterProvider
* @description
*
* Filters are just functions which transform input to an output. However filters need to be Dependency Injected. To
* achieve this a filter definition consists of a factory function which is annotated with dependencies and is
- * responsible for creating a the filter function.
+ * responsible for creating a filter function.
*
* <pre>
* // Filter registration
* function MyModule($provide, $filterProvider) {
* // create a service to demonstrate injection (not always needed)
@@ -9501,11 +9583,11 @@
* @description
* Filters are used for formatting data displayed to the user.
*
* The general syntax in templates is as follows:
*
- * {{ expression | [ filter_name ] }}
+ * {{ expression [| filter_name[:parameter_value] ... ] }}
*
* @param {String} name Name of the filter function to retrieve
* @return {Function} the filter function
*/
$FilterProvider.$inject = ['$provide'];
@@ -9577,26 +9659,26 @@
{name:'Adam', phone:'555-5678'},
{name:'Julie', phone:'555-8765'}]"></div>
Search: <input ng-model="searchText">
<table id="searchTextResults">
- <tr><th>Name</th><th>Phone</th><tr>
+ <tr><th>Name</th><th>Phone</th></tr>
<tr ng-repeat="friend in friends | filter:searchText">
<td>{{friend.name}}</td>
<td>{{friend.phone}}</td>
- <tr>
+ </tr>
</table>
<hr>
Any: <input ng-model="search.$"> <br>
Name only <input ng-model="search.name"><br>
- Phone only <input ng-model="search.phone"Ã¥><br>
+ Phone only <input ng-model="search.phone"><br>
<table id="searchObjResults">
- <tr><th>Name</th><th>Phone</th><tr>
+ <tr><th>Name</th><th>Phone</th></tr>
<tr ng-repeat="friend in friends | filter:search">
<td>{{friend.name}}</td>
<td>{{friend.phone}}</td>
- <tr>
+ </tr>
</table>
</doc:source>
<doc:scenario>
it('should search across all fields when filtering with a string', function() {
input('searchText').enter('m');
@@ -9760,11 +9842,11 @@
*
* If the input is not a number an empty string is returned.
*
* @param {number|string} number Number to format.
* @param {(number|string)=} [fractionSize=2] Number of decimal places to round the number to.
- * @returns {string} Number rounded to decimalPlaces and places a “,†after each third digit.
+ * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.
*
* @example
<doc:example>
<doc:source>
<script>
@@ -9889,10 +9971,11 @@
return neg + num;
}
function dateGetter(name, size, offset, trim) {
+ offset = offset || 0;
return function(date) {
var value = date['get' + name]();
if (offset > 0 || value > -offset)
value += offset;
if (value === 0 && offset == -12 ) value = 12;
@@ -9911,11 +9994,12 @@
function timeZoneGetter(date) {
var zone = -1 * date.getTimezoneOffset();
var paddedZone = (zone >= 0) ? "+" : "";
- paddedZone += padNumber(zone / 60, 2) + padNumber(Math.abs(zone % 60), 2);
+ paddedZone += padNumber(Math[zone > 0 ? 'floor' : 'ceil'](zone / 60), 2) +
+ padNumber(Math.abs(zone % 60), 2);
return paddedZone;
}
function ampmGetter(date, formats) {
@@ -9977,11 +10061,11 @@
* * `'mm'`: Minute in hour, padded (00-59)
* * `'m'`: Minute in hour (0-59)
* * `'ss'`: Second in minute, padded (00-59)
* * `'s'`: Second in minute (0-59)
* * `'a'`: am/pm marker
- * * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-1200)
+ * * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-+1200)
*
* `format` string can also be one of the following predefined
* {@link guide/i18n localizable formats}:
*
* * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale
@@ -9998,11 +10082,11 @@
* `format` string can contain literal values. These need to be quoted with single quotes (e.g.
* `"h 'in the morning'"`). In order to output single quote, use two single quotes in a sequence
* (e.g. `"h o''clock"`).
*
* @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or
- * number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and it's
+ * number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and its
* shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ). If no timezone is
* specified in the string input, the time is considered to be in the local timezone.
* @param {string=} format Formatting rules (see Description). If not specified,
* `mediumDate` is used.
* @returns {string} Formatted string or the input if input is not recognized as date/millis.
@@ -10289,16 +10373,16 @@
<tr>
<th><a href="" ng-click="predicate = 'name'; reverse=false">Name</a>
(<a href ng-click="predicate = '-name'; reverse=false">^</a>)</th>
<th><a href="" ng-click="predicate = 'phone'; reverse=!reverse">Phone Number</a></th>
<th><a href="" ng-click="predicate = 'age'; reverse=!reverse">Age</a></th>
- <tr>
+ </tr>
<tr ng-repeat="friend in friends | orderBy:predicate:reverse">
<td>{{friend.name}}</td>
<td>{{friend.phone}}</td>
<td>{{friend.age}}</td>
- <tr>
+ </tr>
</table>
</div>
</doc:source>
<doc:scenario>
it('should be reverse ordered by aged', function() {
@@ -10763,11 +10847,11 @@
* @property {boolean} $invalid True if at least one containing control or form is invalid.
*
* @property {Object} $error Is an object hash, containing references to all invalid controls or
* forms, where:
*
- * - keys are validation tokens (error names) — such as `required`, `url` or `email`),
+ * - keys are validation tokens (error names) — such as `required`, `url` or `email`),
* - values are arrays of controls or forms that are invalid with given error.
*
* @description
* `FormController` keeps track of all its controls and nested forms as well as state of them,
* such as being valid/invalid or dirty/pristine.
@@ -11116,12 +11200,12 @@
* Text input with number validation and transformation. Sets the `number` validation
* error if not a valid number.
*
* @param {string} ngModel Assignable angular expression to data-bind to.
* @param {string=} name Property name of the form under which the control is published.
- * @param {string=} min Sets the `min` validation error key if the value entered is less then `min`.
- * @param {string=} max Sets the `max` validation error key if the value entered is greater then `min`.
+ * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`.
+ * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`.
* @param {string=} required Sets `required` validation error key if the value is not entered.
* @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
* the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
* `required` when you want to data-bind to the `required` attribute.
* @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
@@ -11429,27 +11513,36 @@
if ($sniffer.hasEvent('input')) {
element.bind('input', listener);
} else {
var timeout;
+ var deferListener = function() {
+ if (!timeout) {
+ timeout = $browser.defer(function() {
+ listener();
+ timeout = null;
+ });
+ }
+ };
+
element.bind('keydown', function(event) {
var key = event.keyCode;
// ignore
// command modifiers arrows
if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;
- if (!timeout) {
- timeout = $browser.defer(function() {
- listener();
- timeout = null;
- });
- }
+ deferListener();
});
// if user paste into input using mouse, we need "change" event to catch it
element.bind('change', listener);
+
+ // if user modifies input value using context menu in IE, we need "paste" and "cut" events to catch it
+ if ($sniffer.hasEvent('paste')) {
+ element.bind('paste cut', deferListener);
+ }
}
ctrl.$render = function() {
element.val(isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);
@@ -11744,11 +11837,11 @@
<hr>
<tt>user = {{user}}</tt><br/>
<tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>
<tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>
<tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>
- <tt>myForm.userName.$error = {{myForm.lastName.$error}}</tt><br>
+ <tt>myForm.lastName.$error = {{myForm.lastName.$error}}</tt><br>
<tt>myForm.$valid = {{myForm.$valid}}</tt><br>
<tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>
<tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>
<tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>
</div>
@@ -12007,11 +12100,11 @@
*
* This method should be called from within a DOM event handler.
* For example {@link ng.directive:input input} or
* {@link ng.directive:select select} directives call it.
*
- * It internally calls all `formatters` and if resulted value is valid, updates the model and
+ * It internally calls all `parsers` and if resulted value is valid, updates the model and
* calls all registered change listeners.
*
* @param {string} value Value from the view.
*/
this.$setViewValue = function(value) {
@@ -12313,11 +12406,11 @@
* expression changes.
*
* Typically, you don't use `ngBind` directly, but instead you use the double curly markup like
* `{{ expression }}` which is similar but less verbose.
*
- * Once scenario in which the use of `ngBind` is prefered over `{{ expression }}` binding is when
+ * One scenario in which the use of `ngBind` is preferred over `{{ expression }}` binding is when
* it's desirable to put bindings into template that is momentarily displayed by the browser in its
* raw state before Angular compiles it. Since `ngBind` is an element attribute, it makes the
* bindings invisible to the user while the page is loading.
*
* An alternative solution to this problem would be using the
@@ -12454,13 +12547,13 @@
});
if (name !== 'ngClass') {
scope.$watch('$index', function($index, old$index) {
- var mod = $index % 2;
- if (mod !== old$index % 2) {
- if (mod == selector) {
+ var mod = $index & 1;
+ if (mod !== old$index & 1) {
+ if (mod === selector) {
addClass(scope.$eval(attr[name]));
} else {
removeClass(scope.$eval(attr[name]));
}
}
@@ -12468,16 +12561,16 @@
}
function ngClassWatchAction(newVal) {
if (selector === true || scope.$index % 2 === selector) {
- if (oldVal && (newVal !== oldVal)) {
+ if (oldVal && !equals(newVal,oldVal)) {
removeClass(oldVal);
}
addClass(newVal);
}
- oldVal = newVal;
+ oldVal = copy(newVal);
}
function removeClass(classVal) {
if (isObject(classVal) && !isArray(classVal)) {
@@ -12599,11 +12692,11 @@
/**
* @ngdoc directive
* @name ng.directive:ngClassEven
*
* @description
- * The `ngClassOdd` and `ngClassEven` works exactly as
+ * The `ngClassOdd` and `ngClassEven` directives work exactly as
* {@link ng.directive:ngClass ngClass}, except it works in
* conjunction with `ngRepeat` and takes affect only on odd (even) rows.
*
* This directive can be applied only within a scope of an
* {@link ng.directive:ngRepeat ngRepeat}.
@@ -12657,11 +12750,11 @@
*
* `ngCloak` works in cooperation with a css rule that is embedded within `angular.js` and
* `angular.min.js` files. Following is the css rule:
*
* <pre>
- * [ng\:cloak], [ng-cloak], .ng-cloak {
+ * [ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {
* display: none;
* }
* </pre>
*
* When this css rule is loaded by the browser, all html elements (including their children) that
@@ -12711,17 +12804,16 @@
* The `ngController` directive assigns behavior to a scope. This is a key aspect of how angular
* supports the principles behind the Model-View-Controller design pattern.
*
* MVC components in angular:
*
- * * Model — The Model is data in scope properties; scopes are attached to the DOM.
- * * View — The template (HTML with data bindings) is rendered into the View.
- * * Controller — The `ngController` directive specifies a Controller class; the class has
+ * * Model — The Model is data in scope properties; scopes are attached to the DOM.
+ * * View — The template (HTML with data bindings) is rendered into the View.
+ * * Controller — The `ngController` directive specifies a Controller class; the class has
* methods that typically express the business logic behind the application.
*
- * Note that an alternative way to define controllers is via the `{@link ng.$route}`
- * service.
+ * Note that an alternative way to define controllers is via the {@link ng.$route $route} service.
*
* @element ANY
* @scope
* @param {expression} ngController Name of a globally accessible constructor function or an
* {@link guide/expression expression} that on the current scope evaluates to a
@@ -12808,20 +12900,36 @@
/**
* @ngdoc directive
* @name ng.directive:ngCsp
* @priority 1000
*
+ * @element html
* @description
* Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.
- * This directive should be used on the root element of the application (typically the `<html>`
- * element or other element with the {@link ng.directive:ngApp ngApp}
- * directive).
*
- * If enabled the performance of template expression evaluator will suffer slightly, so don't enable
- * this mode unless you need it.
+ * This is necessary when developing things like Google Chrome Extensions.
*
- * @element html
+ * CSP forbids apps to use `eval` or `Function(string)` generated functions (among other things).
+ * For us to be compatible, we just need to implement the "getterFn" in $parse without violating
+ * any of these restrictions.
+ *
+ * AngularJS uses `Function(string)` generated functions as a speed optimization. By applying `ngCsp`
+ * it is be possible to opt into the CSP compatible mode. When this mode is on AngularJS will
+ * evaluate all expressions up to 30% slower than in non-CSP mode, but no security violations will
+ * be raised.
+ *
+ * In order to use this feature put `ngCsp` directive on the root element of the application.
+ *
+ * @example
+ * This example shows how to apply the `ngCsp` directive to the `html` tag.
+ <pre>
+ <!doctype html>
+ <html ng-app ng-csp>
+ ...
+ ...
+ </html>
+ </pre>
*/
var ngCspDirective = ['$sniffer', function($sniffer) {
return {
priority: 1000,
@@ -13442,11 +13550,11 @@
var value = parseFloat(scope.$eval(numberExp));
if (!isNaN(value)) {
//if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,
//check it against pluralization rules in $locale service
- if (!whens[value]) value = $locale.pluralCat(value - offset);
+ if (!(value in whens)) value = $locale.pluralCat(value - offset);
return whensExpFns[value](scope, element, true);
} else {
return '';
}
}, function ngPluralizeWatchAction(newVal) {
@@ -13465,28 +13573,28 @@
* instance gets its own scope, where the given loop variable is set to the current collection item,
* and `$index` is set to the item index or key.
*
* Special properties are exposed on the local scope of each template instance, including:
*
- * * `$index` – `{number}` – iterator offset of the repeated element (0..length-1)
- * * `$first` – `{boolean}` – true if the repeated element is first in the iterator.
- * * `$middle` – `{boolean}` – true if the repeated element is between the first and last in the iterator.
- * * `$last` – `{boolean}` – true if the repeated element is last in the iterator.
+ * * `$index` – `{number}` – iterator offset of the repeated element (0..length-1)
+ * * `$first` – `{boolean}` – true if the repeated element is first in the iterator.
+ * * `$middle` – `{boolean}` – true if the repeated element is between the first and last in the iterator.
+ * * `$last` – `{boolean}` – true if the repeated element is last in the iterator.
*
*
* @element ANY
* @scope
* @priority 1000
* @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. Two
* formats are currently supported:
*
- * * `variable in expression` – where variable is the user defined loop variable and `expression`
+ * * `variable in expression` – where variable is the user defined loop variable and `expression`
* is a scope expression giving the collection to enumerate.
*
* For example: `track in cd.tracks`.
*
- * * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,
+ * * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,
* and `expression` is the scope expression giving the collection to enumerate.
*
* For example: `(name, age) in {'adam':10, 'amalie':12}`.
*
* @example
@@ -13550,11 +13658,11 @@
collection = scope.$eval(rhs),
cursor = iterStartElement, // current position of the node
// Same as lastOrder but it has the current state. It will become the
// lastOrder on the next iteration.
nextOrder = new HashQueueMap(),
- arrayLength,
+ arrayBound,
childScope,
key, value, // key/value of iteration
array,
last; // last object information {scope, element, index}
@@ -13571,11 +13679,11 @@
array.sort();
} else {
array = collection || [];
}
- arrayLength = array.length;
+ arrayBound = array.length-1;
// we are not using forEach for perf reasons (trying to avoid #call)
for (index = 0, length = array.length; index < length; index++) {
key = (collection === array) ? index : array[index];
value = collection[key];
@@ -13608,11 +13716,11 @@
childScope[valueIdent] = value;
if (keyIdent) childScope[keyIdent] = key;
childScope.$index = index;
childScope.$first = (index === 0);
- childScope.$last = (index === (arrayLength - 1));
+ childScope.$last = (index === arrayBound);
childScope.$middle = !(childScope.$first || childScope.$last);
if (!last) {
linker(childScope, function(clone){
cursor.after(clone);
@@ -13775,15 +13883,17 @@
* @restrict EA
*
* @description
* Conditionally change the DOM structure.
*
- * @usageContent
- * <ANY ng-switch-when="matchValue1">...</ANY>
+ * @usage
+ * <ANY ng-switch="expression">
+ * <ANY ng-switch-when="matchValue1">...</ANY>
* <ANY ng-switch-when="matchValue2">...</ANY>
* ...
* <ANY ng-switch-default>...</ANY>
+ * </ANY>
*
* @scope
* @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.
* @paramDescription
* On child elments add:
@@ -14159,11 +14269,11 @@
* # `ngOptions`
*
* Optionally `ngOptions` attribute can be used to dynamically generate a list of `<option>`
* elements for a `<select>` element using an array or an object obtained by evaluating the
* `ngOptions` expression.
- *ËË
+ *˝˝
* When an item in the select menu is select, the value of array element or object property
* represented by the selected option will be bound to the model identified by the `ngModel`
* directive of the parent select element.
*
* Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can
@@ -14173,11 +14283,12 @@
* Note: `ngOptions` provides iterator facility for `<option>` element which should be used instead
* of {@link ng.directive:ngRepeat ngRepeat} when you want the
* `select` model to be bound to a non-string value. This is because an option element can currently
* be bound to string values only.
*
- * @param {string} name assignable expression to data-bind to.
+ * @param {string} ngModel Assignable angular expression to data-bind to.
+ * @param {string=} name Property name of the form under which the control is published.
* @param {string=} required The control is considered valid only if value is entered.
* @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
* the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
* `required` when you want to data-bind to the `required` attribute.
* @param {comprehension_expression=} ngOptions in one of the following forms:
@@ -14268,11 +14379,11 @@
</doc:example>
*/
var ngOptionsDirective = valueFn({ terminal: true });
var selectDirective = ['$compile', '$parse', function($compile, $parse) {
- //00001111100000000000222200000000000000000000003333000000000000044444444444444444000000000555555555555555550000000666666666666666660000000000000007777
+ //0000111110000000000022220000000000000000000000333300000000000000444444444444444440000000005555555555555555500000006666666666666666600000000000000077770
var NG_OPTIONS_REGEXP = /^\s*(.*?)(?:\s+as\s+(.*?))?(?:\s+group\s+by\s+(.*))?\s+for\s+(?:([\$\w][\$\w\d]*)|(?:\(\s*([\$\w][\$\w\d]*)\s*,\s*([\$\w][\$\w\d]*)\s*\)))\s+in\s+(.*)$/,
nullModelCtrl = {$setViewValue: noop};
return {
restrict: 'E',
@@ -14540,14 +14651,10 @@
element,
label;
if (multiple) {
selectedSet = new HashMap(modelValue);
- } else if (modelValue === null || nullOption) {
- // if we are not multiselect, and we are null then we have to add the nullOption
- optionGroups[''].push({selected:modelValue === null, id:'', label:''});
- selectedSet = true;
}
// We now build up the list of options we need (we merge later)
for (index = 0; length = keys.length, index < length; index++) {
locals[valueName] = values[keyName ? locals[keyName]=keys[index]:index];
@@ -14568,13 +14675,18 @@
id: keyName ? keys[index] : index, // either the index into array or key from object
label: label,
selected: selected // determine if we should be selected
});
}
- if (!multiple && !selectedSet) {
- // nothing was selected, we have to insert the undefined item
- optionGroups[''].unshift({id:'?', label:'', selected:true});
+ if (!multiple) {
+ if (nullOption || modelValue === null) {
+ // insert null option if we have a placeholder, or the model is null
+ optionGroups[''].unshift({id:'', label:'', selected:!selectedSet});
+ } else if (!selectedSet) {
+ // option could not be found, we have to insert the undefined item
+ optionGroups[''].unshift({id:'?', label:'', selected:true});
+ }
}
// Now we need to update the list of DOM nodes to match the optionGroups we computed above
for (groupIndex = 0, groupLength = optionGroupNames.length;
groupIndex < groupLength;
@@ -14614,11 +14726,12 @@
lastElement.text(existingOption.label = option.label);
}
if (existingOption.id !== option.id) {
lastElement.val(existingOption.id = option.id);
}
- if (existingOption.element.selected !== option.selected) {
+ // lastElement.prop('selected') provided by jQuery has side-effects
+ if (lastElement[0].selected !== option.selected) {
lastElement.prop('selected', (existingOption.selected = option.selected));
}
} else {
// grow elements
@@ -14717,9 +14830,10 @@
var styleDirective = valueFn({
restrict: 'E',
terminal: true
});
+
//try to bind to jquery now so that one can write angular.element().read()
//but we will rebind on bootstrap again.
bindJQuery();
publishExternalAPI(angular);
\ No newline at end of file