Skip to content

Instantly share code, notes, and snippets.

@jedfoster
Created October 8, 2013 20:11
Show Gist options
  • Save jedfoster/6890830 to your computer and use it in GitHub Desktop.
Save jedfoster/6890830 to your computer and use it in GitHub Desktop.
/**
* ValidatedFields
* -------------------
*
*
*/
function ValidatedFields(errorCallback, successCallback) {
// var ValidatedFields = function(errorCallback, successCallback) {
this.errorCallback = errorCallback || function() {};
this.successCallback = successCallback || function() {};
/**
* Event handler called when a form field loses focus (onblur).
*/
this.validate = function(event) {
var input = event.element(); // form field
return this.validateInput(input, this.successCallback);
};
this.validateInput = function(input, callback) {
var errors = this.getErrorMessages(input); // error messages in data-error attrs
var valid = true;
var validators = new Array;
validators = $w($(input).readAttribute('data-validates'));
if (!validators) {
valid = false;
}
if($(input).hasAttribute('required')) {
validators.push('required');
}
if($(input).readAttribute('type') === 'email') {
validators.push('email');
}
if($(input).hasAttribute('pattern')) {
validators.push('format');
}
for (var i = 0; i < validators.length; i++) {
var v = validators[i];
if(v.match(/\:/)) {
v = v.split(':');
var arg = v[1];
// generate validator method name
var validator = 'validate' + v[0].capitalize();
valid = valid && this[validator]($(input), errors, arg);
}
else {
// generate validator method name
var validator = 'validate' + v.capitalize();
valid = valid && this[validator]($(input), errors);
}
}
// alert(valid);
if (valid) {
if(callback)
this.successCallback($(input));
return true;
}
else {
return false;
}
};
this.validateFormSubmission = function(event) {
var form = event.element();
var self = this;
var inputs = form.getElements();
var validForm = true;
for (var i = 0; i < inputs.length; i++) {
if(!this.validateInput(inputs[i]))
validForm = false;
}
if(!validForm)
event.stop();
return;
};
/**
* Finds all attributes of element that begin with 'data-error-'
* and extracts them to an array.
*/
this.getErrorMessages = function(element) {
var errors = [];
for (var i = 0; i < element.attributes.length; i++) {
var attr = element.attributes[i];
var match = attr.nodeName.match(/^data-error-(.*)$/);
if (match) {
errors[match[1]] = attr.nodeValue;
}
}
return errors;
};
this.validateRequired = function(element, errors) {
var value = $F(element).strip();
if (value === "") {
this.errorCallback(element, errors['required']);
return false;
}
return true;
};
this.validateFormat = function(element, errors) {
var value = $F(element).strip();
var allowBlank = element.hasAttribute('data-allow-blank');
if (value === "" && allowBlank) {
return true;
}
var p = element.readAttribute('pattern');
// it's also possible to do "re = eval(p)", but might be dangerous
var re = new RegExp(p.slice(p.indexOf('/')+1, p.lastIndexOf('/')), p.slice(p.lastIndexOf('/')+1));
var res = re.test(value);
if (!res) {
this.errorCallback(element, errors['format']);
}
return res;
};
this.validateLength = function(element, errors) {
var value = $F(element).strip();
var min = parseInt(element.readAttribute('min')); // the browser will take care of maxlength
var allowBlank = element.hasAttribute('data-allow-blank');
if (value === "" && allowBlank) {
return true;
}
if (value.length < min) {
var msgKey = 'too-short' in errors ? 'too-short' : 'invalid-length';
this.errorCallback(element, errors[msgKey]);
return false;
}
return true;
};
this.validateEmail = function(element, errors) {
var value = $F(element).strip();
var allowBlank = element.hasAttribute('data-allow-blank');
if (value === "" && allowBlank) {
return true;
}
var res = /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i.test(value);
if (!res) {
this.errorCallback(element, errors['email']);
}
return res;
};
this.validateMatches = function(element, errors, matchField) {
var value = $F(element).strip();
// var matchField = element.readAttribute('data-validate-matches');
if ($F(element) !== $F(matchField)) {
this.errorCallback(element, errors["matches"]);
return false;
}
return true;
};
// --------------------------------------------------------
// set up events for all elements with the 'validated' class
$$('*[required],input[type="email"],*[pattern],*[data-validates]').invoke('observe', 'blur', this.validate.bind(this));
$$('form').invoke('observe', 'submit', this.validateFormSubmission.bind(this));
};
document.observe('dom:loaded', function() {
// var valid = new ValidatedFields(
new ValidatedFields(
// function called when validation fails
function(element, errorMsg) {
element.setStyle({'border': '1px red solid'});
element.next('span.error').update(errorMsg); // show error message
},
// function called when validation succeeds
function(element) {
element.setStyle({'border': '1px green solid'});
element.next('span.error').update(''); // clear error message
}
);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment