hoarder-js 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. data/CHANGELOG +2 -0
  2. data/Gemfile.lock +2 -2
  3. data/Manifest +14 -3
  4. data/assets/scripts/coffee/hoarder/form/form.coffee +47 -44
  5. data/assets/scripts/coffee/hoarder/form/form_serializer.coffee +23 -0
  6. data/assets/scripts/coffee/hoarder/form_manager.coffee +35 -19
  7. data/assets/scripts/coffee/hoarder/submitter/form_submitter.coffee +10 -15
  8. data/assets/scripts/coffee/hoarder/submitter/submitters/base_submitter.coffee +11 -0
  9. data/assets/scripts/coffee/hoarder/submitter/submitters/polling_submitter.coffee +30 -27
  10. data/assets/scripts/coffee/hoarder/submitter/submitters/simple_submitter.coffee +11 -21
  11. data/assets/scripts/coffee/hoarder/validator/constraints/alpha_constraint.coffee +8 -14
  12. data/assets/scripts/coffee/hoarder/validator/constraints/alphanumeric_constraint.coffee +8 -14
  13. data/assets/scripts/coffee/hoarder/validator/constraints/base_constraint.coffee +10 -0
  14. data/assets/scripts/coffee/hoarder/validator/constraints/credit_card_constraint.coffee +8 -14
  15. data/assets/scripts/coffee/hoarder/validator/constraints/email_constraint.coffee +8 -14
  16. data/assets/scripts/coffee/hoarder/validator/constraints/max_length_constraint.coffee +8 -14
  17. data/assets/scripts/coffee/hoarder/validator/constraints/min_length_constraint.coffee +8 -14
  18. data/assets/scripts/coffee/hoarder/validator/constraints/numeric_constraint.coffee +8 -14
  19. data/assets/scripts/coffee/hoarder/validator/constraints/phone_constraint.coffee +8 -14
  20. data/assets/scripts/coffee/hoarder/validator/constraints/required_constraint.coffee +8 -14
  21. data/assets/scripts/coffee/hoarder/validator/form_validator.coffee +30 -25
  22. data/assets/scripts/coffee/hoarder/validator/rules/validation_rule.coffee +10 -0
  23. data/assets/scripts/js/lib/bonzo.js +1151 -0
  24. data/assets/scripts/js/lib/qwery.js +369 -0
  25. data/assets/scripts/js/lib/reqwest.js +565 -0
  26. data/assets/scripts/js/patches/event_listeners.js +73 -0
  27. data/bin/hoarder.js +2807 -369
  28. data/hoarder-js.gemspec +3 -3
  29. data/spec/jasmine.yml +3 -0
  30. data/spec/runner.html +44 -34
  31. data/spec/support/fixtures.coffee +19 -0
  32. data/spec/support/lib/jasmine-fixture.js +506 -0
  33. data/spec/support/lib/jquery-1.7.1.min.js +4 -0
  34. data/spec/support/mocks.coffee +12 -37
  35. data/spec/support/requirements.coffee +0 -1
  36. data/spec/tests/form/form_serializer_spec.coffee +78 -0
  37. data/spec/tests/form/form_spec.coffee +127 -0
  38. data/spec/tests/form_manager_spec.coffee +128 -40
  39. data/spec/tests/submitter/form_submitter_spec.coffee +59 -42
  40. data/spec/tests/submitter/submitters/polling_submitter_spec.coffee +102 -57
  41. data/spec/tests/submitter/submitters/simple_submitter_spec.coffee +42 -16
  42. data/spec/tests/validator/constraints_spec.coffee +65 -57
  43. data/spec/tests/validator/form_validator_spec.coffee +39 -23
  44. data/spec/tests/validator/validation_rule_spec.coffee +14 -0
  45. metadata +16 -5
  46. data/assets/scripts/coffee/hoarder/form/form_element.coffee +0 -22
  47. data/assets/scripts/coffee/hoarder/validator/error/validation_error.coffee +0 -9
  48. data/assets/scripts/js/lib/jquery.js +0 -5
data/CHANGELOG CHANGED
@@ -1 +1,3 @@
1
+ v0.0.2 removed all dependencies on jquery and update library API - version 1.0.0 pending successful use in a production project
2
+
1
3
  v0.0.1 new library
@@ -1,6 +1,6 @@
1
1
  GIT
2
2
  remote: git://github.com/jpeace/keystone.git
3
- revision: 3680c30328bf3b93af7c7f1b1bad685cbaec35dd
3
+ revision: 54627ade405d8b3307e349f36bab6e87b75fae84
4
4
  specs:
5
5
  keystone (0.0.1)
6
6
  closure-compiler
@@ -85,7 +85,7 @@ GEM
85
85
  multi_json (~> 1.0)
86
86
  rack (~> 1.0)
87
87
  tilt (~> 1.1, != 1.3.0)
88
- tilt (1.3.7)
88
+ tilt (1.4.0)
89
89
  websocket (1.0.7)
90
90
 
91
91
  PLATFORMS
data/Manifest CHANGED
@@ -6,13 +6,15 @@ Manifest
6
6
  README.rdoc
7
7
  Rakefile
8
8
  assets/scripts/coffee/hoarder/form/form.coffee
9
- assets/scripts/coffee/hoarder/form/form_element.coffee
9
+ assets/scripts/coffee/hoarder/form/form_serializer.coffee
10
10
  assets/scripts/coffee/hoarder/form_manager.coffee
11
11
  assets/scripts/coffee/hoarder/submitter/form_submitter.coffee
12
+ assets/scripts/coffee/hoarder/submitter/submitters/base_submitter.coffee
12
13
  assets/scripts/coffee/hoarder/submitter/submitters/polling_submitter.coffee
13
14
  assets/scripts/coffee/hoarder/submitter/submitters/simple_submitter.coffee
14
15
  assets/scripts/coffee/hoarder/validator/constraints/alpha_constraint.coffee
15
16
  assets/scripts/coffee/hoarder/validator/constraints/alphanumeric_constraint.coffee
17
+ assets/scripts/coffee/hoarder/validator/constraints/base_constraint.coffee
16
18
  assets/scripts/coffee/hoarder/validator/constraints/credit_card_constraint.coffee
17
19
  assets/scripts/coffee/hoarder/validator/constraints/email_constraint.coffee
18
20
  assets/scripts/coffee/hoarder/validator/constraints/max_length_constraint.coffee
@@ -20,9 +22,12 @@ assets/scripts/coffee/hoarder/validator/constraints/min_length_constraint.coffee
20
22
  assets/scripts/coffee/hoarder/validator/constraints/numeric_constraint.coffee
21
23
  assets/scripts/coffee/hoarder/validator/constraints/phone_constraint.coffee
22
24
  assets/scripts/coffee/hoarder/validator/constraints/required_constraint.coffee
23
- assets/scripts/coffee/hoarder/validator/error/validation_error.coffee
24
25
  assets/scripts/coffee/hoarder/validator/form_validator.coffee
25
- assets/scripts/js/lib/jquery.js
26
+ assets/scripts/coffee/hoarder/validator/rules/validation_rule.coffee
27
+ assets/scripts/js/lib/bonzo.js
28
+ assets/scripts/js/lib/qwery.js
29
+ assets/scripts/js/lib/reqwest.js
30
+ assets/scripts/js/patches/event_listeners.js
26
31
  bin/hoarder.js
27
32
  config/assets.rb
28
33
  lib/hoarder.rb
@@ -30,13 +35,19 @@ lib/hoarder/symbols.rb
30
35
  spec/jasmine.yml
31
36
  spec/runner.html
32
37
  spec/support/classes.coffee
38
+ spec/support/fixtures.coffee
33
39
  spec/support/helpers.coffee
40
+ spec/support/lib/jasmine-fixture.js
41
+ spec/support/lib/jquery-1.7.1.min.js
34
42
  spec/support/mocks.coffee
35
43
  spec/support/objects.coffee
36
44
  spec/support/requirements.coffee
45
+ spec/tests/form/form_serializer_spec.coffee
46
+ spec/tests/form/form_spec.coffee
37
47
  spec/tests/form_manager_spec.coffee
38
48
  spec/tests/submitter/form_submitter_spec.coffee
39
49
  spec/tests/submitter/submitters/polling_submitter_spec.coffee
40
50
  spec/tests/submitter/submitters/simple_submitter_spec.coffee
41
51
  spec/tests/validator/constraints_spec.coffee
42
52
  spec/tests/validator/form_validator_spec.coffee
53
+ spec/tests/validator/validation_rule_spec.coffee
@@ -1,48 +1,51 @@
1
- require "lib/jquery"
1
+ FormSerializer = require 'hoarder/form/form_serializer'
2
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
3
  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()
4
+
5
+ constructor: (@formElement)->
6
+ @addedElements = [ ]
7
+
8
+ elements: -> (@formElement[index] for index in [0..@formElement.length] when @formElement[index]?.nodeName in [ 'INPUT', 'SELECT', 'TEXTAREA' ])
9
+
10
+ action: -> @formElement.action
11
+
12
+ method: -> @formElement.method
13
+
14
+ addElement: (name, value)->
15
+ throw new Error "'#{name}' already exists as an element on the form." if @hasElement name
16
+ element = createElement name, value
17
+ @formElement.appendChild element
18
+ @addedElements.push element
19
+ element
20
+
21
+ addElements: (elements)->
22
+ errors = [ ]
23
+ for element in elements
24
+ try @addElement(element.name, element.value)
25
+ catch e
26
+ errors.push e
27
+ throw errors[0] if errors.length
28
+
29
+ hasElement: (name)-> @getElement(name)?
30
+
31
+ getElement: (name)-> @formElement[name] if @formElement[name] instanceof HTMLElement
32
+
33
+ updateAddedElement: (name, value)-> if @formElement[name]? then @formElement[name].value = value else @addElement name, value
34
+
35
+ clearAddedElements: ->
36
+ @formElement.removeChild element for element in @addedElements
37
+ @addedElements = []
38
+
39
+ serialize: -> FormSerializer.toString @
40
+
41
+
42
+ # private
43
+
44
+ createElement = (name, value)->
45
+ element = document.createElement("input")
46
+ element.type = "hidden"
47
+ element.name = name
48
+ element.value = value
49
+ element
47
50
 
48
51
  return Form
@@ -0,0 +1,23 @@
1
+ class Serializer
2
+
3
+ @toString: (form)-> removeNulls((serializeElement element for element in form.elements())).join("&")
4
+
5
+ # private
6
+
7
+ serializeElement = (element)->
8
+ return "#{element.name}=#{encodeURIComponent element.value}" unless isComplicated element
9
+ return "#{element.name}=#{encodeURIComponent element.value}" if isCheckable(element) and element.checked
10
+ return ("#{element.name}=#{encodeURIComponent option.value}" for option in element.options when option.selected).join("&") if isMultiSelect(element)
11
+ null
12
+
13
+ isComplicated = (element)-> isCheckable(element) or isMultiSelect(element) or isFile(element)
14
+
15
+ isCheckable = (element)-> element.nodeName is "INPUT" and element.type in [ "checkbox", "radio" ]
16
+
17
+ isMultiSelect = (element)-> element.nodeName is "SELECT" and element.type is "select-multiple"
18
+
19
+ isFile = (element)-> element.nodeName is "INPUT" and element.type is "file"
20
+
21
+ removeNulls = (array)-> array.filter((e)-> return e)
22
+
23
+ return Serializer
@@ -1,32 +1,48 @@
1
+ require 'patches/event_listeners'
2
+
1
3
  Signal = require "cronus/signal"
2
4
  SignalRelay = require "cronus/signal_relay"
3
5
 
6
+ Form = require 'hoarder/form/form'
4
7
  FormSubmitter = require 'hoarder/submitter/form_submitter'
5
8
  FormValidator = require 'hoarder/validator/form_validator'
6
9
 
7
- #
8
- # @author - Tim Shelburne <tim@musiconelive.com>
9
- #
10
- # abstracts submitting and validating forms from the validator and submitter
11
- #
12
10
  class FormManager
13
- constructor: (@formSubmitter, @formValidator)->
14
- @validatedWithErrors = new Signal()
15
- @submittedWithSuccess = new SignalRelay(@formSubmitter.submittedWithSuccess)
16
- @submittedWithError = new SignalRelay(@formSubmitter.submittedWithError)
17
11
 
18
- @default: (pollingUrl="")->
19
- new @(FormSubmitter.default(pollingUrl), FormValidator.default())
12
+ @create: (pollingUrl="", pollFrequency=1000)->
13
+ new @(FormSubmitter.create(pollingUrl, pollFrequency), FormValidator.create())
14
+
15
+ constructor: (@formSubmitter, @formValidator)->
16
+ @validatedWithErrors = new Signal()
17
+ @submittedWithSuccess = new SignalRelay(@formSubmitter.submittedWithSuccess)
18
+ @submittedWithError = new SignalRelay(@formSubmitter.submittedWithError)
19
+ @_forms = [ ]
20
+ @_listeners = { }
21
+
22
+ manage: (formId, type='simple')->
23
+ throw new Error "'#{formId}' is already a managed form." if getForm.call(@, formId)?
24
+ formElement = document.getElementById formId
25
+ form = new Form(formElement)
26
+ formElement.addEventListener 'submit', @_listeners[formId] = (event)=>
27
+ event.preventDefault()
28
+ submit.call @, form, type
29
+ @_forms.push form
30
+ form
20
31
 
21
- validateForm: (form)->
22
- @formValidator.validateForm(form)
32
+ release: (formId)->
33
+ form = getForm.call @, formId
34
+ form.formElement.removeEventListener 'submit', @_listeners[formId]
35
+ delete @_listeners[formId]
36
+ @_forms.splice @_forms.indexOf(form), 1
23
37
 
24
- submitForm: (form)->
25
- errors = @validateForm(form)
38
+ getForm = (formId)->
39
+ for form in @_forms
40
+ return form if form.formElement.id is formId
26
41
 
27
- if (errors.length > 0)
28
- @validatedWithErrors.dispatch(errors)
29
- else
30
- @formSubmitter.submitForm(form)
42
+ submit = (form, type)->
43
+ if @formValidator.validateForm form
44
+ @formSubmitter.submit form, type
45
+ else
46
+ @validatedWithErrors.dispatch form
31
47
 
32
48
  return FormManager
@@ -3,27 +3,22 @@ MultiSignalRelay = require "cronus/multi_signal_relay"
3
3
  SimpleSubmitter = require "hoarder/submitter/submitters/simple_submitter"
4
4
  PollingSubmitter = require "hoarder/submitter/submitters/polling_submitter"
5
5
 
6
- #
7
- # @author - Tim Shelburne <tim@musiconelive.com>
8
- #
9
- # a class to handle submitting forms
10
- #
11
6
  class FormSubmitter
7
+
8
+ @create: (pollingUrl, pollFrequency=1000)->
9
+ new @([ new SimpleSubmitter(), new PollingSubmitter(pollingUrl, pollFrequency)])
10
+
12
11
  constructor: (@submitters)->
13
- successSignals = []
14
- errorSignals = []
15
- for submitter in @submitters
16
- successSignals.push submitter.submittedWithSuccess
17
- errorSignals.push submitter.submittedWithError
12
+ successSignals = (submitter.submittedWithSuccess for submitter in @submitters)
13
+ errorSignals = (submitter.submittedWithError for submitter in @submitters)
18
14
 
19
15
  @submittedWithSuccess = new MultiSignalRelay(successSignals)
20
16
  @submittedWithError = new MultiSignalRelay(errorSignals)
21
17
 
22
- @default: (pollingUrl)->
23
- new @([ new SimpleSubmitter(), new PollingSubmitter(pollingUrl, 1000)])
24
-
25
- submitForm: (form)->
18
+ submit: (form, type)->
26
19
  for submitter in @submitters
27
- submitter.submitForm(form) if submitter.canSubmit(form)
20
+ if submitter.canSubmit(type)
21
+ submitter.submit form
22
+ break
28
23
 
29
24
  return FormSubmitter
@@ -0,0 +1,11 @@
1
+ Signal = require 'cronus/signal'
2
+
3
+ class BaseSubmitter
4
+
5
+ constructor: ->
6
+ @submittedWithSuccess = new Signal()
7
+ @submittedWithError = new Signal()
8
+
9
+ canSubmit: (type)-> type is @type
10
+
11
+ return BaseSubmitter
@@ -1,36 +1,39 @@
1
- SimpleSubmitter = require "hoarder/submitter/submitters/simple_submitter"
1
+ require 'lib/reqwest'
2
2
 
3
- #
4
- # @author - Tim Shelburne <tim@musiconelive.com>
5
- #
6
- # handles executing a delayed
7
- #
8
- class PollingSubmitter extends SimpleSubmitter
3
+ BaseSubmitter = require "hoarder/submitter/submitters/base_submitter"
4
+
5
+ class PollingSubmitter extends BaseSubmitter
6
+
9
7
  constructor: (@pollUrl, @pollFrequency)->
10
8
  super()
9
+ @type = 'polling'
11
10
 
12
- canSubmit: (form)-> form.type is "polling"
11
+ submit: (form)->
12
+ reqwest(
13
+ url: form.action
14
+ type: form.method
15
+ data: form.serialize()
16
+ success: (data)=> @poll(form, data.processId)
17
+ error: (xhr, text)=> @submittedWithError.dispatch(form, text)
18
+ )
13
19
 
14
- submitSuccess: (form, data)->
15
- @interval = setInterval( =>
16
- @queryPoll(form, data.pollId)
17
- , @pollFrequency)
18
- @queryPoll(form, data.pollId)
20
+ poll: (form, processId)=>
21
+ reqwest(
22
+ url: @pollUrl
23
+ type: "POST"
24
+ data: "processId=#{processId}"
25
+ success: (data)=> pollSuccess.call @, form, processId, data
26
+ error: (xhr, text)=> @submittedWithError.dispatch(form, text)
27
+ )
19
28
 
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
+ # private
29
30
 
30
- pollSuccess: (form, pollId, data)=>
31
- @executing = false
32
- if data.pollCompleted
33
- clearInterval(@interval)
34
- @submittedWithSuccess.dispatch(form, data.pollData)
31
+ pollSuccess = (form, processId, data)->
32
+ if data.processCompleted
33
+ @submittedWithSuccess.dispatch(form, data.processData)
34
+ else
35
+ setTimeout( =>
36
+ @poll(form, data.processId)
37
+ , @pollFrequency)
35
38
 
36
39
  return PollingSubmitter
@@ -1,30 +1,20 @@
1
- require "lib/jquery"
1
+ require 'lib/reqwest'
2
2
 
3
- Signal = require "cronus/signal"
3
+ BaseSubmitter = require 'hoarder/submitter/submitters/base_submitter'
4
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()
5
+ class SimpleSubmitter extends BaseSubmitter
14
6
 
15
- canSubmit: (form)-> form.type is "simple"
7
+ constructor: ->
8
+ super()
9
+ @type = 'simple'
16
10
 
17
- submitForm: (form)->
18
- $.ajax
11
+ submit: (form)->
12
+ reqwest(
19
13
  url: form.action
20
14
  type: form.method
21
15
  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)
16
+ success: (data)=> @submittedWithSuccess.dispatch(form, data)
17
+ error: (xhr, text)=> @submittedWithError.dispatch(form, text)
18
+ )
29
19
 
30
20
  return SimpleSubmitter
@@ -1,18 +1,12 @@
1
- ValidationError = require "hoarder/validator/error/validation_error"
1
+ BaseConstraint = require 'hoarder/validator/constraints/base_constraint'
2
2
 
3
- #
4
- # @author - Tim Shelburne <tim@musiconelive.com>
5
- #
6
- #
7
- #
8
- class AlphaConstraint
9
- canHandle: (type)->
10
- type is "alpha"
3
+ class AlphaConstraint extends BaseConstraint
11
4
 
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)." ]
5
+ constructor: ->
6
+ @type = "alpha"
7
+
8
+ rulePasses: (element)-> element.value.match(/^[A-Za-z\s]*$/)
9
+
10
+ errorMessage: -> "This field only accepts numbers and characters (0-9, A-Z, a-z)."
17
11
 
18
12
  return AlphaConstraint