angularjs-rails 1.3.6 → 1.3.8

Sign up to get free protection for your applications and to get access to all the features.
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.