angular.js/src/validators.js

208 lines
6.4 KiB
JavaScript
Raw Normal View History

extend(angularValidator, {
'noop': function() { return _null; },
2010-01-12 00:15:12 +00:00
'regexp': function(value, regexp, msg) {
if (!value.match(regexp)) {
return msg ||
"Value does not match expected format " + regexp + ".";
} else {
return _null;
2010-01-06 00:36:58 +00:00
}
2010-01-12 00:15:12 +00:00
},
2010-01-12 00:15:12 +00:00
'number': function(value, min, max) {
var num = 1 * value;
if (num == value) {
if (typeof min != $undefined && num < min) {
2010-01-12 00:15:12 +00:00
return "Value can not be less than " + min + ".";
}
if (typeof min != $undefined && num > max) {
2010-01-12 00:15:12 +00:00
return "Value can not be greater than " + max + ".";
}
return _null;
2010-01-12 00:15:12 +00:00
} else {
return "Not a number";
2010-01-12 00:15:12 +00:00
}
},
2010-01-12 00:15:12 +00:00
'integer': function(value, min, max) {
2010-02-05 22:41:45 +00:00
var numberError = angularValidator['number'](value, min, max);
if (numberError) return numberError;
if (!("" + value).match(/^\s*[\d+]*\s*$/) || value != Math.round(value)) {
return "Not a whole number";
2010-01-12 00:15:12 +00:00
}
return _null;
2010-01-12 00:15:12 +00:00
},
'date': function(value) {
var fields = /^(\d\d?)\/(\d\d?)\/(\d\d\d\d)$/.exec(value);
var date = fields ? new Date(fields[3], fields[1]-1, fields[2]) : 0;
return (date &&
date.getFullYear() == fields[3] &&
date.getMonth() == fields[1]-1 &&
date.getDate() == fields[2]) ?
_null : "Value is not a date. (Expecting format: 12/31/2009).";
2010-01-12 00:15:12 +00:00
},
2010-01-12 00:15:12 +00:00
'ssn': function(value) {
if (value.match(/^\d\d\d-\d\d-\d\d\d\d$/)) {
return _null;
2010-01-12 00:15:12 +00:00
}
return "SSN needs to be in 999-99-9999 format.";
},
2010-01-12 00:15:12 +00:00
'email': function(value) {
if (value.match(/^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}$/)) {
return _null;
2010-01-12 00:15:12 +00:00
}
return "Email needs to be in username@host.com format.";
},
2010-01-12 00:15:12 +00:00
'phone': function(value) {
if (value.match(/^1\(\d\d\d\)\d\d\d-\d\d\d\d$/)) {
return _null;
2010-01-12 00:15:12 +00:00
}
if (value.match(/^\+\d{2,3} (\(\d{1,5}\))?[\d ]+\d$/)) {
return _null;
2010-01-12 00:15:12 +00:00
}
return "Phone number needs to be in 1(987)654-3210 format in North America or +999 (123) 45678 906 internationaly.";
},
2010-01-12 00:15:12 +00:00
'url': function(value) {
if (value.match(/^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/)) {
return _null;
2010-01-12 00:15:12 +00:00
}
return "URL needs to be in http://server[:port]/path format.";
},
2010-01-12 00:15:12 +00:00
'json': function(value) {
try {
fromJson(value);
return _null;
2010-01-12 00:15:12 +00:00
} catch (e) {
return e.toString();
2010-01-06 00:36:58 +00:00
}
2010-02-13 03:39:01 +00:00
},
/**
* @ngdoc validator
* @name angular.validator.asynchronous
* @description
* Use asynchronous validator if the validation can not be computed
* immediately, but is provided through a callback. The widget
* automatically shows a spinning indicator while the validity of
* the widget is computed. This validator caches the result.
*
* @param {string} value value to validate
* @param {function(inputToValidate,validationDone)} validate function to call to validate the state
* of the input.
* @param {function(data)=} [update=noop] function to call when state of the
* validator changes
*
* @paramDescription
* The `validate` function (specified by you) is called as
* `validate(inputToValidate, validationDone)`:
*
* * `inputToValidate`: value of the input box.
* * `validationDone`: `function(error, data){...}`
* * `error`: error text to display if validation fails
* * `data`: data object to pass to update function
*
* The `update` function is optionally specified by you and is
* called by <angular/> on input change. Since the
* asynchronous validator caches the results, the update
* function can be called without a call to `validate`
* function. The function is called as `update(data)`:
*
* * `data`: data object as passed from validate function
*
2010-11-05 22:05:24 +00:00
* @css ng-input-indicator-wait, ng-validation-error
*
* @exampleDescription
* <pre>
2010-11-05 22:05:24 +00:00
* function myValidator (inputToValidate, validationDone) {
* // simulate delayed response, validate on even input length
* setTimeout(function(){
2010-11-05 22:05:24 +00:00
* validationDone(inputToValidate.length % 2);
* }, 500);
* };
* </pre>
*
* @example
* <script>
2010-11-05 22:05:24 +00:00
* function myValidator(inputToValidate, validationDone) {
* setTimeout(function(){
2010-11-05 22:05:24 +00:00
* validationDone(inputToValidate.length % 2);
* }, 500);
* }
* </script>
* This input is validated asynchronously:
* <input name="text" ng:validate="asynchronous:$window.myValidator">
*
2010-11-05 22:05:24 +00:00
* @scenario
* it('should change color in delayed way', function(){
* var textBox = element('.example :input');
* expect(textBox.attr('className')).not().toMatch(/ng-input-indicator-wait/);
* expect(textBox.attr('className')).not().toMatch(/ng-validation-error/);
*
* input('text').enter('X');
* expect(textBox.attr('className')).toMatch(/ng-input-indicator-wait/);
*
* pause(.6);
*
* expect(textBox.attr('className')).not().toMatch(/ng-input-indicator-wait/);
* expect(textBox.attr('className')).toMatch(/ng-validation-error/);
*
* });
*
*/
2010-04-16 21:01:29 +00:00
/*
* cache is attached to the element
* cache: {
* inputs : {
* 'user input': {
* response: server response,
* error: validation error
* },
* current: 'current input'
* }
*
*/
'asynchronous': function(input, asynchronousFn, updateFn) {
if (!input) return;
var scope = this;
var element = scope.$element;
var cache = element.data('$asyncValidator');
2010-03-30 04:36:34 +00:00
if (!cache) {
2010-04-16 21:01:29 +00:00
element.data('$asyncValidator', cache = {inputs:{}});
2010-03-30 04:36:34 +00:00
}
2010-04-16 21:01:29 +00:00
cache.current = input;
var inputState = cache.inputs[input];
if (!inputState) {
cache.inputs[input] = inputState = { inFlight: true };
scope.$invalidWidgets.markInvalid(scope.$element);
2010-03-30 04:36:34 +00:00
element.addClass('ng-input-indicator-wait');
2010-04-16 21:01:29 +00:00
asynchronousFn(input, function(error, data) {
inputState.response = data;
inputState.error = error;
inputState.inFlight = false;
if (cache.current == input) {
2010-03-30 04:36:34 +00:00
element.removeClass('ng-input-indicator-wait');
2010-04-16 21:01:29 +00:00
scope.$invalidWidgets.markValid(element);
2010-02-13 03:39:01 +00:00
}
2010-04-17 00:03:06 +00:00
element.data('$validate')();
2010-04-16 21:01:29 +00:00
scope.$root.$eval();
2010-02-13 03:39:01 +00:00
});
2010-04-16 21:01:29 +00:00
} else if (inputState.inFlight) {
2010-02-13 03:39:01 +00:00
// request in flight, mark widget invalid, but don't show it to user
2010-04-16 21:01:29 +00:00
scope.$invalidWidgets.markInvalid(scope.$element);
} else {
(updateFn||noop)(inputState.response);
2010-02-13 03:39:01 +00:00
}
2010-04-16 21:01:29 +00:00
return inputState.error;
2010-01-06 00:36:58 +00:00
}
2010-02-13 03:39:01 +00:00
});