rails-angularjs 1.3.12 → 1.3.14

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/lib/rails-angularjs/version.rb +2 -2
  4. data/vendor/assets/javascripts/{angularjs/angular-animate.js → angular-animate.js} +1 -1
  5. data/vendor/assets/javascripts/{angularjs/angular-animate.min.js → angular-animate.min.js} +1 -1
  6. data/vendor/assets/javascripts/{angularjs/angular-aria.js → angular-aria.js} +16 -6
  7. data/vendor/assets/javascripts/angular-aria.min.js +12 -0
  8. data/vendor/assets/javascripts/{angularjs/angular-cookies.js → angular-cookies.js} +1 -1
  9. data/vendor/assets/javascripts/{angularjs/angular-cookies.min.js → angular-cookies.min.js} +1 -1
  10. data/vendor/assets/javascripts/{angularjs/angular-loader.js → angular-loader.js} +2 -2
  11. data/vendor/assets/javascripts/{angularjs/angular-loader.min.js → angular-loader.min.js} +2 -2
  12. data/vendor/assets/javascripts/{angularjs/angular-messages.js → angular-messages.js} +1 -1
  13. data/vendor/assets/javascripts/{angularjs/angular-messages.min.js → angular-messages.min.js} +1 -1
  14. data/vendor/assets/javascripts/{angularjs/angular-mocks.js → angular-mocks.js} +2 -2
  15. data/vendor/assets/javascripts/{angularjs/angular-resource.js → angular-resource.js} +2 -1
  16. data/vendor/assets/javascripts/{angularjs/angular-resource.min.js → angular-resource.min.js} +1 -1
  17. data/vendor/assets/javascripts/{angularjs/angular-route.js → angular-route.js} +1 -1
  18. data/vendor/assets/javascripts/{angularjs/angular-route.min.js → angular-route.min.js} +1 -1
  19. data/vendor/assets/javascripts/{angularjs/angular-sanitize.js → angular-sanitize.js} +7 -19
  20. data/vendor/assets/javascripts/angular-sanitize.min.js +16 -0
  21. data/vendor/assets/javascripts/{angularjs/angular-scenario.js → angular-scenario.js} +89 -38
  22. data/vendor/assets/javascripts/{angularjs/angular-touch.js → angular-touch.js} +1 -1
  23. data/vendor/assets/javascripts/{angularjs/angular-touch.min.js → angular-touch.min.js} +1 -1
  24. data/vendor/assets/javascripts/{angularjs/angular.js → angular.js} +89 -38
  25. data/vendor/assets/javascripts/angular.min.js +250 -0
  26. data/vendor/assets/javascripts/{angularjs/unstable → unstable}/angular-animate.js +1 -1
  27. data/vendor/assets/javascripts/{angularjs/unstable → unstable}/angular-animate.min.js +1 -1
  28. data/vendor/assets/javascripts/{angularjs/unstable → unstable}/angular-aria.js +16 -6
  29. data/vendor/assets/javascripts/unstable/angular-aria.min.js +12 -0
  30. data/vendor/assets/javascripts/{angularjs/unstable → unstable}/angular-cookies.js +1 -1
  31. data/vendor/assets/javascripts/{angularjs/unstable → unstable}/angular-cookies.min.js +1 -1
  32. data/vendor/assets/javascripts/{angularjs/unstable → unstable}/angular-loader.js +2 -2
  33. data/vendor/assets/javascripts/{angularjs/unstable → unstable}/angular-loader.min.js +2 -2
  34. data/vendor/assets/javascripts/unstable/angular-messages.js +644 -0
  35. data/vendor/assets/javascripts/unstable/angular-messages.min.js +12 -0
  36. data/vendor/assets/javascripts/{angularjs/unstable → unstable}/angular-mocks.js +2 -2
  37. data/vendor/assets/javascripts/{angularjs/unstable → unstable}/angular-resource.js +3 -2
  38. data/vendor/assets/javascripts/{angularjs/unstable → unstable}/angular-resource.min.js +1 -1
  39. data/vendor/assets/javascripts/{angularjs/unstable → unstable}/angular-route.js +1 -1
  40. data/vendor/assets/javascripts/{angularjs/unstable → unstable}/angular-route.min.js +1 -1
  41. data/vendor/assets/javascripts/{angularjs/unstable → unstable}/angular-sanitize.js +12 -22
  42. data/vendor/assets/javascripts/unstable/angular-sanitize.min.js +16 -0
  43. data/vendor/assets/javascripts/{angularjs/unstable → unstable}/angular-scenario.js +317 -155
  44. data/vendor/assets/javascripts/{angularjs/unstable → unstable}/angular-touch.js +1 -1
  45. data/vendor/assets/javascripts/{angularjs/unstable → unstable}/angular-touch.min.js +1 -1
  46. data/vendor/assets/javascripts/{angularjs/unstable → unstable}/angular.js +317 -155
  47. data/vendor/assets/javascripts/unstable/angular.min.js +282 -0
  48. metadata +46 -46
  49. data/vendor/assets/javascripts/angularjs/angular-aria.min.js +0 -12
  50. data/vendor/assets/javascripts/angularjs/angular-sanitize.min.js +0 -16
  51. data/vendor/assets/javascripts/angularjs/angular.min.js +0 -250
  52. data/vendor/assets/javascripts/angularjs/unstable/angular-aria.min.js +0 -12
  53. data/vendor/assets/javascripts/angularjs/unstable/angular-messages.js +0 -400
  54. data/vendor/assets/javascripts/angularjs/unstable/angular-messages.min.js +0 -10
  55. data/vendor/assets/javascripts/angularjs/unstable/angular-sanitize.min.js +0 -16
  56. data/vendor/assets/javascripts/angularjs/unstable/angular.min.js +0 -281
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.4.0-beta.3
2
+ * @license AngularJS v1.4.0-beta.5
3
3
  * (c) 2010-2015 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -57,7 +57,7 @@ function minErr(module, ErrorConstructor) {
57
57
  return match;
58
58
  });
59
59
 
60
- message += '\nhttp://errors.angularjs.org/1.4.0-beta.3/' +
60
+ message += '\nhttp://errors.angularjs.org/1.4.0-beta.5/' +
61
61
  (module ? module + '/' : '') + code;
62
62
 
63
63
  for (i = SKIP_INDEXES, paramPrefix = '?'; i < templateArgs.length; i++, paramPrefix = '&') {
@@ -127,6 +127,7 @@ function minErr(module, ErrorConstructor) {
127
127
  shallowCopy: true,
128
128
  equals: true,
129
129
  csp: true,
130
+ jq: true,
130
131
  concat: true,
131
132
  sliceArgs: true,
132
133
  bind: true,
@@ -970,7 +971,61 @@ var csp = function() {
970
971
  return (csp.isActive_ = active);
971
972
  };
972
973
 
974
+ /**
975
+ * @ngdoc directive
976
+ * @module ng
977
+ * @name ngJq
978
+ *
979
+ * @element ANY
980
+ * @param {string=} the name of the library available under `window`
981
+ * to be used for angular.element
982
+ * @description
983
+ * Use this directive to force the angular.element library. This should be
984
+ * used to force either jqLite by leaving ng-jq blank or setting the name of
985
+ * the jquery variable under window (eg. jQuery).
986
+ *
987
+ * Since this directive is global for the angular library, it is recommended
988
+ * that it's added to the same element as ng-app or the HTML element, but it is not mandatory.
989
+ * It needs to be noted that only the first instance of `ng-jq` will be used and all others
990
+ * ignored.
991
+ *
992
+ * @example
993
+ * This example shows how to force jqLite using the `ngJq` directive to the `html` tag.
994
+ ```html
995
+ <!doctype html>
996
+ <html ng-app ng-jq>
997
+ ...
998
+ ...
999
+ </html>
1000
+ ```
1001
+ * @example
1002
+ * This example shows how to use a jQuery based library of a different name.
1003
+ * The library name must be available at the top most 'window'.
1004
+ ```html
1005
+ <!doctype html>
1006
+ <html ng-app ng-jq="jQueryLib">
1007
+ ...
1008
+ ...
1009
+ </html>
1010
+ ```
1011
+ */
1012
+ var jq = function() {
1013
+ if (isDefined(jq.name_)) return jq.name_;
1014
+ var el;
1015
+ var i, ii = ngAttrPrefixes.length;
1016
+ for (i = 0; i < ii; ++i) {
1017
+ if (el = document.querySelector('[' + ngAttrPrefixes[i].replace(':', '\\:') + 'jq]')) {
1018
+ break;
1019
+ }
1020
+ }
973
1021
 
1022
+ var name;
1023
+ if (el) {
1024
+ name = getNgAttribute(el, "jq");
1025
+ }
1026
+
1027
+ return (jq.name_ = name);
1028
+ };
974
1029
 
975
1030
  function concat(array1, array2, index) {
976
1031
  return array1.concat(slice.call(array2, index));
@@ -1543,7 +1598,12 @@ function bindJQuery() {
1543
1598
  }
1544
1599
 
1545
1600
  // bind to jQuery if present;
1546
- jQuery = window.jQuery;
1601
+ var jqName = jq();
1602
+ jQuery = window.jQuery; // use default jQuery.
1603
+ if (isDefined(jqName)) { // `ngJq` present
1604
+ jQuery = jqName === null ? undefined : window[jqName]; // if empty; use jqLite. if not empty, use jQuery specified by `ngJq`.
1605
+ }
1606
+
1547
1607
  // Use jQuery if it exists with proper functionality, otherwise default to us.
1548
1608
  // Angular 1.2+ requires jQuery 1.7+ for on()/off() support.
1549
1609
  // Angular 1.3+ technically requires at least jQuery 2.1+ but it may work with older
@@ -2135,11 +2195,11 @@ function toDebugString(obj) {
2135
2195
  * - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat".
2136
2196
  */
2137
2197
  var version = {
2138
- full: '1.4.0-beta.3', // all of these placeholder strings will be replaced by grunt's
2198
+ full: '1.4.0-beta.5', // all of these placeholder strings will be replaced by grunt's
2139
2199
  major: 1, // package task
2140
2200
  minor: 4,
2141
2201
  dot: 0,
2142
- codeName: 'substance-mimicry'
2202
+ codeName: 'karmic-stabilization'
2143
2203
  };
2144
2204
 
2145
2205
 
@@ -7347,7 +7407,6 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
7347
7407
  var terminalPriority = -Number.MAX_VALUE,
7348
7408
  newScopeDirective,
7349
7409
  controllerDirectives = previousCompileContext.controllerDirectives,
7350
- controllers,
7351
7410
  newIsolateScopeDirective = previousCompileContext.newIsolateScopeDirective,
7352
7411
  templateDirective = previousCompileContext.templateDirective,
7353
7412
  nonTlbTranscludeDirective = previousCompileContext.nonTlbTranscludeDirective,
@@ -7405,7 +7464,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
7405
7464
 
7406
7465
  if (!directive.templateUrl && directive.controller) {
7407
7466
  directiveValue = directive.controller;
7408
- controllerDirectives = controllerDirectives || {};
7467
+ controllerDirectives = controllerDirectives || createMap();
7409
7468
  assertNoDuplicate("'" + directiveName + "' controller",
7410
7469
  controllerDirectives[directiveName], directive, $compileNode);
7411
7470
  controllerDirectives[directiveName] = directive;
@@ -7573,51 +7632,74 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
7573
7632
 
7574
7633
 
7575
7634
  function getControllers(directiveName, require, $element, elementControllers) {
7576
- var value, retrievalMethod = 'data', optional = false;
7577
- var $searchElement = $element;
7578
- var match;
7579
- if (isString(require)) {
7580
- match = require.match(REQUIRE_PREFIX_REGEXP);
7581
- require = require.substring(match[0].length);
7635
+ var value;
7582
7636
 
7583
- if (match[3]) {
7584
- if (match[1]) match[3] = null;
7585
- else match[1] = match[3];
7586
- }
7587
- if (match[1] === '^') {
7588
- retrievalMethod = 'inheritedData';
7589
- } else if (match[1] === '^^') {
7590
- retrievalMethod = 'inheritedData';
7591
- $searchElement = $element.parent();
7592
- }
7593
- if (match[2] === '?') {
7594
- optional = true;
7637
+ if (isString(require)) {
7638
+ var match = require.match(REQUIRE_PREFIX_REGEXP);
7639
+ var name = require.substring(match[0].length);
7640
+ var inheritType = match[1] || match[3];
7641
+ var optional = match[2] === '?';
7642
+
7643
+ //If only parents then start at the parent element
7644
+ if (inheritType === '^^') {
7645
+ $element = $element.parent();
7646
+ //Otherwise attempt getting the controller from elementControllers in case
7647
+ //the element is transcluded (and has no data) and to avoid .data if possible
7648
+ } else {
7649
+ value = elementControllers && elementControllers[name];
7650
+ value = value && value.instance;
7595
7651
  }
7596
7652
 
7597
- value = null;
7598
-
7599
- if (elementControllers && retrievalMethod === 'data') {
7600
- if (value = elementControllers[require]) {
7601
- value = value.instance;
7602
- }
7653
+ if (!value) {
7654
+ var dataName = '$' + name + 'Controller';
7655
+ value = inheritType ? $element.inheritedData(dataName) : $element.data(dataName);
7603
7656
  }
7604
- value = value || $searchElement[retrievalMethod]('$' + require + 'Controller');
7605
7657
 
7606
7658
  if (!value && !optional) {
7607
7659
  throw $compileMinErr('ctreq',
7608
7660
  "Controller '{0}', required by directive '{1}', can't be found!",
7609
- require, directiveName);
7661
+ name, directiveName);
7610
7662
  }
7611
- return value || null;
7612
7663
  } else if (isArray(require)) {
7613
7664
  value = [];
7614
- forEach(require, function(require) {
7615
- value.push(getControllers(directiveName, require, $element, elementControllers));
7616
- });
7665
+ for (var i = 0, ii = require.length; i < ii; i++) {
7666
+ value[i] = getControllers(directiveName, require[i], $element, elementControllers);
7667
+ }
7617
7668
  }
7618
- return value;
7669
+
7670
+ return value || null;
7619
7671
  }
7620
7672
 
7673
+ function setupControllers($element, attrs, transcludeFn, controllerDirectives, isolateScope, scope) {
7674
+ var elementControllers = createMap();
7675
+ for (var controllerKey in controllerDirectives) {
7676
+ var directive = controllerDirectives[controllerKey];
7677
+ var locals = {
7678
+ $scope: directive === newIsolateScopeDirective || directive.$$isolateScope ? isolateScope : scope,
7679
+ $element: $element,
7680
+ $attrs: attrs,
7681
+ $transclude: transcludeFn
7682
+ };
7683
+
7684
+ var controller = directive.controller;
7685
+ if (controller == '@') {
7686
+ controller = attrs[directive.name];
7687
+ }
7688
+
7689
+ var controllerInstance = $controller(controller, locals, true, directive.controllerAs);
7690
+
7691
+ // For directives with element transclusion the element is a comment,
7692
+ // but jQuery .data doesn't support attaching data to comment nodes as it's hard to
7693
+ // clean up (http://bugs.jquery.com/ticket/8335).
7694
+ // Instead, we save the controllers for the element in a local hash and attach to .data
7695
+ // later, once we have the actual element.
7696
+ elementControllers[directive.name] = controllerInstance;
7697
+ if (!hasElementTranscludeDirective) {
7698
+ $element.data('$' + directive.name + 'Controller', controllerInstance.instance);
7699
+ }
7700
+ }
7701
+ return elementControllers;
7702
+ }
7621
7703
 
7622
7704
  function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn,
7623
7705
  thisLinkFn) {
@@ -7644,36 +7726,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
7644
7726
  }
7645
7727
 
7646
7728
  if (controllerDirectives) {
7647
- // TODO: merge `controllers` and `elementControllers` into single object.
7648
- controllers = {};
7649
- elementControllers = {};
7650
- forEach(controllerDirectives, function(directive) {
7651
- var locals = {
7652
- $scope: directive === newIsolateScopeDirective || directive.$$isolateScope ? isolateScope : scope,
7653
- $element: $element,
7654
- $attrs: attrs,
7655
- $transclude: transcludeFn
7656
- }, controllerInstance;
7657
-
7658
- controller = directive.controller;
7659
- if (controller == '@') {
7660
- controller = attrs[directive.name];
7661
- }
7662
-
7663
- controllerInstance = $controller(controller, locals, true, directive.controllerAs);
7664
-
7665
- // For directives with element transclusion the element is a comment,
7666
- // but jQuery .data doesn't support attaching data to comment nodes as it's hard to
7667
- // clean up (http://bugs.jquery.com/ticket/8335).
7668
- // Instead, we save the controllers for the element in a local hash and attach to .data
7669
- // later, once we have the actual element.
7670
- elementControllers[directive.name] = controllerInstance;
7671
- if (!hasElementTranscludeDirective) {
7672
- $element.data('$' + directive.name + 'Controller', controllerInstance.instance);
7673
- }
7674
-
7675
- controllers[directive.name] = controllerInstance;
7676
- });
7729
+ elementControllers = setupControllers($element, attrs, transcludeFn, controllerDirectives, isolateScope, scope);
7677
7730
  }
7678
7731
 
7679
7732
  if (newIsolateScopeDirective) {
@@ -7687,14 +7740,14 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
7687
7740
  isolateScope.$$isolateBindings,
7688
7741
  newIsolateScopeDirective, isolateScope);
7689
7742
  }
7690
- if (controllers) {
7743
+ if (elementControllers) {
7691
7744
  // Initialize bindToController bindings for new/isolate scopes
7692
7745
  var scopeDirective = newIsolateScopeDirective || newScopeDirective;
7693
7746
  var bindings;
7694
7747
  var controllerForBindings;
7695
- if (scopeDirective && controllers[scopeDirective.name]) {
7748
+ if (scopeDirective && elementControllers[scopeDirective.name]) {
7696
7749
  bindings = scopeDirective.$$bindings.bindToController;
7697
- controller = controllers[scopeDirective.name];
7750
+ controller = elementControllers[scopeDirective.name];
7698
7751
 
7699
7752
  if (controller && controller.identifier && bindings) {
7700
7753
  controllerForBindings = controller;
@@ -7703,18 +7756,18 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
7703
7756
  bindings, scopeDirective);
7704
7757
  }
7705
7758
  }
7706
- forEach(controllers, function(controller) {
7707
- var result = controller();
7708
- if (result !== controller.instance &&
7759
+ for (i in elementControllers) {
7760
+ controller = elementControllers[i];
7761
+ var controllerResult = controller();
7762
+ if (controllerResult !== controller.instance &&
7709
7763
  controller === controllerForBindings) {
7710
7764
  // Remove and re-install bindToController bindings
7711
7765
  thisLinkFn.$$destroyBindings();
7712
7766
  thisLinkFn.$$destroyBindings =
7713
- initializeDirectiveBindings(scope, attrs, result,
7767
+ initializeDirectiveBindings(scope, attrs, controllerResult,
7714
7768
  bindings, scopeDirective);
7715
7769
  }
7716
- });
7717
- controllers = null;
7770
+ }
7718
7771
  }
7719
7772
 
7720
7773
  // PRELINKING
@@ -8725,19 +8778,24 @@ function isJsonLike(str) {
8725
8778
  * @returns {Object} Parsed headers as key value object
8726
8779
  */
8727
8780
  function parseHeaders(headers) {
8728
- var parsed = createMap(), key, val, i;
8729
-
8730
- if (!headers) return parsed;
8731
-
8732
- forEach(headers.split('\n'), function(line) {
8733
- i = line.indexOf(':');
8734
- key = lowercase(trim(line.substr(0, i)));
8735
- val = trim(line.substr(i + 1));
8781
+ var parsed = createMap(), i;
8736
8782
 
8783
+ function fillInParsed(key, val) {
8737
8784
  if (key) {
8738
8785
  parsed[key] = parsed[key] ? parsed[key] + ', ' + val : val;
8739
8786
  }
8740
- });
8787
+ }
8788
+
8789
+ if (isString(headers)) {
8790
+ forEach(headers.split('\n'), function(line) {
8791
+ i = line.indexOf(':');
8792
+ fillInParsed(lowercase(trim(line.substr(0, i))), trim(line.substr(i + 1)));
8793
+ });
8794
+ } else if (isObject(headers)) {
8795
+ forEach(headers, function(headerVal, headerKey) {
8796
+ fillInParsed(lowercase(headerKey), trim(headerVal));
8797
+ });
8798
+ }
8741
8799
 
8742
8800
  return parsed;
8743
8801
  }
@@ -8756,7 +8814,7 @@ function parseHeaders(headers) {
8756
8814
  * - if called with no arguments returns an object containing all headers.
8757
8815
  */
8758
8816
  function headersGetter(headers) {
8759
- var headersObj = isObject(headers) ? headers : undefined;
8817
+ var headersObj;
8760
8818
 
8761
8819
  return function(name) {
8762
8820
  if (!headersObj) headersObj = parseHeaders(headers);
@@ -11504,7 +11562,7 @@ function $LocationProvider() {
11504
11562
 
11505
11563
 
11506
11564
  // rewrite hashbang url <> html5 url
11507
- if ($location.absUrl() != initialUrl) {
11565
+ if (trimEmptyHash($location.absUrl()) != trimEmptyHash(initialUrl)) {
11508
11566
  $browser.url($location.absUrl(), true);
11509
11567
  }
11510
11568
 
@@ -12746,7 +12804,7 @@ ASTCompiler.prototype = {
12746
12804
  self.if(self.notNull(right), function() {
12747
12805
  self.addEnsureSafeFunction(right);
12748
12806
  forEach(ast.arguments, function(expr) {
12749
- self.recurse(expr, undefined, undefined, function(argument) {
12807
+ self.recurse(expr, self.nextId(), undefined, function(argument) {
12750
12808
  args.push(self.ensureSafeObject(argument));
12751
12809
  });
12752
12810
  });
@@ -12777,14 +12835,14 @@ ASTCompiler.prototype = {
12777
12835
  self.addEnsureSafeObject(self.member(left.context, left.name, left.computed));
12778
12836
  expression = self.member(left.context, left.name, left.computed) + ast.operator + right;
12779
12837
  self.assign(intoId, expression);
12780
- recursionFn(expression);
12838
+ recursionFn(intoId || expression);
12781
12839
  });
12782
12840
  }, 1);
12783
12841
  break;
12784
12842
  case AST.ArrayExpression:
12785
12843
  args = [];
12786
12844
  forEach(ast.elements, function(expr) {
12787
- self.recurse(expr, undefined, undefined, function(argument) {
12845
+ self.recurse(expr, self.nextId(), undefined, function(argument) {
12788
12846
  args.push(argument);
12789
12847
  });
12790
12848
  });
@@ -12795,7 +12853,7 @@ ASTCompiler.prototype = {
12795
12853
  case AST.ObjectExpression:
12796
12854
  args = [];
12797
12855
  forEach(ast.properties, function(property) {
12798
- self.recurse(property.value, undefined, undefined, function(expr) {
12856
+ self.recurse(property.value, self.nextId(), undefined, function(expr) {
12799
12857
  args.push(self.escape(
12800
12858
  property.key.type === AST.Identifier ? property.key.name :
12801
12859
  ('' + property.key.value)) +
@@ -16449,7 +16507,7 @@ function $SceProvider() {
16449
16507
  * escaping.
16450
16508
  *
16451
16509
  * @param {string} type The kind of context in which this value is safe for use. e.g. url,
16452
- * resource_url, html, js and css.
16510
+ * resourceUrl, html, js and css.
16453
16511
  * @param {*} value The value that that should be considered trusted/safe.
16454
16512
  * @returns {*} A value that can be used to stand in for the provided `value` in places
16455
16513
  * where Angular expects a $sce.trustAs() return value.
@@ -16827,7 +16885,7 @@ function $TemplateRequestProvider() {
16827
16885
  };
16828
16886
 
16829
16887
  return $http.get(tpl, httpOptions)
16830
- .finally(function() {
16888
+ ['finally'](function() {
16831
16889
  handleRequestFn.totalPendingRequests--;
16832
16890
  })
16833
16891
  .then(function(response) {
@@ -17982,7 +18040,9 @@ var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZEw']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d
17982
18040
  * specified in the string input, the time is considered to be in the local timezone.
17983
18041
  * @param {string=} format Formatting rules (see Description). If not specified,
17984
18042
  * `mediumDate` is used.
17985
- * @param {string=} timezone Timezone to be used for formatting. Right now, only `'UTC'` is supported.
18043
+ * @param {string=} timezone Timezone to be used for formatting. It understands UTC/GMT and the
18044
+ * continental US time zone abbreviations, but for general use, use a time zone offset, for
18045
+ * example, `'+0430'` (4 hours, 30 minutes east of the Greenwich meridian)
17986
18046
  * If not specified, the timezone of the browser will be used.
17987
18047
  * @returns {string} Formatted string or the input if input is not recognized as date/millis.
17988
18048
  *
@@ -18172,6 +18232,8 @@ var uppercaseFilter = valueFn(uppercase);
18172
18232
  * If the number is negative, `limit` number of items from the end of the source array/string
18173
18233
  * are copied. The `limit` will be trimmed if it exceeds `array.length`. If `limit` is undefined,
18174
18234
  * the input will be returned unchanged.
18235
+ * @param {(string|number)=} begin Index at which to begin limitation. As a negative index, `begin`
18236
+ * indicates an offset from the end of `input`. Defaults to `0`.
18175
18237
  * @returns {Array|string} A new sub-array or substring of length `limit` or less if input array
18176
18238
  * had less than `limit` elements.
18177
18239
  *
@@ -18243,7 +18305,7 @@ var uppercaseFilter = valueFn(uppercase);
18243
18305
  </example>
18244
18306
  */
18245
18307
  function limitToFilter() {
18246
- return function(input, limit) {
18308
+ return function(input, limit, begin) {
18247
18309
  if (Math.abs(Number(limit)) === Infinity) {
18248
18310
  limit = Number(limit);
18249
18311
  } else {
@@ -18254,7 +18316,18 @@ function limitToFilter() {
18254
18316
  if (isNumber(input)) input = input.toString();
18255
18317
  if (!isArray(input) && !isString(input)) return input;
18256
18318
 
18257
- return limit >= 0 ? input.slice(0, limit) : input.slice(limit);
18319
+ begin = (!begin || isNaN(begin)) ? 0 : toInt(begin);
18320
+ begin = (begin < 0 && begin >= -input.length) ? input.length + begin : begin;
18321
+
18322
+ if (limit >= 0) {
18323
+ return input.slice(begin, begin + limit);
18324
+ } else {
18325
+ if (begin === 0) {
18326
+ return input.slice(limit, input.length);
18327
+ } else {
18328
+ return input.slice(Math.max(0, begin + limit), begin);
18329
+ }
18330
+ }
18258
18331
  };
18259
18332
  }
18260
18333
 
@@ -18666,20 +18739,23 @@ var htmlAnchorDirective = valueFn({
18666
18739
  *
18667
18740
  * @description
18668
18741
  *
18669
- * We shouldn't do this, because it will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:
18742
+ * This directive sets the `disabled` attribute on the element if the
18743
+ * {@link guide/expression expression} inside `ngDisabled` evaluates to truthy.
18744
+ *
18745
+ * A special directive is necessary because we cannot use interpolation inside the `disabled`
18746
+ * attribute. The following example would make the button enabled on Chrome/Firefox
18747
+ * but not on older IEs:
18748
+ *
18670
18749
  * ```html
18671
- * <div ng-init="scope = { isDisabled: false }">
18672
- * <button disabled="{{scope.isDisabled}}">Disabled</button>
18750
+ * <div ng-init="isDisabled = false">
18751
+ * <button disabled="{{isDisabled}}">Disabled</button>
18673
18752
  * </div>
18674
18753
  * ```
18675
18754
  *
18676
- * The HTML specification does not require browsers to preserve the values of boolean attributes
18677
- * such as disabled. (Their presence means true and their absence means false.)
18755
+ * This is because the HTML specification does not require browsers to preserve the values of
18756
+ * boolean attributes such as `disabled` (Their presence means true and their absence means false.)
18678
18757
  * If we put an Angular interpolation expression into such an attribute then the
18679
18758
  * binding information would be lost when the browser removes the attribute.
18680
- * The `ngDisabled` directive solves this problem for the `disabled` attribute.
18681
- * This complementary directive is not removed by the browser and so provides
18682
- * a permanent reliable place to store the binding information.
18683
18759
  *
18684
18760
  * @example
18685
18761
  <example>
@@ -18698,7 +18774,7 @@ var htmlAnchorDirective = valueFn({
18698
18774
  *
18699
18775
  * @element INPUT
18700
18776
  * @param {expression} ngDisabled If the {@link guide/expression expression} is truthy,
18701
- * then special attribute "disabled" will be set on the element
18777
+ * then the `disabled` attribute will be set on the element
18702
18778
  */
18703
18779
 
18704
18780
 
@@ -20712,7 +20788,7 @@ function numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {
20712
20788
  return value;
20713
20789
  });
20714
20790
 
20715
- if (attr.min || attr.ngMin) {
20791
+ if (isDefined(attr.min) || attr.ngMin) {
20716
20792
  var minVal;
20717
20793
  ctrl.$validators.min = function(value) {
20718
20794
  return ctrl.$isEmpty(value) || isUndefined(minVal) || value >= minVal;
@@ -20728,7 +20804,7 @@ function numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {
20728
20804
  });
20729
20805
  }
20730
20806
 
20731
- if (attr.max || attr.ngMax) {
20807
+ if (isDefined(attr.max) || attr.ngMax) {
20732
20808
  var maxVal;
20733
20809
  ctrl.$validators.max = function(value) {
20734
20810
  return ctrl.$isEmpty(value) || isUndefined(maxVal) || value <= maxVal;
@@ -23534,6 +23610,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
23534
23610
  ngModelGet = parsedNgModel,
23535
23611
  ngModelSet = parsedNgModelAssign,
23536
23612
  pendingDebounce = null,
23613
+ parserValid,
23537
23614
  ctrl = this;
23538
23615
 
23539
23616
  this.$$setOptions = function(options) {
@@ -23806,16 +23883,12 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
23806
23883
  // the model although neither viewValue nor the model on the scope changed
23807
23884
  var modelValue = ctrl.$$rawModelValue;
23808
23885
 
23809
- // Check if the there's a parse error, so we don't unset it accidentially
23810
- var parserName = ctrl.$$parserName || 'parse';
23811
- var parserValid = ctrl.$error[parserName] ? false : undefined;
23812
-
23813
23886
  var prevValid = ctrl.$valid;
23814
23887
  var prevModelValue = ctrl.$modelValue;
23815
23888
 
23816
23889
  var allowInvalid = ctrl.$options && ctrl.$options.allowInvalid;
23817
23890
 
23818
- ctrl.$$runValidators(parserValid, modelValue, viewValue, function(allValid) {
23891
+ ctrl.$$runValidators(modelValue, viewValue, function(allValid) {
23819
23892
  // If there was no change in validity, don't update the model
23820
23893
  // This prevents changing an invalid modelValue to undefined
23821
23894
  if (!allowInvalid && prevValid !== allValid) {
@@ -23833,12 +23906,12 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
23833
23906
 
23834
23907
  };
23835
23908
 
23836
- this.$$runValidators = function(parseValid, modelValue, viewValue, doneCallback) {
23909
+ this.$$runValidators = function(modelValue, viewValue, doneCallback) {
23837
23910
  currentValidationRunId++;
23838
23911
  var localValidationRunId = currentValidationRunId;
23839
23912
 
23840
23913
  // check parser error
23841
- if (!processParseErrors(parseValid)) {
23914
+ if (!processParseErrors()) {
23842
23915
  validationDone(false);
23843
23916
  return;
23844
23917
  }
@@ -23848,21 +23921,22 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
23848
23921
  }
23849
23922
  processAsyncValidators();
23850
23923
 
23851
- function processParseErrors(parseValid) {
23924
+ function processParseErrors() {
23852
23925
  var errorKey = ctrl.$$parserName || 'parse';
23853
- if (parseValid === undefined) {
23926
+ if (parserValid === undefined) {
23854
23927
  setValidity(errorKey, null);
23855
23928
  } else {
23856
- setValidity(errorKey, parseValid);
23857
- if (!parseValid) {
23929
+ if (!parserValid) {
23858
23930
  forEach(ctrl.$validators, function(v, name) {
23859
23931
  setValidity(name, null);
23860
23932
  });
23861
23933
  forEach(ctrl.$asyncValidators, function(v, name) {
23862
23934
  setValidity(name, null);
23863
23935
  });
23864
- return false;
23865
23936
  }
23937
+ // Set the parse error last, to prevent unsetting it, should a $validators key == parserName
23938
+ setValidity(errorKey, parserValid);
23939
+ return parserValid;
23866
23940
  }
23867
23941
  return true;
23868
23942
  }
@@ -23957,7 +24031,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
23957
24031
  this.$$parseAndValidate = function() {
23958
24032
  var viewValue = ctrl.$$lastCommittedViewValue;
23959
24033
  var modelValue = viewValue;
23960
- var parserValid = isUndefined(modelValue) ? undefined : true;
24034
+ parserValid = isUndefined(modelValue) ? undefined : true;
23961
24035
 
23962
24036
  if (parserValid) {
23963
24037
  for (var i = 0; i < ctrl.$parsers.length; i++) {
@@ -23983,7 +24057,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
23983
24057
 
23984
24058
  // Pass the $$lastCommittedViewValue here, because the cached viewValue might be out of date.
23985
24059
  // This can happen if e.g. $setViewValue is called from inside a parser
23986
- ctrl.$$runValidators(parserValid, modelValue, ctrl.$$lastCommittedViewValue, function(allValid) {
24060
+ ctrl.$$runValidators(modelValue, ctrl.$$lastCommittedViewValue, function(allValid) {
23987
24061
  if (!allowInvalid) {
23988
24062
  // Note: Don't check ctrl.$valid here, as we could have
23989
24063
  // external validators (e.g. calculated on the server),
@@ -24104,6 +24178,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
24104
24178
  // TODO(perf): why not move this to the action fn?
24105
24179
  if (modelValue !== ctrl.$modelValue) {
24106
24180
  ctrl.$modelValue = ctrl.$$rawModelValue = modelValue;
24181
+ parserValid = undefined;
24107
24182
 
24108
24183
  var formatters = ctrl.$formatters,
24109
24184
  idx = formatters.length;
@@ -24116,7 +24191,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
24116
24191
  ctrl.$viewValue = ctrl.$$lastCommittedViewValue = viewValue;
24117
24192
  ctrl.$render();
24118
24193
 
24119
- ctrl.$$runValidators(undefined, modelValue, viewValue, noop);
24194
+ ctrl.$$runValidators(modelValue, viewValue, noop);
24120
24195
  }
24121
24196
  }
24122
24197
 
@@ -24752,15 +24827,20 @@ var ngOptionsMinErr = minErr('ngOptions');
24752
24827
  * * `label` **`for`** `value` **`in`** `array`
24753
24828
  * * `select` **`as`** `label` **`for`** `value` **`in`** `array`
24754
24829
  * * `label` **`group by`** `group` **`for`** `value` **`in`** `array`
24830
+ * * `label` **`disable when`** `disable` **`for`** `value` **`in`** `array`
24755
24831
  * * `label` **`group by`** `group` **`for`** `value` **`in`** `array` **`track by`** `trackexpr`
24832
+ * * `label` **`disable when`** `disable` **`for`** `value` **`in`** `array` **`track by`** `trackexpr`
24756
24833
  * * `label` **`for`** `value` **`in`** `array` | orderBy:`orderexpr` **`track by`** `trackexpr`
24757
24834
  * (for including a filter with `track by`)
24758
24835
  * * for object data sources:
24759
24836
  * * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`
24760
24837
  * * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`
24761
24838
  * * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`
24839
+ * * `label` **`disable when`** `disable` **`for (`**`key`**`,`** `value`**`) in`** `object`
24762
24840
  * * `select` **`as`** `label` **`group by`** `group`
24763
24841
  * **`for` `(`**`key`**`,`** `value`**`) in`** `object`
24842
+ * * `select` **`as`** `label` **`disable when`** `disable`
24843
+ * **`for` `(`**`key`**`,`** `value`**`) in`** `object`
24764
24844
  *
24765
24845
  * Where:
24766
24846
  *
@@ -24774,6 +24854,8 @@ var ngOptionsMinErr = minErr('ngOptions');
24774
24854
  * element. If not specified, `select` expression will default to `value`.
24775
24855
  * * `group`: The result of this expression will be used to group options using the `<optgroup>`
24776
24856
  * DOM element.
24857
+ * * `disable`: The result of this expression will be used to disable the rendered `<option>`
24858
+ * element. Return `true` to disable.
24777
24859
  * * `trackexpr`: Used when working with an array of objects. The result of this expression will be
24778
24860
  * used to identify the objects in the array. The `trackexpr` will most likely refer to the
24779
24861
  * `value` variable (e.g. `value.propertyName`). With this the selection is preserved
@@ -24787,10 +24869,10 @@ var ngOptionsMinErr = minErr('ngOptions');
24787
24869
  .controller('ExampleController', ['$scope', function($scope) {
24788
24870
  $scope.colors = [
24789
24871
  {name:'black', shade:'dark'},
24790
- {name:'white', shade:'light'},
24872
+ {name:'white', shade:'light', notAnOption: true},
24791
24873
  {name:'red', shade:'dark'},
24792
- {name:'blue', shade:'dark'},
24793
- {name:'yellow', shade:'light'}
24874
+ {name:'blue', shade:'dark', notAnOption: true},
24875
+ {name:'yellow', shade:'light', notAnOption: false}
24794
24876
  ];
24795
24877
  $scope.myColor = $scope.colors[2]; // red
24796
24878
  }]);
@@ -24799,6 +24881,7 @@ var ngOptionsMinErr = minErr('ngOptions');
24799
24881
  <ul>
24800
24882
  <li ng-repeat="color in colors">
24801
24883
  Name: <input ng-model="color.name">
24884
+ <input type="checkbox" ng-model="color.notAnOption"> Disabled?
24802
24885
  [<a href ng-click="colors.splice($index, 1)">X</a>]
24803
24886
  </li>
24804
24887
  <li>
@@ -24820,6 +24903,12 @@ var ngOptionsMinErr = minErr('ngOptions');
24820
24903
  <select ng-model="myColor" ng-options="color.name group by color.shade for color in colors">
24821
24904
  </select><br/>
24822
24905
 
24906
+ Color grouped by shade, with some disabled:
24907
+ <select ng-model="myColor"
24908
+ ng-options="color.name group by color.shade disable when color.notAnOption for color in colors">
24909
+ </select><br/>
24910
+
24911
+
24823
24912
 
24824
24913
  Select <a href ng-click="myColor = { name:'not in list', shade: 'other' }">bogus</a>.<br>
24825
24914
  <hr/>
@@ -24844,16 +24933,17 @@ var ngOptionsMinErr = minErr('ngOptions');
24844
24933
  */
24845
24934
 
24846
24935
  // jshint maxlen: false
24847
- //000011111111110000000000022222222220000000000000000000003333333333000000000000004444444444444440000000005555555555555550000000666666666666666000000000000000777777777700000000000000000008888888888
24848
- var NG_OPTIONS_REGEXP = /^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+group\s+by\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?$/;
24936
+ // //00001111111111000000000002222222222000000000000000000000333333333300000000000000000000000004444444444400000000000005555555555555550000000006666666666666660000000777777777777777000000000000000888888888800000000000000000009999999999
24937
+ var NG_OPTIONS_REGEXP = /^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+group\s+by\s+([\s\S]+?))?(?:\s+disable\s+when\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?$/;
24849
24938
  // 1: value expression (valueFn)
24850
24939
  // 2: label expression (displayFn)
24851
24940
  // 3: group by expression (groupByFn)
24852
- // 4: array item variable name
24853
- // 5: object item key variable name
24854
- // 6: object item value variable name
24855
- // 7: collection expression
24856
- // 8: track by expression
24941
+ // 4: disable when expression (disableWhenFn)
24942
+ // 5: array item variable name
24943
+ // 6: object item key variable name
24944
+ // 7: object item value variable name
24945
+ // 8: collection expression
24946
+ // 9: track by expression
24857
24947
  // jshint maxlen: 100
24858
24948
 
24859
24949
 
@@ -24873,14 +24963,14 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
24873
24963
  // Extract the parts from the ngOptions expression
24874
24964
 
24875
24965
  // The variable name for the value of the item in the collection
24876
- var valueName = match[4] || match[6];
24966
+ var valueName = match[5] || match[7];
24877
24967
  // The variable name for the key of the item in the collection
24878
- var keyName = match[5];
24968
+ var keyName = match[6];
24879
24969
 
24880
24970
  // An expression that generates the viewValue for an option if there is a label expression
24881
24971
  var selectAs = / as /.test(match[0]) && match[1];
24882
24972
  // An expression that is used to track the id of each object in the options collection
24883
- var trackBy = match[8];
24973
+ var trackBy = match[9];
24884
24974
  // An expression that generates the viewValue for an option if there is no label expression
24885
24975
  var valueFn = $parse(match[2] ? match[1] : valueName);
24886
24976
  var selectAsFn = selectAs && $parse(selectAs);
@@ -24895,7 +24985,8 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
24895
24985
  function getHashOfValue(viewValue) { return hashKey(viewValue); };
24896
24986
  var displayFn = $parse(match[2] || match[1]);
24897
24987
  var groupByFn = $parse(match[3] || '');
24898
- var valuesFn = $parse(match[7]);
24988
+ var disableWhenFn = $parse(match[4] || '');
24989
+ var valuesFn = $parse(match[8]);
24899
24990
 
24900
24991
  var locals = {};
24901
24992
  var getLocals = keyName ? function(value, key) {
@@ -24908,11 +24999,12 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
24908
24999
  };
24909
25000
 
24910
25001
 
24911
- function Option(selectValue, viewValue, label, group) {
25002
+ function Option(selectValue, viewValue, label, group, disabled) {
24912
25003
  this.selectValue = selectValue;
24913
25004
  this.viewValue = viewValue;
24914
25005
  this.label = label;
24915
25006
  this.group = group;
25007
+ this.disabled = disabled;
24916
25008
  }
24917
25009
 
24918
25010
  return {
@@ -24925,10 +25017,20 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
24925
25017
 
24926
25018
  Object.keys(values).forEach(function getWatchable(key) {
24927
25019
  var locals = getLocals(values[key], key);
24928
- var label = displayFn(scope, locals);
24929
25020
  var selectValue = getTrackByValue(values[key], locals);
24930
25021
  watchedArray.push(selectValue);
24931
- watchedArray.push(label);
25022
+
25023
+ // Only need to watch the displayFn if there is a specific label expression
25024
+ if (match[2]) {
25025
+ var label = displayFn(scope, locals);
25026
+ watchedArray.push(label);
25027
+ }
25028
+
25029
+ // Only need to watch the disableWhenFn if there is a specific disable expression
25030
+ if (match[4]) {
25031
+ var disableWhen = disableWhenFn(scope, locals);
25032
+ watchedArray.push(disableWhen);
25033
+ }
24932
25034
  });
24933
25035
  return watchedArray;
24934
25036
  }),
@@ -24954,7 +25056,8 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
24954
25056
  var selectValue = getTrackByValue(viewValue, locals);
24955
25057
  var label = displayFn(scope, locals);
24956
25058
  var group = groupByFn(scope, locals);
24957
- var optionItem = new Option(selectValue, viewValue, label, group);
25059
+ var disabled = disableWhenFn(scope, locals);
25060
+ var optionItem = new Option(selectValue, viewValue, label, group, disabled);
24958
25061
 
24959
25062
  optionItems.push(optionItem);
24960
25063
  selectValueMap[selectValue] = optionItem;
@@ -25031,7 +25134,7 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
25031
25134
  selectCtrl.writeValue = function writeNgOptionsValue(value) {
25032
25135
  var option = options.getOptionFromViewValue(value);
25033
25136
 
25034
- if (option) {
25137
+ if (option && !option.disabled) {
25035
25138
  if (selectElement[0].value !== option.selectValue) {
25036
25139
  removeUnknownOption();
25037
25140
  removeEmptyOption();
@@ -25055,7 +25158,7 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
25055
25158
 
25056
25159
  var selectedOption = options.selectValueMap[selectElement.val()];
25057
25160
 
25058
- if (selectedOption) {
25161
+ if (selectedOption && !selectedOption.disabled) {
25059
25162
  removeEmptyOption();
25060
25163
  removeUnknownOption();
25061
25164
  return selectedOption.viewValue;
@@ -25080,18 +25183,22 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
25080
25183
  if (value) {
25081
25184
  value.forEach(function(item) {
25082
25185
  var option = options.getOptionFromViewValue(item);
25083
- if (option) option.element.selected = true;
25186
+ if (option && !option.disabled) option.element.selected = true;
25084
25187
  });
25085
25188
  }
25086
25189
  };
25087
25190
 
25088
25191
 
25089
25192
  selectCtrl.readValue = function readNgOptionsMultiple() {
25090
- var selectedValues = selectElement.val() || [];
25091
- return selectedValues.map(function(selectedKey) {
25092
- var option = options.selectValueMap[selectedKey];
25093
- return option.viewValue;
25193
+ var selectedValues = selectElement.val() || [],
25194
+ selections = [];
25195
+
25196
+ forEach(selectedValues, function(value) {
25197
+ var option = options.selectValueMap[value];
25198
+ if (!option.disabled) selections.push(option.viewValue);
25094
25199
  });
25200
+
25201
+ return selections;
25095
25202
  };
25096
25203
  }
25097
25204
 
@@ -25124,6 +25231,7 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
25124
25231
 
25125
25232
  function updateOptionElement(option, element) {
25126
25233
  option.element = element;
25234
+ element.disabled = option.disabled;
25127
25235
  if (option.value !== element.value) element.value = option.selectValue;
25128
25236
  if (option.label !== element.label) {
25129
25237
  element.label = option.label;
@@ -25557,6 +25665,55 @@ var ngPluralizeDirective = ['$locale', '$interpolate', '$log', function($locale,
25557
25665
  * or implement a `$watch` on the object yourself.
25558
25666
  *
25559
25667
  *
25668
+ * # Tracking and Duplicates
25669
+ *
25670
+ * When the contents of the collection change, `ngRepeat` makes the corresponding changes to the DOM:
25671
+ *
25672
+ * * When an item is added, a new instance of the template is added to the DOM.
25673
+ * * When an item is removed, its template instance is removed from the DOM.
25674
+ * * When items are reordered, their respective templates are reordered in the DOM.
25675
+ *
25676
+ * By default, `ngRepeat` does not allow duplicate items in arrays. This is because when
25677
+ * there are duplicates, it is not possible to maintain a one-to-one mapping between collection
25678
+ * items and DOM elements.
25679
+ *
25680
+ * If you do need to repeat duplicate items, you can substitute the default tracking behavior
25681
+ * with your own using the `track by` expression.
25682
+ *
25683
+ * For example, you may track items by the index of each item in the collection, using the
25684
+ * special scope property `$index`:
25685
+ * ```html
25686
+ * <div ng-repeat="n in [42, 42, 43, 43] track by $index">
25687
+ * {{n}}
25688
+ * </div>
25689
+ * ```
25690
+ *
25691
+ * You may use arbitrary expressions in `track by`, including references to custom functions
25692
+ * on the scope:
25693
+ * ```html
25694
+ * <div ng-repeat="n in [42, 42, 43, 43] track by myTrackingFunction(n)">
25695
+ * {{n}}
25696
+ * </div>
25697
+ * ```
25698
+ *
25699
+ * If you are working with objects that have an identifier property, you can track
25700
+ * by the identifier instead of the whole object. Should you reload your data later, `ngRepeat`
25701
+ * will not have to rebuild the DOM elements for items it has already rendered, even if the
25702
+ * JavaScript objects in the collection have been substituted for new ones:
25703
+ * ```html
25704
+ * <div ng-repeat="model in collection track by model.id">
25705
+ * {{model.name}}
25706
+ * </div>
25707
+ * ```
25708
+ *
25709
+ * When no `track by` expression is provided, it is equivalent to tracking by the built-in
25710
+ * `$id` function, which tracks items by their identity:
25711
+ * ```html
25712
+ * <div ng-repeat="obj in collection track by $id(obj)">
25713
+ * {{obj.prop}}
25714
+ * </div>
25715
+ * ```
25716
+ *
25560
25717
  * # Special repeat start and end points
25561
25718
  * To repeat a series of elements instead of just one parent element, ngRepeat (as well as other ng directives) supports extending
25562
25719
  * the range of the repeater by defining explicit start and end points by using **ng-repeat-start** and **ng-repeat-end** respectively.
@@ -25624,12 +25781,12 @@ var ngPluralizeDirective = ['$locale', '$interpolate', '$log', function($locale,
25624
25781
  *
25625
25782
  * For example: `(name, age) in {'adam':10, 'amalie':12}`.
25626
25783
  *
25627
- * * `variable in expression track by tracking_expression` – You can also provide an optional tracking function
25628
- * which can be used to associate the objects in the collection with the DOM elements. If no tracking function
25629
- * is specified the ng-repeat associates elements by identity in the collection. It is an error to have
25630
- * more than one tracking function to resolve to the same key. (This would mean that two distinct objects are
25631
- * mapped to the same DOM element, which is not possible.) Filters should be applied to the expression,
25632
- * before specifying a tracking expression.
25784
+ * * `variable in expression track by tracking_expression` – You can also provide an optional tracking expression
25785
+ * which can be used to associate the objects in the collection with the DOM elements. If no tracking expression
25786
+ * is specified, ng-repeat associates elements by identity. It is an error to have
25787
+ * more than one tracking expression value resolve to the same key. (This would mean that two distinct objects are
25788
+ * mapped to the same DOM element, which is not possible.) If filters are used in the expression, they should be
25789
+ * applied before the tracking expression.
25633
25790
  *
25634
25791
  * For example: `item in items` is equivalent to `item in items track by $id(item)`. This implies that the DOM elements
25635
25792
  * will be associated by item identity in the array.
@@ -25653,6 +25810,11 @@ var ngPluralizeDirective = ['$locale', '$interpolate', '$log', function($locale,
25653
25810
  * For example: `item in items | filter:x as results` will store the fragment of the repeated items as `results`, but only after
25654
25811
  * the items have been processed through the filter.
25655
25812
  *
25813
+ * Please note that `as [variable name] is not an operator but rather a part of ngRepeat micro-syntax so it can be used only at the end
25814
+ * (and not as operator, inside an expression).
25815
+ *
25816
+ * For example: `item in items | filter : x | orderBy : order | limitTo : limit as results` .
25817
+ *
25656
25818
  * @example
25657
25819
  * This example initializes the scope to a list of names and
25658
25820
  * then uses `ngRepeat` to display every person:
@@ -26492,7 +26654,6 @@ var ngStyleDirective = ngDirective(function(scope, element, attr) {
26492
26654
  */
26493
26655
  var ngSwitchDirective = ['$animate', function($animate) {
26494
26656
  return {
26495
- restrict: 'EA',
26496
26657
  require: 'ngSwitch',
26497
26658
 
26498
26659
  // asks for $scope to fool the BC controller module
@@ -26760,6 +26921,7 @@ var SelectController =
26760
26921
  if (value === '') self.emptyOption.prop('selected', true); // to make IE9 happy
26761
26922
  } else {
26762
26923
  if (isUndefined(value) && self.emptyOption) {
26924
+ self.removeUnknownOption();
26763
26925
  $element.val('');
26764
26926
  } else {
26765
26927
  self.renderUnknownOption(value);