angularjs-rails 1.4.7 → 1.4.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7bae5d9940bff568ab17129d188748335bd1cc9f
4
- data.tar.gz: 9a01f2802010654a254df0e1fc59928138aa5a31
3
+ metadata.gz: 2207f74add954921e782d488f371f0585dcf3444
4
+ data.tar.gz: 19350206dd0f9aaedf3c29ea4efa5e0702f6b764
5
5
  SHA512:
6
- metadata.gz: fcf4268bf060a5ab19e0244aa3f1a12e771eca9ed57b25b2dd3edf1f56552d678cc7bf829128df527e185a7f920c2708f30d86497ffe8cb83bfd9781b1d87623
7
- data.tar.gz: 6c9efedf3be8ddd17f046264fd67495fb15ffbdd96bff38c66f289f30772e8a15260433c53daa425c7c5adc45fad530435870c82c179ac2d2f8531c6b3be1417
6
+ metadata.gz: 9cf08093f16ac21d0b9edc221f3544fac6ee747e178fb0f3c3edc7a0cef9a6201f1897a0fbd22db5a9aa678365a100532e5c6c0edcb12c33ec40b6cd21c9a8e2
7
+ data.tar.gz: fad7acb23401023066766f4f0a9b97e7cb80399dceb61f9242d2b58818e395fd8ebfcd9ab343b4f7b14302227b6f1313890952bc06c9004e06e79a2187b1f114
@@ -1,6 +1,6 @@
1
1
  module AngularJS
2
2
  module Rails
3
- VERSION = "1.4.7"
4
- UNSTABLE_VERSION = "2.0.0-alpha.37"
3
+ VERSION = "1.4.8"
4
+ UNSTABLE_VERSION = "2.0.0-alpha.48"
5
5
  end
6
6
  end
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.4.7
2
+ * @license AngularJS v1.4.8
3
3
  * (c) 2010-2015 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -622,6 +622,8 @@ var ANIMATE_TIMER_KEY = '$$animateCss';
622
622
  *
623
623
  * * `event` - The DOM event (e.g. enter, leave, move). When used, a generated CSS class of `ng-EVENT` and `ng-EVENT-active` will be applied
624
624
  * to the element during the animation. Multiple events can be provided when spaces are used as a separator. (Note that this will not perform any DOM operation.)
625
+ * * `structural` - Indicates that the `ng-` prefix will be added to the event class. Setting to `false` or omitting will turn `ng-EVENT` and
626
+ * `ng-EVENT-active` in `EVENT` and `EVENT-active`. Unused if `event` is omitted.
625
627
  * * `easing` - The CSS easing value that will be applied to the transition or keyframe animation (or both).
626
628
  * * `transitionStyle` - The raw CSS transition style that will be used (e.g. `1s linear all`).
627
629
  * * `keyframeStyle` - The raw CSS keyframe animation style that will be used (e.g. `1s my_animation linear`).
@@ -2133,8 +2135,9 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
2133
2135
  return mergeAnimationOptions(element, options, {});
2134
2136
  }
2135
2137
 
2136
- function findCallbacks(element, event) {
2138
+ function findCallbacks(parent, element, event) {
2137
2139
  var targetNode = getDomNode(element);
2140
+ var targetParentNode = getDomNode(parent);
2138
2141
 
2139
2142
  var matches = [];
2140
2143
  var entries = callbackRegistry[event];
@@ -2142,6 +2145,8 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
2142
2145
  forEach(entries, function(entry) {
2143
2146
  if (entry.node.contains(targetNode)) {
2144
2147
  matches.push(entry.callback);
2148
+ } else if (event === 'leave' && entry.node.contains(targetParentNode)) {
2149
+ matches.push(entry.callback);
2145
2150
  }
2146
2151
  });
2147
2152
  }
@@ -2467,7 +2472,7 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
2467
2472
 
2468
2473
  function notifyProgress(runner, event, phase, data) {
2469
2474
  runInNextPostDigestOrNow(function() {
2470
- var callbacks = findCallbacks(element, event);
2475
+ var callbacks = findCallbacks(parent, element, event);
2471
2476
  if (callbacks.length) {
2472
2477
  // do not optimize this call here to RAF because
2473
2478
  // we don't know how heavy the callback code here will
@@ -3458,7 +3463,7 @@ var $$AnimationProvider = ['$animateProvider', function($animateProvider) {
3458
3463
  * jQuery(element).fadeOut(1000, doneFn);
3459
3464
  * }
3460
3465
  * }
3461
- * }]
3466
+ * }]);
3462
3467
  * ```
3463
3468
  *
3464
3469
  * The nice thing about JS-based animations is that we can inject other services and make use of advanced animation libraries such as
@@ -3489,7 +3494,7 @@ var $$AnimationProvider = ['$animateProvider', function($animateProvider) {
3489
3494
  * // do some cool animation and call the doneFn
3490
3495
  * }
3491
3496
  * }
3492
- * }]
3497
+ * }]);
3493
3498
  * ```
3494
3499
  *
3495
3500
  * ## CSS + JS Animations Together
@@ -3511,7 +3516,7 @@ var $$AnimationProvider = ['$animateProvider', function($animateProvider) {
3511
3516
  * jQuery(element).slideIn(1000, doneFn);
3512
3517
  * }
3513
3518
  * }
3514
- * }]
3519
+ * }]);
3515
3520
  * ```
3516
3521
  *
3517
3522
  * ```css
@@ -3531,16 +3536,15 @@ var $$AnimationProvider = ['$animateProvider', function($animateProvider) {
3531
3536
  * ```js
3532
3537
  * myModule.animation('.slide', ['$animateCss', function($animateCss) {
3533
3538
  * return {
3534
- * enter: function(element, doneFn) {
3539
+ * enter: function(element) {
3535
3540
  * // this will trigger `.slide.ng-enter` and `.slide.ng-enter-active`.
3536
- * var runner = $animateCss(element, {
3541
+ * return $animateCss(element, {
3537
3542
  * event: 'enter',
3538
3543
  * structural: true
3539
- * }).start();
3540
- * runner.done(doneFn);
3544
+ * });
3541
3545
  * }
3542
3546
  * }
3543
- * }]
3547
+ * }]);
3544
3548
  * ```
3545
3549
  *
3546
3550
  * The nice thing here is that we can save bandwidth by sticking to our CSS-based animation code and we don't need to rely on a 3rd-party animation framework.
@@ -3552,19 +3556,17 @@ var $$AnimationProvider = ['$animateProvider', function($animateProvider) {
3552
3556
  * ```js
3553
3557
  * myModule.animation('.slide', ['$animateCss', function($animateCss) {
3554
3558
  * return {
3555
- * enter: function(element, doneFn) {
3556
- * var runner = $animateCss(element, {
3559
+ * enter: function(element) {
3560
+ * return $animateCss(element, {
3557
3561
  * event: 'enter',
3558
3562
  * structural: true,
3559
3563
  * addClass: 'maroon-setting',
3560
3564
  * from: { height:0 },
3561
3565
  * to: { height: 200 }
3562
- * }).start();
3563
- *
3564
- * runner.done(doneFn);
3566
+ * });
3565
3567
  * }
3566
3568
  * }
3567
- * }]
3569
+ * }]);
3568
3570
  * ```
3569
3571
  *
3570
3572
  * Now we can fill in the rest via our transition CSS code:
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.4.7
2
+ * @license AngularJS v1.4.8
3
3
  * (c) 2010-2015 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -240,7 +240,8 @@ ngAriaModule.directive('ngShow', ['$aria', function($aria) {
240
240
  }
241
241
  },
242
242
  post: function(scope, elem, attr, ngModel) {
243
- var needsTabIndex = shouldAttachAttr('tabindex', 'tabindex', elem);
243
+ var needsTabIndex = shouldAttachAttr('tabindex', 'tabindex', elem)
244
+ && !isNodeOneOf(elem, nodeBlackList);
244
245
 
245
246
  function ngAriaWatchModelValue() {
246
247
  return ngModel.$modelValue;
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.4.7
2
+ * @license AngularJS v1.4.8
3
3
  * (c) 2010-2015 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.4.7
2
+ * @license AngularJS v1.4.8
3
3
  * (c) 2010-2015 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -59,7 +59,7 @@ function minErr(module, ErrorConstructor) {
59
59
  return match;
60
60
  });
61
61
 
62
- message += '\nhttp://errors.angularjs.org/1.4.7/' +
62
+ message += '\nhttp://errors.angularjs.org/1.4.8/' +
63
63
  (module ? module + '/' : '') + code;
64
64
 
65
65
  for (i = SKIP_INDEXES, paramPrefix = '?'; i < templateArgs.length; i++, paramPrefix = '&') {
@@ -259,7 +259,7 @@ function setupModuleLoader(window) {
259
259
  * @param {string} name constant name
260
260
  * @param {*} object Constant value.
261
261
  * @description
262
- * Because the constant are fixed, they get applied before other provide methods.
262
+ * Because the constants are fixed, they get applied before other provide methods.
263
263
  * See {@link auto.$provide#constant $provide.constant()}.
264
264
  */
265
265
  constant: invokeLater('$provide', 'constant', 'unshift'),
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.4.7
2
+ * @license AngularJS v1.4.8
3
3
  * (c) 2010-2015 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.4.7
2
+ * @license AngularJS v1.4.8
3
3
  * (c) 2010-2015 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.4.7
2
+ * @license AngularJS v1.4.8
3
3
  * (c) 2010-2015 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -2278,8 +2278,9 @@ if (window.jasmine || window.mocha) {
2278
2278
  * @param {...(string|Function|Object)} fns any number of modules which are represented as string
2279
2279
  * aliases or as anonymous module initialization functions. The modules are used to
2280
2280
  * configure the injector. The 'ng' and 'ngMock' modules are automatically loaded. If an
2281
- * object literal is passed they will be registered as values in the module, the key being
2282
- * the module name and the value being what is returned.
2281
+ * object literal is passed each key-value pair will be registered on the module via
2282
+ * {@link auto.$provide $provide}.value, the key being the string name (or token) to associate
2283
+ * with the value on the injector.
2283
2284
  */
2284
2285
  window.module = angular.mock.module = function() {
2285
2286
  var moduleFns = Array.prototype.slice.call(arguments, 0);
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.4.7
2
+ * @license AngularJS v1.4.8
3
3
  * (c) 2010-2015 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -573,8 +573,17 @@ angular.module('ngResource', ['ng']).
573
573
  undefined;
574
574
 
575
575
  forEach(action, function(value, key) {
576
- if (key != 'params' && key != 'isArray' && key != 'interceptor') {
577
- httpConfig[key] = copy(value);
576
+ switch (key) {
577
+ default:
578
+ httpConfig[key] = copy(value);
579
+ break;
580
+ case 'params':
581
+ case 'isArray':
582
+ case 'interceptor':
583
+ break;
584
+ case 'timeout':
585
+ httpConfig[key] = value;
586
+ break;
578
587
  }
579
588
  });
580
589
 
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.4.7
2
+ * @license AngularJS v1.4.8
3
3
  * (c) 2010-2015 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.4.7
2
+ * @license AngularJS v1.4.8
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.7
9193
+ * @license AngularJS v1.4.8
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.7/' +
9252
+ message += '\nhttp://errors.angularjs.org/1.4.8/' +
9253
9253
  (module ? module + '/' : '') + code;
9254
9254
 
9255
9255
  for (i = SKIP_INDEXES, paramPrefix = '?'; i < templateArgs.length; i++, paramPrefix = '&') {
@@ -9459,20 +9459,24 @@ msie = document.documentMode;
9459
9459
  * String ...)
9460
9460
  */
9461
9461
  function isArrayLike(obj) {
9462
- if (obj == null || isWindow(obj)) {
9463
- return false;
9464
- }
9462
+
9463
+ // `null`, `undefined` and `window` are not array-like
9464
+ if (obj == null || isWindow(obj)) return false;
9465
+
9466
+ // arrays, strings and jQuery/jqLite objects are array like
9467
+ // * jqLite is either the jQuery or jqLite constructor function
9468
+ // * we have to check the existance of jqLite first as this method is called
9469
+ // via the forEach method when constructing the jqLite object in the first place
9470
+ if (isArray(obj) || isString(obj) || (jqLite && obj instanceof jqLite)) return true;
9465
9471
 
9466
9472
  // Support: iOS 8.2 (not reproducible in simulator)
9467
9473
  // "length" in obj used to prevent JIT error (gh-11508)
9468
9474
  var length = "length" in Object(obj) && obj.length;
9469
9475
 
9470
- if (obj.nodeType === NODE_TYPE_ELEMENT && length) {
9471
- return true;
9472
- }
9473
-
9474
- return isString(obj) || isArray(obj) || length === 0 ||
9475
- typeof length === 'number' && length > 0 && (length - 1) in obj;
9476
+ // NodeList objects (with `item` method) and
9477
+ // other objects with suitable length characteristics are array-like
9478
+ return isNumber(length) &&
9479
+ (length >= 0 && (length - 1) in obj || typeof obj.item == 'function');
9476
9480
  }
9477
9481
 
9478
9482
  /**
@@ -9617,6 +9621,10 @@ function baseExtend(dst, objs, deep) {
9617
9621
  dst[key] = new Date(src.valueOf());
9618
9622
  } else if (isRegExp(src)) {
9619
9623
  dst[key] = new RegExp(src);
9624
+ } else if (src.nodeName) {
9625
+ dst[key] = src.cloneNode(true);
9626
+ } else if (isElement(src)) {
9627
+ dst[key] = src.clone();
9620
9628
  } else {
9621
9629
  if (!isObject(dst[key])) dst[key] = isArray(src) ? [] : {};
9622
9630
  baseExtend(dst[key], [src], true);
@@ -9732,7 +9740,7 @@ identity.$inject = [];
9732
9740
  function valueFn(value) {return function() {return value;};}
9733
9741
 
9734
9742
  function hasCustomToString(obj) {
9735
- return isFunction(obj.toString) && obj.toString !== Object.prototype.toString;
9743
+ return isFunction(obj.toString) && obj.toString !== toString;
9736
9744
  }
9737
9745
 
9738
9746
 
@@ -9931,9 +9939,9 @@ function isPromiseLike(obj) {
9931
9939
  }
9932
9940
 
9933
9941
 
9934
- var TYPED_ARRAY_REGEXP = /^\[object (Uint8(Clamped)?)|(Uint16)|(Uint32)|(Int8)|(Int16)|(Int32)|(Float(32)|(64))Array\]$/;
9942
+ var TYPED_ARRAY_REGEXP = /^\[object (?:Uint8|Uint8Clamped|Uint16|Uint32|Int8|Int16|Int32|Float32|Float64)Array\]$/;
9935
9943
  function isTypedArray(value) {
9936
- return TYPED_ARRAY_REGEXP.test(toString.call(value));
9944
+ return value && isNumber(value.length) && TYPED_ARRAY_REGEXP.test(toString.call(value));
9937
9945
  }
9938
9946
 
9939
9947
 
@@ -10055,100 +10063,111 @@ function arrayRemove(array, value) {
10055
10063
  </file>
10056
10064
  </example>
10057
10065
  */
10058
- function copy(source, destination, stackSource, stackDest) {
10059
- if (isWindow(source) || isScope(source)) {
10060
- throw ngMinErr('cpws',
10061
- "Can't copy! Making copies of Window or Scope instances is not supported.");
10062
- }
10063
- if (isTypedArray(destination)) {
10064
- throw ngMinErr('cpta',
10065
- "Can't copy! TypedArray destination cannot be mutated.");
10066
- }
10066
+ function copy(source, destination) {
10067
+ var stackSource = [];
10068
+ var stackDest = [];
10067
10069
 
10068
- if (!destination) {
10069
- destination = source;
10070
- if (isObject(source)) {
10071
- var index;
10072
- if (stackSource && (index = stackSource.indexOf(source)) !== -1) {
10073
- return stackDest[index];
10074
- }
10075
-
10076
- // TypedArray, Date and RegExp have specific copy functionality and must be
10077
- // pushed onto the stack before returning.
10078
- // Array and other objects create the base object and recurse to copy child
10079
- // objects. The array/object will be pushed onto the stack when recursed.
10080
- if (isArray(source)) {
10081
- return copy(source, [], stackSource, stackDest);
10082
- } else if (isTypedArray(source)) {
10083
- destination = new source.constructor(source);
10084
- } else if (isDate(source)) {
10085
- destination = new Date(source.getTime());
10086
- } else if (isRegExp(source)) {
10087
- destination = new RegExp(source.source, source.toString().match(/[^\/]*$/)[0]);
10088
- destination.lastIndex = source.lastIndex;
10089
- } else if (isFunction(source.cloneNode)) {
10090
- destination = source.cloneNode(true);
10091
- } else {
10092
- var emptyObject = Object.create(getPrototypeOf(source));
10093
- return copy(source, emptyObject, stackSource, stackDest);
10094
- }
10070
+ if (destination) {
10071
+ if (isTypedArray(destination)) {
10072
+ throw ngMinErr('cpta', "Can't copy! TypedArray destination cannot be mutated.");
10073
+ }
10074
+ if (source === destination) {
10075
+ throw ngMinErr('cpi', "Can't copy! Source and destination are identical.");
10076
+ }
10095
10077
 
10096
- if (stackDest) {
10097
- stackSource.push(source);
10098
- stackDest.push(destination);
10099
- }
10078
+ // Empty the destination object
10079
+ if (isArray(destination)) {
10080
+ destination.length = 0;
10081
+ } else {
10082
+ forEach(destination, function(value, key) {
10083
+ if (key !== '$$hashKey') {
10084
+ delete destination[key];
10085
+ }
10086
+ });
10100
10087
  }
10101
- } else {
10102
- if (source === destination) throw ngMinErr('cpi',
10103
- "Can't copy! Source and destination are identical.");
10104
10088
 
10105
- stackSource = stackSource || [];
10106
- stackDest = stackDest || [];
10089
+ stackSource.push(source);
10090
+ stackDest.push(destination);
10091
+ return copyRecurse(source, destination);
10092
+ }
10107
10093
 
10108
- if (isObject(source)) {
10109
- stackSource.push(source);
10110
- stackDest.push(destination);
10111
- }
10094
+ return copyElement(source);
10112
10095
 
10096
+ function copyRecurse(source, destination) {
10097
+ var h = destination.$$hashKey;
10113
10098
  var result, key;
10114
10099
  if (isArray(source)) {
10115
- destination.length = 0;
10116
- for (var i = 0; i < source.length; i++) {
10117
- destination.push(copy(source[i], null, stackSource, stackDest));
10100
+ for (var i = 0, ii = source.length; i < ii; i++) {
10101
+ destination.push(copyElement(source[i]));
10118
10102
  }
10119
- } else {
10120
- var h = destination.$$hashKey;
10121
- if (isArray(destination)) {
10122
- destination.length = 0;
10123
- } else {
10124
- forEach(destination, function(value, key) {
10125
- delete destination[key];
10126
- });
10103
+ } else if (isBlankObject(source)) {
10104
+ // createMap() fast path --- Safe to avoid hasOwnProperty check because prototype chain is empty
10105
+ for (key in source) {
10106
+ destination[key] = copyElement(source[key]);
10127
10107
  }
10128
- if (isBlankObject(source)) {
10129
- // createMap() fast path --- Safe to avoid hasOwnProperty check because prototype chain is empty
10130
- for (key in source) {
10131
- destination[key] = copy(source[key], null, stackSource, stackDest);
10132
- }
10133
- } else if (source && typeof source.hasOwnProperty === 'function') {
10134
- // Slow path, which must rely on hasOwnProperty
10135
- for (key in source) {
10136
- if (source.hasOwnProperty(key)) {
10137
- destination[key] = copy(source[key], null, stackSource, stackDest);
10138
- }
10108
+ } else if (source && typeof source.hasOwnProperty === 'function') {
10109
+ // Slow path, which must rely on hasOwnProperty
10110
+ for (key in source) {
10111
+ if (source.hasOwnProperty(key)) {
10112
+ destination[key] = copyElement(source[key]);
10139
10113
  }
10140
- } else {
10141
- // Slowest path --- hasOwnProperty can't be called as a method
10142
- for (key in source) {
10143
- if (hasOwnProperty.call(source, key)) {
10144
- destination[key] = copy(source[key], null, stackSource, stackDest);
10145
- }
10114
+ }
10115
+ } else {
10116
+ // Slowest path --- hasOwnProperty can't be called as a method
10117
+ for (key in source) {
10118
+ if (hasOwnProperty.call(source, key)) {
10119
+ destination[key] = copyElement(source[key]);
10146
10120
  }
10147
10121
  }
10148
- setHashKey(destination,h);
10149
10122
  }
10123
+ setHashKey(destination, h);
10124
+ return destination;
10125
+ }
10126
+
10127
+ function copyElement(source) {
10128
+ // Simple values
10129
+ if (!isObject(source)) {
10130
+ return source;
10131
+ }
10132
+
10133
+ // Already copied values
10134
+ var index = stackSource.indexOf(source);
10135
+ if (index !== -1) {
10136
+ return stackDest[index];
10137
+ }
10138
+
10139
+ if (isWindow(source) || isScope(source)) {
10140
+ throw ngMinErr('cpws',
10141
+ "Can't copy! Making copies of Window or Scope instances is not supported.");
10142
+ }
10143
+
10144
+ var needsRecurse = false;
10145
+ var destination;
10146
+
10147
+ if (isArray(source)) {
10148
+ destination = [];
10149
+ needsRecurse = true;
10150
+ } else if (isTypedArray(source)) {
10151
+ destination = new source.constructor(source);
10152
+ } else if (isDate(source)) {
10153
+ destination = new Date(source.getTime());
10154
+ } else if (isRegExp(source)) {
10155
+ destination = new RegExp(source.source, source.toString().match(/[^\/]*$/)[0]);
10156
+ destination.lastIndex = source.lastIndex;
10157
+ } else if (isFunction(source.cloneNode)) {
10158
+ destination = source.cloneNode(true);
10159
+ } else {
10160
+ destination = Object.create(getPrototypeOf(source));
10161
+ needsRecurse = true;
10162
+ }
10163
+
10164
+ stackSource.push(source);
10165
+ stackDest.push(destination);
10166
+
10167
+ return needsRecurse
10168
+ ? copyRecurse(source, destination)
10169
+ : destination;
10150
10170
  }
10151
- return destination;
10152
10171
  }
10153
10172
 
10154
10173
  /**
@@ -11272,7 +11291,7 @@ function setupModuleLoader(window) {
11272
11291
  * @param {string} name constant name
11273
11292
  * @param {*} object Constant value.
11274
11293
  * @description
11275
- * Because the constant are fixed, they get applied before other provide methods.
11294
+ * Because the constants are fixed, they get applied before other provide methods.
11276
11295
  * See {@link auto.$provide#constant $provide.constant()}.
11277
11296
  */
11278
11297
  constant: invokeLater('$provide', 'constant', 'unshift'),
@@ -11571,11 +11590,11 @@ function toDebugString(obj) {
11571
11590
  * - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat".
11572
11591
  */
11573
11592
  var version = {
11574
- full: '1.4.7', // all of these placeholder strings will be replaced by grunt's
11593
+ full: '1.4.8', // all of these placeholder strings will be replaced by grunt's
11575
11594
  major: 1, // package task
11576
11595
  minor: 4,
11577
- dot: 7,
11578
- codeName: 'dark-luminescence'
11596
+ dot: 8,
11597
+ codeName: 'ice-manipulation'
11579
11598
  };
11580
11599
 
11581
11600
 
@@ -11957,6 +11976,14 @@ function jqLiteParseHTML(html, context) {
11957
11976
  return [];
11958
11977
  }
11959
11978
 
11979
+
11980
+ // IE9-11 has no method "contains" in SVG element and in Node.prototype. Bug #10259.
11981
+ var jqLiteContains = Node.prototype.contains || function(arg) {
11982
+ // jshint bitwise: false
11983
+ return !!(this.compareDocumentPosition(arg) & 16);
11984
+ // jshint bitwise: true
11985
+ };
11986
+
11960
11987
  /////////////////////////////////////////////
11961
11988
  function JQLite(element) {
11962
11989
  if (element instanceof JQLite) {
@@ -12015,17 +12042,23 @@ function jqLiteOff(element, type, fn, unsupported) {
12015
12042
  delete events[type];
12016
12043
  }
12017
12044
  } else {
12018
- forEach(type.split(' '), function(type) {
12045
+
12046
+ var removeHandler = function(type) {
12047
+ var listenerFns = events[type];
12019
12048
  if (isDefined(fn)) {
12020
- var listenerFns = events[type];
12021
12049
  arrayRemove(listenerFns || [], fn);
12022
- if (listenerFns && listenerFns.length > 0) {
12023
- return;
12024
- }
12025
12050
  }
12051
+ if (!(isDefined(fn) && listenerFns && listenerFns.length > 0)) {
12052
+ removeEventListenerFn(element, type, handle);
12053
+ delete events[type];
12054
+ }
12055
+ };
12026
12056
 
12027
- removeEventListenerFn(element, type, handle);
12028
- delete events[type];
12057
+ forEach(type.split(' '), function(type) {
12058
+ removeHandler(type);
12059
+ if (MOUSE_EVENT_MAP[type]) {
12060
+ removeHandler(MOUSE_EVENT_MAP[type]);
12061
+ }
12029
12062
  });
12030
12063
  }
12031
12064
  }
@@ -12480,6 +12513,9 @@ function createEventHandler(element, events) {
12480
12513
  return event.immediatePropagationStopped === true;
12481
12514
  };
12482
12515
 
12516
+ // Some events have special handlers that wrap the real handler
12517
+ var handlerWrapper = eventFns.specialHandlerWrapper || defaultHandlerWrapper;
12518
+
12483
12519
  // Copy event handlers in case event handlers array is modified during execution.
12484
12520
  if ((eventFnsLength > 1)) {
12485
12521
  eventFns = shallowCopy(eventFns);
@@ -12487,7 +12523,7 @@ function createEventHandler(element, events) {
12487
12523
 
12488
12524
  for (var i = 0; i < eventFnsLength; i++) {
12489
12525
  if (!event.isImmediatePropagationStopped()) {
12490
- eventFns[i].call(element, event);
12526
+ handlerWrapper(element, event, eventFns[i]);
12491
12527
  }
12492
12528
  }
12493
12529
  };
@@ -12498,6 +12534,22 @@ function createEventHandler(element, events) {
12498
12534
  return eventHandler;
12499
12535
  }
12500
12536
 
12537
+ function defaultHandlerWrapper(element, event, handler) {
12538
+ handler.call(element, event);
12539
+ }
12540
+
12541
+ function specialMouseHandlerWrapper(target, event, handler) {
12542
+ // Refer to jQuery's implementation of mouseenter & mouseleave
12543
+ // Read about mouseenter and mouseleave:
12544
+ // http://www.quirksmode.org/js/events_mouse.html#link8
12545
+ var related = event.relatedTarget;
12546
+ // For mousenter/leave call the handler if related is outside the target.
12547
+ // NB: No relatedTarget if the mouse left/entered the browser window
12548
+ if (!related || (related !== target && !jqLiteContains.call(target, related))) {
12549
+ handler.call(target, event);
12550
+ }
12551
+ }
12552
+
12501
12553
  //////////////////////////////////////////
12502
12554
  // Functions iterating traversal.
12503
12555
  // These functions chain results into a single
@@ -12526,35 +12578,28 @@ forEach({
12526
12578
  var types = type.indexOf(' ') >= 0 ? type.split(' ') : [type];
12527
12579
  var i = types.length;
12528
12580
 
12529
- while (i--) {
12530
- type = types[i];
12581
+ var addHandler = function(type, specialHandlerWrapper, noEventListener) {
12531
12582
  var eventFns = events[type];
12532
12583
 
12533
12584
  if (!eventFns) {
12534
- events[type] = [];
12535
-
12536
- if (type === 'mouseenter' || type === 'mouseleave') {
12537
- // Refer to jQuery's implementation of mouseenter & mouseleave
12538
- // Read about mouseenter and mouseleave:
12539
- // http://www.quirksmode.org/js/events_mouse.html#link8
12540
-
12541
- jqLiteOn(element, MOUSE_EVENT_MAP[type], function(event) {
12542
- var target = this, related = event.relatedTarget;
12543
- // For mousenter/leave call the handler if related is outside the target.
12544
- // NB: No relatedTarget if the mouse left/entered the browser window
12545
- if (!related || (related !== target && !target.contains(related))) {
12546
- handle(event, type);
12547
- }
12548
- });
12549
-
12550
- } else {
12551
- if (type !== '$destroy') {
12552
- addEventListenerFn(element, type, handle);
12553
- }
12585
+ eventFns = events[type] = [];
12586
+ eventFns.specialHandlerWrapper = specialHandlerWrapper;
12587
+ if (type !== '$destroy' && !noEventListener) {
12588
+ addEventListenerFn(element, type, handle);
12554
12589
  }
12555
- eventFns = events[type];
12556
12590
  }
12591
+
12557
12592
  eventFns.push(fn);
12593
+ };
12594
+
12595
+ while (i--) {
12596
+ type = types[i];
12597
+ if (MOUSE_EVENT_MAP[type]) {
12598
+ addHandler(MOUSE_EVENT_MAP[type], specialMouseHandlerWrapper);
12599
+ addHandler(type, undefined, true);
12600
+ } else {
12601
+ addHandler(type);
12602
+ }
12558
12603
  }
12559
12604
  },
12560
12605
 
@@ -13735,7 +13780,7 @@ function $AnchorScrollProvider() {
13735
13780
  * When called, it scrolls to the element related to the specified `hash` or (if omitted) to the
13736
13781
  * current value of {@link ng.$location#hash $location.hash()}, according to the rules specified
13737
13782
  * in the
13738
- * [HTML5 spec](http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document).
13783
+ * [HTML5 spec](http://www.w3.org/html/wg/drafts/html/master/browsers.html#the-indicated-part-of-the-document).
13739
13784
  *
13740
13785
  * It also watches the {@link ng.$location#hash $location.hash()} and automatically scrolls to
13741
13786
  * match any anchor whenever it changes. This can be disabled by calling
@@ -14250,7 +14295,7 @@ var $AnimateProvider = ['$provide', function($provide) {
14250
14295
  * when an animation is detected (and animations are enabled), $animate will do the heavy lifting
14251
14296
  * to ensure that animation runs with the triggered DOM operation.
14252
14297
  *
14253
- * By default $animate doesn't trigger an animations. This is because the `ngAnimate` module isn't
14298
+ * By default $animate doesn't trigger any animations. This is because the `ngAnimate` module isn't
14254
14299
  * included and only when it is active then the animation hooks that `$animate` triggers will be
14255
14300
  * functional. Once active then all structural `ng-` directives will trigger animations as they perform
14256
14301
  * their DOM-related operations (enter, leave and move). Other directives such as `ngClass`,
@@ -15102,9 +15147,9 @@ function $CacheFactoryProvider() {
15102
15147
 
15103
15148
  var size = 0,
15104
15149
  stats = extend({}, options, {id: cacheId}),
15105
- data = {},
15150
+ data = createMap(),
15106
15151
  capacity = (options && options.capacity) || Number.MAX_VALUE,
15107
- lruHash = {},
15152
+ lruHash = createMap(),
15108
15153
  freshEnd = null,
15109
15154
  staleEnd = null;
15110
15155
 
@@ -15232,6 +15277,8 @@ function $CacheFactoryProvider() {
15232
15277
  delete lruHash[key];
15233
15278
  }
15234
15279
 
15280
+ if (!(key in data)) return;
15281
+
15235
15282
  delete data[key];
15236
15283
  size--;
15237
15284
  },
@@ -15246,9 +15293,9 @@ function $CacheFactoryProvider() {
15246
15293
  * Clears the cache object of any entries.
15247
15294
  */
15248
15295
  removeAll: function() {
15249
- data = {};
15296
+ data = createMap();
15250
15297
  size = 0;
15251
- lruHash = {};
15298
+ lruHash = createMap();
15252
15299
  freshEnd = staleEnd = null;
15253
15300
  },
15254
15301
 
@@ -16649,6 +16696,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
16649
16696
  return template.replace(/\{\{/g, startSymbol).replace(/}}/g, endSymbol);
16650
16697
  },
16651
16698
  NG_ATTR_BINDING = /^ngAttr[A-Z]/;
16699
+ var MULTI_ELEMENT_DIR_RE = /^(.+)Start$/;
16652
16700
 
16653
16701
  compile.$$addBindingInfo = debugInfoEnabled ? function $$addBindingInfo($element, binding) {
16654
16702
  var bindings = $element.data('$binding') || [];
@@ -16701,6 +16749,14 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
16701
16749
  return function publicLinkFn(scope, cloneConnectFn, options) {
16702
16750
  assertArg(scope, 'scope');
16703
16751
 
16752
+ if (previousCompileContext && previousCompileContext.needsNewScope) {
16753
+ // A parent directive did a replace and a directive on this element asked
16754
+ // for transclusion, which caused us to lose a layer of element on which
16755
+ // we could hold the new transclusion scope, so we will create it manually
16756
+ // here.
16757
+ scope = scope.$parent.$new();
16758
+ }
16759
+
16704
16760
  options = options || {};
16705
16761
  var parentBoundTranscludeFn = options.parentBoundTranscludeFn,
16706
16762
  transcludeControllers = options.transcludeControllers,
@@ -16846,11 +16902,6 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
16846
16902
  if (nodeLinkFn.scope) {
16847
16903
  childScope = scope.$new();
16848
16904
  compile.$$addScopeInfo(jqLite(node), childScope);
16849
- var destroyBindings = nodeLinkFn.$$destroyBindings;
16850
- if (destroyBindings) {
16851
- nodeLinkFn.$$destroyBindings = null;
16852
- childScope.$on('$destroyed', destroyBindings);
16853
- }
16854
16905
  } else {
16855
16906
  childScope = scope;
16856
16907
  }
@@ -16869,8 +16920,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
16869
16920
  childBoundTranscludeFn = null;
16870
16921
  }
16871
16922
 
16872
- nodeLinkFn(childLinkFn, childScope, node, $rootElement, childBoundTranscludeFn,
16873
- nodeLinkFn);
16923
+ nodeLinkFn(childLinkFn, childScope, node, $rootElement, childBoundTranscludeFn);
16874
16924
 
16875
16925
  } else if (childLinkFn) {
16876
16926
  childLinkFn(scope, node.childNodes, undefined, parentBoundTranscludeFn);
@@ -16939,13 +16989,11 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
16939
16989
  });
16940
16990
  }
16941
16991
 
16942
- var directiveNName = ngAttrName.replace(/(Start|End)$/, '');
16943
- if (directiveIsMultiElement(directiveNName)) {
16944
- if (ngAttrName === directiveNName + 'Start') {
16945
- attrStartName = name;
16946
- attrEndName = name.substr(0, name.length - 5) + 'end';
16947
- name = name.substr(0, name.length - 6);
16948
- }
16992
+ var multiElementMatch = ngAttrName.match(MULTI_ELEMENT_DIR_RE);
16993
+ if (multiElementMatch && directiveIsMultiElement(multiElementMatch[1])) {
16994
+ attrStartName = name;
16995
+ attrEndName = name.substr(0, name.length - 5) + 'end';
16996
+ name = name.substr(0, name.length - 6);
16949
16997
  }
16950
16998
 
16951
16999
  nName = directiveNormalize(name.toLowerCase());
@@ -17184,7 +17232,8 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
17184
17232
  } else {
17185
17233
  $template = jqLite(jqLiteClone(compileNode)).contents();
17186
17234
  $compileNode.empty(); // clear contents
17187
- childTranscludeFn = compile($template, transcludeFn);
17235
+ childTranscludeFn = compile($template, transcludeFn, undefined,
17236
+ undefined, { needsNewScope: directive.$$isolateScope || directive.$$newScope});
17188
17237
  }
17189
17238
  }
17190
17239
 
@@ -17226,8 +17275,11 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
17226
17275
  var templateDirectives = collectDirectives(compileNode, [], newTemplateAttrs);
17227
17276
  var unprocessedDirectives = directives.splice(i + 1, directives.length - (i + 1));
17228
17277
 
17229
- if (newIsolateScopeDirective) {
17230
- markDirectivesAsIsolate(templateDirectives);
17278
+ if (newIsolateScopeDirective || newScopeDirective) {
17279
+ // The original directive caused the current element to be replaced but this element
17280
+ // also needs to have a new scope, so we need to tell the template directives
17281
+ // that they would need to get their scope from further up, if they require transclusion
17282
+ markDirectiveScope(templateDirectives, newIsolateScopeDirective, newScopeDirective);
17231
17283
  }
17232
17284
  directives = directives.concat(templateDirectives).concat(unprocessedDirectives);
17233
17285
  mergeTemplateAttributes(templateAttrs, newTemplateAttrs);
@@ -17380,10 +17432,9 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
17380
17432
  return elementControllers;
17381
17433
  }
17382
17434
 
17383
- function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn,
17384
- thisLinkFn) {
17385
- var i, ii, linkFn, controller, isolateScope, elementControllers, transcludeFn, $element,
17386
- attrs;
17435
+ function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {
17436
+ var linkFn, isolateScope, controllerScope, elementControllers, transcludeFn, $element,
17437
+ attrs, removeScopeBindingWatches, removeControllerBindingWatches;
17387
17438
 
17388
17439
  if (compileNode === linkNode) {
17389
17440
  attrs = templateAttrs;
@@ -17393,8 +17444,11 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
17393
17444
  attrs = new Attributes($element, templateAttrs);
17394
17445
  }
17395
17446
 
17447
+ controllerScope = scope;
17396
17448
  if (newIsolateScopeDirective) {
17397
17449
  isolateScope = scope.$new(true);
17450
+ } else if (newScopeDirective) {
17451
+ controllerScope = scope.$parent;
17398
17452
  }
17399
17453
 
17400
17454
  if (boundTranscludeFn) {
@@ -17415,42 +17469,34 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
17415
17469
  compile.$$addScopeClass($element, true);
17416
17470
  isolateScope.$$isolateBindings =
17417
17471
  newIsolateScopeDirective.$$isolateBindings;
17418
- initializeDirectiveBindings(scope, attrs, isolateScope,
17419
- isolateScope.$$isolateBindings,
17420
- newIsolateScopeDirective, isolateScope);
17421
- }
17422
- if (elementControllers) {
17423
- // Initialize bindToController bindings for new/isolate scopes
17424
- var scopeDirective = newIsolateScopeDirective || newScopeDirective;
17425
- var bindings;
17426
- var controllerForBindings;
17427
- if (scopeDirective && elementControllers[scopeDirective.name]) {
17428
- bindings = scopeDirective.$$bindings.bindToController;
17429
- controller = elementControllers[scopeDirective.name];
17430
-
17431
- if (controller && controller.identifier && bindings) {
17432
- controllerForBindings = controller;
17433
- thisLinkFn.$$destroyBindings =
17434
- initializeDirectiveBindings(scope, attrs, controller.instance,
17435
- bindings, scopeDirective);
17436
- }
17472
+ removeScopeBindingWatches = initializeDirectiveBindings(scope, attrs, isolateScope,
17473
+ isolateScope.$$isolateBindings,
17474
+ newIsolateScopeDirective);
17475
+ if (removeScopeBindingWatches) {
17476
+ isolateScope.$on('$destroy', removeScopeBindingWatches);
17437
17477
  }
17438
- for (i in elementControllers) {
17439
- controller = elementControllers[i];
17440
- var controllerResult = controller();
17441
-
17442
- if (controllerResult !== controller.instance) {
17443
- // If the controller constructor has a return value, overwrite the instance
17444
- // from setupControllers and update the element data
17445
- controller.instance = controllerResult;
17446
- $element.data('$' + i + 'Controller', controllerResult);
17447
- if (controller === controllerForBindings) {
17448
- // Remove and re-install bindToController bindings
17449
- thisLinkFn.$$destroyBindings();
17450
- thisLinkFn.$$destroyBindings =
17451
- initializeDirectiveBindings(scope, attrs, controllerResult, bindings, scopeDirective);
17452
- }
17453
- }
17478
+ }
17479
+
17480
+ // Initialize bindToController bindings
17481
+ for (var name in elementControllers) {
17482
+ var controllerDirective = controllerDirectives[name];
17483
+ var controller = elementControllers[name];
17484
+ var bindings = controllerDirective.$$bindings.bindToController;
17485
+
17486
+ if (controller.identifier && bindings) {
17487
+ removeControllerBindingWatches =
17488
+ initializeDirectiveBindings(controllerScope, attrs, controller.instance, bindings, controllerDirective);
17489
+ }
17490
+
17491
+ var controllerResult = controller();
17492
+ if (controllerResult !== controller.instance) {
17493
+ // If the controller constructor has a return value, overwrite the instance
17494
+ // from setupControllers
17495
+ controller.instance = controllerResult;
17496
+ $element.data('$' + controllerDirective.name + 'Controller', controllerResult);
17497
+ removeControllerBindingWatches && removeControllerBindingWatches();
17498
+ removeControllerBindingWatches =
17499
+ initializeDirectiveBindings(controllerScope, attrs, controller.instance, bindings, controllerDirective);
17454
17500
  }
17455
17501
  }
17456
17502
 
@@ -17510,10 +17556,15 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
17510
17556
  }
17511
17557
  }
17512
17558
 
17513
- function markDirectivesAsIsolate(directives) {
17514
- // mark all directives as needing isolate scope.
17559
+ // Depending upon the context in which a directive finds itself it might need to have a new isolated
17560
+ // or child scope created. For instance:
17561
+ // * if the directive has been pulled into a template because another directive with a higher priority
17562
+ // asked for element transclusion
17563
+ // * if the directive itself asks for transclusion but it is at the root of a template and the original
17564
+ // element was replaced. See https://github.com/angular/angular.js/issues/12936
17565
+ function markDirectiveScope(directives, isolateScope, newScope) {
17515
17566
  for (var j = 0, jj = directives.length; j < jj; j++) {
17516
- directives[j] = inherit(directives[j], {$$isolateScope: true});
17567
+ directives[j] = inherit(directives[j], {$$isolateScope: isolateScope, $$newScope: newScope});
17517
17568
  }
17518
17569
  }
17519
17570
 
@@ -17660,7 +17711,9 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
17660
17711
  var templateDirectives = collectDirectives(compileNode, [], tempTemplateAttrs);
17661
17712
 
17662
17713
  if (isObject(origAsyncDirective.scope)) {
17663
- markDirectivesAsIsolate(templateDirectives);
17714
+ // the original directive that caused the template to be loaded async required
17715
+ // an isolate scope
17716
+ markDirectiveScope(templateDirectives, true);
17664
17717
  }
17665
17718
  directives = templateDirectives.concat(directives);
17666
17719
  mergeTemplateAttributes(tAttrs, tempTemplateAttrs);
@@ -17709,7 +17762,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
17709
17762
  childBoundTranscludeFn = boundTranscludeFn;
17710
17763
  }
17711
17764
  afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement,
17712
- childBoundTranscludeFn, afterTemplateNodeLinkFn);
17765
+ childBoundTranscludeFn);
17713
17766
  }
17714
17767
  linkQueue = null;
17715
17768
  });
@@ -17726,8 +17779,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
17726
17779
  if (afterTemplateNodeLinkFn.transcludeOnThisElement) {
17727
17780
  childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude, boundTranscludeFn);
17728
17781
  }
17729
- afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, childBoundTranscludeFn,
17730
- afterTemplateNodeLinkFn);
17782
+ afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, childBoundTranscludeFn);
17731
17783
  }
17732
17784
  };
17733
17785
  }
@@ -17939,7 +17991,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
17939
17991
  // Copy over user data (that includes Angular's $scope etc.). Don't copy private
17940
17992
  // data here because there's no public interface in jQuery to do that and copying over
17941
17993
  // event listeners (which is the main use of private data) wouldn't work anyway.
17942
- jqLite(newNode).data(jqLite(firstElementToRemove).data());
17994
+ jqLite.data(newNode, jqLite.data(firstElementToRemove));
17943
17995
 
17944
17996
  // Remove data of the replaced element. We cannot just call .remove()
17945
17997
  // on the element it since that would deallocate scope that is needed
@@ -17987,9 +18039,8 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
17987
18039
 
17988
18040
  // Set up $watches for isolate scope and controller bindings. This process
17989
18041
  // only occurs for isolate scopes and new scopes with controllerAs.
17990
- function initializeDirectiveBindings(scope, attrs, destination, bindings,
17991
- directive, newScope) {
17992
- var onNewScopeDestroyed;
18042
+ function initializeDirectiveBindings(scope, attrs, destination, bindings, directive) {
18043
+ var removeWatchCollection = [];
17993
18044
  forEach(bindings, function(definition, scopeName) {
17994
18045
  var attrName = definition.attrName,
17995
18046
  optional = definition.optional,
@@ -18051,14 +18102,13 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
18051
18102
  return lastValue = parentValue;
18052
18103
  };
18053
18104
  parentValueWatch.$stateful = true;
18054
- var unwatch;
18105
+ var removeWatch;
18055
18106
  if (definition.collection) {
18056
- unwatch = scope.$watchCollection(attrs[attrName], parentValueWatch);
18107
+ removeWatch = scope.$watchCollection(attrs[attrName], parentValueWatch);
18057
18108
  } else {
18058
- unwatch = scope.$watch($parse(attrs[attrName], parentValueWatch), null, parentGet.literal);
18109
+ removeWatch = scope.$watch($parse(attrs[attrName], parentValueWatch), null, parentGet.literal);
18059
18110
  }
18060
- onNewScopeDestroyed = (onNewScopeDestroyed || []);
18061
- onNewScopeDestroyed.push(unwatch);
18111
+ removeWatchCollection.push(removeWatch);
18062
18112
  break;
18063
18113
 
18064
18114
  case '&':
@@ -18074,16 +18124,12 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
18074
18124
  break;
18075
18125
  }
18076
18126
  });
18077
- var destroyBindings = onNewScopeDestroyed ? function destroyBindings() {
18078
- for (var i = 0, ii = onNewScopeDestroyed.length; i < ii; ++i) {
18079
- onNewScopeDestroyed[i]();
18127
+
18128
+ return removeWatchCollection.length && function removeWatches() {
18129
+ for (var i = 0, ii = removeWatchCollection.length; i < ii; ++i) {
18130
+ removeWatchCollection[i]();
18080
18131
  }
18081
- } : noop;
18082
- if (newScope && destroyBindings !== noop) {
18083
- newScope.$on('$destroy', destroyBindings);
18084
- return noop;
18085
- }
18086
- return destroyBindings;
18132
+ };
18087
18133
  }
18088
18134
  }];
18089
18135
  }
@@ -18808,9 +18854,9 @@ function $HttpProvider() {
18808
18854
  * Configure `$http` service to return promises without the shorthand methods `success` and `error`.
18809
18855
  * This should be used to make sure that applications work without these methods.
18810
18856
  *
18811
- * Defaults to false. If no value is specified, returns the current configured value.
18857
+ * Defaults to true. If no value is specified, returns the current configured value.
18812
18858
  *
18813
- * @param {boolean=} value If true, `$http` will return a normal promise without the `success` and `error` methods.
18859
+ * @param {boolean=} value If true, `$http` will return a promise with the deprecated legacy `success` and `error` methods.
18814
18860
  *
18815
18861
  * @returns {boolean|Object} If a value is specified, returns the $httpProvider for chaining.
18816
18862
  * otherwise, returns the current configured value.
@@ -19462,11 +19508,8 @@ function $HttpProvider() {
19462
19508
  function transformResponse(response) {
19463
19509
  // make a copy since the response must be cacheable
19464
19510
  var resp = extend({}, response);
19465
- if (!response.data) {
19466
- resp.data = response.data;
19467
- } else {
19468
- resp.data = transformData(response.data, response.headers, response.status, config.transformResponse);
19469
- }
19511
+ resp.data = transformData(response.data, response.headers, response.status,
19512
+ config.transformResponse);
19470
19513
  return (isSuccess(response.status))
19471
19514
  ? resp
19472
19515
  : $q.reject(resp);
@@ -21100,9 +21143,9 @@ var locationPrototype = {
21100
21143
  * @description
21101
21144
  * This method is getter / setter.
21102
21145
  *
21103
- * Return hash fragment when called without any parameter.
21146
+ * Returns the hash fragment when called without any parameters.
21104
21147
  *
21105
- * Change hash fragment when called with parameter and return `$location`.
21148
+ * Changes the hash fragment when called with a parameter and returns `$location`.
21106
21149
  *
21107
21150
  *
21108
21151
  * ```js
@@ -21123,8 +21166,8 @@ var locationPrototype = {
21123
21166
  * @name $location#replace
21124
21167
  *
21125
21168
  * @description
21126
- * If called, all changes to $location during current `$digest` will be replacing current history
21127
- * record, instead of adding new one.
21169
+ * If called, all changes to $location during the current `$digest` will replace the current history
21170
+ * record, instead of adding a new one.
21128
21171
  */
21129
21172
  replace: function() {
21130
21173
  this.$$replace = true;
@@ -21444,7 +21487,7 @@ function $LocationProvider() {
21444
21487
  var oldUrl = $location.absUrl();
21445
21488
  var oldState = $location.$$state;
21446
21489
  var defaultPrevented;
21447
-
21490
+ newUrl = trimEmptyHash(newUrl);
21448
21491
  $location.$$parse(newUrl);
21449
21492
  $location.$$state = newState;
21450
21493
 
@@ -23585,13 +23628,14 @@ function $ParseProvider() {
23585
23628
  function addInterceptor(parsedExpression, interceptorFn) {
23586
23629
  if (!interceptorFn) return parsedExpression;
23587
23630
  var watchDelegate = parsedExpression.$$watchDelegate;
23631
+ var useInputs = false;
23588
23632
 
23589
23633
  var regularWatch =
23590
23634
  watchDelegate !== oneTimeLiteralWatchDelegate &&
23591
23635
  watchDelegate !== oneTimeWatchDelegate;
23592
23636
 
23593
23637
  var fn = regularWatch ? function regularInterceptedExpression(scope, locals, assign, inputs) {
23594
- var value = parsedExpression(scope, locals, assign, inputs);
23638
+ var value = useInputs && inputs ? inputs[0] : parsedExpression(scope, locals, assign, inputs);
23595
23639
  return interceptorFn(value, scope, locals);
23596
23640
  } : function oneTimeInterceptedExpression(scope, locals, assign, inputs) {
23597
23641
  var value = parsedExpression(scope, locals, assign, inputs);
@@ -23609,6 +23653,7 @@ function $ParseProvider() {
23609
23653
  // If there is an interceptor, but no watchDelegate then treat the interceptor like
23610
23654
  // we treat filters - it is assumed to be a pure function unless flagged with $stateful
23611
23655
  fn.$$watchDelegate = inputsWatchDelegate;
23656
+ useInputs = !parsedExpression.inputs;
23612
23657
  fn.inputs = parsedExpression.inputs ? parsedExpression.inputs : [parsedExpression];
23613
23658
  }
23614
23659
 
@@ -23670,6 +23715,8 @@ function $ParseProvider() {
23670
23715
  *
23671
23716
  * Note: progress/notify callbacks are not currently supported via the ES6-style interface.
23672
23717
  *
23718
+ * Note: unlike ES6 behaviour, an exception thrown in the constructor function will NOT implicitly reject the promise.
23719
+ *
23673
23720
  * However, the more traditional CommonJS-style usage is still available, and documented below.
23674
23721
  *
23675
23722
  * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an
@@ -24254,15 +24301,15 @@ function $$RAFProvider() { //rAF
24254
24301
  * exposed as $$____ properties
24255
24302
  *
24256
24303
  * Loop operations are optimized by using while(count--) { ... }
24257
- * - this means that in order to keep the same order of execution as addition we have to add
24304
+ * - This means that in order to keep the same order of execution as addition we have to add
24258
24305
  * items to the array at the beginning (unshift) instead of at the end (push)
24259
24306
  *
24260
24307
  * Child scopes are created and removed often
24261
- * - Using an array would be slow since inserts in middle are expensive so we use linked list
24308
+ * - Using an array would be slow since inserts in the middle are expensive; so we use linked lists
24262
24309
  *
24263
- * There are few watches then a lot of observers. This is why you don't want the observer to be
24264
- * implemented in the same way as watch. Watch requires return of initialization function which
24265
- * are expensive to construct.
24310
+ * There are fewer watches than observers. This is why you don't want the observer to be implemented
24311
+ * in the same way as watch. Watch requires return of the initialization function which is expensive
24312
+ * to construct.
24266
24313
  */
24267
24314
 
24268
24315
 
@@ -24304,7 +24351,7 @@ function $$RAFProvider() { //rAF
24304
24351
  * Every application has a single root {@link ng.$rootScope.Scope scope}.
24305
24352
  * All other scopes are descendant scopes of the root scope. Scopes provide separation
24306
24353
  * between the model and the view, via a mechanism for watching the model for changes.
24307
- * They also provide an event emission/broadcast and subscription facility. See the
24354
+ * They also provide event emission/broadcast and subscription facility. See the
24308
24355
  * {@link guide/scope developer guide on scopes}.
24309
24356
  */
24310
24357
  function $RootScopeProvider() {
@@ -24341,6 +24388,29 @@ function $RootScopeProvider() {
24341
24388
  $event.currentScope.$$destroyed = true;
24342
24389
  }
24343
24390
 
24391
+ function cleanUpScope($scope) {
24392
+
24393
+ if (msie === 9) {
24394
+ // There is a memory leak in IE9 if all child scopes are not disconnected
24395
+ // completely when a scope is destroyed. So this code will recurse up through
24396
+ // all this scopes children
24397
+ //
24398
+ // See issue https://github.com/angular/angular.js/issues/10706
24399
+ $scope.$$childHead && cleanUpScope($scope.$$childHead);
24400
+ $scope.$$nextSibling && cleanUpScope($scope.$$nextSibling);
24401
+ }
24402
+
24403
+ // The code below works around IE9 and V8's memory leaks
24404
+ //
24405
+ // See:
24406
+ // - https://code.google.com/p/v8/issues/detail?id=2073#c26
24407
+ // - https://github.com/angular/angular.js/issues/6794#issuecomment-38648909
24408
+ // - https://github.com/angular/angular.js/issues/1313#issuecomment-10378451
24409
+
24410
+ $scope.$parent = $scope.$$nextSibling = $scope.$$prevSibling = $scope.$$childHead =
24411
+ $scope.$$childTail = $scope.$root = $scope.$$watchers = null;
24412
+ }
24413
+
24344
24414
  /**
24345
24415
  * @ngdoc type
24346
24416
  * @name $rootScope.Scope
@@ -25137,16 +25207,9 @@ function $RootScopeProvider() {
25137
25207
  this.$on = this.$watch = this.$watchGroup = function() { return noop; };
25138
25208
  this.$$listeners = {};
25139
25209
 
25140
- // All of the code below is bogus code that works around V8's memory leak via optimized code
25141
- // and inline caches.
25142
- //
25143
- // see:
25144
- // - https://code.google.com/p/v8/issues/detail?id=2073#c26
25145
- // - https://github.com/angular/angular.js/issues/6794#issuecomment-38648909
25146
- // - https://github.com/angular/angular.js/issues/1313#issuecomment-10378451
25147
-
25148
- this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =
25149
- this.$$childTail = this.$root = this.$$watchers = null;
25210
+ // Disconnect the next sibling to prevent `cleanUpScope` destroying those too
25211
+ this.$$nextSibling = null;
25212
+ cleanUpScope(this);
25150
25213
  },
25151
25214
 
25152
25215
  /**
@@ -26142,7 +26205,7 @@ function $SceDelegateProvider() {
26142
26205
  * By default, Angular only loads templates from the same domain and protocol as the application
26143
26206
  * document. This is done by calling {@link ng.$sce#getTrustedResourceUrl
26144
26207
  * $sce.getTrustedResourceUrl} on the template URL. To load templates from other domains and/or
26145
- * protocols, you may either either {@link ng.$sceDelegateProvider#resourceUrlWhitelist whitelist
26208
+ * protocols, you may either {@link ng.$sceDelegateProvider#resourceUrlWhitelist whitelist
26146
26209
  * them} or {@link ng.$sce#trustAsResourceUrl wrap it} into a trusted value.
26147
26210
  *
26148
26211
  * *Please note*:
@@ -28393,7 +28456,7 @@ function limitToFilter() {
28393
28456
  if (!isArray(input) && !isString(input)) return input;
28394
28457
 
28395
28458
  begin = (!begin || isNaN(begin)) ? 0 : toInt(begin);
28396
- begin = (begin < 0 && begin >= -input.length) ? input.length + begin : begin;
28459
+ begin = (begin < 0) ? Math.max(0, input.length + begin) : begin;
28397
28460
 
28398
28461
  if (limit >= 0) {
28399
28462
  return input.slice(begin, begin + limit);
@@ -29753,7 +29816,8 @@ var ngFormDirective = formDirectiveFactory(true);
29753
29816
 
29754
29817
  // Regex code is obtained from SO: https://stackoverflow.com/questions/3143070/javascript-regex-iso-datetime#answer-3143231
29755
29818
  var ISO_DATE_REGEXP = /\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z)/;
29756
- var URL_REGEXP = /^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/;
29819
+ // See valid URLs in RFC3987 (http://tools.ietf.org/html/rfc3987)
29820
+ var URL_REGEXP = /^[A-Za-z][A-Za-z\d.+-]*:\/*(?:\w+(?::\w+)?@)?[^\s/]+(?::\d+)?(?:\/[\w#!:.?+=&%@\-/]*)?$/;
29757
29821
  var EMAIL_REGEXP = /^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i;
29758
29822
  var NUMBER_REGEXP = /^\s*(\-|\+)?(\d+|(\d*(\.\d*)))([eE][+-]?\d+)?\s*$/;
29759
29823
  var DATE_REGEXP = /^(\d{4})-(\d{2})-(\d{2})$/;
@@ -33319,7 +33383,13 @@ var ngIfDirective = ['$animate', function($animate) {
33319
33383
  * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,
33320
33384
  * make sure you wrap it in **single** quotes, e.g. `src="'myPartialTemplate.html'"`.
33321
33385
  * @param {string=} onload Expression to evaluate when a new partial is loaded.
33322
- *
33386
+ * <div class="alert alert-warning">
33387
+ * **Note:** When using onload on SVG elements in IE11, the browser will try to call
33388
+ * a function with the name on the window element, which will usually throw a
33389
+ * "function is undefined" error. To fix this, you can instead use `data-onload` or a
33390
+ * different form that {@link guide/directive#normalization matches} `onload`.
33391
+ * </div>
33392
+ *
33323
33393
  * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll
33324
33394
  * $anchorScroll} to scroll the viewport after the content is loaded.
33325
33395
  *
@@ -34912,12 +34982,13 @@ var DEFAULT_REGEXP = /(\s+|^)default(\s+|$)/;
34912
34982
  </label><br />
34913
34983
  </form>
34914
34984
  <pre>user.name = <span ng-bind="user.name"></span></pre>
34985
+ <pre>user.data = <span ng-bind="user.data"></span></pre>
34915
34986
  </div>
34916
34987
  </file>
34917
34988
  <file name="app.js">
34918
34989
  angular.module('optionsExample', [])
34919
34990
  .controller('ExampleController', ['$scope', function($scope) {
34920
- $scope.user = { name: 'say', data: '' };
34991
+ $scope.user = { name: 'John', data: '' };
34921
34992
 
34922
34993
  $scope.cancel = function(e) {
34923
34994
  if (e.keyCode == 27) {
@@ -34932,20 +35003,20 @@ var DEFAULT_REGEXP = /(\s+|^)default(\s+|$)/;
34932
35003
  var other = element(by.model('user.data'));
34933
35004
 
34934
35005
  it('should allow custom events', function() {
34935
- input.sendKeys(' hello');
35006
+ input.sendKeys(' Doe');
34936
35007
  input.click();
34937
- expect(model.getText()).toEqual('say');
35008
+ expect(model.getText()).toEqual('John');
34938
35009
  other.click();
34939
- expect(model.getText()).toEqual('say hello');
35010
+ expect(model.getText()).toEqual('John Doe');
34940
35011
  });
34941
35012
 
34942
35013
  it('should $rollbackViewValue when model changes', function() {
34943
- input.sendKeys(' hello');
34944
- expect(input.getAttribute('value')).toEqual('say hello');
35014
+ input.sendKeys(' Doe');
35015
+ expect(input.getAttribute('value')).toEqual('John Doe');
34945
35016
  input.sendKeys(protractor.Key.ESCAPE);
34946
- expect(input.getAttribute('value')).toEqual('say');
35017
+ expect(input.getAttribute('value')).toEqual('John');
34947
35018
  other.click();
34948
- expect(model.getText()).toEqual('say');
35019
+ expect(model.getText()).toEqual('John');
34949
35020
  });
34950
35021
  </file>
34951
35022
  </example>
@@ -34971,7 +35042,7 @@ var DEFAULT_REGEXP = /(\s+|^)default(\s+|$)/;
34971
35042
  <file name="app.js">
34972
35043
  angular.module('optionsExample', [])
34973
35044
  .controller('ExampleController', ['$scope', function($scope) {
34974
- $scope.user = { name: 'say' };
35045
+ $scope.user = { name: 'Igor' };
34975
35046
  }]);
34976
35047
  </file>
34977
35048
  </example>
@@ -35204,19 +35275,27 @@ var ngOptionsMinErr = minErr('ngOptions');
35204
35275
  *
35205
35276
  * ## Complex Models (objects or collections)
35206
35277
  *
35207
- * **Note:** By default, `ngModel` watches the model by reference, not value. This is important when
35208
- * binding any input directive to a model that is an object or a collection.
35278
+ * By default, `ngModel` watches the model by reference, not value. This is important to know when
35279
+ * binding the select to a model that is an object or a collection.
35209
35280
  *
35210
- * Since this is a common situation for `ngOptions` the directive additionally watches the model using
35211
- * `$watchCollection` when the select has the `multiple` attribute or when there is a `track by` clause in
35212
- * the options expression. This allows ngOptions to trigger a re-rendering of the options even if the actual
35213
- * object/collection has not changed identity but only a property on the object or an item in the collection
35214
- * changes.
35281
+ * One issue occurs if you want to preselect an option. For example, if you set
35282
+ * the model to an object that is equal to an object in your collection, `ngOptions` won't be able to set the selection,
35283
+ * because the objects are not identical. So by default, you should always reference the item in your collection
35284
+ * for preselections, e.g.: `$scope.selected = $scope.collection[3]`.
35215
35285
  *
35216
- * Note that `$watchCollection` does a shallow comparison of the properties of the object (or the items in the collection
35217
- * if the model is an array). This means that changing a property deeper inside the object/collection that the
35218
- * first level will not trigger a re-rendering.
35286
+ * Another solution is to use a `track by` clause, because then `ngOptions` will track the identity
35287
+ * of the item not by reference, but by the result of the `track by` expression. For example, if your
35288
+ * collection items have an id property, you would `track by item.id`.
35289
+ *
35290
+ * A different issue with objects or collections is that ngModel won't detect if an object property or
35291
+ * a collection item changes. For that reason, `ngOptions` additionally watches the model using
35292
+ * `$watchCollection`, when the expression contains a `track by` clause or the the select has the `multiple` attribute.
35293
+ * This allows ngOptions to trigger a re-rendering of the options even if the actual object/collection
35294
+ * has not changed identity, but only a property on the object or an item in the collection changes.
35219
35295
  *
35296
+ * Note that `$watchCollection` does a shallow comparison of the properties of the object (or the items in the collection
35297
+ * if the model is an array). This means that changing a property deeper than the first level inside the
35298
+ * object/collection will not trigger a re-rendering.
35220
35299
  *
35221
35300
  * ## `select` **`as`**
35222
35301
  *
@@ -35229,17 +35308,13 @@ var ngOptionsMinErr = minErr('ngOptions');
35229
35308
  * ### `select` **`as`** and **`track by`**
35230
35309
  *
35231
35310
  * <div class="alert alert-warning">
35232
- * Do not use `select` **`as`** and **`track by`** in the same expression. They are not designed to work together.
35311
+ * Be careful when using `select` **`as`** and **`track by`** in the same expression.
35233
35312
  * </div>
35234
35313
  *
35235
- * Consider the following example:
35236
- *
35237
- * ```html
35238
- * <select ng-options="item.subItem as item.label for item in values track by item.id" ng-model="selected"></select>
35239
- * ```
35314
+ * Given this array of items on the $scope:
35240
35315
  *
35241
35316
  * ```js
35242
- * $scope.values = [{
35317
+ * $scope.items = [{
35243
35318
  * id: 1,
35244
35319
  * label: 'aLabel',
35245
35320
  * subItem: { name: 'aSubItem' }
@@ -35248,20 +35323,33 @@ var ngOptionsMinErr = minErr('ngOptions');
35248
35323
  * label: 'bLabel',
35249
35324
  * subItem: { name: 'bSubItem' }
35250
35325
  * }];
35326
+ * ```
35327
+ *
35328
+ * This will work:
35251
35329
  *
35252
- * $scope.selected = { name: 'aSubItem' };
35330
+ * ```html
35331
+ * <select ng-options="item as item.label for item in items track by item.id" ng-model="selected"></select>
35332
+ * ```
35333
+ * ```js
35334
+ * $scope.selected = $scope.items[0];
35253
35335
  * ```
35254
35336
  *
35255
- * With the purpose of preserving the selection, the **`track by`** expression is always applied to the element
35256
- * of the data source (to `item` in this example). To calculate whether an element is selected, we do the
35257
- * following:
35337
+ * but this will not work:
35258
35338
  *
35259
- * 1. Apply **`track by`** to the elements in the array. In the example: `[1, 2]`
35260
- * 2. Apply **`track by`** to the already selected value in `ngModel`.
35261
- * In the example: this is not possible as **`track by`** refers to `item.id`, but the selected
35262
- * value from `ngModel` is `{name: 'aSubItem'}`, so the **`track by`** expression is applied to
35263
- * a wrong object, the selected element can't be found, `<select>` is always reset to the "not
35264
- * selected" option.
35339
+ * ```html
35340
+ * <select ng-options="item.subItem as item.label for item in items track by item.id" ng-model="selected"></select>
35341
+ * ```
35342
+ * ```js
35343
+ * $scope.selected = $scope.items[0].subItem;
35344
+ * ```
35345
+ *
35346
+ * In both examples, the **`track by`** expression is applied successfully to each `item` in the
35347
+ * `items` array. Because the selected option has been set programmatically in the controller, the
35348
+ * **`track by`** expression is also applied to the `ngModel` value. In the first example, the
35349
+ * `ngModel` value is `items[0]` and the **`track by`** expression evaluates to `items[0].id` with
35350
+ * no issue. In the second example, the `ngModel` value is `items[0].subItem` and the **`track by`**
35351
+ * expression evaluates to `items[0].subItem.id` (which is undefined). As a result, the model value
35352
+ * is not matched against any `<option>` and the `<select>` appears as having no selected value.
35265
35353
  *
35266
35354
  *
35267
35355
  * @param {string} ngModel Assignable angular expression to data-bind to.
@@ -35563,11 +35651,8 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
35563
35651
  var optionTemplate = document.createElement('option'),
35564
35652
  optGroupTemplate = document.createElement('optgroup');
35565
35653
 
35566
- return {
35567
- restrict: 'A',
35568
- terminal: true,
35569
- require: ['select', '?ngModel'],
35570
- link: function(scope, selectElement, attr, ctrls) {
35654
+
35655
+ function ngOptionsPostLink(scope, selectElement, attr, ctrls) {
35571
35656
 
35572
35657
  // if ngModel is not defined, we don't need to do anything
35573
35658
  var ngModelCtrl = ctrls[1];
@@ -35622,7 +35707,6 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
35622
35707
  unknownOption.remove();
35623
35708
  };
35624
35709
 
35625
-
35626
35710
  // Update the controller methods for multiple selectable options
35627
35711
  if (!multiple) {
35628
35712
 
@@ -35797,13 +35881,15 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
35797
35881
  var emptyOption_ = emptyOption && emptyOption[0];
35798
35882
  var unknownOption_ = unknownOption && unknownOption[0];
35799
35883
 
35884
+ // We cannot rely on the extracted empty option being the same as the compiled empty option,
35885
+ // because the compiled empty option might have been replaced by a comment because
35886
+ // it had an "element" transclusion directive on it (such as ngIf)
35800
35887
  if (emptyOption_ || unknownOption_) {
35801
35888
  while (current &&
35802
35889
  (current === emptyOption_ ||
35803
35890
  current === unknownOption_ ||
35804
- emptyOption_ && emptyOption_.nodeType === NODE_TYPE_COMMENT)) {
35805
- // Empty options might have directives that transclude
35806
- // and insert comments (e.g. ngIf)
35891
+ current.nodeType === NODE_TYPE_COMMENT ||
35892
+ current.value === '')) {
35807
35893
  current = current.nextSibling;
35808
35894
  }
35809
35895
  }
@@ -35900,7 +35986,20 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
35900
35986
  }
35901
35987
 
35902
35988
  }
35989
+ }
35903
35990
 
35991
+ return {
35992
+ restrict: 'A',
35993
+ terminal: true,
35994
+ require: ['select', '?ngModel'],
35995
+ link: {
35996
+ pre: function ngOptionsPreLink(scope, selectElement, attr, ctrls) {
35997
+ // Deactivate the SelectController.register method to prevent
35998
+ // option directives from accidentally registering themselves
35999
+ // (and unwanted $destroy handlers etc.)
36000
+ ctrls[0].registerOption = noop;
36001
+ },
36002
+ post: ngOptionsPostLink
35904
36003
  }
35905
36004
  };
35906
36005
  }];
@@ -36187,7 +36286,7 @@ var ngPluralizeDirective = ['$locale', '$interpolate', '$log', function($locale,
36187
36286
  * Version 1.4 removed the alphabetic sorting. We now rely on the order returned by the browser
36188
36287
  * when running `for key in myObj`. It seems that browsers generally follow the strategy of providing
36189
36288
  * keys in the order in which they were defined, although there are exceptions when keys are deleted
36190
- * and reinstated. See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/delete#Cross-browser_issues
36289
+ * and reinstated. See the [MDN page on `delete` for more info](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/delete#Cross-browser_notes).
36191
36290
  *
36192
36291
  * If this is not desired, the recommended workaround is to convert your object into an array
36193
36292
  * that is sorted into the order that you prefer before providing it to `ngRepeat`. You could
@@ -36197,15 +36296,21 @@ var ngPluralizeDirective = ['$locale', '$interpolate', '$log', function($locale,
36197
36296
  *
36198
36297
  * # Tracking and Duplicates
36199
36298
  *
36200
- * When the contents of the collection change, `ngRepeat` makes the corresponding changes to the DOM:
36299
+ * `ngRepeat` uses {@link $rootScope.Scope#$watchCollection $watchCollection} to detect changes in
36300
+ * the collection. When a change happens, ngRepeat then makes the corresponding changes to the DOM:
36201
36301
  *
36202
36302
  * * When an item is added, a new instance of the template is added to the DOM.
36203
36303
  * * When an item is removed, its template instance is removed from the DOM.
36204
36304
  * * When items are reordered, their respective templates are reordered in the DOM.
36205
36305
  *
36206
- * By default, `ngRepeat` does not allow duplicate items in arrays. This is because when
36207
- * there are duplicates, it is not possible to maintain a one-to-one mapping between collection
36208
- * items and DOM elements.
36306
+ * To minimize creation of DOM elements, `ngRepeat` uses a function
36307
+ * to "keep track" of all items in the collection and their corresponding DOM elements.
36308
+ * For example, if an item is added to the collection, ngRepeat will know that all other items
36309
+ * already have DOM elements, and will not re-render them.
36310
+ *
36311
+ * The default tracking function (which tracks items by their identity) does not allow
36312
+ * duplicate items in arrays. This is because when there are duplicates, it is not possible
36313
+ * to maintain a one-to-one mapping between collection items and DOM elements.
36209
36314
  *
36210
36315
  * If you do need to repeat duplicate items, you can substitute the default tracking behavior
36211
36316
  * with your own using the `track by` expression.
@@ -36218,7 +36323,7 @@ var ngPluralizeDirective = ['$locale', '$interpolate', '$log', function($locale,
36218
36323
  * </div>
36219
36324
  * ```
36220
36325
  *
36221
- * You may use arbitrary expressions in `track by`, including references to custom functions
36326
+ * You may also use arbitrary expressions in `track by`, including references to custom functions
36222
36327
  * on the scope:
36223
36328
  * ```html
36224
36329
  * <div ng-repeat="n in [42, 42, 43, 43] track by myTrackingFunction(n)">
@@ -36226,10 +36331,14 @@ var ngPluralizeDirective = ['$locale', '$interpolate', '$log', function($locale,
36226
36331
  * </div>
36227
36332
  * ```
36228
36333
  *
36229
- * If you are working with objects that have an identifier property, you can track
36334
+ * <div class="alert alert-success">
36335
+ * If you are working with objects that have an identifier property, you should track
36230
36336
  * by the identifier instead of the whole object. Should you reload your data later, `ngRepeat`
36231
36337
  * will not have to rebuild the DOM elements for items it has already rendered, even if the
36232
- * JavaScript objects in the collection have been substituted for new ones:
36338
+ * JavaScript objects in the collection have been substituted for new ones. For large collections,
36339
+ * this signifincantly improves rendering performance. If you don't have a unique identifier,
36340
+ * `track by $index` can also provide a performance boost.
36341
+ * </div>
36233
36342
  * ```html
36234
36343
  * <div ng-repeat="model in collection track by model.id">
36235
36344
  * {{model.name}}
@@ -37387,6 +37496,15 @@ var scriptDirective = ['$templateCache', function($templateCache) {
37387
37496
 
37388
37497
  var noopNgModelController = { $setViewValue: noop, $render: noop };
37389
37498
 
37499
+ function chromeHack(optionElement) {
37500
+ // Workaround for https://code.google.com/p/chromium/issues/detail?id=381459
37501
+ // Adding an <option selected="selected"> element to a <select required="required"> should
37502
+ // automatically select the new element
37503
+ if (optionElement[0].hasAttribute('selected')) {
37504
+ optionElement[0].selected = true;
37505
+ }
37506
+ }
37507
+
37390
37508
  /**
37391
37509
  * @ngdoc type
37392
37510
  * @name select.SelectController
@@ -37462,6 +37580,8 @@ var SelectController =
37462
37580
  }
37463
37581
  var count = optionsMap.get(value) || 0;
37464
37582
  optionsMap.put(value, count + 1);
37583
+ self.ngModelCtrl.$render();
37584
+ chromeHack(element);
37465
37585
  };
37466
37586
 
37467
37587
  // Tell the select control that an option, with the given value, has been removed
@@ -37483,6 +37603,39 @@ var SelectController =
37483
37603
  self.hasOption = function(value) {
37484
37604
  return !!optionsMap.get(value);
37485
37605
  };
37606
+
37607
+
37608
+ self.registerOption = function(optionScope, optionElement, optionAttrs, interpolateValueFn, interpolateTextFn) {
37609
+
37610
+ if (interpolateValueFn) {
37611
+ // The value attribute is interpolated
37612
+ var oldVal;
37613
+ optionAttrs.$observe('value', function valueAttributeObserveAction(newVal) {
37614
+ if (isDefined(oldVal)) {
37615
+ self.removeOption(oldVal);
37616
+ }
37617
+ oldVal = newVal;
37618
+ self.addOption(newVal, optionElement);
37619
+ });
37620
+ } else if (interpolateTextFn) {
37621
+ // The text content is interpolated
37622
+ optionScope.$watch(interpolateTextFn, function interpolateWatchAction(newVal, oldVal) {
37623
+ optionAttrs.$set('value', newVal);
37624
+ if (oldVal !== newVal) {
37625
+ self.removeOption(oldVal);
37626
+ }
37627
+ self.addOption(newVal, optionElement);
37628
+ });
37629
+ } else {
37630
+ // The value attribute is static
37631
+ self.addOption(optionAttrs.value, optionElement);
37632
+ }
37633
+
37634
+ optionElement.on('$destroy', function() {
37635
+ self.removeOption(optionAttrs.value);
37636
+ self.ngModelCtrl.$render();
37637
+ });
37638
+ };
37486
37639
  }];
37487
37640
 
37488
37641
  /**
@@ -37528,6 +37681,8 @@ var SelectController =
37528
37681
  *
37529
37682
  * @param {string} ngModel Assignable angular expression to data-bind to.
37530
37683
  * @param {string=} name Property name of the form under which the control is published.
37684
+ * @param {string=} multiple Allows multiple options to be selected. The selected values will be
37685
+ * bound to the model as an array.
37531
37686
  * @param {string=} required Sets `required` validation error key if the value is not entered.
37532
37687
  * @param {string=} ngRequired Adds required attribute and required validation constraint to
37533
37688
  * the element when the ngRequired expression evaluates to true. Use ngRequired instead of required
@@ -37693,7 +37848,13 @@ var selectDirective = function() {
37693
37848
  restrict: 'E',
37694
37849
  require: ['select', '?ngModel'],
37695
37850
  controller: SelectController,
37696
- link: function(scope, element, attr, ctrls) {
37851
+ priority: 1,
37852
+ link: {
37853
+ pre: selectPreLink
37854
+ }
37855
+ };
37856
+
37857
+ function selectPreLink(scope, element, attr, ctrls) {
37697
37858
 
37698
37859
  // if ngModel is not defined, we don't need to do anything
37699
37860
  var ngModelCtrl = ctrls[1];
@@ -37763,7 +37924,6 @@ var selectDirective = function() {
37763
37924
 
37764
37925
  }
37765
37926
  }
37766
- };
37767
37927
  };
37768
37928
 
37769
37929
 
@@ -37771,16 +37931,6 @@ var selectDirective = function() {
37771
37931
  // of dynamically created (and destroyed) option elements to their containing select
37772
37932
  // directive via its controller.
37773
37933
  var optionDirective = ['$interpolate', function($interpolate) {
37774
-
37775
- function chromeHack(optionElement) {
37776
- // Workaround for https://code.google.com/p/chromium/issues/detail?id=381459
37777
- // Adding an <option selected="selected"> element to a <select required="required"> should
37778
- // automatically select the new element
37779
- if (optionElement[0].hasAttribute('selected')) {
37780
- optionElement[0].selected = true;
37781
- }
37782
- }
37783
-
37784
37934
  return {
37785
37935
  restrict: 'E',
37786
37936
  priority: 100,
@@ -37788,12 +37938,12 @@ var optionDirective = ['$interpolate', function($interpolate) {
37788
37938
 
37789
37939
  if (isDefined(attr.value)) {
37790
37940
  // If the value attribute is defined, check if it contains an interpolation
37791
- var valueInterpolated = $interpolate(attr.value, true);
37941
+ var interpolateValueFn = $interpolate(attr.value, true);
37792
37942
  } else {
37793
37943
  // If the value attribute is not defined then we fall back to the
37794
37944
  // text content of the option element, which may be interpolated
37795
- var interpolateFn = $interpolate(element.text(), true);
37796
- if (!interpolateFn) {
37945
+ var interpolateTextFn = $interpolate(element.text(), true);
37946
+ if (!interpolateTextFn) {
37797
37947
  attr.$set('value', element.text());
37798
37948
  }
37799
37949
  }
@@ -37807,44 +37957,8 @@ var optionDirective = ['$interpolate', function($interpolate) {
37807
37957
  selectCtrl = parent.data(selectCtrlName) ||
37808
37958
  parent.parent().data(selectCtrlName); // in case we are in optgroup
37809
37959
 
37810
- function addOption(optionValue) {
37811
- selectCtrl.addOption(optionValue, element);
37812
- selectCtrl.ngModelCtrl.$render();
37813
- chromeHack(element);
37814
- }
37815
-
37816
- // Only update trigger option updates if this is an option within a `select`
37817
- // that also has `ngModel` attached
37818
- if (selectCtrl && selectCtrl.ngModelCtrl) {
37819
-
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
37832
- scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {
37833
- attr.$set('value', newVal);
37834
- if (oldVal !== newVal) {
37835
- selectCtrl.removeOption(oldVal);
37836
- }
37837
- addOption(newVal);
37838
- });
37839
- } else {
37840
- // The value attribute is static
37841
- addOption(attr.value);
37842
- }
37843
-
37844
- element.on('$destroy', function() {
37845
- selectCtrl.removeOption(attr.value);
37846
- selectCtrl.ngModelCtrl.$render();
37847
- });
37960
+ if (selectCtrl) {
37961
+ selectCtrl.registerOption(scope, element, attr, interpolateValueFn, interpolateTextFn);
37848
37962
  }
37849
37963
  };
37850
37964
  }
@@ -38427,6 +38541,7 @@ _jQuery.fn.bindings = function(windowJquery, bindExp) {
38427
38541
  if (!element) return;
38428
38542
 
38429
38543
  eventData = eventData || {};
38544
+ var relatedTarget = eventData.relatedTarget || element;
38430
38545
  var keys = eventData.keys;
38431
38546
  var x = eventData.x;
38432
38547
  var y = eventData.y;
@@ -38496,7 +38611,7 @@ _jQuery.fn.bindings = function(windowJquery, bindExp) {
38496
38611
  x = x || 0;
38497
38612
  y = y || 0;
38498
38613
  evnt.initMouseEvent(eventType, true, true, window, 0, x, y, x, y, pressed('ctrl'),
38499
- pressed('alt'), pressed('shift'), pressed('meta'), 0, element);
38614
+ pressed('alt'), pressed('shift'), pressed('meta'), 0, relatedTarget);
38500
38615
  }
38501
38616
 
38502
38617
  /* we're unable to change the timeStamp value directly so this