active_scaffold 3.2.20 → 3.3.0.rc

Sign up to get free protection for your applications and to get access to all the features.
Files changed (152) hide show
  1. data/CHANGELOG +19 -13
  2. data/README +66 -0
  3. data/app/assets/javascripts/jquery/active_scaffold.js +156 -113
  4. data/app/assets/javascripts/jquery/active_scaffold_chosen.js +11 -0
  5. data/app/assets/javascripts/jquery/date_picker_bridge.js.erb +0 -1
  6. data/app/assets/javascripts/jquery/jquery.editinplace.js +132 -128
  7. data/app/assets/javascripts/prototype/active_scaffold.js +68 -25
  8. data/{frontends/default/views/_horizontal_subform_footer.html.erb → app/assets/javascripts/prototype/active_scaffold_chosen.js} +0 -0
  9. data/app/assets/stylesheets/active_scaffold_colors.css.scss +8 -1
  10. data/app/assets/stylesheets/active_scaffold_layout.css +14 -8
  11. data/{frontends/default/views → app/views/active_scaffold_overrides}/_add_existing_form.html.erb +0 -0
  12. data/{frontends/default/views → app/views/active_scaffold_overrides}/_base_form.html.erb +0 -0
  13. data/{frontends/default/views → app/views/active_scaffold_overrides}/_create_form.html.erb +0 -0
  14. data/{frontends/default/views → app/views/active_scaffold_overrides}/_create_form_on_list.html.erb +0 -0
  15. data/{frontends/default/views → app/views/active_scaffold_overrides}/_field_search.html.erb +0 -0
  16. data/{frontends/default/views → app/views/active_scaffold_overrides}/_form.html.erb +0 -0
  17. data/{frontends/default/views → app/views/active_scaffold_overrides}/_form_association.html.erb +8 -3
  18. data/{frontends/default/views → app/views/active_scaffold_overrides}/_form_association_footer.html.erb +5 -4
  19. data/app/views/active_scaffold_overrides/_form_association_record.html.erb +85 -0
  20. data/app/views/active_scaffold_overrides/_form_attribute.html.erb +23 -0
  21. data/{frontends/default/views → app/views/active_scaffold_overrides}/_form_hidden_attribute.html.erb +0 -0
  22. data/{frontends/default/views → app/views/active_scaffold_overrides}/_form_messages.html.erb +0 -0
  23. data/app/views/active_scaffold_overrides/_horizontal_subform.html.erb +12 -0
  24. data/app/views/active_scaffold_overrides/_horizontal_subform_footer.html.erb +0 -0
  25. data/{frontends/default/views → app/views/active_scaffold_overrides}/_horizontal_subform_header.html.erb +3 -2
  26. data/{frontends/default/views → app/views/active_scaffold_overrides}/_human_conditions.html.erb +0 -0
  27. data/app/views/active_scaffold_overrides/_list.html.erb +35 -0
  28. data/{frontends/default/views → app/views/active_scaffold_overrides}/_list_calculations.html.erb +0 -0
  29. data/{frontends/default/views → app/views/active_scaffold_overrides}/_list_column_headings.html.erb +0 -0
  30. data/app/views/active_scaffold_overrides/_list_header.html.erb +8 -0
  31. data/{frontends/default/views → app/views/active_scaffold_overrides}/_list_inline_adapter.html.erb +0 -0
  32. data/{frontends/default/views → app/views/active_scaffold_overrides}/_list_messages.html.erb +4 -4
  33. data/{frontends/default/views → app/views/active_scaffold_overrides}/_list_pagination.html.erb +0 -0
  34. data/{frontends/default/views → app/views/active_scaffold_overrides}/_list_pagination_links.html.erb +0 -0
  35. data/app/views/active_scaffold_overrides/_list_record.html.erb +30 -0
  36. data/{frontends/default/views → app/views/active_scaffold_overrides}/_list_with_header.html.erb +0 -0
  37. data/{frontends/default/views → app/views/active_scaffold_overrides}/_messages.html.erb +0 -0
  38. data/app/views/active_scaffold_overrides/_refresh_list.js.erb +1 -0
  39. data/{frontends/default/views → app/views/active_scaffold_overrides}/_render_field.js.erb +9 -1
  40. data/{frontends/default/views → app/views/active_scaffold_overrides}/_row.html.erb +0 -0
  41. data/{frontends/default/views → app/views/active_scaffold_overrides}/_search.html.erb +0 -0
  42. data/{frontends/default/views → app/views/active_scaffold_overrides}/_search_attribute.html.erb +0 -0
  43. data/{frontends/default/views → app/views/active_scaffold_overrides}/_show.html.erb +0 -0
  44. data/{frontends/default/views → app/views/active_scaffold_overrides}/_show_columns.html.erb +0 -0
  45. data/app/views/active_scaffold_overrides/_update_actions.html.erb +9 -0
  46. data/{frontends/default/views → app/views/active_scaffold_overrides}/_update_calculations.js.erb +0 -0
  47. data/app/views/active_scaffold_overrides/_update_column.js.erb +16 -0
  48. data/{frontends/default/views → app/views/active_scaffold_overrides}/_update_form.html.erb +0 -0
  49. data/{frontends/default/views → app/views/active_scaffold_overrides}/_update_messages.js.erb +0 -0
  50. data/app/views/active_scaffold_overrides/_vertical_subform.html.erb +8 -0
  51. data/{frontends/default/views → app/views/active_scaffold_overrides}/action_confirmation.html.erb +0 -0
  52. data/{frontends/default/views → app/views/active_scaffold_overrides}/add_existing.js.erb +0 -0
  53. data/{frontends/default/views → app/views/active_scaffold_overrides}/add_existing_form.html.erb +0 -0
  54. data/{frontends/default/views → app/views/active_scaffold_overrides}/create.html.erb +0 -0
  55. data/{frontends/default/views → app/views/active_scaffold_overrides}/delete.html.erb +0 -0
  56. data/{frontends/default/views → app/views/active_scaffold_overrides}/destroy.js.erb +0 -0
  57. data/{frontends/default/views → app/views/active_scaffold_overrides}/edit_associated.js.erb +1 -1
  58. data/{frontends/default/views → app/views/active_scaffold_overrides}/field_search.html.erb +0 -0
  59. data/{frontends/default/views → app/views/active_scaffold_overrides}/form_messages.js.erb +0 -0
  60. data/{frontends/default/views → app/views/active_scaffold_overrides}/list.html.erb +0 -0
  61. data/{frontends/default/views → app/views/active_scaffold_overrides}/on_action_update.js.erb +3 -3
  62. data/{frontends/default/views → app/views/active_scaffold_overrides}/on_create.js.erb +1 -1
  63. data/{frontends/default/views → app/views/active_scaffold_overrides}/on_mark.js.erb +0 -0
  64. data/{frontends/default/views → app/views/active_scaffold_overrides}/on_update.js.erb +4 -4
  65. data/{frontends/default/views → app/views/active_scaffold_overrides}/render_field.js.erb +0 -0
  66. data/{frontends/default/views → app/views/active_scaffold_overrides}/row.js.erb +1 -1
  67. data/{frontends/default/views → app/views/active_scaffold_overrides}/search.html.erb +0 -0
  68. data/{frontends/default/views → app/views/active_scaffold_overrides}/show.html.erb +0 -0
  69. data/{frontends/default/views → app/views/active_scaffold_overrides}/update.html.erb +1 -1
  70. data/app/views/active_scaffold_overrides/update_column.js.erb +26 -0
  71. data/{frontends/default/views → app/views/active_scaffold_overrides}/update_row.js.erb +0 -0
  72. data/config/locales/de.yml +1 -0
  73. data/config/locales/en.yml +1 -0
  74. data/config/locales/es.yml +1 -0
  75. data/config/locales/fr.yml +1 -0
  76. data/config/locales/hu.yml +1 -0
  77. data/config/locales/ja.yml +1 -0
  78. data/config/locales/ru.yml +1 -0
  79. data/lib/active_scaffold.rb +14 -26
  80. data/lib/active_scaffold/actions/core.rb +14 -11
  81. data/lib/active_scaffold/actions/create.rb +3 -3
  82. data/lib/active_scaffold/actions/delete.rb +3 -0
  83. data/lib/active_scaffold/actions/list.rb +9 -6
  84. data/lib/active_scaffold/actions/mark.rb +1 -1
  85. data/lib/active_scaffold/actions/nested.rb +8 -6
  86. data/lib/active_scaffold/actions/show.rb +6 -1
  87. data/lib/active_scaffold/actions/update.rb +39 -19
  88. data/lib/active_scaffold/active_record_permissions.rb +29 -12
  89. data/lib/active_scaffold/attribute_params.rb +14 -7
  90. data/lib/active_scaffold/bridges/calendar_date_select.rb +1 -1
  91. data/lib/active_scaffold/bridges/cancan/cancan_bridge.rb +1 -2
  92. data/lib/active_scaffold/bridges/carrierwave/list_ui.rb +1 -1
  93. data/lib/active_scaffold/bridges/chosen.rb +14 -0
  94. data/lib/active_scaffold/bridges/chosen/helpers.rb +48 -0
  95. data/lib/active_scaffold/bridges/date_picker/helper.rb +7 -6
  96. data/lib/active_scaffold/bridges/dragonfly/form_ui.rb +1 -1
  97. data/lib/active_scaffold/bridges/dragonfly/list_ui.rb +1 -1
  98. data/lib/active_scaffold/bridges/file_column.rb +1 -1
  99. data/lib/active_scaffold/bridges/file_column/as_file_column_bridge.rb +1 -1
  100. data/lib/active_scaffold/bridges/file_column/file_column_helpers.rb +2 -2
  101. data/lib/active_scaffold/bridges/file_column/list_ui.rb +4 -4
  102. data/lib/active_scaffold/bridges/paperclip.rb +1 -1
  103. data/lib/active_scaffold/bridges/paperclip/form_ui.rb +1 -1
  104. data/lib/active_scaffold/bridges/paperclip/list_ui.rb +1 -1
  105. data/lib/active_scaffold/bridges/paperclip/paperclip_bridge_helpers.rb +1 -1
  106. data/lib/active_scaffold/bridges/shared/date_bridge.rb +1 -1
  107. data/lib/active_scaffold/bridges/tiny_mce/helpers.rb +1 -1
  108. data/lib/active_scaffold/config/core.rb +9 -2
  109. data/lib/active_scaffold/config/list.rb +9 -13
  110. data/lib/active_scaffold/config/nested.rb +11 -2
  111. data/lib/active_scaffold/data_structures/action_columns.rb +19 -5
  112. data/lib/active_scaffold/data_structures/action_link.rb +9 -2
  113. data/lib/active_scaffold/data_structures/action_links.rb +5 -36
  114. data/lib/active_scaffold/data_structures/column.rb +21 -21
  115. data/lib/active_scaffold/data_structures/nested_info.rb +31 -44
  116. data/lib/active_scaffold/extensions/action_controller_rescueing.rb +1 -0
  117. data/lib/active_scaffold/extensions/action_view_rendering.rb +30 -36
  118. data/lib/active_scaffold/extensions/reverse_associations.rb +10 -6
  119. data/lib/active_scaffold/extensions/routing_mapper.rb +6 -5
  120. data/lib/active_scaffold/extensions/unsaved_associated.rb +1 -1
  121. data/lib/active_scaffold/finder.rb +18 -10
  122. data/lib/active_scaffold/helpers/association_helpers.rb +21 -2
  123. data/lib/active_scaffold/helpers/controller_helpers.rb +14 -16
  124. data/lib/active_scaffold/helpers/form_column_helpers.rb +161 -21
  125. data/lib/active_scaffold/helpers/id_helpers.rb +7 -7
  126. data/lib/active_scaffold/helpers/list_column_helpers.rb +42 -92
  127. data/lib/active_scaffold/helpers/search_column_helpers.rb +10 -3
  128. data/lib/active_scaffold/helpers/show_column_helpers.rb +4 -9
  129. data/lib/active_scaffold/helpers/view_helpers.rb +278 -78
  130. data/lib/active_scaffold/version.rb +2 -2
  131. data/lib/generators/active_scaffold_controller/templates/controller.rb +1 -1
  132. data/test/bridges/paperclip_test.rb +2 -2
  133. data/vendor/assets/javascripts/jquery-ui-timepicker-addon.js +1882 -1276
  134. metadata +79 -80
  135. data/README.md +0 -67
  136. data/frontends/default/views/_action_group.html.erb +0 -24
  137. data/frontends/default/views/_form_attribute.html.erb +0 -23
  138. data/frontends/default/views/_horizontal_subform.html.erb +0 -22
  139. data/frontends/default/views/_horizontal_subform_record.html.erb +0 -43
  140. data/frontends/default/views/_list.html.erb +0 -18
  141. data/frontends/default/views/_list_actions.html.erb +0 -15
  142. data/frontends/default/views/_list_header.html.erb +0 -10
  143. data/frontends/default/views/_list_record.html.erb +0 -13
  144. data/frontends/default/views/_list_record_columns.html.erb +0 -8
  145. data/frontends/default/views/_refresh_list.js.erb +0 -1
  146. data/frontends/default/views/_update_actions.html.erb +0 -9
  147. data/frontends/default/views/_vertical_subform.html.erb +0 -12
  148. data/frontends/default/views/_vertical_subform_record.html.erb +0 -43
  149. data/frontends/default/views/refresh_list.js.erb +0 -2
  150. data/frontends/default/views/update_column.js.erb +0 -15
  151. data/lib/active_scaffold/extensions/active_record_offset.rb +0 -12
  152. data/lib/active_scaffold/extensions/nil_id_in_url_params.rb +0 -7
@@ -0,0 +1,11 @@
1
+ jQuery(document).ready(function() {
2
+ jQuery(document).on('as:element_updated', function(event) {
3
+ jQuery('select.chosen', event.target).chosen();
4
+ });
5
+ jQuery(document).on('as:action_success', 'a.as_action', function(event, action_link) {
6
+ if (action_link.adapter) {
7
+ jQuery('select.chosen', action_link.adapter).chosen();
8
+ }
9
+ });
10
+ jQuery('select.chosen').chosen();
11
+ });
@@ -1,4 +1,3 @@
1
- <%# encoding: utf-8 %>
2
1
  <%= ActiveScaffold::Bridges[:date_picker].localization %>
3
2
 
4
3
  jQuery(document).ready(function() {
@@ -46,15 +46,15 @@ $.fn.editInPlace = function(options) {
46
46
  /// Required Options: Either url or callback, so the editor knows what to do with the edited values.
47
47
  $.fn.editInPlace.defaults = {
48
48
  url: "", // string: POST URL to send edited content
49
- ajax_data_type: "html", // string: dataType (html|script) for ajax call to save updated value
49
+ ajax_data_type: "html", // string: dataType (html|script) for ajax call to save updated value
50
50
  bg_over: "#ffc", // string: background color of hover of unactivated editor
51
51
  bg_out: "transparent", // string: background color on restore from hover
52
- hover_class: "", // string: class added to root element during hover. Will override bg_over and bg_out
52
+ hover_class: "", // string: class added to root element during hover. Will override bg_over and bg_out
53
53
  show_buttons: false, // boolean: will show the buttons: cancel or save; will automatically cancel out the onBlur functionality
54
54
  save_button: '<button class="inplace_save">Save</button>', // string: image button tag to use as “Save” button
55
55
  cancel_button: '<button class="inplace_cancel">Cancel</button>', // string: image button tag to use as “Cancel” button
56
56
  params: "", // string: example: first_name=dave&last_name=hauenstein extra paramters sent via the post request to the server
57
- field_type: "text", // string: "text", "textarea", or "select", or "remote", or "clone"; The type of form field that will appear on instantiation
57
+ field_type: "text", // string: "text", "textarea", or "select", or "remote", or "clone"; The type of form field that will appear on instantiation
58
58
  default_text: "(Click here to add text)", // string: text to show up if the element that has this functionality is empty
59
59
  use_html: false, // boolean, set to true if the editor should use jQuery.fn.html() to extract the value to show from the dom node (keep in mind that IE will uppercase all tags, so use with caution)
60
60
  textarea_rows: 10, // integer: set rows attribute of textarea, if field_type is set to textarea. Use CSS if possible though
@@ -62,28 +62,29 @@ $.fn.editInPlace.defaults = {
62
62
  select_text: "Choose new value", // string: default text to show up in select box
63
63
  select_options: "", // string or array: Used if field_type is set to 'select'. Can be comma delimited list of options 'textandValue,text:value', Array of options ['textAndValue', 'text:value'] or array of arrays ['textAndValue', ['text', 'value']]. The last form is especially usefull if your labels or values contain colons)
64
64
  text_size: null, // integer: set cols attribute of text input, if field_type is set to text. Use CSS if possible though
65
- editor_url: null, // for field_type: remote url to get html_code for edit_control
66
- loading_text: 'Loading...', // shown if inplace editor is loaded from server
65
+ editor_url: null, // for field_type: remote url to get html_code for edit_control
66
+ loading_text: 'Loading...', // shown if inplace editor is loaded from server
67
67
  // Specifying callback_skip_dom_reset will disable all saving_* options
68
68
  saving_text: undefined, // string: text to be used when server is saving information. Example "Saving..."
69
69
  saving_image: "", // string: uses saving text specify an image location instead of text while server is saving
70
70
  saving_animation_color: 'transparent', // hex color string, will be the color the pulsing animation during the save pulses to. Note: Only works if jquery-ui is loaded
71
- clone_selector: null, // if field_type clone a selector to clone editor from
72
- clone_id_suffix: null, // if field_type clone a suffix to create unique ids
71
+ clone_selector: null, // if field_type clone a selector to clone editor from
72
+ clone_id_suffix: null, // if field_type clone a suffix to create unique ids
73
73
 
74
74
  value_required: false, // boolean: if set to true, the element will not be saved unless a value is entered
75
75
  element_id: "element_id", // string: name of parameter holding the id or the editable
76
76
  update_value: "update_value", // string: name of parameter holding the updated/edited value
77
77
  original_value: 'original_value', // string: name of parameter holding the updated/edited value
78
78
  original_html: "original_html", // string: name of parameter holding original_html value of the editable /* DEPRECATED in 2.2.0 */ use original_value instead.
79
- save_if_nothing_changed: false, // boolean: submit to function or server even if the user did not change anything
79
+ save_if_nothing_changed: false, // boolean: submit to function or server even if the user did not change anything
80
80
  on_blur: "save", // string: "save" or null; what to do on blur; will be overridden if show_buttons is true
81
81
  cancel: "", // string: if not empty, a jquery selector for elements that will not cause the editor to open even though they are clicked. E.g. if you have extra buttons inside editable fields
82
82
 
83
83
  // All callbacks will have this set to the DOM node of the editor that triggered the callback
84
84
 
85
85
  callback: null, // function: function to be called when editing is complete; cancels ajax submission to the url param. Prototype: function(idOfEditor, enteredText, orinalHTMLContent, settingsParams, callbacks). The function needs to return the value that should be shown in the dom. Returning undefined means cancel and will restore the dom and trigger an error. callbacks is a dictionary with two functions didStartSaving and didEndSaving() that you can use to tell the inline editor that it should start and stop any saving animations it has configured. /* DEPRECATED in 2.1.0 */ Parameter idOfEditor, use $(this).attr('id') instead
86
- callback_skip_dom_reset: false, // boolean: set this to true if the callback should handle replacing the editor with the new value to show
86
+ callback_skip_dom_reset: false, // boolean: set this to true if the callback should handle replacing the editor with the new value to show
87
+ beforeSend: null, // function: this function gets called before sending new value to server. Prototype: function(request, requestSettings)
87
88
  success: null, // function: this function gets called if server responds with a success. Prototype: function(newEditorContentString)
88
89
  error: null, // function: this function gets called if server responds with an error. Prototype: function(request)
89
90
  error_sink: function(idOfEditor, errorString) { alert(errorString); }, // function: gets id of the editor and the error. Make sure the editor has an id, or it will just be undefined. If set to null, no error will be reported. /* DEPRECATED in 2.1.0 */ Parameter idOfEditor, use $(this).attr('id') instead
@@ -156,7 +157,7 @@ $.extend(InlineEditor.prototype, {
156
157
  },
157
158
 
158
159
  disconnectOpeningEvents: function() {
159
- // prevent re-opening the editor when it is already open
160
+ // prevent re-opening the editor when it is already open
160
161
  this.dom.unbind('.editInPlace');
161
162
  },
162
163
 
@@ -184,8 +185,8 @@ $.extend(InlineEditor.prototype, {
184
185
  this.saveOriginalValue();
185
186
  this.markEditorAsActive();
186
187
  this.replaceContentWithEditor();
187
- this.setInitialValue();
188
- this.workAroundMissingBlurBug();
188
+ this.setInitialValue();
189
+ this.workAroundMissingBlurBug();
189
190
  this.connectClosingEventsToEditor();
190
191
  this.triggerDelegateCall('didOpenEditInPlace');
191
192
  },
@@ -240,15 +241,15 @@ $.extend(InlineEditor.prototype, {
240
241
  },
241
242
 
242
243
  workAroundMissingBlurBug: function() {
243
- // Strangely, all browser will forget to send a blur event to an input element
244
- // when another one is created and selected programmatically. (at least under some circumstances).
245
- // This means that if another inline editor is opened, existing inline editors will _not_ close
246
- // if they are configured to submit when blurred.
244
+ // Strangely, all browser will forget to send a blur event to an input element
245
+ // when another one is created and selected programmatically. (at least under some circumstances).
246
+ // This means that if another inline editor is opened, existing inline editors will _not_ close
247
+ // if they are configured to submit when blurred.
247
248
 
248
249
  // Using parents() instead document as base to workaround the fact that in the unittests
249
250
  // the editor is not a child of window.document but of a document fragment
250
- var ourInput = this.dom.find(':input');
251
- this.dom.parents(':last').find('.editInPlace-active :input').not(ourInput).blur();
251
+ var ourInput = this.dom.find(':input');
252
+ this.dom.parents(':last').find('.editInPlace-active :input').not(ourInput).blur();
252
253
  },
253
254
 
254
255
  replaceContentWithEditor: function() {
@@ -270,7 +271,7 @@ $.extend(InlineEditor.prototype, {
270
271
  editor = this.createSelectEditor();
271
272
  else if ("text" === this.settings.field_type)
272
273
  editor = $('<input type="text" ' + this.inputNameAndClass()
273
- + ' size="' + this.settings.text_size + '" />');
274
+ + ' size="' + this.settings.text_size + '" />');
274
275
  else if ("textarea" === this.settings.field_type)
275
276
  editor = $('<textarea ' + this.inputNameAndClass()
276
277
  + ' rows="' + this.settings.textarea_rows + '" '
@@ -278,93 +279,93 @@ $.extend(InlineEditor.prototype, {
278
279
  else if ("remote" === this.settings.field_type)
279
280
  editor = this.createRemoteGeneratedEditor();
280
281
  else if ("clone" === this.settings.field_type) {
281
- editor = this.cloneEditor();
282
- return editor;
282
+ editor = this.cloneEditor();
283
+ return editor;
283
284
  }
284
285
  return editor;
285
286
  },
286
287
 
287
- setInitialValue: function() {
288
- if (this.settings.field_type == 'remote') return; // remote generated editor doesn't need initial value
289
- var initialValue = this.triggerDelegateCall('willOpenEditInPlace', this.originalValue);
290
- var editor = this.dom.find(':input');
291
- editor.val(initialValue);
292
-
293
- // Workaround for select fields which don't contain the original value.
294
- // Somehow the browsers don't like to select the instructional choice (disabled) in that case
295
- if (editor.val() !== initialValue)
296
- editor.val(''); // selects instructional choice
297
- },
298
-
288
+ setInitialValue: function() {
289
+ if (this.settings.field_type == 'remote' || this.settings.field_type == 'clone') return; // remote and clone generated editor doesn't need initial value
290
+ var initialValue = this.triggerDelegateCall('willOpenEditInPlace', this.originalValue);
291
+ var editor = this.dom.find(':input');
292
+ editor.val(initialValue);
293
+
294
+ // Workaround for select fields which don't contain the original value.
295
+ // Somehow the browsers don't like to select the instructional choice (disabled) in that case
296
+ if (editor.val() !== initialValue)
297
+ editor.val(''); // selects instructional choice
298
+ },
299
+
299
300
  createRemoteGeneratedEditor: function () {
300
- this.dom.html(this.settings.loading_text);
301
- return $($.ajax({
302
- url: this.settings.editor_url,
303
- async: false
304
- }).responseText);
301
+ this.dom.html(this.settings.loading_text);
302
+ return $($.ajax({
303
+ url: this.settings.editor_url,
304
+ async: false
305
+ }).responseText);
305
306
  },
306
307
 
307
308
  cloneEditor: function() {
308
- var patternNodes = this.getPatternNodes(this.settings.clone_selector);
309
- if (patternNodes.editNode == null) {
310
- alert('did not find any matching node for ' + this.settings.clone_selector);
311
- return;
312
- }
313
-
314
- var editorNode = patternNodes.editNode.clone();
315
- var clonedNodes = null;
316
- if (editorNode.attr('id')) editorNode.attr('id', editorNode.attr('id') + this.settings.clone_id_suffix);
317
- editorNode.attr('name', 'inplace_value');
318
- editorNode.addClass('editor_field');
319
- this.setValue(editorNode, this.originalValue);
320
- clonedNodes = editorNode;
321
-
322
- if (patternNodes.additionalNodes) {
323
- patternNodes.additionalNodes.each(function (index, node) {
324
- var patternNode = $(node).clone();
325
- if (patternNode.attr('id')) {
326
- patternNode.attr('id', patternNode.attr('id') + this.settings.clone_id_suffix);
327
- }
328
- clonedNodes = clonedNodes.after(patternNode);
329
- });
330
- }
331
- return clonedNodes;
332
- },
333
-
334
- getPatternNodes: function(clone_selector) {
335
- var nodes = {editNode: null, additionalNodes: null};
336
- var selectedNodes = $(clone_selector);
337
- var firstNode = selectedNodes.first();
338
-
339
- if (typeof(firstNode) !== 'undefined') {
340
- // AS inplace_edit_control_container -> we have to select all child nodes
341
- // Workaround for ie which does not support css > selector
342
- if (firstNode.hasClass('as_inplace_pattern')) {
343
- selectedNodes = firstNode.children();
344
- }
345
- nodes.editNode = selectedNodes.first();
346
- nodes.additionalNodes = selectedNodes.slice(1);
347
- }
348
- return nodes;
349
- },
350
-
351
- setValue: function(editField, textValue) {
352
- var function_name = 'setValueFor' + editField.get(0).nodeName.toLowerCase();
353
- if (typeof(this[function_name]) == 'function') {
354
- this[function_name](editField, textValue);
355
- } else {
356
- editField.val(textValue);
357
- }
358
- },
359
-
360
- setValueForselect: function(editField, textValue) {
361
- var option_value = editField.children("option:contains('" + textValue + "')").val();
362
-
363
- if (typeof(option_value) !== 'undefined') {
364
- editField.val(option_value);
365
- }
366
- },
309
+ var patternNodes = this.getPatternNodes(this.settings.clone_selector);
310
+ if (patternNodes.editNode == null) {
311
+ alert('did not find any matching node for ' + this.settings.clone_selector);
312
+ return;
313
+ }
314
+
315
+ var editorNode = patternNodes.editNode.clone();
316
+ var clonedNodes = null;
317
+ if (editorNode.attr('id')) editorNode.attr('id', editorNode.attr('id') + this.settings.clone_id_suffix);
318
+ editorNode.attr('name', 'inplace_value');
319
+ editorNode.addClass('editor_field');
320
+ this.setValue(editorNode, this.originalValue);
321
+ clonedNodes = editorNode;
322
+
323
+ if (patternNodes.additionalNodes) {
324
+ patternNodes.additionalNodes.each(function (index, node) {
325
+ var patternNode = $(node).clone();
326
+ if (patternNode.attr('id')) {
327
+ patternNode.attr('id', patternNode.attr('id') + this.settings.clone_id_suffix);
328
+ }
329
+ clonedNodes = clonedNodes.after(patternNode);
330
+ });
331
+ }
332
+ return clonedNodes;
333
+ },
334
+
335
+ getPatternNodes: function(clone_selector) {
336
+ var nodes = {editNode: null, additionalNodes: null};
337
+ var selectedNodes = $(clone_selector);
338
+ var firstNode = selectedNodes.first();
339
+
340
+ if (typeof(firstNode) !== 'undefined') {
341
+ // AS inplace_edit_control_container -> we have to select all child nodes
342
+ // Workaround for ie which does not support css > selector
343
+ if (firstNode.hasClass('as_inplace_pattern')) {
344
+ selectedNodes = firstNode.children();
345
+ }
346
+ nodes.editNode = selectedNodes.first();
347
+ nodes.additionalNodes = selectedNodes.slice(1);
348
+ }
349
+ return nodes;
350
+ },
367
351
 
352
+ setValue: function(editField, textValue) {
353
+ var function_name = 'setValueFor' + editField.get(0).nodeName.toLowerCase();
354
+ if (typeof(this[function_name]) == 'function') {
355
+ this[function_name](editField, textValue);
356
+ } else {
357
+ editField.val(textValue);
358
+ }
359
+ },
360
+
361
+ setValueForselect: function(editField, textValue) {
362
+ var option_value = editField.children("option:contains('" + textValue + "')").val();
363
+
364
+ if (typeof(option_value) !== 'undefined') {
365
+ editField.val(option_value);
366
+ }
367
+ },
368
+
368
369
  inputNameAndClass: function() {
369
370
  return ' name="inplace_value" class="inplace_field" ';
370
371
  },
@@ -386,10 +387,10 @@ $.extend(InlineEditor.prototype, {
386
387
  var value = trim(currentTextAndValue[1] || currentTextAndValue[0]);
387
388
  var text = trim(currentTextAndValue[0]);
388
389
 
389
- var option = $('<option>').val(value).text(text);
390
+ var option = $('<option>').val(value).text(text);
390
391
  editor.append(option);
391
392
  }
392
-
393
+
393
394
  return editor;
394
395
  },
395
396
 
@@ -449,7 +450,7 @@ $.extend(InlineEditor.prototype, {
449
450
  if (enter === event.which)
450
451
  return that.dom.find('form').submit();
451
452
  });
452
-
453
+
453
454
  },
454
455
 
455
456
  handleCancelEditor: function(anEvent) {
@@ -470,15 +471,15 @@ $.extend(InlineEditor.prototype, {
470
471
  if (false === this.triggerDelegateCall('shouldCloseEditInPlace', true, anEvent))
471
472
  return;
472
473
 
473
- var editor = this.dom.find(':input:not(:button)').not('input:checkbox:not(:checked)').not('input:radio:not(:checked)');
474
- var enteredText = '';
475
- if (editor.length > 1) {
476
- enteredText = jQuery.map(editor, function(item, index) {
477
- return $(item).val();
478
- });
479
- } else {
480
- enteredText = editor.val();
481
- }
474
+ var editor = this.dom.find('[name]:input:not(:button,[name=""])').not('input:checkbox:not(:checked)').not('input:radio:not(:checked)');
475
+ var enteredText = '';
476
+ if (editor.length > 1) {
477
+ enteredText = jQuery.map(editor, function(item, index) {
478
+ return $(item).val();
479
+ });
480
+ } else {
481
+ enteredText = editor.val();
482
+ }
482
483
  enteredText = this.triggerDelegateCall('willCloseEditInPlace', enteredText);
483
484
 
484
485
  if (this.isDisabledDefaultSelectChoice()
@@ -555,15 +556,15 @@ $.extend(InlineEditor.prototype, {
555
556
 
556
557
  handleSubmitToServer: function(enteredText) {
557
558
  var data = '';
558
- if (typeof(enteredText) === 'string') {
559
- data += this.settings.update_value + '=' + encodeURIComponent(enteredText) + '&';
560
- } else {
561
- for(var i = 0;i < enteredText.length; i++) {
562
- data += this.settings.update_value + '[]=' + encodeURIComponent(enteredText[i]) + '&';
563
- }
564
- }
565
-
566
- data += this.settings.element_id + '=' + this.dom.attr("id")
559
+ if (typeof(enteredText) === 'string') {
560
+ data += this.settings.update_value + '=' + encodeURIComponent(enteredText) + '&';
561
+ } else {
562
+ for(var i = 0;i < enteredText.length; i++) {
563
+ data += this.settings.update_value + '[]=' + encodeURIComponent(enteredText[i]) + '&';
564
+ }
565
+ }
566
+
567
+ data += this.settings.element_id + '=' + this.dom.attr("id")
567
568
  + ((this.settings.params) ? '&' + this.settings.params : '')
568
569
  + '&' + this.settings.original_html + '=' + encodeURIComponent(this.originalValue) /* DEPRECATED in 2.2.0 */
569
570
  + '&' + this.settings.original_value + '=' + encodeURIComponent(this.originalValue);
@@ -576,19 +577,22 @@ $.extend(InlineEditor.prototype, {
576
577
  type: "POST",
577
578
  data: data,
578
579
  dataType: that.settings.ajax_data_type,
580
+ beforeSend: function(request, settings) {
581
+ that.triggerCallback(that.settings.beforeSend, request, settings);
582
+ },
579
583
  complete: function(request){
580
584
  that.didEndSaving();
581
585
  },
582
586
  success: function(data){
583
- if (that.settings.ajax_data_type == 'html') {
584
- var new_text = data || that.settings.default_text;
585
-
586
- /* put the newly updated info into the original element */
587
- // FIXME: should be affected by the preferences switch
588
- that.dom.html(new_text);
589
- // REFACT: remove dom parameter, already in this, not documented, should be easy to remove
590
- // REFACT: callback should be able to override what gets put into the DOM
591
- }
587
+ if (that.settings.ajax_data_type == 'html') {
588
+ var new_text = data || that.settings.default_text;
589
+
590
+ /* put the newly updated info into the original element */
591
+ // FIXME: should be affected by the preferences switch
592
+ that.dom.html(new_text);
593
+ // REFACT: remove dom parameter, already in this, not documented, should be easy to remove
594
+ // REFACT: callback should be able to override what gets put into the DOM
595
+ }
592
596
  that.triggerCallback(that.settings.success,data);
593
597
  },
594
598
  error: function(request) {
@@ -620,7 +624,7 @@ $.extend(InlineEditor.prototype, {
620
624
  || ! $.isFunction(this.settings.delegate[aDelegateMethodName]))
621
625
  return defaultReturnValue;
622
626
 
623
- var delegateReturnValue = this.settings.delegate[aDelegateMethodName](this.dom, this.settings, optionalEvent);
627
+ var delegateReturnValue = this.settings.delegate[aDelegateMethodName](this.dom, this.settings, optionalEvent);
624
628
  return (undefined === delegateReturnValue)
625
629
  ? defaultReturnValue
626
630
  : delegateReturnValue;
@@ -12,6 +12,15 @@ if (!Element.Methods.highlight) Element.addMethods({highlight: Prototype.emptyFu
12
12
 
13
13
 
14
14
  document.observe("dom:loaded", function() {
15
+ document.on('click', function(event) {
16
+ $$('.action_group.dyn ul').invoke('remove');
17
+ });
18
+ document.on('ajax:complete', '.action_group.dyn ul a', function() {
19
+ var source = event.findElement();
20
+ var action_link = ActiveScaffold.find_action_link(source);
21
+ if (action_link.loading_indicator) action_link.loading_indicator.css('visibility','hidden');
22
+ $(source).up('.action_group.dyn ul').remove();
23
+ });
15
24
  document.on('ajax:create', 'form.as_form', function(event) {
16
25
  var source = event.findElement();
17
26
  var as_form = event.findElement('form');
@@ -42,7 +51,7 @@ document.observe("dom:loaded", function() {
42
51
  return false;
43
52
  }
44
53
  });
45
- document.on('submit', 'form.as_form.as_remote_upload', function(event) {
54
+ document.on('submit', 'form.as_form:not([data-remote])', function(event) {
46
55
  var as_form = event.findElement('form');
47
56
  if (as_form && as_form.readAttribute('data-loading') == 'true') {
48
57
  setTimeout("ActiveScaffold.disable_form('" + as_form.readAttribute('id') + "')", 10);
@@ -95,7 +104,7 @@ document.observe("dom:loaded", function() {
95
104
  var action_link = ActiveScaffold.find_action_link(as_cancel);
96
105
 
97
106
  if (action_link) {
98
- var refresh_data = action_link.readAttribute('data-cancel-refresh') || as_cancel.readAttribute('data-refresh');
107
+ var refresh_data = action_link.tag.readAttribute('data-cancel-refresh') || as_cancel.readAttribute('data-refresh');
99
108
  if (refresh_data && action_link.refresh_url) {
100
109
  event.memo.url = action_link.refresh_url;
101
110
  } else if (!refresh_data || as_cancel.readAttribute('href').blank()) {
@@ -392,8 +401,9 @@ var ActiveScaffold = {
392
401
  return element;
393
402
  },
394
403
 
395
- remove: function(element) {
404
+ remove: function(element, callback) {
396
405
  $(element).remove();
406
+ if (callback) callback();
397
407
  },
398
408
 
399
409
  update_inplace_edit: function(element, value, empty) {
@@ -447,6 +457,20 @@ var ActiveScaffold = {
447
457
  tbody.insert({bottom: html});
448
458
  }
449
459
  new_row = Selector.findChildElements(tbody, ['tr.record']).last();
460
+ } else if (typeof options.insert_at == 'object') {
461
+ var insert_method, get_method, row, id;
462
+ if (options.insert_at.after) {
463
+ insert_method = 'after';
464
+ get_method = 'next';
465
+ } else {
466
+ insert_method = 'before';
467
+ get_method = 'previous';
468
+ }
469
+ if (id = options.insert_at[insert_method]) row = $(id);
470
+ if (row) {
471
+ row.insert({insert_method: html});
472
+ new_row = row[get_method]();
473
+ }
450
474
  }
451
475
 
452
476
  this.stripe(tbody);
@@ -477,11 +501,12 @@ var ActiveScaffold = {
477
501
  action_link.close_previous_adapter();
478
502
  }
479
503
  }
480
- row.remove();
481
- tbody = $(tbody);
482
- this.stripe(tbody);
483
- this.decrement_record_count(tbody.up('div.active-scaffold'));
484
- this.reload_if_empty(tbody, page_reload_url);
504
+ ActiveScaffold.remove(row, function() {
505
+ tbody = $(tbody);
506
+ ActiveScaffold.stripe(tbody);
507
+ ActiveScaffold.decrement_record_count(tbody.up('div.active-scaffold'));
508
+ ActiveScaffold.reload_if_empty(tbody, page_reload_url);
509
+ });
485
510
  },
486
511
 
487
512
  delete_subform_record: function(record) {
@@ -511,6 +536,13 @@ var ActiveScaffold = {
511
536
  element = $(element);
512
537
  return ActiveScaffold.ActionLink.get(element.match('.actions a') ? element : element.up('.as_adapter'));
513
538
  },
539
+
540
+ display_dynamic_action_group: function(link, html) {
541
+ link = $(link);
542
+ link.next('ul').remove();
543
+ link.up('td').addClassName('action_group dyn');
544
+ link.insert({after: html});
545
+ },
514
546
 
515
547
  scroll_to: function(element, checkInViewport) {
516
548
  if (typeof checkInViewport == 'undefined') checkInViewport = true;
@@ -650,17 +682,21 @@ var ActiveScaffold = {
650
682
  var params = null;
651
683
 
652
684
  if (send_form) {
653
- var selector;
685
+ var selector, base = as_form;
686
+ if (send_form == 'row') base = element.up('.association-record, form');
654
687
  if (selector = element.readAttribute('data-update_send_form_selector'))
655
- params = Form.serializeElements(as_form.getElementsBySelector(selector), true);
688
+ params = Form.serializeElements(base.getElementsBySelector(selector), true);
689
+ else if (base != as_form)
690
+ params = Form.serializeElements(base.getElementsBySelector('input, textarea, select'), true);
656
691
  else params = as_form.serialize(true);
692
+ params['_method'] = '';
657
693
  } else {
658
694
  params = {value: val};
659
695
  }
660
696
  params.source_id = source_id;
661
697
 
662
698
  new Ajax.Request(url, {
663
- method: 'get',
699
+ method: 'post',
664
700
  parameters: params,
665
701
  onLoading: function(response) {
666
702
  element.next('img.loading-indicator').style.visibility = 'visible';
@@ -803,7 +839,9 @@ ActiveScaffold.ActionLink = {
803
839
  if (parent && parent.nodeName.toUpperCase() == 'TD') {
804
840
  // record action
805
841
  parent = parent.up('tr.record')
806
- new ActiveScaffold.Actions.Record(parent.select('a.as_action'), parent, parent.down('td.actions .loading-indicator'));
842
+ var loading_indicator = parent.down('td.actions .loading-indicator');
843
+ if (!loading_indicator) loading_indicator = element.parent().find('.loading-indicator');
844
+ new ActiveScaffold.Actions.Record(parent.select('a.as_action'), parent, loading_indicator);
807
845
  } else if (parent && parent.nodeName.toUpperCase() == 'DIV') {
808
846
  //table action
809
847
  new ActiveScaffold.Actions.Table(parent.select('a.as_action'), parent.up('div.active-scaffold').down('tbody.before-header'), parent.down('.loading-indicator'));
@@ -836,10 +874,17 @@ ActiveScaffold.ActionLink.Abstract = Class.create({
836
874
  },
837
875
 
838
876
  close: function() {
839
- this.enable();
840
- this.adapter.remove();
841
- if (this.hide_target) this.target.show();
842
- if (ActiveScaffold.config.scroll_on_close) ActiveScaffold.scroll_to(this.target.id, ActiveScaffold.config.scroll_on_close == 'checkInViewport');
877
+ var link = this;
878
+ ActiveScaffold.remove(this.adapter, function() {
879
+ link.enable();
880
+ if (link.hide_target) link.target.show();
881
+ if (ActiveScaffold.config.scroll_on_close) ActiveScaffold.scroll_to(link.target.id, ActiveScaffold.config.scroll_on_close == 'checkInViewport');
882
+ });
883
+ },
884
+
885
+ reload: function() {
886
+ this.close();
887
+ this.open();
843
888
  },
844
889
 
845
890
  get_new_adapter_id: function() {
@@ -878,6 +923,10 @@ ActiveScaffold.ActionLink.Abstract = Class.create({
878
923
  this.adapter = element;
879
924
  this.adapter.addClassName('as_adapter');
880
925
  this.adapter.store('action_link', this);
926
+ },
927
+
928
+ keep_open: function() {
929
+ return !this.tag.readAttribute('data-keep-open').blank();
881
930
  }
882
931
  });
883
932
 
@@ -901,9 +950,8 @@ ActiveScaffold.Actions.Record = Class.create(ActiveScaffold.Actions.Abstract, {
901
950
  ActiveScaffold.ActionLink.Record = Class.create(ActiveScaffold.ActionLink.Abstract, {
902
951
  close_previous_adapter: function() {
903
952
  this.set.links.each(function(item) {
904
- if (item.url != this.url && item.is_disabled() && item.adapter) {
905
- item.enable();
906
- item.adapter.remove();
953
+ if (item.url != this.url && item.is_disabled() && !item.keep_open() && item.adapter) {
954
+ ActiveScaffold.remove(item.adapter, function () { item.enable(); });
907
955
  }
908
956
  }.bind(this));
909
957
  },
@@ -934,7 +982,7 @@ ActiveScaffold.ActionLink.Record = Class.create(ActiveScaffold.ActionLink.Abstra
934
982
  $super();
935
983
  if (refreshed_content_or_reload) {
936
984
  if (typeof refreshed_content_or_reload == 'string') {
937
- ActiveScaffold.update_row(this.target, refreshed_content_or_update);
985
+ ActiveScaffold.update_row(this.target, refreshed_content_or_reload);
938
986
  } else if (this.refresh_url) {
939
987
  var target = this.target;
940
988
  new Ajax.Request(this.refresh_url, {
@@ -997,11 +1045,6 @@ ActiveScaffold.ActionLink.Table = Class.create(ActiveScaffold.ActionLink.Abstrac
997
1045
  }
998
1046
  ActiveScaffold.highlight(this.adapter.down('td').down());
999
1047
  },
1000
-
1001
- reload: function() {
1002
- this.close();
1003
- this.open();
1004
- },
1005
1048
  });
1006
1049
 
1007
1050
  if (Ajax.InPlaceEditor) {