angularjs-rails 1.2.18 → 1.2.19

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.3.0-beta.13
2
+ * @license AngularJS v1.3.0-beta.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.0-beta.13
2
+ * @license AngularJS v1.3.0-beta.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.0-beta.13
2
+ * @license AngularJS v1.3.0-beta.14
3
3
  * (c) 2010-2014 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -69,7 +69,7 @@ function minErr(module) {
69
69
  return match;
70
70
  });
71
71
 
72
- message = message + '\nhttp://errors.angularjs.org/1.3.0-beta.13/' +
72
+ message = message + '\nhttp://errors.angularjs.org/1.3.0-beta.14/' +
73
73
  (module ? module + '/' : '') + code;
74
74
  for (i = 2; i < arguments.length; i++) {
75
75
  message = message + (i == 2 ? '?' : '&') + 'p' + (i-2) + '=' +
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.3.0-beta.13
2
+ * @license AngularJS v1.3.0-beta.14
3
3
  * (c) 2010-2014 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -169,7 +169,7 @@ angular.module('ngMessages', [])
169
169
  *
170
170
  * @description
171
171
  * `ngMessages` is a directive that is designed to show and hide messages based on the state
172
- * of a key/value object that is listens on. The directive itself compliments error message
172
+ * of a key/value object that it listens on. The directive itself compliments error message
173
173
  * reporting with the `ngModel` $error object (which stores a key/value state of validation errors).
174
174
  *
175
175
  * `ngMessages` manages the state of internal messages within its container element. The internal
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.3.0-beta.13
2
+ * @license AngularJS v1.3.0-beta.14
3
3
  * (c) 2010-2014 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -462,7 +462,7 @@ angular.mock.$IntervalProvider = function() {
462
462
  iteration = 0,
463
463
  skipApply = (angular.isDefined(invokeApply) && !invokeApply);
464
464
 
465
- count = (angular.isDefined(count)) ? count : 0,
465
+ count = (angular.isDefined(count)) ? count : 0;
466
466
  promise.then(null, null, fn);
467
467
 
468
468
  promise.$$intervalId = nextRepeatId;
@@ -1990,6 +1990,12 @@ if(window.jasmine || window.mocha) {
1990
1990
  (window.afterEach || window.teardown)(function() {
1991
1991
  var injector = currentSpec.$injector;
1992
1992
 
1993
+ angular.forEach(currentSpec.$modules, function(module) {
1994
+ if (module && module.$$hashKey) {
1995
+ module.$$hashKey = undefined;
1996
+ }
1997
+ });
1998
+
1993
1999
  currentSpec.$injector = null;
1994
2000
  currentSpec.$modules = null;
1995
2001
  currentSpec = null;
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.3.0-beta.13
2
+ * @license AngularJS v1.3.0-beta.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.0-beta.13
2
+ * @license AngularJS v1.3.0-beta.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.0-beta.13
2
+ * @license AngularJS v1.3.0-beta.14
3
3
  * (c) 2010-2014 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -9790,7 +9790,7 @@ if ( typeof module === "object" && module && typeof module.exports === "object"
9790
9790
  })( window );
9791
9791
 
9792
9792
  /**
9793
- * @license AngularJS v1.3.0-beta.13
9793
+ * @license AngularJS v1.3.0-beta.14
9794
9794
  * (c) 2010-2014 Google, Inc. http://angularjs.org
9795
9795
  * License: MIT
9796
9796
  */
@@ -9860,7 +9860,7 @@ function minErr(module) {
9860
9860
  return match;
9861
9861
  });
9862
9862
 
9863
- message = message + '\nhttp://errors.angularjs.org/1.3.0-beta.13/' +
9863
+ message = message + '\nhttp://errors.angularjs.org/1.3.0-beta.14/' +
9864
9864
  (module ? module + '/' : '') + code;
9865
9865
  for (i = 2; i < arguments.length; i++) {
9866
9866
  message = message + (i == 2 ? '?' : '&') + 'p' + (i-2) + '=' +
@@ -9885,6 +9885,7 @@ function minErr(module) {
9885
9885
  -nodeName_,
9886
9886
  -uid,
9887
9887
  -REGEX_STRING_REGEXP,
9888
+ -VALIDITY_STATE_PROPERTY,
9888
9889
 
9889
9890
  -lowercase,
9890
9891
  -uppercase,
@@ -9937,7 +9938,6 @@ function minErr(module) {
9937
9938
  -toJsonReplacer,
9938
9939
  -toJson,
9939
9940
  -fromJson,
9940
- -toBoolean,
9941
9941
  -startingTag,
9942
9942
  -tryDecodeURIComponent,
9943
9943
  -parseKeyValue,
@@ -9976,6 +9976,10 @@ function minErr(module) {
9976
9976
 
9977
9977
  var REGEX_STRING_REGEXP = /^\/(.+)\/([a-z]*)$/;
9978
9978
 
9979
+ // The name of a form control's ValidityState property.
9980
+ // This is used so that it's possible for internal tests to create mock ValidityStates.
9981
+ var VALIDITY_STATE_PROPERTY = 'validity';
9982
+
9979
9983
  /**
9980
9984
  * @ngdoc function
9981
9985
  * @name angular.lowercase
@@ -10112,12 +10116,12 @@ function forEach(obj, iterator, context) {
10112
10116
  iterator.call(context, obj[key], key);
10113
10117
  }
10114
10118
  }
10115
- } else if (obj.forEach && obj.forEach !== forEach) {
10116
- obj.forEach(iterator, context);
10117
- } else if (isArrayLike(obj)) {
10119
+ } else if (isArray(obj) || isArrayLike(obj)) {
10118
10120
  for (key = 0, length = obj.length; key < length; key++) {
10119
10121
  iterator.call(context, obj[key], key);
10120
10122
  }
10123
+ } else if (obj.forEach && obj.forEach !== forEach) {
10124
+ obj.forEach(iterator, context);
10121
10125
  } else {
10122
10126
  for (key in obj) {
10123
10127
  if (obj.hasOwnProperty(key)) {
@@ -10486,12 +10490,14 @@ function makeMap(str) {
10486
10490
  if (msie < 9) {
10487
10491
  nodeName_ = function(element) {
10488
10492
  element = element.nodeName ? element : element[0];
10489
- return (element.scopeName && element.scopeName != 'HTML')
10490
- ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;
10493
+ return lowercase(
10494
+ (element.scopeName && element.scopeName != 'HTML')
10495
+ ? element.scopeName + ':' + element.nodeName : element.nodeName
10496
+ );
10491
10497
  };
10492
10498
  } else {
10493
10499
  nodeName_ = function(element) {
10494
- return element.nodeName ? element.nodeName : element[0].nodeName;
10500
+ return lowercase(element.nodeName ? element.nodeName : element[0].nodeName);
10495
10501
  };
10496
10502
  }
10497
10503
 
@@ -10554,10 +10560,10 @@ function arrayRemove(array, value) {
10554
10560
 
10555
10561
  function isLeafNode (node) {
10556
10562
  if (node) {
10557
- switch (node.nodeName) {
10558
- case "OPTION":
10559
- case "PRE":
10560
- case "TITLE":
10563
+ switch (nodeName_(node)) {
10564
+ case "option":
10565
+ case "pre":
10566
+ case "title":
10561
10567
  return true;
10562
10568
  }
10563
10569
  }
@@ -10637,7 +10643,8 @@ function copy(source, destination, stackSource, stackDest) {
10637
10643
  } else if (isRegExp(source)) {
10638
10644
  destination = new RegExp(source.source);
10639
10645
  } else if (isObject(source)) {
10640
- destination = copy(source, {}, stackSource, stackDest);
10646
+ var emptyObject = Object.create(Object.getPrototypeOf(source));
10647
+ destination = copy(source, emptyObject, stackSource, stackDest);
10641
10648
  }
10642
10649
  }
10643
10650
  } else {
@@ -10672,12 +10679,14 @@ function copy(source, destination, stackSource, stackDest) {
10672
10679
  delete destination[key];
10673
10680
  });
10674
10681
  for ( var key in source) {
10675
- result = copy(source[key], null, stackSource, stackDest);
10676
- if (isObject(source[key])) {
10677
- stackSource.push(source[key]);
10678
- stackDest.push(result);
10682
+ if(source.hasOwnProperty(key)) {
10683
+ result = copy(source[key], null, stackSource, stackDest);
10684
+ if (isObject(source[key])) {
10685
+ stackSource.push(source[key]);
10686
+ stackDest.push(result);
10687
+ }
10688
+ destination[key] = result;
10679
10689
  }
10680
- destination[key] = result;
10681
10690
  }
10682
10691
  setHashKey(destination,h);
10683
10692
  }
@@ -10897,18 +10906,6 @@ function fromJson(json) {
10897
10906
  }
10898
10907
 
10899
10908
 
10900
- function toBoolean(value) {
10901
- if (typeof value === 'function') {
10902
- value = true;
10903
- } else if (value && value.length !== 0) {
10904
- var v = lowercase("" + value);
10905
- value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');
10906
- } else {
10907
- value = false;
10908
- }
10909
- return value;
10910
- }
10911
-
10912
10909
  /**
10913
10910
  * @returns {string} Returns the string representation of the element.
10914
10911
  */
@@ -11238,7 +11235,7 @@ function angularInit(element, bootstrap) {
11238
11235
  *
11239
11236
  * Angular will detect if it has been loaded into the browser more than once and only allow the
11240
11237
  * first loaded script to be bootstrapped and will report a warning to the browser console for
11241
- * each of the subsequent scripts. This prevents strange results in applications, where otherwise
11238
+ * each of the subsequent scripts. This prevents strange results in applications, where otherwise
11242
11239
  * multiple instances of Angular try to work on the DOM.
11243
11240
  *
11244
11241
  * ```html
@@ -11381,7 +11378,7 @@ function assertArgFn(arg, name, acceptArrayAnnotation) {
11381
11378
  }
11382
11379
 
11383
11380
  assertArg(isFunction(arg), name, 'not a function, got ' +
11384
- (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg));
11381
+ (arg && typeof arg === 'object' ? arg.constructor.name || 'Object' : typeof arg));
11385
11382
  return arg;
11386
11383
  }
11387
11384
 
@@ -11836,6 +11833,7 @@ function setupModuleLoader(window) {
11836
11833
  $ParseProvider,
11837
11834
  $RootScopeProvider,
11838
11835
  $QProvider,
11836
+ $$QProvider,
11839
11837
  $$SanitizeUriProvider,
11840
11838
  $SceProvider,
11841
11839
  $SceDelegateProvider,
@@ -11863,11 +11861,11 @@ function setupModuleLoader(window) {
11863
11861
  * - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat".
11864
11862
  */
11865
11863
  var version = {
11866
- full: '1.3.0-beta.13', // all of these placeholder strings will be replaced by grunt's
11864
+ full: '1.3.0-beta.14', // all of these placeholder strings will be replaced by grunt's
11867
11865
  major: 1, // package task
11868
11866
  minor: 3,
11869
11867
  dot: 0,
11870
- codeName: 'idiosyncratic-numerification'
11868
+ codeName: 'harmonious-cacophonies'
11871
11869
  };
11872
11870
 
11873
11871
 
@@ -11985,6 +11983,7 @@ function publishExternalAPI(angular){
11985
11983
  $parse: $ParseProvider,
11986
11984
  $rootScope: $RootScopeProvider,
11987
11985
  $q: $QProvider,
11986
+ $$q: $$QProvider,
11988
11987
  $sce: $SceProvider,
11989
11988
  $sceDelegate: $SceDelegateProvider,
11990
11989
  $sniffer: $SnifferProvider,
@@ -12159,6 +12158,12 @@ function jqLiteIsTextNode(html) {
12159
12158
  return !HTML_REGEXP.test(html);
12160
12159
  }
12161
12160
 
12161
+ function jqLiteAcceptsData(node) {
12162
+ // The window object can accept data but has no nodeType
12163
+ // Otherwise we are only interested in elements (1) and documents (9)
12164
+ return !node.nodeType || node.nodeType === 1 || node.nodeType === 9;
12165
+ }
12166
+
12162
12167
  function jqLiteBuildFragment(html, context) {
12163
12168
  var elem, tmp, tag, wrap,
12164
12169
  fragment = context.createDocumentFragment(),
@@ -12306,30 +12311,29 @@ function jqLiteExpandoStore(element, key, value) {
12306
12311
  }
12307
12312
 
12308
12313
  function jqLiteData(element, key, value) {
12309
- var data = jqLiteExpandoStore(element, 'data'),
12310
- isSetter = isDefined(value),
12311
- keyDefined = !isSetter && isDefined(key),
12312
- isSimpleGetter = keyDefined && !isObject(key);
12314
+ if (jqLiteAcceptsData(element)) {
12315
+ var data = jqLiteExpandoStore(element, 'data'),
12316
+ isSetter = isDefined(value),
12317
+ keyDefined = !isSetter && isDefined(key),
12318
+ isSimpleGetter = keyDefined && !isObject(key);
12313
12319
 
12314
- if (!data && !isSimpleGetter) {
12315
- jqLiteExpandoStore(element, 'data', data = {});
12316
- }
12320
+ if (!data && !isSimpleGetter) {
12321
+ jqLiteExpandoStore(element, 'data', data = {});
12322
+ }
12317
12323
 
12318
- if (isSetter) {
12319
- // set data only on Elements and Documents
12320
- if (element.nodeType === 1 || element.nodeType === 9) {
12324
+ if (isSetter) {
12321
12325
  data[key] = value;
12322
- }
12323
- } else {
12324
- if (keyDefined) {
12325
- if (isSimpleGetter) {
12326
- // don't create data in this case.
12327
- return data && data[key];
12326
+ } else {
12327
+ if (keyDefined) {
12328
+ if (isSimpleGetter) {
12329
+ // don't create data in this case.
12330
+ return data && data[key];
12331
+ } else {
12332
+ extend(data, key);
12333
+ }
12328
12334
  } else {
12329
- extend(data, key);
12335
+ return data;
12330
12336
  }
12331
- } else {
12332
- return data;
12333
12337
  }
12334
12338
  }
12335
12339
  }
@@ -12383,6 +12387,10 @@ function jqLiteAddNodes(root, elements) {
12383
12387
  // if an Array or NodeList and not a Window
12384
12388
  if (typeof length === 'number' && elements.window !== elements) {
12385
12389
  if (length) {
12390
+ if (elements.item) {
12391
+ // convert NodeList to an Array to make PhantomJS 1.x happy
12392
+ elements = slice.call(elements);
12393
+ }
12386
12394
  push.apply(root, elements);
12387
12395
  }
12388
12396
  } else {
@@ -12480,7 +12488,7 @@ forEach('multiple,selected,checked,disabled,readOnly,required,open'.split(','),
12480
12488
  });
12481
12489
  var BOOLEAN_ELEMENTS = {};
12482
12490
  forEach('input,select,option,textarea,button,form,details'.split(','), function(value) {
12483
- BOOLEAN_ELEMENTS[uppercase(value)] = true;
12491
+ BOOLEAN_ELEMENTS[value] = true;
12484
12492
  });
12485
12493
  var ALIASED_ATTR = {
12486
12494
  'ngMinlength' : 'minlength',
@@ -12493,7 +12501,7 @@ function getBooleanAttrName(element, name) {
12493
12501
  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];
12494
12502
 
12495
12503
  // booleanAttr is here twice to minimize DOM access
12496
- return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;
12504
+ return booleanAttr && BOOLEAN_ELEMENTS[nodeName_(element)] && booleanAttr;
12497
12505
  }
12498
12506
 
12499
12507
  function getAliasedAttrName(element, name) {
@@ -12603,7 +12611,7 @@ forEach({
12603
12611
 
12604
12612
  val: function(element, value) {
12605
12613
  if (isUndefined(value)) {
12606
- if (nodeName_(element) === 'SELECT' && element.multiple) {
12614
+ if (element.multiple && nodeName_(element) === 'select') {
12607
12615
  var result = [];
12608
12616
  forEach(element.options, function (option) {
12609
12617
  if (option.selected) {
@@ -12748,6 +12756,11 @@ forEach({
12748
12756
  on: function onFn(element, type, fn, unsupported){
12749
12757
  if (isDefined(unsupported)) throw jqLiteMinErr('onargs', 'jqLite#on() does not support the `selector` or `eventData` parameters');
12750
12758
 
12759
+ // Do not add event handlers to non-elements because they will not be cleaned up.
12760
+ if (!jqLiteAcceptsData(element)) {
12761
+ return;
12762
+ }
12763
+
12751
12764
  var events = jqLiteExpandoStore(element, 'events'),
12752
12765
  handle = jqLiteExpandoStore(element, 'handle');
12753
12766
 
@@ -12937,7 +12950,12 @@ forEach({
12937
12950
  eventData = eventData || [];
12938
12951
 
12939
12952
  var event = [{
12940
- preventDefault: noop,
12953
+ preventDefault: function() {
12954
+ this.defaultPrevented = true;
12955
+ },
12956
+ isDefaultPrevented: function() {
12957
+ return this.defaultPrevented === true;
12958
+ },
12941
12959
  stopPropagation: noop
12942
12960
  }];
12943
12961
 
@@ -12982,16 +13000,16 @@ forEach({
12982
13000
  * @returns {string} hash string such that the same input will have the same hash string.
12983
13001
  * The resulting string key is in 'type:hashKey' format.
12984
13002
  */
12985
- function hashKey(obj) {
13003
+ function hashKey(obj, nextUidFn) {
12986
13004
  var objType = typeof obj,
12987
13005
  key;
12988
13006
 
12989
- if (objType == 'object' && obj !== null) {
13007
+ if (objType == 'function' || (objType == 'object' && obj !== null)) {
12990
13008
  if (typeof (key = obj.$$hashKey) == 'function') {
12991
13009
  // must invoke on object to keep the right this
12992
13010
  key = obj.$$hashKey();
12993
13011
  } else if (key === undefined) {
12994
- key = obj.$$hashKey = nextUid();
13012
+ key = obj.$$hashKey = (nextUidFn || nextUid)();
12995
13013
  }
12996
13014
  } else {
12997
13015
  key = obj;
@@ -13003,7 +13021,13 @@ function hashKey(obj) {
13003
13021
  /**
13004
13022
  * HashMap which can use objects as keys
13005
13023
  */
13006
- function HashMap(array){
13024
+ function HashMap(array, isolatedUid) {
13025
+ if (isolatedUid) {
13026
+ var uid = 0;
13027
+ this.nextUid = function() {
13028
+ return ++uid;
13029
+ };
13030
+ }
13007
13031
  forEach(array, this.put, this);
13008
13032
  }
13009
13033
  HashMap.prototype = {
@@ -13013,7 +13037,7 @@ HashMap.prototype = {
13013
13037
  * @param value value to store can be any type
13014
13038
  */
13015
13039
  put: function(key, value) {
13016
- this[hashKey(key)] = value;
13040
+ this[hashKey(key, this.nextUid)] = value;
13017
13041
  },
13018
13042
 
13019
13043
  /**
@@ -13021,7 +13045,7 @@ HashMap.prototype = {
13021
13045
  * @returns {Object} the value for the key
13022
13046
  */
13023
13047
  get: function(key) {
13024
- return this[hashKey(key)];
13048
+ return this[hashKey(key, this.nextUid)];
13025
13049
  },
13026
13050
 
13027
13051
  /**
@@ -13029,7 +13053,7 @@ HashMap.prototype = {
13029
13053
  * @param key
13030
13054
  */
13031
13055
  remove: function(key) {
13032
- var value = this[key = hashKey(key)];
13056
+ var value = this[key = hashKey(key, this.nextUid)];
13033
13057
  delete this[key];
13034
13058
  return value;
13035
13059
  }
@@ -13119,7 +13143,7 @@ function annotate(fn, strictDi, name) {
13119
13143
  argDecl,
13120
13144
  last;
13121
13145
 
13122
- if (typeof fn == 'function') {
13146
+ if (typeof fn === 'function') {
13123
13147
  if (!($inject = fn.$inject)) {
13124
13148
  $inject = [];
13125
13149
  if (fn.length) {
@@ -13339,7 +13363,7 @@ function annotate(fn, strictDi, name) {
13339
13363
 
13340
13364
 
13341
13365
  /**
13342
- * @ngdoc object
13366
+ * @ngdoc service
13343
13367
  * @name $provide
13344
13368
  *
13345
13369
  * @description
@@ -13646,7 +13670,7 @@ function createInjector(modulesToLoad, strictDi) {
13646
13670
  var INSTANTIATING = {},
13647
13671
  providerSuffix = 'Provider',
13648
13672
  path = [],
13649
- loadedModules = new HashMap(),
13673
+ loadedModules = new HashMap([], true),
13650
13674
  providerCache = {
13651
13675
  $provide: {
13652
13676
  provider: supportObject(provider),
@@ -13827,8 +13851,7 @@ function createInjector(modulesToLoad, strictDi) {
13827
13851
  : getService(key)
13828
13852
  );
13829
13853
  }
13830
- if (!fn.$inject) {
13831
- // this means that we must be an array.
13854
+ if (isArray(fn)) {
13832
13855
  fn = fn[length];
13833
13856
  }
13834
13857
 
@@ -13931,7 +13954,7 @@ function $AnchorScrollProvider() {
13931
13954
  function getFirstAnchor(list) {
13932
13955
  var result = null;
13933
13956
  forEach(list, function(element) {
13934
- if (!result && lowercase(element.nodeName) === 'a') result = element;
13957
+ if (!result && nodeName_(element) === 'a') result = element;
13935
13958
  });
13936
13959
  return result;
13937
13960
  }
@@ -15756,8 +15779,8 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
15756
15779
  nodeName = nodeName_(this.$$element);
15757
15780
 
15758
15781
  // sanitize a[href] and img[src] values
15759
- if ((nodeName === 'A' && key === 'href') ||
15760
- (nodeName === 'IMG' && key === 'src')) {
15782
+ if ((nodeName === 'a' && key === 'href') ||
15783
+ (nodeName === 'img' && key === 'src')) {
15761
15784
  this[key] = value = $$sanitizeUri(value, key === 'src');
15762
15785
  }
15763
15786
 
@@ -16027,10 +16050,10 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
16027
16050
  case 1: /* Element */
16028
16051
  // use the node name: <directive>
16029
16052
  addDirective(directives,
16030
- directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority, ignoreDirective);
16053
+ directiveNormalize(nodeName_(node)), 'E', maxPriority, ignoreDirective);
16031
16054
 
16032
16055
  // iterate over the attributes
16033
- for (var attr, name, nName, ngAttrName, value, nAttrs = node.attributes,
16056
+ for (var attr, name, nName, ngAttrName, value, isNgAttr, nAttrs = node.attributes,
16034
16057
  j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {
16035
16058
  var attrStartName = false;
16036
16059
  var attrEndName = false;
@@ -16038,9 +16061,11 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
16038
16061
  attr = nAttrs[j];
16039
16062
  if (!msie || msie >= 8 || attr.specified) {
16040
16063
  name = attr.name;
16064
+ value = trim(attr.value);
16065
+
16041
16066
  // support ngAttr attribute binding
16042
16067
  ngAttrName = directiveNormalize(name);
16043
- if (NG_ATTR_BINDING.test(ngAttrName)) {
16068
+ if (isNgAttr = NG_ATTR_BINDING.test(ngAttrName)) {
16044
16069
  name = snake_case(ngAttrName.substr(6), '-');
16045
16070
  }
16046
16071
 
@@ -16053,9 +16078,11 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
16053
16078
 
16054
16079
  nName = directiveNormalize(name.toLowerCase());
16055
16080
  attrsMap[nName] = name;
16056
- attrs[nName] = value = trim(attr.value);
16057
- if (getBooleanAttrName(node, nName)) {
16058
- attrs[nName] = true; // presence means true
16081
+ if (isNgAttr || !attrs.hasOwnProperty(nName)) {
16082
+ attrs[nName] = value;
16083
+ if (getBooleanAttrName(node, nName)) {
16084
+ attrs[nName] = true; // presence means true
16085
+ }
16059
16086
  }
16060
16087
  addAttrInterpolateDirective(node, directives, value, nName);
16061
16088
  addDirective(directives, nName, 'A', maxPriority, ignoreDirective, attrStartName,
@@ -16890,8 +16917,8 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
16890
16917
  var tag = nodeName_(node);
16891
16918
  // maction[xlink:href] can source SVG. It's not limited to <maction>.
16892
16919
  if (attrNormalizedName == "xlinkHref" ||
16893
- (tag == "FORM" && attrNormalizedName == "action") ||
16894
- (tag != "IMG" && (attrNormalizedName == "src" ||
16920
+ (tag == "form" && attrNormalizedName == "action") ||
16921
+ (tag != "img" && (attrNormalizedName == "src" ||
16895
16922
  attrNormalizedName == "ngSrc"))) {
16896
16923
  return $sce.RESOURCE_URL;
16897
16924
  }
@@ -16905,7 +16932,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
16905
16932
  if (!interpolateFn) return;
16906
16933
 
16907
16934
 
16908
- if (name === "multiple" && nodeName_(node) === "SELECT") {
16935
+ if (name === "multiple" && nodeName_(node) === "select") {
16909
16936
  throw $compileMinErr("selmulti",
16910
16937
  "Binding to the 'multiple' attribute is not supported. Element: {0}",
16911
16938
  startingTag(node));
@@ -17183,7 +17210,7 @@ function $ControllerProvider() {
17183
17210
  instance = $injector.instantiate(expression, locals, constructor);
17184
17211
 
17185
17212
  if (identifier) {
17186
- if (!(locals && typeof locals.$scope == 'object')) {
17213
+ if (!(locals && typeof locals.$scope === 'object')) {
17187
17214
  throw minErr('$controller')('noscp',
17188
17215
  "Cannot export controller '{0}' as '{1}'! No $scope object provided via `locals`.",
17189
17216
  constructor || expression.name, identifier);
@@ -18057,7 +18084,21 @@ function $HttpProvider() {
18057
18084
  * @param {Object=} config Optional configuration object
18058
18085
  * @returns {HttpPromise} Future object
18059
18086
  */
18060
- createShortMethodsWithData('post', 'put');
18087
+
18088
+ /**
18089
+ * @ngdoc method
18090
+ * @name ng.$http#patch
18091
+ * @methodOf ng.$http
18092
+ *
18093
+ * @description
18094
+ * Shortcut method to perform `PATCH` request.
18095
+ *
18096
+ * @param {string} url Relative or absolute URL specifying the destination of the request
18097
+ * @param {*} data Request content
18098
+ * @param {Object=} config Optional configuration object
18099
+ * @returns {HttpPromise} Future object
18100
+ */
18101
+ createShortMethodsWithData('post', 'put', 'patch');
18061
18102
 
18062
18103
  /**
18063
18104
  * @ngdoc property
@@ -18313,7 +18354,8 @@ function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDoc
18313
18354
  // Safari respectively.
18314
18355
  if (xhr && xhr.readyState == 4) {
18315
18356
  var responseHeaders = null,
18316
- response = null;
18357
+ response = null,
18358
+ statusText = '';
18317
18359
 
18318
18360
  if(status !== ABORTED) {
18319
18361
  responseHeaders = xhr.getAllResponseHeaders();
@@ -18323,11 +18365,17 @@ function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDoc
18323
18365
  response = ('response' in xhr) ? xhr.response : xhr.responseText;
18324
18366
  }
18325
18367
 
18368
+ // Accessing statusText on an aborted xhr object will
18369
+ // throw an 'c00c023f error' in IE9 and lower, don't touch it.
18370
+ if (!(status === ABORTED && msie < 10)) {
18371
+ statusText = xhr.statusText;
18372
+ }
18373
+
18326
18374
  completeRequest(callback,
18327
18375
  status || xhr.status,
18328
18376
  response,
18329
18377
  responseHeaders,
18330
- xhr.statusText || '');
18378
+ statusText);
18331
18379
  }
18332
18380
  };
18333
18381
 
@@ -18807,8 +18855,8 @@ function $InterpolateProvider() {
18807
18855
  }
18808
18856
 
18809
18857
  function $IntervalProvider() {
18810
- this.$get = ['$rootScope', '$window', '$q',
18811
- function($rootScope, $window, $q) {
18858
+ this.$get = ['$rootScope', '$window', '$q', '$$q',
18859
+ function($rootScope, $window, $q, $$q) {
18812
18860
  var intervals = {};
18813
18861
 
18814
18862
 
@@ -18938,10 +18986,10 @@ function $IntervalProvider() {
18938
18986
  function interval(fn, delay, count, invokeApply) {
18939
18987
  var setInterval = $window.setInterval,
18940
18988
  clearInterval = $window.clearInterval,
18941
- deferred = $q.defer(),
18942
- promise = deferred.promise,
18943
18989
  iteration = 0,
18944
- skipApply = (isDefined(invokeApply) && !invokeApply);
18990
+ skipApply = (isDefined(invokeApply) && !invokeApply),
18991
+ deferred = (skipApply ? $$q : $q).defer(),
18992
+ promise = deferred.promise;
18945
18993
 
18946
18994
  count = isDefined(count) ? count : 0;
18947
18995
 
@@ -18979,7 +19027,7 @@ function $IntervalProvider() {
18979
19027
  interval.cancel = function(promise) {
18980
19028
  if (promise && promise.$$intervalId in intervals) {
18981
19029
  intervals[promise.$$intervalId].reject('canceled');
18982
- clearInterval(promise.$$intervalId);
19030
+ $window.clearInterval(promise.$$intervalId);
18983
19031
  delete intervals[promise.$$intervalId];
18984
19032
  return true;
18985
19033
  }
@@ -19613,7 +19661,7 @@ function $LocationProvider(){
19613
19661
  html5Mode = false;
19614
19662
 
19615
19663
  /**
19616
- * @ngdoc property
19664
+ * @ngdoc method
19617
19665
  * @name $locationProvider#hashPrefix
19618
19666
  * @description
19619
19667
  * @param {string=} prefix Prefix for hash part (containing path and search)
@@ -19629,7 +19677,7 @@ function $LocationProvider(){
19629
19677
  };
19630
19678
 
19631
19679
  /**
19632
- * @ngdoc property
19680
+ * @ngdoc method
19633
19681
  * @name $locationProvider#html5Mode
19634
19682
  * @description
19635
19683
  * @param {boolean=} mode Use HTML5 strategy if available.
@@ -19698,7 +19746,7 @@ function $LocationProvider(){
19698
19746
  var elm = jqLite(event.target);
19699
19747
 
19700
19748
  // traverse the DOM up to find first A tag
19701
- while (lowercase(elm[0].nodeName) !== 'a') {
19749
+ while (nodeName_(elm[0]) !== 'a') {
19702
19750
  // ignore rewriting if no A tag (reached root element, or no parent - removed from document)
19703
19751
  if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;
19704
19752
  }
@@ -19985,14 +20033,7 @@ var $parseMinErr = minErr('$parse');
19985
20033
  //
19986
20034
  // As an example, consider the following Angular expression:
19987
20035
  //
19988
- // {}.toString.constructor(alert("evil JS code"))
19989
- //
19990
- // We want to prevent this type of access. For the sake of performance, during the lexing phase we
19991
- // disallow any "dotted" access to any member named "constructor".
19992
- //
19993
- // For reflective calls (a[b]) we check that the value of the lookup is not the Function constructor
19994
- // while evaluating the expression, which is a stronger but more expensive test. Since reflective
19995
- // calls are expensive anyway, this is not such a big deal compared to static dereferencing.
20036
+ // {}.toString.constructor('alert("evil JS code")')
19996
20037
  //
19997
20038
  // This sandboxing technique is not perfect and doesn't aim to be. The goal is to prevent exploits
19998
20039
  // against the expression language, but not to prevent exploits that were enabled by exposing
@@ -20000,17 +20041,19 @@ var $parseMinErr = minErr('$parse');
20000
20041
  // practice and therefore we are not even trying to protect against interaction with an object
20001
20042
  // explicitly exposed in this way.
20002
20043
  //
20003
- // A developer could foil the name check by aliasing the Function constructor under a different
20004
- // name on the scope.
20005
- //
20006
20044
  // In general, it is not possible to access a Window object from an angular expression unless a
20007
20045
  // window or some DOM object that has a reference to window is published onto a Scope.
20046
+ // Similarly we prevent invocations of function known to be dangerous, as well as assignments to
20047
+ // native objects.
20048
+
20008
20049
 
20009
20050
  function ensureSafeMemberName(name, fullExpression) {
20010
- if (name === "constructor") {
20051
+ if (name === "__defineGetter__" || name === "__defineSetter__"
20052
+ || name === "__lookupGetter__" || name === "__lookupSetter__"
20053
+ || name === "__proto__") {
20011
20054
  throw $parseMinErr('isecfld',
20012
- 'Referencing "constructor" field in Angular expressions is disallowed! Expression: {0}',
20013
- fullExpression);
20055
+ 'Attempting to access a disallowed field in Angular expressions! '
20056
+ +'Expression: {0}', fullExpression);
20014
20057
  }
20015
20058
  return name;
20016
20059
  }
@@ -20023,7 +20066,7 @@ function ensureSafeObject(obj, fullExpression) {
20023
20066
  'Referencing Function in Angular expressions is disallowed! Expression: {0}',
20024
20067
  fullExpression);
20025
20068
  } else if (// isWindow(obj)
20026
- obj.document && obj.location && obj.alert && obj.setInterval) {
20069
+ obj.window === obj) {
20027
20070
  throw $parseMinErr('isecwindow',
20028
20071
  'Referencing the Window in Angular expressions is disallowed! Expression: {0}',
20029
20072
  fullExpression);
@@ -20032,11 +20075,34 @@ function ensureSafeObject(obj, fullExpression) {
20032
20075
  throw $parseMinErr('isecdom',
20033
20076
  'Referencing DOM nodes in Angular expressions is disallowed! Expression: {0}',
20034
20077
  fullExpression);
20078
+ } else if (// block Object so that we can't get hold of dangerous Object.* methods
20079
+ obj === Object) {
20080
+ throw $parseMinErr('isecobj',
20081
+ 'Referencing Object in Angular expressions is disallowed! Expression: {0}',
20082
+ fullExpression);
20035
20083
  }
20036
20084
  }
20037
20085
  return obj;
20038
20086
  }
20039
20087
 
20088
+ var CALL = Function.prototype.call;
20089
+ var APPLY = Function.prototype.apply;
20090
+ var BIND = Function.prototype.bind;
20091
+
20092
+ function ensureSafeFunction(obj, fullExpression) {
20093
+ if (obj) {
20094
+ if (obj.constructor === obj) {
20095
+ throw $parseMinErr('isecfn',
20096
+ 'Referencing Function in Angular expressions is disallowed! Expression: {0}',
20097
+ fullExpression);
20098
+ } else if (obj === CALL || obj === APPLY || obj === BIND) {
20099
+ throw $parseMinErr('isecff',
20100
+ 'Referencing call, apply or bind in Angular expressions is disallowed! Expression: {0}',
20101
+ fullExpression);
20102
+ }
20103
+ }
20104
+ }
20105
+
20040
20106
  var OPERATORS = {
20041
20107
  /* jshint bitwise : false */
20042
20108
  'null':function(){return null;},
@@ -20656,6 +20722,7 @@ Parser.prototype = {
20656
20722
  i = indexFn(self, locals),
20657
20723
  v;
20658
20724
 
20725
+ ensureSafeMemberName(i, parser.text);
20659
20726
  if (!o) return undefined;
20660
20727
  v = ensureSafeObject(o[i], parser.text);
20661
20728
  return v;
@@ -20690,7 +20757,7 @@ Parser.prototype = {
20690
20757
  var fnPtr = fn(scope, locals, context) || noop;
20691
20758
 
20692
20759
  ensureSafeObject(context, parser.text);
20693
- ensureSafeObject(fnPtr, parser.text);
20760
+ ensureSafeFunction(fnPtr, parser.text);
20694
20761
 
20695
20762
  // IE stupidity! (IE doesn't have apply for some native functions)
20696
20763
  var v = fnPtr.apply
@@ -20785,6 +20852,8 @@ function setter(obj, path, setValue, fullExp) {
20785
20852
  obj = propertyObj;
20786
20853
  }
20787
20854
  key = ensureSafeMemberName(element.shift(), fullExp);
20855
+ ensureSafeObject(obj, fullExp);
20856
+ ensureSafeObject(obj[key], fullExp);
20788
20857
  obj[key] = setValue;
20789
20858
  return setValue;
20790
20859
  }
@@ -21002,11 +21071,7 @@ function $ParseProvider() {
21002
21071
  cache[exp] = parsedExpression;
21003
21072
  }
21004
21073
 
21005
- if (parsedExpression.constant) {
21006
- parsedExpression.$$unwatch = true;
21007
- }
21008
-
21009
- return oneTime ? oneTimeWrapper(parsedExpression) : parsedExpression;
21074
+ return oneTime || parsedExpression.constant ? oneTimeWrapper(parsedExpression) : parsedExpression;
21010
21075
 
21011
21076
  case 'function':
21012
21077
  return exp;
@@ -21025,7 +21090,7 @@ function $ParseProvider() {
21025
21090
 
21026
21091
  function oneTimeParseFn(self, locals) {
21027
21092
  if (!stable) {
21028
- lastValue = expression(self, locals);
21093
+ lastValue = expression.constant && lastValue ? lastValue : expression(self, locals);
21029
21094
  oneTimeParseFn.$$unwatch = isDefined(lastValue);
21030
21095
  if (oneTimeParseFn.$$unwatch && self && self.$$postDigestQueue) {
21031
21096
  self.$$postDigestQueue.push(function () {
@@ -21067,17 +21132,13 @@ function $ParseProvider() {
21067
21132
  * var deferred = $q.defer();
21068
21133
  *
21069
21134
  * setTimeout(function() {
21070
- * // since this fn executes async in a future turn of the event loop, we need to wrap
21071
- * // our code into an $apply call so that the model changes are properly observed.
21072
- * scope.$apply(function() {
21073
- * deferred.notify('About to greet ' + name + '.');
21074
- *
21075
- * if (okToGreet(name)) {
21076
- * deferred.resolve('Hello, ' + name + '!');
21077
- * } else {
21078
- * deferred.reject('Greeting ' + name + ' is not allowed.');
21079
- * }
21080
- * });
21135
+ * deferred.notify('About to greet ' + name + '.');
21136
+ *
21137
+ * if (okToGreet(name)) {
21138
+ * deferred.resolve('Hello, ' + name + '!');
21139
+ * } else {
21140
+ * deferred.reject('Greeting ' + name + ' is not allowed.');
21141
+ * }
21081
21142
  * }, 1000);
21082
21143
  *
21083
21144
  * return deferred.promise;
@@ -21221,6 +21282,13 @@ function $QProvider() {
21221
21282
  }];
21222
21283
  }
21223
21284
 
21285
+ function $$QProvider() {
21286
+ this.$get = ['$browser', '$exceptionHandler', function($browser, $exceptionHandler) {
21287
+ return qFactory(function(callback) {
21288
+ $browser.defer(callback);
21289
+ }, $exceptionHandler);
21290
+ }];
21291
+ }
21224
21292
 
21225
21293
  /**
21226
21294
  * Constructs a promise manager.
@@ -21968,7 +22036,7 @@ function $RootScopeProvider(){
21968
22036
  * A variant of {@link ng.$rootScope.Scope#$watch $watch()} where it watches an array of `watchExpressions`.
21969
22037
  * If any one expression in the collection changes the `listener` is executed.
21970
22038
  *
21971
- * - The items in the `watchCollection` array are observed via standard $watch operation and are examined on every
22039
+ * - The items in the `watchExpressions` array are observed via standard $watch operation and are examined on every
21972
22040
  * call to $digest() to see if any items changes.
21973
22041
  * - The `listener` is called whenever any expression in the `watchExpressions` array changes.
21974
22042
  *
@@ -22298,7 +22366,7 @@ function $RootScopeProvider(){
22298
22366
  if ((value = watch.get(current)) !== (last = watch.last) &&
22299
22367
  !(watch.eq
22300
22368
  ? equals(value, last)
22301
- : (typeof value == 'number' && typeof last == 'number'
22369
+ : (typeof value === 'number' && typeof last === 'number'
22302
22370
  && isNaN(value) && isNaN(last)))) {
22303
22371
  dirty = true;
22304
22372
  lastDirtyWatch = watch;
@@ -23658,7 +23726,7 @@ function $SceProvider() {
23658
23726
 
23659
23727
  /**
23660
23728
  * @ngdoc method
23661
- * @name $sce#parse
23729
+ * @name $sce#parseAs
23662
23730
  *
23663
23731
  * @description
23664
23732
  * Converts Angular {@link guide/expression expression} into a function. This is like {@link
@@ -24045,8 +24113,8 @@ function $SnifferProvider() {
24045
24113
  }
24046
24114
 
24047
24115
  function $TimeoutProvider() {
24048
- this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler',
24049
- function($rootScope, $browser, $q, $exceptionHandler) {
24116
+ this.$get = ['$rootScope', '$browser', '$q', '$$q', '$exceptionHandler',
24117
+ function($rootScope, $browser, $q, $$q, $exceptionHandler) {
24050
24118
  var deferreds = {};
24051
24119
 
24052
24120
 
@@ -24076,9 +24144,9 @@ function $TimeoutProvider() {
24076
24144
  *
24077
24145
  */
24078
24146
  function timeout(fn, delay, invokeApply) {
24079
- var deferred = $q.defer(),
24147
+ var skipApply = (isDefined(invokeApply) && !invokeApply),
24148
+ deferred = (skipApply ? $$q : $q).defer(),
24080
24149
  promise = deferred.promise,
24081
- skipApply = (isDefined(invokeApply) && !invokeApply),
24082
24150
  timeoutId;
24083
24151
 
24084
24152
  timeoutId = $browser.defer(function() {
@@ -24616,7 +24684,7 @@ function filterFilter() {
24616
24684
  // jshint +W086
24617
24685
  for (var key in expression) {
24618
24686
  (function(path) {
24619
- if (typeof expression[path] == 'undefined') return;
24687
+ if (typeof expression[path] === 'undefined') return;
24620
24688
  predicates.push(function(value) {
24621
24689
  return search(path == '$' ? value : (value && value[path]), expression[path]);
24622
24690
  });
@@ -24771,6 +24839,7 @@ function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {
24771
24839
  var match = numStr.match(/([\d\.]+)e(-?)(\d+)/);
24772
24840
  if (match && match[2] == '-' && match[3] > fractionSize + 1) {
24773
24841
  numStr = '0';
24842
+ number = 0;
24774
24843
  } else {
24775
24844
  formatedText = numStr;
24776
24845
  hasExponent = true;
@@ -24785,8 +24854,11 @@ function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {
24785
24854
  fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);
24786
24855
  }
24787
24856
 
24788
- var pow = Math.pow(10, fractionSize + 1);
24789
- number = Math.floor(number * pow + 5) / pow;
24857
+ // safely round numbers in JS without hitting imprecisions of floating-point arithmetics
24858
+ // inspired by:
24859
+ // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round
24860
+ number = +(Math.round(+(number.toString() + 'e' + fractionSize)).toString() + 'e' + -fractionSize);
24861
+
24790
24862
  var fraction = ('' + number).split(DECIMAL_SEP);
24791
24863
  var whole = fraction[0];
24792
24864
  fraction = fraction[1] || '';
@@ -25409,7 +25481,7 @@ function orderByFilter($parse){
25409
25481
  return 0;
25410
25482
  }
25411
25483
  function reverseComparator(comp, descending) {
25412
- return toBoolean(descending)
25484
+ return descending
25413
25485
  ? function(a,b){return comp(b,a);}
25414
25486
  : comp;
25415
25487
  }
@@ -26368,7 +26440,7 @@ var ngFormDirective = formDirectiveFactory(true);
26368
26440
  */
26369
26441
 
26370
26442
  var URL_REGEXP = /^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/;
26371
- var EMAIL_REGEXP = /^[a-z0-9!#$%&'*+/=?^_`{|}~.-]+@[a-z0-9-]+(\.[a-z0-9-]+)*$/i;
26443
+ var EMAIL_REGEXP = /^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9-]+(\.[a-z0-9-]+)*$/i;
26372
26444
  var NUMBER_REGEXP = /^\s*(\-|\+)?(\d+|(\d*(\.\d*)))\s*$/;
26373
26445
  var DATE_REGEXP = /^(\d{4})-(\d{2})-(\d{2})$/;
26374
26446
  var DATETIMELOCAL_REGEXP = /^(\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d)$/;
@@ -26534,7 +26606,7 @@ var inputType = {
26534
26606
  expect(valid.getText()).toContain('myForm.input.$valid = false');
26535
26607
  });
26536
26608
  </file>
26537
- </example>f
26609
+ </example>
26538
26610
  */
26539
26611
  'date': createDateInputType('date', DATE_REGEXP,
26540
26612
  createDateParser(DATE_REGEXP, ['yyyy', 'MM', 'dd']),
@@ -27219,15 +27291,29 @@ function validate(ctrl, validatorName, validity, value){
27219
27291
  return validity ? value : undefined;
27220
27292
  }
27221
27293
 
27294
+ function testFlags(validity, flags) {
27295
+ var i, flag;
27296
+ if (flags) {
27297
+ for (i=0; i<flags.length; ++i) {
27298
+ flag = flags[i];
27299
+ if (validity[flag]) {
27300
+ return true;
27301
+ }
27302
+ }
27303
+ }
27304
+ return false;
27305
+ }
27222
27306
 
27223
- function addNativeHtml5Validators(ctrl, validatorName, element) {
27224
- var validity = element.prop('validity');
27307
+ // Pass validity so that behaviour can be mocked easier.
27308
+ function addNativeHtml5Validators(ctrl, validatorName, badFlags, ignoreFlags, validity) {
27225
27309
  if (isObject(validity)) {
27310
+ ctrl.$$hasNativeValidators = true;
27226
27311
  var validator = function(value) {
27227
27312
  // Don't overwrite previous validation, don't consider valueMissing to apply (ng-required can
27228
27313
  // perform the required validation)
27229
- if (!ctrl.$error[validatorName] && (validity.badInput || validity.customError ||
27230
- validity.typeMismatch) && !validity.valueMissing) {
27314
+ if (!ctrl.$error[validatorName] &&
27315
+ !testFlags(validity, ignoreFlags) &&
27316
+ testFlags(validity, badFlags)) {
27231
27317
  ctrl.$setValidity(validatorName, false);
27232
27318
  return;
27233
27319
  }
@@ -27238,8 +27324,9 @@ function addNativeHtml5Validators(ctrl, validatorName, element) {
27238
27324
  }
27239
27325
 
27240
27326
  function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
27241
- var validity = element.prop('validity');
27327
+ var validity = element.prop(VALIDITY_STATE_PROPERTY);
27242
27328
  var placeholder = element[0].placeholder, noevent = {};
27329
+ ctrl.$$validityState = validity;
27243
27330
 
27244
27331
  // In composition mode, users are still inputing intermediate text buffer,
27245
27332
  // hold the listener until composition is done.
@@ -27274,20 +27361,20 @@ function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
27274
27361
  // By default we will trim the value
27275
27362
  // If the attribute ng-trim exists we will avoid trimming
27276
27363
  // e.g. <input ng-model="foo" ng-trim="false">
27277
- if (toBoolean(attr.ngTrim || 'T')) {
27364
+ if (!attr.ngTrim || attr.ngTrim !== 'false') {
27278
27365
  value = trim(value);
27279
27366
  }
27280
27367
 
27281
- if (ctrl.$viewValue !== value ||
27282
- // If the value is still empty/falsy, and there is no `required` error, run validators
27283
- // again. This enables HTML5 constraint validation errors to affect Angular validation
27284
- // even when the first character entered causes an error.
27285
- (validity && value === '' && !validity.valueMissing)) {
27368
+ // If a control is suffering from bad input, browsers discard its value, so it may be
27369
+ // necessary to revalidate even if the control's value is the same empty value twice in
27370
+ // a row.
27371
+ var revalidate = validity && ctrl.$$hasNativeValidators;
27372
+ if (ctrl.$viewValue !== value || (value === '' && revalidate)) {
27286
27373
  if (scope.$$phase) {
27287
- ctrl.$setViewValue(value, event);
27374
+ ctrl.$setViewValue(value, event, revalidate);
27288
27375
  } else {
27289
27376
  scope.$apply(function() {
27290
- ctrl.$setViewValue(value, event);
27377
+ ctrl.$setViewValue(value, event, revalidate);
27291
27378
  });
27292
27379
  }
27293
27380
  }
@@ -27436,6 +27523,8 @@ function createDateInputType(type, regexp, parseDate, format) {
27436
27523
  };
27437
27524
  }
27438
27525
 
27526
+ var numberBadFlags = ['badInput'];
27527
+
27439
27528
  function numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {
27440
27529
  textInputType(scope, element, attr, ctrl, $sniffer, $browser);
27441
27530
 
@@ -27450,7 +27539,7 @@ function numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {
27450
27539
  }
27451
27540
  });
27452
27541
 
27453
- addNativeHtml5Validators(ctrl, 'number', element);
27542
+ addNativeHtml5Validators(ctrl, 'number', numberBadFlags, null, ctrl.$$validityState);
27454
27543
 
27455
27544
  ctrl.$formatters.push(function(value) {
27456
27545
  return ctrl.$isEmpty(value) ? '' : '' + value;
@@ -27484,23 +27573,19 @@ function numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {
27484
27573
  function urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {
27485
27574
  textInputType(scope, element, attr, ctrl, $sniffer, $browser);
27486
27575
 
27487
- var urlValidator = function(value) {
27488
- return validate(ctrl, 'url', ctrl.$isEmpty(value) || URL_REGEXP.test(value), value);
27576
+ ctrl.$validators.url = function(modelValue, viewValue) {
27577
+ var value = modelValue || viewValue;
27578
+ return ctrl.$isEmpty(value) || URL_REGEXP.test(value);
27489
27579
  };
27490
-
27491
- ctrl.$formatters.push(urlValidator);
27492
- ctrl.$parsers.push(urlValidator);
27493
27580
  }
27494
27581
 
27495
27582
  function emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {
27496
27583
  textInputType(scope, element, attr, ctrl, $sniffer, $browser);
27497
27584
 
27498
- var emailValidator = function(value) {
27499
- return validate(ctrl, 'email', ctrl.$isEmpty(value) || EMAIL_REGEXP.test(value), value);
27585
+ ctrl.$validators.email = function(modelValue, viewValue) {
27586
+ var value = modelValue || viewValue;
27587
+ return ctrl.$isEmpty(value) || EMAIL_REGEXP.test(value);
27500
27588
  };
27501
-
27502
- ctrl.$formatters.push(emailValidator);
27503
- ctrl.$parsers.push(emailValidator);
27504
27589
  }
27505
27590
 
27506
27591
  function radioInputType(scope, element, attr, ctrl) {
@@ -27955,7 +28040,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
27955
28040
  * `ngModel.$validators` pipeline which is designed to handle validations with true/false values.
27956
28041
  *
27957
28042
  * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign
27958
- * to `$error[validationErrorKey]=isValid` so that it is available for data-binding.
28043
+ * to `$error[validationErrorKey]=!isValid` so that it is available for data-binding.
27959
28044
  * The `validationErrorKey` should be in camelCase and will get converted into dash-case
27960
28045
  * for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`
27961
28046
  * class and can be bound to as `{{someForm.someControl.$error.myError}}` .
@@ -28134,11 +28219,11 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
28134
28219
  * event defined in `ng-model-options`. this method is rarely needed as `NgModelController`
28135
28220
  * usually handles calling this in response to input events.
28136
28221
  */
28137
- this.$commitViewValue = function() {
28222
+ this.$commitViewValue = function(revalidate) {
28138
28223
  var viewValue = ctrl.$viewValue;
28139
28224
 
28140
28225
  $timeout.cancel(pendingDebounce);
28141
- if (ctrl.$$lastCommittedViewValue === viewValue) {
28226
+ if (!revalidate && ctrl.$$lastCommittedViewValue === viewValue) {
28142
28227
  return;
28143
28228
  }
28144
28229
  ctrl.$$lastCommittedViewValue = viewValue;
@@ -28203,14 +28288,14 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
28203
28288
  * @param {string} value Value from the view.
28204
28289
  * @param {string} trigger Event that triggered the update.
28205
28290
  */
28206
- this.$setViewValue = function(value, trigger) {
28291
+ this.$setViewValue = function(value, trigger, revalidate) {
28207
28292
  ctrl.$viewValue = value;
28208
28293
  if (!ctrl.$options || ctrl.$options.updateOnDefault) {
28209
- ctrl.$$debounceViewValueCommit(trigger);
28294
+ ctrl.$$debounceViewValueCommit(trigger, revalidate);
28210
28295
  }
28211
28296
  };
28212
28297
 
28213
- this.$$debounceViewValueCommit = function(trigger) {
28298
+ this.$$debounceViewValueCommit = function(trigger, revalidate) {
28214
28299
  var debounceDelay = 0,
28215
28300
  options = ctrl.$options,
28216
28301
  debounce;
@@ -28229,10 +28314,10 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
28229
28314
  $timeout.cancel(pendingDebounce);
28230
28315
  if (debounceDelay) {
28231
28316
  pendingDebounce = $timeout(function() {
28232
- ctrl.$commitViewValue();
28317
+ ctrl.$commitViewValue(revalidate);
28233
28318
  }, debounceDelay);
28234
28319
  } else {
28235
- ctrl.$commitViewValue();
28320
+ ctrl.$commitViewValue(revalidate);
28236
28321
  }
28237
28322
  };
28238
28323
 
@@ -30276,7 +30361,7 @@ var ngIfDirective = ['$animate', function($animate) {
30276
30361
  var block, childScope, previousElements;
30277
30362
  $scope.$watch($attr.ngIf, function ngIfWatchAction(value) {
30278
30363
 
30279
- if (toBoolean(value)) {
30364
+ if (value) {
30280
30365
  if (!childScope) {
30281
30366
  $transclude(function (clone, newScope) {
30282
30367
  childScope = newScope;
@@ -30759,7 +30844,7 @@ var ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });
30759
30844
  * When one person, perhaps John, views the document, "John is viewing" will be shown.
30760
30845
  * When three people view the document, no explicit number rule is found, so
30761
30846
  * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.
30762
- * In this case, plural category 'one' is matched and "John, Marry and one other person are viewing"
30847
+ * In this case, plural category 'one' is matched and "John, Mary and one other person are viewing"
30763
30848
  * is shown.
30764
30849
  *
30765
30850
  * Note that when you specify offsets, you must provide explicit number rules for
@@ -31308,15 +31393,10 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
31308
31393
  * <div ng-show="myValue" class="ng-hide"></div>
31309
31394
  * ```
31310
31395
  *
31311
- * When the ngShow expression evaluates to false then the ng-hide CSS class is added to the class attribute
31312
- * on the element causing it to become hidden. When true, the ng-hide CSS class is removed
31396
+ * When the ngShow expression evaluates to a falsy value then the ng-hide CSS class is added to the class
31397
+ * attribute on the element causing it to become hidden. When truthy, the ng-hide CSS class is removed
31313
31398
  * from the element causing the element not to appear hidden.
31314
31399
  *
31315
- * <div class="alert alert-warning">
31316
- * **Note:** Here is a list of values that ngShow will consider as a falsy value (case insensitive):<br />
31317
- * "f" / "0" / "false" / "no" / "n" / "[]"
31318
- * </div>
31319
- *
31320
31400
  * ## Why is !important used?
31321
31401
  *
31322
31402
  * You may be wondering why !important is used for the .ng-hide CSS class. This is because the `.ng-hide` selector
@@ -31452,7 +31532,7 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
31452
31532
  var ngShowDirective = ['$animate', function($animate) {
31453
31533
  return function(scope, element, attr) {
31454
31534
  scope.$watch(attr.ngShow, function ngShowWatchAction(value){
31455
- $animate[toBoolean(value) ? 'removeClass' : 'addClass'](element, 'ng-hide');
31535
+ $animate[value ? 'removeClass' : 'addClass'](element, 'ng-hide');
31456
31536
  });
31457
31537
  };
31458
31538
  }];
@@ -31477,15 +31557,10 @@ var ngShowDirective = ['$animate', function($animate) {
31477
31557
  * <div ng-hide="myValue"></div>
31478
31558
  * ```
31479
31559
  *
31480
- * When the ngHide expression evaluates to true then the .ng-hide CSS class is added to the class attribute
31481
- * on the element causing it to become hidden. When false, the ng-hide CSS class is removed
31560
+ * When the ngHide expression evaluates to a truthy value then the .ng-hide CSS class is added to the class
31561
+ * attribute on the element causing it to become hidden. When falsy, the ng-hide CSS class is removed
31482
31562
  * from the element causing the element not to appear hidden.
31483
31563
  *
31484
- * <div class="alert alert-warning">
31485
- * **Note:** Here is a list of values that ngHide will consider as a falsy value (case insensitive):<br />
31486
- * "f" / "0" / "false" / "no" / "n" / "[]"
31487
- * </div>
31488
- *
31489
31564
  * ## Why is !important used?
31490
31565
  *
31491
31566
  * You may be wondering why !important is used for the .ng-hide CSS class. This is because the `.ng-hide` selector
@@ -31608,7 +31683,7 @@ var ngShowDirective = ['$animate', function($animate) {
31608
31683
  var ngHideDirective = ['$animate', function($animate) {
31609
31684
  return function(scope, element, attr) {
31610
31685
  scope.$watch(attr.ngHide, function ngHideWatchAction(value){
31611
- $animate[toBoolean(value) ? 'addClass' : 'removeClass'](element, 'ng-hide');
31686
+ $animate[value ? 'addClass' : 'removeClass'](element, 'ng-hide');
31612
31687
  });
31613
31688
  };
31614
31689
  }];
@@ -32925,7 +33000,7 @@ _jQuery.fn.bindings = function(windowJquery, bindExp) {
32925
33000
  function push(value) {
32926
33001
  if (value === undefined) {
32927
33002
  value = '';
32928
- } else if (typeof value != 'string') {
33003
+ } else if (typeof value !== 'string') {
32929
33004
  value = angular.toJson(value);
32930
33005
  }
32931
33006
  result.push('' + value);
@@ -32993,7 +33068,6 @@ _jQuery.fn.bindings = function(windowJquery, bindExp) {
32993
33068
 
32994
33069
  var inputType = (element.type) ? element.type.toLowerCase() : null,
32995
33070
  nodeName = element.nodeName.toLowerCase();
32996
-
32997
33071
  if (!eventType) {
32998
33072
  eventType = {
32999
33073
  'text': 'change',
@@ -34455,7 +34529,7 @@ angular.scenario.dsl('element', function() {
34455
34529
  var href = elements.attr('href');
34456
34530
  var eventProcessDefault = elements.trigger('click')[0];
34457
34531
 
34458
- if (href && elements[0].nodeName.toUpperCase() === 'A' && eventProcessDefault) {
34532
+ if (href && elements[0].nodeName.toLowerCase() === 'a' && eventProcessDefault) {
34459
34533
  this.application.navigateTo(href, function() {
34460
34534
  done();
34461
34535
  }, done);
@@ -34472,7 +34546,7 @@ angular.scenario.dsl('element', function() {
34472
34546
  var href = elements.attr('href');
34473
34547
  var eventProcessDefault = elements.trigger('dblclick')[0];
34474
34548
 
34475
- if (href && elements[0].nodeName.toUpperCase() === 'A' && eventProcessDefault) {
34549
+ if (href && elements[0].nodeName.toLowerCase() === 'a' && eventProcessDefault) {
34476
34550
  this.application.navigateTo(href, function() {
34477
34551
  done();
34478
34552
  }, done);