angular-gem 1.1.2 → 1.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (29) hide show
  1. data/README.md +9 -2
  2. data/Rakefile +86 -19
  3. data/lib/angular-gem/version.rb +1 -1
  4. data/lib/generators/angular/resource_helpers.rb +13 -13
  5. data/test/dummy/log/test.log +1 -3
  6. data/test/dummy/tmp/cache/assets/{DF8/FD0/sprockets%2F87b01decd5c7fd3c6f174b8cba0d810f → D65/250/sprockets%2F54a960d46bb0b354e8bd46fa03f5e0e4} +0 -0
  7. data/test/dummy/tmp/cache/assets/{D73/C00/sprockets%2Fa3620dc4bbd0562669b546e9c58eede4 → D6A/FB0/sprockets%2F92721e9941b77adcfdfba3d060622de2} +0 -0
  8. data/test/dummy/tmp/cache/assets/E07/040/sprockets%2Ff55b8ce9d0f28ce36b768a1c7aeb2ef3 +0 -0
  9. data/test/test_helper.rb +3 -0
  10. data/vendor/assets/javascripts/1.0.5/angular-1.0.5.js +14733 -0
  11. data/vendor/assets/javascripts/1.0.5/angular-resource-1.0.5.js +445 -0
  12. data/vendor/assets/javascripts/1.0.5/angular-sanitize-1.0.5.js +535 -0
  13. data/{test/dummy/tmp/cache/assets/CF7/120/sprockets%2Fd6adf41113c67a57c4a1330845ba0d08 → vendor/assets/javascripts/1.1.2/angular-1.1.2.js} +0 -0
  14. data/vendor/assets/javascripts/1.1.2/angular-resource-1.1.2.js +472 -0
  15. data/vendor/assets/javascripts/1.1.2/angular-sanitize-1.1.2.js +556 -0
  16. data/{test/dummy/tmp/cache/assets/CD5/C60/sprockets%2F4348b099c4aadda10262e757261e0f81 → vendor/assets/javascripts/1.1.3/angular-1.1.3.js} +0 -0
  17. data/vendor/assets/javascripts/1.1.3/angular-resource-1.1.3.js +507 -0
  18. data/vendor/assets/javascripts/1.1.3/angular-sanitize-1.1.3.js +556 -0
  19. data/vendor/assets/javascripts/angular-resource-unstable.js +507 -0
  20. data/vendor/assets/javascripts/angular-resource.js +23 -50
  21. data/vendor/assets/javascripts/angular-sanitize-unstable.js +556 -0
  22. data/vendor/assets/javascripts/angular-sanitize.js +4 -25
  23. data/{test/dummy/tmp/cache/assets/CE3/300/sprockets%2Fc11999ba09d72e745355212e48bc72dd → vendor/assets/javascripts/angular-unstable.js} +0 -0
  24. data/vendor/assets/javascripts/angular.js +305 -454
  25. metadata +53 -21
  26. data/test/dummy/tmp/cache/assets/D71/060/sprockets%2Fc434a3f93ecb87049eb12e766005fede +0 -0
  27. data/test/dummy/tmp/cache/assets/D79/F40/sprockets%2F9088cfe323d1b81dd526e6a9e3ed358c +0 -0
  28. data/test/dummy/tmp/cache/assets/D9E/830/sprockets%2Fbb7eb0f50f1afed5705594e9d812b8d0 +0 -0
  29. data/test/dummy/tmp/cache/assets/DD4/250/sprockets%2Feaa70f0d0954a5edffe77c9ca1e93860 +0 -0
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.1.2
2
+ * @license AngularJS v1.0.5
3
3
  * (c) 2010-2012 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -129,7 +129,7 @@ var START_TAG_REGEXP = /^<\s*([\w:-]+)((?:\s+[\w:-]+(?:\s*=\s*(?:(?:"[^"]*")|(?:
129
129
  BEGING_END_TAGE_REGEXP = /^<\s*\//,
130
130
  COMMENT_REGEXP = /<!--(.*?)-->/g,
131
131
  CDATA_REGEXP = /<!\[CDATA\[(.*?)]]>/g,
132
- URI_REGEXP = /^((ftp|https?):\/\/|mailto:|tel:|#)/,
132
+ URI_REGEXP = /^((ftp|https?):\/\/|mailto:|#)/,
133
133
  NON_ALPHANUMERIC_REGEXP = /([^\#-~| |!])/g; // Match everything outside of normal chars and " (quote character)
134
134
 
135
135
 
@@ -432,7 +432,6 @@ angular.module('ngSanitize').directive('ngBindHtml', ['$sanitize', function($san
432
432
  * plain email address links.
433
433
  *
434
434
  * @param {string} text Input text.
435
- * @param {string} target Window (_blank|_self|_parent|_top) or named frame to open links in.
436
435
  * @returns {string} Html-linkified text.
437
436
  *
438
437
  * @usage
@@ -449,7 +448,6 @@ angular.module('ngSanitize').directive('ngBindHtml', ['$sanitize', function($san
449
448
  'mailto:us@somewhere.org,\n'+
450
449
  'another@somewhere.org,\n'+
451
450
  'and one more: ftp://127.0.0.1/.';
452
- $scope.snippetWithTarget = 'http://angularjs.org/';
453
451
  }
454
452
  </script>
455
453
  <div ng-controller="Ctrl">
@@ -469,15 +467,6 @@ angular.module('ngSanitize').directive('ngBindHtml', ['$sanitize', function($san
469
467
  <div ng-bind-html="snippet | linky"></div>
470
468
  </td>
471
469
  </tr>
472
- <tr id="linky-target">
473
- <td>linky target</td>
474
- <td>
475
- <pre>&lt;div ng-bind-html="snippetWithTarget | linky:'_blank'"&gt;<br>&lt;/div&gt;</pre>
476
- </td>
477
- <td>
478
- <div ng-bind-html="snippetWithTarget | linky:'_blank'"></div>
479
- </td>
480
- </tr>
481
470
  <tr id="escaped-html">
482
471
  <td>no filter</td>
483
472
  <td><pre>&lt;div ng-bind="snippet"&gt;<br>&lt;/div&gt;</pre></td>
@@ -510,11 +499,6 @@ angular.module('ngSanitize').directive('ngBindHtml', ['$sanitize', function($san
510
499
  toBe('new <a href="http://link">http://link</a>.');
511
500
  expect(using('#escaped-html').binding('snippet')).toBe('new http://link.');
512
501
  });
513
-
514
- it('should work with the target property', function() {
515
- expect(using('#linky-target').binding("snippetWithTarget | linky:'_blank'")).
516
- toBe('<a target="_blank" href="http://angularjs.org/">http://angularjs.org/</a>');
517
- });
518
502
  </doc:scenario>
519
503
  </doc:example>
520
504
  */
@@ -522,7 +506,7 @@ angular.module('ngSanitize').filter('linky', function() {
522
506
  var LINKY_URL_REGEXP = /((ftp|https?):\/\/|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s\.\;\,\(\)\{\}\<\>]/,
523
507
  MAILTO_REGEXP = /^mailto:/;
524
508
 
525
- return function(text, target) {
509
+ return function(text) {
526
510
  if (!text) return text;
527
511
  var match;
528
512
  var raw = text;
@@ -531,10 +515,6 @@ angular.module('ngSanitize').filter('linky', function() {
531
515
  var writer = htmlSanitizeWriter(html);
532
516
  var url;
533
517
  var i;
534
- var properties = {};
535
- if (angular.isDefined(target)) {
536
- properties.target = target;
537
- }
538
518
  while ((match = raw.match(LINKY_URL_REGEXP))) {
539
519
  // We can not end in these as they are sometimes found at the end of the sentence
540
520
  url = match[0];
@@ -542,8 +522,7 @@ angular.module('ngSanitize').filter('linky', function() {
542
522
  if (match[2] == match[3]) url = 'mailto:' + url;
543
523
  i = match.index;
544
524
  writer.chars(raw.substr(0, i));
545
- properties.href = url;
546
- writer.start('a', properties);
525
+ writer.start('a', {href:url});
547
526
  writer.chars(match[0].replace(MAILTO_REGEXP, ''));
548
527
  writer.end('a');
549
528
  raw = raw.substring(i + match[0].length);
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.1.2
2
+ * @license AngularJS v1.0.5
3
3
  * (c) 2010-2012 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -55,8 +55,7 @@ if ('i' !== 'I'.toLowerCase()) {
55
55
  function fromCharCode(code) {return String.fromCharCode(code);}
56
56
 
57
57
 
58
- var Error = window.Error,
59
- /** holds major version number for IE or NaN for real browsers */
58
+ var /** holds major version number for IE or NaN for real browsers */
60
59
  msie = int((/msie (\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]),
61
60
  jqLite, // delay binding since jQuery could be loaded after us.
62
61
  jQuery, // delay binding
@@ -97,6 +96,30 @@ var Error = window.Error,
97
96
  * @param {Object=} context Object to become context (`this`) for the iterator function.
98
97
  * @returns {Object|Array} Reference to `obj`.
99
98
  */
99
+
100
+
101
+ /**
102
+ * @private
103
+ * @param {*} obj
104
+ * @return {boolean} Returns true if `obj` is an array or array-like object (NodeList, Arguments, ...)
105
+ */
106
+ function isArrayLike(obj) {
107
+ if (!obj || (typeof obj.length !== 'number')) return false;
108
+
109
+ // We have on object which has length property. Should we treat it as array?
110
+ if (typeof obj.hasOwnProperty != 'function' &&
111
+ typeof obj.constructor != 'function') {
112
+ // This is here for IE8: it is a bogus object treat it as array;
113
+ return true;
114
+ } else {
115
+ return obj instanceof JQLite || // JQLite
116
+ (jQuery && obj instanceof jQuery) || // jQuery
117
+ toString.call(obj) !== '[object Object]' || // some browser native object
118
+ typeof obj.callee === 'function'; // arguments (on IE8 looks like regular obj)
119
+ }
120
+ }
121
+
122
+
100
123
  function forEach(obj, iterator, context) {
101
124
  var key;
102
125
  if (obj) {
@@ -108,7 +131,7 @@ function forEach(obj, iterator, context) {
108
131
  }
109
132
  } else if (obj.forEach && obj.forEach !== forEach) {
110
133
  obj.forEach(iterator, context);
111
- } else if (isObject(obj) && isNumber(obj.length)) {
134
+ } else if (isArrayLike(obj)) {
112
135
  for (key = 0; key < obj.length; key++)
113
136
  iterator.call(context, obj[key], key);
114
137
  } else {
@@ -153,7 +176,7 @@ function reverseParams(iteratorFn) {
153
176
  /**
154
177
  * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric
155
178
  * characters such as '012ABC'. The reason why we are not using simply a number counter is that
156
- * the number string gets longer over time, and it can also overflow, where as the the nextId
179
+ * the number string gets longer over time, and it can also overflow, where as the nextId
157
180
  * will grow much slower, it is a string, and it will never overflow.
158
181
  *
159
182
  * @returns an unique alpha-numeric string
@@ -549,9 +572,7 @@ function copy(source, destination){
549
572
  } else {
550
573
  if (source === destination) throw Error("Can't copy equivalent objects or arrays");
551
574
  if (isArray(source)) {
552
- while(destination.length) {
553
- destination.pop();
554
- }
575
+ destination.length = 0;
555
576
  for ( var i = 0; i < source.length; i++) {
556
577
  destination.push(copy(source[i]));
557
578
  }
@@ -762,9 +783,18 @@ function startingTag(element) {
762
783
  // are not allowed to have children. So we just ignore it.
763
784
  element.html('');
764
785
  } catch(e) {}
765
- return jqLite('<div>').append(element).html().
766
- match(/^(<[^>]+>)/)[1].
767
- replace(/^<([\w\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });
786
+ // As Per DOM Standards
787
+ var TEXT_NODE = 3;
788
+ var elemHtml = jqLite('<div>').append(element).html();
789
+ try {
790
+ return element[0].nodeType === TEXT_NODE ? lowercase(elemHtml) :
791
+ elemHtml.
792
+ match(/^(<[^>]+>)/)[1].
793
+ replace(/^<([\w\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });
794
+ } catch(e) {
795
+ return lowercase(elemHtml);
796
+ }
797
+
768
798
  }
769
799
 
770
800
 
@@ -848,7 +878,7 @@ function encodeUriQuery(val, pctEncodeSpaces) {
848
878
  * Use this directive to auto-bootstrap on application. Only
849
879
  * one directive can be used per HTML document. The directive
850
880
  * designates the root of the application and is typically placed
851
- * ot the root of the page.
881
+ * at the root of the page.
852
882
  *
853
883
  * In the example below if the `ngApp` directive would not be placed
854
884
  * on the `html` element then the document would not be compiled
@@ -1249,11 +1279,11 @@ function setupModuleLoader(window) {
1249
1279
  * - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat".
1250
1280
  */
1251
1281
  var version = {
1252
- full: '1.1.2', // all of these placeholder strings will be replaced by rake's
1282
+ full: '1.0.5', // all of these placeholder strings will be replaced by rake's
1253
1283
  major: 1, // compile task
1254
- minor: 1,
1255
- dot: 2,
1256
- codeName: 'tofu-animation'
1284
+ minor: 0,
1285
+ dot: 5,
1286
+ codeName: 'flatulent-propulsion'
1257
1287
  };
1258
1288
 
1259
1289
 
@@ -1719,11 +1749,11 @@ var JQLitePrototype = JQLite.prototype = {
1719
1749
  // value on get.
1720
1750
  //////////////////////////////////////////
1721
1751
  var BOOLEAN_ATTR = {};
1722
- forEach('multiple,selected,checked,disabled,readOnly,required,open'.split(','), function(value) {
1752
+ forEach('multiple,selected,checked,disabled,readOnly,required'.split(','), function(value) {
1723
1753
  BOOLEAN_ATTR[lowercase(value)] = value;
1724
1754
  });
1725
1755
  var BOOLEAN_ELEMENTS = {};
1726
- forEach('input,select,option,textarea,button,form,details'.split(','), function(value) {
1756
+ forEach('input,select,option,textarea,button,form'.split(','), function(value) {
1727
1757
  BOOLEAN_ELEMENTS[uppercase(value)] = true;
1728
1758
  });
1729
1759
 
@@ -2025,9 +2055,8 @@ forEach({
2025
2055
 
2026
2056
  append: function(element, node) {
2027
2057
  forEach(new JQLite(node), function(child){
2028
- if (element.nodeType === 1 || element.nodeType === 11) {
2058
+ if (element.nodeType === 1)
2029
2059
  element.appendChild(child);
2030
- }
2031
2060
  });
2032
2061
  },
2033
2062
 
@@ -2431,7 +2460,7 @@ function annotate(fn) {
2431
2460
  * This method does not work with code minfication / obfuscation. For this reason the following annotation strategies
2432
2461
  * are supported.
2433
2462
  *
2434
- * # The `$injector` property
2463
+ * # The `$inject` property
2435
2464
  *
2436
2465
  * If a function has an `$inject` property and its value is an array of strings, then the strings represent names of
2437
2466
  * services to be injected into the function.
@@ -2649,10 +2678,9 @@ function createInjector(modulesToLoad) {
2649
2678
  decorator: decorator
2650
2679
  }
2651
2680
  },
2652
- providerInjector = (providerCache.$injector =
2653
- createInternalInjector(providerCache, function() {
2654
- throw Error("Unknown provider: " + path.join(' <- '));
2655
- })),
2681
+ providerInjector = createInternalInjector(providerCache, function() {
2682
+ throw Error("Unknown provider: " + path.join(' <- '));
2683
+ }),
2656
2684
  instanceCache = {},
2657
2685
  instanceInjector = (instanceCache.$injector =
2658
2686
  createInternalInjector(instanceCache, function(servicename) {
@@ -2729,7 +2757,9 @@ function createInjector(modulesToLoad) {
2729
2757
  try {
2730
2758
  for(var invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {
2731
2759
  var invokeArgs = invokeQueue[i],
2732
- provider = providerInjector.get(invokeArgs[0]);
2760
+ provider = invokeArgs[0] == '$injector'
2761
+ ? providerInjector
2762
+ : providerInjector.get(invokeArgs[0]);
2733
2763
 
2734
2764
  provider[invokeArgs[1]].apply(provider, invokeArgs[2]);
2735
2765
  }
@@ -3144,7 +3174,7 @@ function Browser(window, document, $log, $sniffer) {
3144
3174
  */
3145
3175
  self.baseHref = function() {
3146
3176
  var href = baseElement.attr('href');
3147
- return href ? href.replace(/^https?\:\/\/[^\/]*/, '') : href;
3177
+ return href ? href.replace(/^https?\:\/\/[^\/]*/, '') : '';
3148
3178
  };
3149
3179
 
3150
3180
  //////////////////////////////////////////////////////////////
@@ -3284,7 +3314,7 @@ function $BrowserProvider(){
3284
3314
  * @returns {object} Newly created cache object with the following set of methods:
3285
3315
  *
3286
3316
  * - `{object}` `info()` — Returns id, size, and options of cache.
3287
- * - `{{*}}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache and returns it.
3317
+ * - `{void}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache.
3288
3318
  * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.
3289
3319
  * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.
3290
3320
  * - `{void}` `removeAll()` — Removes all cached values.
@@ -3323,8 +3353,6 @@ function $CacheFactoryProvider() {
3323
3353
  if (size > capacity) {
3324
3354
  this.remove(staleEnd.key);
3325
3355
  }
3326
-
3327
- return value;
3328
3356
  },
3329
3357
 
3330
3358
 
@@ -3596,7 +3624,8 @@ function $CompileProvider($provide) {
3596
3624
  Suffix = 'Directive',
3597
3625
  COMMENT_DIRECTIVE_REGEXP = /^\s*directive\:\s*([\d\w\-_]+)\s+(.*)$/,
3598
3626
  CLASS_DIRECTIVE_REGEXP = /(([\d\w\-_]+)(?:\:([^;]+))?;?)/,
3599
- MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ';
3627
+ MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ',
3628
+ urlSanitizationWhitelist = /^\s*(https?|ftp|mailto):/;
3600
3629
 
3601
3630
 
3602
3631
  /**
@@ -3650,11 +3679,41 @@ function $CompileProvider($provide) {
3650
3679
  };
3651
3680
 
3652
3681
 
3682
+ /**
3683
+ * @ngdoc function
3684
+ * @name ng.$compileProvider#urlSanitizationWhitelist
3685
+ * @methodOf ng.$compileProvider
3686
+ * @function
3687
+ *
3688
+ * @description
3689
+ * Retrieves or overrides the default regular expression that is used for whitelisting of safe
3690
+ * urls during a[href] sanitization.
3691
+ *
3692
+ * The sanitization is a security measure aimed at prevent XSS attacks via html links.
3693
+ *
3694
+ * Any url about to be assigned to a[href] via data-binding is first normalized and turned into an
3695
+ * absolute url. Afterwards the url is matched against the `urlSanitizationWhitelist` regular
3696
+ * expression. If a match is found the original url is written into the dom. Otherwise the
3697
+ * absolute url is prefixed with `'unsafe:'` string and only then it is written into the DOM.
3698
+ *
3699
+ * @param {RegExp=} regexp New regexp to whitelist urls with.
3700
+ * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for
3701
+ * chaining otherwise.
3702
+ */
3703
+ this.urlSanitizationWhitelist = function(regexp) {
3704
+ if (isDefined(regexp)) {
3705
+ urlSanitizationWhitelist = regexp;
3706
+ return this;
3707
+ }
3708
+ return urlSanitizationWhitelist;
3709
+ };
3710
+
3711
+
3653
3712
  this.$get = [
3654
3713
  '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',
3655
- '$controller', '$rootScope',
3714
+ '$controller', '$rootScope', '$document',
3656
3715
  function($injector, $interpolate, $exceptionHandler, $http, $templateCache, $parse,
3657
- $controller, $rootScope) {
3716
+ $controller, $rootScope, $document) {
3658
3717
 
3659
3718
  var Attributes = function(element, attr) {
3660
3719
  this.$$element = element;
@@ -3676,7 +3735,8 @@ function $CompileProvider($provide) {
3676
3735
  */
3677
3736
  $set: function(key, value, writeAttr, attrName) {
3678
3737
  var booleanKey = getBooleanAttrName(this.$$element[0], key),
3679
- $$observers = this.$$observers;
3738
+ $$observers = this.$$observers,
3739
+ normalizedVal;
3680
3740
 
3681
3741
  if (booleanKey) {
3682
3742
  this.$$element.prop(key, value);
@@ -3695,6 +3755,19 @@ function $CompileProvider($provide) {
3695
3755
  }
3696
3756
  }
3697
3757
 
3758
+
3759
+ // sanitize a[href] values
3760
+ if (nodeName_(this.$$element[0]) === 'A' && key === 'href') {
3761
+ urlSanitizationNode.setAttribute('href', value);
3762
+
3763
+ // href property always returns normalized absolute url, so we can match against that
3764
+ normalizedVal = urlSanitizationNode.href;
3765
+ if (!normalizedVal.match(urlSanitizationWhitelist)) {
3766
+ this[key] = value = 'unsafe:' + normalizedVal;
3767
+ }
3768
+ }
3769
+
3770
+
3698
3771
  if (writeAttr !== false) {
3699
3772
  if (value === null || value === undefined) {
3700
3773
  this.$$element.removeAttr(attrName);
@@ -3738,7 +3811,8 @@ function $CompileProvider($provide) {
3738
3811
  }
3739
3812
  };
3740
3813
 
3741
- var startSymbol = $interpolate.startSymbol(),
3814
+ var urlSanitizationNode = $document[0].createElement('a'),
3815
+ startSymbol = $interpolate.startSymbol(),
3742
3816
  endSymbol = $interpolate.endSymbol(),
3743
3817
  denormalizeTemplate = (startSymbol == '{{' || endSymbol == '}}')
3744
3818
  ? identity
@@ -3771,7 +3845,14 @@ function $CompileProvider($provide) {
3771
3845
  var $linkNode = cloneConnectFn
3772
3846
  ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!
3773
3847
  : $compileNodes;
3774
- $linkNode.data('$scope', scope);
3848
+
3849
+ // Attach scope only to non-text nodes.
3850
+ for(var i = 0, ii = $linkNode.length; i<ii; i++) {
3851
+ var node = $linkNode[i];
3852
+ if (node.nodeType == 1 /* element */ || node.nodeType == 9 /* document */) {
3853
+ $linkNode.eq(i).data('$scope', scope);
3854
+ }
3855
+ }
3775
3856
  safeAddClass($linkNode, 'ng-scope');
3776
3857
  if (cloneConnectFn) cloneConnectFn($linkNode, scope);
3777
3858
  if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode);
@@ -3861,6 +3942,7 @@ function $CompileProvider($provide) {
3861
3942
  (function(transcludeFn) {
3862
3943
  return function(cloneFn) {
3863
3944
  var transcludeScope = scope.$new();
3945
+ transcludeScope.$$transcluded = true;
3864
3946
 
3865
3947
  return transcludeFn(transcludeScope, cloneFn).
3866
3948
  bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));
@@ -4166,6 +4248,8 @@ function $CompileProvider($provide) {
4166
4248
  lastValue,
4167
4249
  parentGet, parentSet;
4168
4250
 
4251
+ scope.$$isolateBindings[scopeName] = mode + attrName;
4252
+
4169
4253
  switch (mode) {
4170
4254
 
4171
4255
  case '@': {
@@ -4376,7 +4460,7 @@ function $CompileProvider($provide) {
4376
4460
  }
4377
4461
 
4378
4462
  directives.unshift(derivedSyncDirective);
4379
- afterTemplateNodeLinkFn = applyDirectivesToNode(directives, $compileNode, tAttrs, childTranscludeFn);
4463
+ afterTemplateNodeLinkFn = applyDirectivesToNode(directives, compileNode, tAttrs, childTranscludeFn);
4380
4464
  afterTemplateChildLinkFn = compileNodes($compileNode.contents(), childTranscludeFn);
4381
4465
 
4382
4466
 
@@ -4456,10 +4540,10 @@ function $CompileProvider($provide) {
4456
4540
  function addAttrInterpolateDirective(node, directives, value, name) {
4457
4541
  var interpolateFn = $interpolate(value, true);
4458
4542
 
4459
-
4460
4543
  // no interpolation found -> ignore
4461
4544
  if (!interpolateFn) return;
4462
4545
 
4546
+
4463
4547
  directives.push({
4464
4548
  priority: 100,
4465
4549
  compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) {
@@ -4754,7 +4838,7 @@ function $InterpolateProvider() {
4754
4838
  };
4755
4839
 
4756
4840
 
4757
- this.$get = ['$parse', '$exceptionHandler', function($parse, $exceptionHandler) {
4841
+ this.$get = ['$parse', function($parse) {
4758
4842
  var startSymbolLength = startSymbol.length,
4759
4843
  endSymbolLength = endSymbol.length;
4760
4844
 
@@ -4826,24 +4910,18 @@ function $InterpolateProvider() {
4826
4910
  if (!mustHaveExpression || hasInterpolation) {
4827
4911
  concat.length = length;
4828
4912
  fn = function(context) {
4829
- try {
4830
- for(var i = 0, ii = length, part; i<ii; i++) {
4831
- if (typeof (part = parts[i]) == 'function') {
4832
- part = part(context);
4833
- if (part == null || part == undefined) {
4834
- part = '';
4835
- } else if (typeof part != 'string') {
4836
- part = toJson(part);
4837
- }
4913
+ for(var i = 0, ii = length, part; i<ii; i++) {
4914
+ if (typeof (part = parts[i]) == 'function') {
4915
+ part = part(context);
4916
+ if (part == null || part == undefined) {
4917
+ part = '';
4918
+ } else if (typeof part != 'string') {
4919
+ part = toJson(part);
4838
4920
  }
4839
- concat[i] = part;
4840
4921
  }
4841
- return concat.join('');
4842
- }
4843
- catch(err) {
4844
- var newErr = new Error('Error while interpolating: ' + text + '\n' + err.toString());
4845
- $exceptionHandler(newErr);
4922
+ concat[i] = part;
4846
4923
  }
4924
+ return concat.join('');
4847
4925
  };
4848
4926
  fn.exp = text;
4849
4927
  fn.parts = parts;
@@ -5539,33 +5617,7 @@ function $LocationProvider(){
5539
5617
  </example>
5540
5618
  */
5541
5619
 
5542
- /**
5543
- * @ngdoc object
5544
- * @name ng.$logProvider
5545
- * @description
5546
- * Use the `$logProvider` to configure how the application logs messages
5547
- */
5548
5620
  function $LogProvider(){
5549
- var debug = true,
5550
- self = this;
5551
-
5552
- /**
5553
- * @ngdoc property
5554
- * @name ng.$logProvider#debugEnabled
5555
- * @methodOf ng.$logProvider
5556
- * @description
5557
- * @param {string=} flag enable or disable debug level messages
5558
- * @returns {*} current value if used as getter or itself (chaining) if used as setter
5559
- */
5560
- this.debugEnabled = function(flag) {
5561
- if (isDefined(flag)) {
5562
- debug = flag;
5563
- return this;
5564
- } else {
5565
- return debug;
5566
- }
5567
- };
5568
-
5569
5621
  this.$get = ['$window', function($window){
5570
5622
  return {
5571
5623
  /**
@@ -5606,25 +5658,7 @@ function $LogProvider(){
5606
5658
  * @description
5607
5659
  * Write an error message
5608
5660
  */
5609
- error: consoleLog('error'),
5610
-
5611
- /**
5612
- * @ngdoc method
5613
- * @name ng.$log#debug
5614
- * @methodOf ng.$log
5615
- *
5616
- * @description
5617
- * Write a debug message
5618
- */
5619
- debug: (function () {
5620
- var fn = consoleLog('debug');
5621
-
5622
- return function() {
5623
- if (debug) {
5624
- fn.apply(self, arguments);
5625
- }
5626
- }
5627
- }())
5661
+ error: consoleLog('error')
5628
5662
  };
5629
5663
 
5630
5664
  function formatError(arg) {
@@ -5683,8 +5717,6 @@ var OPERATORS = {
5683
5717
  '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},
5684
5718
  '^':function(self, locals, a,b){return a(self, locals)^b(self, locals);},
5685
5719
  '=':noop,
5686
- '===':function(self, locals, a, b){return a(self, locals)===b(self, locals);},
5687
- '!==':function(self, locals, a, b){return a(self, locals)!==b(self, locals);},
5688
5720
  '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);},
5689
5721
  '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);},
5690
5722
  '<':function(self, locals, a,b){return a(self, locals)<b(self, locals);},
@@ -5735,14 +5767,9 @@ function lex(text, csp){
5735
5767
  continue;
5736
5768
  } else {
5737
5769
  var ch2 = ch + peek(),
5738
- ch3 = ch2 + peek(2),
5739
5770
  fn = OPERATORS[ch],
5740
- fn2 = OPERATORS[ch2],
5741
- fn3 = OPERATORS[ch3];
5742
- if (fn3) {
5743
- tokens.push({index:index, text:ch3, fn:fn3});
5744
- index += 3;
5745
- } else if (fn2) {
5771
+ fn2 = OPERATORS[ch2];
5772
+ if (fn2) {
5746
5773
  tokens.push({index:index, text:ch2, fn:fn2});
5747
5774
  index += 2;
5748
5775
  } else if (fn) {
@@ -5764,9 +5791,8 @@ function lex(text, csp){
5764
5791
  return chars.indexOf(lastCh) != -1;
5765
5792
  }
5766
5793
 
5767
- function peek(i) {
5768
- var num = i || 1;
5769
- return index + num < text.length ? text.charAt(index + num) : false;
5794
+ function peek() {
5795
+ return index + 1 < text.length ? text.charAt(index + 1) : false;
5770
5796
  }
5771
5797
  function isNumber(ch) {
5772
5798
  return '0' <= ch && ch <= '9';
@@ -6127,7 +6153,7 @@ function parser(text, json, $filter, csp){
6127
6153
  function equality() {
6128
6154
  var left = relational();
6129
6155
  var token;
6130
- if ((token = expect('==','!=','===','!=='))) {
6156
+ if ((token = expect('==','!='))) {
6131
6157
  left = binaryFn(left, token.fn, equality());
6132
6158
  }
6133
6159
  return left;
@@ -6511,9 +6537,10 @@ function getterFn(path, csp) {
6511
6537
  * @param {string} expression String expression to compile.
6512
6538
  * @returns {function(context, locals)} a function which represents the compiled expression:
6513
6539
  *
6514
- * * `context`: an object against which any expressions embedded in the strings are evaluated
6515
- * against (Topically a scope object).
6516
- * * `locals`: local variables context object, useful for overriding values in `context`.
6540
+ * * `context` – `{object}` – an object against which any expressions embedded in the strings
6541
+ * are evaluated against (tipically a scope object).
6542
+ * * `locals` – `{object=}` – local variables context object, useful for overriding values in
6543
+ * `context`.
6517
6544
  *
6518
6545
  * The return function also has an `assign` property, if the expression is assignable, which
6519
6546
  * allows one to set values to expressions.
@@ -6549,7 +6576,7 @@ function $ParseProvider() {
6549
6576
  * interface for interacting with an object that represents the result of an action that is
6550
6577
  * performed asynchronously, and may or may not be finished at any given point in time.
6551
6578
  *
6552
- * From the perspective of dealing with error handling, deferred and promise apis are to
6579
+ * From the perspective of dealing with error handling, deferred and promise APIs are to
6553
6580
  * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.
6554
6581
  *
6555
6582
  * <pre>
@@ -6584,7 +6611,7 @@ function $ParseProvider() {
6584
6611
  *
6585
6612
  * At first it might not be obvious why this extra complexity is worth the trouble. The payoff
6586
6613
  * comes in the way of
6587
- * [guarantees that promise and deferred apis make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md).
6614
+ * [guarantees that promise and deferred APIs make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md).
6588
6615
  *
6589
6616
  * Additionally the promise api allows for composition that is very hard to do with the
6590
6617
  * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.
@@ -6596,7 +6623,7 @@ function $ParseProvider() {
6596
6623
  *
6597
6624
  * A new instance of deferred is constructed by calling `$q.defer()`.
6598
6625
  *
6599
- * The purpose of the deferred object is to expose the associated Promise instance as well as apis
6626
+ * The purpose of the deferred object is to expose the associated Promise instance as well as APIs
6600
6627
  * that can be used for signaling the successful or unsuccessful completion of the task.
6601
6628
  *
6602
6629
  * **Methods**
@@ -6639,7 +6666,7 @@ function $ParseProvider() {
6639
6666
  * return result + 1;
6640
6667
  * });
6641
6668
  *
6642
- * // promiseB will be resolved immediately after promiseA is resolved and it's value will be
6669
+ * // promiseB will be resolved immediately after promiseA is resolved and its value will be
6643
6670
  * // the result of promiseA incremented by 1
6644
6671
  * </pre>
6645
6672
  *
@@ -6664,7 +6691,7 @@ function $ParseProvider() {
6664
6691
  * # Testing
6665
6692
  *
6666
6693
  * <pre>
6667
- * it('should simulate promise', inject(function($q, $rootSCope) {
6694
+ * it('should simulate promise', inject(function($q, $rootScope) {
6668
6695
  * var deferred = $q.defer();
6669
6696
  * var promise = deferred.promise;
6670
6697
  * var resolvedValue;
@@ -6673,7 +6700,7 @@ function $ParseProvider() {
6673
6700
  * expect(resolvedValue).toBeUndefined();
6674
6701
  *
6675
6702
  * // Simulate resolving of promise
6676
- * defered.resolve(123);
6703
+ * deferred.resolve(123);
6677
6704
  * // Note that the 'then' function does not get called synchronously.
6678
6705
  * // This is because we want the promise API to always be async, whether or not
6679
6706
  * // it got called synchronously or asynchronously.
@@ -6849,12 +6876,12 @@ function qFactory(nextTick, exceptionHandler) {
6849
6876
  * @methodOf ng.$q
6850
6877
  * @description
6851
6878
  * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.
6852
- * This is useful when you are dealing with on object that might or might not be a promise, or if
6879
+ * This is useful when you are dealing with an object that might or might not be a promise, or if
6853
6880
  * the promise comes from a source that can't be trusted.
6854
6881
  *
6855
6882
  * @param {*} value Value or a promise
6856
6883
  * @returns {Promise} Returns a single promise that will be resolved with an array of values,
6857
- * each value coresponding to the promise at the same index in the `promises` array. If any of
6884
+ * each value corresponding to the promise at the same index in the `promises` array. If any of
6858
6885
  * the promises is resolved with a rejection, this resulting promise will be resolved with the
6859
6886
  * same rejection.
6860
6887
  */
@@ -6916,7 +6943,7 @@ function qFactory(nextTick, exceptionHandler) {
6916
6943
  *
6917
6944
  * @param {Array.<Promise>} promises An array of promises.
6918
6945
  * @returns {Promise} Returns a single promise that will be resolved with an array of values,
6919
- * each value coresponding to the promise at the same index in the `promises` array. If any of
6946
+ * each value corresponding to the promise at the same index in the `promises` array. If any of
6920
6947
  * the promises is resolved with a rejection, this resulting promise will be resolved with the
6921
6948
  * same rejection.
6922
6949
  */
@@ -6985,24 +7012,12 @@ function $RouteProvider(){
6985
7012
  * - `controller` – `{(string|function()=}` – Controller fn that should be associated with newly
6986
7013
  * created scope or the name of a {@link angular.Module#controller registered controller}
6987
7014
  * if passed as a string.
6988
- * - `template` – `{string=|function()=}` – html template as a string or function that returns
6989
- * an html template as a string which should be used by {@link ng.directive:ngView ngView} or
7015
+ * - `template` – `{string=}` – html template as a string that should be used by
7016
+ * {@link ng.directive:ngView ngView} or
6990
7017
  * {@link ng.directive:ngInclude ngInclude} directives.
6991
- * This property takes precedence over `templateUrl`.
6992
- *
6993
- * If `template` is a function, it will be called with the following parameters:
6994
- *
6995
- * - `{Array.<Object>}` - route parameters extracted from the current
6996
- * `$location.path()` by applying the current route
6997
- *
6998
- * - `templateUrl` – `{string=|function()=}` – path or function that returns a path to an html
6999
- * template that should be used by {@link ng.directive:ngView ngView}.
7000
- *
7001
- * If `templateUrl` is a function, it will be called with the following parameters:
7002
- *
7003
- * - `{Array.<Object>}` - route parameters extracted from the current
7004
- * `$location.path()` by applying the current route
7005
- *
7018
+ * this property takes precedence over `templateUrl`.
7019
+ * - `templateUrl` – `{string=}` – path to an html template that should be used by
7020
+ * {@link ng.directive:ngView ngView}.
7006
7021
  * - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should
7007
7022
  * be injected into the controller. If any of these dependencies are promises, they will be
7008
7023
  * resolved and converted to a value before the controller is instantiated and the
@@ -7357,18 +7372,9 @@ function $RouteProvider(){
7357
7372
  values.push(isString(value) ? $injector.get(value) : $injector.invoke(value));
7358
7373
  });
7359
7374
  if (isDefined(template = next.template)) {
7360
- if (isFunction(template)) {
7361
- template = template(next.params);
7362
- }
7363
7375
  } else if (isDefined(template = next.templateUrl)) {
7364
- if (isFunction(template)) {
7365
- template = template(next.params);
7366
- }
7367
- if (isDefined(template)) {
7368
- next.loadedTemplateUrl = template;
7369
- template = $http.get(template, {cache: $templateCache}).
7370
- then(function(response) { return response.data; });
7371
- }
7376
+ template = $http.get(template, {cache: $templateCache}).
7377
+ then(function(response) { return response.data; });
7372
7378
  }
7373
7379
  if (isDefined(template)) {
7374
7380
  keys.push('$template');
@@ -7606,6 +7612,7 @@ function $RootScopeProvider(){
7606
7612
  this.$$destroyed = false;
7607
7613
  this.$$asyncQueue = [];
7608
7614
  this.$$listeners = {};
7615
+ this.$$isolateBindings = {};
7609
7616
  }
7610
7617
 
7611
7618
  /**
@@ -7665,6 +7672,7 @@ function $RootScopeProvider(){
7665
7672
  child['this'] = child;
7666
7673
  child.$$listeners = {};
7667
7674
  child.$parent = this;
7675
+ child.$$asyncQueue = [];
7668
7676
  child.$$watchers = child.$$nextSibling = child.$$childHead = child.$$childTail = null;
7669
7677
  child.$$prevSibling = this.$$childTail;
7670
7678
  if (this.$$childHead) {
@@ -7831,7 +7839,7 @@ function $RootScopeProvider(){
7831
7839
  $digest: function() {
7832
7840
  var watch, value, last,
7833
7841
  watchers,
7834
- asyncQueue = this.$$asyncQueue,
7842
+ asyncQueue,
7835
7843
  length,
7836
7844
  dirty, ttl = TTL,
7837
7845
  next, current, target = this,
@@ -7840,19 +7848,18 @@ function $RootScopeProvider(){
7840
7848
 
7841
7849
  beginPhase('$digest');
7842
7850
 
7843
- do { // "while dirty" loop
7851
+ do {
7844
7852
  dirty = false;
7845
7853
  current = target;
7846
-
7847
- while(asyncQueue.length) {
7848
- try {
7849
- current.$eval(asyncQueue.shift());
7850
- } catch (e) {
7851
- $exceptionHandler(e);
7854
+ do {
7855
+ asyncQueue = current.$$asyncQueue;
7856
+ while(asyncQueue.length) {
7857
+ try {
7858
+ current.$eval(asyncQueue.shift());
7859
+ } catch (e) {
7860
+ $exceptionHandler(e);
7861
+ }
7852
7862
  }
7853
- }
7854
-
7855
- do { // "traverse the scopes" loop
7856
7863
  if ((watchers = current.$$watchers)) {
7857
7864
  // process our watches
7858
7865
  length = watchers.length;
@@ -8087,10 +8094,6 @@ function $RootScopeProvider(){
8087
8094
  * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for discussion of
8088
8095
  * event life cycle.
8089
8096
  *
8090
- * @param {string} name Event name to listen on.
8091
- * @param {function(event)} listener Function to call when the event is emitted.
8092
- * @returns {function()} Returns a deregistration function for this listener.
8093
- *
8094
8097
  * The event listener function format is: `function(event, args...)`. The `event` object
8095
8098
  * passed into the listener has the following attributes:
8096
8099
  *
@@ -8101,6 +8104,10 @@ function $RootScopeProvider(){
8101
8104
  * propagation (available only for events that were `$emit`-ed).
8102
8105
  * - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag to true.
8103
8106
  * - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.
8107
+ *
8108
+ * @param {string} name Event name to listen on.
8109
+ * @param {function(event, args...)} listener Function to call when the event is emitted.
8110
+ * @returns {function()} Returns a deregistration function for this listener.
8104
8111
  */
8105
8112
  $on: function(name, listener) {
8106
8113
  var namedListeners = this.$$listeners[name];
@@ -8278,7 +8285,7 @@ function $RootScopeProvider(){
8278
8285
 
8279
8286
  /**
8280
8287
  * function used as an initial value for watchers.
8281
- * because it's uniqueue we can easily tell it apart from other values
8288
+ * because it's unique we can easily tell it apart from other values
8282
8289
  */
8283
8290
  function initWatchVal() {}
8284
8291
  }];
@@ -8289,7 +8296,6 @@ function $RootScopeProvider(){
8289
8296
  *
8290
8297
  * @name ng.$sniffer
8291
8298
  * @requires $window
8292
- * @requires $document
8293
8299
  *
8294
8300
  * @property {boolean} history Does the browser support html5 history api ?
8295
8301
  * @property {boolean} hashchange Does the browser support hashchange event ?
@@ -8298,10 +8304,9 @@ function $RootScopeProvider(){
8298
8304
  * This is very simple implementation of testing browser's features.
8299
8305
  */
8300
8306
  function $SnifferProvider() {
8301
- this.$get = ['$window', '$document', function($window, $document) {
8307
+ this.$get = ['$window', function($window) {
8302
8308
  var eventSupport = {},
8303
- android = int((/android (\d+)/.exec(lowercase($window.navigator.userAgent)) || [])[1]),
8304
- document = $document[0];
8309
+ android = int((/android (\d+)/.exec(lowercase($window.navigator.userAgent)) || [])[1]);
8305
8310
 
8306
8311
  return {
8307
8312
  // Android has history.pushState, but it does not update location correctly
@@ -8311,7 +8316,7 @@ function $SnifferProvider() {
8311
8316
  history: !!($window.history && $window.history.pushState && !(android < 4)),
8312
8317
  hashchange: 'onhashchange' in $window &&
8313
8318
  // IE8 compatible mode lies
8314
- (!document.documentMode || document.documentMode > 7),
8319
+ (!$window.document.documentMode || $window.document.documentMode > 7),
8315
8320
  hasEvent: function(event) {
8316
8321
  // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have
8317
8322
  // it. In particular the event is not fired when backspace or delete key are pressed or
@@ -8319,13 +8324,14 @@ function $SnifferProvider() {
8319
8324
  if (event == 'input' && msie == 9) return false;
8320
8325
 
8321
8326
  if (isUndefined(eventSupport[event])) {
8322
- var divElm = document.createElement('div');
8327
+ var divElm = $window.document.createElement('div');
8323
8328
  eventSupport[event] = 'on' + event in divElm;
8324
8329
  }
8325
8330
 
8326
8331
  return eventSupport[event];
8327
8332
  },
8328
- csp: document.securityPolicy ? document.securityPolicy.isActive : false
8333
+ // TODO(i): currently there is no way to feature detect CSP without triggering alerts
8334
+ csp: false
8329
8335
  };
8330
8336
  }];
8331
8337
  }
@@ -8386,43 +8392,6 @@ function parseHeaders(headers) {
8386
8392
  }
8387
8393
 
8388
8394
 
8389
- var IS_SAME_DOMAIN_URL_MATCH = /^(([^:]+):)?\/\/(\w+:{0,1}\w*@)?([\w\.-]*)?(:([0-9]+))?(.*)$/;
8390
-
8391
-
8392
- /**
8393
- * Parse a request and location URL and determine whether this is a same-domain request.
8394
- *
8395
- * @param {string} requestUrl The url of the request.
8396
- * @param {string} locationUrl The current browser location url.
8397
- * @returns {boolean} Whether the request is for the same domain.
8398
- */
8399
- function isSameDomain(requestUrl, locationUrl) {
8400
- var match = IS_SAME_DOMAIN_URL_MATCH.exec(requestUrl);
8401
- // if requestUrl is relative, the regex does not match.
8402
- if (match == null) return true;
8403
-
8404
- var domain1 = {
8405
- protocol: match[2],
8406
- host: match[4],
8407
- port: int(match[6]) || DEFAULT_PORTS[match[2]] || null,
8408
- // IE8 sets unmatched groups to '' instead of undefined.
8409
- relativeProtocol: match[2] === undefined || match[2] === ''
8410
- };
8411
-
8412
- match = URL_MATCH.exec(locationUrl);
8413
- var domain2 = {
8414
- protocol: match[1],
8415
- host: match[3],
8416
- port: int(match[5]) || DEFAULT_PORTS[match[1]] || null
8417
- };
8418
-
8419
- return (domain1.protocol == domain2.protocol || domain1.relativeProtocol) &&
8420
- domain1.host == domain2.host &&
8421
- (domain1.port == domain2.port || (domain1.relativeProtocol &&
8422
- domain2.port == DEFAULT_PORTS[domain2.protocol]));
8423
- }
8424
-
8425
-
8426
8395
  /**
8427
8396
  * Returns a function that provides access to parsed headers.
8428
8397
  *
@@ -8482,7 +8451,7 @@ function $HttpProvider() {
8482
8451
  JSON_END = /[\}\]]\s*$/,
8483
8452
  PROTECTION_PREFIX = /^\)\]\}',?\n/;
8484
8453
 
8485
- var defaults = this.defaults = {
8454
+ var $config = this.defaults = {
8486
8455
  // transform incoming response data
8487
8456
  transformResponse: [function(data) {
8488
8457
  if (isString(data)) {
@@ -8502,7 +8471,8 @@ function $HttpProvider() {
8502
8471
  // default headers
8503
8472
  headers: {
8504
8473
  common: {
8505
- 'Accept': 'application/json, text/plain, */*'
8474
+ 'Accept': 'application/json, text/plain, */*',
8475
+ 'X-Requested-With': 'XMLHttpRequest'
8506
8476
  },
8507
8477
  post: {'Content-Type': 'application/json;charset=utf-8'},
8508
8478
  put: {'Content-Type': 'application/json;charset=utf-8'}
@@ -8608,6 +8578,7 @@ function $HttpProvider() {
8608
8578
  *
8609
8579
  * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):
8610
8580
  * - `Accept: application/json, text/plain, * / *`
8581
+ * - `X-Requested-With: XMLHttpRequest`
8611
8582
  * - `$httpProvider.defaults.headers.post`: (header defaults for HTTP POST requests)
8612
8583
  * - `Content-Type: application/json`
8613
8584
  * - `$httpProvider.defaults.headers.put` (header defaults for HTTP PUT requests)
@@ -8742,7 +8713,7 @@ function $HttpProvider() {
8742
8713
  * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie
8743
8714
  * called `XSRF-TOKEN` and sets it as the HTTP header `X-XSRF-TOKEN`. Since only JavaScript that
8744
8715
  * runs on your domain could read the cookie, your server can be assured that the XHR came from
8745
- * JavaScript running on your domain. The header will not be set for cross-domain requests.
8716
+ * JavaScript running on your domain.
8746
8717
  *
8747
8718
  * To take advantage of this, your server needs to set a token in a JavaScript readable session
8748
8719
  * cookie called `XSRF-TOKEN` on first HTTP GET request. On subsequent non-GET requests the
@@ -8776,8 +8747,6 @@ function $HttpProvider() {
8776
8747
  * - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the
8777
8748
  * XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5
8778
8749
  * requests with credentials} for more information.
8779
- * - **responseType** - `{string}` - see {@link
8780
- * https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#responseType requestType}.
8781
8750
  *
8782
8751
  * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the
8783
8752
  * standard `then` method and two http specific methods: `success` and `error`. The `then`
@@ -8870,12 +8839,10 @@ function $HttpProvider() {
8870
8839
  function $http(config) {
8871
8840
  config.method = uppercase(config.method);
8872
8841
 
8873
- var reqTransformFn = config.transformRequest || defaults.transformRequest,
8874
- respTransformFn = config.transformResponse || defaults.transformResponse,
8875
- defHeaders = defaults.headers,
8876
- xsrfToken = isSameDomain(config.url, $browser.url()) ?
8877
- $browser.cookies()['XSRF-TOKEN'] : undefined,
8878
- reqHeaders = extend({'X-XSRF-TOKEN': xsrfToken},
8842
+ var reqTransformFn = config.transformRequest || $config.transformRequest,
8843
+ respTransformFn = config.transformResponse || $config.transformResponse,
8844
+ defHeaders = $config.headers,
8845
+ reqHeaders = extend({'X-XSRF-TOKEN': $browser.cookies()['XSRF-TOKEN']},
8879
8846
  defHeaders.common, defHeaders[lowercase(config.method)], config.headers),
8880
8847
  reqData = transformData(config.data, headersGetter(reqHeaders), reqTransformFn),
8881
8848
  promise;
@@ -8885,10 +8852,6 @@ function $HttpProvider() {
8885
8852
  delete reqHeaders['Content-Type'];
8886
8853
  }
8887
8854
 
8888
- if (isUndefined(config.withCredentials) && !isUndefined(defaults.withCredentials)) {
8889
- config.withCredentials = defaults.withCredentials;
8890
- }
8891
-
8892
8855
  // send request
8893
8856
  promise = sendReq(config, reqData, reqHeaders);
8894
8857
 
@@ -9020,11 +8983,11 @@ function $HttpProvider() {
9020
8983
  *
9021
8984
  * @description
9022
8985
  * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of
9023
- * default headers, withCredentials as well as request and response transformations.
8986
+ * default headers as well as request and response transformations.
9024
8987
  *
9025
8988
  * See "Setting HTTP Headers" and "Transforming Requests and Responses" sections above.
9026
8989
  */
9027
- $http.defaults = defaults;
8990
+ $http.defaults = $config;
9028
8991
 
9029
8992
 
9030
8993
  return $http;
@@ -9059,7 +9022,7 @@ function $HttpProvider() {
9059
9022
  * Makes the request
9060
9023
  *
9061
9024
  * !!! ACCESSES CLOSURE VARS:
9062
- * $httpBackend, defaults, $log, $rootScope, defaultCache, $http.pendingRequests
9025
+ * $httpBackend, $config, $log, $rootScope, defaultCache, $http.pendingRequests
9063
9026
  */
9064
9027
  function sendReq(config, reqData, reqHeaders) {
9065
9028
  var deferred = $q.defer(),
@@ -9100,7 +9063,7 @@ function $HttpProvider() {
9100
9063
  // if we won't have the response in cache, send the request to the backend
9101
9064
  if (!cachedResp) {
9102
9065
  $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,
9103
- config.withCredentials, config.responseType);
9066
+ config.withCredentials);
9104
9067
  }
9105
9068
 
9106
9069
  return promise;
@@ -9155,15 +9118,10 @@ function $HttpProvider() {
9155
9118
  var parts = [];
9156
9119
  forEachSorted(params, function(value, key) {
9157
9120
  if (value == null || value == undefined) return;
9158
- if (!isArray(value)) value = [value];
9159
-
9160
- forEach(value, function(v) {
9161
- if (isObject(v)) {
9162
- v = toJson(v);
9163
- }
9164
- parts.push(encodeURIComponent(key) + '=' +
9165
- encodeURIComponent(v));
9166
- });
9121
+ if (isObject(value)) {
9122
+ value = toJson(value);
9123
+ }
9124
+ parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));
9167
9125
  });
9168
9126
  return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');
9169
9127
  }
@@ -9205,7 +9163,7 @@ function $HttpBackendProvider() {
9205
9163
 
9206
9164
  function createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument, locationProtocol) {
9207
9165
  // TODO(vojta): fix the signature
9208
- return function(method, url, post, callback, headers, timeout, withCredentials, responseType) {
9166
+ return function(method, url, post, callback, headers, timeout, withCredentials) {
9209
9167
  $browser.$$incOutstandingRequestCount();
9210
9168
  url = url || $browser.url();
9211
9169
 
@@ -9238,8 +9196,30 @@ function createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument,
9238
9196
  // always async
9239
9197
  xhr.onreadystatechange = function() {
9240
9198
  if (xhr.readyState == 4) {
9241
- completeRequest(callback, status || xhr.status, xhr.response || xhr.responseText,
9242
- xhr.getAllResponseHeaders());
9199
+ var responseHeaders = xhr.getAllResponseHeaders();
9200
+
9201
+ // TODO(vojta): remove once Firefox 21 gets released.
9202
+ // begin: workaround to overcome Firefox CORS http response headers bug
9203
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=608735
9204
+ // Firefox already patched in nightly. Should land in Firefox 21.
9205
+
9206
+ // CORS "simple response headers" http://www.w3.org/TR/cors/
9207
+ var value,
9208
+ simpleHeaders = ["Cache-Control", "Content-Language", "Content-Type",
9209
+ "Expires", "Last-Modified", "Pragma"];
9210
+ if (!responseHeaders) {
9211
+ responseHeaders = "";
9212
+ forEach(simpleHeaders, function (header) {
9213
+ var value = xhr.getResponseHeader(header);
9214
+ if (value) {
9215
+ responseHeaders += header + ": " + value + "\n";
9216
+ }
9217
+ });
9218
+ }
9219
+ // end of the workaround.
9220
+
9221
+ completeRequest(callback, status || xhr.status, xhr.responseText,
9222
+ responseHeaders);
9243
9223
  }
9244
9224
  };
9245
9225
 
@@ -9247,10 +9227,6 @@ function createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument,
9247
9227
  xhr.withCredentials = true;
9248
9228
  }
9249
9229
 
9250
- if (responseType) {
9251
- xhr.responseType = responseType;
9252
- }
9253
-
9254
9230
  xhr.send(post || '');
9255
9231
 
9256
9232
  if (timeout > 0) {
@@ -9642,7 +9618,7 @@ function $FilterProvider($provide) {
9642
9618
  */
9643
9619
  function filterFilter() {
9644
9620
  return function(array, expression) {
9645
- if (!(array instanceof Array)) return array;
9621
+ if (!isArray(array)) return array;
9646
9622
  var predicates = [];
9647
9623
  predicates.check = function(value) {
9648
9624
  for (var j = 0; j < predicates.length; j++) {
@@ -9891,7 +9867,7 @@ function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {
9891
9867
  fraction += '0';
9892
9868
  }
9893
9869
 
9894
- if (fractionSize) formatedText += decimalSep + fraction.substr(0, fractionSize);
9870
+ if (fractionSize && fractionSize !== "0") formatedText += decimalSep + fraction.substr(0, fractionSize);
9895
9871
  }
9896
9872
 
9897
9873
  parts.push(isNegative ? pattern.negPre : pattern.posPre);
@@ -9934,8 +9910,12 @@ function dateStrGetter(name, shortForm) {
9934
9910
  }
9935
9911
 
9936
9912
  function timeZoneGetter(date) {
9937
- var offset = date.getTimezoneOffset();
9938
- return padNumber(offset / 60, 2) + padNumber(Math.abs(offset % 60), 2);
9913
+ var zone = -1 * date.getTimezoneOffset();
9914
+ var paddedZone = (zone >= 0) ? "+" : "";
9915
+
9916
+ paddedZone += padNumber(zone / 60, 2) + padNumber(Math.abs(zone % 60), 2);
9917
+
9918
+ return paddedZone;
9939
9919
  }
9940
9920
 
9941
9921
  function ampmGetter(date, formats) {
@@ -10021,7 +10001,8 @@ var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+
10021
10001
  *
10022
10002
  * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or
10023
10003
  * number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and it's
10024
- * shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ).
10004
+ * shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ). If no timezone is
10005
+ * specified in the string input, the time is considered to be in the local timezone.
10025
10006
  * @param {string=} format Formatting rules (see Description). If not specified,
10026
10007
  * `mediumDate` is used.
10027
10008
  * @returns {string} Formatted string or the input if input is not recognized as date/millis.
@@ -10041,7 +10022,7 @@ var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+
10041
10022
  expect(binding("1288323623006 | date:'medium'")).
10042
10023
  toMatch(/Oct 2\d, 2010 \d{1,2}:\d{2}:\d{2} (AM|PM)/);
10043
10024
  expect(binding("1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'")).
10044
- toMatch(/2010\-10\-2\d \d{2}:\d{2}:\d{2} \-?\d{4}/);
10025
+ toMatch(/2010\-10\-2\d \d{2}:\d{2}:\d{2} (\-|\+)?\d{4}/);
10045
10026
  expect(binding("'1288323623006' | date:'MM/dd/yyyy @ h:mma'")).
10046
10027
  toMatch(/10\/2\d\/2010 @ \d{1,2}:\d{2}(AM|PM)/);
10047
10028
  });
@@ -10053,22 +10034,18 @@ function dateFilter($locale) {
10053
10034
 
10054
10035
 
10055
10036
  var R_ISO8601_STR = /^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/;
10056
- // 1 2 3 4 5 6 7 8 9 10 11
10057
- function jsonStringToDate(string) {
10037
+ function jsonStringToDate(string){
10058
10038
  var match;
10059
10039
  if (match = string.match(R_ISO8601_STR)) {
10060
10040
  var date = new Date(0),
10061
10041
  tzHour = 0,
10062
- tzMin = 0,
10063
- dateSetter = match[8] ? date.setUTCFullYear : date.setFullYear,
10064
- timeSetter = match[8] ? date.setUTCHours : date.setHours;
10065
-
10042
+ tzMin = 0;
10066
10043
  if (match[9]) {
10067
10044
  tzHour = int(match[9] + match[10]);
10068
10045
  tzMin = int(match[9] + match[11]);
10069
10046
  }
10070
- dateSetter.call(date, int(match[1]), int(match[2]) - 1, int(match[3]));
10071
- timeSetter.call(date, int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));
10047
+ date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));
10048
+ date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));
10072
10049
  return date;
10073
10050
  }
10074
10051
  return string;
@@ -10182,20 +10159,20 @@ var uppercaseFilter = valueFn(uppercase);
10182
10159
  * @function
10183
10160
  *
10184
10161
  * @description
10185
- * Creates a new array or string containing only a specified number of elements. The elements
10186
- * are taken from either the beginning or the end of the source array or string, as specified by
10187
- * the value and sign (positive or negative) of `limit`.
10162
+ * Creates a new array containing only a specified number of elements in an array. The elements
10163
+ * are taken from either the beginning or the end of the source array, as specified by the
10164
+ * value and sign (positive or negative) of `limit`.
10188
10165
  *
10189
10166
  * Note: This function is used to augment the `Array` type in Angular expressions. See
10190
10167
  * {@link ng.$filter} for more information about Angular arrays.
10191
10168
  *
10192
- * @param {Array|string} input Source array or string to be limited.
10193
- * @param {string|number} limit The length of the returned array or string. If the `limit` number
10194
- * is positive, `limit` number of items from the beginning of the source array/string are copied.
10195
- * If the number is negative, `limit` number of items from the end of the source array/string
10196
- * are copied. The `limit` will be trimmed if it exceeds `array.length`
10197
- * @returns {Array|string} A new sub-array or substring of length `limit` or less if input array
10198
- * had less than `limit` elements.
10169
+ * @param {Array} array Source array to be limited.
10170
+ * @param {string|Number} limit The length of the returned array. If the `limit` number is
10171
+ * positive, `limit` number of items from the beginning of the source array are copied.
10172
+ * If the number is negative, `limit` number of items from the end of the source array are
10173
+ * copied. The `limit` will be trimmed if it exceeds `array.length`
10174
+ * @returns {Array} A new sub-array of length `limit` or less if input array had less than `limit`
10175
+ * elements.
10199
10176
  *
10200
10177
  * @example
10201
10178
  <doc:example>
@@ -10203,76 +10180,59 @@ var uppercaseFilter = valueFn(uppercase);
10203
10180
  <script>
10204
10181
  function Ctrl($scope) {
10205
10182
  $scope.numbers = [1,2,3,4,5,6,7,8,9];
10206
- $scope.letters = "abcdefghi";
10207
- $scope.numLimit = 3;
10208
- $scope.letterLimit = 3;
10183
+ $scope.limit = 3;
10209
10184
  }
10210
10185
  </script>
10211
10186
  <div ng-controller="Ctrl">
10212
- Limit {{numbers}} to: <input type="integer" ng-model="numLimit">
10213
- <p>Output numbers: {{ numbers | limitTo:numLimit }}</p>
10214
- Limit {{letters}} to: <input type="integer" ng-model="letterLimit">
10215
- <p>Output letters: {{ letters | limitTo:letterLimit }}</p>
10187
+ Limit {{numbers}} to: <input type="integer" ng-model="limit">
10188
+ <p>Output: {{ numbers | limitTo:limit }}</p>
10216
10189
  </div>
10217
10190
  </doc:source>
10218
10191
  <doc:scenario>
10219
- it('should limit the number array to first three items', function() {
10220
- expect(element('.doc-example-live input[ng-model=numLimit]').val()).toBe('3');
10221
- expect(element('.doc-example-live input[ng-model=letterLimit]').val()).toBe('3');
10222
- expect(binding('numbers | limitTo:numLimit')).toEqual('[1,2,3]');
10223
- expect(binding('letters | limitTo:letterLimit')).toEqual('abc');
10192
+ it('should limit the numer array to first three items', function() {
10193
+ expect(element('.doc-example-live input[ng-model=limit]').val()).toBe('3');
10194
+ expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3]');
10224
10195
  });
10225
10196
 
10226
10197
  it('should update the output when -3 is entered', function() {
10227
- input('numLimit').enter(-3);
10228
- input('letterLimit').enter(-3);
10229
- expect(binding('numbers | limitTo:numLimit')).toEqual('[7,8,9]');
10230
- expect(binding('letters | limitTo:letterLimit')).toEqual('ghi');
10198
+ input('limit').enter(-3);
10199
+ expect(binding('numbers | limitTo:limit')).toEqual('[7,8,9]');
10231
10200
  });
10232
10201
 
10233
10202
  it('should not exceed the maximum size of input array', function() {
10234
- input('numLimit').enter(100);
10235
- input('letterLimit').enter(100);
10236
- expect(binding('numbers | limitTo:numLimit')).toEqual('[1,2,3,4,5,6,7,8,9]');
10237
- expect(binding('letters | limitTo:letterLimit')).toEqual('abcdefghi');
10203
+ input('limit').enter(100);
10204
+ expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3,4,5,6,7,8,9]');
10238
10205
  });
10239
10206
  </doc:scenario>
10240
10207
  </doc:example>
10241
10208
  */
10242
10209
  function limitToFilter(){
10243
- return function(input, limit) {
10244
- if (!isArray(input) && !isString(input)) return input;
10245
-
10210
+ return function(array, limit) {
10211
+ if (!(array instanceof Array)) return array;
10246
10212
  limit = int(limit);
10247
-
10248
- if (isString(input)) {
10249
- //NaN check on limit
10250
- if (limit) {
10251
- return limit >= 0 ? input.slice(0, limit) : input.slice(limit, input.length);
10252
- } else {
10253
- return "";
10254
- }
10255
- }
10256
-
10257
10213
  var out = [],
10258
10214
  i, n;
10259
10215
 
10216
+ // check that array is iterable
10217
+ if (!array || !(array instanceof Array))
10218
+ return out;
10219
+
10260
10220
  // if abs(limit) exceeds maximum length, trim it
10261
- if (limit > input.length)
10262
- limit = input.length;
10263
- else if (limit < -input.length)
10264
- limit = -input.length;
10221
+ if (limit > array.length)
10222
+ limit = array.length;
10223
+ else if (limit < -array.length)
10224
+ limit = -array.length;
10265
10225
 
10266
10226
  if (limit > 0) {
10267
10227
  i = 0;
10268
10228
  n = limit;
10269
10229
  } else {
10270
- i = input.length + limit;
10271
- n = input.length;
10230
+ i = array.length + limit;
10231
+ n = array.length;
10272
10232
  }
10273
10233
 
10274
10234
  for (; i<n; i++) {
10275
- out.push(input[i]);
10235
+ out.push(array[i]);
10276
10236
  }
10277
10237
 
10278
10238
  return out;
@@ -10368,7 +10328,7 @@ function limitToFilter(){
10368
10328
  orderByFilter.$inject = ['$parse'];
10369
10329
  function orderByFilter($parse){
10370
10330
  return function(array, sortPredicate, reverseOrder) {
10371
- if (!(array instanceof Array)) return array;
10331
+ if (!isArray(array)) return array;
10372
10332
  if (!sortPredicate) return array;
10373
10333
  sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];
10374
10334
  sortPredicate = map(sortPredicate, function(predicate){
@@ -10436,15 +10396,25 @@ function ngDirective(directive) {
10436
10396
  *
10437
10397
  * The reasoning for this change is to allow easy creation of action links with `ngClick` directive
10438
10398
  * without changing the location or causing page reloads, e.g.:
10439
- * <a href="" ng-click="model.$save()">Save</a>
10399
+ * `<a href="" ng-click="model.$save()">Save</a>`
10440
10400
  */
10441
10401
  var htmlAnchorDirective = valueFn({
10442
10402
  restrict: 'E',
10443
10403
  compile: function(element, attr) {
10444
- // turn <a href ng-click="..">link</a> into a link in IE
10445
- // but only if it doesn't have name attribute, in which case it's an anchor
10446
- if (!attr.href) {
10447
- attr.$set('href', '');
10404
+
10405
+ if (msie <= 8) {
10406
+
10407
+ // turn <a href ng-click="..">link</a> into a stylable link in IE
10408
+ // but only if it doesn't have name attribute, in which case it's an anchor
10409
+ if (!attr.href && !attr.name) {
10410
+ attr.$set('href', '');
10411
+ }
10412
+
10413
+ // add a comment node to anchors to workaround IE bug that causes element content to be reset
10414
+ // to new attribute content if attribute is updated with value containing @ and element also
10415
+ // contains value with @
10416
+ // see issue #1949
10417
+ element.append(document.createComment('IE fix'));
10448
10418
  }
10449
10419
 
10450
10420
  return function(scope, element) {
@@ -10524,7 +10494,7 @@ var htmlAnchorDirective = valueFn({
10524
10494
  it('should execute ng-click but not reload when no href but name specified', function() {
10525
10495
  element('#link-5').click();
10526
10496
  expect(input('value').val()).toEqual('5');
10527
- expect(element('#link-5').attr('href')).toBe('');
10497
+ expect(element('#link-5').attr('href')).toBe(undefined);
10528
10498
  });
10529
10499
 
10530
10500
  it('should only change url when only ng-href', function() {
@@ -10730,37 +10700,6 @@ var htmlAnchorDirective = valueFn({
10730
10700
  * @param {string} expression Angular expression that will be evaluated.
10731
10701
  */
10732
10702
 
10733
- /**
10734
- * @ngdoc directive
10735
- * @name ng.directive:ngOpen
10736
- * @restrict A
10737
- *
10738
- * @description
10739
- * The HTML specs do not require browsers to preserve the special attributes such as open.
10740
- * (The presence of them means true and absence means false)
10741
- * This prevents the angular compiler from correctly retrieving the binding expression.
10742
- * To solve this problem, we introduce the `ngOpen` directive.
10743
- *
10744
- * @example
10745
- <doc:example>
10746
- <doc:source>
10747
- Check me check multiple: <input type="checkbox" ng-model="open"><br/>
10748
- <details id="details" ng-open="open">
10749
- <summary>Show/Hide me</summary>
10750
- </details>
10751
- </doc:source>
10752
- <doc:scenario>
10753
- it('should toggle open', function() {
10754
- expect(element('#details').prop('open')).toBeFalsy();
10755
- input('open').check();
10756
- expect(element('#details').prop('open')).toBeTruthy();
10757
- });
10758
- </doc:scenario>
10759
- </doc:example>
10760
- *
10761
- * @element DETAILS
10762
- * @param {string} expression Angular expression that will be evaluated.
10763
- */
10764
10703
 
10765
10704
  var ngAttributeAliasDirectives = {};
10766
10705
 
@@ -10798,8 +10737,9 @@ forEach(['src', 'href'], function(attrName) {
10798
10737
 
10799
10738
  // on IE, if "ng:src" directive declaration is used and "src" attribute doesn't exist
10800
10739
  // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need
10801
- // to set the property as well to achieve the desired effect
10802
- if (msie) element.prop(attrName, value);
10740
+ // to set the property as well to achieve the desired effect.
10741
+ // we use attr[attrName] value since $set can sanitize the url.
10742
+ if (msie) element.prop(attrName, attr[attrName]);
10803
10743
  });
10804
10744
  }
10805
10745
  };
@@ -10810,8 +10750,7 @@ var nullFormCtrl = {
10810
10750
  $addControl: noop,
10811
10751
  $removeControl: noop,
10812
10752
  $setValidity: noop,
10813
- $setDirty: noop,
10814
- $setPristine: noop
10753
+ $setDirty: noop
10815
10754
  };
10816
10755
 
10817
10756
  /**
@@ -10843,8 +10782,7 @@ function FormController(element, attrs) {
10843
10782
  var form = this,
10844
10783
  parentForm = element.parent().controller('form') || nullFormCtrl,
10845
10784
  invalidCount = 0, // used to easily determine if we are valid
10846
- errors = form.$error = {},
10847
- controls = [];
10785
+ errors = form.$error = {};
10848
10786
 
10849
10787
  // init state
10850
10788
  form.$name = attrs.name;
@@ -10868,8 +10806,6 @@ function FormController(element, attrs) {
10868
10806
  }
10869
10807
 
10870
10808
  form.$addControl = function(control) {
10871
- controls.push(control);
10872
-
10873
10809
  if (control.$name && !form.hasOwnProperty(control.$name)) {
10874
10810
  form[control.$name] = control;
10875
10811
  }
@@ -10882,8 +10818,6 @@ function FormController(element, attrs) {
10882
10818
  forEach(errors, function(queue, validationToken) {
10883
10819
  form.$setValidity(validationToken, true, control);
10884
10820
  });
10885
-
10886
- arrayRemove(controls, control);
10887
10821
  };
10888
10822
 
10889
10823
  form.$setValidity = function(validationToken, isValid, control) {
@@ -10931,29 +10865,6 @@ function FormController(element, attrs) {
10931
10865
  parentForm.$setDirty();
10932
10866
  };
10933
10867
 
10934
- /**
10935
- * @ngdoc function
10936
- * @name ng.directive:form.FormController#$setPristine
10937
- * @methodOf ng.directive:form.FormController
10938
- *
10939
- * @description
10940
- * Sets the form to its pristine state.
10941
- *
10942
- * This method can be called to remove the 'ng-dirty' class and set the form to its pristine
10943
- * state (ng-pristine class). This method will also propagate to all the controls contained
10944
- * in this form.
10945
- *
10946
- * Setting a form back to a pristine state is often useful when we want to 'reuse' a form after
10947
- * saving or resetting it.
10948
- */
10949
- form.$setPristine = function () {
10950
- element.removeClass(DIRTY_CLASS).addClass(PRISTINE_CLASS);
10951
- form.$dirty = false;
10952
- form.$pristine = true;
10953
- forEach(controls, function(control) {
10954
- control.$setPristine();
10955
- });
10956
- };
10957
10868
  }
10958
10869
 
10959
10870
 
@@ -11150,8 +11061,6 @@ var inputType = {
11150
11061
  * patterns defined as scope expressions.
11151
11062
  * @param {string=} ngChange Angular expression to be executed when input changes due to user
11152
11063
  * interaction with the input element.
11153
- * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trimming the
11154
- * input.
11155
11064
  *
11156
11065
  * @example
11157
11066
  <doc:example>
@@ -11159,12 +11068,12 @@ var inputType = {
11159
11068
  <script>
11160
11069
  function Ctrl($scope) {
11161
11070
  $scope.text = 'guest';
11162
- $scope.word = /^\s*\w*\s*$/;
11071
+ $scope.word = /^\w*$/;
11163
11072
  }
11164
11073
  </script>
11165
11074
  <form name="myForm" ng-controller="Ctrl">
11166
11075
  Single word: <input type="text" name="input" ng-model="text"
11167
- ng-pattern="word" required ng-trim="false">
11076
+ ng-pattern="word" required>
11168
11077
  <span class="error" ng-show="myForm.input.$error.required">
11169
11078
  Required!</span>
11170
11079
  <span class="error" ng-show="myForm.input.$error.pattern">
@@ -11193,12 +11102,6 @@ var inputType = {
11193
11102
  input('text').enter('hello world');
11194
11103
  expect(binding('myForm.input.$valid')).toEqual('false');
11195
11104
  });
11196
-
11197
- it('should not be trimmed', function() {
11198
- input('text').enter('untrimmed ');
11199
- expect(binding('text')).toEqual('untrimmed ');
11200
- expect(binding('myForm.input.$valid')).toEqual('true');
11201
- });
11202
11105
  </doc:scenario>
11203
11106
  </doc:example>
11204
11107
  */
@@ -11512,14 +11415,7 @@ function isEmpty(value) {
11512
11415
  function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
11513
11416
 
11514
11417
  var listener = function() {
11515
- var value = element.val();
11516
-
11517
- // By default we will trim the value
11518
- // If the attribute ng-trim exists we will avoid trimming
11519
- // e.g. <input ng-model="foo" ng-trim="false">
11520
- if (toBoolean(attr.ngTrim || 'T')) {
11521
- value = trim(value);
11522
- }
11418
+ var value = trim(element.val());
11523
11419
 
11524
11420
  if (ctrl.$viewValue !== value) {
11525
11421
  scope.$apply(function() {
@@ -12100,22 +11996,6 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
12100
11996
  parentForm.$setValidity(validationErrorKey, isValid, this);
12101
11997
  };
12102
11998
 
12103
- /**
12104
- * @ngdoc function
12105
- * @name ng.directive:ngModel.NgModelController#$setPristine
12106
- * @methodOf ng.directive:ngModel.NgModelController
12107
- *
12108
- * @description
12109
- * Sets the control to its pristine state.
12110
- *
12111
- * This method can be called to remove the 'ng-dirty' class and set the control to its pristine
12112
- * state (ng-pristine class).
12113
- */
12114
- this.$setPristine = function () {
12115
- this.$dirty = false;
12116
- this.$pristine = true;
12117
- $element.removeClass(DIRTY_CLASS).addClass(PRISTINE_CLASS);
12118
- };
12119
11999
 
12120
12000
  /**
12121
12001
  * @ngdoc function
@@ -12564,6 +12444,7 @@ var ngBindHtmlUnsafeDirective = [function() {
12564
12444
  function classDirective(name, selector) {
12565
12445
  name = 'ngClass' + name;
12566
12446
  return ngDirective(function(scope, element, attr) {
12447
+ var oldVal = undefined;
12567
12448
 
12568
12449
  scope.$watch(attr[name], ngClassWatchAction, true);
12569
12450
 
@@ -12587,13 +12468,14 @@ function classDirective(name, selector) {
12587
12468
  }
12588
12469
 
12589
12470
 
12590
- function ngClassWatchAction(newVal, oldVal) {
12471
+ function ngClassWatchAction(newVal) {
12591
12472
  if (selector === true || scope.$index % 2 === selector) {
12592
12473
  if (oldVal && (newVal !== oldVal)) {
12593
12474
  removeClass(oldVal);
12594
12475
  }
12595
12476
  addClass(newVal);
12596
12477
  }
12478
+ oldVal = newVal;
12597
12479
  }
12598
12480
 
12599
12481
 
@@ -12626,7 +12508,7 @@ function classDirective(name, selector) {
12626
12508
  *
12627
12509
  * The directive won't add duplicate classes if a particular class was already set.
12628
12510
  *
12629
- * When the expression changes, the previously added classes are removed and only then the classes
12511
+ * When the expression changes, the previously added classes are removed and only then the
12630
12512
  * new classes are added.
12631
12513
  *
12632
12514
  * @element ANY
@@ -12986,7 +12868,7 @@ var ngCspDirective = ['$sniffer', function($sniffer) {
12986
12868
  */
12987
12869
  var ngEventDirectives = {};
12988
12870
  forEach(
12989
- 'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave keydown keyup'.split(' '),
12871
+ 'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave'.split(' '),
12990
12872
  function(name) {
12991
12873
  var directiveName = directiveNormalize('ng-' + name);
12992
12874
  ngEventDirectives[directiveName] = ['$parse', function($parse) {
@@ -13113,38 +12995,6 @@ forEach(
13113
12995
  */
13114
12996
 
13115
12997
 
13116
- /**
13117
- * @ngdoc directive
13118
- * @name ng.directive:ngKeydown
13119
- *
13120
- * @description
13121
- * Specify custom behavior on keydown event.
13122
- *
13123
- * @element ANY
13124
- * @param {expression} ngKeydown {@link guide/expression Expression} to evaluate upon
13125
- * keydown. (Event object is available as `$event` and can be interrogated for keyCode, altKey, etc.)
13126
- *
13127
- * @example
13128
- * See {@link ng.directive:ngClick ngClick}
13129
- */
13130
-
13131
-
13132
- /**
13133
- * @ngdoc directive
13134
- * @name ng.directive:ngKeyup
13135
- *
13136
- * @description
13137
- * Specify custom behavior on keyup event.
13138
- *
13139
- * @element ANY
13140
- * @param {expression} ngKeyup {@link guide/expression Expression} to evaluate upon
13141
- * keyup. (Event object is available as `$event` and can be interrogated for keyCode, altKey, etc.)
13142
- *
13143
- * @example
13144
- * See {@link ng.directive:ngClick ngClick}
13145
- */
13146
-
13147
-
13148
12998
  /**
13149
12999
  * @ngdoc directive
13150
13000
  * @name ng.directive:ngSubmit
@@ -13982,9 +13832,10 @@ var NG_SWITCH = 'ng-switch';
13982
13832
  var ngSwitchDirective = valueFn({
13983
13833
  restrict: 'EA',
13984
13834
  require: 'ngSwitch',
13985
- controller: function ngSwitchController() {
13835
+ // asks for $scope to fool the BC controller module
13836
+ controller: ['$scope', function ngSwitchController() {
13986
13837
  this.cases = {};
13987
- },
13838
+ }],
13988
13839
  link: function(scope, element, attr, ctrl) {
13989
13840
  var watchExpr = attr.ngSwitch || attr.on,
13990
13841
  selectedTransclude,
@@ -14235,7 +14086,7 @@ var ngViewDirective = ['$http', '$templateCache', '$route', '$anchorScroll', '$c
14235
14086
  if (current.controller) {
14236
14087
  locals.$scope = lastScope;
14237
14088
  controller = $controller(current.controller, locals);
14238
- element.contents().data('$ngControllerController', controller);
14089
+ element.children().data('$ngControllerController', controller);
14239
14090
  }
14240
14091
 
14241
14092
  link(lastScope);