Skip to content

Instantly share code, notes, and snippets.

@wess
Created February 8, 2012 14:57
Show Gist options
  • Save wess/1770234 to your computer and use it in GitHub Desktop.
Save wess/1770234 to your computer and use it in GitHub Desktop.
Django like form generation and validation for client side (in CoffeeScript)
#
# 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