sexy_form 0.9.0

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 (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