angularjs-rails 1.0.2 → 1.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -19,7 +19,5 @@ If you desire to require (optional) Angular files, you may include them as well
19
19
 
20
20
  ## Versioning
21
21
 
22
- angularjs-rails 1.0.0 == Angular.js 1.0.0
23
-
24
22
  Every attempt is made to mirror the currently shipping Angular.js version number wherever possible.
25
23
  The major, minor, and patch version numbers will always represent the Angular.js version.
@@ -1,5 +1,5 @@
1
1
  module AngularJS
2
2
  module Rails
3
- VERSION = "1.0.2"
3
+ VERSION = "1.0.3"
4
4
  end
5
5
  end
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.0.2
2
+ * @license AngularJS v1.0.3
3
3
  * (c) 2010-2012 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -216,7 +216,7 @@ directive.ngEmbedApp = ['$templateCache', '$browser', '$rootScope', '$location',
216
216
  }, $delegate);
217
217
  }]);
218
218
  $provide.decorator('$rootScope', ['$delegate', function(embedRootScope) {
219
- docsRootScope.$watch(function() {
219
+ docsRootScope.$watch(function embedRootScopeDigestWatch() {
220
220
  embedRootScope.$digest();
221
221
  });
222
222
  return embedRootScope;
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.0.2
2
+ * @license AngularJS v1.0.3
3
3
  * (c) 2010-2012 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -15,7 +15,7 @@ directive.dropdownToggle =
15
15
  return {
16
16
  restrict: 'C',
17
17
  link: function(scope, element, attrs) {
18
- scope.$watch(function(){return $location.path();}, function() {
18
+ scope.$watch(function dropdownTogglePathWatch(){return $location.path();}, function dropdownTogglePathWatchAction() {
19
19
  close && close();
20
20
  });
21
21
 
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.0.2
2
+ * @license AngularJS v1.0.3
3
3
  * (c) 2010-2012 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.0.2
2
+ * @license AngularJS v1.0.3
3
3
  * (c) 2010-2012 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -36,7 +36,7 @@ function setupModuleLoader(window) {
36
36
  *
37
37
  * # Module
38
38
  *
39
- * A module is a collocation of services, directives, filters, and configure information. Module
39
+ * A module is a collocation of services, directives, filters, and configuration information. Module
40
40
  * is used to configure the {@link AUTO.$injector $injector}.
41
41
  *
42
42
  * <pre>
@@ -67,7 +67,7 @@ function setupModuleLoader(window) {
67
67
  * @param {!string} name The name of the module to create or retrieve.
68
68
  * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the
69
69
  * the module is being retrieved for further configuration.
70
- * @param {Function} configFn Option configuration function for the module. Same as
70
+ * @param {Function} configFn Optional configuration function for the module. Same as
71
71
  * {@link angular.Module#config Module#config()}.
72
72
  * @returns {module} new module with the {@link angular.Module} api.
73
73
  */
@@ -222,8 +222,8 @@ function setupModuleLoader(window) {
222
222
  * @param {Function} initializationFn Execute this function after injector creation.
223
223
  * Useful for application initialization.
224
224
  * @description
225
- * Use this method to register work which needs to be performed when the injector with
226
- * with the current module is finished loading.
225
+ * Use this method to register work which should be performed when the injector is done
226
+ * loading all modules.
227
227
  */
228
228
  run: function(block) {
229
229
  runBlocks.push(block);
@@ -1,6 +1,6 @@
1
1
 
2
2
  /**
3
- * @license AngularJS v1.0.2
3
+ * @license AngularJS v1.0.3
4
4
  * (c) 2010-2012 Google, Inc. http://angularjs.org
5
5
  * License: MIT
6
6
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.0.2
2
+ * @license AngularJS v1.0.3
3
3
  * (c) 2010-2012 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -231,7 +231,7 @@ angular.module('ngResource', ['ng']).
231
231
  };
232
232
 
233
233
  /**
234
- * We need our custom mehtod because encodeURIComponent is too agressive and doesn't follow
234
+ * We need our custom mehtod because encodeURIComponent is too aggressive and doesn't follow
235
235
  * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path
236
236
  * segments:
237
237
  * segment = *pchar
@@ -285,12 +285,18 @@ angular.module('ngResource', ['ng']).
285
285
  url: function(params) {
286
286
  var self = this,
287
287
  url = this.template,
288
+ val,
288
289
  encodedVal;
289
290
 
290
291
  params = params || {};
291
292
  forEach(this.urlParams, function(_, urlParam){
292
- encodedVal = encodeUriSegment(params[urlParam] || self.defaults[urlParam] || "");
293
- url = url.replace(new RegExp(":" + urlParam + "(\\W)"), encodedVal + "$1");
293
+ val = params.hasOwnProperty(urlParam) ? params[urlParam] : self.defaults[urlParam];
294
+ if (angular.isDefined(val) && val !== null) {
295
+ encodedVal = encodeUriSegment(val);
296
+ url = url.replace(new RegExp(":" + urlParam + "(\\W)", "g"), encodedVal + "$1");
297
+ } else {
298
+ url = url.replace(new RegExp("/?:" + urlParam + "(\\W)", "g"), '$1');
299
+ }
294
300
  });
295
301
  url = url.replace(/\/?#$/, '');
296
302
  var query = [];
@@ -311,9 +317,10 @@ angular.module('ngResource', ['ng']).
311
317
 
312
318
  actions = extend({}, DEFAULT_ACTIONS, actions);
313
319
 
314
- function extractParams(data){
320
+ function extractParams(data, actionParams){
315
321
  var ids = {};
316
- forEach(paramDefaults || {}, function(value, key){
322
+ actionParams = extend({}, paramDefaults, actionParams);
323
+ forEach(actionParams, function(value, key){
317
324
  ids[key] = value.charAt && value.charAt(0) == '@' ? getter(data, value.substr(1)) : value;
318
325
  });
319
326
  return ids;
@@ -367,7 +374,7 @@ angular.module('ngResource', ['ng']).
367
374
  var value = this instanceof Resource ? this : (action.isArray ? [] : new Resource(data));
368
375
  $http({
369
376
  method: action.method,
370
- url: route.url(extend({}, extractParams(data), action.params || {}, params)),
377
+ url: route.url(extend({}, extractParams(data, action.params || {}), params)),
371
378
  data: data
372
379
  }).then(function(response) {
373
380
  var data = response.data;
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.0.2
2
+ * @license AngularJS v1.0.3
3
3
  * (c) 2010-2012 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -416,7 +416,7 @@ angular.module('ngSanitize', []).value('$sanitize', $sanitize);
416
416
  angular.module('ngSanitize').directive('ngBindHtml', ['$sanitize', function($sanitize) {
417
417
  return function(scope, element, attr) {
418
418
  element.addClass('ng-binding').data('$binding', attr.ngBindHtml);
419
- scope.$watch(attr.ngBindHtml, function(value) {
419
+ scope.$watch(attr.ngBindHtml, function ngBindHtmlWatchAction(value) {
420
420
  value = $sanitize(value);
421
421
  element.html(value || '');
422
422
  });
@@ -9404,7 +9404,7 @@ if ( typeof define === "function" && define.amd && define.amd.jQuery ) {
9404
9404
 
9405
9405
  })( window );
9406
9406
  /**
9407
- * @license AngularJS v1.0.2
9407
+ * @license AngularJS v1.0.3
9408
9408
  * (c) 2010-2012 Google, Inc. http://angularjs.org
9409
9409
  * License: MIT
9410
9410
  */
@@ -10199,7 +10199,7 @@ function toKeyValue(obj) {
10199
10199
 
10200
10200
 
10201
10201
  /**
10202
- * We need our custom mehtod because encodeURIComponent is too agressive and doesn't follow
10202
+ * We need our custom method because encodeURIComponent is too agressive and doesn't follow
10203
10203
  * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path
10204
10204
  * segments:
10205
10205
  * segment = *pchar
@@ -10243,7 +10243,7 @@ function encodeUriQuery(val, pctEncodeSpaces) {
10243
10243
  * @name ng.directive:ngApp
10244
10244
  *
10245
10245
  * @element ANY
10246
- * @param {angular.Module} ngApp on optional application
10246
+ * @param {angular.Module} ngApp an optional application
10247
10247
  * {@link angular.module module} name to load.
10248
10248
  *
10249
10249
  * @description
@@ -10420,7 +10420,7 @@ function setupModuleLoader(window) {
10420
10420
  *
10421
10421
  * # Module
10422
10422
  *
10423
- * A module is a collocation of services, directives, filters, and configure information. Module
10423
+ * A module is a collocation of services, directives, filters, and configuration information. Module
10424
10424
  * is used to configure the {@link AUTO.$injector $injector}.
10425
10425
  *
10426
10426
  * <pre>
@@ -10450,7 +10450,7 @@ function setupModuleLoader(window) {
10450
10450
  * @param {!string} name The name of the module to create or retrieve.
10451
10451
  * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the
10452
10452
  * the module is being retrieved for further configuration.
10453
- * @param {Function} configFn Option configuration function for the module. Same as
10453
+ * @param {Function} configFn Optional configuration function for the module. Same as
10454
10454
  * {@link angular.Module#config Module#config()}.
10455
10455
  * @returns {module} new module with the {@link angular.Module} api.
10456
10456
  */
@@ -10605,8 +10605,8 @@ function setupModuleLoader(window) {
10605
10605
  * @param {Function} initializationFn Execute this function after injector creation.
10606
10606
  * Useful for application initialization.
10607
10607
  * @description
10608
- * Use this method to register work which needs to be performed when the injector with
10609
- * with the current module is finished loading.
10608
+ * Use this method to register work which should be performed when the injector is done
10609
+ * loading all modules.
10610
10610
  */
10611
10611
  run: function(block) {
10612
10612
  runBlocks.push(block);
@@ -10652,11 +10652,11 @@ function setupModuleLoader(window) {
10652
10652
  * - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat".
10653
10653
  */
10654
10654
  var version = {
10655
- full: '1.0.2', // all of these placeholder strings will be replaced by rake's
10655
+ full: '1.0.3', // all of these placeholder strings will be replaced by rake's
10656
10656
  major: 1, // compile task
10657
10657
  minor: 0,
10658
- dot: 2,
10659
- codeName: 'debilitating-awesomeness'
10658
+ dot: 3,
10659
+ codeName: 'bouncy-thunder'
10660
10660
  };
10661
10661
 
10662
10662
 
@@ -10823,6 +10823,7 @@ function publishExternalAPI(angular){
10823
10823
  * - [replaceWith()](http://api.jquery.com/replaceWith/)
10824
10824
  * - [text()](http://api.jquery.com/text/)
10825
10825
  * - [toggleClass()](http://api.jquery.com/toggleClass/)
10826
+ * - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Doesn't pass native event objects to handlers.
10826
10827
  * - [unbind()](http://api.jquery.com/unbind/)
10827
10828
  * - [val()](http://api.jquery.com/val/)
10828
10829
  * - [wrap()](http://api.jquery.com/wrap/)
@@ -10898,12 +10899,7 @@ function JQLitePatchJQueryRemove(name, dispatchThis) {
10898
10899
  for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {
10899
10900
  element = jqLite(set[setIndex]);
10900
10901
  if (fireEvent) {
10901
- events = element.data('events');
10902
- if ( (fns = events && events.$destroy) ) {
10903
- forEach(fns, function(fn){
10904
- fn.handler();
10905
- });
10906
- }
10902
+ element.triggerHandler('$destroy');
10907
10903
  } else {
10908
10904
  fireEvent = !fireEvent;
10909
10905
  }
@@ -11035,9 +11031,9 @@ function JQLiteHasClass(element, selector) {
11035
11031
  indexOf( " " + selector + " " ) > -1);
11036
11032
  }
11037
11033
 
11038
- function JQLiteRemoveClass(element, selector) {
11039
- if (selector) {
11040
- forEach(selector.split(' '), function(cssClass) {
11034
+ function JQLiteRemoveClass(element, cssClasses) {
11035
+ if (cssClasses) {
11036
+ forEach(cssClasses.split(' '), function(cssClass) {
11041
11037
  element.className = trim(
11042
11038
  (" " + element.className + " ")
11043
11039
  .replace(/[\n\t]/g, " ")
@@ -11047,9 +11043,9 @@ function JQLiteRemoveClass(element, selector) {
11047
11043
  }
11048
11044
  }
11049
11045
 
11050
- function JQLiteAddClass(element, selector) {
11051
- if (selector) {
11052
- forEach(selector.split(' '), function(cssClass) {
11046
+ function JQLiteAddClass(element, cssClasses) {
11047
+ if (cssClasses) {
11048
+ forEach(cssClasses.split(' '), function(cssClass) {
11053
11049
  if (!JQLiteHasClass(element, cssClass)) {
11054
11050
  element.className = trim(element.className + ' ' + trim(cssClass));
11055
11051
  }
@@ -11497,7 +11493,15 @@ forEach({
11497
11493
  return element.getElementsByTagName(selector);
11498
11494
  },
11499
11495
 
11500
- clone: JQLiteClone
11496
+ clone: JQLiteClone,
11497
+
11498
+ triggerHandler: function(element, eventName) {
11499
+ var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName];
11500
+
11501
+ forEach(eventFns, function(fn) {
11502
+ fn.call(element, null);
11503
+ });
11504
+ }
11501
11505
  }, function(fn, name){
11502
11506
  /**
11503
11507
  * chaining functions
@@ -11615,6 +11619,16 @@ HashQueueMap.prototype = {
11615
11619
  return array.shift();
11616
11620
  }
11617
11621
  }
11622
+ },
11623
+
11624
+ /**
11625
+ * return the first item without deleting it
11626
+ */
11627
+ peek: function(key) {
11628
+ var array = this[hashKey(key)];
11629
+ if (array) {
11630
+ return array[0];
11631
+ }
11618
11632
  }
11619
11633
  };
11620
11634
 
@@ -11638,7 +11652,7 @@ HashQueueMap.prototype = {
11638
11652
  * // create an injector
11639
11653
  * var $injector = angular.injector(['ng']);
11640
11654
  *
11641
- * // use the injector to kick of your application
11655
+ * // use the injector to kick off your application
11642
11656
  * // use the type inference to auto inject arguments, or use implicit injection
11643
11657
  * $injector.invoke(function($rootScope, $compile, $document){
11644
11658
  * $compile($document)($rootScope);
@@ -11658,7 +11672,7 @@ HashQueueMap.prototype = {
11658
11672
 
11659
11673
  var FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m;
11660
11674
  var FN_ARG_SPLIT = /,/;
11661
- var FN_ARG = /^\s*(_?)(.+?)\1\s*$/;
11675
+ var FN_ARG = /^\s*(_?)(\S+?)\1\s*$/;
11662
11676
  var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
11663
11677
  function annotate(fn) {
11664
11678
  var $inject,
@@ -12277,9 +12291,10 @@ function $AnchorScrollProvider() {
12277
12291
  // does not scroll when user clicks on anchor link that is currently on
12278
12292
  // (no url change, no $locaiton.hash() change), browser native does scroll
12279
12293
  if (autoScrollingEnabled) {
12280
- $rootScope.$watch(function() {return $location.hash();}, function() {
12281
- $rootScope.$evalAsync(scroll);
12282
- });
12294
+ $rootScope.$watch(function autoScrollWatch() {return $location.hash();},
12295
+ function autoScrollWatchAction() {
12296
+ $rootScope.$evalAsync(scroll);
12297
+ });
12283
12298
  }
12284
12299
 
12285
12300
  return scroll;
@@ -12663,10 +12678,10 @@ function $BrowserProvider(){
12663
12678
  *
12664
12679
  * - `{object}` `info()` — Returns id, size, and options of cache.
12665
12680
  * - `{void}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache.
12666
- * - `{{*}} `get({string} key) — Returns cached value for `key` or undefined for cache miss.
12667
- * - `{void}` `remove({string} key) — Removes a key-value pair from the cache.
12668
- * - `{void}` `removeAll() — Removes all cached values.
12669
- * - `{void}` `destroy() — Removes references to this cache from $cacheFactory.
12681
+ * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.
12682
+ * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.
12683
+ * - `{void}` `removeAll()` — Removes all cached values.
12684
+ * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.
12670
12685
  *
12671
12686
  */
12672
12687
  function $CacheFactoryProvider() {
@@ -12718,6 +12733,8 @@ function $CacheFactoryProvider() {
12718
12733
  remove: function(key) {
12719
12734
  var lruEntry = lruHash[key];
12720
12735
 
12736
+ if (!lruEntry) return;
12737
+
12721
12738
  if (lruEntry == freshEnd) freshEnd = lruEntry.p;
12722
12739
  if (lruEntry == staleEnd) staleEnd = lruEntry.n;
12723
12740
  link(lruEntry.n,lruEntry.p);
@@ -13125,26 +13142,26 @@ function $CompileProvider($provide) {
13125
13142
 
13126
13143
  //================================
13127
13144
 
13128
- function compile($compileNode, transcludeFn, maxPriority) {
13129
- if (!($compileNode instanceof jqLite)) {
13145
+ function compile($compileNodes, transcludeFn, maxPriority) {
13146
+ if (!($compileNodes instanceof jqLite)) {
13130
13147
  // jquery always rewraps, where as we need to preserve the original selector so that we can modify it.
13131
- $compileNode = jqLite($compileNode);
13148
+ $compileNodes = jqLite($compileNodes);
13132
13149
  }
13133
13150
  // We can not compile top level text elements since text nodes can be merged and we will
13134
13151
  // not be able to attach scope data to them, so we will wrap them in <span>
13135
- forEach($compileNode, function(node, index){
13152
+ forEach($compileNodes, function(node, index){
13136
13153
  if (node.nodeType == 3 /* text node */) {
13137
- $compileNode[index] = jqLite(node).wrap('<span></span>').parent()[0];
13154
+ $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];
13138
13155
  }
13139
13156
  });
13140
- var compositeLinkFn = compileNodes($compileNode, transcludeFn, $compileNode, maxPriority);
13141
- return function(scope, cloneConnectFn){
13157
+ var compositeLinkFn = compileNodes($compileNodes, transcludeFn, $compileNodes, maxPriority);
13158
+ return function publicLinkFn(scope, cloneConnectFn){
13142
13159
  assertArg(scope, 'scope');
13143
13160
  // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart
13144
13161
  // and sometimes changes the structure of the DOM.
13145
13162
  var $linkNode = cloneConnectFn
13146
- ? JQLitePrototype.clone.call($compileNode) // IMPORTANT!!!
13147
- : $compileNode;
13163
+ ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!
13164
+ : $compileNodes;
13148
13165
  $linkNode.data('$scope', scope);
13149
13166
  safeAddClass($linkNode, 'ng-scope');
13150
13167
  if (cloneConnectFn) cloneConnectFn($linkNode, scope);
@@ -13195,7 +13212,7 @@ function $CompileProvider($provide) {
13195
13212
  ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)
13196
13213
  : null;
13197
13214
 
13198
- childLinkFn = (nodeLinkFn && nodeLinkFn.terminal)
13215
+ childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes.length)
13199
13216
  ? null
13200
13217
  : compileNodes(nodeList[i].childNodes,
13201
13218
  nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);
@@ -13247,13 +13264,14 @@ function $CompileProvider($provide) {
13247
13264
 
13248
13265
 
13249
13266
  /**
13250
- * Looks for directives on the given node ands them to the directive collection which is sorted.
13267
+ * Looks for directives on the given node and adds them to the directive collection which is
13268
+ * sorted.
13251
13269
  *
13252
- * @param node node to search
13253
- * @param directives an array to which the directives are added to. This array is sorted before
13270
+ * @param node Node to search.
13271
+ * @param directives An array to which the directives are added to. This array is sorted before
13254
13272
  * the function returns.
13255
- * @param attrs the shared attrs object which is used to populate the normalized attributes.
13256
- * @param {number=} max directive priority
13273
+ * @param attrs The shared attrs object which is used to populate the normalized attributes.
13274
+ * @param {number=} maxPriority Max directive priority.
13257
13275
  */
13258
13276
  function collectDirectives(node, directives, attrs, maxPriority) {
13259
13277
  var nodeType = node.nodeType,
@@ -13288,7 +13306,7 @@ function $CompileProvider($provide) {
13288
13306
 
13289
13307
  // use class as directive
13290
13308
  className = node.className;
13291
- if (isString(className)) {
13309
+ if (isString(className) && className !== '') {
13292
13310
  while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {
13293
13311
  nName = directiveNormalize(match[2]);
13294
13312
  if (addDirective(directives, nName, 'C', maxPriority)) {
@@ -13342,7 +13360,7 @@ function $CompileProvider($provide) {
13342
13360
  preLinkFns = [],
13343
13361
  postLinkFns = [],
13344
13362
  newScopeDirective = null,
13345
- newIsolatedScopeDirective = null,
13363
+ newIsolateScopeDirective = null,
13346
13364
  templateDirective = null,
13347
13365
  $compileNode = templateAttrs.$$element = jqLite(compileNode),
13348
13366
  directive,
@@ -13364,10 +13382,10 @@ function $CompileProvider($provide) {
13364
13382
  }
13365
13383
 
13366
13384
  if (directiveValue = directive.scope) {
13367
- assertNoDuplicate('isolated scope', newIsolatedScopeDirective, directive, $compileNode);
13385
+ assertNoDuplicate('isolated scope', newIsolateScopeDirective, directive, $compileNode);
13368
13386
  if (isObject(directiveValue)) {
13369
13387
  safeAddClass($compileNode, 'ng-isolate-scope');
13370
- newIsolatedScopeDirective = directive;
13388
+ newIsolateScopeDirective = directive;
13371
13389
  }
13372
13390
  safeAddClass($compileNode, 'ng-scope');
13373
13391
  newScopeDirective = newScopeDirective || directive;
@@ -13521,12 +13539,12 @@ function $CompileProvider($provide) {
13521
13539
  }
13522
13540
  $element = attrs.$$element;
13523
13541
 
13524
- if (newScopeDirective && isObject(newScopeDirective.scope)) {
13542
+ if (newIsolateScopeDirective) {
13525
13543
  var LOCAL_REGEXP = /^\s*([@=&])\s*(\w*)\s*$/;
13526
13544
 
13527
13545
  var parentScope = scope.$parent || scope;
13528
13546
 
13529
- forEach(newScopeDirective.scope, function(definiton, scopeName) {
13547
+ forEach(newIsolateScopeDirective.scope, function(definiton, scopeName) {
13530
13548
  var match = definiton.match(LOCAL_REGEXP) || [],
13531
13549
  attrName = match[2]|| scopeName,
13532
13550
  mode = match[1], // @, =, or &
@@ -13549,10 +13567,10 @@ function $CompileProvider($provide) {
13549
13567
  // reset the change, or we will throw this exception on every $digest
13550
13568
  lastValue = scope[scopeName] = parentGet(parentScope);
13551
13569
  throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + attrs[attrName] +
13552
- ' (directive: ' + newScopeDirective.name + ')');
13570
+ ' (directive: ' + newIsolateScopeDirective.name + ')');
13553
13571
  };
13554
13572
  lastValue = scope[scopeName] = parentGet(parentScope);
13555
- scope.$watch(function() {
13573
+ scope.$watch(function parentValueWatch() {
13556
13574
  var parentValue = parentGet(parentScope);
13557
13575
 
13558
13576
  if (parentValue !== scope[scopeName]) {
@@ -13562,7 +13580,7 @@ function $CompileProvider($provide) {
13562
13580
  lastValue = scope[scopeName] = parentValue;
13563
13581
  } else {
13564
13582
  // if the parent can be assigned then do so
13565
- parentSet(parentScope, lastValue = scope[scopeName]);
13583
+ parentSet(parentScope, parentValue = lastValue = scope[scopeName]);
13566
13584
  }
13567
13585
  }
13568
13586
  return parentValue;
@@ -13580,7 +13598,7 @@ function $CompileProvider($provide) {
13580
13598
 
13581
13599
  default: {
13582
13600
  throw Error('Invalid isolate scope definition for directive ' +
13583
- newScopeDirective.name + ': ' + definiton);
13601
+ newIsolateScopeDirective.name + ': ' + definiton);
13584
13602
  }
13585
13603
  }
13586
13604
  });
@@ -13714,7 +13732,7 @@ function $CompileProvider($provide) {
13714
13732
  origAsyncDirective = directives.shift(),
13715
13733
  // The fact that we have to copy and patch the directive seems wrong!
13716
13734
  derivedSyncDirective = extend({}, origAsyncDirective, {
13717
- controller: null, templateUrl: null, transclude: null
13735
+ controller: null, templateUrl: null, transclude: null, scope: null
13718
13736
  });
13719
13737
 
13720
13738
  $compileNode.html('');
@@ -13806,12 +13824,12 @@ function $CompileProvider($provide) {
13806
13824
  if (interpolateFn) {
13807
13825
  directives.push({
13808
13826
  priority: 0,
13809
- compile: valueFn(function(scope, node) {
13827
+ compile: valueFn(function textInterpolateLinkFn(scope, node) {
13810
13828
  var parent = node.parent(),
13811
13829
  bindings = parent.data('$binding') || [];
13812
13830
  bindings.push(interpolateFn);
13813
13831
  safeAddClass(parent.data('$binding', bindings), 'ng-binding');
13814
- scope.$watch(interpolateFn, function(value) {
13832
+ scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {
13815
13833
  node[0].nodeValue = value;
13816
13834
  });
13817
13835
  })
@@ -13829,7 +13847,7 @@ function $CompileProvider($provide) {
13829
13847
 
13830
13848
  directives.push({
13831
13849
  priority: 100,
13832
- compile: valueFn(function(scope, element, attr) {
13850
+ compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) {
13833
13851
  var $$observers = (attr.$$observers || (attr.$$observers = {}));
13834
13852
 
13835
13853
  if (name === 'class') {
@@ -13841,7 +13859,7 @@ function $CompileProvider($provide) {
13841
13859
  attr[name] = undefined;
13842
13860
  ($$observers[name] || ($$observers[name] = [])).$$inter = true;
13843
13861
  (attr.$$observers && attr.$$observers[name].$$scope || scope).
13844
- $watch(interpolateFn, function(value) {
13862
+ $watch(interpolateFn, function interpolateFnWatchAction(value) {
13845
13863
  attr.$set(name, value);
13846
13864
  });
13847
13865
  })
@@ -14839,6 +14857,7 @@ function $LocationProvider(){
14839
14857
  var changeCounter = 0;
14840
14858
  $rootScope.$watch(function $locationWatch() {
14841
14859
  var oldUrl = $browser.url();
14860
+ var currentReplace = $location.$$replace;
14842
14861
 
14843
14862
  if (!changeCounter || oldUrl != $location.absUrl()) {
14844
14863
  changeCounter++;
@@ -14847,12 +14866,12 @@ function $LocationProvider(){
14847
14866
  defaultPrevented) {
14848
14867
  $location.$$parse(oldUrl);
14849
14868
  } else {
14850
- $browser.url($location.absUrl(), $location.$$replace);
14851
- $location.$$replace = false;
14869
+ $browser.url($location.absUrl(), currentReplace);
14852
14870
  afterLocationChange(oldUrl);
14853
14871
  }
14854
14872
  });
14855
14873
  }
14874
+ $location.$$replace = false;
14856
14875
 
14857
14876
  return changeCounter;
14858
14877
  });
@@ -14983,7 +15002,15 @@ var OPERATORS = {
14983
15002
  'true':function(){return true;},
14984
15003
  'false':function(){return false;},
14985
15004
  undefined:noop,
14986
- '+':function(self, locals, a,b){a=a(self, locals); b=b(self, locals); return (isDefined(a)?a:0)+(isDefined(b)?b:0);},
15005
+ '+':function(self, locals, a,b){
15006
+ a=a(self, locals); b=b(self, locals);
15007
+ if (isDefined(a)) {
15008
+ if (isDefined(b)) {
15009
+ return a + b;
15010
+ }
15011
+ return a;
15012
+ }
15013
+ return isDefined(b)?b:undefined;},
14987
15014
  '-':function(self, locals, a,b){a=a(self, locals); b=b(self, locals); return (isDefined(a)?a:0)-(isDefined(b)?b:0);},
14988
15015
  '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);},
14989
15016
  '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);},
@@ -15878,7 +15905,7 @@ function $ParseProvider() {
15878
15905
  * alert('Success: ' + greeting);
15879
15906
  * }, function(reason) {
15880
15907
  * alert('Failed: ' + reason);
15881
- * );
15908
+ * });
15882
15909
  * </pre>
15883
15910
  *
15884
15911
  * At first it might not be obvious why this extra complexity is worth the trouble. The payoff
@@ -16253,7 +16280,7 @@ function $RouteProvider(){
16253
16280
  * Object properties:
16254
16281
  *
16255
16282
  * - `controller` – `{(string|function()=}` – Controller fn that should be associated with newly
16256
- * created scope or the name of a {@link angular.Module#controller registered controller}
16283
+ * created scope or the name of a {@link angular.Module#controller registered controller}
16257
16284
  * if passed as a string.
16258
16285
  * - `template` – `{string=}` – html template as a string that should be used by
16259
16286
  * {@link ng.directive:ngView ngView} or
@@ -16264,7 +16291,7 @@ function $RouteProvider(){
16264
16291
  * - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should
16265
16292
  * be injected into the controller. If any of these dependencies are promises, they will be
16266
16293
  * resolved and converted to a value before the controller is instantiated and the
16267
- * `$afterRouteChange` event is fired. The map object is:
16294
+ * `$routeChangeSuccess` event is fired. The map object is:
16268
16295
  *
16269
16296
  * - `key` – `{string}`: a name of a dependency to be injected into the controller.
16270
16297
  * - `factory` - `{string|function}`: If `string` then it is an alias for a service.
@@ -16598,7 +16625,7 @@ function $RouteProvider(){
16598
16625
 
16599
16626
  forEach(next.resolve || {}, function(value, key) {
16600
16627
  keys.push(key);
16601
- values.push(isFunction(value) ? $injector.invoke(value) : $injector.get(value));
16628
+ values.push(isString(value) ? $injector.get(value) : $injector.invoke(value));
16602
16629
  });
16603
16630
  if (isDefined(template = next.template)) {
16604
16631
  } else if (isDefined(template = next.templateUrl)) {
@@ -16869,9 +16896,9 @@ function $RootScopeProvider(){
16869
16896
  * the scope and its child scopes to be permanently detached from the parent and thus stop
16870
16897
  * participating in model change detection and listener notification by invoking.
16871
16898
  *
16872
- * @param {boolean} isolate if true then the scoped does not prototypically inherit from the
16873
- * parent scope. The scope is isolated, as it can not se parent scope properties.
16874
- * When creating widgets it is useful for the widget to not accidently read parent
16899
+ * @param {boolean} isolate if true then the scope does not prototypically inherit from the
16900
+ * parent scope. The scope is isolated, as it can not see parent scope properties.
16901
+ * When creating widgets it is useful for the widget to not accidentally read parent
16875
16902
  * state.
16876
16903
  *
16877
16904
  * @returns {Object} The newly created child scope.
@@ -16925,18 +16952,18 @@ function $RootScopeProvider(){
16925
16952
  * reruns when it detects changes the `watchExpression` can execute multiple times per
16926
16953
  * {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)
16927
16954
  * - The `listener` is called only when the value from the current `watchExpression` and the
16928
- * previous call to `watchExpression' are not equal (with the exception of the initial run
16955
+ * previous call to `watchExpression` are not equal (with the exception of the initial run,
16929
16956
  * see below). The inequality is determined according to
16930
- * {@link angular.equals} function. To save the value of the object for later comparison
16957
+ * {@link angular.equals} function. To save the value of the object for later comparison, the
16931
16958
  * {@link angular.copy} function is used. It also means that watching complex options will
16932
16959
  * have adverse memory and performance implications.
16933
16960
  * - The watch `listener` may change the model, which may trigger other `listener`s to fire. This
16934
16961
  * is achieved by rerunning the watchers until no changes are detected. The rerun iteration
16935
- * limit is 100 to prevent infinity loop deadlock.
16962
+ * limit is 10 to prevent an infinite loop deadlock.
16936
16963
  *
16937
16964
  *
16938
16965
  * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,
16939
- * you can register an `watchExpression` function with no `listener`. (Since `watchExpression`,
16966
+ * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`
16940
16967
  * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a change is
16941
16968
  * detected, be prepared for multiple calls to your listener.)
16942
16969
  *
@@ -16982,7 +17009,7 @@ function $RootScopeProvider(){
16982
17009
  * - `string`: Evaluated as {@link guide/expression expression}
16983
17010
  * - `function(newValue, oldValue, scope)`: called with current and previous values as parameters.
16984
17011
  *
16985
- * @param {boolean=} objectEquality Compare object for equality rather then for refference.
17012
+ * @param {boolean=} objectEquality Compare object for equality rather than for reference.
16986
17013
  * @returns {function()} Returns a deregistration function for this listener.
16987
17014
  */
16988
17015
  $watch: function(watchExp, listener, objectEquality) {
@@ -17157,7 +17184,7 @@ function $RootScopeProvider(){
17157
17184
  * @function
17158
17185
  *
17159
17186
  * @description
17160
- * Remove the current scope (and all of its children) from the parent scope. Removal implies
17187
+ * Removes the current scope (and all of its children) from the parent scope. Removal implies
17161
17188
  * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer
17162
17189
  * propagate to the current scope and its children. Removal also implies that the current
17163
17190
  * scope is eligible for garbage collection.
@@ -17180,6 +17207,11 @@ function $RootScopeProvider(){
17180
17207
  if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;
17181
17208
  if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;
17182
17209
  if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;
17210
+
17211
+ // This is bogus code that works around Chrome's GC leak
17212
+ // see: https://github.com/angular/angular.js/issues/1313#issuecomment-10378451
17213
+ this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =
17214
+ this.$$childTail = null;
17183
17215
  },
17184
17216
 
17185
17217
  /**
@@ -17190,7 +17222,7 @@ function $RootScopeProvider(){
17190
17222
  *
17191
17223
  * @description
17192
17224
  * Executes the `expression` on the current scope returning the result. Any exceptions in the
17193
- * expression are propagated (uncaught). This is useful when evaluating engular expressions.
17225
+ * expression are propagated (uncaught). This is useful when evaluating Angular expressions.
17194
17226
  *
17195
17227
  * # Example
17196
17228
  * <pre>
@@ -17311,7 +17343,7 @@ function $RootScopeProvider(){
17311
17343
  * @function
17312
17344
  *
17313
17345
  * @description
17314
- * Listen on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for discussion of
17346
+ * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for discussion of
17315
17347
  * event life cycle.
17316
17348
  *
17317
17349
  * @param {string} name Event name to listen on.
@@ -17321,13 +17353,13 @@ function $RootScopeProvider(){
17321
17353
  * The event listener function format is: `function(event, args...)`. The `event` object
17322
17354
  * passed into the listener has the following attributes:
17323
17355
  *
17324
- * - `targetScope` - {Scope}: the scope on which the event was `$emit`-ed or `$broadcast`-ed.
17325
- * - `currentScope` - {Scope}: the current scope which is handling the event.
17326
- * - `name` - {string}: Name of the event.
17327
- * - `stopPropagation` - {function=}: calling `stopPropagation` function will cancel further event propagation
17328
- * (available only for events that were `$emit`-ed).
17329
- * - `preventDefault` - {function}: calling `preventDefault` sets `defaultPrevented` flag to true.
17330
- * - `defaultPrevented` - {boolean}: true if `preventDefault` was called.
17356
+ * - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or `$broadcast`-ed.
17357
+ * - `currentScope` - `{Scope}`: the current scope which is handling the event.
17358
+ * - `name` - `{string}`: Name of the event.
17359
+ * - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel further event
17360
+ * propagation (available only for events that were `$emit`-ed).
17361
+ * - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag to true.
17362
+ * - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.
17331
17363
  */
17332
17364
  $on: function(name, listener) {
17333
17365
  var namedListeners = this.$$listeners[name];
@@ -17337,7 +17369,7 @@ function $RootScopeProvider(){
17337
17369
  namedListeners.push(listener);
17338
17370
 
17339
17371
  return function() {
17340
- arrayRemove(namedListeners, listener);
17372
+ namedListeners[indexOf(namedListeners, listener)] = null;
17341
17373
  };
17342
17374
  },
17343
17375
 
@@ -17385,6 +17417,14 @@ function $RootScopeProvider(){
17385
17417
  namedListeners = scope.$$listeners[name] || empty;
17386
17418
  event.currentScope = scope;
17387
17419
  for (i=0, length=namedListeners.length; i<length; i++) {
17420
+
17421
+ // if listeners were deregistered, defragment the array
17422
+ if (!namedListeners[i]) {
17423
+ namedListeners.splice(i, 1);
17424
+ i--;
17425
+ length--;
17426
+ continue;
17427
+ }
17388
17428
  try {
17389
17429
  namedListeners[i].apply(null, listenerArgs);
17390
17430
  if (stopPropagation) return event;
@@ -17434,19 +17474,29 @@ function $RootScopeProvider(){
17434
17474
  },
17435
17475
  defaultPrevented: false
17436
17476
  },
17437
- listenerArgs = concat([event], arguments, 1);
17477
+ listenerArgs = concat([event], arguments, 1),
17478
+ listeners, i, length;
17438
17479
 
17439
17480
  //down while you can, then up and next sibling or up and next sibling until back at root
17440
17481
  do {
17441
17482
  current = next;
17442
17483
  event.currentScope = current;
17443
- forEach(current.$$listeners[name], function(listener) {
17484
+ listeners = current.$$listeners[name] || [];
17485
+ for (i=0, length = listeners.length; i<length; i++) {
17486
+ // if listeners were deregistered, defragment the array
17487
+ if (!listeners[i]) {
17488
+ listeners.splice(i, 1);
17489
+ i--;
17490
+ length--;
17491
+ continue;
17492
+ }
17493
+
17444
17494
  try {
17445
- listener.apply(null, listenerArgs);
17495
+ listeners[i].apply(null, listenerArgs);
17446
17496
  } catch(e) {
17447
17497
  $exceptionHandler(e);
17448
17498
  }
17449
- });
17499
+ }
17450
17500
 
17451
17501
  // Insanity Warning: scope depth-first traversal
17452
17502
  // yes, this code is a bit crazy, but it works and we have tests to prove it!
@@ -18554,7 +18604,7 @@ function $TimeoutProvider() {
18554
18604
  * @param {number=} [delay=0] Delay in milliseconds.
18555
18605
  * @param {boolean=} [invokeApply=true] If set to false skips model dirty checking, otherwise
18556
18606
  * will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.
18557
- * @returns {*} Promise that will be resolved when the timeout is reached. The value this
18607
+ * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this
18558
18608
  * promise will be resolved with is the return value of the `fn` function.
18559
18609
  */
18560
18610
  function timeout(fn, delay, invokeApply) {
@@ -18993,9 +19043,18 @@ function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {
18993
19043
  formatedText = '',
18994
19044
  parts = [];
18995
19045
 
19046
+ var hasExponent = false;
18996
19047
  if (numStr.indexOf('e') !== -1) {
18997
- formatedText = numStr;
18998
- } else {
19048
+ var match = numStr.match(/([\d\.]+)e(-?)(\d+)/);
19049
+ if (match && match[2] == '-' && match[3] > fractionSize + 1) {
19050
+ numStr = '0';
19051
+ } else {
19052
+ formatedText = numStr;
19053
+ hasExponent = true;
19054
+ }
19055
+ }
19056
+
19057
+ if (!hasExponent) {
18999
19058
  var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;
19000
19059
 
19001
19060
  // determine fractionSize if it is not specified
@@ -19196,7 +19255,7 @@ dateFilter.$inject = ['$locale'];
19196
19255
  function dateFilter($locale) {
19197
19256
 
19198
19257
 
19199
- var R_ISO8601_STR = /^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d{3}))?)?)?(Z|([+-])(\d\d):?(\d\d)))?$/;
19258
+ var R_ISO8601_STR = /^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/;
19200
19259
  function jsonStringToDate(string){
19201
19260
  var match;
19202
19261
  if (match = string.match(R_ISO8601_STR)) {
@@ -19575,6 +19634,7 @@ var htmlAnchorDirective = valueFn({
19575
19634
  // if we have no href url, then don't navigate anywhere.
19576
19635
  if (!element.attr('href')) {
19577
19636
  event.preventDefault();
19637
+ return false; // Needed for opera
19578
19638
  }
19579
19639
  });
19580
19640
  }
@@ -19865,7 +19925,7 @@ forEach(BOOLEAN_ATTR, function(propName, attrName) {
19865
19925
  priority: 100,
19866
19926
  compile: function() {
19867
19927
  return function(scope, element, attr) {
19868
- scope.$watch(attr[normalized], function(value) {
19928
+ scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {
19869
19929
  attr.$set(attrName, !!value);
19870
19930
  });
19871
19931
  };
@@ -19883,6 +19943,9 @@ forEach(['src', 'href'], function(attrName) {
19883
19943
  priority: 99, // it needs to run after the attributes are interpolated
19884
19944
  link: function(scope, element, attr) {
19885
19945
  attr.$observe(normalized, function(value) {
19946
+ if (!value)
19947
+ return;
19948
+
19886
19949
  attr.$set(attrName, value);
19887
19950
 
19888
19951
  // on IE, if "ng:src" directive declaration is used and "src" attribute doesn't exist
@@ -20011,6 +20074,7 @@ function FormController(element, attrs) {
20011
20074
  element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);
20012
20075
  form.$dirty = true;
20013
20076
  form.$pristine = false;
20077
+ parentForm.$setDirty();
20014
20078
  };
20015
20079
 
20016
20080
  }
@@ -20196,7 +20260,10 @@ var inputType = {
20196
20260
  *
20197
20261
  * @param {string} ngModel Assignable angular expression to data-bind to.
20198
20262
  * @param {string=} name Property name of the form under which the control is published.
20199
- * @param {string=} required Sets `required` validation error key if the value is not entered.
20263
+ * @param {string=} required Adds `required` validation error key if the value is not entered.
20264
+ * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
20265
+ * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
20266
+ * `required` when you want to data-bind to the `required` attribute.
20200
20267
  * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
20201
20268
  * minlength.
20202
20269
  * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
@@ -20266,6 +20333,9 @@ var inputType = {
20266
20333
  * @param {string=} min Sets the `min` validation error key if the value entered is less then `min`.
20267
20334
  * @param {string=} max Sets the `max` validation error key if the value entered is greater then `min`.
20268
20335
  * @param {string=} required Sets `required` validation error key if the value is not entered.
20336
+ * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
20337
+ * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
20338
+ * `required` when you want to data-bind to the `required` attribute.
20269
20339
  * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
20270
20340
  * minlength.
20271
20341
  * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
@@ -20332,6 +20402,9 @@ var inputType = {
20332
20402
  * @param {string} ngModel Assignable angular expression to data-bind to.
20333
20403
  * @param {string=} name Property name of the form under which the control is published.
20334
20404
  * @param {string=} required Sets `required` validation error key if the value is not entered.
20405
+ * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
20406
+ * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
20407
+ * `required` when you want to data-bind to the `required` attribute.
20335
20408
  * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
20336
20409
  * minlength.
20337
20410
  * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
@@ -20397,6 +20470,9 @@ var inputType = {
20397
20470
  * @param {string} ngModel Assignable angular expression to data-bind to.
20398
20471
  * @param {string=} name Property name of the form under which the control is published.
20399
20472
  * @param {string=} required Sets `required` validation error key if the value is not entered.
20473
+ * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
20474
+ * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
20475
+ * `required` when you want to data-bind to the `required` attribute.
20400
20476
  * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
20401
20477
  * minlength.
20402
20478
  * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
@@ -20819,6 +20895,9 @@ function checkboxInputType(scope, element, attr, ctrl) {
20819
20895
  * @param {string} ngModel Assignable angular expression to data-bind to.
20820
20896
  * @param {string=} name Property name of the form under which the control is published.
20821
20897
  * @param {string=} required Sets `required` validation error key if the value is not entered.
20898
+ * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
20899
+ * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
20900
+ * `required` when you want to data-bind to the `required` attribute.
20822
20901
  * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
20823
20902
  * minlength.
20824
20903
  * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
@@ -20843,6 +20922,7 @@ function checkboxInputType(scope, element, attr, ctrl) {
20843
20922
  * @param {string} ngModel Assignable angular expression to data-bind to.
20844
20923
  * @param {string=} name Property name of the form under which the control is published.
20845
20924
  * @param {string=} required Sets `required` validation error key if the value is not entered.
20925
+ * @param {boolean=} ngRequired Sets `required` attribute if set to true
20846
20926
  * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
20847
20927
  * minlength.
20848
20928
  * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
@@ -21176,22 +21256,25 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
21176
21256
 
21177
21257
  // model -> value
21178
21258
  var ctrl = this;
21179
- $scope.$watch(ngModelGet, function(value) {
21180
21259
 
21181
- // ignore change from view
21182
- if (ctrl.$modelValue === value) return;
21260
+ $scope.$watch(function ngModelWatch() {
21261
+ var value = ngModelGet($scope);
21183
21262
 
21184
- var formatters = ctrl.$formatters,
21185
- idx = formatters.length;
21263
+ // if scope model value and ngModel value are out of sync
21264
+ if (ctrl.$modelValue !== value) {
21186
21265
 
21187
- ctrl.$modelValue = value;
21188
- while(idx--) {
21189
- value = formatters[idx](value);
21190
- }
21266
+ var formatters = ctrl.$formatters,
21267
+ idx = formatters.length;
21191
21268
 
21192
- if (ctrl.$viewValue !== value) {
21193
- ctrl.$viewValue = value;
21194
- ctrl.$render();
21269
+ ctrl.$modelValue = value;
21270
+ while(idx--) {
21271
+ value = formatters[idx](value);
21272
+ }
21273
+
21274
+ if (ctrl.$viewValue !== value) {
21275
+ ctrl.$viewValue = value;
21276
+ ctrl.$render();
21277
+ }
21195
21278
  }
21196
21279
  });
21197
21280
  }];
@@ -21340,7 +21423,7 @@ var requiredDirective = function() {
21340
21423
  * @name ng.directive:ngList
21341
21424
  *
21342
21425
  * @description
21343
- * Text input that converts between comma-seperated string into an array of strings.
21426
+ * Text input that converts between comma-separated string into an array of strings.
21344
21427
  *
21345
21428
  * @element input
21346
21429
  * @param {string=} ngList optional delimiter that should be used to split the value. If
@@ -21423,7 +21506,7 @@ var ngValueDirective = function() {
21423
21506
  };
21424
21507
  } else {
21425
21508
  return function(scope, elm, attr) {
21426
- scope.$watch(attr.ngValue, function(value) {
21509
+ scope.$watch(attr.ngValue, function valueWatchAction(value) {
21427
21510
  attr.$set('value', value, false);
21428
21511
  });
21429
21512
  };
@@ -21481,7 +21564,7 @@ var ngValueDirective = function() {
21481
21564
  */
21482
21565
  var ngBindDirective = ngDirective(function(scope, element, attr) {
21483
21566
  element.addClass('ng-binding').data('$binding', attr.ngBind);
21484
- scope.$watch(attr.ngBind, function(value) {
21567
+ scope.$watch(attr.ngBind, function ngBindWatchAction(value) {
21485
21568
  element.text(value == undefined ? '' : value);
21486
21569
  });
21487
21570
  });
@@ -21564,7 +21647,7 @@ var ngBindTemplateDirective = ['$interpolate', function($interpolate) {
21564
21647
  var ngBindHtmlUnsafeDirective = [function() {
21565
21648
  return function(scope, element, attr) {
21566
21649
  element.addClass('ng-binding').data('$binding', attr.ngBindHtmlUnsafe);
21567
- scope.$watch(attr.ngBindHtmlUnsafe, function(value) {
21650
+ scope.$watch(attr.ngBindHtmlUnsafe, function ngBindHtmlUnsafeWatchAction(value) {
21568
21651
  element.html(value || '');
21569
21652
  });
21570
21653
  };
@@ -21573,17 +21656,55 @@ var ngBindHtmlUnsafeDirective = [function() {
21573
21656
  function classDirective(name, selector) {
21574
21657
  name = 'ngClass' + name;
21575
21658
  return ngDirective(function(scope, element, attr) {
21576
- scope.$watch(attr[name], function(newVal, oldVal) {
21659
+
21660
+ scope.$watch(attr[name], ngClassWatchAction, true);
21661
+
21662
+ attr.$observe('class', function(value) {
21663
+ var ngClass = scope.$eval(attr[name]);
21664
+ ngClassWatchAction(ngClass, ngClass);
21665
+ });
21666
+
21667
+
21668
+ if (name !== 'ngClass') {
21669
+ scope.$watch('$index', function($index, old$index) {
21670
+ var mod = $index % 2;
21671
+ if (mod !== old$index % 2) {
21672
+ if (mod == selector) {
21673
+ addClass(scope.$eval(attr[name]));
21674
+ } else {
21675
+ removeClass(scope.$eval(attr[name]));
21676
+ }
21677
+ }
21678
+ });
21679
+ }
21680
+
21681
+
21682
+ function ngClassWatchAction(newVal, oldVal) {
21577
21683
  if (selector === true || scope.$index % 2 === selector) {
21578
21684
  if (oldVal && (newVal !== oldVal)) {
21579
- if (isObject(oldVal) && !isArray(oldVal))
21580
- oldVal = map(oldVal, function(v, k) { if (v) return k });
21581
- element.removeClass(isArray(oldVal) ? oldVal.join(' ') : oldVal);
21582
- }
21583
- if (isObject(newVal) && !isArray(newVal))
21584
- newVal = map(newVal, function(v, k) { if (v) return k });
21585
- if (newVal) element.addClass(isArray(newVal) ? newVal.join(' ') : newVal); }
21586
- }, true);
21685
+ removeClass(oldVal);
21686
+ }
21687
+ addClass(newVal);
21688
+ }
21689
+ }
21690
+
21691
+
21692
+ function removeClass(classVal) {
21693
+ if (isObject(classVal) && !isArray(classVal)) {
21694
+ classVal = map(classVal, function(v, k) { if (v) return k });
21695
+ }
21696
+ element.removeClass(isArray(classVal) ? classVal.join(' ') : classVal);
21697
+ }
21698
+
21699
+
21700
+ function addClass(classVal) {
21701
+ if (isObject(classVal) && !isArray(classVal)) {
21702
+ classVal = map(classVal, function(v, k) { if (v) return k });
21703
+ }
21704
+ if (classVal) {
21705
+ element.addClass(isArray(classVal) ? classVal.join(' ') : classVal);
21706
+ }
21707
+ }
21587
21708
  });
21588
21709
  }
21589
21710
 
@@ -22242,7 +22363,7 @@ var ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile'
22242
22363
  element.html('');
22243
22364
  };
22244
22365
 
22245
- scope.$watch(srcExp, function(src) {
22366
+ scope.$watch(srcExp, function ngIncludeWatchAction(src) {
22246
22367
  var thisChangeId = ++changeCounter;
22247
22368
 
22248
22369
  if (src) {
@@ -22527,7 +22648,7 @@ var ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interp
22527
22648
  offset + endSymbol));
22528
22649
  });
22529
22650
 
22530
- scope.$watch(function() {
22651
+ scope.$watch(function ngPluralizeWatch() {
22531
22652
  var value = parseFloat(scope.$eval(numberExp));
22532
22653
 
22533
22654
  if (!isNaN(value)) {
@@ -22538,7 +22659,7 @@ var ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interp
22538
22659
  } else {
22539
22660
  return '';
22540
22661
  }
22541
- }, function(newVal) {
22662
+ }, function ngPluralizeWatchAction(newVal) {
22542
22663
  element.text(newVal);
22543
22664
  });
22544
22665
  }
@@ -22633,7 +22754,8 @@ var ngRepeatDirective = ngDirective({
22633
22754
  // We need an array of these objects since the same object can be returned from the iterator.
22634
22755
  // We expect this to be a rare case.
22635
22756
  var lastOrder = new HashQueueMap();
22636
- scope.$watch(function(scope){
22757
+
22758
+ scope.$watch(function ngRepeatWatch(scope){
22637
22759
  var index, length,
22638
22760
  collection = scope.$eval(rhs),
22639
22761
  collectionLength = size(collection, true),
@@ -22662,7 +22784,9 @@ var ngRepeatDirective = ngDirective({
22662
22784
  for (index = 0, length = array.length; index < length; index++) {
22663
22785
  key = (collection === array) ? index : array[index];
22664
22786
  value = collection[key];
22787
+
22665
22788
  last = lastOrder.shift(value);
22789
+
22666
22790
  if (last) {
22667
22791
  // if we have already seen this object, then we need to reuse the
22668
22792
  // associated scope/element
@@ -22759,7 +22883,7 @@ var ngRepeatDirective = ngDirective({
22759
22883
  */
22760
22884
  //TODO(misko): refactor to remove element from the DOM
22761
22885
  var ngShowDirective = ngDirective(function(scope, element, attr){
22762
- scope.$watch(attr.ngShow, function(value){
22886
+ scope.$watch(attr.ngShow, function ngShowWatchAction(value){
22763
22887
  element.css('display', toBoolean(value) ? '' : 'none');
22764
22888
  });
22765
22889
  });
@@ -22770,11 +22894,11 @@ var ngShowDirective = ngDirective(function(scope, element, attr){
22770
22894
  * @name ng.directive:ngHide
22771
22895
  *
22772
22896
  * @description
22773
- * The `ngHide` and `ngShow` directives hide or show a portion
22774
- * of the HTML conditionally.
22897
+ * The `ngHide` and `ngShow` directives hide or show a portion of the DOM tree (HTML)
22898
+ * conditionally.
22775
22899
  *
22776
22900
  * @element ANY
22777
- * @param {expression} ngHide If the {@link guide/expression expression} truthy then
22901
+ * @param {expression} ngHide If the {@link guide/expression expression} is truthy then
22778
22902
  * the element is shown or hidden respectively.
22779
22903
  *
22780
22904
  * @example
@@ -22799,7 +22923,7 @@ var ngShowDirective = ngDirective(function(scope, element, attr){
22799
22923
  */
22800
22924
  //TODO(misko): refactor to remove element from the DOM
22801
22925
  var ngHideDirective = ngDirective(function(scope, element, attr){
22802
- scope.$watch(attr.ngHide, function(value){
22926
+ scope.$watch(attr.ngHide, function ngHideWatchAction(value){
22803
22927
  element.css('display', toBoolean(value) ? 'none' : '');
22804
22928
  });
22805
22929
  });
@@ -22842,7 +22966,7 @@ var ngHideDirective = ngDirective(function(scope, element, attr){
22842
22966
  </example>
22843
22967
  */
22844
22968
  var ngStyleDirective = ngDirective(function(scope, element, attr) {
22845
- scope.$watch(attr.ngStyle, function(newStyles, oldStyles) {
22969
+ scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {
22846
22970
  if (oldStyles && (newStyles !== oldStyles)) {
22847
22971
  forEach(oldStyles, function(val, style) { element.css(style, '');});
22848
22972
  }
@@ -22922,7 +23046,7 @@ var ngSwitchDirective = valueFn({
22922
23046
  selectedElement,
22923
23047
  selectedScope;
22924
23048
 
22925
- scope.$watch(watchExpr, function(value) {
23049
+ scope.$watch(watchExpr, function ngSwitchWatchAction(value) {
22926
23050
  if (selectedElement) {
22927
23051
  selectedScope.$destroy();
22928
23052
  selectedElement.remove();
@@ -23256,6 +23380,9 @@ var scriptDirective = ['$templateCache', function($templateCache) {
23256
23380
  *
23257
23381
  * @param {string} name assignable expression to data-bind to.
23258
23382
  * @param {string=} required The control is considered valid only if value is entered.
23383
+ * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
23384
+ * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
23385
+ * `required` when you want to data-bind to the `required` attribute.
23259
23386
  * @param {comprehension_expression=} ngOptions in one of the following forms:
23260
23387
  *
23261
23388
  * * for array data sources:
@@ -23496,7 +23623,7 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
23496
23623
 
23497
23624
  // we have to do it on each watch since ngModel watches reference, but
23498
23625
  // we need to work of an array, so we need to see if anything was inserted/removed
23499
- scope.$watch(function() {
23626
+ scope.$watch(function selectMultipleWatch() {
23500
23627
  if (!equals(lastView, ctrl.$viewValue)) {
23501
23628
  lastView = copy(ctrl.$viewValue);
23502
23629
  ctrl.$render();
@@ -23613,7 +23740,8 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
23613
23740
  selected,
23614
23741
  selectedSet = false, // nothing is selected yet
23615
23742
  lastElement,
23616
- element;
23743
+ element,
23744
+ label;
23617
23745
 
23618
23746
  if (multiple) {
23619
23747
  selectedSet = new HashMap(modelValue);
@@ -23637,9 +23765,11 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
23637
23765
  selected = modelValue === valueFn(scope, locals);
23638
23766
  selectedSet = selectedSet || selected; // see if at least one item is selected
23639
23767
  }
23768
+ label = displayFn(scope, locals); // what will be seen by the user
23769
+ label = label === undefined ? '' : label; // doing displayFn(scope, locals) || '' overwrites zero values
23640
23770
  optionGroup.push({
23641
23771
  id: keyName ? keys[index] : index, // either the index into array or key from object
23642
- label: displayFn(scope, locals) || '', // what will be seen by the user
23772
+ label: label,
23643
23773
  selected: selected // determine if we should be selected
23644
23774
  });
23645
23775
  }
@@ -23771,7 +23901,7 @@ var optionDirective = ['$interpolate', function($interpolate) {
23771
23901
  }
23772
23902
 
23773
23903
  if (interpolateFn) {
23774
- scope.$watch(interpolateFn, function(newVal, oldVal) {
23904
+ scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {
23775
23905
  attr.$set('value', newVal);
23776
23906
  if (newVal !== oldVal) selectCtrl.removeOption(oldVal);
23777
23907
  selectCtrl.addOption(newVal);
@@ -24086,10 +24216,11 @@ function browserTrigger(element, type, keys) {
24086
24216
  iframe = _jQuery('#application iframe')[0],
24087
24217
  appWindow = iframe ? iframe.contentWindow : window,
24088
24218
  fakeProcessDefault = true,
24089
- finalProcessDefault;
24219
+ finalProcessDefault,
24220
+ angular = appWindow.angular || {};
24090
24221
 
24091
24222
  // igor: temporary fix for https://bugzilla.mozilla.org/show_bug.cgi?id=684208
24092
- appWindow.angular['ff-684208-preventDefault'] = false;
24223
+ angular['ff-684208-preventDefault'] = false;
24093
24224
  evnt.preventDefault = function() {
24094
24225
  fakeProcessDefault = false;
24095
24226
  return originalPreventDefault.apply(evnt, arguments);
@@ -24099,9 +24230,9 @@ function browserTrigger(element, type, keys) {
24099
24230
  pressed('shift'), pressed('meta'), 0, element);
24100
24231
 
24101
24232
  element.dispatchEvent(evnt);
24102
- finalProcessDefault = !(appWindow.angular['ff-684208-preventDefault'] || !fakeProcessDefault);
24233
+ finalProcessDefault = !(angular['ff-684208-preventDefault'] || !fakeProcessDefault);
24103
24234
 
24104
- delete appWindow.angular['ff-684208-preventDefault'];
24235
+ delete angular['ff-684208-preventDefault'];
24105
24236
 
24106
24237
  return finalProcessDefault;
24107
24238
  }
@@ -24637,6 +24768,9 @@ angular.scenario.ObjectModel = function(runner) {
24637
24768
  self.emit('StepError', it, modelStep, error);
24638
24769
  });
24639
24770
 
24771
+ runner.on('RunnerBegin', function() {
24772
+ self.emit('RunnerBegin');
24773
+ });
24640
24774
  runner.on('RunnerEnd', function() {
24641
24775
  self.emit('RunnerEnd');
24642
24776
  });
@@ -25276,7 +25410,9 @@ angular.scenario.SpecRunner.prototype.addFutureAction = function(name, behavior,
25276
25410
  });
25277
25411
  var result = $document.find(selector);
25278
25412
  if (selector.match(NG)) {
25279
- result = result.add(selector.replace(NG, '[ng-'), $document);
25413
+ angular.forEach(['[ng-','[data-ng-','[x-ng-'], function(value, index){
25414
+ result = result.add(selector.replace(NG, value), $document);
25415
+ });
25280
25416
  }
25281
25417
  if (!result.length) {
25282
25418
  throw {