Permalink
Browse files

Add support for more formats (‘date’, ‘time’, ‘date-time’, ...)

  • Loading branch information...
1 parent 83f0dd1 commit a653c014662c826b399c5ae9b4bdccaa11ab83a6 @Baggz committed Mar 12, 2012
Showing with 111 additions and 82 deletions.
  1. +111 −82 src/engines/json/attributes/format.js
@@ -19,18 +19,23 @@ Validation.prototype.addAttributeConstructor('format', function formatConstructo
*/
'date-time': {
type: 'string',
- pattern: /asd/
+ pattern: /^\d{4}-(?:0[0-9]{1}|1[0-2]{1})-[0-9]{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/
},
/**
* date
*
- * This should be a date in the format of YYYY-MM-DD. It is recommended that you
+ * This should be a date in the format of YYYY-MM-DD. It is recommended that you
* use the "date-time" format instead of "date" unless you need to transfer only the date part.
*/
- 'date': {
- type: 'string',
- pattern: /a/
+ date: function(input) {
+ if (isString(input)) {
+ return input.match(/^\d{4}-(?:0[0-9]{1}|1[0-2]{1})-[0-9]{2}$/);
+ }
+ if (isObject(input)) {
+ return Object.prototype.toString.call(input) === '[object Date]';
+ }
+ return false;
},
/**
@@ -40,17 +45,18 @@ Validation.prototype.addAttributeConstructor('format', function formatConstructo
*/
'time': {
type: 'string',
- pattern: /a/
+ pattern: /^\d{2}:\d{2}:\d{2}$/
},
/**
* utc-milisec
*
- * This should be a time in the format of hh:mm:ss.
+ * This should be the difference, measured in milliseconds, between the specified
+ * time and midnight, 00:00 of January 1, 1970 UTC. The value
+ * should be a number (integer or float).
*/
'utc-milisec': {
- type: 'string',
- pattern: /a/
+ type: 'number'
},
/**
@@ -65,47 +71,44 @@ Validation.prototype.addAttributeConstructor('format', function formatConstructo
/**
* color
*
- * This should be a time in the format of hh:mm:ss.
+ * This is a CSS color (like "#FF0000" or "red"), based on CSS 2.1.
*/
'color': {
- type: 'string',
- pattern: /a/
+ type: 'string'
},
/**
* style
*
- * This should be a time in the format of hh:mm:ss.
+ * This is a CSS style definition (like "color: red; background-color:#FFF"), based on CSS 2.1.
*/
'style': {
- type: 'string',
- pattern: /a/
+ type: 'string'
},
/**
* phone
*
- * This should be a time in the format of hh:mm:ss.
+ * This should be a phone number.
*/
'phone': {
- type: 'string',
- pattern: /a/
+ type: 'number'
},
/**
* uri
*
- * This should be a time in the format of hh:mm:ss.
+ * This value should be a URI.
*/
'uri': {
type: 'string',
- pattern: /a/
+ pattern: /^(?:(?:ht|f)tp(?:s?)\:\/\/|~\/|\/)?(?:\w+:\w+@)?((?:(?:[-\w\d{1-3}]+\.)+(?:com|org|cat|coop|int|pro|tel|xxx|net|gov|mil|biz|info|mobi|name|aero|jobs|edu|co\.uk|ac\.uk|it|fr|tv|museum|asia|local|travel|[a-z]{2})?)|((\b25[0-5]\b|\b[2][0-4][0-9]\b|\b[0-1]?[0-9]?[0-9]\b)(\.(\b25[0-5]\b|\b[2][0-4][0-9]\b|\b[0-1]?[0-9]?[0-9]\b)){3}))(?::[\d]{1,5})?(?:(?:(?:\/(?:[-\w~!$+|.,=]|%[a-f\d]{2})+)+|\/)+|\?|#)?(?:(?:\?(?:[-\w~!$+|.,*:]|%[a-f\d{2}])+=?(?:[-\w~!$+|.,*:=]|%[a-f\d]{2})*)(?:&(?:[-\w~!$+|.,*:]|%[a-f\d{2}])+=?(?:[-\w~!$+|.,*:=]|%[a-f\d]{2})*)*)*(?:#(?:[-\w~!$ |\/.,*:;=]|%[a-f\d]{2})*)?$/
},
/**
* email
*
- * This should be a time in the format of hh:mm:ss.
+ * This should be an email address.
*/
'email': {
type: 'string',
@@ -115,17 +118,17 @@ Validation.prototype.addAttributeConstructor('format', function formatConstructo
/**
* ip-address
*
- * This should be a time in the format of hh:mm:ss.
+ * This should be an ip version 4 address.
*/
'ip-address': {
type: 'string',
- pattern: /a/
+ pattern: /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/
},
/**
* ipv6
*
- * This should be a time in the format of hh:mm:ss.
+ * This should be an ip version 6 address.
*/
'ipv6': {
type: 'string',
@@ -135,89 +138,115 @@ Validation.prototype.addAttributeConstructor('format', function formatConstructo
/**
* host-name
*
- * This should be a time in the format of hh:mm:ss.
+ * This should be a host-name.
*/
'host-name': {
- type: 'string',
- pattern: /a/
+ type: 'string'
}
};
/**
* CustomFormats
+ * --------------------
*/
- var customFormats = {
-
- 'alpha': {
- type: 'string',
- pattern: /^[a-zA-Z]+$/
- },
-
- 'alphanumeric': {
- type: ['string', 'number'],
- pattern: /^[a-zA-Z0-9]+$/
- },
-
- 'decimal': {
- type: 'string',
- pattern: /^[0-9]+(\.[0-9]{1,2})?$/
- },
+ formats.alpha = {
+ required: true,
+ type: 'string',
+ pattern: /^[a-zA-Z]+$/
+ };
- 'percentage': {
- type: ['string', 'number'],
- pattern: /^-?[0-9]{0,2}(\.[0-9]{1,2})?$|^-?(100)(\.[0]{1,2})?$/,
- minimum: -100,
- maximum: 100
- },
+ formats.alphanumeric = {
+ required: true,
+ type: ['string', 'number'],
+ pattern: /^[a-zA-Z0-9]+$/
+ };
- 'port': {
- type: ['string', 'number'],
- pattern: /\:\d+/
- }
+ formats.decimal = function(input) {
+ if (!isNumber(input)) return false;
+ return (input + '').match(/^[0-9]+(\.[0-9]{1,2})?$/);
+ };
+ formats.percentage = {
+ required: true,
+ type: ['string', 'number'],
+ pattern: /^-?[0-9]{0,2}(\.[0-9]{1,2})?$|^-?(100)(\.[0]{1,2})?$/,
+ minimum: -100,
+ maximum: 100
};
- /*
- var aliases = {
- 'ip': formats.ip,
-
- 'hostName': formats['host-name'],
- 'host': formats['host-name'],
+ formats.port = {
+ required: true,
+ type: ['string', 'number'],
+ pattern: /\:\d+/
+ };
- };
- */
+ /**
+ * Aliases
+ * --------------------
+ */
+ var aliases = {
+ url: 'uri',
+ ip: 'ip-address',
+ ipv4: 'ip-address',
+ host: 'host-name',
+ hostName: 'host-name'
+ };
- /*
- 'ipv4': function(input) {
- return typeof input === 'string' && input.match(/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/);
- },
- 'ip': function(input) {
- return formats.ipv4(input) || formats.ipv6;
- },
- 'url': function(input) {
- return typeof input === 'string' && input.match(/^(?:(?:ht|f)tp(?:s?)\:\/\/|~\/|\/)?(?:\w+:\w+@)?((?:(?:[-\w\d{1-3}]+\.)+(?:com|org|cat|coop|int|pro|tel|xxx|net|gov|mil|biz|info|mobi|name|aero|jobs|edu|co\.uk|ac\.uk|it|fr|tv|museum|asia|local|travel|[a-z]{2})?)|((\b25[0-5]\b|\b[2][0-4][0-9]\b|\b[0-1]?[0-9]?[0-9]\b)(\.(\b25[0-5]\b|\b[2][0-4][0-9]\b|\b[0-1]?[0-9]?[0-9]\b)){3}))(?::[\d]{1,5})?(?:(?:(?:\/(?:[-\w~!$+|.,=]|%[a-f\d]{2})+)+|\/)+|\?|#)?(?:(?:\?(?:[-\w~!$+|.,*:]|%[a-f\d{2}])+=?(?:[-\w~!$+|.,*:=]|%[a-f\d]{2})*)(?:&(?:[-\w~!$+|.,*:]|%[a-f\d{2}])+=?(?:[-\w~!$+|.,*:=]|%[a-f\d]{2})*)*)*(?:#(?:[-\w~!$ |\/.,*:;=]|%[a-f\d]{2})*)?$/);
- },
- */
+ // Apply aliases
+ each(aliases, function(alias, format) {
+ formats[alias] = formats[format];
+ });
+ // Export
return function format(property, propertyValue, attributeValue, propertyAttributes, callback) {
- if (!hasProperty(formats, attributeValue)) {
+ /**
+ * {
+ * format: {
+ * type: 'string',
+ * pattern: /abc/
+ * ...
+ * }
+ * ...
+ * }
+ */
+ if (isObject(attributeValue)) {
+ return this.validateProperty(property, propertyValue, attributeValue, callback);
+ }
+
+ /**
+ * {
+ * format: 'lorem ipsum dolor',
+ * ...
+ * }
+ */
+ if (isString(attributeValue) && !hasProperty(formats, attributeValue)) {
throw new Error('The format ‘' + attributeValue + '’ is not supported.');
}
- var format = formats[attributeValue];
+ /**
+ * {
+ * format: 'phone',
+ * ...
+ * }
+ */
+ if (isString(attributeValue)) {
+
+ var fn = formats[attributeValue];
- if (isFunction(format)) {
- var noError = format(propertyValue);
- if (!noError) {
- this.addError();
+ if (isFunction(fn)) {
+ var noError = fn(propertyValue);
+ if (!noError) {
+ this.addError();
+ }
+ return callback();
+ }
+
+ if (isObject(fn)) {
+ return this.validateProperty(property, propertyValue, fn, callback);
}
- return callback();
- }
- if (isObject(format)) {
- return this.validateProperty(property, propertyValue, format, callback);
}
};

0 comments on commit a653c01

Please sign in to comment.