dynamic_fieldsets 0.1.6 → 0.1.7
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/CHANGELOG +6 -0
- data/VERSION +1 -1
- data/app/helpers/dynamic_fieldsets_helper.rb +3 -2
- data/app/models/dynamic_fieldsets/checkbox_field.rb +8 -1
- data/app/views/dynamic_fieldsets/form_partials/_input_header.html.erb +2 -2
- data/app/views/dynamic_fieldsets/form_partials/_radio_field.html.erb +1 -1
- data/app/views/dynamic_fieldsets/shared/_javascript_watcher.html.erb +139 -190
- data/dynamic_fieldsets.gemspec +2 -2
- metadata +3 -3
data/CHANGELOG
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
== unreleased changes
|
2
2
|
|
3
|
+
== 0.1.7
|
4
|
+
* Major refactor of the dependency javascript. All dependencies now work and dependencies on duplicate fields on the same page in different associators now work.
|
5
|
+
* Renamed the dependency list variable to dynamic_fieldsets_dependencies
|
6
|
+
* Fixed an issue on the checkbox field view where the id was not being set correctly
|
7
|
+
* Fixed an issue on the radio field view where the id was not being set correctly
|
8
|
+
|
3
9
|
== 0.1.6
|
4
10
|
|
5
11
|
* Fixed missing li tags in the show multiple answer partial
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.7
|
@@ -60,7 +60,8 @@ module DynamicFieldsetsHelper
|
|
60
60
|
field_markup.push render(:partial => field.form_header_partial, :locals => {
|
61
61
|
:classes => classes,
|
62
62
|
:field => field,
|
63
|
-
:fieldset_child => fieldset_child
|
63
|
+
:fieldset_child => fieldset_child,
|
64
|
+
:field_input_name => DynamicFieldsets.config.form_fieldset_associator_prefix + fsa.id.to_s + "_" + DynamicFieldsets.config.form_field_prefix + fieldset_child.id.to_s,
|
64
65
|
})
|
65
66
|
end
|
66
67
|
|
@@ -143,7 +144,7 @@ module DynamicFieldsetsHelper
|
|
143
144
|
# @return [String] The javascript variable that shows what fields have dependencies
|
144
145
|
def javascript_renderer(fsa)
|
145
146
|
unless fsa.id == nil
|
146
|
-
rendered_javascript = "<script type='text/javascript'> var
|
147
|
+
rendered_javascript = "<script type='text/javascript'> var dynamic_fieldsets_dependencies = #{fsa.dependency_child_hash.to_json}; </script>"
|
147
148
|
rendered_javascript += render "dynamic_fieldsets/shared/javascript_watcher"
|
148
149
|
return rendered_javascript.html_safe
|
149
150
|
else
|
@@ -15,12 +15,19 @@ module DynamicFieldsets
|
|
15
15
|
output = super
|
16
16
|
output[:options] = []
|
17
17
|
field_options.each do |option|
|
18
|
+
# rails is screwing up the ids just for the checkbox field
|
19
|
+
# this is a (hopefully) temporary solution/hack to get the id right (JH 3-29-2012)
|
20
|
+
# another possibility would be to update the html attributes method and add fsa and fsc arguments to it
|
21
|
+
adjusted_html_attributes = html_attribute_hash.merge({
|
22
|
+
:id => "#{DynamicFieldsets.config.form_fieldset_associator_prefix}#{args[:fsa].id}_#{DynamicFieldsets.config.form_field_prefix}#{args[:fieldset_child].id}_#{option.id.to_s}"
|
23
|
+
});
|
24
|
+
|
18
25
|
output[:options] << {
|
19
26
|
:name => "#{DynamicFieldsets.config.form_fieldset_associator_prefix}#{args[:fsa].id}[#{DynamicFieldsets.config.form_field_prefix}#{args[:fieldset_child].id}][]",
|
20
27
|
:value => option.id.to_s,
|
21
28
|
:checked => values_or_defaults_for_form(args[:values]).include?(option.id.to_s),
|
22
29
|
:label => option.name,
|
23
|
-
:html_attributes =>
|
30
|
+
:html_attributes => adjusted_html_attributes,
|
24
31
|
}
|
25
32
|
end
|
26
33
|
return output
|
@@ -1,5 +1,5 @@
|
|
1
|
-
<li class='<%= classes %>' id='input-<%=
|
2
|
-
|
1
|
+
<li class='<%= classes %>' id='input-<%= field_input_name %>'>
|
2
|
+
<label for ='<%= field_input_name %>'>
|
3
3
|
<%= field.label %>
|
4
4
|
<% if field.required? %>
|
5
5
|
<abbr title='required'>*</abbr>
|
@@ -1,101 +1,86 @@
|
|
1
1
|
<script type='text/javascript'>
|
2
2
|
|
3
3
|
// The only inputs we care about are visible... not hidden
|
4
|
-
var
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
var id_array = field.attr('id').split('-');
|
36
|
-
return id_array[id_array.length-1];
|
37
|
-
default:
|
38
|
-
return ''
|
39
|
-
}
|
40
|
-
};
|
41
|
-
|
42
|
-
/***************************************************************************
|
43
|
-
|
44
|
-
evaluate() does the logical computing between two values with a given
|
45
|
-
relationship.
|
46
|
-
|
47
|
-
params [entered_value] - The current value of the input that called the
|
48
|
-
change()
|
49
|
-
params [relationship] - The relationship of the dependency that the
|
50
|
-
input that called the change() is tied to
|
51
|
-
params [value] - The value that we are testing against for the dependency
|
52
|
-
that the input that called the change() is tied to
|
53
|
-
returns [bool] - The boolean value by comparing the entered_value against
|
54
|
-
the value using the relationship.
|
4
|
+
var all_inputs = $(":input:not(:hidden)");
|
5
|
+
|
6
|
+
//Return the fieldset child id for the input
|
7
|
+
//This uniquely associated the fieldset child with the fieldset associator
|
8
|
+
//New fields should use the fieldset_child_id data attribute
|
9
|
+
//But older fields can still attempt to parse it out of the id of the dom element
|
10
|
+
//
|
11
|
+
// field: Field dom element from dynamic fieldsets
|
12
|
+
// type: The type of element from get_type
|
13
|
+
// return: The fieldset child id of the field
|
14
|
+
function get_fieldset_child_id(field, type) {
|
15
|
+
if(typeof(field.attr("data-fsc_id")) != "undefined") {
|
16
|
+
return field.attr("data-fsc_id")
|
17
|
+
} else {
|
18
|
+
switch(type)
|
19
|
+
{
|
20
|
+
case 'text':
|
21
|
+
case 'textarea':
|
22
|
+
case 'select':
|
23
|
+
case 'multi-select':
|
24
|
+
var id_array = field.attr('id').split('-');
|
25
|
+
return id_array[id_array.length-1];
|
26
|
+
case 'radio':
|
27
|
+
case 'checkbox':
|
28
|
+
var id_array = field.closest("div").attr("id").split('-');
|
29
|
+
return id_array[id_array.length-1];
|
30
|
+
default:
|
31
|
+
return ''
|
32
|
+
}
|
33
|
+
}
|
34
|
+
}
|
55
35
|
|
56
|
-
|
36
|
+
// Pulls the fieldset associator id from the data attribute
|
37
|
+
// And falls back on the the string between '-' and '_' at the beginning of the id
|
38
|
+
function get_fieldset_associator_id(field) {
|
39
|
+
if(typeof(field.attr("data-fsa_id")) != "undefined") {
|
40
|
+
return field.attr("data-fsa_id")
|
41
|
+
} else {
|
42
|
+
//format should be fsa-###_field-###
|
43
|
+
return field.attr('id').split("_")[0].split("-")[1]
|
44
|
+
}
|
45
|
+
}
|
57
46
|
|
58
|
-
|
47
|
+
//Determines whether the dependency has been satisfied
|
48
|
+
//CHANGE THIS if the dependency model changes which relationships are allowed.
|
49
|
+
//
|
50
|
+
// user_value: The value on the form
|
51
|
+
// stored_value: The value that satisfies the dependency
|
52
|
+
// relationship: The predicate used to compare the user and stored values
|
53
|
+
//
|
54
|
+
// returns the result of the relationship between user and stored valued
|
55
|
+
function evaluate_dependency(user_value, relationship, stored_value) {
|
59
56
|
switch(relationship)
|
60
57
|
{
|
61
|
-
/* CHANGE THIS if the model changes on which relationships
|
62
|
-
are allowed. */
|
63
58
|
case 'equals':
|
64
|
-
return
|
59
|
+
return user_value == stored_value;
|
65
60
|
case 'not equals':
|
66
|
-
return
|
61
|
+
return user_value != stored_value;
|
67
62
|
case 'includes':
|
68
|
-
return
|
63
|
+
return $.inArray(stored_value, user_value) != -1;
|
69
64
|
case 'not includes':
|
70
|
-
return
|
65
|
+
return $.inArray(stored_value, user_value) == -1;
|
71
66
|
case 'blank':
|
72
|
-
return
|
67
|
+
return user_value == "";
|
73
68
|
case 'not blank':
|
74
|
-
return
|
69
|
+
return user_value != "";
|
75
70
|
default:
|
76
71
|
return false;
|
77
72
|
}
|
78
73
|
};
|
79
74
|
|
80
|
-
|
75
|
+
// What to do to the field based on the dependency information
|
76
|
+
// CHANGE THIS if the dependency group model changes which actions are allowed
|
77
|
+
//
|
78
|
+
// success_flag: whether the dependency group returned true or false
|
79
|
+
// action: the type of update to apply to the field
|
80
|
+
// group_field: the field to update (generally not the field that triggered the change)
|
81
|
+
function dependency_action(success_flag, action, group_field) {
|
81
82
|
|
82
|
-
|
83
|
-
appropriate action upon the group_field of the dependency_group.
|
84
|
-
|
85
|
-
params [success_flag] - Either set to succeed or failure to indicate
|
86
|
-
the results of evaluate()
|
87
|
-
params [action] - Either set to show or enable.
|
88
|
-
params [group_field] - The field tied to the dependency_group that is
|
89
|
-
to experience the action based off of the success of evaluate()
|
90
|
-
returns - changes the group_field
|
91
|
-
|
92
|
-
*************************************************************************/
|
93
|
-
|
94
|
-
function group_action(success_flag, action, group_field) {
|
95
|
-
|
96
|
-
/* CHANGE THIS if the model change on which actions are allowed */
|
97
|
-
|
98
|
-
if (success_flag == true){
|
83
|
+
if (success_flag){
|
99
84
|
switch(action)
|
100
85
|
{
|
101
86
|
case 'show':
|
@@ -114,142 +99,106 @@ function group_action(success_flag, action, group_field) {
|
|
114
99
|
}
|
115
100
|
};
|
116
101
|
|
117
|
-
function
|
102
|
+
function get_input_value(field, type) {
|
118
103
|
switch(type)
|
119
104
|
{
|
120
105
|
case 'text':
|
121
|
-
return field.attr('value').toLowerCase();
|
122
|
-
case 'radio':
|
123
|
-
if (field.val() == $(':checked').val())
|
124
|
-
{
|
125
|
-
field_val = field.attr('id').split('-').slice(2);
|
126
|
-
return field_val.join(" ").toLowerCase();
|
127
|
-
}
|
128
106
|
case 'textarea':
|
129
107
|
return field.val();
|
130
|
-
case '
|
131
|
-
|
132
|
-
|
133
|
-
var sibling_ray = field.closest('div').children().children();
|
134
|
-
var checked_ray = $('input:checked');
|
135
|
-
value_ray = getIntersect(sibling_ray, checked_ray)
|
136
|
-
for (var element in value_ray) {
|
137
|
-
field_ray.push(value_ray[element].id.split('-').slice(2)[0]);
|
108
|
+
case 'radio':
|
109
|
+
if (field.attr('checked') == 'checked') {
|
110
|
+
return $.trim(field.parent('label').text());
|
138
111
|
}
|
139
|
-
|
112
|
+
case 'checkbox':
|
113
|
+
return $('input[name="' + field.attr('name') + '"]:checked').map(function(index,option) {
|
114
|
+
return $.trim($(option).parent('label').text())
|
115
|
+
});
|
140
116
|
case 'select':
|
141
|
-
return
|
117
|
+
return field.find(':selected').text();
|
142
118
|
case 'multi-select':
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
{
|
147
|
-
var temp = value_ray[element].text;
|
148
|
-
if (typeof(temp) == "string") { field_ray.push(temp.toLowerCase()); }
|
149
|
-
}
|
150
|
-
return field_ray;
|
119
|
+
return field.find(':selected').map(function(index, option) {
|
120
|
+
return $(option).text();
|
121
|
+
});
|
151
122
|
default:
|
152
123
|
return '';
|
153
124
|
}
|
154
125
|
};
|
155
126
|
|
156
|
-
|
157
|
-
|
158
|
-
|
127
|
+
//returns the input type for the field
|
128
|
+
//this code is necessary to handle text areas and multiple selects
|
129
|
+
function get_field_type(field) {
|
130
|
+
if (field.attr('type') != undefined) {
|
159
131
|
return field.attr('type')
|
160
|
-
}
|
161
|
-
else if ($('textarea#'+field.attr('id')).length > 0)
|
162
|
-
{
|
132
|
+
} else if ($('textarea#'+field.attr('id')).length > 0) {
|
163
133
|
return "textarea";
|
164
|
-
}
|
165
|
-
|
166
|
-
{
|
167
|
-
if (field.attr('multiple') == "multiple")
|
168
|
-
{
|
134
|
+
} else if ($('select#'+field.attr('id')).length > 0) {
|
135
|
+
if (field.attr('multiple') == "multiple") {
|
169
136
|
return "multi-select";
|
170
|
-
}
|
171
|
-
else {
|
137
|
+
} else {
|
172
138
|
return "select";
|
173
139
|
}
|
174
|
-
}
|
175
|
-
else
|
176
|
-
{
|
140
|
+
} else {
|
177
141
|
return "invalid";
|
178
142
|
}
|
179
143
|
}
|
180
144
|
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
145
|
+
// when a dynamic fieldsets field fires a change event,
|
146
|
+
// update the page based on dependency information
|
147
|
+
//
|
148
|
+
// the dependency information is stored in dynamic_fieldsets_dependencies
|
149
|
+
all_inputs.change( function() {
|
150
|
+
var field = $(this);
|
151
|
+
var type = get_field_type(field);
|
152
|
+
var fieldset_child_id = get_fieldset_child_id(field, type);
|
153
|
+
var fieldset_associator_id = get_fieldset_associator_id(field);
|
154
|
+
var user_input = get_input_value(field, type)
|
155
|
+
|
156
|
+
|
157
|
+
if (fieldset_child_id in dynamic_fieldsets_dependencies) {
|
158
|
+
$.each(dynamic_fieldsets_dependencies[fieldset_child_id], function(index, group) {
|
159
|
+
update_dependency_group_for_fieldset_child(group, user_input, fieldset_associator_id);
|
160
|
+
});
|
161
|
+
}
|
162
|
+
});
|
163
|
+
|
164
|
+
// checks the clauses for a dependency group and runs the action
|
165
|
+
// group: the dependency group
|
166
|
+
// user_input: the input from the form
|
167
|
+
function update_dependency_group_for_fieldset_child(group, user_input, fieldset_associator_id) {
|
168
|
+
var action = group['action'];
|
169
|
+
var group_fsc_id = group['fieldset_child_id'];
|
170
|
+
var group_field_id = group['field_id'];
|
171
|
+
var group_field = '<%= DynamicFieldsets.config.form_fieldset_associator_prefix %>' + fieldset_associator_id + '_' + '<%=DynamicFieldsets.config.form_field_prefix %>' + group_fsc_id;
|
172
|
+
|
173
|
+
dependency_action(all_dependency_clauses_true(group, user_input), action, group_field)
|
192
174
|
}
|
193
175
|
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
var field = $(this);
|
207
|
-
var type = grab_type(field);
|
208
|
-
var fieldset_child_id = grab_fsc_id(field, type);
|
209
|
-
var entered_value = grab_value(field, type)
|
210
|
-
if (fieldset_child_id in json_holder) {
|
211
|
-
for (var group in json_holder[fieldset_child_id]) {
|
212
|
-
var action = json_holder[fieldset_child_id][group]['action'];
|
213
|
-
var group_fsc_id = json_holder[fieldset_child_id][group]['fieldset_child_id'];
|
214
|
-
var group_field_id = json_holder[fieldset_child_id][group]['field_id'];
|
215
|
-
var group_field = '<%= DynamicFieldsets.config.form_field_prefix %>' + group_field_id + '-child-' + group_fsc_id;
|
216
|
-
|
217
|
-
// As each dependency clause is AND'd together, we'll assume it'll be
|
218
|
-
// true until short circuited into being false.`
|
219
|
-
var group_break_flag = true;
|
220
|
-
group:
|
221
|
-
for (var clause in json_holder[fieldset_child_id][group]["clause"]) {
|
222
|
-
// As each clause ORs dependencies together, we'll assume it'll be
|
223
|
-
// false until short circuited into being true.
|
224
|
-
var clause_break_flag = false;
|
225
|
-
clause:
|
226
|
-
for (var dependency in json_holder[fieldset_child_id][group]["clause"][clause])
|
227
|
-
{
|
228
|
-
var relationship = json_holder[fieldset_child_id][group]["clause"][clause][dependency]['relationship'];
|
229
|
-
var value = json_holder[fieldset_child_id][group]["clause"][clause][dependency]['value'].toLowerCase();
|
230
|
-
// Short circuit from looking at each dependency in the case
|
231
|
-
// we determine a true dependency (OR)
|
232
|
-
if (evaluate(entered_value, relationship, value)) {
|
233
|
-
clause_break_flag = true;
|
234
|
-
break clause;
|
235
|
-
}
|
236
|
-
}
|
237
|
-
|
238
|
-
// Short circuit from looking at each clause in the case we determine
|
239
|
-
// a false dependency (AND)
|
240
|
-
if (clause_break_flag == false) {
|
241
|
-
group_break_flag = false;
|
242
|
-
break group;
|
243
|
-
}
|
244
|
-
}
|
245
|
-
// If successful, group_break_flag will pass true into group_action
|
246
|
-
group_action(group_break_flag, action, group_field);
|
247
|
-
|
248
|
-
}
|
176
|
+
//all dependencies must be satisfied
|
177
|
+
//the first one that is false makes this return false
|
178
|
+
//only return true if all return true
|
179
|
+
function all_dependency_clauses_true(group, user_input) {
|
180
|
+
for(var key in group["clause"]) {
|
181
|
+
var clause = group["clause"][key]
|
182
|
+
if(!at_least_one_dependency_true(clause, user_input)) {
|
183
|
+
return false;
|
184
|
+
}
|
185
|
+
}
|
186
|
+
return true;
|
187
|
+
}
|
249
188
|
|
250
|
-
|
189
|
+
//The dependencies are ORed together
|
190
|
+
//So as soon as one returns true, return true
|
191
|
+
//Only return false if all are false
|
192
|
+
function at_least_one_dependency_true(clause, user_input) {
|
193
|
+
for(var key in clause) {
|
194
|
+
var dependency = clause[key]
|
195
|
+
if(evaluate_dependency(user_input, dependency["relationship"], dependency["value"])) {
|
196
|
+
return true
|
197
|
+
}
|
198
|
+
}
|
199
|
+
return false
|
200
|
+
}
|
251
201
|
|
252
|
-
|
253
|
-
.change();
|
202
|
+
all_inputs.change();
|
254
203
|
|
255
204
|
</script>
|
data/dynamic_fieldsets.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "dynamic_fieldsets"
|
8
|
-
s.version = "0.1.
|
8
|
+
s.version = "0.1.7"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Jeremiah Hemphill", "Ethan Pemble", "John Carter"]
|
12
|
-
s.date = "2012-03-
|
12
|
+
s.date = "2012-03-30"
|
13
13
|
s.description = "Dynamic fieldsets for rails controllers"
|
14
14
|
s.email = "jeremiah@cloudspace.com"
|
15
15
|
s.extra_rdoc_files = [
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: dynamic_fieldsets
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.1.
|
5
|
+
version: 0.1.7
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Jeremiah Hemphill
|
@@ -12,7 +12,7 @@ autorequire:
|
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
14
|
|
15
|
-
date: 2012-03-
|
15
|
+
date: 2012-03-30 00:00:00 Z
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
18
18
|
name: rails
|
@@ -431,7 +431,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
431
431
|
requirements:
|
432
432
|
- - ">="
|
433
433
|
- !ruby/object:Gem::Version
|
434
|
-
hash: -
|
434
|
+
hash: -3084786597539631494
|
435
435
|
segments:
|
436
436
|
- 0
|
437
437
|
version: "0"
|