active_scaffold-sequel 0.5.1 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -38,6 +38,29 @@ jQuery(document).ready(function() {
38
38
  }
39
39
  return true;
40
40
  });
41
+ jQuery('a.as_action.marked_records_action').live('ajax:before', function(event) {
42
+ var action_link = jQuery(this);
43
+ var marked_records = 'marked_records=' + ActiveScaffold.marked_records.join('%2C');
44
+ var regexp = /(\?|&)marked_records=[^&]*/g;
45
+ var match;
46
+ if (action_link.search[0] == '?') {
47
+ match = regexp.exec(action_link.search);
48
+ if (match) {
49
+ action_link.search = action_link.search.slice(0, match.index) + match[1] + marked_records + action_link.search.slice(regexp.lastIndex, action_link.search.length);
50
+ } else {
51
+ action_link.search = action_link.search + '&' + marked_records;
52
+ }
53
+ } else {
54
+ action_link.search = '?' + marked_records;
55
+ }
56
+ return true;
57
+ });
58
+ jQuery('a.as_action.marked_records_action').live('ajax:complete', function(event) {
59
+ var action_link = jQuery(this);
60
+ ActiveScaffold.mark_records(action_link.readAttribute('data-tbody_id'), false);
61
+ ActiveScaffold.marked_records = [];
62
+ return true;
63
+ });
41
64
  jQuery('a.as_action').live('ajax:success', function(event, response) {
42
65
  var action_link = ActiveScaffold.ActionLink.get(jQuery(this));
43
66
  if (action_link) {
@@ -111,7 +134,7 @@ jQuery(document).ready(function() {
111
134
  ActiveScaffold.report_500_response(as_scaffold);
112
135
  return true;
113
136
  });
114
- jQuery('span.in_place_editor_field').live('hover', function(event) {
137
+ jQuery('span.mark_record_field,span.mark_heading,span.in_place_editor_field').live('hover', function(event) {
115
138
  jQuery(this).data(); // $ 1.4.2 workaround
116
139
  if (event.type == 'mouseenter') {
117
140
  if (typeof(jQuery(this).data('editInPlace')) === 'undefined') jQuery(this).addClass("hover");
@@ -121,6 +144,19 @@ jQuery(document).ready(function() {
121
144
  }
122
145
  return true;
123
146
  });
147
+ jQuery('span.mark_record_field').live('click', function(event) {
148
+ ActiveScaffold.mark_span(jQuery(this));
149
+ });
150
+ jQuery('span.mark_heading').live('click', function(event) {
151
+ var span = jQuery(this);
152
+ var checkbox = span.find('input[type="checkbox"]').first();
153
+ var tbody_id = span.attr('data-tbody_id');
154
+ if (checkbox.checked) {
155
+ ActiveScaffold.mark_records(tbody_id, true);
156
+ } else {
157
+ ActiveScaffold.mark_records(tbody_id, false);
158
+ }
159
+ });
124
160
  jQuery('span.in_place_editor_field').live('click', function(event) {
125
161
  ActiveScaffold.in_place_editor_field_clicked(jQuery(this));
126
162
  });
@@ -653,28 +689,37 @@ var ActiveScaffold = {
653
689
  });
654
690
  },
655
691
 
656
- // element is tbody id
657
- mark_records: function(element, options) {
658
- if (typeof(element) == 'string') element = '#' + element;
659
- var element = jQuery(element);
660
- var mark_checkboxes = jQuery('#' + element.attr('id') + ' > tr.record td.marked-column input[type="checkbox"]');
661
- mark_checkboxes.each(function (index) {
662
- var item = jQuery(this);
663
- if(options.checked === true) {
664
- item.attr('checked', 'checked');
665
- } else {
666
- item.removeAttr('checked');
667
- }
668
- item.attr('value', ('' + !options.checked));
669
- });
670
- if(options.include_mark_all === true) {
671
- var mark_all_checkbox = element.prev('thead').find('th.marked-column_heading span input[type="checkbox"]');
672
- if(options.checked === true) {
673
- mark_all_checkbox.attr('checked', 'checked');
674
- } else {
675
- mark_all_checkbox.removeAttr('checked');
692
+ mark_span: function(span, mark_flag) {
693
+ var record_id = span.attr('data-ie_id');
694
+ var checkbox = span.find('input[type="checkbox"]').first();
695
+ if (mark_flag == false || (typeof(mark_flag) == 'undefined' && !checkbox.checked)) {
696
+ ActiveScaffold.unmark_record(record_id);
697
+ } else {
698
+ ActiveScaffold.mark_record(record_id);
699
+ }
700
+ return checkbox;
701
+ },
702
+
703
+ mark_records: function(tbody_id, mark_flag) {
704
+ var spans = $('#' + tbody_id + ' > tr.record td.marked-column span.mark_record_field');
705
+ var checkbox;
706
+ for (var i = 0; i < spans.length; i++) {
707
+ checkbox = ActiveScaffold.mark_span(spans[i], mark_flag);
708
+ checkbox.checked = mark_flag;
709
+ }
710
+ },
711
+
712
+ marked_records: [],
713
+
714
+ mark_record: function(record_id) {
715
+ ActiveScaffold.marked_records.push(record_id);
716
+ },
717
+
718
+ unmark_record: function(record_id) {
719
+ for (var i = ActiveScaffold.marked_records.length - 1; i >= 0; i--) {
720
+ if (ActiveScaffold.marked_records[i] == record_id) {
721
+ ActiveScaffold.marked_records.splice(i, 1);
676
722
  }
677
- mark_all_checkbox.attr('value', ('' + !options.checked));
678
723
  }
679
724
  },
680
725
 
@@ -61,6 +61,29 @@ document.observe("dom:loaded", function() {
61
61
  }
62
62
  return true;
63
63
  });
64
+ document.on('ajax:before', 'a.as_action.marked_records_action', function(event) {
65
+ var action_link = event.findElement();
66
+ var marked_records = 'marked_records=' + ActiveScaffold.marked_records.join('%2C');
67
+ var regexp = /(\?|&)marked_records=[^&]*/g;
68
+ var match;
69
+ if (action_link.search[0] == '?') {
70
+ match = regexp.exec(action_link.search);
71
+ if (match) {
72
+ action_link.search = action_link.search.slice(0, match.index) + match[1] + marked_records + action_link.search.slice(regexp.lastIndex, action_link.search.length);
73
+ } else {
74
+ action_link.search = action_link.search + '&' + marked_records;
75
+ }
76
+ } else {
77
+ action_link.search = '?' + marked_records;
78
+ }
79
+ return true;
80
+ });
81
+ document.on('ajax:complete', 'a.as_action.marked_records_action', function(event) {
82
+ var action_link = event.findElement();
83
+ ActiveScaffold.mark_records(action_link.readAttribute('data-tbody_id'), false);
84
+ ActiveScaffold.marked_records = [];
85
+ return true;
86
+ });
64
87
  document.on('ajax:success', 'a.as_action', function(event) {
65
88
  var action_link = ActiveScaffold.ActionLink.get(event.findElement());
66
89
  if (action_link && event.memo && event.memo.request) {
@@ -135,15 +158,28 @@ document.observe("dom:loaded", function() {
135
158
  ActiveScaffold.report_500_response(as_scaffold);
136
159
  return true;
137
160
  });
138
- document.on('mouseover', 'span.in_place_editor_field', function(event) {
161
+ document.on('mouseover', 'span.mark_record_field,span.mark_heading,span.in_place_editor_field', function(event) {
139
162
  event.findElement().addClassName('hover');
140
163
  });
141
- document.on('mouseout', 'span.in_place_editor_field', function(event) {
164
+ document.on('mouseout', 'span.mark_record_field,span.mark_heading,span.in_place_editor_field', function(event) {
142
165
  event.findElement().removeClassName('hover');
143
166
  });
167
+ document.on('click', 'span.mark_record_field', function(event) {
168
+ ActiveScaffold.mark_span(event.findElement('span.mark_record_field'));
169
+ });
170
+ document.on('click', 'span.mark_heading', function(event) {
171
+ var span = event.findElement('span.mark_heading');
172
+ var checkbox = span.down('input[type="checkbox"]');
173
+ var tbody_id = span.readAttribute('data-tbody_id');
174
+ if (checkbox.checked) {
175
+ ActiveScaffold.mark_records(tbody_id, true);
176
+ } else {
177
+ ActiveScaffold.mark_records(tbody_id, false);
178
+ }
179
+ });
144
180
  document.on('click', 'span.in_place_editor_field', function(event) {
145
181
  var span = event.findElement('span.in_place_editor_field');
146
-
182
+
147
183
  if (typeof(span.inplace_edit) === 'undefined') {
148
184
  var options = {htmlResponse: false,
149
185
  onEnterHover: null,
@@ -159,14 +195,14 @@ document.observe("dom:loaded", function() {
159
195
  if(!(my_parent.nodeName.toLowerCase() === 'td' || my_parent.nodeName.toLowerCase() === 'th')){
160
196
  my_parent = span.up('td');
161
197
  }
162
-
198
+
163
199
  if (my_parent.nodeName.toLowerCase() === 'td') {
164
200
  var heading_selector = '.' + span.up().readAttribute('class').split(' ')[0] + '_heading';
165
201
  column_heading = span.up('.active-scaffold').down(heading_selector);
166
202
  } else if (my_parent.nodeName.toLowerCase() === 'th') {
167
203
  column_heading = my_parent;
168
204
  }
169
-
205
+
170
206
  var render_url = column_heading.readAttribute('data-ie_render_url'),
171
207
  mode = column_heading.readAttribute('data-ie_mode'),
172
208
  record_id = span.readAttribute('data-ie_id');
@@ -188,7 +224,7 @@ document.observe("dom:loaded", function() {
188
224
  }
189
225
  options['params'] += ("eid=" + span.up('div.active-scaffold').readAttribute('data-eid'));
190
226
  }
191
-
227
+
192
228
  if (mode === 'clone') {
193
229
  options.nodeIdSuffix = record_id;
194
230
  options.inplacePatternSelector = '#' + column_heading.readAttribute('id') + ' .as_inplace_pattern';
@@ -583,26 +619,41 @@ var ActiveScaffold = {
583
619
  );
584
620
  },
585
621
 
586
- // element is tbody id
587
- mark_records: function(element, options) {
588
- var element = $(element);
589
- var mark_checkboxes = $$('#' + element.readAttribute('id') + ' > tr.record td.marked-column input[type="checkbox"]');
590
- mark_checkboxes.each(function(item) {
591
- if(options.checked === true) {
592
- item.writeAttribute({ checked: 'checked' });
593
- } else {
594
- item.removeAttribute('checked');
595
- }
596
- item.writeAttribute('value', ('' + !options.checked));
597
- });
598
- if(options.include_mark_all === true) {
599
- var mark_all_checkbox = element.previous('thead').down('th.marked-column_heading span input[type="checkbox"]');
600
- if(options.checked === true) {
601
- mark_all_checkbox.writeAttribute({ checked: 'checked' });
602
- } else {
603
- mark_all_checkbox.removeAttribute('checked');
622
+ mark_span: function(span, mark_flag) {
623
+ var record_id = span.readAttribute('data-ie_id');
624
+ var checkbox = span.down('input[type="checkbox"]');
625
+ /*
626
+ when the "mark_flag" is "undefined", the "checked" attribute is already set to the new value,
627
+ when the "mark_flag" is defined (this function is called by the "mark_records" function), the "checked" attribute is still set to the old value
628
+ */
629
+ if (mark_flag == false || (typeof(mark_flag) == 'undefined' && !checkbox.checked)) {
630
+ ActiveScaffold.unmark_record(record_id);
631
+ } else {
632
+ ActiveScaffold.mark_record(record_id);
633
+ }
634
+ return checkbox;
635
+ },
636
+
637
+ mark_records: function(tbody_id, mark_flag) {
638
+ var spans = $$('#' + tbody_id + ' > tr.record td.marked-column span.mark_record_field');
639
+ var checkbox;
640
+ for (var i = 0; i < spans.length; i++) {
641
+ checkbox = ActiveScaffold.mark_span(spans[i], mark_flag);
642
+ checkbox.checked = mark_flag;
643
+ }
644
+ },
645
+
646
+ marked_records: [],
647
+
648
+ mark_record: function(record_id) {
649
+ ActiveScaffold.marked_records.push(record_id);
650
+ },
651
+
652
+ unmark_record: function(record_id) {
653
+ for (var i = ActiveScaffold.marked_records.length - 1; i >= 0; i--) {
654
+ if (ActiveScaffold.marked_records[i] == record_id) {
655
+ ActiveScaffold.marked_records.splice(i, 1);
604
656
  }
605
- mark_all_checkbox.writeAttribute('value', ('' + !options.checked));
606
657
  }
607
658
  },
608
659
 
data/doc/README.mark ADDED
@@ -0,0 +1,30 @@
1
+ #########
2
+ # HOWTO #
3
+ #########
4
+
5
+ 1) add the :mark action
6
+ 2) use css class "marked_records_action" for actions working with marked records
7
+ 3) use the controller method "marked_records" to retrieve the IDs of marked records
8
+
9
+ ########################################
10
+ # Example code for Comments controller #
11
+ ########################################
12
+
13
+ config.actions.add :mark
14
+ config.action_links.add('delete_selected', :label => 'Delete selected comments', :type => :collection, :method => :post,
15
+ :position => false, :html_options => {:class => 'marked_records_action'})
16
+
17
+ ...
18
+
19
+ def delete_selected
20
+ record_ids = marked_records
21
+ Comment.where(:id => record_ids).all.each do |comment|
22
+ comment.deleted = true
23
+ comment.save(:columns => [:deleted], :validate => false)
24
+ end
25
+ render :update do |page|
26
+ record_ids.each do |record_id|
27
+ page.remove(element_row_id(:action => 'list', :id => record_id))
28
+ end
29
+ end
30
+ end
@@ -1,16 +1,14 @@
1
- <% @column_span_id ||= element_cell_id(:id => @record.id.to_s, :action => 'update_column', :name => params[:column]) %>
2
- <% unless controller.send :successful?%>
3
- alert('<%= escape_javascript(@record.errors.full_messages.join("\n"))%>');
4
- <% @record.reload%>
5
- <% end%>
6
- <% column = active_scaffold_config.columns[params[:column]]%>
7
- <% if column.inplace_edit%>
8
- ActiveScaffold.replace_html('<%=@column_span_id%>','<%=escape_javascript(get_column_value(@record, column))%>');
9
- <% else%>
10
- <% formatted_value = get_column_value(@record, column)%>
11
- ActiveScaffold.replace_html('<%=@column_span_id%>','<%=escape_javascript(formatted_value)%>');
12
- <% end%>
13
- <% if column.calculation?%>
14
- ActiveScaffold.replace_html('<%=active_scaffold_calculations_id(column)%>', '<%=escape_javascript(render_column_calculation(column))%>');
15
- <% end%>
16
-
1
+ <% @column_span_id ||= element_cell_id(:id => @record.id.to_s, :action => 'update_column', :name => @column.name) -%>
2
+ <% unless controller.send :successful? -%>
3
+ alert('<%= escape_javascript(@record.errors.full_messages.join("\n")) %>');
4
+ <% @record.reload -%>
5
+ <% end -%>
6
+ <% if @column.inplace_edit -%>
7
+ ActiveScaffold.replace_html('<%= @column_span_id %>','<%= escape_javascript(get_column_value(@record, @column)) %>');
8
+ <% else -%>
9
+ <% formatted_value = get_column_value(@record, @column)%>
10
+ ActiveScaffold.replace_html('<%= @column_span_id %>','<%= escape_javascript(formatted_value) %>');
11
+ <% end -%>
12
+ <% if @column.calculation? %>
13
+ ActiveScaffold.replace_html('<%= active_scaffold_calculations_id(@column) %>', '<%= escape_javascript(render_column_calculation(@column)) %>');
14
+ <% end -%>
@@ -71,13 +71,10 @@ module ActiveScaffold::Actions
71
71
  end
72
72
  end
73
73
 
74
- def marked_records
75
- active_scaffold_session_storage[:marked_records] ||= Set.new
76
- end
77
-
78
74
  def default_formats
79
75
  [:html, :js, :json, :xml, :yaml]
80
76
  end
77
+
81
78
  # Returns true if the client accepts one of the MIME types passed to it
82
79
  # ex: accepts? :html, :xml
83
80
  def accepts?(*types)
@@ -52,7 +52,6 @@ module ActiveScaffold::Actions
52
52
  @record ||= destroy_find_record
53
53
  begin
54
54
  self.successful = @record.destroy
55
- marked_records.delete @record.id.to_s if successful?
56
55
  rescue
57
56
  flash[:warning] = as_(:cant_destroy_record, :record => @record.to_label)
58
57
  self.successful = false
@@ -1,75 +1,17 @@
1
1
  module ActiveScaffold::Actions
2
2
  module Mark
3
-
4
3
  def self.included(base)
5
- base.before_filter :mark_authorized?, :only => :mark
6
- #base.prepend_before_filter :assign_marked_records_to_model
7
4
  base.helper_method :marked_records
8
5
  end
9
6
 
10
- def mark_all
11
- if mark_all? || mark_all_scope_forced?
12
- do_mark_all
13
- else
14
- do_unmark
15
- end
16
- respond_to_action(:mark_all)
17
- end
18
7
  protected
19
8
 
20
- def mark_all_respond_to_html
21
- do_list
22
- list_respond_to_html
23
- end
24
-
25
- def mark_all_respond_to_js
26
- do_list
27
- render :action => 'on_mark_all', :locals => {:mark_all => mark_all?}
28
- end
29
-
30
- # We need to give the ActiveRecord classes a handle to currently marked records. We don't want to just pass the object,
31
- # because the object may change. So we give ActiveRecord a proc that ties to the
32
- # marked_records_method on this ApplicationController.
33
- def assign_marked_records_to_model
34
- active_scaffold_config.model.marked_records = marked_records
35
- end
36
-
37
- def mark?
38
- params[:value] == 'true'
39
- end
40
-
41
- def mark_all?
42
- @mark_all ||= [true, 'true', 1, '1', 'T', 't'].include?(params[:value].class == String ? params[:value].downcase : params[:value])
43
- end
44
-
45
- def mark_all_scope_forced?
46
- !params[:mark_target].nil? && params[:mark_target]=='scope'
47
- end
48
-
49
- def do_mark_all
50
- if active_scaffold_config.mark.mark_all_mode == :page && !mark_all_scope_forced? then
51
- each_record_in_page {|record| marked_records << record.id}
52
- else
53
- each_record_in_scope {|record| marked_records << record.id}
54
- end
55
- end
56
-
57
- def do_demark_all
58
- if active_scaffold_config.mark.mark_all_mode == :page then
59
- each_record_in_page {|record| marked_records.delete(record.id)}
9
+ def marked_records
10
+ if params[:marked_records]
11
+ params[:marked_records].split(',').collect {|x| Integer(x)}.uniq
60
12
  else
61
- each_record_in_scope {|record| marked_records.delete(record.id)}
13
+ []
62
14
  end
63
15
  end
64
-
65
- # The default security delegates to ModelPermissions.
66
- # You may override the method to customize.
67
- def mark_authorized?
68
- authorized_for?(:crud_type => :read)
69
- end
70
-
71
- def mark_all_formats
72
- (default_formats + active_scaffold_config.formats).uniq
73
- end
74
16
  end
75
17
  end
@@ -97,17 +97,25 @@ module ActiveScaffold::Actions
97
97
  end
98
98
 
99
99
  def do_update_column
100
- @record = active_scaffold_config.model.find(params[:id])
101
- if @record.authorized_for?(:crud_type => :update, :column => params[:column])
102
- column = active_scaffold_config.columns[params[:column].to_sym]
103
- params[:value] ||= @record.column_for_attribute(params[:column]).default unless @record.column_for_attribute(params[:column]).nil? || @record.column_for_attribute(params[:column])[:allow_null]
104
- unless column.nil?
105
- params[:value] = column_value_from_param_value(@record, column, params[:value])
106
- params[:value] = [] if params[:value].nil? && column.form_ui && column.plural_association?
100
+ # delete from params so update :table won't break urls, also they shouldn't be used in sort links too
101
+ value = params.delete(:value)
102
+ column = params.delete(:column).to_sym
103
+ params.delete(:original_html)
104
+ params.delete(:original_value)
105
+
106
+ @record = find_if_allowed(params[:id], :read)
107
+ if @record.authorized_for?(:crud_type => :update, :column => column)
108
+ @column = active_scaffold_config.columns[column]
109
+ value ||= unless @column.column.nil? || @column.column.null
110
+ @column.column.default == true ? false : @column.column.default
111
+ end
112
+ unless @column.nil?
113
+ value = column_value_from_param_value(@record, @column, value)
114
+ value = [] if value.nil? && @column.form_ui && @column.plural_association?
107
115
  end
108
- @record.send("#{params[:column]}=", params[:value])
116
+ @record.send("#{@column.name}=", value)
109
117
  before_update_save(@record)
110
- @record.save
118
+ self.successful = @record.save
111
119
  after_update_save(@record)
112
120
  end
113
121
  end