summaryrefslogtreecommitdiff
path: root/www/lib/angular/angular.js
diff options
context:
space:
mode:
Diffstat (limited to 'www/lib/angular/angular.js')
-rw-r--r--www/lib/angular/angular.js490
1 files changed, 322 insertions, 168 deletions
diff --git a/www/lib/angular/angular.js b/www/lib/angular/angular.js
index 5e6fb2c3..05ebff5b 100644
--- a/www/lib/angular/angular.js
+++ b/www/lib/angular/angular.js
@@ -1,9 +1,9 @@
/**
- * @license AngularJS v1.5.3
+ * @license AngularJS v1.5.5
* (c) 2010-2016 Google, Inc. http://angularjs.org
* License: MIT
*/
-(function(window, document, undefined) {'use strict';
+(function(window) {'use strict';
/**
* @description
@@ -57,7 +57,7 @@ function minErr(module, ErrorConstructor) {
return match;
});
- message += '\nhttp://errors.angularjs.org/1.5.3/' +
+ message += '\nhttp://errors.angularjs.org/1.5.5/' +
(module ? module + '/' : '') + code;
for (i = SKIP_INDEXES, paramPrefix = '?'; i < templateArgs.length; i++, paramPrefix = '&') {
@@ -171,6 +171,7 @@ function minErr(module, ErrorConstructor) {
* @ngdoc module
* @name ng
* @module ng
+ * @installation
* @description
*
* # ng (core module)
@@ -237,7 +238,7 @@ var
* documentMode is an IE-only property
* http://msdn.microsoft.com/en-us/library/ie/cc196988(v=vs.85).aspx
*/
-msie = document.documentMode;
+msie = window.document.documentMode;
/**
@@ -1047,6 +1048,41 @@ function shallowCopy(src, dst) {
* @param {*} o1 Object or value to compare.
* @param {*} o2 Object or value to compare.
* @returns {boolean} True if arguments are equal.
+ *
+ * @example
+ <example module="equalsExample" name="equalsExample">
+ <file name="index.html">
+ <div ng-controller="ExampleController">
+ <form novalidate>
+ <h3>User 1</h3>
+ Name: <input type="text" ng-model="user1.name">
+ Age: <input type="number" ng-model="user1.age">
+
+ <h3>User 2</h3>
+ Name: <input type="text" ng-model="user2.name">
+ Age: <input type="number" ng-model="user2.age">
+
+ <div>
+ <br/>
+ <input type="button" value="Compare" ng-click="compare()">
+ </div>
+ User 1: <pre>{{user1 | json}}</pre>
+ User 2: <pre>{{user2 | json}}</pre>
+ Equal: <pre>{{result}}</pre>
+ </form>
+ </div>
+ </file>
+ <file name="script.js">
+ angular.module('equalsExample', []).controller('ExampleController', ['$scope', function($scope) {
+ $scope.user1 = {};
+ $scope.user2 = {};
+ $scope.result;
+ $scope.compare = function() {
+ $scope.result = angular.equals($scope.user1, $scope.user2);
+ };
+ }]);
+ </file>
+ </example>
*/
function equals(o1, o2) {
if (o1 === o2) return true;
@@ -1093,8 +1129,8 @@ var csp = function() {
if (!isDefined(csp.rules)) {
- var ngCspElement = (document.querySelector('[ng-csp]') ||
- document.querySelector('[data-ng-csp]'));
+ var ngCspElement = (window.document.querySelector('[ng-csp]') ||
+ window.document.querySelector('[data-ng-csp]'));
if (ngCspElement) {
var ngCspAttribute = ngCspElement.getAttribute('ng-csp') ||
@@ -1169,7 +1205,7 @@ var jq = function() {
var i, ii = ngAttrPrefixes.length, prefix, name;
for (i = 0; i < ii; ++i) {
prefix = ngAttrPrefixes[i];
- if (el = document.querySelector('[' + prefix.replace(':', '\\:') + 'jq]')) {
+ if (el = window.document.querySelector('[' + prefix.replace(':', '\\:') + 'jq]')) {
name = el.getAttribute(prefix + 'jq');
break;
}
@@ -1234,7 +1270,7 @@ function toJsonReplacer(key, value) {
val = undefined;
} else if (isWindow(value)) {
val = '$WINDOW';
- } else if (value && document === value) {
+ } else if (value && window.document === value) {
val = '$DOCUMENT';
} else if (isScope(value)) {
val = '$SCOPE';
@@ -1686,11 +1722,11 @@ function bootstrap(element, modules, config) {
element = jqLite(element);
if (element.injector()) {
- var tag = (element[0] === document) ? 'document' : startingTag(element);
+ var tag = (element[0] === window.document) ? 'document' : startingTag(element);
//Encode angle brackets to prevent input from being sanitized to empty string #8683
throw ngMinErr(
'btstrpd',
- "App Already Bootstrapped with this Element '{0}'",
+ "App already bootstrapped with this element '{0}'",
tag.replace(/</,'&lt;').replace(/>/,'&gt;'));
}
@@ -2137,9 +2173,9 @@ function setupModuleLoader(window) {
* @ngdoc method
* @name angular.Module#decorator
* @module ng
- * @param {string} The name of the service to decorate.
- * @param {Function} This function will be invoked when the service needs to be
- * instantiated and should return the decorated service instance.
+ * @param {string} name The name of the service to decorate.
+ * @param {Function} decorFn This function will be invoked when the service needs to be
+ * instantiated and should return the decorated service instance.
* @description
* See {@link auto.$provide#decorator $provide.decorator()}.
*/
@@ -2443,11 +2479,11 @@ function toDebugString(obj) {
* - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat".
*/
var version = {
- full: '1.5.3', // all of these placeholder strings will be replaced by grunt's
+ full: '1.5.5', // all of these placeholder strings will be replaced by grunt's
major: 1, // package task
minor: 5,
- dot: 3,
- codeName: 'diplohaplontic-meiosis'
+ dot: 5,
+ codeName: 'material-conspiration'
};
@@ -2704,6 +2740,9 @@ function publishExternalAPI(angular) {
* - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top
* parent element is reached.
*
+ * @knownIssue You cannot spy on `angular.element` if you are using Jasmine version 1.x. See
+ * https://github.com/angular/angular.js/issues/14251 for more information.
+ *
* @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.
* @returns {Object} jQuery object.
*/
@@ -2830,7 +2869,7 @@ function jqLiteBuildFragment(html, context) {
}
function jqLiteParseHTML(html, context) {
- context = context || document;
+ context = context || window.document;
var parsed;
if ((parsed = SINGLE_TAG_REGEXP.exec(html))) {
@@ -2856,7 +2895,7 @@ function jqLiteWrapNode(node, wrapper) {
// IE9-11 has no method "contains" in SVG element and in Node.prototype. Bug #10259.
-var jqLiteContains = Node.prototype.contains || function(arg) {
+var jqLiteContains = window.Node.prototype.contains || function(arg) {
// jshint bitwise: false
return !!(this.compareDocumentPosition(arg) & 16);
// jshint bitwise: true
@@ -3128,8 +3167,8 @@ var JQLitePrototype = JQLite.prototype = {
}
// check if document is already loaded
- if (document.readyState === 'complete') {
- setTimeout(trigger);
+ if (window.document.readyState === 'complete') {
+ window.setTimeout(trigger);
} else {
this.on('DOMContentLoaded', trigger); // works for modern browsers and IE9
// we can not use jqLite since we are not done loading and jQuery could be loaded later.
@@ -3819,6 +3858,7 @@ var $$HashMapProvider = [function() {
/**
* @ngdoc module
* @name auto
+ * @installation
* @description
*
* Implicit module which gets automatically added to each {@link auto.$injector $injector}.
@@ -3832,7 +3872,7 @@ var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
var $injectorMinErr = minErr('$injector');
function extractArgs(fn) {
- var fnText = fn.toString().replace(STRIP_COMMENTS, ''),
+ var fnText = Function.prototype.toString.call(fn).replace(STRIP_COMMENTS, ''),
args = fnText.match(ARROW_ARG) || fnText.match(FN_ARGS);
return args;
}
@@ -5252,6 +5292,9 @@ var $AnimateProvider = ['$provide', function($provide) {
* // remove all the animation event listeners listening for `enter`
* $animate.off('enter');
*
+ * // remove listeners for all animation events from the container element
+ * $animate.off(container);
+ *
* // remove all the animation event listeners listening for `enter` on the given element and its children
* $animate.off('enter', container);
*
@@ -5260,7 +5303,9 @@ var $AnimateProvider = ['$provide', function($provide) {
* $animate.off('enter', container, callback);
* ```
*
- * @param {string} event the animation event (e.g. enter, leave, move, addClass, removeClass, etc...)
+ * @param {string|DOMElement} event|container the animation event (e.g. enter, leave, move,
+ * addClass, removeClass, etc...), or the container element. If it is the element, all other
+ * arguments are ignored.
* @param {DOMElement=} container the container element the event listener was placed on
* @param {Function=} callback the callback function that was registered as the listener
*/
@@ -6833,8 +6878,8 @@ function $TemplateCacheProvider() {
* this element). This is a good place to put initialization code for your controller.
* * `$onChanges(changesObj)` - Called whenever one-way (`<`) or interpolation (`@`) bindings are updated. The
* `changesObj` is a hash whose keys are the names of the bound properties that have changed, and the values are an
- * object of the form `{ currentValue: ..., previousValue: ... }`. Use this hook to trigger updates within a component
- * such as cloning the bound value to prevent accidental mutation of the outer value.
+ * object of the form `{ currentValue, previousValue, isFirstChange() }`. Use this hook to trigger updates within a
+ * component such as cloning the bound value to prevent accidental mutation of the outer value.
* * `$onDestroy()` - Called on a controller when its containing scope is destroyed. Use this hook for releasing
* external resources, watches and event handlers. Note that components have their `$onDestroy()` hooks called in
* the same order as the `$scope.$broadcast` events are triggered, which is top down. This means that parent
@@ -7381,6 +7426,9 @@ function $TemplateCacheProvider() {
var $compileMinErr = minErr('$compile');
+function UNINITIALIZED_VALUE() {}
+var _UNINITIALIZED_VALUE = new UNINITIALIZED_VALUE();
+
/**
* @ngdoc provider
* @name $compileProvider
@@ -7405,7 +7453,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
function parseIsolateBindings(scope, directiveName, isController) {
var LOCAL_REGEXP = /^\s*([@&<]|=(\*?))(\??)\s*(\w*)\s*$/;
- var bindings = {};
+ var bindings = createMap();
forEach(scope, function(definition, scopeName) {
if (definition in bindingCache) {
@@ -7579,6 +7627,9 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
* See {@link ng.$compile#-bindtocontroller- `bindToController`}.
* - `transclude` – `{boolean=}` – whether {@link $compile#transclusion content transclusion} is enabled.
* Disabled by default.
+ * - `require` - `{Object<string, string>=}` - requires the controllers of other directives and binds them to
+ * this component's controller. The object keys specify the property names under which the required
+ * controllers (object values) will be bound. See {@link ng.$compile#-require- `require`}.
* - `$...` – additional properties to attach to the directive factory function and the controller
* constructor function. (This is used by the component router to annotate)
*
@@ -7624,7 +7675,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
* See also {@link ng.$compileProvider#directive $compileProvider.directive()}.
*/
this.component = function registerComponent(name, options) {
- var controller = options.controller || noop;
+ var controller = options.controller || function() {};
function factory($injector) {
function makeInjectable(fn) {
@@ -7638,7 +7689,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
}
var template = (!options.template && !options.templateUrl ? '' : options.template);
- return {
+ var ddo = {
controller: controller,
controllerAs: identifierForController(options.controller) || options.controllerAs || '$ctrl',
template: makeInjectable(template),
@@ -7649,14 +7700,27 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
restrict: 'E',
require: options.require
};
+
+ // Copy annotations (starting with $) over to the DDO
+ forEach(options, function(val, key) {
+ if (key.charAt(0) === '$') ddo[key] = val;
+ });
+
+ return ddo;
}
- // Copy any annotation properties (starting with $) over to the factory function
+ // TODO(pete) remove the following `forEach` before we release 1.6.0
+ // The component-router@0.2.0 looks for the annotations on the controller constructor
+ // Nothing in Angular looks for annotations on the factory function but we can't remove
+ // it from 1.5.x yet.
+
+ // Copy any annotation properties (starting with $) over to the factory and controller constructor functions
// These could be used by libraries such as the new component router
forEach(options, function(val, key) {
if (key.charAt(0) === '$') {
factory[key] = val;
- controller[key] = val;
+ // Don't try to copy over annotations to named controller
+ if (isFunction(controller)) controller[key] = val;
}
});
@@ -7793,7 +7857,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
$controller, $rootScope, $sce, $animate, $$sanitizeUri) {
var SIMPLE_ATTR_NAME = /^\w/;
- var specialAttrHolder = document.createElement('div');
+ var specialAttrHolder = window.document.createElement('div');
@@ -8124,7 +8188,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
if (debugInfoEnabled) {
content = ' ' + (directiveName || '') + ': ' + (comment || '') + ' ';
}
- return document.createComment(content);
+ return window.document.createComment(content);
};
return compile;
@@ -8147,7 +8211,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
var domNode = $compileNodes[i];
if (domNode.nodeType === NODE_TYPE_TEXT && domNode.nodeValue.match(NOT_EMPTY) /* non-empty */) {
- jqLiteWrapNode(domNode, $compileNodes[i] = document.createElement('span'));
+ jqLiteWrapNode(domNode, $compileNodes[i] = window.document.createElement('span'));
}
}
@@ -8840,7 +8904,9 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
replaceDirective = directive;
}
+ /* jshint -W021 */
nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i), $compileNode,
+ /* jshint +W021 */
templateAttrs, jqCollection, hasTranscludeDirective && childTranscludeFn, preLinkFns, postLinkFns, {
controllerDirectives: controllerDirectives,
newScopeDirective: (newScopeDirective !== directive) && newScopeDirective,
@@ -8904,7 +8970,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {
var i, ii, linkFn, isolateScope, controllerScope, elementControllers, transcludeFn, $element,
- attrs, removeScopeBindingWatches, removeControllerBindingWatches;
+ attrs, scopeBindingInfo;
if (compileNode === linkNode) {
attrs = templateAttrs;
@@ -8943,11 +9009,11 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
compile.$$addScopeClass($element, true);
isolateScope.$$isolateBindings =
newIsolateScopeDirective.$$isolateBindings;
- removeScopeBindingWatches = initializeDirectiveBindings(scope, attrs, isolateScope,
+ scopeBindingInfo = initializeDirectiveBindings(scope, attrs, isolateScope,
isolateScope.$$isolateBindings,
newIsolateScopeDirective);
- if (removeScopeBindingWatches) {
- isolateScope.$on('$destroy', removeScopeBindingWatches);
+ if (scopeBindingInfo.removeWatches) {
+ isolateScope.$on('$destroy', scopeBindingInfo.removeWatches);
}
}
@@ -8958,8 +9024,10 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
var bindings = controllerDirective.$$bindings.bindToController;
if (controller.identifier && bindings) {
- removeControllerBindingWatches =
+ controller.bindingInfo =
initializeDirectiveBindings(controllerScope, attrs, controller.instance, bindings, controllerDirective);
+ } else {
+ controller.bindingInfo = {};
}
var controllerResult = controller();
@@ -8968,8 +9036,8 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
// from setupControllers
controller.instance = controllerResult;
$element.data('$' + controllerDirective.name + 'Controller', controllerResult);
- removeControllerBindingWatches && removeControllerBindingWatches();
- removeControllerBindingWatches =
+ controller.bindingInfo.removeWatches && controller.bindingInfo.removeWatches();
+ controller.bindingInfo =
initializeDirectiveBindings(controllerScope, attrs, controller.instance, bindings, controllerDirective);
}
}
@@ -8985,6 +9053,9 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
// Handle the init and destroy lifecycle hooks on all controllers that have them
forEach(elementControllers, function(controller) {
var controllerInstance = controller.instance;
+ if (isFunction(controllerInstance.$onChanges)) {
+ controllerInstance.$onChanges(controller.bindingInfo.initialChanges);
+ }
if (isFunction(controllerInstance.$onInit)) {
controllerInstance.$onInit();
}
@@ -9441,7 +9512,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
switch (type) {
case 'svg':
case 'math':
- var wrapper = document.createElement('div');
+ var wrapper = window.document.createElement('div');
wrapper.innerHTML = '<' + type + '>' + template + '</' + type + '>';
return wrapper.childNodes[0].childNodes;
default:
@@ -9585,7 +9656,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
// - remove them from the DOM
// - allow them to still be traversed with .nextSibling
// - allow a single fragment.qSA to fetch all elements being removed
- var fragment = document.createDocumentFragment();
+ var fragment = window.document.createDocumentFragment();
for (i = 0; i < removeCount; i++) {
fragment.appendChild(elementsToRemove[i]);
}
@@ -9631,6 +9702,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
// only occurs for isolate scopes and new scopes with controllerAs.
function initializeDirectiveBindings(scope, attrs, destination, bindings, directive) {
var removeWatchCollection = [];
+ var initialChanges = {};
var changes;
forEach(bindings, function initializeBinding(definition, scopeName) {
var attrName = definition.attrName,
@@ -9646,7 +9718,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
destination[scopeName] = attrs[attrName] = void 0;
}
attrs.$observe(attrName, function(value) {
- if (isString(value)) {
+ if (isString(value) || isBoolean(value)) {
var oldValue = destination[scopeName];
recordChanges(scopeName, value, oldValue);
destination[scopeName] = value;
@@ -9663,6 +9735,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
// the value to boolean rather than a string, so we special case this situation
destination[scopeName] = lastValue;
}
+ initialChanges[scopeName] = new SimpleChange(_UNINITIALIZED_VALUE, destination[scopeName]);
break;
case '=':
@@ -9718,11 +9791,16 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
parentGet = $parse(attrs[attrName]);
destination[scopeName] = parentGet(scope);
+ initialChanges[scopeName] = new SimpleChange(_UNINITIALIZED_VALUE, destination[scopeName]);
- removeWatch = scope.$watch(parentGet, function parentValueWatchAction(newParentValue) {
- var oldValue = destination[scopeName];
- recordChanges(scopeName, newParentValue, oldValue);
- destination[scopeName] = newParentValue;
+ removeWatch = scope.$watch(parentGet, function parentValueWatchAction(newValue, oldValue) {
+ if (newValue === oldValue) {
+ // If the new and old values are identical then this is the first time the watch has been triggered
+ // So instead we use the current value on the destination as the old value
+ oldValue = destination[scopeName];
+ }
+ recordChanges(scopeName, newValue, oldValue);
+ destination[scopeName] = newValue;
}, parentGet.literal);
removeWatchCollection.push(removeWatch);
@@ -9759,7 +9837,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
previousValue = changes[key].previousValue;
}
// Store this change
- changes[key] = {previousValue: previousValue, currentValue: currentValue};
+ changes[key] = new SimpleChange(previousValue, currentValue);
}
}
@@ -9769,15 +9847,25 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
changes = undefined;
}
- return removeWatchCollection.length && function removeWatches() {
- for (var i = 0, ii = removeWatchCollection.length; i < ii; ++i) {
- removeWatchCollection[i]();
+ return {
+ initialChanges: initialChanges,
+ removeWatches: removeWatchCollection.length && function removeWatches() {
+ for (var i = 0, ii = removeWatchCollection.length; i < ii; ++i) {
+ removeWatchCollection[i]();
+ }
}
};
}
}];
}
+function SimpleChange(previous, current) {
+ this.previousValue = previous;
+ this.currentValue = current;
+}
+SimpleChange.prototype.isFirstChange = function() { return this.previousValue === _UNINITIALIZED_VALUE; };
+
+
var PREFIX_REGEXP = /^((?:x|data)[\:\-_])/i;
/**
* Converts all accepted directives format into proper directive name.
@@ -10717,7 +10805,7 @@ function $HttpProvider() {
* 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.
+ * To prevent this, 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.
* </div>
*
@@ -10963,6 +11051,12 @@ function $HttpProvider() {
* - **headers** – `{Object}` – Map of strings or functions which return strings representing
* HTTP headers to send to the server. If the return value of a function is null, the
* header will not be sent. Functions accept a config object as an argument.
+ * - **eventHandlers** - `{Object}` - Event listeners to be bound to the XMLHttpRequest object.
+ * To bind events to the XMLHttpRequest upload object, use `uploadEventHandlers`.
+ * The handler will be called in the context of a `$apply` block.
+ * - **uploadEventHandlers** - `{Object}` - Event listeners to be bound to the XMLHttpRequest upload
+ * object. To bind events to the XMLHttpRequest object, use `eventHandlers`.
+ * The handler will be called in the context of a `$apply` block.
* - **xsrfHeaderName** – `{string}` – Name of HTTP header to populate with the XSRF token.
* - **xsrfCookieName** – `{string}` – Name of cookie containing the XSRF token.
* - **transformRequest** –
@@ -11421,11 +11515,35 @@ function $HttpProvider() {
}
$httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,
- config.withCredentials, config.responseType);
+ config.withCredentials, config.responseType,
+ createApplyHandlers(config.eventHandlers),
+ createApplyHandlers(config.uploadEventHandlers));
}
return promise;
+ function createApplyHandlers(eventHandlers) {
+ if (eventHandlers) {
+ var applyHandlers = {};
+ forEach(eventHandlers, function(eventHandler, key) {
+ applyHandlers[key] = function(event) {
+ if (useApplyAsync) {
+ $rootScope.$applyAsync(callEventHandler);
+ } else if ($rootScope.$$phase) {
+ callEventHandler();
+ } else {
+ $rootScope.$apply(callEventHandler);
+ }
+
+ function callEventHandler() {
+ eventHandler(event);
+ }
+ };
+ });
+ return applyHandlers;
+ }
+ }
+
/**
* Callback registered to $httpBackend():
@@ -11546,7 +11664,7 @@ function $HttpBackendProvider() {
function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDocument) {
// TODO(vojta): fix the signature
- return function(method, url, post, callback, headers, timeout, withCredentials, responseType) {
+ return function(method, url, post, callback, headers, timeout, withCredentials, responseType, eventHandlers, uploadEventHandlers) {
$browser.$$incOutstandingRequestCount();
url = url || $browser.url();
@@ -11606,6 +11724,14 @@ function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDoc
xhr.onerror = requestError;
xhr.onabort = requestError;
+ forEach(eventHandlers, function(value, key) {
+ xhr.addEventListener(key, value);
+ });
+
+ forEach(uploadEventHandlers, function(value, key) {
+ xhr.upload.addEventListener(key, value);
+ });
+
if (withCredentials) {
xhr.withCredentials = true;
}
@@ -13584,7 +13710,7 @@ Lexer.prototype = {
this.readString(ch);
} else if (this.isNumber(ch) || ch === '.' && this.isNumber(this.peek())) {
this.readNumber();
- } else if (this.isIdent(ch)) {
+ } else if (this.isIdentifierStart(this.peekMultichar())) {
this.readIdent();
} else if (this.is(ch, '(){}[].,;:?')) {
this.tokens.push({index: this.index, text: ch});
@@ -13628,12 +13754,49 @@ Lexer.prototype = {
ch === '\n' || ch === '\v' || ch === '\u00A0');
},
- isIdent: function(ch) {
+ isIdentifierStart: function(ch) {
+ return this.options.isIdentifierStart ?
+ this.options.isIdentifierStart(ch, this.codePointAt(ch)) :
+ this.isValidIdentifierStart(ch);
+ },
+
+ isValidIdentifierStart: function(ch) {
return ('a' <= ch && ch <= 'z' ||
'A' <= ch && ch <= 'Z' ||
'_' === ch || ch === '$');
},
+ isIdentifierContinue: function(ch) {
+ return this.options.isIdentifierContinue ?
+ this.options.isIdentifierContinue(ch, this.codePointAt(ch)) :
+ this.isValidIdentifierContinue(ch);
+ },
+
+ isValidIdentifierContinue: function(ch, cp) {
+ return this.isValidIdentifierStart(ch, cp) || this.isNumber(ch);
+ },
+
+ codePointAt: function(ch) {
+ if (ch.length === 1) return ch.charCodeAt(0);
+ /*jshint bitwise: false*/
+ return (ch.charCodeAt(0) << 10) + ch.charCodeAt(1) - 0x35FDC00;
+ /*jshint bitwise: true*/
+ },
+
+ peekMultichar: function() {
+ var ch = this.text.charAt(this.index);
+ var peek = this.peek();
+ if (!peek) {
+ return ch;
+ }
+ var cp1 = ch.charCodeAt(0);
+ var cp2 = peek.charCodeAt(0);
+ if (cp1 >= 0xD800 && cp1 <= 0xDBFF && cp2 >= 0xDC00 && cp2 <= 0xDFFF) {
+ return ch + peek;
+ }
+ return ch;
+ },
+
isExpOperator: function(ch) {
return (ch === '-' || ch === '+' || this.isNumber(ch));
},
@@ -13682,12 +13845,13 @@ Lexer.prototype = {
readIdent: function() {
var start = this.index;
+ this.index += this.peekMultichar().length;
while (this.index < this.text.length) {
- var ch = this.text.charAt(this.index);
- if (!(this.isIdent(ch) || this.isNumber(ch))) {
+ var ch = this.peekMultichar();
+ if (!this.isIdentifierContinue(ch)) {
break;
}
- this.index++;
+ this.index += ch.length;
}
this.tokens.push({
index: start,
@@ -14617,7 +14781,13 @@ ASTCompiler.prototype = {
},
nonComputedMember: function(left, right) {
- return left + '.' + right;
+ var SAFE_IDENTIFIER = /[$_a-zA-Z][$_a-zA-Z0-9]*/;
+ var UNSAFE_CHARACTERS = /[^$_a-zA-Z0-9]/g;
+ if (SAFE_IDENTIFIER.test(right)) {
+ return left + '.' + right;
+ } else {
+ return left + '["' + right.replace(UNSAFE_CHARACTERS, this.stringEscapeFn) + '"]';
+ }
},
computedMember: function(left, right) {
@@ -15180,6 +15350,7 @@ function $ParseProvider() {
'null': null,
'undefined': undefined
};
+ var identStart, identContinue;
/**
* @ngdoc method
@@ -15196,17 +15367,50 @@ function $ParseProvider() {
literals[literalName] = literalValue;
};
+ /**
+ * @ngdoc method
+ * @name $parseProvider#setIdentifierFns
+ * @description
+ *
+ * Allows defining the set of characters that are allowed in Angular expressions. The function
+ * `identifierStart` will get called to know if a given character is a valid character to be the
+ * first character for an identifier. The function `identifierContinue` will get called to know if
+ * a given character is a valid character to be a follow-up identifier character. The functions
+ * `identifierStart` and `identifierContinue` will receive as arguments the single character to be
+ * identifier and the character code point. These arguments will be `string` and `numeric`. Keep in
+ * mind that the `string` parameter can be two characters long depending on the character
+ * representation. It is expected for the function to return `true` or `false`, whether that
+ * character is allowed or not.
+ *
+ * Since this function will be called extensivelly, keep the implementation of these functions fast,
+ * as the performance of these functions have a direct impact on the expressions parsing speed.
+ *
+ * @param {function=} identifierStart The function that will decide whether the given character is
+ * a valid identifier start character.
+ * @param {function=} identifierContinue The function that will decide whether the given character is
+ * a valid identifier continue character.
+ */
+ this.setIdentifierFns = function(identifierStart, identifierContinue) {
+ identStart = identifierStart;
+ identContinue = identifierContinue;
+ return this;
+ };
+
this.$get = ['$filter', function($filter) {
var noUnsafeEval = csp().noUnsafeEval;
var $parseOptions = {
csp: noUnsafeEval,
expensiveChecks: false,
- literals: copy(literals)
+ literals: copy(literals),
+ isIdentifierStart: isFunction(identStart) && identStart,
+ isIdentifierContinue: isFunction(identContinue) && identContinue
},
$parseOptionsExpensive = {
csp: noUnsafeEval,
expensiveChecks: true,
- literals: copy(literals)
+ literals: copy(literals),
+ isIdentifierStart: isFunction(identStart) && identStart,
+ isIdentifierContinue: isFunction(identContinue) && identContinue
};
var runningChecksEnabled = false;
@@ -19001,7 +19205,7 @@ function $TimeoutProvider() {
// doesn't know about mocked locations and resolves URLs to the real document - which is
// exactly the behavior needed here. There is little value is mocking these out for this
// service.
-var urlParsingNode = document.createElement("a");
+var urlParsingNode = window.document.createElement("a");
var originUrl = urlResolve(window.location.href);
@@ -19701,7 +19905,9 @@ 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 `fractionSize` appropriately formatted based on the current
+ * locale (e.g., in the en_US locale it will have "." as the decimal separator and
+ * include "," group separators after each third digit).
*
* @example
<example module="numberFilterExample">
@@ -23930,7 +24136,11 @@ function classDirective(name, selector) {
updateClasses(oldClasses, newClasses);
}
}
- oldVal = shallowCopy(newVal);
+ if (isArray(newVal)) {
+ oldVal = newVal.map(function(v) { return shallowCopy(v); });
+ } else {
+ oldVal = shallowCopy(newVal);
+ }
}
}
};
@@ -25646,7 +25856,7 @@ var ngIncludeFillContentDirective = ['$compile',
// support innerHTML, so detect this here and try to generate the contents
// specially.
$element.empty();
- $compile(jqLiteBuildFragment(ctrl.template, document).childNodes)(scope,
+ $compile(jqLiteBuildFragment(ctrl.template, window.document).childNodes)(scope,
function namespaceAdaptedClone(clone) {
$element.append(clone);
}, {futureParentElement: $element});
@@ -27560,7 +27770,7 @@ var NG_OPTIONS_REGEXP = /^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+group\s+by\s
// jshint maxlen: 100
-var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
+var ngOptionsDirective = ['$compile', '$document', '$parse', function($compile, $document, $parse) {
function parseOptionsExpression(optionsExp, selectElement, scope) {
@@ -27721,8 +27931,8 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
// we can't just jqLite('<option>') since jqLite is not smart enough
// to create it in <select> and IE barfs otherwise.
- var optionTemplate = document.createElement('option'),
- optGroupTemplate = document.createElement('optgroup');
+ var optionTemplate = window.document.createElement('option'),
+ optGroupTemplate = window.document.createElement('optgroup');
function ngOptionsPostLink(scope, selectElement, attr, ctrls) {
@@ -27747,7 +27957,10 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
var options;
var ngOptions = parseOptionsExpression(attr.ngOptions, selectElement, scope);
-
+ // This stores the newly created options before they are appended to the select.
+ // Since the contents are removed from the fragment when it is appended,
+ // we only need to create it once.
+ var listFragment = $document[0].createDocumentFragment();
var renderEmptyOption = function() {
if (!providedEmptyOption) {
@@ -27782,7 +27995,7 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
selectCtrl.writeValue = function writeNgOptionsValue(value) {
var option = options.getOptionFromViewValue(value);
- if (option && !option.disabled) {
+ if (option) {
// 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
@@ -27844,7 +28057,7 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
if (value) {
value.forEach(function(item) {
var option = options.getOptionFromViewValue(item);
- if (option && !option.disabled) option.element.selected = true;
+ if (option) option.element.selected = true;
});
}
};
@@ -27896,6 +28109,8 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
emptyOption = jqLite(optionTemplate.cloneNode(false));
}
+ selectElement.empty();
+
// We need to do this here to ensure that the options object is defined
// when we first hit it in writeNgOptionsValue
updateOptions();
@@ -27905,6 +28120,12 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
// ------------------------------------------------------------------ //
+ function addOptionElement(option, parent) {
+ var optionElement = optionTemplate.cloneNode(false);
+ parent.appendChild(optionElement);
+ updateOptionElement(option, optionElement);
+ }
+
function updateOptionElement(option, element) {
option.element = element;
@@ -27921,133 +28142,66 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
if (option.value !== element.value) element.value = option.selectValue;
}
- function addOrReuseElement(parent, current, type, templateElement) {
- var element;
- // Check whether we can reuse the next element
- if (current && lowercase(current.nodeName) === type) {
- // The next element is the right type so reuse it
- element = current;
- } else {
- // The next element is not the right type so create a new one
- element = templateElement.cloneNode(false);
- if (!current) {
- // There are no more elements so just append it to the select
- parent.appendChild(element);
- } else {
- // The next element is not a group so insert the new one
- parent.insertBefore(element, current);
- }
- }
- return element;
- }
-
-
- function removeExcessElements(current) {
- var next;
- while (current) {
- next = current.nextSibling;
- jqLiteRemove(current);
- current = next;
- }
- }
-
-
- function skipEmptyAndUnknownOptions(current) {
- var emptyOption_ = emptyOption && emptyOption[0];
- var unknownOption_ = unknownOption && unknownOption[0];
+ function updateOptions() {
+ var previousValue = options && selectCtrl.readValue();
- // We cannot rely on the extracted empty option being the same as the compiled empty option,
- // because the compiled empty option might have been replaced by a comment because
- // it had an "element" transclusion directive on it (such as ngIf)
- if (emptyOption_ || unknownOption_) {
- while (current &&
- (current === emptyOption_ ||
- current === unknownOption_ ||
- current.nodeType === NODE_TYPE_COMMENT ||
- (nodeName_(current) === 'option' && current.value === ''))) {
- current = current.nextSibling;
+ // We must remove all current options, but cannot simply set innerHTML = null
+ // since the providedEmptyOption might have an ngIf on it that inserts comments which we
+ // must preserve.
+ // Instead, iterate over the current option elements and remove them or their optgroup
+ // parents
+ if (options) {
+
+ for (var i = options.items.length - 1; i >= 0; i--) {
+ var option = options.items[i];
+ if (option.group) {
+ jqLiteRemove(option.element.parentNode);
+ } else {
+ jqLiteRemove(option.element);
+ }
}
}
- return current;
- }
-
-
- function updateOptions() {
-
- var previousValue = options && selectCtrl.readValue();
options = ngOptions.getOptions();
- var groupMap = {};
- var currentElement = selectElement[0].firstChild;
+ var groupElementMap = {};
// Ensure that the empty option is always there if it was explicitly provided
if (providedEmptyOption) {
selectElement.prepend(emptyOption);
}
- currentElement = skipEmptyAndUnknownOptions(currentElement);
-
- options.items.forEach(function updateOption(option) {
- var group;
+ options.items.forEach(function addOption(option) {
var groupElement;
- var optionElement;
if (isDefined(option.group)) {
// This option is to live in a group
// See if we have already created this group
- group = groupMap[option.group];
+ groupElement = groupElementMap[option.group];
- if (!group) {
+ if (!groupElement) {
- // We have not already created this group
- groupElement = addOrReuseElement(selectElement[0],
- currentElement,
- 'optgroup',
- optGroupTemplate);
- // Move to the next element
- currentElement = groupElement.nextSibling;
+ groupElement = optGroupTemplate.cloneNode(false);
+ listFragment.appendChild(groupElement);
// Update the label on the group element
groupElement.label = option.group;
// Store it for use later
- group = groupMap[option.group] = {
- groupElement: groupElement,
- currentOptionElement: groupElement.firstChild
- };
-
+ groupElementMap[option.group] = groupElement;
}
- // So now we have a group for this option we add the option to the group
- optionElement = addOrReuseElement(group.groupElement,
- group.currentOptionElement,
- 'option',
- optionTemplate);
- updateOptionElement(option, optionElement);
- // Move to the next element
- group.currentOptionElement = optionElement.nextSibling;
+ addOptionElement(option, groupElement);
} else {
// This option is not in a group
- optionElement = addOrReuseElement(selectElement[0],
- currentElement,
- 'option',
- optionTemplate);
- updateOptionElement(option, optionElement);
- // Move to the next element
- currentElement = optionElement.nextSibling;
+ addOptionElement(option, listFragment);
}
});
-
- // Now remove all excess options and group
- Object.keys(groupMap).forEach(function(key) {
- removeExcessElements(groupMap[key].currentOptionElement);
- });
- removeExcessElements(currentElement);
+ selectElement[0].appendChild(listFragment);
ngModelCtrl.$render();
@@ -29742,7 +29896,7 @@ var SelectController =
//
// We can't just jqLite('<option>') since jqLite is not smart enough
// to create it in <select> and IE barfs otherwise.
- self.unknownOption = jqLite(document.createElement('option'));
+ self.unknownOption = jqLite(window.document.createElement('option'));
self.renderUnknownOption = function(val) {
var unknownVal = '? ' + hashKey(val) + ' ?';
self.unknownOption.val(unknownVal);
@@ -30705,10 +30859,10 @@ $provide.value("$locale", {
});
}]);
- jqLite(document).ready(function() {
- angularInit(document, bootstrap);
+ jqLite(window.document).ready(function() {
+ angularInit(window.document, bootstrap);
});
-})(window, document);
+})(window);
!window.angular.$$csp().noInlineStyle && window.angular.element(document.head).prepend('<style type="text/css">@charset "UTF-8";[ng\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak,.ng-hide:not(.ng-hide-animate){display:none !important;}ng\\:form{display:block;}.ng-animate-shim{visibility:hidden;}.ng-anchor{position:absolute;}</style>'); \ No newline at end of file