angularjs-rails 1.2.16 → 1.2.18

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.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.2.16
2
+ * @license AngularJS v1.2.18
3
3
  * (c) 2010-2014 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -187,13 +187,16 @@ ngTouch.factory('$swipe', [function() {
187
187
  * upon tap. (Event object is available as `$event`)
188
188
  *
189
189
  * @example
190
- <example>
190
+ <example module="ngClickExample" deps="angular-touch.js">
191
191
  <file name="index.html">
192
192
  <button ng-click="count = count + 1" ng-init="count=0">
193
193
  Increment
194
194
  </button>
195
195
  count: {{ count }}
196
196
  </file>
197
+ <file name="script.js">
198
+ angular.module('ngClickExample', ['ngTouch']);
199
+ </file>
197
200
  </example>
198
201
  */
199
202
 
@@ -230,7 +233,7 @@ ngTouch.directive('ngClick', ['$parse', '$timeout', '$rootElement',
230
233
  //
231
234
  // What happens when the browser then generates a click event?
232
235
  // The browser, of course, also detects the tap and fires a click after a delay. This results in
233
- // tapping/clicking twice. So we do "clickbusting" to prevent it.
236
+ // tapping/clicking twice. We do "clickbusting" to prevent it.
234
237
  //
235
238
  // How does it work?
236
239
  // We attach global touchstart and click handlers, that run during the capture (early) phase.
@@ -253,9 +256,9 @@ ngTouch.directive('ngClick', ['$parse', '$timeout', '$rootElement',
253
256
  // encapsulates this ugly logic away from the user.
254
257
  //
255
258
  // Why not just put click handlers on the element?
256
- // We do that too, just to be sure. The problem is that the tap event might have caused the DOM
257
- // to change, so that the click fires in the same position but something else is there now. So
258
- // the handlers are global and care only about coordinates and not elements.
259
+ // We do that too, just to be sure. If the tap event caused the DOM to change,
260
+ // it is possible another element is now in that position. To take account for these possibly
261
+ // distinct elements, the handlers are global and care only about coordinates.
259
262
 
260
263
  // Checks if the coordinates are close enough to be within the region.
261
264
  function hit(x1, y1, x2, y2) {
@@ -469,7 +472,7 @@ ngTouch.directive('ngClick', ['$parse', '$timeout', '$rootElement',
469
472
  * upon left swipe. (Event object is available as `$event`)
470
473
  *
471
474
  * @example
472
- <example>
475
+ <example module="ngSwipeLeftExample" deps="angular-touch.js">
473
476
  <file name="index.html">
474
477
  <div ng-show="!showActions" ng-swipe-left="showActions = true">
475
478
  Some list content, like an email in the inbox
@@ -479,6 +482,9 @@ ngTouch.directive('ngClick', ['$parse', '$timeout', '$rootElement',
479
482
  <button ng-click="delete()">Delete</button>
480
483
  </div>
481
484
  </file>
485
+ <file name="script.js">
486
+ angular.module('ngSwipeLeftExample', ['ngTouch']);
487
+ </file>
482
488
  </example>
483
489
  */
484
490
 
@@ -499,7 +505,7 @@ ngTouch.directive('ngClick', ['$parse', '$timeout', '$rootElement',
499
505
  * upon right swipe. (Event object is available as `$event`)
500
506
  *
501
507
  * @example
502
- <example>
508
+ <example module="ngSwipeRightExample" deps="angular-touch.js">
503
509
  <file name="index.html">
504
510
  <div ng-show="!showActions" ng-swipe-left="showActions = true">
505
511
  Some list content, like an email in the inbox
@@ -509,6 +515,9 @@ ngTouch.directive('ngClick', ['$parse', '$timeout', '$rootElement',
509
515
  <button ng-click="delete()">Delete</button>
510
516
  </div>
511
517
  </file>
518
+ <file name="script.js">
519
+ angular.module('ngSwipeRightExample', ['ngTouch']);
520
+ </file>
512
521
  </example>
513
522
  */
514
523
 
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.2.16
2
+ * @license AngularJS v1.2.18
3
3
  * (c) 2010-2014 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -68,7 +68,7 @@ function minErr(module) {
68
68
  return match;
69
69
  });
70
70
 
71
- message = message + '\nhttp://errors.angularjs.org/1.2.16/' +
71
+ message = message + '\nhttp://errors.angularjs.org/1.2.18/' +
72
72
  (module ? module + '/' : '') + code;
73
73
  for (i = 2; i < arguments.length; i++) {
74
74
  message = message + (i == 2 ? '?' : '&') + 'p' + (i-2) + '=' +
@@ -89,7 +89,6 @@ function minErr(module) {
89
89
  -push,
90
90
  -toString,
91
91
  -ngMinErr,
92
- -_angular,
93
92
  -angularModule,
94
93
  -nodeName_,
95
94
  -uid,
@@ -186,7 +185,7 @@ function minErr(module) {
186
185
  * @ngdoc function
187
186
  * @name angular.lowercase
188
187
  * @module ng
189
- * @function
188
+ * @kind function
190
189
  *
191
190
  * @description Converts the specified string to lowercase.
192
191
  * @param {string} string String to be converted to lowercase.
@@ -199,7 +198,7 @@ var hasOwnProperty = Object.prototype.hasOwnProperty;
199
198
  * @ngdoc function
200
199
  * @name angular.uppercase
201
200
  * @module ng
202
- * @function
201
+ * @kind function
203
202
  *
204
203
  * @description Converts the specified string to uppercase.
205
204
  * @param {string} string String to be converted to uppercase.
@@ -240,8 +239,6 @@ var /** holds major version number for IE or NaN for real browsers */
240
239
  toString = Object.prototype.toString,
241
240
  ngMinErr = minErr('ng'),
242
241
 
243
-
244
- _angular = window.angular,
245
242
  /** @name angular */
246
243
  angular = window.angular || (window.angular = {}),
247
244
  angularModule,
@@ -283,7 +280,7 @@ function isArrayLike(obj) {
283
280
  * @ngdoc function
284
281
  * @name angular.forEach
285
282
  * @module ng
286
- * @function
283
+ * @kind function
287
284
  *
288
285
  * @description
289
286
  * Invokes the `iterator` function once for each item in `obj` collection, which can be either an
@@ -297,7 +294,7 @@ function isArrayLike(obj) {
297
294
  ```js
298
295
  var values = {name: 'misko', gender: 'male'};
299
296
  var log = [];
300
- angular.forEach(values, function(value, key){
297
+ angular.forEach(values, function(value, key) {
301
298
  this.push(key + ': ' + value);
302
299
  }, log);
303
300
  expect(log).toEqual(['name: misko', 'gender: male']);
@@ -311,7 +308,7 @@ function isArrayLike(obj) {
311
308
  function forEach(obj, iterator, context) {
312
309
  var key;
313
310
  if (obj) {
314
- if (isFunction(obj)){
311
+ if (isFunction(obj)) {
315
312
  for (key in obj) {
316
313
  // Need to check if hasOwnProperty exists,
317
314
  // as on IE8 the result of querySelectorAll is an object without a hasOwnProperty function
@@ -412,7 +409,7 @@ function setHashKey(obj, h) {
412
409
  * @ngdoc function
413
410
  * @name angular.extend
414
411
  * @module ng
415
- * @function
412
+ * @kind function
416
413
  *
417
414
  * @description
418
415
  * Extends the destination object `dst` by copying all of the properties from the `src` object(s)
@@ -424,9 +421,9 @@ function setHashKey(obj, h) {
424
421
  */
425
422
  function extend(dst) {
426
423
  var h = dst.$$hashKey;
427
- forEach(arguments, function(obj){
424
+ forEach(arguments, function(obj) {
428
425
  if (obj !== dst) {
429
- forEach(obj, function(value, key){
426
+ forEach(obj, function(value, key) {
430
427
  dst[key] = value;
431
428
  });
432
429
  }
@@ -449,7 +446,7 @@ function inherit(parent, extra) {
449
446
  * @ngdoc function
450
447
  * @name angular.noop
451
448
  * @module ng
452
- * @function
449
+ * @kind function
453
450
  *
454
451
  * @description
455
452
  * A function that performs no operations. This function can be useful when writing code in the
@@ -469,7 +466,7 @@ noop.$inject = [];
469
466
  * @ngdoc function
470
467
  * @name angular.identity
471
468
  * @module ng
472
- * @function
469
+ * @kind function
473
470
  *
474
471
  * @description
475
472
  * A function that returns its first argument. This function is useful when writing code in the
@@ -491,7 +488,7 @@ function valueFn(value) {return function() {return value;};}
491
488
  * @ngdoc function
492
489
  * @name angular.isUndefined
493
490
  * @module ng
494
- * @function
491
+ * @kind function
495
492
  *
496
493
  * @description
497
494
  * Determines if a reference is undefined.
@@ -506,7 +503,7 @@ function isUndefined(value){return typeof value === 'undefined';}
506
503
  * @ngdoc function
507
504
  * @name angular.isDefined
508
505
  * @module ng
509
- * @function
506
+ * @kind function
510
507
  *
511
508
  * @description
512
509
  * Determines if a reference is defined.
@@ -521,7 +518,7 @@ function isDefined(value){return typeof value !== 'undefined';}
521
518
  * @ngdoc function
522
519
  * @name angular.isObject
523
520
  * @module ng
524
- * @function
521
+ * @kind function
525
522
  *
526
523
  * @description
527
524
  * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not
@@ -537,7 +534,7 @@ function isObject(value){return value != null && typeof value === 'object';}
537
534
  * @ngdoc function
538
535
  * @name angular.isString
539
536
  * @module ng
540
- * @function
537
+ * @kind function
541
538
  *
542
539
  * @description
543
540
  * Determines if a reference is a `String`.
@@ -552,7 +549,7 @@ function isString(value){return typeof value === 'string';}
552
549
  * @ngdoc function
553
550
  * @name angular.isNumber
554
551
  * @module ng
555
- * @function
552
+ * @kind function
556
553
  *
557
554
  * @description
558
555
  * Determines if a reference is a `Number`.
@@ -567,7 +564,7 @@ function isNumber(value){return typeof value === 'number';}
567
564
  * @ngdoc function
568
565
  * @name angular.isDate
569
566
  * @module ng
570
- * @function
567
+ * @kind function
571
568
  *
572
569
  * @description
573
570
  * Determines if a value is a date.
@@ -575,7 +572,7 @@ function isNumber(value){return typeof value === 'number';}
575
572
  * @param {*} value Reference to check.
576
573
  * @returns {boolean} True if `value` is a `Date`.
577
574
  */
578
- function isDate(value){
575
+ function isDate(value) {
579
576
  return toString.call(value) === '[object Date]';
580
577
  }
581
578
 
@@ -584,7 +581,7 @@ function isDate(value){
584
581
  * @ngdoc function
585
582
  * @name angular.isArray
586
583
  * @module ng
587
- * @function
584
+ * @kind function
588
585
  *
589
586
  * @description
590
587
  * Determines if a reference is an `Array`.
@@ -592,16 +589,20 @@ function isDate(value){
592
589
  * @param {*} value Reference to check.
593
590
  * @returns {boolean} True if `value` is an `Array`.
594
591
  */
595
- function isArray(value) {
596
- return toString.call(value) === '[object Array]';
597
- }
598
-
592
+ var isArray = (function() {
593
+ if (!isFunction(Array.isArray)) {
594
+ return function(value) {
595
+ return toString.call(value) === '[object Array]';
596
+ };
597
+ }
598
+ return Array.isArray;
599
+ })();
599
600
 
600
601
  /**
601
602
  * @ngdoc function
602
603
  * @name angular.isFunction
603
604
  * @module ng
604
- * @function
605
+ * @kind function
605
606
  *
606
607
  * @description
607
608
  * Determines if a reference is a `Function`.
@@ -675,7 +676,7 @@ var trim = (function() {
675
676
  * @ngdoc function
676
677
  * @name angular.isElement
677
678
  * @module ng
678
- * @function
679
+ * @kind function
679
680
  *
680
681
  * @description
681
682
  * Determines if a reference is a DOM element (or wrapped jQuery element).
@@ -693,7 +694,7 @@ function isElement(node) {
693
694
  * @param str 'key1,key2,...'
694
695
  * @returns {object} in the form of {key1:true, key2:true, ...}
695
696
  */
696
- function makeMap(str){
697
+ function makeMap(str) {
697
698
  var obj = {}, items = str.split(","), i;
698
699
  for ( i = 0; i < items.length; i++ )
699
700
  obj[ items[i] ] = true;
@@ -740,7 +741,7 @@ function size(obj, ownPropsOnly) {
740
741
 
741
742
  if (isArray(obj) || isString(obj)) {
742
743
  return obj.length;
743
- } else if (isObject(obj)){
744
+ } else if (isObject(obj)) {
744
745
  for (key in obj)
745
746
  if (!ownPropsOnly || obj.hasOwnProperty(key))
746
747
  count++;
@@ -786,7 +787,7 @@ function isLeafNode (node) {
786
787
  * @ngdoc function
787
788
  * @name angular.copy
788
789
  * @module ng
789
- * @function
790
+ * @kind function
790
791
  *
791
792
  * @description
792
793
  * Creates a deep copy of `source`, which should be an object or an array.
@@ -839,7 +840,7 @@ function isLeafNode (node) {
839
840
  </file>
840
841
  </example>
841
842
  */
842
- function copy(source, destination){
843
+ function copy(source, destination, stackSource, stackDest) {
843
844
  if (isWindow(source) || isScope(source)) {
844
845
  throw ngMinErr('cpws',
845
846
  "Can't copy! Making copies of Window or Scope instances is not supported.");
@@ -849,52 +850,82 @@ function copy(source, destination){
849
850
  destination = source;
850
851
  if (source) {
851
852
  if (isArray(source)) {
852
- destination = copy(source, []);
853
+ destination = copy(source, [], stackSource, stackDest);
853
854
  } else if (isDate(source)) {
854
855
  destination = new Date(source.getTime());
855
856
  } else if (isRegExp(source)) {
856
857
  destination = new RegExp(source.source);
857
858
  } else if (isObject(source)) {
858
- destination = copy(source, {});
859
+ destination = copy(source, {}, stackSource, stackDest);
859
860
  }
860
861
  }
861
862
  } else {
862
863
  if (source === destination) throw ngMinErr('cpi',
863
864
  "Can't copy! Source and destination are identical.");
865
+
866
+ stackSource = stackSource || [];
867
+ stackDest = stackDest || [];
868
+
869
+ if (isObject(source)) {
870
+ var index = indexOf(stackSource, source);
871
+ if (index !== -1) return stackDest[index];
872
+
873
+ stackSource.push(source);
874
+ stackDest.push(destination);
875
+ }
876
+
877
+ var result;
864
878
  if (isArray(source)) {
865
879
  destination.length = 0;
866
880
  for ( var i = 0; i < source.length; i++) {
867
- destination.push(copy(source[i]));
881
+ result = copy(source[i], null, stackSource, stackDest);
882
+ if (isObject(source[i])) {
883
+ stackSource.push(source[i]);
884
+ stackDest.push(result);
885
+ }
886
+ destination.push(result);
868
887
  }
869
888
  } else {
870
889
  var h = destination.$$hashKey;
871
- forEach(destination, function(value, key){
890
+ forEach(destination, function(value, key) {
872
891
  delete destination[key];
873
892
  });
874
893
  for ( var key in source) {
875
- destination[key] = copy(source[key]);
894
+ result = copy(source[key], null, stackSource, stackDest);
895
+ if (isObject(source[key])) {
896
+ stackSource.push(source[key]);
897
+ stackDest.push(result);
898
+ }
899
+ destination[key] = result;
876
900
  }
877
901
  setHashKey(destination,h);
878
902
  }
903
+
879
904
  }
880
905
  return destination;
881
906
  }
882
907
 
883
908
  /**
884
- * Create a shallow copy of an object
909
+ * Creates a shallow copy of an object, an array or a primitive
885
910
  */
886
911
  function shallowCopy(src, dst) {
887
- dst = dst || {};
912
+ if (isArray(src)) {
913
+ dst = dst || [];
914
+
915
+ for ( var i = 0; i < src.length; i++) {
916
+ dst[i] = src[i];
917
+ }
918
+ } else if (isObject(src)) {
919
+ dst = dst || {};
888
920
 
889
- for(var key in src) {
890
- // shallowCopy is only ever called by $compile nodeLinkFn, which has control over src
891
- // so we don't need to worry about using our custom hasOwnProperty here
892
- if (src.hasOwnProperty(key) && !(key.charAt(0) === '$' && key.charAt(1) === '$')) {
893
- dst[key] = src[key];
921
+ for (var key in src) {
922
+ if (hasOwnProperty.call(src, key) && !(key.charAt(0) === '$' && key.charAt(1) === '$')) {
923
+ dst[key] = src[key];
924
+ }
894
925
  }
895
926
  }
896
927
 
897
- return dst;
928
+ return dst || src;
898
929
  }
899
930
 
900
931
 
@@ -902,7 +933,7 @@ function shallowCopy(src, dst) {
902
933
  * @ngdoc function
903
934
  * @name angular.equals
904
935
  * @module ng
905
- * @function
936
+ * @kind function
906
937
  *
907
938
  * @description
908
939
  * Determines if two objects or two values are equivalent. Supports value types, regular
@@ -914,7 +945,7 @@ function shallowCopy(src, dst) {
914
945
  * * Both objects or values are of the same type and all of their properties are equal by
915
946
  * comparing them with `angular.equals`.
916
947
  * * Both values are NaN. (In JavaScript, NaN == NaN => false. But we consider two NaN as equal)
917
- * * Both values represent the same regular expression (In JavasScript,
948
+ * * Both values represent the same regular expression (In JavaScript,
918
949
  * /abc/ == /abc/ => false. But we consider two regular expressions as equal when their textual
919
950
  * representation matches).
920
951
  *
@@ -989,7 +1020,7 @@ function sliceArgs(args, startIndex) {
989
1020
  * @ngdoc function
990
1021
  * @name angular.bind
991
1022
  * @module ng
992
- * @function
1023
+ * @kind function
993
1024
  *
994
1025
  * @description
995
1026
  * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for
@@ -1045,7 +1076,7 @@ function toJsonReplacer(key, value) {
1045
1076
  * @ngdoc function
1046
1077
  * @name angular.toJson
1047
1078
  * @module ng
1048
- * @function
1079
+ * @kind function
1049
1080
  *
1050
1081
  * @description
1051
1082
  * Serializes input into a JSON-formatted string. Properties with leading $ characters will be
@@ -1065,7 +1096,7 @@ function toJson(obj, pretty) {
1065
1096
  * @ngdoc function
1066
1097
  * @name angular.fromJson
1067
1098
  * @module ng
1068
- * @function
1099
+ * @kind function
1069
1100
  *
1070
1101
  * @description
1071
1102
  * Deserializes a JSON string.
@@ -1142,7 +1173,7 @@ function tryDecodeURIComponent(value) {
1142
1173
  */
1143
1174
  function parseKeyValue(/**string*/keyValue) {
1144
1175
  var obj = {}, key_value, key;
1145
- forEach((keyValue || "").split('&'), function(keyValue){
1176
+ forEach((keyValue || "").split('&'), function(keyValue) {
1146
1177
  if ( keyValue ) {
1147
1178
  key_value = keyValue.split('=');
1148
1179
  key = tryDecodeURIComponent(key_value[0]);
@@ -1404,7 +1435,7 @@ function bootstrap(element, modules) {
1404
1435
  }
1405
1436
 
1406
1437
  var SNAKE_CASE_REGEXP = /[A-Z]/g;
1407
- function snake_case(name, separator){
1438
+ function snake_case(name, separator) {
1408
1439
  separator = separator || '_';
1409
1440
  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {
1410
1441
  return (pos ? separator : '') + letter.toLowerCase();
@@ -1414,8 +1445,9 @@ function snake_case(name, separator){
1414
1445
  function bindJQuery() {
1415
1446
  // bind to jQuery if present;
1416
1447
  jQuery = window.jQuery;
1417
- // reset to jQuery or default to us.
1418
- if (jQuery) {
1448
+ // Use jQuery if it exists with proper functionality, otherwise default to us.
1449
+ // Angular 1.2+ requires jQuery 1.7.1+ for on()/off() support.
1450
+ if (jQuery && jQuery.fn.on) {
1419
1451
  jqLite = jQuery;
1420
1452
  extend(jQuery.fn, {
1421
1453
  scope: JQLitePrototype.scope,
@@ -1561,7 +1593,7 @@ function setupModuleLoader(window) {
1561
1593
  *
1562
1594
  * # Module
1563
1595
  *
1564
- * A module is a collection of services, directives, filters, and configuration information.
1596
+ * A module is a collection of services, directives, controllers, filters, and configuration information.
1565
1597
  * `angular.module` is used to configure the {@link auto.$injector $injector}.
1566
1598
  *
1567
1599
  * ```js
@@ -1589,9 +1621,9 @@ function setupModuleLoader(window) {
1589
1621
  * {@link angular.bootstrap} to simplify this process for you.
1590
1622
  *
1591
1623
  * @param {!string} name The name of the module to create or retrieve.
1592
- <<<<<* @param {!Array.<string>=} requires If specified then new module is being created. If
1593
- >>>>>* unspecified then the module is being retrieved for further configuration.
1594
- * @param {Function} configFn Optional configuration function for the module. Same as
1624
+ * @param {!Array.<string>=} requires If specified then new module is being created. If
1625
+ * unspecified then the module is being retrieved for further configuration.
1626
+ * @param {Function=} configFn Optional configuration function for the module. Same as
1595
1627
  * {@link angular.Module#config Module#config()}.
1596
1628
  * @returns {module} new module with the {@link angular.Module} api.
1597
1629
  */
@@ -1783,6 +1815,8 @@ function setupModuleLoader(window) {
1783
1815
  * configuration.
1784
1816
  * @description
1785
1817
  * Use this method to register work which needs to be performed on module loading.
1818
+ * For more about how to configure services, see
1819
+ * {@link providers#providers_provider-recipe Provider Recipe}.
1786
1820
  */
1787
1821
  config: config,
1788
1822
 
@@ -1919,11 +1953,11 @@ function setupModuleLoader(window) {
1919
1953
  * - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat".
1920
1954
  */
1921
1955
  var version = {
1922
- full: '1.2.16', // all of these placeholder strings will be replaced by grunt's
1956
+ full: '1.2.18', // all of these placeholder strings will be replaced by grunt's
1923
1957
  major: 1, // package task
1924
1958
  minor: 2,
1925
- dot: 16,
1926
- codeName: 'badger-enumeration'
1959
+ dot: 18,
1960
+ codeName: 'ear-extendability'
1927
1961
  };
1928
1962
 
1929
1963
 
@@ -2063,7 +2097,7 @@ function publishExternalAPI(angular){
2063
2097
  * @ngdoc function
2064
2098
  * @name angular.element
2065
2099
  * @module ng
2066
- * @function
2100
+ * @kind function
2067
2101
  *
2068
2102
  * @description
2069
2103
  * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.
@@ -2146,7 +2180,7 @@ function publishExternalAPI(angular){
2146
2180
  */
2147
2181
 
2148
2182
  var jqCache = JQLite.cache = {},
2149
- jqName = JQLite.expando = 'ng-' + new Date().getTime(),
2183
+ jqName = JQLite.expando = 'ng' + new Date().getTime(),
2150
2184
  jqId = 1,
2151
2185
  addEventListenerFn = (window.document.addEventListener
2152
2186
  ? function(element, type, fn) {element.addEventListener(type, fn, false);}
@@ -2699,6 +2733,7 @@ forEach({
2699
2733
  */
2700
2734
  JQLite.prototype[name] = function(arg1, arg2) {
2701
2735
  var i, key;
2736
+ var nodeCount = this.length;
2702
2737
 
2703
2738
  // jqLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it
2704
2739
  // in a way that survives minification.
@@ -2708,7 +2743,7 @@ forEach({
2708
2743
  if (isObject(arg1)) {
2709
2744
 
2710
2745
  // we are a write, but the object properties are the key/values
2711
- for (i = 0; i < this.length; i++) {
2746
+ for (i = 0; i < nodeCount; i++) {
2712
2747
  if (fn === jqLiteData) {
2713
2748
  // data() takes the whole object in jQuery
2714
2749
  fn(this[i], arg1);
@@ -2722,9 +2757,10 @@ forEach({
2722
2757
  return this;
2723
2758
  } else {
2724
2759
  // we are a read, so read the first child.
2760
+ // TODO: do we still need this?
2725
2761
  var value = fn.$dv;
2726
2762
  // Only if we have $dv do we iterate over all, otherwise it is just the first element.
2727
- var jj = (value === undefined) ? Math.min(this.length, 1) : this.length;
2763
+ var jj = (value === undefined) ? Math.min(nodeCount, 1) : nodeCount;
2728
2764
  for (var j = 0; j < jj; j++) {
2729
2765
  var nodeValue = fn(this[j], arg1, arg2);
2730
2766
  value = value ? value + nodeValue : nodeValue;
@@ -2733,7 +2769,7 @@ forEach({
2733
2769
  }
2734
2770
  } else {
2735
2771
  // we are a write, so apply to all children
2736
- for (i = 0; i < this.length; i++) {
2772
+ for (i = 0; i < nodeCount; i++) {
2737
2773
  fn(this[i], arg1, arg2);
2738
2774
  }
2739
2775
  // return self for chaining
@@ -3102,7 +3138,7 @@ HashMap.prototype = {
3102
3138
  * @ngdoc function
3103
3139
  * @module ng
3104
3140
  * @name angular.injector
3105
- * @function
3141
+ * @kind function
3106
3142
  *
3107
3143
  * @description
3108
3144
  * Creates an injector function that can be used for retrieving services as well as for
@@ -3129,7 +3165,7 @@ HashMap.prototype = {
3129
3165
  *
3130
3166
  * Sometimes you want to get access to the injector of a currently running Angular app
3131
3167
  * from outside Angular. Perhaps, you want to inject and compile some markup after the
3132
- * application has been bootstrapped. You can do this using extra `injector()` added
3168
+ * application has been bootstrapped. You can do this using the extra `injector()` added
3133
3169
  * to JQuery/jqLite elements. See {@link angular.element}.
3134
3170
  *
3135
3171
  * *This is fairly rare but could be the case if a third party library is injecting the
@@ -3199,7 +3235,7 @@ function annotate(fn) {
3199
3235
  /**
3200
3236
  * @ngdoc service
3201
3237
  * @name $injector
3202
- * @function
3238
+ * @kind function
3203
3239
  *
3204
3240
  * @description
3205
3241
  *
@@ -3242,7 +3278,7 @@ function annotate(fn) {
3242
3278
  * minification, and obfuscation tools since these tools change the argument names.
3243
3279
  *
3244
3280
  * ## `$inject` Annotation
3245
- * By adding a `$inject` property onto a function the injection parameters can be specified.
3281
+ * By adding an `$inject` property onto a function the injection parameters can be specified.
3246
3282
  *
3247
3283
  * ## Inline
3248
3284
  * As an array of injection names, where the last item in the array is the function to call.
@@ -3279,7 +3315,7 @@ function annotate(fn) {
3279
3315
  * @name $injector#has
3280
3316
  *
3281
3317
  * @description
3282
- * Allows the user to query if the particular service exist.
3318
+ * Allows the user to query if the particular service exists.
3283
3319
  *
3284
3320
  * @param {string} Name of the service to query.
3285
3321
  * @returns {boolean} returns true if injector has given service.
@@ -3289,8 +3325,8 @@ function annotate(fn) {
3289
3325
  * @ngdoc method
3290
3326
  * @name $injector#instantiate
3291
3327
  * @description
3292
- * Create a new instance of JS type. The method takes a constructor function invokes the new
3293
- * operator and supplies all of the arguments to the constructor function as specified by the
3328
+ * Create a new instance of JS type. The method takes a constructor function, invokes the new
3329
+ * operator, and supplies all of the arguments to the constructor function as specified by the
3294
3330
  * constructor annotation.
3295
3331
  *
3296
3332
  * @param {Function} Type Annotated constructor function.
@@ -3822,7 +3858,8 @@ function createInjector(modulesToLoad) {
3822
3858
  function getService(serviceName) {
3823
3859
  if (cache.hasOwnProperty(serviceName)) {
3824
3860
  if (cache[serviceName] === INSTANTIATING) {
3825
- throw $injectorMinErr('cdep', 'Circular dependency found: {0}', path.join(' <- '));
3861
+ throw $injectorMinErr('cdep', 'Circular dependency found: {0}',
3862
+ serviceName + ' <- ' + path.join(' <- '));
3826
3863
  }
3827
3864
  return cache[serviceName];
3828
3865
  } else {
@@ -3903,7 +3940,7 @@ function createInjector(modulesToLoad) {
3903
3940
  * @requires $rootScope
3904
3941
  *
3905
3942
  * @description
3906
- * When called, it checks current value of `$location.hash()` and scroll to related element,
3943
+ * When called, it checks current value of `$location.hash()` and scrolls to the related element,
3907
3944
  * according to rules specified in
3908
3945
  * [Html5 spec](http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document).
3909
3946
  *
@@ -4105,7 +4142,7 @@ var $AnimateProvider = ['$provide', function($provide) {
4105
4142
  *
4106
4143
  * @ngdoc method
4107
4144
  * @name $animate#enter
4108
- * @function
4145
+ * @kind function
4109
4146
  * @description Inserts the element into the DOM either after the `after` element or within
4110
4147
  * the `parent` element. Once complete, the done() callback will be fired (if provided).
4111
4148
  * @param {DOMElement} element the element which will be inserted into the DOM
@@ -4132,7 +4169,7 @@ var $AnimateProvider = ['$provide', function($provide) {
4132
4169
  *
4133
4170
  * @ngdoc method
4134
4171
  * @name $animate#leave
4135
- * @function
4172
+ * @kind function
4136
4173
  * @description Removes the element from the DOM. Once complete, the done() callback will be
4137
4174
  * fired (if provided).
4138
4175
  * @param {DOMElement} element the element which will be removed from the DOM
@@ -4148,7 +4185,7 @@ var $AnimateProvider = ['$provide', function($provide) {
4148
4185
  *
4149
4186
  * @ngdoc method
4150
4187
  * @name $animate#move
4151
- * @function
4188
+ * @kind function
4152
4189
  * @description Moves the position of the provided element within the DOM to be placed
4153
4190
  * either after the `after` element or inside of the `parent` element. Once complete, the
4154
4191
  * done() callback will be fired (if provided).
@@ -4172,7 +4209,7 @@ var $AnimateProvider = ['$provide', function($provide) {
4172
4209
  *
4173
4210
  * @ngdoc method
4174
4211
  * @name $animate#addClass
4175
- * @function
4212
+ * @kind function
4176
4213
  * @description Adds the provided className CSS class value to the provided element. Once
4177
4214
  * complete, the done() callback will be fired (if provided).
4178
4215
  * @param {DOMElement} element the element which will have the className value
@@ -4195,7 +4232,7 @@ var $AnimateProvider = ['$provide', function($provide) {
4195
4232
  *
4196
4233
  * @ngdoc method
4197
4234
  * @name $animate#removeClass
4198
- * @function
4235
+ * @kind function
4199
4236
  * @description Removes the provided className CSS class value from the provided element.
4200
4237
  * Once complete, the done() callback will be fired (if provided).
4201
4238
  * @param {DOMElement} element the element which will have the className value
@@ -4218,10 +4255,10 @@ var $AnimateProvider = ['$provide', function($provide) {
4218
4255
  *
4219
4256
  * @ngdoc method
4220
4257
  * @name $animate#setClass
4221
- * @function
4258
+ * @kind function
4222
4259
  * @description Adds and/or removes the given CSS classes to and from the element.
4223
4260
  * Once complete, the done() callback will be fired (if provided).
4224
- * @param {DOMElement} element the element which will it's CSS classes changed
4261
+ * @param {DOMElement} element the element which will have its CSS classes changed
4225
4262
  * removed from it
4226
4263
  * @param {string} add the CSS classes which will be added to the element
4227
4264
  * @param {string} remove the CSS class which will be removed from the element
@@ -4775,7 +4812,7 @@ function $CacheFactoryProvider() {
4775
4812
  /**
4776
4813
  * @ngdoc method
4777
4814
  * @name $cacheFactory.Cache#put
4778
- * @function
4815
+ * @kind function
4779
4816
  *
4780
4817
  * @description
4781
4818
  * Inserts a named entry into the {@link $cacheFactory.Cache Cache} object to be
@@ -4811,7 +4848,7 @@ function $CacheFactoryProvider() {
4811
4848
  /**
4812
4849
  * @ngdoc method
4813
4850
  * @name $cacheFactory.Cache#get
4814
- * @function
4851
+ * @kind function
4815
4852
  *
4816
4853
  * @description
4817
4854
  * Retrieves named data stored in the {@link $cacheFactory.Cache Cache} object.
@@ -4835,7 +4872,7 @@ function $CacheFactoryProvider() {
4835
4872
  /**
4836
4873
  * @ngdoc method
4837
4874
  * @name $cacheFactory.Cache#remove
4838
- * @function
4875
+ * @kind function
4839
4876
  *
4840
4877
  * @description
4841
4878
  * Removes an entry from the {@link $cacheFactory.Cache Cache} object.
@@ -4863,7 +4900,7 @@ function $CacheFactoryProvider() {
4863
4900
  /**
4864
4901
  * @ngdoc method
4865
4902
  * @name $cacheFactory.Cache#removeAll
4866
- * @function
4903
+ * @kind function
4867
4904
  *
4868
4905
  * @description
4869
4906
  * Clears the cache object of any entries.
@@ -4879,7 +4916,7 @@ function $CacheFactoryProvider() {
4879
4916
  /**
4880
4917
  * @ngdoc method
4881
4918
  * @name $cacheFactory.Cache#destroy
4882
- * @function
4919
+ * @kind function
4883
4920
  *
4884
4921
  * @description
4885
4922
  * Destroys the {@link $cacheFactory.Cache Cache} object entirely,
@@ -4896,7 +4933,7 @@ function $CacheFactoryProvider() {
4896
4933
  /**
4897
4934
  * @ngdoc method
4898
4935
  * @name $cacheFactory.Cache#info
4899
- * @function
4936
+ * @kind function
4900
4937
  *
4901
4938
  * @description
4902
4939
  * Retrieve information regarding a particular {@link $cacheFactory.Cache Cache}.
@@ -4951,7 +4988,7 @@ function $CacheFactoryProvider() {
4951
4988
  * @name $cacheFactory#info
4952
4989
  *
4953
4990
  * @description
4954
- * Get information about all the of the caches that have been created
4991
+ * Get information about all the caches that have been created
4955
4992
  *
4956
4993
  * @returns {Object} - key-value map of `cacheId` to the result of calling `cache#info`
4957
4994
  */
@@ -5052,7 +5089,7 @@ function $TemplateCacheProvider() {
5052
5089
  /**
5053
5090
  * @ngdoc service
5054
5091
  * @name $compile
5055
- * @function
5092
+ * @kind function
5056
5093
  *
5057
5094
  * @description
5058
5095
  * Compiles an HTML string or DOM into a template and produces a template function, which
@@ -5090,7 +5127,6 @@ function $TemplateCacheProvider() {
5090
5127
  * template: '<div></div>', // or // function(tElement, tAttrs) { ... },
5091
5128
  * // or
5092
5129
  * // templateUrl: 'directive.html', // or // function(tElement, tAttrs) { ... },
5093
- * replace: false,
5094
5130
  * transclude: false,
5095
5131
  * restrict: 'A',
5096
5132
  * scope: false,
@@ -5266,7 +5302,7 @@ function $TemplateCacheProvider() {
5266
5302
  * api/ng.$sce#getTrustedResourceUrl $sce.getTrustedResourceUrl}.
5267
5303
  *
5268
5304
  *
5269
- * #### `replace`
5305
+ * #### `replace` ([*DEPRECATED*!], will be removed in next major release)
5270
5306
  * specify where the template should be inserted. Defaults to `false`.
5271
5307
  *
5272
5308
  * * `true` - the template will replace the current element.
@@ -5293,11 +5329,7 @@ function $TemplateCacheProvider() {
5293
5329
  * ```
5294
5330
  *
5295
5331
  * The compile function deals with transforming the template DOM. Since most directives do not do
5296
- * template transformation, it is not used often. Examples that require compile functions are
5297
- * directives that transform template DOM, such as {@link
5298
- * api/ng.directive:ngRepeat ngRepeat}, or load the contents
5299
- * asynchronously, such as {@link ngRoute.directive:ngView ngView}. The
5300
- * compile function takes the following arguments.
5332
+ * template transformation, it is not used often. The compile function takes the following arguments:
5301
5333
  *
5302
5334
  * * `tElement` - template element - The element where the directive has been declared. It is
5303
5335
  * safe to do template transformation on the element and child elements only.
@@ -5535,7 +5567,7 @@ var $compileMinErr = minErr('$compile');
5535
5567
  /**
5536
5568
  * @ngdoc provider
5537
5569
  * @name $compileProvider
5538
- * @function
5570
+ * @kind function
5539
5571
  *
5540
5572
  * @description
5541
5573
  */
@@ -5543,8 +5575,8 @@ $CompileProvider.$inject = ['$provide', '$$sanitizeUriProvider'];
5543
5575
  function $CompileProvider($provide, $$sanitizeUriProvider) {
5544
5576
  var hasDirectives = {},
5545
5577
  Suffix = 'Directive',
5546
- COMMENT_DIRECTIVE_REGEXP = /^\s*directive\:\s*([\d\w\-_]+)\s+(.*)$/,
5547
- CLASS_DIRECTIVE_REGEXP = /(([\d\w\-_]+)(?:\:([^;]+))?;?)/;
5578
+ COMMENT_DIRECTIVE_REGEXP = /^\s*directive\:\s*([\d\w_\-]+)\s+(.*)$/,
5579
+ CLASS_DIRECTIVE_REGEXP = /(([\d\w_\-]+)(?:\:([^;]+))?;?)/;
5548
5580
 
5549
5581
  // Ref: http://developers.whatwg.org/webappapis.html#event-handler-idl-attributes
5550
5582
  // The assumption is that future DOM event attribute names will begin with
@@ -5554,7 +5586,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
5554
5586
  /**
5555
5587
  * @ngdoc method
5556
5588
  * @name $compileProvider#directive
5557
- * @function
5589
+ * @kind function
5558
5590
  *
5559
5591
  * @description
5560
5592
  * Register a new directive with the compiler.
@@ -5607,7 +5639,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
5607
5639
  /**
5608
5640
  * @ngdoc method
5609
5641
  * @name $compileProvider#aHrefSanitizationWhitelist
5610
- * @function
5642
+ * @kind function
5611
5643
  *
5612
5644
  * @description
5613
5645
  * Retrieves or overrides the default regular expression that is used for whitelisting of safe
@@ -5637,7 +5669,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
5637
5669
  /**
5638
5670
  * @ngdoc method
5639
5671
  * @name $compileProvider#imgSrcSanitizationWhitelist
5640
- * @function
5672
+ * @kind function
5641
5673
  *
5642
5674
  * @description
5643
5675
  * Retrieves or overrides the default regular expression that is used for whitelisting of safe
@@ -5681,7 +5713,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
5681
5713
  /**
5682
5714
  * @ngdoc method
5683
5715
  * @name $compile.directive.Attributes#$addClass
5684
- * @function
5716
+ * @kind function
5685
5717
  *
5686
5718
  * @description
5687
5719
  * Adds the CSS class value specified by the classVal parameter to the element. If animations
@@ -5698,7 +5730,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
5698
5730
  /**
5699
5731
  * @ngdoc method
5700
5732
  * @name $compile.directive.Attributes#$removeClass
5701
- * @function
5733
+ * @kind function
5702
5734
  *
5703
5735
  * @description
5704
5736
  * Removes the CSS class value specified by the classVal parameter from the element. If
@@ -5715,7 +5747,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
5715
5747
  /**
5716
5748
  * @ngdoc method
5717
5749
  * @name $compile.directive.Attributes#$updateClass
5718
- * @function
5750
+ * @kind function
5719
5751
  *
5720
5752
  * @description
5721
5753
  * Adds and removes the appropriate CSS class values to the element based on the difference
@@ -5803,7 +5835,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
5803
5835
  /**
5804
5836
  * @ngdoc method
5805
5837
  * @name $compile.directive.Attributes#$observe
5806
- * @function
5838
+ * @kind function
5807
5839
  *
5808
5840
  * @description
5809
5841
  * Observes an interpolated attribute.
@@ -5866,7 +5898,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
5866
5898
  compileNodes($compileNodes, transcludeFn, $compileNodes,
5867
5899
  maxPriority, ignoreDirective, previousCompileContext);
5868
5900
  safeAddClass($compileNodes, 'ng-scope');
5869
- return function publicLinkFn(scope, cloneConnectFn, transcludeControllers){
5901
+ return function publicLinkFn(scope, cloneConnectFn, transcludeControllers, parentBoundTranscludeFn){
5870
5902
  assertArg(scope, 'scope');
5871
5903
  // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart
5872
5904
  // and sometimes changes the structure of the DOM.
@@ -5888,7 +5920,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
5888
5920
  }
5889
5921
 
5890
5922
  if (cloneConnectFn) cloneConnectFn($linkNode, scope);
5891
- if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode);
5923
+ if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode, parentBoundTranscludeFn);
5892
5924
  return $linkNode;
5893
5925
  };
5894
5926
  }
@@ -5943,7 +5975,9 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
5943
5975
  !childNodes.length)
5944
5976
  ? null
5945
5977
  : compileNodes(childNodes,
5946
- nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);
5978
+ nodeLinkFn ? (
5979
+ (nodeLinkFn.transcludeOnThisElement || !nodeLinkFn.templateOnThisElement)
5980
+ && nodeLinkFn.transclude) : transcludeFn);
5947
5981
 
5948
5982
  linkFns.push(nodeLinkFn, childLinkFn);
5949
5983
  linkFnFound = linkFnFound || nodeLinkFn || childLinkFn;
@@ -5954,8 +5988,8 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
5954
5988
  // return a linking function if we have found anything, null otherwise
5955
5989
  return linkFnFound ? compositeLinkFn : null;
5956
5990
 
5957
- function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {
5958
- var nodeLinkFn, childLinkFn, node, $node, childScope, childTranscludeFn, i, ii, n;
5991
+ function compositeLinkFn(scope, nodeList, $rootElement, parentBoundTranscludeFn) {
5992
+ var nodeLinkFn, childLinkFn, node, $node, childScope, i, ii, n, childBoundTranscludeFn;
5959
5993
 
5960
5994
  // copy nodeList so that linking doesn't break due to live list updates.
5961
5995
  var nodeListLength = nodeList.length,
@@ -5977,23 +6011,32 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
5977
6011
  } else {
5978
6012
  childScope = scope;
5979
6013
  }
5980
- childTranscludeFn = nodeLinkFn.transclude;
5981
- if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {
5982
- nodeLinkFn(childLinkFn, childScope, node, $rootElement,
5983
- createBoundTranscludeFn(scope, childTranscludeFn || transcludeFn)
5984
- );
6014
+
6015
+ if ( nodeLinkFn.transcludeOnThisElement ) {
6016
+ childBoundTranscludeFn = createBoundTranscludeFn(scope, nodeLinkFn.transclude, parentBoundTranscludeFn);
6017
+
6018
+ } else if (!nodeLinkFn.templateOnThisElement && parentBoundTranscludeFn) {
6019
+ childBoundTranscludeFn = parentBoundTranscludeFn;
6020
+
6021
+ } else if (!parentBoundTranscludeFn && transcludeFn) {
6022
+ childBoundTranscludeFn = createBoundTranscludeFn(scope, transcludeFn);
6023
+
5985
6024
  } else {
5986
- nodeLinkFn(childLinkFn, childScope, node, $rootElement, boundTranscludeFn);
6025
+ childBoundTranscludeFn = null;
5987
6026
  }
6027
+
6028
+ nodeLinkFn(childLinkFn, childScope, node, $rootElement, childBoundTranscludeFn);
6029
+
5988
6030
  } else if (childLinkFn) {
5989
- childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);
6031
+ childLinkFn(scope, node.childNodes, undefined, parentBoundTranscludeFn);
5990
6032
  }
5991
6033
  }
5992
6034
  }
5993
6035
  }
5994
6036
 
5995
- function createBoundTranscludeFn(scope, transcludeFn) {
5996
- return function boundTranscludeFn(transcludedScope, cloneFn, controllers) {
6037
+ function createBoundTranscludeFn(scope, transcludeFn, previousBoundTranscludeFn) {
6038
+
6039
+ var boundTranscludeFn = function(transcludedScope, cloneFn, controllers) {
5997
6040
  var scopeCreated = false;
5998
6041
 
5999
6042
  if (!transcludedScope) {
@@ -6002,12 +6045,14 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
6002
6045
  scopeCreated = true;
6003
6046
  }
6004
6047
 
6005
- var clone = transcludeFn(transcludedScope, cloneFn, controllers);
6048
+ var clone = transcludeFn(transcludedScope, cloneFn, controllers, previousBoundTranscludeFn);
6006
6049
  if (scopeCreated) {
6007
- clone.on('$destroy', bind(transcludedScope, transcludedScope.$destroy));
6050
+ clone.on('$destroy', function() { transcludedScope.$destroy(); });
6008
6051
  }
6009
6052
  return clone;
6010
6053
  };
6054
+
6055
+ return boundTranscludeFn;
6011
6056
  }
6012
6057
 
6013
6058
  /**
@@ -6185,6 +6230,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
6185
6230
  templateDirective = previousCompileContext.templateDirective,
6186
6231
  nonTlbTranscludeDirective = previousCompileContext.nonTlbTranscludeDirective,
6187
6232
  hasTranscludeDirective = false,
6233
+ hasTemplate = false,
6188
6234
  hasElementTranscludeDirective = previousCompileContext.hasElementTranscludeDirective,
6189
6235
  $compileNode = templateAttrs.$$element = jqLite(compileNode),
6190
6236
  directive,
@@ -6275,6 +6321,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
6275
6321
  }
6276
6322
 
6277
6323
  if (directive.template) {
6324
+ hasTemplate = true;
6278
6325
  assertNoDuplicate('template', templateDirective, directive, $compileNode);
6279
6326
  templateDirective = directive;
6280
6327
 
@@ -6289,7 +6336,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
6289
6336
  if (jqLiteIsTextNode(directiveValue)) {
6290
6337
  $template = [];
6291
6338
  } else {
6292
- $template = jqLite(directiveValue);
6339
+ $template = jqLite(trim(directiveValue));
6293
6340
  }
6294
6341
  compileNode = $template[0];
6295
6342
 
@@ -6324,6 +6371,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
6324
6371
  }
6325
6372
 
6326
6373
  if (directive.templateUrl) {
6374
+ hasTemplate = true;
6327
6375
  assertNoDuplicate('template', templateDirective, directive, $compileNode);
6328
6376
  templateDirective = directive;
6329
6377
 
@@ -6332,7 +6380,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
6332
6380
  }
6333
6381
 
6334
6382
  nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i), $compileNode,
6335
- templateAttrs, jqCollection, childTranscludeFn, preLinkFns, postLinkFns, {
6383
+ templateAttrs, jqCollection, hasTranscludeDirective && childTranscludeFn, preLinkFns, postLinkFns, {
6336
6384
  controllerDirectives: controllerDirectives,
6337
6385
  newIsolateScopeDirective: newIsolateScopeDirective,
6338
6386
  templateDirective: templateDirective,
@@ -6360,7 +6408,10 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
6360
6408
  }
6361
6409
 
6362
6410
  nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope === true;
6363
- nodeLinkFn.transclude = hasTranscludeDirective && childTranscludeFn;
6411
+ nodeLinkFn.transcludeOnThisElement = hasTranscludeDirective;
6412
+ nodeLinkFn.templateOnThisElement = hasTemplate;
6413
+ nodeLinkFn.transclude = childTranscludeFn;
6414
+
6364
6415
  previousCompileContext.hasElementTranscludeDirective = hasElementTranscludeDirective;
6365
6416
 
6366
6417
  // might be normal or delayed nodeLinkFn depending on if templateUrl is present
@@ -6372,6 +6423,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
6372
6423
  if (pre) {
6373
6424
  if (attrStart) pre = groupElementsLinkFnWrapper(pre, attrStart, attrEnd);
6374
6425
  pre.require = directive.require;
6426
+ pre.directiveName = directiveName;
6375
6427
  if (newIsolateScopeDirective === directive || directive.$$isolateScope) {
6376
6428
  pre = cloneAndAnnotateFn(pre, {isolateScope: true});
6377
6429
  }
@@ -6380,6 +6432,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
6380
6432
  if (post) {
6381
6433
  if (attrStart) post = groupElementsLinkFnWrapper(post, attrStart, attrEnd);
6382
6434
  post.require = directive.require;
6435
+ post.directiveName = directiveName;
6383
6436
  if (newIsolateScopeDirective === directive || directive.$$isolateScope) {
6384
6437
  post = cloneAndAnnotateFn(post, {isolateScope: true});
6385
6438
  }
@@ -6388,7 +6441,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
6388
6441
  }
6389
6442
 
6390
6443
 
6391
- function getControllers(require, $element, elementControllers) {
6444
+ function getControllers(directiveName, require, $element, elementControllers) {
6392
6445
  var value, retrievalMethod = 'data', optional = false;
6393
6446
  if (isString(require)) {
6394
6447
  while((value = require.charAt(0)) == '^' || value == '?') {
@@ -6414,7 +6467,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
6414
6467
  } else if (isArray(require)) {
6415
6468
  value = [];
6416
6469
  forEach(require, function(require) {
6417
- value.push(getControllers(require, $element, elementControllers));
6470
+ value.push(getControllers(directiveName, require, $element, elementControllers));
6418
6471
  });
6419
6472
  }
6420
6473
  return value;
@@ -6437,7 +6490,8 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
6437
6490
 
6438
6491
  isolateScope = scope.$new(true);
6439
6492
 
6440
- if (templateDirective && (templateDirective === newIsolateScopeDirective.$$originalDirective)) {
6493
+ if (templateDirective && (templateDirective === newIsolateScopeDirective ||
6494
+ templateDirective === newIsolateScopeDirective.$$originalDirective)) {
6441
6495
  $linkNode.data('$isolateScope', isolateScope) ;
6442
6496
  } else {
6443
6497
  $linkNode.data('$isolateScopeNoTemplate', isolateScope);
@@ -6557,7 +6611,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
6557
6611
  try {
6558
6612
  linkFn = preLinkFns[i];
6559
6613
  linkFn(linkFn.isolateScope ? isolateScope : scope, $element, attrs,
6560
- linkFn.require && getControllers(linkFn.require, $element, elementControllers), transcludeFn);
6614
+ linkFn.require && getControllers(linkFn.directiveName, linkFn.require, $element, elementControllers), transcludeFn);
6561
6615
  } catch (e) {
6562
6616
  $exceptionHandler(e, startingTag($element));
6563
6617
  }
@@ -6577,7 +6631,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
6577
6631
  try {
6578
6632
  linkFn = postLinkFns[i];
6579
6633
  linkFn(linkFn.isolateScope ? isolateScope : scope, $element, attrs,
6580
- linkFn.require && getControllers(linkFn.require, $element, elementControllers), transcludeFn);
6634
+ linkFn.require && getControllers(linkFn.directiveName, linkFn.require, $element, elementControllers), transcludeFn);
6581
6635
  } catch (e) {
6582
6636
  $exceptionHandler(e, startingTag($element));
6583
6637
  }
@@ -6663,7 +6717,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
6663
6717
  // reapply the old attributes to the new element
6664
6718
  forEach(dst, function(value, key) {
6665
6719
  if (key.charAt(0) != '$') {
6666
- if (src[key]) {
6720
+ if (src[key] && src[key] !== value) {
6667
6721
  value += (key === 'style' ? ';' : ' ') + src[key];
6668
6722
  }
6669
6723
  dst.$set(key, value, true, srcAttr[key]);
@@ -6716,7 +6770,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
6716
6770
  if (jqLiteIsTextNode(content)) {
6717
6771
  $template = [];
6718
6772
  } else {
6719
- $template = jqLite(content);
6773
+ $template = jqLite(trim(content));
6720
6774
  }
6721
6775
  compileNode = $template[0];
6722
6776
 
@@ -6752,7 +6806,6 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
6752
6806
  });
6753
6807
  afterTemplateChildLinkFn = compileNodes($compileNode[0].childNodes, childTranscludeFn);
6754
6808
 
6755
-
6756
6809
  while(linkQueue.length) {
6757
6810
  var scope = linkQueue.shift(),
6758
6811
  beforeTemplateLinkNode = linkQueue.shift(),
@@ -6774,8 +6827,8 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
6774
6827
  // Copy in CSS classes from original node
6775
6828
  safeAddClass(jqLite(linkNode), oldClasses);
6776
6829
  }
6777
- if (afterTemplateNodeLinkFn.transclude) {
6778
- childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude);
6830
+ if (afterTemplateNodeLinkFn.transcludeOnThisElement) {
6831
+ childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude, boundTranscludeFn);
6779
6832
  } else {
6780
6833
  childBoundTranscludeFn = boundTranscludeFn;
6781
6834
  }
@@ -6789,13 +6842,17 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
6789
6842
  });
6790
6843
 
6791
6844
  return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, boundTranscludeFn) {
6845
+ var childBoundTranscludeFn = boundTranscludeFn;
6792
6846
  if (linkQueue) {
6793
6847
  linkQueue.push(scope);
6794
6848
  linkQueue.push(node);
6795
6849
  linkQueue.push(rootElement);
6796
- linkQueue.push(boundTranscludeFn);
6850
+ linkQueue.push(childBoundTranscludeFn);
6797
6851
  } else {
6798
- afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, boundTranscludeFn);
6852
+ if (afterTemplateNodeLinkFn.transcludeOnThisElement) {
6853
+ childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude, boundTranscludeFn);
6854
+ }
6855
+ afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, childBoundTranscludeFn);
6799
6856
  }
6800
6857
  };
6801
6858
  }
@@ -6820,23 +6877,31 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
6820
6877
  }
6821
6878
 
6822
6879
 
6823
- function addTextInterpolateDirective(directives, text) {
6824
- var interpolateFn = $interpolate(text, true);
6825
- if (interpolateFn) {
6826
- directives.push({
6827
- priority: 0,
6828
- compile: valueFn(function textInterpolateLinkFn(scope, node) {
6829
- var parent = node.parent(),
6830
- bindings = parent.data('$binding') || [];
6831
- bindings.push(interpolateFn);
6832
- safeAddClass(parent.data('$binding', bindings), 'ng-binding');
6833
- scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {
6834
- node[0].nodeValue = value;
6835
- });
6836
- })
6837
- });
6880
+ function addTextInterpolateDirective(directives, text) {
6881
+ var interpolateFn = $interpolate(text, true);
6882
+ if (interpolateFn) {
6883
+ directives.push({
6884
+ priority: 0,
6885
+ compile: function textInterpolateCompileFn(templateNode) {
6886
+ // when transcluding a template that has bindings in the root
6887
+ // then we don't have a parent and should do this in the linkFn
6888
+ var parent = templateNode.parent(), hasCompileParent = parent.length;
6889
+ if (hasCompileParent) safeAddClass(templateNode.parent(), 'ng-binding');
6890
+
6891
+ return function textInterpolateLinkFn(scope, node) {
6892
+ var parent = node.parent(),
6893
+ bindings = parent.data('$binding') || [];
6894
+ bindings.push(interpolateFn);
6895
+ parent.data('$binding', bindings);
6896
+ if (!hasCompileParent) safeAddClass(parent, 'ng-binding');
6897
+ scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {
6898
+ node[0].nodeValue = value;
6899
+ });
6900
+ };
6901
+ }
6902
+ });
6903
+ }
6838
6904
  }
6839
- }
6840
6905
 
6841
6906
 
6842
6907
  function getTrustedContext(node, attrNormalizedName) {
@@ -6997,7 +7062,9 @@ function directiveNormalize(name) {
6997
7062
  * element attributes. The values reflect current binding state `{{ }}`. The normalization is
6998
7063
  * needed since all of these are treated as equivalent in Angular:
6999
7064
  *
7065
+ * ```
7000
7066
  * <span ng:bind="a" ng-bind="a" data-ng-bind="a" x-ng-bind="a">
7067
+ * ```
7001
7068
  */
7002
7069
 
7003
7070
  /**
@@ -7011,7 +7078,7 @@ function directiveNormalize(name) {
7011
7078
  /**
7012
7079
  * @ngdoc method
7013
7080
  * @name $compile.directive.Attributes#$set
7014
- * @function
7081
+ * @kind function
7015
7082
  *
7016
7083
  * @description
7017
7084
  * Set DOM element attribute value.
@@ -7329,9 +7396,9 @@ function $HttpProvider() {
7329
7396
  common: {
7330
7397
  'Accept': 'application/json, text/plain, */*'
7331
7398
  },
7332
- post: copy(CONTENT_TYPE_APPLICATION_JSON),
7333
- put: copy(CONTENT_TYPE_APPLICATION_JSON),
7334
- patch: copy(CONTENT_TYPE_APPLICATION_JSON)
7399
+ post: shallowCopy(CONTENT_TYPE_APPLICATION_JSON),
7400
+ put: shallowCopy(CONTENT_TYPE_APPLICATION_JSON),
7401
+ patch: shallowCopy(CONTENT_TYPE_APPLICATION_JSON)
7335
7402
  },
7336
7403
 
7337
7404
  xsrfCookieName: 'XSRF-TOKEN',
@@ -7573,14 +7640,14 @@ function $HttpProvider() {
7573
7640
  *
7574
7641
  * There are two kinds of interceptors (and two kinds of rejection interceptors):
7575
7642
  *
7576
- * * `request`: interceptors get called with http `config` object. The function is free to
7577
- * modify the `config` or create a new one. The function needs to return the `config`
7578
- * directly or as a promise.
7643
+ * * `request`: interceptors get called with a http `config` object. The function is free to
7644
+ * modify the `config` object or create a new one. The function needs to return the `config`
7645
+ * object directly, or a promise containing the `config` or a new `config` object.
7579
7646
  * * `requestError`: interceptor gets called when a previous interceptor threw an error or
7580
7647
  * resolved with a rejection.
7581
7648
  * * `response`: interceptors get called with http `response` object. The function is free to
7582
- * modify the `response` or create a new one. The function needs to return the `response`
7583
- * directly or as a promise.
7649
+ * modify the `response` object or create a new one. The function needs to return the `response`
7650
+ * object directly, or as a promise containing the `response` or a new `response` object.
7584
7651
  * * `responseError`: interceptor gets called when a previous interceptor threw an error or
7585
7652
  * resolved with a rejection.
7586
7653
  *
@@ -7592,7 +7659,7 @@ function $HttpProvider() {
7592
7659
  * // optional method
7593
7660
  * 'request': function(config) {
7594
7661
  * // do something on success
7595
- * return config || $q.when(config);
7662
+ * return config;
7596
7663
  * },
7597
7664
  *
7598
7665
  * // optional method
@@ -7609,7 +7676,7 @@ function $HttpProvider() {
7609
7676
  * // optional method
7610
7677
  * 'response': function(response) {
7611
7678
  * // do something on success
7612
- * return response || $q.when(response);
7679
+ * return response;
7613
7680
  * },
7614
7681
  *
7615
7682
  * // optional method
@@ -7770,7 +7837,7 @@ function $HttpProvider() {
7770
7837
  * caching.
7771
7838
  * - **timeout** – `{number|Promise}` – timeout in milliseconds, or {@link ng.$q promise}
7772
7839
  * that should abort the request when resolved.
7773
- * - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the
7840
+ * - **withCredentials** - `{boolean}` - whether to set the `withCredentials` flag on the
7774
7841
  * XHR object. See [requests with credentials]https://developer.mozilla.org/en/http_access_control#section_5
7775
7842
  * for more information.
7776
7843
  * - **responseType** - `{string}` - see
@@ -7808,11 +7875,11 @@ function $HttpProvider() {
7808
7875
  <button id="samplegetbtn" ng-click="updateModel('GET', 'http-hello.html')">Sample GET</button>
7809
7876
  <button id="samplejsonpbtn"
7810
7877
  ng-click="updateModel('JSONP',
7811
- 'http://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')">
7878
+ 'https://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')">
7812
7879
  Sample JSONP
7813
7880
  </button>
7814
7881
  <button id="invalidjsonpbtn"
7815
- ng-click="updateModel('JSONP', 'http://angularjs.org/doesntexist&callback=JSON_CALLBACK')">
7882
+ ng-click="updateModel('JSONP', 'https://angularjs.org/doesntexist&callback=JSON_CALLBACK')">
7816
7883
  Invalid JSONP
7817
7884
  </button>
7818
7885
  <pre>http status code: {{status}}</pre>
@@ -7892,14 +7959,6 @@ function $HttpProvider() {
7892
7959
  config.headers = headers;
7893
7960
  config.method = uppercase(config.method);
7894
7961
 
7895
- var xsrfValue = urlIsSameOrigin(config.url)
7896
- ? $browser.cookies()[config.xsrfCookieName || defaults.xsrfCookieName]
7897
- : undefined;
7898
- if (xsrfValue) {
7899
- headers[(config.xsrfHeaderName || defaults.xsrfHeaderName)] = xsrfValue;
7900
- }
7901
-
7902
-
7903
7962
  var serverRequest = function(config) {
7904
7963
  headers = config.headers;
7905
7964
  var reqData = transformData(config.data, headersGetter(headers), config.transformRequest);
@@ -8164,7 +8223,7 @@ function $HttpProvider() {
8164
8223
  } else {
8165
8224
  // serving from cache
8166
8225
  if (isArray(cachedResp)) {
8167
- resolvePromise(cachedResp[1], cachedResp[0], copy(cachedResp[2]), cachedResp[3]);
8226
+ resolvePromise(cachedResp[1], cachedResp[0], shallowCopy(cachedResp[2]), cachedResp[3]);
8168
8227
  } else {
8169
8228
  resolvePromise(cachedResp, 200, {}, 'OK');
8170
8229
  }
@@ -8175,8 +8234,17 @@ function $HttpProvider() {
8175
8234
  }
8176
8235
  }
8177
8236
 
8178
- // if we won't have the response in cache, send the request to the backend
8237
+
8238
+ // if we won't have the response in cache, set the xsrf headers and
8239
+ // send the request to the backend
8179
8240
  if (isUndefined(cachedResp)) {
8241
+ var xsrfValue = urlIsSameOrigin(config.url)
8242
+ ? $browser.cookies()[config.xsrfCookieName || defaults.xsrfCookieName]
8243
+ : undefined;
8244
+ if (xsrfValue) {
8245
+ reqHeaders[(config.xsrfHeaderName || defaults.xsrfHeaderName)] = xsrfValue;
8246
+ }
8247
+
8180
8248
  $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,
8181
8249
  config.withCredentials, config.responseType);
8182
8250
  }
@@ -8303,16 +8371,13 @@ function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDoc
8303
8371
  var callbackId = '_' + (callbacks.counter++).toString(36);
8304
8372
  callbacks[callbackId] = function(data) {
8305
8373
  callbacks[callbackId].data = data;
8374
+ callbacks[callbackId].called = true;
8306
8375
  };
8307
8376
 
8308
8377
  var jsonpDone = jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),
8309
- function() {
8310
- if (callbacks[callbackId].data) {
8311
- completeRequest(callback, 200, callbacks[callbackId].data);
8312
- } else {
8313
- completeRequest(callback, status || -2);
8314
- }
8315
- callbacks[callbackId] = angular.noop;
8378
+ callbackId, function(status, text) {
8379
+ completeRequest(callback, status, callbacks[callbackId].data, "", text);
8380
+ callbacks[callbackId] = noop;
8316
8381
  });
8317
8382
  } else {
8318
8383
 
@@ -8414,34 +8479,52 @@ function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDoc
8414
8479
  }
8415
8480
  };
8416
8481
 
8417
- function jsonpReq(url, done) {
8482
+ function jsonpReq(url, callbackId, done) {
8418
8483
  // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:
8419
8484
  // - fetches local scripts via XHR and evals them
8420
8485
  // - adds and immediately removes script elements from the document
8421
- var script = rawDocument.createElement('script'),
8422
- doneWrapper = function() {
8423
- script.onreadystatechange = script.onload = script.onerror = null;
8424
- rawDocument.body.removeChild(script);
8425
- if (done) done();
8426
- };
8427
-
8428
- script.type = 'text/javascript';
8486
+ var script = rawDocument.createElement('script'), callback = null;
8487
+ script.type = "text/javascript";
8429
8488
  script.src = url;
8489
+ script.async = true;
8490
+
8491
+ callback = function(event) {
8492
+ removeEventListenerFn(script, "load", callback);
8493
+ removeEventListenerFn(script, "error", callback);
8494
+ rawDocument.body.removeChild(script);
8495
+ script = null;
8496
+ var status = -1;
8497
+ var text = "unknown";
8498
+
8499
+ if (event) {
8500
+ if (event.type === "load" && !callbacks[callbackId].called) {
8501
+ event = { type: "error" };
8502
+ }
8503
+ text = event.type;
8504
+ status = event.type === "error" ? 404 : 200;
8505
+ }
8506
+
8507
+ if (done) {
8508
+ done(status, text);
8509
+ }
8510
+ };
8511
+
8512
+ addEventListenerFn(script, "load", callback);
8513
+ addEventListenerFn(script, "error", callback);
8430
8514
 
8431
- if (msie && msie <= 8) {
8515
+ if (msie <= 8) {
8432
8516
  script.onreadystatechange = function() {
8433
- if (/loaded|complete/.test(script.readyState)) {
8434
- doneWrapper();
8517
+ if (isString(script.readyState) && /loaded|complete/.test(script.readyState)) {
8518
+ script.onreadystatechange = null;
8519
+ callback({
8520
+ type: 'load'
8521
+ });
8435
8522
  }
8436
8523
  };
8437
- } else {
8438
- script.onload = script.onerror = function() {
8439
- doneWrapper();
8440
- };
8441
8524
  }
8442
8525
 
8443
8526
  rawDocument.body.appendChild(script);
8444
- return doneWrapper;
8527
+ return callback;
8445
8528
  }
8446
8529
  }
8447
8530
 
@@ -8450,7 +8533,7 @@ var $interpolateMinErr = minErr('$interpolate');
8450
8533
  /**
8451
8534
  * @ngdoc provider
8452
8535
  * @name $interpolateProvider
8453
- * @function
8536
+ * @kind function
8454
8537
  *
8455
8538
  * @description
8456
8539
  *
@@ -8468,7 +8551,7 @@ var $interpolateMinErr = minErr('$interpolate');
8468
8551
  });
8469
8552
 
8470
8553
 
8471
- customInterpolationApp.controller('DemoController', function DemoController() {
8554
+ customInterpolationApp.controller('DemoController', function() {
8472
8555
  this.label = "This binding is brought you by // interpolation symbols.";
8473
8556
  });
8474
8557
  </script>
@@ -8531,7 +8614,7 @@ function $InterpolateProvider() {
8531
8614
  /**
8532
8615
  * @ngdoc service
8533
8616
  * @name $interpolate
8534
- * @function
8617
+ * @kind function
8535
8618
  *
8536
8619
  * @requires $parse
8537
8620
  * @requires $sce
@@ -8623,10 +8706,24 @@ function $InterpolateProvider() {
8623
8706
  } else {
8624
8707
  part = $sce.valueOf(part);
8625
8708
  }
8626
- if (part === null || isUndefined(part)) {
8709
+ if (part == null) { // null || undefined
8627
8710
  part = '';
8628
- } else if (typeof part != 'string') {
8629
- part = toJson(part);
8711
+ } else {
8712
+ switch (typeof part) {
8713
+ case 'string':
8714
+ {
8715
+ break;
8716
+ }
8717
+ case 'number':
8718
+ {
8719
+ part = '' + part;
8720
+ break;
8721
+ }
8722
+ default:
8723
+ {
8724
+ part = toJson(part);
8725
+ }
8726
+ }
8630
8727
  }
8631
8728
  }
8632
8729
  concat[i] = part;
@@ -9137,7 +9234,7 @@ function LocationHashbangUrl(appBase, hashPrefix) {
9137
9234
  Matches paths for file protocol on windows,
9138
9235
  such as /C:/foo/bar, and captures only /foo/bar.
9139
9236
  */
9140
- var windowsFilePathExp = /^\/?.*?:(\/.*)/;
9237
+ var windowsFilePathExp = /^\/[A-Z]:(\/.*)/;
9141
9238
 
9142
9239
  var firstPathSegmentMatch;
9143
9240
 
@@ -9146,10 +9243,7 @@ function LocationHashbangUrl(appBase, hashPrefix) {
9146
9243
  url = url.replace(base, '');
9147
9244
  }
9148
9245
 
9149
- /*
9150
- * The input URL intentionally contains a
9151
- * first path segment that ends with a colon.
9152
- */
9246
+ // The input URL intentionally contains a first path segment that ends with a colon.
9153
9247
  if (windowsFilePathExp.exec(url)) {
9154
9248
  return path;
9155
9249
  }
@@ -9205,6 +9299,16 @@ function LocationHashbangInHtml5Url(appBase, hashPrefix) {
9205
9299
  return appBaseNoFile;
9206
9300
  }
9207
9301
  };
9302
+
9303
+ this.$$compose = function() {
9304
+ var search = toKeyValue(this.$$search),
9305
+ hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';
9306
+
9307
+ this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;
9308
+ // include hashPrefix in $$absUrl when $$url is empty so IE8 & 9 do not reload page because of removal of '#'
9309
+ this.$$absUrl = appBase + hashPrefix + this.$$url;
9310
+ };
9311
+
9208
9312
  }
9209
9313
 
9210
9314
 
@@ -9336,15 +9440,37 @@ LocationHashbangInHtml5Url.prototype =
9336
9440
  *
9337
9441
  * Change search part when called with parameter and return `$location`.
9338
9442
  *
9443
+ *
9444
+ * ```js
9445
+ * // given url http://example.com/#/some/path?foo=bar&baz=xoxo
9446
+ * var searchObject = $location.search();
9447
+ * // => {foo: 'bar', baz: 'xoxo'}
9448
+ *
9449
+ *
9450
+ * // set foo to 'yipee'
9451
+ * $location.search('foo', 'yipee');
9452
+ * // => $location
9453
+ * ```
9454
+ *
9339
9455
  * @param {string|Object.<string>|Object.<Array.<string>>} search New search params - string or
9340
- * hash object. Hash object may contain an array of values, which will be decoded as duplicates in
9341
- * the url.
9456
+ * hash object.
9457
+ *
9458
+ * When called with a single argument the method acts as a setter, setting the `search` component
9459
+ * of `$location` to the specified value.
9460
+ *
9461
+ * If the argument is a hash object containing an array of values, these values will be encoded
9462
+ * as duplicate search parameters in the url.
9342
9463
  *
9343
- * @param {(string|Array<string>)=} paramValue If `search` is a string, then `paramValue` will override only a
9344
- * single search parameter. If `paramValue` is an array, it will set the parameter as a
9345
- * comma-separated value. If `paramValue` is `null`, the parameter will be deleted.
9464
+ * @param {(string|Array<string>)=} paramValue If `search` is a string, then `paramValue` will
9465
+ * override only a single search property.
9346
9466
  *
9347
- * @return {string} search
9467
+ * If `paramValue` is an array, it will override the property of the `search` component of
9468
+ * `$location` specified via the first argument.
9469
+ *
9470
+ * If `paramValue` is `null`, the property specified via the first argument will be deleted.
9471
+ *
9472
+ * @return {Object} If called with no arguments returns the parsed `search` object. If called with
9473
+ * one or more arguments returns `$location` object itself.
9348
9474
  */
9349
9475
  search: function(search, paramValue) {
9350
9476
  switch (arguments.length) {
@@ -9557,6 +9683,39 @@ function $LocationProvider(){
9557
9683
  absHref = urlResolve(absHref.animVal).href;
9558
9684
  }
9559
9685
 
9686
+ // Make relative links work in HTML5 mode for legacy browsers (or at least IE8 & 9)
9687
+ // The href should be a regular url e.g. /link/somewhere or link/somewhere or ../somewhere or
9688
+ // somewhere#anchor or http://example.com/somewhere
9689
+ if (LocationMode === LocationHashbangInHtml5Url) {
9690
+ // get the actual href attribute - see
9691
+ // http://msdn.microsoft.com/en-us/library/ie/dd347148(v=vs.85).aspx
9692
+ var href = elm.attr('href') || elm.attr('xlink:href');
9693
+
9694
+ if (href.indexOf('://') < 0) { // Ignore absolute URLs
9695
+ var prefix = '#' + hashPrefix;
9696
+ if (href[0] == '/') {
9697
+ // absolute path - replace old path
9698
+ absHref = appBase + prefix + href;
9699
+ } else if (href[0] == '#') {
9700
+ // local anchor
9701
+ absHref = appBase + prefix + ($location.path() || '/') + href;
9702
+ } else {
9703
+ // relative path - join with current path
9704
+ var stack = $location.path().split("/"),
9705
+ parts = href.split("/");
9706
+ for (var i=0; i<parts.length; i++) {
9707
+ if (parts[i] == ".")
9708
+ continue;
9709
+ else if (parts[i] == "..")
9710
+ stack.pop();
9711
+ else if (parts[i].length)
9712
+ stack.push(parts[i]);
9713
+ }
9714
+ absHref = appBase + prefix + stack.join('/');
9715
+ }
9716
+ }
9717
+ }
9718
+
9560
9719
  var rewrittenUrl = $location.$$rewrite(absHref);
9561
9720
 
9562
9721
  if (absHref && !elm.attr('target') && rewrittenUrl && !event.isDefaultPrevented()) {
@@ -9917,9 +10076,6 @@ Lexer.prototype = {
9917
10076
 
9918
10077
  this.tokens = [];
9919
10078
 
9920
- var token;
9921
- var json = [];
9922
-
9923
10079
  while (this.index < this.text.length) {
9924
10080
  this.ch = this.text.charAt(this.index);
9925
10081
  if (this.is('"\'')) {
@@ -9928,19 +10084,11 @@ Lexer.prototype = {
9928
10084
  this.readNumber();
9929
10085
  } else if (this.isIdent(this.ch)) {
9930
10086
  this.readIdent();
9931
- // identifiers can only be if the preceding char was a { or ,
9932
- if (this.was('{,') && json[0] === '{' &&
9933
- (token = this.tokens[this.tokens.length - 1])) {
9934
- token.json = token.text.indexOf('.') === -1;
9935
- }
9936
10087
  } else if (this.is('(){}[].,;:?')) {
9937
10088
  this.tokens.push({
9938
10089
  index: this.index,
9939
- text: this.ch,
9940
- json: (this.was(':[,') && this.is('{[')) || this.is('}]:,')
10090
+ text: this.ch
9941
10091
  });
9942
- if (this.is('{[')) json.unshift(this.ch);
9943
- if (this.is('}]')) json.shift();
9944
10092
  this.index++;
9945
10093
  } else if (this.isWhitespace(this.ch)) {
9946
10094
  this.index++;
@@ -9961,8 +10109,7 @@ Lexer.prototype = {
9961
10109
  this.tokens.push({
9962
10110
  index: this.index,
9963
10111
  text: this.ch,
9964
- fn: fn,
9965
- json: (this.was('[,:') && this.is('+-'))
10112
+ fn: fn
9966
10113
  });
9967
10114
  this.index += 1;
9968
10115
  } else {
@@ -10045,7 +10192,8 @@ Lexer.prototype = {
10045
10192
  this.tokens.push({
10046
10193
  index: start,
10047
10194
  text: number,
10048
- json: true,
10195
+ literal: true,
10196
+ constant: true,
10049
10197
  fn: function() { return number; }
10050
10198
  });
10051
10199
  },
@@ -10097,7 +10245,8 @@ Lexer.prototype = {
10097
10245
  // OPERATORS is our own object so we don't need to use special hasOwnPropertyFn
10098
10246
  if (OPERATORS.hasOwnProperty(ident)) {
10099
10247
  token.fn = OPERATORS[ident];
10100
- token.json = OPERATORS[ident];
10248
+ token.literal = true;
10249
+ token.constant = true;
10101
10250
  } else {
10102
10251
  var getter = getterFn(ident, this.options, this.text);
10103
10252
  token.fn = extend(function(self, locals) {
@@ -10114,13 +10263,11 @@ Lexer.prototype = {
10114
10263
  if (methodName) {
10115
10264
  this.tokens.push({
10116
10265
  index:lastDot,
10117
- text: '.',
10118
- json: false
10266
+ text: '.'
10119
10267
  });
10120
10268
  this.tokens.push({
10121
10269
  index: lastDot + 1,
10122
- text: methodName,
10123
- json: false
10270
+ text: methodName
10124
10271
  });
10125
10272
  }
10126
10273
  },
@@ -10158,7 +10305,8 @@ Lexer.prototype = {
10158
10305
  index: start,
10159
10306
  text: rawString,
10160
10307
  string: string,
10161
- json: true,
10308
+ literal: true,
10309
+ constant: true,
10162
10310
  fn: function() { return string; }
10163
10311
  });
10164
10312
  return;
@@ -10190,28 +10338,12 @@ Parser.ZERO = extend(function () {
10190
10338
  Parser.prototype = {
10191
10339
  constructor: Parser,
10192
10340
 
10193
- parse: function (text, json) {
10341
+ parse: function (text) {
10194
10342
  this.text = text;
10195
10343
 
10196
- //TODO(i): strip all the obsolte json stuff from this file
10197
- this.json = json;
10198
-
10199
10344
  this.tokens = this.lexer.lex(text);
10200
10345
 
10201
- if (json) {
10202
- // The extra level of aliasing is here, just in case the lexer misses something, so that
10203
- // we prevent any accidental execution in JSON.
10204
- this.assignment = this.logicalOR;
10205
-
10206
- this.functionCall =
10207
- this.fieldAccess =
10208
- this.objectIndex =
10209
- this.filterChain = function() {
10210
- this.throwError('is not valid json', {text: text, index: 0});
10211
- };
10212
- }
10213
-
10214
- var value = json ? this.primary() : this.statements();
10346
+ var value = this.statements();
10215
10347
 
10216
10348
  if (this.tokens.length !== 0) {
10217
10349
  this.throwError('is an unexpected token', this.tokens[0]);
@@ -10238,10 +10370,8 @@ Parser.prototype = {
10238
10370
  if (!primary) {
10239
10371
  this.throwError('not a primary expression', token);
10240
10372
  }
10241
- if (token.json) {
10242
- primary.constant = true;
10243
- primary.literal = true;
10244
- }
10373
+ primary.literal = !!token.literal;
10374
+ primary.constant = !!token.constant;
10245
10375
  }
10246
10376
 
10247
10377
  var next, context;
@@ -10289,9 +10419,6 @@ Parser.prototype = {
10289
10419
  expect: function(e1, e2, e3, e4){
10290
10420
  var token = this.peek(e1, e2, e3, e4);
10291
10421
  if (token) {
10292
- if (this.json && !token.json) {
10293
- this.throwError('is not valid json', token);
10294
- }
10295
10422
  this.tokens.shift();
10296
10423
  return token;
10297
10424
  }
@@ -10926,7 +11053,7 @@ function getterFn(path, options, fullExp) {
10926
11053
  /**
10927
11054
  * @ngdoc provider
10928
11055
  * @name $parseProvider
10929
- * @function
11056
+ * @kind function
10930
11057
  *
10931
11058
  * @description
10932
11059
  * `$parseProvider` can be used for configuring the default behavior of the {@link ng.$parse $parse}
@@ -11045,7 +11172,7 @@ function $ParseProvider() {
11045
11172
 
11046
11173
  var lexer = new Lexer($parseOptions);
11047
11174
  var parser = new Parser(lexer, $filter, $parseOptions);
11048
- parsedExpression = parser.parse(exp, false);
11175
+ parsedExpression = parser.parse(exp);
11049
11176
 
11050
11177
  if (exp !== 'hasOwnProperty') {
11051
11178
  // Only cache the value if it's not going to mess up the cache object
@@ -11256,7 +11383,7 @@ function qFactory(nextTick, exceptionHandler) {
11256
11383
  /**
11257
11384
  * @ngdoc method
11258
11385
  * @name $q#defer
11259
- * @function
11386
+ * @kind function
11260
11387
  *
11261
11388
  * @description
11262
11389
  * Creates a `Deferred` object which represents a task which will finish in the future.
@@ -11413,7 +11540,7 @@ function qFactory(nextTick, exceptionHandler) {
11413
11540
  /**
11414
11541
  * @ngdoc method
11415
11542
  * @name $q#reject
11416
- * @function
11543
+ * @kind function
11417
11544
  *
11418
11545
  * @description
11419
11546
  * Creates a promise that is resolved as rejected with the specified `reason`. This api should be
@@ -11473,7 +11600,7 @@ function qFactory(nextTick, exceptionHandler) {
11473
11600
  /**
11474
11601
  * @ngdoc method
11475
11602
  * @name $q#when
11476
- * @function
11603
+ * @kind function
11477
11604
  *
11478
11605
  * @description
11479
11606
  * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.
@@ -11545,7 +11672,7 @@ function qFactory(nextTick, exceptionHandler) {
11545
11672
  /**
11546
11673
  * @ngdoc method
11547
11674
  * @name $q#all
11548
- * @function
11675
+ * @kind function
11549
11676
  *
11550
11677
  * @description
11551
11678
  * Combines multiple promises into a single promise that is resolved when all of the input
@@ -11636,7 +11763,7 @@ function $$RAFProvider(){ //rAF
11636
11763
  *
11637
11764
  * Loop operations are optimized by using while(count--) { ... }
11638
11765
  * - this means that in order to keep the same order of execution as addition we have to add
11639
- * items to the array at the beginning (shift) instead of at the end (push)
11766
+ * items to the array at the beginning (unshift) instead of at the end (push)
11640
11767
  *
11641
11768
  * Child scopes are created and removed often
11642
11769
  * - Using an array would be slow since inserts in middle are expensive so we use linked list
@@ -11770,7 +11897,7 @@ function $RootScopeProvider(){
11770
11897
  /**
11771
11898
  * @ngdoc method
11772
11899
  * @name $rootScope.Scope#$new
11773
- * @function
11900
+ * @kind function
11774
11901
  *
11775
11902
  * @description
11776
11903
  * Creates a new child {@link ng.$rootScope.Scope scope}.
@@ -11802,18 +11929,23 @@ function $RootScopeProvider(){
11802
11929
  child.$$asyncQueue = this.$$asyncQueue;
11803
11930
  child.$$postDigestQueue = this.$$postDigestQueue;
11804
11931
  } else {
11805
- ChildScope = function() {}; // should be anonymous; This is so that when the minifier munges
11806
- // the name it does not become random set of chars. This will then show up as class
11807
- // name in the web inspector.
11808
- ChildScope.prototype = this;
11809
- child = new ChildScope();
11810
- child.$id = nextUid();
11932
+ // Only create a child scope class if somebody asks for one,
11933
+ // but cache it to allow the VM to optimize lookups.
11934
+ if (!this.$$childScopeClass) {
11935
+ this.$$childScopeClass = function() {
11936
+ this.$$watchers = this.$$nextSibling =
11937
+ this.$$childHead = this.$$childTail = null;
11938
+ this.$$listeners = {};
11939
+ this.$$listenerCount = {};
11940
+ this.$id = nextUid();
11941
+ this.$$childScopeClass = null;
11942
+ };
11943
+ this.$$childScopeClass.prototype = this;
11944
+ }
11945
+ child = new this.$$childScopeClass();
11811
11946
  }
11812
11947
  child['this'] = child;
11813
- child.$$listeners = {};
11814
- child.$$listenerCount = {};
11815
11948
  child.$parent = this;
11816
- child.$$watchers = child.$$nextSibling = child.$$childHead = child.$$childTail = null;
11817
11949
  child.$$prevSibling = this.$$childTail;
11818
11950
  if (this.$$childHead) {
11819
11951
  this.$$childTail.$$nextSibling = child;
@@ -11827,7 +11959,7 @@ function $RootScopeProvider(){
11827
11959
  /**
11828
11960
  * @ngdoc method
11829
11961
  * @name $rootScope.Scope#$watch
11830
- * @function
11962
+ * @kind function
11831
11963
  *
11832
11964
  * @description
11833
11965
  * Registers a `listener` callback to be executed whenever the `watchExpression` changes.
@@ -11839,10 +11971,14 @@ function $RootScopeProvider(){
11839
11971
  * {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)
11840
11972
  * - The `listener` is called only when the value from the current `watchExpression` and the
11841
11973
  * previous call to `watchExpression` are not equal (with the exception of the initial run,
11842
- * see below). The inequality is determined according to
11843
- * {@link angular.equals} function. To save the value of the object for later comparison,
11844
- * the {@link angular.copy} function is used. It also means that watching complex options
11845
- * will have adverse memory and performance implications.
11974
+ * see below). Inequality is determined according to reference inequality,
11975
+ * [strict comparison](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators)
11976
+ * via the `!==` Javascript operator, unless `objectEquality == true`
11977
+ * (see next point)
11978
+ * - When `objectEquality == true`, inequality of the `watchExpression` is determined
11979
+ * according to the {@link angular.equals} function. To save the value of the object for
11980
+ * later comparison, the {@link angular.copy} function is used. This therefore means that
11981
+ * watching complex objects will have adverse memory and performance implications.
11846
11982
  * - The watch `listener` may change the model, which may trigger other `listener`s to fire.
11847
11983
  * This is achieved by rerunning the watchers until no changes are detected. The rerun
11848
11984
  * iteration limit is 10 to prevent an infinite loop deadlock.
@@ -11877,13 +12013,17 @@ function $RootScopeProvider(){
11877
12013
  expect(scope.counter).toEqual(0);
11878
12014
 
11879
12015
  scope.$digest();
11880
- // no variable change
11881
- expect(scope.counter).toEqual(0);
12016
+ // the listener is always called during the first $digest loop after it was registered
12017
+ expect(scope.counter).toEqual(1);
11882
12018
 
11883
- scope.name = 'adam';
11884
12019
  scope.$digest();
12020
+ // but now it will not be called unless the value changes
11885
12021
  expect(scope.counter).toEqual(1);
11886
12022
 
12023
+ scope.name = 'adam';
12024
+ scope.$digest();
12025
+ expect(scope.counter).toEqual(2);
12026
+
11887
12027
 
11888
12028
 
11889
12029
  // Using a listener function
@@ -11969,7 +12109,7 @@ function $RootScopeProvider(){
11969
12109
  // the while loop reads in reverse order.
11970
12110
  array.unshift(watcher);
11971
12111
 
11972
- return function() {
12112
+ return function deregisterWatch() {
11973
12113
  arrayRemove(array, watcher);
11974
12114
  lastDirtyWatch = null;
11975
12115
  };
@@ -11979,7 +12119,7 @@ function $RootScopeProvider(){
11979
12119
  /**
11980
12120
  * @ngdoc method
11981
12121
  * @name $rootScope.Scope#$watchCollection
11982
- * @function
12122
+ * @kind function
11983
12123
  *
11984
12124
  * @description
11985
12125
  * Shallow watches the properties of an object and fires whenever any of the properties change
@@ -12155,7 +12295,7 @@ function $RootScopeProvider(){
12155
12295
  /**
12156
12296
  * @ngdoc method
12157
12297
  * @name $rootScope.Scope#$digest
12158
- * @function
12298
+ * @kind function
12159
12299
  *
12160
12300
  * @description
12161
12301
  * Processes all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and
@@ -12190,12 +12330,16 @@ function $RootScopeProvider(){
12190
12330
  expect(scope.counter).toEqual(0);
12191
12331
 
12192
12332
  scope.$digest();
12193
- // no variable change
12194
- expect(scope.counter).toEqual(0);
12333
+ // the listener is always called during the first $digest loop after it was registered
12334
+ expect(scope.counter).toEqual(1);
12195
12335
 
12196
- scope.name = 'adam';
12197
12336
  scope.$digest();
12337
+ // but now it will not be called unless the value changes
12198
12338
  expect(scope.counter).toEqual(1);
12339
+
12340
+ scope.name = 'adam';
12341
+ scope.$digest();
12342
+ expect(scope.counter).toEqual(2);
12199
12343
  * ```
12200
12344
  *
12201
12345
  */
@@ -12247,7 +12391,7 @@ function $RootScopeProvider(){
12247
12391
  && isNaN(value) && isNaN(last)))) {
12248
12392
  dirty = true;
12249
12393
  lastDirtyWatch = watch;
12250
- watch.last = watch.eq ? copy(value) : value;
12394
+ watch.last = watch.eq ? copy(value, null) : value;
12251
12395
  watch.fn(value, ((last === initWatchVal) ? value : last), current);
12252
12396
  if (ttl < 5) {
12253
12397
  logIdx = 4 - ttl;
@@ -12322,7 +12466,7 @@ function $RootScopeProvider(){
12322
12466
  /**
12323
12467
  * @ngdoc method
12324
12468
  * @name $rootScope.Scope#$destroy
12325
- * @function
12469
+ * @kind function
12326
12470
  *
12327
12471
  * @description
12328
12472
  * Removes the current scope (and all of its children) from the parent scope. Removal implies
@@ -12383,7 +12527,7 @@ function $RootScopeProvider(){
12383
12527
  /**
12384
12528
  * @ngdoc method
12385
12529
  * @name $rootScope.Scope#$eval
12386
- * @function
12530
+ * @kind function
12387
12531
  *
12388
12532
  * @description
12389
12533
  * Executes the `expression` on the current scope and returns the result. Any exceptions in
@@ -12415,7 +12559,7 @@ function $RootScopeProvider(){
12415
12559
  /**
12416
12560
  * @ngdoc method
12417
12561
  * @name $rootScope.Scope#$evalAsync
12418
- * @function
12562
+ * @kind function
12419
12563
  *
12420
12564
  * @description
12421
12565
  * Executes the expression on the current scope at a later point in time.
@@ -12462,7 +12606,7 @@ function $RootScopeProvider(){
12462
12606
  /**
12463
12607
  * @ngdoc method
12464
12608
  * @name $rootScope.Scope#$apply
12465
- * @function
12609
+ * @kind function
12466
12610
  *
12467
12611
  * @description
12468
12612
  * `$apply()` is used to execute an expression in angular from outside of the angular
@@ -12524,7 +12668,7 @@ function $RootScopeProvider(){
12524
12668
  /**
12525
12669
  * @ngdoc method
12526
12670
  * @name $rootScope.Scope#$on
12527
- * @function
12671
+ * @kind function
12528
12672
  *
12529
12673
  * @description
12530
12674
  * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for
@@ -12573,7 +12717,7 @@ function $RootScopeProvider(){
12573
12717
  /**
12574
12718
  * @ngdoc method
12575
12719
  * @name $rootScope.Scope#$emit
12576
- * @function
12720
+ * @kind function
12577
12721
  *
12578
12722
  * @description
12579
12723
  * Dispatches an event `name` upwards through the scope hierarchy notifying the
@@ -12641,7 +12785,7 @@ function $RootScopeProvider(){
12641
12785
  /**
12642
12786
  * @ngdoc method
12643
12787
  * @name $rootScope.Scope#$broadcast
12644
- * @function
12788
+ * @kind function
12645
12789
  *
12646
12790
  * @description
12647
12791
  * Dispatches an event `name` downwards to all child scopes (and their children) notifying the
@@ -12889,7 +13033,7 @@ function adjustMatchers(matchers) {
12889
13033
  /**
12890
13034
  * @ngdoc service
12891
13035
  * @name $sceDelegate
12892
- * @function
13036
+ * @kind function
12893
13037
  *
12894
13038
  * @description
12895
13039
  *
@@ -12961,7 +13105,7 @@ function $SceDelegateProvider() {
12961
13105
  /**
12962
13106
  * @ngdoc method
12963
13107
  * @name $sceDelegateProvider#resourceUrlWhitelist
12964
- * @function
13108
+ * @kind function
12965
13109
  *
12966
13110
  * @param {Array=} whitelist When provided, replaces the resourceUrlWhitelist with the value
12967
13111
  * provided. This must be an array or null. A snapshot of this array is used so further
@@ -12990,7 +13134,7 @@ function $SceDelegateProvider() {
12990
13134
  /**
12991
13135
  * @ngdoc method
12992
13136
  * @name $sceDelegateProvider#resourceUrlBlacklist
12993
- * @function
13137
+ * @kind function
12994
13138
  *
12995
13139
  * @param {Array=} blacklist When provided, replaces the resourceUrlBlacklist with the value
12996
13140
  * provided. This must be an array or null. A snapshot of this array is used so further
@@ -13217,7 +13361,7 @@ function $SceDelegateProvider() {
13217
13361
  /**
13218
13362
  * @ngdoc service
13219
13363
  * @name $sce
13220
- * @function
13364
+ * @kind function
13221
13365
  *
13222
13366
  * @description
13223
13367
  *
@@ -13343,7 +13487,7 @@ function $SceDelegateProvider() {
13343
13487
  *
13344
13488
  * | Context | Notes |
13345
13489
  * |---------------------|----------------|
13346
- * | `$sce.HTML` | For HTML that's safe to source into the application. The {@link ng.directive:ngBindHtml ngBindHtml} directive uses this context for bindings. |
13490
+ * | `$sce.HTML` | For HTML that's safe to source into the application. The {@link ng.directive:ngBindHtml ngBindHtml} directive uses this context for bindings. If an unsafe value is encountered and the {@link ngSanitize $sanitize} module is present this will sanitize the value instead of throwing an error. |
13347
13491
  * | `$sce.CSS` | For CSS that's safe to source into the application. Currently unused. Feel free to use it in your own directives. |
13348
13492
  * | `$sce.URL` | For URLs that are safe to follow as links. Currently unused (`<a href=` and `<img src=` sanitize their urls and don't constitute an SCE context. |
13349
13493
  * | `$sce.RESOURCE_URL` | For URLs that are not only safe to follow as links, but whose contents are also safe to include in your application. Examples include `ng-include`, `src` / `ngSrc` bindings for tags other than `IMG` (e.g. `IFRAME`, `OBJECT`, etc.) <br><br>Note that `$sce.RESOURCE_URL` makes a stronger statement about the URL than `$sce.URL` does and therefore contexts requiring values trusted for `$sce.RESOURCE_URL` can be used anywhere that values trusted for `$sce.URL` are required. |
@@ -13367,7 +13511,7 @@ function $SceDelegateProvider() {
13367
13511
  * - `**`: matches zero or more occurrences of *any* character. As such, it's not
13368
13512
  * not appropriate to use in for a scheme, domain, etc. as it would match too much. (e.g.
13369
13513
  * http://**.example.com/ would match http://evil.com/?ignore=.example.com/ and that might
13370
- * not have been the intention.) It's usage at the very end of the path is ok. (e.g.
13514
+ * not have been the intention.) Its usage at the very end of the path is ok. (e.g.
13371
13515
  * http://foo.example.com/templates/**).
13372
13516
  * - **RegExp** (*see caveat below*)
13373
13517
  * - *Caveat*: While regular expressions are powerful and offer great flexibility, their syntax
@@ -13488,7 +13632,7 @@ function $SceProvider() {
13488
13632
  /**
13489
13633
  * @ngdoc method
13490
13634
  * @name $sceProvider#enabled
13491
- * @function
13635
+ * @kind function
13492
13636
  *
13493
13637
  * @param {boolean=} value If provided, then enables/disables SCE.
13494
13638
  * @return {boolean} true if SCE is enabled, false otherwise.
@@ -13561,12 +13705,12 @@ function $SceProvider() {
13561
13705
  'document. See http://docs.angularjs.org/api/ng.$sce for more information.');
13562
13706
  }
13563
13707
 
13564
- var sce = copy(SCE_CONTEXTS);
13708
+ var sce = shallowCopy(SCE_CONTEXTS);
13565
13709
 
13566
13710
  /**
13567
13711
  * @ngdoc method
13568
13712
  * @name $sce#isEnabled
13569
- * @function
13713
+ * @kind function
13570
13714
  *
13571
13715
  * @return {Boolean} true if SCE is enabled, false otherwise. If you want to set the value, you
13572
13716
  * have to do it at module config time on {@link ng.$sceProvider $sceProvider}.
@@ -14101,7 +14245,7 @@ var originUrl = urlResolve(window.location.href, true);
14101
14245
  * https://github.com/angular/angular.js/pull/2902
14102
14246
  * http://james.padolsey.com/javascript/parsing-urls-with-the-dom/
14103
14247
  *
14104
- * @function
14248
+ * @kind function
14105
14249
  * @param {string} url The URL to be parsed.
14106
14250
  * @description Normalizes and parses a URL.
14107
14251
  * @returns {object} Returns the normalized URL as a dictionary.
@@ -14265,7 +14409,7 @@ function $WindowProvider(){
14265
14409
  /**
14266
14410
  * @ngdoc service
14267
14411
  * @name $filter
14268
- * @function
14412
+ * @kind function
14269
14413
  * @description
14270
14414
  * Filters are used for formatting data displayed to the user.
14271
14415
  *
@@ -14275,7 +14419,24 @@ function $WindowProvider(){
14275
14419
  *
14276
14420
  * @param {String} name Name of the filter function to retrieve
14277
14421
  * @return {Function} the filter function
14278
- */
14422
+ * @example
14423
+ <example name="$filter" module="filterExample">
14424
+ <file name="index.html">
14425
+ <div ng-controller="MainCtrl">
14426
+ <h3>{{ originalText }}</h3>
14427
+ <h3>{{ filteredText }}</h3>
14428
+ </div>
14429
+ </file>
14430
+
14431
+ <file name="script.js">
14432
+ angular.module('filterExample', [])
14433
+ .controller('MainCtrl', function($scope, $filter) {
14434
+ $scope.originalText = 'hello';
14435
+ $scope.filteredText = $filter('uppercase')($scope.originalText);
14436
+ });
14437
+ </file>
14438
+ </example>
14439
+ */
14279
14440
  $FilterProvider.$inject = ['$provide'];
14280
14441
  function $FilterProvider($provide) {
14281
14442
  var suffix = 'Filter';
@@ -14335,7 +14496,7 @@ function $FilterProvider($provide) {
14335
14496
  /**
14336
14497
  * @ngdoc filter
14337
14498
  * @name filter
14338
- * @function
14499
+ * @kind function
14339
14500
  *
14340
14501
  * @description
14341
14502
  * Selects a subset of items from `array` and returns it as a new array.
@@ -14367,15 +14528,15 @@ function $FilterProvider($provide) {
14367
14528
  *
14368
14529
  * Can be one of:
14369
14530
  *
14370
- * - `function(actual, expected)`:
14371
- * The function will be given the object value and the predicate value to compare and
14372
- * should return true if the item should be included in filtered result.
14531
+ * - `function(actual, expected)`:
14532
+ * The function will be given the object value and the predicate value to compare and
14533
+ * should return true if the item should be included in filtered result.
14373
14534
  *
14374
- * - `true`: A shorthand for `function(actual, expected) { return angular.equals(expected, actual)}`.
14375
- * this is essentially strict comparison of expected and actual.
14535
+ * - `true`: A shorthand for `function(actual, expected) { return angular.equals(expected, actual)}`.
14536
+ * this is essentially strict comparison of expected and actual.
14376
14537
  *
14377
- * - `false|undefined`: A short hand for a function which will look for a substring match in case
14378
- * insensitive way.
14538
+ * - `false|undefined`: A short hand for a function which will look for a substring match in case
14539
+ * insensitive way.
14379
14540
  *
14380
14541
  * @example
14381
14542
  <example>
@@ -14554,7 +14715,7 @@ function filterFilter() {
14554
14715
  /**
14555
14716
  * @ngdoc filter
14556
14717
  * @name currency
14557
- * @function
14718
+ * @kind function
14558
14719
  *
14559
14720
  * @description
14560
14721
  * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default
@@ -14611,7 +14772,7 @@ function currencyFilter($locale) {
14611
14772
  /**
14612
14773
  * @ngdoc filter
14613
14774
  * @name number
14614
- * @function
14775
+ * @kind function
14615
14776
  *
14616
14777
  * @description
14617
14778
  * Formats a number as text.
@@ -14696,8 +14857,8 @@ function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {
14696
14857
  fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);
14697
14858
  }
14698
14859
 
14699
- var pow = Math.pow(10, fractionSize);
14700
- number = Math.round(number * pow) / pow;
14860
+ var pow = Math.pow(10, fractionSize + 1);
14861
+ number = Math.floor(number * pow + 5) / pow;
14701
14862
  var fraction = ('' + number).split(DECIMAL_SEP);
14702
14863
  var whole = fraction[0];
14703
14864
  fraction = fraction[1] || '';
@@ -14823,7 +14984,7 @@ var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+
14823
14984
  /**
14824
14985
  * @ngdoc filter
14825
14986
  * @name date
14826
- * @function
14987
+ * @kind function
14827
14988
  *
14828
14989
  * @description
14829
14990
  * Formats `date` to a string based on the requested `format`.
@@ -14980,7 +15141,7 @@ function dateFilter($locale) {
14980
15141
  /**
14981
15142
  * @ngdoc filter
14982
15143
  * @name json
14983
- * @function
15144
+ * @kind function
14984
15145
  *
14985
15146
  * @description
14986
15147
  * Allows you to convert a JavaScript object into JSON string.
@@ -15015,7 +15176,7 @@ function jsonFilter() {
15015
15176
  /**
15016
15177
  * @ngdoc filter
15017
15178
  * @name lowercase
15018
- * @function
15179
+ * @kind function
15019
15180
  * @description
15020
15181
  * Converts string to lowercase.
15021
15182
  * @see angular.lowercase
@@ -15026,7 +15187,7 @@ var lowercaseFilter = valueFn(lowercase);
15026
15187
  /**
15027
15188
  * @ngdoc filter
15028
15189
  * @name uppercase
15029
- * @function
15190
+ * @kind function
15030
15191
  * @description
15031
15192
  * Converts string to uppercase.
15032
15193
  * @see angular.uppercase
@@ -15036,7 +15197,7 @@ var uppercaseFilter = valueFn(uppercase);
15036
15197
  /**
15037
15198
  * @ngdoc filter
15038
15199
  * @name limitTo
15039
- * @function
15200
+ * @kind function
15040
15201
  *
15041
15202
  * @description
15042
15203
  * Creates a new array or string containing only a specified number of elements. The elements
@@ -15106,7 +15267,11 @@ function limitToFilter(){
15106
15267
  return function(input, limit) {
15107
15268
  if (!isArray(input) && !isString(input)) return input;
15108
15269
 
15109
- limit = int(limit);
15270
+ if (Math.abs(Number(limit)) === Infinity) {
15271
+ limit = Number(limit);
15272
+ } else {
15273
+ limit = int(limit);
15274
+ }
15110
15275
 
15111
15276
  if (isString(input)) {
15112
15277
  //NaN check on limit
@@ -15145,10 +15310,12 @@ function limitToFilter(){
15145
15310
  /**
15146
15311
  * @ngdoc filter
15147
15312
  * @name orderBy
15148
- * @function
15313
+ * @kind function
15149
15314
  *
15150
15315
  * @description
15151
- * Orders a specified `array` by the `expression` predicate.
15316
+ * Orders a specified `array` by the `expression` predicate. It is ordered alphabetically
15317
+ * for strings and numerically for numbers. Note: if you notice numbers are not being sorted
15318
+ * correctly, make sure they are actually being saved as numbers and not strings.
15152
15319
  *
15153
15320
  * @param {Array} array The array to sort.
15154
15321
  * @param {function(*)|string|Array.<(function(*)|string)>} expression A predicate to be
@@ -15201,6 +15368,51 @@ function limitToFilter(){
15201
15368
  </div>
15202
15369
  </file>
15203
15370
  </example>
15371
+ *
15372
+ * It's also possible to call the orderBy filter manually, by injecting `$filter`, retrieving the
15373
+ * filter routine with `$filter('orderBy')`, and calling the returned filter routine with the
15374
+ * desired parameters.
15375
+ *
15376
+ * Example:
15377
+ *
15378
+ * @example
15379
+ <example>
15380
+ <file name="index.html">
15381
+ <div ng-controller="Ctrl">
15382
+ <table class="friend">
15383
+ <tr>
15384
+ <th><a href="" ng-click="reverse=false;order('name', false)">Name</a>
15385
+ (<a href="" ng-click="order('-name',false)">^</a>)</th>
15386
+ <th><a href="" ng-click="reverse=!reverse;order('phone', reverse)">Phone Number</a></th>
15387
+ <th><a href="" ng-click="reverse=!reverse;order('age',reverse)">Age</a></th>
15388
+ </tr>
15389
+ <tr ng-repeat="friend in friends">
15390
+ <td>{{friend.name}}</td>
15391
+ <td>{{friend.phone}}</td>
15392
+ <td>{{friend.age}}</td>
15393
+ </tr>
15394
+ </table>
15395
+ </div>
15396
+ </file>
15397
+
15398
+ <file name="script.js">
15399
+ function Ctrl($scope, $filter) {
15400
+ var orderBy = $filter('orderBy');
15401
+ $scope.friends = [
15402
+ { name: 'John', phone: '555-1212', age: 10 },
15403
+ { name: 'Mary', phone: '555-9876', age: 19 },
15404
+ { name: 'Mike', phone: '555-4321', age: 21 },
15405
+ { name: 'Adam', phone: '555-5678', age: 35 },
15406
+ { name: 'Julie', phone: '555-8765', age: 29 }
15407
+ ];
15408
+
15409
+ $scope.order = function(predicate, reverse) {
15410
+ $scope.friends = orderBy($scope.friends, predicate, reverse);
15411
+ };
15412
+ $scope.order('-age',false);
15413
+ }
15414
+ </file>
15415
+ </example>
15204
15416
  */
15205
15417
  orderByFilter.$inject = ['$parse'];
15206
15418
  function orderByFilter($parse){
@@ -15752,7 +15964,7 @@ var nullFormCtrl = {
15752
15964
  * - `url`
15753
15965
  *
15754
15966
  * @description
15755
- * `FormController` keeps track of all its controls and nested forms as well as state of them,
15967
+ * `FormController` keeps track of all its controls and nested forms as well as the state of them,
15756
15968
  * such as being valid/invalid or dirty/pristine.
15757
15969
  *
15758
15970
  * Each {@link ng.directive:form form} directive creates an instance
@@ -16594,6 +16806,8 @@ function addNativeHtml5Validators(ctrl, validatorName, element) {
16594
16806
 
16595
16807
  function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
16596
16808
  var validity = element.prop('validity');
16809
+ var placeholder = element[0].placeholder, noevent = {};
16810
+
16597
16811
  // In composition mode, users are still inputing intermediate text buffer,
16598
16812
  // hold the listener until composition is done.
16599
16813
  // More about composition events: https://developer.mozilla.org/en-US/docs/Web/API/CompositionEvent
@@ -16610,10 +16824,19 @@ function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
16610
16824
  });
16611
16825
  }
16612
16826
 
16613
- var listener = function() {
16827
+ var listener = function(ev) {
16614
16828
  if (composing) return;
16615
16829
  var value = element.val();
16616
16830
 
16831
+ // IE (11 and under) seem to emit an 'input' event if the placeholder value changes.
16832
+ // We don't want to dirty the value when this happens, so we abort here. Unfortunately,
16833
+ // IE also sends input events for other non-input-related things, (such as focusing on a
16834
+ // form control), so this change is not entirely enough to solve this.
16835
+ if (msie && (ev || noevent).type === 'input' && element[0].placeholder !== placeholder) {
16836
+ placeholder = element[0].placeholder;
16837
+ return;
16838
+ }
16839
+
16617
16840
  // By default we will trim the value
16618
16841
  // If the attribute ng-trim exists we will avoid trimming
16619
16842
  // e.g. <input ng-model="foo" ng-trim="false">
@@ -16877,6 +17100,7 @@ function checkboxInputType(scope, element, attr, ctrl) {
16877
17100
  * patterns defined as scope expressions.
16878
17101
  * @param {string=} ngChange Angular expression to be executed when input changes due to user
16879
17102
  * interaction with the input element.
17103
+ * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input.
16880
17104
  */
16881
17105
 
16882
17106
 
@@ -17026,14 +17250,14 @@ var VALID_CLASS = 'ng-valid',
17026
17250
  * @property {Array.<Function>} $formatters Array of functions to execute, as a pipeline, whenever
17027
17251
  the model value changes. Each function is called, in turn, passing the value through to the
17028
17252
  next. Used to format / convert values for display in the control and validation.
17029
- * ```js
17030
- * function formatter(value) {
17031
- * if (value) {
17032
- * return value.toUpperCase();
17033
- * }
17034
- * }
17035
- * ngModel.$formatters.push(formatter);
17036
- * ```
17253
+ * ```js
17254
+ * function formatter(value) {
17255
+ * if (value) {
17256
+ * return value.toUpperCase();
17257
+ * }
17258
+ * }
17259
+ * ngModel.$formatters.push(formatter);
17260
+ * ```
17037
17261
  *
17038
17262
  * @property {Array.<Function>} $viewChangeListeners Array of functions to execute whenever the
17039
17263
  * view value has changed. It is called with no arguments, and its return value is ignored.
@@ -17062,7 +17286,12 @@ var VALID_CLASS = 'ng-valid',
17062
17286
  * Note that `contenteditable` is an HTML5 attribute, which tells the browser to let the element
17063
17287
  * contents be edited in place by the user. This will not work on older browsers.
17064
17288
  *
17065
- * <example name="NgModelController" module="customControl">
17289
+ * We are using the {@link ng.service:$sce $sce} service here and include the {@link ngSanitize $sanitize}
17290
+ * module to automatically remove "bad" content like inline event listener (e.g. `<span onclick="...">`).
17291
+ * However, as we are using `$sce` the model can still decide to to provide unsafe content if it marks
17292
+ * that content using the `$sce` service.
17293
+ *
17294
+ * <example name="NgModelController" module="customControl" deps="angular-sanitize.js">
17066
17295
  <file name="style.css">
17067
17296
  [contenteditable] {
17068
17297
  border: 1px solid black;
@@ -17076,8 +17305,8 @@ var VALID_CLASS = 'ng-valid',
17076
17305
 
17077
17306
  </file>
17078
17307
  <file name="script.js">
17079
- angular.module('customControl', []).
17080
- directive('contenteditable', function() {
17308
+ angular.module('customControl', ['ngSanitize']).
17309
+ directive('contenteditable', ['$sce', function($sce) {
17081
17310
  return {
17082
17311
  restrict: 'A', // only activate on element attribute
17083
17312
  require: '?ngModel', // get a hold of NgModelController
@@ -17086,7 +17315,7 @@ var VALID_CLASS = 'ng-valid',
17086
17315
 
17087
17316
  // Specify how UI should be updated
17088
17317
  ngModel.$render = function() {
17089
- element.html(ngModel.$viewValue || '');
17318
+ element.html($sce.getTrustedHtml(ngModel.$viewValue || ''));
17090
17319
  };
17091
17320
 
17092
17321
  // Listen for change events to enable binding
@@ -17107,7 +17336,7 @@ var VALID_CLASS = 'ng-valid',
17107
17336
  }
17108
17337
  }
17109
17338
  };
17110
- });
17339
+ }]);
17111
17340
  </file>
17112
17341
  <file name="index.html">
17113
17342
  <form name="myForm">
@@ -17781,14 +18010,19 @@ var ngValueDirective = function() {
17781
18010
  </file>
17782
18011
  </example>
17783
18012
  */
17784
- var ngBindDirective = ngDirective(function(scope, element, attr) {
17785
- element.addClass('ng-binding').data('$binding', attr.ngBind);
17786
- scope.$watch(attr.ngBind, function ngBindWatchAction(value) {
17787
- // We are purposefully using == here rather than === because we want to
17788
- // catch when value is "null or undefined"
17789
- // jshint -W041
17790
- element.text(value == undefined ? '' : value);
17791
- });
18013
+ var ngBindDirective = ngDirective({
18014
+ compile: function(templateElement) {
18015
+ templateElement.addClass('ng-binding');
18016
+ return function (scope, element, attr) {
18017
+ element.data('$binding', attr.ngBind);
18018
+ scope.$watch(attr.ngBind, function ngBindWatchAction(value) {
18019
+ // We are purposefully using == here rather than === because we want to
18020
+ // catch when value is "null or undefined"
18021
+ // jshint -W041
18022
+ element.text(value == undefined ? '' : value);
18023
+ });
18024
+ };
18025
+ }
17792
18026
  });
17793
18027
 
17794
18028
 
@@ -17932,7 +18166,7 @@ function classDirective(name, selector) {
17932
18166
  scope.$watch('$index', function($index, old$index) {
17933
18167
  // jshint bitwise: false
17934
18168
  var mod = $index & 1;
17935
- if (mod !== old$index & 1) {
18169
+ if (mod !== (old$index & 1)) {
17936
18170
  var classes = arrayClasses(scope.$eval(attr[name]));
17937
18171
  mod === selector ?
17938
18172
  addClasses(classes) :
@@ -17991,7 +18225,7 @@ function classDirective(name, selector) {
17991
18225
  updateClasses(oldClasses, newClasses);
17992
18226
  }
17993
18227
  }
17994
- oldVal = copy(newVal);
18228
+ oldVal = shallowCopy(newVal);
17995
18229
  }
17996
18230
  }
17997
18231
  };
@@ -18019,7 +18253,7 @@ function classDirective(name, selector) {
18019
18253
  var classes = [], i = 0;
18020
18254
  forEach(classVal, function(v, k) {
18021
18255
  if (v) {
18022
- classes.push(k);
18256
+ classes = classes.concat(k.split(' '));
18023
18257
  }
18024
18258
  });
18025
18259
  return classes;
@@ -18344,7 +18578,7 @@ var ngCloakDirective = ngDirective({
18344
18578
  *
18345
18579
  * MVC components in angular:
18346
18580
  *
18347
- * * Model — The Model is scope properties; scopes are attached to the DOM where scope properties
18581
+ * * Model — Models are the properties of a scope; scopes are attached to the DOM where scope properties
18348
18582
  * are accessed through bindings.
18349
18583
  * * View — The template (HTML with data bindings) that is rendered into the View.
18350
18584
  * * Controller — The `ngController` directive specifies a Controller class; the class contains business
@@ -18365,165 +18599,186 @@ var ngCloakDirective = ngDirective({
18365
18599
  * @example
18366
18600
  * Here is a simple form for editing user contact information. Adding, removing, clearing, and
18367
18601
  * greeting are methods declared on the controller (see source tab). These methods can
18368
- * easily be called from the angular markup. Notice that the scope becomes the `this` for the
18369
- * controller's instance. This allows for easy access to the view data from the controller. Also
18370
- * notice that any changes to the data are automatically reflected in the View without the need
18371
- * for a manual update. The example is shown in two different declaration styles you may use
18372
- * according to preference.
18373
- <example>
18374
- <file name="index.html">
18375
- <script>
18376
- function SettingsController1() {
18377
- this.name = "John Smith";
18378
- this.contacts = [
18379
- {type: 'phone', value: '408 555 1212'},
18380
- {type: 'email', value: 'john.smith@example.org'} ];
18381
- };
18382
-
18383
- SettingsController1.prototype.greet = function() {
18384
- alert(this.name);
18385
- };
18386
-
18387
- SettingsController1.prototype.addContact = function() {
18388
- this.contacts.push({type: 'email', value: 'yourname@example.org'});
18389
- };
18390
-
18391
- SettingsController1.prototype.removeContact = function(contactToRemove) {
18392
- var index = this.contacts.indexOf(contactToRemove);
18393
- this.contacts.splice(index, 1);
18394
- };
18395
-
18396
- SettingsController1.prototype.clearContact = function(contact) {
18397
- contact.type = 'phone';
18398
- contact.value = '';
18399
- };
18400
- </script>
18401
- <div id="ctrl-as-exmpl" ng-controller="SettingsController1 as settings">
18402
- Name: <input type="text" ng-model="settings.name"/>
18403
- [ <a href="" ng-click="settings.greet()">greet</a> ]<br/>
18404
- Contact:
18405
- <ul>
18406
- <li ng-repeat="contact in settings.contacts">
18407
- <select ng-model="contact.type">
18408
- <option>phone</option>
18409
- <option>email</option>
18410
- </select>
18411
- <input type="text" ng-model="contact.value"/>
18412
- [ <a href="" ng-click="settings.clearContact(contact)">clear</a>
18413
- | <a href="" ng-click="settings.removeContact(contact)">X</a> ]
18414
- </li>
18415
- <li>[ <a href="" ng-click="settings.addContact()">add</a> ]</li>
18416
- </ul>
18417
- </div>
18418
- </file>
18419
- <file name="protractor.js" type="protractor">
18420
- it('should check controller as', function() {
18421
- var container = element(by.id('ctrl-as-exmpl'));
18422
-
18423
- expect(container.findElement(by.model('settings.name'))
18424
- .getAttribute('value')).toBe('John Smith');
18425
-
18426
- var firstRepeat =
18427
- container.findElement(by.repeater('contact in settings.contacts').row(0));
18428
- var secondRepeat =
18429
- container.findElement(by.repeater('contact in settings.contacts').row(1));
18430
-
18431
- expect(firstRepeat.findElement(by.model('contact.value')).getAttribute('value'))
18432
- .toBe('408 555 1212');
18433
- expect(secondRepeat.findElement(by.model('contact.value')).getAttribute('value'))
18434
- .toBe('john.smith@example.org');
18435
-
18436
- firstRepeat.findElement(by.linkText('clear')).click();
18437
-
18438
- expect(firstRepeat.findElement(by.model('contact.value')).getAttribute('value'))
18439
- .toBe('');
18440
-
18441
- container.findElement(by.linkText('add')).click();
18442
-
18443
- expect(container.findElement(by.repeater('contact in settings.contacts').row(2))
18444
- .findElement(by.model('contact.value'))
18445
- .getAttribute('value'))
18446
- .toBe('yourname@example.org');
18447
- });
18448
- </file>
18449
- </example>
18450
- <example>
18451
- <file name="index.html">
18452
- <script>
18453
- function SettingsController2($scope) {
18454
- $scope.name = "John Smith";
18455
- $scope.contacts = [
18456
- {type:'phone', value:'408 555 1212'},
18457
- {type:'email', value:'john.smith@example.org'} ];
18458
-
18459
- $scope.greet = function() {
18460
- alert(this.name);
18461
- };
18462
-
18463
- $scope.addContact = function() {
18464
- this.contacts.push({type:'email', value:'yourname@example.org'});
18465
- };
18466
-
18467
- $scope.removeContact = function(contactToRemove) {
18468
- var index = this.contacts.indexOf(contactToRemove);
18469
- this.contacts.splice(index, 1);
18470
- };
18471
-
18472
- $scope.clearContact = function(contact) {
18473
- contact.type = 'phone';
18474
- contact.value = '';
18475
- };
18476
- }
18477
- </script>
18478
- <div id="ctrl-exmpl" ng-controller="SettingsController2">
18479
- Name: <input type="text" ng-model="name"/>
18480
- [ <a href="" ng-click="greet()">greet</a> ]<br/>
18481
- Contact:
18482
- <ul>
18483
- <li ng-repeat="contact in contacts">
18484
- <select ng-model="contact.type">
18485
- <option>phone</option>
18486
- <option>email</option>
18487
- </select>
18488
- <input type="text" ng-model="contact.value"/>
18489
- [ <a href="" ng-click="clearContact(contact)">clear</a>
18490
- | <a href="" ng-click="removeContact(contact)">X</a> ]
18491
- </li>
18492
- <li>[ <a href="" ng-click="addContact()">add</a> ]</li>
18493
- </ul>
18494
- </div>
18495
- </file>
18496
- <file name="protractor.js" type="protractor">
18497
- it('should check controller', function() {
18498
- var container = element(by.id('ctrl-exmpl'));
18499
-
18500
- expect(container.findElement(by.model('name'))
18501
- .getAttribute('value')).toBe('John Smith');
18502
-
18503
- var firstRepeat =
18504
- container.findElement(by.repeater('contact in contacts').row(0));
18505
- var secondRepeat =
18506
- container.findElement(by.repeater('contact in contacts').row(1));
18507
-
18508
- expect(firstRepeat.findElement(by.model('contact.value')).getAttribute('value'))
18509
- .toBe('408 555 1212');
18510
- expect(secondRepeat.findElement(by.model('contact.value')).getAttribute('value'))
18511
- .toBe('john.smith@example.org');
18512
-
18513
- firstRepeat.findElement(by.linkText('clear')).click();
18514
-
18515
- expect(firstRepeat.findElement(by.model('contact.value')).getAttribute('value'))
18516
- .toBe('');
18517
-
18518
- container.findElement(by.linkText('add')).click();
18519
-
18520
- expect(container.findElement(by.repeater('contact in contacts').row(2))
18521
- .findElement(by.model('contact.value'))
18522
- .getAttribute('value'))
18523
- .toBe('yourname@example.org');
18524
- });
18525
- </file>
18526
- </example>
18602
+ * easily be called from the angular markup. Any changes to the data are automatically reflected
18603
+ * in the View without the need for a manual update.
18604
+ *
18605
+ * Two different declaration styles are included below:
18606
+ *
18607
+ * * one binds methods and properties directly onto the controller using `this`:
18608
+ * `ng-controller="SettingsController1 as settings"`
18609
+ * * one injects `$scope` into the controller:
18610
+ * `ng-controller="SettingsController2"`
18611
+ *
18612
+ * The second option is more common in the Angular community, and is generally used in boilerplates
18613
+ * and in this guide. However, there are advantages to binding properties directly to the controller
18614
+ * and avoiding scope.
18615
+ *
18616
+ * * Using `controller as` makes it obvious which controller you are accessing in the template when
18617
+ * multiple controllers apply to an element.
18618
+ * * If you are writing your controllers as classes you have easier access to the properties and
18619
+ * methods, which will appear on the scope, from inside the controller code.
18620
+ * * Since there is always a `.` in the bindings, you don't have to worry about prototypal
18621
+ * inheritance masking primitives.
18622
+ *
18623
+ * This example demonstrates the `controller as` syntax.
18624
+ *
18625
+ * <example name="ngControllerAs">
18626
+ * <file name="index.html">
18627
+ * <div id="ctrl-as-exmpl" ng-controller="SettingsController1 as settings">
18628
+ * Name: <input type="text" ng-model="settings.name"/>
18629
+ * [ <a href="" ng-click="settings.greet()">greet</a> ]<br/>
18630
+ * Contact:
18631
+ * <ul>
18632
+ * <li ng-repeat="contact in settings.contacts">
18633
+ * <select ng-model="contact.type">
18634
+ * <option>phone</option>
18635
+ * <option>email</option>
18636
+ * </select>
18637
+ * <input type="text" ng-model="contact.value"/>
18638
+ * [ <a href="" ng-click="settings.clearContact(contact)">clear</a>
18639
+ * | <a href="" ng-click="settings.removeContact(contact)">X</a> ]
18640
+ * </li>
18641
+ * <li>[ <a href="" ng-click="settings.addContact()">add</a> ]</li>
18642
+ * </ul>
18643
+ * </div>
18644
+ * </file>
18645
+ * <file name="app.js">
18646
+ * function SettingsController1() {
18647
+ * this.name = "John Smith";
18648
+ * this.contacts = [
18649
+ * {type: 'phone', value: '408 555 1212'},
18650
+ * {type: 'email', value: 'john.smith@example.org'} ];
18651
+ * }
18652
+ *
18653
+ * SettingsController1.prototype.greet = function() {
18654
+ * alert(this.name);
18655
+ * };
18656
+ *
18657
+ * SettingsController1.prototype.addContact = function() {
18658
+ * this.contacts.push({type: 'email', value: 'yourname@example.org'});
18659
+ * };
18660
+ *
18661
+ * SettingsController1.prototype.removeContact = function(contactToRemove) {
18662
+ * var index = this.contacts.indexOf(contactToRemove);
18663
+ * this.contacts.splice(index, 1);
18664
+ * };
18665
+ *
18666
+ * SettingsController1.prototype.clearContact = function(contact) {
18667
+ * contact.type = 'phone';
18668
+ * contact.value = '';
18669
+ * };
18670
+ * </file>
18671
+ * <file name="protractor.js" type="protractor">
18672
+ * it('should check controller as', function() {
18673
+ * var container = element(by.id('ctrl-as-exmpl'));
18674
+ * expect(container.findElement(by.model('settings.name'))
18675
+ * .getAttribute('value')).toBe('John Smith');
18676
+ *
18677
+ * var firstRepeat =
18678
+ * container.findElement(by.repeater('contact in settings.contacts').row(0));
18679
+ * var secondRepeat =
18680
+ * container.findElement(by.repeater('contact in settings.contacts').row(1));
18681
+ *
18682
+ * expect(firstRepeat.findElement(by.model('contact.value')).getAttribute('value'))
18683
+ * .toBe('408 555 1212');
18684
+ *
18685
+ * expect(secondRepeat.findElement(by.model('contact.value')).getAttribute('value'))
18686
+ * .toBe('john.smith@example.org');
18687
+ *
18688
+ * firstRepeat.findElement(by.linkText('clear')).click();
18689
+ *
18690
+ * expect(firstRepeat.findElement(by.model('contact.value')).getAttribute('value'))
18691
+ * .toBe('');
18692
+ *
18693
+ * container.findElement(by.linkText('add')).click();
18694
+ *
18695
+ * expect(container.findElement(by.repeater('contact in settings.contacts').row(2))
18696
+ * .findElement(by.model('contact.value'))
18697
+ * .getAttribute('value'))
18698
+ * .toBe('yourname@example.org');
18699
+ * });
18700
+ * </file>
18701
+ * </example>
18702
+ *
18703
+ * This example demonstrates the "attach to `$scope`" style of controller.
18704
+ *
18705
+ * <example name="ngController">
18706
+ * <file name="index.html">
18707
+ * <div id="ctrl-exmpl" ng-controller="SettingsController2">
18708
+ * Name: <input type="text" ng-model="name"/>
18709
+ * [ <a href="" ng-click="greet()">greet</a> ]<br/>
18710
+ * Contact:
18711
+ * <ul>
18712
+ * <li ng-repeat="contact in contacts">
18713
+ * <select ng-model="contact.type">
18714
+ * <option>phone</option>
18715
+ * <option>email</option>
18716
+ * </select>
18717
+ * <input type="text" ng-model="contact.value"/>
18718
+ * [ <a href="" ng-click="clearContact(contact)">clear</a>
18719
+ * | <a href="" ng-click="removeContact(contact)">X</a> ]
18720
+ * </li>
18721
+ * <li>[ <a href="" ng-click="addContact()">add</a> ]</li>
18722
+ * </ul>
18723
+ * </div>
18724
+ * </file>
18725
+ * <file name="app.js">
18726
+ * function SettingsController2($scope) {
18727
+ * $scope.name = "John Smith";
18728
+ * $scope.contacts = [
18729
+ * {type:'phone', value:'408 555 1212'},
18730
+ * {type:'email', value:'john.smith@example.org'} ];
18731
+ *
18732
+ * $scope.greet = function() {
18733
+ * alert($scope.name);
18734
+ * };
18735
+ *
18736
+ * $scope.addContact = function() {
18737
+ * $scope.contacts.push({type:'email', value:'yourname@example.org'});
18738
+ * };
18739
+ *
18740
+ * $scope.removeContact = function(contactToRemove) {
18741
+ * var index = $scope.contacts.indexOf(contactToRemove);
18742
+ * $scope.contacts.splice(index, 1);
18743
+ * };
18744
+ *
18745
+ * $scope.clearContact = function(contact) {
18746
+ * contact.type = 'phone';
18747
+ * contact.value = '';
18748
+ * };
18749
+ * }
18750
+ * </file>
18751
+ * <file name="protractor.js" type="protractor">
18752
+ * it('should check controller', function() {
18753
+ * var container = element(by.id('ctrl-exmpl'));
18754
+ *
18755
+ * expect(container.findElement(by.model('name'))
18756
+ * .getAttribute('value')).toBe('John Smith');
18757
+ *
18758
+ * var firstRepeat =
18759
+ * container.findElement(by.repeater('contact in contacts').row(0));
18760
+ * var secondRepeat =
18761
+ * container.findElement(by.repeater('contact in contacts').row(1));
18762
+ *
18763
+ * expect(firstRepeat.findElement(by.model('contact.value')).getAttribute('value'))
18764
+ * .toBe('408 555 1212');
18765
+ * expect(secondRepeat.findElement(by.model('contact.value')).getAttribute('value'))
18766
+ * .toBe('john.smith@example.org');
18767
+ *
18768
+ * firstRepeat.findElement(by.linkText('clear')).click();
18769
+ *
18770
+ * expect(firstRepeat.findElement(by.model('contact.value')).getAttribute('value'))
18771
+ * .toBe('');
18772
+ *
18773
+ * container.findElement(by.linkText('add')).click();
18774
+ *
18775
+ * expect(container.findElement(by.repeater('contact in contacts').row(2))
18776
+ * .findElement(by.model('contact.value'))
18777
+ * .getAttribute('value'))
18778
+ * .toBe('yourname@example.org');
18779
+ * });
18780
+ * </file>
18781
+ *</example>
18527
18782
 
18528
18783
  */
18529
18784
  var ngControllerDirective = [function() {
@@ -18621,7 +18876,7 @@ forEach(
18621
18876
  return {
18622
18877
  compile: function($element, attr) {
18623
18878
  var fn = $parse(attr[directiveName]);
18624
- return function(scope, element, attr) {
18879
+ return function ngEventHandler(scope, element) {
18625
18880
  element.on(lowercase(name), function(event) {
18626
18881
  scope.$apply(function() {
18627
18882
  fn(scope, {$event:event});
@@ -18838,8 +19093,13 @@ forEach(
18838
19093
  * @example
18839
19094
  <example>
18840
19095
  <file name="index.html">
18841
- <input ng-keyup="count = count + 1" ng-init="count=0">
18842
- key up count: {{count}}
19096
+ <p>Typing in the input box below updates the key count</p>
19097
+ <input ng-keyup="count = count + 1" ng-init="count=0"> key up count: {{count}}
19098
+
19099
+ <p>Typing in the input box below updates the keycode</p>
19100
+ <input ng-keyup="event=$event">
19101
+ <p>event keyCode: {{ event.keyCode }}</p>
19102
+ <p>event altKey: {{ event.altKey }}</p>
18843
19103
  </file>
18844
19104
  </example>
18845
19105
  */
@@ -19111,7 +19371,7 @@ var ngIfDirective = ['$animate', function($animate) {
19111
19371
  clone[clone.length++] = document.createComment(' end ngIf: ' + $attr.ngIf + ' ');
19112
19372
  // Note: We only need the first/last node of the cloned nodes.
19113
19373
  // However, we need to keep the reference to the jqlite wrapper as it might be changed later
19114
- // by a directive with templateUrl when it's template arrives.
19374
+ // by a directive with templateUrl when its template arrives.
19115
19375
  block = {
19116
19376
  clone: clone
19117
19377
  };
@@ -19810,7 +20070,7 @@ var ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interp
19810
20070
  * mapped to the same DOM element, which is not possible.) Filters should be applied to the expression,
19811
20071
  * before specifying a tracking expression.
19812
20072
  *
19813
- * For example: `item in items` is equivalent to `item in items track by $id(item)'. This implies that the DOM elements
20073
+ * For example: `item in items` is equivalent to `item in items track by $id(item)`. This implies that the DOM elements
19814
20074
  * will be associated by item identity in the array.
19815
20075
  *
19816
20076
  * For example: `item in items track by $id(item)`. A built in `$id()` function can be used to assign a unique
@@ -20088,7 +20348,7 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
20088
20348
  block.scope = childScope;
20089
20349
  // Note: We only need the first/last node of the cloned nodes.
20090
20350
  // However, we need to keep the reference to the jqlite wrapper as it might be changed later
20091
- // by a directive with templateUrl when it's template arrives.
20351
+ // by a directive with templateUrl when its template arrives.
20092
20352
  block.clone = clone;
20093
20353
  nextBlockMap[block.id] = block;
20094
20354
  });
@@ -20131,6 +20391,11 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
20131
20391
  * on the element causing it to become hidden. When true, the ng-hide CSS class is removed
20132
20392
  * from the element causing the element not to appear hidden.
20133
20393
  *
20394
+ * <div class="alert alert-warning">
20395
+ * **Note:** Here is a list of values that ngShow will consider as a falsy value (case insensitive):<br />
20396
+ * "f" / "0" / "false" / "no" / "n" / "[]"
20397
+ * </div>
20398
+ *
20134
20399
  * ## Why is !important used?
20135
20400
  *
20136
20401
  * You may be wondering why !important is used for the .ng-hide CSS class. This is because the `.ng-hide` selector
@@ -20144,26 +20409,21 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
20144
20409
  *
20145
20410
  * ### Overriding .ng-hide
20146
20411
  *
20147
- * If you wish to change the hide behavior with ngShow/ngHide then this can be achieved by
20148
- * restating the styles for the .ng-hide class in CSS:
20412
+ * By default, the `.ng-hide` class will style the element with `display:none!important`. If you wish to change
20413
+ * the hide behavior with ngShow/ngHide then this can be achieved by restating the styles for the `.ng-hide`
20414
+ * class in CSS:
20415
+ *
20149
20416
  * ```css
20150
20417
  * .ng-hide {
20151
- * //!annotate CSS Specificity|Not to worry, this will override the AngularJS default...
20152
- * display:block!important;
20153
- *
20154
20418
  * //this is just another form of hiding an element
20419
+ * display:block!important;
20155
20420
  * position:absolute;
20156
20421
  * top:-9999px;
20157
20422
  * left:-9999px;
20158
20423
  * }
20159
20424
  * ```
20160
20425
  *
20161
- * Just remember to include the important flag so the CSS override will function.
20162
- *
20163
- * <div class="alert alert-warning">
20164
- * **Note:** Here is a list of values that ngShow will consider as a falsy value (case insensitive):<br />
20165
- * "f" / "0" / "false" / "no" / "n" / "[]"
20166
- * </div>
20426
+ * By default you don't need to override in CSS anything and the animations will work around the display style.
20167
20427
  *
20168
20428
  * ## A note about animations with ngShow
20169
20429
  *
@@ -20178,7 +20438,6 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
20178
20438
  * //
20179
20439
  * .my-element.ng-hide-add, .my-element.ng-hide-remove {
20180
20440
  * transition:0.5s linear all;
20181
- * display:block!important;
20182
20441
  * }
20183
20442
  *
20184
20443
  * .my-element.ng-hide-add { ... }
@@ -20187,6 +20446,9 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
20187
20446
  * .my-element.ng-hide-remove.ng-hide-remove-active { ... }
20188
20447
  * ```
20189
20448
  *
20449
+ * Keep in mind that, as of AngularJS version 1.2.17 (and 1.3.0-beta.11), there is no need to change the display
20450
+ * property to block during animation states--ngAnimate will handle the style toggling automatically for you.
20451
+ *
20190
20452
  * @animations
20191
20453
  * addClass: .ng-hide - happens after the ngShow expression evaluates to a truthy value and the just before contents are set to visible
20192
20454
  * removeClass: .ng-hide - happens after the ngShow expression evaluates to a non truthy value and just before the contents are set to hidden
@@ -20226,11 +20488,6 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
20226
20488
  background:white;
20227
20489
  }
20228
20490
 
20229
- .animate-show.ng-hide-add,
20230
- .animate-show.ng-hide-remove {
20231
- display:block!important;
20232
- }
20233
-
20234
20491
  .animate-show.ng-hide {
20235
20492
  line-height:0;
20236
20493
  opacity:0;
@@ -20281,16 +20538,21 @@ var ngShowDirective = ['$animate', function($animate) {
20281
20538
  *
20282
20539
  * ```html
20283
20540
  * <!-- when $scope.myValue is truthy (element is hidden) -->
20284
- * <div ng-hide="myValue"></div>
20541
+ * <div ng-hide="myValue" class="ng-hide"></div>
20285
20542
  *
20286
20543
  * <!-- when $scope.myValue is falsy (element is visible) -->
20287
- * <div ng-hide="myValue" class="ng-hide"></div>
20544
+ * <div ng-hide="myValue"></div>
20288
20545
  * ```
20289
20546
  *
20290
20547
  * When the ngHide expression evaluates to true then the .ng-hide CSS class is added to the class attribute
20291
20548
  * on the element causing it to become hidden. When false, the ng-hide CSS class is removed
20292
20549
  * from the element causing the element not to appear hidden.
20293
20550
  *
20551
+ * <div class="alert alert-warning">
20552
+ * **Note:** Here is a list of values that ngHide will consider as a falsy value (case insensitive):<br />
20553
+ * "f" / "0" / "false" / "no" / "n" / "[]"
20554
+ * </div>
20555
+ *
20294
20556
  * ## Why is !important used?
20295
20557
  *
20296
20558
  * You may be wondering why !important is used for the .ng-hide CSS class. This is because the `.ng-hide` selector
@@ -20304,33 +20566,27 @@ var ngShowDirective = ['$animate', function($animate) {
20304
20566
  *
20305
20567
  * ### Overriding .ng-hide
20306
20568
  *
20307
- * If you wish to change the hide behavior with ngShow/ngHide then this can be achieved by
20308
- * restating the styles for the .ng-hide class in CSS:
20569
+ * By default, the `.ng-hide` class will style the element with `display:none!important`. If you wish to change
20570
+ * the hide behavior with ngShow/ngHide then this can be achieved by restating the styles for the `.ng-hide`
20571
+ * class in CSS:
20572
+ *
20309
20573
  * ```css
20310
20574
  * .ng-hide {
20311
- * //!annotate CSS Specificity|Not to worry, this will override the AngularJS default...
20312
- * display:block!important;
20313
- *
20314
20575
  * //this is just another form of hiding an element
20576
+ * display:block!important;
20315
20577
  * position:absolute;
20316
20578
  * top:-9999px;
20317
20579
  * left:-9999px;
20318
20580
  * }
20319
20581
  * ```
20320
20582
  *
20321
- * Just remember to include the important flag so the CSS override will function.
20322
- *
20323
- * <div class="alert alert-warning">
20324
- * **Note:** Here is a list of values that ngHide will consider as a falsy value (case insensitive):<br />
20325
- * "f" / "0" / "false" / "no" / "n" / "[]"
20326
- * </div>
20583
+ * By default you don't need to override in CSS anything and the animations will work around the display style.
20327
20584
  *
20328
20585
  * ## A note about animations with ngHide
20329
20586
  *
20330
20587
  * Animations in ngShow/ngHide work with the show and hide events that are triggered when the directive expression
20331
- * is true and false. This system works like the animation system present with ngClass, except that
20332
- * you must also include the !important flag to override the display property so
20333
- * that you can perform an animation when the element is hidden during the time of the animation.
20588
+ * is true and false. This system works like the animation system present with ngClass, except that the `.ng-hide`
20589
+ * CSS class is added and removed for you instead of your own CSS class.
20334
20590
  *
20335
20591
  * ```css
20336
20592
  * //
@@ -20338,7 +20594,6 @@ var ngShowDirective = ['$animate', function($animate) {
20338
20594
  * //
20339
20595
  * .my-element.ng-hide-add, .my-element.ng-hide-remove {
20340
20596
  * transition:0.5s linear all;
20341
- * display:block!important;
20342
20597
  * }
20343
20598
  *
20344
20599
  * .my-element.ng-hide-add { ... }
@@ -20347,6 +20602,9 @@ var ngShowDirective = ['$animate', function($animate) {
20347
20602
  * .my-element.ng-hide-remove.ng-hide-remove-active { ... }
20348
20603
  * ```
20349
20604
  *
20605
+ * Keep in mind that, as of AngularJS version 1.2.17 (and 1.3.0-beta.11), there is no need to change the display
20606
+ * property to block during animation states--ngAnimate will handle the style toggling automatically for you.
20607
+ *
20350
20608
  * @animations
20351
20609
  * removeClass: .ng-hide - happens after the ngHide expression evaluates to a truthy value and just before the contents are set to hidden
20352
20610
  * addClass: .ng-hide - happens after the ngHide expression evaluates to a non truthy value and just before the contents are set to visible
@@ -20386,11 +20644,6 @@ var ngShowDirective = ['$animate', function($animate) {
20386
20644
  background:white;
20387
20645
  }
20388
20646
 
20389
- .animate-hide.ng-hide-add,
20390
- .animate-hide.ng-hide-remove {
20391
- display:block!important;
20392
- }
20393
-
20394
20647
  .animate-hide.ng-hide {
20395
20648
  line-height:0;
20396
20649
  opacity:0;
@@ -20436,14 +20689,20 @@ var ngHideDirective = ['$animate', function($animate) {
20436
20689
  * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.
20437
20690
  *
20438
20691
  * @element ANY
20439
- * @param {expression} ngStyle {@link guide/expression Expression} which evals to an
20440
- * object whose keys are CSS style names and values are corresponding values for those CSS
20441
- * keys.
20692
+ * @param {expression} ngStyle
20693
+ *
20694
+ * {@link guide/expression Expression} which evals to an
20695
+ * object whose keys are CSS style names and values are corresponding values for those CSS
20696
+ * keys.
20697
+ *
20698
+ * Since some CSS style names are not valid keys for an object, they must be quoted.
20699
+ * See the 'background-color' style in the example below.
20442
20700
  *
20443
20701
  * @example
20444
20702
  <example>
20445
20703
  <file name="index.html">
20446
- <input type="button" value="set" ng-click="myStyle={color:'red'}">
20704
+ <input type="button" value="set color" ng-click="myStyle={color:'red'}">
20705
+ <input type="button" value="set background" ng-click="myStyle={'background-color':'blue'}">
20447
20706
  <input type="button" value="clear" ng-click="myStyle={}">
20448
20707
  <br/>
20449
20708
  <span ng-style="myStyle">Sample Text</span>
@@ -20457,9 +20716,9 @@ var ngHideDirective = ['$animate', function($animate) {
20457
20716
  <file name="protractor.js" type="protractor">
20458
20717
  var colorSpan = element(by.css('span'));
20459
20718
 
20460
- it('should check ng-style', function() {
20719
+ iit('should check ng-style', function() {
20461
20720
  expect(colorSpan.getCssValue('color')).toBe('rgba(0, 0, 0, 1)');
20462
- element(by.css('input[value=set]')).click();
20721
+ element(by.css('input[value=\'set color\']')).click();
20463
20722
  expect(colorSpan.getCssValue('color')).toBe('rgba(255, 0, 0, 1)');
20464
20723
  element(by.css('input[value=clear]')).click();
20465
20724
  expect(colorSpan.getCssValue('color')).toBe('rgba(0, 0, 0, 1)');
@@ -20507,11 +20766,14 @@ var ngStyleDirective = ngDirective(function(scope, element, attr) {
20507
20766
  * leave - happens just after the ngSwitch contents change and just before the former contents are removed from the DOM
20508
20767
  *
20509
20768
  * @usage
20769
+ *
20770
+ * ```
20510
20771
  * <ANY ng-switch="expression">
20511
20772
  * <ANY ng-switch-when="matchValue1">...</ANY>
20512
20773
  * <ANY ng-switch-when="matchValue2">...</ANY>
20513
20774
  * <ANY ng-switch-default>...</ANY>
20514
20775
  * </ANY>
20776
+ * ```
20515
20777
  *
20516
20778
  *
20517
20779
  * @scope
@@ -20611,37 +20873,29 @@ var ngSwitchDirective = ['$animate', function($animate) {
20611
20873
  }],
20612
20874
  link: function(scope, element, attr, ngSwitchController) {
20613
20875
  var watchExpr = attr.ngSwitch || attr.on,
20614
- selectedTranscludes,
20615
- selectedElements,
20616
- previousElements,
20876
+ selectedTranscludes = [],
20877
+ selectedElements = [],
20878
+ previousElements = [],
20617
20879
  selectedScopes = [];
20618
20880
 
20619
20881
  scope.$watch(watchExpr, function ngSwitchWatchAction(value) {
20620
- var i, ii = selectedScopes.length;
20621
- if(ii > 0) {
20622
- if(previousElements) {
20623
- for (i = 0; i < ii; i++) {
20624
- previousElements[i].remove();
20625
- }
20626
- previousElements = null;
20627
- }
20628
-
20629
- previousElements = [];
20630
- for (i= 0; i<ii; i++) {
20631
- var selected = selectedElements[i];
20632
- selectedScopes[i].$destroy();
20633
- previousElements[i] = selected;
20634
- $animate.leave(selected, function() {
20635
- previousElements.splice(i, 1);
20636
- if(previousElements.length === 0) {
20637
- previousElements = null;
20638
- }
20639
- });
20640
- }
20882
+ var i, ii;
20883
+ for (i = 0, ii = previousElements.length; i < ii; ++i) {
20884
+ previousElements[i].remove();
20885
+ }
20886
+ previousElements.length = 0;
20887
+
20888
+ for (i = 0, ii = selectedScopes.length; i < ii; ++i) {
20889
+ var selected = selectedElements[i];
20890
+ selectedScopes[i].$destroy();
20891
+ previousElements[i] = selected;
20892
+ $animate.leave(selected, function() {
20893
+ previousElements.splice(i, 1);
20894
+ });
20641
20895
  }
20642
20896
 
20643
- selectedElements = [];
20644
- selectedScopes = [];
20897
+ selectedElements.length = 0;
20898
+ selectedScopes.length = 0;
20645
20899
 
20646
20900
  if ((selectedTranscludes = ngSwitchController.cases['!' + value] || ngSwitchController.cases['?'])) {
20647
20901
  scope.$eval(attr.change);
@@ -20885,7 +21139,7 @@ var ngOptionsMinErr = minErr('ngOptions');
20885
21139
  {name:'blue', shade:'dark'},
20886
21140
  {name:'yellow', shade:'light'}
20887
21141
  ];
20888
- $scope.color = $scope.colors[2]; // red
21142
+ $scope.myColor = $scope.colors[2]; // red
20889
21143
  }
20890
21144
  </script>
20891
21145
  <div ng-controller="MyCntrl">
@@ -20900,37 +21154,37 @@ var ngOptionsMinErr = minErr('ngOptions');
20900
21154
  </ul>
20901
21155
  <hr/>
20902
21156
  Color (null not allowed):
20903
- <select ng-model="color" ng-options="c.name for c in colors"></select><br>
21157
+ <select ng-model="myColor" ng-options="color.name for color in colors"></select><br>
20904
21158
 
20905
21159
  Color (null allowed):
20906
21160
  <span class="nullable">
20907
- <select ng-model="color" ng-options="c.name for c in colors">
21161
+ <select ng-model="myColor" ng-options="color.name for color in colors">
20908
21162
  <option value="">-- choose color --</option>
20909
21163
  </select>
20910
21164
  </span><br/>
20911
21165
 
20912
21166
  Color grouped by shade:
20913
- <select ng-model="color" ng-options="c.name group by c.shade for c in colors">
21167
+ <select ng-model="myColor" ng-options="color.name group by color.shade for color in colors">
20914
21168
  </select><br/>
20915
21169
 
20916
21170
 
20917
- Select <a href ng-click="color={name:'not in list'}">bogus</a>.<br>
21171
+ Select <a href ng-click="myColor = { name:'not in list', shade: 'other' }">bogus</a>.<br>
20918
21172
  <hr/>
20919
- Currently selected: {{ {selected_color:color} }}
21173
+ Currently selected: {{ {selected_color:myColor} }}
20920
21174
  <div style="border:solid 1px black; height:20px"
20921
- ng-style="{'background-color':color.name}">
21175
+ ng-style="{'background-color':myColor.name}">
20922
21176
  </div>
20923
21177
  </div>
20924
21178
  </file>
20925
21179
  <file name="protractor.js" type="protractor">
20926
21180
  it('should check ng-options', function() {
20927
- expect(element(by.binding('{selected_color:color}')).getText()).toMatch('red');
20928
- element.all(by.select('color')).first().click();
20929
- element.all(by.css('select[ng-model="color"] option')).first().click();
20930
- expect(element(by.binding('{selected_color:color}')).getText()).toMatch('black');
20931
- element(by.css('.nullable select[ng-model="color"]')).click();
20932
- element.all(by.css('.nullable select[ng-model="color"] option')).first().click();
20933
- expect(element(by.binding('{selected_color:color}')).getText()).toMatch('null');
21181
+ expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('red');
21182
+ element.all(by.select('myColor')).first().click();
21183
+ element.all(by.css('select[ng-model="myColor"] option')).first().click();
21184
+ expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('black');
21185
+ element(by.css('.nullable select[ng-model="myColor"]')).click();
21186
+ element.all(by.css('.nullable select[ng-model="myColor"] option')).first().click();
21187
+ expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('null');
20934
21188
  });
20935
21189
  </file>
20936
21190
  </example>
@@ -21085,7 +21339,7 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
21085
21339
  // we need to work of an array, so we need to see if anything was inserted/removed
21086
21340
  scope.$watch(function selectMultipleWatch() {
21087
21341
  if (!equals(lastView, ctrl.$viewValue)) {
21088
- lastView = copy(ctrl.$viewValue);
21342
+ lastView = shallowCopy(ctrl.$viewValue);
21089
21343
  ctrl.$render();
21090
21344
  }
21091
21345
  });
@@ -21461,4 +21715,4 @@ var styleDirective = valueFn({
21461
21715
 
21462
21716
  })(window, document);
21463
21717
 
21464
- !angular.$$csp() && angular.element(document).find('head').prepend('<style type="text/css">@charset "UTF-8";[ng\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak,.ng-hide{display:none !important;}ng\\:form{display:block;}.ng-animate-block-transitions{transition:0s all!important;-webkit-transition:0s all!important;}</style>');
21718
+ !window.angular.$$csp() && window.angular.element(document).find('head').prepend('<style type="text/css">@charset "UTF-8";[ng\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak,.ng-hide{display:none !important;}ng\\:form{display:block;}.ng-animate-block-transitions{transition:0s all!important;-webkit-transition:0s all!important;}.ng-hide-add-active,.ng-hide-remove{display:block!important;}</style>');