angularjs-rails 1.2.22 → 1.2.25

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.2.22
2
+ * @license AngularJS v1.2.25
3
3
  * (c) 2010-2014 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.2.22
2
+ * @license AngularJS v1.2.25
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.22/' +
71
+ message = message + '\nhttp://errors.angularjs.org/1.2.25/' +
72
72
  (module ? module + '/' : '') + code;
73
73
  for (i = 2; i < arguments.length; i++) {
74
74
  message = message + (i == 2 ? '?' : '&') + 'p' + (i-2) + '=' +
@@ -899,9 +899,13 @@ function copy(source, destination, stackSource, stackDest) {
899
899
  }
900
900
  } else {
901
901
  var h = destination.$$hashKey;
902
- forEach(destination, function(value, key) {
903
- delete destination[key];
904
- });
902
+ if (isArray(destination)) {
903
+ destination.length = 0;
904
+ } else {
905
+ forEach(destination, function(value, key) {
906
+ delete destination[key];
907
+ });
908
+ }
905
909
  for ( var key in source) {
906
910
  result = copy(source[key], null, stackSource, stackDest);
907
911
  if (isObject(source[key])) {
@@ -986,7 +990,8 @@ function equals(o1, o2) {
986
990
  return true;
987
991
  }
988
992
  } else if (isDate(o1)) {
989
- return isDate(o2) && o1.getTime() == o2.getTime();
993
+ if (!isDate(o2)) return false;
994
+ return (isNaN(o1.getTime()) && isNaN(o2.getTime())) || (o1.getTime() === o2.getTime());
990
995
  } else if (isRegExp(o1) && isRegExp(o2)) {
991
996
  return o1.toString() == o2.toString();
992
997
  } else {
@@ -1424,7 +1429,11 @@ function bootstrap(element, modules) {
1424
1429
 
1425
1430
  if (element.injector()) {
1426
1431
  var tag = (element[0] === document) ? 'document' : startingTag(element);
1427
- throw ngMinErr('btstrpd', "App Already Bootstrapped with this Element '{0}'", tag);
1432
+ //Encode angle brackets to prevent input from being sanitized to empty string #8683
1433
+ throw ngMinErr(
1434
+ 'btstrpd',
1435
+ "App Already Bootstrapped with this Element '{0}'",
1436
+ tag.replace(/</,'&lt;').replace(/>/,'&gt;'));
1428
1437
  }
1429
1438
 
1430
1439
  modules = modules || [];
@@ -1688,7 +1697,7 @@ function setupModuleLoader(window) {
1688
1697
  * @ngdoc property
1689
1698
  * @name angular.Module#requires
1690
1699
  * @module ng
1691
- * @returns {Array.<string>} List of module names which must be loaded before this module.
1700
+ *
1692
1701
  * @description
1693
1702
  * Holds the list of modules which the injector will load before the current module is
1694
1703
  * loaded.
@@ -1699,8 +1708,9 @@ function setupModuleLoader(window) {
1699
1708
  * @ngdoc property
1700
1709
  * @name angular.Module#name
1701
1710
  * @module ng
1702
- * @returns {string} Name of the module.
1711
+ *
1703
1712
  * @description
1713
+ * Name of the module.
1704
1714
  */
1705
1715
  name: name,
1706
1716
 
@@ -1977,11 +1987,11 @@ function setupModuleLoader(window) {
1977
1987
  * - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat".
1978
1988
  */
1979
1989
  var version = {
1980
- full: '1.2.22', // all of these placeholder strings will be replaced by grunt's
1990
+ full: '1.2.25', // all of these placeholder strings will be replaced by grunt's
1981
1991
  major: 1, // package task
1982
1992
  minor: 2,
1983
- dot: 22,
1984
- codeName: 'finicky-pleasure'
1993
+ dot: 25,
1994
+ codeName: 'hypnotic-gesticulation'
1985
1995
  };
1986
1996
 
1987
1997
 
@@ -4572,6 +4582,13 @@ function Browser(window, document, $log, $sniffer) {
4572
4582
  return callback;
4573
4583
  };
4574
4584
 
4585
+ /**
4586
+ * Checks whether the url has changed outside of Angular.
4587
+ * Needs to be exported to be able to check for changes that have been done in sync,
4588
+ * as hashchange/popstate events fire in async.
4589
+ */
4590
+ self.$$checkUrlChange = fireUrlChange;
4591
+
4575
4592
  //////////////////////////////////////////////////////////////
4576
4593
  // Misc API
4577
4594
  //////////////////////////////////////////////////////////////
@@ -4788,8 +4805,10 @@ function $BrowserProvider(){
4788
4805
  $scope.keys = [];
4789
4806
  $scope.cache = $cacheFactory('cacheId');
4790
4807
  $scope.put = function(key, value) {
4791
- $scope.cache.put(key, value);
4792
- $scope.keys.push(key);
4808
+ if ($scope.cache.get(key) === undefined) {
4809
+ $scope.keys.push(key);
4810
+ }
4811
+ $scope.cache.put(key, value === undefined ? null : value);
4793
4812
  };
4794
4813
  }]);
4795
4814
  </file>
@@ -5309,9 +5328,9 @@ function $TemplateCacheProvider() {
5309
5328
  *
5310
5329
  * * (no prefix) - Locate the required controller on the current element. Throw an error if not found.
5311
5330
  * * `?` - Attempt to locate the required controller or pass `null` to the `link` fn if not found.
5312
- * * `^` - Locate the required controller by searching the element's parents. Throw an error if not found.
5313
- * * `?^` - Attempt to locate the required controller by searching the element's parents or pass `null` to the
5314
- * `link` fn if not found.
5331
+ * * `^` - Locate the required controller by searching the element and its parents. Throw an error if not found.
5332
+ * * `?^` - Attempt to locate the required controller by searching the element and its parents or pass
5333
+ * `null` to the `link` fn if not found.
5315
5334
  *
5316
5335
  *
5317
5336
  * #### `controllerAs`
@@ -7129,8 +7148,10 @@ function directiveNormalize(name) {
7129
7148
  /**
7130
7149
  * @ngdoc property
7131
7150
  * @name $compile.directive.Attributes#$attr
7132
- * @returns {object} A map of DOM element attribute names to the normalized name. This is
7133
- * needed to do reverse lookup from normalized name back to actual name.
7151
+ *
7152
+ * @description
7153
+ * A map of DOM element attribute names to the normalized name. This is
7154
+ * needed to do reverse lookup from normalized name back to actual name.
7134
7155
  */
7135
7156
 
7136
7157
 
@@ -7885,7 +7906,7 @@ function $HttpProvider() {
7885
7906
  * that only JavaScript running on your domain could have sent the request. The token must be
7886
7907
  * unique for each user and must be verifiable by the server (to prevent the JavaScript from
7887
7908
  * making up its own tokens). We recommend that the token is a digest of your site's
7888
- * authentication cookie with a [salt](https://en.wikipedia.org/wiki/Salt_(cryptography))
7909
+ * authentication cookie with a [salt](https://en.wikipedia.org/wiki/Salt_(cryptography&#41;)
7889
7910
  * for added security.
7890
7911
  *
7891
7912
  * The name of the headers can be specified using the xsrfHeaderName and xsrfCookieName
@@ -8393,7 +8414,7 @@ function $HttpProvider() {
8393
8414
  if (isObject(v)) {
8394
8415
  if (isDate(v)){
8395
8416
  v = v.toISOString();
8396
- } else if (isObject(v)) {
8417
+ } else {
8397
8418
  v = toJson(v);
8398
8419
  }
8399
8420
  }
@@ -8843,7 +8864,7 @@ function $InterpolateProvider() {
8843
8864
  * @description
8844
8865
  * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.
8845
8866
  *
8846
- * Use {@link ng.$interpolateProvider#startSymbol $interpolateProvider#startSymbol} to change
8867
+ * Use {@link ng.$interpolateProvider#startSymbol `$interpolateProvider.startSymbol`} to change
8847
8868
  * the symbol.
8848
8869
  *
8849
8870
  * @returns {string} start symbol.
@@ -8859,7 +8880,7 @@ function $InterpolateProvider() {
8859
8880
  * @description
8860
8881
  * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.
8861
8882
  *
8862
- * Use {@link ng.$interpolateProvider#endSymbol $interpolateProvider#endSymbol} to change
8883
+ * Use {@link ng.$interpolateProvider#endSymbol `$interpolateProvider.endSymbol`} to change
8863
8884
  * the symbol.
8864
8885
  *
8865
8886
  * @returns {string} end symbol.
@@ -8951,7 +8972,7 @@ function $IntervalProvider() {
8951
8972
  * };
8952
8973
  *
8953
8974
  * $scope.$on('$destroy', function() {
8954
- * // Make sure that the interval nis destroyed too
8975
+ * // Make sure that the interval is destroyed too
8955
8976
  * $scope.stopFight();
8956
8977
  * });
8957
8978
  * }])
@@ -9449,17 +9470,16 @@ LocationHashbangInHtml5Url.prototype =
9449
9470
  * Change path, search and hash, when called with parameter and return `$location`.
9450
9471
  *
9451
9472
  * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)
9452
- * @param {string=} replace The path that will be changed
9453
9473
  * @return {string} url
9454
9474
  */
9455
- url: function(url, replace) {
9475
+ url: function(url) {
9456
9476
  if (isUndefined(url))
9457
9477
  return this.$$url;
9458
9478
 
9459
9479
  var match = PATH_MATCH.exec(url);
9460
9480
  if (match[1]) this.path(decodeURIComponent(match[1]));
9461
9481
  if (match[2] || match[1]) this.search(match[3] || '');
9462
- this.hash(match[5] || '', replace);
9482
+ this.hash(match[5] || '');
9463
9483
 
9464
9484
  return this;
9465
9485
  },
@@ -9517,10 +9537,11 @@ LocationHashbangInHtml5Url.prototype =
9517
9537
  * Note: Path should always begin with forward slash (/), this method will add the forward slash
9518
9538
  * if it is missing.
9519
9539
  *
9520
- * @param {string=} path New path
9540
+ * @param {(string|number)=} path New path
9521
9541
  * @return {string} path
9522
9542
  */
9523
9543
  path: locationGetterSetter('$$path', function(path) {
9544
+ path = path ? path.toString() : '';
9524
9545
  return path.charAt(0) == '/' ? path : '/' + path;
9525
9546
  }),
9526
9547
 
@@ -9556,7 +9577,7 @@ LocationHashbangInHtml5Url.prototype =
9556
9577
  * If the argument is a hash object containing an array of values, these values will be encoded
9557
9578
  * as duplicate search parameters in the url.
9558
9579
  *
9559
- * @param {(string|Array<string>|boolean)=} paramValue If `search` is a string, then `paramValue`
9580
+ * @param {(string|Number|Array<string>|boolean)=} paramValue If `search` is a string or number, then `paramValue`
9560
9581
  * will override only a single search property.
9561
9582
  *
9562
9583
  * If `paramValue` is an array, it will override the property of the `search` component of
@@ -9575,7 +9596,8 @@ LocationHashbangInHtml5Url.prototype =
9575
9596
  case 0:
9576
9597
  return this.$$search;
9577
9598
  case 1:
9578
- if (isString(search)) {
9599
+ if (isString(search) || isNumber(search)) {
9600
+ search = search.toString();
9579
9601
  this.$$search = parseKeyValue(search);
9580
9602
  } else if (isObject(search)) {
9581
9603
  // remove object undefined or null properties
@@ -9612,10 +9634,12 @@ LocationHashbangInHtml5Url.prototype =
9612
9634
  *
9613
9635
  * Change hash fragment when called with parameter and return `$location`.
9614
9636
  *
9615
- * @param {string=} hash New hash fragment
9637
+ * @param {(string|number)=} hash New hash fragment
9616
9638
  * @return {string} hash
9617
9639
  */
9618
- hash: locationGetterSetter('$$hash', identity),
9640
+ hash: locationGetterSetter('$$hash', function(hash) {
9641
+ return hash ? hash.toString() : '';
9642
+ }),
9619
9643
 
9620
9644
  /**
9621
9645
  * @ngdoc method
@@ -9799,7 +9823,7 @@ function $LocationProvider(){
9799
9823
  // http://msdn.microsoft.com/en-us/library/ie/dd347148(v=vs.85).aspx
9800
9824
  var href = elm.attr('href') || elm.attr('xlink:href');
9801
9825
 
9802
- if (href.indexOf('://') < 0) { // Ignore absolute URLs
9826
+ if (href && href.indexOf('://') < 0) { // Ignore absolute URLs
9803
9827
  var prefix = '#' + hashPrefix;
9804
9828
  if (href[0] == '/') {
9805
9829
  // absolute path - replace old path
@@ -9811,6 +9835,7 @@ function $LocationProvider(){
9811
9835
  // relative path - join with current path
9812
9836
  var stack = $location.path().split("/"),
9813
9837
  parts = href.split("/");
9838
+ if (stack.length === 2 && !stack[1]) stack.length = 1;
9814
9839
  for (var i=0; i<parts.length; i++) {
9815
9840
  if (parts[i] == ".")
9816
9841
  continue;
@@ -10809,7 +10834,7 @@ Parser.prototype = {
10809
10834
  var context = contextGetter ? contextGetter(scope, locals) : scope;
10810
10835
 
10811
10836
  for (var i = 0; i < argsFn.length; i++) {
10812
- args.push(argsFn[i](scope, locals));
10837
+ args.push(ensureSafeObject(argsFn[i](scope, locals), parser.text));
10813
10838
  }
10814
10839
  var fnPtr = fn(scope, locals, context) || noop;
10815
10840
 
@@ -10897,13 +10922,15 @@ Parser.prototype = {
10897
10922
  //////////////////////////////////////////////////
10898
10923
 
10899
10924
  function setter(obj, path, setValue, fullExp, options) {
10925
+ ensureSafeObject(obj, fullExp);
10926
+
10900
10927
  //needed?
10901
10928
  options = options || {};
10902
10929
 
10903
10930
  var element = path.split('.'), key;
10904
10931
  for (var i = 0; element.length > 1; i++) {
10905
10932
  key = ensureSafeMemberName(element.shift(), fullExp);
10906
- var propertyObj = obj[key];
10933
+ var propertyObj = ensureSafeObject(obj[key], fullExp);
10907
10934
  if (!propertyObj) {
10908
10935
  propertyObj = {};
10909
10936
  obj[key] = propertyObj;
@@ -10923,7 +10950,6 @@ function setter(obj, path, setValue, fullExp, options) {
10923
10950
  }
10924
10951
  }
10925
10952
  key = ensureSafeMemberName(element.shift(), fullExp);
10926
- ensureSafeObject(obj, fullExp);
10927
10953
  ensureSafeObject(obj[key], fullExp);
10928
10954
  obj[key] = setValue;
10929
10955
  return setValue;
@@ -11987,10 +12013,26 @@ function $RootScopeProvider(){
11987
12013
  /**
11988
12014
  * @ngdoc property
11989
12015
  * @name $rootScope.Scope#$id
11990
- * @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for
11991
- * debugging.
12016
+ *
12017
+ * @description
12018
+ * Unique scope ID (monotonically increasing) useful for debugging.
11992
12019
  */
11993
12020
 
12021
+ /**
12022
+ * @ngdoc property
12023
+ * @name $rootScope.Scope#$parent
12024
+ *
12025
+ * @description
12026
+ * Reference to the parent scope.
12027
+ */
12028
+
12029
+ /**
12030
+ * @ngdoc property
12031
+ * @name $rootScope.Scope#$root
12032
+ *
12033
+ * @description
12034
+ * Reference to the root scope.
12035
+ */
11994
12036
 
11995
12037
  Scope.prototype = {
11996
12038
  constructor: Scope,
@@ -12002,9 +12044,8 @@ function $RootScopeProvider(){
12002
12044
  * @description
12003
12045
  * Creates a new child {@link ng.$rootScope.Scope scope}.
12004
12046
  *
12005
- * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} and
12006
- * {@link ng.$rootScope.Scope#$digest $digest()} events. The scope can be removed from the
12007
- * scope hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.
12047
+ * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} event.
12048
+ * The scope can be removed from the scope hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.
12008
12049
  *
12009
12050
  * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is
12010
12051
  * desired for the scope and its child scopes to be permanently detached from the parent and
@@ -12457,6 +12498,8 @@ function $RootScopeProvider(){
12457
12498
  logIdx, logMsg, asyncTask;
12458
12499
 
12459
12500
  beginPhase('$digest');
12501
+ // Check for changes to browser url that happened in sync before the call to $digest
12502
+ $browser.$$checkUrlChange();
12460
12503
 
12461
12504
  lastDirtyWatch = null;
12462
12505
 
@@ -13003,7 +13046,7 @@ function $RootScopeProvider(){
13003
13046
  */
13004
13047
  function $$SanitizeUriProvider() {
13005
13048
  var aHrefSanitizationWhitelist = /^\s*(https?|ftp|mailto|tel|file):/,
13006
- imgSrcSanitizationWhitelist = /^\s*(https?|ftp|file):|data:image\//;
13049
+ imgSrcSanitizationWhitelist = /^\s*((https?|ftp|file):|data:image\/)/;
13007
13050
 
13008
13051
  /**
13009
13052
  * @description
@@ -14510,16 +14553,6 @@ function $WindowProvider(){
14510
14553
  * For more information about how angular filters work, and how to create your own filters, see
14511
14554
  * {@link guide/filter Filters} in the Angular Developer Guide.
14512
14555
  */
14513
- /**
14514
- * @ngdoc method
14515
- * @name $filterProvider#register
14516
- * @description
14517
- * Register filter factory function.
14518
- *
14519
- * @param {String} name Name of the filter.
14520
- * @param {Function} fn The filter factory function which is injectable.
14521
- */
14522
-
14523
14556
 
14524
14557
  /**
14525
14558
  * @ngdoc service
@@ -14558,7 +14591,7 @@ function $FilterProvider($provide) {
14558
14591
 
14559
14592
  /**
14560
14593
  * @ngdoc method
14561
- * @name $controllerProvider#register
14594
+ * @name $filterProvider#register
14562
14595
  * @param {string|Object} name Name of the filter function, or an object map of filters where
14563
14596
  * the keys are the filter names and the values are the filter factories.
14564
14597
  * @returns {Object} Registered filter instance, or if a map of filters was provided then a map
@@ -14631,7 +14664,9 @@ function $FilterProvider($provide) {
14631
14664
  * which have property `name` containing "M" and property `phone` containing "1". A special
14632
14665
  * property name `$` can be used (as in `{$:"text"}`) to accept a match against any
14633
14666
  * property of the object. That's equivalent to the simple substring match with a `string`
14634
- * as described above.
14667
+ * as described above. The predicate can be negated by prefixing the string with `!`.
14668
+ * For Example `{name: "!M"}` predicate will return an array of items which have property `name`
14669
+ * not containing "M".
14635
14670
  *
14636
14671
  * - `function(value)`: A predicate function can be used to write arbitrary filters. The function is
14637
14672
  * called for each element of `array`. The final result is an array of those elements that
@@ -14980,6 +15015,10 @@ function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {
14980
15015
  // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round
14981
15016
  number = +(Math.round(+(number.toString() + 'e' + fractionSize)).toString() + 'e' + -fractionSize);
14982
15017
 
15018
+ if (number === 0) {
15019
+ isNegative = false;
15020
+ }
15021
+
14983
15022
  var fraction = ('' + number).split(DECIMAL_SEP);
14984
15023
  var whole = fraction[0];
14985
15024
  fraction = fraction[1] || '';
@@ -15149,8 +15188,8 @@ var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+
15149
15188
  * * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm)
15150
15189
  * * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm)
15151
15190
  *
15152
- * `format` string can contain literal values. These need to be quoted with single quotes (e.g.
15153
- * `"h 'in the morning'"`). In order to output single quote, use two single quotes in a sequence
15191
+ * `format` string can contain literal values. These need to be escaped by surrounding with single quotes (e.g.
15192
+ * `"h 'in the morning'"`). In order to output a single quote, escape it - i.e., two single quotes in a sequence
15154
15193
  * (e.g. `"h 'o''clock'"`).
15155
15194
  *
15156
15195
  * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or
@@ -15170,6 +15209,8 @@ var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+
15170
15209
  <span>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span><br>
15171
15210
  <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:
15172
15211
  <span>{{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}</span><br>
15212
+ <span ng-non-bindable>{{1288323623006 | date:"MM/dd/yyyy 'at' h:mma"}}</span>:
15213
+ <span>{{'1288323623006' | date:"MM/dd/yyyy 'at' h:mma"}}</span><br>
15173
15214
  </file>
15174
15215
  <file name="protractor.js" type="protractor">
15175
15216
  it('should format date', function() {
@@ -15179,6 +15220,8 @@ var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+
15179
15220
  toMatch(/2010\-10\-2\d \d{2}:\d{2}:\d{2} (\-|\+)?\d{4}/);
15180
15221
  expect(element(by.binding("'1288323623006' | date:'MM/dd/yyyy @ h:mma'")).getText()).
15181
15222
  toMatch(/10\/2\d\/2010 @ \d{1,2}:\d{2}(AM|PM)/);
15223
+ expect(element(by.binding("'1288323623006' | date:\"MM/dd/yyyy 'at' h:mma\"")).getText()).
15224
+ toMatch(/10\/2\d\/2010 at \d{1,2}:\d{2}(AM|PM)/);
15182
15225
  });
15183
15226
  </file>
15184
15227
  </example>
@@ -15443,9 +15486,13 @@ function limitToFilter(){
15443
15486
  *
15444
15487
  * - `function`: Getter function. The result of this function will be sorted using the
15445
15488
  * `<`, `=`, `>` operator.
15446
- * - `string`: An Angular expression which evaluates to an object to order by, such as 'name'
15447
- * to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control
15448
- * ascending or descending sort order (for example, +name or -name).
15489
+ * - `string`: An Angular expression. The result of this expression is used to compare elements
15490
+ * (for example `name` to sort by a property called `name` or `name.substr(0, 3)` to sort by
15491
+ * 3 first characters of a property called `name`). The result of a constant expression
15492
+ * is interpreted as a property name to be used in comparisons (for example `"special name"`
15493
+ * to sort object by the value of their `special name` property). An expression can be
15494
+ * optionally prefixed with `+` or `-` to control ascending or descending sort order
15495
+ * (for example, `+name` or `-name`).
15449
15496
  * - `Array`: An array of function or string predicates. The first predicate in the array
15450
15497
  * is used for sorting, but when two items are equivalent, the next predicate is used.
15451
15498
  *
@@ -15536,7 +15583,7 @@ function limitToFilter(){
15536
15583
  orderByFilter.$inject = ['$parse'];
15537
15584
  function orderByFilter($parse){
15538
15585
  return function(array, sortPredicate, reverseOrder) {
15539
- if (!isArray(array)) return array;
15586
+ if (!(isArrayLike(array))) return array;
15540
15587
  if (!sortPredicate) return array;
15541
15588
  sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];
15542
15589
  sortPredicate = map(sortPredicate, function(predicate){
@@ -15813,7 +15860,7 @@ var htmlAnchorDirective = valueFn({
15813
15860
  *
15814
15861
  * @description
15815
15862
  *
15816
- * The following markup will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:
15863
+ * We shouldn't do this, because it will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:
15817
15864
  * ```html
15818
15865
  * <div ng-init="scope = { isDisabled: false }">
15819
15866
  * <button disabled="{{scope.isDisabled}}">Disabled</button>
@@ -16033,8 +16080,12 @@ forEach(['src', 'srcset', 'href'], function(attrName) {
16033
16080
  }
16034
16081
 
16035
16082
  attr.$observe(normalized, function(value) {
16036
- if (!value)
16037
- return;
16083
+ if (!value) {
16084
+ if (attrName === 'href') {
16085
+ attr.$set(name, null);
16086
+ }
16087
+ return;
16088
+ }
16038
16089
 
16039
16090
  attr.$set(name, value);
16040
16091
 
@@ -16119,8 +16170,9 @@ function FormController(element, attrs, $scope, $animate) {
16119
16170
  // convenience method for easy toggling of classes
16120
16171
  function toggleValidCss(isValid, validationErrorKey) {
16121
16172
  validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';
16122
- $animate.removeClass(element, (isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey);
16123
- $animate.addClass(element, (isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);
16173
+ $animate.setClass(element,
16174
+ (isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey,
16175
+ (isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey);
16124
16176
  }
16125
16177
 
16126
16178
  /**
@@ -16335,8 +16387,6 @@ function FormController(element, attrs, $scope, $animate) {
16335
16387
  * hitting enter in any of the input fields will trigger the click handler on the *first* button or
16336
16388
  * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)
16337
16389
  *
16338
- * @param {string=} name Name of the form. If specified, the form controller will be published into
16339
- * related scope, under this name.
16340
16390
  *
16341
16391
  * ## Animation Hooks
16342
16392
  *
@@ -16414,6 +16464,8 @@ function FormController(element, attrs, $scope, $animate) {
16414
16464
  </file>
16415
16465
  </example>
16416
16466
  *
16467
+ * @param {string=} name Name of the form. If specified, the form controller will be published into
16468
+ * related scope, under this name.
16417
16469
  */
16418
16470
  var formDirectiveFactory = function(isNgForm) {
16419
16471
  return ['$timeout', function($timeout) {
@@ -16492,7 +16544,9 @@ var inputType = {
16492
16544
  * @name input[text]
16493
16545
  *
16494
16546
  * @description
16495
- * Standard HTML text input with angular data binding.
16547
+ * Standard HTML text input with angular data binding, inherited by most of the `input` elements.
16548
+ *
16549
+ * *NOTE* Not every feature offered is available for all input types.
16496
16550
  *
16497
16551
  * @param {string} ngModel Assignable angular expression to data-bind to.
16498
16552
  * @param {string=} name Property name of the form under which the control is published.
@@ -16510,6 +16564,8 @@ var inputType = {
16510
16564
  * @param {string=} ngChange Angular expression to be executed when input changes due to user
16511
16565
  * interaction with the input element.
16512
16566
  * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input.
16567
+ * This parameter is ignored for input[type=password] controls, which will never trim the
16568
+ * input.
16513
16569
  *
16514
16570
  * @example
16515
16571
  <example name="text-input-directive" module="textInputExample">
@@ -16949,6 +17005,7 @@ function addNativeHtml5Validators(ctrl, validatorName, badFlags, ignoreFlags, va
16949
17005
  function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
16950
17006
  var validity = element.prop(VALIDITY_STATE_PROPERTY);
16951
17007
  var placeholder = element[0].placeholder, noevent = {};
17008
+ var type = lowercase(element[0].type);
16952
17009
  ctrl.$$validityState = validity;
16953
17010
 
16954
17011
  // In composition mode, users are still inputing intermediate text buffer,
@@ -16982,8 +17039,8 @@ function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
16982
17039
 
16983
17040
  // By default we will trim the value
16984
17041
  // If the attribute ng-trim exists we will avoid trimming
16985
- // e.g. <input ng-model="foo" ng-trim="false">
16986
- if (toBoolean(attr.ngTrim || 'T')) {
17042
+ // If input type is 'password', the value is never trimmed
17043
+ if (type !== 'password' && (toBoolean(attr.ngTrim || 'T'))) {
16987
17044
  value = trim(value);
16988
17045
  }
16989
17046
 
@@ -16992,7 +17049,7 @@ function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
16992
17049
  // a row.
16993
17050
  var revalidate = validity && ctrl.$$hasNativeValidators;
16994
17051
  if (ctrl.$viewValue !== value || (value === '' && revalidate)) {
16995
- if (scope.$$phase) {
17052
+ if (scope.$root.$$phase) {
16996
17053
  ctrl.$setViewValue(value);
16997
17054
  } else {
16998
17055
  scope.$apply(function() {
@@ -17258,6 +17315,8 @@ function checkboxInputType(scope, element, attr, ctrl) {
17258
17315
  * HTML input element control with angular data-binding. Input control follows HTML5 input types
17259
17316
  * and polyfills the HTML5 validation behavior for older browsers.
17260
17317
  *
17318
+ * *NOTE* Not every feature offered is available for all input types.
17319
+ *
17261
17320
  * @param {string} ngModel Assignable angular expression to data-bind to.
17262
17321
  * @param {string=} name Property name of the form under which the control is published.
17263
17322
  * @param {string=} required Sets `required` validation error key if the value is not entered.
@@ -17271,6 +17330,9 @@ function checkboxInputType(scope, element, attr, ctrl) {
17271
17330
  * patterns defined as scope expressions.
17272
17331
  * @param {string=} ngChange Angular expression to be executed when input changes due to user
17273
17332
  * interaction with the input element.
17333
+ * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input.
17334
+ * This parameter is ignored for input[type=password] controls, which will never trim the
17335
+ * input.
17274
17336
  *
17275
17337
  * @example
17276
17338
  <example name="input-directive" module="inputExample">
@@ -18260,7 +18322,6 @@ var ngBindTemplateDirective = ['$interpolate', function($interpolate) {
18260
18322
  * @param {expression} ngBindHtml {@link guide/expression Expression} to evaluate.
18261
18323
  *
18262
18324
  * @example
18263
- Try it here: enter text in text box and watch the greeting change.
18264
18325
 
18265
18326
  <example module="bindHtmlExample" deps="angular-sanitize.js">
18266
18327
  <file name="index.html">
@@ -19030,7 +19091,9 @@ var ngControllerDirective = [function() {
19030
19091
  <button ng-click="count = count + 1" ng-init="count=0">
19031
19092
  Increment
19032
19093
  </button>
19033
- count: {{count}}
19094
+ <span>
19095
+ count: {{count}}
19096
+ <span>
19034
19097
  </file>
19035
19098
  <file name="protractor.js" type="protractor">
19036
19099
  it('should check ng-click', function() {
@@ -19048,19 +19111,32 @@ var ngControllerDirective = [function() {
19048
19111
  * Events that are handled via these handler are always configured not to propagate further.
19049
19112
  */
19050
19113
  var ngEventDirectives = {};
19114
+
19115
+ // For events that might fire synchronously during DOM manipulation
19116
+ // we need to execute their event handlers asynchronously using $evalAsync,
19117
+ // so that they are not executed in an inconsistent state.
19118
+ var forceAsyncEvents = {
19119
+ 'blur': true,
19120
+ 'focus': true
19121
+ };
19051
19122
  forEach(
19052
19123
  'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave keydown keyup keypress submit focus blur copy cut paste'.split(' '),
19053
- function(name) {
19054
- var directiveName = directiveNormalize('ng-' + name);
19055
- ngEventDirectives[directiveName] = ['$parse', function($parse) {
19124
+ function(eventName) {
19125
+ var directiveName = directiveNormalize('ng-' + eventName);
19126
+ ngEventDirectives[directiveName] = ['$parse', '$rootScope', function($parse, $rootScope) {
19056
19127
  return {
19057
19128
  compile: function($element, attr) {
19058
19129
  var fn = $parse(attr[directiveName]);
19059
19130
  return function ngEventHandler(scope, element) {
19060
- element.on(lowercase(name), function(event) {
19061
- scope.$apply(function() {
19131
+ element.on(eventName, function(event) {
19132
+ var callback = function() {
19062
19133
  fn(scope, {$event:event});
19063
- });
19134
+ };
19135
+ if (forceAsyncEvents[eventName] && $rootScope.$$phase) {
19136
+ scope.$evalAsync(callback);
19137
+ } else {
19138
+ scope.$apply(callback);
19139
+ }
19064
19140
  });
19065
19141
  };
19066
19142
  }
@@ -19377,6 +19453,10 @@ forEach(
19377
19453
  * @description
19378
19454
  * Specify custom behavior on focus event.
19379
19455
  *
19456
+ * Note: As the `focus` event is executed synchronously when calling `input.focus()`
19457
+ * AngularJS executes the expression using `scope.$evalAsync` if the event is fired
19458
+ * during an `$apply` to ensure a consistent state.
19459
+ *
19380
19460
  * @element window, input, select, textarea, a
19381
19461
  * @priority 0
19382
19462
  * @param {expression} ngFocus {@link guide/expression Expression} to evaluate upon
@@ -19393,6 +19473,14 @@ forEach(
19393
19473
  * @description
19394
19474
  * Specify custom behavior on blur event.
19395
19475
  *
19476
+ * A [blur event](https://developer.mozilla.org/en-US/docs/Web/Events/blur) fires when
19477
+ * an element has lost focus.
19478
+ *
19479
+ * Note: As the `blur` event is executed synchronously also during DOM manipulations
19480
+ * (e.g. removing a focussed input),
19481
+ * AngularJS executes the expression using `scope.$evalAsync` if the event is fired
19482
+ * during an `$apply` to ensure a consistent state.
19483
+ *
19396
19484
  * @element window, input, select, textarea, a
19397
19485
  * @priority 0
19398
19486
  * @param {expression} ngBlur {@link guide/expression Expression} to evaluate upon
@@ -20473,8 +20561,9 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
20473
20561
  if (block && block.scope) lastBlockMap[block.id] = block;
20474
20562
  });
20475
20563
  // This is a duplicate and we need to throw an error
20476
- throw ngRepeatMinErr('dupes', "Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: {0}, Duplicate key: {1}",
20477
- expression, trackById);
20564
+ throw ngRepeatMinErr('dupes',
20565
+ "Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: {0}, Duplicate key: {1}, Duplicate value: {2}",
20566
+ expression, trackById, toJson(value));
20478
20567
  } else {
20479
20568
  // new never before seen block
20480
20569
  nextBlockOrder[index] = { id: trackById };
@@ -20565,8 +20654,8 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
20565
20654
  *
20566
20655
  * @description
20567
20656
  * The `ngShow` directive shows or hides the given HTML element based on the expression
20568
- * provided to the ngShow attribute. The element is shown or hidden by removing or adding
20569
- * the `ng-hide` CSS class onto the element. The `.ng-hide` CSS class is predefined
20657
+ * provided to the `ngShow` attribute. The element is shown or hidden by removing or adding
20658
+ * the `.ng-hide` CSS class onto the element. The `.ng-hide` CSS class is predefined
20570
20659
  * in AngularJS and sets the display style to none (using an !important flag).
20571
20660
  * For CSP mode please add `angular-csp.css` to your html file (see {@link ng.directive:ngCsp ngCsp}).
20572
20661
  *
@@ -20578,8 +20667,8 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
20578
20667
  * <div ng-show="myValue" class="ng-hide"></div>
20579
20668
  * ```
20580
20669
  *
20581
- * When the ngShow expression evaluates to false then the ng-hide CSS class is added to the class attribute
20582
- * on the element causing it to become hidden. When true, the ng-hide CSS class is removed
20670
+ * When the `ngShow` expression evaluates to false then the `.ng-hide` CSS class is added to the class attribute
20671
+ * on the element causing it to become hidden. When true, the `.ng-hide` CSS class is removed
20583
20672
  * from the element causing the element not to appear hidden.
20584
20673
  *
20585
20674
  * <div class="alert alert-warning">
@@ -20589,7 +20678,7 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
20589
20678
  *
20590
20679
  * ## Why is !important used?
20591
20680
  *
20592
- * You may be wondering why !important is used for the .ng-hide CSS class. This is because the `.ng-hide` selector
20681
+ * You may be wondering why !important is used for the `.ng-hide` CSS class. This is because the `.ng-hide` selector
20593
20682
  * can be easily overridden by heavier selectors. For example, something as simple
20594
20683
  * as changing the display style on a HTML list item would make hidden elements appear visible.
20595
20684
  * This also becomes a bigger issue when dealing with CSS frameworks.
@@ -20598,7 +20687,7 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
20598
20687
  * specificity (when !important isn't used with any conflicting styles). If a developer chooses to override the
20599
20688
  * styling to change how to hide an element then it is just a matter of using !important in their own CSS code.
20600
20689
  *
20601
- * ### Overriding .ng-hide
20690
+ * ### Overriding `.ng-hide`
20602
20691
  *
20603
20692
  * By default, the `.ng-hide` class will style the element with `display:none!important`. If you wish to change
20604
20693
  * the hide behavior with ngShow/ngHide then this can be achieved by restating the styles for the `.ng-hide`
@@ -20616,7 +20705,7 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
20616
20705
  *
20617
20706
  * By default you don't need to override in CSS anything and the animations will work around the display style.
20618
20707
  *
20619
- * ## A note about animations with ngShow
20708
+ * ## A note about animations with `ngShow`
20620
20709
  *
20621
20710
  * Animations in ngShow/ngHide work with the show and hide events that are triggered when the directive expression
20622
20711
  * is true and false. This system works like the animation system present with ngClass except that
@@ -20641,8 +20730,8 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
20641
20730
  * property to block during animation states--ngAnimate will handle the style toggling automatically for you.
20642
20731
  *
20643
20732
  * @animations
20644
- * addClass: .ng-hide - happens after the ngShow expression evaluates to a truthy value and the just before contents are set to visible
20645
- * removeClass: .ng-hide - happens after the ngShow expression evaluates to a non truthy value and just before the contents are set to hidden
20733
+ * addClass: `.ng-hide` - happens after the `ngShow` expression evaluates to a truthy value and the just before contents are set to visible
20734
+ * removeClass: `.ng-hide` - happens after the `ngShow` expression evaluates to a non truthy value and just before the contents are set to hidden
20646
20735
  *
20647
20736
  * @element ANY
20648
20737
  * @param {expression} ngShow If the {@link guide/expression expression} is truthy
@@ -20722,7 +20811,7 @@ var ngShowDirective = ['$animate', function($animate) {
20722
20811
  *
20723
20812
  * @description
20724
20813
  * The `ngHide` directive shows or hides the given HTML element based on the expression
20725
- * provided to the ngHide attribute. The element is shown or hidden by removing or adding
20814
+ * provided to the `ngHide` attribute. The element is shown or hidden by removing or adding
20726
20815
  * the `ng-hide` CSS class onto the element. The `.ng-hide` CSS class is predefined
20727
20816
  * in AngularJS and sets the display style to none (using an !important flag).
20728
20817
  * For CSP mode please add `angular-csp.css` to your html file (see {@link ng.directive:ngCsp ngCsp}).
@@ -20735,8 +20824,8 @@ var ngShowDirective = ['$animate', function($animate) {
20735
20824
  * <div ng-hide="myValue"></div>
20736
20825
  * ```
20737
20826
  *
20738
- * When the ngHide expression evaluates to true then the .ng-hide CSS class is added to the class attribute
20739
- * on the element causing it to become hidden. When false, the ng-hide CSS class is removed
20827
+ * When the `.ngHide` expression evaluates to true then the `.ng-hide` CSS class is added to the class attribute
20828
+ * on the element causing it to become hidden. When false, the `.ng-hide` CSS class is removed
20740
20829
  * from the element causing the element not to appear hidden.
20741
20830
  *
20742
20831
  * <div class="alert alert-warning">
@@ -20746,7 +20835,7 @@ var ngShowDirective = ['$animate', function($animate) {
20746
20835
  *
20747
20836
  * ## Why is !important used?
20748
20837
  *
20749
- * You may be wondering why !important is used for the .ng-hide CSS class. This is because the `.ng-hide` selector
20838
+ * You may be wondering why !important is used for the `.ng-hide` CSS class. This is because the `.ng-hide` selector
20750
20839
  * can be easily overridden by heavier selectors. For example, something as simple
20751
20840
  * as changing the display style on a HTML list item would make hidden elements appear visible.
20752
20841
  * This also becomes a bigger issue when dealing with CSS frameworks.
@@ -20755,7 +20844,7 @@ var ngShowDirective = ['$animate', function($animate) {
20755
20844
  * specificity (when !important isn't used with any conflicting styles). If a developer chooses to override the
20756
20845
  * styling to change how to hide an element then it is just a matter of using !important in their own CSS code.
20757
20846
  *
20758
- * ### Overriding .ng-hide
20847
+ * ### Overriding `.ng-hide`
20759
20848
  *
20760
20849
  * By default, the `.ng-hide` class will style the element with `display:none!important`. If you wish to change
20761
20850
  * the hide behavior with ngShow/ngHide then this can be achieved by restating the styles for the `.ng-hide`
@@ -20773,7 +20862,7 @@ var ngShowDirective = ['$animate', function($animate) {
20773
20862
  *
20774
20863
  * By default you don't need to override in CSS anything and the animations will work around the display style.
20775
20864
  *
20776
- * ## A note about animations with ngHide
20865
+ * ## A note about animations with `ngHide`
20777
20866
  *
20778
20867
  * Animations in ngShow/ngHide work with the show and hide events that are triggered when the directive expression
20779
20868
  * is true and false. This system works like the animation system present with ngClass, except that the `.ng-hide`
@@ -20797,8 +20886,8 @@ var ngShowDirective = ['$animate', function($animate) {
20797
20886
  * property to block during animation states--ngAnimate will handle the style toggling automatically for you.
20798
20887
  *
20799
20888
  * @animations
20800
- * removeClass: .ng-hide - happens after the ngHide expression evaluates to a truthy value and just before the contents are set to hidden
20801
- * addClass: .ng-hide - happens after the ngHide expression evaluates to a non truthy value and just before the contents are set to visible
20889
+ * removeClass: `.ng-hide` - happens after the `ngHide` expression evaluates to a truthy value and just before the contents are set to hidden
20890
+ * addClass: `.ng-hide` - happens after the `ngHide` expression evaluates to a non truthy value and just before the contents are set to visible
20802
20891
  *
20803
20892
  * @element ANY
20804
20893
  * @param {expression} ngHide If the {@link guide/expression expression} is truthy then
@@ -21651,6 +21740,19 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
21651
21740
  ctrl.$render = render;
21652
21741
 
21653
21742
  scope.$watchCollection(valuesFn, render);
21743
+ scope.$watchCollection(function () {
21744
+ var locals = {},
21745
+ values = valuesFn(scope);
21746
+ if (values) {
21747
+ var toDisplay = new Array(values.length);
21748
+ for (var i = 0, ii = values.length; i < ii; i++) {
21749
+ locals[valueName] = values[i];
21750
+ toDisplay[i] = displayFn(scope, locals);
21751
+ }
21752
+ return toDisplay;
21753
+ }
21754
+ }, render);
21755
+
21654
21756
  if ( multiple ) {
21655
21757
  scope.$watchCollection(function() { return ctrl.$modelValue; }, render);
21656
21758
  }