angularjs-rails 1.4.4 → 1.4.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.4.4
2
+ * @license AngularJS v1.4.7
3
3
  * (c) 2010-2015 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -9190,7 +9190,7 @@ return jQuery;
9190
9190
  }));
9191
9191
 
9192
9192
  /**
9193
- * @license AngularJS v1.4.4
9193
+ * @license AngularJS v1.4.7
9194
9194
  * (c) 2010-2015 Google, Inc. http://angularjs.org
9195
9195
  * License: MIT
9196
9196
  */
@@ -9249,7 +9249,7 @@ function minErr(module, ErrorConstructor) {
9249
9249
  return match;
9250
9250
  });
9251
9251
 
9252
- message += '\nhttp://errors.angularjs.org/1.4.4/' +
9252
+ message += '\nhttp://errors.angularjs.org/1.4.7/' +
9253
9253
  (module ? module + '/' : '') + code;
9254
9254
 
9255
9255
  for (i = SKIP_INDEXES, paramPrefix = '?'; i < templateArgs.length; i++, paramPrefix = '&') {
@@ -10086,6 +10086,8 @@ function copy(source, destination, stackSource, stackDest) {
10086
10086
  } else if (isRegExp(source)) {
10087
10087
  destination = new RegExp(source.source, source.toString().match(/[^\/]*$/)[0]);
10088
10088
  destination.lastIndex = source.lastIndex;
10089
+ } else if (isFunction(source.cloneNode)) {
10090
+ destination = source.cloneNode(true);
10089
10091
  } else {
10090
10092
  var emptyObject = Object.create(getPrototypeOf(source));
10091
10093
  return copy(source, emptyObject, stackSource, stackDest);
@@ -10236,7 +10238,7 @@ function equals(o1, o2) {
10236
10238
  for (key in o2) {
10237
10239
  if (!(key in keySet) &&
10238
10240
  key.charAt(0) !== '$' &&
10239
- o2[key] !== undefined &&
10241
+ isDefined(o2[key]) &&
10240
10242
  !isFunction(o2[key])) return false;
10241
10243
  }
10242
10244
  return true;
@@ -10932,10 +10934,9 @@ function bindJQuery() {
10932
10934
 
10933
10935
  // bind to jQuery if present;
10934
10936
  var jqName = jq();
10935
- jQuery = window.jQuery; // use default jQuery.
10936
- if (isDefined(jqName)) { // `ngJq` present
10937
- jQuery = jqName === null ? undefined : window[jqName]; // if empty; use jqLite. if not empty, use jQuery specified by `ngJq`.
10938
- }
10937
+ jQuery = isUndefined(jqName) ? window.jQuery : // use jQuery (if present)
10938
+ !jqName ? undefined : // use jqLite
10939
+ window[jqName]; // use jQuery specified by `ngJq`
10939
10940
 
10940
10941
  // Use jQuery if it exists with proper functionality, otherwise default to us.
10941
10942
  // Angular 1.2+ requires jQuery 1.7+ for on()/off() support.
@@ -11040,22 +11041,24 @@ function getter(obj, path, bindFnToScope) {
11040
11041
  /**
11041
11042
  * Return the DOM siblings between the first and last node in the given array.
11042
11043
  * @param {Array} array like object
11043
- * @returns {jqLite} jqLite collection containing the nodes
11044
+ * @returns {Array} the inputted object or a jqLite collection containing the nodes
11044
11045
  */
11045
11046
  function getBlockNodes(nodes) {
11046
- // TODO(perf): just check if all items in `nodes` are siblings and if they are return the original
11047
- // collection, otherwise update the original collection.
11047
+ // TODO(perf): update `nodes` instead of creating a new object?
11048
11048
  var node = nodes[0];
11049
11049
  var endNode = nodes[nodes.length - 1];
11050
- var blockNodes = [node];
11050
+ var blockNodes;
11051
11051
 
11052
- do {
11053
- node = node.nextSibling;
11054
- if (!node) break;
11055
- blockNodes.push(node);
11056
- } while (node !== endNode);
11052
+ for (var i = 1; node !== endNode && (node = node.nextSibling); i++) {
11053
+ if (blockNodes || nodes[i] !== node) {
11054
+ if (!blockNodes) {
11055
+ blockNodes = jqLite(slice.call(nodes, 0, i));
11056
+ }
11057
+ blockNodes.push(node);
11058
+ }
11059
+ }
11057
11060
 
11058
- return jqLite(blockNodes);
11061
+ return blockNodes || nodes;
11059
11062
  }
11060
11063
 
11061
11064
 
@@ -11439,7 +11442,7 @@ function serializeObject(obj) {
11439
11442
  val = toJsonReplacer(key, val);
11440
11443
  if (isObject(val)) {
11441
11444
 
11442
- if (seen.indexOf(val) >= 0) return '<<already seen>>';
11445
+ if (seen.indexOf(val) >= 0) return '...';
11443
11446
 
11444
11447
  seen.push(val);
11445
11448
  }
@@ -11450,7 +11453,7 @@ function serializeObject(obj) {
11450
11453
  function toDebugString(obj) {
11451
11454
  if (typeof obj === 'function') {
11452
11455
  return obj.toString().replace(/ \{[\s\S]*$/, '');
11453
- } else if (typeof obj === 'undefined') {
11456
+ } else if (isUndefined(obj)) {
11454
11457
  return 'undefined';
11455
11458
  } else if (typeof obj !== 'string') {
11456
11459
  return serializeObject(obj);
@@ -11530,6 +11533,7 @@ function toDebugString(obj) {
11530
11533
  $HttpParamSerializerProvider,
11531
11534
  $HttpParamSerializerJQLikeProvider,
11532
11535
  $HttpBackendProvider,
11536
+ $xhrFactoryProvider,
11533
11537
  $LocationProvider,
11534
11538
  $LogProvider,
11535
11539
  $ParseProvider,
@@ -11556,8 +11560,9 @@ function toDebugString(obj) {
11556
11560
  * @name angular.version
11557
11561
  * @module ng
11558
11562
  * @description
11559
- * An object that contains information about the current AngularJS version. This object has the
11560
- * following properties:
11563
+ * An object that contains information about the current AngularJS version.
11564
+ *
11565
+ * This object has the following properties:
11561
11566
  *
11562
11567
  * - `full` – `{string}` – Full version string, such as "0.9.18".
11563
11568
  * - `major` – `{number}` – Major version number, such as "0".
@@ -11566,11 +11571,11 @@ function toDebugString(obj) {
11566
11571
  * - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat".
11567
11572
  */
11568
11573
  var version = {
11569
- full: '1.4.4', // all of these placeholder strings will be replaced by grunt's
11574
+ full: '1.4.7', // all of these placeholder strings will be replaced by grunt's
11570
11575
  major: 1, // package task
11571
11576
  minor: 4,
11572
- dot: 4,
11573
- codeName: 'pylon-requirement'
11577
+ dot: 7,
11578
+ codeName: 'dark-luminescence'
11574
11579
  };
11575
11580
 
11576
11581
 
@@ -11687,6 +11692,7 @@ function publishExternalAPI(angular) {
11687
11692
  $httpParamSerializer: $HttpParamSerializerProvider,
11688
11693
  $httpParamSerializerJQLike: $HttpParamSerializerJQLikeProvider,
11689
11694
  $httpBackend: $HttpBackendProvider,
11695
+ $xhrFactory: $xhrFactoryProvider,
11690
11696
  $location: $LocationProvider,
11691
11697
  $log: $LogProvider,
11692
11698
  $parse: $ParseProvider,
@@ -11775,7 +11781,7 @@ function publishExternalAPI(angular) {
11775
11781
  * - [`html()`](http://api.jquery.com/html/)
11776
11782
  * - [`next()`](http://api.jquery.com/next/) - Does not support selectors
11777
11783
  * - [`on()`](http://api.jquery.com/on/) - Does not support namespaces, selectors or eventData
11778
- * - [`off()`](http://api.jquery.com/off/) - Does not support namespaces or selectors
11784
+ * - [`off()`](http://api.jquery.com/off/) - Does not support namespaces, selectors or event object as parameter
11779
11785
  * - [`one()`](http://api.jquery.com/one/) - Does not support namespaces or selectors
11780
11786
  * - [`parent()`](http://api.jquery.com/parent/) - Does not support selectors
11781
11787
  * - [`prepend()`](http://api.jquery.com/prepend/)
@@ -11789,7 +11795,7 @@ function publishExternalAPI(angular) {
11789
11795
  * - [`text()`](http://api.jquery.com/text/)
11790
11796
  * - [`toggleClass()`](http://api.jquery.com/toggleClass/)
11791
11797
  * - [`triggerHandler()`](http://api.jquery.com/triggerHandler/) - Passes a dummy event object to handlers.
11792
- * - [`unbind()`](http://api.jquery.com/unbind/) - Does not support namespaces
11798
+ * - [`unbind()`](http://api.jquery.com/unbind/) - Does not support namespaces or event object as parameter
11793
11799
  * - [`val()`](http://api.jquery.com/val/)
11794
11800
  * - [`wrap()`](http://api.jquery.com/wrap/)
11795
11801
  *
@@ -11861,10 +11867,10 @@ function camelCase(name) {
11861
11867
  replace(MOZ_HACK_REGEXP, 'Moz$1');
11862
11868
  }
11863
11869
 
11864
- var SINGLE_TAG_REGEXP = /^<(\w+)\s*\/?>(?:<\/\1>|)$/;
11870
+ var SINGLE_TAG_REGEXP = /^<([\w-]+)\s*\/?>(?:<\/\1>|)$/;
11865
11871
  var HTML_REGEXP = /<|&#?\w+;/;
11866
- var TAG_NAME_REGEXP = /<([\w:]+)/;
11867
- var XHTML_TAG_REGEXP = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi;
11872
+ var TAG_NAME_REGEXP = /<([\w:-]+)/;
11873
+ var XHTML_TAG_REGEXP = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi;
11868
11874
 
11869
11875
  var wrapMap = {
11870
11876
  'option': [1, '<select multiple="multiple">', '</select>'],
@@ -12160,7 +12166,7 @@ function jqLiteInheritedData(element, name, value) {
12160
12166
 
12161
12167
  while (element) {
12162
12168
  for (var i = 0, ii = names.length; i < ii; i++) {
12163
- if ((value = jqLite.data(element, names[i])) !== undefined) return value;
12169
+ if (isDefined(value = jqLite.data(element, names[i]))) return value;
12164
12170
  }
12165
12171
 
12166
12172
  // If dealing with a document fragment node with a host element, and no parent, use the host
@@ -12266,9 +12272,8 @@ function getBooleanAttrName(element, name) {
12266
12272
  return booleanAttr && BOOLEAN_ELEMENTS[nodeName_(element)] && booleanAttr;
12267
12273
  }
12268
12274
 
12269
- function getAliasedAttrName(element, name) {
12270
- var nodeName = element.nodeName;
12271
- return (nodeName === 'INPUT' || nodeName === 'TEXTAREA') && ALIASED_ATTR[name];
12275
+ function getAliasedAttrName(name) {
12276
+ return ALIASED_ATTR[name];
12272
12277
  }
12273
12278
 
12274
12279
  forEach({
@@ -12405,7 +12410,7 @@ forEach({
12405
12410
  // in a way that survives minification.
12406
12411
  // jqLiteEmpty takes no arguments but is a setter.
12407
12412
  if (fn !== jqLiteEmpty &&
12408
- (((fn.length == 2 && (fn !== jqLiteHasClass && fn !== jqLiteController)) ? arg1 : arg2) === undefined)) {
12413
+ (isUndefined((fn.length == 2 && (fn !== jqLiteHasClass && fn !== jqLiteController)) ? arg1 : arg2))) {
12409
12414
  if (isObject(arg1)) {
12410
12415
 
12411
12416
  // we are a write, but the object properties are the key/values
@@ -12426,7 +12431,7 @@ forEach({
12426
12431
  // TODO: do we still need this?
12427
12432
  var value = fn.$dv;
12428
12433
  // Only if we have $dv do we iterate over all, otherwise it is just the first element.
12429
- var jj = (value === undefined) ? Math.min(nodeCount, 1) : nodeCount;
12434
+ var jj = (isUndefined(value)) ? Math.min(nodeCount, 1) : nodeCount;
12430
12435
  for (var j = 0; j < jj; j++) {
12431
12436
  var nodeValue = fn(this[j], arg1, arg2);
12432
12437
  value = value ? value + nodeValue : nodeValue;
@@ -14065,61 +14070,66 @@ var $$CoreAnimateQueueProvider = function() {
14065
14070
  }
14066
14071
  };
14067
14072
 
14068
- function addRemoveClassesPostDigest(element, add, remove) {
14069
- var classVal, data = postDigestQueue.get(element);
14070
14073
 
14071
- if (!data) {
14072
- postDigestQueue.put(element, data = {});
14073
- postDigestElements.push(element);
14074
+ function updateData(data, classes, value) {
14075
+ var changed = false;
14076
+ if (classes) {
14077
+ classes = isString(classes) ? classes.split(' ') :
14078
+ isArray(classes) ? classes : [];
14079
+ forEach(classes, function(className) {
14080
+ if (className) {
14081
+ changed = true;
14082
+ data[className] = value;
14083
+ }
14084
+ });
14074
14085
  }
14075
-
14076
- var updateData = function(classes, value) {
14077
- var changed = false;
14078
- if (classes) {
14079
- classes = isString(classes) ? classes.split(' ') :
14080
- isArray(classes) ? classes : [];
14081
- forEach(classes, function(className) {
14082
- if (className) {
14083
- changed = true;
14084
- data[className] = value;
14086
+ return changed;
14087
+ }
14088
+
14089
+ function handleCSSClassChanges() {
14090
+ forEach(postDigestElements, function(element) {
14091
+ var data = postDigestQueue.get(element);
14092
+ if (data) {
14093
+ var existing = splitClasses(element.attr('class'));
14094
+ var toAdd = '';
14095
+ var toRemove = '';
14096
+ forEach(data, function(status, className) {
14097
+ var hasClass = !!existing[className];
14098
+ if (status !== hasClass) {
14099
+ if (status) {
14100
+ toAdd += (toAdd.length ? ' ' : '') + className;
14101
+ } else {
14102
+ toRemove += (toRemove.length ? ' ' : '') + className;
14103
+ }
14085
14104
  }
14086
14105
  });
14106
+
14107
+ forEach(element, function(elm) {
14108
+ toAdd && jqLiteAddClass(elm, toAdd);
14109
+ toRemove && jqLiteRemoveClass(elm, toRemove);
14110
+ });
14111
+ postDigestQueue.remove(element);
14087
14112
  }
14088
- return changed;
14089
- };
14113
+ });
14114
+ postDigestElements.length = 0;
14115
+ }
14090
14116
 
14091
- var classesAdded = updateData(add, true);
14092
- var classesRemoved = updateData(remove, false);
14093
- if ((!classesAdded && !classesRemoved) || postDigestElements.length > 1) return;
14094
-
14095
- $rootScope.$$postDigest(function() {
14096
- forEach(postDigestElements, function(element) {
14097
- var data = postDigestQueue.get(element);
14098
- if (data) {
14099
- var existing = splitClasses(element.attr('class'));
14100
- var toAdd = '';
14101
- var toRemove = '';
14102
- forEach(data, function(status, className) {
14103
- var hasClass = !!existing[className];
14104
- if (status !== hasClass) {
14105
- if (status) {
14106
- toAdd += (toAdd.length ? ' ' : '') + className;
14107
- } else {
14108
- toRemove += (toRemove.length ? ' ' : '') + className;
14109
- }
14110
- }
14111
- });
14112
14117
 
14113
- forEach(element, function(elm) {
14114
- toAdd && jqLiteAddClass(elm, toAdd);
14115
- toRemove && jqLiteRemoveClass(elm, toRemove);
14116
- });
14117
- postDigestQueue.remove(element);
14118
- }
14119
- });
14118
+ function addRemoveClassesPostDigest(element, add, remove) {
14119
+ var data = postDigestQueue.get(element) || {};
14120
14120
 
14121
- postDigestElements.length = 0;
14122
- });
14121
+ var classesAdded = updateData(data, add, true);
14122
+ var classesRemoved = updateData(data, remove, false);
14123
+
14124
+ if (classesAdded || classesRemoved) {
14125
+
14126
+ postDigestQueue.put(element, data);
14127
+ postDigestElements.push(element);
14128
+
14129
+ if (postDigestElements.length === 1) {
14130
+ $rootScope.$$postDigest(handleCSSClassChanges);
14131
+ }
14132
+ }
14123
14133
  }
14124
14134
  }];
14125
14135
  };
@@ -14584,14 +14594,21 @@ var $CoreAnimateCssProvider = function() {
14584
14594
  return this.getPromise().then(f1,f2);
14585
14595
  },
14586
14596
  'catch': function(f1) {
14587
- return this.getPromise().catch(f1);
14597
+ return this.getPromise()['catch'](f1);
14588
14598
  },
14589
14599
  'finally': function(f1) {
14590
- return this.getPromise().finally(f1);
14600
+ return this.getPromise()['finally'](f1);
14591
14601
  }
14592
14602
  };
14593
14603
 
14594
14604
  return function(element, options) {
14605
+ // there is no point in applying the styles since
14606
+ // there is no animation that goes on at all in
14607
+ // this version of $animateCss.
14608
+ if (options.cleanupStyles) {
14609
+ options.from = options.to = null;
14610
+ }
14611
+
14595
14612
  if (options.from) {
14596
14613
  element.css(options.from);
14597
14614
  options.from = null;
@@ -14720,7 +14737,7 @@ function Browser(window, document, $log, $sniffer) {
14720
14737
  var cachedState, lastHistoryState,
14721
14738
  lastBrowserUrl = location.href,
14722
14739
  baseElement = document.find('base'),
14723
- reloadLocation = null;
14740
+ pendingLocation = null;
14724
14741
 
14725
14742
  cacheState();
14726
14743
  lastHistoryState = cachedState;
@@ -14780,8 +14797,8 @@ function Browser(window, document, $log, $sniffer) {
14780
14797
  // Do the assignment again so that those two variables are referentially identical.
14781
14798
  lastHistoryState = cachedState;
14782
14799
  } else {
14783
- if (!sameBase || reloadLocation) {
14784
- reloadLocation = url;
14800
+ if (!sameBase || pendingLocation) {
14801
+ pendingLocation = url;
14785
14802
  }
14786
14803
  if (replace) {
14787
14804
  location.replace(url);
@@ -14790,14 +14807,18 @@ function Browser(window, document, $log, $sniffer) {
14790
14807
  } else {
14791
14808
  location.hash = getHash(url);
14792
14809
  }
14810
+ if (location.href !== url) {
14811
+ pendingLocation = url;
14812
+ }
14793
14813
  }
14794
14814
  return self;
14795
14815
  // getter
14796
14816
  } else {
14797
- // - reloadLocation is needed as browsers don't allow to read out
14798
- // the new location.href if a reload happened.
14817
+ // - pendingLocation is needed as browsers don't allow to read out
14818
+ // the new location.href if a reload happened or if there is a bug like in iOS 9 (see
14819
+ // https://openradar.appspot.com/22186109).
14799
14820
  // - the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172
14800
- return reloadLocation || location.href.replace(/%27/g,"'");
14821
+ return pendingLocation || location.href.replace(/%27/g,"'");
14801
14822
  }
14802
14823
  };
14803
14824
 
@@ -14819,6 +14840,7 @@ function Browser(window, document, $log, $sniffer) {
14819
14840
  urlChangeInit = false;
14820
14841
 
14821
14842
  function cacheStateAndFireUrlChange() {
14843
+ pendingLocation = null;
14822
14844
  cacheState();
14823
14845
  fireUrlChange();
14824
14846
  }
@@ -15054,10 +15076,10 @@ function $BrowserProvider() {
15054
15076
  $scope.keys = [];
15055
15077
  $scope.cache = $cacheFactory('cacheId');
15056
15078
  $scope.put = function(key, value) {
15057
- if ($scope.cache.get(key) === undefined) {
15079
+ if (angular.isUndefined($scope.cache.get(key))) {
15058
15080
  $scope.keys.push(key);
15059
15081
  }
15060
- $scope.cache.put(key, value === undefined ? null : value);
15082
+ $scope.cache.put(key, angular.isUndefined(value) ? null : value);
15061
15083
  };
15062
15084
  }]);
15063
15085
  </file>
@@ -15533,18 +15555,24 @@ function $TemplateCacheProvider() {
15533
15555
  * and other directives used in the directive's template will also be excluded from execution.
15534
15556
  *
15535
15557
  * #### `scope`
15536
- * **If set to `true`,** then a new scope will be created for this directive. If multiple directives on the
15537
- * same element request a new scope, only one new scope is created. The new scope rule does not
15538
- * apply for the root of the template since the root of the template always gets a new scope.
15558
+ * The scope property can be `true`, an object or a falsy value:
15559
+ *
15560
+ * * **falsy:** No scope will be created for the directive. The directive will use its parent's scope.
15561
+ *
15562
+ * * **`true`:** A new child scope that prototypically inherits from its parent will be created for
15563
+ * the directive's element. If multiple directives on the same element request a new scope,
15564
+ * only one new scope is created. The new scope rule does not apply for the root of the template
15565
+ * since the root of the template always gets a new scope.
15539
15566
  *
15540
- * **If set to `{}` (object hash),** then a new "isolate" scope is created. The 'isolate' scope differs from
15541
- * normal scope in that it does not prototypically inherit from the parent scope. This is useful
15542
- * when creating reusable components, which should not accidentally read or modify data in the
15543
- * parent scope.
15567
+ * * **`{...}` (an object hash):** A new "isolate" scope is created for the directive's element. The
15568
+ * 'isolate' scope differs from normal scope in that it does not prototypically inherit from its parent
15569
+ * scope. This is useful when creating reusable components, which should not accidentally read or modify
15570
+ * data in the parent scope.
15544
15571
  *
15545
- * The 'isolate' scope takes an object hash which defines a set of local scope properties
15546
- * derived from the parent scope. These local properties are useful for aliasing values for
15547
- * templates. Locals definition is a hash of local scope property to its source:
15572
+ * The 'isolate' scope object hash defines a set of local scope properties derived from attributes on the
15573
+ * directive's element. These local properties are useful for aliasing values for templates. The keys in
15574
+ * the object hash map to the name of the property on the isolate scope; the values define how the property
15575
+ * is bound to the parent scope, via matching attributes on the directive's element:
15548
15576
  *
15549
15577
  * * `@` or `@attr` - bind a local scope property to the value of DOM attribute. The result is
15550
15578
  * always a string since DOM attributes are strings. If no `attr` name is specified then the
@@ -15577,6 +15605,20 @@ function $TemplateCacheProvider() {
15577
15605
  * For example, if the expression is `increment(amount)` then we can specify the amount value
15578
15606
  * by calling the `localFn` as `localFn({amount: 22})`.
15579
15607
  *
15608
+ * In general it's possible to apply more than one directive to one element, but there might be limitations
15609
+ * depending on the type of scope required by the directives. The following points will help explain these limitations.
15610
+ * For simplicity only two directives are taken into account, but it is also applicable for several directives:
15611
+ *
15612
+ * * **no scope** + **no scope** => Two directives which don't require their own scope will use their parent's scope
15613
+ * * **child scope** + **no scope** => Both directives will share one single child scope
15614
+ * * **child scope** + **child scope** => Both directives will share one single child scope
15615
+ * * **isolated scope** + **no scope** => The isolated directive will use it's own created isolated scope. The other directive will use
15616
+ * its parent's scope
15617
+ * * **isolated scope** + **child scope** => **Won't work!** Only one scope can be related to one element. Therefore these directives cannot
15618
+ * be applied to the same element.
15619
+ * * **isolated scope** + **isolated scope** => **Won't work!** Only one scope can be related to one element. Therefore these directives
15620
+ * cannot be applied to the same element.
15621
+ *
15580
15622
  *
15581
15623
  * #### `bindToController`
15582
15624
  * When an isolate scope is used for a component (see above), and `controllerAs` is used, `bindToController: true` will
@@ -15585,7 +15627,7 @@ function $TemplateCacheProvider() {
15585
15627
  *
15586
15628
  * #### `controller`
15587
15629
  * Controller constructor function. The controller is instantiated before the
15588
- * pre-linking phase and it is shared with other directives (see
15630
+ * pre-linking phase and can be accessed by other directives (see
15589
15631
  * `require` attribute). This allows the directives to communicate with each other and augment
15590
15632
  * each other's behavior. The controller is injectable (and supports bracket notation) with the following locals:
15591
15633
  *
@@ -15625,9 +15667,10 @@ function $TemplateCacheProvider() {
15625
15667
  *
15626
15668
  * #### `controllerAs`
15627
15669
  * Identifier name for a reference to the controller in the directive's scope.
15628
- * This allows the controller to be referenced from the directive template. The directive
15629
- * needs to define a scope for this configuration to be used. Useful in the case when
15630
- * directive is used as component.
15670
+ * This allows the controller to be referenced from the directive template. This is especially
15671
+ * useful when a directive is used as component, i.e. with an `isolate` scope. It's also possible
15672
+ * to use it in a directive without an `isolate` / `new` scope, but you need to be aware that the
15673
+ * `controllerAs` reference might overwrite a property that already exists on the parent scope.
15631
15674
  *
15632
15675
  *
15633
15676
  * #### `restrict`
@@ -16464,7 +16507,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
16464
16507
 
16465
16508
  var node = this.$$element[0],
16466
16509
  booleanKey = getBooleanAttrName(node, key),
16467
- aliasedKey = getAliasedAttrName(node, key),
16510
+ aliasedKey = getAliasedAttrName(key),
16468
16511
  observer = key,
16469
16512
  nodeName;
16470
16513
 
@@ -16531,7 +16574,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
16531
16574
  }
16532
16575
 
16533
16576
  if (writeAttr !== false) {
16534
- if (value === null || value === undefined) {
16577
+ if (value === null || isUndefined(value)) {
16535
16578
  this.$$element.removeAttr(attrName);
16536
16579
  } else {
16537
16580
  this.$$element.attr(attrName, value);
@@ -17497,7 +17540,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
17497
17540
  i = 0, ii = directives.length; i < ii; i++) {
17498
17541
  try {
17499
17542
  directive = directives[i];
17500
- if ((maxPriority === undefined || maxPriority > directive.priority) &&
17543
+ if ((isUndefined(maxPriority) || maxPriority > directive.priority) &&
17501
17544
  directive.restrict.indexOf(location) != -1) {
17502
17545
  if (startAttrName) {
17503
17546
  directive = inherit(directive, {$$start: startAttrName, $$end: endAttrName});
@@ -17793,7 +17836,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
17793
17836
  compile: function() {
17794
17837
  return {
17795
17838
  pre: function attrInterpolatePreLinkFn(scope, element, attr) {
17796
- var $$observers = (attr.$$observers || (attr.$$observers = {}));
17839
+ var $$observers = (attr.$$observers || (attr.$$observers = createMap()));
17797
17840
 
17798
17841
  if (EVENT_HANDLER_ATTR_REGEXP.test(name)) {
17799
17842
  throw $compileMinErr('nodomevents',
@@ -18845,28 +18888,18 @@ function $HttpProvider() {
18845
18888
  *
18846
18889
  *
18847
18890
  * ## General usage
18848
- * The `$http` service is a function which takes a single argument — a configuration object —
18891
+ * The `$http` service is a function which takes a single argument — a {@link $http#usage configuration object}
18849
18892
  * that is used to generate an HTTP request and returns a {@link ng.$q promise}.
18850
18893
  *
18851
18894
  * ```js
18852
- * // Simple GET request example :
18853
- * $http.get('/someUrl').
18854
- * then(function(response) {
18855
- * // this callback will be called asynchronously
18856
- * // when the response is available
18857
- * }, function(response) {
18858
- * // called asynchronously if an error occurs
18859
- * // or server returns response with an error status.
18860
- * });
18861
- * ```
18862
- *
18863
- * ```js
18864
- * // Simple POST request example (passing data) :
18865
- * $http.post('/someUrl', {msg:'hello word!'}).
18866
- * then(function(response) {
18895
+ * // Simple GET request example:
18896
+ * $http({
18897
+ * method: 'GET',
18898
+ * url: '/someUrl'
18899
+ * }).then(function successCallback(response) {
18867
18900
  * // this callback will be called asynchronously
18868
18901
  * // when the response is available
18869
- * }, function(response) {
18902
+ * }, function errorCallback(response) {
18870
18903
  * // called asynchronously if an error occurs
18871
18904
  * // or server returns response with an error status.
18872
18905
  * });
@@ -18886,25 +18919,16 @@ function $HttpProvider() {
18886
18919
  * XMLHttpRequest will transparently follow it, meaning that the error callback will not be
18887
18920
  * called for such responses.
18888
18921
  *
18889
- * ## Writing Unit Tests that use $http
18890
- * When unit testing (using {@link ngMock ngMock}), it is necessary to call
18891
- * {@link ngMock.$httpBackend#flush $httpBackend.flush()} to flush each pending
18892
- * request using trained responses.
18893
- *
18894
- * ```
18895
- * $httpBackend.expectGET(...);
18896
- * $http.get(...);
18897
- * $httpBackend.flush();
18898
- * ```
18899
18922
  *
18900
18923
  * ## Shortcut methods
18901
18924
  *
18902
18925
  * Shortcut methods are also available. All shortcut methods require passing in the URL, and
18903
- * request data must be passed in for POST/PUT requests.
18926
+ * request data must be passed in for POST/PUT requests. An optional config can be passed as the
18927
+ * last argument.
18904
18928
  *
18905
18929
  * ```js
18906
- * $http.get('/someUrl').then(successCallback);
18907
- * $http.post('/someUrl', data).then(successCallback);
18930
+ * $http.get('/someUrl', config).then(successCallback, errorCallback);
18931
+ * $http.post('/someUrl', data, config).then(successCallback, errorCallback);
18908
18932
  * ```
18909
18933
  *
18910
18934
  * Complete list of shortcut methods:
@@ -18918,6 +18942,17 @@ function $HttpProvider() {
18918
18942
  * - {@link ng.$http#patch $http.patch}
18919
18943
  *
18920
18944
  *
18945
+ * ## Writing Unit Tests that use $http
18946
+ * When unit testing (using {@link ngMock ngMock}), it is necessary to call
18947
+ * {@link ngMock.$httpBackend#flush $httpBackend.flush()} to flush each pending
18948
+ * request using trained responses.
18949
+ *
18950
+ * ```
18951
+ * $httpBackend.expectGET(...);
18952
+ * $http.get(...);
18953
+ * $httpBackend.flush();
18954
+ * ```
18955
+ *
18921
18956
  * ## Deprecation Notice
18922
18957
  * <div class="alert alert-danger">
18923
18958
  * The `$http` legacy promise methods `success` and `error` have been deprecated.
@@ -19075,7 +19110,7 @@ function $HttpProvider() {
19075
19110
  *
19076
19111
  * There are two kinds of interceptors (and two kinds of rejection interceptors):
19077
19112
  *
19078
- * * `request`: interceptors get called with a http `config` object. The function is free to
19113
+ * * `request`: interceptors get called with a http {@link $http#usage config} object. The function is free to
19079
19114
  * modify the `config` object or create a new one. The function needs to return the `config`
19080
19115
  * object directly, or a promise containing the `config` or a new `config` object.
19081
19116
  * * `requestError`: interceptor gets called when a previous interceptor threw an error or
@@ -19709,8 +19744,8 @@ function $HttpProvider() {
19709
19744
  * Resolves the raw $http promise.
19710
19745
  */
19711
19746
  function resolvePromise(response, status, headers, statusText) {
19712
- // normalize internal statuses to 0
19713
- status = Math.max(status, 0);
19747
+ //status: HTTP response status code, 0, -1 (aborted by timeout / promise)
19748
+ status = status >= -1 ? status : 0;
19714
19749
 
19715
19750
  (isSuccess(status) ? deferred.resolve : deferred.reject)({
19716
19751
  data: response,
@@ -19741,8 +19776,33 @@ function $HttpProvider() {
19741
19776
  }];
19742
19777
  }
19743
19778
 
19744
- function createXhr() {
19745
- return new window.XMLHttpRequest();
19779
+ /**
19780
+ * @ngdoc service
19781
+ * @name $xhrFactory
19782
+ *
19783
+ * @description
19784
+ * Factory function used to create XMLHttpRequest objects.
19785
+ *
19786
+ * Replace or decorate this service to create your own custom XMLHttpRequest objects.
19787
+ *
19788
+ * ```
19789
+ * angular.module('myApp', [])
19790
+ * .factory('$xhrFactory', function() {
19791
+ * return function createXhr(method, url) {
19792
+ * return new window.XMLHttpRequest({mozSystem: true});
19793
+ * };
19794
+ * });
19795
+ * ```
19796
+ *
19797
+ * @param {string} method HTTP method of the request (GET, POST, PUT, ..)
19798
+ * @param {string} url URL of the request.
19799
+ */
19800
+ function $xhrFactoryProvider() {
19801
+ this.$get = function() {
19802
+ return function createXhr() {
19803
+ return new window.XMLHttpRequest();
19804
+ };
19805
+ };
19746
19806
  }
19747
19807
 
19748
19808
  /**
@@ -19750,6 +19810,7 @@ function createXhr() {
19750
19810
  * @name $httpBackend
19751
19811
  * @requires $window
19752
19812
  * @requires $document
19813
+ * @requires $xhrFactory
19753
19814
  *
19754
19815
  * @description
19755
19816
  * HTTP backend used by the {@link ng.$http service} that delegates to
@@ -19762,8 +19823,8 @@ function createXhr() {
19762
19823
  * $httpBackend} which can be trained with responses.
19763
19824
  */
19764
19825
  function $HttpBackendProvider() {
19765
- this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {
19766
- return createHttpBackend($browser, createXhr, $browser.defer, $window.angular.callbacks, $document[0]);
19826
+ this.$get = ['$browser', '$window', '$document', '$xhrFactory', function($browser, $window, $document, $xhrFactory) {
19827
+ return createHttpBackend($browser, $xhrFactory, $browser.defer, $window.angular.callbacks, $document[0]);
19767
19828
  }];
19768
19829
  }
19769
19830
 
@@ -19787,7 +19848,7 @@ function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDoc
19787
19848
  });
19788
19849
  } else {
19789
19850
 
19790
- var xhr = createXhr();
19851
+ var xhr = createXhr(method, url);
19791
19852
 
19792
19853
  xhr.open(method, url, true);
19793
19854
  forEach(headers, function(value, key) {
@@ -19850,7 +19911,7 @@ function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDoc
19850
19911
  }
19851
19912
  }
19852
19913
 
19853
- xhr.send(post);
19914
+ xhr.send(isUndefined(post) ? null : post);
19854
19915
  }
19855
19916
 
19856
19917
  if (timeout > 0) {
@@ -19867,7 +19928,7 @@ function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDoc
19867
19928
 
19868
19929
  function completeRequest(callback, status, response, headersString, statusText) {
19869
19930
  // cancel timeout and subsequent timeout promise resolution
19870
- if (timeoutId !== undefined) {
19931
+ if (isDefined(timeoutId)) {
19871
19932
  $browserDefer.cancel(timeoutId);
19872
19933
  }
19873
19934
  jsonpDone = xhr = null;
@@ -20053,7 +20114,7 @@ function $InterpolateProvider() {
20053
20114
  * ```js
20054
20115
  * var $interpolate = ...; // injected
20055
20116
  * var exp = $interpolate('Hello {{name | uppercase}}!');
20056
- * expect(exp({name:'Angular'}).toEqual('Hello ANGULAR!');
20117
+ * expect(exp({name:'Angular'})).toEqual('Hello ANGULAR!');
20057
20118
  * ```
20058
20119
  *
20059
20120
  * `$interpolate` takes an optional fourth argument, `allOrNothing`. If `allOrNothing` is
@@ -20606,14 +20667,14 @@ function LocationHtml5Url(appBase, appBaseNoFile, basePrefix) {
20606
20667
  var appUrl, prevAppUrl;
20607
20668
  var rewrittenUrl;
20608
20669
 
20609
- if ((appUrl = beginsWith(appBase, url)) !== undefined) {
20670
+ if (isDefined(appUrl = beginsWith(appBase, url))) {
20610
20671
  prevAppUrl = appUrl;
20611
- if ((appUrl = beginsWith(basePrefix, appUrl)) !== undefined) {
20672
+ if (isDefined(appUrl = beginsWith(basePrefix, appUrl))) {
20612
20673
  rewrittenUrl = appBaseNoFile + (beginsWith('/', appUrl) || appUrl);
20613
20674
  } else {
20614
20675
  rewrittenUrl = appBase + prevAppUrl;
20615
20676
  }
20616
- } else if ((appUrl = beginsWith(appBaseNoFile, url)) !== undefined) {
20677
+ } else if (isDefined(appUrl = beginsWith(appBaseNoFile, url))) {
20617
20678
  rewrittenUrl = appBaseNoFile + appUrl;
20618
20679
  } else if (appBaseNoFile == url + '/') {
20619
20680
  rewrittenUrl = appBaseNoFile;
@@ -21666,6 +21727,25 @@ function ensureSafeMemberName(name, fullExpression) {
21666
21727
  return name;
21667
21728
  }
21668
21729
 
21730
+ function getStringValue(name, fullExpression) {
21731
+ // From the JavaScript docs:
21732
+ // Property names must be strings. This means that non-string objects cannot be used
21733
+ // as keys in an object. Any non-string object, including a number, is typecasted
21734
+ // into a string via the toString method.
21735
+ //
21736
+ // So, to ensure that we are checking the same `name` that JavaScript would use,
21737
+ // we cast it to a string, if possible.
21738
+ // Doing `name + ''` can cause a repl error if the result to `toString` is not a string,
21739
+ // this is, this will handle objects that misbehave.
21740
+ name = name + '';
21741
+ if (!isString(name)) {
21742
+ throw $parseMinErr('iseccst',
21743
+ 'Cannot convert object to primitive value! '
21744
+ + 'Expression: {0}', fullExpression);
21745
+ }
21746
+ return name;
21747
+ }
21748
+
21669
21749
  function ensureSafeObject(obj, fullExpression) {
21670
21750
  // nifty check if obj is Function that is fast and works across iframes and other contexts
21671
21751
  if (obj) {
@@ -21711,6 +21791,16 @@ function ensureSafeFunction(obj, fullExpression) {
21711
21791
  }
21712
21792
  }
21713
21793
 
21794
+ function ensureSafeAssignContext(obj, fullExpression) {
21795
+ if (obj) {
21796
+ if (obj === (0).constructor || obj === (false).constructor || obj === ''.constructor ||
21797
+ obj === {}.constructor || obj === [].constructor || obj === Function.constructor) {
21798
+ throw $parseMinErr('isecaf',
21799
+ 'Assigning to a constructor is disallowed! Expression: {0}', fullExpression);
21800
+ }
21801
+ }
21802
+ }
21803
+
21714
21804
  var OPERATORS = createMap();
21715
21805
  forEach('+ - * / % === !== == != < > <= >= && || ! = |'.split(' '), function(operator) { OPERATORS[operator] = true; });
21716
21806
  var ESCAPE = {"n":"\n", "f":"\f", "r":"\r", "t":"\t", "v":"\v", "'":"'", '"':'"'};
@@ -22392,6 +22482,7 @@ ASTCompiler.prototype = {
22392
22482
  this.state.computing = 'assign';
22393
22483
  var result = this.nextId();
22394
22484
  this.recurse(assignable, result);
22485
+ this.return_(result);
22395
22486
  extra = 'fn.assign=' + this.generateFunction('assign', 's,v,l');
22396
22487
  }
22397
22488
  var toWatch = getInputs(ast.body);
@@ -22424,6 +22515,8 @@ ASTCompiler.prototype = {
22424
22515
  'ensureSafeMemberName',
22425
22516
  'ensureSafeObject',
22426
22517
  'ensureSafeFunction',
22518
+ 'getStringValue',
22519
+ 'ensureSafeAssignContext',
22427
22520
  'ifDefined',
22428
22521
  'plus',
22429
22522
  'text',
@@ -22432,6 +22525,8 @@ ASTCompiler.prototype = {
22432
22525
  ensureSafeMemberName,
22433
22526
  ensureSafeObject,
22434
22527
  ensureSafeFunction,
22528
+ getStringValue,
22529
+ ensureSafeAssignContext,
22435
22530
  ifDefined,
22436
22531
  plusFn,
22437
22532
  expression);
@@ -22575,6 +22670,7 @@ ASTCompiler.prototype = {
22575
22670
  if (ast.computed) {
22576
22671
  right = self.nextId();
22577
22672
  self.recurse(ast.property, right);
22673
+ self.getStringValue(right);
22578
22674
  self.addEnsureSafeMemberName(right);
22579
22675
  if (create && create !== 1) {
22580
22676
  self.if_(self.not(self.computedMember(left, right)), self.lazyAssign(self.computedMember(left, right), '{}'));
@@ -22658,6 +22754,7 @@ ASTCompiler.prototype = {
22658
22754
  self.if_(self.notNull(left.context), function() {
22659
22755
  self.recurse(ast.right, right);
22660
22756
  self.addEnsureSafeObject(self.member(left.context, left.name, left.computed));
22757
+ self.addEnsureSafeAssignContext(left.context);
22661
22758
  expression = self.member(left.context, left.name, left.computed) + ast.operator + right;
22662
22759
  self.assign(intoId, expression);
22663
22760
  recursionFn(intoId || expression);
@@ -22783,6 +22880,10 @@ ASTCompiler.prototype = {
22783
22880
  this.current().body.push(this.ensureSafeFunction(item), ';');
22784
22881
  },
22785
22882
 
22883
+ addEnsureSafeAssignContext: function(item) {
22884
+ this.current().body.push(this.ensureSafeAssignContext(item), ';');
22885
+ },
22886
+
22786
22887
  ensureSafeObject: function(item) {
22787
22888
  return 'ensureSafeObject(' + item + ',text)';
22788
22889
  },
@@ -22795,6 +22896,14 @@ ASTCompiler.prototype = {
22795
22896
  return 'ensureSafeFunction(' + item + ',text)';
22796
22897
  },
22797
22898
 
22899
+ getStringValue: function(item) {
22900
+ this.assign(item, 'getStringValue(' + item + ',text)');
22901
+ },
22902
+
22903
+ ensureSafeAssignContext: function(item) {
22904
+ return 'ensureSafeAssignContext(' + item + ',text)';
22905
+ },
22906
+
22798
22907
  lazyRecurse: function(ast, intoId, nameId, recursionFn, create, skipWatchIdCheck) {
22799
22908
  var self = this;
22800
22909
  return function() {
@@ -22972,6 +23081,7 @@ ASTInterpreter.prototype = {
22972
23081
  var lhs = left(scope, locals, assign, inputs);
22973
23082
  var rhs = right(scope, locals, assign, inputs);
22974
23083
  ensureSafeObject(lhs.value, self.expression);
23084
+ ensureSafeAssignContext(lhs.context);
22975
23085
  lhs.context[lhs.name] = rhs;
22976
23086
  return context ? {value: rhs} : rhs;
22977
23087
  };
@@ -23169,6 +23279,7 @@ ASTInterpreter.prototype = {
23169
23279
  var value;
23170
23280
  if (lhs != null) {
23171
23281
  rhs = right(scope, locals, assign, inputs);
23282
+ rhs = getStringValue(rhs);
23172
23283
  ensureSafeMemberName(rhs, expression);
23173
23284
  if (create && create !== 1 && lhs && !(lhs[rhs])) {
23174
23285
  lhs[rhs] = {};
@@ -24109,7 +24220,7 @@ function $$RAFProvider() { //rAF
24109
24220
  $window.webkitCancelRequestAnimationFrame;
24110
24221
 
24111
24222
  var rafSupported = !!requestAnimationFrame;
24112
- var rafFn = rafSupported
24223
+ var raf = rafSupported
24113
24224
  ? function(fn) {
24114
24225
  var id = requestAnimationFrame(fn);
24115
24226
  return function() {
@@ -24123,47 +24234,9 @@ function $$RAFProvider() { //rAF
24123
24234
  };
24124
24235
  };
24125
24236
 
24126
- queueFn.supported = rafSupported;
24127
-
24128
- var cancelLastRAF;
24129
- var taskCount = 0;
24130
- var taskQueue = [];
24131
- return queueFn;
24132
-
24133
- function flush() {
24134
- for (var i = 0; i < taskQueue.length; i++) {
24135
- var task = taskQueue[i];
24136
- if (task) {
24137
- taskQueue[i] = null;
24138
- task();
24139
- }
24140
- }
24141
- taskCount = taskQueue.length = 0;
24142
- }
24143
-
24144
- function queueFn(asyncFn) {
24145
- var index = taskQueue.length;
24237
+ raf.supported = rafSupported;
24146
24238
 
24147
- taskCount++;
24148
- taskQueue.push(asyncFn);
24149
-
24150
- if (index === 0) {
24151
- cancelLastRAF = rafFn(flush);
24152
- }
24153
-
24154
- return function cancelQueueFn() {
24155
- if (index >= 0) {
24156
- taskQueue[index] = null;
24157
- index = null;
24158
-
24159
- if (--taskCount === 0 && cancelLastRAF) {
24160
- cancelLastRAF();
24161
- cancelLastRAF = null;
24162
- taskQueue.length = 0;
24163
- }
24164
- }
24165
- };
24166
- }
24239
+ return raf;
24167
24240
  }];
24168
24241
  }
24169
24242
 
@@ -24420,10 +24493,10 @@ function $RootScopeProvider() {
24420
24493
  * Registers a `listener` callback to be executed whenever the `watchExpression` changes.
24421
24494
  *
24422
24495
  * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest
24423
- * $digest()} and should return the value that will be watched. (Since
24424
- * {@link ng.$rootScope.Scope#$digest $digest()} reruns when it detects changes the
24425
- * `watchExpression` can execute multiple times per
24426
- * {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)
24496
+ * $digest()} and should return the value that will be watched. (`watchExpression` should not change
24497
+ * its value when executed multiple times with the same input because it may be executed multiple
24498
+ * times by {@link ng.$rootScope.Scope#$digest $digest()}. That is, `watchExpression` should be
24499
+ * [idempotent](http://en.wikipedia.org/wiki/Idempotence).
24427
24500
  * - The `listener` is called only when the value from the current `watchExpression` and the
24428
24501
  * previous call to `watchExpression` are not equal (with the exception of the initial run,
24429
24502
  * see below). Inequality is determined according to reference inequality,
@@ -24772,7 +24845,7 @@ function $RootScopeProvider() {
24772
24845
  // copy the items to oldValue and look for changes.
24773
24846
  newLength = 0;
24774
24847
  for (key in newValue) {
24775
- if (newValue.hasOwnProperty(key)) {
24848
+ if (hasOwnProperty.call(newValue, key)) {
24776
24849
  newLength++;
24777
24850
  newItem = newValue[key];
24778
24851
  oldItem = oldValue[key];
@@ -24794,7 +24867,7 @@ function $RootScopeProvider() {
24794
24867
  // we used to have more keys, need to find them and destroy them.
24795
24868
  changeDetected++;
24796
24869
  for (key in oldValue) {
24797
- if (!newValue.hasOwnProperty(key)) {
24870
+ if (!hasOwnProperty.call(newValue, key)) {
24798
24871
  oldLength--;
24799
24872
  delete oldValue[key];
24800
24873
  }
@@ -25879,7 +25952,7 @@ function $SceDelegateProvider() {
25879
25952
  'Attempted to trust a value in invalid context. Context: {0}; Value: {1}',
25880
25953
  type, trustedValue);
25881
25954
  }
25882
- if (trustedValue === null || trustedValue === undefined || trustedValue === '') {
25955
+ if (trustedValue === null || isUndefined(trustedValue) || trustedValue === '') {
25883
25956
  return trustedValue;
25884
25957
  }
25885
25958
  // All the current contexts in SCE_CONTEXTS happen to be strings. In order to avoid trusting
@@ -25934,7 +26007,7 @@ function $SceDelegateProvider() {
25934
26007
  * `$sceDelegate.trustAs`} if valid in this context. Otherwise, throws an exception.
25935
26008
  */
25936
26009
  function getTrusted(type, maybeTrusted) {
25937
- if (maybeTrusted === null || maybeTrusted === undefined || maybeTrusted === '') {
26010
+ if (maybeTrusted === null || isUndefined(maybeTrusted) || maybeTrusted === '') {
25938
26011
  return maybeTrusted;
25939
26012
  }
25940
26013
  var constructor = (byType.hasOwnProperty(type) ? byType[type] : null);
@@ -27195,7 +27268,7 @@ function $$CookieReader($document) {
27195
27268
  // the first value that is seen for a cookie is the most
27196
27269
  // specific one. values for the same cookie name that
27197
27270
  // follow are for less specific paths.
27198
- if (lastCookies[name] === undefined) {
27271
+ if (isUndefined(lastCookies[name])) {
27199
27272
  lastCookies[name] = safeDecodeURIComponent(cookie.substring(index + 1));
27200
27273
  }
27201
27274
  }
@@ -27843,6 +27916,7 @@ function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {
27843
27916
  if (fractionSize > 0 && number < 1) {
27844
27917
  formatedText = number.toFixed(fractionSize);
27845
27918
  number = parseFloat(formatedText);
27919
+ formatedText = formatedText.replace(DECIMAL_SEP, decimalSep);
27846
27920
  }
27847
27921
  }
27848
27922
 
@@ -29141,6 +29215,7 @@ function nullFormRenameControl(control, name) {
29141
29215
  * @property {boolean} $dirty True if user has already interacted with the form.
29142
29216
  * @property {boolean} $valid True if all of the containing forms and controls are valid.
29143
29217
  * @property {boolean} $invalid True if at least one containing control or form is invalid.
29218
+ * @property {boolean} $pending True if at least one containing control or form is pending.
29144
29219
  * @property {boolean} $submitted True if user has submitted the form even if its invalid.
29145
29220
  *
29146
29221
  * @property {Object} $error Is an object hash, containing references to controls or
@@ -29180,8 +29255,6 @@ function FormController(element, attrs, $scope, $animate, $interpolate) {
29180
29255
  var form = this,
29181
29256
  controls = [];
29182
29257
 
29183
- var parentForm = form.$$parentForm = element.parent().controller('form') || nullFormCtrl;
29184
-
29185
29258
  // init state
29186
29259
  form.$error = {};
29187
29260
  form.$$success = {};
@@ -29192,8 +29265,7 @@ function FormController(element, attrs, $scope, $animate, $interpolate) {
29192
29265
  form.$valid = true;
29193
29266
  form.$invalid = false;
29194
29267
  form.$submitted = false;
29195
-
29196
- parentForm.$addControl(form);
29268
+ form.$$parentForm = nullFormCtrl;
29197
29269
 
29198
29270
  /**
29199
29271
  * @ngdoc method
@@ -29232,11 +29304,23 @@ function FormController(element, attrs, $scope, $animate, $interpolate) {
29232
29304
  /**
29233
29305
  * @ngdoc method
29234
29306
  * @name form.FormController#$addControl
29307
+ * @param {object} control control object, either a {@link form.FormController} or an
29308
+ * {@link ngModel.NgModelController}
29235
29309
  *
29236
29310
  * @description
29237
- * Register a control with the form.
29311
+ * Register a control with the form. Input elements using ngModelController do this automatically
29312
+ * when they are linked.
29238
29313
  *
29239
- * Input elements using ngModelController do this automatically when they are linked.
29314
+ * Note that the current state of the control will not be reflected on the new parent form. This
29315
+ * is not an issue with normal use, as freshly compiled and linked controls are in a `$pristine`
29316
+ * state.
29317
+ *
29318
+ * However, if the method is used programmatically, for example by adding dynamically created controls,
29319
+ * or controls that have been previously removed without destroying their corresponding DOM element,
29320
+ * it's the developers responsiblity to make sure the current state propagates to the parent form.
29321
+ *
29322
+ * For example, if an input control is added that is already `$dirty` and has `$error` properties,
29323
+ * calling `$setDirty()` and `$validate()` afterwards will propagate the state to the parent form.
29240
29324
  */
29241
29325
  form.$addControl = function(control) {
29242
29326
  // Breaking change - before, inputs whose name was "hasOwnProperty" were quietly ignored
@@ -29247,6 +29331,8 @@ function FormController(element, attrs, $scope, $animate, $interpolate) {
29247
29331
  if (control.$name) {
29248
29332
  form[control.$name] = control;
29249
29333
  }
29334
+
29335
+ control.$$parentForm = form;
29250
29336
  };
29251
29337
 
29252
29338
  // Private API: rename a form control
@@ -29263,11 +29349,18 @@ function FormController(element, attrs, $scope, $animate, $interpolate) {
29263
29349
  /**
29264
29350
  * @ngdoc method
29265
29351
  * @name form.FormController#$removeControl
29352
+ * @param {object} control control object, either a {@link form.FormController} or an
29353
+ * {@link ngModel.NgModelController}
29266
29354
  *
29267
29355
  * @description
29268
29356
  * Deregister a control from the form.
29269
29357
  *
29270
29358
  * Input elements using ngModelController do this automatically when they are destroyed.
29359
+ *
29360
+ * Note that only the removed control's validation state (`$errors`etc.) will be removed from the
29361
+ * form. `$dirty`, `$submitted` states will not be changed, because the expected behavior can be
29362
+ * different from case to case. For example, removing the only `$dirty` control from a form may or
29363
+ * may not mean that the form is still `$dirty`.
29271
29364
  */
29272
29365
  form.$removeControl = function(control) {
29273
29366
  if (control.$name && form[control.$name] === control) {
@@ -29284,6 +29377,7 @@ function FormController(element, attrs, $scope, $animate, $interpolate) {
29284
29377
  });
29285
29378
 
29286
29379
  arrayRemove(controls, control);
29380
+ control.$$parentForm = nullFormCtrl;
29287
29381
  };
29288
29382
 
29289
29383
 
@@ -29320,7 +29414,6 @@ function FormController(element, attrs, $scope, $animate, $interpolate) {
29320
29414
  delete object[property];
29321
29415
  }
29322
29416
  },
29323
- parentForm: parentForm,
29324
29417
  $animate: $animate
29325
29418
  });
29326
29419
 
@@ -29339,7 +29432,7 @@ function FormController(element, attrs, $scope, $animate, $interpolate) {
29339
29432
  $animate.addClass(element, DIRTY_CLASS);
29340
29433
  form.$dirty = true;
29341
29434
  form.$pristine = false;
29342
- parentForm.$setDirty();
29435
+ form.$$parentForm.$setDirty();
29343
29436
  };
29344
29437
 
29345
29438
  /**
@@ -29395,7 +29488,7 @@ function FormController(element, attrs, $scope, $animate, $interpolate) {
29395
29488
  form.$setSubmitted = function() {
29396
29489
  $animate.addClass(element, SUBMITTED_CLASS);
29397
29490
  form.$submitted = true;
29398
- parentForm.$setSubmitted();
29491
+ form.$$parentForm.$setSubmitted();
29399
29492
  };
29400
29493
  }
29401
29494
 
@@ -29445,6 +29538,7 @@ function FormController(element, attrs, $scope, $animate, $interpolate) {
29445
29538
  * # CSS classes
29446
29539
  * - `ng-valid` is set if the form is valid.
29447
29540
  * - `ng-invalid` is set if the form is invalid.
29541
+ * - `ng-pending` is set if the form is pending.
29448
29542
  * - `ng-pristine` is set if the form is pristine.
29449
29543
  * - `ng-dirty` is set if the form is dirty.
29450
29544
  * - `ng-submitted` is set if the form was submitted.
@@ -29520,7 +29614,6 @@ function FormController(element, attrs, $scope, $animate, $interpolate) {
29520
29614
  </script>
29521
29615
  <style>
29522
29616
  .my-form {
29523
- -webkit-transition:all linear 0.5s;
29524
29617
  transition:all linear 0.5s;
29525
29618
  background: transparent;
29526
29619
  }
@@ -29569,6 +29662,7 @@ var formDirectiveFactory = function(isNgForm) {
29569
29662
  var formDirective = {
29570
29663
  name: 'form',
29571
29664
  restrict: isNgForm ? 'EAC' : 'E',
29665
+ require: ['form', '^^?form'], //first is the form's own ctrl, second is an optional parent form
29572
29666
  controller: FormController,
29573
29667
  compile: function ngFormCompile(formElement, attr) {
29574
29668
  // Setup initial state of the control
@@ -29577,7 +29671,9 @@ var formDirectiveFactory = function(isNgForm) {
29577
29671
  var nameAttr = attr.name ? 'name' : (isNgForm && attr.ngForm ? 'ngForm' : false);
29578
29672
 
29579
29673
  return {
29580
- pre: function ngFormPreLink(scope, formElement, attr, controller) {
29674
+ pre: function ngFormPreLink(scope, formElement, attr, ctrls) {
29675
+ var controller = ctrls[0];
29676
+
29581
29677
  // if `action` attr is not present on the form, prevent the default action (submission)
29582
29678
  if (!('action' in attr)) {
29583
29679
  // we can't use jq events because if a form is destroyed during submission the default
@@ -29606,7 +29702,9 @@ var formDirectiveFactory = function(isNgForm) {
29606
29702
  });
29607
29703
  }
29608
29704
 
29609
- var parentFormCtrl = controller.$$parentForm;
29705
+ var parentFormCtrl = ctrls[1] || controller.$$parentForm;
29706
+ parentFormCtrl.$addControl(controller);
29707
+
29610
29708
  var setter = nameAttr ? getSetter(controller.$name) : noop;
29611
29709
 
29612
29710
  if (nameAttr) {
@@ -29614,13 +29712,13 @@ var formDirectiveFactory = function(isNgForm) {
29614
29712
  attr.$observe(nameAttr, function(newValue) {
29615
29713
  if (controller.$name === newValue) return;
29616
29714
  setter(scope, undefined);
29617
- parentFormCtrl.$$renameControl(controller, newValue);
29715
+ controller.$$parentForm.$$renameControl(controller, newValue);
29618
29716
  setter = getSetter(controller.$name);
29619
29717
  setter(scope, controller);
29620
29718
  });
29621
29719
  }
29622
29720
  formElement.on('$destroy', function() {
29623
- parentFormCtrl.$removeControl(controller);
29721
+ controller.$$parentForm.$removeControl(controller);
29624
29722
  setter(scope, undefined);
29625
29723
  extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards
29626
29724
  });
@@ -29782,9 +29880,17 @@ var inputType = {
29782
29880
  * @param {string} ngModel Assignable angular expression to data-bind to.
29783
29881
  * @param {string=} name Property name of the form under which the control is published.
29784
29882
  * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a
29785
- * valid ISO date string (yyyy-MM-dd).
29883
+ * valid ISO date string (yyyy-MM-dd). You can also use interpolation inside this attribute
29884
+ * (e.g. `min="{{minDate | date:'yyyy-MM-dd'}}"`). Note that `min` will also add native HTML5
29885
+ * constraint validation.
29786
29886
  * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be
29787
- * a valid ISO date string (yyyy-MM-dd).
29887
+ * a valid ISO date string (yyyy-MM-dd). You can also use interpolation inside this attribute
29888
+ * (e.g. `max="{{maxDate | date:'yyyy-MM-dd'}}"`). Note that `max` will also add native HTML5
29889
+ * constraint validation.
29890
+ * @param {(date|string)=} ngMin Sets the `min` validation constraint to the Date / ISO date string
29891
+ * the `ngMin` expression evaluates to. Note that it does not set the `min` attribute.
29892
+ * @param {(date|string)=} ngMax Sets the `max` validation constraint to the Date / ISO date string
29893
+ * the `ngMax` expression evaluates to. Note that it does not set the `max` attribute.
29788
29894
  * @param {string=} required Sets `required` validation error key if the value is not entered.
29789
29895
  * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
29790
29896
  * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
@@ -29876,10 +29982,18 @@ var inputType = {
29876
29982
  *
29877
29983
  * @param {string} ngModel Assignable angular expression to data-bind to.
29878
29984
  * @param {string=} name Property name of the form under which the control is published.
29879
- * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a
29880
- * valid ISO datetime format (yyyy-MM-ddTHH:mm:ss).
29881
- * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be
29882
- * a valid ISO datetime format (yyyy-MM-ddTHH:mm:ss).
29985
+ * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`.
29986
+ * This must be a valid ISO datetime format (yyyy-MM-ddTHH:mm:ss). You can also use interpolation
29987
+ * inside this attribute (e.g. `min="{{minDatetimeLocal | date:'yyyy-MM-ddTHH:mm:ss'}}"`).
29988
+ * Note that `min` will also add native HTML5 constraint validation.
29989
+ * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`.
29990
+ * This must be a valid ISO datetime format (yyyy-MM-ddTHH:mm:ss). You can also use interpolation
29991
+ * inside this attribute (e.g. `max="{{maxDatetimeLocal | date:'yyyy-MM-ddTHH:mm:ss'}}"`).
29992
+ * Note that `max` will also add native HTML5 constraint validation.
29993
+ * @param {(date|string)=} ngMin Sets the `min` validation error key to the Date / ISO datetime string
29994
+ * the `ngMin` expression evaluates to. Note that it does not set the `min` attribute.
29995
+ * @param {(date|string)=} ngMax Sets the `max` validation error key to the Date / ISO datetime string
29996
+ * the `ngMax` expression evaluates to. Note that it does not set the `max` attribute.
29883
29997
  * @param {string=} required Sets `required` validation error key if the value is not entered.
29884
29998
  * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
29885
29999
  * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
@@ -29972,10 +30086,18 @@ var inputType = {
29972
30086
  *
29973
30087
  * @param {string} ngModel Assignable angular expression to data-bind to.
29974
30088
  * @param {string=} name Property name of the form under which the control is published.
29975
- * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a
29976
- * valid ISO time format (HH:mm:ss).
29977
- * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be a
29978
- * valid ISO time format (HH:mm:ss).
30089
+ * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`.
30090
+ * This must be a valid ISO time format (HH:mm:ss). You can also use interpolation inside this
30091
+ * attribute (e.g. `min="{{minTime | date:'HH:mm:ss'}}"`). Note that `min` will also add
30092
+ * native HTML5 constraint validation.
30093
+ * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`.
30094
+ * This must be a valid ISO time format (HH:mm:ss). You can also use interpolation inside this
30095
+ * attribute (e.g. `max="{{maxTime | date:'HH:mm:ss'}}"`). Note that `max` will also add
30096
+ * native HTML5 constraint validation.
30097
+ * @param {(date|string)=} ngMin Sets the `min` validation constraint to the Date / ISO time string the
30098
+ * `ngMin` expression evaluates to. Note that it does not set the `min` attribute.
30099
+ * @param {(date|string)=} ngMax Sets the `max` validation constraint to the Date / ISO time string the
30100
+ * `ngMax` expression evaluates to. Note that it does not set the `max` attribute.
29979
30101
  * @param {string=} required Sets `required` validation error key if the value is not entered.
29980
30102
  * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
29981
30103
  * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
@@ -30067,10 +30189,18 @@ var inputType = {
30067
30189
  *
30068
30190
  * @param {string} ngModel Assignable angular expression to data-bind to.
30069
30191
  * @param {string=} name Property name of the form under which the control is published.
30070
- * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a
30071
- * valid ISO week format (yyyy-W##).
30072
- * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be
30073
- * a valid ISO week format (yyyy-W##).
30192
+ * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`.
30193
+ * This must be a valid ISO week format (yyyy-W##). You can also use interpolation inside this
30194
+ * attribute (e.g. `min="{{minWeek | date:'yyyy-Www'}}"`). Note that `min` will also add
30195
+ * native HTML5 constraint validation.
30196
+ * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`.
30197
+ * This must be a valid ISO week format (yyyy-W##). You can also use interpolation inside this
30198
+ * attribute (e.g. `max="{{maxWeek | date:'yyyy-Www'}}"`). Note that `max` will also add
30199
+ * native HTML5 constraint validation.
30200
+ * @param {(date|string)=} ngMin Sets the `min` validation constraint to the Date / ISO week string
30201
+ * the `ngMin` expression evaluates to. Note that it does not set the `min` attribute.
30202
+ * @param {(date|string)=} ngMax Sets the `max` validation constraint to the Date / ISO week string
30203
+ * the `ngMax` expression evaluates to. Note that it does not set the `max` attribute.
30074
30204
  * @param {string=} required Sets `required` validation error key if the value is not entered.
30075
30205
  * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
30076
30206
  * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
@@ -30164,10 +30294,19 @@ var inputType = {
30164
30294
  *
30165
30295
  * @param {string} ngModel Assignable angular expression to data-bind to.
30166
30296
  * @param {string=} name Property name of the form under which the control is published.
30167
- * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be
30168
- * a valid ISO month format (yyyy-MM).
30169
- * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must
30170
- * be a valid ISO month format (yyyy-MM).
30297
+ * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`.
30298
+ * This must be a valid ISO month format (yyyy-MM). You can also use interpolation inside this
30299
+ * attribute (e.g. `min="{{minMonth | date:'yyyy-MM'}}"`). Note that `min` will also add
30300
+ * native HTML5 constraint validation.
30301
+ * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`.
30302
+ * This must be a valid ISO month format (yyyy-MM). You can also use interpolation inside this
30303
+ * attribute (e.g. `max="{{maxMonth | date:'yyyy-MM'}}"`). Note that `max` will also add
30304
+ * native HTML5 constraint validation.
30305
+ * @param {(date|string)=} ngMin Sets the `min` validation constraint to the Date / ISO week string
30306
+ * the `ngMin` expression evaluates to. Note that it does not set the `min` attribute.
30307
+ * @param {(date|string)=} ngMax Sets the `max` validation constraint to the Date / ISO week string
30308
+ * the `ngMax` expression evaluates to. Note that it does not set the `max` attribute.
30309
+
30171
30310
  * @param {string=} required Sets `required` validation error key if the value is not entered.
30172
30311
  * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
30173
30312
  * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
@@ -30929,7 +31068,7 @@ function createDateInputType(type, regexp, parseDate, format) {
30929
31068
  }
30930
31069
 
30931
31070
  function parseObservedDateValue(val) {
30932
- return isDefined(val) ? (isDate(val) ? val : parseDate(val)) : undefined;
31071
+ return isDefined(val) && !isDate(val) ? parseDate(val) || undefined : val;
30933
31072
  }
30934
31073
  };
30935
31074
  }
@@ -31424,7 +31563,7 @@ var ngBindDirective = ['$compile', function($compile) {
31424
31563
  $compile.$$addBindingInfo(element, attr.ngBind);
31425
31564
  element = element[0];
31426
31565
  scope.$watch(attr.ngBind, function ngBindWatchAction(value) {
31427
- element.textContent = value === undefined ? '' : value;
31566
+ element.textContent = isUndefined(value) ? '' : value;
31428
31567
  });
31429
31568
  };
31430
31569
  }
@@ -31492,7 +31631,7 @@ var ngBindTemplateDirective = ['$interpolate', '$compile', function($interpolate
31492
31631
  $compile.$$addBindingInfo(element, interpolateFn.expressions);
31493
31632
  element = element[0];
31494
31633
  attr.$observe('ngBindTemplate', function(value) {
31495
- element.textContent = value === undefined ? '' : value;
31634
+ element.textContent = isUndefined(value) ? '' : value;
31496
31635
  });
31497
31636
  };
31498
31637
  }
@@ -31909,7 +32048,6 @@ function classDirective(name, selector) {
31909
32048
  </file>
31910
32049
  <file name="style.css">
31911
32050
  .base-class {
31912
- -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
31913
32051
  transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
31914
32052
  }
31915
32053
 
@@ -33084,7 +33222,6 @@ forEach(
33084
33222
  }
33085
33223
 
33086
33224
  .animate-if.ng-enter, .animate-if.ng-leave {
33087
- -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
33088
33225
  transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
33089
33226
  }
33090
33227
 
@@ -33233,7 +33370,6 @@ var ngIfDirective = ['$animate', function($animate) {
33233
33370
  }
33234
33371
 
33235
33372
  .slide-animate.ng-enter, .slide-animate.ng-leave {
33236
- -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
33237
33373
  transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
33238
33374
 
33239
33375
  position:absolute;
@@ -33452,16 +33588,18 @@ var ngIncludeFillContentDirective = ['$compile',
33452
33588
  * current scope.
33453
33589
  *
33454
33590
  * <div class="alert alert-danger">
33455
- * The only appropriate use of `ngInit` is for aliasing special properties of
33456
- * {@link ng.directive:ngRepeat `ngRepeat`}, as seen in the demo below. Besides this case, you
33457
- * should use {@link guide/controller controllers} rather than `ngInit`
33458
- * to initialize values on a scope.
33591
+ * This directive can be abused to add unnecessary amounts of logic into your templates.
33592
+ * There are only a few appropriate uses of `ngInit`, such as for aliasing special properties of
33593
+ * {@link ng.directive:ngRepeat `ngRepeat`}, as seen in the demo below; and for injecting data via
33594
+ * server side scripting. Besides these few cases, you should use {@link guide/controller controllers}
33595
+ * rather than `ngInit` to initialize values on a scope.
33459
33596
  * </div>
33597
+ *
33460
33598
  * <div class="alert alert-warning">
33461
- * **Note**: If you have assignment in `ngInit` along with {@link ng.$filter `$filter`}, make
33462
- * sure you have parenthesis for correct precedence:
33599
+ * **Note**: If you have assignment in `ngInit` along with a {@link ng.$filter `filter`}, make
33600
+ * sure you have parentheses to ensure correct operator precedence:
33463
33601
  * <pre class="prettyprint">
33464
- * `<div ng-init="test1 = (data | orderBy:'name')"></div>`
33602
+ * `<div ng-init="test1 = ($index | toString)"></div>`
33465
33603
  * </pre>
33466
33604
  * </div>
33467
33605
  *
@@ -33574,7 +33712,7 @@ var ngInitDirective = ngDirective({
33574
33712
  * </file>
33575
33713
  * </example>
33576
33714
  *
33577
- * ### Example - splitting on whitespace
33715
+ * ### Example - splitting on newline
33578
33716
  * <example name="ngList-directive-newlines">
33579
33717
  * <file name="index.html">
33580
33718
  * <textarea ng-model="list" ng-list="&#10;" ng-trim="false"></textarea>
@@ -33659,7 +33797,9 @@ var ngModelMinErr = minErr('ngModel');
33659
33797
  * @ngdoc type
33660
33798
  * @name ngModel.NgModelController
33661
33799
  *
33662
- * @property {string} $viewValue Actual string value in the view.
33800
+ * @property {*} $viewValue The actual value from the control's view. For `input` elements, this is a
33801
+ * String. See {@link ngModel.NgModelController#$setViewValue} for information about when the $viewValue
33802
+ * is set.
33663
33803
  * @property {*} $modelValue The value in the model that the control is bound to.
33664
33804
  * @property {Array.<Function>} $parsers Array of functions to execute, as a pipeline, whenever
33665
33805
  the control reads value from the DOM. The functions are called in array order, each passing
@@ -33873,7 +34013,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
33873
34013
  this.$$success = {}; // keep valid keys here
33874
34014
  this.$pending = undefined; // keep pending keys here
33875
34015
  this.$name = $interpolate($attr.name || '', false)($scope);
33876
-
34016
+ this.$$parentForm = nullFormCtrl;
33877
34017
 
33878
34018
  var parsedNgModel = $parse($attr.ngModel),
33879
34019
  parsedNgModelAssign = parsedNgModel.assign,
@@ -33953,8 +34093,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
33953
34093
  return isUndefined(value) || value === '' || value === null || value !== value;
33954
34094
  };
33955
34095
 
33956
- var parentForm = $element.inheritedData('$formController') || nullFormCtrl,
33957
- currentValidationRunId = 0;
34096
+ var currentValidationRunId = 0;
33958
34097
 
33959
34098
  /**
33960
34099
  * @ngdoc method
@@ -33987,7 +34126,6 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
33987
34126
  unset: function(object, property) {
33988
34127
  delete object[property];
33989
34128
  },
33990
- parentForm: parentForm,
33991
34129
  $animate: $animate
33992
34130
  });
33993
34131
 
@@ -34025,7 +34163,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
34025
34163
  ctrl.$pristine = false;
34026
34164
  $animate.removeClass($element, PRISTINE_CLASS);
34027
34165
  $animate.addClass($element, DIRTY_CLASS);
34028
- parentForm.$setDirty();
34166
+ ctrl.$$parentForm.$setDirty();
34029
34167
  };
34030
34168
 
34031
34169
  /**
@@ -34195,7 +34333,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
34195
34333
 
34196
34334
  function processParseErrors() {
34197
34335
  var errorKey = ctrl.$$parserName || 'parse';
34198
- if (parserValid === undefined) {
34336
+ if (isUndefined(parserValid)) {
34199
34337
  setValidity(errorKey, null);
34200
34338
  } else {
34201
34339
  if (!parserValid) {
@@ -34365,37 +34503,47 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
34365
34503
  * @description
34366
34504
  * Update the view value.
34367
34505
  *
34368
- * This method should be called when an input directive want to change the view value; typically,
34369
- * this is done from within a DOM event handler.
34370
- *
34371
- * For example {@link ng.directive:input input} calls it when the value of the input changes and
34372
- * {@link ng.directive:select select} calls it when an option is selected.
34373
- *
34374
- * If the new `value` is an object (rather than a string or a number), we should make a copy of the
34375
- * object before passing it to `$setViewValue`. This is because `ngModel` does not perform a deep
34376
- * watch of objects, it only looks for a change of identity. If you only change the property of
34377
- * the object then ngModel will not realise that the object has changed and will not invoke the
34378
- * `$parsers` and `$validators` pipelines.
34379
- *
34380
- * For this reason, you should not change properties of the copy once it has been passed to
34381
- * `$setViewValue`. Otherwise you may cause the model value on the scope to change incorrectly.
34506
+ * This method should be called when a control wants to change the view value; typically,
34507
+ * this is done from within a DOM event handler. For example, the {@link ng.directive:input input}
34508
+ * directive calls it when the value of the input changes and {@link ng.directive:select select}
34509
+ * calls it when an option is selected.
34382
34510
  *
34383
- * When this method is called, the new `value` will be staged for committing through the `$parsers`
34511
+ * When `$setViewValue` is called, the new `value` will be staged for committing through the `$parsers`
34384
34512
  * and `$validators` pipelines. If there are no special {@link ngModelOptions} specified then the staged
34385
34513
  * value sent directly for processing, finally to be applied to `$modelValue` and then the
34386
- * **expression** specified in the `ng-model` attribute.
34387
- *
34388
- * Lastly, all the registered change listeners, in the `$viewChangeListeners` list, are called.
34514
+ * **expression** specified in the `ng-model` attribute. Lastly, all the registered change listeners,
34515
+ * in the `$viewChangeListeners` list, are called.
34389
34516
  *
34390
34517
  * In case the {@link ng.directive:ngModelOptions ngModelOptions} directive is used with `updateOn`
34391
34518
  * and the `default` trigger is not listed, all those actions will remain pending until one of the
34392
34519
  * `updateOn` events is triggered on the DOM element.
34393
34520
  * All these actions will be debounced if the {@link ng.directive:ngModelOptions ngModelOptions}
34394
34521
  * directive is used with a custom debounce for this particular event.
34522
+ * Note that a `$digest` is only triggered once the `updateOn` events are fired, or if `debounce`
34523
+ * is specified, once the timer runs out.
34524
+ *
34525
+ * When used with standard inputs, the view value will always be a string (which is in some cases
34526
+ * parsed into another type, such as a `Date` object for `input[date]`.)
34527
+ * However, custom controls might also pass objects to this method. In this case, we should make
34528
+ * a copy of the object before passing it to `$setViewValue`. This is because `ngModel` does not
34529
+ * perform a deep watch of objects, it only looks for a change of identity. If you only change
34530
+ * the property of the object then ngModel will not realise that the object has changed and
34531
+ * will not invoke the `$parsers` and `$validators` pipelines. For this reason, you should
34532
+ * not change properties of the copy once it has been passed to `$setViewValue`.
34533
+ * Otherwise you may cause the model value on the scope to change incorrectly.
34534
+ *
34535
+ * <div class="alert alert-info">
34536
+ * In any case, the value passed to the method should always reflect the current value
34537
+ * of the control. For example, if you are calling `$setViewValue` for an input element,
34538
+ * you should pass the input DOM value. Otherwise, the control and the scope model become
34539
+ * out of sync. It's also important to note that `$setViewValue` does not call `$render` or change
34540
+ * the control's DOM value in any way. If we want to change the control's DOM value
34541
+ * programmatically, we should update the `ngModel` scope expression. Its new value will be
34542
+ * picked up by the model controller, which will run it through the `$formatters`, `$render` it
34543
+ * to update the DOM, and finally call `$validate` on it.
34544
+ * </div>
34395
34545
  *
34396
- * Note that calling this function does not trigger a `$digest`.
34397
- *
34398
- * @param {string} value Value from the view.
34546
+ * @param {*} value value from the view.
34399
34547
  * @param {string} trigger Event that triggered the update.
34400
34548
  */
34401
34549
  this.$setViewValue = function(value, trigger) {
@@ -34572,7 +34720,6 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
34572
34720
  </script>
34573
34721
  <style>
34574
34722
  .my-input {
34575
- -webkit-transition:all linear 0.5s;
34576
34723
  transition:all linear 0.5s;
34577
34724
  background: transparent;
34578
34725
  }
@@ -34659,7 +34806,7 @@ var ngModelDirective = ['$rootScope', function($rootScope) {
34659
34806
  return {
34660
34807
  pre: function ngModelPreLink(scope, element, attr, ctrls) {
34661
34808
  var modelCtrl = ctrls[0],
34662
- formCtrl = ctrls[1] || nullFormCtrl;
34809
+ formCtrl = ctrls[1] || modelCtrl.$$parentForm;
34663
34810
 
34664
34811
  modelCtrl.$$setOptions(ctrls[2] && ctrls[2].$options);
34665
34812
 
@@ -34668,12 +34815,12 @@ var ngModelDirective = ['$rootScope', function($rootScope) {
34668
34815
 
34669
34816
  attr.$observe('name', function(newValue) {
34670
34817
  if (modelCtrl.$name !== newValue) {
34671
- formCtrl.$$renameControl(modelCtrl, newValue);
34818
+ modelCtrl.$$parentForm.$$renameControl(modelCtrl, newValue);
34672
34819
  }
34673
34820
  });
34674
34821
 
34675
34822
  scope.$on('$destroy', function() {
34676
- formCtrl.$removeControl(modelCtrl);
34823
+ modelCtrl.$$parentForm.$removeControl(modelCtrl);
34677
34824
  });
34678
34825
  },
34679
34826
  post: function ngModelPostLink(scope, element, attr, ctrls) {
@@ -34868,7 +35015,7 @@ var ngModelOptionsDirective = function() {
34868
35015
  var that = this;
34869
35016
  this.$options = copy($scope.$eval($attrs.ngModelOptions));
34870
35017
  // Allow adding/overriding bound events
34871
- if (this.$options.updateOn !== undefined) {
35018
+ if (isDefined(this.$options.updateOn)) {
34872
35019
  this.$options.updateOnDefault = false;
34873
35020
  // extract "default" pseudo-event from list of events that can trigger a model update
34874
35021
  this.$options.updateOn = trim(this.$options.updateOn.replace(DEFAULT_REGEXP, function() {
@@ -34891,7 +35038,6 @@ function addSetValidityMethod(context) {
34891
35038
  classCache = {},
34892
35039
  set = context.set,
34893
35040
  unset = context.unset,
34894
- parentForm = context.parentForm,
34895
35041
  $animate = context.$animate;
34896
35042
 
34897
35043
  classCache[INVALID_CLASS] = !(classCache[VALID_CLASS] = $element.hasClass(VALID_CLASS));
@@ -34899,7 +35045,7 @@ function addSetValidityMethod(context) {
34899
35045
  ctrl.$setValidity = setValidity;
34900
35046
 
34901
35047
  function setValidity(validationErrorKey, state, controller) {
34902
- if (state === undefined) {
35048
+ if (isUndefined(state)) {
34903
35049
  createAndSet('$pending', validationErrorKey, controller);
34904
35050
  } else {
34905
35051
  unsetAndCleanup('$pending', validationErrorKey, controller);
@@ -34943,7 +35089,7 @@ function addSetValidityMethod(context) {
34943
35089
  }
34944
35090
 
34945
35091
  toggleValidationCss(validationErrorKey, combinedState);
34946
- parentForm.$setValidity(validationErrorKey, combinedState, ctrl);
35092
+ ctrl.$$parentForm.$setValidity(validationErrorKey, combinedState, ctrl);
34947
35093
  }
34948
35094
 
34949
35095
  function createAndSet(name, value, controller) {
@@ -35604,11 +35750,16 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
35604
35750
  function updateOptionElement(option, element) {
35605
35751
  option.element = element;
35606
35752
  element.disabled = option.disabled;
35607
- if (option.value !== element.value) element.value = option.selectValue;
35753
+ // NOTE: The label must be set before the value, otherwise IE10/11/EDGE create unresponsive
35754
+ // selects in certain circumstances when multiple selects are next to each other and display
35755
+ // the option list in listbox style, i.e. the select is [multiple], or specifies a [size].
35756
+ // See https://github.com/angular/angular.js/issues/11314 for more info.
35757
+ // This is unfortunately untestable with unit / e2e tests
35608
35758
  if (option.label !== element.label) {
35609
35759
  element.label = option.label;
35610
35760
  element.textContent = option.label;
35611
35761
  }
35762
+ if (option.value !== element.value) element.value = option.selectValue;
35612
35763
  }
35613
35764
 
35614
35765
  function addOrReuseElement(parent, current, type, templateElement) {
@@ -35649,7 +35800,10 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
35649
35800
  if (emptyOption_ || unknownOption_) {
35650
35801
  while (current &&
35651
35802
  (current === emptyOption_ ||
35652
- current === unknownOption_)) {
35803
+ current === unknownOption_ ||
35804
+ emptyOption_ && emptyOption_.nodeType === NODE_TYPE_COMMENT)) {
35805
+ // Empty options might have directives that transclude
35806
+ // and insert comments (e.g. ngIf)
35653
35807
  current = current.nextSibling;
35654
35808
  }
35655
35809
  }
@@ -36011,8 +36165,10 @@ var ngPluralizeDirective = ['$locale', '$interpolate', '$log', function($locale,
36011
36165
  * | `$even` | {@type boolean} | true if the iterator position `$index` is even (otherwise false). |
36012
36166
  * | `$odd` | {@type boolean} | true if the iterator position `$index` is odd (otherwise false). |
36013
36167
  *
36014
- * Creating aliases for these properties is possible with {@link ng.directive:ngInit `ngInit`}.
36015
- * This may be useful when, for instance, nesting ngRepeats.
36168
+ * <div class="alert alert-info">
36169
+ * Creating aliases for these properties is possible with {@link ng.directive:ngInit `ngInit`}.
36170
+ * This may be useful when, for instance, nesting ngRepeats.
36171
+ * </div>
36016
36172
  *
36017
36173
  *
36018
36174
  * # Iterating over object properties
@@ -36246,7 +36402,6 @@ var ngPluralizeDirective = ['$locale', '$interpolate', '$log', function($locale,
36246
36402
  .animate-repeat.ng-move,
36247
36403
  .animate-repeat.ng-enter,
36248
36404
  .animate-repeat.ng-leave {
36249
- -webkit-transition:all linear 0.5s;
36250
36405
  transition:all linear 0.5s;
36251
36406
  }
36252
36407
 
@@ -36418,7 +36573,7 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
36418
36573
  // if object, extract keys, in enumeration order, unsorted
36419
36574
  collectionKeys = [];
36420
36575
  for (var itemKey in collection) {
36421
- if (collection.hasOwnProperty(itemKey) && itemKey.charAt(0) !== '$') {
36576
+ if (hasOwnProperty.call(collection, itemKey) && itemKey.charAt(0) !== '$') {
36422
36577
  collectionKeys.push(itemKey);
36423
36578
  }
36424
36579
  }
@@ -36643,9 +36798,7 @@ var NG_HIDE_IN_PROGRESS_CLASS = 'ng-hide-animate';
36643
36798
  background: white;
36644
36799
  }
36645
36800
 
36646
- .animate-show.ng-hide-add.ng-hide-add-active,
36647
- .animate-show.ng-hide-remove.ng-hide-remove-active {
36648
- -webkit-transition: all linear 0.5s;
36801
+ .animate-show.ng-hide-add, .animate-show.ng-hide-remove {
36649
36802
  transition: all linear 0.5s;
36650
36803
  }
36651
36804
 
@@ -36802,7 +36955,6 @@ var ngShowDirective = ['$animate', function($animate) {
36802
36955
  </file>
36803
36956
  <file name="animations.css">
36804
36957
  .animate-hide {
36805
- -webkit-transition: all linear 0.5s;
36806
36958
  transition: all linear 0.5s;
36807
36959
  line-height: 20px;
36808
36960
  opacity: 1;
@@ -37001,7 +37153,6 @@ var ngStyleDirective = ngDirective(function(scope, element, attr) {
37001
37153
  }
37002
37154
 
37003
37155
  .animate-switch.ng-animate {
37004
- -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
37005
37156
  transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
37006
37157
 
37007
37158
  position:absolute;
@@ -37342,31 +37493,162 @@ var SelectController =
37342
37493
  * @description
37343
37494
  * HTML `SELECT` element with angular data-binding.
37344
37495
  *
37345
- * In many cases, `ngRepeat` can be used on `<option>` elements instead of {@link ng.directive:ngOptions
37346
- * ngOptions} to achieve a similar result. However, `ngOptions` provides some benefits such as reducing
37347
- * memory and increasing speed by not creating a new scope for each repeated instance, as well as providing
37348
- * more flexibility in how the `<select>`'s model is assigned via the `select` **`as`** part of the
37349
- * comprehension expression.
37496
+ * The `select` directive is used together with {@link ngModel `ngModel`} to provide data-binding
37497
+ * between the scope and the `<select>` control (including setting default values).
37498
+ * Ìt also handles dynamic `<option>` elements, which can be added using the {@link ngRepeat `ngRepeat}` or
37499
+ * {@link ngOptions `ngOptions`} directives.
37350
37500
  *
37351
- * When an item in the `<select>` menu is selected, the array element or object property
37352
- * represented by the selected option will be bound to the model identified by the `ngModel`
37353
- * directive.
37501
+ * When an item in the `<select>` menu is selected, the value of the selected option will be bound
37502
+ * to the model identified by the `ngModel` directive. With static or repeated options, this is
37503
+ * the content of the `value` attribute or the textContent of the `<option>`, if the value attribute is missing.
37504
+ * If you want dynamic value attributes, you can use interpolation inside the value attribute.
37354
37505
  *
37355
- * If the viewValue contains a value that doesn't match any of the options then the control
37356
- * will automatically add an "unknown" option, which it then removes when this is resolved.
37506
+ * <div class="alert alert-warning">
37507
+ * Note that the value of a `select` directive used without `ngOptions` is always a string.
37508
+ * When the model needs to be bound to a non-string value, you must either explictly convert it
37509
+ * using a directive (see example below) or use `ngOptions` to specify the set of options.
37510
+ * This is because an option element can only be bound to string values at present.
37511
+ * </div>
37512
+ *
37513
+ * If the viewValue of `ngModel` does not match any of the options, then the control
37514
+ * will automatically add an "unknown" option, which it then removes when the mismatch is resolved.
37357
37515
  *
37358
37516
  * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can
37359
37517
  * be nested into the `<select>` element. This element will then represent the `null` or "not selected"
37360
37518
  * option. See example below for demonstration.
37361
37519
  *
37362
37520
  * <div class="alert alert-info">
37363
- * The value of a `select` directive used without `ngOptions` is always a string.
37364
- * When the model needs to be bound to a non-string value, you must either explictly convert it
37365
- * using a directive (see example below) or use `ngOptions` to specify the set of options.
37366
- * This is because an option element can only be bound to string values at present.
37521
+ * In many cases, `ngRepeat` can be used on `<option>` elements instead of {@link ng.directive:ngOptions
37522
+ * ngOptions} to achieve a similar result. However, `ngOptions` provides some benefits, such as
37523
+ * more flexibility in how the `<select>`'s model is assigned via the `select` **`as`** part of the
37524
+ * comprehension expression, and additionally in reducing memory and increasing speed by not creating
37525
+ * a new scope for each repeated instance.
37526
+ * </div>
37527
+ *
37528
+ *
37529
+ * @param {string} ngModel Assignable angular expression to data-bind to.
37530
+ * @param {string=} name Property name of the form under which the control is published.
37531
+ * @param {string=} required Sets `required` validation error key if the value is not entered.
37532
+ * @param {string=} ngRequired Adds required attribute and required validation constraint to
37533
+ * the element when the ngRequired expression evaluates to true. Use ngRequired instead of required
37534
+ * when you want to data-bind to the required attribute.
37535
+ * @param {string=} ngChange Angular expression to be executed when selected option(s) changes due to user
37536
+ * interaction with the select element.
37537
+ * @param {string=} ngOptions sets the options that the select is populated with and defines what is
37538
+ * set on the model on selection. See {@link ngOptions `ngOptions`}.
37539
+ *
37540
+ * @example
37541
+ * ### Simple `select` elements with static options
37542
+ *
37543
+ * <example name="static-select" module="staticSelect">
37544
+ * <file name="index.html">
37545
+ * <div ng-controller="ExampleController">
37546
+ * <form name="myForm">
37547
+ * <label for="singleSelect"> Single select: </label><br>
37548
+ * <select name="singleSelect" ng-model="data.singleSelect">
37549
+ * <option value="option-1">Option 1</option>
37550
+ * <option value="option-2">Option 2</option>
37551
+ * </select><br>
37552
+ *
37553
+ * <label for="singleSelect"> Single select with "not selected" option and dynamic option values: </label><br>
37554
+ * <select name="singleSelect" id="singleSelect" ng-model="data.singleSelect">
37555
+ * <option value="">---Please select---</option> <!-- not selected / blank option -->
37556
+ * <option value="{{data.option1}}">Option 1</option> <!-- interpolation -->
37557
+ * <option value="option-2">Option 2</option>
37558
+ * </select><br>
37559
+ * <button ng-click="forceUnknownOption()">Force unknown option</button><br>
37560
+ * <tt>singleSelect = {{data.singleSelect}}</tt>
37561
+ *
37562
+ * <hr>
37563
+ * <label for="multipleSelect"> Multiple select: </label><br>
37564
+ * <select name="multipleSelect" id="multipleSelect" ng-model="data.multipleSelect" multiple>
37565
+ * <option value="option-1">Option 1</option>
37566
+ * <option value="option-2">Option 2</option>
37567
+ * <option value="option-3">Option 3</option>
37568
+ * </select><br>
37569
+ * <tt>multipleSelect = {{data.multipleSelect}}</tt><br/>
37570
+ * </form>
37571
+ * </div>
37572
+ * </file>
37573
+ * <file name="app.js">
37574
+ * angular.module('staticSelect', [])
37575
+ * .controller('ExampleController', ['$scope', function($scope) {
37576
+ * $scope.data = {
37577
+ * singleSelect: null,
37578
+ * multipleSelect: [],
37579
+ * option1: 'option-1',
37580
+ * };
37581
+ *
37582
+ * $scope.forceUnknownOption = function() {
37583
+ * $scope.data.singleSelect = 'nonsense';
37584
+ * };
37585
+ * }]);
37586
+ * </file>
37587
+ *</example>
37588
+ *
37589
+ * ### Using `ngRepeat` to generate `select` options
37590
+ * <example name="ngrepeat-select" module="ngrepeatSelect">
37591
+ * <file name="index.html">
37592
+ * <div ng-controller="ExampleController">
37593
+ * <form name="myForm">
37594
+ * <label for="repeatSelect"> Repeat select: </label>
37595
+ * <select name="repeatSelect" id="repeatSelect" ng-model="data.repeatSelect">
37596
+ * <option ng-repeat="option in data.availableOptions" value="{{option.id}}">{{option.name}}</option>
37597
+ * </select>
37598
+ * </form>
37599
+ * <hr>
37600
+ * <tt>repeatSelect = {{data.repeatSelect}}</tt><br/>
37367
37601
  * </div>
37602
+ * </file>
37603
+ * <file name="app.js">
37604
+ * angular.module('ngrepeatSelect', [])
37605
+ * .controller('ExampleController', ['$scope', function($scope) {
37606
+ * $scope.data = {
37607
+ * repeatSelect: null,
37608
+ * availableOptions: [
37609
+ * {id: '1', name: 'Option A'},
37610
+ * {id: '2', name: 'Option B'},
37611
+ * {id: '3', name: 'Option C'}
37612
+ * ],
37613
+ * };
37614
+ * }]);
37615
+ * </file>
37616
+ *</example>
37368
37617
  *
37369
- * ### Example (binding `select` to a non-string value)
37618
+ *
37619
+ * ### Using `select` with `ngOptions` and setting a default value
37620
+ * See the {@link ngOptions ngOptions documentation} for more `ngOptions` usage examples.
37621
+ *
37622
+ * <example name="select-with-default-values" module="defaultValueSelect">
37623
+ * <file name="index.html">
37624
+ * <div ng-controller="ExampleController">
37625
+ * <form name="myForm">
37626
+ * <label for="mySelect">Make a choice:</label>
37627
+ * <select name="mySelect" id="mySelect"
37628
+ * ng-options="option.name for option in data.availableOptions track by option.id"
37629
+ * ng-model="data.selectedOption"></select>
37630
+ * </form>
37631
+ * <hr>
37632
+ * <tt>option = {{data.selectedOption}}</tt><br/>
37633
+ * </div>
37634
+ * </file>
37635
+ * <file name="app.js">
37636
+ * angular.module('defaultValueSelect', [])
37637
+ * .controller('ExampleController', ['$scope', function($scope) {
37638
+ * $scope.data = {
37639
+ * availableOptions: [
37640
+ * {id: '1', name: 'Option A'},
37641
+ * {id: '2', name: 'Option B'},
37642
+ * {id: '3', name: 'Option C'}
37643
+ * ],
37644
+ * selectedOption: {id: '3', name: 'Option C'} //This sets the default value of the select in the ui
37645
+ * };
37646
+ * }]);
37647
+ * </file>
37648
+ *</example>
37649
+ *
37650
+ *
37651
+ * ### Binding `select` to a non-string value via `ngModel` parsing / formatting
37370
37652
  *
37371
37653
  * <example name="select-with-non-string-options" module="nonStringSelect">
37372
37654
  * <file name="index.html">
@@ -37504,9 +37786,12 @@ var optionDirective = ['$interpolate', function($interpolate) {
37504
37786
  priority: 100,
37505
37787
  compile: function(element, attr) {
37506
37788
 
37507
- // If the value attribute is not defined then we fall back to the
37508
- // text content of the option element, which may be interpolated
37509
- if (isUndefined(attr.value)) {
37789
+ if (isDefined(attr.value)) {
37790
+ // If the value attribute is defined, check if it contains an interpolation
37791
+ var valueInterpolated = $interpolate(attr.value, true);
37792
+ } else {
37793
+ // If the value attribute is not defined then we fall back to the
37794
+ // text content of the option element, which may be interpolated
37510
37795
  var interpolateFn = $interpolate(element.text(), true);
37511
37796
  if (!interpolateFn) {
37512
37797
  attr.$set('value', element.text());
@@ -37522,24 +37807,38 @@ var optionDirective = ['$interpolate', function($interpolate) {
37522
37807
  selectCtrl = parent.data(selectCtrlName) ||
37523
37808
  parent.parent().data(selectCtrlName); // in case we are in optgroup
37524
37809
 
37810
+ function addOption(optionValue) {
37811
+ selectCtrl.addOption(optionValue, element);
37812
+ selectCtrl.ngModelCtrl.$render();
37813
+ chromeHack(element);
37814
+ }
37815
+
37525
37816
  // Only update trigger option updates if this is an option within a `select`
37526
37817
  // that also has `ngModel` attached
37527
37818
  if (selectCtrl && selectCtrl.ngModelCtrl) {
37528
37819
 
37529
- if (interpolateFn) {
37820
+ if (valueInterpolated) {
37821
+ // The value attribute is interpolated
37822
+ var oldVal;
37823
+ attr.$observe('value', function valueAttributeObserveAction(newVal) {
37824
+ if (isDefined(oldVal)) {
37825
+ selectCtrl.removeOption(oldVal);
37826
+ }
37827
+ oldVal = newVal;
37828
+ addOption(newVal);
37829
+ });
37830
+ } else if (interpolateFn) {
37831
+ // The text content is interpolated
37530
37832
  scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {
37531
37833
  attr.$set('value', newVal);
37532
37834
  if (oldVal !== newVal) {
37533
37835
  selectCtrl.removeOption(oldVal);
37534
37836
  }
37535
- selectCtrl.addOption(newVal, element);
37536
- selectCtrl.ngModelCtrl.$render();
37537
- chromeHack(element);
37837
+ addOption(newVal);
37538
37838
  });
37539
37839
  } else {
37540
- selectCtrl.addOption(attr.value, element);
37541
- selectCtrl.ngModelCtrl.$render();
37542
- chromeHack(element);
37840
+ // The value attribute is static
37841
+ addOption(attr.value);
37543
37842
  }
37544
37843
 
37545
37844
  element.on('$destroy', function() {
@@ -37600,8 +37899,9 @@ var patternDirective = function() {
37600
37899
  ctrl.$validate();
37601
37900
  });
37602
37901
 
37603
- ctrl.$validators.pattern = function(value) {
37604
- return ctrl.$isEmpty(value) || isUndefined(regexp) || regexp.test(value);
37902
+ ctrl.$validators.pattern = function(modelValue, viewValue) {
37903
+ // HTML5 pattern constraint validates the input value, so we validate the viewValue
37904
+ return ctrl.$isEmpty(viewValue) || isUndefined(regexp) || regexp.test(viewValue);
37605
37905
  };
37606
37906
  }
37607
37907
  };
@@ -38079,7 +38379,7 @@ _jQuery.fn.bindings = function(windowJquery, bindExp) {
38079
38379
  }
38080
38380
 
38081
38381
  function push(value) {
38082
- if (value === undefined) {
38382
+ if (angular.isUndefined(value)) {
38083
38383
  value = '';
38084
38384
  } else if (typeof value !== 'string') {
38085
38385
  value = angular.toJson(value);