hoarder-js 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +1 -0
- data/Gemfile +9 -0
- data/Gemfile.lock +100 -0
- data/LICENSE +21 -0
- data/Manifest +42 -0
- data/README.rdoc +0 -0
- data/Rakefile +38 -0
- data/assets/scripts/coffee/hoarder/form/form.coffee +48 -0
- data/assets/scripts/coffee/hoarder/form/form_element.coffee +22 -0
- data/assets/scripts/coffee/hoarder/form_manager.coffee +32 -0
- data/assets/scripts/coffee/hoarder/submitter/form_submitter.coffee +29 -0
- data/assets/scripts/coffee/hoarder/submitter/submitters/polling_submitter.coffee +36 -0
- data/assets/scripts/coffee/hoarder/submitter/submitters/simple_submitter.coffee +30 -0
- data/assets/scripts/coffee/hoarder/validator/constraints/alpha_constraint.coffee +18 -0
- data/assets/scripts/coffee/hoarder/validator/constraints/alphanumeric_constraint.coffee +18 -0
- data/assets/scripts/coffee/hoarder/validator/constraints/credit_card_constraint.coffee +18 -0
- data/assets/scripts/coffee/hoarder/validator/constraints/email_constraint.coffee +18 -0
- data/assets/scripts/coffee/hoarder/validator/constraints/max_length_constraint.coffee +18 -0
- data/assets/scripts/coffee/hoarder/validator/constraints/min_length_constraint.coffee +18 -0
- data/assets/scripts/coffee/hoarder/validator/constraints/numeric_constraint.coffee +18 -0
- data/assets/scripts/coffee/hoarder/validator/constraints/phone_constraint.coffee +18 -0
- data/assets/scripts/coffee/hoarder/validator/constraints/required_constraint.coffee +18 -0
- data/assets/scripts/coffee/hoarder/validator/error/validation_error.coffee +9 -0
- data/assets/scripts/coffee/hoarder/validator/form_validator.coffee +53 -0
- data/assets/scripts/js/lib/jquery.js +5 -0
- data/bin/hoarder.js +1197 -0
- data/config/assets.rb +8 -0
- data/hoarder-js.gemspec +36 -0
- data/lib/hoarder.rb +1 -0
- data/lib/hoarder/symbols.rb +17 -0
- data/spec/jasmine.yml +44 -0
- data/spec/runner.html +75 -0
- data/spec/support/classes.coffee +0 -0
- data/spec/support/helpers.coffee +22 -0
- data/spec/support/mocks.coffee +42 -0
- data/spec/support/objects.coffee +0 -0
- data/spec/support/requirements.coffee +1 -0
- data/spec/tests/form_manager_spec.coffee +43 -0
- data/spec/tests/submitter/form_submitter_spec.coffee +47 -0
- data/spec/tests/submitter/submitters/polling_submitter_spec.coffee +60 -0
- data/spec/tests/submitter/submitters/simple_submitter_spec.coffee +19 -0
- data/spec/tests/validator/constraints_spec.coffee +74 -0
- data/spec/tests/validator/form_validator_spec.coffee +29 -0
- metadata +132 -0
data/CHANGELOG
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
v0.0.1 new library
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
GIT
|
2
|
+
remote: git://github.com/jpeace/keystone.git
|
3
|
+
revision: 3680c30328bf3b93af7c7f1b1bad685cbaec35dd
|
4
|
+
specs:
|
5
|
+
keystone (0.0.1)
|
6
|
+
closure-compiler
|
7
|
+
coffee-script
|
8
|
+
sass
|
9
|
+
sinatra
|
10
|
+
|
11
|
+
GIT
|
12
|
+
remote: git://github.com/tshelburne/cronus-js.git
|
13
|
+
revision: c2cb5da182efb6c3742518dabda93f48b5281126
|
14
|
+
specs:
|
15
|
+
cronus (0.0.1)
|
16
|
+
|
17
|
+
GEM
|
18
|
+
remote: http://rubygems.org/
|
19
|
+
specs:
|
20
|
+
allison (2.0.3)
|
21
|
+
childprocess (0.3.9)
|
22
|
+
ffi (~> 1.0, >= 1.0.11)
|
23
|
+
closure-compiler (1.1.8)
|
24
|
+
coffee-script (2.2.0)
|
25
|
+
coffee-script-source
|
26
|
+
execjs
|
27
|
+
coffee-script-source (1.6.2)
|
28
|
+
diff-lcs (1.2.4)
|
29
|
+
echoe (4.6.3)
|
30
|
+
allison (>= 2.0.3)
|
31
|
+
gemcutter (>= 0.7.0)
|
32
|
+
rake (>= 0.9.2)
|
33
|
+
rdoc (>= 3.6.1)
|
34
|
+
rubyforge (>= 2.0.4)
|
35
|
+
execjs (1.4.0)
|
36
|
+
multi_json (~> 1.0)
|
37
|
+
ffi (1.8.1)
|
38
|
+
gemcutter (0.7.1)
|
39
|
+
hike (1.2.2)
|
40
|
+
jasmine (1.3.2)
|
41
|
+
jasmine-core (~> 1.3.1)
|
42
|
+
rack (~> 1.0)
|
43
|
+
rspec (>= 1.3.1)
|
44
|
+
selenium-webdriver (>= 0.1.3)
|
45
|
+
jasmine-core (1.3.1)
|
46
|
+
jasmine-headless-webkit (0.8.4)
|
47
|
+
coffee-script
|
48
|
+
jasmine-core (~> 1.1)
|
49
|
+
multi_json
|
50
|
+
rainbow
|
51
|
+
sprockets (~> 2)
|
52
|
+
json (1.7.7)
|
53
|
+
json_pure (1.7.7)
|
54
|
+
multi_json (1.7.2)
|
55
|
+
rack (1.5.2)
|
56
|
+
rack-protection (1.5.0)
|
57
|
+
rack
|
58
|
+
rainbow (1.1.4)
|
59
|
+
rake (10.0.4)
|
60
|
+
rdoc (4.0.1)
|
61
|
+
json (~> 1.4)
|
62
|
+
rspec (2.13.0)
|
63
|
+
rspec-core (~> 2.13.0)
|
64
|
+
rspec-expectations (~> 2.13.0)
|
65
|
+
rspec-mocks (~> 2.13.0)
|
66
|
+
rspec-core (2.13.1)
|
67
|
+
rspec-expectations (2.13.0)
|
68
|
+
diff-lcs (>= 1.1.3, < 2.0)
|
69
|
+
rspec-mocks (2.13.1)
|
70
|
+
rubyforge (2.0.4)
|
71
|
+
json_pure (>= 1.1.7)
|
72
|
+
rubyzip (0.9.9)
|
73
|
+
sass (3.2.8)
|
74
|
+
selenium-webdriver (2.32.1)
|
75
|
+
childprocess (>= 0.2.5)
|
76
|
+
multi_json (~> 1.0)
|
77
|
+
rubyzip
|
78
|
+
websocket (~> 1.0.4)
|
79
|
+
sinatra (1.4.2)
|
80
|
+
rack (~> 1.5, >= 1.5.2)
|
81
|
+
rack-protection (~> 1.4)
|
82
|
+
tilt (~> 1.3, >= 1.3.4)
|
83
|
+
sprockets (2.9.3)
|
84
|
+
hike (~> 1.2)
|
85
|
+
multi_json (~> 1.0)
|
86
|
+
rack (~> 1.0)
|
87
|
+
tilt (~> 1.1, != 1.3.0)
|
88
|
+
tilt (1.3.7)
|
89
|
+
websocket (1.0.7)
|
90
|
+
|
91
|
+
PLATFORMS
|
92
|
+
ruby
|
93
|
+
|
94
|
+
DEPENDENCIES
|
95
|
+
cronus!
|
96
|
+
echoe
|
97
|
+
jasmine
|
98
|
+
jasmine-headless-webkit
|
99
|
+
keystone!
|
100
|
+
rake
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2013 Tim Shelburne
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/Manifest
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
CHANGELOG
|
2
|
+
Gemfile
|
3
|
+
Gemfile.lock
|
4
|
+
LICENSE
|
5
|
+
Manifest
|
6
|
+
README.rdoc
|
7
|
+
Rakefile
|
8
|
+
assets/scripts/coffee/hoarder/form/form.coffee
|
9
|
+
assets/scripts/coffee/hoarder/form/form_element.coffee
|
10
|
+
assets/scripts/coffee/hoarder/form_manager.coffee
|
11
|
+
assets/scripts/coffee/hoarder/submitter/form_submitter.coffee
|
12
|
+
assets/scripts/coffee/hoarder/submitter/submitters/polling_submitter.coffee
|
13
|
+
assets/scripts/coffee/hoarder/submitter/submitters/simple_submitter.coffee
|
14
|
+
assets/scripts/coffee/hoarder/validator/constraints/alpha_constraint.coffee
|
15
|
+
assets/scripts/coffee/hoarder/validator/constraints/alphanumeric_constraint.coffee
|
16
|
+
assets/scripts/coffee/hoarder/validator/constraints/credit_card_constraint.coffee
|
17
|
+
assets/scripts/coffee/hoarder/validator/constraints/email_constraint.coffee
|
18
|
+
assets/scripts/coffee/hoarder/validator/constraints/max_length_constraint.coffee
|
19
|
+
assets/scripts/coffee/hoarder/validator/constraints/min_length_constraint.coffee
|
20
|
+
assets/scripts/coffee/hoarder/validator/constraints/numeric_constraint.coffee
|
21
|
+
assets/scripts/coffee/hoarder/validator/constraints/phone_constraint.coffee
|
22
|
+
assets/scripts/coffee/hoarder/validator/constraints/required_constraint.coffee
|
23
|
+
assets/scripts/coffee/hoarder/validator/error/validation_error.coffee
|
24
|
+
assets/scripts/coffee/hoarder/validator/form_validator.coffee
|
25
|
+
assets/scripts/js/lib/jquery.js
|
26
|
+
bin/hoarder.js
|
27
|
+
config/assets.rb
|
28
|
+
lib/hoarder.rb
|
29
|
+
lib/hoarder/symbols.rb
|
30
|
+
spec/jasmine.yml
|
31
|
+
spec/runner.html
|
32
|
+
spec/support/classes.coffee
|
33
|
+
spec/support/helpers.coffee
|
34
|
+
spec/support/mocks.coffee
|
35
|
+
spec/support/objects.coffee
|
36
|
+
spec/support/requirements.coffee
|
37
|
+
spec/tests/form_manager_spec.coffee
|
38
|
+
spec/tests/submitter/form_submitter_spec.coffee
|
39
|
+
spec/tests/submitter/submitters/polling_submitter_spec.coffee
|
40
|
+
spec/tests/submitter/submitters/simple_submitter_spec.coffee
|
41
|
+
spec/tests/validator/constraints_spec.coffee
|
42
|
+
spec/tests/validator/form_validator_spec.coffee
|
data/README.rdoc
ADDED
File without changes
|
data/Rakefile
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
$: << File.expand_path("#{File.dirname(__FILE__)}/lib")
|
2
|
+
|
3
|
+
require 'hoarder'
|
4
|
+
require 'cronus'
|
5
|
+
|
6
|
+
require 'rake'
|
7
|
+
require 'jasmine-headless-webkit'
|
8
|
+
require 'keystone'
|
9
|
+
require 'echoe'
|
10
|
+
|
11
|
+
Echoe.new("hoarder-js") do |p|
|
12
|
+
p.author = "Tim Shelburne"
|
13
|
+
p.email = "shelburt02@gmail.com"
|
14
|
+
p.url = "https://github.com/tshelburne/hoarder-js"
|
15
|
+
|
16
|
+
p.ignore_pattern = FileList[".gitignore"]
|
17
|
+
p.development_dependencies = [ "jasmine", "jasmine-headless-webkit" ]
|
18
|
+
end
|
19
|
+
|
20
|
+
desc "Default"
|
21
|
+
task default: :'test:jasmine'
|
22
|
+
|
23
|
+
namespace :test do
|
24
|
+
|
25
|
+
desc "Run Jasmine tests"
|
26
|
+
Jasmine::Headless::Task.new(jasmine: :assets) do |t|
|
27
|
+
t.colors = true
|
28
|
+
t.keep_on_error = true
|
29
|
+
t.jasmine_config = './spec/jasmine.yml'
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
desc "Build assets"
|
35
|
+
Keystone::RakeTask.new :assets do |t|
|
36
|
+
t.config_file = "config/assets.rb"
|
37
|
+
t.output_path = 'bin'
|
38
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require "lib/jquery"
|
2
|
+
|
3
|
+
FormElement = require "hoarder/form/form_element"
|
4
|
+
|
5
|
+
#
|
6
|
+
# @author - Tim Shelburne <tim@musiconelive.com>
|
7
|
+
#
|
8
|
+
# wraps an HTML form for easier form management
|
9
|
+
#
|
10
|
+
class Form
|
11
|
+
constructor: (formId, @type = "simple")->
|
12
|
+
@form = $("##{formId}")
|
13
|
+
@form.submit (e)-> e.preventDefault()
|
14
|
+
@action = @form.attr("action")
|
15
|
+
@method = @form.attr("method")
|
16
|
+
@addedElements = []
|
17
|
+
|
18
|
+
elements: ->
|
19
|
+
elements = []
|
20
|
+
inputs = @form.find("input")
|
21
|
+
elements = elements.concat inputs.toArray() if inputs.length > 0
|
22
|
+
selects = @form.find("select")
|
23
|
+
elements = elements.concat selects.toArray() if selects.length > 0
|
24
|
+
textareas = @form.find("textarea")
|
25
|
+
elements = elements.concat textareas.toArray() if textareas.length > 0
|
26
|
+
|
27
|
+
formElements = []
|
28
|
+
for element in elements
|
29
|
+
validationRules = if element.getAttribute("data-validation")? then (rule.trim() for rule in element.getAttribute("data-validation").split(',')) else []
|
30
|
+
selector = "#{element.nodeName}[data-bind='#{element.getAttribute("data-bind")}']"
|
31
|
+
formElements.push new FormElement(element.name, element.value, selector, validationRules)
|
32
|
+
formElements
|
33
|
+
|
34
|
+
addElement: (name, value, isRemovable = true)->
|
35
|
+
@form.append "<input type='hidden' name='#{name}' value='#{value}'/>"
|
36
|
+
@addedElements.push $("input[name='#{name}']", @form) if isRemovable
|
37
|
+
|
38
|
+
addElements: (elements)-> @addElement(element.name, element.value) for element in elements
|
39
|
+
|
40
|
+
updateAddedElement: (name, value)-> @form.find("input[name='#{name}']").val(value)
|
41
|
+
|
42
|
+
clearAddedElements: ->
|
43
|
+
element.remove() for element in @addedElements
|
44
|
+
@addedElements = []
|
45
|
+
|
46
|
+
serialize: -> @form.serialize()
|
47
|
+
|
48
|
+
return Form
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require "lib/jquery"
|
2
|
+
|
3
|
+
#
|
4
|
+
# @author - Tim Shelburne <tim@musiconelive.com>
|
5
|
+
#
|
6
|
+
# represents a single element in a form
|
7
|
+
#
|
8
|
+
class FormElement
|
9
|
+
constructor: (@name, @value, @selector, @validationRules = [])->
|
10
|
+
|
11
|
+
addError: (error)->
|
12
|
+
$(@selector).closest("li").addClass("invalid")
|
13
|
+
$(@selector).closest("li").find("aside.tooltip").html(error.message)
|
14
|
+
$(@selector).focus -> $(this).closest("li").addClass("focused")
|
15
|
+
$(@selector).blur -> $(this).closest("li").removeClass("focused")
|
16
|
+
|
17
|
+
clearError: ->
|
18
|
+
$(@selector).closest("li").removeClass("invalid")
|
19
|
+
$(@selector).closest("li").find("aside.tooltip").html("")
|
20
|
+
$(@selector).unbind("focus").unbind("blur")
|
21
|
+
|
22
|
+
return FormElement
|
@@ -0,0 +1,32 @@
|
|
1
|
+
Signal = require "cronus/signal"
|
2
|
+
SignalRelay = require "cronus/signal_relay"
|
3
|
+
|
4
|
+
FormSubmitter = require 'hoarder/submitter/form_submitter'
|
5
|
+
FormValidator = require 'hoarder/validator/form_validator'
|
6
|
+
|
7
|
+
#
|
8
|
+
# @author - Tim Shelburne <tim@musiconelive.com>
|
9
|
+
#
|
10
|
+
# abstracts submitting and validating forms from the validator and submitter
|
11
|
+
#
|
12
|
+
class FormManager
|
13
|
+
constructor: (@formSubmitter, @formValidator)->
|
14
|
+
@validatedWithErrors = new Signal()
|
15
|
+
@submittedWithSuccess = new SignalRelay(@formSubmitter.submittedWithSuccess)
|
16
|
+
@submittedWithError = new SignalRelay(@formSubmitter.submittedWithError)
|
17
|
+
|
18
|
+
@default: (pollingUrl="")->
|
19
|
+
new @(FormSubmitter.default(pollingUrl), FormValidator.default())
|
20
|
+
|
21
|
+
validateForm: (form)->
|
22
|
+
@formValidator.validateForm(form)
|
23
|
+
|
24
|
+
submitForm: (form)->
|
25
|
+
errors = @validateForm(form)
|
26
|
+
|
27
|
+
if (errors.length > 0)
|
28
|
+
@validatedWithErrors.dispatch(errors)
|
29
|
+
else
|
30
|
+
@formSubmitter.submitForm(form)
|
31
|
+
|
32
|
+
return FormManager
|
@@ -0,0 +1,29 @@
|
|
1
|
+
MultiSignalRelay = require "cronus/multi_signal_relay"
|
2
|
+
|
3
|
+
SimpleSubmitter = require "hoarder/submitter/submitters/simple_submitter"
|
4
|
+
PollingSubmitter = require "hoarder/submitter/submitters/polling_submitter"
|
5
|
+
|
6
|
+
#
|
7
|
+
# @author - Tim Shelburne <tim@musiconelive.com>
|
8
|
+
#
|
9
|
+
# a class to handle submitting forms
|
10
|
+
#
|
11
|
+
class FormSubmitter
|
12
|
+
constructor: (@submitters)->
|
13
|
+
successSignals = []
|
14
|
+
errorSignals = []
|
15
|
+
for submitter in @submitters
|
16
|
+
successSignals.push submitter.submittedWithSuccess
|
17
|
+
errorSignals.push submitter.submittedWithError
|
18
|
+
|
19
|
+
@submittedWithSuccess = new MultiSignalRelay(successSignals)
|
20
|
+
@submittedWithError = new MultiSignalRelay(errorSignals)
|
21
|
+
|
22
|
+
@default: (pollingUrl)->
|
23
|
+
new @([ new SimpleSubmitter(), new PollingSubmitter(pollingUrl, 1000)])
|
24
|
+
|
25
|
+
submitForm: (form)->
|
26
|
+
for submitter in @submitters
|
27
|
+
submitter.submitForm(form) if submitter.canSubmit(form)
|
28
|
+
|
29
|
+
return FormSubmitter
|
@@ -0,0 +1,36 @@
|
|
1
|
+
SimpleSubmitter = require "hoarder/submitter/submitters/simple_submitter"
|
2
|
+
|
3
|
+
#
|
4
|
+
# @author - Tim Shelburne <tim@musiconelive.com>
|
5
|
+
#
|
6
|
+
# handles executing a delayed
|
7
|
+
#
|
8
|
+
class PollingSubmitter extends SimpleSubmitter
|
9
|
+
constructor: (@pollUrl, @pollFrequency)->
|
10
|
+
super()
|
11
|
+
|
12
|
+
canSubmit: (form)-> form.type is "polling"
|
13
|
+
|
14
|
+
submitSuccess: (form, data)->
|
15
|
+
@interval = setInterval( =>
|
16
|
+
@queryPoll(form, data.pollId)
|
17
|
+
, @pollFrequency)
|
18
|
+
@queryPoll(form, data.pollId)
|
19
|
+
|
20
|
+
queryPoll: (form, pollId)=>
|
21
|
+
unless @executing
|
22
|
+
@executing = true
|
23
|
+
$.ajax
|
24
|
+
url: @pollUrl
|
25
|
+
type: "POST"
|
26
|
+
data: "pollId=#{pollId}"
|
27
|
+
success: (data)=> @pollSuccess(form, pollId, data)
|
28
|
+
error: (xhr, text)=> @submitError(form, xhr, text)
|
29
|
+
|
30
|
+
pollSuccess: (form, pollId, data)=>
|
31
|
+
@executing = false
|
32
|
+
if data.pollCompleted
|
33
|
+
clearInterval(@interval)
|
34
|
+
@submittedWithSuccess.dispatch(form, data.pollData)
|
35
|
+
|
36
|
+
return PollingSubmitter
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require "lib/jquery"
|
2
|
+
|
3
|
+
Signal = require "cronus/signal"
|
4
|
+
|
5
|
+
#
|
6
|
+
# @author - Tim Shelburne <tim@musiconelive.com>
|
7
|
+
#
|
8
|
+
# handles submitting a form and waiting for a response
|
9
|
+
#
|
10
|
+
class SimpleSubmitter
|
11
|
+
constructor: ->
|
12
|
+
@submittedWithSuccess = new Signal()
|
13
|
+
@submittedWithError = new Signal()
|
14
|
+
|
15
|
+
canSubmit: (form)-> form.type is "simple"
|
16
|
+
|
17
|
+
submitForm: (form)->
|
18
|
+
$.ajax
|
19
|
+
url: form.action
|
20
|
+
type: form.method
|
21
|
+
data: form.serialize()
|
22
|
+
success: (data)=>
|
23
|
+
@submitSuccess(form, data)
|
24
|
+
error: (xhr, text)=> @submitError(form, xhr, text)
|
25
|
+
|
26
|
+
submitSuccess: (form, data)-> @submittedWithSuccess.dispatch(form, data)
|
27
|
+
|
28
|
+
submitError: (form, xhr, text)-> @submittedWithError.dispatch(form, text)
|
29
|
+
|
30
|
+
return SimpleSubmitter
|
@@ -0,0 +1,18 @@
|
|
1
|
+
ValidationError = require "hoarder/validator/error/validation_error"
|
2
|
+
|
3
|
+
#
|
4
|
+
# @author - Tim Shelburne <tim@musiconelive.com>
|
5
|
+
#
|
6
|
+
#
|
7
|
+
#
|
8
|
+
class AlphaConstraint
|
9
|
+
canHandle: (type)->
|
10
|
+
type is "alpha"
|
11
|
+
|
12
|
+
handle: (element)->
|
13
|
+
# if element.value.match(/^[A-Za-z0-9\s]*$/)
|
14
|
+
# return []
|
15
|
+
# else
|
16
|
+
# return [ new ValidationError "This field only accepts numbers and characters (0-9, A-Z, a-z)." ]
|
17
|
+
|
18
|
+
return AlphaConstraint
|