angularjs-rails 1.3.10 → 1.3.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. checksums.yaml +4 -4
  2. data/lib/angularjs-rails/version.rb +2 -2
  3. data/vendor/assets/javascripts/angular-animate.js +2 -3
  4. data/vendor/assets/javascripts/angular-aria.js +16 -6
  5. data/vendor/assets/javascripts/angular-cookies.js +1 -1
  6. data/vendor/assets/javascripts/angular-loader.js +2 -2
  7. data/vendor/assets/javascripts/angular-messages.js +1 -1
  8. data/vendor/assets/javascripts/angular-mocks.js +15 -1
  9. data/vendor/assets/javascripts/angular-resource.js +2 -1
  10. data/vendor/assets/javascripts/angular-route.js +5 -11
  11. data/vendor/assets/javascripts/angular-sanitize.js +15 -27
  12. data/vendor/assets/javascripts/angular-scenario.js +243 -138
  13. data/vendor/assets/javascripts/angular-touch.js +1 -1
  14. data/vendor/assets/javascripts/angular.js +209 -119
  15. data/vendor/assets/javascripts/unstable/angular-animate.js +2 -3
  16. data/vendor/assets/javascripts/unstable/angular-aria.js +16 -6
  17. data/vendor/assets/javascripts/unstable/angular-cookies.js +1 -1
  18. data/vendor/assets/javascripts/unstable/angular-loader.js +2 -2
  19. data/vendor/assets/javascripts/unstable/angular-messages.js +1 -1
  20. data/vendor/assets/javascripts/unstable/angular-mocks.js +15 -1
  21. data/vendor/assets/javascripts/unstable/angular-resource.js +2 -1
  22. data/vendor/assets/javascripts/unstable/angular-route.js +5 -11
  23. data/vendor/assets/javascripts/unstable/angular-sanitize.js +15 -27
  24. data/vendor/assets/javascripts/unstable/angular-scenario.js +243 -138
  25. data/vendor/assets/javascripts/unstable/angular-touch.js +1 -1
  26. data/vendor/assets/javascripts/unstable/angular.js +209 -119
  27. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5a121dbbf6f1ca3f7e7398f18c2dc67475ef4747
4
- data.tar.gz: 4156411033215270bb5a45f65efd6b5e92cc3ae3
3
+ metadata.gz: 902ca9439ac5c7f5fc4a004f907c1cb801b8279b
4
+ data.tar.gz: e36f2acd15fcc9e3bcb28416b2bdcb50f6a94999
5
5
  SHA512:
6
- metadata.gz: b1d0ecd81cd37e143a25d9a1dbfff375a89b4e0eede79dcfecf37bc0539a685d97d125bdfb647046d0211ca1c509fdd7abb52f3399f7594945b14c9b8549d167
7
- data.tar.gz: 27032be69e3320d65b331e8e93a265201d1b81060a4648919d620eb9d862fa5ede2fd1d3dffabd3e6c1d9b7883794a49cdd57ad731dd28cd28683df58306f7f9
6
+ metadata.gz: 8e2f1975d21dd4a3d855cfbc3f1bae230d08d1b1ac8b9ed406c22b13be26901c1b364b13e40dd95a22e766861d070f976686d23bec61d2531b82e68b5d98a043
7
+ data.tar.gz: 890c3d008ccff40296f22e4e67e7c36f8dc895da223338e86188f3237e8e3f0771bf2afd8d1249f9293656c2108695d0e8eef171d82051039fba6da28540b28a
@@ -1,6 +1,6 @@
1
1
  module AngularJS
2
2
  module Rails
3
- VERSION = "1.3.10"
4
- UNSTABLE_VERSION = "1.3.10"
3
+ VERSION = "1.3.14"
4
+ UNSTABLE_VERSION = "1.3.14"
5
5
  end
6
6
  end
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.3.10
2
+ * @license AngularJS v1.3.14
3
3
  * (c) 2010-2014 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -1333,8 +1333,7 @@ angular.module('ngAnimate', ['ng'])
1333
1333
  } else if (lastAnimation.event == 'setClass') {
1334
1334
  animationsToCancel.push(lastAnimation);
1335
1335
  cleanup(element, className);
1336
- }
1337
- else if (runningAnimations[className]) {
1336
+ } else if (runningAnimations[className]) {
1338
1337
  var current = runningAnimations[className];
1339
1338
  if (current.event == animationEvent) {
1340
1339
  skipAnimation = true;
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.3.10
2
+ * @license AngularJS v1.3.14
3
3
  * (c) 2010-2014 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -105,7 +105,8 @@ function $AriaProvider() {
105
105
  * - **ariaMultiline** – `{boolean}` – Enables/disables aria-multiline tags
106
106
  * - **ariaValue** – `{boolean}` – Enables/disables aria-valuemin, aria-valuemax and aria-valuenow tags
107
107
  * - **tabindex** – `{boolean}` – Enables/disables tabindex tags
108
- * - **bindKeypress** – `{boolean}` – Enables/disables keypress event binding on ng-click
108
+ * - **bindKeypress** – `{boolean}` – Enables/disables keypress event binding on `<div>` and
109
+ * `<li>` elements with ng-click
109
110
  *
110
111
  * @description
111
112
  * Enables/disables various ARIA attributes
@@ -133,6 +134,7 @@ function $AriaProvider() {
133
134
  * @name $aria
134
135
  *
135
136
  * @description
137
+ * @priority 200
136
138
  *
137
139
  * The $aria service contains helper methods for applying common
138
140
  * [ARIA](http://www.w3.org/TR/wai-aria/) attributes to HTML directives.
@@ -209,6 +211,7 @@ ngAriaModule.directive('ngShow', ['$aria', function($aria) {
209
211
  return {
210
212
  restrict: 'A',
211
213
  require: '?ngModel',
214
+ priority: 200, //Make sure watches are fired after any other directives that affect the ngModel value
212
215
  link: function(scope, elem, attr, ngModel) {
213
216
  var shape = getShape(attr, elem);
214
217
  var needsTabIndex = shouldAttachAttr('tabindex', 'tabindex', elem);
@@ -221,19 +224,19 @@ ngAriaModule.directive('ngShow', ['$aria', function($aria) {
221
224
  if (needsTabIndex) {
222
225
  needsTabIndex = false;
223
226
  return function ngAriaRadioReaction(newVal) {
224
- var boolVal = newVal === attr.value;
227
+ var boolVal = (attr.value == ngModel.$viewValue);
225
228
  elem.attr('aria-checked', boolVal);
226
229
  elem.attr('tabindex', 0 - !boolVal);
227
230
  };
228
231
  } else {
229
232
  return function ngAriaRadioReaction(newVal) {
230
- elem.attr('aria-checked', newVal === attr.value);
233
+ elem.attr('aria-checked', (attr.value == ngModel.$viewValue));
231
234
  };
232
235
  }
233
236
  }
234
237
 
235
238
  function ngAriaCheckboxReaction(newVal) {
236
- elem.attr('aria-checked', !!newVal);
239
+ elem.attr('aria-checked', !ngModel.$isEmpty(ngModel.$viewValue));
237
240
  }
238
241
 
239
242
  switch (shape) {
@@ -308,11 +311,18 @@ ngAriaModule.directive('ngShow', ['$aria', function($aria) {
308
311
  compile: function(elem, attr) {
309
312
  var fn = $parse(attr.ngClick, /* interceptorFn */ null, /* expensiveChecks */ true);
310
313
  return function(scope, elem, attr) {
314
+
315
+ function isNodeOneOf(elem, nodeTypeArray) {
316
+ if (nodeTypeArray.indexOf(elem[0].nodeName) !== -1) {
317
+ return true;
318
+ }
319
+ }
320
+
311
321
  if ($aria.config('tabindex') && !elem.attr('tabindex')) {
312
322
  elem.attr('tabindex', 0);
313
323
  }
314
324
 
315
- if ($aria.config('bindKeypress') && !attr.ngKeypress) {
325
+ if ($aria.config('bindKeypress') && !attr.ngKeypress && isNodeOneOf(elem, ['DIV', 'LI'])) {
316
326
  elem.on('keypress', function(event) {
317
327
  if (event.keyCode === 32 || event.keyCode === 13) {
318
328
  scope.$apply(callback);
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.3.10
2
+ * @license AngularJS v1.3.14
3
3
  * (c) 2010-2014 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.3.10
2
+ * @license AngularJS v1.3.14
3
3
  * (c) 2010-2014 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -55,7 +55,7 @@ function minErr(module, ErrorConstructor) {
55
55
  return match;
56
56
  });
57
57
 
58
- message = message + '\nhttp://errors.angularjs.org/1.3.10/' +
58
+ message = message + '\nhttp://errors.angularjs.org/1.3.14/' +
59
59
  (module ? module + '/' : '') + code;
60
60
  for (i = 2; i < arguments.length; i++) {
61
61
  message = message + (i == 2 ? '?' : '&') + 'p' + (i - 2) + '=' +
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.3.10
2
+ * @license AngularJS v1.3.14
3
3
  * (c) 2010-2014 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.3.10
2
+ * @license AngularJS v1.3.14
3
3
  * (c) 2010-2014 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -2134,18 +2134,32 @@ angular.mock.$RootScopeDecorator = ['$delegate', function($delegate) {
2134
2134
  if (window.jasmine || window.mocha) {
2135
2135
 
2136
2136
  var currentSpec = null,
2137
+ annotatedFunctions = [],
2137
2138
  isSpecRunning = function() {
2138
2139
  return !!currentSpec;
2139
2140
  };
2140
2141
 
2142
+ angular.mock.$$annotate = angular.injector.$$annotate;
2143
+ angular.injector.$$annotate = function(fn) {
2144
+ if (typeof fn === 'function' && !fn.$inject) {
2145
+ annotatedFunctions.push(fn);
2146
+ }
2147
+ return angular.mock.$$annotate.apply(this, arguments);
2148
+ };
2149
+
2141
2150
 
2142
2151
  (window.beforeEach || window.setup)(function() {
2152
+ annotatedFunctions = [];
2143
2153
  currentSpec = this;
2144
2154
  });
2145
2155
 
2146
2156
  (window.afterEach || window.teardown)(function() {
2147
2157
  var injector = currentSpec.$injector;
2148
2158
 
2159
+ annotatedFunctions.forEach(function(fn) {
2160
+ delete fn.$inject;
2161
+ });
2162
+
2149
2163
  angular.forEach(currentSpec.$modules, function(module) {
2150
2164
  if (module && module.$$hashKey) {
2151
2165
  module.$$hashKey = undefined;
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.3.10
2
+ * @license AngularJS v1.3.14
3
3
  * (c) 2010-2014 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -213,6 +213,7 @@ function shallowClearAndCopy(src, dst) {
213
213
  * - non-GET "class" actions: `Resource.action([parameters], postData, [success], [error])`
214
214
  * - non-GET instance actions: `instance.$action([parameters], [success], [error])`
215
215
  *
216
+ *
216
217
  * Success callback is called with (value, responseHeaders) arguments. Error callback is called
217
218
  * with (httpResponse) argument.
218
219
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.3.10
2
+ * @license AngularJS v1.3.14
3
3
  * (c) 2010-2014 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -482,21 +482,15 @@ function $RouteProvider() {
482
482
  * definitions will be interpolated into the location's path, while
483
483
  * remaining properties will be treated as query params.
484
484
  *
485
- * @param {Object} newParams mapping of URL parameter names to values
485
+ * @param {!Object<string, string>} newParams mapping of URL parameter names to values
486
486
  */
487
487
  updateParams: function(newParams) {
488
488
  if (this.current && this.current.$$route) {
489
- var searchParams = {}, self=this;
490
-
491
- angular.forEach(Object.keys(newParams), function(key) {
492
- if (!self.current.pathParams[key]) searchParams[key] = newParams[key];
493
- });
494
-
495
489
  newParams = angular.extend({}, this.current.params, newParams);
496
490
  $location.path(interpolate(this.current.$$route.originalPath, newParams));
497
- $location.search(angular.extend({}, $location.search(), searchParams));
498
- }
499
- else {
491
+ // interpolate modifies newParams, only query params are left
492
+ $location.search(newParams);
493
+ } else {
500
494
  throw $routeMinErr('norout', 'Tried updating route when with no current route');
501
495
  }
502
496
  }
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.3.10
2
+ * @license AngularJS v1.3.14
3
3
  * (c) 2010-2014 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -276,14 +276,14 @@ function htmlParser(html, handler) {
276
276
  }
277
277
  }
278
278
  var index, chars, match, stack = [], last = html, text;
279
- stack.last = function() { return stack[ stack.length - 1 ]; };
279
+ stack.last = function() { return stack[stack.length - 1]; };
280
280
 
281
281
  while (html) {
282
282
  text = '';
283
283
  chars = true;
284
284
 
285
285
  // Make sure we're not in a script or style element
286
- if (!stack.last() || !specialElements[ stack.last() ]) {
286
+ if (!stack.last() || !specialElements[stack.last()]) {
287
287
 
288
288
  // Comment
289
289
  if (html.indexOf("<!--") === 0) {
@@ -341,7 +341,8 @@ function htmlParser(html, handler) {
341
341
  }
342
342
 
343
343
  } else {
344
- html = html.replace(new RegExp("(.*)<\\s*\\/\\s*" + stack.last() + "[^>]*>", 'i'),
344
+ // IE versions 9 and 10 do not understand the regex '[^]', so using a workaround with [\W\w].
345
+ html = html.replace(new RegExp("([\\W\\w]*)<\\s*\\/\\s*" + stack.last() + "[^>]*>", 'i'),
345
346
  function(all, text) {
346
347
  text = text.replace(COMMENT_REGEXP, "$1").replace(CDATA_REGEXP, "$1");
347
348
 
@@ -365,17 +366,17 @@ function htmlParser(html, handler) {
365
366
 
366
367
  function parseStartTag(tag, tagName, rest, unary) {
367
368
  tagName = angular.lowercase(tagName);
368
- if (blockElements[ tagName ]) {
369
- while (stack.last() && inlineElements[ stack.last() ]) {
369
+ if (blockElements[tagName]) {
370
+ while (stack.last() && inlineElements[stack.last()]) {
370
371
  parseEndTag("", stack.last());
371
372
  }
372
373
  }
373
374
 
374
- if (optionalEndTagElements[ tagName ] && stack.last() == tagName) {
375
+ if (optionalEndTagElements[tagName] && stack.last() == tagName) {
375
376
  parseEndTag("", tagName);
376
377
  }
377
378
 
378
- unary = voidElements[ tagName ] || !!unary;
379
+ unary = voidElements[tagName] || !!unary;
379
380
 
380
381
  if (!unary)
381
382
  stack.push(tagName);
@@ -400,13 +401,13 @@ function htmlParser(html, handler) {
400
401
  if (tagName)
401
402
  // Find the closest opened tag of the same type
402
403
  for (pos = stack.length - 1; pos >= 0; pos--)
403
- if (stack[ pos ] == tagName)
404
+ if (stack[pos] == tagName)
404
405
  break;
405
406
 
406
407
  if (pos >= 0) {
407
408
  // Close all the open elements, up the stack
408
409
  for (i = stack.length - 1; i >= pos; i--)
409
- if (handler.end) handler.end(stack[ i ]);
410
+ if (handler.end) handler.end(stack[i]);
410
411
 
411
412
  // Remove the open elements from the stack
412
413
  stack.length = pos;
@@ -415,7 +416,6 @@ function htmlParser(html, handler) {
415
416
  }
416
417
 
417
418
  var hiddenPre=document.createElement("pre");
418
- var spaceRe = /^(\s*)([\s\S]*?)(\s*)$/;
419
419
  /**
420
420
  * decodes all entities into regular string
421
421
  * @param value
@@ -424,22 +424,10 @@ var spaceRe = /^(\s*)([\s\S]*?)(\s*)$/;
424
424
  function decodeEntities(value) {
425
425
  if (!value) { return ''; }
426
426
 
427
- // Note: IE8 does not preserve spaces at the start/end of innerHTML
428
- // so we must capture them and reattach them afterward
429
- var parts = spaceRe.exec(value);
430
- var spaceBefore = parts[1];
431
- var spaceAfter = parts[3];
432
- var content = parts[2];
433
- if (content) {
434
- hiddenPre.innerHTML=content.replace(/</g,"&lt;");
435
- // innerText depends on styling as it doesn't display hidden elements.
436
- // Therefore, it's better to use textContent not to cause unnecessary
437
- // reflows. However, IE<9 don't support textContent so the innerText
438
- // fallback is necessary.
439
- content = 'textContent' in hiddenPre ?
440
- hiddenPre.textContent : hiddenPre.innerText;
441
- }
442
- return spaceBefore + content + spaceAfter;
427
+ hiddenPre.innerHTML = value.replace(/</g,"&lt;");
428
+ // innerText depends on styling as it doesn't display hidden elements.
429
+ // Therefore, it's better to use textContent not to cause unnecessary reflows.
430
+ return hiddenPre.textContent;
443
431
  }
444
432
 
445
433
  /**
@@ -9190,7 +9190,7 @@ return jQuery;
9190
9190
  }));
9191
9191
 
9192
9192
  /**
9193
- * @license AngularJS v1.3.10
9193
+ * @license AngularJS v1.3.14
9194
9194
  * (c) 2010-2014 Google, Inc. http://angularjs.org
9195
9195
  * License: MIT
9196
9196
  */
@@ -9246,7 +9246,7 @@ function minErr(module, ErrorConstructor) {
9246
9246
  return match;
9247
9247
  });
9248
9248
 
9249
- message = message + '\nhttp://errors.angularjs.org/1.3.10/' +
9249
+ message = message + '\nhttp://errors.angularjs.org/1.3.14/' +
9250
9250
  (module ? module + '/' : '') + code;
9251
9251
  for (i = 2; i < arguments.length; i++) {
9252
9252
  message = message + (i == 2 ? '?' : '&') + 'p' + (i - 2) + '=' +
@@ -9573,8 +9573,7 @@ function nextUid() {
9573
9573
  function setHashKey(obj, h) {
9574
9574
  if (h) {
9575
9575
  obj.$$hashKey = h;
9576
- }
9577
- else {
9576
+ } else {
9578
9577
  delete obj.$$hashKey;
9579
9578
  }
9580
9579
  }
@@ -9883,7 +9882,7 @@ function isElement(node) {
9883
9882
  function makeMap(str) {
9884
9883
  var obj = {}, items = str.split(","), i;
9885
9884
  for (i = 0; i < items.length; i++)
9886
- obj[ items[i] ] = true;
9885
+ obj[items[i]] = true;
9887
9886
  return obj;
9888
9887
  }
9889
9888
 
@@ -10664,8 +10663,12 @@ function bootstrap(element, modules, config) {
10664
10663
  forEach(extraModules, function(module) {
10665
10664
  modules.push(module);
10666
10665
  });
10667
- doBootstrap();
10666
+ return doBootstrap();
10668
10667
  };
10668
+
10669
+ if (isFunction(angular.resumeDeferredBootstrap)) {
10670
+ angular.resumeDeferredBootstrap();
10671
+ }
10669
10672
  }
10670
10673
 
10671
10674
  /**
@@ -11310,11 +11313,11 @@ function toDebugString(obj) {
11310
11313
  * - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat".
11311
11314
  */
11312
11315
  var version = {
11313
- full: '1.3.10', // all of these placeholder strings will be replaced by grunt's
11316
+ full: '1.3.14', // all of these placeholder strings will be replaced by grunt's
11314
11317
  major: 1, // package task
11315
11318
  minor: 3,
11316
- dot: 10,
11317
- codeName: 'heliotropic-sundial'
11319
+ dot: 14,
11320
+ codeName: 'instantaneous-browserification'
11318
11321
  };
11319
11322
 
11320
11323
 
@@ -13349,7 +13352,7 @@ function createInjector(modulesToLoad, strictDi) {
13349
13352
  }
13350
13353
 
13351
13354
  var args = [],
13352
- $inject = annotate(fn, strictDi, serviceName),
13355
+ $inject = createInjector.$$annotate(fn, strictDi, serviceName),
13353
13356
  length, i,
13354
13357
  key;
13355
13358
 
@@ -13388,7 +13391,7 @@ function createInjector(modulesToLoad, strictDi) {
13388
13391
  invoke: invoke,
13389
13392
  instantiate: instantiate,
13390
13393
  get: getService,
13391
- annotate: annotate,
13394
+ annotate: createInjector.$$annotate,
13392
13395
  has: function(name) {
13393
13396
  return providerCache.hasOwnProperty(name + providerSuffix) || cache.hasOwnProperty(name);
13394
13397
  }
@@ -17062,8 +17065,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
17062
17065
  afterTemplateChildLinkFn,
17063
17066
  beforeTemplateCompileNode = $compileNode[0],
17064
17067
  origAsyncDirective = directives.shift(),
17065
- // The fact that we have to copy and patch the directive seems wrong!
17066
- derivedSyncDirective = extend({}, origAsyncDirective, {
17068
+ derivedSyncDirective = inherit(origAsyncDirective, {
17067
17069
  templateUrl: null, transclude: null, replace: null, $$originalDirective: origAsyncDirective
17068
17070
  }),
17069
17071
  templateUrl = (isFunction(origAsyncDirective.templateUrl))
@@ -17516,6 +17518,8 @@ function removeComments(jqNodes) {
17516
17518
  return jqNodes;
17517
17519
  }
17518
17520
 
17521
+ var $controllerMinErr = minErr('$controller');
17522
+
17519
17523
  /**
17520
17524
  * @ngdoc provider
17521
17525
  * @name $controllerProvider
@@ -17603,7 +17607,12 @@ function $ControllerProvider() {
17603
17607
  }
17604
17608
 
17605
17609
  if (isString(expression)) {
17606
- match = expression.match(CNTRL_REG),
17610
+ match = expression.match(CNTRL_REG);
17611
+ if (!match) {
17612
+ throw $controllerMinErr('ctrlfmt',
17613
+ "Badly formed controller string '{0}'. " +
17614
+ "Must match `__name__ as __id__` or `__name__`.", expression);
17615
+ }
17607
17616
  constructor = match[1],
17608
17617
  identifier = identifier || match[3];
17609
17618
  expression = controllers.hasOwnProperty(constructor)
@@ -20512,7 +20521,7 @@ function $LocationProvider() {
20512
20521
  // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)
20513
20522
  // currently we open nice url link and redirect then
20514
20523
 
20515
- if (!html5Mode.rewriteLinks || event.ctrlKey || event.metaKey || event.which == 2) return;
20524
+ if (!html5Mode.rewriteLinks || event.ctrlKey || event.metaKey || event.shiftKey || event.which == 2 || event.button == 2) return;
20516
20525
 
20517
20526
  var elm = jqLite(event.target);
20518
20527
 
@@ -20554,7 +20563,7 @@ function $LocationProvider() {
20554
20563
 
20555
20564
 
20556
20565
  // rewrite hashbang url <> html5 url
20557
- if ($location.absUrl() != initialUrl) {
20566
+ if (trimEmptyHash($location.absUrl()) != trimEmptyHash(initialUrl)) {
20558
20567
  $browser.url($location.absUrl(), true);
20559
20568
  }
20560
20569
 
@@ -21528,6 +21537,11 @@ Parser.prototype = {
21528
21537
  ? fn.apply(context, args)
21529
21538
  : fn(args[0], args[1], args[2], args[3], args[4]);
21530
21539
 
21540
+ if (args) {
21541
+ // Free-up the memory (arguments of the last function call).
21542
+ args.length = 0;
21543
+ }
21544
+
21531
21545
  return ensureSafeObject(v, expressionText);
21532
21546
  };
21533
21547
  },
@@ -22399,8 +22413,7 @@ function qFactory(nextTick, exceptionHandler) {
22399
22413
  'qcycle',
22400
22414
  "Expected promise to be resolved with value other than itself '{0}'",
22401
22415
  val));
22402
- }
22403
- else {
22416
+ } else {
22404
22417
  this.$$resolve(val);
22405
22418
  }
22406
22419
 
@@ -26857,6 +26870,9 @@ var htmlAnchorDirective = valueFn({
26857
26870
  compile: function(element, attr) {
26858
26871
  if (!attr.href && !attr.xlinkHref && !attr.name) {
26859
26872
  return function(scope, element) {
26873
+ // If the linked element is not an anchor tag anymore, do nothing
26874
+ if (element[0].nodeName.toLowerCase() !== 'a') return;
26875
+
26860
26876
  // SVGAElement does not use the href attribute, but rather the 'xlinkHref' attribute.
26861
26877
  var href = toString.call(element.prop('href')) === '[object SVGAnimatedString]' ?
26862
26878
  'xlink:href' : 'href';
@@ -27030,20 +27046,23 @@ var htmlAnchorDirective = valueFn({
27030
27046
  *
27031
27047
  * @description
27032
27048
  *
27033
- * We shouldn't do this, because it will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:
27049
+ * This directive sets the `disabled` attribute on the element if the
27050
+ * {@link guide/expression expression} inside `ngDisabled` evaluates to truthy.
27051
+ *
27052
+ * A special directive is necessary because we cannot use interpolation inside the `disabled`
27053
+ * attribute. The following example would make the button enabled on Chrome/Firefox
27054
+ * but not on older IEs:
27055
+ *
27034
27056
  * ```html
27035
- * <div ng-init="scope = { isDisabled: false }">
27036
- * <button disabled="{{scope.isDisabled}}">Disabled</button>
27057
+ * <div ng-init="isDisabled = false">
27058
+ * <button disabled="{{isDisabled}}">Disabled</button>
27037
27059
  * </div>
27038
27060
  * ```
27039
27061
  *
27040
- * The HTML specification does not require browsers to preserve the values of boolean attributes
27041
- * such as disabled. (Their presence means true and their absence means false.)
27062
+ * This is because the HTML specification does not require browsers to preserve the values of
27063
+ * boolean attributes such as `disabled` (Their presence means true and their absence means false.)
27042
27064
  * If we put an Angular interpolation expression into such an attribute then the
27043
27065
  * binding information would be lost when the browser removes the attribute.
27044
- * The `ngDisabled` directive solves this problem for the `disabled` attribute.
27045
- * This complementary directive is not removed by the browser and so provides
27046
- * a permanent reliable place to store the binding information.
27047
27066
  *
27048
27067
  * @example
27049
27068
  <example>
@@ -27062,7 +27081,7 @@ var htmlAnchorDirective = valueFn({
27062
27081
  *
27063
27082
  * @element INPUT
27064
27083
  * @param {expression} ngDisabled If the {@link guide/expression expression} is truthy,
27065
- * then special attribute "disabled" will be set on the element
27084
+ * then the `disabled` attribute will be set on the element
27066
27085
  */
27067
27086
 
27068
27087
 
@@ -27875,19 +27894,21 @@ var inputType = {
27875
27894
  <script>
27876
27895
  angular.module('textInputExample', [])
27877
27896
  .controller('ExampleController', ['$scope', function($scope) {
27878
- $scope.text = 'guest';
27879
- $scope.word = /^\s*\w*\s*$/;
27897
+ $scope.example = {
27898
+ text: 'guest',
27899
+ word: /^\s*\w*\s*$/
27900
+ };
27880
27901
  }]);
27881
27902
  </script>
27882
27903
  <form name="myForm" ng-controller="ExampleController">
27883
- Single word: <input type="text" name="input" ng-model="text"
27884
- ng-pattern="word" required ng-trim="false">
27904
+ Single word: <input type="text" name="input" ng-model="example.text"
27905
+ ng-pattern="example.word" required ng-trim="false">
27885
27906
  <span class="error" ng-show="myForm.input.$error.required">
27886
27907
  Required!</span>
27887
27908
  <span class="error" ng-show="myForm.input.$error.pattern">
27888
27909
  Single word only!</span>
27889
27910
 
27890
- <tt>text = {{text}}</tt><br/>
27911
+ <tt>text = {{example.text}}</tt><br/>
27891
27912
  <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
27892
27913
  <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
27893
27914
  <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
@@ -27895,9 +27916,9 @@ var inputType = {
27895
27916
  </form>
27896
27917
  </file>
27897
27918
  <file name="protractor.js" type="protractor">
27898
- var text = element(by.binding('text'));
27919
+ var text = element(by.binding('example.text'));
27899
27920
  var valid = element(by.binding('myForm.input.$valid'));
27900
- var input = element(by.model('text'));
27921
+ var input = element(by.model('example.text'));
27901
27922
 
27902
27923
  it('should initialize to model', function() {
27903
27924
  expect(text.getText()).toContain('guest');
@@ -27959,18 +27980,20 @@ var inputType = {
27959
27980
  <script>
27960
27981
  angular.module('dateInputExample', [])
27961
27982
  .controller('DateController', ['$scope', function($scope) {
27962
- $scope.value = new Date(2013, 9, 22);
27983
+ $scope.example = {
27984
+ value: new Date(2013, 9, 22)
27985
+ };
27963
27986
  }]);
27964
27987
  </script>
27965
27988
  <form name="myForm" ng-controller="DateController as dateCtrl">
27966
27989
  Pick a date in 2013:
27967
- <input type="date" id="exampleInput" name="input" ng-model="value"
27990
+ <input type="date" id="exampleInput" name="input" ng-model="example.value"
27968
27991
  placeholder="yyyy-MM-dd" min="2013-01-01" max="2013-12-31" required />
27969
27992
  <span class="error" ng-show="myForm.input.$error.required">
27970
27993
  Required!</span>
27971
27994
  <span class="error" ng-show="myForm.input.$error.date">
27972
27995
  Not a valid date!</span>
27973
- <tt>value = {{value | date: "yyyy-MM-dd"}}</tt><br/>
27996
+ <tt>value = {{example.value | date: "yyyy-MM-dd"}}</tt><br/>
27974
27997
  <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
27975
27998
  <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
27976
27999
  <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
@@ -27978,9 +28001,9 @@ var inputType = {
27978
28001
  </form>
27979
28002
  </file>
27980
28003
  <file name="protractor.js" type="protractor">
27981
- var value = element(by.binding('value | date: "yyyy-MM-dd"'));
28004
+ var value = element(by.binding('example.value | date: "yyyy-MM-dd"'));
27982
28005
  var valid = element(by.binding('myForm.input.$valid'));
27983
- var input = element(by.model('value'));
28006
+ var input = element(by.model('example.value'));
27984
28007
 
27985
28008
  // currently protractor/webdriver does not support
27986
28009
  // sending keys to all known HTML5 input controls
@@ -28050,18 +28073,20 @@ var inputType = {
28050
28073
  <script>
28051
28074
  angular.module('dateExample', [])
28052
28075
  .controller('DateController', ['$scope', function($scope) {
28053
- $scope.value = new Date(2010, 11, 28, 14, 57);
28076
+ $scope.example = {
28077
+ value: new Date(2010, 11, 28, 14, 57)
28078
+ };
28054
28079
  }]);
28055
28080
  </script>
28056
28081
  <form name="myForm" ng-controller="DateController as dateCtrl">
28057
28082
  Pick a date between in 2013:
28058
- <input type="datetime-local" id="exampleInput" name="input" ng-model="value"
28083
+ <input type="datetime-local" id="exampleInput" name="input" ng-model="example.value"
28059
28084
  placeholder="yyyy-MM-ddTHH:mm:ss" min="2001-01-01T00:00:00" max="2013-12-31T00:00:00" required />
28060
28085
  <span class="error" ng-show="myForm.input.$error.required">
28061
28086
  Required!</span>
28062
28087
  <span class="error" ng-show="myForm.input.$error.datetimelocal">
28063
28088
  Not a valid date!</span>
28064
- <tt>value = {{value | date: "yyyy-MM-ddTHH:mm:ss"}}</tt><br/>
28089
+ <tt>value = {{example.value | date: "yyyy-MM-ddTHH:mm:ss"}}</tt><br/>
28065
28090
  <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
28066
28091
  <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
28067
28092
  <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
@@ -28069,9 +28094,9 @@ var inputType = {
28069
28094
  </form>
28070
28095
  </file>
28071
28096
  <file name="protractor.js" type="protractor">
28072
- var value = element(by.binding('value | date: "yyyy-MM-ddTHH:mm:ss"'));
28097
+ var value = element(by.binding('example.value | date: "yyyy-MM-ddTHH:mm:ss"'));
28073
28098
  var valid = element(by.binding('myForm.input.$valid'));
28074
- var input = element(by.model('value'));
28099
+ var input = element(by.model('example.value'));
28075
28100
 
28076
28101
  // currently protractor/webdriver does not support
28077
28102
  // sending keys to all known HTML5 input controls
@@ -28142,18 +28167,20 @@ var inputType = {
28142
28167
  <script>
28143
28168
  angular.module('timeExample', [])
28144
28169
  .controller('DateController', ['$scope', function($scope) {
28145
- $scope.value = new Date(1970, 0, 1, 14, 57, 0);
28170
+ $scope.example = {
28171
+ value: new Date(1970, 0, 1, 14, 57, 0)
28172
+ };
28146
28173
  }]);
28147
28174
  </script>
28148
28175
  <form name="myForm" ng-controller="DateController as dateCtrl">
28149
28176
  Pick a between 8am and 5pm:
28150
- <input type="time" id="exampleInput" name="input" ng-model="value"
28177
+ <input type="time" id="exampleInput" name="input" ng-model="example.value"
28151
28178
  placeholder="HH:mm:ss" min="08:00:00" max="17:00:00" required />
28152
28179
  <span class="error" ng-show="myForm.input.$error.required">
28153
28180
  Required!</span>
28154
28181
  <span class="error" ng-show="myForm.input.$error.time">
28155
28182
  Not a valid date!</span>
28156
- <tt>value = {{value | date: "HH:mm:ss"}}</tt><br/>
28183
+ <tt>value = {{example.value | date: "HH:mm:ss"}}</tt><br/>
28157
28184
  <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
28158
28185
  <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
28159
28186
  <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
@@ -28161,9 +28188,9 @@ var inputType = {
28161
28188
  </form>
28162
28189
  </file>
28163
28190
  <file name="protractor.js" type="protractor">
28164
- var value = element(by.binding('value | date: "HH:mm:ss"'));
28191
+ var value = element(by.binding('example.value | date: "HH:mm:ss"'));
28165
28192
  var valid = element(by.binding('myForm.input.$valid'));
28166
- var input = element(by.model('value'));
28193
+ var input = element(by.model('example.value'));
28167
28194
 
28168
28195
  // currently protractor/webdriver does not support
28169
28196
  // sending keys to all known HTML5 input controls
@@ -28233,18 +28260,20 @@ var inputType = {
28233
28260
  <script>
28234
28261
  angular.module('weekExample', [])
28235
28262
  .controller('DateController', ['$scope', function($scope) {
28236
- $scope.value = new Date(2013, 0, 3);
28263
+ $scope.example = {
28264
+ value: new Date(2013, 0, 3)
28265
+ };
28237
28266
  }]);
28238
28267
  </script>
28239
28268
  <form name="myForm" ng-controller="DateController as dateCtrl">
28240
28269
  Pick a date between in 2013:
28241
- <input id="exampleInput" type="week" name="input" ng-model="value"
28270
+ <input id="exampleInput" type="week" name="input" ng-model="example.value"
28242
28271
  placeholder="YYYY-W##" min="2012-W32" max="2013-W52" required />
28243
28272
  <span class="error" ng-show="myForm.input.$error.required">
28244
28273
  Required!</span>
28245
28274
  <span class="error" ng-show="myForm.input.$error.week">
28246
28275
  Not a valid date!</span>
28247
- <tt>value = {{value | date: "yyyy-Www"}}</tt><br/>
28276
+ <tt>value = {{example.value | date: "yyyy-Www"}}</tt><br/>
28248
28277
  <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
28249
28278
  <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
28250
28279
  <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
@@ -28252,9 +28281,9 @@ var inputType = {
28252
28281
  </form>
28253
28282
  </file>
28254
28283
  <file name="protractor.js" type="protractor">
28255
- var value = element(by.binding('value | date: "yyyy-Www"'));
28284
+ var value = element(by.binding('example.value | date: "yyyy-Www"'));
28256
28285
  var valid = element(by.binding('myForm.input.$valid'));
28257
- var input = element(by.model('value'));
28286
+ var input = element(by.model('example.value'));
28258
28287
 
28259
28288
  // currently protractor/webdriver does not support
28260
28289
  // sending keys to all known HTML5 input controls
@@ -28324,18 +28353,20 @@ var inputType = {
28324
28353
  <script>
28325
28354
  angular.module('monthExample', [])
28326
28355
  .controller('DateController', ['$scope', function($scope) {
28327
- $scope.value = new Date(2013, 9, 1);
28356
+ $scope.example = {
28357
+ value: new Date(2013, 9, 1)
28358
+ };
28328
28359
  }]);
28329
28360
  </script>
28330
28361
  <form name="myForm" ng-controller="DateController as dateCtrl">
28331
- Pick a month int 2013:
28332
- <input id="exampleInput" type="month" name="input" ng-model="value"
28362
+ Pick a month in 2013:
28363
+ <input id="exampleInput" type="month" name="input" ng-model="example.value"
28333
28364
  placeholder="yyyy-MM" min="2013-01" max="2013-12" required />
28334
28365
  <span class="error" ng-show="myForm.input.$error.required">
28335
28366
  Required!</span>
28336
28367
  <span class="error" ng-show="myForm.input.$error.month">
28337
28368
  Not a valid month!</span>
28338
- <tt>value = {{value | date: "yyyy-MM"}}</tt><br/>
28369
+ <tt>value = {{example.value | date: "yyyy-MM"}}</tt><br/>
28339
28370
  <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
28340
28371
  <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
28341
28372
  <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
@@ -28343,9 +28374,9 @@ var inputType = {
28343
28374
  </form>
28344
28375
  </file>
28345
28376
  <file name="protractor.js" type="protractor">
28346
- var value = element(by.binding('value | date: "yyyy-MM"'));
28377
+ var value = element(by.binding('example.value | date: "yyyy-MM"'));
28347
28378
  var valid = element(by.binding('myForm.input.$valid'));
28348
- var input = element(by.model('value'));
28379
+ var input = element(by.model('example.value'));
28349
28380
 
28350
28381
  // currently protractor/webdriver does not support
28351
28382
  // sending keys to all known HTML5 input controls
@@ -28421,17 +28452,19 @@ var inputType = {
28421
28452
  <script>
28422
28453
  angular.module('numberExample', [])
28423
28454
  .controller('ExampleController', ['$scope', function($scope) {
28424
- $scope.value = 12;
28455
+ $scope.example = {
28456
+ value: 12
28457
+ };
28425
28458
  }]);
28426
28459
  </script>
28427
28460
  <form name="myForm" ng-controller="ExampleController">
28428
- Number: <input type="number" name="input" ng-model="value"
28461
+ Number: <input type="number" name="input" ng-model="example.value"
28429
28462
  min="0" max="99" required>
28430
28463
  <span class="error" ng-show="myForm.input.$error.required">
28431
28464
  Required!</span>
28432
28465
  <span class="error" ng-show="myForm.input.$error.number">
28433
28466
  Not valid number!</span>
28434
- <tt>value = {{value}}</tt><br/>
28467
+ <tt>value = {{example.value}}</tt><br/>
28435
28468
  <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
28436
28469
  <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
28437
28470
  <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
@@ -28439,9 +28472,9 @@ var inputType = {
28439
28472
  </form>
28440
28473
  </file>
28441
28474
  <file name="protractor.js" type="protractor">
28442
- var value = element(by.binding('value'));
28475
+ var value = element(by.binding('example.value'));
28443
28476
  var valid = element(by.binding('myForm.input.$valid'));
28444
- var input = element(by.model('value'));
28477
+ var input = element(by.model('example.value'));
28445
28478
 
28446
28479
  it('should initialize to model', function() {
28447
28480
  expect(value.getText()).toContain('12');
@@ -28509,16 +28542,18 @@ var inputType = {
28509
28542
  <script>
28510
28543
  angular.module('urlExample', [])
28511
28544
  .controller('ExampleController', ['$scope', function($scope) {
28512
- $scope.text = 'http://google.com';
28545
+ $scope.url = {
28546
+ text: 'http://google.com'
28547
+ };
28513
28548
  }]);
28514
28549
  </script>
28515
28550
  <form name="myForm" ng-controller="ExampleController">
28516
- URL: <input type="url" name="input" ng-model="text" required>
28551
+ URL: <input type="url" name="input" ng-model="url.text" required>
28517
28552
  <span class="error" ng-show="myForm.input.$error.required">
28518
28553
  Required!</span>
28519
28554
  <span class="error" ng-show="myForm.input.$error.url">
28520
28555
  Not valid url!</span>
28521
- <tt>text = {{text}}</tt><br/>
28556
+ <tt>text = {{url.text}}</tt><br/>
28522
28557
  <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
28523
28558
  <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
28524
28559
  <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
@@ -28527,9 +28562,9 @@ var inputType = {
28527
28562
  </form>
28528
28563
  </file>
28529
28564
  <file name="protractor.js" type="protractor">
28530
- var text = element(by.binding('text'));
28565
+ var text = element(by.binding('url.text'));
28531
28566
  var valid = element(by.binding('myForm.input.$valid'));
28532
- var input = element(by.model('text'));
28567
+ var input = element(by.model('url.text'));
28533
28568
 
28534
28569
  it('should initialize to model', function() {
28535
28570
  expect(text.getText()).toContain('http://google.com');
@@ -28598,16 +28633,18 @@ var inputType = {
28598
28633
  <script>
28599
28634
  angular.module('emailExample', [])
28600
28635
  .controller('ExampleController', ['$scope', function($scope) {
28601
- $scope.text = 'me@example.com';
28636
+ $scope.email = {
28637
+ text: 'me@example.com'
28638
+ };
28602
28639
  }]);
28603
28640
  </script>
28604
28641
  <form name="myForm" ng-controller="ExampleController">
28605
- Email: <input type="email" name="input" ng-model="text" required>
28642
+ Email: <input type="email" name="input" ng-model="email.text" required>
28606
28643
  <span class="error" ng-show="myForm.input.$error.required">
28607
28644
  Required!</span>
28608
28645
  <span class="error" ng-show="myForm.input.$error.email">
28609
28646
  Not valid email!</span>
28610
- <tt>text = {{text}}</tt><br/>
28647
+ <tt>text = {{email.text}}</tt><br/>
28611
28648
  <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
28612
28649
  <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
28613
28650
  <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
@@ -28616,9 +28653,9 @@ var inputType = {
28616
28653
  </form>
28617
28654
  </file>
28618
28655
  <file name="protractor.js" type="protractor">
28619
- var text = element(by.binding('text'));
28656
+ var text = element(by.binding('email.text'));
28620
28657
  var valid = element(by.binding('myForm.input.$valid'));
28621
- var input = element(by.model('text'));
28658
+ var input = element(by.model('email.text'));
28622
28659
 
28623
28660
  it('should initialize to model', function() {
28624
28661
  expect(text.getText()).toContain('me@example.com');
@@ -28665,7 +28702,9 @@ var inputType = {
28665
28702
  <script>
28666
28703
  angular.module('radioExample', [])
28667
28704
  .controller('ExampleController', ['$scope', function($scope) {
28668
- $scope.color = 'blue';
28705
+ $scope.color = {
28706
+ name: 'blue'
28707
+ };
28669
28708
  $scope.specialValue = {
28670
28709
  "id": "12345",
28671
28710
  "value": "green"
@@ -28673,20 +28712,20 @@ var inputType = {
28673
28712
  }]);
28674
28713
  </script>
28675
28714
  <form name="myForm" ng-controller="ExampleController">
28676
- <input type="radio" ng-model="color" value="red"> Red <br/>
28677
- <input type="radio" ng-model="color" ng-value="specialValue"> Green <br/>
28678
- <input type="radio" ng-model="color" value="blue"> Blue <br/>
28679
- <tt>color = {{color | json}}</tt><br/>
28715
+ <input type="radio" ng-model="color.name" value="red"> Red <br/>
28716
+ <input type="radio" ng-model="color.name" ng-value="specialValue"> Green <br/>
28717
+ <input type="radio" ng-model="color.name" value="blue"> Blue <br/>
28718
+ <tt>color = {{color.name | json}}</tt><br/>
28680
28719
  </form>
28681
28720
  Note that `ng-value="specialValue"` sets radio item's value to be the value of `$scope.specialValue`.
28682
28721
  </file>
28683
28722
  <file name="protractor.js" type="protractor">
28684
28723
  it('should change state', function() {
28685
- var color = element(by.binding('color'));
28724
+ var color = element(by.binding('color.name'));
28686
28725
 
28687
28726
  expect(color.getText()).toContain('blue');
28688
28727
 
28689
- element.all(by.model('color')).get(0).click();
28728
+ element.all(by.model('color.name')).get(0).click();
28690
28729
 
28691
28730
  expect(color.getText()).toContain('red');
28692
28731
  });
@@ -28716,28 +28755,30 @@ var inputType = {
28716
28755
  <script>
28717
28756
  angular.module('checkboxExample', [])
28718
28757
  .controller('ExampleController', ['$scope', function($scope) {
28719
- $scope.value1 = true;
28720
- $scope.value2 = 'YES'
28758
+ $scope.checkboxModel = {
28759
+ value1 : true,
28760
+ value2 : 'YES'
28761
+ };
28721
28762
  }]);
28722
28763
  </script>
28723
28764
  <form name="myForm" ng-controller="ExampleController">
28724
- Value1: <input type="checkbox" ng-model="value1"> <br/>
28725
- Value2: <input type="checkbox" ng-model="value2"
28765
+ Value1: <input type="checkbox" ng-model="checkboxModel.value1"> <br/>
28766
+ Value2: <input type="checkbox" ng-model="checkboxModel.value2"
28726
28767
  ng-true-value="'YES'" ng-false-value="'NO'"> <br/>
28727
- <tt>value1 = {{value1}}</tt><br/>
28728
- <tt>value2 = {{value2}}</tt><br/>
28768
+ <tt>value1 = {{checkboxModel.value1}}</tt><br/>
28769
+ <tt>value2 = {{checkboxModel.value2}}</tt><br/>
28729
28770
  </form>
28730
28771
  </file>
28731
28772
  <file name="protractor.js" type="protractor">
28732
28773
  it('should change state', function() {
28733
- var value1 = element(by.binding('value1'));
28734
- var value2 = element(by.binding('value2'));
28774
+ var value1 = element(by.binding('checkboxModel.value1'));
28775
+ var value2 = element(by.binding('checkboxModel.value2'));
28735
28776
 
28736
28777
  expect(value1.getText()).toContain('true');
28737
28778
  expect(value2.getText()).toContain('YES');
28738
28779
 
28739
- element(by.model('value1')).click();
28740
- element(by.model('value2')).click();
28780
+ element(by.model('checkboxModel.value1')).click();
28781
+ element(by.model('checkboxModel.value2')).click();
28741
28782
 
28742
28783
  expect(value1.getText()).toContain('false');
28743
28784
  expect(value2.getText()).toContain('NO');
@@ -29042,7 +29083,7 @@ function numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {
29042
29083
  return value;
29043
29084
  });
29044
29085
 
29045
- if (attr.min || attr.ngMin) {
29086
+ if (isDefined(attr.min) || attr.ngMin) {
29046
29087
  var minVal;
29047
29088
  ctrl.$validators.min = function(value) {
29048
29089
  return ctrl.$isEmpty(value) || isUndefined(minVal) || value >= minVal;
@@ -29058,7 +29099,7 @@ function numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {
29058
29099
  });
29059
29100
  }
29060
29101
 
29061
- if (attr.max || attr.ngMax) {
29102
+ if (isDefined(attr.max) || attr.ngMax) {
29062
29103
  var maxVal;
29063
29104
  ctrl.$validators.max = function(value) {
29064
29105
  return ctrl.$isEmpty(value) || isUndefined(maxVal) || value <= maxVal;
@@ -31446,7 +31487,7 @@ var ngIncludeFillContentDirective = ['$compile',
31446
31487
  * **Note**: If you have assignment in `ngInit` along with {@link ng.$filter `$filter`}, make
31447
31488
  * sure you have parenthesis for correct precedence:
31448
31489
  * <pre class="prettyprint">
31449
- * <div ng-init="test1 = (data | orderBy:'name')"></div>
31490
+ * `<div ng-init="test1 = (data | orderBy:'name')"></div>`
31450
31491
  * </pre>
31451
31492
  * </div>
31452
31493
  *
@@ -31864,6 +31905,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
31864
31905
  ngModelGet = parsedNgModel,
31865
31906
  ngModelSet = parsedNgModelAssign,
31866
31907
  pendingDebounce = null,
31908
+ parserValid,
31867
31909
  ctrl = this;
31868
31910
 
31869
31911
  this.$$setOptions = function(options) {
@@ -32136,16 +32178,12 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
32136
32178
  // the model although neither viewValue nor the model on the scope changed
32137
32179
  var modelValue = ctrl.$$rawModelValue;
32138
32180
 
32139
- // Check if the there's a parse error, so we don't unset it accidentially
32140
- var parserName = ctrl.$$parserName || 'parse';
32141
- var parserValid = ctrl.$error[parserName] ? false : undefined;
32142
-
32143
32181
  var prevValid = ctrl.$valid;
32144
32182
  var prevModelValue = ctrl.$modelValue;
32145
32183
 
32146
32184
  var allowInvalid = ctrl.$options && ctrl.$options.allowInvalid;
32147
32185
 
32148
- ctrl.$$runValidators(parserValid, modelValue, viewValue, function(allValid) {
32186
+ ctrl.$$runValidators(modelValue, viewValue, function(allValid) {
32149
32187
  // If there was no change in validity, don't update the model
32150
32188
  // This prevents changing an invalid modelValue to undefined
32151
32189
  if (!allowInvalid && prevValid !== allValid) {
@@ -32163,12 +32201,12 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
32163
32201
 
32164
32202
  };
32165
32203
 
32166
- this.$$runValidators = function(parseValid, modelValue, viewValue, doneCallback) {
32204
+ this.$$runValidators = function(modelValue, viewValue, doneCallback) {
32167
32205
  currentValidationRunId++;
32168
32206
  var localValidationRunId = currentValidationRunId;
32169
32207
 
32170
32208
  // check parser error
32171
- if (!processParseErrors(parseValid)) {
32209
+ if (!processParseErrors()) {
32172
32210
  validationDone(false);
32173
32211
  return;
32174
32212
  }
@@ -32178,21 +32216,22 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
32178
32216
  }
32179
32217
  processAsyncValidators();
32180
32218
 
32181
- function processParseErrors(parseValid) {
32219
+ function processParseErrors() {
32182
32220
  var errorKey = ctrl.$$parserName || 'parse';
32183
- if (parseValid === undefined) {
32221
+ if (parserValid === undefined) {
32184
32222
  setValidity(errorKey, null);
32185
32223
  } else {
32186
- setValidity(errorKey, parseValid);
32187
- if (!parseValid) {
32224
+ if (!parserValid) {
32188
32225
  forEach(ctrl.$validators, function(v, name) {
32189
32226
  setValidity(name, null);
32190
32227
  });
32191
32228
  forEach(ctrl.$asyncValidators, function(v, name) {
32192
32229
  setValidity(name, null);
32193
32230
  });
32194
- return false;
32195
32231
  }
32232
+ // Set the parse error last, to prevent unsetting it, should a $validators key == parserName
32233
+ setValidity(errorKey, parserValid);
32234
+ return parserValid;
32196
32235
  }
32197
32236
  return true;
32198
32237
  }
@@ -32287,7 +32326,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
32287
32326
  this.$$parseAndValidate = function() {
32288
32327
  var viewValue = ctrl.$$lastCommittedViewValue;
32289
32328
  var modelValue = viewValue;
32290
- var parserValid = isUndefined(modelValue) ? undefined : true;
32329
+ parserValid = isUndefined(modelValue) ? undefined : true;
32291
32330
 
32292
32331
  if (parserValid) {
32293
32332
  for (var i = 0; i < ctrl.$parsers.length; i++) {
@@ -32313,7 +32352,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
32313
32352
 
32314
32353
  // Pass the $$lastCommittedViewValue here, because the cached viewValue might be out of date.
32315
32354
  // This can happen if e.g. $setViewValue is called from inside a parser
32316
- ctrl.$$runValidators(parserValid, modelValue, ctrl.$$lastCommittedViewValue, function(allValid) {
32355
+ ctrl.$$runValidators(modelValue, ctrl.$$lastCommittedViewValue, function(allValid) {
32317
32356
  if (!allowInvalid) {
32318
32357
  // Note: Don't check ctrl.$valid here, as we could have
32319
32358
  // external validators (e.g. calculated on the server),
@@ -32434,6 +32473,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
32434
32473
  // TODO(perf): why not move this to the action fn?
32435
32474
  if (modelValue !== ctrl.$modelValue) {
32436
32475
  ctrl.$modelValue = ctrl.$$rawModelValue = modelValue;
32476
+ parserValid = undefined;
32437
32477
 
32438
32478
  var formatters = ctrl.$formatters,
32439
32479
  idx = formatters.length;
@@ -32446,7 +32486,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
32446
32486
  ctrl.$viewValue = ctrl.$$lastCommittedViewValue = viewValue;
32447
32487
  ctrl.$render();
32448
32488
 
32449
- ctrl.$$runValidators(undefined, modelValue, viewValue, noop);
32489
+ ctrl.$$runValidators(modelValue, viewValue, noop);
32450
32490
  }
32451
32491
  }
32452
32492
 
@@ -33262,6 +33302,55 @@ var ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interp
33262
33302
  * when keys are deleted and reinstated.
33263
33303
  *
33264
33304
  *
33305
+ * # Tracking and Duplicates
33306
+ *
33307
+ * When the contents of the collection change, `ngRepeat` makes the corresponding changes to the DOM:
33308
+ *
33309
+ * * When an item is added, a new instance of the template is added to the DOM.
33310
+ * * When an item is removed, its template instance is removed from the DOM.
33311
+ * * When items are reordered, their respective templates are reordered in the DOM.
33312
+ *
33313
+ * By default, `ngRepeat` does not allow duplicate items in arrays. This is because when
33314
+ * there are duplicates, it is not possible to maintain a one-to-one mapping between collection
33315
+ * items and DOM elements.
33316
+ *
33317
+ * If you do need to repeat duplicate items, you can substitute the default tracking behavior
33318
+ * with your own using the `track by` expression.
33319
+ *
33320
+ * For example, you may track items by the index of each item in the collection, using the
33321
+ * special scope property `$index`:
33322
+ * ```html
33323
+ * <div ng-repeat="n in [42, 42, 43, 43] track by $index">
33324
+ * {{n}}
33325
+ * </div>
33326
+ * ```
33327
+ *
33328
+ * You may use arbitrary expressions in `track by`, including references to custom functions
33329
+ * on the scope:
33330
+ * ```html
33331
+ * <div ng-repeat="n in [42, 42, 43, 43] track by myTrackingFunction(n)">
33332
+ * {{n}}
33333
+ * </div>
33334
+ * ```
33335
+ *
33336
+ * If you are working with objects that have an identifier property, you can track
33337
+ * by the identifier instead of the whole object. Should you reload your data later, `ngRepeat`
33338
+ * will not have to rebuild the DOM elements for items it has already rendered, even if the
33339
+ * JavaScript objects in the collection have been substituted for new ones:
33340
+ * ```html
33341
+ * <div ng-repeat="model in collection track by model.id">
33342
+ * {{model.name}}
33343
+ * </div>
33344
+ * ```
33345
+ *
33346
+ * When no `track by` expression is provided, it is equivalent to tracking by the built-in
33347
+ * `$id` function, which tracks items by their identity:
33348
+ * ```html
33349
+ * <div ng-repeat="obj in collection track by $id(obj)">
33350
+ * {{obj.prop}}
33351
+ * </div>
33352
+ * ```
33353
+ *
33265
33354
  * # Special repeat start and end points
33266
33355
  * To repeat a series of elements instead of just one parent element, ngRepeat (as well as other ng directives) supports extending
33267
33356
  * the range of the repeater by defining explicit start and end points by using **ng-repeat-start** and **ng-repeat-end** respectively.
@@ -33329,12 +33418,12 @@ var ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interp
33329
33418
  *
33330
33419
  * For example: `(name, age) in {'adam':10, 'amalie':12}`.
33331
33420
  *
33332
- * * `variable in expression track by tracking_expression` – You can also provide an optional tracking function
33333
- * which can be used to associate the objects in the collection with the DOM elements. If no tracking function
33334
- * is specified the ng-repeat associates elements by identity in the collection. It is an error to have
33335
- * more than one tracking function to resolve to the same key. (This would mean that two distinct objects are
33336
- * mapped to the same DOM element, which is not possible.) Filters should be applied to the expression,
33337
- * before specifying a tracking expression.
33421
+ * * `variable in expression track by tracking_expression` – You can also provide an optional tracking expression
33422
+ * which can be used to associate the objects in the collection with the DOM elements. If no tracking expression
33423
+ * is specified, ng-repeat associates elements by identity. It is an error to have
33424
+ * more than one tracking expression value resolve to the same key. (This would mean that two distinct objects are
33425
+ * mapped to the same DOM element, which is not possible.) If filters are used in the expression, they should be
33426
+ * applied before the tracking expression.
33338
33427
  *
33339
33428
  * For example: `item in items` is equivalent to `item in items track by $id(item)`. This implies that the DOM elements
33340
33429
  * will be associated by item identity in the array.
@@ -33718,10 +33807,11 @@ var NG_HIDE_IN_PROGRESS_CLASS = 'ng-hide-animate';
33718
33807
  *
33719
33808
  * By default, the `.ng-hide` class will style the element with `display: none!important`. If you wish to change
33720
33809
  * the hide behavior with ngShow/ngHide then this can be achieved by restating the styles for the `.ng-hide`
33721
- * class in CSS:
33810
+ * class CSS. Note that the selector that needs to be used is actually `.ng-hide:not(.ng-hide-animate)` to cope
33811
+ * with extra animation classes that can be added.
33722
33812
  *
33723
33813
  * ```css
33724
- * .ng-hide {
33814
+ * .ng-hide:not(.ng-hide-animate) {
33725
33815
  * /&#42; this is just another form of hiding an element &#42;/
33726
33816
  * display: block!important;
33727
33817
  * position: absolute;
@@ -35237,7 +35327,7 @@ var maxlengthDirective = function() {
35237
35327
  ctrl.$validate();
35238
35328
  });
35239
35329
  ctrl.$validators.maxlength = function(modelValue, viewValue) {
35240
- return (maxlength < 0) || ctrl.$isEmpty(modelValue) || (viewValue.length <= maxlength);
35330
+ return (maxlength < 0) || ctrl.$isEmpty(viewValue) || (viewValue.length <= maxlength);
35241
35331
  };
35242
35332
  }
35243
35333
  };
@@ -35565,7 +35655,7 @@ _jQuery.fn.bindings = function(windowJquery, bindExp) {
35565
35655
  var element = windowJquery(this),
35566
35656
  bindings;
35567
35657
  if (bindings = element.data('$binding')) {
35568
- for (var expressions = [], binding, j=0, jj=bindings.length; j < jj; j++) {
35658
+ for (var expressions = [], binding, j=0, jj=bindings.length; j < jj; j++) {
35569
35659
  binding = bindings[j];
35570
35660
 
35571
35661
  if (binding.expressions) {
@@ -35641,8 +35731,7 @@ _jQuery.fn.bindings = function(windowJquery, bindExp) {
35641
35731
  if (window.WebKitTransitionEvent) {
35642
35732
  evnt = new WebKitTransitionEvent(eventType, eventData);
35643
35733
  evnt.initEvent(eventType, false, true);
35644
- }
35645
- else {
35734
+ } else {
35646
35735
  try {
35647
35736
  evnt = new TransitionEvent(eventType, eventData);
35648
35737
  }
@@ -35651,13 +35740,11 @@ _jQuery.fn.bindings = function(windowJquery, bindExp) {
35651
35740
  evnt.initTransitionEvent(eventType, null, null, null, eventData.elapsedTime || 0);
35652
35741
  }
35653
35742
  }
35654
- }
35655
- else if (/animationend/.test(eventType)) {
35743
+ } else if (/animationend/.test(eventType)) {
35656
35744
  if (window.WebKitAnimationEvent) {
35657
35745
  evnt = new WebKitAnimationEvent(eventType, eventData);
35658
35746
  evnt.initEvent(eventType, false, true);
35659
- }
35660
- else {
35747
+ } else {
35661
35748
  try {
35662
35749
  evnt = new AnimationEvent(eventType, eventData);
35663
35750
  }
@@ -35666,8 +35753,7 @@ _jQuery.fn.bindings = function(windowJquery, bindExp) {
35666
35753
  evnt.initAnimationEvent(eventType, null, null, null, eventData.elapsedTime || 0);
35667
35754
  }
35668
35755
  }
35669
- }
35670
- else {
35756
+ } else {
35671
35757
  evnt = document.createEvent('MouseEvents');
35672
35758
  x = x || 0;
35673
35759
  y = y || 0;
@@ -35772,19 +35858,31 @@ angular.scenario.Application.prototype.navigateTo = function(url, loadFn, errorF
35772
35858
  try {
35773
35859
  var $window = self.getWindow_();
35774
35860
 
35775
- if ($window.angular) {
35776
- // Disable animations
35777
- $window.angular.resumeBootstrap([['$provide', function($provide) {
35778
- return ['$animate', function($animate) {
35779
- $animate.enabled(false);
35780
- }];
35781
- }]]);
35861
+ if (!$window.angular) {
35862
+ self.executeAction(loadFn);
35863
+ return;
35864
+ }
35865
+
35866
+ if (!$window.angular.resumeBootstrap) {
35867
+ $window.angular.resumeDeferredBootstrap = resumeDeferredBootstrap;
35868
+ } else {
35869
+ resumeDeferredBootstrap();
35782
35870
  }
35783
35871
 
35784
- self.executeAction(loadFn);
35785
35872
  } catch (e) {
35786
35873
  errorFn(e);
35787
35874
  }
35875
+
35876
+ function resumeDeferredBootstrap() {
35877
+ // Disable animations
35878
+ var $injector = $window.angular.resumeBootstrap([['$provide', function($provide) {
35879
+ return ['$animate', function($animate) {
35880
+ $animate.enabled(false);
35881
+ }];
35882
+ }]]);
35883
+ self.rootElement = $injector.get('$rootElement')[0];
35884
+ self.executeAction(loadFn);
35885
+ }
35788
35886
  }).attr('src', url);
35789
35887
 
35790
35888
  // for IE compatibility set the name *after* setting the frame url
@@ -35809,7 +35907,14 @@ angular.scenario.Application.prototype.executeAction = function(action) {
35809
35907
  if (!$window.angular) {
35810
35908
  return action.call(this, $window, _jQuery($window.document));
35811
35909
  }
35812
- angularInit($window.document, function(element) {
35910
+
35911
+ if (!!this.rootElement) {
35912
+ executeWithElement(this.rootElement);
35913
+ } else {
35914
+ angularInit($window.document, angular.bind(this, executeWithElement));
35915
+ }
35916
+
35917
+ function executeWithElement(element) {
35813
35918
  var $injector = $window.angular.element(element).injector();
35814
35919
  var $element = _jQuery(element);
35815
35920
 
@@ -35822,7 +35927,7 @@ angular.scenario.Application.prototype.executeAction = function(action) {
35822
35927
  action.call(self, $window, $element);
35823
35928
  });
35824
35929
  });
35825
- });
35930
+ }
35826
35931
  };
35827
35932
 
35828
35933
  /**