X-Git-Url: http://repos.xcallymotion.com/?a=blobdiff_plain;f=public%2Fbower_components%2Fangular%2Fangular.js;h=a3aee7d6a51ab08914cad6f7a85f102d372924ce;hb=221ba7c2ffc043570bbad1e8f0d6074fb4ff1fb0;hp=ea563c02300ce49bf70a8851d99baff18ba72a49;hpb=5d92478b1cb7479f39a43973775a6f6147fba8ac;p=motion.git diff --git a/public/bower_components/angular/angular.js b/public/bower_components/angular/angular.js index ea563c0..a3aee7d 100644 --- a/public/bower_components/angular/angular.js +++ b/public/bower_components/angular/angular.js @@ -1,5 +1,5 @@ /** - * @license AngularJS v1.4.10 + * @license AngularJS v1.4.8 * (c) 2010-2015 Google, Inc. http://angularjs.org * License: MIT */ @@ -57,7 +57,7 @@ function minErr(module, ErrorConstructor) { return match; }); - message += '\nhttp://errors.angularjs.org/1.4.10/' + + message += '\nhttp://errors.angularjs.org/1.4.8/' + (module ? module + '/' : '') + code; for (i = SKIP_INDEXES, paramPrefix = '?'; i < templateArgs.length; i++, paramPrefix = '&') { @@ -284,8 +284,7 @@ function isArrayLike(obj) { // NodeList objects (with `item` method) and // other objects with suitable length characteristics are array-like return isNumber(length) && - (length >= 0 && ((length - 1) in obj || obj instanceof Array) || typeof obj.item == 'function'); - + (length >= 0 && (length - 1) in obj || typeof obj.item == 'function'); } /** @@ -305,7 +304,7 @@ function isArrayLike(obj) { * * Unlike ES262's * [Array.prototype.forEach](http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.18), - * providing 'undefined' or 'null' values for `obj` will not throw a TypeError, but rather just + * Providing 'undefined' or 'null' values for `obj` will not throw a TypeError, but rather just * return the value provided. * ```js @@ -382,7 +381,7 @@ function forEachSorted(obj, iterator, context) { * @returns {function(*, string)} */ function reverseParams(iteratorFn) { - return function(value, key) {iteratorFn(key, value);}; + return function(value, key) { iteratorFn(key, value); }; } /** @@ -790,7 +789,7 @@ function isElement(node) { * @returns {object} in the form of {key1:true, key2:true, ...} */ function makeMap(str) { - var obj = {}, items = str.split(','), i; + var obj = {}, items = str.split(","), i; for (i = 0; i < items.length; i++) { obj[items[i]] = true; } @@ -963,8 +962,6 @@ function copy(source, destination) { } else if (isRegExp(source)) { destination = new RegExp(source.source, source.toString().match(/[^\/]*$/)[0]); destination.lastIndex = source.lastIndex; - } else if (isBlob(source)) { - destination = new source.constructor([source], {type: source.type}); } else if (isFunction(source.cloneNode)) { destination = source.cloneNode(true); } else { @@ -1249,7 +1246,7 @@ function toJsonReplacer(key, value) { * @returns {string|undefined} JSON-ified string representing `obj`. */ function toJson(obj, pretty) { - if (isUndefined(obj)) return undefined; + if (typeof obj === 'undefined') return undefined; if (!isNumber(pretty)) { pretty = pretty ? 2 : null; } @@ -1276,10 +1273,7 @@ function fromJson(json) { } -var ALL_COLONS = /:/g; function timezoneToOffset(timezone, fallback) { - // IE/Edge do not "understand" colon (`:`) in timezone - timezone = timezone.replace(ALL_COLONS, ''); var requestedTimezoneOffset = Date.parse('Jan 01, 1970 00:00:00 ' + timezone) / 60000; return isNaN(requestedTimezoneOffset) ? fallback : requestedTimezoneOffset; } @@ -1294,9 +1288,8 @@ function addDateMinutes(date, minutes) { function convertTimezoneToLocal(date, timezone, reverse) { reverse = reverse ? -1 : 1; - var dateTimezoneOffset = date.getTimezoneOffset(); - var timezoneOffset = timezoneToOffset(timezone, dateTimezoneOffset); - return addDateMinutes(date, reverse * (timezoneOffset - dateTimezoneOffset)); + var timezoneOffset = timezoneToOffset(timezone, date.getTimezoneOffset()); + return addDateMinutes(date, reverse * (timezoneOffset - date.getTimezoneOffset())); } @@ -1315,7 +1308,7 @@ function startingTag(element) { return element[0].nodeType === NODE_TYPE_TEXT ? lowercase(elemHtml) : elemHtml. match(/^(<[^>]+>)/)[1]. - replace(/^<([\w\-]+)/, function(match, nodeName) {return '<' + lowercase(nodeName);}); + replace(/^<([\w\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); }); } catch (e) { return lowercase(elemHtml); } @@ -1994,7 +1987,7 @@ function setupModuleLoader(window) { * unspecified then the module is being retrieved for further configuration. * @param {Function=} configFn Optional configuration function for the module. Same as * {@link angular.Module#config Module#config()}. - * @returns {angular.Module} new module with the {@link angular.Module} api. + * @returns {module} new module with the {@link angular.Module} api. */ return function module(name, requires, configFn) { var assertNotHasOwnProperty = function(name, context) { @@ -2351,10 +2344,8 @@ function toDebugString(obj) { $AnchorScrollProvider, $AnimateProvider, $CoreAnimateCssProvider, - $$CoreAnimateJsProvider, $$CoreAnimateQueueProvider, - $$AnimateRunnerFactoryProvider, - $$AnimateAsyncRunFactoryProvider, + $$CoreAnimateRunnerProvider, $BrowserProvider, $CacheFactoryProvider, $ControllerProvider, @@ -2407,11 +2398,11 @@ function toDebugString(obj) { * - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat". */ var version = { - full: '1.4.10', // all of these placeholder strings will be replaced by grunt's + full: '1.4.8', // all of these placeholder strings will be replaced by grunt's major: 1, // package task minor: 4, - dot: 10, - codeName: 'benignant-oscillation' + dot: 8, + codeName: 'ice-manipulation' }; @@ -2513,10 +2504,8 @@ function publishExternalAPI(angular) { $anchorScroll: $AnchorScrollProvider, $animate: $AnimateProvider, $animateCss: $CoreAnimateCssProvider, - $$animateJs: $$CoreAnimateJsProvider, $$animateQueue: $$CoreAnimateQueueProvider, - $$AnimateRunner: $$AnimateRunnerFactoryProvider, - $$animateAsyncRun: $$AnimateAsyncRunFactoryProvider, + $$AnimateRunner: $$CoreAnimateRunnerProvider, $browser: $BrowserProvider, $cacheFactory: $CacheFactoryProvider, $controller: $ControllerProvider, @@ -2587,22 +2576,16 @@ function publishExternalAPI(angular) { * * If jQuery is available, `angular.element` is an alias for the * [jQuery](http://api.jquery.com/jQuery/) function. If jQuery is not available, `angular.element` - * delegates to Angular's built-in subset of jQuery, called "jQuery lite" or **jqLite**. - * - * jqLite is a tiny, API-compatible subset of jQuery that allows - * Angular to manipulate the DOM in a cross-browser compatible way. jqLite implements only the most - * commonly needed functionality with the goal of having a very small footprint. + * delegates to Angular's built-in subset of jQuery, called "jQuery lite" or "jqLite." * - * To use `jQuery`, simply ensure it is loaded before the `angular.js` file. You can also use the - * {@link ngJq `ngJq`} directive to specify that jqlite should be used over jQuery, or to use a - * specific version of jQuery if multiple versions exist on the page. + *
jqLite is a tiny, API-compatible subset of jQuery that allows + * Angular to manipulate the DOM in a cross-browser compatible way. **jqLite** implements only the most + * commonly needed functionality with the goal of having a very small footprint.
* - *
**Note:** All element references in Angular are always wrapped with jQuery or - * jqLite (such as the element argument in a directive's compile / link function). They are never raw DOM references.
+ * To use `jQuery`, simply ensure it is loaded before the `angular.js` file. * - *
**Note:** Keep in mind that this function will not find elements - * by tag name / CSS selector. For lookups by tag name, try instead `angular.element(document).find(...)` - * or `$document.find()`, or use the standard DOM APIs, e.g. `document.querySelectorAll()`.
+ *
**Note:** all element references in Angular are always wrapped with jQuery or + * jqLite; they are never raw DOM references.
* * ## Angular's jqLite * jqLite provides only the following jQuery methods: @@ -2615,8 +2598,7 @@ function publishExternalAPI(angular) { * - [`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/) - Only retrieves inline-styles, does not call `getComputedStyle()`. - * As a setter, does not convert numbers to strings or append 'px', and also does not have automatic property prefixing. + * - [`css()`](http://api.jquery.com/css/) - Only retrieves inline-styles, does not call `getComputedStyle()`. As a setter, does not convert numbers to strings or append 'px'. * - [`data()`](http://api.jquery.com/data/) * - [`detach()`](http://api.jquery.com/detach/) * - [`empty()`](http://api.jquery.com/empty/) @@ -2802,16 +2784,6 @@ function jqLiteParseHTML(html, context) { return []; } -function jqLiteWrapNode(node, wrapper) { - var parent = node.parentNode; - - if (parent) { - parent.replaceChild(wrapper, node); - } - - wrapper.appendChild(node); -} - // IE9-11 has no method "contains" in SVG element and in Node.prototype. Bug #10259. var jqLiteContains = Node.prototype.contains || function(arg) { @@ -3503,7 +3475,12 @@ forEach({ }, wrap: function(element, wrapNode) { - jqLiteWrapNode(element, jqLite(wrapNode).eq(0).clone()[0]); + wrapNode = jqLite(wrapNode).eq(0).clone()[0]; + var parent = element.parentNode; + if (parent) { + parent.replaceChild(wrapNode, element); + } + wrapNode.appendChild(element); }, remove: jqLiteRemove, @@ -4206,20 +4183,8 @@ function annotate(fn, strictDi, name) { * * 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 a factory - * function that returns an instance instantiated by the injector from the service constructor - * function. - * - * Internally it looks a bit like this: - * - * ``` - * { - * $get: function() { - * return $injector.instantiate(constructor); - * } - * } - * ``` - * + * This is short for registering a service where its provider's `$get` property is the service + * constructor function that will be used to instantiate the service instance. * * You should use {@link auto.$provide#service $provide.service(class)} if you define your service * as a type/class. @@ -4259,13 +4224,14 @@ function annotate(fn, strictDi, name) { * @description * * Register a **value service** with the {@link auto.$injector $injector}, such as a string, a - * number, an array, an object or a function. This is short for registering a service where its + * number, an array, an object or a function. This is short for registering a service where its * provider's `$get` property is a factory function that takes no arguments and returns the **value - * service**. That also means it is not possible to inject other services into a value service. + * service**. * * Value services are similar to constant services, except that they cannot be injected into a * module configuration function (see {@link angular.Module#config}) but they can be overridden by - * an Angular {@link auto.$provide#decorator decorator}. + * an Angular + * {@link auto.$provide#decorator decorator}. * * @param {string} name The name of the instance. * @param {*} value The value. @@ -4290,11 +4256,8 @@ function annotate(fn, strictDi, name) { * @name $provide#constant * @description * - * Register a **constant service** with the {@link auto.$injector $injector}, such as a string, - * a number, an array, an object or a function. Like the {@link auto.$provide#value value}, it is not - * possible to inject other services into a constant. - * - * But unlike {@link auto.$provide#value value}, a constant can be + * Register a **constant service**, such as a string, a number, an array, an object or a function, + * with the {@link auto.$injector $injector}. Unlike {@link auto.$provide#value value} it can be * injected into a module configuration function (see {@link angular.Module#config}) and it cannot * be overridden by an Angular {@link auto.$provide#decorator decorator}. * @@ -4322,7 +4285,7 @@ function annotate(fn, strictDi, name) { * @description * * 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 behavior 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 which replaces or wraps and delegates to the original service. * @@ -4908,8 +4871,27 @@ function prepareAnimateOptions(options) { : {}; } -var $$CoreAnimateJsProvider = function() { - this.$get = function() {}; +var $$CoreAnimateRunnerProvider = function() { + this.$get = ['$q', '$$rAF', function($q, $$rAF) { + function AnimateRunner() {} + AnimateRunner.all = noop; + AnimateRunner.chain = noop; + AnimateRunner.prototype = { + end: noop, + cancel: noop, + resume: noop, + pause: noop, + complete: noop, + then: function(pass, fail) { + return $q(function(resolve) { + $$rAF(function() { + resolve(); + }); + }).then(pass, fail); + } + }; + return AnimateRunner; + }]; }; // this is prefixed with Core since it conflicts with @@ -4937,12 +4919,7 @@ var $$CoreAnimateQueueProvider = function() { addRemoveClassesPostDigest(element, options.addClass, options.removeClass); } - var runner = new $$AnimateRunner(); // jshint ignore:line - - // since there are no animations to run the runner needs to be - // notified that the animation call is complete. - runner.complete(); - return runner; + return new $$AnimateRunner(); // jshint ignore:line } }; @@ -5407,23 +5384,10 @@ var $AnimateProvider = ['$provide', function($provide) { * @kind function * * @description Performs an inline animation on the element which applies the provided to and from CSS styles to the element. - * If any detected CSS transition, keyframe or JavaScript matches the provided className value, then the animation will take - * on the provided styles. For example, if a transition animation is set for the given className, then the provided `from` and - * `to` styles will be applied alongside the given transition. If the CSS style provided in `from` does not have a corresponding - * style in `to`, the style in `from` is applied immediately, and no animation is run. - * If a JavaScript animation is detected then the provided styles will be given in as function parameters into the `animate` - * method (or as part of the `options` parameter): - * - * ```js - * ngModule.animation('.my-inline-animation', function() { - * return { - * animate : function(element, from, to, done, options) { - * //animation - * done(); - * } - * } - * }); - * ``` + * If any detected CSS transition, keyframe or JavaScript matches the provided className value then the animation will take + * on the provided styles. For example, if a transition animation is set for the given className then the provided from and + * to styles will be applied alongside the given transition. If a JavaScript animation is detected then the provided styles + * will be given in as function paramters into the `animate` method (or as apart of the `options` parameter). * * @param {DOMElement} element the element which the CSS styles will be applied to * @param {object} from the from (starting) CSS styles that will be applied to the element and across the animation. @@ -5448,190 +5412,6 @@ var $AnimateProvider = ['$provide', function($provide) { }]; }]; -var $$AnimateAsyncRunFactoryProvider = function() { - this.$get = ['$$rAF', function($$rAF) { - var waitQueue = []; - - function waitForTick(fn) { - waitQueue.push(fn); - if (waitQueue.length > 1) return; - $$rAF(function() { - for (var i = 0; i < waitQueue.length; i++) { - waitQueue[i](); - } - waitQueue = []; - }); - } - - return function() { - var passed = false; - waitForTick(function() { - passed = true; - }); - return function(callback) { - passed ? callback() : waitForTick(callback); - }; - }; - }]; -}; - -var $$AnimateRunnerFactoryProvider = function() { - this.$get = ['$q', '$sniffer', '$$animateAsyncRun', '$document', '$timeout', - function($q, $sniffer, $$animateAsyncRun, $document, $timeout) { - - var INITIAL_STATE = 0; - var DONE_PENDING_STATE = 1; - var DONE_COMPLETE_STATE = 2; - - AnimateRunner.chain = function(chain, callback) { - var index = 0; - - next(); - function next() { - if (index === chain.length) { - callback(true); - return; - } - - chain[index](function(response) { - if (response === false) { - callback(false); - return; - } - index++; - next(); - }); - } - }; - - AnimateRunner.all = function(runners, callback) { - var count = 0; - var status = true; - forEach(runners, function(runner) { - runner.done(onProgress); - }); - - function onProgress(response) { - status = status && response; - if (++count === runners.length) { - callback(status); - } - } - }; - - function AnimateRunner(host) { - this.setHost(host); - - var rafTick = $$animateAsyncRun(); - var timeoutTick = function(fn) { - $timeout(fn, 0, false); - }; - - this._doneCallbacks = []; - this._tick = function(fn) { - var doc = $document[0]; - - // the document may not be ready or attached - // to the module for some internal tests - if (doc && doc.hidden) { - timeoutTick(fn); - } else { - rafTick(fn); - } - }; - this._state = 0; - } - - AnimateRunner.prototype = { - setHost: function(host) { - this.host = host || {}; - }, - - done: function(fn) { - if (this._state === DONE_COMPLETE_STATE) { - fn(); - } else { - this._doneCallbacks.push(fn); - } - }, - - progress: noop, - - getPromise: function() { - if (!this.promise) { - var self = this; - this.promise = $q(function(resolve, reject) { - self.done(function(status) { - status === false ? reject() : resolve(); - }); - }); - } - return this.promise; - }, - - then: function(resolveHandler, rejectHandler) { - return this.getPromise().then(resolveHandler, rejectHandler); - }, - - 'catch': function(handler) { - return this.getPromise()['catch'](handler); - }, - - 'finally': function(handler) { - return this.getPromise()['finally'](handler); - }, - - pause: function() { - if (this.host.pause) { - this.host.pause(); - } - }, - - resume: function() { - if (this.host.resume) { - this.host.resume(); - } - }, - - end: function() { - if (this.host.end) { - this.host.end(); - } - this._resolve(true); - }, - - cancel: function() { - if (this.host.cancel) { - this.host.cancel(); - } - this._resolve(false); - }, - - complete: function(response) { - var self = this; - if (self._state === INITIAL_STATE) { - self._state = DONE_PENDING_STATE; - self._tick(function() { - self._resolve(response); - }); - } - }, - - _resolve: function(response) { - if (this._state !== DONE_COMPLETE_STATE) { - forEach(this._doneCallbacks, function(fn) { - fn(response); - }); - this._doneCallbacks.length = 0; - this._state = DONE_COMPLETE_STATE; - } - } - }; - - return AnimateRunner; - }]; -}; - /** * @ngdoc service * @name $animateCss @@ -5644,18 +5424,37 @@ var $$AnimateRunnerFactoryProvider = function() { * Click here {@link ngAnimate.$animateCss to read the documentation for $animateCss}. */ var $CoreAnimateCssProvider = function() { - this.$get = ['$$rAF', '$q', '$$AnimateRunner', function($$rAF, $q, $$AnimateRunner) { + this.$get = ['$$rAF', '$q', function($$rAF, $q) { - return function(element, initialOptions) { - // all of the animation functions should create - // a copy of the options data, however, if a - // parent service has already created a copy then - // we should stick to using that - var options = initialOptions || {}; - if (!options.$$prepared) { - options = copy(options); + var RAFPromise = function() {}; + RAFPromise.prototype = { + done: function(cancel) { + this.defer && this.defer[cancel === true ? 'reject' : 'resolve'](); + }, + end: function() { + this.done(); + }, + cancel: function() { + this.done(true); + }, + getPromise: function() { + if (!this.defer) { + this.defer = $q.defer(); + } + return this.defer.promise; + }, + then: function(f1,f2) { + return this.getPromise().then(f1,f2); + }, + 'catch': function(f1) { + return this.getPromise()['catch'](f1); + }, + 'finally': function(f1) { + return this.getPromise()['finally'](f1); } + }; + return function(element, options) { // there is no point in applying the styles since // there is no animation that goes on at all in // this version of $animateCss. @@ -5668,8 +5467,7 @@ var $CoreAnimateCssProvider = function() { options.from = null; } - /* jshint newcap: false*/ - var closed, runner = new $$AnimateRunner(); + var closed, runner = new RAFPromise(); return { start: run, end: run @@ -5677,16 +5475,16 @@ var $CoreAnimateCssProvider = function() { function run() { $$rAF(function() { - applyAnimationContents(); + close(); if (!closed) { - runner.complete(); + runner.done(); } closed = true; }); return runner; } - function applyAnimationContents() { + function close() { if (options.addClass) { element.addClass(options.addClass); options.addClass = null; @@ -6632,38 +6430,35 @@ function $TemplateCacheProvider() { * is bound to the parent scope, via matching attributes on the directive's element: * * * `@` or `@attr` - bind a local scope property to the value of DOM attribute. The result is - * always a string since DOM attributes are strings. If no `attr` name is specified then the - * attribute name is assumed to be the same as the local name. Given `` and the isolate scope definition `scope: { localName:'@myAttr' }`, - * the directive's scope property `localName` will reflect the interpolated value of `hello - * {{name}}`. As the `name` attribute changes so will the `localName` property on the directive's - * scope. The `name` is read from the parent scope (not the directive's scope). - * - * * `=` or `=attr` - set up a bidirectional binding between a local scope property and an expression - * passed via the attribute `attr`. The expression is evaluated in the context of the parent scope. - * If no `attr` name is specified then the attribute name is assumed to be the same as the local - * name. Given `` and the isolate scope definition `scope: { - * localModel: '=myAttr' }`, the property `localModel` on the directive's scope will reflect the - * value of `parentModel` on the parent scope. Changes to `parentModel` will be reflected in - * `localModel` and vice versa. Optional attributes should be marked as such with a question mark: - * `=?` or `=?attr`. If the binding expression is non-assignable, or if the attribute isn't - * optional and doesn't exist, an exception ({@link error/$compile/nonassign `$compile:nonassign`}) - * will be thrown upon discovering changes to the local value, since it will be impossible to sync - * them back to the parent scope. By default, the {@link ng.$rootScope.Scope#$watch `$watch`} - * method is used for tracking changes, and the equality check is based on object identity. - * However, if an object literal or an array literal is passed as the binding expression, the - * equality check is done by value (using the {@link angular.equals} function). It's also possible - * to watch the evaluated value shallowly with {@link ng.$rootScope.Scope#$watchCollection - * `$watchCollection`}: use `=*` or `=*attr` (`=*?` or `=*?attr` if the attribute is optional). - * - * * `&` or `&attr` - provides a way to execute an expression in the context of the parent scope. If - * no `attr` name is specified then the attribute name is assumed to be the same as the local name. - * Given `` and the isolate scope definition `scope: { - * localFn:'&myAttr' }`, the isolate scope property `localFn` will point to a function wrapper for - * the `count = count + value` expression. Often it's desirable to pass data from the isolated scope - * via an expression to the parent scope. This can be done by passing a map of local variable names - * and values into the expression wrapper fn. For example, if the expression is `increment(amount)` - * then we can specify the amount value by calling the `localFn` as `localFn({amount: 22})`. + * always a string since DOM attributes are strings. If no `attr` name is specified then the + * attribute name is assumed to be the same as the local name. + * Given `` and widget definition + * of `scope: { localName:'@myAttr' }`, then widget scope property `localName` will reflect + * the interpolated value of `hello {{name}}`. As the `name` attribute changes so will the + * `localName` property on the widget scope. The `name` is read from the parent scope (not + * component scope). + * + * * `=` or `=attr` - set up bi-directional binding between a local scope property and the + * parent scope property of name defined via the value of the `attr` attribute. If no `attr` + * name is specified then the attribute name is assumed to be the same as the local name. + * Given `` and widget definition of + * `scope: { localModel:'=myAttr' }`, then widget scope property `localModel` will reflect the + * value of `parentModel` on the parent scope. Any changes to `parentModel` will be reflected + * in `localModel` and any changes in `localModel` will reflect in `parentModel`. If the parent + * scope property doesn't exist, it will throw a NON_ASSIGNABLE_MODEL_EXPRESSION exception. You + * can avoid this behavior using `=?` or `=?attr` in order to flag the property as optional. If + * you want to shallow watch for changes (i.e. $watchCollection instead of $watch) you can use + * `=*` or `=*attr` (`=*?` or `=*?attr` if the property is optional). + * + * * `&` or `&attr` - provides a way to execute an expression in the context of the parent scope. + * If no `attr` name is specified then the attribute name is assumed to be the same as the + * local name. Given `` and widget definition of + * `scope: { localFn:'&myAttr' }`, then isolate scope property `localFn` will point to + * a function wrapper for the `count = count + value` expression. Often it's desirable to + * pass data from the isolated scope via an expression to the parent scope, this can be + * done by passing a map of local variable names and values into the expression wrapper fn. + * For example, if the expression is `increment(amount)` then we can specify the amount value + * by calling the `localFn` as `localFn({amount: 22})`. * * In general it's possible to apply more than one directive to one element, but there might be limitations * depending on the type of scope required by the directives. The following points will help explain these limitations. @@ -6681,23 +6476,10 @@ function $TemplateCacheProvider() { * * * #### `bindToController` - * This property is used to bind scope properties directly to the controller. It can be either - * `true` or an object hash with the same format as the `scope` property. Additionally, a controller - * alias must be set, either by using `controllerAs: 'myAlias'` or by specifying the alias in the controller - * definition: `controller: 'myCtrl as myAlias'`. - * - * When an isolate scope is used for a directive (see above), `bindToController: true` will + * When an isolate scope is used for a component (see above), and `controllerAs` is used, `bindToController: true` will * allow a component to have its properties bound to the controller, rather than to scope. When the controller * is instantiated, the initial values of the isolate scope bindings are already available. * - * It is also possible to set `bindToController` to an object hash with the same format as the `scope` property. - * This will set up the scope bindings to the controller directly. Note that `scope` can still be used - * to define which kind of scope is created. By default, no scope is created. Use `scope: {}` to create an isolate - * scope (useful for component directives). - * - * If both `bindToController` and `scope` are defined and have object hashes, `bindToController` overrides `scope`. - * - * * #### `controller` * Controller constructor function. The controller is instantiated before the * pre-linking phase and can be accessed by other directives (see @@ -6854,7 +6636,7 @@ function $TemplateCacheProvider() { *
* **Note:** The compile function cannot handle directives that recursively use themselves in their - * own templates or compile functions. Compiling these directives results in an infinite loop and + * own templates or compile functions. Compiling these directives results in an infinite loop and a * stack overflow errors. * * This can be avoided by manually using $compile in the postLink function to imperatively compile @@ -7033,19 +6815,19 @@ function $TemplateCacheProvider() { * * The `$parent` scope hierarchy will look like this: * - ``` - - $rootScope - - isolate - - transclusion - ``` + * ``` + * - $rootScope + * - isolate + * - transclusion + * ``` * * but the scopes will inherit prototypically from different scopes to their `$parent`. * - ``` - - $rootScope - - transclusion - - isolate - ``` + * ``` + * - $rootScope + * - transclusion + * - isolate + * ``` * * * ### Attributes @@ -7053,9 +6835,10 @@ function $TemplateCacheProvider() { * The {@link ng.$compile.directive.Attributes Attributes} object - passed as a parameter in the * `link()` or `compile()` functions. It has a variety of uses. * - * * *Accessing normalized attribute names:* Directives like 'ngBind' can be expressed in many ways: - * 'ng:bind', `data-ng-bind`, or 'x-ng-bind'. The attributes object allows for normalized access - * to the attributes. + * accessing *Normalized attribute names:* + * Directives like 'ngBind' can be expressed in many ways: 'ng:bind', `data-ng-bind`, or 'x-ng-bind'. + * the attributes object allows for normalized access to + * the attributes. * * * *Directive inter-communication:* All directives share the same instance of the attributes * object which allows the directives to use the attributes object as inter directive @@ -7176,15 +6959,8 @@ function $TemplateCacheProvider() { * directives; if given, it will be passed through to the link functions of * directives found in `element` during compilation. * * `transcludeControllers` - an object hash with keys that map controller names - * to a hash with the key `instance`, which maps to the controller instance; - * if given, it will make the controllers available to directives on the compileNode: - * ``` - * { - * parent: { - * instance: parentControllerInstance - * } - * } - * ``` + * to controller instances; if given, it will make the controllers + * available to directives. * * `futureParentElement` - defines the parent to which the `cloneAttachFn` will add * the cloned elements; only needed for transcludes that are allowed to contain non html * elements (e.g. SVG elements). See also the directive.controller property. @@ -7243,7 +7019,6 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { // The assumption is that future DOM event attribute names will begin with // 'on' and be composed of only English letters. var EVENT_HANDLER_ATTR_REGEXP = /^(on[a-z]+|formaction)$/; - var bindingCache = createMap(); function parseIsolateBindings(scope, directiveName, isController) { var LOCAL_REGEXP = /^\s*([@&]|=(\*?))(\??)\s*(\w*)\s*$/; @@ -7251,10 +7026,6 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { var bindings = {}; forEach(scope, function(definition, scopeName) { - if (definition in bindingCache) { - bindings[scopeName] = bindingCache[definition]; - return; - } var match = definition.match(LOCAL_REGEXP); if (!match) { @@ -7272,9 +7043,6 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { optional: match[3] === '?', attrName: match[4] || scopeName }; - if (match[4]) { - bindingCache[definition] = bindings[scopeName]; - } }); return bindings; @@ -7367,6 +7135,11 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { directive.name = directive.name || name; directive.require = directive.require || (directive.controller && directive.name); directive.restrict = directive.restrict || 'EA'; + var bindings = directive.$$bindings = + parseDirectiveBindings(directive, directive.name); + if (isObject(bindings.isolateScope)) { + directive.$$isolateBindings = bindings.isolateScope; + } directive.$$moduleName = directiveFactory.$$moduleName; directives.push(directive); } catch (e) { @@ -7476,9 +7249,9 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { this.$get = [ '$injector', '$interpolate', '$exceptionHandler', '$templateRequest', '$parse', - '$controller', '$rootScope', '$sce', '$animate', '$$sanitizeUri', + '$controller', '$rootScope', '$document', '$sce', '$animate', '$$sanitizeUri', function($injector, $interpolate, $exceptionHandler, $templateRequest, $parse, - $controller, $rootScope, $sce, $animate, $$sanitizeUri) { + $controller, $rootScope, $document, $sce, $animate, $$sanitizeUri) { var Attributes = function(element, attributesToCopy) { if (attributesToCopy) { @@ -7690,8 +7463,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { * @param {string} key Normalized key. (ie ngAttribute) . * @param {function(interpolatedValue)} fn Function that will be called whenever the interpolated value of the attribute changes. - * See the {@link guide/interpolation#how-text-and-attribute-bindings-work Interpolation - * guide} for more info. + * See the {@link guide/directive#text-and-attribute-bindings Directives} guide for more info. * @returns {function()} Returns a deregistration function for this observer. */ $observe: function(key, fn) { @@ -7726,7 +7498,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { var startSymbol = $interpolate.startSymbol(), endSymbol = $interpolate.endSymbol(), - denormalizeTemplate = (startSymbol == '{{' && endSymbol == '}}') + denormalizeTemplate = (startSymbol == '{{' || endSymbol == '}}') ? identity : function denormalizeTemplate(template) { return template.replace(/\{\{/g, startSymbol).replace(/}}/g, endSymbol); @@ -7770,19 +7542,13 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { // modify it. $compileNodes = jqLite($compileNodes); } - - var NOT_EMPTY = /\S+/; - // 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 - for (var i = 0, len = $compileNodes.length; i < len; i++) { - var domNode = $compileNodes[i]; - - if (domNode.nodeType === NODE_TYPE_TEXT && domNode.nodeValue.match(NOT_EMPTY) /* non-empty */) { - jqLiteWrapNode(domNode, $compileNodes[i] = document.createElement('span')); + forEach($compileNodes, function(node, index) { + if (node.nodeType == NODE_TYPE_TEXT && node.nodeValue.match(/\S+/) /* non-empty */ ) { + $compileNodes[index] = jqLite(node).wrap('').parent()[0]; } - } - + }); var compositeLinkFn = compileNodes($compileNodes, transcludeFn, $compileNodes, maxPriority, ignoreDirective, previousCompileContext); @@ -8461,12 +8227,15 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { var controllerInstance = $controller(controller, locals, true, directive.controllerAs); - // For directives with element transclusion the element is a comment. - // In this case .data will not attach any data. + // For directives with element transclusion the element is a comment, + // but jQuery .data doesn't support attaching data to comment nodes as it's hard to + // clean up (http://bugs.jquery.com/ticket/8335). // Instead, we save the controllers for the element in a local hash and attach to .data // later, once we have the actual element. elementControllers[directive.name] = controllerInstance; - $element.data('$' + directive.name + 'Controller', controllerInstance.instance); + if (!hasElementTranscludeDirective) { + $element.data('$' + directive.name + 'Controller', controllerInstance.instance); + } } return elementControllers; } @@ -8635,13 +8404,6 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { if (startAttrName) { directive = inherit(directive, {$$start: startAttrName, $$end: endAttrName}); } - if (!directive.$$bindings) { - var bindings = directive.$$bindings = - parseDirectiveBindings(directive, directive.name); - if (isObject(bindings.isolateScope)) { - directive.$$isolateBindings = bindings.isolateScope; - } - } tDirectives.push(directive); match = directive; } @@ -9106,15 +8868,10 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { } }); attrs.$$observers[attrName].$$scope = scope; - lastValue = attrs[attrName]; - if (isString(lastValue)) { + if (isString(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 - destination[scopeName] = $interpolate(lastValue)(scope); - } else if (isBoolean(lastValue)) { - // If the attributes is one of the BOOLEAN_ATTR then Angular will have converted - // the value to boolean rather than a string, so we special case this situation - destination[scopeName] = lastValue; + destination[scopeName] = $interpolate(attrs[attrName])(scope); } break; @@ -9135,8 +8892,8 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { // reset the change, or we will throw this exception on every $digest lastValue = destination[scopeName] = parentGet(scope); throw $compileMinErr('nonassign', - "Expression '{0}' in attribute '{1}' used with directive '{2}' is non-assignable!", - attrs[attrName], attrName, directive.name); + "Expression '{0}' used with directive '{1}' is non-assignable!", + attrs[attrName], directive.name); }; lastValue = destination[scopeName] = parentGet(scope); var parentValueWatch = function parentValueWatch(parentValue) { @@ -9290,7 +9047,7 @@ function removeComments(jqNodes) { var $controllerMinErr = minErr('$controller'); -var CNTRL_REG = /^(\S+)(\s+as\s+([\w$]+))?$/; +var CNTRL_REG = /^(\S+)(\s+as\s+(\w+))?$/; function identifierForController(controller, ident) { if (ident && isString(ident)) return ident; if (isString(controller)) { @@ -9817,9 +9574,10 @@ function $HttpProvider() { * * Object containing default values for all {@link ng.$http $http} requests. * - * - **`defaults.cache`** - {boolean|Object} - A boolean value or object created with - * {@link ng.$cacheFactory `$cacheFactory`} to enable or disable caching of HTTP responses - * by default. See {@link $http#caching $http Caching} for more information. + * - **`defaults.cache`** - {Object} - an object built with {@link ng.$cacheFactory `$cacheFactory`} + * that will provide the cache for all requests who set their `cache` property to `true`. + * If you set the `defaults.cache = false` then only requests that specify their own custom + * cache object will be cached. See {@link $http#caching $http Caching} for more information. * * - **`defaults.xsrfCookieName`** - {string} - Name of cookie containing the XSRF token. * Defaults value is `'XSRF-TOKEN'`. @@ -10110,15 +9868,6 @@ function $HttpProvider() { * the transformed value (`function(data, headersGetter, status)`) or an array of such transformation functions, * which allows you to `push` or `unshift` a new transformation function into the transformation chain. * - *
- * **Note:** Angular does not make a copy of the `data` parameter before it is passed into the `transformRequest` pipeline. - * That means changes to the properties of `data` are not local to the transform function (since Javascript passes objects by reference). - * For example, when calling `$http.get(url, $scope.myObject)`, modifications to the object's properties in a transformRequest - * function will be reflected on the scope and in any templates where the object is data-bound. - * To prevent his, transform functions should have no side-effects. - * If you need to modify properties, it is recommended to make a copy of the data, or create new object to return. - *
- * * ### Default Transformations * * The `$httpProvider` provider and `$http` service expose `defaults.transformRequest` and @@ -10176,35 +9925,26 @@ function $HttpProvider() { * * ## Caching * - * {@link ng.$http `$http`} responses are not cached by default. To enable caching, you must - * set the config.cache value or the default cache value to TRUE or to a cache object (created - * with {@link ng.$cacheFactory `$cacheFactory`}). If defined, the value of config.cache takes - * precedence over the default cache value. - * - * In order to: - * * cache all responses - set the default cache value to TRUE or to a cache object - * * cache a specific response - set config.cache value to TRUE or to a cache object - * - * If caching is enabled, but neither the default cache nor config.cache are set to a cache object, - * then the default `$cacheFactory($http)` object is used. + * To enable caching, set the request configuration `cache` property to `true` (to use default + * cache) or to a custom cache object (built with {@link ng.$cacheFactory `$cacheFactory`}). + * When the cache is enabled, `$http` stores the response from the server in the specified + * cache. The next time the same request is made, the response is served from the cache without + * sending a request to the server. * - * The default cache value can be set by updating the - * {@link ng.$http#defaults `$http.defaults.cache`} property or the - * {@link $httpProvider#defaults `$httpProvider.defaults.cache`} property. + * Note that even if the response is served from cache, delivery of the data is asynchronous in + * the same way that real requests are. * - * When caching is enabled, {@link ng.$http `$http`} stores the response from the server using - * the relevant cache object. The next time the same request is made, the response is returned - * from the cache without sending a request to the server. + * 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 from the first request. * - * Take note that: - * - * * Only GET and JSONP requests are cached. - * * The cache key is the request URL including search parameters; headers are not considered. - * * Cached responses are returned asynchronously, in the same way as responses from the server. - * * If multiple identical requests are made using the same cache, which is not yet populated, - * one request will be made to the server and remaining requests will return the same response. - * * A cache-control header on the response does not affect if or how responses are cached. + * You can change the default cache to a new object (built with + * {@link ng.$cacheFactory `$cacheFactory`}) by updating the + * {@link ng.$http#defaults `$http.defaults.cache`} property. All requests who set + * their `cache` property to `true` will now use this cache object. * + * If you set the default cache to `false` then only requests that specify their own custom + * cache object will be cached. * * ## Interceptors * @@ -10326,13 +10066,13 @@ function $HttpProvider() { * * ### Cross Site Request Forgery (XSRF) Protection * - * [XSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery) is an attack technique by - * which the attacker can trick an authenticated user into unknowingly executing actions on your - * website. Angular provides a mechanism to counter XSRF. When performing XHR requests, the - * $http service reads a token from a cookie (by default, `XSRF-TOKEN`) and sets it as an 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. - * The header will not be set for cross-domain requests. + * [XSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery) is a technique by which + * 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 + * (by default, `XSRF-TOKEN`) and sets it as an 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. The header will not be set for + * cross-domain requests. * * To take advantage of this, your server needs to set a token in a JavaScript readable session * cookie called `XSRF-TOKEN` on the first HTTP GET request. On subsequent XHR requests the @@ -10374,7 +10114,7 @@ function $HttpProvider() { * transform function or an array of such functions. The transform function takes the http * response body, headers and status and returns its transformed (typically deserialized) version. * See {@link ng.$http#overriding-the-default-transformations-per-request - * Overriding the Default Transformations} + * Overriding the Default TransformationjqLiks} * - **paramSerializer** - `{string|function(Object):string}` - A function used to * prepare the string representation of request parameters (specified as an object). * If specified as string, it is interpreted as function registered with the @@ -10382,9 +10122,10 @@ function $HttpProvider() { * by registering it as a {@link auto.$provide#service service}. * The default serializer is the {@link $httpParamSerializer $httpParamSerializer}; * alternatively, you can use the {@link $httpParamSerializerJQLike $httpParamSerializerJQLike} - * - **cache** – `{boolean|Object}` – A boolean value or object created with - * {@link ng.$cacheFactory `$cacheFactory`} to enable or disable caching of the HTTP response. - * See {@link $http#caching $http Caching} for more information. + * - **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|Promise}` – timeout in milliseconds, or {@link ng.$q promise} * that should abort the request when resolved. * - **withCredentials** - `{boolean}` - whether to set the `withCredentials` flag on the @@ -10494,10 +10235,6 @@ function $HttpProvider() { throw minErr('$http')('badreq', 'Http request configuration must be an object. Received: {0}', requestConfig); } - if (!isString(requestConfig.url)) { - throw minErr('$http')('badreq', 'Http request configuration url must be a string. Received: {0}', requestConfig.url); - } - var config = extend({ method: 'get', transformRequest: defaults.transformRequest, @@ -11110,7 +10847,7 @@ $interpolateMinErr.interr = function(text, err) { * Used for configuring the interpolation markup. Defaults to `{{` and `}}`. * * @example - + -
+
//demo.label//
@@ -13781,9 +13518,6 @@ ASTCompiler.prototype = { intoId = intoId || this.nextId(); self.recurse(ast.object, left, undefined, function() { self.if_(self.notNull(left), function() { - if (create && create !== 1) { - self.addEnsureSafeAssignContext(left); - } if (ast.computed) { right = self.nextId(); self.recurse(ast.property, right); @@ -13865,7 +13599,7 @@ ASTCompiler.prototype = { right = this.nextId(); left = {}; if (!isAssignable(ast.left)) { - throw $parseMinErr('lval', 'Trying to assign a value to a non l-value'); + throw $parseMinErr('lval', 'Trying to assing a value to a non l-value'); } this.recurse(ast.left, undefined, left, function() { self.if_(self.notNull(left.context), function() { @@ -14398,11 +14132,8 @@ ASTInterpreter.prototype = { rhs = right(scope, locals, assign, inputs); rhs = getStringValue(rhs); ensureSafeMemberName(rhs, expression); - if (create && create !== 1) { - ensureSafeAssignContext(lhs); - if (lhs && !(lhs[rhs])) { - lhs[rhs] = {}; - } + if (create && create !== 1 && lhs && !(lhs[rhs])) { + lhs[rhs] = {}; } value = lhs[rhs]; ensureSafeObject(value, expression); @@ -14417,11 +14148,8 @@ ASTInterpreter.prototype = { nonComputedMember: function(left, right, expensiveChecks, context, create, expression) { return function(scope, locals, assign, inputs) { var lhs = left(scope, locals, assign, inputs); - if (create && create !== 1) { - ensureSafeAssignContext(lhs); - if (lhs && !(lhs[right])) { - lhs[right] = {}; - } + if (create && create !== 1 && lhs && !(lhs[right])) { + lhs[right] = {}; } var value = lhs != null ? lhs[right] : undefined; if (expensiveChecks || isPossiblyDangerousMemberName(right)) { @@ -14462,6 +14190,9 @@ Parser.prototype = { } }; +var getterFnCacheDefault = createMap(); +var getterFnCacheExpensive = createMap(); + function isPossiblyDangerousMemberName(name) { return name == 'constructor'; } @@ -14537,19 +14268,10 @@ function $ParseProvider() { csp: noUnsafeEval, expensiveChecks: true }; - var runningChecksEnabled = false; - - $parse.$$runningExpensiveChecks = function() { - return runningChecksEnabled; - }; - - return $parse; - function $parse(exp, interceptorFn, expensiveChecks) { + return function $parse(exp, interceptorFn, expensiveChecks) { var parsedExpression, oneTime, cacheKey; - expensiveChecks = expensiveChecks || runningChecksEnabled; - switch (typeof exp) { case 'string': exp = exp.trim(); @@ -14575,9 +14297,6 @@ function $ParseProvider() { } else if (parsedExpression.inputs) { parsedExpression.$$watchDelegate = inputsWatchDelegate; } - if (expensiveChecks) { - parsedExpression = expensiveChecksInterceptor(parsedExpression); - } cache[cacheKey] = parsedExpression; } return addInterceptor(parsedExpression, interceptorFn); @@ -14586,33 +14305,9 @@ function $ParseProvider() { return addInterceptor(exp, interceptorFn); default: - return addInterceptor(noop, interceptorFn); - } - } - - function expensiveChecksInterceptor(fn) { - if (!fn) return fn; - expensiveCheckFn.$$watchDelegate = fn.$$watchDelegate; - expensiveCheckFn.assign = expensiveChecksInterceptor(fn.assign); - expensiveCheckFn.constant = fn.constant; - expensiveCheckFn.literal = fn.literal; - for (var i = 0; fn.inputs && i < fn.inputs.length; ++i) { - fn.inputs[i] = expensiveChecksInterceptor(fn.inputs[i]); - } - expensiveCheckFn.inputs = fn.inputs; - - return expensiveCheckFn; - - function expensiveCheckFn(scope, locals, assign, inputs) { - var expensiveCheckOldValue = runningChecksEnabled; - runningChecksEnabled = true; - try { - return fn(scope, locals, assign, inputs); - } finally { - runningChecksEnabled = expensiveCheckOldValue; - } + return noop; } - } + }; function expressionInputDirtyCheck(newValue, oldValueOfValue) { @@ -16144,7 +15839,7 @@ function $RootScopeProvider() { * */ $digest: function() { - var watch, value, last, fn, get, + var watch, value, last, watchers, length, dirty, ttl = TTL, @@ -16190,8 +15885,7 @@ function $RootScopeProvider() { // Most common watches are on primitives, in which case we can short // circuit it with === operator, only when === fails do we use .equals if (watch) { - get = watch.get; - if ((value = get(current)) !== (last = watch.last) && + if ((value = watch.get(current)) !== (last = watch.last) && !(watch.eq ? equals(value, last) : (typeof value === 'number' && typeof last === 'number' @@ -16199,8 +15893,7 @@ function $RootScopeProvider() { dirty = true; lastDirtyWatch = watch; watch.last = watch.eq ? copy(value, null) : value; - fn = watch.fn; - fn(value, ((last === initWatchVal) ? value : last), current); + watch.fn(value, ((last === initWatchVal) ? value : last), current); if (ttl < 5) { logIdx = 4 - ttl; if (!watchLog[logIdx]) watchLog[logIdx] = []; @@ -16400,7 +16093,7 @@ function $RootScopeProvider() { }); } - asyncQueue.push({scope: this, expression: $parse(expr), locals: locals}); + asyncQueue.push({scope: this, expression: expr, locals: locals}); }, $$postDigest: function(fn) { @@ -16492,7 +16185,6 @@ function $RootScopeProvider() { $applyAsync: function(expr) { var scope = this; expr && applyAsyncQueue.push($applyAsyncExpression); - expr = $parse(expr); scheduleApplyAsync(); function $applyAsyncExpression() { @@ -16768,21 +16460,6 @@ function $RootScopeProvider() { } /** - * @ngdoc service - * @name $rootElement - * - * @description - * The root element of Angular application. This is either the element where {@link - * ng.directive:ngApp ngApp} was declared or the element passed into - * {@link angular.bootstrap}. The element represents the root element of application. It is also the - * location where the application's {@link auto.$injector $injector} service gets - * published, and can be retrieved using `$rootElement.injector()`. - */ - - -// the implementation is in angular.bootstrap - -/** * @description * Private service to sanitize uris for links and images. Used by $compile and $sanitize. */ @@ -16996,15 +16673,13 @@ function $SceDelegateProvider() { * @kind function * * @param {Array=} whitelist When provided, replaces the resourceUrlWhitelist with the value - * provided. This must be an array or null. A snapshot of this array is used so further - * changes to the array are ignored. + * provided. This must be an array or null. A snapshot of this array is used so further + * changes to the array are ignored. * - * Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items - * allowed in this array. + * Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items + * allowed in this array. * - *
- * **Note:** an empty whitelist array will block all URLs! - *
+ * Note: **an empty whitelist array will block all URLs**! * * @return {Array} the currently set whitelist array. * @@ -17027,17 +16702,17 @@ function $SceDelegateProvider() { * @kind function * * @param {Array=} blacklist When provided, replaces the resourceUrlBlacklist with the value - * provided. This must be an array or null. A snapshot of this array is used so further - * changes to the array are ignored. + * provided. This must be an array or null. A snapshot of this array is used so further + * changes to the array are ignored. * - * Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items - * allowed in this array. + * Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items + * allowed in this array. * - * The typical usage for the blacklist is to **block - * [open redirects](http://cwe.mitre.org/data/definitions/601.html)** served by your domain as - * these would otherwise be trusted but actually return content from the redirected domain. + * The typical usage for the blacklist is to **block + * [open redirects](http://cwe.mitre.org/data/definitions/601.html)** served by your domain as + * 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. * @@ -18221,8 +17896,8 @@ function $TimeoutProvider() { * @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. * @param {...*=} Pass additional parameters to the executed function. - * @returns {Promise} Promise that will be resolved when the timeout is reached. The promise - * will be resolved with the return value of the `fn` function. + * @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) { @@ -18898,10 +18573,6 @@ function getTypeForFilter(val) { return (val === null) ? 'null' : typeof val; } -var MAX_DIGITS = 22; -var DECIMAL_SEP = '.'; -var ZERO_CHAR = '0'; - /** * @ngdoc filter * @name currency @@ -18983,7 +18654,7 @@ function currencyFilter($locale) { * Formats a number as text. * * If the input is null or undefined, it will just be returned. - * If the input is infinite (Infinity or -Infinity), the Infinity symbol '∞' or '-∞' is returned, respectively. + * If the input is infinite (Infinity/-Infinity) the Infinity symbol '∞' is returned. * If the input is not a number an empty string is returned. * * @@ -18991,7 +18662,7 @@ function currencyFilter($locale) { * @param {(number|string)=} fractionSize Number of decimal places to round the number to. * If this is not provided then the fraction size is computed from the current locale's number * formatting pattern. In the case of the default locale, it will be 3. - * @returns {string} Number rounded to fractionSize and places a “,” after each third digit. + * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit. * * @example @@ -19026,6 +18697,8 @@ function currencyFilter($locale) { */ + + numberFilter.$inject = ['$locale']; function numberFilter($locale) { var formats = $locale.NUMBER_FORMATS; @@ -19039,194 +18712,93 @@ function numberFilter($locale) { }; } -/** - * Parse a number (as a string) into three components that can be used - * for formatting the number. - * - * (Significant bits of this parse algorithm came from https://github.com/MikeMcl/big.js/) - * - * @param {string} numStr The number to parse - * @return {object} An object describing this number, containing the following keys: - * - d : an array of digits containing leading zeros as necessary - * - i : the number of the digits in `d` that are to the left of the decimal point - * - e : the exponent for numbers that would need more than `MAX_DIGITS` digits in `d` - * - */ -function parse(numStr) { - var exponent = 0, digits, numberOfIntegerDigits; - var i, j, zeros; - - // Decimal point? - if ((numberOfIntegerDigits = numStr.indexOf(DECIMAL_SEP)) > -1) { - numStr = numStr.replace(DECIMAL_SEP, ''); - } - - // Exponential form? - if ((i = numStr.search(/e/i)) > 0) { - // Work out the exponent. - if (numberOfIntegerDigits < 0) numberOfIntegerDigits = i; - numberOfIntegerDigits += +numStr.slice(i + 1); - numStr = numStr.substring(0, i); - } else if (numberOfIntegerDigits < 0) { - // There was no decimal point or exponent so it is an integer. - numberOfIntegerDigits = numStr.length; - } - - // Count the number of leading zeros. - for (i = 0; numStr.charAt(i) == ZERO_CHAR; i++) {/* jshint noempty: false */} - - if (i == (zeros = numStr.length)) { - // The digits are all zero. - digits = [0]; - numberOfIntegerDigits = 1; - } else { - // Count the number of trailing zeros - zeros--; - while (numStr.charAt(zeros) == ZERO_CHAR) zeros--; - - // Trailing zeros are insignificant so ignore them - numberOfIntegerDigits -= i; - digits = []; - // Convert string to array of digits without leading/trailing zeros. - for (j = 0; i <= zeros; i++, j++) { - digits[j] = +numStr.charAt(i); - } - } +var DECIMAL_SEP = '.'; +function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) { + if (isObject(number)) return ''; - // If the number overflows the maximum allowed digits then use an exponent. - if (numberOfIntegerDigits > MAX_DIGITS) { - digits = digits.splice(0, MAX_DIGITS - 1); - exponent = numberOfIntegerDigits - 1; - numberOfIntegerDigits = 1; - } + var isNegative = number < 0; + number = Math.abs(number); - return { d: digits, e: exponent, i: numberOfIntegerDigits }; -} + var isInfinity = number === Infinity; + if (!isInfinity && !isFinite(number)) return ''; -/** - * Round the parsed number to the specified number of decimal places - * This function changed the parsedNumber in-place - */ -function roundNumber(parsedNumber, fractionSize, minFrac, maxFrac) { - var digits = parsedNumber.d; - var fractionLen = digits.length - parsedNumber.i; + var numStr = number + '', + formatedText = '', + hasExponent = false, + parts = []; - // determine fractionSize if it is not specified; `+fractionSize` converts it to a number - fractionSize = (isUndefined(fractionSize)) ? Math.min(Math.max(minFrac, fractionLen), maxFrac) : +fractionSize; + if (isInfinity) formatedText = '\u221e'; - // The index of the digit to where rounding is to occur - var roundAt = fractionSize + parsedNumber.i; - var digit = digits[roundAt]; - - if (roundAt > 0) { - digits.splice(roundAt); + if (!isInfinity && numStr.indexOf('e') !== -1) { + var match = numStr.match(/([\d\.]+)e(-?)(\d+)/); + if (match && match[2] == '-' && match[3] > fractionSize + 1) { + number = 0; } else { - // We rounded to zero so reset the parsedNumber - parsedNumber.i = 1; - digits.length = roundAt = fractionSize + 1; - for (var i=0; i < roundAt; i++) digits[i] = 0; + formatedText = numStr; + hasExponent = true; } + } - if (digit >= 5) digits[roundAt - 1]++; - - // Pad out with zeros to get the required fraction length - for (; fractionLen < fractionSize; fractionLen++) digits.push(0); - + if (!isInfinity && !hasExponent) { + var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length; - // Do any carrying, e.g. a digit was rounded up to 10 - var carry = digits.reduceRight(function(carry, d, i, digits) { - d = d + carry; - digits[i] = d % 10; - return Math.floor(d / 10); - }, 0); - if (carry) { - digits.unshift(carry); - parsedNumber.i++; + // determine fractionSize if it is not specified + if (isUndefined(fractionSize)) { + fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac); } -} - -/** - * Format a number into a string - * @param {number} number The number to format - * @param {{ - * minFrac, // the minimum number of digits required in the fraction part of the number - * maxFrac, // the maximum number of digits required in the fraction part of the number - * gSize, // number of digits in each group of separated digits - * lgSize, // number of digits in the last group of digits before the decimal separator - * negPre, // the string to go in front of a negative number (e.g. `-` or `(`)) - * posPre, // the string to go in front of a positive number - * negSuf, // the string to go after a negative number (e.g. `)`) - * posSuf // the string to go after a positive number - * }} pattern - * @param {string} groupSep The string to separate groups of number (e.g. `,`) - * @param {string} decimalSep The string to act as the decimal separator (e.g. `.`) - * @param {[type]} fractionSize The size of the fractional part of the number - * @return {string} The number formatted as a string - */ -function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) { - - if (!(isString(number) || isNumber(number)) || isNaN(number)) return ''; - - var isInfinity = !isFinite(number); - var isZero = false; - var numStr = Math.abs(number) + '', - formattedText = '', - parsedNumber; - - if (isInfinity) { - formattedText = '\u221e'; - } else { - parsedNumber = parse(numStr); - roundNumber(parsedNumber, fractionSize, pattern.minFrac, pattern.maxFrac); + // safely round numbers in JS without hitting imprecisions of floating-point arithmetics + // inspired by: + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round + number = +(Math.round(+(number.toString() + 'e' + fractionSize)).toString() + 'e' + -fractionSize); - var digits = parsedNumber.d; - var integerLen = parsedNumber.i; - var exponent = parsedNumber.e; - var decimals = []; - isZero = digits.reduce(function(isZero, d) { return isZero && !d; }, true); + var fraction = ('' + number).split(DECIMAL_SEP); + var whole = fraction[0]; + fraction = fraction[1] || ''; - // pad zeros for small numbers - while (integerLen < 0) { - digits.unshift(0); - integerLen++; - } + var i, pos = 0, + lgroup = pattern.lgSize, + group = pattern.gSize; - // extract decimals digits - if (integerLen > 0) { - decimals = digits.splice(integerLen); - } else { - decimals = digits; - digits = [0]; + if (whole.length >= (lgroup + group)) { + pos = whole.length - lgroup; + for (i = 0; i < pos; i++) { + if ((pos - i) % group === 0 && i !== 0) { + formatedText += groupSep; + } + formatedText += whole.charAt(i); + } } - // format the integer digits with grouping separators - var groups = []; - if (digits.length > pattern.lgSize) { - groups.unshift(digits.splice(-pattern.lgSize).join('')); - } - while (digits.length > pattern.gSize) { - groups.unshift(digits.splice(-pattern.gSize).join('')); - } - if (digits.length) { - groups.unshift(digits.join('')); + for (i = pos; i < whole.length; i++) { + if ((whole.length - i) % lgroup === 0 && i !== 0) { + formatedText += groupSep; + } + formatedText += whole.charAt(i); } - formattedText = groups.join(groupSep); - // append the decimal digits - if (decimals.length) { - formattedText += decimalSep + decimals.join(''); + // format fraction part. + while (fraction.length < fractionSize) { + fraction += '0'; } - if (exponent) { - formattedText += 'e+' + exponent; + if (fractionSize && fractionSize !== "0") formatedText += decimalSep + fraction.substr(0, fractionSize); + } else { + if (fractionSize > 0 && number < 1) { + formatedText = number.toFixed(fractionSize); + number = parseFloat(formatedText); + formatedText = formatedText.replace(DECIMAL_SEP, decimalSep); } } - if (number < 0 && !isZero) { - return pattern.negPre + formattedText + pattern.negSuf; - } else { - return pattern.posPre + formattedText + pattern.posSuf; + + if (number === 0) { + isNegative = false; } + + parts.push(isNegative ? pattern.negPre : pattern.posPre, + formatedText, + isNegative ? pattern.negSuf : pattern.posSuf); + return parts.join(''); } function padNumber(num, digits, trim) { @@ -19236,7 +18808,7 @@ function padNumber(num, digits, trim) { num = -num; } num = '' + num; - while (num.length < digits) num = ZERO_CHAR + num; + while (num.length < digits) num = '0' + num; if (trim) { num = num.substr(num.length - digits); } @@ -19505,13 +19077,13 @@ function dateFilter($locale) { var dateTimezoneOffset = date.getTimezoneOffset(); if (timezone) { - dateTimezoneOffset = timezoneToOffset(timezone, dateTimezoneOffset); + dateTimezoneOffset = timezoneToOffset(timezone, date.getTimezoneOffset()); date = convertTimezoneToLocal(date, timezone, true); } forEach(parts, function(value) { fn = DATE_FORMATS[value]; text += fn ? fn(date, $locale.DATETIME_FORMATS, dateTimezoneOffset) - : value === "''" ? "'" : value.replace(/(^'|'$)/g, '').replace(/''/g, "'"); + : value.replace(/(^'|'$)/g, '').replace(/''/g, "'"); }); return text; @@ -19747,6 +19319,17 @@ function limitToFilter() { * `reverse` is not set, which means it defaults to `false`. +
@@ -19762,17 +19345,6 @@ function limitToFilter() {
- - angular.module('orderByExample', []) - .controller('ExampleController', ['$scope', function($scope) { - $scope.friends = - [{name:'John', phone:'555-1212', age:10}, - {name:'Mary', phone:'555-9876', age:19}, - {name:'Mike', phone:'555-4321', age:21}, - {name:'Adam', phone:'555-5678', age:35}, - {name:'Julie', phone:'555-8765', age:29}]; - }]); -
* * The predicate and reverse parameters can be controlled dynamically through scope properties, @@ -19780,24 +19352,49 @@ function limitToFilter() { * @example + +
Sorting predicate = {{predicate}}; reverse = {{reverse}}

- + [ unsorted ] - - - + + + @@ -19807,31 +19404,6 @@ function limitToFilter() {
- - - - - - - - - + Name + + + Phone Number + + + Age + +
{{friend.name}}
- - angular.module('orderByExample', []) - .controller('ExampleController', ['$scope', function($scope) { - $scope.friends = - [{name:'John', phone:'555-1212', age:10}, - {name:'Mary', phone:'555-9876', age:19}, - {name:'Mike', phone:'555-4321', age:21}, - {name:'Adam', phone:'555-5678', age:35}, - {name:'Julie', phone:'555-8765', age:29}]; - $scope.predicate = 'age'; - $scope.reverse = true; - $scope.order = function(predicate) { - $scope.reverse = ($scope.predicate === predicate) ? !$scope.reverse : false; - $scope.predicate = predicate; - }; - }]); - - - .sortorder:after { - content: '\25b2'; - } - .sortorder.reverse:after { - content: '\25bc'; - } -
* * It's also possible to call the orderBy filter manually, by injecting `$filter`, retrieving the @@ -19843,30 +19415,21 @@ function limitToFilter() { * @example -
-
Sorting predicate = {{predicate}}; reverse = {{reverse}}
- - - - - - - - - - - -
- - - - - - - - -
{{friend.name}}{{friend.phone}}{{friend.age}}
-
+
+ + + + + + + + + + + +
Name + (^)Phone NumberAge
{{friend.name}}{{friend.phone}}{{friend.age}}
+
@@ -19880,23 +19443,12 @@ function limitToFilter() { { name: 'Adam', phone: '555-5678', age: 35 }, { name: 'Julie', phone: '555-8765', age: 29 } ]; - $scope.order = function(predicate) { - $scope.predicate = predicate; - $scope.reverse = ($scope.predicate === predicate) ? !$scope.reverse : false; - $scope.friends = orderBy($scope.friends, predicate, $scope.reverse); + $scope.order = function(predicate, reverse) { + $scope.friends = orderBy($scope.friends, predicate, reverse); }; - $scope.order('age', true); + $scope.order('-age',false); }]); - - - .sortorder:after { - content: '\25b2'; - } - .sortorder.reverse:after { - content: '\25bc'; - } -
*/ orderByFilter.$inject = ['$parse']; @@ -20226,7 +19778,20 @@ var htmlAnchorDirective = valueFn({ * {@link guide/expression expression} inside `ngDisabled` evaluates to truthy. * * A special directive is necessary because we cannot use interpolation inside the `disabled` - * attribute. See the {@link guide/interpolation interpolation guide} for more info. + * attribute. The following example would make the button enabled on Chrome/Firefox + * but not on older IEs: + * + * ```html + * + *
+ * + *
+ * ``` + * + * This is because the HTML specification does not require browsers to preserve the values of + * boolean attributes such as `disabled` (Their presence means true and their absence means false.) + * If we put an Angular interpolation expression into such an attribute then the + * binding information would be lost when the browser removes the attribute. * * @example @@ -20261,9 +19826,15 @@ var htmlAnchorDirective = valueFn({ * Note that this directive should not be used together with {@link ngModel `ngModel`}, * as this can lead to unexpected behavior. * - * A special directive is necessary because we cannot use interpolation inside the `checked` - * attribute. See the {@link guide/interpolation interpolation guide} for more info. + * ### Why do we need `ngChecked`? * + * The HTML specification does not require browsers to preserve the values of boolean attributes + * such as checked. (Their presence means true and their absence means false.) + * If we put an Angular interpolation expression into such an attribute then the + * binding information would be lost when the browser removes the attribute. + * The `ngChecked` directive solves this problem for the `checked` attribute. + * This complementary directive is not removed by the browser and so provides + * a permanent reliable place to store the binding information. * @example @@ -20292,12 +19863,13 @@ var htmlAnchorDirective = valueFn({ * @priority 100 * * @description - * - * Sets the `readOnly` attribute on the element, if the expression inside `ngReadonly` is truthy. - * - * A special directive is necessary because we cannot use interpolation inside the `readOnly` - * attribute. See the {@link guide/interpolation interpolation guide} for more info. - * + * The HTML specification does not require browsers to preserve the values of boolean attributes + * such as readonly. (Their presence means true and their absence means false.) + * If we put an Angular interpolation expression into such an attribute then the + * binding information would be lost when the browser removes the attribute. + * The `ngReadonly` directive solves this problem for the `readonly` attribute. + * This complementary directive is not removed by the browser and so provides + * a permanent reliable place to store the binding information. * @example @@ -20326,11 +19898,13 @@ var htmlAnchorDirective = valueFn({ * @priority 100 * * @description - * - * Sets the `selected` attribute on the element, if the expression inside `ngSelected` is truthy. - * - * A special directive is necessary because we cannot use interpolation inside the `selected` - * attribute. See the {@link guide/interpolation interpolation guide} for more info. + * The HTML specification does not require browsers to preserve the values of boolean attributes + * such as selected. (Their presence means true and their absence means false.) + * If we put an Angular interpolation expression into such an attribute then the + * binding information would be lost when the browser removes the attribute. + * The `ngSelected` directive solves this problem for the `selected` attribute. + * This complementary directive is not removed by the browser and so provides + * a permanent reliable place to store the binding information. * * @example @@ -20362,12 +19936,13 @@ var htmlAnchorDirective = valueFn({ * @priority 100 * * @description - * - * Sets the `open` attribute on the element, if the expression inside `ngOpen` is truthy. - * - * A special directive is necessary because we cannot use interpolation inside the `open` - * attribute. See the {@link guide/interpolation interpolation guide} for more info. - * + * The HTML specification does not require browsers to preserve the values of boolean attributes + * such as open. (Their presence means true and their absence means false.) + * If we put an Angular interpolation expression into such an attribute then the + * binding information would be lost when the browser removes the attribute. + * The `ngOpen` directive solves this problem for the `open` attribute. + * This complementary directive is not removed by the browser and so provides + * a permanent reliable place to store the binding information. * @example @@ -20823,9 +20398,13 @@ function FormController(element, attrs, $scope, $animate, $interpolate) { * * In Angular, forms can be nested. This means that the outer form is valid when all of the child * forms are valid as well. However, browsers do not allow nesting of `
` elements, so - * Angular provides the {@link ng.directive:ngForm `ngForm`} directive, which behaves identically to - * `form` but can be nested. Nested forms can be useful, for example, if the validity of a sub-group - * of controls needs to be determined. + * Angular provides the {@link ng.directive:ngForm `ngForm`} directive which behaves identically to + * `` but can be nested. This allows you to have nested forms, which is very useful when + * using Angular validation directives in forms that are dynamically generated using the + * {@link ng.directive:ngRepeat `ngRepeat`} directive. Since you cannot dynamically generate the `name` + * attribute of input elements using interpolation, you have to wrap each set of repeated inputs in an + * `ngForm` directive and nest these in an outer `form` element. + * * * # CSS classes * - `ng-valid` is set if the form is valid. @@ -21046,18 +20625,7 @@ var ngFormDirective = formDirectiveFactory(true); // Regex code is obtained from SO: https://stackoverflow.com/questions/3143070/javascript-regex-iso-datetime#answer-3143231 var ISO_DATE_REGEXP = /\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z)/; // See valid URLs in RFC3987 (http://tools.ietf.org/html/rfc3987) -// Note: We are being more lenient, because browsers are too. -// 1. Scheme -// 2. Slashes -// 3. Username -// 4. Password -// 5. Hostname -// 6. Port -// 7. Path -// 8. Query -// 9. Fragment -// 1111111111111111 222 333333 44444 555555555555555555555555 666 77777777 8888888 999 -var URL_REGEXP = /^[a-z][a-z\d.+-]*:\/*(?:[^:@]+(?::[^@]+)?@)?(?:[^\s:/?#]+|\[[a-f\d:]+\])(?::\d+)?(?:\/[^?#]*)?(?:\?[^#]*)?(?:#.*)?$/i; +var URL_REGEXP = /^[A-Za-z][A-Za-z\d.+-]*:\/*(?:\w+(?::\w+)?@)?[^\s/]+(?::\d+)?(?:\/[\w#!:.?+=&%@\-/]*)?$/; var EMAIL_REGEXP = /^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i; var NUMBER_REGEXP = /^\s*(\-|\+)?(\d+|(\d*(\.\d*)))([eE][+-]?\d+)?\s*$/; var DATE_REGEXP = /^(\d{4})-(\d{2})-(\d{2})$/; @@ -21066,12 +20634,6 @@ var WEEK_REGEXP = /^(\d{4})-W(\d\d)$/; var MONTH_REGEXP = /^(\d{4})-(\d\d)$/; var TIME_REGEXP = /^(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/; -var PARTIAL_VALIDATION_EVENTS = 'keydown wheel mousedown'; -var PARTIAL_VALIDATION_TYPES = createMap(); -forEach('date,datetime-local,month,time,week'.split(','), function(type) { - PARTIAL_VALIDATION_TYPES[type] = true; -}); - var inputType = { /** @@ -22158,8 +21720,6 @@ function baseInputType(scope, element, attr, ctrl, $sniffer, $browser) { }); } - var timeout; - var listener = function(ev) { if (timeout) { $browser.defer.cancel(timeout); @@ -22189,6 +21749,8 @@ function baseInputType(scope, element, attr, ctrl, $sniffer, $browser) { if ($sniffer.hasEvent('input')) { element.on('input', listener); } else { + var timeout; + var deferListener = function(ev, input, origValue) { if (!timeout) { timeout = $browser.defer(function() { @@ -22220,26 +21782,6 @@ function baseInputType(scope, element, attr, ctrl, $sniffer, $browser) { // or form autocomplete on newer browser, we need "change" event to catch it element.on('change', listener); - // Some native input types (date-family) have the ability to change validity without - // firing any input/change events. - // For these event types, when native validators are present and the browser supports the type, - // check for validity changes on various DOM events. - if (PARTIAL_VALIDATION_TYPES[type] && ctrl.$$hasNativeValidators && type === attr.type) { - element.on(PARTIAL_VALIDATION_EVENTS, function(ev) { - if (!timeout) { - var validity = this[VALIDITY_STATE_PROPERTY]; - var origBadInput = validity.badInput; - var origTypeMismatch = validity.typeMismatch; - timeout = $browser.defer(function() { - timeout = null; - if (validity.badInput !== origBadInput || validity.typeMismatch !== origTypeMismatch) { - listener(ev); - } - }); - } - }); - } - ctrl.$render = function() { // Workaround for Firefox validation #12102. var value = ctrl.$isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue; @@ -24847,8 +24389,6 @@ var ngIncludeDirective = ['$templateRequest', '$anchorScroll', '$animate', //set the 2nd param to true to ignore the template request error so that the inner //contents and scope can be cleaned up. $templateRequest(src, true).then(function(response) { - if (scope.$$destroyed) return; - if (thisChangeId !== changeCounter) return; var newScope = scope.$new(); ctrl.template = response; @@ -24870,8 +24410,6 @@ var ngIncludeDirective = ['$templateRequest', '$anchorScroll', '$animate', currentScope.$emit('$includeContentLoaded', src); scope.$eval(onloadExp); }, function() { - if (scope.$$destroyed) return; - if (thisChangeId === changeCounter) { cleanupLastIncludeContent(); scope.$emit('$includeContentError', src); @@ -25550,14 +25088,11 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$ * which may be caused by a pending debounced event or because the input is waiting for a some * future event. * - * If you have an input that uses `ng-model-options` to set up debounced updates or updates that - * depend on special events such as blur, you can have a situation where there is a period when - * the `$viewValue` is out of sync with the ngModel's `$modelValue`. - * - * In this case, you can use `$rollbackViewValue()` to manually cancel the debounced / future update - * and reset the input to the last committed view value. + * If you have an input that uses `ng-model-options` to set up debounced events or events such + * as blur you can have a situation where there is a period when the `$viewValue` + * is out of synch with the ngModel's `$modelValue`. * - * It is also possible that you run into difficulties if you try to update the ngModel's `$modelValue` + * In this case, you can run into difficulties if you try to update the ngModel's `$modelValue` * programmatically before these debounced/future events have resolved/occurred, because Angular's * dirty checking mechanism is not able to tell whether the model has actually changed or not. * @@ -25570,63 +25105,39 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$ * angular.module('cancel-update-example', []) * * .controller('CancelUpdateController', ['$scope', function($scope) { - * $scope.model = {}; - * - * $scope.setEmpty = function(e, value, rollback) { + * $scope.resetWithCancel = function(e) { + * if (e.keyCode == 27) { + * $scope.myForm.myInput1.$rollbackViewValue(); + * $scope.myValue = ''; + * } + * }; + * $scope.resetWithoutCancel = function(e) { * if (e.keyCode == 27) { - * e.preventDefault(); - * if (rollback) { - * $scope.myForm[value].$rollbackViewValue(); - * } - * $scope.model[value] = ''; + * $scope.myValue = ''; * } * }; * }]); * * *
- *

Both of these inputs are only updated if they are blurred. Hitting escape should - * empty them. Follow these steps and observe the difference:

- *
    - *
  1. Type something in the input. You will see that the model is not yet updated
  2. - *
  3. Press the Escape key. - *
      - *
    1. In the first example, nothing happens, because the model is already '', and no - * update is detected. If you blur the input, the model will be set to the current view. - *
    2. - *
    3. In the second example, the pending update is cancelled, and the input is set back - * to the last committed view value (''). Blurring the input does nothing. - *
    4. - *
    - *
  4. - *
+ *

Try typing something in each input. See that the model only updates when you + * blur off the input. + *

+ *

Now see what happens if you start typing then press the Escape key

* * - *
- *

Without $rollbackViewValue():

- * - * value1: "{{ model.value1 }}" - *
- * - *
- *

With $rollbackViewValue():

- * - * value2: "{{ model.value2 }}" - *
+ *

With $rollbackViewValue()

+ *
+ * myValue: "{{ myValue }}" + * + *

Without $rollbackViewValue()

+ *
+ * myValue: "{{ myValue }}" * *
*
- - div { - display: table-cell; - } - div:nth-child(1) { - padding-right: 30px; - } - - *
*/ this.$rollbackViewValue = function() { @@ -25740,7 +25251,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$ forEach(ctrl.$asyncValidators, function(validator, name) { var promise = validator(modelValue, viewValue); if (!isPromiseLike(promise)) { - throw ngModelMinErr('nopromise', + throw ngModelMinErr("$asyncValidators", "Expected asynchronous validator to return a promise but got '{0}' instead.", promise); } setValidity(name, undefined); @@ -26036,22 +25547,6 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$ * - {@link ng.directive:select select} * - {@link ng.directive:textarea textarea} * - * # Complex Models (objects or collections) - * - * By default, `ngModel` watches the model by reference, not value. This is important to know when - * binding inputs to models that are objects (e.g. `Date`) or collections (e.g. arrays). If only properties of the - * object or collection change, `ngModel` will not be notified and so the input will not be re-rendered. - * - * The model must be assigned an entirely new object or collection before a re-rendering will occur. - * - * Some directives have options that will cause them to use a custom `$watchCollection` on the model expression - * - for example, `ngOptions` will do so when a `track by` clause is included in the comprehension expression or - * if the select is given the `multiple` attribute. - * - * The `$watchCollection()` method only does a shallow comparison, meaning that changing properties deeper than the - * first level of the object (or only changing the properties of an item in the collection if it's an array) will still - * not trigger a re-rendering of the model. - * * # CSS classes * The following CSS classes are added and removed on the associated input/select/textarea element * depending on the validity of the model. @@ -27027,20 +26522,14 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) { var option = options.getOptionFromViewValue(value); if (option && !option.disabled) { - // Don't update the option when it is already selected. - // For example, the browser will select the first option by default. In that case, - // most properties are set automatically - except the `selected` attribute, which we - // set always - if (selectElement[0].value !== option.selectValue) { removeUnknownOption(); removeEmptyOption(); selectElement[0].value = option.selectValue; option.element.selected = true; + option.element.setAttribute('selected', 'selected'); } - - option.element.setAttribute('selected', 'selected'); } else { if (value === null || providedEmptyOption) { removeUnknownOption(); @@ -27208,7 +26697,7 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) { (current === emptyOption_ || current === unknownOption_ || current.nodeType === NODE_TYPE_COMMENT || - (nodeName_(current) === 'option' && current.value === ''))) { + current.value === '')) { current = current.nextSibling; } } @@ -27298,8 +26787,7 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) { // Check to see if the value has changed due to the update to the options if (!ngModelCtrl.$isEmpty(previousValue)) { var nextValue = selectCtrl.readValue(); - var isNotPrimitive = ngOptions.trackBy || multiple; - if (isNotPrimitive ? !equals(previousValue, nextValue) : previousValue !== nextValue) { + if (ngOptions.trackBy ? !equals(previousValue, nextValue) : previousValue !== nextValue) { ngModelCtrl.$setViewValue(nextValue); ngModelCtrl.$render(); } @@ -28071,7 +27559,7 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) { if (getBlockStart(block) != nextNode) { // existing item which got moved - $animate.move(getBlockNodes(block.clone), null, previousNode); + $animate.move(getBlockNodes(block.clone), null, jqLite(previousNode)); } previousNode = getBlockEnd(block); updateScope(block.scope, index, valueIdentifier, value, keyIdentifier, key, collectionLength); @@ -28083,7 +27571,8 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) { var endNode = ngRepeatEndComment.cloneNode(false); clone[clone.length++] = endNode; - $animate.enter(clone, null, previousNode); + // TODO(perf): support naked previousNode in `enter` to avoid creation of jqLite wrapper? + $animate.enter(clone, null, jqLite(previousNode)); previousNode = endNode; // Note: We only need the first/last node of the cloned nodes. // However, we need to keep the reference to the jqlite wrapper as it might be changed later @@ -28893,9 +28382,6 @@ var SelectController = // Tell the select control that an option, with the given value, has been added self.addOption = function(value, element) { - // Skip comment nodes, as they only pollute the `optionsMap` - if (element[0].nodeType === NODE_TYPE_COMMENT) return; - assertNotHasOwnProperty(value, '"option value"'); if (value === '') { self.emptyOption = element; @@ -28970,7 +28456,7 @@ var SelectController = * * The `select` directive is used together with {@link ngModel `ngModel`} to provide data-binding * between the scope and the `` menu is selected, the value of the selected option will be bound @@ -29172,8 +28658,7 @@ var selectDirective = function() { controller: SelectController, priority: 1, link: { - pre: selectPreLink, - post: selectPostLink + pre: selectPreLink } }; @@ -29187,6 +28672,13 @@ var selectDirective = function() { selectCtrl.ngModelCtrl = ngModelCtrl; + // We delegate rendering to the `writeValue` method, which can be changed + // if the select can have multiple selected values or if the options are being + // generated by `ngOptions` + ngModelCtrl.$render = function() { + selectCtrl.writeValue(ngModelCtrl.$viewValue); + }; + // When the selected item(s) changes we delegate getting the value of the select control // to the `readValue` method, which can be changed if the select can have multiple // selected values or if the options are being generated by `ngOptions` @@ -29240,23 +28732,6 @@ var selectDirective = function() { } } - - function selectPostLink(scope, element, attrs, ctrls) { - // if ngModel is not defined, we don't need to do anything - var ngModelCtrl = ctrls[1]; - if (!ngModelCtrl) return; - - var selectCtrl = ctrls[0]; - - // We delegate rendering to the `writeValue` method, which can be changed - // if the select can have multiple selected values or if the options are being - // generated by `ngOptions`. - // This must be done in the postLink fn to prevent $render to be called before - // all nodes have been linked correctly. - ngModelCtrl.$render = function() { - selectCtrl.writeValue(ngModelCtrl.$viewValue); - }; - } }; @@ -29268,6 +28743,7 @@ var optionDirective = ['$interpolate', function($interpolate) { restrict: 'E', priority: 100, compile: function(element, attr) { + if (isDefined(attr.value)) { // If the value attribute is defined, check if it contains an interpolation var interpolateValueFn = $interpolate(attr.value, true); @@ -29281,6 +28757,7 @@ var optionDirective = ['$interpolate', function($interpolate) { } return function(scope, element, attr) { + // This is an optimization over using ^^ since we don't want to have to search // all the way to the root of the DOM for every single option element var selectCtrlName = '$selectController', @@ -29301,64 +28778,6 @@ var styleDirective = valueFn({ terminal: false }); -/** - * @ngdoc directive - * @name ngRequired - * - * @description - * - * ngRequired adds the required {@link ngModel.NgModelController#$validators `validator`} to {@link ngModel `ngModel`}. - * It is most often used for {@link input `input`} and {@link select `select`} controls, but can also be - * applied to custom controls. - * - * The directive sets the `required` attribute on the element if the Angular expression inside - * `ngRequired` evaluates to true. A special directive for setting `required` is necessary because we - * cannot use interpolation inside `required`. See the {@link guide/interpolation interpolation guide} - * for more info. - * - * The validator will set the `required` error key to true if the `required` attribute is set and - * calling {@link ngModel.NgModelController#$isEmpty `NgModelController.$isEmpty`} with the - * {@link ngModel.NgModelController#$viewValue `ngModel.$viewValue`} returns `true`. For example, the - * `$isEmpty()` implementation for `input[text]` checks the length of the `$viewValue`. When developing - * custom controls, `$isEmpty()` can be overwritten to account for a $viewValue that is not string-based. - * - * @example - * - * - * - *
- *
- * - * - *
- * - *
- *
- * required error set? = {{form.input.$error.required}}
- * model = {{model}} - *
- *
- *
- * - var required = element(by.binding('form.input.$error.required')); - var model = element(by.binding('model')); - var input = element(by.id('input')); - - it('should set the required error', function() { - expect(required.getText()).toContain('true'); - - input.sendKeys('123'); - expect(required.getText()).not.toContain('true'); - expect(model.getText()).toContain('123'); - }); - * - *
- */ var requiredDirective = function() { return { restrict: 'A', @@ -29378,81 +28797,7 @@ var requiredDirective = function() { }; }; -/** - * @ngdoc directive - * @name ngPattern - * - * @description - * - * ngPattern adds the pattern {@link ngModel.NgModelController#$validators `validator`} to {@link ngModel `ngModel`}. - * It is most often used for text-based {@link input `input`} controls, but can also be applied to custom text-based controls. - * - * The validator sets the `pattern` error key if the {@link ngModel.NgModelController#$viewValue `ngModel.$viewValue`} - * does not match a RegExp which is obtained by evaluating the Angular expression given in the - * `ngPattern` attribute value: - * * If the expression evaluates to a RegExp object, then this is used directly. - * * If the expression evaluates to a string, then it will be converted to a RegExp after wrapping it - * in `^` and `$` characters. For instance, `"abc"` will be converted to `new RegExp('^abc$')`. - * - *
- * **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to - * start at the index of the last search's match, thus not taking the whole input value into - * account. - *
- * - *
- * **Note:** This directive is also added when the plain `pattern` attribute is used, with two - * differences: - *
    - *
  1. - * `ngPattern` does not set the `pattern` attribute and therefore HTML5 constraint validation is - * not available. - *
  2. - *
  3. - * The `ngPattern` attribute must be an expression, while the `pattern` value must be - * interpolated. - *
  4. - *
- *
- * - * @example - * - * - * - *
- *
- * - * - *
- * - *
- *
- * input valid? = {{form.input.$valid}}
- * model = {{model}} - *
- *
- *
- * - var model = element(by.binding('model')); - var input = element(by.id('input')); - - it('should validate the input with the default pattern', function() { - input.sendKeys('aaa'); - expect(model.getText()).not.toContain('aaa'); - input.clear().then(function() { - input.sendKeys('123'); - expect(model.getText()).toContain('123'); - }); - }); - * - *
- */ var patternDirective = function() { return { restrict: 'A', @@ -29484,72 +28829,7 @@ var patternDirective = function() { }; }; -/** - * @ngdoc directive - * @name ngMaxlength - * - * @description - * - * ngMaxlength adds the maxlength {@link ngModel.NgModelController#$validators `validator`} to {@link ngModel `ngModel`}. - * It is most often used for text-based {@link input `input`} controls, but can also be applied to custom text-based controls. - * - * The validator sets the `maxlength` error key if the {@link ngModel.NgModelController#$viewValue `ngModel.$viewValue`} - * is longer than the integer obtained by evaluating the Angular expression given in the - * `ngMaxlength` attribute value. - * - *
- * **Note:** This directive is also added when the plain `maxlength` attribute is used, with two - * differences: - *
    - *
  1. - * `ngMaxlength` does not set the `maxlength` attribute and therefore HTML5 constraint - * validation is not available. - *
  2. - *
  3. - * The `ngMaxlength` attribute must be an expression, while the `maxlength` value must be - * interpolated. - *
  4. - *
- *
- * - * @example - * - * - * - *
- *
- * - * - *
- * - *
- *
- * input valid? = {{form.input.$valid}}
- * model = {{model}} - *
- *
- *
- * - var model = element(by.binding('model')); - var input = element(by.id('input')); - - it('should validate the input with the default maxlength', function() { - input.sendKeys('abcdef'); - expect(model.getText()).not.toContain('abcdef'); - input.clear().then(function() { - input.sendKeys('abcde'); - expect(model.getText()).toContain('abcde'); - }); - }); - * - *
- */ var maxlengthDirective = function() { return { restrict: 'A', @@ -29570,70 +28850,6 @@ var maxlengthDirective = function() { }; }; -/** - * @ngdoc directive - * @name ngMinlength - * - * @description - * - * ngMinlength adds the minlength {@link ngModel.NgModelController#$validators `validator`} to {@link ngModel `ngModel`}. - * It is most often used for text-based {@link input `input`} controls, but can also be applied to custom text-based controls. - * - * The validator sets the `minlength` error key if the {@link ngModel.NgModelController#$viewValue `ngModel.$viewValue`} - * is shorter than the integer obtained by evaluating the Angular expression given in the - * `ngMinlength` attribute value. - * - *
- * **Note:** This directive is also added when the plain `minlength` attribute is used, with two - * differences: - *
    - *
  1. - * `ngMinlength` does not set the `minlength` attribute and therefore HTML5 constraint - * validation is not available. - *
  2. - *
  3. - * The `ngMinlength` value must be an expression, while the `minlength` value must be - * interpolated. - *
  4. - *
- *
- * - * @example - * - * - * - *
- *
- * - * - *
- * - *
- *
- * input valid? = {{form.input.$valid}}
- * model = {{model}} - *
- *
- *
- * - var model = element(by.binding('model')); - var input = element(by.id('input')); - - it('should validate the input with the default minlength', function() { - input.sendKeys('ab'); - expect(model.getText()).not.toContain('ab'); - - input.sendKeys('abc'); - expect(model.getText()).toContain('abc'); - }); - * - *
- */ var minlengthDirective = function() { return { restrict: 'A', @@ -29655,9 +28871,7 @@ var minlengthDirective = function() { if (window.angular.bootstrap) { //AngularJS is already loaded, so we can return here... - if (window.console) { - console.log('WARNING: Tried to load angular more than once.'); - } + console.log('WARNING: Tried to load angular more than once.'); return; } @@ -29748,20 +28962,6 @@ $provide.value("$locale", { "Nov", "Dec" ], - "STANDALONEMONTH": [ - "January", - "February", - "March", - "April", - "May", - "June", - "July", - "August", - "September", - "October", - "November", - "December" - ], "WEEKENDRANGE": [ 5, 6 @@ -29805,7 +29005,6 @@ $provide.value("$locale", { ] }, "id": "en-us", - "localeID": "en_US", "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;} }); }]);