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 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.6
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 json_holder = #{fsa.dependency_child_hash.to_json}; </script>"
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 => html_attribute_hash
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-<%= DynamicFieldsets.config.form_field_prefix %><%= field.id %>-child-<%= fieldset_child.id %>'>
2
- <label for ='<%=DynamicFieldsets.config.form_field_prefix %><%= field.id %>'>
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,4 +1,4 @@
1
- <div id='<%= name %>'>
1
+ <div id='<%= id %>'>
2
2
  <% options.each do |option| %>
3
3
  <label for='<%= option[:name] %>'>
4
4
  <%= radio_button_tag(option[:name], option[:value], option[:checked], option[:html_attributes]) %>
@@ -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 allInputs = $(":input:not(:hidden)");
5
-
6
- /***************************************************************************
7
-
8
- field-[group_field]-child-[group_fsc] - just want the last value from the
9
- input's id. This function rips it.
10
-
11
- input - called upon the input that just called the change()
12
- returns [integer] - the group_fsc id from the end of the id
13
-
14
- ***************************************************************************/
15
-
16
- function grab_fsc_id(field, type) {
17
- switch(type)
18
- {
19
- case 'text':
20
- var id_array = field.attr('id').split('-');
21
- return id_array[id_array.length-1];
22
- case 'radio':
23
- var id_array = field.closest("div").attr("id").split('-');
24
- return id_array[id_array.length-1];
25
- case 'textarea':
26
- var id_array = field.attr('id').split('-');
27
- return id_array[id_array.length-1];
28
- case 'checkbox':
29
- var id_array = field.closest("div").attr("id").split('-');
30
- return id_array[id_array.length-1];
31
- case 'select':
32
- var id_array = field.attr('id').split('-');
33
- return id_array[id_array.length-1];
34
- case 'multi-select':
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
- function evaluate(entered_value, relationship, value) {
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 entered_value == value;
59
+ return user_value == stored_value;
65
60
  case 'not equals':
66
- return entered_value != value;
61
+ return user_value != stored_value;
67
62
  case 'includes':
68
- return jQuery.inArray(value, entered_value) != -1;
63
+ return $.inArray(stored_value, user_value) != -1;
69
64
  case 'not includes':
70
- return jQuery.inArray(value, entered_value) == -1;
65
+ return $.inArray(stored_value, user_value) == -1;
71
66
  case 'blank':
72
- return entered_value == "";
67
+ return user_value == "";
73
68
  case 'not blank':
74
- return entered_value != "";
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
- group_action() responds to the results of evaluate() to enact the
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 grab_value(field, type) {
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 'checkbox':
131
- var value_ray = [];
132
- var field_ray = [];
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
- return field_ray;
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 $('#' + field.attr('id') + ' option:selected').text().toLowerCase();
117
+ return field.find(':selected').text();
142
118
  case 'multi-select':
143
- var value_ray = $('#' + field.attr('id') + ' option:selected');
144
- var field_ray = []
145
- for (var element in value_ray)
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
- function grab_type(field) {
157
- if (field.attr('type') != undefined)
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
- else if ($('select#'+field.attr('id')).length > 0)
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
- function getIntersect(arr1, arr2) {
182
- var temp = [];
183
- for(var i = 0; i < arr1.length; i++){
184
- for(var k = 0; k < arr2.length; k++){
185
- if(arr1[i] == arr2[k]){
186
- temp.push( arr1[i]);
187
- break;
188
- }
189
- }
190
- }
191
- return temp;
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
- This watches for ANY change that may take place on the page. It then
197
- pushes the object through grab_fsc_id to get an id we can check against
198
- the json_holder. If it's in there, it then grabs all the related data,
199
- checks the current value against the expected value through the
200
- evaluate() function and then goes through the needed action AFTER
201
- checking each dependency and dependency_clause.
202
-
203
- ***********************************************************************/
204
-
205
- allInputs.change( function() {
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>
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "dynamic_fieldsets"
8
- s.version = "0.1.6"
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-27"
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.6
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-27 00:00:00 Z
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: -760912244715357845
434
+ hash: -3084786597539631494
435
435
  segments:
436
436
  - 0
437
437
  version: "0"