angularjs-rails 1.0.3 → 1.0.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.0.3
2
+ * @license AngularJS v1.0.4
3
3
  * (c) 2010-2012 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -627,13 +627,15 @@ function equals(o1, o2) {
627
627
  if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2)) return false;
628
628
  keySet = {};
629
629
  for(key in o1) {
630
- if (key.charAt(0) !== '$' && !isFunction(o1[key]) && !equals(o1[key], o2[key])) {
631
- return false;
632
- }
630
+ if (key.charAt(0) === '$' || isFunction(o1[key])) continue;
631
+ if (!equals(o1[key], o2[key])) return false;
633
632
  keySet[key] = true;
634
633
  }
635
634
  for(key in o2) {
636
- if (!keySet[key] && key.charAt(0) !== '$' && !isFunction(o2[key])) return false;
635
+ if (!keySet[key] &&
636
+ key.charAt(0) !== '$' &&
637
+ o2[key] !== undefined &&
638
+ !isFunction(o2[key])) return false;
637
639
  }
638
640
  return true;
639
641
  }
@@ -1247,11 +1249,11 @@ function setupModuleLoader(window) {
1247
1249
  * - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat".
1248
1250
  */
1249
1251
  var version = {
1250
- full: '1.0.3', // all of these placeholder strings will be replaced by rake's
1252
+ full: '1.0.4', // all of these placeholder strings will be replaced by rake's
1251
1253
  major: 1, // compile task
1252
1254
  minor: 0,
1253
- dot: 3,
1254
- codeName: 'bouncy-thunder'
1255
+ dot: 4,
1256
+ codeName: 'bewildering-hair'
1255
1257
  };
1256
1258
 
1257
1259
 
@@ -1423,7 +1425,7 @@ function publishExternalAPI(angular){
1423
1425
  * - [val()](http://api.jquery.com/val/)
1424
1426
  * - [wrap()](http://api.jquery.com/wrap/)
1425
1427
  *
1426
- * ## In addtion to the above, Angular privides an additional method to both jQuery and jQuery lite:
1428
+ * ## In addtion to the above, Angular provides additional methods to both jQuery and jQuery lite:
1427
1429
  *
1428
1430
  * - `controller(name)` - retrieves the controller of the current element or its parent. By default
1429
1431
  * retrieves controller associated with the `ngController` directive. If `name` is provided as
@@ -2011,14 +2013,14 @@ forEach({
2011
2013
  children: function(element) {
2012
2014
  var children = [];
2013
2015
  forEach(element.childNodes, function(element){
2014
- if (element.nodeName != '#text')
2016
+ if (element.nodeType === 1)
2015
2017
  children.push(element);
2016
2018
  });
2017
2019
  return children;
2018
2020
  },
2019
2021
 
2020
2022
  contents: function(element) {
2021
- return element.childNodes;
2023
+ return element.childNodes || [];
2022
2024
  },
2023
2025
 
2024
2026
  append: function(element, node) {
@@ -2081,7 +2083,16 @@ forEach({
2081
2083
  },
2082
2084
 
2083
2085
  next: function(element) {
2084
- return element.nextSibling;
2086
+ if (element.nextElementSibling) {
2087
+ return element.nextElementSibling;
2088
+ }
2089
+
2090
+ // IE8 doesn't have nextElementSibling
2091
+ var elm = element.nextSibling;
2092
+ while (elm != null && elm.nodeType !== 1) {
2093
+ elm = elm.nextSibling;
2094
+ }
2095
+ return elm;
2085
2096
  },
2086
2097
 
2087
2098
  find: function(element, selector) {
@@ -2667,7 +2678,7 @@ function createInjector(modulesToLoad) {
2667
2678
  }
2668
2679
 
2669
2680
  function provider(name, provider_) {
2670
- if (isFunction(provider_)) {
2681
+ if (isFunction(provider_) || isArray(provider_)) {
2671
2682
  provider_ = providerInjector.instantiate(provider_);
2672
2683
  }
2673
2684
  if (!provider_.$get) {
@@ -2784,7 +2795,7 @@ function createInjector(modulesToLoad) {
2784
2795
  args.push(
2785
2796
  locals && locals.hasOwnProperty(key)
2786
2797
  ? locals[key]
2787
- : getService(key, path)
2798
+ : getService(key)
2788
2799
  );
2789
2800
  }
2790
2801
  if (!fn.$inject) {
@@ -2884,7 +2895,7 @@ function $AnchorScrollProvider() {
2884
2895
  }
2885
2896
 
2886
2897
  // does not scroll when user clicks on anchor link that is currently on
2887
- // (no url change, no $locaiton.hash() change), browser native does scroll
2898
+ // (no url change, no $location.hash() change), browser native does scroll
2888
2899
  if (autoScrollingEnabled) {
2889
2900
  $rootScope.$watch(function autoScrollWatch() {return $location.hash();},
2890
2901
  function autoScrollWatchAction() {
@@ -3172,14 +3183,15 @@ function Browser(window, document, $log, $sniffer) {
3172
3183
  } else {
3173
3184
  if (isString(value)) {
3174
3185
  cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) + ';path=' + cookiePath).length + 1;
3186
+
3187
+ // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:
3188
+ // - 300 cookies
3189
+ // - 20 cookies per unique domain
3190
+ // - 4096 bytes per cookie
3175
3191
  if (cookieLength > 4096) {
3176
3192
  $log.warn("Cookie '"+ name +"' possibly not set or overflowed because it was too large ("+
3177
3193
  cookieLength + " > 4096 bytes)!");
3178
3194
  }
3179
- if (lastCookies.length > 20) {
3180
- $log.warn("Cookie '"+ name +"' possibly not set or overflowed because too many cookies " +
3181
- "were already set (" + lastCookies.length + " > 20 )");
3182
- }
3183
3195
  }
3184
3196
  }
3185
3197
  } else {
@@ -3745,7 +3757,7 @@ function $CompileProvider($provide) {
3745
3757
  // We can not compile top level text elements since text nodes can be merged and we will
3746
3758
  // not be able to attach scope data to them, so we will wrap them in <span>
3747
3759
  forEach($compileNodes, function(node, index){
3748
- if (node.nodeType == 3 /* text node */) {
3760
+ if (node.nodeType == 3 /* text node */ && node.nodeValue.match(/\S+/) /* non-empty */ ) {
3749
3761
  $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];
3750
3762
  }
3751
3763
  });
@@ -3794,68 +3806,74 @@ function $CompileProvider($provide) {
3794
3806
  * @returns {?function} A composite linking function of all of the matched directives or null.
3795
3807
  */
3796
3808
  function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority) {
3797
- var linkFns = [],
3798
- nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;
3809
+ var linkFns = [],
3810
+ nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;
3799
3811
 
3800
- for(var i = 0; i < nodeList.length; i++) {
3801
- attrs = new Attributes();
3812
+ for(var i = 0; i < nodeList.length; i++) {
3813
+ attrs = new Attributes();
3802
3814
 
3803
- // we must always refer to nodeList[i] since the nodes can be replaced underneath us.
3804
- directives = collectDirectives(nodeList[i], [], attrs, maxPriority);
3815
+ // we must always refer to nodeList[i] since the nodes can be replaced underneath us.
3816
+ directives = collectDirectives(nodeList[i], [], attrs, maxPriority);
3805
3817
 
3806
- nodeLinkFn = (directives.length)
3807
- ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)
3808
- : null;
3818
+ nodeLinkFn = (directives.length)
3819
+ ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)
3820
+ : null;
3809
3821
 
3810
- childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes.length)
3811
- ? null
3812
- : compileNodes(nodeList[i].childNodes,
3813
- nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);
3822
+ childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes.length)
3823
+ ? null
3824
+ : compileNodes(nodeList[i].childNodes,
3825
+ nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);
3814
3826
 
3815
- linkFns.push(nodeLinkFn);
3816
- linkFns.push(childLinkFn);
3817
- linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);
3818
- }
3827
+ linkFns.push(nodeLinkFn);
3828
+ linkFns.push(childLinkFn);
3829
+ linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);
3830
+ }
3819
3831
 
3820
- // return a linking function if we have found anything, null otherwise
3821
- return linkFnFound ? compositeLinkFn : null;
3832
+ // return a linking function if we have found anything, null otherwise
3833
+ return linkFnFound ? compositeLinkFn : null;
3822
3834
 
3823
- function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {
3824
- var nodeLinkFn, childLinkFn, node, childScope, childTranscludeFn;
3835
+ function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {
3836
+ var nodeLinkFn, childLinkFn, node, childScope, childTranscludeFn, i, ii, n;
3825
3837
 
3826
- for(var i = 0, n = 0, ii = linkFns.length; i < ii; n++) {
3827
- node = nodeList[n];
3828
- nodeLinkFn = linkFns[i++];
3829
- childLinkFn = linkFns[i++];
3838
+ // copy nodeList so that linking doesn't break due to live list updates.
3839
+ var stableNodeList = [];
3840
+ for (i = 0, ii = nodeList.length; i < ii; i++) {
3841
+ stableNodeList.push(nodeList[i]);
3842
+ }
3830
3843
 
3831
- if (nodeLinkFn) {
3832
- if (nodeLinkFn.scope) {
3833
- childScope = scope.$new(isObject(nodeLinkFn.scope));
3834
- jqLite(node).data('$scope', childScope);
3835
- } else {
3836
- childScope = scope;
3837
- }
3838
- childTranscludeFn = nodeLinkFn.transclude;
3839
- if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {
3840
- nodeLinkFn(childLinkFn, childScope, node, $rootElement,
3841
- (function(transcludeFn) {
3842
- return function(cloneFn) {
3843
- var transcludeScope = scope.$new();
3844
-
3845
- return transcludeFn(transcludeScope, cloneFn).
3846
- bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));
3844
+ for(i = 0, n = 0, ii = linkFns.length; i < ii; n++) {
3845
+ node = stableNodeList[n];
3846
+ nodeLinkFn = linkFns[i++];
3847
+ childLinkFn = linkFns[i++];
3848
+
3849
+ if (nodeLinkFn) {
3850
+ if (nodeLinkFn.scope) {
3851
+ childScope = scope.$new(isObject(nodeLinkFn.scope));
3852
+ jqLite(node).data('$scope', childScope);
3853
+ } else {
3854
+ childScope = scope;
3855
+ }
3856
+ childTranscludeFn = nodeLinkFn.transclude;
3857
+ if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {
3858
+ nodeLinkFn(childLinkFn, childScope, node, $rootElement,
3859
+ (function(transcludeFn) {
3860
+ return function(cloneFn) {
3861
+ var transcludeScope = scope.$new();
3862
+
3863
+ return transcludeFn(transcludeScope, cloneFn).
3864
+ bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));
3847
3865
  };
3848
3866
  })(childTranscludeFn || transcludeFn)
3849
- );
3850
- } else {
3851
- nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn);
3852
- }
3853
- } else if (childLinkFn) {
3854
- childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);
3855
- }
3856
- }
3857
- }
3858
- }
3867
+ );
3868
+ } else {
3869
+ nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn);
3870
+ }
3871
+ } else if (childLinkFn) {
3872
+ childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);
3873
+ }
3874
+ }
3875
+ }
3876
+ }
3859
3877
 
3860
3878
 
3861
3879
  /**
@@ -4002,7 +4020,7 @@ function $CompileProvider($provide) {
4002
4020
  if (directiveValue == 'element') {
4003
4021
  $template = jqLite(compileNode);
4004
4022
  $compileNode = templateAttrs.$$element =
4005
- jqLite('<!-- ' + directiveName + ': ' + templateAttrs[directiveName] + ' -->');
4023
+ jqLite(document.createComment(' ' + directiveName + ': ' + templateAttrs[directiveName] + ' '));
4006
4024
  compileNode = $compileNode[0];
4007
4025
  replaceWith($rootElement, jqLite($template[0]), compileNode);
4008
4026
  childTranscludeFn = compile($template, transcludeFn, terminalPriority);
@@ -4667,11 +4685,12 @@ function $DocumentProvider(){
4667
4685
  * the browser console.
4668
4686
  *
4669
4687
  * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by
4670
- * {@link ngMock.$exceptionHandler mock $exceptionHandler}
4688
+ * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.
4671
4689
  *
4672
4690
  * @param {Error} exception Exception associated with the error.
4673
4691
  * @param {string=} cause optional information about the context in which
4674
4692
  * the error was thrown.
4693
+ *
4675
4694
  */
4676
4695
  function $ExceptionHandlerProvider() {
4677
4696
  this.$get = ['$log', function($log){
@@ -6471,7 +6490,7 @@ function $ParseProvider() {
6471
6490
  * performed asynchronously, and may or may not be finished at any given point in time.
6472
6491
  *
6473
6492
  * From the perspective of dealing with error handling, deferred and promise apis are to
6474
- * asynchronous programing what `try`, `catch` and `throw` keywords are to synchronous programing.
6493
+ * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.
6475
6494
  *
6476
6495
  * <pre>
6477
6496
  * // for the purpose of this example let's assume that variables `$q` and `scope` are
@@ -6581,6 +6600,30 @@ function $ParseProvider() {
6581
6600
  * you can treat promises attached to a scope as if they were the resulting values.
6582
6601
  * - Q has many more features that $q, but that comes at a cost of bytes. $q is tiny, but contains
6583
6602
  * all the important functionality needed for common async tasks.
6603
+ *
6604
+ * # Testing
6605
+ *
6606
+ * <pre>
6607
+ * it('should simulate promise', inject(function($q, $rootSCope) {
6608
+ * var deferred = $q.defer();
6609
+ * var promise = deferred.promise;
6610
+ * var resolvedValue;
6611
+ *
6612
+ * promise.then(function(value) { resolvedValue = value; });
6613
+ * expect(resolvedValue).toBeUndefined();
6614
+ *
6615
+ * // Simulate resolving of promise
6616
+ * defered.resolve(123);
6617
+ * // Note that the 'then' function does not get called synchronously.
6618
+ * // This is because we want the promise API to always be async, whether or not
6619
+ * // it got called synchronously or asynchronously.
6620
+ * expect(resolvedValue).toBeUndefined();
6621
+ *
6622
+ * // Propagate promise resolution to 'then' functions using $apply().
6623
+ * $rootScope.$apply();
6624
+ * expect(resolvedValue).toEqual(123);
6625
+ * });
6626
+ * </pre>
6584
6627
  */
6585
6628
  function $QProvider() {
6586
6629
 
@@ -6867,8 +6910,13 @@ function $RouteProvider(){
6867
6910
  *
6868
6911
  * @param {string} path Route path (matched against `$location.path`). If `$location.path`
6869
6912
  * contains redundant trailing slash or is missing one, the route will still match and the
6870
- * `$location.path` will be updated to add or drop the trailing slash to exacly match the
6913
+ * `$location.path` will be updated to add or drop the trailing slash to exactly match the
6871
6914
  * route definition.
6915
+ *
6916
+ * `path` can contain named groups starting with a colon (`:name`). All characters up to the
6917
+ * next slash are matched and stored in `$routeParams` under the given `name` when the route
6918
+ * matches.
6919
+ *
6872
6920
  * @param {Object} route Mapping information to be assigned to `$route.current` on route
6873
6921
  * match.
6874
6922
  *
@@ -7133,8 +7181,7 @@ function $RouteProvider(){
7133
7181
  * instance of the Controller.
7134
7182
  */
7135
7183
 
7136
- var matcher = switchRouteMatcher,
7137
- forceReload = false,
7184
+ var forceReload = false,
7138
7185
  $route = {
7139
7186
  routes: routes,
7140
7187
 
@@ -7162,21 +7209,36 @@ function $RouteProvider(){
7162
7209
 
7163
7210
  /////////////////////////////////////////////////////
7164
7211
 
7212
+ /**
7213
+ * @param on {string} current url
7214
+ * @param when {string} route when template to match the url against
7215
+ * @return {?Object}
7216
+ */
7165
7217
  function switchRouteMatcher(on, when) {
7166
7218
  // TODO(i): this code is convoluted and inefficient, we should construct the route matching
7167
7219
  // regex only once and then reuse it
7168
- var regex = '^' + when.replace(/([\.\\\(\)\^\$])/g, "\\$1") + '$',
7220
+
7221
+ // Escape regexp special characters.
7222
+ when = '^' + when.replace(/[-\/\\^$*+?.()|[\]{}]/g, "\\$&") + '$';
7223
+ var regex = '',
7169
7224
  params = [],
7170
7225
  dst = {};
7171
- forEach(when.split(/\W/), function(param) {
7172
- if (param) {
7173
- var paramRegExp = new RegExp(":" + param + "([\\W])");
7174
- if (regex.match(paramRegExp)) {
7175
- regex = regex.replace(paramRegExp, "([^\\/]*)$1");
7176
- params.push(param);
7177
- }
7178
- }
7179
- });
7226
+
7227
+ var re = /:(\w+)/g,
7228
+ paramMatch,
7229
+ lastMatchedIndex = 0;
7230
+
7231
+ while ((paramMatch = re.exec(when)) !== null) {
7232
+ // Find each :param in `when` and replace it with a capturing group.
7233
+ // Append all other sections of when unchanged.
7234
+ regex += when.slice(lastMatchedIndex, paramMatch.index);
7235
+ regex += '([^\\/]*)';
7236
+ params.push(paramMatch[1]);
7237
+ lastMatchedIndex = re.lastIndex;
7238
+ }
7239
+ // Append trailing path part.
7240
+ regex += when.substr(lastMatchedIndex);
7241
+
7180
7242
  var match = on.match(new RegExp(regex));
7181
7243
  if (match) {
7182
7244
  forEach(params, function(name, index) {
@@ -7265,7 +7327,7 @@ function $RouteProvider(){
7265
7327
  // Match a route
7266
7328
  var params, match;
7267
7329
  forEach(routes, function(route, path) {
7268
- if (!match && (params = matcher($location.path(), path))) {
7330
+ if (!match && (params = switchRouteMatcher($location.path(), path))) {
7269
7331
  match = inherit(route, {
7270
7332
  params: extend({}, $location.search(), params),
7271
7333
  pathParams: params});
@@ -7417,7 +7479,7 @@ function $RootScopeProvider(){
7417
7479
  expect(scope.greeting).toEqual(undefined);
7418
7480
 
7419
7481
  scope.$watch('name', function() {
7420
- this.greeting = this.salutation + ' ' + this.name + '!';
7482
+ scope.greeting = scope.salutation + ' ' + scope.name + '!';
7421
7483
  }); // initialize the watch
7422
7484
 
7423
7485
  expect(scope.greeting).toEqual(undefined);
@@ -7460,6 +7522,7 @@ function $RootScopeProvider(){
7460
7522
  this.$$nextSibling = this.$$prevSibling =
7461
7523
  this.$$childHead = this.$$childTail = null;
7462
7524
  this['this'] = this.$root = this;
7525
+ this.$$destroyed = false;
7463
7526
  this.$$asyncQueue = [];
7464
7527
  this.$$listeners = {};
7465
7528
  }
@@ -7578,7 +7641,7 @@ function $RootScopeProvider(){
7578
7641
  scope.counter = 0;
7579
7642
 
7580
7643
  expect(scope.counter).toEqual(0);
7581
- scope.$watch('name', function(newValue, oldValue) { counter = counter + 1; });
7644
+ scope.$watch('name', function(newValue, oldValue) { scope.counter = scope.counter + 1; });
7582
7645
  expect(scope.counter).toEqual(0);
7583
7646
 
7584
7647
  scope.$digest();
@@ -7671,7 +7734,7 @@ function $RootScopeProvider(){
7671
7734
 
7672
7735
  expect(scope.counter).toEqual(0);
7673
7736
  scope.$watch('name', function(newValue, oldValue) {
7674
- counter = counter + 1;
7737
+ scope.counter = scope.counter + 1;
7675
7738
  });
7676
7739
  expect(scope.counter).toEqual(0);
7677
7740
 
@@ -7793,10 +7856,12 @@ function $RootScopeProvider(){
7793
7856
  * perform any necessary cleanup.
7794
7857
  */
7795
7858
  $destroy: function() {
7796
- if ($rootScope == this) return; // we can't remove the root node;
7859
+ // we can't destroy the root scope or a scope that has been already destroyed
7860
+ if ($rootScope == this || this.$$destroyed) return;
7797
7861
  var parent = this.$parent;
7798
7862
 
7799
7863
  this.$broadcast('$destroy');
7864
+ this.$$destroyed = true;
7800
7865
 
7801
7866
  if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;
7802
7867
  if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;
@@ -8346,7 +8411,7 @@ function $HttpProvider() {
8346
8411
  /**
8347
8412
  * @ngdoc function
8348
8413
  * @name ng.$http
8349
- * @requires $httpBacked
8414
+ * @requires $httpBackend
8350
8415
  * @requires $browser
8351
8416
  * @requires $cacheFactory
8352
8417
  * @requires $rootScope
@@ -8382,8 +8447,7 @@ function $HttpProvider() {
8382
8447
  * }).
8383
8448
  * error(function(data, status, headers, config) {
8384
8449
  * // called asynchronously if an error occurs
8385
- * // or server returns response with status
8386
- * // code outside of the <200, 400) range
8450
+ * // or server returns response with an error status.
8387
8451
  * });
8388
8452
  * </pre>
8389
8453
  *
@@ -8392,6 +8456,10 @@ function $HttpProvider() {
8392
8456
  * an object representing the response. See the api signature and type info below for more
8393
8457
  * details.
8394
8458
  *
8459
+ * A response status code that falls in the [200, 300) range is considered a success status and
8460
+ * will result in the success callback being called. Note that if the response is a redirect,
8461
+ * XMLHttpRequest will transparently follow it, meaning that the error callback will not be
8462
+ * called for such responses.
8395
8463
  *
8396
8464
  * # Shortcut methods
8397
8465
  *
@@ -10229,7 +10297,6 @@ var htmlAnchorDirective = valueFn({
10229
10297
  // if we have no href url, then don't navigate anywhere.
10230
10298
  if (!element.attr('href')) {
10231
10299
  event.preventDefault();
10232
- return false; // Needed for opera
10233
10300
  }
10234
10301
  });
10235
10302
  }
@@ -10566,13 +10633,13 @@ var nullFormCtrl = {
10566
10633
  *
10567
10634
  * @property {boolean} $pristine True if user has not interacted with the form yet.
10568
10635
  * @property {boolean} $dirty True if user has already interacted with the form.
10569
- * @property {boolean} $valid True if all of the containg forms and controls are valid.
10636
+ * @property {boolean} $valid True if all of the containing forms and controls are valid.
10570
10637
  * @property {boolean} $invalid True if at least one containing control or form is invalid.
10571
10638
  *
10572
10639
  * @property {Object} $error Is an object hash, containing references to all invalid controls or
10573
10640
  * forms, where:
10574
10641
  *
10575
- * - keys are validation tokens (error names) — such as `REQUIRED`, `URL` or `EMAIL`),
10642
+ * - keys are validation tokens (error names) — such as `required`, `url` or `email`),
10576
10643
  * - values are arrays of controls or forms that are invalid with given error.
10577
10644
  *
10578
10645
  * @description
@@ -10685,7 +10752,7 @@ function FormController(element, attrs) {
10685
10752
  * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a
10686
10753
  * sub-group of controls needs to be determined.
10687
10754
  *
10688
- * @param {string=} ngForm|name Name of the form. If specified, the form controller will be published into
10755
+ * @param {string=} name|ngForm Name of the form. If specified, the form controller will be published into
10689
10756
  * related scope, under this name.
10690
10757
  *
10691
10758
  */
@@ -10758,12 +10825,12 @@ function FormController(element, attrs) {
10758
10825
  </script>
10759
10826
  <form name="myForm" ng-controller="Ctrl">
10760
10827
  userType: <input name="input" ng-model="userType" required>
10761
- <span class="error" ng-show="myForm.input.$error.REQUIRED">Required!</span><br>
10828
+ <span class="error" ng-show="myForm.input.$error.required">Required!</span><br>
10762
10829
  <tt>userType = {{userType}}</tt><br>
10763
10830
  <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>
10764
10831
  <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>
10765
10832
  <tt>myForm.$valid = {{myForm.$valid}}</tt><br>
10766
- <tt>myForm.$error.REQUIRED = {{!!myForm.$error.REQUIRED}}</tt><br>
10833
+ <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>
10767
10834
  </form>
10768
10835
  </doc:source>
10769
10836
  <doc:scenario>
@@ -13353,14 +13420,17 @@ var ngRepeatDirective = ngDirective({
13353
13420
  scope.$watch(function ngRepeatWatch(scope){
13354
13421
  var index, length,
13355
13422
  collection = scope.$eval(rhs),
13356
- collectionLength = size(collection, true),
13357
- childScope,
13423
+ cursor = iterStartElement, // current position of the node
13358
13424
  // Same as lastOrder but it has the current state. It will become the
13359
13425
  // lastOrder on the next iteration.
13360
13426
  nextOrder = new HashQueueMap(),
13427
+ arrayLength,
13428
+ childScope,
13361
13429
  key, value, // key/value of iteration
13362
- array, last, // last object information {scope, element, index}
13363
- cursor = iterStartElement; // current position of the node
13430
+ array,
13431
+ last; // last object information {scope, element, index}
13432
+
13433
+
13364
13434
 
13365
13435
  if (!isArray(collection)) {
13366
13436
  // if object, extract keys, sort them and use to determine order of iteration over obj props
@@ -13375,6 +13445,8 @@ var ngRepeatDirective = ngDirective({
13375
13445
  array = collection || [];
13376
13446
  }
13377
13447
 
13448
+ arrayLength = array.length;
13449
+
13378
13450
  // we are not using forEach for perf reasons (trying to avoid #call)
13379
13451
  for (index = 0, length = array.length; index < length; index++) {
13380
13452
  key = (collection === array) ? index : array[index];
@@ -13410,7 +13482,7 @@ var ngRepeatDirective = ngDirective({
13410
13482
  childScope.$index = index;
13411
13483
 
13412
13484
  childScope.$first = (index === 0);
13413
- childScope.$last = (index === (collectionLength - 1));
13485
+ childScope.$last = (index === (arrayLength - 1));
13414
13486
  childScope.$middle = !(childScope.$first || childScope.$last);
13415
13487
 
13416
13488
  if (!last) {
@@ -13631,52 +13703,53 @@ var ngStyleDirective = ngDirective(function(scope, element, attr) {
13631
13703
  var NG_SWITCH = 'ng-switch';
13632
13704
  var ngSwitchDirective = valueFn({
13633
13705
  restrict: 'EA',
13634
- compile: function(element, attr) {
13706
+ require: 'ngSwitch',
13707
+ controller: function ngSwitchController() {
13708
+ this.cases = {};
13709
+ },
13710
+ link: function(scope, element, attr, ctrl) {
13635
13711
  var watchExpr = attr.ngSwitch || attr.on,
13636
- cases = {};
13637
-
13638
- element.data(NG_SWITCH, cases);
13639
- return function(scope, element){
13640
- var selectedTransclude,
13641
- selectedElement,
13642
- selectedScope;
13643
-
13644
- scope.$watch(watchExpr, function ngSwitchWatchAction(value) {
13645
- if (selectedElement) {
13646
- selectedScope.$destroy();
13647
- selectedElement.remove();
13648
- selectedElement = selectedScope = null;
13649
- }
13650
- if ((selectedTransclude = cases['!' + value] || cases['?'])) {
13651
- scope.$eval(attr.change);
13652
- selectedScope = scope.$new();
13653
- selectedTransclude(selectedScope, function(caseElement) {
13654
- selectedElement = caseElement;
13655
- element.append(caseElement);
13656
- });
13657
- }
13658
- });
13659
- };
13712
+ selectedTransclude,
13713
+ selectedElement,
13714
+ selectedScope;
13715
+
13716
+ scope.$watch(watchExpr, function ngSwitchWatchAction(value) {
13717
+ if (selectedElement) {
13718
+ selectedScope.$destroy();
13719
+ selectedElement.remove();
13720
+ selectedElement = selectedScope = null;
13721
+ }
13722
+ if ((selectedTransclude = ctrl.cases['!' + value] || ctrl.cases['?'])) {
13723
+ scope.$eval(attr.change);
13724
+ selectedScope = scope.$new();
13725
+ selectedTransclude(selectedScope, function(caseElement) {
13726
+ selectedElement = caseElement;
13727
+ element.append(caseElement);
13728
+ });
13729
+ }
13730
+ });
13660
13731
  }
13661
13732
  });
13662
13733
 
13663
13734
  var ngSwitchWhenDirective = ngDirective({
13664
13735
  transclude: 'element',
13665
13736
  priority: 500,
13737
+ require: '^ngSwitch',
13666
13738
  compile: function(element, attrs, transclude) {
13667
- var cases = element.inheritedData(NG_SWITCH);
13668
- assertArg(cases);
13669
- cases['!' + attrs.ngSwitchWhen] = transclude;
13739
+ return function(scope, element, attr, ctrl) {
13740
+ ctrl.cases['!' + attrs.ngSwitchWhen] = transclude;
13741
+ };
13670
13742
  }
13671
13743
  });
13672
13744
 
13673
13745
  var ngSwitchDefaultDirective = ngDirective({
13674
13746
  transclude: 'element',
13675
13747
  priority: 500,
13748
+ require: '^ngSwitch',
13676
13749
  compile: function(element, attrs, transclude) {
13677
- var cases = element.inheritedData(NG_SWITCH);
13678
- assertArg(cases);
13679
- cases['?'] = transclude;
13750
+ return function(scope, element, attr, ctrl) {
13751
+ ctrl.cases['?'] = transclude;
13752
+ };
13680
13753
  }
13681
13754
  });
13682
13755
 
@@ -13765,7 +13838,7 @@ var ngTranscludeDirective = ngDirective({
13765
13838
  <hr />
13766
13839
 
13767
13840
  <pre>$location.path() = {{$location.path()}}</pre>
13768
- <pre>$route.current.template = {{$route.current.template}}</pre>
13841
+ <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>
13769
13842
  <pre>$route.current.params = {{$route.current.params}}</pre>
13770
13843
  <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>
13771
13844
  <pre>$routeParams = {{$routeParams}}</pre>
@@ -14211,7 +14284,7 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
14211
14284
  var lastView;
14212
14285
  ctrl.$render = function() {
14213
14286
  var items = new HashMap(ctrl.$viewValue);
14214
- forEach(selectElement.children(), function(option) {
14287
+ forEach(selectElement.find('option'), function(option) {
14215
14288
  option.selected = isDefined(items.get(option.value));
14216
14289
  });
14217
14290
  };
@@ -14228,7 +14301,7 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
14228
14301
  selectElement.bind('change', function() {
14229
14302
  scope.$apply(function() {
14230
14303
  var array = [];
14231
- forEach(selectElement.children(), function(option) {
14304
+ forEach(selectElement.find('option'), function(option) {
14232
14305
  if (option.selected) {
14233
14306
  array.push(option.value);
14234
14307
  }