caisson 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. data/README.md +13 -1
  2. data/app/assets/javascripts/caisson/base.coffee +4 -0
  3. data/app/assets/javascripts/caisson/form/fields/base.coffee +115 -0
  4. data/app/assets/javascripts/caisson/form/fields/checkbox.coffee +13 -0
  5. data/app/assets/javascripts/caisson/form/fields/select.coffee +14 -0
  6. data/app/assets/javascripts/caisson/form/fields/text_field.coffee +22 -0
  7. data/app/assets/javascripts/caisson/form/fields/validator.coffee +116 -0
  8. data/app/assets/javascripts/caisson/form/form.coffee +119 -0
  9. data/app/assets/javascripts/caisson/form/form_caisson.coffee +30 -0
  10. data/app/assets/javascripts/caisson/index.js +2 -0
  11. data/app/assets/javascripts/caisson/module.coffee +8 -0
  12. data/app/assets/javascripts/caisson/orbit-slider.coffee +2 -1
  13. data/app/assets/stylesheets/caisson/base.css.scss +7 -0
  14. data/app/assets/stylesheets/caisson/index.css +3 -0
  15. data/lib/caisson/helpers/form/base.rb +195 -0
  16. data/lib/caisson/helpers/form/builder/base.rb +72 -0
  17. data/lib/caisson/helpers/form/builder/field/base.rb +168 -0
  18. data/lib/caisson/helpers/form/builder/field/checkbox.rb +15 -0
  19. data/lib/caisson/helpers/form/builder/field/money.rb +13 -0
  20. data/lib/caisson/helpers/form/builder/field/password.rb +13 -0
  21. data/lib/caisson/helpers/form/builder/field/percent.rb +13 -0
  22. data/lib/caisson/helpers/form/builder/field/select.rb +41 -0
  23. data/lib/caisson/helpers/form/builder/field/text.rb +13 -0
  24. data/lib/caisson/helpers/form/builder/field/textarea.rb +13 -0
  25. data/lib/caisson/helpers/form/builder/field_builder/base.rb +81 -0
  26. data/lib/caisson/helpers/form/builder/field_builder/nature.rb +85 -0
  27. data/lib/caisson/helpers/form/builder/interpreti.rb +107 -0
  28. data/lib/caisson/helpers/form/button.rb +62 -0
  29. data/lib/caisson/helpers/form/field/base.rb +43 -0
  30. data/lib/caisson/helpers/form/field/checkbox.rb +39 -0
  31. data/lib/caisson/helpers/form/field/money.rb +29 -0
  32. data/lib/caisson/helpers/form/field/password.rb +14 -0
  33. data/lib/caisson/helpers/form/field/percent.rb +23 -0
  34. data/lib/caisson/helpers/form/field/select.rb +34 -0
  35. data/lib/caisson/helpers/form/field/text.rb +17 -0
  36. data/lib/caisson/helpers/form/field/textarea.rb +16 -0
  37. data/lib/caisson/helpers/form.rb +30 -0
  38. data/lib/caisson/helpers/grid.rb +32 -0
  39. data/lib/caisson/helpers/orbit_slider.rb +16 -21
  40. data/lib/caisson/helpers.rb +26 -0
  41. data/lib/caisson/implants/mongoid.rb +67 -0
  42. data/lib/caisson/implants/railtie.rb +4 -0
  43. metadata +41 -6
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  Caisson
2
2
  ===============
3
3
 
4
- Caisson will provide a set of tools to facilitate the integration of Zurb-Foundation to your Rails project.
4
+ Caisson provide a set of tools to facilitate the integration of Zurb-Foundation to your Rails project.
5
5
 
6
6
  Install
7
7
  -------
@@ -19,6 +19,18 @@ gem 'zurb-foundation'
19
19
  gem 'caisson'
20
20
  ```
21
21
 
22
+ In your application.js
23
+
24
+ ```javascript
25
+ //= require foundation
26
+ //= require caisson
27
+ ```
28
+
29
+ In your application.scss
30
+ ```css
31
+ @import "foundation";
32
+ ```
33
+
22
34
  Orbit Slider
23
35
  -----
24
36
 
@@ -1,5 +1,9 @@
1
1
  class Caisson
2
2
  constructor: () ->
3
+ $(document).foundation()
4
+
5
+ FormCaisson.load()
6
+
3
7
  $('div[data-caisson]').each (i, component) =>
4
8
  switch $(component).data('caisson')
5
9
  when 'orbit-slider' then new OrbitSlider $(component)
@@ -0,0 +1,115 @@
1
+ #*************************************************************************************
2
+ # TOCOMMENT
3
+ #*************************************************************************************
4
+ @caissonMod "FormCaisson", ->
5
+ @caissonMod "Field", ->
6
+ class @Base
7
+ #*************************************************************************************
8
+ # CONSTRUCTOR
9
+ #*************************************************************************************
10
+ constructor: (@field) ->
11
+ @build()
12
+
13
+ #*************************************************************************************
14
+ # PUBLIC INSTANCE METHODS
15
+ #*************************************************************************************
16
+ build: () ->
17
+ @initPlaceholder()
18
+ @tagField()
19
+
20
+ @field.on('validate', (e) => @validate())
21
+ @field.blur (e) => @validate() if @hasErrors()
22
+
23
+
24
+ closest: (path) -> @field.closest(path)
25
+
26
+ data: (key, val) -> @field.data key, val
27
+
28
+
29
+ hasApproximateName: (names) ->
30
+ return name for name in names when name is @field.attr('name') or @field.attr('name').indexOf("[#{name}]") > 0
31
+
32
+ return ''
33
+
34
+
35
+ hideErrors: ->
36
+ @wrapper().removeClass('errors')
37
+ @wrapper().find('div.error-messages').fadeOut 500, -> $(this).remove()
38
+ $('#form-caisson-flash-' + @id()).fadeOut 500, -> $(this).remove()
39
+
40
+
41
+ find: (key) -> @field.find key
42
+
43
+ hasErrors: -> @wrapper().hasClass('errors')
44
+
45
+ id: () -> @field.attr('id')
46
+
47
+ input: () -> if @field[0].tagName.toLowerCase() == 'input' then @field else $(@field.find('input'))
48
+
49
+ isPlaceholder: () -> @field.attr('placeholder') isnt undefined
50
+
51
+ isSubmitAuto: () -> @field.data('submit') is 1
52
+
53
+ label: () -> @wrapper().find('label')
54
+
55
+ labelText: () -> @label().text()
56
+
57
+ showErrors: (messages) ->
58
+ @removeErrorMessages()
59
+ @wrapper().addClass('errors')
60
+ @popErrors messages
61
+
62
+
63
+ validate: () ->
64
+ v = @validator()
65
+
66
+ if v.validate() then @hideErrors() else @showErrors v.messages
67
+
68
+
69
+ validateWithAjax: (url, caller, callback) ->
70
+ $.getJSON url, (data) =>
71
+ if data['state'] is 'error' then @showErrors([data['message']])
72
+ caller[callback]()
73
+
74
+
75
+ validator: () -> new FormCaisson.Field.Validator(@field.data('validations'), @field.val())
76
+
77
+ wrapper: () -> @field.closest('div.field')
78
+
79
+
80
+ #*************************************************************************************
81
+ # PRIVATE INSTANCE METHODS
82
+ #*************************************************************************************
83
+ initPlaceholder: () ->
84
+ if @isPlaceholder()
85
+ @input().placeholder()
86
+ @input().focus (e) => $(@wrapper().find('.ui-placeholder')).addClass('focus')
87
+ @input().blur (e) => $(@wrapper().find('.ui-placeholder')).removeClass('focus')
88
+
89
+
90
+ removeErrorMessages: () ->
91
+ @wrapper().find('div.error-messages').remove()
92
+ $('#form-caisson-flash-' + @id()).remove()
93
+
94
+
95
+ popErrors: (messages) ->
96
+ content = ''
97
+ content += '<span class="text">' + message + '</span>' for message in messages
98
+
99
+ flashPop = $('<div class="form-caisson-flash error" id="form-caisson-flash-' + @id() + '">').html(content)
100
+
101
+ flashPop.click () -> $(@).fadeOut(700)
102
+
103
+ if @hasErrors() then $('body').append(flashPop) else $('body').append(flashPop.hide().fadeIn(700))
104
+
105
+ align = ((@field.outerHeight() - flashPop.outerHeight()) / 2)
106
+
107
+ flashPop.css
108
+ "left": (@field.offset().left + (@field.outerWidth())) + "px"
109
+ "top": (@field.offset().top + align) + "px"
110
+
111
+
112
+ tagField: () ->
113
+ @field.data('caisson', 'field')
114
+ @field.attr('data-caisson', 'field')
115
+ @field.attr('id', 'field-caisson-' + Math.floor(Math.random()*10000)) if not @field.attr('id')
@@ -0,0 +1,13 @@
1
+ #*************************************************************************************
2
+ # TOCOMMENT
3
+ #*************************************************************************************
4
+ @caissonMod "FormCaisson", ->
5
+ @caissonMod "Field", ->
6
+ class @Checkbox extends FormCaisson.Field.Base
7
+ #*************************************************************************************
8
+ # CONSTRUCTOR
9
+ #*************************************************************************************
10
+ constructor: (@field) ->
11
+ if @isSubmitAuto() then @input().change (event) => @closest('form').submit()
12
+
13
+ super @field
@@ -0,0 +1,14 @@
1
+ #*************************************************************************************
2
+ # TOCOMMENT
3
+ # TODO : Add keyboard shortcuts
4
+ #*************************************************************************************
5
+ @caissonMod "FormCaisson", ->
6
+ @caissonMod "Field", ->
7
+ class @SelectField extends FormCaisson.Field.Base
8
+ #*************************************************************************************
9
+ # CONSTRUCTOR
10
+ #*************************************************************************************
11
+ constructor: (@field) ->
12
+ if @isSubmitAuto() then $(@field).change (event) => @closest('form').submit()
13
+
14
+ super @field
@@ -0,0 +1,22 @@
1
+ #*************************************************************************************
2
+ # TOCOMMENT
3
+ #*************************************************************************************
4
+ @caissonMod "FormCaisson", ->
5
+ @caissonMod "Field", ->
6
+ class @TextField extends FormCaisson.Field.Base
7
+ #*************************************************************************************
8
+ # CONSTRUCTOR
9
+ #*************************************************************************************
10
+ constructor: (@field) ->
11
+ super @field
12
+
13
+
14
+ #*************************************************************************************
15
+ # PUBLIC INSTANCE METHODS
16
+ #*************************************************************************************
17
+ #getCreditCardType: () -> @validator().getCreditCardType @field.val()
18
+
19
+
20
+ #*************************************************************************************
21
+ # PRIVATE INSTANCE METHODS
22
+ #*************************************************************************************
@@ -0,0 +1,116 @@
1
+ #*************************************************************************************
2
+ # TOCOMMENT
3
+ #*************************************************************************************
4
+ @caissonMod "FormCaisson", ->
5
+ @caissonMod "Field", ->
6
+ class @Validator
7
+ #*************************************************************************************
8
+ # CONSTRUCTOR
9
+ #*************************************************************************************
10
+ constructor: (specs, @value) ->
11
+ @specs = if specs then specs.split(' ') else []
12
+ @messages = []
13
+
14
+
15
+ #*************************************************************************************
16
+ # PUBLIC INSTANCE METHODS
17
+ #*************************************************************************************
18
+ checkSpec: (spec) ->
19
+ stripped_spec = spec.split('-')[0]
20
+
21
+ if stripped_spec is 'blank'
22
+ @isBlank()
23
+ else if @notBlank()
24
+ switch stripped_spec
25
+ when 'confirm' then @isConfirmed spec
26
+ when 'creditcard' then @isCreditCard spec
27
+ when 'creditcardname' then @isCreditCardName()
28
+ when 'creditcardexpiration' then @isCreditCardExpiration()
29
+ when 'email' then @isEmail()
30
+ when 'length' then @isLengthEql spec
31
+ when 'max' then @isMax spec
32
+ when 'min' then @isMin spec
33
+ when 'numeric' then @isNumeric()
34
+ when 'within' then @isWithin spec
35
+ else
36
+
37
+
38
+ getCreditCardType: (rawCCNumber) ->
39
+ ccNumber = rawCCNumber.replace(/(\s|-)/g, '')
40
+
41
+ if /^4[0-9]{12}(?:[0-9]{3})?$/.test(ccNumber)
42
+ 'visa'
43
+ else if /^5[1-5][0-9]{14}$/.test(ccNumber)
44
+ 'mastercard'
45
+ else if /^3[47][0-9]{13}$/.test(ccNumber)
46
+ 'amex'
47
+ else
48
+ ''
49
+
50
+
51
+ isValid: () -> @messages.length is 0
52
+
53
+ validate: () ->
54
+ @checkSpec spec for spec in @specs if @specs
55
+
56
+ return @isValid()
57
+
58
+
59
+ #*************************************************************************************
60
+ # PRIVATE INSTANCE METHODS
61
+ #*************************************************************************************
62
+ isBlank: () -> if @value is "" then @messages.push 'Le champ ne peut être vide.'
63
+
64
+ isConfirmed: (spec) ->
65
+ [tag, idOtherField] = spec.split('-')
66
+
67
+ if @value isnt $('#' + idOtherField).val() then @messages.push 'La confirmation est erronée'
68
+
69
+
70
+ isCreditCard: (spec) ->
71
+ types = spec.replace('creditcard-', '').split('-')
72
+ currentType = @getCreditCardType @value
73
+ if $.inArray(currentType, types) is -1 then @messages.push "Le numéro de carte de crédit est invalide."
74
+
75
+
76
+ isCreditCardName: () -> if not /^\S+ \S+/.test(@value) then @messages.push "Entrez le nom complet figurant sur votre carte."
77
+
78
+ isCreditCardExpiration: () ->
79
+ value = @value.replace('/', '').replace('-', '').replace(' ', '')
80
+
81
+ value = value.slice(0,2) + '20' + value.slice(2,4) if value.length is 4
82
+
83
+ if value.length is 6 and /^[0-9]*$/.test value
84
+ expiration = new Date(value.slice(2,6), Number(value.slice(0,2)) - 1, 31)
85
+
86
+ if expiration < new Date() then @messages.push "Votre carte de crédit est expirée."
87
+ else
88
+ @messages.push "La date d'expiration est doit avoir un format MM/AA."
89
+
90
+
91
+ isEmail: () -> if not /^[a-zA-Z0-9.\$#%+-\/=?_]+@([a-zA-Z0-9.\-]+\.)+[a-zA-Z0-9.\-]{2,6}$/.test(@value) then @messages.push 'Le courriel est invalide.'
92
+
93
+ isLengthEql: (spec) ->
94
+ [tag, length] = spec.split('-')
95
+ if @value.length != Number(length) then @messages.push "Le champ doit contenir #{length} caractères."
96
+
97
+ isMax: (spec) ->
98
+ [tag, max] = spec.split('-')
99
+ if @value.length > Number(max) then @messages.push "Le champ doit contenir moins de #{max} caractères."
100
+
101
+
102
+ isMin: (spec) ->
103
+ [tag, min] = spec.split('-')
104
+ if @value.length < Number(min) then @messages.push "Le champ doit contenir plus de #{min} caractères."
105
+
106
+
107
+ isNumeric: -> if not /^$|^([\-]?[0-9]*)?([\.,][0-9]*)?$/.test(@value) then @messages.push 'Le champ doit être numérique.'
108
+
109
+ isWithin: (spec) ->
110
+ [tag, min, max] = spec.split('-')
111
+
112
+ @isMin "min-#{min}"
113
+ @isMax "max-#{max}"
114
+
115
+
116
+ notBlank: () -> @value isnt ""
@@ -0,0 +1,119 @@
1
+ #*************************************************************************************
2
+ # TOCOMMENT
3
+ #*************************************************************************************
4
+ @caissonMod "FormCaisson", ->
5
+ class @Form
6
+ #*************************************************************************************
7
+ # CONSTRUCTOR
8
+ #*************************************************************************************
9
+ constructor: (@form) ->
10
+ @fields = []
11
+
12
+ @initFormId()
13
+ @initEvents()
14
+ @initFields()
15
+
16
+
17
+ #*************************************************************************************
18
+ # PUBLIC INSTANCE METHODS
19
+ #*************************************************************************************
20
+ field: (id) -> return f for f in @fields when f.id() is id
21
+
22
+ hasErrors: () -> @form.find('div.field.errors').length > 0
23
+
24
+ hasField: (id) -> if @field(id) then true else false
25
+
26
+ hideErrors: () -> field.hideErrors() for field in @fields
27
+
28
+ id: () -> @form.attr('id')
29
+
30
+ send: (callback) ->
31
+ if @validate()
32
+ callback = {} if not callback
33
+ callback['loading'](true) if callback['loading']
34
+
35
+ $.ajax(
36
+ type: @form.attr('method')
37
+ url: @form.attr("action") + '.json'
38
+ dataType: "json"
39
+ data: @form.serialize()
40
+ complete: (data) -> callback['loading'](false) if callback['loading']
41
+ error: (xhr, ajax_error) =>
42
+ switch xhr.status
43
+ when 400 then @setFieldErrors $.parseJSON(xhr.responseText)
44
+ when 401 then #alert '401'
45
+ else @showAjaxError xhr.responseText, ajax_error
46
+ statusCode: callback
47
+ )
48
+
49
+
50
+ validate: () ->
51
+ field.validate() for field in @fields
52
+
53
+ if @hasErrors()
54
+ @form.find('div.field.errors:first input').focus()
55
+ return false
56
+ else
57
+ return true
58
+
59
+
60
+ #*************************************************************************************
61
+ # PRIVATE INSTANCE METHODS
62
+ #*************************************************************************************
63
+ initEvents: () ->
64
+ @form.on('validate', (e) => @validate())
65
+ @form.on('send', (e) => @send())
66
+
67
+ @form.submit (e) =>
68
+ if @validate()
69
+ field.input().trigger 'before-submit-form' for field in @fields
70
+
71
+ $(e.target).find('input[type=submit]').attr 'disabled', 'disabled'
72
+ $(e.target).find('button').attr 'disabled', 'disabled'
73
+
74
+ return true
75
+ else
76
+ return false
77
+
78
+
79
+ initField: (path, fieldClass) -> @form.find(path).each (i, elem) => @fields.push new fieldClass $(elem)
80
+
81
+
82
+ initFields: ->
83
+ @initField 'input.checkbox', FormCaisson.Field.Checkbox
84
+ @initField 'select', FormCaisson.Field.SelectField
85
+ #@_initField 'div.switch-field', FormCaisson.Field.SwitchField
86
+ @initField 'input.text-field', FormCaisson.Field.TextField
87
+ #@_initField 'input.percent-field', FormCaisson.Field.PercentField
88
+ #@_initField 'input.money-field', FormCaisson.Field.MoneyField
89
+ #@_initField 'div.time-field', FormCaisson.Field.TimeField
90
+
91
+
92
+ initFormId: ->
93
+ @form.data('caisson', 'form')
94
+ @form.attr('data-caisson', 'form')
95
+ @form.attr('id', 'form-caisson-' + Math.floor(Math.random()*10000)) if not @form.attr('id')
96
+
97
+
98
+ setFieldErrors: (errors) ->
99
+ names = (k for k,v of errors)
100
+
101
+ for field in @fields
102
+ errorKey = field.hasApproximateName names
103
+
104
+ if errorKey
105
+ field.showErrors $.flatten(errors[errorKey])
106
+ else if field.hasErrors()
107
+ field.hideErrors()
108
+
109
+ return errors
110
+
111
+
112
+ showAjaxError: (message, ajax_error) ->
113
+ left = ($('body').width() - 700) / 2
114
+
115
+ pop = $('<div id="ajax-error" style="display:none;margin-left:' + left + 'px"><h1>AJAX : ' + ajax_error + '</h1>' + message + '</div>')
116
+ pop.dblclick (e) -> $(e.target).closest('div#ajax-error').remove()
117
+
118
+ $('body').before pop
119
+ pop.fadeIn(500)
@@ -0,0 +1,30 @@
1
+ #*************************************************************************************
2
+ # TOCOMMENT
3
+ #*************************************************************************************
4
+ @caissonMod "FormCaisson", ->
5
+ #*************************************************************************************
6
+ # PUBLIC MODULE METHODS
7
+ #*************************************************************************************
8
+ @findFormById = (id) -> return form for form in @forms when form.id() is id
9
+
10
+ @findFieldById = (id) -> return form.field(id) for form in @forms when form.hasField(id)
11
+
12
+ @initForms = () -> $('form').each (i, form) => @forms.push new FormCaisson.Form $(form)
13
+
14
+ @initHelpers = () ->
15
+ $.fn.caisson = () ->
16
+ switch $(this).data('caisson')
17
+ when "form" then FormCaisson.findFormById $(this).attr('id')
18
+ when "field" then FormCaisson.findFieldById $(this).attr('id')
19
+ else FormCaisson.findFieldById $(this).closest('div[data-caisson]').attr('id') if $(this).closest('div[data-caisson]')
20
+
21
+
22
+ @load = () ->
23
+ @forms = []
24
+ @initForms()
25
+ @initHelpers()
26
+
27
+
28
+ @reload = () -> @load()
29
+
30
+
@@ -1,2 +1,4 @@
1
+ //= require ./module
1
2
  //= require ./base
3
+ //= require_tree ./form
2
4
  //= require ./orbit-slider
@@ -0,0 +1,8 @@
1
+ @caissonMod = (names, fn) ->
2
+ names = names.split '.' if typeof names is 'string'
3
+ space = @[names.shift()] ||= {}
4
+ space.caissonMod ||= @caissonMod
5
+ if names.length
6
+ space.caissonMod names, fn
7
+ else
8
+ fn.call space
@@ -3,7 +3,8 @@
3
3
  #*************************************************************************************
4
4
  class @OrbitSlider
5
5
  constructor: (@holder) ->
6
- @holder.orbit @buildAttributes()
6
+ # DEPRECATED IN VERSION 4
7
+ #@holder.orbit @buildAttributes()
7
8
 
8
9
 
9
10
  buildAttributes: () ->
@@ -0,0 +1,7 @@
1
+ @import "foundation";
2
+
3
+ div.line-checkbox{margin-bottom:1em;}
4
+ div.field-percent{
5
+ input{float:left;width:6em;}
6
+ span.postfix{float:left;width:3em;}
7
+ }
@@ -0,0 +1,3 @@
1
+ /*
2
+ *= require_tree .
3
+ */