angularjs-rails 1.3.6 → 1.3.8

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 +3 -2
  4. data/vendor/assets/javascripts/angular-aria.js +20 -13
  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 +15 -15
  9. data/vendor/assets/javascripts/angular-resource.js +2 -2
  10. data/vendor/assets/javascripts/angular-route.js +1 -1
  11. data/vendor/assets/javascripts/angular-sanitize.js +1 -1
  12. data/vendor/assets/javascripts/angular-scenario.js +223 -153
  13. data/vendor/assets/javascripts/angular-touch.js +1 -1
  14. data/vendor/assets/javascripts/angular.js +223 -153
  15. data/vendor/assets/javascripts/unstable/angular-animate.js +3 -2
  16. data/vendor/assets/javascripts/unstable/angular-aria.js +20 -13
  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 +15 -15
  21. data/vendor/assets/javascripts/unstable/angular-resource.js +2 -2
  22. data/vendor/assets/javascripts/unstable/angular-route.js +1 -1
  23. data/vendor/assets/javascripts/unstable/angular-sanitize.js +1 -1
  24. data/vendor/assets/javascripts/unstable/angular-scenario.js +223 -153
  25. data/vendor/assets/javascripts/unstable/angular-touch.js +1 -1
  26. data/vendor/assets/javascripts/unstable/angular.js +223 -153
  27. metadata +1 -1
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.3.36
2
+ * @license AngularJS v1.3.8
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.36
2
+ * @license AngularJS v1.3.8
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.36/' +
57
+ message = message + '\nhttp://errors.angularjs.org/1.3.8/' +
58
58
  (module ? module + '/' : '') + code;
59
59
  for (i = 2; i < arguments.length; i++) {
60
60
  message = message + (i == 2 ? '?' : '&') + 'p' + (i - 2) + '=' +
@@ -109,6 +109,7 @@ function minErr(module, ErrorConstructor) {
109
109
  isWindow: true,
110
110
  isScope: true,
111
111
  isFile: true,
112
+ isFormData: true,
112
113
  isBlob: true,
113
114
  isBoolean: true,
114
115
  isPromiseLike: true,
@@ -464,6 +465,8 @@ noop.$inject = [];
464
465
  return (transformationFn || angular.identity)(value);
465
466
  };
466
467
  ```
468
+ * @param {*} value to be returned.
469
+ * @returns {*} the value passed in.
467
470
  */
468
471
  function identity($) {return $;}
469
472
  identity.$inject = [];
@@ -630,6 +633,11 @@ function isFile(obj) {
630
633
  }
631
634
 
632
635
 
636
+ function isFormData(obj) {
637
+ return toString.call(obj) === '[object FormData]';
638
+ }
639
+
640
+
633
641
  function isBlob(obj) {
634
642
  return toString.call(obj) === '[object Blob]';
635
643
  }
@@ -713,7 +721,7 @@ function arrayRemove(array, value) {
713
721
  * Creates a deep copy of `source`, which should be an object or an array.
714
722
  *
715
723
  * * If no destination is supplied, a copy of the object or array is created.
716
- * * If a destination is provided, all of its elements (for array) or properties (for objects)
724
+ * * If a destination is provided, all of its elements (for arrays) or properties (for objects)
717
725
  * are deleted and then all elements/properties from the source are copied to it.
718
726
  * * If `source` is not an object or array (inc. `null` and `undefined`), `source` is returned.
719
727
  * * If `source` is identical to 'destination' an exception will be thrown.
@@ -1051,7 +1059,7 @@ function toJson(obj, pretty) {
1051
1059
  * Deserializes a JSON string.
1052
1060
  *
1053
1061
  * @param {string} json JSON string to deserialize.
1054
- * @returns {Object|Array|string|number} Deserialized thingy.
1062
+ * @returns {Object|Array|string|number} Deserialized JSON string.
1055
1063
  */
1056
1064
  function fromJson(json) {
1057
1065
  return isString(json)
@@ -1224,7 +1232,7 @@ function getNgAttribute(element, ngAttr) {
1224
1232
  * {@link angular.bootstrap} instead. AngularJS applications cannot be nested within each other.
1225
1233
  *
1226
1234
  * You can specify an **AngularJS module** to be used as the root module for the application. This
1227
- * module will be loaded into the {@link auto.$injector} when the application is bootstrapped and
1235
+ * module will be loaded into the {@link auto.$injector} when the application is bootstrapped. It
1228
1236
  * should contain the application code needed or have dependencies on other modules that will
1229
1237
  * contain the code. See {@link angular.module} for more information.
1230
1238
  *
@@ -1232,7 +1240,7 @@ function getNgAttribute(element, ngAttr) {
1232
1240
  * document would not be compiled, the `AppController` would not be instantiated and the `{{ a+b }}`
1233
1241
  * would not be resolved to `3`.
1234
1242
  *
1235
- * `ngApp` is the easiest, and most common, way to bootstrap an application.
1243
+ * `ngApp` is the easiest, and most common way to bootstrap an application.
1236
1244
  *
1237
1245
  <example module="ngAppDemo">
1238
1246
  <file name="index.html">
@@ -1492,7 +1500,12 @@ function reloadWithDebugInfo() {
1492
1500
  * @param {DOMElement} element DOM element which is the root of angular application.
1493
1501
  */
1494
1502
  function getTestability(rootElement) {
1495
- return angular.element(rootElement).injector().get('$$testability');
1503
+ var injector = angular.element(rootElement).injector();
1504
+ if (!injector) {
1505
+ throw ngMinErr('test',
1506
+ 'no injector found for element argument to getTestability');
1507
+ }
1508
+ return injector.get('$$testability');
1496
1509
  }
1497
1510
 
1498
1511
  var SNAKE_CASE_REGEXP = /[A-Z]/g;
@@ -2105,11 +2118,11 @@ function toDebugString(obj) {
2105
2118
  * - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat".
2106
2119
  */
2107
2120
  var version = {
2108
- full: '1.3.36', // all of these placeholder strings will be replaced by grunt's
2121
+ full: '1.3.8', // all of these placeholder strings will be replaced by grunt's
2109
2122
  major: 1, // package task
2110
2123
  minor: 3,
2111
- dot: 36,
2112
- codeName: 'robofunky-danceblaster'
2124
+ dot: 8,
2125
+ codeName: 'prophetic-narwhal'
2113
2126
  };
2114
2127
 
2115
2128
 
@@ -7122,7 +7135,10 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
7122
7135
  // support ngAttr attribute binding
7123
7136
  ngAttrName = directiveNormalize(name);
7124
7137
  if (isNgAttr = NG_ATTR_BINDING.test(ngAttrName)) {
7125
- name = snake_case(ngAttrName.substr(6), '-');
7138
+ name = name.replace(PREFIX_REGEXP, '')
7139
+ .substr(8).replace(/_(.)/g, function(match, letter) {
7140
+ return letter.toUpperCase();
7141
+ });
7126
7142
  }
7127
7143
 
7128
7144
  var directiveNName = ngAttrName.replace(/(Start|End)$/, '');
@@ -8034,7 +8050,10 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
8034
8050
 
8035
8051
 
8036
8052
  function addAttrInterpolateDirective(node, directives, value, name, allOrNothing) {
8037
- var interpolateFn = $interpolate(value, true);
8053
+ var trustedContext = getTrustedContext(node, name);
8054
+ allOrNothing = ALL_OR_NOTHING_ATTRS[name] || allOrNothing;
8055
+
8056
+ var interpolateFn = $interpolate(value, true, trustedContext, allOrNothing);
8038
8057
 
8039
8058
  // no interpolation found -> ignore
8040
8059
  if (!interpolateFn) return;
@@ -8059,16 +8078,16 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
8059
8078
  "ng- versions (such as ng-click instead of onclick) instead.");
8060
8079
  }
8061
8080
 
8062
- // If the attribute was removed, then we are done
8063
- if (!attr[name]) {
8064
- return;
8081
+ // If the attribute has changed since last $interpolate()ed
8082
+ var newValue = attr[name];
8083
+ if (newValue !== value) {
8084
+ // we need to interpolate again since the attribute value has been updated
8085
+ // (e.g. by another directive's compile function)
8086
+ // ensure unset/empty values make interpolateFn falsy
8087
+ interpolateFn = newValue && $interpolate(newValue, true, trustedContext, allOrNothing);
8088
+ value = newValue;
8065
8089
  }
8066
8090
 
8067
- // we need to interpolate again, in case the attribute value has been updated
8068
- // (e.g. by another directive's compile function)
8069
- interpolateFn = $interpolate(attr[name], true, getTrustedContext(node, name),
8070
- ALL_OR_NOTHING_ATTRS[name] || allOrNothing);
8071
-
8072
8091
  // if attribute was updated so that there is no interpolation going on we don't want to
8073
8092
  // register any observers
8074
8093
  if (!interpolateFn) return;
@@ -8529,23 +8548,34 @@ function $ExceptionHandlerProvider() {
8529
8548
 
8530
8549
  var APPLICATION_JSON = 'application/json';
8531
8550
  var CONTENT_TYPE_APPLICATION_JSON = {'Content-Type': APPLICATION_JSON + ';charset=utf-8'};
8532
- var JSON_START = /^\s*(\[|\{[^\{])/;
8533
- var JSON_END = /[\}\]]\s*$/;
8551
+ var JSON_START = /^\[|^\{(?!\{)/;
8552
+ var JSON_ENDS = {
8553
+ '[': /]$/,
8554
+ '{': /}$/
8555
+ };
8534
8556
  var JSON_PROTECTION_PREFIX = /^\)\]\}',?\n/;
8535
8557
 
8536
8558
  function defaultHttpResponseTransform(data, headers) {
8537
8559
  if (isString(data)) {
8538
- // strip json vulnerability protection prefix
8539
- data = data.replace(JSON_PROTECTION_PREFIX, '');
8540
- var contentType = headers('Content-Type');
8541
- if ((contentType && contentType.indexOf(APPLICATION_JSON) === 0 && data.trim()) ||
8542
- (JSON_START.test(data) && JSON_END.test(data))) {
8543
- data = fromJson(data);
8560
+ // Strip json vulnerability protection prefix and trim whitespace
8561
+ var tempData = data.replace(JSON_PROTECTION_PREFIX, '').trim();
8562
+
8563
+ if (tempData) {
8564
+ var contentType = headers('Content-Type');
8565
+ if ((contentType && (contentType.indexOf(APPLICATION_JSON) === 0)) || isJsonLike(tempData)) {
8566
+ data = fromJson(tempData);
8567
+ }
8544
8568
  }
8545
8569
  }
8570
+
8546
8571
  return data;
8547
8572
  }
8548
8573
 
8574
+ function isJsonLike(str) {
8575
+ var jsonStart = str.match(JSON_START);
8576
+ return jsonStart && JSON_ENDS[jsonStart[0]].test(str);
8577
+ }
8578
+
8549
8579
  /**
8550
8580
  * Parse headers into key value object
8551
8581
  *
@@ -8608,16 +8638,17 @@ function headersGetter(headers) {
8608
8638
  * This function is used for both request and response transforming
8609
8639
  *
8610
8640
  * @param {*} data Data to transform.
8611
- * @param {function(string=)} headers Http headers getter fn.
8641
+ * @param {function(string=)} headers HTTP headers getter fn.
8642
+ * @param {number} status HTTP status code of the response.
8612
8643
  * @param {(Function|Array.<Function>)} fns Function or an array of functions.
8613
8644
  * @returns {*} Transformed data.
8614
8645
  */
8615
- function transformData(data, headers, fns) {
8646
+ function transformData(data, headers, status, fns) {
8616
8647
  if (isFunction(fns))
8617
- return fns(data, headers);
8648
+ return fns(data, headers, status);
8618
8649
 
8619
8650
  forEach(fns, function(fn) {
8620
- data = fn(data, headers);
8651
+ data = fn(data, headers, status);
8621
8652
  });
8622
8653
 
8623
8654
  return data;
@@ -8669,7 +8700,7 @@ function $HttpProvider() {
8669
8700
 
8670
8701
  // transform outgoing request data
8671
8702
  transformRequest: [function(d) {
8672
- return isObject(d) && !isFile(d) && !isBlob(d) ? toJson(d) : d;
8703
+ return isObject(d) && !isFile(d) && !isBlob(d) && !isFormData(d) ? toJson(d) : d;
8673
8704
  }],
8674
8705
 
8675
8706
  // default headers
@@ -8896,7 +8927,7 @@ function $HttpProvider() {
8896
8927
  *
8897
8928
  * Both requests and responses can be transformed using transformation functions: `transformRequest`
8898
8929
  * and `transformResponse`. These properties can be a single function that returns
8899
- * the transformed value (`{function(data, headersGetter)`) or an array of such transformation functions,
8930
+ * the transformed value (`{function(data, headersGetter, status)`) or an array of such transformation functions,
8900
8931
  * which allows you to `push` or `unshift` a new transformation function into the transformation chain.
8901
8932
  *
8902
8933
  * ### Default Transformations
@@ -9140,9 +9171,9 @@ function $HttpProvider() {
9140
9171
  * See {@link ng.$http#overriding-the-default-transformations-per-request
9141
9172
  * Overriding the Default Transformations}
9142
9173
  * - **transformResponse** –
9143
- * `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –
9174
+ * `{function(data, headersGetter, status)|Array.<function(data, headersGetter, status)>}` –
9144
9175
  * transform function or an array of such functions. The transform function takes the http
9145
- * response body and headers and returns its transformed (typically deserialized) version.
9176
+ * response body, headers and status and returns its transformed (typically deserialized) version.
9146
9177
  * See {@link ng.$http#overriding-the-default-transformations-per-request
9147
9178
  * Overriding the Default Transformations}
9148
9179
  * - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the
@@ -9265,24 +9296,23 @@ function $HttpProvider() {
9265
9296
  </example>
9266
9297
  */
9267
9298
  function $http(requestConfig) {
9268
- var config = {
9269
- method: 'get',
9270
- transformRequest: defaults.transformRequest,
9271
- transformResponse: defaults.transformResponse
9272
- };
9273
- var headers = mergeHeaders(requestConfig);
9274
9299
 
9275
9300
  if (!angular.isObject(requestConfig)) {
9276
9301
  throw minErr('$http')('badreq', 'Http request configuration must be an object. Received: {0}', requestConfig);
9277
9302
  }
9278
9303
 
9279
- extend(config, requestConfig);
9280
- config.headers = headers;
9304
+ var config = extend({
9305
+ method: 'get',
9306
+ transformRequest: defaults.transformRequest,
9307
+ transformResponse: defaults.transformResponse
9308
+ }, requestConfig);
9309
+
9310
+ config.headers = mergeHeaders(requestConfig);
9281
9311
  config.method = uppercase(config.method);
9282
9312
 
9283
9313
  var serverRequest = function(config) {
9284
- headers = config.headers;
9285
- var reqData = transformData(config.data, headersGetter(headers), config.transformRequest);
9314
+ var headers = config.headers;
9315
+ var reqData = transformData(config.data, headersGetter(headers), undefined, config.transformRequest);
9286
9316
 
9287
9317
  // strip content-type if data is undefined
9288
9318
  if (isUndefined(reqData)) {
@@ -9298,7 +9328,7 @@ function $HttpProvider() {
9298
9328
  }
9299
9329
 
9300
9330
  // send request
9301
- return sendReq(config, reqData, headers).then(transformResponse, transformResponse);
9331
+ return sendReq(config, reqData).then(transformResponse, transformResponse);
9302
9332
  };
9303
9333
 
9304
9334
  var chain = [serverRequest, undefined];
@@ -9343,13 +9373,30 @@ function $HttpProvider() {
9343
9373
  if (!response.data) {
9344
9374
  resp.data = response.data;
9345
9375
  } else {
9346
- resp.data = transformData(response.data, response.headers, config.transformResponse);
9376
+ resp.data = transformData(response.data, response.headers, response.status, config.transformResponse);
9347
9377
  }
9348
9378
  return (isSuccess(response.status))
9349
9379
  ? resp
9350
9380
  : $q.reject(resp);
9351
9381
  }
9352
9382
 
9383
+ function executeHeaderFns(headers) {
9384
+ var headerContent, processedHeaders = {};
9385
+
9386
+ forEach(headers, function(headerFn, header) {
9387
+ if (isFunction(headerFn)) {
9388
+ headerContent = headerFn();
9389
+ if (headerContent != null) {
9390
+ processedHeaders[header] = headerContent;
9391
+ }
9392
+ } else {
9393
+ processedHeaders[header] = headerFn;
9394
+ }
9395
+ });
9396
+
9397
+ return processedHeaders;
9398
+ }
9399
+
9353
9400
  function mergeHeaders(config) {
9354
9401
  var defHeaders = defaults.headers,
9355
9402
  reqHeaders = extend({}, config.headers),
@@ -9372,23 +9419,7 @@ function $HttpProvider() {
9372
9419
  }
9373
9420
 
9374
9421
  // execute if header value is a function for merged headers
9375
- execHeaders(reqHeaders);
9376
- return reqHeaders;
9377
-
9378
- function execHeaders(headers) {
9379
- var headerContent;
9380
-
9381
- forEach(headers, function(headerFn, header) {
9382
- if (isFunction(headerFn)) {
9383
- headerContent = headerFn();
9384
- if (headerContent != null) {
9385
- headers[header] = headerContent;
9386
- } else {
9387
- delete headers[header];
9388
- }
9389
- }
9390
- });
9391
- }
9422
+ return executeHeaderFns(reqHeaders);
9392
9423
  }
9393
9424
  }
9394
9425
 
@@ -9531,11 +9562,12 @@ function $HttpProvider() {
9531
9562
  * !!! ACCESSES CLOSURE VARS:
9532
9563
  * $httpBackend, defaults, $log, $rootScope, defaultCache, $http.pendingRequests
9533
9564
  */
9534
- function sendReq(config, reqData, reqHeaders) {
9565
+ function sendReq(config, reqData) {
9535
9566
  var deferred = $q.defer(),
9536
9567
  promise = deferred.promise,
9537
9568
  cache,
9538
9569
  cachedResp,
9570
+ reqHeaders = config.headers,
9539
9571
  url = buildUrl(config.url, config.params);
9540
9572
 
9541
9573
  $http.pendingRequests.push(config);
@@ -11235,8 +11267,8 @@ function $LocationProvider() {
11235
11267
  * @param {string=} oldState History state object that was before it was changed.
11236
11268
  */
11237
11269
 
11238
- this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',
11239
- function($rootScope, $browser, $sniffer, $rootElement) {
11270
+ this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement', '$window',
11271
+ function($rootScope, $browser, $sniffer, $rootElement, $window) {
11240
11272
  var $location,
11241
11273
  LocationMode,
11242
11274
  baseHref = $browser.baseHref(), // if base[href] is undefined, it defaults to ''
@@ -11318,7 +11350,7 @@ function $LocationProvider() {
11318
11350
  if ($location.absUrl() != $browser.url()) {
11319
11351
  $rootScope.$apply();
11320
11352
  // hack to work around FF6 bug 684208 when scenario runner clicks on links
11321
- window.angular['ff-684208-preventDefault'] = true;
11353
+ $window.angular['ff-684208-preventDefault'] = true;
11322
11354
  }
11323
11355
  }
11324
11356
  }
@@ -11934,6 +11966,8 @@ Parser.prototype = {
11934
11966
  primary = this.arrayDeclaration();
11935
11967
  } else if (this.expect('{')) {
11936
11968
  primary = this.object();
11969
+ } else if (this.peek().identifier && this.peek().text in CONSTANTS) {
11970
+ primary = CONSTANTS[this.consume().text];
11937
11971
  } else if (this.peek().identifier) {
11938
11972
  primary = this.identifier();
11939
11973
  } else if (this.peek().constant) {
@@ -12036,7 +12070,7 @@ Parser.prototype = {
12036
12070
  id += this.consume().text + this.consume().text;
12037
12071
  }
12038
12072
 
12039
- return CONSTANTS[id] || getterFn(id, this.options, this.text);
12073
+ return getterFn(id, this.options, this.text);
12040
12074
  },
12041
12075
 
12042
12076
  constant: function() {
@@ -12226,17 +12260,16 @@ Parser.prototype = {
12226
12260
  },
12227
12261
 
12228
12262
  fieldAccess: function(object) {
12229
- var expression = this.text;
12230
- var field = this.consume().text;
12231
- var getter = getterFn(field, this.options, expression);
12263
+ var getter = this.identifier();
12232
12264
 
12233
12265
  return extend(function $parseFieldAccess(scope, locals, self) {
12234
- return getter(self || object(scope, locals));
12266
+ var o = self || object(scope, locals);
12267
+ return (o == null) ? undefined : getter(o);
12235
12268
  }, {
12236
12269
  assign: function(scope, value, locals) {
12237
12270
  var o = object(scope, locals);
12238
12271
  if (!o) object.assign(scope, o = {});
12239
- return setter(o, field, value, expression);
12272
+ return getter.assign(o, value);
12240
12273
  }
12241
12274
  });
12242
12275
  },
@@ -13394,12 +13427,10 @@ function qFactory(nextTick, exceptionHandler) {
13394
13427
  function $$RAFProvider() { //rAF
13395
13428
  this.$get = ['$window', '$timeout', function($window, $timeout) {
13396
13429
  var requestAnimationFrame = $window.requestAnimationFrame ||
13397
- $window.webkitRequestAnimationFrame ||
13398
- $window.mozRequestAnimationFrame;
13430
+ $window.webkitRequestAnimationFrame;
13399
13431
 
13400
13432
  var cancelAnimationFrame = $window.cancelAnimationFrame ||
13401
13433
  $window.webkitCancelAnimationFrame ||
13402
- $window.mozCancelAnimationFrame ||
13403
13434
  $window.webkitCancelRequestAnimationFrame;
13404
13435
 
13405
13436
  var rafSupported = !!requestAnimationFrame;
@@ -13528,7 +13559,6 @@ function $RootScopeProvider() {
13528
13559
  var child = parent.$new();
13529
13560
 
13530
13561
  parent.salutation = "Hello";
13531
- child.name = "World";
13532
13562
  expect(child.salutation).toEqual('Hello');
13533
13563
 
13534
13564
  child.salutation = "Welcome";
@@ -14166,7 +14196,7 @@ function $RootScopeProvider() {
14166
14196
  while (asyncQueue.length) {
14167
14197
  try {
14168
14198
  asyncTask = asyncQueue.shift();
14169
- asyncTask.scope.$eval(asyncTask.expression);
14199
+ asyncTask.scope.$eval(asyncTask.expression, asyncTask.locals);
14170
14200
  } catch (e) {
14171
14201
  $exceptionHandler(e);
14172
14202
  }
@@ -14381,8 +14411,9 @@ function $RootScopeProvider() {
14381
14411
  * - `string`: execute using the rules as defined in {@link guide/expression expression}.
14382
14412
  * - `function(scope)`: execute the function with the current `scope` parameter.
14383
14413
  *
14414
+ * @param {(object)=} locals Local variables object, useful for overriding values in scope.
14384
14415
  */
14385
- $evalAsync: function(expr) {
14416
+ $evalAsync: function(expr, locals) {
14386
14417
  // if we are outside of an $digest loop and this is the first time we are scheduling async
14387
14418
  // task also schedule async auto-flush
14388
14419
  if (!$rootScope.$$phase && !asyncQueue.length) {
@@ -14393,7 +14424,7 @@ function $RootScopeProvider() {
14393
14424
  });
14394
14425
  }
14395
14426
 
14396
- asyncQueue.push({scope: this, expression: expr});
14427
+ asyncQueue.push({scope: this, expression: expr, locals: locals});
14397
14428
  },
14398
14429
 
14399
14430
  $$postDigest: function(fn) {
@@ -15965,7 +15996,7 @@ var $compileMinErr = minErr('$compile');
15965
15996
  * @description
15966
15997
  * The `$templateRequest` service downloads the provided template using `$http` and, upon success,
15967
15998
  * stores the contents inside of `$templateCache`. If the HTTP request fails or the response data
15968
- * of the HTTP request is empty then a `$compile` error will be thrown (the exception can be thwarted
15999
+ * of the HTTP request is empty, a `$compile` error will be thrown (the exception can be thwarted
15969
16000
  * by setting the 2nd parameter of the function to true).
15970
16001
  *
15971
16002
  * @param {string} tpl The HTTP request template URL
@@ -16525,19 +16556,26 @@ function $FilterProvider($provide) {
16525
16556
  *
16526
16557
  * Can be one of:
16527
16558
  *
16528
- * - `string`: The string is evaluated as an expression and the resulting value is used for substring match against
16529
- * the contents of the `array`. All strings or objects with string properties in `array` that contain this string
16530
- * will be returned. The predicate can be negated by prefixing the string with `!`.
16559
+ * - `string`: The string is used for matching against the contents of the `array`. All strings or
16560
+ * objects with string properties in `array` that match this string will be returned. This also
16561
+ * applies to nested object properties.
16562
+ * The predicate can be negated by prefixing the string with `!`.
16531
16563
  *
16532
16564
  * - `Object`: A pattern object can be used to filter specific properties on objects contained
16533
16565
  * by `array`. For example `{name:"M", phone:"1"}` predicate will return an array of items
16534
16566
  * which have property `name` containing "M" and property `phone` containing "1". A special
16535
16567
  * property name `$` can be used (as in `{$:"text"}`) to accept a match against any
16536
- * property of the object. That's equivalent to the simple substring match with a `string`
16537
- * as described above. The predicate can be negated by prefixing the string with `!`.
16538
- * For Example `{name: "!M"}` predicate will return an array of items which have property `name`
16568
+ * property of the object or its nested object properties. That's equivalent to the simple
16569
+ * substring match with a `string` as described above. The predicate can be negated by prefixing
16570
+ * the string with `!`.
16571
+ * For example `{name: "!M"}` predicate will return an array of items which have property `name`
16539
16572
  * not containing "M".
16540
16573
  *
16574
+ * Note that a named property will match properties on the same level only, while the special
16575
+ * `$` property will match properties on the same level or deeper. E.g. an array item like
16576
+ * `{name: {first: 'John', last: 'Doe'}}` will **not** be matched by `{name: 'John'}`, but
16577
+ * **will** be matched by `{$: 'John'}`.
16578
+ *
16541
16579
  * - `function(value, index)`: A predicate function can be used to write arbitrary filters. The
16542
16580
  * function is called for each element of `array`. The final result is an array of those
16543
16581
  * elements that the predicate returned true for.
@@ -16550,10 +16588,10 @@ function $FilterProvider($provide) {
16550
16588
  *
16551
16589
  * - `function(actual, expected)`:
16552
16590
  * The function will be given the object value and the predicate value to compare and
16553
- * should return true if the item should be included in filtered result.
16591
+ * should return true if both values should be considered equal.
16554
16592
  *
16555
- * - `true`: A shorthand for `function(actual, expected) { return angular.equals(expected, actual)}`.
16556
- * this is essentially strict comparison of expected and actual.
16593
+ * - `true`: A shorthand for `function(actual, expected) { return angular.equals(actual, expected)}`.
16594
+ * This is essentially strict comparison of expected and actual.
16557
16595
  *
16558
16596
  * - `false|undefined`: A short hand for a function which will look for a substring match in case
16559
16597
  * insensitive way.
@@ -16656,6 +16694,7 @@ function filterFilter() {
16656
16694
 
16657
16695
  // Helper functions for `filterFilter`
16658
16696
  function createPredicateFn(expression, comparator, matchAgainstAnyProp) {
16697
+ var shouldMatchPrimitives = isObject(expression) && ('$' in expression);
16659
16698
  var predicateFn;
16660
16699
 
16661
16700
  if (comparator === true) {
@@ -16674,13 +16713,16 @@ function createPredicateFn(expression, comparator, matchAgainstAnyProp) {
16674
16713
  }
16675
16714
 
16676
16715
  predicateFn = function(item) {
16716
+ if (shouldMatchPrimitives && !isObject(item)) {
16717
+ return deepCompare(item, expression.$, comparator, false);
16718
+ }
16677
16719
  return deepCompare(item, expression, comparator, matchAgainstAnyProp);
16678
16720
  };
16679
16721
 
16680
16722
  return predicateFn;
16681
16723
  }
16682
16724
 
16683
- function deepCompare(actual, expected, comparator, matchAgainstAnyProp) {
16725
+ function deepCompare(actual, expected, comparator, matchAgainstAnyProp, dontMatchWholeObject) {
16684
16726
  var actualType = typeof actual;
16685
16727
  var expectedType = typeof expected;
16686
16728
 
@@ -16699,11 +16741,11 @@ function deepCompare(actual, expected, comparator, matchAgainstAnyProp) {
16699
16741
  var key;
16700
16742
  if (matchAgainstAnyProp) {
16701
16743
  for (key in actual) {
16702
- if ((key.charAt(0) !== '$') && deepCompare(actual[key], expected, comparator)) {
16744
+ if ((key.charAt(0) !== '$') && deepCompare(actual[key], expected, comparator, true)) {
16703
16745
  return true;
16704
16746
  }
16705
16747
  }
16706
- return false;
16748
+ return dontMatchWholeObject ? false : deepCompare(actual, expected, comparator, false);
16707
16749
  } else if (expectedType === 'object') {
16708
16750
  for (key in expected) {
16709
16751
  var expectedVal = expected[key];
@@ -16711,9 +16753,9 @@ function deepCompare(actual, expected, comparator, matchAgainstAnyProp) {
16711
16753
  continue;
16712
16754
  }
16713
16755
 
16714
- var keyIsDollar = key === '$';
16715
- var actualVal = keyIsDollar ? actual : actual[key];
16716
- if (!deepCompare(actualVal, expectedVal, comparator, keyIsDollar)) {
16756
+ var matchAnyProperty = key === '$';
16757
+ var actualVal = matchAnyProperty ? actual : actual[key];
16758
+ if (!deepCompare(actualVal, expectedVal, comparator, matchAnyProperty, matchAnyProperty)) {
16717
16759
  return false;
16718
16760
  }
16719
16761
  }
@@ -17085,8 +17127,8 @@ var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZEw']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d
17085
17127
  * * `'.sss' or ',sss'`: Millisecond in second, padded (000-999)
17086
17128
  * * `'a'`: AM/PM marker
17087
17129
  * * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-+1200)
17088
- * * `'ww'`: ISO-8601 week of year (00-53)
17089
- * * `'w'`: ISO-8601 week of year (0-53)
17130
+ * * `'ww'`: Week of year, padded (00-53). Week 01 is the week with the first Thursday of the year
17131
+ * * `'w'`: Week of year (0-53). Week 1 is the week with the first Thursday of the year
17090
17132
  *
17091
17133
  * `format` string can also be one of the following predefined
17092
17134
  * {@link guide/i18n localizable formats}:
@@ -17386,8 +17428,7 @@ function limitToFilter() {
17386
17428
  }
17387
17429
  }
17388
17430
 
17389
- var out = [],
17390
- i, n;
17431
+ var i, n;
17391
17432
 
17392
17433
  // if abs(limit) exceeds maximum length, trim it
17393
17434
  if (limit > input.length)
@@ -17399,15 +17440,14 @@ function limitToFilter() {
17399
17440
  i = 0;
17400
17441
  n = limit;
17401
17442
  } else {
17443
+ // zero and NaN check on limit - return empty array
17444
+ if (!limit) return [];
17445
+
17402
17446
  i = input.length + limit;
17403
17447
  n = input.length;
17404
17448
  }
17405
17449
 
17406
- for (; i < n; i++) {
17407
- out.push(input[i]);
17408
- }
17409
-
17410
- return out;
17450
+ return input.slice(i, n);
17411
17451
  };
17412
17452
  }
17413
17453
 
@@ -17541,9 +17581,7 @@ function orderByFilter($parse) {
17541
17581
  }
17542
17582
  if (predicate === '') {
17543
17583
  // Effectively no predicate was passed so we compare identity
17544
- return reverseComparator(function(a, b) {
17545
- return compare(a, b);
17546
- }, descending);
17584
+ return reverseComparator(compare, descending);
17547
17585
  }
17548
17586
  get = $parse(predicate);
17549
17587
  if (get.constant) {
@@ -17571,29 +17609,37 @@ function orderByFilter($parse) {
17571
17609
  ? function(a, b) {return comp(b,a);}
17572
17610
  : comp;
17573
17611
  }
17612
+
17613
+ function isPrimitive(value) {
17614
+ switch (typeof value) {
17615
+ case 'number': /* falls through */
17616
+ case 'boolean': /* falls through */
17617
+ case 'string':
17618
+ return true;
17619
+ default:
17620
+ return false;
17621
+ }
17622
+ }
17623
+
17624
+ function objectToString(value) {
17625
+ if (value === null) return 'null';
17626
+ if (typeof value.valueOf === 'function') {
17627
+ value = value.valueOf();
17628
+ if (isPrimitive(value)) return value;
17629
+ }
17630
+ if (typeof value.toString === 'function') {
17631
+ value = value.toString();
17632
+ if (isPrimitive(value)) return value;
17633
+ }
17634
+ return '';
17635
+ }
17636
+
17574
17637
  function compare(v1, v2) {
17575
17638
  var t1 = typeof v1;
17576
17639
  var t2 = typeof v2;
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
17640
  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;
17596
- }
17641
+ v1 = objectToString(v1);
17642
+ v2 = objectToString(v2);
17597
17643
  }
17598
17644
  if (t1 === t2) {
17599
17645
  if (t1 === "string") {
@@ -24327,7 +24373,7 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
24327
24373
  var aliasAs = match[3];
24328
24374
  var trackByExp = match[4];
24329
24375
 
24330
- match = lhs.match(/^(?:([\$\w]+)|\(([\$\w]+)\s*,\s*([\$\w]+)\))$/);
24376
+ match = lhs.match(/^(?:(\s*[\$\w]+)|\(\s*([\$\w]+)\s*,\s*([\$\w]+)\s*\))$/);
24331
24377
 
24332
24378
  if (!match) {
24333
24379
  throw ngRepeatMinErr('iidexp', "'_item_' in '_item_ in _collection_' should be an identifier or '(_key_, _value_)' expression, but got '{0}'.",
@@ -25236,14 +25282,15 @@ var ngOptionsMinErr = minErr('ngOptions');
25236
25282
  *
25237
25283
  * The `ngOptions` attribute can be used to dynamically generate a list of `<option>`
25238
25284
  * elements for the `<select>` element using the array or object obtained by evaluating the
25239
- * `ngOptions` comprehension_expression.
25285
+ * `ngOptions` comprehension expression.
25240
25286
  *
25241
25287
  * In many cases, `ngRepeat` can be used on `<option>` elements instead of `ngOptions` to achieve a
25242
- * similar result. However, the `ngOptions` provides some benefits such as reducing memory and
25288
+ * similar result. However, `ngOptions` provides some benefits such as reducing memory and
25243
25289
  * increasing speed by not creating a new scope for each repeated instance, as well as providing
25244
- * more flexibility in how the `select`'s model is assigned via `select as`. `ngOptions` should be
25245
- * used when the `select` model needs to be bound to a non-string value. This is because an option
25246
- * element can only be bound to string values at present.
25290
+ * more flexibility in how the `<select>`'s model is assigned via the `select` **`as`** part of the
25291
+ * comprehension expression. `ngOptions` should be used when the `<select>` model needs to be bound
25292
+ * to a non-string value. This is because an option element can only be bound to string values at
25293
+ * present.
25247
25294
  *
25248
25295
  * When an item in the `<select>` menu is selected, the array element or object property
25249
25296
  * represented by the selected option will be bound to the model identified by the `ngModel`
@@ -25258,28 +25305,51 @@ var ngOptionsMinErr = minErr('ngOptions');
25258
25305
  * array of objects. See an example [in this jsfiddle](http://jsfiddle.net/qWzTb/).
25259
25306
  * </div>
25260
25307
  *
25261
- * ## `select as`
25308
+ * ## `select` **`as`**
25262
25309
  *
25263
- * Using `select as` will bind the result of the `select as` expression to the model, but
25310
+ * Using `select` **`as`** will bind the result of the `select` expression to the model, but
25264
25311
  * the value of the `<select>` and `<option>` html elements will be either the index (for array data sources)
25265
- * or property name (for object data sources) of the value within the collection. If a `track by` expression
25312
+ * or property name (for object data sources) of the value within the collection. If a **`track by`** expression
25266
25313
  * is used, the result of that expression will be set as the value of the `option` and `select` elements.
25267
25314
  *
25268
- * ### `select as` with `track by`
25269
- *
25270
- * Using `select as` together with `track by` is not recommended. Reasoning:
25271
- *
25272
- * - Example: &lt;select ng-options="item.subItem as item.label for item in values track by item.id" ng-model="selected"&gt;
25273
- * values: [{id: 1, label: 'aLabel', subItem: {name: 'aSubItem'}}, {id: 2, label: 'bLabel', subItem: {name: 'bSubItem'}}],
25274
- * $scope.selected = {name: 'aSubItem'};
25275
- * - track by is always applied to `value`, with the purpose of preserving the selection,
25276
- * (to `item` in this case)
25277
- * - to calculate whether an item is selected we do the following:
25278
- * 1. apply `track by` to the values in the array, e.g.
25279
- * In the example: [1,2]
25280
- * 2. apply `track by` to the already selected value in `ngModel`:
25281
- * In the example: this is not possible, as `track by` refers to `item.id`, but the selected
25282
- * value from `ngModel` is `{name: aSubItem}`.
25315
+ *
25316
+ * ### `select` **`as`** and **`track by`**
25317
+ *
25318
+ * <div class="alert alert-warning">
25319
+ * Do not use `select` **`as`** and **`track by`** in the same expression. They are not designed to work together.
25320
+ * </div>
25321
+ *
25322
+ * Consider the following example:
25323
+ *
25324
+ * ```html
25325
+ * <select ng-options="item.subItem as item.label for item in values track by item.id" ng-model="selected">
25326
+ * ```
25327
+ *
25328
+ * ```js
25329
+ * $scope.values = [{
25330
+ * id: 1,
25331
+ * label: 'aLabel',
25332
+ * subItem: { name: 'aSubItem' }
25333
+ * }, {
25334
+ * id: 2,
25335
+ * label: 'bLabel',
25336
+ * subItem: { name: 'bSubItem' }
25337
+ * }];
25338
+ *
25339
+ * $scope.selected = { name: 'aSubItem' };
25340
+ * ```
25341
+ *
25342
+ * With the purpose of preserving the selection, the **`track by`** expression is always applied to the element
25343
+ * of the data source (to `item` in this example). To calculate whether an element is selected, we do the
25344
+ * following:
25345
+ *
25346
+ * 1. Apply **`track by`** to the elements in the array. In the example: `[1, 2]`
25347
+ * 2. Apply **`track by`** to the already selected value in `ngModel`.
25348
+ * In the example: this is not possible as **`track by`** refers to `item.id`, but the selected
25349
+ * value from `ngModel` is `{name: 'aSubItem'}`, so the **`track by`** expression is applied to
25350
+ * a wrong object, the selected element can't be found, `<select>` is always reset to the "not
25351
+ * selected" option.
25352
+ *
25283
25353
  *
25284
25354
  * @param {string} ngModel Assignable angular expression to data-bind to.
25285
25355
  * @param {string=} name Property name of the form under which the control is published.