angularjs-rails 1.3.10 → 1.3.14

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -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
  /**