angular-gem 1.2.18.1 → 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.2.18
2
+ * @license AngularJS v1.2.19
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.2.18
2
+ * @license AngularJS v1.2.19
3
3
  * (c) 2010-2014 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -68,7 +68,7 @@ function minErr(module) {
68
68
  return match;
69
69
  });
70
70
 
71
- message = message + '\nhttp://errors.angularjs.org/1.2.18/' +
71
+ message = message + '\nhttp://errors.angularjs.org/1.2.19/' +
72
72
  (module ? module + '/' : '') + code;
73
73
  for (i = 2; i < arguments.length; i++) {
74
74
  message = message + (i == 2 ? '?' : '&') + 'p' + (i-2) + '=' +
@@ -92,6 +92,7 @@ function minErr(module) {
92
92
  -angularModule,
93
93
  -nodeName_,
94
94
  -uid,
95
+ -VALIDITY_STATE_PROPERTY,
95
96
 
96
97
  -lowercase,
97
98
  -uppercase,
@@ -181,6 +182,10 @@ function minErr(module) {
181
182
  * <div doc-module-components="ng"></div>
182
183
  */
183
184
 
185
+ // The name of a form control's ValidityState property.
186
+ // This is used so that it's possible for internal tests to create mock ValidityStates.
187
+ var VALIDITY_STATE_PROPERTY = 'validity';
188
+
184
189
  /**
185
190
  * @ngdoc function
186
191
  * @name angular.lowercase
@@ -1353,7 +1358,7 @@ function angularInit(element, bootstrap) {
1353
1358
  *
1354
1359
  * Angular will detect if it has been loaded into the browser more than once and only allow the
1355
1360
  * first loaded script to be bootstrapped and will report a warning to the browser console for
1356
- * each of the subsequent scripts. This prevents strange results in applications, where otherwise
1361
+ * each of the subsequent scripts. This prevents strange results in applications, where otherwise
1357
1362
  * multiple instances of Angular try to work on the DOM.
1358
1363
  *
1359
1364
  * <example name="multi-bootstrap" module="multi-bootstrap">
@@ -1483,7 +1488,7 @@ function assertArgFn(arg, name, acceptArrayAnnotation) {
1483
1488
  }
1484
1489
 
1485
1490
  assertArg(isFunction(arg), name, 'not a function, got ' +
1486
- (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg));
1491
+ (arg && typeof arg === 'object' ? arg.constructor.name || 'Object' : typeof arg));
1487
1492
  return arg;
1488
1493
  }
1489
1494
 
@@ -1953,11 +1958,11 @@ function setupModuleLoader(window) {
1953
1958
  * - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat".
1954
1959
  */
1955
1960
  var version = {
1956
- full: '1.2.18', // all of these placeholder strings will be replaced by grunt's
1961
+ full: '1.2.19', // all of these placeholder strings will be replaced by grunt's
1957
1962
  major: 1, // package task
1958
1963
  minor: 2,
1959
- dot: 18,
1960
- codeName: 'ear-extendability'
1964
+ dot: 19,
1965
+ codeName: 'precognitive-flashbacks'
1961
1966
  };
1962
1967
 
1963
1968
 
@@ -2179,8 +2184,9 @@ function publishExternalAPI(angular){
2179
2184
  * @returns {Object} jQuery object.
2180
2185
  */
2181
2186
 
2187
+ JQLite.expando = 'ng339';
2188
+
2182
2189
  var jqCache = JQLite.cache = {},
2183
- jqName = JQLite.expando = 'ng' + new Date().getTime(),
2184
2190
  jqId = 1,
2185
2191
  addEventListenerFn = (window.document.addEventListener
2186
2192
  ? function(element, type, fn) {element.addEventListener(type, fn, false);}
@@ -2390,7 +2396,7 @@ function jqLiteOff(element, type, fn, unsupported) {
2390
2396
  }
2391
2397
 
2392
2398
  function jqLiteRemoveData(element, name) {
2393
- var expandoId = element[jqName],
2399
+ var expandoId = element.ng339,
2394
2400
  expandoStore = jqCache[expandoId];
2395
2401
 
2396
2402
  if (expandoStore) {
@@ -2404,17 +2410,17 @@ function jqLiteRemoveData(element, name) {
2404
2410
  jqLiteOff(element);
2405
2411
  }
2406
2412
  delete jqCache[expandoId];
2407
- element[jqName] = undefined; // ie does not allow deletion of attributes on elements.
2413
+ element.ng339 = undefined; // don't delete DOM expandos. IE and Chrome don't like it
2408
2414
  }
2409
2415
  }
2410
2416
 
2411
2417
  function jqLiteExpandoStore(element, key, value) {
2412
- var expandoId = element[jqName],
2418
+ var expandoId = element.ng339,
2413
2419
  expandoStore = jqCache[expandoId || -1];
2414
2420
 
2415
2421
  if (isDefined(value)) {
2416
2422
  if (!expandoStore) {
2417
- element[jqName] = expandoId = jqNextId();
2423
+ element.ng339 = expandoId = jqNextId();
2418
2424
  expandoStore = jqCache[expandoId] = {};
2419
2425
  }
2420
2426
  expandoStore[key] = value;
@@ -3081,16 +3087,16 @@ forEach({
3081
3087
  * @returns {string} hash string such that the same input will have the same hash string.
3082
3088
  * The resulting string key is in 'type:hashKey' format.
3083
3089
  */
3084
- function hashKey(obj) {
3090
+ function hashKey(obj, nextUidFn) {
3085
3091
  var objType = typeof obj,
3086
3092
  key;
3087
3093
 
3088
- if (objType == 'object' && obj !== null) {
3094
+ if (objType == 'function' || (objType == 'object' && obj !== null)) {
3089
3095
  if (typeof (key = obj.$$hashKey) == 'function') {
3090
3096
  // must invoke on object to keep the right this
3091
3097
  key = obj.$$hashKey();
3092
3098
  } else if (key === undefined) {
3093
- key = obj.$$hashKey = nextUid();
3099
+ key = obj.$$hashKey = (nextUidFn || nextUid)();
3094
3100
  }
3095
3101
  } else {
3096
3102
  key = obj;
@@ -3102,7 +3108,13 @@ function hashKey(obj) {
3102
3108
  /**
3103
3109
  * HashMap which can use objects as keys
3104
3110
  */
3105
- function HashMap(array){
3111
+ function HashMap(array, isolatedUid) {
3112
+ if (isolatedUid) {
3113
+ var uid = 0;
3114
+ this.nextUid = function() {
3115
+ return ++uid;
3116
+ };
3117
+ }
3106
3118
  forEach(array, this.put, this);
3107
3119
  }
3108
3120
  HashMap.prototype = {
@@ -3112,7 +3124,7 @@ HashMap.prototype = {
3112
3124
  * @param value value to store can be any type
3113
3125
  */
3114
3126
  put: function(key, value) {
3115
- this[hashKey(key)] = value;
3127
+ this[hashKey(key, this.nextUid)] = value;
3116
3128
  },
3117
3129
 
3118
3130
  /**
@@ -3120,7 +3132,7 @@ HashMap.prototype = {
3120
3132
  * @returns {Object} the value for the key
3121
3133
  */
3122
3134
  get: function(key) {
3123
- return this[hashKey(key)];
3135
+ return this[hashKey(key, this.nextUid)];
3124
3136
  },
3125
3137
 
3126
3138
  /**
@@ -3128,7 +3140,7 @@ HashMap.prototype = {
3128
3140
  * @param key
3129
3141
  */
3130
3142
  remove: function(key) {
3131
- var value = this[key = hashKey(key)];
3143
+ var value = this[key = hashKey(key, this.nextUid)];
3132
3144
  delete this[key];
3133
3145
  return value;
3134
3146
  }
@@ -3206,7 +3218,7 @@ function annotate(fn) {
3206
3218
  argDecl,
3207
3219
  last;
3208
3220
 
3209
- if (typeof fn == 'function') {
3221
+ if (typeof fn === 'function') {
3210
3222
  if (!($inject = fn.$inject)) {
3211
3223
  $inject = [];
3212
3224
  if (fn.length) {
@@ -3419,7 +3431,7 @@ function annotate(fn) {
3419
3431
 
3420
3432
 
3421
3433
  /**
3422
- * @ngdoc object
3434
+ * @ngdoc service
3423
3435
  * @name $provide
3424
3436
  *
3425
3437
  * @description
@@ -3725,7 +3737,7 @@ function createInjector(modulesToLoad) {
3725
3737
  var INSTANTIATING = {},
3726
3738
  providerSuffix = 'Provider',
3727
3739
  path = [],
3728
- loadedModules = new HashMap(),
3740
+ loadedModules = new HashMap([], true),
3729
3741
  providerCache = {
3730
3742
  $provide: {
3731
3743
  provider: supportObject(provider),
@@ -3896,8 +3908,7 @@ function createInjector(modulesToLoad) {
3896
3908
  : getService(key)
3897
3909
  );
3898
3910
  }
3899
- if (!fn.$inject) {
3900
- // this means that we must be an array.
3911
+ if (isArray(fn)) {
3901
3912
  fn = fn[length];
3902
3913
  }
3903
3914
 
@@ -6078,7 +6089,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
6078
6089
  directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority, ignoreDirective);
6079
6090
 
6080
6091
  // iterate over the attributes
6081
- for (var attr, name, nName, ngAttrName, value, nAttrs = node.attributes,
6092
+ for (var attr, name, nName, ngAttrName, value, isNgAttr, nAttrs = node.attributes,
6082
6093
  j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {
6083
6094
  var attrStartName = false;
6084
6095
  var attrEndName = false;
@@ -6086,9 +6097,11 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
6086
6097
  attr = nAttrs[j];
6087
6098
  if (!msie || msie >= 8 || attr.specified) {
6088
6099
  name = attr.name;
6100
+ value = trim(attr.value);
6101
+
6089
6102
  // support ngAttr attribute binding
6090
6103
  ngAttrName = directiveNormalize(name);
6091
- if (NG_ATTR_BINDING.test(ngAttrName)) {
6104
+ if (isNgAttr = NG_ATTR_BINDING.test(ngAttrName)) {
6092
6105
  name = snake_case(ngAttrName.substr(6), '-');
6093
6106
  }
6094
6107
 
@@ -6101,9 +6114,11 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
6101
6114
 
6102
6115
  nName = directiveNormalize(name.toLowerCase());
6103
6116
  attrsMap[nName] = name;
6104
- attrs[nName] = value = trim(attr.value);
6105
- if (getBooleanAttrName(node, nName)) {
6106
- attrs[nName] = true; // presence means true
6117
+ if (isNgAttr || !attrs.hasOwnProperty(nName)) {
6118
+ attrs[nName] = value;
6119
+ if (getBooleanAttrName(node, nName)) {
6120
+ attrs[nName] = true; // presence means true
6121
+ }
6107
6122
  }
6108
6123
  addAttrInterpolateDirective(node, directives, value, nName);
6109
6124
  addDirective(directives, nName, 'A', maxPriority, ignoreDirective, attrStartName,
@@ -7201,7 +7216,7 @@ function $ControllerProvider() {
7201
7216
  instance = $injector.instantiate(expression, locals);
7202
7217
 
7203
7218
  if (identifier) {
7204
- if (!(locals && typeof locals.$scope == 'object')) {
7219
+ if (!(locals && typeof locals.$scope === 'object')) {
7205
7220
  throw minErr('$controller')('noscp',
7206
7221
  "Cannot export controller '{0}' as '{1}'! No $scope object provided via `locals`.",
7207
7222
  constructor || expression.name, identifier);
@@ -8403,7 +8418,8 @@ function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDoc
8403
8418
  // Safari respectively.
8404
8419
  if (xhr && xhr.readyState == 4) {
8405
8420
  var responseHeaders = null,
8406
- response = null;
8421
+ response = null,
8422
+ statusText = '';
8407
8423
 
8408
8424
  if(status !== ABORTED) {
8409
8425
  responseHeaders = xhr.getAllResponseHeaders();
@@ -8413,11 +8429,17 @@ function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDoc
8413
8429
  response = ('response' in xhr) ? xhr.response : xhr.responseText;
8414
8430
  }
8415
8431
 
8432
+ // Accessing statusText on an aborted xhr object will
8433
+ // throw an 'c00c023f error' in IE9 and lower, don't touch it.
8434
+ if (!(status === ABORTED && msie < 10)) {
8435
+ statusText = xhr.statusText;
8436
+ }
8437
+
8416
8438
  completeRequest(callback,
8417
8439
  status || xhr.status,
8418
8440
  response,
8419
8441
  responseHeaders,
8420
- xhr.statusText || '');
8442
+ statusText);
8421
8443
  }
8422
8444
  };
8423
8445
 
@@ -8951,7 +8973,7 @@ function $IntervalProvider() {
8951
8973
  interval.cancel = function(promise) {
8952
8974
  if (promise && promise.$$intervalId in intervals) {
8953
8975
  intervals[promise.$$intervalId].reject('canceled');
8954
- clearInterval(promise.$$intervalId);
8976
+ $window.clearInterval(promise.$$intervalId);
8955
8977
  delete intervals[promise.$$intervalId];
8956
8978
  return true;
8957
8979
  }
@@ -9585,7 +9607,7 @@ function $LocationProvider(){
9585
9607
  html5Mode = false;
9586
9608
 
9587
9609
  /**
9588
- * @ngdoc property
9610
+ * @ngdoc method
9589
9611
  * @name $locationProvider#hashPrefix
9590
9612
  * @description
9591
9613
  * @param {string=} prefix Prefix for hash part (containing path and search)
@@ -9601,7 +9623,7 @@ function $LocationProvider(){
9601
9623
  };
9602
9624
 
9603
9625
  /**
9604
- * @ngdoc property
9626
+ * @ngdoc method
9605
9627
  * @name $locationProvider#html5Mode
9606
9628
  * @description
9607
9629
  * @param {boolean=} mode Use HTML5 strategy if available.
@@ -9959,14 +9981,7 @@ var promiseWarning;
9959
9981
  //
9960
9982
  // As an example, consider the following Angular expression:
9961
9983
  //
9962
- // {}.toString.constructor(alert("evil JS code"))
9963
- //
9964
- // We want to prevent this type of access. For the sake of performance, during the lexing phase we
9965
- // disallow any "dotted" access to any member named "constructor".
9966
- //
9967
- // For reflective calls (a[b]) we check that the value of the lookup is not the Function constructor
9968
- // while evaluating the expression, which is a stronger but more expensive test. Since reflective
9969
- // calls are expensive anyway, this is not such a big deal compared to static dereferencing.
9984
+ // {}.toString.constructor('alert("evil JS code")')
9970
9985
  //
9971
9986
  // This sandboxing technique is not perfect and doesn't aim to be. The goal is to prevent exploits
9972
9987
  // against the expression language, but not to prevent exploits that were enabled by exposing
@@ -9974,17 +9989,19 @@ var promiseWarning;
9974
9989
  // practice and therefore we are not even trying to protect against interaction with an object
9975
9990
  // explicitly exposed in this way.
9976
9991
  //
9977
- // A developer could foil the name check by aliasing the Function constructor under a different
9978
- // name on the scope.
9979
- //
9980
9992
  // In general, it is not possible to access a Window object from an angular expression unless a
9981
9993
  // window or some DOM object that has a reference to window is published onto a Scope.
9994
+ // Similarly we prevent invocations of function known to be dangerous, as well as assignments to
9995
+ // native objects.
9996
+
9982
9997
 
9983
9998
  function ensureSafeMemberName(name, fullExpression) {
9984
- if (name === "constructor") {
9999
+ if (name === "__defineGetter__" || name === "__defineSetter__"
10000
+ || name === "__lookupGetter__" || name === "__lookupSetter__"
10001
+ || name === "__proto__") {
9985
10002
  throw $parseMinErr('isecfld',
9986
- 'Referencing "constructor" field in Angular expressions is disallowed! Expression: {0}',
9987
- fullExpression);
10003
+ 'Attempting to access a disallowed field in Angular expressions! '
10004
+ +'Expression: {0}', fullExpression);
9988
10005
  }
9989
10006
  return name;
9990
10007
  }
@@ -10006,11 +10023,34 @@ function ensureSafeObject(obj, fullExpression) {
10006
10023
  throw $parseMinErr('isecdom',
10007
10024
  'Referencing DOM nodes in Angular expressions is disallowed! Expression: {0}',
10008
10025
  fullExpression);
10026
+ } else if (// block Object so that we can't get hold of dangerous Object.* methods
10027
+ obj === Object) {
10028
+ throw $parseMinErr('isecobj',
10029
+ 'Referencing Object in Angular expressions is disallowed! Expression: {0}',
10030
+ fullExpression);
10009
10031
  }
10010
10032
  }
10011
10033
  return obj;
10012
10034
  }
10013
10035
 
10036
+ var CALL = Function.prototype.call;
10037
+ var APPLY = Function.prototype.apply;
10038
+ var BIND = Function.prototype.bind;
10039
+
10040
+ function ensureSafeFunction(obj, fullExpression) {
10041
+ if (obj) {
10042
+ if (obj.constructor === obj) {
10043
+ throw $parseMinErr('isecfn',
10044
+ 'Referencing Function in Angular expressions is disallowed! Expression: {0}',
10045
+ fullExpression);
10046
+ } else if (obj === CALL || obj === APPLY || (BIND && obj === BIND)) {
10047
+ throw $parseMinErr('isecff',
10048
+ 'Referencing call, apply or bind in Angular expressions is disallowed! Expression: {0}',
10049
+ fullExpression);
10050
+ }
10051
+ }
10052
+ }
10053
+
10014
10054
  var OPERATORS = {
10015
10055
  /* jshint bitwise : false */
10016
10056
  'null':function(){return null;},
@@ -10645,6 +10685,7 @@ Parser.prototype = {
10645
10685
  i = indexFn(self, locals),
10646
10686
  v, p;
10647
10687
 
10688
+ ensureSafeMemberName(i, parser.text);
10648
10689
  if (!o) return undefined;
10649
10690
  v = ensureSafeObject(o[i], parser.text);
10650
10691
  if (v && v.then && parser.options.unwrapPromises) {
@@ -10687,7 +10728,7 @@ Parser.prototype = {
10687
10728
  var fnPtr = fn(scope, locals, context) || noop;
10688
10729
 
10689
10730
  ensureSafeObject(context, parser.text);
10690
- ensureSafeObject(fnPtr, parser.text);
10731
+ ensureSafeFunction(fnPtr, parser.text);
10691
10732
 
10692
10733
  // IE stupidity! (IE doesn't have apply for some native functions)
10693
10734
  var v = fnPtr.apply
@@ -10796,6 +10837,8 @@ function setter(obj, path, setValue, fullExp, options) {
10796
10837
  }
10797
10838
  }
10798
10839
  key = ensureSafeMemberName(element.shift(), fullExp);
10840
+ ensureSafeObject(obj, fullExp);
10841
+ ensureSafeObject(obj[key], fullExp);
10799
10842
  obj[key] = setValue;
10800
10843
  return setValue;
10801
10844
  }
@@ -11215,17 +11258,13 @@ function $ParseProvider() {
11215
11258
  * var deferred = $q.defer();
11216
11259
  *
11217
11260
  * setTimeout(function() {
11218
- * // since this fn executes async in a future turn of the event loop, we need to wrap
11219
- * // our code into an $apply call so that the model changes are properly observed.
11220
- * scope.$apply(function() {
11221
- * deferred.notify('About to greet ' + name + '.');
11222
- *
11223
- * if (okToGreet(name)) {
11224
- * deferred.resolve('Hello, ' + name + '!');
11225
- * } else {
11226
- * deferred.reject('Greeting ' + name + ' is not allowed.');
11227
- * }
11228
- * });
11261
+ * deferred.notify('About to greet ' + name + '.');
11262
+ *
11263
+ * if (okToGreet(name)) {
11264
+ * deferred.resolve('Hello, ' + name + '!');
11265
+ * } else {
11266
+ * deferred.reject('Greeting ' + name + ' is not allowed.');
11267
+ * }
11229
11268
  * }, 1000);
11230
11269
  *
11231
11270
  * return deferred.promise;
@@ -12387,7 +12426,7 @@ function $RootScopeProvider(){
12387
12426
  if ((value = watch.get(current)) !== (last = watch.last) &&
12388
12427
  !(watch.eq
12389
12428
  ? equals(value, last)
12390
- : (typeof value == 'number' && typeof last == 'number'
12429
+ : (typeof value === 'number' && typeof last === 'number'
12391
12430
  && isNaN(value) && isNaN(last)))) {
12392
12431
  dirty = true;
12393
12432
  lastDirtyWatch = watch;
@@ -13732,7 +13771,7 @@ function $SceProvider() {
13732
13771
 
13733
13772
  /**
13734
13773
  * @ngdoc method
13735
- * @name $sce#parse
13774
+ * @name $sce#parseAs
13736
13775
  *
13737
13776
  * @description
13738
13777
  * Converts Angular {@link guide/expression expression} into a function. This is like {@link
@@ -14688,7 +14727,7 @@ function filterFilter() {
14688
14727
  // jshint +W086
14689
14728
  for (var key in expression) {
14690
14729
  (function(path) {
14691
- if (typeof expression[path] == 'undefined') return;
14730
+ if (typeof expression[path] === 'undefined') return;
14692
14731
  predicates.push(function(value) {
14693
14732
  return search(path == '$' ? value : (value && value[path]), expression[path]);
14694
14733
  });
@@ -14843,6 +14882,7 @@ function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {
14843
14882
  var match = numStr.match(/([\d\.]+)e(-?)(\d+)/);
14844
14883
  if (match && match[2] == '-' && match[3] > fractionSize + 1) {
14845
14884
  numStr = '0';
14885
+ number = 0;
14846
14886
  } else {
14847
14887
  formatedText = numStr;
14848
14888
  hasExponent = true;
@@ -14857,8 +14897,11 @@ function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {
14857
14897
  fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);
14858
14898
  }
14859
14899
 
14860
- var pow = Math.pow(10, fractionSize + 1);
14861
- number = Math.floor(number * pow + 5) / pow;
14900
+ // safely round numbers in JS without hitting imprecisions of floating-point arithmetics
14901
+ // inspired by:
14902
+ // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round
14903
+ number = +(Math.round(+(number.toString() + 'e' + fractionSize)).toString() + 'e' + -fractionSize);
14904
+
14862
14905
  var fraction = ('' + number).split(DECIMAL_SEP);
14863
14906
  var whole = fraction[0];
14864
14907
  fraction = fraction[1] || '';
@@ -16360,7 +16403,7 @@ var ngFormDirective = formDirectiveFactory(true);
16360
16403
  */
16361
16404
 
16362
16405
  var URL_REGEXP = /^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/;
16363
- var EMAIL_REGEXP = /^[a-z0-9!#$%&'*+/=?^_`{|}~.-]+@[a-z0-9-]+(\.[a-z0-9-]+)*$/i;
16406
+ var EMAIL_REGEXP = /^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9-]+(\.[a-z0-9-]+)*$/i;
16364
16407
  var NUMBER_REGEXP = /^\s*(\-|\+)?(\d+|(\d*(\.\d*)))\s*$/;
16365
16408
 
16366
16409
  var inputType = {
@@ -16786,15 +16829,29 @@ function validate(ctrl, validatorName, validity, value){
16786
16829
  return validity ? value : undefined;
16787
16830
  }
16788
16831
 
16832
+ function testFlags(validity, flags) {
16833
+ var i, flag;
16834
+ if (flags) {
16835
+ for (i=0; i<flags.length; ++i) {
16836
+ flag = flags[i];
16837
+ if (validity[flag]) {
16838
+ return true;
16839
+ }
16840
+ }
16841
+ }
16842
+ return false;
16843
+ }
16789
16844
 
16790
- function addNativeHtml5Validators(ctrl, validatorName, element) {
16791
- var validity = element.prop('validity');
16845
+ // Pass validity so that behaviour can be mocked easier.
16846
+ function addNativeHtml5Validators(ctrl, validatorName, badFlags, ignoreFlags, validity) {
16792
16847
  if (isObject(validity)) {
16848
+ ctrl.$$hasNativeValidators = true;
16793
16849
  var validator = function(value) {
16794
16850
  // Don't overwrite previous validation, don't consider valueMissing to apply (ng-required can
16795
16851
  // perform the required validation)
16796
- if (!ctrl.$error[validatorName] && (validity.badInput || validity.customError ||
16797
- validity.typeMismatch) && !validity.valueMissing) {
16852
+ if (!ctrl.$error[validatorName] &&
16853
+ !testFlags(validity, ignoreFlags) &&
16854
+ testFlags(validity, badFlags)) {
16798
16855
  ctrl.$setValidity(validatorName, false);
16799
16856
  return;
16800
16857
  }
@@ -16805,8 +16862,9 @@ function addNativeHtml5Validators(ctrl, validatorName, element) {
16805
16862
  }
16806
16863
 
16807
16864
  function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
16808
- var validity = element.prop('validity');
16865
+ var validity = element.prop(VALIDITY_STATE_PROPERTY);
16809
16866
  var placeholder = element[0].placeholder, noevent = {};
16867
+ ctrl.$$validityState = validity;
16810
16868
 
16811
16869
  // In composition mode, users are still inputing intermediate text buffer,
16812
16870
  // hold the listener until composition is done.
@@ -16844,11 +16902,11 @@ function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
16844
16902
  value = trim(value);
16845
16903
  }
16846
16904
 
16847
- if (ctrl.$viewValue !== value ||
16848
- // If the value is still empty/falsy, and there is no `required` error, run validators
16849
- // again. This enables HTML5 constraint validation errors to affect Angular validation
16850
- // even when the first character entered causes an error.
16851
- (validity && value === '' && !validity.valueMissing)) {
16905
+ // If a control is suffering from bad input, browsers discard its value, so it may be
16906
+ // necessary to revalidate even if the control's value is the same empty value twice in
16907
+ // a row.
16908
+ var revalidate = validity && ctrl.$$hasNativeValidators;
16909
+ if (ctrl.$viewValue !== value || (value === '' && revalidate)) {
16852
16910
  if (scope.$$phase) {
16853
16911
  ctrl.$setViewValue(value);
16854
16912
  } else {
@@ -16954,6 +17012,8 @@ function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
16954
17012
  }
16955
17013
  }
16956
17014
 
17015
+ var numberBadFlags = ['badInput'];
17016
+
16957
17017
  function numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {
16958
17018
  textInputType(scope, element, attr, ctrl, $sniffer, $browser);
16959
17019
 
@@ -16968,7 +17028,7 @@ function numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {
16968
17028
  }
16969
17029
  });
16970
17030
 
16971
- addNativeHtml5Validators(ctrl, 'number', element);
17031
+ addNativeHtml5Validators(ctrl, 'number', numberBadFlags, null, ctrl.$$validityState);
16972
17032
 
16973
17033
  ctrl.$formatters.push(function(value) {
16974
17034
  return ctrl.$isEmpty(value) ? '' : '' + value;
@@ -17450,7 +17510,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
17450
17510
  * This method should be called by validators - i.e. the parser or formatter functions.
17451
17511
  *
17452
17512
  * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign
17453
- * to `$error[validationErrorKey]=isValid` so that it is available for data-binding.
17513
+ * to `$error[validationErrorKey]=!isValid` so that it is available for data-binding.
17454
17514
  * The `validationErrorKey` should be in camelCase and will get converted into dash-case
17455
17515
  * for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`
17456
17516
  * class and can be bound to as `{{someForm.someControl.$error.myError}}` .
@@ -19834,7 +19894,7 @@ var ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });
19834
19894
  * When one person, perhaps John, views the document, "John is viewing" will be shown.
19835
19895
  * When three people view the document, no explicit number rule is found, so
19836
19896
  * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.
19837
- * In this case, plural category 'one' is matched and "John, Marry and one other person are viewing"
19897
+ * In this case, plural category 'one' is matched and "John, Mary and one other person are viewing"
19838
19898
  * is shown.
19839
19899
  *
19840
19900
  * Note that when you specify offsets, you must provide explicit number rules for
@@ -20716,7 +20776,7 @@ var ngHideDirective = ['$animate', function($animate) {
20716
20776
  <file name="protractor.js" type="protractor">
20717
20777
  var colorSpan = element(by.css('span'));
20718
20778
 
20719
- iit('should check ng-style', function() {
20779
+ it('should check ng-style', function() {
20720
20780
  expect(colorSpan.getCssValue('color')).toBe('rgba(0, 0, 0, 1)');
20721
20781
  element(by.css('input[value=\'set color\']')).click();
20722
20782
  expect(colorSpan.getCssValue('color')).toBe('rgba(255, 0, 0, 1)');
@@ -21609,7 +21669,7 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
21609
21669
  // rather then the element.
21610
21670
  (element = optionTemplate.clone())
21611
21671
  .val(option.id)
21612
- .attr('selected', option.selected)
21672
+ .prop('selected', option.selected)
21613
21673
  .text(option.label);
21614
21674
  }
21615
21675