angularjs-rails 1.0.3 → 1.0.4

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.
@@ -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
  }