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
  */
@@ -68,7 +68,7 @@ function minErr(module) {
68
68
  return match;
69
69
  });
70
70
 
71
- message = message + '\nhttp://errors.angularjs.org/1.3.0-beta.13/' +
71
+ message = message + '\nhttp://errors.angularjs.org/1.3.0-beta.14/' +
72
72
  (module ? module + '/' : '') + code;
73
73
  for (i = 2; i < arguments.length; i++) {
74
74
  message = message + (i == 2 ? '?' : '&') + 'p' + (i-2) + '=' +
@@ -93,6 +93,7 @@ function minErr(module) {
93
93
  -nodeName_,
94
94
  -uid,
95
95
  -REGEX_STRING_REGEXP,
96
+ -VALIDITY_STATE_PROPERTY,
96
97
 
97
98
  -lowercase,
98
99
  -uppercase,
@@ -145,7 +146,6 @@ function minErr(module) {
145
146
  -toJsonReplacer,
146
147
  -toJson,
147
148
  -fromJson,
148
- -toBoolean,
149
149
  -startingTag,
150
150
  -tryDecodeURIComponent,
151
151
  -parseKeyValue,
@@ -184,6 +184,10 @@ function minErr(module) {
184
184
 
185
185
  var REGEX_STRING_REGEXP = /^\/(.+)\/([a-z]*)$/;
186
186
 
187
+ // The name of a form control's ValidityState property.
188
+ // This is used so that it's possible for internal tests to create mock ValidityStates.
189
+ var VALIDITY_STATE_PROPERTY = 'validity';
190
+
187
191
  /**
188
192
  * @ngdoc function
189
193
  * @name angular.lowercase
@@ -320,12 +324,12 @@ function forEach(obj, iterator, context) {
320
324
  iterator.call(context, obj[key], key);
321
325
  }
322
326
  }
323
- } else if (obj.forEach && obj.forEach !== forEach) {
324
- obj.forEach(iterator, context);
325
- } else if (isArrayLike(obj)) {
327
+ } else if (isArray(obj) || isArrayLike(obj)) {
326
328
  for (key = 0, length = obj.length; key < length; key++) {
327
329
  iterator.call(context, obj[key], key);
328
330
  }
331
+ } else if (obj.forEach && obj.forEach !== forEach) {
332
+ obj.forEach(iterator, context);
329
333
  } else {
330
334
  for (key in obj) {
331
335
  if (obj.hasOwnProperty(key)) {
@@ -694,12 +698,14 @@ function makeMap(str) {
694
698
  if (msie < 9) {
695
699
  nodeName_ = function(element) {
696
700
  element = element.nodeName ? element : element[0];
697
- return (element.scopeName && element.scopeName != 'HTML')
698
- ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;
701
+ return lowercase(
702
+ (element.scopeName && element.scopeName != 'HTML')
703
+ ? element.scopeName + ':' + element.nodeName : element.nodeName
704
+ );
699
705
  };
700
706
  } else {
701
707
  nodeName_ = function(element) {
702
- return element.nodeName ? element.nodeName : element[0].nodeName;
708
+ return lowercase(element.nodeName ? element.nodeName : element[0].nodeName);
703
709
  };
704
710
  }
705
711
 
@@ -762,10 +768,10 @@ function arrayRemove(array, value) {
762
768
 
763
769
  function isLeafNode (node) {
764
770
  if (node) {
765
- switch (node.nodeName) {
766
- case "OPTION":
767
- case "PRE":
768
- case "TITLE":
771
+ switch (nodeName_(node)) {
772
+ case "option":
773
+ case "pre":
774
+ case "title":
769
775
  return true;
770
776
  }
771
777
  }
@@ -845,7 +851,8 @@ function copy(source, destination, stackSource, stackDest) {
845
851
  } else if (isRegExp(source)) {
846
852
  destination = new RegExp(source.source);
847
853
  } else if (isObject(source)) {
848
- destination = copy(source, {}, stackSource, stackDest);
854
+ var emptyObject = Object.create(Object.getPrototypeOf(source));
855
+ destination = copy(source, emptyObject, stackSource, stackDest);
849
856
  }
850
857
  }
851
858
  } else {
@@ -880,12 +887,14 @@ function copy(source, destination, stackSource, stackDest) {
880
887
  delete destination[key];
881
888
  });
882
889
  for ( var key in source) {
883
- result = copy(source[key], null, stackSource, stackDest);
884
- if (isObject(source[key])) {
885
- stackSource.push(source[key]);
886
- stackDest.push(result);
890
+ if(source.hasOwnProperty(key)) {
891
+ result = copy(source[key], null, stackSource, stackDest);
892
+ if (isObject(source[key])) {
893
+ stackSource.push(source[key]);
894
+ stackDest.push(result);
895
+ }
896
+ destination[key] = result;
887
897
  }
888
- destination[key] = result;
889
898
  }
890
899
  setHashKey(destination,h);
891
900
  }
@@ -1105,18 +1114,6 @@ function fromJson(json) {
1105
1114
  }
1106
1115
 
1107
1116
 
1108
- function toBoolean(value) {
1109
- if (typeof value === 'function') {
1110
- value = true;
1111
- } else if (value && value.length !== 0) {
1112
- var v = lowercase("" + value);
1113
- value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');
1114
- } else {
1115
- value = false;
1116
- }
1117
- return value;
1118
- }
1119
-
1120
1117
  /**
1121
1118
  * @returns {string} Returns the string representation of the element.
1122
1119
  */
@@ -1446,7 +1443,7 @@ function angularInit(element, bootstrap) {
1446
1443
  *
1447
1444
  * Angular will detect if it has been loaded into the browser more than once and only allow the
1448
1445
  * first loaded script to be bootstrapped and will report a warning to the browser console for
1449
- * each of the subsequent scripts. This prevents strange results in applications, where otherwise
1446
+ * each of the subsequent scripts. This prevents strange results in applications, where otherwise
1450
1447
  * multiple instances of Angular try to work on the DOM.
1451
1448
  *
1452
1449
  * ```html
@@ -1589,7 +1586,7 @@ function assertArgFn(arg, name, acceptArrayAnnotation) {
1589
1586
  }
1590
1587
 
1591
1588
  assertArg(isFunction(arg), name, 'not a function, got ' +
1592
- (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg));
1589
+ (arg && typeof arg === 'object' ? arg.constructor.name || 'Object' : typeof arg));
1593
1590
  return arg;
1594
1591
  }
1595
1592
 
@@ -2044,6 +2041,7 @@ function setupModuleLoader(window) {
2044
2041
  $ParseProvider,
2045
2042
  $RootScopeProvider,
2046
2043
  $QProvider,
2044
+ $$QProvider,
2047
2045
  $$SanitizeUriProvider,
2048
2046
  $SceProvider,
2049
2047
  $SceDelegateProvider,
@@ -2071,11 +2069,11 @@ function setupModuleLoader(window) {
2071
2069
  * - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat".
2072
2070
  */
2073
2071
  var version = {
2074
- full: '1.3.0-beta.13', // all of these placeholder strings will be replaced by grunt's
2072
+ full: '1.3.0-beta.14', // all of these placeholder strings will be replaced by grunt's
2075
2073
  major: 1, // package task
2076
2074
  minor: 3,
2077
2075
  dot: 0,
2078
- codeName: 'idiosyncratic-numerification'
2076
+ codeName: 'harmonious-cacophonies'
2079
2077
  };
2080
2078
 
2081
2079
 
@@ -2193,6 +2191,7 @@ function publishExternalAPI(angular){
2193
2191
  $parse: $ParseProvider,
2194
2192
  $rootScope: $RootScopeProvider,
2195
2193
  $q: $QProvider,
2194
+ $$q: $$QProvider,
2196
2195
  $sce: $SceProvider,
2197
2196
  $sceDelegate: $SceDelegateProvider,
2198
2197
  $sniffer: $SnifferProvider,
@@ -2367,6 +2366,12 @@ function jqLiteIsTextNode(html) {
2367
2366
  return !HTML_REGEXP.test(html);
2368
2367
  }
2369
2368
 
2369
+ function jqLiteAcceptsData(node) {
2370
+ // The window object can accept data but has no nodeType
2371
+ // Otherwise we are only interested in elements (1) and documents (9)
2372
+ return !node.nodeType || node.nodeType === 1 || node.nodeType === 9;
2373
+ }
2374
+
2370
2375
  function jqLiteBuildFragment(html, context) {
2371
2376
  var elem, tmp, tag, wrap,
2372
2377
  fragment = context.createDocumentFragment(),
@@ -2514,30 +2519,29 @@ function jqLiteExpandoStore(element, key, value) {
2514
2519
  }
2515
2520
 
2516
2521
  function jqLiteData(element, key, value) {
2517
- var data = jqLiteExpandoStore(element, 'data'),
2518
- isSetter = isDefined(value),
2519
- keyDefined = !isSetter && isDefined(key),
2520
- isSimpleGetter = keyDefined && !isObject(key);
2521
-
2522
- if (!data && !isSimpleGetter) {
2523
- jqLiteExpandoStore(element, 'data', data = {});
2524
- }
2522
+ if (jqLiteAcceptsData(element)) {
2523
+ var data = jqLiteExpandoStore(element, 'data'),
2524
+ isSetter = isDefined(value),
2525
+ keyDefined = !isSetter && isDefined(key),
2526
+ isSimpleGetter = keyDefined && !isObject(key);
2527
+
2528
+ if (!data && !isSimpleGetter) {
2529
+ jqLiteExpandoStore(element, 'data', data = {});
2530
+ }
2525
2531
 
2526
- if (isSetter) {
2527
- // set data only on Elements and Documents
2528
- if (element.nodeType === 1 || element.nodeType === 9) {
2532
+ if (isSetter) {
2529
2533
  data[key] = value;
2530
- }
2531
- } else {
2532
- if (keyDefined) {
2533
- if (isSimpleGetter) {
2534
- // don't create data in this case.
2535
- return data && data[key];
2534
+ } else {
2535
+ if (keyDefined) {
2536
+ if (isSimpleGetter) {
2537
+ // don't create data in this case.
2538
+ return data && data[key];
2539
+ } else {
2540
+ extend(data, key);
2541
+ }
2536
2542
  } else {
2537
- extend(data, key);
2543
+ return data;
2538
2544
  }
2539
- } else {
2540
- return data;
2541
2545
  }
2542
2546
  }
2543
2547
  }
@@ -2591,6 +2595,10 @@ function jqLiteAddNodes(root, elements) {
2591
2595
  // if an Array or NodeList and not a Window
2592
2596
  if (typeof length === 'number' && elements.window !== elements) {
2593
2597
  if (length) {
2598
+ if (elements.item) {
2599
+ // convert NodeList to an Array to make PhantomJS 1.x happy
2600
+ elements = slice.call(elements);
2601
+ }
2594
2602
  push.apply(root, elements);
2595
2603
  }
2596
2604
  } else {
@@ -2688,7 +2696,7 @@ forEach('multiple,selected,checked,disabled,readOnly,required,open'.split(','),
2688
2696
  });
2689
2697
  var BOOLEAN_ELEMENTS = {};
2690
2698
  forEach('input,select,option,textarea,button,form,details'.split(','), function(value) {
2691
- BOOLEAN_ELEMENTS[uppercase(value)] = true;
2699
+ BOOLEAN_ELEMENTS[value] = true;
2692
2700
  });
2693
2701
  var ALIASED_ATTR = {
2694
2702
  'ngMinlength' : 'minlength',
@@ -2701,7 +2709,7 @@ function getBooleanAttrName(element, name) {
2701
2709
  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];
2702
2710
 
2703
2711
  // booleanAttr is here twice to minimize DOM access
2704
- return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;
2712
+ return booleanAttr && BOOLEAN_ELEMENTS[nodeName_(element)] && booleanAttr;
2705
2713
  }
2706
2714
 
2707
2715
  function getAliasedAttrName(element, name) {
@@ -2811,7 +2819,7 @@ forEach({
2811
2819
 
2812
2820
  val: function(element, value) {
2813
2821
  if (isUndefined(value)) {
2814
- if (nodeName_(element) === 'SELECT' && element.multiple) {
2822
+ if (element.multiple && nodeName_(element) === 'select') {
2815
2823
  var result = [];
2816
2824
  forEach(element.options, function (option) {
2817
2825
  if (option.selected) {
@@ -2956,6 +2964,11 @@ forEach({
2956
2964
  on: function onFn(element, type, fn, unsupported){
2957
2965
  if (isDefined(unsupported)) throw jqLiteMinErr('onargs', 'jqLite#on() does not support the `selector` or `eventData` parameters');
2958
2966
 
2967
+ // Do not add event handlers to non-elements because they will not be cleaned up.
2968
+ if (!jqLiteAcceptsData(element)) {
2969
+ return;
2970
+ }
2971
+
2959
2972
  var events = jqLiteExpandoStore(element, 'events'),
2960
2973
  handle = jqLiteExpandoStore(element, 'handle');
2961
2974
 
@@ -3145,7 +3158,12 @@ forEach({
3145
3158
  eventData = eventData || [];
3146
3159
 
3147
3160
  var event = [{
3148
- preventDefault: noop,
3161
+ preventDefault: function() {
3162
+ this.defaultPrevented = true;
3163
+ },
3164
+ isDefaultPrevented: function() {
3165
+ return this.defaultPrevented === true;
3166
+ },
3149
3167
  stopPropagation: noop
3150
3168
  }];
3151
3169
 
@@ -3190,16 +3208,16 @@ forEach({
3190
3208
  * @returns {string} hash string such that the same input will have the same hash string.
3191
3209
  * The resulting string key is in 'type:hashKey' format.
3192
3210
  */
3193
- function hashKey(obj) {
3211
+ function hashKey(obj, nextUidFn) {
3194
3212
  var objType = typeof obj,
3195
3213
  key;
3196
3214
 
3197
- if (objType == 'object' && obj !== null) {
3215
+ if (objType == 'function' || (objType == 'object' && obj !== null)) {
3198
3216
  if (typeof (key = obj.$$hashKey) == 'function') {
3199
3217
  // must invoke on object to keep the right this
3200
3218
  key = obj.$$hashKey();
3201
3219
  } else if (key === undefined) {
3202
- key = obj.$$hashKey = nextUid();
3220
+ key = obj.$$hashKey = (nextUidFn || nextUid)();
3203
3221
  }
3204
3222
  } else {
3205
3223
  key = obj;
@@ -3211,7 +3229,13 @@ function hashKey(obj) {
3211
3229
  /**
3212
3230
  * HashMap which can use objects as keys
3213
3231
  */
3214
- function HashMap(array){
3232
+ function HashMap(array, isolatedUid) {
3233
+ if (isolatedUid) {
3234
+ var uid = 0;
3235
+ this.nextUid = function() {
3236
+ return ++uid;
3237
+ };
3238
+ }
3215
3239
  forEach(array, this.put, this);
3216
3240
  }
3217
3241
  HashMap.prototype = {
@@ -3221,7 +3245,7 @@ HashMap.prototype = {
3221
3245
  * @param value value to store can be any type
3222
3246
  */
3223
3247
  put: function(key, value) {
3224
- this[hashKey(key)] = value;
3248
+ this[hashKey(key, this.nextUid)] = value;
3225
3249
  },
3226
3250
 
3227
3251
  /**
@@ -3229,7 +3253,7 @@ HashMap.prototype = {
3229
3253
  * @returns {Object} the value for the key
3230
3254
  */
3231
3255
  get: function(key) {
3232
- return this[hashKey(key)];
3256
+ return this[hashKey(key, this.nextUid)];
3233
3257
  },
3234
3258
 
3235
3259
  /**
@@ -3237,7 +3261,7 @@ HashMap.prototype = {
3237
3261
  * @param key
3238
3262
  */
3239
3263
  remove: function(key) {
3240
- var value = this[key = hashKey(key)];
3264
+ var value = this[key = hashKey(key, this.nextUid)];
3241
3265
  delete this[key];
3242
3266
  return value;
3243
3267
  }
@@ -3327,7 +3351,7 @@ function annotate(fn, strictDi, name) {
3327
3351
  argDecl,
3328
3352
  last;
3329
3353
 
3330
- if (typeof fn == 'function') {
3354
+ if (typeof fn === 'function') {
3331
3355
  if (!($inject = fn.$inject)) {
3332
3356
  $inject = [];
3333
3357
  if (fn.length) {
@@ -3547,7 +3571,7 @@ function annotate(fn, strictDi, name) {
3547
3571
 
3548
3572
 
3549
3573
  /**
3550
- * @ngdoc object
3574
+ * @ngdoc service
3551
3575
  * @name $provide
3552
3576
  *
3553
3577
  * @description
@@ -3854,7 +3878,7 @@ function createInjector(modulesToLoad, strictDi) {
3854
3878
  var INSTANTIATING = {},
3855
3879
  providerSuffix = 'Provider',
3856
3880
  path = [],
3857
- loadedModules = new HashMap(),
3881
+ loadedModules = new HashMap([], true),
3858
3882
  providerCache = {
3859
3883
  $provide: {
3860
3884
  provider: supportObject(provider),
@@ -4035,8 +4059,7 @@ function createInjector(modulesToLoad, strictDi) {
4035
4059
  : getService(key)
4036
4060
  );
4037
4061
  }
4038
- if (!fn.$inject) {
4039
- // this means that we must be an array.
4062
+ if (isArray(fn)) {
4040
4063
  fn = fn[length];
4041
4064
  }
4042
4065
 
@@ -4139,7 +4162,7 @@ function $AnchorScrollProvider() {
4139
4162
  function getFirstAnchor(list) {
4140
4163
  var result = null;
4141
4164
  forEach(list, function(element) {
4142
- if (!result && lowercase(element.nodeName) === 'a') result = element;
4165
+ if (!result && nodeName_(element) === 'a') result = element;
4143
4166
  });
4144
4167
  return result;
4145
4168
  }
@@ -5964,8 +5987,8 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
5964
5987
  nodeName = nodeName_(this.$$element);
5965
5988
 
5966
5989
  // sanitize a[href] and img[src] values
5967
- if ((nodeName === 'A' && key === 'href') ||
5968
- (nodeName === 'IMG' && key === 'src')) {
5990
+ if ((nodeName === 'a' && key === 'href') ||
5991
+ (nodeName === 'img' && key === 'src')) {
5969
5992
  this[key] = value = $$sanitizeUri(value, key === 'src');
5970
5993
  }
5971
5994
 
@@ -6235,10 +6258,10 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
6235
6258
  case 1: /* Element */
6236
6259
  // use the node name: <directive>
6237
6260
  addDirective(directives,
6238
- directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority, ignoreDirective);
6261
+ directiveNormalize(nodeName_(node)), 'E', maxPriority, ignoreDirective);
6239
6262
 
6240
6263
  // iterate over the attributes
6241
- for (var attr, name, nName, ngAttrName, value, nAttrs = node.attributes,
6264
+ for (var attr, name, nName, ngAttrName, value, isNgAttr, nAttrs = node.attributes,
6242
6265
  j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {
6243
6266
  var attrStartName = false;
6244
6267
  var attrEndName = false;
@@ -6246,9 +6269,11 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
6246
6269
  attr = nAttrs[j];
6247
6270
  if (!msie || msie >= 8 || attr.specified) {
6248
6271
  name = attr.name;
6272
+ value = trim(attr.value);
6273
+
6249
6274
  // support ngAttr attribute binding
6250
6275
  ngAttrName = directiveNormalize(name);
6251
- if (NG_ATTR_BINDING.test(ngAttrName)) {
6276
+ if (isNgAttr = NG_ATTR_BINDING.test(ngAttrName)) {
6252
6277
  name = snake_case(ngAttrName.substr(6), '-');
6253
6278
  }
6254
6279
 
@@ -6261,9 +6286,11 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
6261
6286
 
6262
6287
  nName = directiveNormalize(name.toLowerCase());
6263
6288
  attrsMap[nName] = name;
6264
- attrs[nName] = value = trim(attr.value);
6265
- if (getBooleanAttrName(node, nName)) {
6266
- attrs[nName] = true; // presence means true
6289
+ if (isNgAttr || !attrs.hasOwnProperty(nName)) {
6290
+ attrs[nName] = value;
6291
+ if (getBooleanAttrName(node, nName)) {
6292
+ attrs[nName] = true; // presence means true
6293
+ }
6267
6294
  }
6268
6295
  addAttrInterpolateDirective(node, directives, value, nName);
6269
6296
  addDirective(directives, nName, 'A', maxPriority, ignoreDirective, attrStartName,
@@ -7098,8 +7125,8 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
7098
7125
  var tag = nodeName_(node);
7099
7126
  // maction[xlink:href] can source SVG. It's not limited to <maction>.
7100
7127
  if (attrNormalizedName == "xlinkHref" ||
7101
- (tag == "FORM" && attrNormalizedName == "action") ||
7102
- (tag != "IMG" && (attrNormalizedName == "src" ||
7128
+ (tag == "form" && attrNormalizedName == "action") ||
7129
+ (tag != "img" && (attrNormalizedName == "src" ||
7103
7130
  attrNormalizedName == "ngSrc"))) {
7104
7131
  return $sce.RESOURCE_URL;
7105
7132
  }
@@ -7113,7 +7140,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
7113
7140
  if (!interpolateFn) return;
7114
7141
 
7115
7142
 
7116
- if (name === "multiple" && nodeName_(node) === "SELECT") {
7143
+ if (name === "multiple" && nodeName_(node) === "select") {
7117
7144
  throw $compileMinErr("selmulti",
7118
7145
  "Binding to the 'multiple' attribute is not supported. Element: {0}",
7119
7146
  startingTag(node));
@@ -7391,7 +7418,7 @@ function $ControllerProvider() {
7391
7418
  instance = $injector.instantiate(expression, locals, constructor);
7392
7419
 
7393
7420
  if (identifier) {
7394
- if (!(locals && typeof locals.$scope == 'object')) {
7421
+ if (!(locals && typeof locals.$scope === 'object')) {
7395
7422
  throw minErr('$controller')('noscp',
7396
7423
  "Cannot export controller '{0}' as '{1}'! No $scope object provided via `locals`.",
7397
7424
  constructor || expression.name, identifier);
@@ -8265,7 +8292,21 @@ function $HttpProvider() {
8265
8292
  * @param {Object=} config Optional configuration object
8266
8293
  * @returns {HttpPromise} Future object
8267
8294
  */
8268
- createShortMethodsWithData('post', 'put');
8295
+
8296
+ /**
8297
+ * @ngdoc method
8298
+ * @name ng.$http#patch
8299
+ * @methodOf ng.$http
8300
+ *
8301
+ * @description
8302
+ * Shortcut method to perform `PATCH` request.
8303
+ *
8304
+ * @param {string} url Relative or absolute URL specifying the destination of the request
8305
+ * @param {*} data Request content
8306
+ * @param {Object=} config Optional configuration object
8307
+ * @returns {HttpPromise} Future object
8308
+ */
8309
+ createShortMethodsWithData('post', 'put', 'patch');
8269
8310
 
8270
8311
  /**
8271
8312
  * @ngdoc property
@@ -8521,7 +8562,8 @@ function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDoc
8521
8562
  // Safari respectively.
8522
8563
  if (xhr && xhr.readyState == 4) {
8523
8564
  var responseHeaders = null,
8524
- response = null;
8565
+ response = null,
8566
+ statusText = '';
8525
8567
 
8526
8568
  if(status !== ABORTED) {
8527
8569
  responseHeaders = xhr.getAllResponseHeaders();
@@ -8531,11 +8573,17 @@ function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDoc
8531
8573
  response = ('response' in xhr) ? xhr.response : xhr.responseText;
8532
8574
  }
8533
8575
 
8576
+ // Accessing statusText on an aborted xhr object will
8577
+ // throw an 'c00c023f error' in IE9 and lower, don't touch it.
8578
+ if (!(status === ABORTED && msie < 10)) {
8579
+ statusText = xhr.statusText;
8580
+ }
8581
+
8534
8582
  completeRequest(callback,
8535
8583
  status || xhr.status,
8536
8584
  response,
8537
8585
  responseHeaders,
8538
- xhr.statusText || '');
8586
+ statusText);
8539
8587
  }
8540
8588
  };
8541
8589
 
@@ -9015,8 +9063,8 @@ function $InterpolateProvider() {
9015
9063
  }
9016
9064
 
9017
9065
  function $IntervalProvider() {
9018
- this.$get = ['$rootScope', '$window', '$q',
9019
- function($rootScope, $window, $q) {
9066
+ this.$get = ['$rootScope', '$window', '$q', '$$q',
9067
+ function($rootScope, $window, $q, $$q) {
9020
9068
  var intervals = {};
9021
9069
 
9022
9070
 
@@ -9146,10 +9194,10 @@ function $IntervalProvider() {
9146
9194
  function interval(fn, delay, count, invokeApply) {
9147
9195
  var setInterval = $window.setInterval,
9148
9196
  clearInterval = $window.clearInterval,
9149
- deferred = $q.defer(),
9150
- promise = deferred.promise,
9151
9197
  iteration = 0,
9152
- skipApply = (isDefined(invokeApply) && !invokeApply);
9198
+ skipApply = (isDefined(invokeApply) && !invokeApply),
9199
+ deferred = (skipApply ? $$q : $q).defer(),
9200
+ promise = deferred.promise;
9153
9201
 
9154
9202
  count = isDefined(count) ? count : 0;
9155
9203
 
@@ -9187,7 +9235,7 @@ function $IntervalProvider() {
9187
9235
  interval.cancel = function(promise) {
9188
9236
  if (promise && promise.$$intervalId in intervals) {
9189
9237
  intervals[promise.$$intervalId].reject('canceled');
9190
- clearInterval(promise.$$intervalId);
9238
+ $window.clearInterval(promise.$$intervalId);
9191
9239
  delete intervals[promise.$$intervalId];
9192
9240
  return true;
9193
9241
  }
@@ -9821,7 +9869,7 @@ function $LocationProvider(){
9821
9869
  html5Mode = false;
9822
9870
 
9823
9871
  /**
9824
- * @ngdoc property
9872
+ * @ngdoc method
9825
9873
  * @name $locationProvider#hashPrefix
9826
9874
  * @description
9827
9875
  * @param {string=} prefix Prefix for hash part (containing path and search)
@@ -9837,7 +9885,7 @@ function $LocationProvider(){
9837
9885
  };
9838
9886
 
9839
9887
  /**
9840
- * @ngdoc property
9888
+ * @ngdoc method
9841
9889
  * @name $locationProvider#html5Mode
9842
9890
  * @description
9843
9891
  * @param {boolean=} mode Use HTML5 strategy if available.
@@ -9906,7 +9954,7 @@ function $LocationProvider(){
9906
9954
  var elm = jqLite(event.target);
9907
9955
 
9908
9956
  // traverse the DOM up to find first A tag
9909
- while (lowercase(elm[0].nodeName) !== 'a') {
9957
+ while (nodeName_(elm[0]) !== 'a') {
9910
9958
  // ignore rewriting if no A tag (reached root element, or no parent - removed from document)
9911
9959
  if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;
9912
9960
  }
@@ -10193,14 +10241,7 @@ var $parseMinErr = minErr('$parse');
10193
10241
  //
10194
10242
  // As an example, consider the following Angular expression:
10195
10243
  //
10196
- // {}.toString.constructor(alert("evil JS code"))
10197
- //
10198
- // We want to prevent this type of access. For the sake of performance, during the lexing phase we
10199
- // disallow any "dotted" access to any member named "constructor".
10200
- //
10201
- // For reflective calls (a[b]) we check that the value of the lookup is not the Function constructor
10202
- // while evaluating the expression, which is a stronger but more expensive test. Since reflective
10203
- // calls are expensive anyway, this is not such a big deal compared to static dereferencing.
10244
+ // {}.toString.constructor('alert("evil JS code")')
10204
10245
  //
10205
10246
  // This sandboxing technique is not perfect and doesn't aim to be. The goal is to prevent exploits
10206
10247
  // against the expression language, but not to prevent exploits that were enabled by exposing
@@ -10208,17 +10249,19 @@ var $parseMinErr = minErr('$parse');
10208
10249
  // practice and therefore we are not even trying to protect against interaction with an object
10209
10250
  // explicitly exposed in this way.
10210
10251
  //
10211
- // A developer could foil the name check by aliasing the Function constructor under a different
10212
- // name on the scope.
10213
- //
10214
10252
  // In general, it is not possible to access a Window object from an angular expression unless a
10215
10253
  // window or some DOM object that has a reference to window is published onto a Scope.
10254
+ // Similarly we prevent invocations of function known to be dangerous, as well as assignments to
10255
+ // native objects.
10256
+
10216
10257
 
10217
10258
  function ensureSafeMemberName(name, fullExpression) {
10218
- if (name === "constructor") {
10259
+ if (name === "__defineGetter__" || name === "__defineSetter__"
10260
+ || name === "__lookupGetter__" || name === "__lookupSetter__"
10261
+ || name === "__proto__") {
10219
10262
  throw $parseMinErr('isecfld',
10220
- 'Referencing "constructor" field in Angular expressions is disallowed! Expression: {0}',
10221
- fullExpression);
10263
+ 'Attempting to access a disallowed field in Angular expressions! '
10264
+ +'Expression: {0}', fullExpression);
10222
10265
  }
10223
10266
  return name;
10224
10267
  }
@@ -10231,7 +10274,7 @@ function ensureSafeObject(obj, fullExpression) {
10231
10274
  'Referencing Function in Angular expressions is disallowed! Expression: {0}',
10232
10275
  fullExpression);
10233
10276
  } else if (// isWindow(obj)
10234
- obj.document && obj.location && obj.alert && obj.setInterval) {
10277
+ obj.window === obj) {
10235
10278
  throw $parseMinErr('isecwindow',
10236
10279
  'Referencing the Window in Angular expressions is disallowed! Expression: {0}',
10237
10280
  fullExpression);
@@ -10240,11 +10283,34 @@ function ensureSafeObject(obj, fullExpression) {
10240
10283
  throw $parseMinErr('isecdom',
10241
10284
  'Referencing DOM nodes in Angular expressions is disallowed! Expression: {0}',
10242
10285
  fullExpression);
10286
+ } else if (// block Object so that we can't get hold of dangerous Object.* methods
10287
+ obj === Object) {
10288
+ throw $parseMinErr('isecobj',
10289
+ 'Referencing Object in Angular expressions is disallowed! Expression: {0}',
10290
+ fullExpression);
10243
10291
  }
10244
10292
  }
10245
10293
  return obj;
10246
10294
  }
10247
10295
 
10296
+ var CALL = Function.prototype.call;
10297
+ var APPLY = Function.prototype.apply;
10298
+ var BIND = Function.prototype.bind;
10299
+
10300
+ function ensureSafeFunction(obj, fullExpression) {
10301
+ if (obj) {
10302
+ if (obj.constructor === obj) {
10303
+ throw $parseMinErr('isecfn',
10304
+ 'Referencing Function in Angular expressions is disallowed! Expression: {0}',
10305
+ fullExpression);
10306
+ } else if (obj === CALL || obj === APPLY || obj === BIND) {
10307
+ throw $parseMinErr('isecff',
10308
+ 'Referencing call, apply or bind in Angular expressions is disallowed! Expression: {0}',
10309
+ fullExpression);
10310
+ }
10311
+ }
10312
+ }
10313
+
10248
10314
  var OPERATORS = {
10249
10315
  /* jshint bitwise : false */
10250
10316
  'null':function(){return null;},
@@ -10864,6 +10930,7 @@ Parser.prototype = {
10864
10930
  i = indexFn(self, locals),
10865
10931
  v;
10866
10932
 
10933
+ ensureSafeMemberName(i, parser.text);
10867
10934
  if (!o) return undefined;
10868
10935
  v = ensureSafeObject(o[i], parser.text);
10869
10936
  return v;
@@ -10898,7 +10965,7 @@ Parser.prototype = {
10898
10965
  var fnPtr = fn(scope, locals, context) || noop;
10899
10966
 
10900
10967
  ensureSafeObject(context, parser.text);
10901
- ensureSafeObject(fnPtr, parser.text);
10968
+ ensureSafeFunction(fnPtr, parser.text);
10902
10969
 
10903
10970
  // IE stupidity! (IE doesn't have apply for some native functions)
10904
10971
  var v = fnPtr.apply
@@ -10993,6 +11060,8 @@ function setter(obj, path, setValue, fullExp) {
10993
11060
  obj = propertyObj;
10994
11061
  }
10995
11062
  key = ensureSafeMemberName(element.shift(), fullExp);
11063
+ ensureSafeObject(obj, fullExp);
11064
+ ensureSafeObject(obj[key], fullExp);
10996
11065
  obj[key] = setValue;
10997
11066
  return setValue;
10998
11067
  }
@@ -11210,11 +11279,7 @@ function $ParseProvider() {
11210
11279
  cache[exp] = parsedExpression;
11211
11280
  }
11212
11281
 
11213
- if (parsedExpression.constant) {
11214
- parsedExpression.$$unwatch = true;
11215
- }
11216
-
11217
- return oneTime ? oneTimeWrapper(parsedExpression) : parsedExpression;
11282
+ return oneTime || parsedExpression.constant ? oneTimeWrapper(parsedExpression) : parsedExpression;
11218
11283
 
11219
11284
  case 'function':
11220
11285
  return exp;
@@ -11233,7 +11298,7 @@ function $ParseProvider() {
11233
11298
 
11234
11299
  function oneTimeParseFn(self, locals) {
11235
11300
  if (!stable) {
11236
- lastValue = expression(self, locals);
11301
+ lastValue = expression.constant && lastValue ? lastValue : expression(self, locals);
11237
11302
  oneTimeParseFn.$$unwatch = isDefined(lastValue);
11238
11303
  if (oneTimeParseFn.$$unwatch && self && self.$$postDigestQueue) {
11239
11304
  self.$$postDigestQueue.push(function () {
@@ -11275,17 +11340,13 @@ function $ParseProvider() {
11275
11340
  * var deferred = $q.defer();
11276
11341
  *
11277
11342
  * setTimeout(function() {
11278
- * // since this fn executes async in a future turn of the event loop, we need to wrap
11279
- * // our code into an $apply call so that the model changes are properly observed.
11280
- * scope.$apply(function() {
11281
- * deferred.notify('About to greet ' + name + '.');
11282
- *
11283
- * if (okToGreet(name)) {
11284
- * deferred.resolve('Hello, ' + name + '!');
11285
- * } else {
11286
- * deferred.reject('Greeting ' + name + ' is not allowed.');
11287
- * }
11288
- * });
11343
+ * deferred.notify('About to greet ' + name + '.');
11344
+ *
11345
+ * if (okToGreet(name)) {
11346
+ * deferred.resolve('Hello, ' + name + '!');
11347
+ * } else {
11348
+ * deferred.reject('Greeting ' + name + ' is not allowed.');
11349
+ * }
11289
11350
  * }, 1000);
11290
11351
  *
11291
11352
  * return deferred.promise;
@@ -11429,6 +11490,13 @@ function $QProvider() {
11429
11490
  }];
11430
11491
  }
11431
11492
 
11493
+ function $$QProvider() {
11494
+ this.$get = ['$browser', '$exceptionHandler', function($browser, $exceptionHandler) {
11495
+ return qFactory(function(callback) {
11496
+ $browser.defer(callback);
11497
+ }, $exceptionHandler);
11498
+ }];
11499
+ }
11432
11500
 
11433
11501
  /**
11434
11502
  * Constructs a promise manager.
@@ -12176,7 +12244,7 @@ function $RootScopeProvider(){
12176
12244
  * A variant of {@link ng.$rootScope.Scope#$watch $watch()} where it watches an array of `watchExpressions`.
12177
12245
  * If any one expression in the collection changes the `listener` is executed.
12178
12246
  *
12179
- * - The items in the `watchCollection` array are observed via standard $watch operation and are examined on every
12247
+ * - The items in the `watchExpressions` array are observed via standard $watch operation and are examined on every
12180
12248
  * call to $digest() to see if any items changes.
12181
12249
  * - The `listener` is called whenever any expression in the `watchExpressions` array changes.
12182
12250
  *
@@ -12506,7 +12574,7 @@ function $RootScopeProvider(){
12506
12574
  if ((value = watch.get(current)) !== (last = watch.last) &&
12507
12575
  !(watch.eq
12508
12576
  ? equals(value, last)
12509
- : (typeof value == 'number' && typeof last == 'number'
12577
+ : (typeof value === 'number' && typeof last === 'number'
12510
12578
  && isNaN(value) && isNaN(last)))) {
12511
12579
  dirty = true;
12512
12580
  lastDirtyWatch = watch;
@@ -13866,7 +13934,7 @@ function $SceProvider() {
13866
13934
 
13867
13935
  /**
13868
13936
  * @ngdoc method
13869
- * @name $sce#parse
13937
+ * @name $sce#parseAs
13870
13938
  *
13871
13939
  * @description
13872
13940
  * Converts Angular {@link guide/expression expression} into a function. This is like {@link
@@ -14253,8 +14321,8 @@ function $SnifferProvider() {
14253
14321
  }
14254
14322
 
14255
14323
  function $TimeoutProvider() {
14256
- this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler',
14257
- function($rootScope, $browser, $q, $exceptionHandler) {
14324
+ this.$get = ['$rootScope', '$browser', '$q', '$$q', '$exceptionHandler',
14325
+ function($rootScope, $browser, $q, $$q, $exceptionHandler) {
14258
14326
  var deferreds = {};
14259
14327
 
14260
14328
 
@@ -14284,9 +14352,9 @@ function $TimeoutProvider() {
14284
14352
  *
14285
14353
  */
14286
14354
  function timeout(fn, delay, invokeApply) {
14287
- var deferred = $q.defer(),
14355
+ var skipApply = (isDefined(invokeApply) && !invokeApply),
14356
+ deferred = (skipApply ? $$q : $q).defer(),
14288
14357
  promise = deferred.promise,
14289
- skipApply = (isDefined(invokeApply) && !invokeApply),
14290
14358
  timeoutId;
14291
14359
 
14292
14360
  timeoutId = $browser.defer(function() {
@@ -14824,7 +14892,7 @@ function filterFilter() {
14824
14892
  // jshint +W086
14825
14893
  for (var key in expression) {
14826
14894
  (function(path) {
14827
- if (typeof expression[path] == 'undefined') return;
14895
+ if (typeof expression[path] === 'undefined') return;
14828
14896
  predicates.push(function(value) {
14829
14897
  return search(path == '$' ? value : (value && value[path]), expression[path]);
14830
14898
  });
@@ -14979,6 +15047,7 @@ function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {
14979
15047
  var match = numStr.match(/([\d\.]+)e(-?)(\d+)/);
14980
15048
  if (match && match[2] == '-' && match[3] > fractionSize + 1) {
14981
15049
  numStr = '0';
15050
+ number = 0;
14982
15051
  } else {
14983
15052
  formatedText = numStr;
14984
15053
  hasExponent = true;
@@ -14993,8 +15062,11 @@ function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {
14993
15062
  fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);
14994
15063
  }
14995
15064
 
14996
- var pow = Math.pow(10, fractionSize + 1);
14997
- number = Math.floor(number * pow + 5) / pow;
15065
+ // safely round numbers in JS without hitting imprecisions of floating-point arithmetics
15066
+ // inspired by:
15067
+ // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round
15068
+ number = +(Math.round(+(number.toString() + 'e' + fractionSize)).toString() + 'e' + -fractionSize);
15069
+
14998
15070
  var fraction = ('' + number).split(DECIMAL_SEP);
14999
15071
  var whole = fraction[0];
15000
15072
  fraction = fraction[1] || '';
@@ -15617,7 +15689,7 @@ function orderByFilter($parse){
15617
15689
  return 0;
15618
15690
  }
15619
15691
  function reverseComparator(comp, descending) {
15620
- return toBoolean(descending)
15692
+ return descending
15621
15693
  ? function(a,b){return comp(b,a);}
15622
15694
  : comp;
15623
15695
  }
@@ -16576,7 +16648,7 @@ var ngFormDirective = formDirectiveFactory(true);
16576
16648
  */
16577
16649
 
16578
16650
  var URL_REGEXP = /^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/;
16579
- var EMAIL_REGEXP = /^[a-z0-9!#$%&'*+/=?^_`{|}~.-]+@[a-z0-9-]+(\.[a-z0-9-]+)*$/i;
16651
+ var EMAIL_REGEXP = /^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9-]+(\.[a-z0-9-]+)*$/i;
16580
16652
  var NUMBER_REGEXP = /^\s*(\-|\+)?(\d+|(\d*(\.\d*)))\s*$/;
16581
16653
  var DATE_REGEXP = /^(\d{4})-(\d{2})-(\d{2})$/;
16582
16654
  var DATETIMELOCAL_REGEXP = /^(\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d)$/;
@@ -16742,7 +16814,7 @@ var inputType = {
16742
16814
  expect(valid.getText()).toContain('myForm.input.$valid = false');
16743
16815
  });
16744
16816
  </file>
16745
- </example>f
16817
+ </example>
16746
16818
  */
16747
16819
  'date': createDateInputType('date', DATE_REGEXP,
16748
16820
  createDateParser(DATE_REGEXP, ['yyyy', 'MM', 'dd']),
@@ -17427,15 +17499,29 @@ function validate(ctrl, validatorName, validity, value){
17427
17499
  return validity ? value : undefined;
17428
17500
  }
17429
17501
 
17502
+ function testFlags(validity, flags) {
17503
+ var i, flag;
17504
+ if (flags) {
17505
+ for (i=0; i<flags.length; ++i) {
17506
+ flag = flags[i];
17507
+ if (validity[flag]) {
17508
+ return true;
17509
+ }
17510
+ }
17511
+ }
17512
+ return false;
17513
+ }
17430
17514
 
17431
- function addNativeHtml5Validators(ctrl, validatorName, element) {
17432
- var validity = element.prop('validity');
17515
+ // Pass validity so that behaviour can be mocked easier.
17516
+ function addNativeHtml5Validators(ctrl, validatorName, badFlags, ignoreFlags, validity) {
17433
17517
  if (isObject(validity)) {
17518
+ ctrl.$$hasNativeValidators = true;
17434
17519
  var validator = function(value) {
17435
17520
  // Don't overwrite previous validation, don't consider valueMissing to apply (ng-required can
17436
17521
  // perform the required validation)
17437
- if (!ctrl.$error[validatorName] && (validity.badInput || validity.customError ||
17438
- validity.typeMismatch) && !validity.valueMissing) {
17522
+ if (!ctrl.$error[validatorName] &&
17523
+ !testFlags(validity, ignoreFlags) &&
17524
+ testFlags(validity, badFlags)) {
17439
17525
  ctrl.$setValidity(validatorName, false);
17440
17526
  return;
17441
17527
  }
@@ -17446,8 +17532,9 @@ function addNativeHtml5Validators(ctrl, validatorName, element) {
17446
17532
  }
17447
17533
 
17448
17534
  function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
17449
- var validity = element.prop('validity');
17535
+ var validity = element.prop(VALIDITY_STATE_PROPERTY);
17450
17536
  var placeholder = element[0].placeholder, noevent = {};
17537
+ ctrl.$$validityState = validity;
17451
17538
 
17452
17539
  // In composition mode, users are still inputing intermediate text buffer,
17453
17540
  // hold the listener until composition is done.
@@ -17482,20 +17569,20 @@ function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
17482
17569
  // By default we will trim the value
17483
17570
  // If the attribute ng-trim exists we will avoid trimming
17484
17571
  // e.g. <input ng-model="foo" ng-trim="false">
17485
- if (toBoolean(attr.ngTrim || 'T')) {
17572
+ if (!attr.ngTrim || attr.ngTrim !== 'false') {
17486
17573
  value = trim(value);
17487
17574
  }
17488
17575
 
17489
- if (ctrl.$viewValue !== value ||
17490
- // If the value is still empty/falsy, and there is no `required` error, run validators
17491
- // again. This enables HTML5 constraint validation errors to affect Angular validation
17492
- // even when the first character entered causes an error.
17493
- (validity && value === '' && !validity.valueMissing)) {
17576
+ // If a control is suffering from bad input, browsers discard its value, so it may be
17577
+ // necessary to revalidate even if the control's value is the same empty value twice in
17578
+ // a row.
17579
+ var revalidate = validity && ctrl.$$hasNativeValidators;
17580
+ if (ctrl.$viewValue !== value || (value === '' && revalidate)) {
17494
17581
  if (scope.$$phase) {
17495
- ctrl.$setViewValue(value, event);
17582
+ ctrl.$setViewValue(value, event, revalidate);
17496
17583
  } else {
17497
17584
  scope.$apply(function() {
17498
- ctrl.$setViewValue(value, event);
17585
+ ctrl.$setViewValue(value, event, revalidate);
17499
17586
  });
17500
17587
  }
17501
17588
  }
@@ -17644,6 +17731,8 @@ function createDateInputType(type, regexp, parseDate, format) {
17644
17731
  };
17645
17732
  }
17646
17733
 
17734
+ var numberBadFlags = ['badInput'];
17735
+
17647
17736
  function numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {
17648
17737
  textInputType(scope, element, attr, ctrl, $sniffer, $browser);
17649
17738
 
@@ -17658,7 +17747,7 @@ function numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {
17658
17747
  }
17659
17748
  });
17660
17749
 
17661
- addNativeHtml5Validators(ctrl, 'number', element);
17750
+ addNativeHtml5Validators(ctrl, 'number', numberBadFlags, null, ctrl.$$validityState);
17662
17751
 
17663
17752
  ctrl.$formatters.push(function(value) {
17664
17753
  return ctrl.$isEmpty(value) ? '' : '' + value;
@@ -17692,23 +17781,19 @@ function numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {
17692
17781
  function urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {
17693
17782
  textInputType(scope, element, attr, ctrl, $sniffer, $browser);
17694
17783
 
17695
- var urlValidator = function(value) {
17696
- return validate(ctrl, 'url', ctrl.$isEmpty(value) || URL_REGEXP.test(value), value);
17784
+ ctrl.$validators.url = function(modelValue, viewValue) {
17785
+ var value = modelValue || viewValue;
17786
+ return ctrl.$isEmpty(value) || URL_REGEXP.test(value);
17697
17787
  };
17698
-
17699
- ctrl.$formatters.push(urlValidator);
17700
- ctrl.$parsers.push(urlValidator);
17701
17788
  }
17702
17789
 
17703
17790
  function emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {
17704
17791
  textInputType(scope, element, attr, ctrl, $sniffer, $browser);
17705
17792
 
17706
- var emailValidator = function(value) {
17707
- return validate(ctrl, 'email', ctrl.$isEmpty(value) || EMAIL_REGEXP.test(value), value);
17793
+ ctrl.$validators.email = function(modelValue, viewValue) {
17794
+ var value = modelValue || viewValue;
17795
+ return ctrl.$isEmpty(value) || EMAIL_REGEXP.test(value);
17708
17796
  };
17709
-
17710
- ctrl.$formatters.push(emailValidator);
17711
- ctrl.$parsers.push(emailValidator);
17712
17797
  }
17713
17798
 
17714
17799
  function radioInputType(scope, element, attr, ctrl) {
@@ -18163,7 +18248,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
18163
18248
  * `ngModel.$validators` pipeline which is designed to handle validations with true/false values.
18164
18249
  *
18165
18250
  * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign
18166
- * to `$error[validationErrorKey]=isValid` so that it is available for data-binding.
18251
+ * to `$error[validationErrorKey]=!isValid` so that it is available for data-binding.
18167
18252
  * The `validationErrorKey` should be in camelCase and will get converted into dash-case
18168
18253
  * for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`
18169
18254
  * class and can be bound to as `{{someForm.someControl.$error.myError}}` .
@@ -18342,11 +18427,11 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
18342
18427
  * event defined in `ng-model-options`. this method is rarely needed as `NgModelController`
18343
18428
  * usually handles calling this in response to input events.
18344
18429
  */
18345
- this.$commitViewValue = function() {
18430
+ this.$commitViewValue = function(revalidate) {
18346
18431
  var viewValue = ctrl.$viewValue;
18347
18432
 
18348
18433
  $timeout.cancel(pendingDebounce);
18349
- if (ctrl.$$lastCommittedViewValue === viewValue) {
18434
+ if (!revalidate && ctrl.$$lastCommittedViewValue === viewValue) {
18350
18435
  return;
18351
18436
  }
18352
18437
  ctrl.$$lastCommittedViewValue = viewValue;
@@ -18411,14 +18496,14 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
18411
18496
  * @param {string} value Value from the view.
18412
18497
  * @param {string} trigger Event that triggered the update.
18413
18498
  */
18414
- this.$setViewValue = function(value, trigger) {
18499
+ this.$setViewValue = function(value, trigger, revalidate) {
18415
18500
  ctrl.$viewValue = value;
18416
18501
  if (!ctrl.$options || ctrl.$options.updateOnDefault) {
18417
- ctrl.$$debounceViewValueCommit(trigger);
18502
+ ctrl.$$debounceViewValueCommit(trigger, revalidate);
18418
18503
  }
18419
18504
  };
18420
18505
 
18421
- this.$$debounceViewValueCommit = function(trigger) {
18506
+ this.$$debounceViewValueCommit = function(trigger, revalidate) {
18422
18507
  var debounceDelay = 0,
18423
18508
  options = ctrl.$options,
18424
18509
  debounce;
@@ -18437,10 +18522,10 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
18437
18522
  $timeout.cancel(pendingDebounce);
18438
18523
  if (debounceDelay) {
18439
18524
  pendingDebounce = $timeout(function() {
18440
- ctrl.$commitViewValue();
18525
+ ctrl.$commitViewValue(revalidate);
18441
18526
  }, debounceDelay);
18442
18527
  } else {
18443
- ctrl.$commitViewValue();
18528
+ ctrl.$commitViewValue(revalidate);
18444
18529
  }
18445
18530
  };
18446
18531
 
@@ -20484,7 +20569,7 @@ var ngIfDirective = ['$animate', function($animate) {
20484
20569
  var block, childScope, previousElements;
20485
20570
  $scope.$watch($attr.ngIf, function ngIfWatchAction(value) {
20486
20571
 
20487
- if (toBoolean(value)) {
20572
+ if (value) {
20488
20573
  if (!childScope) {
20489
20574
  $transclude(function (clone, newScope) {
20490
20575
  childScope = newScope;
@@ -20967,7 +21052,7 @@ var ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });
20967
21052
  * When one person, perhaps John, views the document, "John is viewing" will be shown.
20968
21053
  * When three people view the document, no explicit number rule is found, so
20969
21054
  * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.
20970
- * In this case, plural category 'one' is matched and "John, Marry and one other person are viewing"
21055
+ * In this case, plural category 'one' is matched and "John, Mary and one other person are viewing"
20971
21056
  * is shown.
20972
21057
  *
20973
21058
  * Note that when you specify offsets, you must provide explicit number rules for
@@ -21516,15 +21601,10 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
21516
21601
  * <div ng-show="myValue" class="ng-hide"></div>
21517
21602
  * ```
21518
21603
  *
21519
- * When the ngShow expression evaluates to false then the ng-hide CSS class is added to the class attribute
21520
- * on the element causing it to become hidden. When true, the ng-hide CSS class is removed
21604
+ * When the ngShow expression evaluates to a falsy value then the ng-hide CSS class is added to the class
21605
+ * attribute on the element causing it to become hidden. When truthy, the ng-hide CSS class is removed
21521
21606
  * from the element causing the element not to appear hidden.
21522
21607
  *
21523
- * <div class="alert alert-warning">
21524
- * **Note:** Here is a list of values that ngShow will consider as a falsy value (case insensitive):<br />
21525
- * "f" / "0" / "false" / "no" / "n" / "[]"
21526
- * </div>
21527
- *
21528
21608
  * ## Why is !important used?
21529
21609
  *
21530
21610
  * You may be wondering why !important is used for the .ng-hide CSS class. This is because the `.ng-hide` selector
@@ -21660,7 +21740,7 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
21660
21740
  var ngShowDirective = ['$animate', function($animate) {
21661
21741
  return function(scope, element, attr) {
21662
21742
  scope.$watch(attr.ngShow, function ngShowWatchAction(value){
21663
- $animate[toBoolean(value) ? 'removeClass' : 'addClass'](element, 'ng-hide');
21743
+ $animate[value ? 'removeClass' : 'addClass'](element, 'ng-hide');
21664
21744
  });
21665
21745
  };
21666
21746
  }];
@@ -21685,15 +21765,10 @@ var ngShowDirective = ['$animate', function($animate) {
21685
21765
  * <div ng-hide="myValue"></div>
21686
21766
  * ```
21687
21767
  *
21688
- * When the ngHide expression evaluates to true then the .ng-hide CSS class is added to the class attribute
21689
- * on the element causing it to become hidden. When false, the ng-hide CSS class is removed
21768
+ * When the ngHide expression evaluates to a truthy value then the .ng-hide CSS class is added to the class
21769
+ * attribute on the element causing it to become hidden. When falsy, the ng-hide CSS class is removed
21690
21770
  * from the element causing the element not to appear hidden.
21691
21771
  *
21692
- * <div class="alert alert-warning">
21693
- * **Note:** Here is a list of values that ngHide will consider as a falsy value (case insensitive):<br />
21694
- * "f" / "0" / "false" / "no" / "n" / "[]"
21695
- * </div>
21696
- *
21697
21772
  * ## Why is !important used?
21698
21773
  *
21699
21774
  * You may be wondering why !important is used for the .ng-hide CSS class. This is because the `.ng-hide` selector
@@ -21816,7 +21891,7 @@ var ngShowDirective = ['$animate', function($animate) {
21816
21891
  var ngHideDirective = ['$animate', function($animate) {
21817
21892
  return function(scope, element, attr) {
21818
21893
  scope.$watch(attr.ngHide, function ngHideWatchAction(value){
21819
- $animate[toBoolean(value) ? 'addClass' : 'removeClass'](element, 'ng-hide');
21894
+ $animate[value ? 'addClass' : 'removeClass'](element, 'ng-hide');
21820
21895
  });
21821
21896
  };
21822
21897
  }];