angularjs-rails 1.3.6 → 1.3.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. checksums.yaml +4 -4
  2. data/lib/angularjs-rails/version.rb +2 -2
  3. data/vendor/assets/javascripts/angular-animate.js +3 -2
  4. data/vendor/assets/javascripts/angular-aria.js +20 -13
  5. data/vendor/assets/javascripts/angular-cookies.js +1 -1
  6. data/vendor/assets/javascripts/angular-loader.js +2 -2
  7. data/vendor/assets/javascripts/angular-messages.js +1 -1
  8. data/vendor/assets/javascripts/angular-mocks.js +15 -15
  9. data/vendor/assets/javascripts/angular-resource.js +2 -2
  10. data/vendor/assets/javascripts/angular-route.js +1 -1
  11. data/vendor/assets/javascripts/angular-sanitize.js +1 -1
  12. data/vendor/assets/javascripts/angular-scenario.js +223 -153
  13. data/vendor/assets/javascripts/angular-touch.js +1 -1
  14. data/vendor/assets/javascripts/angular.js +223 -153
  15. data/vendor/assets/javascripts/unstable/angular-animate.js +3 -2
  16. data/vendor/assets/javascripts/unstable/angular-aria.js +20 -13
  17. data/vendor/assets/javascripts/unstable/angular-cookies.js +1 -1
  18. data/vendor/assets/javascripts/unstable/angular-loader.js +2 -2
  19. data/vendor/assets/javascripts/unstable/angular-messages.js +1 -1
  20. data/vendor/assets/javascripts/unstable/angular-mocks.js +15 -15
  21. data/vendor/assets/javascripts/unstable/angular-resource.js +2 -2
  22. data/vendor/assets/javascripts/unstable/angular-route.js +1 -1
  23. data/vendor/assets/javascripts/unstable/angular-sanitize.js +1 -1
  24. data/vendor/assets/javascripts/unstable/angular-scenario.js +223 -153
  25. data/vendor/assets/javascripts/unstable/angular-touch.js +1 -1
  26. data/vendor/assets/javascripts/unstable/angular.js +223 -153
  27. metadata +1 -1
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.3.36
2
+ * @license AngularJS v1.3.8
3
3
  * (c) 2010-2014 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -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.