angularjs-rails 1.2.18 → 1.2.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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);