effective_datatables 1.2.5 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 087d65c39d2b88c60fcc041b5f7a564bc61bded7
4
- data.tar.gz: 611af4b47aaa06ccb61d59b5d8cd4bcb56363d91
3
+ metadata.gz: 42c5bd2f4e9f486d7aaf7b6eb9f50d518d454b54
4
+ data.tar.gz: b759ac1ff2af026ff64e514ee520d2e0a894ca53
5
5
  SHA512:
6
- metadata.gz: 6ddaca87e620c93d477081bd48fc4e6ba8029fef349ef3042d1b4b4dae736d6603822366d9d7f0741f0ecb5280e91833466ed2fd9a53b520d79b4e5de066d08c
7
- data.tar.gz: e2217a2fd7c3b191bbf755a55f46b5ac85ac6ec44d67a6465302590710982660f3ab4f4a3d56661c4f47864c0d1023e49cd3073cce75c59795e345a9df26e840
6
+ metadata.gz: 70674bc43be1f4d30d4be2f97f73841bcf5300193a2e0968470669bd6902a015a8cf147e1aa91b799779a864fa8d331c165e16f9435111209efa8fa5f51d4aad
7
+ data.tar.gz: ee6b5e40da9ef3d41e70d951be314aabfd4cab55da491bfbb5f5197638ee9666dc06ba32218dd6c0ab6ef57292476a3f7ce61faaaee0ea920933b9dda77e5320
data/README.md CHANGED
@@ -99,14 +99,10 @@ Here we just render the datatable:
99
99
 
100
100
  ```erb
101
101
  <h1>All Posts</h1>
102
-
103
- <% if @datatable.collection.length == 0 %>
104
- <p>There are no posts.</p>
105
- <% else %>
106
- <%= render_datatable(@datatable) %>
107
- <% end %>
102
+ <%= render_datatable(@datatable) %>
108
103
  ```
109
104
 
105
+
110
106
  ## How It Works
111
107
 
112
108
  When the jQuery DataTable is first initialized on the front-end, it makes an AJAX request back to the server asking for data.
@@ -403,6 +399,69 @@ Valid options are `10, 25, 50, 100, 250, 1000, :all`
403
399
 
404
400
  There are a few other ways to customize the behaviour of effective_datatables
405
401
 
402
+ ### Display of an Empty Datatable
403
+
404
+ How an empty datatable (0 display records) is displayed depends on how `render_datatable` is called.
405
+
406
+ To render the full datatable with the default 'No data available in table' message:
407
+
408
+ ```haml
409
+ = render_datatable(@datatable)
410
+ ```
411
+
412
+ To skip rendering the datatable and just output a custom message:
413
+
414
+ ```haml
415
+ = render_datatable(@datatable, 'There are no posts.')
416
+ ```
417
+
418
+ or
419
+
420
+ ```haml
421
+ = render_datatable(@datatable, :empty => 'There are no posts.')
422
+ ```
423
+
424
+ To skip rendering the datatable and instead render given content:
425
+
426
+ ```haml
427
+ = render_datatable(@datatable) do
428
+ %p There are no posts.
429
+ %p
430
+ Have a picture of a cat instead
431
+ = image_tag('cat.png')
432
+ ```
433
+
434
+ ### Checking for Empty collection
435
+
436
+ While the 'what to render when empty' situation is handled by the above syntax, you may still check whether the datatable has records to display by calling `@datatable.empty?` and `@datatable.present?`.
437
+
438
+ The gotcha with these methods is that the `@datatable.view` must first be assigned (which is done automatically by the `render_datatable` view method).
439
+
440
+ This implementation is a bit awkward but has significant performance tradeoffs.
441
+
442
+ To check for an empty datatable collection before it's rendered, you must manually assign a view:
443
+
444
+ ```ruby
445
+ class PostsController < ApplicationController
446
+ def index
447
+ @datatable = Effective::Datatables::Posts.new()
448
+ @datatable.view = view_context # built in Rails controller method refering to the view
449
+ @datatable.empty?
450
+ end
451
+ end
452
+ ```
453
+
454
+ or
455
+
456
+ ```ruby
457
+ class PostsController < ApplicationController
458
+ def index
459
+ @datatable = Effective::Datatables::Posts.new()
460
+ @datatable.empty?(view_context)
461
+ end
462
+ end
463
+ ```
464
+
406
465
  ### Customize Filter Behaviour
407
466
 
408
467
  This gem does its best to provide "just works" filtering of both raw SQL (table_column) and processed results (array_column) out-of-the-box.
@@ -13,6 +13,7 @@ initializeDataTables = ->
13
13
  bProcessing: true
14
14
  bSaveState: true
15
15
  bAutoWidth: false
16
+ deferLoading: datatable.data('total-entries')
16
17
  deferRender: true
17
18
  order: datatable.data('default-order')
18
19
  sAjaxSource: datatable.data('source')
@@ -27,7 +28,7 @@ initializeDataTables = ->
27
28
  # If this is the very first request to the server we have to manually set any selected filter options here
28
29
  # So that we can skip an fnFilter call in the dataTables.columnFilter that results in a double AJAX call
29
30
  ((sEcho = data; break) if data.name == 'sEcho') for data in aoData
30
- if sEcho && sEcho.value == 1
31
+ if sEcho && sEcho.value == 2
31
32
  $.each (datatable.data('filter') || []), (index, filter) ->
32
33
  if(filter.selected)
33
34
  sSearch = undefined
@@ -4,7 +4,7 @@ module Effective
4
4
 
5
5
  def show
6
6
  @datatable = Effective::Datatable.find(params[:id], params[:attributes])
7
- @datatable.view = view_context if @datatable.present?
7
+ @datatable.view = view_context if !@datatable.nil?
8
8
 
9
9
  EffectiveDatatables.authorized?(self, :index, @datatable.try(:collection_class) || Effective::Datatable)
10
10
 
@@ -1,10 +1,23 @@
1
1
  module EffectiveDatatablesHelper
2
- def render_datatable(datatable, opts = {})
2
+ def render_datatable(datatable, opts = {}, &block)
3
3
  datatable.view = self
4
- locals = {:style => :full, :filterable => true, :sortable => true, :table_class => 'table-bordered table-striped'}.merge(opts)
4
+
5
+ locals = {:style => :full, :filterable => true, :sortable => true, :table_class => 'table-bordered table-striped'}
6
+ locals = locals.merge(opts) if opts.kind_of?(Hash)
5
7
  locals[:table_class] = 'sorting-hidden ' + locals[:table_class].to_s if locals[:sortable] == false
6
8
 
7
- render :partial => 'effective/datatables/datatable', :locals => locals.merge(:datatable => datatable)
9
+ # Do we have to look at empty? behaviour
10
+ if (block_given? || opts.kind_of?(String) || (opts.kind_of?(Hash) && opts[:empty].present?)) && datatable.empty?
11
+ if block_given?
12
+ yield; nil
13
+ elsif opts.kind_of?(String)
14
+ opts
15
+ elsif opts.kind_of?(Hash) && opts[:empty].present?
16
+ opts[:empty]
17
+ end
18
+ else
19
+ render :partial => 'effective/datatables/datatable', :locals => locals.merge(:datatable => datatable)
20
+ end
8
21
  end
9
22
 
10
23
  def render_simple_datatable(datatable, opts = {})
@@ -58,12 +71,6 @@ module EffectiveDatatablesHelper
58
71
  ].to_json()
59
72
  end
60
73
 
61
- def datatable_default_entries(datatable)
62
- default_entries = (datatable.default_entries.presence || EffectiveDatatables.default_entries)
63
- default_entries = -1 if default_entries.to_s.downcase == 'all'
64
- [10, 25, 50, 100, 250, 1000, -1].include?(default_entries) ? default_entries : 25
65
- end
66
-
67
74
  def datatable_widths(datatable)
68
75
  datatable.table_columns.values.map { |options| {'sWidth' => options[:width]} if options[:width] }.to_json()
69
76
  end
@@ -44,7 +44,6 @@ module Effective
44
44
  def default_entries(entries)
45
45
  @default_entries = entries
46
46
  end
47
-
48
47
  end
49
48
 
50
49
  def initialize(*args)
@@ -86,8 +85,10 @@ module Effective
86
85
  end.each_with_index { |(_, col), index| col[:index] = index }
87
86
  end
88
87
 
89
- def to_json(options = {})
90
- {
88
+ def to_json
89
+ raise 'Effective::Datatable to_json called with a nil view. Please call render_datatable(@datatable) or @datatable.view = view before this method' unless view.present?
90
+
91
+ @json ||= {
91
92
  :sEcho => params[:sEcho].to_i,
92
93
  :aaData => table_data || [],
93
94
  :iTotalRecords => (
@@ -105,14 +106,35 @@ module Effective
105
106
  }
106
107
  end
107
108
 
108
- # Wish these were protected
109
+ def present?(view = nil)
110
+ self.view = view unless view.nil?
111
+ to_json[:iTotalDisplayRecords] > 0
112
+ end
109
113
 
114
+ def empty?(view = nil)
115
+ self.view = view unless view.nil?
116
+ to_json[:iTotalDisplayRecords] == 0
117
+ end
118
+
119
+ # Wish these were protected
110
120
  def order_column_index
111
- params[:iSortCol_0].to_i
121
+ if params[:iSortCol_0].present?
122
+ params[:iSortCol_0].to_i
123
+ elsif default_order.present?
124
+ table_columns[default_order.keys.first].fetch(:index, 0)
125
+ else
126
+ 0
127
+ end
112
128
  end
113
129
 
114
130
  def order_direction
115
- params[:sSortDir_0].try(:downcase) == 'desc' ? 'DESC' : 'ASC'
131
+ if params[:sSortDir_0].present?
132
+ params[:sSortDir_0].try(:downcase) == 'desc' ? 'DESC' : 'ASC'
133
+ elsif default_order.present?
134
+ default_order.values.first.to_s.downcase == 'desc' ? 'DESC' : 'ASC'
135
+ else
136
+ 'ASC'
137
+ end
116
138
  end
117
139
 
118
140
  def default_order
@@ -120,14 +142,27 @@ module Effective
120
142
  end
121
143
 
122
144
  def default_entries
123
- self.class.instance_variable_get(:@default_entries)
145
+ @default_entries ||= begin
146
+ entries = (self.class.instance_variable_get(:@default_entries).presence || EffectiveDatatables.default_entries)
147
+ entries = -1 if entries.to_s.downcase == 'all'
148
+ [10, 25, 50, 100, 250, 1000, -1].include?(entries) ? entries : 25
149
+ end
124
150
  end
125
151
 
126
152
  def search_terms
127
153
  @search_terms ||= HashWithIndifferentAccess.new().tap do |terms|
128
- table_columns.keys.each_with_index do |col, x|
129
- unless (params["sVisible_#{x}"] == 'false' && table_columns[col][:filter][:when_hidden] != true)
130
- terms[col] = params["sSearch_#{x}"] if params["sSearch_#{x}"].present?
154
+ if params[:sEcho].present?
155
+ table_columns.keys.each_with_index do |col, x|
156
+ unless (params["sVisible_#{x}"] == 'false' && table_columns[col][:filter][:when_hidden] != true)
157
+ terms[col] = params["sSearch_#{x}"] if params["sSearch_#{x}"].present?
158
+ end
159
+ end
160
+ else
161
+ # We are in the initial render and have to apply default search terms only
162
+ table_columns.each do |name, values|
163
+ if (values[:filter][:selected].present?) && (values[:visible] != false || values[:filter][:when_hidden] == true)
164
+ terms[name] = values[:filter][:selected]
165
+ end
131
166
  end
132
167
  end
133
168
  end
@@ -150,7 +185,7 @@ module Effective
150
185
  elsif length > 0
151
186
  length
152
187
  else
153
- 10
188
+ default_entries
154
189
  end
155
190
  end
156
191
 
@@ -188,13 +223,13 @@ module Effective
188
223
  col = collection
189
224
 
190
225
  if active_record_collection?
191
- self.total_records = (collection_class.connection.execute("SELECT COUNT(*) FROM (#{col.to_sql}) AS datatables_count").first['count'] rescue 1)
226
+ self.total_records = (collection_class.connection.execute("SELECT COUNT(*) FROM (#{col.to_sql}) AS datatables_total_count").first['count'] rescue 1)
192
227
 
193
228
  col = table_tool.order(col)
194
229
  col = table_tool.search(col)
195
230
 
196
231
  if table_tool.search_terms.present? && array_tool.search_terms.blank?
197
- self.display_records = (collection_class.connection.execute("SELECT COUNT(*) FROM (#{col.to_sql}) AS datatables_count").first['count'] rescue 1)
232
+ self.display_records = (collection_class.connection.execute("SELECT COUNT(*) FROM (#{col.to_sql}) AS datatables_filtered_count").first['count'] rescue 1)
198
233
  end
199
234
  else
200
235
  self.total_records = col.size
@@ -1,4 +1,4 @@
1
- %table.effective-datatable{:id => "#{datatable.to_param}-table", :class => ('table ' + table_class.to_s), :data => {'effective-datatables-table' => style, 'source' => effective_datatables.datatable_path(datatable, {:format => 'json'}.merge(:attributes => datatable.attributes)), 'filter' => datatable_filter(datatable, filterable), 'non-sortable' => datatable_non_sortable(datatable, sortable), 'non-visible' => datatable_non_visible(datatable), 'widths' => datatable_widths(datatable), 'default-order' => datatable_default_order(datatable), 'default-entries' => datatable_default_entries(datatable), 'column-classes' => datatable_column_classes(datatable)}}
1
+ %table.effective-datatable{:id => "#{datatable.to_param}-table", :class => ('table ' + table_class.to_s), :data => {'effective-datatables-table' => style, 'source' => effective_datatables.datatable_path(datatable, {:format => 'json'}.merge(:attributes => datatable.attributes)), 'filter' => datatable_filter(datatable, filterable), 'non-sortable' => datatable_non_sortable(datatable, sortable), 'non-visible' => datatable_non_visible(datatable), 'widths' => datatable_widths(datatable), 'default-order' => datatable_default_order(datatable), 'default-entries' => datatable.default_entries, 'total-entries' => (datatable.to_json[:iTotalRecords] || false), 'column-classes' => datatable_column_classes(datatable)}}
2
2
  %thead
3
3
  - max_depth = datatable.table_columns.map { |_, opts| opts[:th][:depth].to_i rescue 0 }.max
4
4
  - [*0..max_depth].each do |depth|
@@ -9,3 +9,7 @@
9
9
  - (opts[:append_th] || []).each do |faux_col|
10
10
  %th{(faux_col[:th] || {}).merge({:title => faux_col[:label]})}= faux_col[:label]
11
11
  %tbody
12
+ - (datatable.to_json[:aaData] || []).each do |row|
13
+ %tr
14
+ - row.each do |col|
15
+ %td= col.to_s.html_safe
@@ -1,3 +1,3 @@
1
1
  module EffectiveDatatables
2
- VERSION = '1.2.5'.freeze
2
+ VERSION = '1.3.0'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: effective_datatables
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.5
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Code and Effect
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-03-09 00:00:00.000000000 Z
11
+ date: 2015-03-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails