sexy_form 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +5 -0
  3. data/LICENSE +21 -0
  4. data/README.md +275 -0
  5. data/Rakefile +15 -0
  6. data/lib/sexy_form.rb +84 -0
  7. data/lib/sexy_form/builder.rb +306 -0
  8. data/lib/sexy_form/themes.rb +22 -0
  9. data/lib/sexy_form/themes/base_theme.rb +39 -0
  10. data/lib/sexy_form/themes/bootstrap_2_horizontal.rb +83 -0
  11. data/lib/sexy_form/themes/bootstrap_2_inline.rb +73 -0
  12. data/lib/sexy_form/themes/bootstrap_2_vertical.rb +80 -0
  13. data/lib/sexy_form/themes/bootstrap_3_horizontal.rb +95 -0
  14. data/lib/sexy_form/themes/bootstrap_3_inline.rb +71 -0
  15. data/lib/sexy_form/themes/bootstrap_3_vertical.rb +70 -0
  16. data/lib/sexy_form/themes/bootstrap_4_horizontal.rb +95 -0
  17. data/lib/sexy_form/themes/bootstrap_4_inline.rb +80 -0
  18. data/lib/sexy_form/themes/bootstrap_4_vertical.rb +79 -0
  19. data/lib/sexy_form/themes/bulma_horizontal.rb +81 -0
  20. data/lib/sexy_form/themes/bulma_vertical.rb +73 -0
  21. data/lib/sexy_form/themes/default.rb +55 -0
  22. data/lib/sexy_form/themes/foundation.rb +67 -0
  23. data/lib/sexy_form/themes/materialize.rb +65 -0
  24. data/lib/sexy_form/themes/milligram.rb +62 -0
  25. data/lib/sexy_form/themes/semantic_ui_inline.rb +63 -0
  26. data/lib/sexy_form/themes/semantic_ui_vertical.rb +63 -0
  27. data/lib/sexy_form/version.rb +3 -0
  28. data/spec/custom_assertions.rb +21 -0
  29. data/spec/sexy_form/builder_spec.rb +104 -0
  30. data/spec/sexy_form/themes/base_theme_spec.rb +16 -0
  31. data/spec/sexy_form/themes/bootstrap_2_horizontal_spec.rb +114 -0
  32. data/spec/sexy_form/themes/bootstrap_2_inline_spec.rb +108 -0
  33. data/spec/sexy_form/themes/bootstrap_2_vertical_spec.rb +111 -0
  34. data/spec/sexy_form/themes/bootstrap_3_horizontal_spec.rb +116 -0
  35. data/spec/sexy_form/themes/bootstrap_3_inline_spec.rb +104 -0
  36. data/spec/sexy_form/themes/bootstrap_3_vertical_spec.rb +122 -0
  37. data/spec/sexy_form/themes/bootstrap_4_horizontal_spec.rb +124 -0
  38. data/spec/sexy_form/themes/bootstrap_4_inline_spec.rb +116 -0
  39. data/spec/sexy_form/themes/bootstrap_4_vertical_spec.rb +114 -0
  40. data/spec/sexy_form/themes/bulma_horizontal_spec.rb +126 -0
  41. data/spec/sexy_form/themes/bulma_vertical_spec.rb +114 -0
  42. data/spec/sexy_form/themes/default_spec.rb +102 -0
  43. data/spec/sexy_form/themes/foundation_spec.rb +103 -0
  44. data/spec/sexy_form/themes/materialize_spec.rb +103 -0
  45. data/spec/sexy_form/themes/milligram_spec.rb +120 -0
  46. data/spec/sexy_form/themes/semantic_ui_inline_spec.rb +105 -0
  47. data/spec/sexy_form/themes/semantic_ui_vertical_spec.rb +105 -0
  48. data/spec/sexy_form/themes/theme_spec_helper.rb +0 -0
  49. data/spec/sexy_form/themes_spec.rb +52 -0
  50. data/spec/sexy_form_spec.rb +54 -0
  51. data/spec/spec_helper.rb +16 -0
  52. metadata +160 -0
@@ -0,0 +1,22 @@
1
+ module SexyForm
2
+ module Themes
3
+
4
+ def self.classes
5
+ ObjectSpace.each_object(Class).select{|klass| klass < SexyForm::Themes::BaseTheme }.sort_by{|x| x.name}
6
+ end
7
+
8
+ def self.from_name(name)
9
+ name = name.to_s
10
+
11
+ classes.each do |klass|
12
+ if klass.theme_name == name
13
+ return klass
14
+ end
15
+ end
16
+
17
+ raise ArgumentError.new("SexyForm theme `#{name}` was not found")
18
+ end
19
+
20
+ end
21
+
22
+ end
@@ -0,0 +1,39 @@
1
+ module SexyForm
2
+ module Themes
3
+ class BaseTheme
4
+
5
+ def self.theme_name
6
+ the_name = self.name.to_s.split("::").last
7
+
8
+ underscored_name = the_name
9
+ .gsub(/::/, '/')
10
+ .gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
11
+ .gsub(/([a-z\d])([A-Z])/,'\1_\2')
12
+ .tr("-", "_")
13
+ .downcase
14
+
15
+ underscored_name
16
+ end
17
+
18
+ # abstract def wrap_field(
19
+ # field_type : String,
20
+ # html_field : String,
21
+ # html_label : String?,
22
+ # html_help_text : String?,
23
+ # html_errors : Array(String)?,
24
+ # wrapper_html_attributes : StringHash,
25
+ # ) : String
26
+
27
+ # abstract def input_html_attributes(html_attrs : StringHash, field_type : String, has_errors? : Bool) : StringHash
28
+
29
+ # abstract def label_html_attributes(html_attrs : StringHash, field_type : String, has_errors? : Bool) : StringHash
30
+
31
+ # abstract def form_html_attributes(html_attrs : StringHash) : StringHash
32
+
33
+ # abstract def build_html_help_text(help_text : String, html_attrs : StringHash, field_type : String) : String
34
+
35
+ # abstract def build_html_error(error : String, html_attrs : StringHash, field_type : String) : String
36
+
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,83 @@
1
+ module SexyForm
2
+ module Themes
3
+ class Bootstrap2Horizontal < BaseTheme
4
+
5
+ def self.theme_name
6
+ "bootstrap_2_horizontal"
7
+ end
8
+
9
+ def wrap_field(field_type:, html_field:, html_label:, html_help_text: nil, html_errors: nil, wrapper_html_attributes:)
10
+ s = ""
11
+
12
+ wrapper_html_attributes["class"] = "control-group#{" error" if html_errors} #{wrapper_html_attributes["class"]}".strip
13
+
14
+ attr_str = SexyForm.build_html_attr_string(wrapper_html_attributes)
15
+ s << "#{attr_str.empty? ? "<div>" : "<div #{attr_str}>"}"
16
+
17
+ if ["checkbox", "radio"].include?(field_type)
18
+ s << %Q(<div class="controls">)
19
+
20
+ if html_label
21
+ s << html_label.sub("\">", "\">#{html_field} ")
22
+ else
23
+ s << "#{html_field}"
24
+ end
25
+ else
26
+ s << "#{html_label}"
27
+ s << %Q(<div class="controls">)
28
+ s << "#{html_field}"
29
+ end
30
+
31
+ s << "#{html_help_text}"
32
+ s << html_errors.join if html_errors
33
+
34
+ s << "</div>"
35
+ s << "</div>"
36
+
37
+ s
38
+ end
39
+
40
+ def input_html_attributes(html_attrs:, field_type:, has_errors:)
41
+ html_attrs
42
+ end
43
+
44
+ def label_html_attributes(html_attrs:, field_type:, has_errors:)
45
+ html_attrs["class"] ||= ""
46
+
47
+ if ["checkbox", "radio"].include?(field_type)
48
+ html_attrs["class"] = "#{field_type} #{html_attrs["class"]}".strip
49
+ else
50
+ html_attrs["class"] = "control-label #{html_attrs["class"]}".strip
51
+ end
52
+
53
+ html_attrs
54
+ end
55
+
56
+ def form_html_attributes(html_attrs:)
57
+ html_attrs["class"] = "form-horizontal #{html_attrs["class"]}".strip
58
+ html_attrs
59
+ end
60
+
61
+ def build_html_help_text(help_text:, html_attrs:, field_type:)
62
+ html_attrs["class"] = "help-block #{html_attrs["class"]}".strip
63
+
64
+ s = ""
65
+ s << (html_attrs.empty? ? "<span>" : "<span #{SexyForm.build_html_attr_string(html_attrs)}>")
66
+ s << "#{help_text}"
67
+ s << "</span>"
68
+ s
69
+ end
70
+
71
+ def build_html_error(error:, html_attrs:, field_type:)
72
+ html_attrs["class"] = "help-block #{html_attrs["class"]}".strip
73
+
74
+ s = ""
75
+ s << (html_attrs.empty? ? "<span>" : "<span #{SexyForm.build_html_attr_string(html_attrs)}>")
76
+ s << "#{error}"
77
+ s << "</span>"
78
+ s
79
+ end
80
+
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,73 @@
1
+ module SexyForm
2
+ module Themes
3
+ class Bootstrap2Inline < BaseTheme
4
+
5
+ def self.theme_name
6
+ "bootstrap_2_inline"
7
+ end
8
+
9
+ def wrap_field(field_type:, html_field:, html_label:, html_help_text: nil, html_errors: nil, wrapper_html_attributes:)
10
+ s = ""
11
+
12
+ if html_errors
13
+ wrapper_html_attributes["class"] = "error #{wrapper_html_attributes["class"]}".strip
14
+ end
15
+
16
+ attr_str = SexyForm.build_html_attr_string(wrapper_html_attributes)
17
+ s << "#{attr_str.empty? ? "<div>" : "<div #{attr_str}>"}"
18
+
19
+ if ["checkbox", "radio"].include?(field_type) && html_label
20
+ s << html_label.sub("\">", "\">#{html_field} ")
21
+ else
22
+ s << "#{html_label}"
23
+ s << "#{html_field}"
24
+ end
25
+
26
+ s << "#{html_help_text}"
27
+ s << html_errors.join if html_errors
28
+
29
+ s << "</div>"
30
+
31
+ s
32
+ end
33
+
34
+ def input_html_attributes(html_attrs:, field_type:, has_errors:)
35
+ html_attrs
36
+ end
37
+
38
+ def label_html_attributes(html_attrs:, field_type:, has_errors:)
39
+ if ["checkbox", "radio"].include?(field_type)
40
+ html_attrs["class"] = "#{field_type} #{html_attrs["class"]}".strip
41
+ end
42
+
43
+ html_attrs
44
+ end
45
+
46
+ def form_html_attributes(html_attrs:)
47
+ html_attrs["class"] = "form-inline #{html_attrs["class"]}".strip
48
+ html_attrs
49
+ end
50
+
51
+ def build_html_help_text(help_text:, html_attrs:, field_type:)
52
+ html_attrs["class"] = "help-block #{html_attrs["class"]}".strip
53
+
54
+ s = ""
55
+ s << (html_attrs.empty? ? "<span>" : "<span #{SexyForm.build_html_attr_string(html_attrs)}>")
56
+ s << "#{help_text}"
57
+ s << "</span>"
58
+ s
59
+ end
60
+
61
+ def build_html_error(error:, html_attrs:, field_type:)
62
+ html_attrs["class"] = "help-block #{html_attrs["class"]}".strip
63
+
64
+ s = ""
65
+ s << (html_attrs.empty? ? "<span>" : "<span #{SexyForm.build_html_attr_string(html_attrs)}>")
66
+ s << "#{error}"
67
+ s << "</span>"
68
+ s
69
+ end
70
+
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,80 @@
1
+ module SexyForm
2
+ module Themes
3
+ class Bootstrap2Vertical < BaseTheme
4
+
5
+ def self.theme_name
6
+ "bootstrap_2_vertical"
7
+ end
8
+
9
+ def wrap_field(field_type:, html_field:, html_label:, html_help_text: nil, html_errors: nil, wrapper_html_attributes:)
10
+ s = ""
11
+
12
+ wrapper_html_attributes["class"] = "control-group#{" error" if html_errors} #{wrapper_html_attributes["class"]}".strip
13
+
14
+ attr_str = SexyForm.build_html_attr_string(wrapper_html_attributes)
15
+ s << "#{attr_str.empty? ? "<div>" : "<div #{attr_str}>"}"
16
+
17
+ if ["checkbox", "radio"].include?(field_type)
18
+ s << %Q(<div class="controls">)
19
+
20
+ if html_label
21
+ s << html_label.sub("\">", "\">#{html_field} ")
22
+ else
23
+ s << "#{html_field}"
24
+ end
25
+ else
26
+ s << "#{html_label}"
27
+ s << %Q(<div class="controls">)
28
+ s << "#{html_field}"
29
+ end
30
+
31
+ s << "#{html_help_text}"
32
+ s << html_errors.join if html_errors
33
+
34
+ s << "</div>"
35
+ s << "</div>"
36
+
37
+ s
38
+ end
39
+
40
+ def input_html_attributes(html_attrs:, field_type:, has_errors:)
41
+ html_attrs
42
+ end
43
+
44
+ def label_html_attributes(html_attrs:, field_type:, has_errors:)
45
+ if ["checkbox", "radio"].include?(field_type)
46
+ html_attrs["class"] = "#{field_type} #{html_attrs["class"]}".strip
47
+ else
48
+ html_attrs["class"] = "control-label #{html_attrs["class"]}".strip
49
+ end
50
+
51
+ html_attrs
52
+ end
53
+
54
+ def form_html_attributes(html_attrs:)
55
+ html_attrs
56
+ end
57
+
58
+ def build_html_help_text(help_text:, html_attrs:, field_type:)
59
+ html_attrs["class"] = "help-block #{html_attrs["class"]}".strip
60
+
61
+ s = ""
62
+ s << (html_attrs.empty? ? "<span>" : "<span #{SexyForm.build_html_attr_string(html_attrs)}>")
63
+ s << "#{help_text}"
64
+ s << "</span>"
65
+ s
66
+ end
67
+
68
+ def build_html_error(error:, html_attrs:, field_type:)
69
+ html_attrs["class"] = "help-block #{html_attrs["class"]}".strip
70
+
71
+ s = ""
72
+ s << (html_attrs.empty? ? "<span>" : "<span #{SexyForm.build_html_attr_string(html_attrs)}>")
73
+ s << "#{error}"
74
+ s << "</span>"
75
+ s
76
+ end
77
+
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,95 @@
1
+ module SexyForm
2
+ module Themes
3
+ class Bootstrap3Horizontal < BaseTheme
4
+
5
+ def self.theme_name
6
+ "bootstrap_3_horizontal"
7
+ end
8
+
9
+ def initialize(column_classes: ["col-sm-3", "col-sm-9"])
10
+ @column_classes = column_classes.first(2)
11
+
12
+ s = "#{@column_classes[0]}"
13
+ @offset_class = (i = s.index(/-\d/)) ? s.insert(i+1, "offset-") : ""
14
+ end
15
+
16
+ def wrap_field(field_type:, html_field:, html_label:, html_help_text: nil, html_errors: nil, wrapper_html_attributes:)
17
+ s = ""
18
+
19
+ wrapper_html_attributes["class"] = "form-group#{" has-error" if html_errors} #{wrapper_html_attributes["class"]}".strip
20
+
21
+ attr_str = SexyForm.build_html_attr_string(wrapper_html_attributes)
22
+ s << "#{attr_str.empty? ? "<div>" : "<div #{attr_str}>"}"
23
+
24
+ if ["checkbox", "radio"].include?(field_type)
25
+ s << %Q(<div class="#{@offset_class} #{@column_classes[1]}">)
26
+ s << %Q(<div class="#{field_type}">)
27
+
28
+ if html_label
29
+ s << html_label.sub("\">", "\">#{html_field} ")
30
+ else
31
+ s << "#{html_field}"
32
+ end
33
+ s << "#{html_help_text}"
34
+ s << html_errors.join if html_errors
35
+
36
+ s << "</div>"
37
+ s << "</div>"
38
+ else
39
+ s << "#{html_label}"
40
+ s << %Q(<div class="#{"#{@offset_class} " unless html_label}#{@column_classes[1]}">)
41
+ s << "#{html_field}"
42
+ s << "#{html_help_text}"
43
+
44
+ if html_errors
45
+ s << html_errors.join
46
+ end
47
+
48
+ s << "</div>"
49
+ end
50
+
51
+ s << "</div>"
52
+
53
+ s
54
+ end
55
+
56
+ def input_html_attributes(html_attrs:, field_type:, has_errors:)
57
+ html_attrs
58
+ end
59
+
60
+ def label_html_attributes(html_attrs:, field_type:, has_errors:)
61
+ unless ["checkbox", "radio"].include?(field_type)
62
+ html_attrs["class"] = " #{@column_classes[0]} control-label #{html_attrs["class"]}".strip
63
+ end
64
+
65
+ html_attrs
66
+ end
67
+
68
+ def form_html_attributes(html_attrs:)
69
+ html_attrs["class"] = "form-horizontal #{html_attrs["class"]}".strip
70
+ html_attrs
71
+ end
72
+
73
+ def build_html_help_text(help_text:, html_attrs:, field_type:)
74
+ html_attrs["class"] = "help-block #{html_attrs["class"]}".strip
75
+
76
+ s = ""
77
+ s << (html_attrs.empty? ? "<span>" : "<span #{SexyForm.build_html_attr_string(html_attrs)}>")
78
+ s << "#{help_text}"
79
+ s << "</span>"
80
+ s
81
+ end
82
+
83
+ def build_html_error(error:, html_attrs:, field_type:)
84
+ html_attrs["class"] = "help-block #{html_attrs["class"]}".strip
85
+
86
+ s = ""
87
+ s << (html_attrs.empty? ? "<span>" : "<span #{SexyForm.build_html_attr_string(html_attrs)}>")
88
+ s << "#{error}"
89
+ s << "</span>"
90
+ s
91
+ end
92
+
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,71 @@
1
+ module SexyForm
2
+ module Themes
3
+ class Bootstrap3Inline < BaseTheme
4
+
5
+ def self.theme_name
6
+ "bootstrap_3_inline"
7
+ end
8
+
9
+ def wrap_field(field_type:, html_field:, html_label:, html_help_text: nil, html_errors: nil, wrapper_html_attributes:)
10
+ s = ""
11
+
12
+ wrapper_html_attributes["class"] = "form-group#{" has-error" if html_errors} #{wrapper_html_attributes["class"]}".strip
13
+
14
+ attr_str = SexyForm.build_html_attr_string(wrapper_html_attributes)
15
+ s << "#{attr_str.empty? ? "<div>" : "<div #{attr_str}>"}"
16
+
17
+ if ["checkbox", "radio"].include?(field_type)
18
+ if html_label
19
+ s << html_label.sub("\">", "\">#{html_field} ")
20
+ else
21
+ s << "#{html_field}"
22
+ end
23
+ else
24
+ s << "#{html_label}"
25
+ s << "#{html_field}"
26
+ end
27
+
28
+ s << "#{html_help_text}"
29
+ s << html_errors.join if html_errors
30
+
31
+ s << "</div>"
32
+
33
+ s
34
+ end
35
+
36
+ def input_html_attributes(html_attrs:, field_type:, has_errors:)
37
+ html_attrs
38
+ end
39
+
40
+ def label_html_attributes(html_attrs:, field_type:, has_errors:)
41
+ html_attrs
42
+ end
43
+
44
+ def form_html_attributes(html_attrs:)
45
+ html_attrs["class"] = "form-inline #{html_attrs["class"]}".strip
46
+ html_attrs
47
+ end
48
+
49
+ def build_html_help_text(help_text:, html_attrs:, field_type:)
50
+ html_attrs["class"] = "help-block #{html_attrs["class"]}".strip
51
+
52
+ s = ""
53
+ s << (html_attrs.empty? ? "<span>" : "<span #{SexyForm.build_html_attr_string(html_attrs)}>")
54
+ s << "#{help_text}"
55
+ s << "</span>"
56
+ s
57
+ end
58
+
59
+ def build_html_error(error:, html_attrs:, field_type:)
60
+ html_attrs["class"] = "help-block #{html_attrs["class"]}".strip
61
+
62
+ s = ""
63
+ s << (html_attrs.empty? ? "<span>" : "<span #{SexyForm.build_html_attr_string(html_attrs)}>")
64
+ s << "#{error}"
65
+ s << "</span>"
66
+ s
67
+ end
68
+
69
+ end
70
+ end
71
+ end