effective_datatables 1.2.5 → 1.3.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.
- checksums.yaml +4 -4
- data/README.md +65 -6
- data/app/assets/javascripts/effective_datatables/initialize.js.coffee +2 -1
- data/app/controllers/effective/datatables_controller.rb +1 -1
- data/app/helpers/effective_datatables_helper.rb +16 -9
- data/app/models/effective/datatable.rb +48 -13
- data/app/views/effective/datatables/_datatable.html.haml +5 -1
- data/lib/effective_datatables/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 42c5bd2f4e9f486d7aaf7b6eb9f50d518d454b54
|
4
|
+
data.tar.gz: b759ac1ff2af026ff64e514ee520d2e0a894ca53
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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 ==
|
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
|
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
|
-
|
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
|
-
|
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
|
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
|
-
|
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].
|
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].
|
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
|
-
|
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
|
-
|
129
|
-
|
130
|
-
|
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
|
-
|
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
|
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
|
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' =>
|
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
|
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.
|
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-
|
11
|
+
date: 2015-03-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|