angular-gem 1.3.5 → 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 +8 -8
  2. data/lib/angular-gem/version.rb +1 -1
  3. data/vendor/assets/javascripts/1.3.6/angular-animate.js +2137 -0
  4. data/vendor/assets/javascripts/1.3.6/angular-aria.js +332 -0
  5. data/vendor/assets/javascripts/1.3.6/angular-cookies.js +206 -0
  6. data/vendor/assets/javascripts/1.3.6/angular-loader.js +405 -0
  7. data/vendor/assets/javascripts/1.3.6/angular-messages.js +400 -0
  8. data/vendor/assets/javascripts/1.3.6/angular-mocks.js +2382 -0
  9. data/vendor/assets/javascripts/1.3.6/angular-resource.js +667 -0
  10. data/vendor/assets/javascripts/1.3.6/angular-route.js +995 -0
  11. data/vendor/assets/javascripts/1.3.6/angular-sanitize.js +680 -0
  12. data/vendor/assets/javascripts/1.3.6/angular-scenario.js +37354 -0
  13. data/vendor/assets/javascripts/1.3.6/angular-touch.js +622 -0
  14. data/vendor/assets/javascripts/1.3.6/angular.js +26000 -0
  15. data/vendor/assets/javascripts/angular-animate.js +121 -120
  16. data/vendor/assets/javascripts/angular-aria.js +39 -28
  17. data/vendor/assets/javascripts/angular-cookies.js +1 -1
  18. data/vendor/assets/javascripts/angular-loader.js +2 -2
  19. data/vendor/assets/javascripts/angular-messages.js +1 -1
  20. data/vendor/assets/javascripts/angular-mocks.js +7 -5
  21. data/vendor/assets/javascripts/angular-resource.js +1 -1
  22. data/vendor/assets/javascripts/angular-route.js +1 -2
  23. data/vendor/assets/javascripts/angular-sanitize.js +6 -4
  24. data/vendor/assets/javascripts/angular-scenario.js +282 -199
  25. data/vendor/assets/javascripts/angular-touch.js +1 -1
  26. data/vendor/assets/javascripts/angular.js +280 -197
  27. metadata +14 -2
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.3.5
2
+ * @license AngularJS v1.3.6
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.5
2
+ * @license AngularJS v1.3.6
3
3
  * (c) 2010-2014 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -54,7 +54,7 @@ function minErr(module, ErrorConstructor) {
54
54
  return match;
55
55
  });
56
56
 
57
- message = message + '\nhttp://errors.angularjs.org/1.3.5/' +
57
+ message = message + '\nhttp://errors.angularjs.org/1.3.6/' +
58
58
  (module ? module + '/' : '') + code;
59
59
  for (i = 2; i < arguments.length; i++) {
60
60
  message = message + (i == 2 ? '?' : '&') + 'p' + (i - 2) + '=' +
@@ -1028,12 +1028,16 @@ function toJsonReplacer(key, value) {
1028
1028
  * stripped since angular uses this notation internally.
1029
1029
  *
1030
1030
  * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.
1031
- * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.
1031
+ * @param {boolean|number=} pretty If set to true, the JSON output will contain newlines and whitespace.
1032
+ * If set to an integer, the JSON output will contain that many spaces per indentation (the default is 2).
1032
1033
  * @returns {string|undefined} JSON-ified string representing `obj`.
1033
1034
  */
1034
1035
  function toJson(obj, pretty) {
1035
1036
  if (typeof obj === 'undefined') return undefined;
1036
- return JSON.stringify(obj, toJsonReplacer, pretty ? ' ' : null);
1037
+ if (!isNumber(pretty)) {
1038
+ pretty = pretty ? 2 : null;
1039
+ }
1040
+ return JSON.stringify(obj, toJsonReplacer, pretty);
1037
1041
  }
1038
1042
 
1039
1043
 
@@ -2081,7 +2085,8 @@ function toDebugString(obj) {
2081
2085
  $TimeoutProvider,
2082
2086
  $$RAFProvider,
2083
2087
  $$AsyncCallbackProvider,
2084
- $WindowProvider
2088
+ $WindowProvider,
2089
+ $$jqLiteProvider
2085
2090
  */
2086
2091
 
2087
2092
 
@@ -2100,11 +2105,11 @@ function toDebugString(obj) {
2100
2105
  * - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat".
2101
2106
  */
2102
2107
  var version = {
2103
- full: '1.3.5', // all of these placeholder strings will be replaced by grunt's
2108
+ full: '1.3.6', // all of these placeholder strings will be replaced by grunt's
2104
2109
  major: 1, // package task
2105
2110
  minor: 3,
2106
- dot: 5,
2107
- codeName: 'cybernetic-mercantilism'
2111
+ dot: 6,
2112
+ codeName: 'robofunky-danceblaster'
2108
2113
  };
2109
2114
 
2110
2115
 
@@ -2234,7 +2239,8 @@ function publishExternalAPI(angular) {
2234
2239
  $timeout: $TimeoutProvider,
2235
2240
  $window: $WindowProvider,
2236
2241
  $$rAF: $$RAFProvider,
2237
- $$asyncCallback: $$AsyncCallbackProvider
2242
+ $$asyncCallback: $$AsyncCallbackProvider,
2243
+ $$jqLite: $$jqLiteProvider
2238
2244
  });
2239
2245
  }
2240
2246
  ]);
@@ -3244,6 +3250,27 @@ forEach({
3244
3250
  JQLite.prototype.unbind = JQLite.prototype.off;
3245
3251
  });
3246
3252
 
3253
+
3254
+ // Provider for private $$jqLite service
3255
+ function $$jqLiteProvider() {
3256
+ this.$get = function $$jqLite() {
3257
+ return extend(JQLite, {
3258
+ hasClass: function(node, classes) {
3259
+ if (node.attr) node = node[0];
3260
+ return jqLiteHasClass(node, classes);
3261
+ },
3262
+ addClass: function(node, classes) {
3263
+ if (node.attr) node = node[0];
3264
+ return jqLiteAddClass(node, classes);
3265
+ },
3266
+ removeClass: function(node, classes) {
3267
+ if (node.attr) node = node[0];
3268
+ return jqLiteRemoveClass(node, classes);
3269
+ }
3270
+ });
3271
+ };
3272
+ }
3273
+
3247
3274
  /**
3248
3275
  * Computes a hash of an 'obj'.
3249
3276
  * Hash of a:
@@ -3496,6 +3523,7 @@ function annotate(fn, strictDi, name) {
3496
3523
  * Return an instance of the service.
3497
3524
  *
3498
3525
  * @param {string} name The name of the instance to retrieve.
3526
+ * @param {string} caller An optional string to provide the origin of the function call for error messages.
3499
3527
  * @return {*} The instance.
3500
3528
  */
3501
3529
 
@@ -3946,14 +3974,17 @@ function createInjector(modulesToLoad, strictDi) {
3946
3974
  }
3947
3975
  },
3948
3976
  providerInjector = (providerCache.$injector =
3949
- createInternalInjector(providerCache, function() {
3977
+ createInternalInjector(providerCache, function(serviceName, caller) {
3978
+ if (angular.isString(caller)) {
3979
+ path.push(caller);
3980
+ }
3950
3981
  throw $injectorMinErr('unpr', "Unknown provider: {0}", path.join(' <- '));
3951
3982
  })),
3952
3983
  instanceCache = {},
3953
3984
  instanceInjector = (instanceCache.$injector =
3954
- createInternalInjector(instanceCache, function(servicename) {
3955
- var provider = providerInjector.get(servicename + providerSuffix);
3956
- return instanceInjector.invoke(provider.$get, provider, undefined, servicename);
3985
+ createInternalInjector(instanceCache, function(serviceName, caller) {
3986
+ var provider = providerInjector.get(serviceName + providerSuffix, caller);
3987
+ return instanceInjector.invoke(provider.$get, provider, undefined, serviceName);
3957
3988
  }));
3958
3989
 
3959
3990
 
@@ -3988,7 +4019,7 @@ function createInjector(modulesToLoad, strictDi) {
3988
4019
 
3989
4020
  function enforceReturnValue(name, factory) {
3990
4021
  return function enforcedReturnValue() {
3991
- var result = instanceInjector.invoke(factory, this, undefined, name);
4022
+ var result = instanceInjector.invoke(factory, this);
3992
4023
  if (isUndefined(result)) {
3993
4024
  throw $injectorMinErr('undef', "Provider '{0}' must return a value from $get factory method.", name);
3994
4025
  }
@@ -4083,7 +4114,7 @@ function createInjector(modulesToLoad, strictDi) {
4083
4114
 
4084
4115
  function createInternalInjector(cache, factory) {
4085
4116
 
4086
- function getService(serviceName) {
4117
+ function getService(serviceName, caller) {
4087
4118
  if (cache.hasOwnProperty(serviceName)) {
4088
4119
  if (cache[serviceName] === INSTANTIATING) {
4089
4120
  throw $injectorMinErr('cdep', 'Circular dependency found: {0}',
@@ -4094,7 +4125,7 @@ function createInjector(modulesToLoad, strictDi) {
4094
4125
  try {
4095
4126
  path.unshift(serviceName);
4096
4127
  cache[serviceName] = INSTANTIATING;
4097
- return cache[serviceName] = factory(serviceName);
4128
+ return cache[serviceName] = factory(serviceName, caller);
4098
4129
  } catch (err) {
4099
4130
  if (cache[serviceName] === INSTANTIATING) {
4100
4131
  delete cache[serviceName];
@@ -4126,7 +4157,7 @@ function createInjector(modulesToLoad, strictDi) {
4126
4157
  args.push(
4127
4158
  locals && locals.hasOwnProperty(key)
4128
4159
  ? locals[key]
4129
- : getService(key)
4160
+ : getService(key, serviceName)
4130
4161
  );
4131
4162
  }
4132
4163
  if (isArray(fn)) {
@@ -4870,6 +4901,11 @@ function Browser(window, document, $log, $sniffer) {
4870
4901
  }
4871
4902
  }
4872
4903
 
4904
+ function getHash(url) {
4905
+ var index = url.indexOf('#');
4906
+ return index === -1 ? '' : url.substr(index + 1);
4907
+ }
4908
+
4873
4909
  /**
4874
4910
  * @private
4875
4911
  * Note: this method is used only by scenario runner
@@ -4999,8 +5035,10 @@ function Browser(window, document, $log, $sniffer) {
4999
5035
  }
5000
5036
  if (replace) {
5001
5037
  location.replace(url);
5002
- } else {
5038
+ } else if (!sameBase) {
5003
5039
  location.href = url;
5040
+ } else {
5041
+ location.hash = getHash(url);
5004
5042
  }
5005
5043
  }
5006
5044
  return self;
@@ -5779,7 +5817,7 @@ function $TemplateCacheProvider() {
5779
5817
  * #### `multiElement`
5780
5818
  * When this property is set to true, the HTML compiler will collect DOM nodes between
5781
5819
  * nodes with the attributes `directive-name-start` and `directive-name-end`, and group them
5782
- * together as the directive elements. It is recomended that this feature be used on directives
5820
+ * together as the directive elements. It is recommended that this feature be used on directives
5783
5821
  * which are not strictly behavioural (such as {@link ngClick}), and which
5784
5822
  * do not manipulate or replace child nodes (such as {@link ngInclude}).
5785
5823
  *
@@ -6571,6 +6609,21 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
6571
6609
  };
6572
6610
 
6573
6611
  Attributes.prototype = {
6612
+ /**
6613
+ * @ngdoc method
6614
+ * @name $compile.directive.Attributes#$normalize
6615
+ * @kind function
6616
+ *
6617
+ * @description
6618
+ * Converts an attribute name (e.g. dash/colon/underscore-delimited string, optionally prefixed with `x-` or
6619
+ * `data-`) to its normalized, camelCase form.
6620
+ *
6621
+ * Also there is special case for Moz prefix starting with upper case letter.
6622
+ *
6623
+ * For further information check out the guide on {@link guide/directive#matching-directives Matching Directives}
6624
+ *
6625
+ * @param {string} name Name to normalize
6626
+ */
6574
6627
  $normalize: directiveNormalize,
6575
6628
 
6576
6629
 
@@ -8149,13 +8202,6 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
8149
8202
  var PREFIX_REGEXP = /^((?:x|data)[\:\-_])/i;
8150
8203
  /**
8151
8204
  * Converts all accepted directives format into proper directive name.
8152
- * All of these will become 'myDirective':
8153
- * my:Directive
8154
- * my-directive
8155
- * x-my-directive
8156
- * data-my:directive
8157
- *
8158
- * Also there is special case for Moz prefix starting with upper case letter.
8159
8205
  * @param name Name to normalize
8160
8206
  */
8161
8207
  function directiveNormalize(name) {
@@ -9508,8 +9554,7 @@ function $HttpProvider() {
9508
9554
  if (isDefined(cachedResp)) {
9509
9555
  if (isPromiseLike(cachedResp)) {
9510
9556
  // cached request has already been sent, but there is no response yet
9511
- cachedResp.then(removePendingReq, removePendingReq);
9512
- return cachedResp;
9557
+ cachedResp.then(resolvePromiseWithResult, resolvePromiseWithResult);
9513
9558
  } else {
9514
9559
  // serving from cache
9515
9560
  if (isArray(cachedResp)) {
@@ -9587,6 +9632,9 @@ function $HttpProvider() {
9587
9632
  });
9588
9633
  }
9589
9634
 
9635
+ function resolvePromiseWithResult(result) {
9636
+ resolvePromise(result.data, result.status, shallowCopy(result.headers()), result.statusText);
9637
+ }
9590
9638
 
9591
9639
  function removePendingReq() {
9592
9640
  var idx = $http.pendingRequests.indexOf(config);
@@ -10198,33 +10246,33 @@ function $IntervalProvider() {
10198
10246
  * // Don't start a new fight if we are already fighting
10199
10247
  * if ( angular.isDefined(stop) ) return;
10200
10248
  *
10201
- * stop = $interval(function() {
10202
- * if ($scope.blood_1 > 0 && $scope.blood_2 > 0) {
10203
- * $scope.blood_1 = $scope.blood_1 - 3;
10204
- * $scope.blood_2 = $scope.blood_2 - 4;
10205
- * } else {
10206
- * $scope.stopFight();
10207
- * }
10208
- * }, 100);
10209
- * };
10249
+ * stop = $interval(function() {
10250
+ * if ($scope.blood_1 > 0 && $scope.blood_2 > 0) {
10251
+ * $scope.blood_1 = $scope.blood_1 - 3;
10252
+ * $scope.blood_2 = $scope.blood_2 - 4;
10253
+ * } else {
10254
+ * $scope.stopFight();
10255
+ * }
10256
+ * }, 100);
10257
+ * };
10210
10258
  *
10211
- * $scope.stopFight = function() {
10212
- * if (angular.isDefined(stop)) {
10213
- * $interval.cancel(stop);
10214
- * stop = undefined;
10215
- * }
10216
- * };
10259
+ * $scope.stopFight = function() {
10260
+ * if (angular.isDefined(stop)) {
10261
+ * $interval.cancel(stop);
10262
+ * stop = undefined;
10263
+ * }
10264
+ * };
10217
10265
  *
10218
- * $scope.resetFight = function() {
10219
- * $scope.blood_1 = 100;
10220
- * $scope.blood_2 = 120;
10221
- * };
10266
+ * $scope.resetFight = function() {
10267
+ * $scope.blood_1 = 100;
10268
+ * $scope.blood_2 = 120;
10269
+ * };
10222
10270
  *
10223
- * $scope.$on('$destroy', function() {
10224
- * // Make sure that the interval is destroyed too
10225
- * $scope.stopFight();
10226
- * });
10227
- * }])
10271
+ * $scope.$on('$destroy', function() {
10272
+ * // Make sure that the interval is destroyed too
10273
+ * $scope.stopFight();
10274
+ * });
10275
+ * }])
10228
10276
  * // Register the 'myCurrentTime' directive factory method.
10229
10277
  * // We inject $interval and dateFilter service since the factory method is DI.
10230
10278
  * .directive('myCurrentTime', ['$interval', 'dateFilter',
@@ -10467,6 +10515,10 @@ function stripHash(url) {
10467
10515
  return index == -1 ? url : url.substr(0, index);
10468
10516
  }
10469
10517
 
10518
+ function trimEmptyHash(url) {
10519
+ return url.replace(/(#.+)|#$/, '$1');
10520
+ }
10521
+
10470
10522
 
10471
10523
  function stripFile(url) {
10472
10524
  return url.substr(0, stripHash(url).lastIndexOf('/') + 1);
@@ -10578,16 +10630,25 @@ function LocationHashbangUrl(appBase, hashPrefix) {
10578
10630
  */
10579
10631
  this.$$parse = function(url) {
10580
10632
  var withoutBaseUrl = beginsWith(appBase, url) || beginsWith(appBaseNoFile, url);
10581
- var withoutHashUrl = withoutBaseUrl.charAt(0) == '#'
10582
- ? beginsWith(hashPrefix, withoutBaseUrl)
10583
- : (this.$$html5)
10584
- ? withoutBaseUrl
10585
- : '';
10633
+ var withoutHashUrl;
10634
+
10635
+ if (withoutBaseUrl.charAt(0) === '#') {
10636
+
10637
+ // The rest of the url starts with a hash so we have
10638
+ // got either a hashbang path or a plain hash fragment
10639
+ withoutHashUrl = beginsWith(hashPrefix, withoutBaseUrl);
10640
+ if (isUndefined(withoutHashUrl)) {
10641
+ // There was no hashbang prefix so we just have a hash fragment
10642
+ withoutHashUrl = withoutBaseUrl;
10643
+ }
10586
10644
 
10587
- if (!isString(withoutHashUrl)) {
10588
- throw $locationMinErr('ihshprfx', 'Invalid url "{0}", missing hash prefix "{1}".', url,
10589
- hashPrefix);
10645
+ } else {
10646
+ // There was no hashbang path nor hash fragment:
10647
+ // If we are in HTML5 mode we use what is left as the path;
10648
+ // Otherwise we ignore what is left
10649
+ withoutHashUrl = this.$$html5 ? withoutBaseUrl : '';
10590
10650
  }
10651
+
10591
10652
  parseAppUrl(withoutHashUrl, this);
10592
10653
 
10593
10654
  this.$$path = removeWindowsDriveName(this.$$path, withoutHashUrl, appBase);
@@ -10950,7 +11011,7 @@ var locationPrototype = {
10950
11011
  *
10951
11012
  *
10952
11013
  * ```js
10953
- * // given url http://example.com/some/path?foo=bar&baz=xoxo#hashValue
11014
+ * // given url http://example.com/#/some/path?foo=bar&baz=xoxo#hashValue
10954
11015
  * var hash = $location.hash();
10955
11016
  * // => "hashValue"
10956
11017
  * ```
@@ -11302,10 +11363,11 @@ function $LocationProvider() {
11302
11363
 
11303
11364
  // update browser
11304
11365
  $rootScope.$watch(function $locationWatch() {
11305
- var oldUrl = $browser.url();
11366
+ var oldUrl = trimEmptyHash($browser.url());
11367
+ var newUrl = trimEmptyHash($location.absUrl());
11306
11368
  var oldState = $browser.state();
11307
11369
  var currentReplace = $location.$$replace;
11308
- var urlOrStateChanged = oldUrl !== $location.absUrl() ||
11370
+ var urlOrStateChanged = oldUrl !== newUrl ||
11309
11371
  ($location.$$html5 && $sniffer.history && oldState !== $location.$$state);
11310
11372
 
11311
11373
  if (initializing || urlOrStateChanged) {
@@ -12108,8 +12170,8 @@ Parser.prototype = {
12108
12170
  logicalAND: function() {
12109
12171
  var left = this.equality();
12110
12172
  var token;
12111
- if ((token = this.expect('&&'))) {
12112
- left = this.binaryFn(left, token.text, this.logicalAND(), true);
12173
+ while ((token = this.expect('&&'))) {
12174
+ left = this.binaryFn(left, token.text, this.equality(), true);
12113
12175
  }
12114
12176
  return left;
12115
12177
  },
@@ -12117,8 +12179,8 @@ Parser.prototype = {
12117
12179
  equality: function() {
12118
12180
  var left = this.relational();
12119
12181
  var token;
12120
- if ((token = this.expect('==','!=','===','!=='))) {
12121
- left = this.binaryFn(left, token.text, this.equality());
12182
+ while ((token = this.expect('==','!=','===','!=='))) {
12183
+ left = this.binaryFn(left, token.text, this.relational());
12122
12184
  }
12123
12185
  return left;
12124
12186
  },
@@ -12126,8 +12188,8 @@ Parser.prototype = {
12126
12188
  relational: function() {
12127
12189
  var left = this.additive();
12128
12190
  var token;
12129
- if ((token = this.expect('<', '>', '<=', '>='))) {
12130
- left = this.binaryFn(left, token.text, this.relational());
12191
+ while ((token = this.expect('<', '>', '<=', '>='))) {
12192
+ left = this.binaryFn(left, token.text, this.additive());
12131
12193
  }
12132
12194
  return left;
12133
12195
  },
@@ -12219,7 +12281,7 @@ Parser.prototype = {
12219
12281
  var args = argsFn.length ? [] : null;
12220
12282
 
12221
12283
  return function $parseFunctionCall(scope, locals) {
12222
- var context = contextGetter ? contextGetter(scope, locals) : scope;
12284
+ var context = contextGetter ? contextGetter(scope, locals) : isDefined(contextGetter) ? undefined : scope;
12223
12285
  var fn = fnGetter(scope, locals, context) || noop;
12224
12286
 
12225
12287
  if (args) {
@@ -15874,7 +15936,9 @@ function $SnifferProvider() {
15874
15936
  // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have
15875
15937
  // it. In particular the event is not fired when backspace or delete key are pressed or
15876
15938
  // when cut operation is performed.
15877
- if (event == 'input' && msie == 9) return false;
15939
+ // IE10+ implements 'input' event but it erroneously fires under various situations,
15940
+ // e.g. when placeholder changes, or a form is focused.
15941
+ if (event === 'input' && msie <= 11) return false;
15878
15942
 
15879
15943
  if (isUndefined(eventSupport[event])) {
15880
15944
  var divElm = document.createElement('div');
@@ -15934,10 +15998,8 @@ function $TemplateRequestProvider() {
15934
15998
 
15935
15999
  return $http.get(tpl, httpOptions)
15936
16000
  .then(function(response) {
15937
- var html = response.data;
15938
16001
  self.totalPendingRequests--;
15939
- $templateCache.put(tpl, html);
15940
- return html;
16002
+ return response.data;
15941
16003
  }, handleError);
15942
16004
 
15943
16005
  function handleError(resp) {
@@ -16568,106 +16630,103 @@ function filterFilter() {
16568
16630
  return function(array, expression, comparator) {
16569
16631
  if (!isArray(array)) return array;
16570
16632
 
16571
- var comparatorType = typeof(comparator),
16572
- predicates = [];
16573
-
16574
- predicates.check = function(value, index) {
16575
- for (var j = 0; j < predicates.length; j++) {
16576
- if (!predicates[j](value, index)) {
16577
- return false;
16578
- }
16579
- }
16580
- return true;
16581
- };
16633
+ var predicateFn;
16634
+ var matchAgainstAnyProp;
16582
16635
 
16583
- if (comparatorType !== 'function') {
16584
- if (comparatorType === 'boolean' && comparator) {
16585
- comparator = function(obj, text) {
16586
- return angular.equals(obj, text);
16587
- };
16588
- } else {
16589
- comparator = function(obj, text) {
16590
- if (obj && text && typeof obj === 'object' && typeof text === 'object') {
16591
- for (var objKey in obj) {
16592
- if (objKey.charAt(0) !== '$' && hasOwnProperty.call(obj, objKey) &&
16593
- comparator(obj[objKey], text[objKey])) {
16594
- return true;
16595
- }
16596
- }
16597
- return false;
16598
- }
16599
- text = ('' + text).toLowerCase();
16600
- return ('' + obj).toLowerCase().indexOf(text) > -1;
16601
- };
16602
- }
16603
- }
16604
-
16605
- var search = function(obj, text) {
16606
- if (typeof text === 'string' && text.charAt(0) === '!') {
16607
- return !search(obj, text.substr(1));
16608
- }
16609
- switch (typeof obj) {
16610
- case 'boolean':
16611
- case 'number':
16612
- case 'string':
16613
- return comparator(obj, text);
16614
- case 'object':
16615
- switch (typeof text) {
16616
- case 'object':
16617
- return comparator(obj, text);
16618
- default:
16619
- for (var objKey in obj) {
16620
- if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {
16621
- return true;
16622
- }
16623
- }
16624
- break;
16625
- }
16626
- return false;
16627
- case 'array':
16628
- for (var i = 0; i < obj.length; i++) {
16629
- if (search(obj[i], text)) {
16630
- return true;
16631
- }
16632
- }
16633
- return false;
16634
- default:
16635
- return false;
16636
- }
16637
- };
16638
16636
  switch (typeof expression) {
16637
+ case 'function':
16638
+ predicateFn = expression;
16639
+ break;
16639
16640
  case 'boolean':
16640
16641
  case 'number':
16641
16642
  case 'string':
16642
- // Set up expression object and fall through
16643
- expression = {$:expression};
16644
- // jshint -W086
16643
+ matchAgainstAnyProp = true;
16644
+ //jshint -W086
16645
16645
  case 'object':
16646
- // jshint +W086
16647
- for (var key in expression) {
16648
- (function(path) {
16649
- if (typeof expression[path] === 'undefined') return;
16650
- predicates.push(function(value) {
16651
- return search(path == '$' ? value : (value && value[path]), expression[path]);
16652
- });
16653
- })(key);
16654
- }
16655
- break;
16656
- case 'function':
16657
- predicates.push(expression);
16646
+ //jshint +W086
16647
+ predicateFn = createPredicateFn(expression, comparator, matchAgainstAnyProp);
16658
16648
  break;
16659
16649
  default:
16660
16650
  return array;
16661
16651
  }
16662
- var filtered = [];
16663
- for (var j = 0; j < array.length; j++) {
16664
- var value = array[j];
16665
- if (predicates.check(value, j)) {
16666
- filtered.push(value);
16652
+
16653
+ return array.filter(predicateFn);
16654
+ };
16655
+ }
16656
+
16657
+ // Helper functions for `filterFilter`
16658
+ function createPredicateFn(expression, comparator, matchAgainstAnyProp) {
16659
+ var predicateFn;
16660
+
16661
+ if (comparator === true) {
16662
+ comparator = equals;
16663
+ } else if (!isFunction(comparator)) {
16664
+ comparator = function(actual, expected) {
16665
+ if (isObject(actual) || isObject(expected)) {
16666
+ // Prevent an object to be considered equal to a string like `'[object'`
16667
+ return false;
16667
16668
  }
16668
- }
16669
- return filtered;
16669
+
16670
+ actual = lowercase('' + actual);
16671
+ expected = lowercase('' + expected);
16672
+ return actual.indexOf(expected) !== -1;
16673
+ };
16674
+ }
16675
+
16676
+ predicateFn = function(item) {
16677
+ return deepCompare(item, expression, comparator, matchAgainstAnyProp);
16670
16678
  };
16679
+
16680
+ return predicateFn;
16681
+ }
16682
+
16683
+ function deepCompare(actual, expected, comparator, matchAgainstAnyProp) {
16684
+ var actualType = typeof actual;
16685
+ var expectedType = typeof expected;
16686
+
16687
+ if ((expectedType === 'string') && (expected.charAt(0) === '!')) {
16688
+ return !deepCompare(actual, expected.substring(1), comparator, matchAgainstAnyProp);
16689
+ } else if (actualType === 'array') {
16690
+ // In case `actual` is an array, consider it a match
16691
+ // if ANY of it's items matches `expected`
16692
+ return actual.some(function(item) {
16693
+ return deepCompare(item, expected, comparator, matchAgainstAnyProp);
16694
+ });
16695
+ }
16696
+
16697
+ switch (actualType) {
16698
+ case 'object':
16699
+ var key;
16700
+ if (matchAgainstAnyProp) {
16701
+ for (key in actual) {
16702
+ if ((key.charAt(0) !== '$') && deepCompare(actual[key], expected, comparator)) {
16703
+ return true;
16704
+ }
16705
+ }
16706
+ return false;
16707
+ } else if (expectedType === 'object') {
16708
+ for (key in expected) {
16709
+ var expectedVal = expected[key];
16710
+ if (isFunction(expectedVal)) {
16711
+ continue;
16712
+ }
16713
+
16714
+ var keyIsDollar = key === '$';
16715
+ var actualVal = keyIsDollar ? actual : actual[key];
16716
+ if (!deepCompare(actualVal, expectedVal, comparator, keyIsDollar)) {
16717
+ return false;
16718
+ }
16719
+ }
16720
+ return true;
16721
+ } else {
16722
+ return comparator(actual, expected);
16723
+ }
16724
+ break;
16725
+ case 'function':
16726
+ return false;
16727
+ default:
16728
+ return comparator(actual, expected);
16729
+ }
16671
16730
  }
16672
16731
 
16673
16732
  /**
@@ -16820,7 +16879,6 @@ function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {
16820
16879
  if (numStr.indexOf('e') !== -1) {
16821
16880
  var match = numStr.match(/([\d\.]+)e(-?)(\d+)/);
16822
16881
  if (match && match[2] == '-' && match[3] > fractionSize + 1) {
16823
- numStr = '0';
16824
16882
  number = 0;
16825
16883
  } else {
16826
16884
  formatedText = numStr;
@@ -16841,10 +16899,6 @@ function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {
16841
16899
  // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round
16842
16900
  number = +(Math.round(+(number.toString() + 'e' + fractionSize)).toString() + 'e' + -fractionSize);
16843
16901
 
16844
- if (number === 0) {
16845
- isNegative = false;
16846
- }
16847
-
16848
16902
  var fraction = ('' + number).split(DECIMAL_SEP);
16849
16903
  var whole = fraction[0];
16850
16904
  fraction = fraction[1] || '';
@@ -16877,12 +16931,16 @@ function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {
16877
16931
 
16878
16932
  if (fractionSize && fractionSize !== "0") formatedText += decimalSep + fraction.substr(0, fractionSize);
16879
16933
  } else {
16880
-
16881
- if (fractionSize > 0 && number > -1 && number < 1) {
16934
+ if (fractionSize > 0 && number < 1) {
16882
16935
  formatedText = number.toFixed(fractionSize);
16936
+ number = parseFloat(formatedText);
16883
16937
  }
16884
16938
  }
16885
16939
 
16940
+ if (number === 0) {
16941
+ isNegative = false;
16942
+ }
16943
+
16886
16944
  parts.push(isNegative ? pattern.negPre : pattern.posPre,
16887
16945
  formatedText,
16888
16946
  isNegative ? pattern.negSuf : pattern.posSuf);
@@ -17172,25 +17230,31 @@ function dateFilter($locale) {
17172
17230
  * the binding is automatically converted to JSON.
17173
17231
  *
17174
17232
  * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.
17233
+ * @param {number=} spacing The number of spaces to use per indentation, defaults to 2.
17175
17234
  * @returns {string} JSON string.
17176
17235
  *
17177
17236
  *
17178
17237
  * @example
17179
17238
  <example>
17180
17239
  <file name="index.html">
17181
- <pre>{{ {'name':'value'} | json }}</pre>
17240
+ <pre id="default-spacing">{{ {'name':'value'} | json }}</pre>
17241
+ <pre id="custom-spacing">{{ {'name':'value'} | json:4 }}</pre>
17182
17242
  </file>
17183
17243
  <file name="protractor.js" type="protractor">
17184
17244
  it('should jsonify filtered objects', function() {
17185
- expect(element(by.binding("{'name':'value'}")).getText()).toMatch(/\{\n "name": ?"value"\n}/);
17245
+ expect(element(by.id('default-spacing')).getText()).toMatch(/\{\n "name": ?"value"\n}/);
17246
+ expect(element(by.id('custom-spacing')).getText()).toMatch(/\{\n "name": ?"value"\n}/);
17186
17247
  });
17187
17248
  </file>
17188
17249
  </example>
17189
17250
  *
17190
17251
  */
17191
17252
  function jsonFilter() {
17192
- return function(object) {
17193
- return toJson(object, true);
17253
+ return function(object, spacing) {
17254
+ if (isUndefined(spacing)) {
17255
+ spacing = 2;
17256
+ }
17257
+ return toJson(object, spacing);
17194
17258
  };
17195
17259
  }
17196
17260
 
@@ -17510,12 +17574,29 @@ function orderByFilter($parse) {
17510
17574
  function compare(v1, v2) {
17511
17575
  var t1 = typeof v1;
17512
17576
  var t2 = typeof v2;
17513
- if (t1 == t2) {
17514
- if (isDate(v1) && isDate(v2)) {
17515
- v1 = v1.valueOf();
17516
- v2 = v2.valueOf();
17577
+ // Prepare values for Abstract Relational Comparison
17578
+ // (http://www.ecma-international.org/ecma-262/5.1/#sec-11.8.5):
17579
+ // If the resulting values are identical, return 0 to prevent
17580
+ // incorrect re-ordering.
17581
+ if (t1 === t2 && t1 === "object") {
17582
+ // If types are both numbers, emulate abstract ToPrimitive() operation
17583
+ // in order to get primitive values suitable for comparison
17584
+ t1 = typeof (v1.valueOf ? v1 = v1.valueOf() : v1);
17585
+ t2 = typeof (v2.valueOf ? v2 = v2.valueOf() : v2);
17586
+ if (t1 === t2 && t1 === "object") {
17587
+ // Object.prototype.valueOf will return the original object, by
17588
+ // default. If we do not receive a primitive value, use ToString()
17589
+ // instead.
17590
+ t1 = typeof (v1.toString ? v1 = v1.toString() : v1);
17591
+ t2 = typeof (v2.toString ? v2 = v2.toString() : v2);
17592
+
17593
+ // If the end result of toString() for each item is the same, do not
17594
+ // perform relational comparison, and do not re-order objects.
17595
+ if (t1 === t2 && v1 === v2 || t1 === "object") return 0;
17517
17596
  }
17518
- if (t1 == "string") {
17597
+ }
17598
+ if (t1 === t2) {
17599
+ if (t1 === "string") {
17519
17600
  v1 = v1.toLowerCase();
17520
17601
  v2 = v2.toLowerCase();
17521
17602
  }
@@ -19464,7 +19545,6 @@ function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
19464
19545
  }
19465
19546
 
19466
19547
  function baseInputType(scope, element, attr, ctrl, $sniffer, $browser) {
19467
- var placeholder = element[0].placeholder, noevent = {};
19468
19548
  var type = lowercase(element[0].type);
19469
19549
 
19470
19550
  // In composition mode, users are still inputing intermediate text buffer,
@@ -19484,19 +19564,14 @@ function baseInputType(scope, element, attr, ctrl, $sniffer, $browser) {
19484
19564
  }
19485
19565
 
19486
19566
  var listener = function(ev) {
19567
+ if (timeout) {
19568
+ $browser.defer.cancel(timeout);
19569
+ timeout = null;
19570
+ }
19487
19571
  if (composing) return;
19488
19572
  var value = element.val(),
19489
19573
  event = ev && ev.type;
19490
19574
 
19491
- // IE (11 and under) seem to emit an 'input' event if the placeholder value changes.
19492
- // We don't want to dirty the value when this happens, so we abort here. Unfortunately,
19493
- // IE also sends input events for other non-input-related things, (such as focusing on a
19494
- // form control), so this change is not entirely enough to solve this.
19495
- if (msie && (ev || noevent).type === 'input' && element[0].placeholder !== placeholder) {
19496
- placeholder = element[0].placeholder;
19497
- return;
19498
- }
19499
-
19500
19575
  // By default we will trim the value
19501
19576
  // If the attribute ng-trim exists we will avoid trimming
19502
19577
  // If input type is 'password', the value is never trimmed
@@ -19519,11 +19594,13 @@ function baseInputType(scope, element, attr, ctrl, $sniffer, $browser) {
19519
19594
  } else {
19520
19595
  var timeout;
19521
19596
 
19522
- var deferListener = function(ev) {
19597
+ var deferListener = function(ev, input, origValue) {
19523
19598
  if (!timeout) {
19524
19599
  timeout = $browser.defer(function() {
19525
- listener(ev);
19526
19600
  timeout = null;
19601
+ if (!input || input.value !== origValue) {
19602
+ listener(ev);
19603
+ }
19527
19604
  });
19528
19605
  }
19529
19606
  };
@@ -19535,7 +19612,7 @@ function baseInputType(scope, element, attr, ctrl, $sniffer, $browser) {
19535
19612
  // command modifiers arrows
19536
19613
  if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;
19537
19614
 
19538
- deferListener(event);
19615
+ deferListener(event, this, this.value);
19539
19616
  });
19540
19617
 
19541
19618
  // if user modifies input value using context menu in IE, we need "paste" and "cut" events to catch it
@@ -20710,11 +20787,15 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
20710
20787
  var prevModelValue = ctrl.$modelValue;
20711
20788
  var allowInvalid = ctrl.$options && ctrl.$options.allowInvalid;
20712
20789
  ctrl.$$rawModelValue = modelValue;
20790
+
20713
20791
  if (allowInvalid) {
20714
20792
  ctrl.$modelValue = modelValue;
20715
20793
  writeToModelIfNeeded();
20716
20794
  }
20717
- ctrl.$$runValidators(parserValid, modelValue, viewValue, function(allValid) {
20795
+
20796
+ // Pass the $$lastCommittedViewValue here, because the cached viewValue might be out of date.
20797
+ // This can happen if e.g. $setViewValue is called from inside a parser
20798
+ ctrl.$$runValidators(parserValid, modelValue, ctrl.$$lastCommittedViewValue, function(allValid) {
20718
20799
  if (!allowInvalid) {
20719
20800
  // Note: Don't check ctrl.$valid here, as we could have
20720
20801
  // external validators (e.g. calculated on the server),
@@ -25056,7 +25137,7 @@ var ngSwitchDefaultDirective = ngDirective({
25056
25137
  }]);
25057
25138
  </script>
25058
25139
  <div ng-controller="ExampleController">
25059
- <input ng-model="title"><br>
25140
+ <input ng-model="title"> <br/>
25060
25141
  <textarea ng-model="text"></textarea> <br/>
25061
25142
  <pane title="{{title}}">{{text}}</pane>
25062
25143
  </div>
@@ -25184,9 +25265,9 @@ var ngOptionsMinErr = minErr('ngOptions');
25184
25265
  * or property name (for object data sources) of the value within the collection. If a `track by` expression
25185
25266
  * is used, the result of that expression will be set as the value of the `option` and `select` elements.
25186
25267
  *
25187
- * ### `select as` with `trackexpr`
25268
+ * ### `select as` with `track by`
25188
25269
  *
25189
- * Using `select as` together with `trackexpr` is not recommended. Reasoning:
25270
+ * Using `select as` together with `track by` is not recommended. Reasoning:
25190
25271
  *
25191
25272
  * - Example: &lt;select ng-options="item.subItem as item.label for item in values track by item.id" ng-model="selected"&gt;
25192
25273
  * values: [{id: 1, label: 'aLabel', subItem: {name: 'aSubItem'}}, {id: 2, label: 'bLabel', subItem: {name: 'bSubItem'}}],
@@ -25211,8 +25292,10 @@ var ngOptionsMinErr = minErr('ngOptions');
25211
25292
  * * for array data sources:
25212
25293
  * * `label` **`for`** `value` **`in`** `array`
25213
25294
  * * `select` **`as`** `label` **`for`** `value` **`in`** `array`
25214
- * * `label` **`group by`** `group` **`for`** `value` **`in`** `array`
25215
- * * `select` **`as`** `label` **`group by`** `group` **`for`** `value` **`in`** `array` **`track by`** `trackexpr`
25295
+ * * `label` **`group by`** `group` **`for`** `value` **`in`** `array`
25296
+ * * `label` **`group by`** `group` **`for`** `value` **`in`** `array` **`track by`** `trackexpr`
25297
+ * * `label` **`for`** `value` **`in`** `array` | orderBy:`orderexpr` **`track by`** `trackexpr`
25298
+ * (for including a filter with `track by`)
25216
25299
  * * for object data sources:
25217
25300
  * * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`
25218
25301
  * * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`