angularjs-rails 1.3.4 → 1.3.6

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.
Files changed (27) hide show
  1. checksums.yaml +4 -4
  2. data/lib/angularjs-rails/version.rb +2 -2
  3. data/vendor/assets/javascripts/angular-animate.js +121 -120
  4. data/vendor/assets/javascripts/angular-aria.js +39 -28
  5. data/vendor/assets/javascripts/angular-cookies.js +1 -1
  6. data/vendor/assets/javascripts/angular-loader.js +2 -2
  7. data/vendor/assets/javascripts/angular-messages.js +1 -1
  8. data/vendor/assets/javascripts/angular-mocks.js +10 -8
  9. data/vendor/assets/javascripts/angular-resource.js +1 -1
  10. data/vendor/assets/javascripts/angular-route.js +2 -3
  11. data/vendor/assets/javascripts/angular-sanitize.js +7 -5
  12. data/vendor/assets/javascripts/angular-scenario.js +316 -231
  13. data/vendor/assets/javascripts/angular-touch.js +1 -1
  14. data/vendor/assets/javascripts/angular.js +314 -229
  15. data/vendor/assets/javascripts/unstable/angular-animate.js +121 -120
  16. data/vendor/assets/javascripts/unstable/angular-aria.js +39 -28
  17. data/vendor/assets/javascripts/unstable/angular-cookies.js +1 -1
  18. data/vendor/assets/javascripts/unstable/angular-loader.js +2 -2
  19. data/vendor/assets/javascripts/unstable/angular-messages.js +1 -1
  20. data/vendor/assets/javascripts/unstable/angular-mocks.js +10 -8
  21. data/vendor/assets/javascripts/unstable/angular-resource.js +1 -1
  22. data/vendor/assets/javascripts/unstable/angular-route.js +2 -3
  23. data/vendor/assets/javascripts/unstable/angular-sanitize.js +7 -5
  24. data/vendor/assets/javascripts/unstable/angular-scenario.js +316 -231
  25. data/vendor/assets/javascripts/unstable/angular-touch.js +1 -1
  26. data/vendor/assets/javascripts/unstable/angular.js +314 -229
  27. metadata +2 -2
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.3.4
2
+ * @license AngularJS v1.3.36
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.3.4
2
+ * @license AngularJS v1.3.36
3
3
  * (c) 2010-2014 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -55,7 +55,7 @@ function minErr(module, ErrorConstructor) {
55
55
  return match;
56
56
  });
57
57
 
58
- message = message + '\nhttp://errors.angularjs.org/1.3.4/' +
58
+ message = message + '\nhttp://errors.angularjs.org/1.3.36/' +
59
59
  (module ? module + '/' : '') + code;
60
60
  for (i = 2; i < arguments.length; i++) {
61
61
  message = message + (i == 2 ? '?' : '&') + 'p' + (i - 2) + '=' +
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.3.4
2
+ * @license AngularJS v1.3.36
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.3.4
2
+ * @license AngularJS v1.3.36
3
3
  * (c) 2010-2014 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -1119,7 +1119,7 @@ angular.mock.dump = function(object) {
1119
1119
  ```
1120
1120
  */
1121
1121
  angular.mock.$HttpBackendProvider = function() {
1122
- this.$get = ['$rootScope', createHttpBackendMock];
1122
+ this.$get = ['$rootScope', '$timeout', createHttpBackendMock];
1123
1123
  };
1124
1124
 
1125
1125
  /**
@@ -1136,7 +1136,7 @@ angular.mock.$HttpBackendProvider = function() {
1136
1136
  * @param {Object=} $browser Auto-flushing enabled if specified
1137
1137
  * @return {Object} Instance of $httpBackend mock
1138
1138
  */
1139
- function createHttpBackendMock($rootScope, $delegate, $browser) {
1139
+ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
1140
1140
  var definitions = [],
1141
1141
  expectations = [],
1142
1142
  responses = [],
@@ -1149,7 +1149,7 @@ function createHttpBackendMock($rootScope, $delegate, $browser) {
1149
1149
  return function() {
1150
1150
  return angular.isNumber(status)
1151
1151
  ? [status, data, headers, statusText]
1152
- : [200, status, data];
1152
+ : [200, status, data, headers];
1153
1153
  };
1154
1154
  }
1155
1155
 
@@ -1166,7 +1166,9 @@ function createHttpBackendMock($rootScope, $delegate, $browser) {
1166
1166
  }
1167
1167
 
1168
1168
  function wrapResponse(wrapped) {
1169
- if (!$browser && timeout && timeout.then) timeout.then(handleTimeout);
1169
+ if (!$browser && timeout) {
1170
+ timeout.then ? timeout.then(handleTimeout) : $timeout(handleTimeout, timeout);
1171
+ }
1170
1172
 
1171
1173
  return handleResponse;
1172
1174
 
@@ -2040,7 +2042,7 @@ angular.module('ngMockE2E', ['ng']).config(['$provide', function($provide) {
2040
2042
  */
2041
2043
  angular.mock.e2e = {};
2042
2044
  angular.mock.e2e.$httpBackendDecorator =
2043
- ['$rootScope', '$delegate', '$browser', createHttpBackendMock];
2045
+ ['$rootScope', '$timeout', '$delegate', '$browser', createHttpBackendMock];
2044
2046
 
2045
2047
 
2046
2048
  /**
@@ -2054,7 +2056,7 @@ angular.mock.e2e.$httpBackendDecorator =
2054
2056
  *
2055
2057
  * In addition to all the regular `Scope` methods, the following helper methods are available:
2056
2058
  */
2057
- angular.mock.$RootScopeDecorator = function($delegate) {
2059
+ angular.mock.$RootScopeDecorator = ['$delegate', function($delegate) {
2058
2060
 
2059
2061
  var $rootScopePrototype = Object.getPrototypeOf($delegate);
2060
2062
 
@@ -2126,7 +2128,7 @@ angular.mock.$RootScopeDecorator = function($delegate) {
2126
2128
 
2127
2129
  return count;
2128
2130
  }
2129
- };
2131
+ }];
2130
2132
 
2131
2133
 
2132
2134
  if (window.jasmine || window.mocha) {
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.3.4
2
+ * @license AngularJS v1.3.36
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.3.4
2
+ * @license AngularJS v1.3.36
3
3
  * (c) 2010-2014 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -180,7 +180,7 @@ function $RouteProvider() {
180
180
  * @description
181
181
  *
182
182
  * A boolean property indicating if routes defined
183
- * using this provider should be matched using a case sensitive
183
+ * using this provider should be matched using a case insensitive
184
184
  * algorithm. Defaults to `false`.
185
185
  */
186
186
  this.caseInsensitiveMatch = false;
@@ -788,7 +788,6 @@ ngRouteModule.directive('ngView', ngViewFillContentFactory);
788
788
  .view-animate-container {
789
789
  position:relative;
790
790
  height:100px!important;
791
- position:relative;
792
791
  background:white;
793
792
  border:1px solid black;
794
793
  height:40px;
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.3.4
2
+ * @license AngularJS v1.3.36
3
3
  * (c) 2010-2014 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -628,7 +628,7 @@ angular.module('ngSanitize', []).provider('$sanitize', $SanitizeProvider);
628
628
  */
629
629
  angular.module('ngSanitize').filter('linky', ['$sanitize', function($sanitize) {
630
630
  var LINKY_URL_REGEXP =
631
- /((ftp|https?):\/\/|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s.;,(){}<>"]/,
631
+ /((ftp|https?):\/\/|(www\.)|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s.;,(){}<>"”’]/,
632
632
  MAILTO_REGEXP = /^mailto:/;
633
633
 
634
634
  return function(text, target) {
@@ -641,8 +641,10 @@ angular.module('ngSanitize').filter('linky', ['$sanitize', function($sanitize) {
641
641
  while ((match = raw.match(LINKY_URL_REGEXP))) {
642
642
  // We can not end in these as they are sometimes found at the end of the sentence
643
643
  url = match[0];
644
- // if we did not match ftp/http/mailto then assume mailto
645
- if (match[2] == match[3]) url = 'mailto:' + url;
644
+ // if we did not match ftp/http/www/mailto then assume mailto
645
+ if (!match[2] && !match[4]) {
646
+ url = (match[3] ? 'http://' : 'mailto:') + url;
647
+ }
646
648
  i = match.index;
647
649
  addText(raw.substr(0, i));
648
650
  addLink(url, match[0].replace(MAILTO_REGEXP, ''));
@@ -666,7 +668,7 @@ angular.module('ngSanitize').filter('linky', ['$sanitize', function($sanitize) {
666
668
  '" ');
667
669
  }
668
670
  html.push('href="',
669
- url.replace('"', '&quot;'),
671
+ url.replace(/"/g, '&quot;'),
670
672
  '">');
671
673
  addText(text);
672
674
  html.push('</a>');
@@ -9190,7 +9190,7 @@ return jQuery;
9190
9190
  }));
9191
9191
 
9192
9192
  /**
9193
- * @license AngularJS v1.3.4
9193
+ * @license AngularJS v1.3.36
9194
9194
  * (c) 2010-2014 Google, Inc. http://angularjs.org
9195
9195
  * License: MIT
9196
9196
  */
@@ -9246,7 +9246,7 @@ function minErr(module, ErrorConstructor) {
9246
9246
  return match;
9247
9247
  });
9248
9248
 
9249
- message = message + '\nhttp://errors.angularjs.org/1.3.4/' +
9249
+ message = message + '\nhttp://errors.angularjs.org/1.3.36/' +
9250
9250
  (module ? module + '/' : '') + code;
9251
9251
  for (i = 2; i < arguments.length; i++) {
9252
9252
  message = message + (i == 2 ? '?' : '&') + 'p' + (i - 2) + '=' +
@@ -9418,8 +9418,8 @@ if ('i' !== 'I'.toLowerCase()) {
9418
9418
  }
9419
9419
 
9420
9420
 
9421
- var /** holds major version number for IE or NaN for real browsers */
9422
- msie,
9421
+ var
9422
+ msie, // holds major version number for IE, or NaN if UA is not IE.
9423
9423
  jqLite, // delay binding since jQuery could be loaded after us.
9424
9424
  jQuery, // delay binding
9425
9425
  slice = [].slice,
@@ -10220,12 +10220,16 @@ function toJsonReplacer(key, value) {
10220
10220
  * stripped since angular uses this notation internally.
10221
10221
  *
10222
10222
  * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.
10223
- * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.
10223
+ * @param {boolean|number=} pretty If set to true, the JSON output will contain newlines and whitespace.
10224
+ * If set to an integer, the JSON output will contain that many spaces per indentation (the default is 2).
10224
10225
  * @returns {string|undefined} JSON-ified string representing `obj`.
10225
10226
  */
10226
10227
  function toJson(obj, pretty) {
10227
10228
  if (typeof obj === 'undefined') return undefined;
10228
- return JSON.stringify(obj, toJsonReplacer, pretty ? ' ' : null);
10229
+ if (!isNumber(pretty)) {
10230
+ pretty = pretty ? 2 : null;
10231
+ }
10232
+ return JSON.stringify(obj, toJsonReplacer, pretty);
10229
10233
  }
10230
10234
 
10231
10235
 
@@ -11273,7 +11277,8 @@ function toDebugString(obj) {
11273
11277
  $TimeoutProvider,
11274
11278
  $$RAFProvider,
11275
11279
  $$AsyncCallbackProvider,
11276
- $WindowProvider
11280
+ $WindowProvider,
11281
+ $$jqLiteProvider
11277
11282
  */
11278
11283
 
11279
11284
 
@@ -11292,11 +11297,11 @@ function toDebugString(obj) {
11292
11297
  * - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat".
11293
11298
  */
11294
11299
  var version = {
11295
- full: '1.3.4', // all of these placeholder strings will be replaced by grunt's
11300
+ full: '1.3.36', // all of these placeholder strings will be replaced by grunt's
11296
11301
  major: 1, // package task
11297
11302
  minor: 3,
11298
- dot: 4,
11299
- codeName: 'highfalutin-petroglyph'
11303
+ dot: 36,
11304
+ codeName: 'robofunky-danceblaster'
11300
11305
  };
11301
11306
 
11302
11307
 
@@ -11426,7 +11431,8 @@ function publishExternalAPI(angular) {
11426
11431
  $timeout: $TimeoutProvider,
11427
11432
  $window: $WindowProvider,
11428
11433
  $$rAF: $$RAFProvider,
11429
- $$asyncCallback: $$AsyncCallbackProvider
11434
+ $$asyncCallback: $$AsyncCallbackProvider,
11435
+ $$jqLite: $$jqLiteProvider
11430
11436
  });
11431
11437
  }
11432
11438
  ]);
@@ -12436,6 +12442,27 @@ forEach({
12436
12442
  JQLite.prototype.unbind = JQLite.prototype.off;
12437
12443
  });
12438
12444
 
12445
+
12446
+ // Provider for private $$jqLite service
12447
+ function $$jqLiteProvider() {
12448
+ this.$get = function $$jqLite() {
12449
+ return extend(JQLite, {
12450
+ hasClass: function(node, classes) {
12451
+ if (node.attr) node = node[0];
12452
+ return jqLiteHasClass(node, classes);
12453
+ },
12454
+ addClass: function(node, classes) {
12455
+ if (node.attr) node = node[0];
12456
+ return jqLiteAddClass(node, classes);
12457
+ },
12458
+ removeClass: function(node, classes) {
12459
+ if (node.attr) node = node[0];
12460
+ return jqLiteRemoveClass(node, classes);
12461
+ }
12462
+ });
12463
+ };
12464
+ }
12465
+
12439
12466
  /**
12440
12467
  * Computes a hash of an 'obj'.
12441
12468
  * Hash of a:
@@ -12688,6 +12715,7 @@ function annotate(fn, strictDi, name) {
12688
12715
  * Return an instance of the service.
12689
12716
  *
12690
12717
  * @param {string} name The name of the instance to retrieve.
12718
+ * @param {string} caller An optional string to provide the origin of the function call for error messages.
12691
12719
  * @return {*} The instance.
12692
12720
  */
12693
12721
 
@@ -13138,14 +13166,17 @@ function createInjector(modulesToLoad, strictDi) {
13138
13166
  }
13139
13167
  },
13140
13168
  providerInjector = (providerCache.$injector =
13141
- createInternalInjector(providerCache, function() {
13169
+ createInternalInjector(providerCache, function(serviceName, caller) {
13170
+ if (angular.isString(caller)) {
13171
+ path.push(caller);
13172
+ }
13142
13173
  throw $injectorMinErr('unpr', "Unknown provider: {0}", path.join(' <- '));
13143
13174
  })),
13144
13175
  instanceCache = {},
13145
13176
  instanceInjector = (instanceCache.$injector =
13146
- createInternalInjector(instanceCache, function(servicename) {
13147
- var provider = providerInjector.get(servicename + providerSuffix);
13148
- return instanceInjector.invoke(provider.$get, provider, undefined, servicename);
13177
+ createInternalInjector(instanceCache, function(serviceName, caller) {
13178
+ var provider = providerInjector.get(serviceName + providerSuffix, caller);
13179
+ return instanceInjector.invoke(provider.$get, provider, undefined, serviceName);
13149
13180
  }));
13150
13181
 
13151
13182
 
@@ -13180,7 +13211,7 @@ function createInjector(modulesToLoad, strictDi) {
13180
13211
 
13181
13212
  function enforceReturnValue(name, factory) {
13182
13213
  return function enforcedReturnValue() {
13183
- var result = instanceInjector.invoke(factory, this, undefined, name);
13214
+ var result = instanceInjector.invoke(factory, this);
13184
13215
  if (isUndefined(result)) {
13185
13216
  throw $injectorMinErr('undef', "Provider '{0}' must return a value from $get factory method.", name);
13186
13217
  }
@@ -13275,7 +13306,7 @@ function createInjector(modulesToLoad, strictDi) {
13275
13306
 
13276
13307
  function createInternalInjector(cache, factory) {
13277
13308
 
13278
- function getService(serviceName) {
13309
+ function getService(serviceName, caller) {
13279
13310
  if (cache.hasOwnProperty(serviceName)) {
13280
13311
  if (cache[serviceName] === INSTANTIATING) {
13281
13312
  throw $injectorMinErr('cdep', 'Circular dependency found: {0}',
@@ -13286,7 +13317,7 @@ function createInjector(modulesToLoad, strictDi) {
13286
13317
  try {
13287
13318
  path.unshift(serviceName);
13288
13319
  cache[serviceName] = INSTANTIATING;
13289
- return cache[serviceName] = factory(serviceName);
13320
+ return cache[serviceName] = factory(serviceName, caller);
13290
13321
  } catch (err) {
13291
13322
  if (cache[serviceName] === INSTANTIATING) {
13292
13323
  delete cache[serviceName];
@@ -13318,7 +13349,7 @@ function createInjector(modulesToLoad, strictDi) {
13318
13349
  args.push(
13319
13350
  locals && locals.hasOwnProperty(key)
13320
13351
  ? locals[key]
13321
- : getService(key)
13352
+ : getService(key, serviceName)
13322
13353
  );
13323
13354
  }
13324
13355
  if (isArray(fn)) {
@@ -14062,6 +14093,11 @@ function Browser(window, document, $log, $sniffer) {
14062
14093
  }
14063
14094
  }
14064
14095
 
14096
+ function getHash(url) {
14097
+ var index = url.indexOf('#');
14098
+ return index === -1 ? '' : url.substr(index + 1);
14099
+ }
14100
+
14065
14101
  /**
14066
14102
  * @private
14067
14103
  * Note: this method is used only by scenario runner
@@ -14191,8 +14227,10 @@ function Browser(window, document, $log, $sniffer) {
14191
14227
  }
14192
14228
  if (replace) {
14193
14229
  location.replace(url);
14194
- } else {
14230
+ } else if (!sameBase) {
14195
14231
  location.href = url;
14232
+ } else {
14233
+ location.hash = getHash(url);
14196
14234
  }
14197
14235
  }
14198
14236
  return self;
@@ -14971,7 +15009,7 @@ function $TemplateCacheProvider() {
14971
15009
  * #### `multiElement`
14972
15010
  * When this property is set to true, the HTML compiler will collect DOM nodes between
14973
15011
  * nodes with the attributes `directive-name-start` and `directive-name-end`, and group them
14974
- * together as the directive elements. It is recomended that this feature be used on directives
15012
+ * together as the directive elements. It is recommended that this feature be used on directives
14975
15013
  * which are not strictly behavioural (such as {@link ngClick}), and which
14976
15014
  * do not manipulate or replace child nodes (such as {@link ngInclude}).
14977
15015
  *
@@ -15659,7 +15697,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
15659
15697
  * Retrieves or overrides the default regular expression that is used for whitelisting of safe
15660
15698
  * urls during a[href] sanitization.
15661
15699
  *
15662
- * The sanitization is a security measure aimed at prevent XSS attacks via html links.
15700
+ * The sanitization is a security measure aimed at preventing XSS attacks via html links.
15663
15701
  *
15664
15702
  * Any url about to be assigned to a[href] via data-binding is first normalized and turned into
15665
15703
  * an absolute url. Afterwards, the url is matched against the `aHrefSanitizationWhitelist`
@@ -15726,7 +15764,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
15726
15764
  * * `ng-binding` CSS class
15727
15765
  * * `$binding` data property containing an array of the binding expressions
15728
15766
  *
15729
- * You may want to use this in production for a significant performance boost. See
15767
+ * You may want to disable this in production for a significant performance boost. See
15730
15768
  * {@link guide/production#disabling-debug-data Disabling Debug Data} for more.
15731
15769
  *
15732
15770
  * The default value is true.
@@ -15763,6 +15801,21 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
15763
15801
  };
15764
15802
 
15765
15803
  Attributes.prototype = {
15804
+ /**
15805
+ * @ngdoc method
15806
+ * @name $compile.directive.Attributes#$normalize
15807
+ * @kind function
15808
+ *
15809
+ * @description
15810
+ * Converts an attribute name (e.g. dash/colon/underscore-delimited string, optionally prefixed with `x-` or
15811
+ * `data-`) to its normalized, camelCase form.
15812
+ *
15813
+ * Also there is special case for Moz prefix starting with upper case letter.
15814
+ *
15815
+ * For further information check out the guide on {@link guide/directive#matching-directives Matching Directives}
15816
+ *
15817
+ * @param {string} name Name to normalize
15818
+ */
15766
15819
  $normalize: directiveNormalize,
15767
15820
 
15768
15821
 
@@ -17341,13 +17394,6 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
17341
17394
  var PREFIX_REGEXP = /^((?:x|data)[\:\-_])/i;
17342
17395
  /**
17343
17396
  * Converts all accepted directives format into proper directive name.
17344
- * All of these will become 'myDirective':
17345
- * my:Directive
17346
- * my-directive
17347
- * x-my-directive
17348
- * data-my:directive
17349
- *
17350
- * Also there is special case for Moz prefix starting with upper case letter.
17351
17397
  * @param name Name to normalize
17352
17398
  */
17353
17399
  function directiveNormalize(name) {
@@ -18283,12 +18329,14 @@ function $HttpProvider() {
18283
18329
  * `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –
18284
18330
  * transform function or an array of such functions. The transform function takes the http
18285
18331
  * request body and headers and returns its transformed (typically serialized) version.
18286
- * See {@link #overriding-the-default-transformations-per-request Overriding the Default Transformations}
18332
+ * See {@link ng.$http#overriding-the-default-transformations-per-request
18333
+ * Overriding the Default Transformations}
18287
18334
  * - **transformResponse** –
18288
18335
  * `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –
18289
18336
  * transform function or an array of such functions. The transform function takes the http
18290
18337
  * response body and headers and returns its transformed (typically deserialized) version.
18291
- * See {@link #overriding-the-default-transformations-per-request Overriding the Default Transformations}
18338
+ * See {@link ng.$http#overriding-the-default-transformations-per-request
18339
+ * Overriding the Default Transformations}
18292
18340
  * - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the
18293
18341
  * GET request, otherwise if a cache instance built with
18294
18342
  * {@link ng.$cacheFactory $cacheFactory}, this cache will be used for
@@ -18698,8 +18746,7 @@ function $HttpProvider() {
18698
18746
  if (isDefined(cachedResp)) {
18699
18747
  if (isPromiseLike(cachedResp)) {
18700
18748
  // cached request has already been sent, but there is no response yet
18701
- cachedResp.then(removePendingReq, removePendingReq);
18702
- return cachedResp;
18749
+ cachedResp.then(resolvePromiseWithResult, resolvePromiseWithResult);
18703
18750
  } else {
18704
18751
  // serving from cache
18705
18752
  if (isArray(cachedResp)) {
@@ -18777,6 +18824,9 @@ function $HttpProvider() {
18777
18824
  });
18778
18825
  }
18779
18826
 
18827
+ function resolvePromiseWithResult(result) {
18828
+ resolvePromise(result.data, result.status, shallowCopy(result.headers()), result.statusText);
18829
+ }
18780
18830
 
18781
18831
  function removePendingReq() {
18782
18832
  var idx = $http.pendingRequests.indexOf(config);
@@ -18938,7 +18988,9 @@ function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDoc
18938
18988
 
18939
18989
  function completeRequest(callback, status, response, headersString, statusText) {
18940
18990
  // cancel timeout and subsequent timeout promise resolution
18941
- timeoutId && $browserDefer.cancel(timeoutId);
18991
+ if (timeoutId !== undefined) {
18992
+ $browserDefer.cancel(timeoutId);
18993
+ }
18942
18994
  jsonpDone = xhr = null;
18943
18995
 
18944
18996
  callback(status, response, headersString, statusText);
@@ -19386,33 +19438,33 @@ function $IntervalProvider() {
19386
19438
  * // Don't start a new fight if we are already fighting
19387
19439
  * if ( angular.isDefined(stop) ) return;
19388
19440
  *
19389
- * stop = $interval(function() {
19390
- * if ($scope.blood_1 > 0 && $scope.blood_2 > 0) {
19391
- * $scope.blood_1 = $scope.blood_1 - 3;
19392
- * $scope.blood_2 = $scope.blood_2 - 4;
19393
- * } else {
19394
- * $scope.stopFight();
19395
- * }
19396
- * }, 100);
19397
- * };
19441
+ * stop = $interval(function() {
19442
+ * if ($scope.blood_1 > 0 && $scope.blood_2 > 0) {
19443
+ * $scope.blood_1 = $scope.blood_1 - 3;
19444
+ * $scope.blood_2 = $scope.blood_2 - 4;
19445
+ * } else {
19446
+ * $scope.stopFight();
19447
+ * }
19448
+ * }, 100);
19449
+ * };
19398
19450
  *
19399
- * $scope.stopFight = function() {
19400
- * if (angular.isDefined(stop)) {
19401
- * $interval.cancel(stop);
19402
- * stop = undefined;
19403
- * }
19404
- * };
19451
+ * $scope.stopFight = function() {
19452
+ * if (angular.isDefined(stop)) {
19453
+ * $interval.cancel(stop);
19454
+ * stop = undefined;
19455
+ * }
19456
+ * };
19405
19457
  *
19406
- * $scope.resetFight = function() {
19407
- * $scope.blood_1 = 100;
19408
- * $scope.blood_2 = 120;
19409
- * };
19458
+ * $scope.resetFight = function() {
19459
+ * $scope.blood_1 = 100;
19460
+ * $scope.blood_2 = 120;
19461
+ * };
19410
19462
  *
19411
- * $scope.$on('$destroy', function() {
19412
- * // Make sure that the interval is destroyed too
19413
- * $scope.stopFight();
19414
- * });
19415
- * }])
19463
+ * $scope.$on('$destroy', function() {
19464
+ * // Make sure that the interval is destroyed too
19465
+ * $scope.stopFight();
19466
+ * });
19467
+ * }])
19416
19468
  * // Register the 'myCurrentTime' directive factory method.
19417
19469
  * // We inject $interval and dateFilter service since the factory method is DI.
19418
19470
  * .directive('myCurrentTime', ['$interval', 'dateFilter',
@@ -19655,6 +19707,10 @@ function stripHash(url) {
19655
19707
  return index == -1 ? url : url.substr(0, index);
19656
19708
  }
19657
19709
 
19710
+ function trimEmptyHash(url) {
19711
+ return url.replace(/(#.+)|#$/, '$1');
19712
+ }
19713
+
19658
19714
 
19659
19715
  function stripFile(url) {
19660
19716
  return url.substr(0, stripHash(url).lastIndexOf('/') + 1);
@@ -19766,16 +19822,25 @@ function LocationHashbangUrl(appBase, hashPrefix) {
19766
19822
  */
19767
19823
  this.$$parse = function(url) {
19768
19824
  var withoutBaseUrl = beginsWith(appBase, url) || beginsWith(appBaseNoFile, url);
19769
- var withoutHashUrl = withoutBaseUrl.charAt(0) == '#'
19770
- ? beginsWith(hashPrefix, withoutBaseUrl)
19771
- : (this.$$html5)
19772
- ? withoutBaseUrl
19773
- : '';
19825
+ var withoutHashUrl;
19826
+
19827
+ if (withoutBaseUrl.charAt(0) === '#') {
19774
19828
 
19775
- if (!isString(withoutHashUrl)) {
19776
- throw $locationMinErr('ihshprfx', 'Invalid url "{0}", missing hash prefix "{1}".', url,
19777
- hashPrefix);
19829
+ // The rest of the url starts with a hash so we have
19830
+ // got either a hashbang path or a plain hash fragment
19831
+ withoutHashUrl = beginsWith(hashPrefix, withoutBaseUrl);
19832
+ if (isUndefined(withoutHashUrl)) {
19833
+ // There was no hashbang prefix so we just have a hash fragment
19834
+ withoutHashUrl = withoutBaseUrl;
19835
+ }
19836
+
19837
+ } else {
19838
+ // There was no hashbang path nor hash fragment:
19839
+ // If we are in HTML5 mode we use what is left as the path;
19840
+ // Otherwise we ignore what is left
19841
+ withoutHashUrl = this.$$html5 ? withoutBaseUrl : '';
19778
19842
  }
19843
+
19779
19844
  parseAppUrl(withoutHashUrl, this);
19780
19845
 
19781
19846
  this.$$path = removeWindowsDriveName(this.$$path, withoutHashUrl, appBase);
@@ -20138,7 +20203,7 @@ var locationPrototype = {
20138
20203
  *
20139
20204
  *
20140
20205
  * ```js
20141
- * // given url http://example.com/some/path?foo=bar&baz=xoxo#hashValue
20206
+ * // given url http://example.com/#/some/path?foo=bar&baz=xoxo#hashValue
20142
20207
  * var hash = $location.hash();
20143
20208
  * // => "hashValue"
20144
20209
  * ```
@@ -20490,10 +20555,11 @@ function $LocationProvider() {
20490
20555
 
20491
20556
  // update browser
20492
20557
  $rootScope.$watch(function $locationWatch() {
20493
- var oldUrl = $browser.url();
20558
+ var oldUrl = trimEmptyHash($browser.url());
20559
+ var newUrl = trimEmptyHash($location.absUrl());
20494
20560
  var oldState = $browser.state();
20495
20561
  var currentReplace = $location.$$replace;
20496
- var urlOrStateChanged = oldUrl !== $location.absUrl() ||
20562
+ var urlOrStateChanged = oldUrl !== newUrl ||
20497
20563
  ($location.$$html5 && $sniffer.history && oldState !== $location.$$state);
20498
20564
 
20499
20565
  if (initializing || urlOrStateChanged) {
@@ -21296,8 +21362,8 @@ Parser.prototype = {
21296
21362
  logicalAND: function() {
21297
21363
  var left = this.equality();
21298
21364
  var token;
21299
- if ((token = this.expect('&&'))) {
21300
- left = this.binaryFn(left, token.text, this.logicalAND(), true);
21365
+ while ((token = this.expect('&&'))) {
21366
+ left = this.binaryFn(left, token.text, this.equality(), true);
21301
21367
  }
21302
21368
  return left;
21303
21369
  },
@@ -21305,8 +21371,8 @@ Parser.prototype = {
21305
21371
  equality: function() {
21306
21372
  var left = this.relational();
21307
21373
  var token;
21308
- if ((token = this.expect('==','!=','===','!=='))) {
21309
- left = this.binaryFn(left, token.text, this.equality());
21374
+ while ((token = this.expect('==','!=','===','!=='))) {
21375
+ left = this.binaryFn(left, token.text, this.relational());
21310
21376
  }
21311
21377
  return left;
21312
21378
  },
@@ -21314,8 +21380,8 @@ Parser.prototype = {
21314
21380
  relational: function() {
21315
21381
  var left = this.additive();
21316
21382
  var token;
21317
- if ((token = this.expect('<', '>', '<=', '>='))) {
21318
- left = this.binaryFn(left, token.text, this.relational());
21383
+ while ((token = this.expect('<', '>', '<=', '>='))) {
21384
+ left = this.binaryFn(left, token.text, this.additive());
21319
21385
  }
21320
21386
  return left;
21321
21387
  },
@@ -21407,7 +21473,7 @@ Parser.prototype = {
21407
21473
  var args = argsFn.length ? [] : null;
21408
21474
 
21409
21475
  return function $parseFunctionCall(scope, locals) {
21410
- var context = contextGetter ? contextGetter(scope, locals) : scope;
21476
+ var context = contextGetter ? contextGetter(scope, locals) : isDefined(contextGetter) ? undefined : scope;
21411
21477
  var fn = fnGetter(scope, locals, context) || noop;
21412
21478
 
21413
21479
  if (args) {
@@ -21420,13 +21486,13 @@ Parser.prototype = {
21420
21486
  ensureSafeObject(context, expressionText);
21421
21487
  ensureSafeFunction(fn, expressionText);
21422
21488
 
21423
- // IE stupidity! (IE doesn't have apply for some native functions)
21489
+ // IE doesn't have apply for some native functions
21424
21490
  var v = fn.apply
21425
21491
  ? fn.apply(context, args)
21426
21492
  : fn(args[0], args[1], args[2], args[3], args[4]);
21427
21493
 
21428
21494
  return ensureSafeObject(v, expressionText);
21429
- };
21495
+ };
21430
21496
  },
21431
21497
 
21432
21498
  // This is used with json array declaration
@@ -25062,7 +25128,9 @@ function $SnifferProvider() {
25062
25128
  // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have
25063
25129
  // it. In particular the event is not fired when backspace or delete key are pressed or
25064
25130
  // when cut operation is performed.
25065
- if (event == 'input' && msie == 9) return false;
25131
+ // IE10+ implements 'input' event but it erroneously fires under various situations,
25132
+ // e.g. when placeholder changes, or a form is focused.
25133
+ if (event === 'input' && msie <= 11) return false;
25066
25134
 
25067
25135
  if (isUndefined(eventSupport[event])) {
25068
25136
  var divElm = document.createElement('div');
@@ -25108,14 +25176,9 @@ function $TemplateRequestProvider() {
25108
25176
  var transformResponse = $http.defaults && $http.defaults.transformResponse;
25109
25177
 
25110
25178
  if (isArray(transformResponse)) {
25111
- var original = transformResponse;
25112
- transformResponse = [];
25113
- for (var i = 0; i < original.length; ++i) {
25114
- var transformer = original[i];
25115
- if (transformer !== defaultHttpResponseTransform) {
25116
- transformResponse.push(transformer);
25117
- }
25118
- }
25179
+ transformResponse = transformResponse.filter(function(transformer) {
25180
+ return transformer !== defaultHttpResponseTransform;
25181
+ });
25119
25182
  } else if (transformResponse === defaultHttpResponseTransform) {
25120
25183
  transformResponse = null;
25121
25184
  }
@@ -25127,18 +25190,16 @@ function $TemplateRequestProvider() {
25127
25190
 
25128
25191
  return $http.get(tpl, httpOptions)
25129
25192
  .then(function(response) {
25130
- var html = response.data;
25131
25193
  self.totalPendingRequests--;
25132
- $templateCache.put(tpl, html);
25133
- return html;
25194
+ return response.data;
25134
25195
  }, handleError);
25135
25196
 
25136
- function handleError() {
25197
+ function handleError(resp) {
25137
25198
  self.totalPendingRequests--;
25138
25199
  if (!ignoreRequestError) {
25139
25200
  throw $compileMinErr('tpload', 'Failed to load template: {0}', tpl);
25140
25201
  }
25141
- return $q.reject();
25202
+ return $q.reject(resp);
25142
25203
  }
25143
25204
  }
25144
25205
 
@@ -25761,106 +25822,103 @@ function filterFilter() {
25761
25822
  return function(array, expression, comparator) {
25762
25823
  if (!isArray(array)) return array;
25763
25824
 
25764
- var comparatorType = typeof(comparator),
25765
- predicates = [];
25825
+ var predicateFn;
25826
+ var matchAgainstAnyProp;
25766
25827
 
25767
- predicates.check = function(value, index) {
25768
- for (var j = 0; j < predicates.length; j++) {
25769
- if (!predicates[j](value, index)) {
25770
- return false;
25771
- }
25772
- }
25773
- return true;
25774
- };
25775
-
25776
- if (comparatorType !== 'function') {
25777
- if (comparatorType === 'boolean' && comparator) {
25778
- comparator = function(obj, text) {
25779
- return angular.equals(obj, text);
25780
- };
25781
- } else {
25782
- comparator = function(obj, text) {
25783
- if (obj && text && typeof obj === 'object' && typeof text === 'object') {
25784
- for (var objKey in obj) {
25785
- if (objKey.charAt(0) !== '$' && hasOwnProperty.call(obj, objKey) &&
25786
- comparator(obj[objKey], text[objKey])) {
25787
- return true;
25788
- }
25789
- }
25790
- return false;
25791
- }
25792
- text = ('' + text).toLowerCase();
25793
- return ('' + obj).toLowerCase().indexOf(text) > -1;
25794
- };
25795
- }
25796
- }
25797
-
25798
- var search = function(obj, text) {
25799
- if (typeof text === 'string' && text.charAt(0) === '!') {
25800
- return !search(obj, text.substr(1));
25801
- }
25802
- switch (typeof obj) {
25803
- case 'boolean':
25804
- case 'number':
25805
- case 'string':
25806
- return comparator(obj, text);
25807
- case 'object':
25808
- switch (typeof text) {
25809
- case 'object':
25810
- return comparator(obj, text);
25811
- default:
25812
- for (var objKey in obj) {
25813
- if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {
25814
- return true;
25815
- }
25816
- }
25817
- break;
25818
- }
25819
- return false;
25820
- case 'array':
25821
- for (var i = 0; i < obj.length; i++) {
25822
- if (search(obj[i], text)) {
25823
- return true;
25824
- }
25825
- }
25826
- return false;
25827
- default:
25828
- return false;
25829
- }
25830
- };
25831
25828
  switch (typeof expression) {
25829
+ case 'function':
25830
+ predicateFn = expression;
25831
+ break;
25832
25832
  case 'boolean':
25833
25833
  case 'number':
25834
25834
  case 'string':
25835
- // Set up expression object and fall through
25836
- expression = {$:expression};
25837
- // jshint -W086
25835
+ matchAgainstAnyProp = true;
25836
+ //jshint -W086
25838
25837
  case 'object':
25839
- // jshint +W086
25840
- for (var key in expression) {
25841
- (function(path) {
25842
- if (typeof expression[path] === 'undefined') return;
25843
- predicates.push(function(value) {
25844
- return search(path == '$' ? value : (value && value[path]), expression[path]);
25845
- });
25846
- })(key);
25847
- }
25848
- break;
25849
- case 'function':
25850
- predicates.push(expression);
25838
+ //jshint +W086
25839
+ predicateFn = createPredicateFn(expression, comparator, matchAgainstAnyProp);
25851
25840
  break;
25852
25841
  default:
25853
25842
  return array;
25854
25843
  }
25855
- var filtered = [];
25856
- for (var j = 0; j < array.length; j++) {
25857
- var value = array[j];
25858
- if (predicates.check(value, j)) {
25859
- filtered.push(value);
25844
+
25845
+ return array.filter(predicateFn);
25846
+ };
25847
+ }
25848
+
25849
+ // Helper functions for `filterFilter`
25850
+ function createPredicateFn(expression, comparator, matchAgainstAnyProp) {
25851
+ var predicateFn;
25852
+
25853
+ if (comparator === true) {
25854
+ comparator = equals;
25855
+ } else if (!isFunction(comparator)) {
25856
+ comparator = function(actual, expected) {
25857
+ if (isObject(actual) || isObject(expected)) {
25858
+ // Prevent an object to be considered equal to a string like `'[object'`
25859
+ return false;
25860
25860
  }
25861
- }
25862
- return filtered;
25861
+
25862
+ actual = lowercase('' + actual);
25863
+ expected = lowercase('' + expected);
25864
+ return actual.indexOf(expected) !== -1;
25865
+ };
25866
+ }
25867
+
25868
+ predicateFn = function(item) {
25869
+ return deepCompare(item, expression, comparator, matchAgainstAnyProp);
25863
25870
  };
25871
+
25872
+ return predicateFn;
25873
+ }
25874
+
25875
+ function deepCompare(actual, expected, comparator, matchAgainstAnyProp) {
25876
+ var actualType = typeof actual;
25877
+ var expectedType = typeof expected;
25878
+
25879
+ if ((expectedType === 'string') && (expected.charAt(0) === '!')) {
25880
+ return !deepCompare(actual, expected.substring(1), comparator, matchAgainstAnyProp);
25881
+ } else if (actualType === 'array') {
25882
+ // In case `actual` is an array, consider it a match
25883
+ // if ANY of it's items matches `expected`
25884
+ return actual.some(function(item) {
25885
+ return deepCompare(item, expected, comparator, matchAgainstAnyProp);
25886
+ });
25887
+ }
25888
+
25889
+ switch (actualType) {
25890
+ case 'object':
25891
+ var key;
25892
+ if (matchAgainstAnyProp) {
25893
+ for (key in actual) {
25894
+ if ((key.charAt(0) !== '$') && deepCompare(actual[key], expected, comparator)) {
25895
+ return true;
25896
+ }
25897
+ }
25898
+ return false;
25899
+ } else if (expectedType === 'object') {
25900
+ for (key in expected) {
25901
+ var expectedVal = expected[key];
25902
+ if (isFunction(expectedVal)) {
25903
+ continue;
25904
+ }
25905
+
25906
+ var keyIsDollar = key === '$';
25907
+ var actualVal = keyIsDollar ? actual : actual[key];
25908
+ if (!deepCompare(actualVal, expectedVal, comparator, keyIsDollar)) {
25909
+ return false;
25910
+ }
25911
+ }
25912
+ return true;
25913
+ } else {
25914
+ return comparator(actual, expected);
25915
+ }
25916
+ break;
25917
+ case 'function':
25918
+ return false;
25919
+ default:
25920
+ return comparator(actual, expected);
25921
+ }
25864
25922
  }
25865
25923
 
25866
25924
  /**
@@ -26013,7 +26071,6 @@ function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {
26013
26071
  if (numStr.indexOf('e') !== -1) {
26014
26072
  var match = numStr.match(/([\d\.]+)e(-?)(\d+)/);
26015
26073
  if (match && match[2] == '-' && match[3] > fractionSize + 1) {
26016
- numStr = '0';
26017
26074
  number = 0;
26018
26075
  } else {
26019
26076
  formatedText = numStr;
@@ -26034,10 +26091,6 @@ function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {
26034
26091
  // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round
26035
26092
  number = +(Math.round(+(number.toString() + 'e' + fractionSize)).toString() + 'e' + -fractionSize);
26036
26093
 
26037
- if (number === 0) {
26038
- isNegative = false;
26039
- }
26040
-
26041
26094
  var fraction = ('' + number).split(DECIMAL_SEP);
26042
26095
  var whole = fraction[0];
26043
26096
  fraction = fraction[1] || '';
@@ -26070,12 +26123,16 @@ function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {
26070
26123
 
26071
26124
  if (fractionSize && fractionSize !== "0") formatedText += decimalSep + fraction.substr(0, fractionSize);
26072
26125
  } else {
26073
-
26074
- if (fractionSize > 0 && number > -1 && number < 1) {
26126
+ if (fractionSize > 0 && number < 1) {
26075
26127
  formatedText = number.toFixed(fractionSize);
26128
+ number = parseFloat(formatedText);
26076
26129
  }
26077
26130
  }
26078
26131
 
26132
+ if (number === 0) {
26133
+ isNegative = false;
26134
+ }
26135
+
26079
26136
  parts.push(isNegative ? pattern.negPre : pattern.posPre,
26080
26137
  formatedText,
26081
26138
  isNegative ? pattern.negSuf : pattern.posSuf);
@@ -26365,25 +26422,31 @@ function dateFilter($locale) {
26365
26422
  * the binding is automatically converted to JSON.
26366
26423
  *
26367
26424
  * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.
26425
+ * @param {number=} spacing The number of spaces to use per indentation, defaults to 2.
26368
26426
  * @returns {string} JSON string.
26369
26427
  *
26370
26428
  *
26371
26429
  * @example
26372
26430
  <example>
26373
26431
  <file name="index.html">
26374
- <pre>{{ {'name':'value'} | json }}</pre>
26432
+ <pre id="default-spacing">{{ {'name':'value'} | json }}</pre>
26433
+ <pre id="custom-spacing">{{ {'name':'value'} | json:4 }}</pre>
26375
26434
  </file>
26376
26435
  <file name="protractor.js" type="protractor">
26377
26436
  it('should jsonify filtered objects', function() {
26378
- expect(element(by.binding("{'name':'value'}")).getText()).toMatch(/\{\n "name": ?"value"\n}/);
26437
+ expect(element(by.id('default-spacing')).getText()).toMatch(/\{\n "name": ?"value"\n}/);
26438
+ expect(element(by.id('custom-spacing')).getText()).toMatch(/\{\n "name": ?"value"\n}/);
26379
26439
  });
26380
26440
  </file>
26381
26441
  </example>
26382
26442
  *
26383
26443
  */
26384
26444
  function jsonFilter() {
26385
- return function(object) {
26386
- return toJson(object, true);
26445
+ return function(object, spacing) {
26446
+ if (isUndefined(spacing)) {
26447
+ spacing = 2;
26448
+ }
26449
+ return toJson(object, spacing);
26387
26450
  };
26388
26451
  }
26389
26452
 
@@ -26703,12 +26766,29 @@ function orderByFilter($parse) {
26703
26766
  function compare(v1, v2) {
26704
26767
  var t1 = typeof v1;
26705
26768
  var t2 = typeof v2;
26706
- if (t1 == t2) {
26707
- if (isDate(v1) && isDate(v2)) {
26708
- v1 = v1.valueOf();
26709
- v2 = v2.valueOf();
26710
- }
26711
- if (t1 == "string") {
26769
+ // Prepare values for Abstract Relational Comparison
26770
+ // (http://www.ecma-international.org/ecma-262/5.1/#sec-11.8.5):
26771
+ // If the resulting values are identical, return 0 to prevent
26772
+ // incorrect re-ordering.
26773
+ if (t1 === t2 && t1 === "object") {
26774
+ // If types are both numbers, emulate abstract ToPrimitive() operation
26775
+ // in order to get primitive values suitable for comparison
26776
+ t1 = typeof (v1.valueOf ? v1 = v1.valueOf() : v1);
26777
+ t2 = typeof (v2.valueOf ? v2 = v2.valueOf() : v2);
26778
+ if (t1 === t2 && t1 === "object") {
26779
+ // Object.prototype.valueOf will return the original object, by
26780
+ // default. If we do not receive a primitive value, use ToString()
26781
+ // instead.
26782
+ t1 = typeof (v1.toString ? v1 = v1.toString() : v1);
26783
+ t2 = typeof (v2.toString ? v2 = v2.toString() : v2);
26784
+
26785
+ // If the end result of toString() for each item is the same, do not
26786
+ // perform relational comparison, and do not re-order objects.
26787
+ if (t1 === t2 && v1 === v2 || t1 === "object") return 0;
26788
+ }
26789
+ }
26790
+ if (t1 === t2) {
26791
+ if (t1 === "string") {
26712
26792
  v1 = v1.toLowerCase();
26713
26793
  v2 = v2.toLowerCase();
26714
26794
  }
@@ -26774,9 +26854,8 @@ var htmlAnchorDirective = valueFn({
26774
26854
  * make the link go to the wrong URL if the user clicks it before
26775
26855
  * Angular has a chance to replace the `{{hash}}` markup with its
26776
26856
  * value. Until Angular replaces the markup the link will be broken
26777
- * and will most likely return a 404 error.
26778
- *
26779
- * The `ngHref` directive solves this problem.
26857
+ * and will most likely return a 404 error. The `ngHref` directive
26858
+ * solves this problem.
26780
26859
  *
26781
26860
  * The wrong way to write it:
26782
26861
  * ```html
@@ -28658,7 +28737,6 @@ function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
28658
28737
  }
28659
28738
 
28660
28739
  function baseInputType(scope, element, attr, ctrl, $sniffer, $browser) {
28661
- var placeholder = element[0].placeholder, noevent = {};
28662
28740
  var type = lowercase(element[0].type);
28663
28741
 
28664
28742
  // In composition mode, users are still inputing intermediate text buffer,
@@ -28678,19 +28756,14 @@ function baseInputType(scope, element, attr, ctrl, $sniffer, $browser) {
28678
28756
  }
28679
28757
 
28680
28758
  var listener = function(ev) {
28759
+ if (timeout) {
28760
+ $browser.defer.cancel(timeout);
28761
+ timeout = null;
28762
+ }
28681
28763
  if (composing) return;
28682
28764
  var value = element.val(),
28683
28765
  event = ev && ev.type;
28684
28766
 
28685
- // IE (11 and under) seem to emit an 'input' event if the placeholder value changes.
28686
- // We don't want to dirty the value when this happens, so we abort here. Unfortunately,
28687
- // IE also sends input events for other non-input-related things, (such as focusing on a
28688
- // form control), so this change is not entirely enough to solve this.
28689
- if (msie && (ev || noevent).type === 'input' && element[0].placeholder !== placeholder) {
28690
- placeholder = element[0].placeholder;
28691
- return;
28692
- }
28693
-
28694
28767
  // By default we will trim the value
28695
28768
  // If the attribute ng-trim exists we will avoid trimming
28696
28769
  // If input type is 'password', the value is never trimmed
@@ -28713,11 +28786,13 @@ function baseInputType(scope, element, attr, ctrl, $sniffer, $browser) {
28713
28786
  } else {
28714
28787
  var timeout;
28715
28788
 
28716
- var deferListener = function(ev) {
28789
+ var deferListener = function(ev, input, origValue) {
28717
28790
  if (!timeout) {
28718
28791
  timeout = $browser.defer(function() {
28719
- listener(ev);
28720
28792
  timeout = null;
28793
+ if (!input || input.value !== origValue) {
28794
+ listener(ev);
28795
+ }
28721
28796
  });
28722
28797
  }
28723
28798
  };
@@ -28729,7 +28804,7 @@ function baseInputType(scope, element, attr, ctrl, $sniffer, $browser) {
28729
28804
  // command modifiers arrows
28730
28805
  if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;
28731
28806
 
28732
- deferListener(event);
28807
+ deferListener(event, this, this.value);
28733
28808
  });
28734
28809
 
28735
28810
  // if user modifies input value using context menu in IE, we need "paste" and "cut" events to catch it
@@ -29904,11 +29979,15 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
29904
29979
  var prevModelValue = ctrl.$modelValue;
29905
29980
  var allowInvalid = ctrl.$options && ctrl.$options.allowInvalid;
29906
29981
  ctrl.$$rawModelValue = modelValue;
29982
+
29907
29983
  if (allowInvalid) {
29908
29984
  ctrl.$modelValue = modelValue;
29909
29985
  writeToModelIfNeeded();
29910
29986
  }
29911
- ctrl.$$runValidators(parserValid, modelValue, viewValue, function(allValid) {
29987
+
29988
+ // Pass the $$lastCommittedViewValue here, because the cached viewValue might be out of date.
29989
+ // This can happen if e.g. $setViewValue is called from inside a parser
29990
+ ctrl.$$runValidators(parserValid, modelValue, ctrl.$$lastCommittedViewValue, function(allValid) {
29912
29991
  if (!allowInvalid) {
29913
29992
  // Note: Don't check ctrl.$valid here, as we could have
29914
29993
  // external validators (e.g. calculated on the server),
@@ -34250,7 +34329,7 @@ var ngSwitchDefaultDirective = ngDirective({
34250
34329
  }]);
34251
34330
  </script>
34252
34331
  <div ng-controller="ExampleController">
34253
- <input ng-model="title"><br>
34332
+ <input ng-model="title"> <br/>
34254
34333
  <textarea ng-model="text"></textarea> <br/>
34255
34334
  <pane title="{{title}}">{{text}}</pane>
34256
34335
  </div>
@@ -34328,7 +34407,6 @@ var scriptDirective = ['$templateCache', function($templateCache) {
34328
34407
  compile: function(element, attr) {
34329
34408
  if (attr.type == 'text/ng-template') {
34330
34409
  var templateUrl = attr.id,
34331
- // IE is not consistent, in scripts we have to read .text but in other nodes we have to read .textContent
34332
34410
  text = element[0].text;
34333
34411
 
34334
34412
  $templateCache.put(templateUrl, text);
@@ -34379,9 +34457,9 @@ var ngOptionsMinErr = minErr('ngOptions');
34379
34457
  * or property name (for object data sources) of the value within the collection. If a `track by` expression
34380
34458
  * is used, the result of that expression will be set as the value of the `option` and `select` elements.
34381
34459
  *
34382
- * ### `select as` with `trackexpr`
34460
+ * ### `select as` with `track by`
34383
34461
  *
34384
- * Using `select as` together with `trackexpr` is not recommended. Reasoning:
34462
+ * Using `select as` together with `track by` is not recommended. Reasoning:
34385
34463
  *
34386
34464
  * - Example: &lt;select ng-options="item.subItem as item.label for item in values track by item.id" ng-model="selected"&gt;
34387
34465
  * values: [{id: 1, label: 'aLabel', subItem: {name: 'aSubItem'}}, {id: 2, label: 'bLabel', subItem: {name: 'bSubItem'}}],
@@ -34406,8 +34484,10 @@ var ngOptionsMinErr = minErr('ngOptions');
34406
34484
  * * for array data sources:
34407
34485
  * * `label` **`for`** `value` **`in`** `array`
34408
34486
  * * `select` **`as`** `label` **`for`** `value` **`in`** `array`
34409
- * * `label` **`group by`** `group` **`for`** `value` **`in`** `array`
34410
- * * `select` **`as`** `label` **`group by`** `group` **`for`** `value` **`in`** `array` **`track by`** `trackexpr`
34487
+ * * `label` **`group by`** `group` **`for`** `value` **`in`** `array`
34488
+ * * `label` **`group by`** `group` **`for`** `value` **`in`** `array` **`track by`** `trackexpr`
34489
+ * * `label` **`for`** `value` **`in`** `array` | orderBy:`orderexpr` **`track by`** `trackexpr`
34490
+ * (for including a filter with `track by`)
34411
34491
  * * for object data sources:
34412
34492
  * * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`
34413
34493
  * * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`
@@ -34549,7 +34629,7 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
34549
34629
  self.removeOption = function(value) {
34550
34630
  if (this.hasOption(value)) {
34551
34631
  delete optionsMap[value];
34552
- if (ngModelCtrl.$viewValue == value) {
34632
+ if (ngModelCtrl.$viewValue === value) {
34553
34633
  this.renderUnknownOption(value);
34554
34634
  }
34555
34635
  }
@@ -35016,18 +35096,23 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
35016
35096
  updateLabelMap(labelMap, option.label, false);
35017
35097
  option.element.remove();
35018
35098
  }
35019
- forEach(labelMap, function(count, label) {
35020
- if (count > 0) {
35021
- selectCtrl.addOption(label);
35022
- } else if (count < 0) {
35023
- selectCtrl.removeOption(label);
35024
- }
35025
- });
35026
35099
  }
35027
35100
  // remove any excessive OPTGROUPs from select
35028
35101
  while (optionGroupsCache.length > groupIndex) {
35029
- optionGroupsCache.pop()[0].element.remove();
35102
+ // remove all the labels in the option group
35103
+ optionGroup = optionGroupsCache.pop();
35104
+ for (index = 1; index < optionGroup.length; ++index) {
35105
+ updateLabelMap(labelMap, optionGroup[index].label, false);
35106
+ }
35107
+ optionGroup[0].element.remove();
35030
35108
  }
35109
+ forEach(labelMap, function(count, label) {
35110
+ if (count > 0) {
35111
+ selectCtrl.addOption(label);
35112
+ } else if (count < 0) {
35113
+ selectCtrl.removeOption(label);
35114
+ }
35115
+ });
35031
35116
  }
35032
35117
  }
35033
35118
  }
@@ -36688,7 +36773,7 @@ angular.scenario.dsl('binding', function() {
36688
36773
  */
36689
36774
  angular.scenario.dsl('input', function() {
36690
36775
  var chain = {};
36691
- var supportInputEvent = 'oninput' in document.createElement('div') && msie != 9;
36776
+ var supportInputEvent = 'oninput' in document.createElement('div') && !(msie && msie <= 11);
36692
36777
 
36693
36778
  chain.enter = function(value, event) {
36694
36779
  return this.addFutureAction("input '" + this.name + "' enter '" + value + "'",