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
  */
@@ -839,7 +839,8 @@ angular.module('ngAnimate', ['ng'])
839
839
  * promise that was returned when the animation was started.
840
840
  *
841
841
  * ```js
842
- * var promise = $animate.addClass(element, 'super-long-animation').then(function() {
842
+ * var promise = $animate.addClass(element, 'super-long-animation');
843
+ * promise.then(function() {
843
844
  * //this will still be called even if cancelled
844
845
  * });
845
846
  *
@@ -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
  */
@@ -302,21 +302,28 @@ ngAriaModule.directive('ngShow', ['$aria', function($aria) {
302
302
  }
303
303
  };
304
304
  })
305
- .directive('ngClick',['$aria', function($aria) {
305
+ .directive('ngClick',['$aria', '$parse', function($aria, $parse) {
306
306
  return {
307
307
  restrict: 'A',
308
- link: function(scope, elem, attr) {
309
- if ($aria.config('tabindex') && !elem.attr('tabindex')) {
310
- elem.attr('tabindex', 0);
311
- }
308
+ compile: function(elem, attr) {
309
+ var fn = $parse(attr.ngClick, /* interceptorFn */ null, /* expensiveChecks */ true);
310
+ return function(scope, elem, attr) {
311
+ if ($aria.config('tabindex') && !elem.attr('tabindex')) {
312
+ elem.attr('tabindex', 0);
313
+ }
312
314
 
313
- if ($aria.config('bindKeypress') && !elem.attr('ng-keypress')) {
314
- elem.on('keypress', function(event) {
315
- if (event.keyCode === 32 || event.keyCode === 13) {
316
- scope.$eval(attr.ngClick);
317
- }
318
- });
319
- }
315
+ if ($aria.config('bindKeypress') && !attr.ngKeypress) {
316
+ elem.on('keypress', function(event) {
317
+ if (event.keyCode === 32 || event.keyCode === 13) {
318
+ scope.$apply(callback);
319
+ }
320
+
321
+ function callback() {
322
+ fn(scope, { $event: event });
323
+ }
324
+ });
325
+ }
326
+ };
320
327
  }
321
328
  };
322
329
  }])
@@ -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
  */
@@ -55,7 +55,7 @@ function minErr(module, ErrorConstructor) {
55
55
  return match;
56
56
  });
57
57
 
58
- message = message + '\nhttp://errors.angularjs.org/1.3.36/' +
58
+ message = message + '\nhttp://errors.angularjs.org/1.3.8/' +
59
59
  (module ? module + '/' : '') + code;
60
60
  for (i = 2; i < arguments.length; i++) {
61
61
  message = message + (i == 2 ? '?' : '&') + 'p' + (i - 2) + '=' +
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.3.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
  */
@@ -1283,7 +1283,7 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
1283
1283
  * @param {string|RegExp|function(string)} url HTTP url or function that receives the url
1284
1284
  * and returns true if the url match the current definition.
1285
1285
  * @param {(Object|function(Object))=} headers HTTP headers.
1286
- * @returns {requestHandler} Returns an object with `respond` method that control how a matched
1286
+ * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1287
1287
  * request is handled. You can save this object for later use and invoke `respond` again in
1288
1288
  * order to change how a matched request is handled.
1289
1289
  */
@@ -1297,7 +1297,7 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
1297
1297
  * @param {string|RegExp|function(string)} url HTTP url or function that receives the url
1298
1298
  * and returns true if the url match the current definition.
1299
1299
  * @param {(Object|function(Object))=} headers HTTP headers.
1300
- * @returns {requestHandler} Returns an object with `respond` method that control how a matched
1300
+ * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1301
1301
  * request is handled. You can save this object for later use and invoke `respond` again in
1302
1302
  * order to change how a matched request is handled.
1303
1303
  */
@@ -1311,7 +1311,7 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
1311
1311
  * @param {string|RegExp|function(string)} url HTTP url or function that receives the url
1312
1312
  * and returns true if the url match the current definition.
1313
1313
  * @param {(Object|function(Object))=} headers HTTP headers.
1314
- * @returns {requestHandler} Returns an object with `respond` method that control how a matched
1314
+ * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1315
1315
  * request is handled. You can save this object for later use and invoke `respond` again in
1316
1316
  * order to change how a matched request is handled.
1317
1317
  */
@@ -1327,7 +1327,7 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
1327
1327
  * @param {(string|RegExp|function(string))=} data HTTP request body or function that receives
1328
1328
  * data string and returns true if the data is as expected.
1329
1329
  * @param {(Object|function(Object))=} headers HTTP headers.
1330
- * @returns {requestHandler} Returns an object with `respond` method that control how a matched
1330
+ * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1331
1331
  * request is handled. You can save this object for later use and invoke `respond` again in
1332
1332
  * order to change how a matched request is handled.
1333
1333
  */
@@ -1343,7 +1343,7 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
1343
1343
  * @param {(string|RegExp|function(string))=} data HTTP request body or function that receives
1344
1344
  * data string and returns true if the data is as expected.
1345
1345
  * @param {(Object|function(Object))=} headers HTTP headers.
1346
- * @returns {requestHandler} Returns an object with `respond` method that control how a matched
1346
+ * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1347
1347
  * request is handled. You can save this object for later use and invoke `respond` again in
1348
1348
  * order to change how a matched request is handled.
1349
1349
  */
@@ -1356,7 +1356,7 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
1356
1356
  *
1357
1357
  * @param {string|RegExp|function(string)} url HTTP url or function that receives the url
1358
1358
  * and returns true if the url match the current definition.
1359
- * @returns {requestHandler} Returns an object with `respond` method that control how a matched
1359
+ * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1360
1360
  * request is handled. You can save this object for later use and invoke `respond` again in
1361
1361
  * order to change how a matched request is handled.
1362
1362
  */
@@ -1377,7 +1377,7 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
1377
1377
  * is in JSON format.
1378
1378
  * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header
1379
1379
  * object and returns true if the headers match the current expectation.
1380
- * @returns {requestHandler} Returns an object with `respond` method that control how a matched
1380
+ * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1381
1381
  * request is handled. You can save this object for later use and invoke `respond` again in
1382
1382
  * order to change how a matched request is handled.
1383
1383
  *
@@ -1412,7 +1412,7 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
1412
1412
  * @param {string|RegExp|function(string)} url HTTP url or function that receives the url
1413
1413
  * and returns true if the url match the current definition.
1414
1414
  * @param {Object=} headers HTTP headers.
1415
- * @returns {requestHandler} Returns an object with `respond` method that control how a matched
1415
+ * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1416
1416
  * request is handled. You can save this object for later use and invoke `respond` again in
1417
1417
  * order to change how a matched request is handled. See #expect for more info.
1418
1418
  */
@@ -1426,7 +1426,7 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
1426
1426
  * @param {string|RegExp|function(string)} url HTTP url or function that receives the url
1427
1427
  * and returns true if the url match the current definition.
1428
1428
  * @param {Object=} headers HTTP headers.
1429
- * @returns {requestHandler} Returns an object with `respond` method that control how a matched
1429
+ * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1430
1430
  * request is handled. You can save this object for later use and invoke `respond` again in
1431
1431
  * order to change how a matched request is handled.
1432
1432
  */
@@ -1440,7 +1440,7 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
1440
1440
  * @param {string|RegExp|function(string)} url HTTP url or function that receives the url
1441
1441
  * and returns true if the url match the current definition.
1442
1442
  * @param {Object=} headers HTTP headers.
1443
- * @returns {requestHandler} Returns an object with `respond` method that control how a matched
1443
+ * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1444
1444
  * request is handled. You can save this object for later use and invoke `respond` again in
1445
1445
  * order to change how a matched request is handled.
1446
1446
  */
@@ -1457,7 +1457,7 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
1457
1457
  * receives data string and returns true if the data is as expected, or Object if request body
1458
1458
  * is in JSON format.
1459
1459
  * @param {Object=} headers HTTP headers.
1460
- * @returns {requestHandler} Returns an object with `respond` method that control how a matched
1460
+ * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1461
1461
  * request is handled. You can save this object for later use and invoke `respond` again in
1462
1462
  * order to change how a matched request is handled.
1463
1463
  */
@@ -1474,7 +1474,7 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
1474
1474
  * receives data string and returns true if the data is as expected, or Object if request body
1475
1475
  * is in JSON format.
1476
1476
  * @param {Object=} headers HTTP headers.
1477
- * @returns {requestHandler} Returns an object with `respond` method that control how a matched
1477
+ * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1478
1478
  * request is handled. You can save this object for later use and invoke `respond` again in
1479
1479
  * order to change how a matched request is handled.
1480
1480
  */
@@ -1491,7 +1491,7 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
1491
1491
  * receives data string and returns true if the data is as expected, or Object if request body
1492
1492
  * is in JSON format.
1493
1493
  * @param {Object=} headers HTTP headers.
1494
- * @returns {requestHandler} Returns an object with `respond` method that control how a matched
1494
+ * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1495
1495
  * request is handled. You can save this object for later use and invoke `respond` again in
1496
1496
  * order to change how a matched request is handled.
1497
1497
  */
@@ -1504,7 +1504,7 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
1504
1504
  *
1505
1505
  * @param {string|RegExp|function(string)} url HTTP url or function that receives the url
1506
1506
  * and returns true if the url match the current definition.
1507
- * @returns {requestHandler} Returns an object with `respond` method that control how a matched
1507
+ * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1508
1508
  * request is handled. You can save this object for later use and invoke `respond` again in
1509
1509
  * order to change how a matched request is handled.
1510
1510
  */
@@ -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
  */
@@ -116,7 +116,7 @@ function shallowClearAndCopy(src, dst) {
116
116
  * example, if the `defaultParam` object is `{someParam: '@someProp'}` then the value of `someParam`
117
117
  * will be `data.someProp`.
118
118
  *
119
- * @param {Object.<Object>=} actions Hash with declaration of custom action that should extend
119
+ * @param {Object.<Object>=} actions Hash with declaration of custom actions that should extend
120
120
  * the default set of resource actions. The declaration should be created in the format of {@link
121
121
  * ng.$http#usage $http.config}:
122
122
  *
@@ -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
  */
@@ -9190,7 +9190,7 @@ return jQuery;
9190
9190
  }));
9191
9191
 
9192
9192
  /**
9193
- * @license AngularJS v1.3.36
9193
+ * @license AngularJS v1.3.8
9194
9194
  * (c) 2010-2014 Google, Inc. http://angularjs.org
9195
9195
  * License: MIT
9196
9196
  */
@@ -9246,7 +9246,7 @@ function minErr(module, ErrorConstructor) {
9246
9246
  return match;
9247
9247
  });
9248
9248
 
9249
- message = message + '\nhttp://errors.angularjs.org/1.3.36/' +
9249
+ message = message + '\nhttp://errors.angularjs.org/1.3.8/' +
9250
9250
  (module ? module + '/' : '') + code;
9251
9251
  for (i = 2; i < arguments.length; i++) {
9252
9252
  message = message + (i == 2 ? '?' : '&') + 'p' + (i - 2) + '=' +
@@ -9301,6 +9301,7 @@ function minErr(module, ErrorConstructor) {
9301
9301
  isWindow: true,
9302
9302
  isScope: true,
9303
9303
  isFile: true,
9304
+ isFormData: true,
9304
9305
  isBlob: true,
9305
9306
  isBoolean: true,
9306
9307
  isPromiseLike: true,
@@ -9656,6 +9657,8 @@ noop.$inject = [];
9656
9657
  return (transformationFn || angular.identity)(value);
9657
9658
  };
9658
9659
  ```
9660
+ * @param {*} value to be returned.
9661
+ * @returns {*} the value passed in.
9659
9662
  */
9660
9663
  function identity($) {return $;}
9661
9664
  identity.$inject = [];
@@ -9822,6 +9825,11 @@ function isFile(obj) {
9822
9825
  }
9823
9826
 
9824
9827
 
9828
+ function isFormData(obj) {
9829
+ return toString.call(obj) === '[object FormData]';
9830
+ }
9831
+
9832
+
9825
9833
  function isBlob(obj) {
9826
9834
  return toString.call(obj) === '[object Blob]';
9827
9835
  }
@@ -9905,7 +9913,7 @@ function arrayRemove(array, value) {
9905
9913
  * Creates a deep copy of `source`, which should be an object or an array.
9906
9914
  *
9907
9915
  * * If no destination is supplied, a copy of the object or array is created.
9908
- * * If a destination is provided, all of its elements (for array) or properties (for objects)
9916
+ * * If a destination is provided, all of its elements (for arrays) or properties (for objects)
9909
9917
  * are deleted and then all elements/properties from the source are copied to it.
9910
9918
  * * If `source` is not an object or array (inc. `null` and `undefined`), `source` is returned.
9911
9919
  * * If `source` is identical to 'destination' an exception will be thrown.
@@ -10243,7 +10251,7 @@ function toJson(obj, pretty) {
10243
10251
  * Deserializes a JSON string.
10244
10252
  *
10245
10253
  * @param {string} json JSON string to deserialize.
10246
- * @returns {Object|Array|string|number} Deserialized thingy.
10254
+ * @returns {Object|Array|string|number} Deserialized JSON string.
10247
10255
  */
10248
10256
  function fromJson(json) {
10249
10257
  return isString(json)
@@ -10416,7 +10424,7 @@ function getNgAttribute(element, ngAttr) {
10416
10424
  * {@link angular.bootstrap} instead. AngularJS applications cannot be nested within each other.
10417
10425
  *
10418
10426
  * You can specify an **AngularJS module** to be used as the root module for the application. This
10419
- * module will be loaded into the {@link auto.$injector} when the application is bootstrapped and
10427
+ * module will be loaded into the {@link auto.$injector} when the application is bootstrapped. It
10420
10428
  * should contain the application code needed or have dependencies on other modules that will
10421
10429
  * contain the code. See {@link angular.module} for more information.
10422
10430
  *
@@ -10424,7 +10432,7 @@ function getNgAttribute(element, ngAttr) {
10424
10432
  * document would not be compiled, the `AppController` would not be instantiated and the `{{ a+b }}`
10425
10433
  * would not be resolved to `3`.
10426
10434
  *
10427
- * `ngApp` is the easiest, and most common, way to bootstrap an application.
10435
+ * `ngApp` is the easiest, and most common way to bootstrap an application.
10428
10436
  *
10429
10437
  <example module="ngAppDemo">
10430
10438
  <file name="index.html">
@@ -10684,7 +10692,12 @@ function reloadWithDebugInfo() {
10684
10692
  * @param {DOMElement} element DOM element which is the root of angular application.
10685
10693
  */
10686
10694
  function getTestability(rootElement) {
10687
- return angular.element(rootElement).injector().get('$$testability');
10695
+ var injector = angular.element(rootElement).injector();
10696
+ if (!injector) {
10697
+ throw ngMinErr('test',
10698
+ 'no injector found for element argument to getTestability');
10699
+ }
10700
+ return injector.get('$$testability');
10688
10701
  }
10689
10702
 
10690
10703
  var SNAKE_CASE_REGEXP = /[A-Z]/g;
@@ -11297,11 +11310,11 @@ function toDebugString(obj) {
11297
11310
  * - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat".
11298
11311
  */
11299
11312
  var version = {
11300
- full: '1.3.36', // all of these placeholder strings will be replaced by grunt's
11313
+ full: '1.3.8', // all of these placeholder strings will be replaced by grunt's
11301
11314
  major: 1, // package task
11302
11315
  minor: 3,
11303
- dot: 36,
11304
- codeName: 'robofunky-danceblaster'
11316
+ dot: 8,
11317
+ codeName: 'prophetic-narwhal'
11305
11318
  };
11306
11319
 
11307
11320
 
@@ -16314,7 +16327,10 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
16314
16327
  // support ngAttr attribute binding
16315
16328
  ngAttrName = directiveNormalize(name);
16316
16329
  if (isNgAttr = NG_ATTR_BINDING.test(ngAttrName)) {
16317
- name = snake_case(ngAttrName.substr(6), '-');
16330
+ name = name.replace(PREFIX_REGEXP, '')
16331
+ .substr(8).replace(/_(.)/g, function(match, letter) {
16332
+ return letter.toUpperCase();
16333
+ });
16318
16334
  }
16319
16335
 
16320
16336
  var directiveNName = ngAttrName.replace(/(Start|End)$/, '');
@@ -17226,7 +17242,10 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
17226
17242
 
17227
17243
 
17228
17244
  function addAttrInterpolateDirective(node, directives, value, name, allOrNothing) {
17229
- var interpolateFn = $interpolate(value, true);
17245
+ var trustedContext = getTrustedContext(node, name);
17246
+ allOrNothing = ALL_OR_NOTHING_ATTRS[name] || allOrNothing;
17247
+
17248
+ var interpolateFn = $interpolate(value, true, trustedContext, allOrNothing);
17230
17249
 
17231
17250
  // no interpolation found -> ignore
17232
17251
  if (!interpolateFn) return;
@@ -17251,16 +17270,16 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
17251
17270
  "ng- versions (such as ng-click instead of onclick) instead.");
17252
17271
  }
17253
17272
 
17254
- // If the attribute was removed, then we are done
17255
- if (!attr[name]) {
17256
- return;
17273
+ // If the attribute has changed since last $interpolate()ed
17274
+ var newValue = attr[name];
17275
+ if (newValue !== value) {
17276
+ // we need to interpolate again since the attribute value has been updated
17277
+ // (e.g. by another directive's compile function)
17278
+ // ensure unset/empty values make interpolateFn falsy
17279
+ interpolateFn = newValue && $interpolate(newValue, true, trustedContext, allOrNothing);
17280
+ value = newValue;
17257
17281
  }
17258
17282
 
17259
- // we need to interpolate again, in case the attribute value has been updated
17260
- // (e.g. by another directive's compile function)
17261
- interpolateFn = $interpolate(attr[name], true, getTrustedContext(node, name),
17262
- ALL_OR_NOTHING_ATTRS[name] || allOrNothing);
17263
-
17264
17283
  // if attribute was updated so that there is no interpolation going on we don't want to
17265
17284
  // register any observers
17266
17285
  if (!interpolateFn) return;
@@ -17721,23 +17740,34 @@ function $ExceptionHandlerProvider() {
17721
17740
 
17722
17741
  var APPLICATION_JSON = 'application/json';
17723
17742
  var CONTENT_TYPE_APPLICATION_JSON = {'Content-Type': APPLICATION_JSON + ';charset=utf-8'};
17724
- var JSON_START = /^\s*(\[|\{[^\{])/;
17725
- var JSON_END = /[\}\]]\s*$/;
17743
+ var JSON_START = /^\[|^\{(?!\{)/;
17744
+ var JSON_ENDS = {
17745
+ '[': /]$/,
17746
+ '{': /}$/
17747
+ };
17726
17748
  var JSON_PROTECTION_PREFIX = /^\)\]\}',?\n/;
17727
17749
 
17728
17750
  function defaultHttpResponseTransform(data, headers) {
17729
17751
  if (isString(data)) {
17730
- // strip json vulnerability protection prefix
17731
- data = data.replace(JSON_PROTECTION_PREFIX, '');
17732
- var contentType = headers('Content-Type');
17733
- if ((contentType && contentType.indexOf(APPLICATION_JSON) === 0 && data.trim()) ||
17734
- (JSON_START.test(data) && JSON_END.test(data))) {
17735
- data = fromJson(data);
17752
+ // Strip json vulnerability protection prefix and trim whitespace
17753
+ var tempData = data.replace(JSON_PROTECTION_PREFIX, '').trim();
17754
+
17755
+ if (tempData) {
17756
+ var contentType = headers('Content-Type');
17757
+ if ((contentType && (contentType.indexOf(APPLICATION_JSON) === 0)) || isJsonLike(tempData)) {
17758
+ data = fromJson(tempData);
17759
+ }
17736
17760
  }
17737
17761
  }
17762
+
17738
17763
  return data;
17739
17764
  }
17740
17765
 
17766
+ function isJsonLike(str) {
17767
+ var jsonStart = str.match(JSON_START);
17768
+ return jsonStart && JSON_ENDS[jsonStart[0]].test(str);
17769
+ }
17770
+
17741
17771
  /**
17742
17772
  * Parse headers into key value object
17743
17773
  *
@@ -17800,16 +17830,17 @@ function headersGetter(headers) {
17800
17830
  * This function is used for both request and response transforming
17801
17831
  *
17802
17832
  * @param {*} data Data to transform.
17803
- * @param {function(string=)} headers Http headers getter fn.
17833
+ * @param {function(string=)} headers HTTP headers getter fn.
17834
+ * @param {number} status HTTP status code of the response.
17804
17835
  * @param {(Function|Array.<Function>)} fns Function or an array of functions.
17805
17836
  * @returns {*} Transformed data.
17806
17837
  */
17807
- function transformData(data, headers, fns) {
17838
+ function transformData(data, headers, status, fns) {
17808
17839
  if (isFunction(fns))
17809
- return fns(data, headers);
17840
+ return fns(data, headers, status);
17810
17841
 
17811
17842
  forEach(fns, function(fn) {
17812
- data = fn(data, headers);
17843
+ data = fn(data, headers, status);
17813
17844
  });
17814
17845
 
17815
17846
  return data;
@@ -17861,7 +17892,7 @@ function $HttpProvider() {
17861
17892
 
17862
17893
  // transform outgoing request data
17863
17894
  transformRequest: [function(d) {
17864
- return isObject(d) && !isFile(d) && !isBlob(d) ? toJson(d) : d;
17895
+ return isObject(d) && !isFile(d) && !isBlob(d) && !isFormData(d) ? toJson(d) : d;
17865
17896
  }],
17866
17897
 
17867
17898
  // default headers
@@ -18088,7 +18119,7 @@ function $HttpProvider() {
18088
18119
  *
18089
18120
  * Both requests and responses can be transformed using transformation functions: `transformRequest`
18090
18121
  * and `transformResponse`. These properties can be a single function that returns
18091
- * the transformed value (`{function(data, headersGetter)`) or an array of such transformation functions,
18122
+ * the transformed value (`{function(data, headersGetter, status)`) or an array of such transformation functions,
18092
18123
  * which allows you to `push` or `unshift` a new transformation function into the transformation chain.
18093
18124
  *
18094
18125
  * ### Default Transformations
@@ -18332,9 +18363,9 @@ function $HttpProvider() {
18332
18363
  * See {@link ng.$http#overriding-the-default-transformations-per-request
18333
18364
  * Overriding the Default Transformations}
18334
18365
  * - **transformResponse** –
18335
- * `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –
18366
+ * `{function(data, headersGetter, status)|Array.<function(data, headersGetter, status)>}` –
18336
18367
  * transform function or an array of such functions. The transform function takes the http
18337
- * response body and headers and returns its transformed (typically deserialized) version.
18368
+ * response body, headers and status and returns its transformed (typically deserialized) version.
18338
18369
  * See {@link ng.$http#overriding-the-default-transformations-per-request
18339
18370
  * Overriding the Default Transformations}
18340
18371
  * - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the
@@ -18457,24 +18488,23 @@ function $HttpProvider() {
18457
18488
  </example>
18458
18489
  */
18459
18490
  function $http(requestConfig) {
18460
- var config = {
18461
- method: 'get',
18462
- transformRequest: defaults.transformRequest,
18463
- transformResponse: defaults.transformResponse
18464
- };
18465
- var headers = mergeHeaders(requestConfig);
18466
18491
 
18467
18492
  if (!angular.isObject(requestConfig)) {
18468
18493
  throw minErr('$http')('badreq', 'Http request configuration must be an object. Received: {0}', requestConfig);
18469
18494
  }
18470
18495
 
18471
- extend(config, requestConfig);
18472
- config.headers = headers;
18496
+ var config = extend({
18497
+ method: 'get',
18498
+ transformRequest: defaults.transformRequest,
18499
+ transformResponse: defaults.transformResponse
18500
+ }, requestConfig);
18501
+
18502
+ config.headers = mergeHeaders(requestConfig);
18473
18503
  config.method = uppercase(config.method);
18474
18504
 
18475
18505
  var serverRequest = function(config) {
18476
- headers = config.headers;
18477
- var reqData = transformData(config.data, headersGetter(headers), config.transformRequest);
18506
+ var headers = config.headers;
18507
+ var reqData = transformData(config.data, headersGetter(headers), undefined, config.transformRequest);
18478
18508
 
18479
18509
  // strip content-type if data is undefined
18480
18510
  if (isUndefined(reqData)) {
@@ -18490,7 +18520,7 @@ function $HttpProvider() {
18490
18520
  }
18491
18521
 
18492
18522
  // send request
18493
- return sendReq(config, reqData, headers).then(transformResponse, transformResponse);
18523
+ return sendReq(config, reqData).then(transformResponse, transformResponse);
18494
18524
  };
18495
18525
 
18496
18526
  var chain = [serverRequest, undefined];
@@ -18535,13 +18565,30 @@ function $HttpProvider() {
18535
18565
  if (!response.data) {
18536
18566
  resp.data = response.data;
18537
18567
  } else {
18538
- resp.data = transformData(response.data, response.headers, config.transformResponse);
18568
+ resp.data = transformData(response.data, response.headers, response.status, config.transformResponse);
18539
18569
  }
18540
18570
  return (isSuccess(response.status))
18541
18571
  ? resp
18542
18572
  : $q.reject(resp);
18543
18573
  }
18544
18574
 
18575
+ function executeHeaderFns(headers) {
18576
+ var headerContent, processedHeaders = {};
18577
+
18578
+ forEach(headers, function(headerFn, header) {
18579
+ if (isFunction(headerFn)) {
18580
+ headerContent = headerFn();
18581
+ if (headerContent != null) {
18582
+ processedHeaders[header] = headerContent;
18583
+ }
18584
+ } else {
18585
+ processedHeaders[header] = headerFn;
18586
+ }
18587
+ });
18588
+
18589
+ return processedHeaders;
18590
+ }
18591
+
18545
18592
  function mergeHeaders(config) {
18546
18593
  var defHeaders = defaults.headers,
18547
18594
  reqHeaders = extend({}, config.headers),
@@ -18564,23 +18611,7 @@ function $HttpProvider() {
18564
18611
  }
18565
18612
 
18566
18613
  // execute if header value is a function for merged headers
18567
- execHeaders(reqHeaders);
18568
- return reqHeaders;
18569
-
18570
- function execHeaders(headers) {
18571
- var headerContent;
18572
-
18573
- forEach(headers, function(headerFn, header) {
18574
- if (isFunction(headerFn)) {
18575
- headerContent = headerFn();
18576
- if (headerContent != null) {
18577
- headers[header] = headerContent;
18578
- } else {
18579
- delete headers[header];
18580
- }
18581
- }
18582
- });
18583
- }
18614
+ return executeHeaderFns(reqHeaders);
18584
18615
  }
18585
18616
  }
18586
18617
 
@@ -18723,11 +18754,12 @@ function $HttpProvider() {
18723
18754
  * !!! ACCESSES CLOSURE VARS:
18724
18755
  * $httpBackend, defaults, $log, $rootScope, defaultCache, $http.pendingRequests
18725
18756
  */
18726
- function sendReq(config, reqData, reqHeaders) {
18757
+ function sendReq(config, reqData) {
18727
18758
  var deferred = $q.defer(),
18728
18759
  promise = deferred.promise,
18729
18760
  cache,
18730
18761
  cachedResp,
18762
+ reqHeaders = config.headers,
18731
18763
  url = buildUrl(config.url, config.params);
18732
18764
 
18733
18765
  $http.pendingRequests.push(config);
@@ -20427,8 +20459,8 @@ function $LocationProvider() {
20427
20459
  * @param {string=} oldState History state object that was before it was changed.
20428
20460
  */
20429
20461
 
20430
- this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',
20431
- function($rootScope, $browser, $sniffer, $rootElement) {
20462
+ this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement', '$window',
20463
+ function($rootScope, $browser, $sniffer, $rootElement, $window) {
20432
20464
  var $location,
20433
20465
  LocationMode,
20434
20466
  baseHref = $browser.baseHref(), // if base[href] is undefined, it defaults to ''
@@ -20510,7 +20542,7 @@ function $LocationProvider() {
20510
20542
  if ($location.absUrl() != $browser.url()) {
20511
20543
  $rootScope.$apply();
20512
20544
  // hack to work around FF6 bug 684208 when scenario runner clicks on links
20513
- window.angular['ff-684208-preventDefault'] = true;
20545
+ $window.angular['ff-684208-preventDefault'] = true;
20514
20546
  }
20515
20547
  }
20516
20548
  }
@@ -21126,6 +21158,8 @@ Parser.prototype = {
21126
21158
  primary = this.arrayDeclaration();
21127
21159
  } else if (this.expect('{')) {
21128
21160
  primary = this.object();
21161
+ } else if (this.peek().identifier && this.peek().text in CONSTANTS) {
21162
+ primary = CONSTANTS[this.consume().text];
21129
21163
  } else if (this.peek().identifier) {
21130
21164
  primary = this.identifier();
21131
21165
  } else if (this.peek().constant) {
@@ -21228,7 +21262,7 @@ Parser.prototype = {
21228
21262
  id += this.consume().text + this.consume().text;
21229
21263
  }
21230
21264
 
21231
- return CONSTANTS[id] || getterFn(id, this.options, this.text);
21265
+ return getterFn(id, this.options, this.text);
21232
21266
  },
21233
21267
 
21234
21268
  constant: function() {
@@ -21418,17 +21452,16 @@ Parser.prototype = {
21418
21452
  },
21419
21453
 
21420
21454
  fieldAccess: function(object) {
21421
- var expression = this.text;
21422
- var field = this.consume().text;
21423
- var getter = getterFn(field, this.options, expression);
21455
+ var getter = this.identifier();
21424
21456
 
21425
21457
  return extend(function $parseFieldAccess(scope, locals, self) {
21426
- return getter(self || object(scope, locals));
21458
+ var o = self || object(scope, locals);
21459
+ return (o == null) ? undefined : getter(o);
21427
21460
  }, {
21428
21461
  assign: function(scope, value, locals) {
21429
21462
  var o = object(scope, locals);
21430
21463
  if (!o) object.assign(scope, o = {});
21431
- return setter(o, field, value, expression);
21464
+ return getter.assign(o, value);
21432
21465
  }
21433
21466
  });
21434
21467
  },
@@ -22586,12 +22619,10 @@ function qFactory(nextTick, exceptionHandler) {
22586
22619
  function $$RAFProvider() { //rAF
22587
22620
  this.$get = ['$window', '$timeout', function($window, $timeout) {
22588
22621
  var requestAnimationFrame = $window.requestAnimationFrame ||
22589
- $window.webkitRequestAnimationFrame ||
22590
- $window.mozRequestAnimationFrame;
22622
+ $window.webkitRequestAnimationFrame;
22591
22623
 
22592
22624
  var cancelAnimationFrame = $window.cancelAnimationFrame ||
22593
22625
  $window.webkitCancelAnimationFrame ||
22594
- $window.mozCancelAnimationFrame ||
22595
22626
  $window.webkitCancelRequestAnimationFrame;
22596
22627
 
22597
22628
  var rafSupported = !!requestAnimationFrame;
@@ -22720,7 +22751,6 @@ function $RootScopeProvider() {
22720
22751
  var child = parent.$new();
22721
22752
 
22722
22753
  parent.salutation = "Hello";
22723
- child.name = "World";
22724
22754
  expect(child.salutation).toEqual('Hello');
22725
22755
 
22726
22756
  child.salutation = "Welcome";
@@ -23358,7 +23388,7 @@ function $RootScopeProvider() {
23358
23388
  while (asyncQueue.length) {
23359
23389
  try {
23360
23390
  asyncTask = asyncQueue.shift();
23361
- asyncTask.scope.$eval(asyncTask.expression);
23391
+ asyncTask.scope.$eval(asyncTask.expression, asyncTask.locals);
23362
23392
  } catch (e) {
23363
23393
  $exceptionHandler(e);
23364
23394
  }
@@ -23573,8 +23603,9 @@ function $RootScopeProvider() {
23573
23603
  * - `string`: execute using the rules as defined in {@link guide/expression expression}.
23574
23604
  * - `function(scope)`: execute the function with the current `scope` parameter.
23575
23605
  *
23606
+ * @param {(object)=} locals Local variables object, useful for overriding values in scope.
23576
23607
  */
23577
- $evalAsync: function(expr) {
23608
+ $evalAsync: function(expr, locals) {
23578
23609
  // if we are outside of an $digest loop and this is the first time we are scheduling async
23579
23610
  // task also schedule async auto-flush
23580
23611
  if (!$rootScope.$$phase && !asyncQueue.length) {
@@ -23585,7 +23616,7 @@ function $RootScopeProvider() {
23585
23616
  });
23586
23617
  }
23587
23618
 
23588
- asyncQueue.push({scope: this, expression: expr});
23619
+ asyncQueue.push({scope: this, expression: expr, locals: locals});
23589
23620
  },
23590
23621
 
23591
23622
  $$postDigest: function(fn) {
@@ -25157,7 +25188,7 @@ var $compileMinErr = minErr('$compile');
25157
25188
  * @description
25158
25189
  * The `$templateRequest` service downloads the provided template using `$http` and, upon success,
25159
25190
  * stores the contents inside of `$templateCache`. If the HTTP request fails or the response data
25160
- * of the HTTP request is empty then a `$compile` error will be thrown (the exception can be thwarted
25191
+ * of the HTTP request is empty, a `$compile` error will be thrown (the exception can be thwarted
25161
25192
  * by setting the 2nd parameter of the function to true).
25162
25193
  *
25163
25194
  * @param {string} tpl The HTTP request template URL
@@ -25717,19 +25748,26 @@ function $FilterProvider($provide) {
25717
25748
  *
25718
25749
  * Can be one of:
25719
25750
  *
25720
- * - `string`: The string is evaluated as an expression and the resulting value is used for substring match against
25721
- * the contents of the `array`. All strings or objects with string properties in `array` that contain this string
25722
- * will be returned. The predicate can be negated by prefixing the string with `!`.
25751
+ * - `string`: The string is used for matching against the contents of the `array`. All strings or
25752
+ * objects with string properties in `array` that match this string will be returned. This also
25753
+ * applies to nested object properties.
25754
+ * The predicate can be negated by prefixing the string with `!`.
25723
25755
  *
25724
25756
  * - `Object`: A pattern object can be used to filter specific properties on objects contained
25725
25757
  * by `array`. For example `{name:"M", phone:"1"}` predicate will return an array of items
25726
25758
  * which have property `name` containing "M" and property `phone` containing "1". A special
25727
25759
  * property name `$` can be used (as in `{$:"text"}`) to accept a match against any
25728
- * property of the object. That's equivalent to the simple substring match with a `string`
25729
- * as described above. The predicate can be negated by prefixing the string with `!`.
25730
- * For Example `{name: "!M"}` predicate will return an array of items which have property `name`
25760
+ * property of the object or its nested object properties. That's equivalent to the simple
25761
+ * substring match with a `string` as described above. The predicate can be negated by prefixing
25762
+ * the string with `!`.
25763
+ * For example `{name: "!M"}` predicate will return an array of items which have property `name`
25731
25764
  * not containing "M".
25732
25765
  *
25766
+ * Note that a named property will match properties on the same level only, while the special
25767
+ * `$` property will match properties on the same level or deeper. E.g. an array item like
25768
+ * `{name: {first: 'John', last: 'Doe'}}` will **not** be matched by `{name: 'John'}`, but
25769
+ * **will** be matched by `{$: 'John'}`.
25770
+ *
25733
25771
  * - `function(value, index)`: A predicate function can be used to write arbitrary filters. The
25734
25772
  * function is called for each element of `array`. The final result is an array of those
25735
25773
  * elements that the predicate returned true for.
@@ -25742,10 +25780,10 @@ function $FilterProvider($provide) {
25742
25780
  *
25743
25781
  * - `function(actual, expected)`:
25744
25782
  * The function will be given the object value and the predicate value to compare and
25745
- * should return true if the item should be included in filtered result.
25783
+ * should return true if both values should be considered equal.
25746
25784
  *
25747
- * - `true`: A shorthand for `function(actual, expected) { return angular.equals(expected, actual)}`.
25748
- * this is essentially strict comparison of expected and actual.
25785
+ * - `true`: A shorthand for `function(actual, expected) { return angular.equals(actual, expected)}`.
25786
+ * This is essentially strict comparison of expected and actual.
25749
25787
  *
25750
25788
  * - `false|undefined`: A short hand for a function which will look for a substring match in case
25751
25789
  * insensitive way.
@@ -25848,6 +25886,7 @@ function filterFilter() {
25848
25886
 
25849
25887
  // Helper functions for `filterFilter`
25850
25888
  function createPredicateFn(expression, comparator, matchAgainstAnyProp) {
25889
+ var shouldMatchPrimitives = isObject(expression) && ('$' in expression);
25851
25890
  var predicateFn;
25852
25891
 
25853
25892
  if (comparator === true) {
@@ -25866,13 +25905,16 @@ function createPredicateFn(expression, comparator, matchAgainstAnyProp) {
25866
25905
  }
25867
25906
 
25868
25907
  predicateFn = function(item) {
25908
+ if (shouldMatchPrimitives && !isObject(item)) {
25909
+ return deepCompare(item, expression.$, comparator, false);
25910
+ }
25869
25911
  return deepCompare(item, expression, comparator, matchAgainstAnyProp);
25870
25912
  };
25871
25913
 
25872
25914
  return predicateFn;
25873
25915
  }
25874
25916
 
25875
- function deepCompare(actual, expected, comparator, matchAgainstAnyProp) {
25917
+ function deepCompare(actual, expected, comparator, matchAgainstAnyProp, dontMatchWholeObject) {
25876
25918
  var actualType = typeof actual;
25877
25919
  var expectedType = typeof expected;
25878
25920
 
@@ -25891,11 +25933,11 @@ function deepCompare(actual, expected, comparator, matchAgainstAnyProp) {
25891
25933
  var key;
25892
25934
  if (matchAgainstAnyProp) {
25893
25935
  for (key in actual) {
25894
- if ((key.charAt(0) !== '$') && deepCompare(actual[key], expected, comparator)) {
25936
+ if ((key.charAt(0) !== '$') && deepCompare(actual[key], expected, comparator, true)) {
25895
25937
  return true;
25896
25938
  }
25897
25939
  }
25898
- return false;
25940
+ return dontMatchWholeObject ? false : deepCompare(actual, expected, comparator, false);
25899
25941
  } else if (expectedType === 'object') {
25900
25942
  for (key in expected) {
25901
25943
  var expectedVal = expected[key];
@@ -25903,9 +25945,9 @@ function deepCompare(actual, expected, comparator, matchAgainstAnyProp) {
25903
25945
  continue;
25904
25946
  }
25905
25947
 
25906
- var keyIsDollar = key === '$';
25907
- var actualVal = keyIsDollar ? actual : actual[key];
25908
- if (!deepCompare(actualVal, expectedVal, comparator, keyIsDollar)) {
25948
+ var matchAnyProperty = key === '$';
25949
+ var actualVal = matchAnyProperty ? actual : actual[key];
25950
+ if (!deepCompare(actualVal, expectedVal, comparator, matchAnyProperty, matchAnyProperty)) {
25909
25951
  return false;
25910
25952
  }
25911
25953
  }
@@ -26277,8 +26319,8 @@ var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZEw']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d
26277
26319
  * * `'.sss' or ',sss'`: Millisecond in second, padded (000-999)
26278
26320
  * * `'a'`: AM/PM marker
26279
26321
  * * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-+1200)
26280
- * * `'ww'`: ISO-8601 week of year (00-53)
26281
- * * `'w'`: ISO-8601 week of year (0-53)
26322
+ * * `'ww'`: Week of year, padded (00-53). Week 01 is the week with the first Thursday of the year
26323
+ * * `'w'`: Week of year (0-53). Week 1 is the week with the first Thursday of the year
26282
26324
  *
26283
26325
  * `format` string can also be one of the following predefined
26284
26326
  * {@link guide/i18n localizable formats}:
@@ -26578,8 +26620,7 @@ function limitToFilter() {
26578
26620
  }
26579
26621
  }
26580
26622
 
26581
- var out = [],
26582
- i, n;
26623
+ var i, n;
26583
26624
 
26584
26625
  // if abs(limit) exceeds maximum length, trim it
26585
26626
  if (limit > input.length)
@@ -26591,15 +26632,14 @@ function limitToFilter() {
26591
26632
  i = 0;
26592
26633
  n = limit;
26593
26634
  } else {
26635
+ // zero and NaN check on limit - return empty array
26636
+ if (!limit) return [];
26637
+
26594
26638
  i = input.length + limit;
26595
26639
  n = input.length;
26596
26640
  }
26597
26641
 
26598
- for (; i < n; i++) {
26599
- out.push(input[i]);
26600
- }
26601
-
26602
- return out;
26642
+ return input.slice(i, n);
26603
26643
  };
26604
26644
  }
26605
26645
 
@@ -26733,9 +26773,7 @@ function orderByFilter($parse) {
26733
26773
  }
26734
26774
  if (predicate === '') {
26735
26775
  // Effectively no predicate was passed so we compare identity
26736
- return reverseComparator(function(a, b) {
26737
- return compare(a, b);
26738
- }, descending);
26776
+ return reverseComparator(compare, descending);
26739
26777
  }
26740
26778
  get = $parse(predicate);
26741
26779
  if (get.constant) {
@@ -26763,29 +26801,37 @@ function orderByFilter($parse) {
26763
26801
  ? function(a, b) {return comp(b,a);}
26764
26802
  : comp;
26765
26803
  }
26804
+
26805
+ function isPrimitive(value) {
26806
+ switch (typeof value) {
26807
+ case 'number': /* falls through */
26808
+ case 'boolean': /* falls through */
26809
+ case 'string':
26810
+ return true;
26811
+ default:
26812
+ return false;
26813
+ }
26814
+ }
26815
+
26816
+ function objectToString(value) {
26817
+ if (value === null) return 'null';
26818
+ if (typeof value.valueOf === 'function') {
26819
+ value = value.valueOf();
26820
+ if (isPrimitive(value)) return value;
26821
+ }
26822
+ if (typeof value.toString === 'function') {
26823
+ value = value.toString();
26824
+ if (isPrimitive(value)) return value;
26825
+ }
26826
+ return '';
26827
+ }
26828
+
26766
26829
  function compare(v1, v2) {
26767
26830
  var t1 = typeof v1;
26768
26831
  var t2 = typeof v2;
26769
- // Prepare values for Abstract Relational Comparison
26770
- // (http://www.ecma-international.org/ecma-262/5.1/#sec-11.8.5):
26771
- // If the resulting values are identical, return 0 to prevent
26772
- // incorrect re-ordering.
26773
26832
  if (t1 === t2 && t1 === "object") {
26774
- // If types are both numbers, emulate abstract ToPrimitive() operation
26775
- // in order to get primitive values suitable for comparison
26776
- t1 = typeof (v1.valueOf ? v1 = v1.valueOf() : v1);
26777
- t2 = typeof (v2.valueOf ? v2 = v2.valueOf() : v2);
26778
- if (t1 === t2 && t1 === "object") {
26779
- // Object.prototype.valueOf will return the original object, by
26780
- // default. If we do not receive a primitive value, use ToString()
26781
- // instead.
26782
- t1 = typeof (v1.toString ? v1 = v1.toString() : v1);
26783
- t2 = typeof (v2.toString ? v2 = v2.toString() : v2);
26784
-
26785
- // If the end result of toString() for each item is the same, do not
26786
- // perform relational comparison, and do not re-order objects.
26787
- if (t1 === t2 && v1 === v2 || t1 === "object") return 0;
26788
- }
26833
+ v1 = objectToString(v1);
26834
+ v2 = objectToString(v2);
26789
26835
  }
26790
26836
  if (t1 === t2) {
26791
26837
  if (t1 === "string") {
@@ -33519,7 +33565,7 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
33519
33565
  var aliasAs = match[3];
33520
33566
  var trackByExp = match[4];
33521
33567
 
33522
- match = lhs.match(/^(?:([\$\w]+)|\(([\$\w]+)\s*,\s*([\$\w]+)\))$/);
33568
+ match = lhs.match(/^(?:(\s*[\$\w]+)|\(\s*([\$\w]+)\s*,\s*([\$\w]+)\s*\))$/);
33523
33569
 
33524
33570
  if (!match) {
33525
33571
  throw ngRepeatMinErr('iidexp', "'_item_' in '_item_ in _collection_' should be an identifier or '(_key_, _value_)' expression, but got '{0}'.",
@@ -34428,14 +34474,15 @@ var ngOptionsMinErr = minErr('ngOptions');
34428
34474
  *
34429
34475
  * The `ngOptions` attribute can be used to dynamically generate a list of `<option>`
34430
34476
  * elements for the `<select>` element using the array or object obtained by evaluating the
34431
- * `ngOptions` comprehension_expression.
34477
+ * `ngOptions` comprehension expression.
34432
34478
  *
34433
34479
  * In many cases, `ngRepeat` can be used on `<option>` elements instead of `ngOptions` to achieve a
34434
- * similar result. However, the `ngOptions` provides some benefits such as reducing memory and
34480
+ * similar result. However, `ngOptions` provides some benefits such as reducing memory and
34435
34481
  * increasing speed by not creating a new scope for each repeated instance, as well as providing
34436
- * more flexibility in how the `select`'s model is assigned via `select as`. `ngOptions` should be
34437
- * used when the `select` model needs to be bound to a non-string value. This is because an option
34438
- * element can only be bound to string values at present.
34482
+ * more flexibility in how the `<select>`'s model is assigned via the `select` **`as`** part of the
34483
+ * comprehension expression. `ngOptions` should be used when the `<select>` model needs to be bound
34484
+ * to a non-string value. This is because an option element can only be bound to string values at
34485
+ * present.
34439
34486
  *
34440
34487
  * When an item in the `<select>` menu is selected, the array element or object property
34441
34488
  * represented by the selected option will be bound to the model identified by the `ngModel`
@@ -34450,28 +34497,51 @@ var ngOptionsMinErr = minErr('ngOptions');
34450
34497
  * array of objects. See an example [in this jsfiddle](http://jsfiddle.net/qWzTb/).
34451
34498
  * </div>
34452
34499
  *
34453
- * ## `select as`
34500
+ * ## `select` **`as`**
34454
34501
  *
34455
- * Using `select as` will bind the result of the `select as` expression to the model, but
34502
+ * Using `select` **`as`** will bind the result of the `select` expression to the model, but
34456
34503
  * the value of the `<select>` and `<option>` html elements will be either the index (for array data sources)
34457
- * or property name (for object data sources) of the value within the collection. If a `track by` expression
34504
+ * or property name (for object data sources) of the value within the collection. If a **`track by`** expression
34458
34505
  * is used, the result of that expression will be set as the value of the `option` and `select` elements.
34459
34506
  *
34460
- * ### `select as` with `track by`
34461
- *
34462
- * Using `select as` together with `track by` is not recommended. Reasoning:
34463
- *
34464
- * - Example: &lt;select ng-options="item.subItem as item.label for item in values track by item.id" ng-model="selected"&gt;
34465
- * values: [{id: 1, label: 'aLabel', subItem: {name: 'aSubItem'}}, {id: 2, label: 'bLabel', subItem: {name: 'bSubItem'}}],
34466
- * $scope.selected = {name: 'aSubItem'};
34467
- * - track by is always applied to `value`, with the purpose of preserving the selection,
34468
- * (to `item` in this case)
34469
- * - to calculate whether an item is selected we do the following:
34470
- * 1. apply `track by` to the values in the array, e.g.
34471
- * In the example: [1,2]
34472
- * 2. apply `track by` to the already selected value in `ngModel`:
34473
- * In the example: this is not possible, as `track by` refers to `item.id`, but the selected
34474
- * value from `ngModel` is `{name: aSubItem}`.
34507
+ *
34508
+ * ### `select` **`as`** and **`track by`**
34509
+ *
34510
+ * <div class="alert alert-warning">
34511
+ * Do not use `select` **`as`** and **`track by`** in the same expression. They are not designed to work together.
34512
+ * </div>
34513
+ *
34514
+ * Consider the following example:
34515
+ *
34516
+ * ```html
34517
+ * <select ng-options="item.subItem as item.label for item in values track by item.id" ng-model="selected">
34518
+ * ```
34519
+ *
34520
+ * ```js
34521
+ * $scope.values = [{
34522
+ * id: 1,
34523
+ * label: 'aLabel',
34524
+ * subItem: { name: 'aSubItem' }
34525
+ * }, {
34526
+ * id: 2,
34527
+ * label: 'bLabel',
34528
+ * subItem: { name: 'bSubItem' }
34529
+ * }];
34530
+ *
34531
+ * $scope.selected = { name: 'aSubItem' };
34532
+ * ```
34533
+ *
34534
+ * With the purpose of preserving the selection, the **`track by`** expression is always applied to the element
34535
+ * of the data source (to `item` in this example). To calculate whether an element is selected, we do the
34536
+ * following:
34537
+ *
34538
+ * 1. Apply **`track by`** to the elements in the array. In the example: `[1, 2]`
34539
+ * 2. Apply **`track by`** to the already selected value in `ngModel`.
34540
+ * In the example: this is not possible as **`track by`** refers to `item.id`, but the selected
34541
+ * value from `ngModel` is `{name: 'aSubItem'}`, so the **`track by`** expression is applied to
34542
+ * a wrong object, the selected element can't be found, `<select>` is always reset to the "not
34543
+ * selected" option.
34544
+ *
34475
34545
  *
34476
34546
  * @param {string} ngModel Assignable angular expression to data-bind to.
34477
34547
  * @param {string=} name Property name of the form under which the control is published.