Skip to content

Commit 89f4840

Browse files
merge upstream
2 parents 649f38e + 7c8f0a9 commit 89f4840

19 files changed

+357
-66
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ spec/dummy/db/*.sqlite3
77
spec/dummy/log/*.log
88
spec/dummy/tmp/
99
spec/dummy/.sass-cache
10+
.idea

README.md

Lines changed: 146 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -99,14 +99,10 @@ Here we just render the datatable:
9999

100100
```erb
101101
<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) %>
108103
```
109104

105+
110106
## How It Works
111107

112108
When the jQuery DataTable is first initialized on the front-end, it makes an AJAX request back to the server asking for data.
@@ -133,12 +129,11 @@ module Effective
133129
module Datatables
134130
class Posts < Effective::Datatable
135131
default_order :created_at, :desc
132+
default_entries 25
136133

137134
table_column :id, :visible => false
138135

139-
table_column :created_at, :width => '25%' do |post|
140-
post.created_at.strftime("%Y-%m-%d %H:%M:%S")
141-
end
136+
table_column :created_at, :width => '25%'
142137

143138
table_column :updated_at, :proc => Proc.new { |post| nicetime(post.updated_at) } # just a standard helper as defined in helpers/application_helper.rb
144139

@@ -156,7 +151,7 @@ module Effective
156151
end
157152
end
158153

159-
table_column :title, :label => 'Post Title'
154+
table_column :title, :label => 'Post Title', :class => 'col-title'
160155
table_column :actions, :sortable => false, :filter => false, :partial => '/posts/actions'
161156

162157
def collection
@@ -184,11 +179,25 @@ or (complex example):
184179

185180
```ruby
186181
def collection
187-
User.unscoped.uniq
188-
.joins('LEFT JOIN customers ON customers.user_id = users.id')
189-
.select('users.*')
190-
.select('customers.stripe_customer_id AS stripe_customer_id')
191-
.includes(:addresses)
182+
collection = Effective::Order.unscoped.purchased
183+
.joins(:user)
184+
.joins(:order_items)
185+
.group('users.email')
186+
.group('orders.id')
187+
.select('users.email AS email')
188+
.select('orders.*')
189+
.select("#{query_total} AS total")
190+
.select("string_agg(order_items.title, '!!OI!!') AS order_items")
191+
192+
if attributes[:user_id].present?
193+
collection.where(:user_id => attributes[:user_id])
194+
else
195+
collection
196+
end
197+
end
198+
199+
def query_total
200+
"SUM((order_items.price * order_items.quantity) + (CASE order_items.tax_exempt WHEN true THEN 0 ELSE ((order_items.price * order_items.quantity) * order_items.tax_rate) END))"
192201
end
193202
```
194203

@@ -251,6 +260,7 @@ The following options control the display behaviour of the column:
251260
:sortable => true|false # Allow sorting of this column. Otherwise the up/down arrows on the frontend will be disabled.
252261
:visible => true|false # Hide this column at startup. Column visbility can be changed on the frontend. By default, hidden column filter terms are ignored.
253262
:width => '100%'|'100px' # Set the width of this column. Can be set on one, all or some of the columns. If using percentages, should never add upto more than 100%
263+
:class => 'col-example' # Adds an html class to the column's TH and all TD elements. Add more than one class with 'example col-example something'
254264
```
255265

256266
### Filtering Options
@@ -374,10 +384,84 @@ Sort the table by this field and direction on start up
374384
default_order :created_at, :asc|:desc
375385
```
376386

387+
## default_entries
388+
389+
The number of entries to show per page
390+
391+
```ruby
392+
default_entries :all
393+
```
394+
395+
Valid options are `10, 25, 50, 100, 250, 1000, :all`
396+
397+
377398
## Additional Functionality
378399

379400
There are a few other ways to customize the behaviour of effective_datatables
380401

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+
381465
### Customize Filter Behaviour
382466

383467
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.
@@ -444,6 +528,53 @@ table_column :user_id, :if => Proc.new { attributes[:user_id].blank? } do |post|
444528
end
445529
```
446530

531+
### Helper methods
532+
533+
Any non-private methods defined in the datatable model will be available to your table_columns and evaluated in the view_context.
534+
535+
```ruby
536+
module Effective
537+
module Datatables
538+
class Posts < Effective::Datatable
539+
table_column :title do |post|
540+
format_post_title(post)
541+
end
542+
543+
def collection
544+
Post.all
545+
end
546+
547+
def format_post_title(post)
548+
if post.title.start_with?('important')
549+
link_to(post.title.upcase, post_path(post))
550+
else
551+
link_to(post.title, post_path(post))
552+
end
553+
end
554+
555+
end
556+
end
557+
end
558+
```
559+
560+
You can also get the same functionality by including a regular Rails helper within the datatable model.
561+
562+
```ruby
563+
module PostHelper
564+
end
565+
```
566+
567+
```ruby
568+
module Effective
569+
module Datatables
570+
class Posts < Effective::Datatable
571+
include PostsHelper
572+
573+
end
574+
end
575+
end
576+
```
577+
447578
## Array Backed collection
448579

449580
Don't want to use ActiveRecord? Not a problem.

app/assets/javascripts/effective_datatables.bootstrap2.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,5 @@
77
//= require_tree ./effective_datatables
88

99
$.extend( $.fn.dataTable.defaults, {
10-
'dom': "<'row'<'span4'l><'span4'T><'span4'f>r>t<'row'<'span6'i><'span6'p>>"
10+
'dom': "<'row'<'span6'l><'span6'TC>r>t<'row'<'span6'i><'span6'p>>"
1111
});

app/assets/javascripts/effective_datatables.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,6 @@
77
//= require_tree ./effective_datatables
88

99
$.extend( $.fn.dataTable.defaults, {
10-
'dom': "<'row'<'col-xs-4'l><'col-xs-4'T><'col-xs-4'fC>r>t<'row'<'col-xs-6'i><'col-xs-6'p>>"
10+
'dom': "<'row'<'col-xs-6'l><'col-xs-6'TC>r>t<'row'<'col-xs-6'i><'col-xs-6'p>>"
1111
});
1212

app/assets/javascripts/vendor/jquery.dataTables.columnFilter.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -404,8 +404,11 @@
404404
oTable.fnFilter(unescape($(this).val()), iColumn); //Issue 25
405405
fnOnFiltered();
406406
});
407-
if (currentFilter != null && currentFilter != "")//Issue 81
408-
oTable.fnFilter(unescape(currentFilter), iColumn);
407+
// Commented out by Matt.
408+
// Removing this and hackign the fnServerParams for the first request
409+
// Prevents a double AJAX call
410+
// if (currentFilter != null && currentFilter != "")//Issue 81
411+
// oTable.fnFilter(unescape(currentFilter), iColumn);
409412
}
410413
}
411414

app/assets/stylesheets/effective_datatables.bootstrap2.css.scss

Lines changed: 0 additions & 8 deletions
This file was deleted.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
@import 'dataTables/jquery.dataTables.css';
2+
@import 'dataTables/bootstrap/2/jquery.dataTables.bootstrap';
3+
@import 'dataTables/extras/dataTables.tableTools';
4+
@import 'dataTables/extras/dataTables.colVis';
5+
6+
@import 'effective_datatables/overrides';

app/assets/stylesheets/effective_datatables.css.scss

Lines changed: 0 additions & 8 deletions
This file was deleted.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
@import 'dataTables/jquery.dataTables.css';
2+
@import 'dataTables/bootstrap/3/jquery.dataTables.bootstrap';
3+
@import 'dataTables/extras/dataTables.tableTools';
4+
@import 'dataTables/extras/dataTables.colVis';
5+
6+
@import 'effective_datatables/overrides';

app/assets/stylesheets/effective_datatables/_overrides.scss

Lines changed: 60 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,48 @@
11
.dataTables_wrapper { // This is the Header
2-
overflow-x: auto;
2+
overflow: hidden;
33

44
.row {
5-
margin-left: 0px;
6-
margin-right: 0px;
5+
margin-left: -15px;
6+
margin-right: -15px;
7+
}
8+
9+
.form-control {
10+
color: #646464;
11+
border: 1px solid #bcbcbc;
12+
13+
&:focus {
14+
box-shadow: none;
15+
border-color: #03428d;
16+
}
17+
}
18+
19+
.DTTT_button,
20+
.ColVis_Button {
21+
color: #00a6ff !important;
22+
border: 1px solid #e0eeff;
23+
background: #fff;
24+
box-shadow: none;
25+
26+
&:hover:not(.ColVis_MasterButton) {
27+
color: #fff !important;
28+
background: #00a6ff !important;
29+
border: 1px solid #e0eeff;
30+
background: #fff;
31+
box-shadow: none;
32+
}
33+
34+
&.active {
35+
color: #fff;
36+
background: #03428d !important;
37+
}
38+
}
39+
40+
.dataTables_length,
41+
.dataTables_filter,
42+
.dataTables_info,
43+
.dataTables_processing,
44+
.dataTables_paginate {
45+
color: #646464;
746
}
847

948
table.dataTable.sorting-hidden {
@@ -25,6 +64,16 @@
2564

2665
.form-inline, .form-control { width: 100%; }
2766
thead, tr, th { padding-left: 6px; }
67+
68+
tbody th, tbody td, thead th, thead td {
69+
border-left: none;
70+
border-bottom: none;
71+
}
72+
73+
thead th { border-top: none; }
74+
75+
.col-actions { white-space: nowrap; }
76+
.col-datetime { white-space: nowrap; }
2877
}
2978

3079
.dataTables_processing {
@@ -54,10 +103,15 @@
54103
}
55104
}
56105

106+
ol,
107+
ul {
108+
list-style-type: none;
109+
padding-left: 0;
110+
}
111+
57112
.DTTT_container {
58-
float: none;
59-
width: 190px;
60-
margin: auto;
113+
float: right;
114+
margin-right: -3px;
61115
}
62116
}
63117

@@ -69,4 +123,3 @@ div.DTTT_print_info {
69123
h6 { color: black; }
70124
p { color: black; }
71125
}
72-

0 commit comments

Comments
 (0)