dynamic_fieldsets 0.1.6 → 0.1.7

Sign up to get free protection for your applications and to get access to all the features.
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"