Created
February 8, 2012 14:57
-
-
Save wess/1770234 to your computer and use it in GitHub Desktop.
Django like form generation and validation for client side (in CoffeeScript)
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
# | |
# forms.coffee | |
# | |
# Created by Wess Cope on 2012-02-07. | |
# | |
window.document.getValuesOfFormWithId = (id)-> | |
tags = ['input', 'select', 'textarea'] | |
nonTypes = ['reset', 'submit', 'button'] | |
form = document.getElementById(id) | |
fields = [] | |
valueObject = {} | |
for element in form.elements | |
if tags.indexOf(element.tagName.toLowerCase()) >= 0 and nonTypes.indexOf(element.type.toLowerCase()) < 0 | |
valueObject[element.name] = element.value | |
return valueObject | |
class Validator | |
@errors : | |
int : "Must be numbers only" | |
alpha : "Must only be letters" | |
alphanum : "Only letters or numbers" | |
min : "Value is too low" | |
minlen : "Field is too short" | |
max : "Value is too high" | |
maxlen : "Field is too long" | |
email : "Not a valid email address" | |
compare : "%@ does not match %@" | |
required : "This field is required" | |
@email: (details, value) -> | |
return @regex(details, value) | |
@max: (details, value) -> | |
return (parseInt(value) <= details.max) | |
@maxlen: (details, value) -> | |
return (value.length <= details.maxlen) | |
@min: (details, value) -> | |
return (parseInt(value) >= details.min) | |
@minlen: (details, value) -> | |
return value.length >= details.minlen | |
@regex: (details, value) -> | |
return details.pattern.test(value) | |
class Form | |
html : '' | |
fields : [] | |
errors : {} | |
constructor: (formId, fields)-> | |
throw new Error("Form ID is required") unless formId | |
@formId = formId.replace("#", "") | |
for key, val of fields | |
val.name = key | |
val.id = val.id.replace(/\(null\)/ig, key) | |
val.tag = val.tag.replace(/\(null\)/ig, key) | |
val.label = val.label.replace(/\(null\)/ig, key) | |
console.log(val) | |
@fields.push(val) | |
@fields = @fields.reverse() | |
buildWithTemplate: (tpl="<p>{{label}} : {{field}}</p>") -> | |
template = [] | |
for field in @fields | |
template.push(tpl.replace("{{label}}", field.label).replace("{{field}}", field.tag)) | |
return template.join("\n") | |
isValid: -> | |
error = no | |
fieldValues = document.getValuesOfFormWithId(@formId) | |
for field in @fields | |
val = fieldValues[field.name] | |
if field.required and val.length == 0 | |
error = yes | |
field.errors.push(Validator.errors.required) | |
else if field.validator and not Validator[field.validator](field, val) | |
error = yes | |
field.errors.push(Validator.errors[field.validator]) | |
if error | |
@errors[field.id] = field.errors | |
return !error | |
class Fields | |
@inputFieldTemplate = "<input %@>" | |
@__input: (options={})-> | |
options = options or {} | |
options.name = options.name or "(null)" | |
attributes = [] | |
details = [] | |
label = "" | |
validator = options.validator or "" | |
delete(options.validator) | |
pattern = options.pattern or null | |
delete(options.pattern) | |
required = if typeof options.required isnt 'undefined' then options.required else yes | |
delete(options.required) | |
options.value = options.value or "" | |
options.id = options.id or "id_%@".$$(options.name) | |
options.type = options.type or "text" | |
options.label = options.label or options.name | |
if options.labelTag | |
label = options.labelTag | |
delete(options.labelTag) | |
else | |
label = '<label for="%@">%@</label>'.$$(options.name, options.label) | |
delete(options.label) | |
if options.attributes | |
for key,val of options.attributes | |
attributes.push('%@="%@"'.$$(key, val)) | |
delete(options.attributes) | |
for key, val of options | |
if (key.toLowerCase() is "value" and val) or (key.toLowerCase() isnt "value") | |
details.push('%@="%@"'.$$(key, val)) | |
return { | |
label: label | |
tag: @inputFieldTemplate.$$((details.join(' ')) + (attributes.join(' '))) | |
name: options.name | |
id: options.id | |
required: required | |
type: options.type | |
validator: validator | |
pattern: pattern | |
errors: [] | |
} | |
@textField: (options={}) => | |
return @__input(options) | |
@emailField: (options={}) => | |
options.pattern = /^[a-zA-Z][\w\.-]*[a-zA-Z0-9]@[a-zA-Z0-9][\w\.-]*[a-zA-Z0-9]\.[a-zA-Z][a-zA-Z\.]*[a-zA-Z]$/ | |
options.type = 'text' | |
options.validator = 'email' | |
return @__input(options) | |
@passwordField: (options={}) => | |
options.type = 'password' | |
return @__input(options) | |
class forms | |
@Form : Form | |
@emailField : Fields.emailField | |
@passwordField : Fields.passwordField | |
@textField : Fields.textField | |
window.forms = forms |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment