Created
May 22, 2010 07:54
-
-
Save drewlesueur/409898 to your computer and use it in GitHub Desktop.
Readable Validator
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!doctype> | |
<html> | |
<head> | |
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script> | |
<script src="jquery.readable-validator.js"></script> | |
<script> | |
$(document).ready(function(){ | |
$('form').readable_validator({ | |
labels: { | |
"Name" : "name", | |
"Phone" : "phone", | |
"Twitter" : "twitter" | |
}, | |
ruleSelector: "#rules", | |
outputSelector: "#errors" | |
}).css('font-family', 'courier'); | |
}) | |
</script> | |
</head> | |
<body> | |
<div id="errors"></div> | |
<form> | |
name<input type="text" id="name" name="name"> | |
<br> | |
phone<input type="text" id="phone" name="phone"> | |
<br> | |
twitter<input type="text" id="twitter" name="twitter"> | |
<br> | |
Like Programming? <input type="radio" name="like" id="like_yes" value="1"><input type="radio" name="like" id="like_no" value="0"> | |
<br> | |
<input type="submit" value="submit"> | |
</form> | |
<textarea id="rules" style="display:none;"> | |
"Name" is "Drew" | |
//"Name" is required | |
//or | |
//"Name" must be filled in | |
If "Twitter" is "drewlesueur" then say "drew, sorry you can't register" | |
"Phone" must be a date if "Twitter" is "kylelesueur" | |
//If "Twitter" is filled in then "Name" must be "hello" //not working yet | |
If "Twitter" is filled in then say "twitter is filled in" | |
If "Phone" is empty then "Twitter" must be filled in | |
</textarea> | |
</body> | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function($) { | |
function tokenize(line) { | |
line = line.split(""); | |
i = 0; | |
var state = "out"; | |
var cur_token = [] | |
var tokens = []; | |
var last_chr = ""; | |
while (i < line.length) { | |
chr = line[i]; | |
if (chr == " " && state == "out") { | |
tokens.push(cur_token.join("")) | |
cur_token = [] | |
} else if (chr == '"' && state == "out") { | |
state = "in"; | |
cur_token.push("'") | |
} else if (chr == '"' && state == "in" && last_chr != "\\") { | |
state = "out"; | |
} else if (chr.match(/:/) && state == "out") { | |
tokens.push(cur_token.join("")) | |
tokens.push(chr) | |
cur_token = [] | |
} else { | |
cur_token.push(chr) | |
} | |
last_chr = chr; | |
i++ | |
} | |
if (cur_token.length > 0) { | |
tokens.push(cur_token.join("")) | |
} | |
return tokens | |
} | |
function array_split(splitter, arr) { | |
var ret = [] | |
var cur = [] | |
var word; | |
for (var i in arr) { | |
word = arr[i]; | |
if (word == splitter) { | |
if (cur.length > 0) { | |
ret.push(cur) | |
} | |
cur = [] | |
} else { | |
cur.push(word) | |
} | |
} | |
if (cur.length > 0) { | |
ret.push(cur) | |
} | |
return ret; | |
} | |
//counting keys in an object | |
function count(foo) { | |
var count = 0; | |
for (var k in foo) { | |
if (foo.hasOwnProperty(k) && k != "toJSON") { | |
++count; | |
} | |
} | |
return count; | |
} | |
function _s(val, start, end) { | |
var need_to_join = false; | |
var ret = [] | |
if (typeof val == "string") { | |
val = val.split("") | |
need_to_join = true; | |
} | |
if (start >= 0) { | |
} else { | |
start = val.length + start | |
} | |
if (end == null) { | |
ret = val.slice(start) | |
} else { | |
if (end < 0) { | |
end = val.length + end; | |
} else { | |
end = end + start | |
} | |
ret = val.slice(start, end) | |
} | |
if (need_to_join) { | |
return ret.join("") | |
} else { | |
return ret; | |
} | |
} | |
function required(value, label, field) { | |
if (value != "") { | |
return true; | |
} else { | |
var ret = {} | |
ret[field] = label + " is required"; | |
return ret; | |
} | |
} | |
var validators = { | |
"required" : required, | |
"filled_in" : required, | |
a_date: function(x, label, field) { | |
if (x.match(/[\d]{2}\/[\d]{2}\/[\d]{4}/)) { | |
return true; | |
} else { | |
var ret = {} | |
ret[field] = label + " must be in the format mm/dd/yyyy"; | |
return ret; | |
} | |
} | |
} | |
$.fn.readable_validator = function(settings) { | |
var config = { | |
"alternateValues" : {}, | |
"lables" : {}, | |
"validators" : validators, | |
"ruleSelector" : "", | |
"outputSelector" : "" | |
}; | |
if (settings) $.extend(true, config, settings); //deep extend | |
this.each(function() { | |
$(this).submit(function(e){ | |
var raw = $(this).serializeArray() | |
var fields = {} | |
for (var i in raw) { | |
fields[raw[i]['name']] = raw[i]['value'] | |
} | |
var label_values = config.labels | |
var alter_values = config.alternateValues | |
var validators = config.validators | |
var rules = $(config.ruleSelector).html().split("\n"); | |
var rule; | |
var errors = {}; | |
var error_i = 0; | |
function validate(rule) { | |
rule = $.trim(rule); | |
if (_s(rule,-1) == ".") { | |
rule = _s(rule,0,-1); | |
} | |
rule = tokenize(rule) | |
function handle_expression(expr) { | |
var field = expr[0] | |
if (field == "say") { | |
error_i = error_i + 1; | |
var ret = {} | |
ret[error_i] = _s(expr[1],1) | |
return ret; | |
} | |
var operation = _s(expr,1,1) | |
var next_one = 2; | |
if (operation == "must") { | |
next_one = 3 | |
operation = operation + " " + _s(expr,2,1); | |
} | |
var value = _s(expr, next_one).join(" "); | |
label = _s(field,1) | |
field = label_values[label]; | |
if (_s(value,0,1) == "'") { | |
operation = operation + " literal"; | |
value = _s(value, 1); | |
if (field in alter_values) { | |
value = alter_values[field](value); | |
} | |
} | |
if (operation == "must be") { | |
operation = "is"; | |
} | |
real_value = fields[field]; | |
if (operation == "is literal") { | |
console.log(value + "_", real_value + "_", operation + "-") | |
var ret = real_value == value; | |
return ret | |
} else if (operation == "isn't literal") { | |
var ret = real_value != value; | |
return ret; | |
} else if (operation == "is") { | |
value = value.replace(/ /g,"_"); | |
if (value in validators) { | |
return validators[value](real_value, label, field); | |
} else { | |
return false; | |
} | |
} else if (operation == "isn't") { | |
value = value.replace(/ /g,"_"); | |
if (value in validators) { | |
return validators[value](real_value, label, field); | |
} else { | |
return false; | |
} | |
} | |
} | |
function handle_if() { | |
rule = rule.slice(1) | |
rule = array_split("then", rule); | |
var left = rule[0]; | |
var right = rule[1]; | |
left = array_split("and", left); | |
right = array_split("and", right); | |
for (var i in left) { | |
var ret = true; | |
var expr = left[i] | |
if (expr == "true") { | |
break; | |
} | |
var handled_expression = handle_expression(expr); | |
if (handled_expression !== true) { | |
handled_expression = false; | |
} | |
ret = ret && handled_expression | |
if (ret == false) { | |
break; | |
} | |
} | |
if (ret == true) { | |
for (var i in right) { | |
var expr = right[i]; | |
var ret = handle_expression(expr); | |
if (ret != true) { | |
for (var i in ret) { | |
errors[i] = ret[i] | |
} | |
} | |
} | |
} else { | |
//alert('good') | |
} | |
} | |
if (rule[0] == "If") { | |
handle_if(); | |
} else { | |
var first = rule[0]; | |
if (!first) { | |
return; | |
} | |
if (_s(first,0,2) == "//") { | |
return | |
} | |
rule = array_split("if", rule) | |
if (rule.length == 1) { | |
rule = rule[0]; | |
rule.splice(0,0, "if", "true", "then"); | |
handle_if(); | |
} else { // "Packet Sent Date" is required if "something" is a date | |
new_rule = ["If"] | |
for (var i in rule[1]) { | |
new_rule.push(rule[1][i]) | |
} | |
new_rule.push('then') | |
for (var i in rule[0]) { | |
new_rule.push(rule[0][i]) | |
} | |
rule = new_rule; | |
handle_if(); | |
} | |
} | |
} | |
for (var i in rules) { | |
rule = rules[i] | |
validate(rule) | |
} | |
if (count(errors) > 0) { | |
$(config.outputSelector).empty() | |
for (var i in errors) { | |
if (i == "toJSON") { | |
continue; | |
} | |
$(config.outputSelector).append("<di"+"v>"+errors[i]+"<"+"/d"+"iv>") | |
window.scroll(0,0) | |
} | |
e.preventDefault(); | |
} else { | |
} | |
}) | |
}); | |
return this; | |
}; | |
})(jQuery); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment