formnestic 1.0.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.
- data/.document +5 -0
- data/.rspec +2 -0
- data/.travis.yml +5 -0
- data/.watchr +31 -0
- data/Gemfile +27 -0
- data/Gemfile.lock +133 -0
- data/MIT-LICENSE +20 -0
- data/README.markdown +126 -0
- data/Rakefile +44 -0
- data/VERSION +1 -0
- data/app/assets/.DS_Store +0 -0
- data/app/assets/javascripts/formnestic/formnestic.js +139 -0
- data/app/assets/stylesheets/formnestic/entypo.css.scss +327 -0
- data/app/assets/stylesheets/formnestic/entypo.eot +0 -0
- data/app/assets/stylesheets/formnestic/entypo.svg +296 -0
- data/app/assets/stylesheets/formnestic/entypo.ttf +0 -0
- data/app/assets/stylesheets/formnestic/entypo.woff +0 -0
- data/app/assets/stylesheets/formnestic/formnestic.css.scss +167 -0
- data/config/locales/formnestic.en.yml +8 -0
- data/formnestic.gemspec +112 -0
- data/lib/formnestic/form_builder/base_builder.rb +55 -0
- data/lib/formnestic/form_builder/list_form_builder.rb +30 -0
- data/lib/formnestic/form_builder/table_form_builder.rb +94 -0
- data/lib/formnestic/form_builder.rb +13 -0
- data/lib/formnestic/helpers/inputs_helper.rb +82 -0
- data/lib/formnestic/helpers.rb +9 -0
- data/lib/formnestic/inputs/base/labelling.rb +15 -0
- data/lib/formnestic/inputs/base/wrapping.rb +52 -0
- data/lib/formnestic/inputs/base.rb +12 -0
- data/lib/formnestic/inputs.rb +7 -0
- data/lib/formnestic.rb +72 -0
- data/lib/generators/formnestic/install_generator.rb +36 -0
- data/log/development.log +0 -0
- data/rwatchr +1 -0
- data/screenshots/list_form.png +0 -0
- data/screenshots/table_form.png +0 -0
- data/spec/helpers/nested_model_helper_spec.rb +277 -0
- data/spec/helpers/nested_model_list_helper_spec.rb +51 -0
- data/spec/inputs/boolean_input_spec.rb +223 -0
- data/spec/spec_helper.rb +553 -0
- data/spec/support/custom_macros.rb +528 -0
- data/spec/support/deferred_garbage_collection.rb +21 -0
- data/spec/support/deprecation.rb +6 -0
- data/spec/support/test_environment.rb +31 -0
- metadata +271 -0
@@ -0,0 +1,167 @@
|
|
1
|
+
@import 'entypo';
|
2
|
+
|
3
|
+
form.formtastic .stringish input {
|
4
|
+
border: 1px solid #ccc;
|
5
|
+
padding: 5px;
|
6
|
+
font-size: 12px;
|
7
|
+
}
|
8
|
+
|
9
|
+
form.formtastic .text textarea {
|
10
|
+
border: 1px solid #ccc;
|
11
|
+
padding: 5px;
|
12
|
+
font-size: 12px;
|
13
|
+
height: 50px;
|
14
|
+
}
|
15
|
+
|
16
|
+
div.formnestic-nested-model-container fieldset.formnestic-li-fieldset {
|
17
|
+
position: relative;
|
18
|
+
margin-bottom: 15px;
|
19
|
+
border-bottom: 1px dashed #ccc;
|
20
|
+
div.formnestic-li-fieldset-legend {
|
21
|
+
background: #346A89;
|
22
|
+
color: #fff;
|
23
|
+
padding: 10px;
|
24
|
+
position: relative;
|
25
|
+
margin-bottom: 10px;
|
26
|
+
}
|
27
|
+
div.formnestic-minus-button-container {
|
28
|
+
position: absolute;
|
29
|
+
top: 7px;
|
30
|
+
right: 0;
|
31
|
+
font-size: 20px;
|
32
|
+
color: #fff;
|
33
|
+
cursor: pointer;
|
34
|
+
}
|
35
|
+
|
36
|
+
}
|
37
|
+
|
38
|
+
div.formnestic-nested-model-container {
|
39
|
+
input[type=text], input[type=number] {
|
40
|
+
border: 1px solid #ccc;
|
41
|
+
padding: 5px;
|
42
|
+
font-size: 12px;
|
43
|
+
}
|
44
|
+
textarea {
|
45
|
+
padding: 5px;
|
46
|
+
border: 1px solid #ccc;
|
47
|
+
height: 50px;
|
48
|
+
}
|
49
|
+
|
50
|
+
div.formnestic-list-new-entry-link-container {
|
51
|
+
margin-bottom: 10px;
|
52
|
+
text-align: right;
|
53
|
+
margin-top: 10px;
|
54
|
+
a {
|
55
|
+
border-radius: 5px;
|
56
|
+
background: #4C88AA;
|
57
|
+
color: #fff;
|
58
|
+
padding: 5px;
|
59
|
+
text-decoration: none;
|
60
|
+
}
|
61
|
+
}
|
62
|
+
}
|
63
|
+
|
64
|
+
table.formnestic-table-inputs {
|
65
|
+
width: 100%;
|
66
|
+
}
|
67
|
+
|
68
|
+
table.formnestic-table-inputs thead th {
|
69
|
+
padding: 5px;
|
70
|
+
background: #333;
|
71
|
+
color: #fff;
|
72
|
+
}
|
73
|
+
|
74
|
+
table.formnestic-table-inputs tbody td {
|
75
|
+
padding: 5px;
|
76
|
+
border-bottom: 1px solid #ccc;
|
77
|
+
input[type=text] {
|
78
|
+
border: 1px solid #ccc;
|
79
|
+
padding: 5px;
|
80
|
+
font-size: 12px;
|
81
|
+
width: 100%;
|
82
|
+
box-sizing: border-box;
|
83
|
+
}
|
84
|
+
|
85
|
+
p.inline-errors {
|
86
|
+
margin-top: 2px;
|
87
|
+
color: #c00;
|
88
|
+
margin-left: 0;
|
89
|
+
line-height: 1.5;
|
90
|
+
}
|
91
|
+
}
|
92
|
+
|
93
|
+
table.formnestic-table-inputs tbody tr.inputs {
|
94
|
+
td {
|
95
|
+
padding: 5px;
|
96
|
+
vertical-align: top;
|
97
|
+
p.inline-hints {
|
98
|
+
margin-left: 0;
|
99
|
+
}
|
100
|
+
}
|
101
|
+
&.formnestic-odd-row td {
|
102
|
+
background: #eee;
|
103
|
+
}
|
104
|
+
|
105
|
+
&.formnestic-even-row td {
|
106
|
+
}
|
107
|
+
}
|
108
|
+
|
109
|
+
table.formnestic-table-inputs td.date_select ol.fragments-group {
|
110
|
+
list-style-type: none;
|
111
|
+
}
|
112
|
+
|
113
|
+
table.formnestic-table-inputs td.date_select ol.fragments-group li.fragment {
|
114
|
+
float: left;
|
115
|
+
margin-right: 5px;
|
116
|
+
}
|
117
|
+
|
118
|
+
table.formnestic-table-inputs thead tr th.formnestic-minus-thead {
|
119
|
+
width: 20px;
|
120
|
+
}
|
121
|
+
|
122
|
+
table.formnestic-table-inputs tbody tr td.formnestic-minus-button-cell {
|
123
|
+
}
|
124
|
+
|
125
|
+
table.formnestic-table-inputs tbody tr td.boolean label {
|
126
|
+
padding-left: 0;
|
127
|
+
}
|
128
|
+
|
129
|
+
table.formnestic-table-inputs tbody tr.formnestic-table-no-border td {
|
130
|
+
text-align: right;
|
131
|
+
border: 0 none;
|
132
|
+
padding-right: 0;
|
133
|
+
background: none;
|
134
|
+
}
|
135
|
+
|
136
|
+
table.formnestic-table-inputs tbody tr td.formnestic-minus-button-cell div.formnestic-table-minus-button {
|
137
|
+
width: 20px;
|
138
|
+
height: 20px;
|
139
|
+
cursor: pointer;
|
140
|
+
font-size: 18px;
|
141
|
+
color: #999;
|
142
|
+
-webkit-transition: all 0.5s; /* For Safari 3.1 to 6.0 */
|
143
|
+
transition: all 0.5s;
|
144
|
+
&:hover {
|
145
|
+
color: #333;
|
146
|
+
}
|
147
|
+
}
|
148
|
+
|
149
|
+
table.formnestic-table-inputs tbody a.formnestic-add-row-field-link {
|
150
|
+
text-decoration: none;
|
151
|
+
background: #A1C988;
|
152
|
+
padding: 5px 10px;
|
153
|
+
color: #fff;
|
154
|
+
margin-top: 10px;
|
155
|
+
line-height: 30px;
|
156
|
+
border-radius: 5px;
|
157
|
+
-webkit-transition: all 0.5s; /* For Safari 3.1 to 6.0 */
|
158
|
+
transition: all 0.5s;
|
159
|
+
|
160
|
+
&:hover {
|
161
|
+
background: #89BC69;
|
162
|
+
};
|
163
|
+
}
|
164
|
+
|
165
|
+
.formnestic-hidden {
|
166
|
+
display: none;
|
167
|
+
}
|
@@ -0,0 +1,8 @@
|
|
1
|
+
en:
|
2
|
+
formnestic:
|
3
|
+
labels:
|
4
|
+
remove_this_entry: Remove this entry
|
5
|
+
there_must_be_at_least_a_number_of_entries:
|
6
|
+
one: "Unable to remove %{entity_singular}. There must be at least 1 %{entity_singular}"
|
7
|
+
other: "Unable to remove %{entity_singular}. There must be at least %{count} %{entity_plural}"
|
8
|
+
add_new_entry: "+ new entry"
|
data/formnestic.gemspec
ADDED
@@ -0,0 +1,112 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = "formnestic"
|
8
|
+
s.version = "1.0.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["James"]
|
12
|
+
s.date = "2014-06-20"
|
13
|
+
s.description = "An extension of famous Formtastic Form Builder to make building nested and association form with nested model addable and removable ability extremely easy and simple"
|
14
|
+
s.email = "james@rubify.com"
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"README.markdown"
|
17
|
+
]
|
18
|
+
s.files = [
|
19
|
+
".document",
|
20
|
+
".rspec",
|
21
|
+
".travis.yml",
|
22
|
+
".watchr",
|
23
|
+
"Gemfile",
|
24
|
+
"Gemfile.lock",
|
25
|
+
"MIT-LICENSE",
|
26
|
+
"README.markdown",
|
27
|
+
"Rakefile",
|
28
|
+
"VERSION",
|
29
|
+
"app/assets/.DS_Store",
|
30
|
+
"app/assets/javascripts/formnestic/formnestic.js",
|
31
|
+
"app/assets/stylesheets/formnestic/entypo.css.scss",
|
32
|
+
"app/assets/stylesheets/formnestic/entypo.eot",
|
33
|
+
"app/assets/stylesheets/formnestic/entypo.svg",
|
34
|
+
"app/assets/stylesheets/formnestic/entypo.ttf",
|
35
|
+
"app/assets/stylesheets/formnestic/entypo.woff",
|
36
|
+
"app/assets/stylesheets/formnestic/formnestic.css.scss",
|
37
|
+
"config/locales/formnestic.en.yml",
|
38
|
+
"formnestic.gemspec",
|
39
|
+
"lib/formnestic.rb",
|
40
|
+
"lib/formnestic/form_builder.rb",
|
41
|
+
"lib/formnestic/form_builder/base_builder.rb",
|
42
|
+
"lib/formnestic/form_builder/list_form_builder.rb",
|
43
|
+
"lib/formnestic/form_builder/table_form_builder.rb",
|
44
|
+
"lib/formnestic/helpers.rb",
|
45
|
+
"lib/formnestic/helpers/inputs_helper.rb",
|
46
|
+
"lib/formnestic/inputs.rb",
|
47
|
+
"lib/formnestic/inputs/base.rb",
|
48
|
+
"lib/formnestic/inputs/base/labelling.rb",
|
49
|
+
"lib/formnestic/inputs/base/wrapping.rb",
|
50
|
+
"lib/generators/formnestic/install_generator.rb",
|
51
|
+
"log/development.log",
|
52
|
+
"rwatchr",
|
53
|
+
"screenshots/list_form.png",
|
54
|
+
"screenshots/table_form.png",
|
55
|
+
"spec/helpers/nested_model_helper_spec.rb",
|
56
|
+
"spec/helpers/nested_model_list_helper_spec.rb",
|
57
|
+
"spec/inputs/boolean_input_spec.rb",
|
58
|
+
"spec/spec_helper.rb",
|
59
|
+
"spec/support/custom_macros.rb",
|
60
|
+
"spec/support/deferred_garbage_collection.rb",
|
61
|
+
"spec/support/deprecation.rb",
|
62
|
+
"spec/support/test_environment.rb"
|
63
|
+
]
|
64
|
+
s.homepage = "http://github.com/jameshuynh/formnestic"
|
65
|
+
s.licenses = ["MIT"]
|
66
|
+
s.require_paths = ["lib"]
|
67
|
+
s.rubygems_version = "1.8.23"
|
68
|
+
s.summary = "An extension of formtastic form builder gem"
|
69
|
+
|
70
|
+
if s.respond_to? :specification_version then
|
71
|
+
s.specification_version = 3
|
72
|
+
|
73
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
74
|
+
s.add_runtime_dependency(%q<actionpack>, [">= 3.2.13"])
|
75
|
+
s.add_runtime_dependency(%q<formtastic>, ["~> 2.2.1"])
|
76
|
+
s.add_development_dependency(%q<shoulda>, [">= 0"])
|
77
|
+
s.add_development_dependency(%q<bundler>, ["~> 1.0"])
|
78
|
+
s.add_development_dependency(%q<rdoc>, ["~> 3.4"])
|
79
|
+
s.add_development_dependency(%q<jeweler>, ["~> 2.0.1"])
|
80
|
+
s.add_development_dependency(%q<rspec-rails>, ["~> 2.14.0"])
|
81
|
+
s.add_development_dependency(%q<rspec_tag_matchers>, [">= 1.0.0"])
|
82
|
+
s.add_development_dependency(%q<tzinfo>, [">= 0"])
|
83
|
+
s.add_development_dependency(%q<spork>, [">= 0"])
|
84
|
+
s.add_development_dependency(%q<watchr>, [">= 0"])
|
85
|
+
else
|
86
|
+
s.add_dependency(%q<actionpack>, [">= 3.2.13"])
|
87
|
+
s.add_dependency(%q<formtastic>, ["~> 2.2.1"])
|
88
|
+
s.add_dependency(%q<shoulda>, [">= 0"])
|
89
|
+
s.add_dependency(%q<bundler>, ["~> 1.0"])
|
90
|
+
s.add_dependency(%q<rdoc>, ["~> 3.4"])
|
91
|
+
s.add_dependency(%q<jeweler>, ["~> 2.0.1"])
|
92
|
+
s.add_dependency(%q<rspec-rails>, ["~> 2.14.0"])
|
93
|
+
s.add_dependency(%q<rspec_tag_matchers>, [">= 1.0.0"])
|
94
|
+
s.add_dependency(%q<tzinfo>, [">= 0"])
|
95
|
+
s.add_dependency(%q<spork>, [">= 0"])
|
96
|
+
s.add_dependency(%q<watchr>, [">= 0"])
|
97
|
+
end
|
98
|
+
else
|
99
|
+
s.add_dependency(%q<actionpack>, [">= 3.2.13"])
|
100
|
+
s.add_dependency(%q<formtastic>, ["~> 2.2.1"])
|
101
|
+
s.add_dependency(%q<shoulda>, [">= 0"])
|
102
|
+
s.add_dependency(%q<bundler>, ["~> 1.0"])
|
103
|
+
s.add_dependency(%q<rdoc>, ["~> 3.4"])
|
104
|
+
s.add_dependency(%q<jeweler>, ["~> 2.0.1"])
|
105
|
+
s.add_dependency(%q<rspec-rails>, ["~> 2.14.0"])
|
106
|
+
s.add_dependency(%q<rspec_tag_matchers>, [">= 1.0.0"])
|
107
|
+
s.add_dependency(%q<tzinfo>, [">= 0"])
|
108
|
+
s.add_dependency(%q<spork>, [">= 0"])
|
109
|
+
s.add_dependency(%q<watchr>, [">= 0"])
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Formnestic
|
2
|
+
module FormBuilder
|
3
|
+
module BaseBuilder
|
4
|
+
|
5
|
+
def formnestic_min_entry_alert_message(record_or_name_or_array, min_entry)
|
6
|
+
entity_name = I18n.t("activerecord.models.#{record_or_name_or_array.to_s.singularize}", default: record_or_name_or_array.to_s.gsub("_", " ").singularize.singularize)
|
7
|
+
min_entry != -1 ? (options[:min_entry_alert_message] ||
|
8
|
+
I18n.t('formnestic.labels.there_must_be_at_least_a_number_of_entries', {
|
9
|
+
count: min_entry,
|
10
|
+
entity_singular: entity_name,
|
11
|
+
entity_plural: entity_name.pluralize})) : ''
|
12
|
+
end
|
13
|
+
|
14
|
+
def formnestic_add_rows_counter_related_attributes
|
15
|
+
instance_eval do
|
16
|
+
instance_variable_set("@rows_counter", 0)
|
17
|
+
def rows_counter
|
18
|
+
return @rows_counter
|
19
|
+
end
|
20
|
+
|
21
|
+
def increase_rows_counter
|
22
|
+
@rows_counter += 1
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def formnestic_link_to_add_fields_with_content(record_or_name_or_array, *args, &block)
|
28
|
+
new_object = self.object.class.reflect_on_association(record_or_name_or_array).klass.new
|
29
|
+
options = args.dup.extract_options!
|
30
|
+
options[:max_entry] ||= -1
|
31
|
+
duplicate_args = args.dup
|
32
|
+
duplicate_args = duplicate_args.unshift(new_object)
|
33
|
+
new_record_form_options = duplicate_args.extract_options!
|
34
|
+
rows_counter = self.rows_counter
|
35
|
+
new_record_form_options[:child_index] = "new_#{record_or_name_or_array}"
|
36
|
+
new_record_form_content = formtastic_semantic_fields_for(record_or_name_or_array, *(duplicate_args << new_record_form_options), &block)
|
37
|
+
link_title = options[:new_record_link_label] || I18n.t("formnestic.labels.add_new_entry")
|
38
|
+
javascript_fn_to_call = js_call_for_nested_model_display_type(options[:display_type])
|
39
|
+
|
40
|
+
template.link_to(link_title, '#', onclick:
|
41
|
+
"Formnestic.#{javascript_fn_to_call}(this, \"#{record_or_name_or_array}\", \"#{escape_javascript(new_record_form_content)}\"); return false;", \
|
42
|
+
"class" => ["formnestic-add-row-field-link", options[:new_record_link_class], (options[:max_entry] != -1 and rows_counter >= options[:max_entry]) ? "formnestic-hidden" : nil].compact.join(" "))
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
def js_call_for_nested_model_display_type(display_type)
|
47
|
+
if display_type == 'table'
|
48
|
+
return 'addNewTableEntry'
|
49
|
+
else
|
50
|
+
return 'addNewListEntry'
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Formnestic
|
2
|
+
module FormBuilder
|
3
|
+
module ListFormBuilder
|
4
|
+
include Formnestic::FormBuilder::BaseBuilder
|
5
|
+
def formnestic_list_semantic_fields_for(record_or_name_or_array, *args, &block)
|
6
|
+
options = args.dup.extract_options!
|
7
|
+
|
8
|
+
formnestic_add_rows_counter_related_attributes
|
9
|
+
existing_rows = formtastic_semantic_fields_for(record_or_name_or_array, *args, &block)
|
10
|
+
contents = [template.content_tag(:div, existing_rows, class: "formnestic-list-entries-container")]
|
11
|
+
|
12
|
+
options[:min_entry] ||= -1
|
13
|
+
options[:max_entry] ||= -1
|
14
|
+
|
15
|
+
options[:min_entry_alert_message] = formnestic_min_entry_alert_message(record_or_name_or_array, options[:min_entry])
|
16
|
+
contents.push(formnestic_add_new_record_button_row_for_list_form(record_or_name_or_array, *args, &block)) if options[:row_addable]
|
17
|
+
options[:class] = [options[:class], "formnestic-nested-model-container"].compact.join
|
18
|
+
|
19
|
+
template.content_tag(:div,
|
20
|
+
contents.join.html_safe,
|
21
|
+
options.except(:builder, :parent, :name, :parent_builder, :display_type, :row_removable, :new_record_link_label, :child_index)
|
22
|
+
)
|
23
|
+
end
|
24
|
+
|
25
|
+
def formnestic_add_new_record_button_row_for_list_form(record_or_name_or_array, *args, &block)
|
26
|
+
template.content_tag(:div, formnestic_link_to_add_fields_with_content(record_or_name_or_array, *args, &block), class: "formnestic-list-new-entry-link-container")
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
module Formnestic
|
2
|
+
module FormBuilder
|
3
|
+
module TableFormBuilder
|
4
|
+
include Formnestic::FormBuilder::BaseBuilder
|
5
|
+
|
6
|
+
def formnestic_table_semantic_fields_for(record_or_name_or_array, *args, &block)
|
7
|
+
options = args.dup.extract_options!
|
8
|
+
formnestic_add_table_headers_form_attributes
|
9
|
+
formnestic_add_rows_counter_related_attributes
|
10
|
+
|
11
|
+
child_form_builder = nil
|
12
|
+
contents = [formtastic_semantic_fields_for(record_or_name_or_array, *args, &lambda {|nested_form_builder|
|
13
|
+
child_form_builder = nested_form_builder
|
14
|
+
block.call(nested_form_builder)
|
15
|
+
})]
|
16
|
+
|
17
|
+
contents.push(formnestic_add_new_record_button_row_for_table(record_or_name_or_array, *args, &block)) if options[:row_addable]
|
18
|
+
options[:class] = ["formnestic-table-inputs formnestic-nested-model", options[:class]].compact.join(" ")
|
19
|
+
options[:min_entry] ||= -1
|
20
|
+
options[:max_entry] ||= -1
|
21
|
+
options[:min_entry_alert_message] = formnestic_min_entry_alert_message(record_or_name_or_array, options[:min_entry])
|
22
|
+
|
23
|
+
### Finally, wrap everything inside a table tag
|
24
|
+
template.content_tag(:table, [
|
25
|
+
formnestic_table_header(options, record_or_name_or_array, child_form_builder), # table header
|
26
|
+
template.content_tag(:tbody, Formtastic::Util.html_safe(contents.join)) # table body
|
27
|
+
].join.html_safe,
|
28
|
+
options.except(:builder, :parent, :name, :parent_builder, :display_type, :row_removable, :new_record_link_label, :table_headers)
|
29
|
+
)
|
30
|
+
end
|
31
|
+
|
32
|
+
def formnestic_add_table_headers_form_attributes
|
33
|
+
instance_eval do
|
34
|
+
instance_variable_set("@table_headers", [])
|
35
|
+
def table_headers
|
36
|
+
return @table_headers
|
37
|
+
end
|
38
|
+
|
39
|
+
def add_table_header(column_name, class_name, label_text)
|
40
|
+
if @table_headers.detect{|x| x[:attr] == column_name}.nil?
|
41
|
+
@table_headers.push({attr: column_name, class: class_name.to_s.tableize.gsub("formtastic/inputs/", "").gsub("_", "-").gsub("-inputs", ""), label_text: label_text})
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def formnestic_add_new_record_button_row_for_table(record_or_name_or_array, *args, &block)
|
48
|
+
template.content_tag(:tr, template.content_tag(:td, formnestic_link_to_add_fields_with_content(record_or_name_or_array, *args, &block), {colspan: "100%"}), class: "formnestic-table-no-border")
|
49
|
+
end
|
50
|
+
|
51
|
+
def formnestic_table_header(header_options, record_or_name_or_array, child_form_builder)
|
52
|
+
association_name = record_or_name_or_array.is_a?(Array) ? record_or_name_or_array[0] : record_or_name_or_array
|
53
|
+
thead_contents = if header_options[:table_headers]
|
54
|
+
formnestic_thead_contents_from_arguments(header_options[:table_headers], record_or_name_or_array, child_form_builder)
|
55
|
+
else
|
56
|
+
formnestic_thead_contents_from_inputs(header_options[:row_removable])
|
57
|
+
end
|
58
|
+
return template.content_tag(:thead, thead_contents.join.html_safe)
|
59
|
+
end
|
60
|
+
|
61
|
+
def formnestic_thead_contents_from_inputs(row_removable)
|
62
|
+
tr_content_arr = []
|
63
|
+
table_headers.each do |header|
|
64
|
+
tr_content_arr.push(template.content_tag(:th, header[:label_text], class: header[:class]))
|
65
|
+
end
|
66
|
+
tr_content_arr.push(template.content_tag(:th, "", class: "formnestic-minus-thead")) if row_removable
|
67
|
+
[template.content_tag(:tr, tr_content_arr.join.html_safe)]
|
68
|
+
end
|
69
|
+
|
70
|
+
def formnestic_thead_contents_from_arguments(theads, record_or_name_or_array, child_form_builder)
|
71
|
+
thead_contents = []
|
72
|
+
theads.each do |el_arr|
|
73
|
+
tr_content_arr = []
|
74
|
+
el_arr.each_with_index do |el, index|
|
75
|
+
tr_content_arr.push(template.content_tag(:th, formnestic_table_thead_th_content(record_or_name_or_array, el, index + 1, child_form_builder), el[:wrapper_html] || {}))
|
76
|
+
end
|
77
|
+
thead_contents.push(template.content_tag(:tr, tr_content_arr.join.html_safe))
|
78
|
+
end
|
79
|
+
thead_contents
|
80
|
+
end
|
81
|
+
|
82
|
+
def formnestic_table_thead_th_content(record_or_name_or_array, table_header_element_opts, position, child_form_builder)
|
83
|
+
if table_header_element_opts[:attr].present?
|
84
|
+
input_base = Formtastic::Inputs::StringInput.new(child_form_builder, "", record_or_name_or_array, child_form_builder.object, table_header_element_opts[:attr], {})
|
85
|
+
return input_base.label_text
|
86
|
+
elsif table_header_element_opts[:label].present?
|
87
|
+
return table_header_element_opts[:label]
|
88
|
+
else
|
89
|
+
return "Column #{position}"
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Formnestic
|
2
|
+
module FormBuilder
|
3
|
+
include ActionView::Helpers::JavaScriptHelper
|
4
|
+
|
5
|
+
autoload :BaseBuilder, File.join(File.dirname(__FILE__), 'form_builder', 'base_builder')
|
6
|
+
autoload :TableFormBuilder, File.join(File.dirname(__FILE__), 'form_builder', 'table_form_builder')
|
7
|
+
autoload :ListFormBuilder, File.join(File.dirname(__FILE__), 'form_builder', 'list_form_builder')
|
8
|
+
|
9
|
+
include Formnestic::FormBuilder::TableFormBuilder
|
10
|
+
include Formnestic::FormBuilder::ListFormBuilder
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
module Formnestic
|
2
|
+
module Helpers
|
3
|
+
module InputsHelper
|
4
|
+
def inputs(*args, &block)
|
5
|
+
if options[:display_type] == 'table'
|
6
|
+
formnestic_table_row_inputs(*args, &block)
|
7
|
+
elsif options[:row_removable] or options[:row_addable]
|
8
|
+
formnestic_list_row_inputs(*args, &block)
|
9
|
+
else
|
10
|
+
formtastic_inputs(*args, &block)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
# for listing form
|
15
|
+
def formnestic_list_row_inputs(*args, &block)
|
16
|
+
html_options = args.extract_options!
|
17
|
+
html_options[:name] = field_set_title_from_args(*args)
|
18
|
+
html_options[:class] = [html_options[:class] || "inputs", "formnestic-li-fieldset", formnestic_row_class_based_on_position(options[:parent_builder].rows_counter)].join(" ")
|
19
|
+
self.options[:parent_builder].increase_rows_counter
|
20
|
+
|
21
|
+
rows_counter = template.content_tag(:span, self.options[:parent_builder].rows_counter, class: "formnestic-li-fieldset-for-order")
|
22
|
+
content_div_content = [formnestic_legend_for_list_form, " #".html_safe, rows_counter].join.html_safe
|
23
|
+
title_div = template.content_tag(:div, content_div_content, class: "formnestic-li-fieldset-legend")
|
24
|
+
template.content_tag(:fieldset, [title_div, (options[:row_removable] ? formnestic_row_removing_content_tag(:list) : ''), template.capture(&block)].join.html_safe, html_options)
|
25
|
+
end
|
26
|
+
|
27
|
+
# For table form
|
28
|
+
def formnestic_table_row_inputs(*args, &block)
|
29
|
+
html_options = args.extract_options!
|
30
|
+
html_options[:name] = field_set_title_from_args(*args)
|
31
|
+
html_options[:class] = [html_options[:class] || "inputs", "formnestic-tr-fieldset", formnestic_row_class_based_on_position(options[:parent_builder].rows_counter)].join(" ")
|
32
|
+
|
33
|
+
self.options[:parent_builder].increase_rows_counter
|
34
|
+
template.content_tag(:tr, [template.capture(&block), (options[:row_removable] ?
|
35
|
+
formnestic_row_removing_content_tag(:table) : '')].join.html_safe, html_options)
|
36
|
+
end
|
37
|
+
|
38
|
+
def formnestic_legend_for_list_form
|
39
|
+
record_name = self.object.class.to_s.underscore.gsub("_", " ").singularize.downcase
|
40
|
+
entity_name = I18n.t("activerecord.models.#{self.object.class.to_s.underscore.downcase}", default: record_name)
|
41
|
+
template.content_tag(:span, record_name.titleize, class: "formnestic-li-fieldset-for")
|
42
|
+
end
|
43
|
+
|
44
|
+
def formnestic_row_removing_content_tag(form_type)
|
45
|
+
contents = []
|
46
|
+
contents.push(self.hidden_field(:_destroy, class: "formnestic-destroy-input", value: false))
|
47
|
+
contents.push(template.content_tag(:div, '', title: I18n.t("formnestic.labels.remove_this_entry"), class: "#{formnestic_row_removing_cell_div_class(form_type)} icon-cancel-circled", onclick: formnestic_row_removing_cell_js_call(form_type)))
|
48
|
+
template.content_tag(form_type == :table ? :td : :div, contents.join.html_safe, class: formnestic_row_removing_cell_container_div_class(form_type))
|
49
|
+
end
|
50
|
+
|
51
|
+
def formnestic_row_removing_cell_js_call(form_type)
|
52
|
+
if form_type == :table
|
53
|
+
'Formnestic.removeATableEntry(this);'
|
54
|
+
else
|
55
|
+
'Formnestic.removeAListEntry(this);'
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def formnestic_row_removing_cell_div_class(form_type)
|
60
|
+
if form_type == :table
|
61
|
+
'formnestic-table-minus-button'
|
62
|
+
else
|
63
|
+
'formnestic-list-item-minus-button'
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def formnestic_row_removing_cell_container_div_class(form_type)
|
68
|
+
if form_type == :table
|
69
|
+
'formnestic-minus-button-cell'
|
70
|
+
else
|
71
|
+
'formnestic-minus-button-container'
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def formnestic_row_class_based_on_position(position)
|
76
|
+
position % 2 == 0 ? 'formnestic-even-row': 'formnestic-odd-row'
|
77
|
+
end
|
78
|
+
|
79
|
+
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
module Formnestic
|
2
|
+
# @private
|
3
|
+
module Helpers
|
4
|
+
autoload :InputsHelper, File.join(File.dirname(__FILE__), 'helpers', 'inputs_helper')
|
5
|
+
Formtastic::FormBuilder.send(:alias_method, :formtastic_inputs, :inputs)
|
6
|
+
Formtastic::FormBuilder.send(:include, Formnestic::Helpers::InputsHelper)
|
7
|
+
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Formnestic
|
2
|
+
module Inputs
|
3
|
+
module Base
|
4
|
+
module Wrapping
|
5
|
+
def input_wrapping(&block)
|
6
|
+
if self.builder.options[:display_type] == "table"
|
7
|
+
if self.instance_of?(Formtastic::Inputs::SelectInput)
|
8
|
+
select_input_wrapping(&block)
|
9
|
+
elsif [
|
10
|
+
"Formtastic::Inputs::DateSelectInput",
|
11
|
+
"Formtastic::Inputs::TimeSelectInput",
|
12
|
+
"Formtastic::Inputs::DateTimeSelectInput",
|
13
|
+
"Formtastic::Inputs::TimeInput",
|
14
|
+
"Formtastic::Inputs::DateInput",
|
15
|
+
].index(self.class.to_s)
|
16
|
+
table_date_select_input_wrapping(&block)
|
17
|
+
else
|
18
|
+
table_input_wrapping(&block)
|
19
|
+
end
|
20
|
+
else
|
21
|
+
formtastic_input_wrapping(&block)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def table_date_select_input_wrapping(&block)
|
26
|
+
self.builder.options[:parent_builder].add_table_header(self.attributized_method_name, self.class, label_text)
|
27
|
+
template.content_tag(:td,
|
28
|
+
template.content_tag(:div, [
|
29
|
+
template.capture(&block), error_html, hint_html].join("\n").html_safe,
|
30
|
+
class: "table-date-select-container"), wrapper_html_options
|
31
|
+
)
|
32
|
+
end
|
33
|
+
|
34
|
+
def table_input_wrapping(&block)
|
35
|
+
self.builder.options[:parent_builder].add_table_header(self.attributized_method_name, self.class, label_text)
|
36
|
+
template.content_tag(:td,
|
37
|
+
[template.capture(&block), error_html, hint_html].join("\n").html_safe,
|
38
|
+
wrapper_html_options
|
39
|
+
)
|
40
|
+
end
|
41
|
+
|
42
|
+
def select_input_wrapping(&block)
|
43
|
+
self.builder.options[:parent_builder].add_table_header(self.attributized_method_name, self.class, label_text)
|
44
|
+
template.content_tag(:td,
|
45
|
+
[template.capture(&block), error_html, hint_html, extra_input_for_other_in_select].join("\n").html_safe,
|
46
|
+
wrapper_html_options
|
47
|
+
)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|