active_scaffold-sequel 0.5.1 → 0.6.0

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