angular-gem 1.2.23 → 1.2.24

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.23
2
+ * @license AngularJS v1.2.24
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.23
2
+ * @license AngularJS v1.2.24
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.23
2
+ * @license AngularJS v1.2.24
3
3
  * (c) 2010-2014 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -69,7 +69,7 @@ function minErr(module) {
69
69
  return match;
70
70
  });
71
71
 
72
- message = message + '\nhttp://errors.angularjs.org/1.2.23/' +
72
+ message = message + '\nhttp://errors.angularjs.org/1.2.24/' +
73
73
  (module ? module + '/' : '') + code;
74
74
  for (i = 2; i < arguments.length; i++) {
75
75
  message = message + (i == 2 ? '?' : '&') + 'p' + (i-2) + '=' +
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.2.23
2
+ * @license AngularJS v1.2.24
3
3
  * (c) 2010-2014 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -63,6 +63,8 @@ angular.mock.$Browser = function() {
63
63
  return listener;
64
64
  };
65
65
 
66
+ self.$$checkUrlChange = angular.noop;
67
+
66
68
  self.cookieHash = {};
67
69
  self.lastCookieHash = {};
68
70
  self.deferredFns = [];
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.2.23
2
+ * @license AngularJS v1.2.24
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.23
2
+ * @license AngularJS v1.2.24
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.23
2
+ * @license AngularJS v1.2.24
3
3
  * (c) 2010-2014 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -9790,7 +9790,7 @@ if ( typeof module === "object" && module && typeof module.exports === "object"
9790
9790
  })( window );
9791
9791
 
9792
9792
  /**
9793
- * @license AngularJS v1.2.23
9793
+ * @license AngularJS v1.2.24
9794
9794
  * (c) 2010-2014 Google, Inc. http://angularjs.org
9795
9795
  * License: MIT
9796
9796
  */
@@ -9860,7 +9860,7 @@ function minErr(module) {
9860
9860
  return match;
9861
9861
  });
9862
9862
 
9863
- message = message + '\nhttp://errors.angularjs.org/1.2.23/' +
9863
+ message = message + '\nhttp://errors.angularjs.org/1.2.24/' +
9864
9864
  (module ? module + '/' : '') + code;
9865
9865
  for (i = 2; i < arguments.length; i++) {
9866
9866
  message = message + (i == 2 ? '?' : '&') + 'p' + (i-2) + '=' +
@@ -11779,11 +11779,11 @@ function setupModuleLoader(window) {
11779
11779
  * - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat".
11780
11780
  */
11781
11781
  var version = {
11782
- full: '1.2.23', // all of these placeholder strings will be replaced by grunt's
11782
+ full: '1.2.24', // all of these placeholder strings will be replaced by grunt's
11783
11783
  major: 1, // package task
11784
11784
  minor: 2,
11785
- dot: 23,
11786
- codeName: 'superficial-malady'
11785
+ dot: 24,
11786
+ codeName: 'static-levitation'
11787
11787
  };
11788
11788
 
11789
11789
 
@@ -14374,6 +14374,13 @@ function Browser(window, document, $log, $sniffer) {
14374
14374
  return callback;
14375
14375
  };
14376
14376
 
14377
+ /**
14378
+ * Checks whether the url has changed outside of Angular.
14379
+ * Needs to be exported to be able to check for changes that have been done in sync,
14380
+ * as hashchange/popstate events fire in async.
14381
+ */
14382
+ self.$$checkUrlChange = fireUrlChange;
14383
+
14377
14384
  //////////////////////////////////////////////////////////////
14378
14385
  // Misc API
14379
14386
  //////////////////////////////////////////////////////////////
@@ -18199,7 +18206,7 @@ function $HttpProvider() {
18199
18206
  if (isObject(v)) {
18200
18207
  if (isDate(v)){
18201
18208
  v = v.toISOString();
18202
- } else if (isObject(v)) {
18209
+ } else {
18203
18210
  v = toJson(v);
18204
18211
  }
18205
18212
  }
@@ -18649,7 +18656,7 @@ function $InterpolateProvider() {
18649
18656
  * @description
18650
18657
  * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.
18651
18658
  *
18652
- * Use {@link ng.$interpolateProvider#startSymbol $interpolateProvider#startSymbol} to change
18659
+ * Use {@link ng.$interpolateProvider#startSymbol `$interpolateProvider.startSymbol`} to change
18653
18660
  * the symbol.
18654
18661
  *
18655
18662
  * @returns {string} start symbol.
@@ -18665,7 +18672,7 @@ function $InterpolateProvider() {
18665
18672
  * @description
18666
18673
  * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.
18667
18674
  *
18668
- * Use {@link ng.$interpolateProvider#endSymbol $interpolateProvider#endSymbol} to change
18675
+ * Use {@link ng.$interpolateProvider#endSymbol `$interpolateProvider.endSymbol`} to change
18669
18676
  * the symbol.
18670
18677
  *
18671
18678
  * @returns {string} end symbol.
@@ -19255,17 +19262,16 @@ LocationHashbangInHtml5Url.prototype =
19255
19262
  * Change path, search and hash, when called with parameter and return `$location`.
19256
19263
  *
19257
19264
  * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)
19258
- * @param {string=} replace The path that will be changed
19259
19265
  * @return {string} url
19260
19266
  */
19261
- url: function(url, replace) {
19267
+ url: function(url) {
19262
19268
  if (isUndefined(url))
19263
19269
  return this.$$url;
19264
19270
 
19265
19271
  var match = PATH_MATCH.exec(url);
19266
19272
  if (match[1]) this.path(decodeURIComponent(match[1]));
19267
19273
  if (match[2] || match[1]) this.search(match[3] || '');
19268
- this.hash(match[5] || '', replace);
19274
+ this.hash(match[5] || '');
19269
19275
 
19270
19276
  return this;
19271
19277
  },
@@ -19323,10 +19329,11 @@ LocationHashbangInHtml5Url.prototype =
19323
19329
  * Note: Path should always begin with forward slash (/), this method will add the forward slash
19324
19330
  * if it is missing.
19325
19331
  *
19326
- * @param {string=} path New path
19332
+ * @param {(string|number)=} path New path
19327
19333
  * @return {string} path
19328
19334
  */
19329
19335
  path: locationGetterSetter('$$path', function(path) {
19336
+ path = path ? path.toString() : '';
19330
19337
  return path.charAt(0) == '/' ? path : '/' + path;
19331
19338
  }),
19332
19339
 
@@ -19362,7 +19369,7 @@ LocationHashbangInHtml5Url.prototype =
19362
19369
  * If the argument is a hash object containing an array of values, these values will be encoded
19363
19370
  * as duplicate search parameters in the url.
19364
19371
  *
19365
- * @param {(string|Array<string>|boolean)=} paramValue If `search` is a string, then `paramValue`
19372
+ * @param {(string|Number|Array<string>|boolean)=} paramValue If `search` is a string or number, then `paramValue`
19366
19373
  * will override only a single search property.
19367
19374
  *
19368
19375
  * If `paramValue` is an array, it will override the property of the `search` component of
@@ -19381,7 +19388,8 @@ LocationHashbangInHtml5Url.prototype =
19381
19388
  case 0:
19382
19389
  return this.$$search;
19383
19390
  case 1:
19384
- if (isString(search)) {
19391
+ if (isString(search) || isNumber(search)) {
19392
+ search = search.toString();
19385
19393
  this.$$search = parseKeyValue(search);
19386
19394
  } else if (isObject(search)) {
19387
19395
  // remove object undefined or null properties
@@ -19418,10 +19426,12 @@ LocationHashbangInHtml5Url.prototype =
19418
19426
  *
19419
19427
  * Change hash fragment when called with parameter and return `$location`.
19420
19428
  *
19421
- * @param {string=} hash New hash fragment
19429
+ * @param {(string|number)=} hash New hash fragment
19422
19430
  * @return {string} hash
19423
19431
  */
19424
- hash: locationGetterSetter('$$hash', identity),
19432
+ hash: locationGetterSetter('$$hash', function(hash) {
19433
+ return hash ? hash.toString() : '';
19434
+ }),
19425
19435
 
19426
19436
  /**
19427
19437
  * @ngdoc method
@@ -20616,7 +20626,7 @@ Parser.prototype = {
20616
20626
  var context = contextGetter ? contextGetter(scope, locals) : scope;
20617
20627
 
20618
20628
  for (var i = 0; i < argsFn.length; i++) {
20619
- args.push(argsFn[i](scope, locals));
20629
+ args.push(ensureSafeObject(argsFn[i](scope, locals), parser.text));
20620
20630
  }
20621
20631
  var fnPtr = fn(scope, locals, context) || noop;
20622
20632
 
@@ -20704,13 +20714,15 @@ Parser.prototype = {
20704
20714
  //////////////////////////////////////////////////
20705
20715
 
20706
20716
  function setter(obj, path, setValue, fullExp, options) {
20717
+ ensureSafeObject(obj, fullExp);
20718
+
20707
20719
  //needed?
20708
20720
  options = options || {};
20709
20721
 
20710
20722
  var element = path.split('.'), key;
20711
20723
  for (var i = 0; element.length > 1; i++) {
20712
20724
  key = ensureSafeMemberName(element.shift(), fullExp);
20713
- var propertyObj = obj[key];
20725
+ var propertyObj = ensureSafeObject(obj[key], fullExp);
20714
20726
  if (!propertyObj) {
20715
20727
  propertyObj = {};
20716
20728
  obj[key] = propertyObj;
@@ -20730,7 +20742,6 @@ function setter(obj, path, setValue, fullExp, options) {
20730
20742
  }
20731
20743
  }
20732
20744
  key = ensureSafeMemberName(element.shift(), fullExp);
20733
- ensureSafeObject(obj, fullExp);
20734
20745
  ensureSafeObject(obj[key], fullExp);
20735
20746
  obj[key] = setValue;
20736
20747
  return setValue;
@@ -21794,10 +21805,26 @@ function $RootScopeProvider(){
21794
21805
  /**
21795
21806
  * @ngdoc property
21796
21807
  * @name $rootScope.Scope#$id
21797
- * @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for
21798
- * debugging.
21808
+ *
21809
+ * @description
21810
+ * Unique scope ID (monotonically increasing) useful for debugging.
21799
21811
  */
21800
21812
 
21813
+ /**
21814
+ * @ngdoc property
21815
+ * @name $rootScope.Scope#$parent
21816
+ *
21817
+ * @description
21818
+ * Reference to the parent scope.
21819
+ */
21820
+
21821
+ /**
21822
+ * @ngdoc property
21823
+ * @name $rootScope.Scope#$root
21824
+ *
21825
+ * @description
21826
+ * Reference to the root scope.
21827
+ */
21801
21828
 
21802
21829
  Scope.prototype = {
21803
21830
  constructor: Scope,
@@ -21809,9 +21836,8 @@ function $RootScopeProvider(){
21809
21836
  * @description
21810
21837
  * Creates a new child {@link ng.$rootScope.Scope scope}.
21811
21838
  *
21812
- * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} and
21813
- * {@link ng.$rootScope.Scope#$digest $digest()} events. The scope can be removed from the
21814
- * scope hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.
21839
+ * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} event.
21840
+ * The scope can be removed from the scope hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.
21815
21841
  *
21816
21842
  * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is
21817
21843
  * desired for the scope and its child scopes to be permanently detached from the parent and
@@ -22264,6 +22290,8 @@ function $RootScopeProvider(){
22264
22290
  logIdx, logMsg, asyncTask;
22265
22291
 
22266
22292
  beginPhase('$digest');
22293
+ // Check for changes to browser url that happened in sync before the call to $digest
22294
+ $browser.$$checkUrlChange();
22267
22295
 
22268
22296
  lastDirtyWatch = null;
22269
22297
 
@@ -24317,16 +24345,6 @@ function $WindowProvider(){
24317
24345
  * For more information about how angular filters work, and how to create your own filters, see
24318
24346
  * {@link guide/filter Filters} in the Angular Developer Guide.
24319
24347
  */
24320
- /**
24321
- * @ngdoc method
24322
- * @name $filterProvider#register
24323
- * @description
24324
- * Register filter factory function.
24325
- *
24326
- * @param {String} name Name of the filter.
24327
- * @param {Function} fn The filter factory function which is injectable.
24328
- */
24329
-
24330
24348
 
24331
24349
  /**
24332
24350
  * @ngdoc service
@@ -24365,7 +24383,7 @@ function $FilterProvider($provide) {
24365
24383
 
24366
24384
  /**
24367
24385
  * @ngdoc method
24368
- * @name $controllerProvider#register
24386
+ * @name $filterProvider#register
24369
24387
  * @param {string|Object} name Name of the filter function, or an object map of filters where
24370
24388
  * the keys are the filter names and the values are the filter factories.
24371
24389
  * @returns {Object} Registered filter instance, or if a map of filters was provided then a map
@@ -24438,7 +24456,9 @@ function $FilterProvider($provide) {
24438
24456
  * which have property `name` containing "M" and property `phone` containing "1". A special
24439
24457
  * property name `$` can be used (as in `{$:"text"}`) to accept a match against any
24440
24458
  * property of the object. That's equivalent to the simple substring match with a `string`
24441
- * as described above.
24459
+ * as described above. The predicate can be negated by prefixing the string with `!`.
24460
+ * For Example `{name: "!M"}` predicate will return an array of items which have property `name`
24461
+ * not containing "M".
24442
24462
  *
24443
24463
  * - `function(value)`: A predicate function can be used to write arbitrary filters. The function is
24444
24464
  * called for each element of `array`. The final result is an array of those elements that
@@ -24787,6 +24807,10 @@ function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {
24787
24807
  // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round
24788
24808
  number = +(Math.round(+(number.toString() + 'e' + fractionSize)).toString() + 'e' + -fractionSize);
24789
24809
 
24810
+ if (number === 0) {
24811
+ isNegative = false;
24812
+ }
24813
+
24790
24814
  var fraction = ('' + number).split(DECIMAL_SEP);
24791
24815
  var whole = fraction[0];
24792
24816
  fraction = fraction[1] || '';
@@ -24956,8 +24980,8 @@ var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+
24956
24980
  * * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm)
24957
24981
  * * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm)
24958
24982
  *
24959
- * `format` string can contain literal values. These need to be quoted with single quotes (e.g.
24960
- * `"h 'in the morning'"`). In order to output single quote, use two single quotes in a sequence
24983
+ * `format` string can contain literal values. These need to be escaped by surrounding with single quotes (e.g.
24984
+ * `"h 'in the morning'"`). In order to output a single quote, escape it - i.e., two single quotes in a sequence
24961
24985
  * (e.g. `"h 'o''clock'"`).
24962
24986
  *
24963
24987
  * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or
@@ -24977,6 +25001,8 @@ var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+
24977
25001
  <span>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span><br>
24978
25002
  <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:
24979
25003
  <span>{{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}</span><br>
25004
+ <span ng-non-bindable>{{1288323623006 | date:"MM/dd/yyyy 'at' h:mma"}}</span>:
25005
+ <span>{{'1288323623006' | date:"MM/dd/yyyy 'at' h:mma"}}</span><br>
24980
25006
  </file>
24981
25007
  <file name="protractor.js" type="protractor">
24982
25008
  it('should format date', function() {
@@ -24986,6 +25012,8 @@ var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+
24986
25012
  toMatch(/2010\-10\-2\d \d{2}:\d{2}:\d{2} (\-|\+)?\d{4}/);
24987
25013
  expect(element(by.binding("'1288323623006' | date:'MM/dd/yyyy @ h:mma'")).getText()).
24988
25014
  toMatch(/10\/2\d\/2010 @ \d{1,2}:\d{2}(AM|PM)/);
25015
+ expect(element(by.binding("'1288323623006' | date:\"MM/dd/yyyy 'at' h:mma\"")).getText()).
25016
+ toMatch(/10\/2\d\/2010 at \d{1,2}:\d{2}(AM|PM)/);
24989
25017
  });
24990
25018
  </file>
24991
25019
  </example>
@@ -25347,7 +25375,7 @@ function limitToFilter(){
25347
25375
  orderByFilter.$inject = ['$parse'];
25348
25376
  function orderByFilter($parse){
25349
25377
  return function(array, sortPredicate, reverseOrder) {
25350
- if (!isArray(array)) return array;
25378
+ if (!(isArrayLike(array))) return array;
25351
25379
  if (!sortPredicate) return array;
25352
25380
  sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];
25353
25381
  sortPredicate = map(sortPredicate, function(predicate){
@@ -25934,8 +25962,9 @@ function FormController(element, attrs, $scope, $animate) {
25934
25962
  // convenience method for easy toggling of classes
25935
25963
  function toggleValidCss(isValid, validationErrorKey) {
25936
25964
  validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';
25937
- $animate.removeClass(element, (isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey);
25938
- $animate.addClass(element, (isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);
25965
+ $animate.setClass(element,
25966
+ (isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey,
25967
+ (isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey);
25939
25968
  }
25940
25969
 
25941
25970
  /**
@@ -26150,8 +26179,6 @@ function FormController(element, attrs, $scope, $animate) {
26150
26179
  * hitting enter in any of the input fields will trigger the click handler on the *first* button or
26151
26180
  * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)
26152
26181
  *
26153
- * @param {string=} name Name of the form. If specified, the form controller will be published into
26154
- * related scope, under this name.
26155
26182
  *
26156
26183
  * ## Animation Hooks
26157
26184
  *
@@ -26229,6 +26256,8 @@ function FormController(element, attrs, $scope, $animate) {
26229
26256
  </file>
26230
26257
  </example>
26231
26258
  *
26259
+ * @param {string=} name Name of the form. If specified, the form controller will be published into
26260
+ * related scope, under this name.
26232
26261
  */
26233
26262
  var formDirectiveFactory = function(isNgForm) {
26234
26263
  return ['$timeout', function($timeout) {
@@ -26812,7 +26841,7 @@ function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
26812
26841
  // a row.
26813
26842
  var revalidate = validity && ctrl.$$hasNativeValidators;
26814
26843
  if (ctrl.$viewValue !== value || (value === '' && revalidate)) {
26815
- if (scope.$$phase) {
26844
+ if (scope.$root.$$phase) {
26816
26845
  ctrl.$setViewValue(value);
26817
26846
  } else {
26818
26847
  scope.$apply(function() {
@@ -28854,7 +28883,9 @@ var ngControllerDirective = [function() {
28854
28883
  <button ng-click="count = count + 1" ng-init="count=0">
28855
28884
  Increment
28856
28885
  </button>
28857
- count: {{count}}
28886
+ <span>
28887
+ count: {{count}}
28888
+ <span>
28858
28889
  </file>
28859
28890
  <file name="protractor.js" type="protractor">
28860
28891
  it('should check ng-click', function() {
@@ -28872,19 +28903,33 @@ var ngControllerDirective = [function() {
28872
28903
  * Events that are handled via these handler are always configured not to propagate further.
28873
28904
  */
28874
28905
  var ngEventDirectives = {};
28906
+
28907
+ // For events that might fire synchronously during DOM manipulation
28908
+ // we need to execute their event handlers asynchronously using $evalAsync,
28909
+ // so that they are not executed in an inconsistent state.
28910
+ var forceAsyncEvents = {
28911
+ 'blur': true,
28912
+ 'focus': true
28913
+ };
28875
28914
  forEach(
28876
28915
  'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave keydown keyup keypress submit focus blur copy cut paste'.split(' '),
28877
28916
  function(name) {
28878
28917
  var directiveName = directiveNormalize('ng-' + name);
28879
- ngEventDirectives[directiveName] = ['$parse', function($parse) {
28918
+ ngEventDirectives[directiveName] = ['$parse', '$rootScope', function($parse, $rootScope) {
28880
28919
  return {
28881
28920
  compile: function($element, attr) {
28882
28921
  var fn = $parse(attr[directiveName]);
28883
28922
  return function ngEventHandler(scope, element) {
28884
- element.on(lowercase(name), function(event) {
28885
- scope.$apply(function() {
28923
+ var eventName = lowercase(name);
28924
+ element.on(eventName, function(event) {
28925
+ var callback = function() {
28886
28926
  fn(scope, {$event:event});
28887
- });
28927
+ };
28928
+ if (forceAsyncEvents[eventName] && $rootScope.$$phase) {
28929
+ scope.$evalAsync(callback);
28930
+ } else {
28931
+ scope.$apply(callback);
28932
+ }
28888
28933
  });
28889
28934
  };
28890
28935
  }
@@ -29201,6 +29246,10 @@ forEach(
29201
29246
  * @description
29202
29247
  * Specify custom behavior on focus event.
29203
29248
  *
29249
+ * Note: As the `focus` event is executed synchronously when calling `input.focus()`
29250
+ * AngularJS executes the expression using `scope.$evalAsync` if the event is fired
29251
+ * during an `$apply` to ensure a consistent state.
29252
+ *
29204
29253
  * @element window, input, select, textarea, a
29205
29254
  * @priority 0
29206
29255
  * @param {expression} ngFocus {@link guide/expression Expression} to evaluate upon
@@ -29217,6 +29266,14 @@ forEach(
29217
29266
  * @description
29218
29267
  * Specify custom behavior on blur event.
29219
29268
  *
29269
+ * A [blur event](https://developer.mozilla.org/en-US/docs/Web/Events/blur) fires when
29270
+ * an element has lost focus.
29271
+ *
29272
+ * Note: As the `blur` event is executed synchronously also during DOM manipulations
29273
+ * (e.g. removing a focussed input),
29274
+ * AngularJS executes the expression using `scope.$evalAsync` if the event is fired
29275
+ * during an `$apply` to ensure a consistent state.
29276
+ *
29220
29277
  * @element window, input, select, textarea, a
29221
29278
  * @priority 0
29222
29279
  * @param {expression} ngBlur {@link guide/expression Expression} to evaluate upon
@@ -30297,8 +30354,9 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
30297
30354
  if (block && block.scope) lastBlockMap[block.id] = block;
30298
30355
  });
30299
30356
  // This is a duplicate and we need to throw an error
30300
- throw ngRepeatMinErr('dupes', "Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: {0}, Duplicate key: {1}",
30301
- expression, trackById);
30357
+ throw ngRepeatMinErr('dupes',
30358
+ "Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: {0}, Duplicate key: {1}, Duplicate value: {2}",
30359
+ expression, trackById, toJson(value));
30302
30360
  } else {
30303
30361
  // new never before seen block
30304
30362
  nextBlockOrder[index] = { id: trackById };