Skip to content

Instantly share code, notes, and snippets.

@kerbyfc
Last active August 29, 2015 13:56
Show Gist options
  • Save kerbyfc/8957316 to your computer and use it in GitHub Desktop.
Save kerbyfc/8957316 to your computer and use it in GitHub Desktop.
class FormValidator
attrs:
state: 'validation'
url: 'validation-url'
root: 'root'
options:
msgCls: 'b-input__error-message'
wrapperCls: 'b-input'
types:
'error': 'b-input_error'
tpl: _.template """
<span class=\"<%= msgCls %>\"><%= msg %></span>
"""
filter_name: ""
submit_event: false
constructor: (@form, options = {}) ->
@allTypes = _.values(@types).join(' ')
@valid = null
@conventions = {}
@form.data('validator', @)
@options = _.clone @options
if _.isObject options
_.extend @options, options
@initialize @form.data()
@
initialize: (@data) ->
for opt, mapping of @attrs
@[opt] = @form.data(mapping)
if @url or @state is "on"
@delegateEvents()
delegateEvents: =>
@form.on 'submit', @submit
$('input, select, textarea', @form).each (i, el) =>
ctl = $(el)
if name = ctl.attr('name')
convention = @pickOutEntityName name
@conventions[convention] = name if convention
unless ctl.attr('novalidate')
eventName = ctl.data("validation-event") or "blur"
ctl.on eventName, (e) =>
@valid = null
@filter_name = $(e.target).attr "name"
@validate false
pickOutEntityName: (name) ->
@form.find('[name="' + name + '"]').data("validation-entity") or /\[([\w\.]+)\]/g.exec(name)?[1]
submit: (e) =>
@filter_name = ""
@validate true
return @valid
validate: (submit = false) =>
if url = @getUrl()
console.log(@serialize())
UI.helpers.jsonRequest(
url: url
type: "POST"
data: @serialize()
dataType: 'json'
async: !submit
).always (data, textStatus, jqXHR) =>
@resolve(data, submit)
getUrl: =>
if _.isString @url
@url
else if @state is "on"
@form.attr('action') + '/validate'
else
false
resolve: (data, submit = false) =>
@valid = data.valid
@showErrors data.errors or {}, submit
@form.triggerHandler("invalid", errors: @errors, submit: submit) unless @valid
template: (tplString) ->
if tplString
@tpl = _.template(tplString)
@tpl
hideErrors: ->
_.each @conventions, (v, k) =>
$input = $ "[name='#{v}']", @form
permanent = $input.data "validation-permanent"
@hideError $input
if permanent
@showError $input, permanent
showErrors: (@errors, submit = false) ->
_.each @conventions, (v, k) =>
$input = $ "[name='#{v}']", @form
proccess = ($input.length and !@filter_name) or (v is @filter_name and $input.val())
if proccess
permanent = $input.data "validation-permanent"
@hideError $input
if @errors[k]
@showError $input, @errors[k][0]
else if permanent
@showError $input, permanent
else
@hideError $input if v is @filter_name and !$input.val()
showError: (input, error) =>
input.after @tpl(_.extend @options, msg: error)
@highlight(input, 'error')
hideError: (input) =>
input.nextAll(".#{@options.msgCls}").remove()
@forgive(input)
highlight: (input, type) ->
if (wrapper = input.closest(".#{@options.wrapperCls}")) and wrapper.length
wrapper.addClass(@types[type])
forgive: (input, type = false) ->
if (wrapper = input.closest(".#{@options.wrapperCls}")) and wrapper.length
wrapper.removeClass(if type then @types[type] else @allTypes)
serialize: =>
data = @form.serializeArray()
json = {}
for pair in data
if key = @pickOutEntityName pair.name
json[ key ] = pair.value
if @root
(rooted = {})[@root] = json
return rooted
json
$.fn.validator = (actionOrOptions, params...) ->
el = if @is('form')
@
else
@find('form')
return false unless el.length
unless el.data 'validator'
opts = if _.isObject(actionOrOptions) then actionOrOptions else {}
el.data 'validator', (new FormValidator @, opts)
validator = el.data 'validator'
if _.isString(actionOrOptions)
validator[actionOrOptions] params...
validator
UI 'form',
selector: 'form[data-validation="on"]'
init: ->
@$el.validator()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment