Skip to content

Instantly share code, notes, and snippets.

@lokamaya
Created December 11, 2008 14:05
Show Gist options
  • Save lokamaya/34716 to your computer and use it in GitHub Desktop.
Save lokamaya/34716 to your computer and use it in GitHub Desktop.
inspectForm: unobtrusive form validation
/**================================================
* InspectForm version 1.0 (for Prototype version 1.6 and above)
* Created: 11 December 2008
* Created by: Zaenal - http://www.lokamaya.net
* ================================================
* Copyright (c) 2008 Zaenal - http://www.lokamaya.net
* Some rights reserved. This work is licensed under a Creative Commons Attribution-Noncommercial 3.0 Unported License.
* ================================================
* Demo: http://code.lokamaya.net/inpectform/
* Blog: http://blog.lokamaya.net
* ================================================
**/
var inspectForm = Class.create({
forms:null,
successElem: null,
formsButton: $A(),
error:false,
errorText:{},
hashElement: new Hash(),
inspectMethod: {},
initialize: function(forms, successElem) {
var that = this;
this.forms = $(forms);
if (successElem)
this.successElem = $(successElem);
if (this.successElem)
(this.successElem).hide();
this.forms.observe('submit', function(evt) {
that.inspect(evt);
});
this.resetObj = that.resetElement.bindAsEventListener(that);
this.inspectMethod = inspectMethod;
this.inspectMethod.field = {};
this.inspectMethod.fieldAlternate = [];
this.inspectMethod.trim = this.trim;
this.inspectMethod.empty = this.empty;
},
register: function(elem, param) {
var that = this;
var found = true;
if (!($(elem))) {
if (this.forms[elem]) {
if ($(this.forms[elem]).id) {
elem = $(this.forms[elem]).id;
} else if (this.forms[elem].name) {
$(this.forms[elem]).id = elem;
} else {
found = false;
}
}
if (!found) {
return alert('Element "'+elem+'" not found');
}
}
this.hashElement.set(elem,param);
$(elem).observe('change', that.resetObj);
},
registerMethod: function(method, callback) {
this.inspectMethod[method] = callback;
},
registerResetButton: function(elem) {
var that = this;
$(elem).observe('click', function(evt) {
that.error = false;
if (that.successElem) {
(that.successElem).update('');
(that.successElem).hide();
}
that.forms.reset();
that.errorCallbackResetAll();
Event.stop(evt);
});
},
inspect: function(evt) {
var that = this;
this.error = false;
this.errorCallbackResetAll();
this.hashElement.each(function(elem){
that.inspectElement(elem);
});
if (this.error) {
this.forms.submit = false;
Event.stop(evt);
return false;
} else {
this.submit();
Event.stop(evt);
return true;
}
},
inspectElement: function(elem) {
if (!($(elem.key).visible()) || $(elem.key).type=='hidden') return;
var that = this;
var valid = true;
var param = false;
var field = {}; field.id = elem.key; field.value = this.getValue(elem.key);
this.inspectMethod.field = field;
this.inspectMethod.errorText = null;
$H(elem.value).each(function(item){
this.inspectMethod.fieldAlternate = [];
if (valid) {
if (that.is_array(item.value)) param = item.value[0];
else param = item.value;
try {that.inspectMethod[item.key](param);}catch(e){alert(elem.key+': method "'+item.key+'" does not exist'); return;}
if (that.inspectMethod.errorText!==null) {
valid = false;
if (that.is_array(item.value) && item.value[1])
that.inspectMethod.errorText = item.value[1];
if (that.is_array(that.inspectMethod.fieldAlternate) && (that.inspectMethod.fieldAlternate).length > 0) {
$(elem.key).addClassName('dependElementTo'+this.inspectMethod.field.id);
$(elem.key).addClassName('dependElement');
that.errorCallback(elem.key, that.inspectMethod.errorText, (that.error == false));
$A(that.inspectMethod.fieldAlternate).each(function(alternate) {
$(alternate).stopObserving('change', that.resetObj);
$(alternate).observe('change', that.resetObj);
$(alternate).addClassName('dependElementTo'+that.inspectMethod.field.id);
$(alternate).addClassName('dependElement');
that.errorCallback(alternate, false);
});
} else {
that.errorCallback(elem.key, that.inspectMethod.errorText, false);
}
that.error = true;
throw $break;
}
}
});
},
successCallback: function(msg, error) {
if (this.successElem) {
(this.successElem).update(msg);
var that = this;
$A((this.successElem).select('[href="#back"]')).each(function(item) {
that.registerResetButton(item);
});
(this.successElem).show();
} else {
alert(msg);
}
if (!error) (this.forms).addClassName("successForm");
},
resetElement: function(event) {
var cleanup = Event.element(event);
if ($(cleanup).hasClassName('dependElement')) {
var that = this;
$(cleanup).readAttribute('class').scan("[a-zA-Z0-9\\-_]+", function(cls) {
if ((cls+'').startsWith('dependElementTo')) {
$A((that.forms).select('*.'+cls)).each(function(cleanup) {
if (cleanup.hasClassName(cls+'')) {
cleanup.removeClassName('dependElement');
cleanup.removeClassName(cls+'');
that.errorCallbackReset(cleanup);
}
});
return;
}
});
} else {
this.errorCallbackReset(cleanup);
}
},
errorCallback: function(elem, msg, focused) {
var that = this;
$(elem).addClassName('errorElement');
if (msg) $(elem).up().appendChild(new Element('label', {'for':'error-'+elem, 'class':'errorLabel'}).update(msg));
if (focused===true) $(elem).focus();
},
errorCallbackReset: function(elem) {
//alert($(elem).id);
$(elem).removeClassName('errorElement');
if ($(elem).up().down('label.errorLabel')) {
$(elem).up().down('label.errorLabel').remove();
}
},
errorCallbackResetAll: function() {
var that = this;
this.forms.getElements().each(function(elem) {
that.errorCallbackReset(elem);
});
(this.forms).removeClassName("successForm");
if (this.successElem) {
(this.successElem).update('');
(this.successElem).hide();
}
},
submit: function() {
var that = this;
(this.forms).request({
onSuccess: function(transport) {
var docRoot = null;
var fields = [];
var error = false;
try {docRoot = transport.responseXML.documentElement;} catch(e){alert(e); return;};
try {fields = (docRoot.getElementsByTagName('messageError')[0]).getElementsByTagName('fields');} catch(e){fields=[]}
$A(fields).each(function(field, i) {
that.errorCallback(field.getAttribute('id'), that.getNodeValue(field), (i==0));
error = true;
});
if (docRoot.getElementsByTagName('message')) {
that.successCallback(that.getNodeValue(docRoot.getElementsByTagName('message')[0]), error);
}
},
onFailure: function() {
alert('Server down, please try to submit this form later!');
}
});
},
getNodeValue: function (oNode) {
if (oNode.nodeValue)
return oNode.nodeValue;
else if (oNode.firstChild)
return this.getNodeValue(oNode.firstChild);
else
return '';
},
is_array: function(mixed_var) {
if (!mixed_var || mixed_var === null || mixed_var === false || mixed_var === true) return false;
return (mixed_var.constructor.toString().indexOf("Array") != -1 || mixed_var instanceof Array || mixed_var instanceof Object);
},
getValue: function(elem) {
return $(elem).getValue();
},
trim: function(str) {
return str.strip();
},
empty: function() {
return ((this.trim(this.field.value)).length == 0);
}
});
var inspectMethod = {
field: {id:null,value:''},
fieldAlternate: [],
errorText: null,
required: function(param){
if (this.empty()) {
this.errorText = 'Required field';
}
return (this.errorText == null);
},
confirm: function(param) {
if(this.field.value != Form.Element.getValue(param)) {
this.errorText = 'Confirm value not macth';
this.fieldAlternate = [param];
}
return (this.errorText == null);
},
alternate: function(param) {
if((this.field.value).length==0) {
var found = false;
$A(param.split('|')).each(function(item) {
if (($(item).getValue()).length > 0) {
if (!found) found = true;
}
});
if (!found) {
this.errorText = 'One of these fields must not empty';
this.fieldAlternate = param.split('|');
}
};
return (this.errorText == null);
},
radio: function(param) {
if($(this.field.id).checked==false) {
var found = false;
$A(param.split('|')).each(function(item) {
if ($(item).checked==true) {
if (!found) found = true;
}
});
if (!found) {
this.errorText = 'One of these fields must be checked';
this.fieldAlternate = param.split('|');
}
};
return (this.errorText == null);
},
checkbox: function(param) {
if ($(this.field.id).checked==false) {
this.errorText = 'Must be checked';
}
return (this.errorText == null);
},
not: function(param) {
if (this.field.value==param) {
this.errorText = 'Value "'+param+'" is not allowed';
}
return (this.errorText == null);
},
maxlength: function(param) {
if (this.empty()) return;
if (parseInt(param) > 0 && this.field.value.length > parseInt(param)) {
this.errorText = 'Maximum ' + parseInt(param) + ' characters';
}
return (this.errorText == null);
},
minlength: function(param) {
if (this.empty() || (parseInt(param) > 0 && this.field.value.length < parseInt(param))){
this.errorText = 'Minimum ' + parseInt(param) + ' characters';
}
return (this.errorText == null);
},
decimal: function(param) {
if (this.empty()) return;
if((this.field.value).search("[^0-9\.,]") > 0 || (this.field.value).search("^(\.|,)")) {
this.errorText = 'Only decimal allowed';
}
return (this.errorText == null);
},
numeric: function(param) {
if (this.empty()) return;
if(!this.strsrc("[^0-9]")) {
this.errorText = 'Only integer number allowed';
}
return (this.errorText == null);
},
alphabet: function(param) {
if (this.empty()) return;
if(!this.strsrc("[^A-Za-z]")) {
this.errorText = 'Only alphabet characters are allowed';
}
return (this.errorText == null);
},
alphanumeric: function(param) {
if (this.empty()) return;
if(!this.strsrc("[^A-Za-z0-9]")) {
this.errorText = 'Only alphabet and number characters are allowed';
}
return (this.errorText == null);
},
lessthan: function(param) {
if (this.empty()) return;
if (isNaN(this.field.value)){
this.errorText = 'Only number allowed';
} else if (parseFloat(this.field.value) > parseFloat(param)){
this.errorText = 'Value greater than ' + parseFloat(param);
}
return (this.errorText == null);
},
greaterthan: function(param) {
if (this.empty()) return;
if (isNaN(this.field.value)){
this.errorText = 'Only number allowed';
} else if (parseFloat(this.field.value) < parseFloat(param)) {
this.errorText = 'Value less than ' + parseFloat(param);
}
return (this.errorText == null);
},
email: function(param) {
if (this.empty()) return;
if(!(new RegExp("^([\\w-]+(?:\\.[\\w-]+)*)@((?:[\\w-]+\\.)*\\w[\\w-]{0,66})\\.([a-z]{2,6}(?:\\.[a-z]{2})?)$", "i")).test(this.trim(this.field.value))) {
this.errorText = 'Not valid email address';
}
return (this.errorText == null);
},
website: function(param) {
if (this.empty()) return;
if(!(new RegExp("^(?:https?):\\/\\/(?:(?:[\\w]+:)?\\w+@)?(?:(?:(?:[\\w-]+\\.)*\\w[\\w-]{0,66}\\.(?:[a-z]{2,6})(?:\\.[a-z]{2})?)|(?:(?:25[0-5]\\.|2[0-4][0-9]\\.|1[0-9]{2}\\.|[0-9]{1,2}\\.)(?:(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[0-9]{1,2})\\.){2}(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[0-9]{1,2})))(?:\\:\\d{1,5})?(?:\\/(~[\\w-_.])?)?(?:(?:\\/[\\w-_]*)*)?$", "i")).test(this.trim(this.field.value))) {
this.errorText = 'Not valid website';
}
return (this.errorText == null);
},
url: function(param) {
if (this.empty()) return;
if(!(new RegExp("^(?:https?):\\/\\/(?:(?:[\\w]+:)?\\w+@)?(?:(?:(?:[\\w-]+\\.)*\\w[\\w-]{0,66}\\.(?:[a-z]{2,6})(?:\\.[a-z]{2})?)|(?:(?:25[0-5]\\.|2[0-4][0-9]\\.|1[0-9]{2}\\.|[0-9]{1,2}\\.)(?:(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[0-9]{1,2})\\.){2}(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[0-9]{1,2})))(?:\\:\\d{1,5})?(?:\\/(~[\\w-_.])?)?(?:(?:\\/[\\w-_.#]*)*)?(\\?)?(?:(?:[\\w-_.#]+\\=[\\w-_.#]+&?)*)?$", "i")).test(this.trim(this.field.value))) {
this.errorText = 'Not valid url address';
}
return (this.errorText == null);
},
file: function(param) {
if (this.empty() || !param) return;
if (!(new RegExp("\.("+param+")$", "i")).test(this.field.value)) {
this.errorText = 'File extension not allowed';
}
return (this.errorText == null);
},
date: function(param) {
if (this.empty()) return;
param = param.toLowerCase();
var oRegex = ((((((param.replace(new RegExp('\\W+', "gi"), "##")).replace('dd', "(0[1-9]|1[0-9]|2[0-9]|3[0-1])")).replace('d', "([1-9]|1[0-9]|2[0-9]|3[0-1])")).replace('mm', "(0[1-9]|1[0-2])")).replace('m', "([1-9]|1[0-2])")).replace('yyyy', "([0-9]{4})")).replace('yy', "([0-9]{2})");
var oValue = (this.field.value).replace(new RegExp('\\W+', "gi"), "##");
if (!(new RegExp("^"+oRegex+"$")).match(oValue)) {
this.errorText = 'Invalid date format';
}
return (this.errorText == null);
},
regexp: function(param) {
if (this.empty()) return;
if(!(param).test(this.field.value)) {
this.errorText = 'Error regex';
}
return (this.errorText == null);
},
strsrc: function(param) {
if (this.empty()) return;
if((this.field.value).search(param) > 0) {
this.errorText = 'Error: characters found';
}
return (this.errorText == null);
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment