8 changed files with 2483 additions and 0 deletions
Unified View
Diff Options
-
536build/minified/modules/form.js
-
1build/minified/modules/form.min.js
-
536build/packaged/modules/form.js
-
536build/uncompressed/modules/form.js
-
253node/src/documents/modules/form.html
-
536node/src/files/components/semantic/modules/form.js
-
29node/src/files/javascript/form.js
-
56node/src/files/javascript/validate-form.js
@ -0,0 +1,536 @@ |
|||||
|
/* ****************************** |
||||
|
Form Validation Components |
||||
|
Author: Jack Lukic |
||||
|
Notes: First Commit April 08, 2012 |
||||
|
|
||||
|
Refactored May 28, 2013 |
||||
|
|
||||
|
Allows you to validate forms based on a form validation object |
||||
|
Form validation objects are bound by either data-validate="" metadata, or form id or name tags |
||||
|
|
||||
|
****************************** */ |
||||
|
|
||||
|
;(function ( $, window, document, undefined ) { |
||||
|
|
||||
|
$.fn.form = function(fields, parameters) { |
||||
|
var |
||||
|
$allModules = $(this), |
||||
|
$document = $(document), |
||||
|
|
||||
|
settings = $.extend(true, {}, $.fn.form.settings, parameters), |
||||
|
|
||||
|
eventNamespace = '.' + settings.namespace, |
||||
|
moduleNamespace = 'module-' + settings.namespace, |
||||
|
|
||||
|
selector = $allModules.selector || '', |
||||
|
time = new Date().getTime(), |
||||
|
performance = [], |
||||
|
|
||||
|
query = arguments[0], |
||||
|
methodInvoked = (typeof query == 'string'), |
||||
|
queryArguments = [].slice.call(arguments, 1), |
||||
|
invokedResponse |
||||
|
; |
||||
|
$allModules |
||||
|
.each(function() { |
||||
|
var |
||||
|
$module = $(this), |
||||
|
$group = $(this).find(settings.selector.group), |
||||
|
$field = $(this).find(settings.selector.field), |
||||
|
$errorPrompt = $(this).find(settings.selector.prompt), |
||||
|
|
||||
|
formErrors = [], |
||||
|
|
||||
|
element = this, |
||||
|
instance = $module.data('module-' + settings.namespace), |
||||
|
|
||||
|
namespace = settings.namespace, |
||||
|
metadata = settings.metadata, |
||||
|
className = settings.className, |
||||
|
errors = settings.errors, |
||||
|
module |
||||
|
; |
||||
|
|
||||
|
module = { |
||||
|
|
||||
|
initialize: function() { |
||||
|
module.verbose('Initializing form validation'); |
||||
|
if(fields !== undefined || !$.isEmptyObject(fields) ) { |
||||
|
// attach event handler
|
||||
|
if(settings.on == 'submit') { |
||||
|
$module |
||||
|
.on('submit.' + namespace, module.validate.form) |
||||
|
; |
||||
|
} |
||||
|
} |
||||
|
else { |
||||
|
module.error(errors.noFields, $module); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
destroy: function() { |
||||
|
$module |
||||
|
.off(namespace) |
||||
|
; |
||||
|
}, |
||||
|
|
||||
|
refresh: function() { |
||||
|
$field = $module.find(settings.selector.field); |
||||
|
}, |
||||
|
|
||||
|
field: { |
||||
|
find: function(identifier) { |
||||
|
module.refresh(); |
||||
|
if( $field.filter('#' + identifier).size() > 0 ) { |
||||
|
return $field.filter('#' + identifier); |
||||
|
} |
||||
|
else if( $field.filter('[name="' + identifier +'"]').size() > 0 ) { |
||||
|
return $field.filter('[name="' + identifier +'"]'); |
||||
|
} |
||||
|
else if( $field.filter('[data-' + metadata.validate + '="'+ identifier +'"]').size() > 0 ) { |
||||
|
return $field.filter('[data-' + metadata.validate + '="'+ identifier +'"]'); |
||||
|
} |
||||
|
return $('<input/>'); |
||||
|
}, |
||||
|
add: { |
||||
|
error: function(field, errors) { |
||||
|
var |
||||
|
$field = module.field.find(field.identifier), |
||||
|
$errorGroup = $field.closest($group), |
||||
|
$errorPrompt = $group.find($errorPrompt), |
||||
|
promptExists = ($errorPrompt.size() !== 0) |
||||
|
; |
||||
|
$errorGroup |
||||
|
.addClass(className.error) |
||||
|
; |
||||
|
if(settings.inlineError) { |
||||
|
// create message container on first invalid validation attempt
|
||||
|
if(!promptExists) { |
||||
|
$errorPrompt = $('<div />') |
||||
|
.addClass(className.prompt) |
||||
|
.insertBefore($field) |
||||
|
; |
||||
|
} |
||||
|
// add prompt message
|
||||
|
$errorPrompt |
||||
|
.html(errors[0]) |
||||
|
.fadeIn(settings.animateSpeed) |
||||
|
; |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
remove: { |
||||
|
error: function(field) { |
||||
|
var |
||||
|
$field = module.field.find(field.identifier), |
||||
|
$errorGroup = $field.closest($group), |
||||
|
$errorPrompt = $group.find($errorPrompt) |
||||
|
; |
||||
|
$errorGroup |
||||
|
.removeClass(className.error) |
||||
|
; |
||||
|
if(settings.inlineError) { |
||||
|
$errorPrompt.hide(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
validate: { |
||||
|
|
||||
|
form: function(event) { |
||||
|
var |
||||
|
allValid = true |
||||
|
; |
||||
|
// reset errors
|
||||
|
formErrors = []; |
||||
|
$.each(fields, function(fieldName, field){ |
||||
|
// form is invalid after first bad field, but keep checking
|
||||
|
if( !( module.validate.field(field) ) ) { |
||||
|
allValid = false; |
||||
|
} |
||||
|
}); |
||||
|
// Evaluate form callbacks
|
||||
|
return (allValid) |
||||
|
? $.proxy(settings.onSuccess, this)(event) |
||||
|
: $.proxy(settings.onFailure, this)(formErrors) |
||||
|
; |
||||
|
}, |
||||
|
|
||||
|
// takes a validation object and returns whether field passes validation
|
||||
|
field: function(field) { |
||||
|
var |
||||
|
$field = module.field.find(field.identifier), |
||||
|
fieldValid = true, |
||||
|
fieldErrors = [] |
||||
|
; |
||||
|
if(field.rules !== undefined) { |
||||
|
// iterate over all validation types for a certain field
|
||||
|
$.each(field.rules, function(index, rule) { |
||||
|
if( !( module.validate.rule(field, rule) ) ) { |
||||
|
module.debug('Field is invalid', field.identifier, rule.type); |
||||
|
fieldErrors.push(rule.prompt); |
||||
|
fieldValid = false; |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
if(fieldValid) { |
||||
|
module.field.remove.error(field, fieldErrors); |
||||
|
settings.onValid($field); |
||||
|
} |
||||
|
else { |
||||
|
formErrors = formErrors.concat(fieldErrors); |
||||
|
module.field.add.error(field, fieldErrors); |
||||
|
$.proxy(settings.onInvalid, $field)(fieldErrors); |
||||
|
return false; |
||||
|
} |
||||
|
return true; |
||||
|
}, |
||||
|
|
||||
|
// takes validation rule and returns whether field passes rule
|
||||
|
rule: function(field, validation) { |
||||
|
var |
||||
|
$field = module.field.find(field.identifier), |
||||
|
type = validation.type, |
||||
|
value = $field.val(), |
||||
|
|
||||
|
bracketRegExp = /\[(.*?)\]/i, |
||||
|
bracket = bracketRegExp.exec(type), |
||||
|
isValid = true, |
||||
|
ancillary, |
||||
|
functionType |
||||
|
; |
||||
|
// if bracket notation is used, pass in extra parameters
|
||||
|
if(bracket !== undefined && bracket != null) { |
||||
|
ancillary = bracket[1]; |
||||
|
functionType = type.replace(bracket[0], ''); |
||||
|
isValid = $.proxy(settings.rules[functionType], $module)(value, ancillary); |
||||
|
} |
||||
|
// normal notation
|
||||
|
else { |
||||
|
isValid = (type == 'checked') |
||||
|
? $field.filter(':checked').size() > 0 |
||||
|
: settings.rules[type](value) |
||||
|
; |
||||
|
} |
||||
|
return isValid; |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
setting: function(name, value) { |
||||
|
if(value !== undefined) { |
||||
|
if( $.isPlainObject(name) ) { |
||||
|
$.extend(true, settings, name); |
||||
|
} |
||||
|
else { |
||||
|
settings[name] = value; |
||||
|
} |
||||
|
} |
||||
|
else { |
||||
|
return settings[name]; |
||||
|
} |
||||
|
}, |
||||
|
internal: function(name, value) { |
||||
|
if(value !== undefined) { |
||||
|
if( $.isPlainObject(name) ) { |
||||
|
$.extend(true, module, name); |
||||
|
} |
||||
|
else { |
||||
|
module[name] = value; |
||||
|
} |
||||
|
} |
||||
|
else { |
||||
|
return module[name]; |
||||
|
} |
||||
|
}, |
||||
|
debug: function() { |
||||
|
if(settings.debug) { |
||||
|
module.performance.log(arguments[0]); |
||||
|
module.debug = Function.prototype.bind.call(console.log, console, settings.moduleName + ':'); |
||||
|
} |
||||
|
}, |
||||
|
verbose: function() { |
||||
|
if(settings.verbose && settings.debug) { |
||||
|
module.performance.log(arguments[0]); |
||||
|
module.verbose = Function.prototype.bind.call(console.info, console, settings.moduleName + ':'); |
||||
|
} |
||||
|
}, |
||||
|
error: function() { |
||||
|
module.error = Function.prototype.bind.call(console.log, console, settings.moduleName + ':'); |
||||
|
}, |
||||
|
performance: { |
||||
|
log: function(message) { |
||||
|
var |
||||
|
currentTime, |
||||
|
executionTime, |
||||
|
previousTime |
||||
|
; |
||||
|
if(settings.performance) { |
||||
|
currentTime = new Date().getTime(); |
||||
|
previousTime = time || currentTime, |
||||
|
executionTime = currentTime - previousTime; |
||||
|
time = currentTime; |
||||
|
performance.push({ |
||||
|
'Element' : element, |
||||
|
'Name' : message, |
||||
|
'Execution Time' : executionTime |
||||
|
}); |
||||
|
clearTimeout(module.performance.timer); |
||||
|
module.performance.timer = setTimeout(module.performance.display, 100); |
||||
|
} |
||||
|
}, |
||||
|
display: function() { |
||||
|
var |
||||
|
title = settings.moduleName, |
||||
|
caption = settings.moduleName + ': ' + selector + '(' + $allModules.size() + ' elements)', |
||||
|
totalExecutionTime = 0 |
||||
|
; |
||||
|
if(selector) { |
||||
|
title += 'Performance (' + selector + ')'; |
||||
|
} |
||||
|
if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { |
||||
|
console.groupCollapsed(title); |
||||
|
if(console.table) { |
||||
|
$.each(performance, function(index, data) { |
||||
|
totalExecutionTime += data['Execution Time']; |
||||
|
}); |
||||
|
console.table(performance); |
||||
|
} |
||||
|
else { |
||||
|
$.each(performance, function(index, data) { |
||||
|
totalExecutionTime += data['Execution Time']; |
||||
|
}); |
||||
|
} |
||||
|
console.log('Total Execution Time:', totalExecutionTime +'ms'); |
||||
|
console.groupEnd(); |
||||
|
performance = []; |
||||
|
time = false; |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
invoke: function(query, passedArguments, context) { |
||||
|
var |
||||
|
maxDepth, |
||||
|
found |
||||
|
; |
||||
|
passedArguments = passedArguments || queryArguments; |
||||
|
context = element || context; |
||||
|
if(typeof query == 'string' && instance !== undefined) { |
||||
|
query = query.split('.'); |
||||
|
maxDepth = query.length - 1; |
||||
|
$.each(query, function(depth, value) { |
||||
|
if( $.isPlainObject( instance[value] ) && (depth != maxDepth) ) { |
||||
|
instance = instance[value]; |
||||
|
return true; |
||||
|
} |
||||
|
else if( instance[value] !== undefined ) { |
||||
|
found = instance[value]; |
||||
|
return true; |
||||
|
} |
||||
|
module.error(errors.method); |
||||
|
return false; |
||||
|
}); |
||||
|
} |
||||
|
if ( $.isFunction( found ) ) { |
||||
|
module.verbose('Executing invoked function', found); |
||||
|
return found.apply(context, passedArguments); |
||||
|
} |
||||
|
return found || false; |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
if(methodInvoked) { |
||||
|
if(instance === undefined) { |
||||
|
module.initialize(); |
||||
|
} |
||||
|
invokedResponse = module.invoke(query); |
||||
|
} |
||||
|
else { |
||||
|
if(instance !== undefined) { |
||||
|
module.destroy(); |
||||
|
} |
||||
|
module.initialize(); |
||||
|
} |
||||
|
}) |
||||
|
; |
||||
|
return (invokedResponse) |
||||
|
? invokedResponse |
||||
|
: this |
||||
|
; |
||||
|
}; |
||||
|
|
||||
|
$.fn.form.settings = { |
||||
|
|
||||
|
// module info
|
||||
|
moduleName : 'Validate Form Module', |
||||
|
debug : true, |
||||
|
verbose : false, |
||||
|
namespace : 'validate', |
||||
|
|
||||
|
animateSpeed : 150, |
||||
|
inlineError : false, |
||||
|
|
||||
|
on: 'submit', |
||||
|
|
||||
|
onValid : function() {}, |
||||
|
onInvalid : function() {}, |
||||
|
onSuccess : function() { return true; }, |
||||
|
onFailure : function() { return false; }, |
||||
|
|
||||
|
metadata : { |
||||
|
validate: 'validate' |
||||
|
}, |
||||
|
|
||||
|
// errors
|
||||
|
errors: { |
||||
|
method : 'The method you called is not defined.', |
||||
|
noFields : 'No validation object specified.' |
||||
|
}, |
||||
|
|
||||
|
|
||||
|
selector : { |
||||
|
group : '.field', |
||||
|
prompt : '.prompt', |
||||
|
field : 'input, textarea, select' |
||||
|
}, |
||||
|
|
||||
|
className : { |
||||
|
error : 'error', |
||||
|
prompt : 'prompt' |
||||
|
}, |
||||
|
|
||||
|
defaults: { |
||||
|
firstName: { |
||||
|
identifier : 'first-name', |
||||
|
rules: [ |
||||
|
{ |
||||
|
type : 'empty', |
||||
|
prompt : 'Please enter your first name' |
||||
|
} |
||||
|
] |
||||
|
}, |
||||
|
lastName: { |
||||
|
identifier : 'last-name', |
||||
|
rules: [ |
||||
|
{ |
||||
|
type : 'empty', |
||||
|
prompt : 'Please enter your last name' |
||||
|
} |
||||
|
] |
||||
|
}, |
||||
|
username: { |
||||
|
identifier : 'username', |
||||
|
rules: [ |
||||
|
{ |
||||
|
type : 'email', |
||||
|
prompt : 'Please enter a username' |
||||
|
} |
||||
|
] |
||||
|
}, |
||||
|
email: { |
||||
|
identifier : 'email', |
||||
|
rules: [ |
||||
|
{ |
||||
|
type : 'empty', |
||||
|
prompt : 'Please enter your email' |
||||
|
}, |
||||
|
{ |
||||
|
type : 'email', |
||||
|
prompt : 'Please enter a valid email' |
||||
|
} |
||||
|
] |
||||
|
}, |
||||
|
password: { |
||||
|
identifier : 'password', |
||||
|
rules: [ |
||||
|
{ |
||||
|
type : 'empty', |
||||
|
prompt : 'Please enter a password' |
||||
|
}, |
||||
|
{ |
||||
|
type : 'length[6]', |
||||
|
prompt : 'Your password must be at least 6 characters' |
||||
|
} |
||||
|
] |
||||
|
}, |
||||
|
passwordConfirm: { |
||||
|
identifier : 'password-confirm', |
||||
|
rules: [ |
||||
|
{ |
||||
|
type : 'empty', |
||||
|
prompt : 'Please confirm your password' |
||||
|
}, |
||||
|
{ |
||||
|
identifier : 'password-confirm', |
||||
|
type : 'match[password]', |
||||
|
prompt : 'Please verify password matches' |
||||
|
} |
||||
|
] |
||||
|
}, |
||||
|
terms: { |
||||
|
identifier : 'terms', |
||||
|
rules: [ |
||||
|
{ |
||||
|
type : 'checked', |
||||
|
prompt : 'You must agree to the terms and conditions' |
||||
|
} |
||||
|
] |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
rules: { |
||||
|
empty: function(value) { |
||||
|
return !(value === undefined || '' === value); |
||||
|
}, |
||||
|
email: function(value){ |
||||
|
var |
||||
|
emailRegExp = new RegExp("[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?") |
||||
|
; |
||||
|
return emailRegExp.test(value); |
||||
|
}, |
||||
|
length: function(value, requiredLength) { |
||||
|
return (value !== undefined) |
||||
|
? (value.length >= requiredLength) |
||||
|
: false |
||||
|
; |
||||
|
}, |
||||
|
not: function(value, notValue) { |
||||
|
return (value != notValue); |
||||
|
}, |
||||
|
maxLength: function(value, maxLength) { |
||||
|
return (value !== undefined) |
||||
|
? (value.length <= maxLength) |
||||
|
: false |
||||
|
; |
||||
|
}, |
||||
|
match: function(value, matchingField) { |
||||
|
// use either id or name of field
|
||||
|
var |
||||
|
$form = $(this), |
||||
|
matchingValue |
||||
|
; |
||||
|
if($form.find('#' + matchingField).size() > 0) { |
||||
|
matchingValue = $form.find('#' + matchingField).val(); |
||||
|
} |
||||
|
else if($form.find('[name=' + matchingField +']').size() > 0) { |
||||
|
matchingValue = $form.find('[name=' + matchingField + ']').val(); |
||||
|
} |
||||
|
else if( $form.find('[data-validate="'+ matchingField +'"]').size() > 0 ) { |
||||
|
matchingValue = $form.find('[data-validate="'+ matchingField +'"]').val(); |
||||
|
} |
||||
|
return (matchingValue !== undefined) |
||||
|
? ( value.toString() == matchingValue.toString() ) |
||||
|
: false |
||||
|
; |
||||
|
}, |
||||
|
url: function(value) { |
||||
|
var |
||||
|
urlRegExp = /(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/ |
||||
|
; |
||||
|
return urlRegExp.test(value); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
}; |
||||
|
|
||||
|
})( jQuery, window , document ); |
1
build/minified/modules/form.min.js
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,536 @@ |
|||||
|
/* ****************************** |
||||
|
Form Validation Components |
||||
|
Author: Jack Lukic |
||||
|
Notes: First Commit April 08, 2012 |
||||
|
|
||||
|
Refactored May 28, 2013 |
||||
|
|
||||
|
Allows you to validate forms based on a form validation object |
||||
|
Form validation objects are bound by either data-validate="" metadata, or form id or name tags |
||||
|
|
||||
|
****************************** */ |
||||
|
|
||||
|
;(function ( $, window, document, undefined ) { |
||||
|
|
||||
|
$.fn.form = function(fields, parameters) { |
||||
|
var |
||||
|
$allModules = $(this), |
||||
|
$document = $(document), |
||||
|
|
||||
|
settings = $.extend(true, {}, $.fn.form.settings, parameters), |
||||
|
|
||||
|
eventNamespace = '.' + settings.namespace, |
||||
|
moduleNamespace = 'module-' + settings.namespace, |
||||
|
|
||||
|
selector = $allModules.selector || '', |
||||
|
time = new Date().getTime(), |
||||
|
performance = [], |
||||
|
|
||||
|
query = arguments[0], |
||||
|
methodInvoked = (typeof query == 'string'), |
||||
|
queryArguments = [].slice.call(arguments, 1), |
||||
|
invokedResponse |
||||
|
; |
||||
|
$allModules |
||||
|
.each(function() { |
||||
|
var |
||||
|
$module = $(this), |
||||
|
$group = $(this).find(settings.selector.group), |
||||
|
$field = $(this).find(settings.selector.field), |
||||
|
$errorPrompt = $(this).find(settings.selector.prompt), |
||||
|
|
||||
|
formErrors = [], |
||||
|
|
||||
|
element = this, |
||||
|
instance = $module.data('module-' + settings.namespace), |
||||
|
|
||||
|
namespace = settings.namespace, |
||||
|
metadata = settings.metadata, |
||||
|
className = settings.className, |
||||
|
errors = settings.errors, |
||||
|
module |
||||
|
; |
||||
|
|
||||
|
module = { |
||||
|
|
||||
|
initialize: function() { |
||||
|
module.verbose('Initializing form validation'); |
||||
|
if(fields !== undefined || !$.isEmptyObject(fields) ) { |
||||
|
// attach event handler
|
||||
|
if(settings.on == 'submit') { |
||||
|
$module |
||||
|
.on('submit.' + namespace, module.validate.form) |
||||
|
; |
||||
|
} |
||||
|
} |
||||
|
else { |
||||
|
module.error(errors.noFields, $module); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
destroy: function() { |
||||
|
$module |
||||
|
.off(namespace) |
||||
|
; |
||||
|
}, |
||||
|
|
||||
|
refresh: function() { |
||||
|
$field = $module.find(settings.selector.field); |
||||
|
}, |
||||
|
|
||||
|
field: { |
||||
|
find: function(identifier) { |
||||
|
module.refresh(); |
||||
|
if( $field.filter('#' + identifier).size() > 0 ) { |
||||
|
return $field.filter('#' + identifier); |
||||
|
} |
||||
|
else if( $field.filter('[name="' + identifier +'"]').size() > 0 ) { |
||||
|
return $field.filter('[name="' + identifier +'"]'); |
||||
|
} |
||||
|
else if( $field.filter('[data-' + metadata.validate + '="'+ identifier +'"]').size() > 0 ) { |
||||
|
return $field.filter('[data-' + metadata.validate + '="'+ identifier +'"]'); |
||||
|
} |
||||
|
return $('<input/>'); |
||||
|
}, |
||||
|
add: { |
||||
|
error: function(field, errors) { |
||||
|
var |
||||
|
$field = module.field.find(field.identifier), |
||||
|
$errorGroup = $field.closest($group), |
||||
|
$errorPrompt = $group.find($errorPrompt), |
||||
|
promptExists = ($errorPrompt.size() !== 0) |
||||
|
; |
||||
|
$errorGroup |
||||
|
.addClass(className.error) |
||||
|
; |
||||
|
if(settings.inlineError) { |
||||
|
// create message container on first invalid validation attempt
|
||||
|
if(!promptExists) { |
||||
|
$errorPrompt = $('<div />') |
||||
|
.addClass(className.prompt) |
||||
|
.insertBefore($field) |
||||
|
; |
||||
|
} |
||||
|
// add prompt message
|
||||
|
$errorPrompt |
||||
|
.html(errors[0]) |
||||
|
.fadeIn(settings.animateSpeed) |
||||
|
; |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
remove: { |
||||
|
error: function(field) { |
||||
|
var |
||||
|
$field = module.field.find(field.identifier), |
||||
|
$errorGroup = $field.closest($group), |
||||
|
$errorPrompt = $group.find($errorPrompt) |
||||
|
; |
||||
|
$errorGroup |
||||
|
.removeClass(className.error) |
||||
|
; |
||||
|
if(settings.inlineError) { |
||||
|
$errorPrompt.hide(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
validate: { |
||||
|
|
||||
|
form: function(event) { |
||||
|
var |
||||
|
allValid = true |
||||
|
; |
||||
|
// reset errors
|
||||
|
formErrors = []; |
||||
|
$.each(fields, function(fieldName, field){ |
||||
|
// form is invalid after first bad field, but keep checking
|
||||
|
if( !( module.validate.field(field) ) ) { |
||||
|
allValid = false; |
||||
|
} |
||||
|
}); |
||||
|
// Evaluate form callbacks
|
||||
|
return (allValid) |
||||
|
? $.proxy(settings.onSuccess, this)(event) |
||||
|
: $.proxy(settings.onFailure, this)(formErrors) |
||||
|
; |
||||
|
}, |
||||
|
|
||||
|
// takes a validation object and returns whether field passes validation
|
||||
|
field: function(field) { |
||||
|
var |
||||
|
$field = module.field.find(field.identifier), |
||||
|
fieldValid = true, |
||||
|
fieldErrors = [] |
||||
|
; |
||||
|
if(field.rules !== undefined) { |
||||
|
// iterate over all validation types for a certain field
|
||||
|
$.each(field.rules, function(index, rule) { |
||||
|
if( !( module.validate.rule(field, rule) ) ) { |
||||
|
module.debug('Field is invalid', field.identifier, rule.type); |
||||
|
fieldErrors.push(rule.prompt); |
||||
|
fieldValid = false; |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
if(fieldValid) { |
||||
|
module.field.remove.error(field, fieldErrors); |
||||
|
settings.onValid($field); |
||||
|
} |
||||
|
else { |
||||
|
formErrors = formErrors.concat(fieldErrors); |
||||
|
module.field.add.error(field, fieldErrors); |
||||
|
$.proxy(settings.onInvalid, $field)(fieldErrors); |
||||
|
return false; |
||||
|
} |
||||
|
return true; |
||||
|
}, |
||||
|
|
||||
|
// takes validation rule and returns whether field passes rule
|
||||
|
rule: function(field, validation) { |
||||
|
var |
||||
|
$field = module.field.find(field.identifier), |
||||
|
type = validation.type, |
||||
|
value = $field.val(), |
||||
|
|
||||
|
bracketRegExp = /\[(.*?)\]/i, |
||||
|
bracket = bracketRegExp.exec(type), |
||||
|
isValid = true, |
||||
|
ancillary, |
||||
|
functionType |
||||
|
; |
||||
|
// if bracket notation is used, pass in extra parameters
|
||||
|
if(bracket !== undefined && bracket != null) { |
||||
|
ancillary = bracket[1]; |
||||
|
functionType = type.replace(bracket[0], ''); |
||||
|
isValid = $.proxy(settings.rules[functionType], $module)(value, ancillary); |
||||
|
} |
||||
|
// normal notation
|
||||
|
else { |
||||
|
isValid = (type == 'checked') |
||||
|
? $field.filter(':checked').size() > 0 |
||||
|
: settings.rules[type](value) |
||||
|
; |
||||
|
} |
||||
|
return isValid; |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
setting: function(name, value) { |
||||
|
if(value !== undefined) { |
||||
|
if( $.isPlainObject(name) ) { |
||||
|
$.extend(true, settings, name); |
||||
|
} |
||||
|
else { |
||||
|
settings[name] = value; |
||||
|
} |
||||
|
} |
||||
|
else { |
||||
|
return settings[name]; |
||||
|
} |
||||
|
}, |
||||
|
internal: function(name, value) { |
||||
|
if(value !== undefined) { |
||||
|
if( $.isPlainObject(name) ) { |
||||
|
$.extend(true, module, name); |
||||
|
} |
||||
|
else { |
||||
|
module[name] = value; |
||||
|
} |
||||
|
} |
||||
|
else { |
||||
|
return module[name]; |
||||
|
} |
||||
|
}, |
||||
|
debug: function() { |
||||
|
if(settings.debug) { |
||||
|
module.performance.log(arguments[0]); |
||||
|
module.debug = Function.prototype.bind.call(console.log, console, settings.moduleName + ':'); |
||||
|
} |
||||
|
}, |
||||
|
verbose: function() { |
||||
|
if(settings.verbose && settings.debug) { |
||||
|
module.performance.log(arguments[0]); |
||||
|
module.verbose = Function.prototype.bind.call(console.info, console, settings.moduleName + ':'); |
||||
|
} |
||||
|
}, |
||||
|
error: function() { |
||||
|
module.error = Function.prototype.bind.call(console.log, console, settings.moduleName + ':'); |
||||
|
}, |
||||
|
performance: { |
||||
|
log: function(message) { |
||||
|
var |
||||
|
currentTime, |
||||
|
executionTime, |
||||
|
previousTime |
||||
|
; |
||||
|
if(settings.performance) { |
||||
|
currentTime = new Date().getTime(); |
||||
|
previousTime = time || currentTime, |
||||
|
executionTime = currentTime - previousTime; |
||||
|
time = currentTime; |
||||
|
performance.push({ |
||||
|
'Element' : element, |
||||
|
'Name' : message, |
||||
|
'Execution Time' : executionTime |
||||
|
}); |
||||
|
clearTimeout(module.performance.timer); |
||||
|
module.performance.timer = setTimeout(module.performance.display, 100); |
||||
|
} |
||||
|
}, |
||||
|
display: function() { |
||||
|
var |
||||
|
title = settings.moduleName, |
||||
|
caption = settings.moduleName + ': ' + selector + '(' + $allModules.size() + ' elements)', |
||||
|
totalExecutionTime = 0 |
||||
|
; |
||||
|
if(selector) { |
||||
|
title += 'Performance (' + selector + ')'; |
||||
|
} |
||||
|
if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { |
||||
|
console.groupCollapsed(title); |
||||
|
if(console.table) { |
||||
|
$.each(performance, function(index, data) { |
||||
|
totalExecutionTime += data['Execution Time']; |
||||
|
}); |
||||
|
console.table(performance); |
||||
|
} |
||||
|
else { |
||||
|
$.each(performance, function(index, data) { |
||||
|
totalExecutionTime += data['Execution Time']; |
||||
|
}); |
||||
|
} |
||||
|
console.log('Total Execution Time:', totalExecutionTime +'ms'); |
||||
|
console.groupEnd(); |
||||
|
performance = []; |
||||
|
time = false; |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
invoke: function(query, passedArguments, context) { |
||||
|
var |
||||
|
maxDepth, |
||||
|
found |
||||
|
; |
||||
|
passedArguments = passedArguments || queryArguments; |
||||
|
context = element || context; |
||||
|
if(typeof query == 'string' && instance !== undefined) { |
||||
|
query = query.split('.'); |
||||
|
maxDepth = query.length - 1; |
||||
|
$.each(query, function(depth, value) { |
||||
|
if( $.isPlainObject( instance[value] ) && (depth != maxDepth) ) { |
||||
|
instance = instance[value]; |
||||
|
return true; |
||||
|
} |
||||
|
else if( instance[value] !== undefined ) { |
||||
|
found = instance[value]; |
||||
|
return true; |
||||
|
} |
||||
|
module.error(errors.method); |
||||
|
return false; |
||||
|
}); |
||||
|
} |
||||
|
if ( $.isFunction( found ) ) { |
||||
|
module.verbose('Executing invoked function', found); |
||||
|
return found.apply(context, passedArguments); |
||||
|
} |
||||
|
return found || false; |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
if(methodInvoked) { |
||||
|
if(instance === undefined) { |
||||
|
module.initialize(); |
||||
|
} |
||||
|
invokedResponse = module.invoke(query); |
||||
|
} |
||||
|
else { |
||||
|
if(instance !== undefined) { |
||||
|
module.destroy(); |
||||
|
} |
||||
|
module.initialize(); |
||||
|
} |
||||
|
}) |
||||
|
; |
||||
|
return (invokedResponse) |
||||
|
? invokedResponse |
||||
|
: this |
||||
|
; |
||||
|
}; |
||||
|
|
||||
|
$.fn.form.settings = { |
||||
|
|
||||
|
// module info
|
||||
|
moduleName : 'Validate Form Module', |
||||
|
debug : true, |
||||
|
verbose : false, |
||||
|
namespace : 'validate', |
||||
|
|
||||
|
animateSpeed : 150, |
||||
|
inlineError : false, |
||||
|
|
||||
|
on: 'submit', |
||||
|
|
||||
|
onValid : function() {}, |
||||
|
onInvalid : function() {}, |
||||
|
onSuccess : function() { return true; }, |
||||
|
onFailure : function() { return false; }, |
||||
|
|
||||
|
metadata : { |
||||
|
validate: 'validate' |
||||
|
}, |
||||
|
|
||||
|
// errors
|
||||
|
errors: { |
||||
|
method : 'The method you called is not defined.', |
||||
|
noFields : 'No validation object specified.' |
||||
|
}, |
||||
|
|
||||
|
|
||||
|
selector : { |
||||
|
group : '.field', |
||||
|
prompt : '.prompt', |
||||
|
field : 'input, textarea, select' |
||||
|
}, |
||||
|
|
||||
|
className : { |
||||
|
error : 'error', |
||||
|
prompt : 'prompt' |
||||
|
}, |
||||
|
|
||||
|
defaults: { |
||||
|
firstName: { |
||||
|
identifier : 'first-name', |
||||
|
rules: [ |
||||
|
{ |
||||
|
type : 'empty', |
||||
|
prompt : 'Please enter your first name' |
||||
|
} |
||||
|
] |
||||
|
}, |
||||
|
lastName: { |
||||
|
identifier : 'last-name', |
||||
|
rules: [ |
||||
|
{ |
||||
|
type : 'empty', |
||||
|
prompt : 'Please enter your last name' |
||||
|
} |
||||
|
] |
||||
|
}, |
||||
|
username: { |
||||
|
identifier : 'username', |
||||
|
rules: [ |
||||
|
{ |
||||
|
type : 'email', |
||||
|
prompt : 'Please enter a username' |
||||
|
} |
||||
|
] |
||||
|
}, |
||||
|
email: { |
||||
|
identifier : 'email', |
||||
|
rules: [ |
||||
|
{ |
||||
|
type : 'empty', |
||||
|
prompt : 'Please enter your email' |
||||
|
}, |
||||
|
{ |
||||
|
type : 'email', |
||||
|
prompt : 'Please enter a valid email' |
||||
|
} |
||||
|
] |
||||
|
}, |
||||
|
password: { |
||||
|
identifier : 'password', |
||||
|
rules: [ |
||||
|
{ |
||||
|
type : 'empty', |
||||
|
prompt : 'Please enter a password' |
||||
|
}, |
||||
|
{ |
||||
|
type : 'length[6]', |
||||
|
prompt : 'Your password must be at least 6 characters' |
||||
|
} |
||||
|
] |
||||
|
}, |
||||
|
passwordConfirm: { |
||||
|
identifier : 'password-confirm', |
||||
|
rules: [ |
||||
|
{ |
||||
|
type : 'empty', |
||||
|
prompt : 'Please confirm your password' |
||||
|
}, |
||||
|
{ |
||||
|
identifier : 'password-confirm', |
||||
|
type : 'match[password]', |
||||
|
prompt : 'Please verify password matches' |
||||
|
} |
||||
|
] |
||||
|
}, |
||||
|
terms: { |
||||
|
identifier : 'terms', |
||||
|
rules: [ |
||||
|
{ |
||||
|
type : 'checked', |
||||
|
prompt : 'You must agree to the terms and conditions' |
||||
|
} |
||||
|
] |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
rules: { |
||||
|
empty: function(value) { |
||||
|
return !(value === undefined || '' === value); |
||||
|
}, |
||||
|
email: function(value){ |
||||
|
var |
||||
|
emailRegExp = new RegExp("[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?") |
||||
|
; |
||||
|
return emailRegExp.test(value); |
||||
|
}, |
||||
|
length: function(value, requiredLength) { |
||||
|
return (value !== undefined) |
||||
|
? (value.length >= requiredLength) |
||||
|
: false |
||||
|
; |
||||
|
}, |
||||
|
not: function(value, notValue) { |
||||
|
return (value != notValue); |
||||
|
}, |
||||
|
maxLength: function(value, maxLength) { |
||||
|
return (value !== undefined) |
||||
|
? (value.length <= maxLength) |
||||
|
: false |
||||
|
; |
||||
|
}, |
||||
|
match: function(value, matchingField) { |
||||
|
// use either id or name of field
|
||||
|
var |
||||
|
$form = $(this), |
||||
|
matchingValue |
||||
|
; |
||||
|
if($form.find('#' + matchingField).size() > 0) { |
||||
|
matchingValue = $form.find('#' + matchingField).val(); |
||||
|
} |
||||
|
else if($form.find('[name=' + matchingField +']').size() > 0) { |
||||
|
matchingValue = $form.find('[name=' + matchingField + ']').val(); |
||||
|
} |
||||
|
else if( $form.find('[data-validate="'+ matchingField +'"]').size() > 0 ) { |
||||
|
matchingValue = $form.find('[data-validate="'+ matchingField +'"]').val(); |
||||
|
} |
||||
|
return (matchingValue !== undefined) |
||||
|
? ( value.toString() == matchingValue.toString() ) |
||||
|
: false |
||||
|
; |
||||
|
}, |
||||
|
url: function(value) { |
||||
|
var |
||||
|
urlRegExp = /(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/ |
||||
|
; |
||||
|
return urlRegExp.test(value); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
}; |
||||
|
|
||||
|
})( jQuery, window , document ); |
@ -0,0 +1,536 @@ |
|||||
|
/* ****************************** |
||||
|
Form Validation Components |
||||
|
Author: Jack Lukic |
||||
|
Notes: First Commit April 08, 2012 |
||||
|
|
||||
|
Refactored May 28, 2013 |
||||
|
|
||||
|
Allows you to validate forms based on a form validation object |
||||
|
Form validation objects are bound by either data-validate="" metadata, or form id or name tags |
||||
|
|
||||
|
****************************** */ |
||||
|
|
||||
|
;(function ( $, window, document, undefined ) { |
||||
|
|
||||
|
$.fn.form = function(fields, parameters) { |
||||
|
var |
||||
|
$allModules = $(this), |
||||
|
$document = $(document), |
||||
|
|
||||
|
settings = $.extend(true, {}, $.fn.form.settings, parameters), |
||||
|
|
||||
|
eventNamespace = '.' + settings.namespace, |
||||
|
moduleNamespace = 'module-' + settings.namespace, |
||||
|
|
||||
|
selector = $allModules.selector || '', |
||||
|
time = new Date().getTime(), |
||||
|
performance = [], |
||||
|
|
||||
|
query = arguments[0], |
||||
|
methodInvoked = (typeof query == 'string'), |
||||
|
queryArguments = [].slice.call(arguments, 1), |
||||
|
invokedResponse |
||||
|
; |
||||
|
$allModules |
||||
|
.each(function() { |
||||
|
var |
||||
|
$module = $(this), |
||||
|
$group = $(this).find(settings.selector.group), |
||||
|
$field = $(this).find(settings.selector.field), |
||||
|
$errorPrompt = $(this).find(settings.selector.prompt), |
||||
|
|
||||
|
formErrors = [], |
||||
|
|
||||
|
element = this, |
||||
|
instance = $module.data('module-' + settings.namespace), |
||||
|
|
||||
|
namespace = settings.namespace, |
||||
|
metadata = settings.metadata, |
||||
|
className = settings.className, |
||||
|
errors = settings.errors, |
||||
|
module |
||||
|
; |
||||
|
|
||||
|
module = { |
||||
|
|
||||
|
initialize: function() { |
||||
|
module.verbose('Initializing form validation'); |
||||
|
if(fields !== undefined || !$.isEmptyObject(fields) ) { |
||||
|
// attach event handler
|
||||
|
if(settings.on == 'submit') { |
||||
|
$module |
||||
|
.on('submit.' + namespace, module.validate.form) |
||||
|
; |
||||
|
} |
||||
|
} |
||||
|
else { |
||||
|
module.error(errors.noFields, $module); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
destroy: function() { |
||||
|
$module |
||||
|
.off(namespace) |
||||
|
; |
||||
|
}, |
||||
|
|
||||
|
refresh: function() { |
||||
|
$field = $module.find(settings.selector.field); |
||||
|
}, |
||||
|
|
||||
|
field: { |
||||
|
find: function(identifier) { |
||||
|
module.refresh(); |
||||
|
if( $field.filter('#' + identifier).size() > 0 ) { |
||||
|
return $field.filter('#' + identifier); |
||||
|
} |
||||
|
else if( $field.filter('[name="' + identifier +'"]').size() > 0 ) { |
||||
|
return $field.filter('[name="' + identifier +'"]'); |
||||
|
} |
||||
|
else if( $field.filter('[data-' + metadata.validate + '="'+ identifier +'"]').size() > 0 ) { |
||||
|
return $field.filter('[data-' + metadata.validate + '="'+ identifier +'"]'); |
||||
|
} |
||||
|
return $('<input/>'); |
||||
|
}, |
||||
|
add: { |
||||
|
error: function(field, errors) { |
||||
|
var |
||||
|
$field = module.field.find(field.identifier), |
||||
|
$errorGroup = $field.closest($group), |
||||
|
$errorPrompt = $group.find($errorPrompt), |
||||
|
promptExists = ($errorPrompt.size() !== 0) |
||||
|
; |
||||
|
$errorGroup |
||||
|
.addClass(className.error) |
||||
|
; |
||||
|
if(settings.inlineError) { |
||||
|
// create message container on first invalid validation attempt
|
||||
|
if(!promptExists) { |
||||
|
$errorPrompt = $('<div />') |
||||
|
.addClass(className.prompt) |
||||
|
.insertBefore($field) |
||||
|
; |
||||
|
} |
||||
|
// add prompt message
|
||||
|
$errorPrompt |
||||
|
.html(errors[0]) |
||||
|
.fadeIn(settings.animateSpeed) |
||||
|
; |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
remove: { |
||||
|
error: function(field) { |
||||
|
var |
||||
|
$field = module.field.find(field.identifier), |
||||
|
$errorGroup = $field.closest($group), |
||||
|
$errorPrompt = $group.find($errorPrompt) |
||||
|
; |
||||
|
$errorGroup |
||||
|
.removeClass(className.error) |
||||
|
; |
||||
|
if(settings.inlineError) { |
||||
|
$errorPrompt.hide(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
validate: { |
||||
|
|
||||
|
form: function(event) { |
||||
|
var |
||||
|
allValid = true |
||||
|
; |
||||
|
// reset errors
|
||||
|
formErrors = []; |
||||
|
$.each(fields, function(fieldName, field){ |
||||
|
// form is invalid after first bad field, but keep checking
|
||||
|
if( !( module.validate.field(field) ) ) { |
||||
|
allValid = false; |
||||
|
} |
||||
|
}); |
||||
|
// Evaluate form callbacks
|
||||
|
return (allValid) |
||||
|
? $.proxy(settings.onSuccess, this)(event) |
||||
|
: $.proxy(settings.onFailure, this)(formErrors) |
||||
|
; |
||||
|
}, |
||||
|
|
||||
|
// takes a validation object and returns whether field passes validation
|
||||
|
field: function(field) { |
||||
|
var |
||||
|
$field = module.field.find(field.identifier), |
||||
|
fieldValid = true, |
||||
|
fieldErrors = [] |
||||
|
; |
||||
|
if(field.rules !== undefined) { |
||||
|
// iterate over all validation types for a certain field
|
||||
|
$.each(field.rules, function(index, rule) { |
||||
|
if( !( module.validate.rule(field, rule) ) ) { |
||||
|
module.debug('Field is invalid', field.identifier, rule.type); |
||||
|
fieldErrors.push(rule.prompt); |
||||
|
fieldValid = false; |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
if(fieldValid) { |
||||
|
module.field.remove.error(field, fieldErrors); |
||||
|
settings.onValid($field); |
||||
|
} |
||||
|
else { |
||||
|
formErrors = formErrors.concat(fieldErrors); |
||||
|
module.field.add.error(field, fieldErrors); |
||||
|
$.proxy(settings.onInvalid, $field)(fieldErrors); |
||||
|
return false; |
||||
|
} |
||||
|
return true; |
||||
|
}, |
||||
|
|
||||
|
// takes validation rule and returns whether field passes rule
|
||||
|
rule: function(field, validation) { |
||||
|
var |
||||
|
$field = module.field.find(field.identifier), |
||||
|
type = validation.type, |
||||
|
value = $field.val(), |
||||
|
|
||||
|
bracketRegExp = /\[(.*?)\]/i, |
||||
|
bracket = bracketRegExp.exec(type), |
||||
|
isValid = true, |
||||
|
ancillary, |
||||
|
functionType |
||||
|
; |
||||
|
// if bracket notation is used, pass in extra parameters
|
||||
|
if(bracket !== undefined && bracket != null) { |
||||
|
ancillary = bracket[1]; |
||||
|
functionType = type.replace(bracket[0], ''); |
||||
|
isValid = $.proxy(settings.rules[functionType], $module)(value, ancillary); |
||||
|
} |
||||
|
// normal notation
|
||||
|
else { |
||||
|
isValid = (type == 'checked') |
||||
|
? $field.filter(':checked').size() > 0 |
||||
|
: settings.rules[type](value) |
||||
|
; |
||||
|
} |
||||
|
return isValid; |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
setting: function(name, value) { |
||||
|
if(value !== undefined) { |
||||
|
if( $.isPlainObject(name) ) { |
||||
|
$.extend(true, settings, name); |
||||
|
} |
||||
|
else { |
||||
|
settings[name] = value; |
||||
|
} |
||||
|
} |
||||
|
else { |
||||
|
return settings[name]; |
||||
|
} |
||||
|
}, |
||||
|
internal: function(name, value) { |
||||
|
if(value !== undefined) { |
||||
|
if( $.isPlainObject(name) ) { |
||||
|
$.extend(true, module, name); |
||||
|
} |
||||
|
else { |
||||
|
module[name] = value; |
||||
|
} |
||||
|
} |
||||
|
else { |
||||
|
return module[name]; |
||||
|
} |
||||
|
}, |
||||
|
debug: function() { |
||||
|
if(settings.debug) { |
||||
|
module.performance.log(arguments[0]); |
||||
|
module.debug = Function.prototype.bind.call(console.log, console, settings.moduleName + ':'); |
||||
|
} |
||||
|
}, |
||||
|
verbose: function() { |
||||
|
if(settings.verbose && settings.debug) { |
||||
|
module.performance.log(arguments[0]); |
||||
|
module.verbose = Function.prototype.bind.call(console.info, console, settings.moduleName + ':'); |
||||
|
} |
||||
|
}, |
||||
|
error: function() { |
||||
|
module.error = Function.prototype.bind.call(console.log, console, settings.moduleName + ':'); |
||||
|
}, |
||||
|
performance: { |
||||
|
log: function(message) { |
||||
|
var |
||||
|
currentTime, |
||||
|
executionTime, |
||||
|
previousTime |
||||
|
; |
||||
|
if(settings.performance) { |
||||
|
currentTime = new Date().getTime(); |
||||
|
previousTime = time || currentTime, |
||||
|
executionTime = currentTime - previousTime; |
||||
|
time = currentTime; |
||||
|
performance.push({ |
||||
|
'Element' : element, |
||||
|
'Name' : message, |
||||
|
'Execution Time' : executionTime |
||||
|
}); |
||||
|
clearTimeout(module.performance.timer); |
||||
|
module.performance.timer = setTimeout(module.performance.display, 100); |
||||
|
} |
||||
|
}, |
||||
|
display: function() { |
||||
|
var |
||||
|
title = settings.moduleName, |
||||
|
caption = settings.moduleName + ': ' + selector + '(' + $allModules.size() + ' elements)', |
||||
|
totalExecutionTime = 0 |
||||
|
; |
||||
|
if(selector) { |
||||
|
title += 'Performance (' + selector + ')'; |
||||
|
} |
||||
|
if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { |
||||
|
console.groupCollapsed(title); |
||||
|
if(console.table) { |
||||
|
$.each(performance, function(index, data) { |
||||
|
totalExecutionTime += data['Execution Time']; |
||||
|
}); |
||||
|
console.table(performance); |
||||
|
} |
||||
|
else { |
||||
|
$.each(performance, function(index, data) { |
||||
|
totalExecutionTime += data['Execution Time']; |
||||
|
}); |
||||
|
} |
||||
|
console.log('Total Execution Time:', totalExecutionTime +'ms'); |
||||
|
console.groupEnd(); |
||||
|
performance = []; |
||||
|
time = false; |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
invoke: function(query, passedArguments, context) { |
||||
|
var |
||||
|
maxDepth, |
||||
|
found |
||||
|
; |
||||
|
passedArguments = passedArguments || queryArguments; |
||||
|
context = element || context; |
||||
|
if(typeof query == 'string' && instance !== undefined) { |
||||
|
query = query.split('.'); |
||||
|
maxDepth = query.length - 1; |
||||
|
$.each(query, function(depth, value) { |
||||
|
if( $.isPlainObject( instance[value] ) && (depth != maxDepth) ) { |
||||
|
instance = instance[value]; |
||||
|
return true; |
||||
|
} |
||||
|
else if( instance[value] !== undefined ) { |
||||
|
found = instance[value]; |
||||
|
return true; |
||||
|
} |
||||
|
module.error(errors.method); |
||||
|
return false; |
||||
|
}); |
||||
|
} |
||||
|
if ( $.isFunction( found ) ) { |
||||
|
module.verbose('Executing invoked function', found); |
||||
|
return found.apply(context, passedArguments); |
||||
|
} |
||||
|
return found || false; |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
if(methodInvoked) { |
||||
|
if(instance === undefined) { |
||||
|
module.initialize(); |
||||
|
} |
||||
|
invokedResponse = module.invoke(query); |
||||
|
} |
||||
|
else { |
||||
|
if(instance !== undefined) { |
||||
|
module.destroy(); |
||||
|
} |
||||
|
module.initialize(); |
||||
|
} |
||||
|
}) |
||||
|
; |
||||
|
return (invokedResponse) |
||||
|
? invokedResponse |
||||
|
: this |
||||
|
; |
||||
|
}; |
||||
|
|
||||
|
$.fn.form.settings = { |
||||
|
|
||||
|
// module info
|
||||
|
moduleName : 'Validate Form Module', |
||||
|
debug : true, |
||||
|
verbose : false, |
||||
|
namespace : 'validate', |
||||
|
|
||||
|
animateSpeed : 150, |
||||
|
inlineError : false, |
||||
|
|
||||
|
on: 'submit', |
||||
|
|
||||
|
onValid : function() {}, |
||||
|
onInvalid : function() {}, |
||||
|
onSuccess : function() { return true; }, |
||||
|
onFailure : function() { return false; }, |
||||
|
|
||||
|
metadata : { |
||||
|
validate: 'validate' |
||||
|
}, |
||||
|
|
||||
|
// errors
|
||||
|
errors: { |
||||
|
method : 'The method you called is not defined.', |
||||
|
noFields : 'No validation object specified.' |
||||
|
}, |
||||
|
|
||||
|
|
||||
|
selector : { |
||||
|
group : '.field', |
||||
|
prompt : '.prompt', |
||||
|
field : 'input, textarea, select' |
||||
|
}, |
||||
|
|
||||
|
className : { |
||||
|
error : 'error', |
||||
|
prompt : 'prompt' |
||||
|
}, |
||||
|
|
||||
|
defaults: { |
||||
|
firstName: { |
||||
|
identifier : 'first-name', |
||||
|
rules: [ |
||||
|
{ |
||||
|
type : 'empty', |
||||
|
prompt : 'Please enter your first name' |
||||
|
} |
||||
|
] |
||||
|
}, |
||||
|
lastName: { |
||||
|
identifier : 'last-name', |
||||
|
rules: [ |
||||
|
{ |
||||
|
type : 'empty', |
||||
|
prompt : 'Please enter your last name' |
||||
|
} |
||||
|
] |
||||
|
}, |
||||
|
username: { |
||||
|
identifier : 'username', |
||||
|
rules: [ |
||||
|
{ |
||||
|
type : 'email', |
||||
|
prompt : 'Please enter a username' |
||||
|
} |
||||
|
] |
||||
|
}, |
||||
|
email: { |
||||
|
identifier : 'email', |
||||
|
rules: [ |
||||
|
{ |
||||
|
type : 'empty', |
||||
|
prompt : 'Please enter your email' |
||||
|
}, |
||||
|
{ |
||||
|
type : 'email', |
||||
|
prompt : 'Please enter a valid email' |
||||
|
} |
||||
|
] |
||||
|
}, |
||||
|
password: { |
||||
|
identifier : 'password', |
||||
|
rules: [ |
||||
|
{ |
||||
|
type : 'empty', |
||||
|
prompt : 'Please enter a password' |
||||
|
}, |
||||
|
{ |
||||
|
type : 'length[6]', |
||||
|
prompt : 'Your password must be at least 6 characters' |
||||
|
} |
||||
|
] |
||||
|
}, |
||||
|
passwordConfirm: { |
||||
|
identifier : 'password-confirm', |
||||
|
rules: [ |
||||
|
{ |
||||
|
type : 'empty', |
||||
|
prompt : 'Please confirm your password' |
||||
|
}, |
||||
|
{ |
||||
|
identifier : 'password-confirm', |
||||
|
type : 'match[password]', |
||||
|
prompt : 'Please verify password matches' |
||||
|
} |
||||
|
] |
||||
|
}, |
||||
|
terms: { |
||||
|
identifier : 'terms', |
||||
|
rules: [ |
||||
|
{ |
||||
|
type : 'checked', |
||||
|
prompt : 'You must agree to the terms and conditions' |
||||
|
} |
||||
|
] |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
rules: { |
||||
|
empty: function(value) { |
||||
|
return !(value === undefined || '' === value); |
||||
|
}, |
||||
|
email: function(value){ |
||||
|
var |
||||
|
emailRegExp = new RegExp("[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?") |
||||
|
; |
||||
|
return emailRegExp.test(value); |
||||
|
}, |
||||
|
length: function(value, requiredLength) { |
||||
|
return (value !== undefined) |
||||
|
? (value.length >= requiredLength) |
||||
|
: false |
||||
|
; |
||||
|
}, |
||||
|
not: function(value, notValue) { |
||||
|
return (value != notValue); |
||||
|
}, |
||||
|
maxLength: function(value, maxLength) { |
||||
|
return (value !== undefined) |
||||
|
? (value.length <= maxLength) |
||||
|
: false |
||||
|
; |
||||
|
}, |
||||
|
match: function(value, matchingField) { |
||||
|
// use either id or name of field
|
||||
|
var |
||||
|
$form = $(this), |
||||
|
matchingValue |
||||
|
; |
||||
|
if($form.find('#' + matchingField).size() > 0) { |
||||
|
matchingValue = $form.find('#' + matchingField).val(); |
||||
|
} |
||||
|
else if($form.find('[name=' + matchingField +']').size() > 0) { |
||||
|
matchingValue = $form.find('[name=' + matchingField + ']').val(); |
||||
|
} |
||||
|
else if( $form.find('[data-validate="'+ matchingField +'"]').size() > 0 ) { |
||||
|
matchingValue = $form.find('[data-validate="'+ matchingField +'"]').val(); |
||||
|
} |
||||
|
return (matchingValue !== undefined) |
||||
|
? ( value.toString() == matchingValue.toString() ) |
||||
|
: false |
||||
|
; |
||||
|
}, |
||||
|
url: function(value) { |
||||
|
var |
||||
|
urlRegExp = /(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/ |
||||
|
; |
||||
|
return urlRegExp.test(value); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
}; |
||||
|
|
||||
|
})( jQuery, window , document ); |
@ -0,0 +1,253 @@ |
|||||
|
--- |
||||
|
layout : 'default' |
||||
|
css : 'form' |
||||
|
|
||||
|
title : 'Validate Form' |
||||
|
type : 'UI Module' |
||||
|
--- |
||||
|
|
||||
|
<script src="/components/semantic/modules/behavior/form.js"></script> |
||||
|
<script src="/javascript/validate-form.js"></script> |
||||
|
|
||||
|
<div class="segment"> |
||||
|
<div class="container"> |
||||
|
<h1 class="ui dividing header">Form Validation</h1> |
||||
|
<p>Form validation checks user input data against a set of criteria before passing along the data to the server.</p> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="main container"> |
||||
|
|
||||
|
<div class="peek"> |
||||
|
<div class="ui vertical pointing secondary menu"> |
||||
|
<a class="item">Usage</a> |
||||
|
<a class="item">Settings</a> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<h2 class="ui dividing header">Usage</h2> |
||||
|
|
||||
|
<div class="example"> |
||||
|
<h4>Basic Validation</h4> |
||||
|
<p>Form validation requires passing in a validation object with the rules required to validate your form.</p> |
||||
|
<div class="ui green message">If no validation object is specified then the form will validate against the default validation set up for the plugin. </div> |
||||
|
<div class="ui form segment"> |
||||
|
<p>Let's go ahead and get you signed up.</p> |
||||
|
<div class="two fields"> |
||||
|
<div class="field"> |
||||
|
<label>First Name</label> |
||||
|
<input placeholder="First Name" name="first-name" type="text"> |
||||
|
</div> |
||||
|
<div class="field"> |
||||
|
<label>Last Name</label> |
||||
|
<input placeholder="Last Name" name="last-name" type="text"> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="field"> |
||||
|
<label>Username</label> |
||||
|
<input placeholder="Username" name="username" type="text"> |
||||
|
</div> |
||||
|
<div class="field"> |
||||
|
<label>Password</label> |
||||
|
<input type="password" name="password"> |
||||
|
</div> |
||||
|
<div class="inline field"> |
||||
|
<div class="ui checkbox"> |
||||
|
<input type="checkbox" name="terms" /> |
||||
|
<label class="box"></label> |
||||
|
</div> |
||||
|
<label>I agree to the terms and conditions</label> |
||||
|
</div> |
||||
|
<div class="ui blue submit button">Submit</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<div class="example"> |
||||
|
<h4>Validation w/ Message</h4> |
||||
|
<p>Forms that contain a <a href="elements/message.html">ui message</a> error block will automatically be filled in with form validation information.</p> |
||||
|
<div class="info message">The template for error messages can be modified by adjusting settings.template.error</div> |
||||
|
<div class="ignore code"> |
||||
|
$('.ui.form') |
||||
|
.form() |
||||
|
; |
||||
|
</div> |
||||
|
<div class="ui form segment"> |
||||
|
<p>Let's go ahead and get you signed up.</p> |
||||
|
<div class="two fields"> |
||||
|
<div class="field"> |
||||
|
<label>First Name</label> |
||||
|
<input placeholder="First Name" name="first-name" type="text"> |
||||
|
</div> |
||||
|
<div class="field"> |
||||
|
<label>Last Name</label> |
||||
|
<input placeholder="Last Name" name="last-name" type="text"> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="field"> |
||||
|
<label>Username</label> |
||||
|
<input placeholder="Username" name="username" type="text"> |
||||
|
</div> |
||||
|
<div class="field"> |
||||
|
<label>Password</label> |
||||
|
<input type="password" name="password"> |
||||
|
</div> |
||||
|
<div class="inline field"> |
||||
|
<div class="ui checkbox"> |
||||
|
<input type="checkbox" name="terms" /> |
||||
|
<label class="box"></label> |
||||
|
</div> |
||||
|
<label>I agree to the terms and conditions</label> |
||||
|
</div> |
||||
|
<div class="ui blue submit button">Submit</div> |
||||
|
<div class="ui error message"></div> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<div class="dog example"> |
||||
|
<h4>Custom Validation</h4> |
||||
|
<p>Custom form validation requires passing in a validation object with the rules required to validate your form.</p> |
||||
|
<div class="ui info message"> |
||||
|
<i class="help icon"></i>A validation object includes a list of form elements, and rules to validate each against. Fields are matched by either the id tag, name tag, or data-validate metadata matching the identifier provided in the settings object. To pass parameters to a rule, use bracket notation |
||||
|
</div> |
||||
|
<div class="ignore code"> |
||||
|
$('.ui.form') |
||||
|
.form({ |
||||
|
dog: { |
||||
|
identifier: 'dog', |
||||
|
rules: [ |
||||
|
{ |
||||
|
type: 'empty', |
||||
|
prompt: 'You must have a dog to add' |
||||
|
}, |
||||
|
{ |
||||
|
type: 'is[fluffy dog]', |
||||
|
prompt: 'I only want you to add fluffy dogs!' |
||||
|
}, |
||||
|
{ |
||||
|
type: 'not[mean]', |
||||
|
prompt: 'Why would you add a mean dog to the list?' |
||||
|
} |
||||
|
] |
||||
|
} |
||||
|
}) |
||||
|
; |
||||
|
</div> |
||||
|
<div class="ui form segment"> |
||||
|
<p>Let's go ahead and get you signed up.</p> |
||||
|
<div class="field"> |
||||
|
<label>Dog</label> |
||||
|
<input placeholder="Dog" name="dog" type="text"> |
||||
|
</div> |
||||
|
<div class="ui blue submit button">Add Dog <i class="add icon"></i></div> |
||||
|
<div class="ui error message"></div> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
|
||||
|
|
||||
|
<h2>Settings</h2> |
||||
|
|
||||
|
<h3 class="ui header">Defaults</h3> |
||||
|
<table class="ui settings celled table"> |
||||
|
<thead> |
||||
|
<th colspan="3">Form Settings</th> |
||||
|
</thead> |
||||
|
<tbody> |
||||
|
<tr> |
||||
|
<td>keyboardShortcuts</td> |
||||
|
<td>true</td> |
||||
|
<td>Adds keyboard shortcuts for enter and escape keys to submit form and blur fields respectively</td> |
||||
|
</tr> |
||||
|
<tr> |
||||
|
<td>on</td> |
||||
|
<td>click</td> |
||||
|
<td>Event used to trigger validation. Can be either submit or change</td> |
||||
|
</tr> |
||||
|
<tr> |
||||
|
<td>inlineError</td> |
||||
|
<td>false</td> |
||||
|
<td>Adds prompt text from template on validation error</td> |
||||
|
</tr> |
||||
|
<tr> |
||||
|
<td>animationDuration</td> |
||||
|
<td>150</td> |
||||
|
<td>Fade in speed for inline prompt</td> |
||||
|
</tr> |
||||
|
</tbody> |
||||
|
</table> |
||||
|
|
||||
|
<table class="ui settings celled table"> |
||||
|
<thead> |
||||
|
<th colspan="3">Callbacks</th> |
||||
|
</thead> |
||||
|
<tbody> |
||||
|
<tr> |
||||
|
<td>onValid</td> |
||||
|
<td>None</td> |
||||
|
<td>Callback on each valid field</td> |
||||
|
</tr> |
||||
|
<tr> |
||||
|
<td>onInvalid</td> |
||||
|
<td>None</td> |
||||
|
<td>Callback on each invalid field</td> |
||||
|
</tr> |
||||
|
<tr> |
||||
|
<td>onSuccess</td> |
||||
|
<td>None</td> |
||||
|
<td>Callback if a form is all valid</td> |
||||
|
</tr> |
||||
|
<tr> |
||||
|
<td>onFailure</td> |
||||
|
<td>None</td> |
||||
|
<td>Callback if any form field is invalid</td> |
||||
|
</tr> |
||||
|
</tbody> |
||||
|
</table> |
||||
|
|
||||
|
<table class="ui settings celled table"> |
||||
|
<thead> |
||||
|
<th colspan="3">General Settings</th> |
||||
|
</thead> |
||||
|
<tbody> |
||||
|
<tr> |
||||
|
<td>moduleName</td> |
||||
|
<td>Form</td> |
||||
|
<td>Name used in debug logs</td> |
||||
|
</tr> |
||||
|
<tr> |
||||
|
<td>debug</td> |
||||
|
<td>False</td> |
||||
|
<td>Provides standard debug output to console</td> |
||||
|
</tr> |
||||
|
<tr> |
||||
|
<td>performance</td> |
||||
|
<td>True</td> |
||||
|
<td>Provides standard debug output to console</td> |
||||
|
</tr> |
||||
|
<tr> |
||||
|
<td>verbose</td> |
||||
|
<td>False</td> |
||||
|
<td>Provides ancillary debug output to console</td> |
||||
|
</tr> |
||||
|
<tr> |
||||
|
<td>namespace</td> |
||||
|
<td>form</td> |
||||
|
<td>Event namespace. Makes sure module teardown does not effect other events attached to an element.</td> |
||||
|
</tr> |
||||
|
<tr> |
||||
|
<td>errors</td> |
||||
|
<td colspan="2"> |
||||
|
<div class="code"> |
||||
|
errors : { |
||||
|
action : 'You called a form action that was not defined', |
||||
|
method : 'The method you called is not defined.' |
||||
|
} |
||||
|
</div> |
||||
|
</td> |
||||
|
</tr> |
||||
|
</tbody> |
||||
|
</table> |
||||
|
|
||||
|
</div> |
||||
|
</body> |
||||
|
|
||||
|
</html> |
@ -0,0 +1,536 @@ |
|||||
|
/* ****************************** |
||||
|
Form Validation Components |
||||
|
Author: Jack Lukic |
||||
|
Notes: First Commit April 08, 2012 |
||||
|
|
||||
|
Refactored May 28, 2013 |
||||
|
|
||||
|
Allows you to validate forms based on a form validation object |
||||
|
Form validation objects are bound by either data-validate="" metadata, or form id or name tags |
||||
|
|
||||
|
****************************** */ |
||||
|
|
||||
|
;(function ( $, window, document, undefined ) { |
||||
|
|
||||
|
$.fn.form = function(fields, parameters) { |
||||
|
var |
||||
|
$allModules = $(this), |
||||
|
$document = $(document), |
||||
|
|
||||
|
settings = $.extend(true, {}, $.fn.form.settings, parameters), |
||||
|
|
||||
|
eventNamespace = '.' + settings.namespace, |
||||
|
moduleNamespace = 'module-' + settings.namespace, |
||||
|
|
||||
|
selector = $allModules.selector || '', |
||||
|
time = new Date().getTime(), |
||||
|
performance = [], |
||||
|
|
||||
|
query = arguments[0], |
||||
|
methodInvoked = (typeof query == 'string'), |
||||
|
queryArguments = [].slice.call(arguments, 1), |
||||
|
invokedResponse |
||||
|
; |
||||
|
$allModules |
||||
|
.each(function() { |
||||
|
var |
||||
|
$module = $(this), |
||||
|
$group = $(this).find(settings.selector.group), |
||||
|
$field = $(this).find(settings.selector.field), |
||||
|
$errorPrompt = $(this).find(settings.selector.prompt), |
||||
|
|
||||
|
formErrors = [], |
||||
|
|
||||
|
element = this, |
||||
|
instance = $module.data('module-' + settings.namespace), |
||||
|
|
||||
|
namespace = settings.namespace, |
||||
|
metadata = settings.metadata, |
||||
|
className = settings.className, |
||||
|
errors = settings.errors, |
||||
|
module |
||||
|
; |
||||
|
|
||||
|
module = { |
||||
|
|
||||
|
initialize: function() { |
||||
|
module.verbose('Initializing form validation'); |
||||
|
if(fields !== undefined || !$.isEmptyObject(fields) ) { |
||||
|
// attach event handler
|
||||
|
if(settings.on == 'submit') { |
||||
|
$module |
||||
|
.on('submit.' + namespace, module.validate.form) |
||||
|
; |
||||
|
} |
||||
|
} |
||||
|
else { |
||||
|
module.error(errors.noFields, $module); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
destroy: function() { |
||||
|
$module |
||||
|
.off(namespace) |
||||
|
; |
||||
|
}, |
||||
|
|
||||
|
refresh: function() { |
||||
|
$field = $module.find(settings.selector.field); |
||||
|
}, |
||||
|
|
||||
|
field: { |
||||
|
find: function(identifier) { |
||||
|
module.refresh(); |
||||
|
if( $field.filter('#' + identifier).size() > 0 ) { |
||||
|
return $field.filter('#' + identifier); |
||||
|
} |
||||
|
else if( $field.filter('[name="' + identifier +'"]').size() > 0 ) { |
||||
|
return $field.filter('[name="' + identifier +'"]'); |
||||
|
} |
||||
|
else if( $field.filter('[data-' + metadata.validate + '="'+ identifier +'"]').size() > 0 ) { |
||||
|
return $field.filter('[data-' + metadata.validate + '="'+ identifier +'"]'); |
||||
|
} |
||||
|
return $('<input/>'); |
||||
|
}, |
||||
|
add: { |
||||
|
error: function(field, errors) { |
||||
|
var |
||||
|
$field = module.field.find(field.identifier), |
||||
|
$errorGroup = $field.closest($group), |
||||
|
$errorPrompt = $group.find($errorPrompt), |
||||
|
promptExists = ($errorPrompt.size() !== 0) |
||||
|
; |
||||
|
$errorGroup |
||||
|
.addClass(className.error) |
||||
|
; |
||||
|
if(settings.inlineError) { |
||||
|
// create message container on first invalid validation attempt
|
||||
|
if(!promptExists) { |
||||
|
$errorPrompt = $('<div />') |
||||
|
.addClass(className.prompt) |
||||
|
.insertBefore($field) |
||||
|
; |
||||
|
} |
||||
|
// add prompt message
|
||||
|
$errorPrompt |
||||
|
.html(errors[0]) |
||||
|
.fadeIn(settings.animateSpeed) |
||||
|
; |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
remove: { |
||||
|
error: function(field) { |
||||
|
var |
||||
|
$field = module.field.find(field.identifier), |
||||
|
$errorGroup = $field.closest($group), |
||||
|
$errorPrompt = $group.find($errorPrompt) |
||||
|
; |
||||
|
$errorGroup |
||||
|
.removeClass(className.error) |
||||
|
; |
||||
|
if(settings.inlineError) { |
||||
|
$errorPrompt.hide(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
validate: { |
||||
|
|
||||
|
form: function(event) { |
||||
|
var |
||||
|
allValid = true |
||||
|
; |
||||
|
// reset errors
|
||||
|
formErrors = []; |
||||
|
$.each(fields, function(fieldName, field){ |
||||
|
// form is invalid after first bad field, but keep checking
|
||||
|
if( !( module.validate.field(field) ) ) { |
||||
|
allValid = false; |
||||
|
} |
||||
|
}); |
||||
|
// Evaluate form callbacks
|
||||
|
return (allValid) |
||||
|
? $.proxy(settings.onSuccess, this)(event) |
||||
|
: $.proxy(settings.onFailure, this)(formErrors) |
||||
|
; |
||||
|
}, |
||||
|
|
||||
|
// takes a validation object and returns whether field passes validation
|
||||
|
field: function(field) { |
||||
|
var |
||||
|
$field = module.field.find(field.identifier), |
||||
|
fieldValid = true, |
||||
|
fieldErrors = [] |
||||
|
; |
||||
|
if(field.rules !== undefined) { |
||||
|
// iterate over all validation types for a certain field
|
||||
|
$.each(field.rules, function(index, rule) { |
||||
|
if( !( module.validate.rule(field, rule) ) ) { |
||||
|
module.debug('Field is invalid', field.identifier, rule.type); |
||||
|
fieldErrors.push(rule.prompt); |
||||
|
fieldValid = false; |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
if(fieldValid) { |
||||
|
module.field.remove.error(field, fieldErrors); |
||||
|
settings.onValid($field); |
||||
|
} |
||||
|
else { |
||||
|
formErrors = formErrors.concat(fieldErrors); |
||||
|
module.field.add.error(field, fieldErrors); |
||||
|
$.proxy(settings.onInvalid, $field)(fieldErrors); |
||||
|
return false; |
||||
|
} |
||||
|
return true; |
||||
|
}, |
||||
|
|
||||
|
// takes validation rule and returns whether field passes rule
|
||||
|
rule: function(field, validation) { |
||||
|
var |
||||
|
$field = module.field.find(field.identifier), |
||||
|
type = validation.type, |
||||
|
value = $field.val(), |
||||
|
|
||||
|
bracketRegExp = /\[(.*?)\]/i, |
||||
|
bracket = bracketRegExp.exec(type), |
||||
|
isValid = true, |
||||
|
ancillary, |
||||
|
functionType |
||||
|
; |
||||
|
// if bracket notation is used, pass in extra parameters
|
||||
|
if(bracket !== undefined && bracket != null) { |
||||
|
ancillary = bracket[1]; |
||||
|
functionType = type.replace(bracket[0], ''); |
||||
|
isValid = $.proxy(settings.rules[functionType], $module)(value, ancillary); |
||||
|
} |
||||
|
// normal notation
|
||||
|
else { |
||||
|
isValid = (type == 'checked') |
||||
|
? $field.filter(':checked').size() > 0 |
||||
|
: settings.rules[type](value) |
||||
|
; |
||||
|
} |
||||
|
return isValid; |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
setting: function(name, value) { |
||||
|
if(value !== undefined) { |
||||
|
if( $.isPlainObject(name) ) { |
||||
|
$.extend(true, settings, name); |
||||
|
} |
||||
|
else { |
||||
|
settings[name] = value; |
||||
|
} |
||||
|
} |
||||
|
else { |
||||
|
return settings[name]; |
||||
|
} |
||||
|
}, |
||||
|
internal: function(name, value) { |
||||
|
if(value !== undefined) { |
||||
|
if( $.isPlainObject(name) ) { |
||||
|
$.extend(true, module, name); |
||||
|
} |
||||
|
else { |
||||
|
module[name] = value; |
||||
|
} |
||||
|
} |
||||
|
else { |
||||
|
return module[name]; |
||||
|
} |
||||
|
}, |
||||
|
debug: function() { |
||||
|
if(settings.debug) { |
||||
|
module.performance.log(arguments[0]); |
||||
|
module.debug = Function.prototype.bind.call(console.log, console, settings.moduleName + ':'); |
||||
|
} |
||||
|
}, |
||||
|
verbose: function() { |
||||
|
if(settings.verbose && settings.debug) { |
||||
|
module.performance.log(arguments[0]); |
||||
|
module.verbose = Function.prototype.bind.call(console.info, console, settings.moduleName + ':'); |
||||
|
} |
||||
|
}, |
||||
|
error: function() { |
||||
|
module.error = Function.prototype.bind.call(console.log, console, settings.moduleName + ':'); |
||||
|
}, |
||||
|
performance: { |
||||
|
log: function(message) { |
||||
|
var |
||||
|
currentTime, |
||||
|
executionTime, |
||||
|
previousTime |
||||
|
; |
||||
|
if(settings.performance) { |
||||
|
currentTime = new Date().getTime(); |
||||
|
previousTime = time || currentTime, |
||||
|
executionTime = currentTime - previousTime; |
||||
|
time = currentTime; |
||||
|
performance.push({ |
||||
|
'Element' : element, |
||||
|
'Name' : message, |
||||
|
'Execution Time' : executionTime |
||||
|
}); |
||||
|
clearTimeout(module.performance.timer); |
||||
|
module.performance.timer = setTimeout(module.performance.display, 100); |
||||
|
} |
||||
|
}, |
||||
|
display: function() { |
||||
|
var |
||||
|
title = settings.moduleName, |
||||
|
caption = settings.moduleName + ': ' + selector + '(' + $allModules.size() + ' elements)', |
||||
|
totalExecutionTime = 0 |
||||
|
; |
||||
|
if(selector) { |
||||
|
title += 'Performance (' + selector + ')'; |
||||
|
} |
||||
|
if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { |
||||
|
console.groupCollapsed(title); |
||||
|
if(console.table) { |
||||
|
$.each(performance, function(index, data) { |
||||
|
totalExecutionTime += data['Execution Time']; |
||||
|
}); |
||||
|
console.table(performance); |
||||
|
} |
||||
|
else { |
||||
|
$.each(performance, function(index, data) { |
||||
|
totalExecutionTime += data['Execution Time']; |
||||
|
}); |
||||
|
} |
||||
|
console.log('Total Execution Time:', totalExecutionTime +'ms'); |
||||
|
console.groupEnd(); |
||||
|
performance = []; |
||||
|
time = false; |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
invoke: function(query, passedArguments, context) { |
||||
|
var |
||||
|
maxDepth, |
||||
|
found |
||||
|
; |
||||
|
passedArguments = passedArguments || queryArguments; |
||||
|
context = element || context; |
||||
|
if(typeof query == 'string' && instance !== undefined) { |
||||
|
query = query.split('.'); |
||||
|
maxDepth = query.length - 1; |
||||
|
$.each(query, function(depth, value) { |
||||
|
if( $.isPlainObject( instance[value] ) && (depth != maxDepth) ) { |
||||
|
instance = instance[value]; |
||||
|
return true; |
||||
|
} |
||||
|
else if( instance[value] !== undefined ) { |
||||
|
found = instance[value]; |
||||
|
return true; |
||||
|
} |
||||
|
module.error(errors.method); |
||||
|
return false; |
||||
|
}); |
||||
|
} |
||||
|
if ( $.isFunction( found ) ) { |
||||
|
module.verbose('Executing invoked function', found); |
||||
|
return found.apply(context, passedArguments); |
||||
|
} |
||||
|
return found || false; |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
if(methodInvoked) { |
||||
|
if(instance === undefined) { |
||||
|
module.initialize(); |
||||
|
} |
||||
|
invokedResponse = module.invoke(query); |
||||
|
} |
||||
|
else { |
||||
|
if(instance !== undefined) { |
||||
|
module.destroy(); |
||||
|
} |
||||
|
module.initialize(); |
||||
|
} |
||||
|
}) |
||||
|
; |
||||
|
return (invokedResponse) |
||||
|
? invokedResponse |
||||
|
: this |
||||
|
; |
||||
|
}; |
||||
|
|
||||
|
$.fn.form.settings = { |
||||
|
|
||||
|
// module info
|
||||
|
moduleName : 'Validate Form Module', |
||||
|
debug : true, |
||||
|
verbose : false, |
||||
|
namespace : 'validate', |
||||
|
|
||||
|
animateSpeed : 150, |
||||
|
inlineError : false, |
||||
|
|
||||
|
on: 'submit', |
||||
|
|
||||
|
onValid : function() {}, |
||||
|
onInvalid : function() {}, |
||||
|
onSuccess : function() { return true; }, |
||||
|
onFailure : function() { return false; }, |
||||
|
|
||||
|
metadata : { |
||||
|
validate: 'validate' |
||||
|
}, |
||||
|
|
||||
|
// errors
|
||||
|
errors: { |
||||
|
method : 'The method you called is not defined.', |
||||
|
noFields : 'No validation object specified.' |
||||
|
}, |
||||
|
|
||||
|
|
||||
|
selector : { |
||||
|
group : '.field', |
||||
|
prompt : '.prompt', |
||||
|
field : 'input, textarea, select' |
||||
|
}, |
||||
|
|
||||
|
className : { |
||||
|
error : 'error', |
||||
|
prompt : 'prompt' |
||||
|
}, |
||||
|
|
||||
|
defaults: { |
||||
|
firstName: { |
||||
|
identifier : 'first-name', |
||||
|
rules: [ |
||||
|
{ |
||||
|
type : 'empty', |
||||
|
prompt : 'Please enter your first name' |
||||
|
} |
||||
|
] |
||||
|
}, |
||||
|
lastName: { |
||||
|
identifier : 'last-name', |
||||
|
rules: [ |
||||
|
{ |
||||
|
type : 'empty', |
||||
|
prompt : 'Please enter your last name' |
||||
|
} |
||||
|
] |
||||
|
}, |
||||
|
username: { |
||||
|
identifier : 'username', |
||||
|
rules: [ |
||||
|
{ |
||||
|
type : 'email', |
||||
|
prompt : 'Please enter a username' |
||||
|
} |
||||
|
] |
||||
|
}, |
||||
|
email: { |
||||
|
identifier : 'email', |
||||
|
rules: [ |
||||
|
{ |
||||
|
type : 'empty', |
||||
|
prompt : 'Please enter your email' |
||||
|
}, |
||||
|
{ |
||||
|
type : 'email', |
||||
|
prompt : 'Please enter a valid email' |
||||
|
} |
||||
|
] |
||||
|
}, |
||||
|
password: { |
||||
|
identifier : 'password', |
||||
|
rules: [ |
||||
|
{ |
||||
|
type : 'empty', |
||||
|
prompt : 'Please enter a password' |
||||
|
}, |
||||
|
{ |
||||
|
type : 'length[6]', |
||||
|
prompt : 'Your password must be at least 6 characters' |
||||
|
} |
||||
|
] |
||||
|
}, |
||||
|
passwordConfirm: { |
||||
|
identifier : 'password-confirm', |
||||
|
rules: [ |
||||
|
{ |
||||
|
type : 'empty', |
||||
|
prompt : 'Please confirm your password' |
||||
|
}, |
||||
|
{ |
||||
|
identifier : 'password-confirm', |
||||
|
type : 'match[password]', |
||||
|
prompt : 'Please verify password matches' |
||||
|
} |
||||
|
] |
||||
|
}, |
||||
|
terms: { |
||||
|
identifier : 'terms', |
||||
|
rules: [ |
||||
|
{ |
||||
|
type : 'checked', |
||||
|
prompt : 'You must agree to the terms and conditions' |
||||
|
} |
||||
|
] |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
rules: { |
||||
|
empty: function(value) { |
||||
|
return !(value === undefined || '' === value); |
||||
|
}, |
||||
|
email: function(value){ |
||||
|
var |
||||
|
emailRegExp = new RegExp("[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?") |
||||
|
; |
||||
|
return emailRegExp.test(value); |
||||
|
}, |
||||
|
length: function(value, requiredLength) { |
||||
|
return (value !== undefined) |
||||
|
? (value.length >= requiredLength) |
||||
|
: false |
||||
|
; |
||||
|
}, |
||||
|
not: function(value, notValue) { |
||||
|
return (value != notValue); |
||||
|
}, |
||||
|
maxLength: function(value, maxLength) { |
||||
|
return (value !== undefined) |
||||
|
? (value.length <= maxLength) |
||||
|
: false |
||||
|
; |
||||
|
}, |
||||
|
match: function(value, matchingField) { |
||||
|
// use either id or name of field
|
||||
|
var |
||||
|
$form = $(this), |
||||
|
matchingValue |
||||
|
; |
||||
|
if($form.find('#' + matchingField).size() > 0) { |
||||
|
matchingValue = $form.find('#' + matchingField).val(); |
||||
|
} |
||||
|
else if($form.find('[name=' + matchingField +']').size() > 0) { |
||||
|
matchingValue = $form.find('[name=' + matchingField + ']').val(); |
||||
|
} |
||||
|
else if( $form.find('[data-validate="'+ matchingField +'"]').size() > 0 ) { |
||||
|
matchingValue = $form.find('[data-validate="'+ matchingField +'"]').val(); |
||||
|
} |
||||
|
return (matchingValue !== undefined) |
||||
|
? ( value.toString() == matchingValue.toString() ) |
||||
|
: false |
||||
|
; |
||||
|
}, |
||||
|
url: function(value) { |
||||
|
var |
||||
|
urlRegExp = /(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/ |
||||
|
; |
||||
|
return urlRegExp.test(value); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
}; |
||||
|
|
||||
|
})( jQuery, window , document ); |
@ -0,0 +1,29 @@ |
|||||
|
semantic.validateForm = {}; |
||||
|
|
||||
|
// ready event
|
||||
|
semantic.validateForm.ready = function() { |
||||
|
|
||||
|
// selector cache
|
||||
|
var |
||||
|
$checkbox = $('.ui.checkbox'), |
||||
|
// alias
|
||||
|
handler |
||||
|
; |
||||
|
|
||||
|
// event handlers
|
||||
|
handler = { |
||||
|
|
||||
|
}; |
||||
|
|
||||
|
$checkbox |
||||
|
.checkbox() |
||||
|
; |
||||
|
|
||||
|
|
||||
|
}; |
||||
|
|
||||
|
|
||||
|
// attach ready event
|
||||
|
$(document) |
||||
|
.ready(semantic.validateForm.ready) |
||||
|
; |
@ -0,0 +1,56 @@ |
|||||
|
semantic.validateForm = {}; |
||||
|
|
||||
|
// ready event
|
||||
|
semantic.validateForm.ready = function() { |
||||
|
|
||||
|
// selector cache
|
||||
|
var |
||||
|
$dogForm = $('.dog.example .ui.form'), |
||||
|
$form = $('.ui.form').not($dogForm), |
||||
|
$checkbox = $('.ui.checkbox'), |
||||
|
// alias
|
||||
|
handler |
||||
|
; |
||||
|
|
||||
|
// event handlers
|
||||
|
handler = { |
||||
|
|
||||
|
}; |
||||
|
|
||||
|
$checkbox |
||||
|
.checkbox() |
||||
|
; |
||||
|
|
||||
|
$dogForm |
||||
|
.form({ |
||||
|
dog: { |
||||
|
identifier: 'dog', |
||||
|
rules: [ |
||||
|
{ |
||||
|
type: 'empty', |
||||
|
prompt: 'You must have a dog to add' |
||||
|
}, |
||||
|
{ |
||||
|
type: 'is[fluffy dog]', |
||||
|
prompt: 'I only want you to add fluffy dogs!' |
||||
|
}, |
||||
|
{ |
||||
|
type: 'not[mean]', |
||||
|
prompt: 'Why would you add a mean dog to the list?' |
||||
|
} |
||||
|
] |
||||
|
} |
||||
|
}) |
||||
|
; |
||||
|
|
||||
|
$form |
||||
|
.form() |
||||
|
; |
||||
|
|
||||
|
}; |
||||
|
|
||||
|
|
||||
|
// attach ready event
|
||||
|
$(document) |
||||
|
.ready(semantic.validateForm.ready) |
||||
|
; |
Write
Preview
Loading…
Cancel
Save