angularjs-rails 1.4.7 → 1.4.8

Sign up to get free protection for your applications and to get access to all the features.
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