effective_datatables 1.4.3 → 1.5.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.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +25 -2
  3. data/app/assets/images/dataTables/sort_asc.png +0 -0
  4. data/app/assets/images/dataTables/sort_both.png +0 -0
  5. data/app/assets/images/dataTables/sort_desc.png +0 -0
  6. data/app/assets/javascripts/dataTables/bootstrap/2/jquery.dataTables.bootstrap.js +148 -0
  7. data/app/assets/javascripts/dataTables/bootstrap/3/jquery.dataTables.bootstrap.js +185 -0
  8. data/app/assets/javascripts/dataTables/dataTables.colReorder.min.js +26 -0
  9. data/app/assets/javascripts/dataTables/dataTables.colVis.min.js +24 -0
  10. data/app/assets/javascripts/dataTables/dataTables.fixedColumns.min.js +30 -0
  11. data/app/assets/javascripts/dataTables/dataTables.tableTools.min.js +70 -0
  12. data/app/assets/javascripts/dataTables/jquery.dataTables.min.js +160 -0
  13. data/app/assets/javascripts/effective_datatables.bootstrap2.js +6 -5
  14. data/app/assets/javascripts/effective_datatables.js +6 -5
  15. data/app/assets/javascripts/effective_datatables/initialize.js.coffee.erb +52 -39
  16. data/app/assets/javascripts/vendor/jquery.debounce.min.js +9 -0
  17. data/app/assets/stylesheets/dataTables/bootstrap/2/jquery.dataTables.bootstrap.scss +207 -0
  18. data/app/assets/stylesheets/dataTables/bootstrap/3/jquery.dataTables.bootstrap.scss +280 -0
  19. data/app/assets/stylesheets/dataTables/dataTables.colReorder.min.css +1 -0
  20. data/app/assets/stylesheets/dataTables/dataTables.colVis.min.css +1 -0
  21. data/app/assets/stylesheets/dataTables/dataTables.fixedColumns.min.css +1 -0
  22. data/app/assets/stylesheets/dataTables/dataTables.tableTools.min.css +1 -0
  23. data/app/assets/stylesheets/dataTables/jquery.dataTables.min.css +1 -0
  24. data/app/assets/stylesheets/effective_datatables.bootstrap2.scss +4 -3
  25. data/app/assets/stylesheets/effective_datatables.scss +4 -3
  26. data/app/assets/stylesheets/effective_datatables/_overrides.scss.erb +71 -63
  27. data/app/controllers/effective/datatables_controller.rb +4 -4
  28. data/app/helpers/effective_datatables_helper.rb +24 -30
  29. data/app/models/effective/active_record_datatable_tool.rb +6 -6
  30. data/app/models/effective/array_datatable_tool.rb +18 -8
  31. data/app/models/effective/datatable.rb +98 -44
  32. data/app/views/effective/datatables/_datatable.html.haml +41 -15
  33. data/lib/effective_datatables.rb +0 -1
  34. data/lib/effective_datatables/version.rb +1 -1
  35. metadata +20 -17
  36. data/app/assets/javascripts/vendor/jquery.dataTables.columnFilter.js +0 -832
@@ -1,15 +1,41 @@
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, 'display-records' => (datatable.to_json[:iTotalDisplayRecords] || 0), 'total-records' => (datatable.to_json[:iTotalRecords] || 0), 'column-classes' => datatable_column_classes(datatable)}}
2
- %thead
3
- - max_depth = datatable.table_columns.map { |_, opts| opts[:th][:depth].to_i rescue 0 }.max
4
- - [*0..max_depth].each do |depth|
5
- %tr
6
- - table_columns = datatable.table_columns.select { |_, opts| (opts[:th][:depth] || 0 rescue 0) == depth }
7
- - table_columns.each do |name, opts|
8
- %th{(opts[:th] || {}).merge({:title => opts[:label] || name})}= opts[:label] || name
9
- - (opts[:append_th] || []).each do |faux_col|
10
- %th{(faux_col[:th] || {}).merge({:title => faux_col[:label]})}= faux_col[:label]
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
+ :ruby
2
+ effective_datatable_params = {
3
+ :id => "#{datatable.to_param}-table",
4
+ :class => ('table ' + table_class.to_s),
5
+ :cellpadding => 0,
6
+ :cellspacing => 0,
7
+ :border => 0,
8
+ :width => '100%',
9
+ :data => {
10
+ 'effective-datatables-table' => style,
11
+ 'source' => effective_datatables.datatable_path(datatable, {:format => 'json'}.merge(:attributes => datatable.attributes)).chomp('?'),
12
+ 'column-names' => datatable_column_names(datatable),
13
+ 'non-sortable' => datatable_non_sortable(datatable, sortable),
14
+ 'non-visible' => datatable_non_visible(datatable),
15
+ 'widths' => datatable_widths(datatable),
16
+ 'default-order' => datatable_default_order(datatable),
17
+ 'default-entries' => datatable.default_entries,
18
+ 'display-records' => (datatable.to_json[:recordsFiltered] || 0),
19
+ 'total-records' => (datatable.to_json[:recordsTotal] || 0),
20
+ 'column-classes' => datatable_column_classes(datatable)
21
+ }
22
+ }
23
+
24
+ = simple_form_for datatable, :url => '#', :html => {:id => "#{datatable.to_param}-form" } do |f|
25
+ %table.effective-datatable{effective_datatable_params}
26
+ %thead
27
+ - max_depth = datatable.table_columns.map { |_, opts| opts[:th][:depth].to_i rescue 0 }.max
28
+ - [*0..max_depth].each do |depth|
29
+ %tr
30
+ - table_columns = datatable.table_columns.select { |_, opts| (opts[:th][:depth] || 0 rescue 0) == depth }
31
+ - table_columns.each do |name, opts|
32
+ %th{(opts[:th] || {}).merge({:title => opts[:label] || name})}
33
+ = render_datatable_header_cell(f, name, opts, filterable)
34
+ - (opts[:append_th] || []).each do |faux_col|
35
+ %th{(faux_col[:th] || {}).merge({:title => faux_col[:label]})}
36
+ = faux_col[:label]
37
+ %tbody
38
+ - (datatable.to_json[:data] || []).each do |row|
39
+ %tr
40
+ - row.each do |col|
41
+ %td= col.to_s.html_safe
@@ -1,4 +1,3 @@
1
- require 'jquery-datatables-rails'
2
1
  require 'kaminari'
3
2
 
4
3
  require "effective_datatables/engine"
@@ -1,3 +1,3 @@
1
1
  module EffectiveDatatables
2
- VERSION = '1.4.3'.freeze
2
+ VERSION = '1.5.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.4.3
4
+ version: 1.5.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-05-08 00:00:00.000000000 Z
11
+ date: 2015-06-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -80,20 +80,6 @@ dependencies:
80
80
  - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
- - !ruby/object:Gem::Dependency
84
- name: jquery-datatables-rails
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - ">="
88
- - !ruby/object:Gem::Version
89
- version: 3.1.1
90
- type: :runtime
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - ">="
95
- - !ruby/object:Gem::Version
96
- version: 3.1.1
97
83
  description: Uniquely powerful server-side searching, sorting and filtering of any
98
84
  ActiveRecord or Array collection as well as post-rendered content displayed as a
99
85
  frontend jQuery Datatable
@@ -106,11 +92,28 @@ files:
106
92
  - MIT-LICENSE
107
93
  - README.md
108
94
  - Rakefile
95
+ - app/assets/images/dataTables/sort_asc.png
96
+ - app/assets/images/dataTables/sort_both.png
97
+ - app/assets/images/dataTables/sort_desc.png
109
98
  - app/assets/images/effective_datatables/copy_csv_xls_pdf.swf
99
+ - app/assets/javascripts/dataTables/bootstrap/2/jquery.dataTables.bootstrap.js
100
+ - app/assets/javascripts/dataTables/bootstrap/3/jquery.dataTables.bootstrap.js
101
+ - app/assets/javascripts/dataTables/dataTables.colReorder.min.js
102
+ - app/assets/javascripts/dataTables/dataTables.colVis.min.js
103
+ - app/assets/javascripts/dataTables/dataTables.fixedColumns.min.js
104
+ - app/assets/javascripts/dataTables/dataTables.tableTools.min.js
105
+ - app/assets/javascripts/dataTables/jquery.dataTables.min.js
110
106
  - app/assets/javascripts/effective_datatables.bootstrap2.js
111
107
  - app/assets/javascripts/effective_datatables.js
112
108
  - app/assets/javascripts/effective_datatables/initialize.js.coffee.erb
113
- - app/assets/javascripts/vendor/jquery.dataTables.columnFilter.js
109
+ - app/assets/javascripts/vendor/jquery.debounce.min.js
110
+ - app/assets/stylesheets/dataTables/bootstrap/2/jquery.dataTables.bootstrap.scss
111
+ - app/assets/stylesheets/dataTables/bootstrap/3/jquery.dataTables.bootstrap.scss
112
+ - app/assets/stylesheets/dataTables/dataTables.colReorder.min.css
113
+ - app/assets/stylesheets/dataTables/dataTables.colVis.min.css
114
+ - app/assets/stylesheets/dataTables/dataTables.fixedColumns.min.css
115
+ - app/assets/stylesheets/dataTables/dataTables.tableTools.min.css
116
+ - app/assets/stylesheets/dataTables/jquery.dataTables.min.css
114
117
  - app/assets/stylesheets/effective_datatables.bootstrap2.scss
115
118
  - app/assets/stylesheets/effective_datatables.scss
116
119
  - app/assets/stylesheets/effective_datatables/_overrides.scss.erb
@@ -1,832 +0,0 @@
1
- /*
2
- * http://code.google.com/p/jquery-datatables-column-filter/source/browse/#svn%2Ftrunk%2Fmedia%2Fjs
3
- * File: jquery.dataTables.columnFilter.js
4
- * Version: 1.5.6.
5
- * Author: Jovan Popovic
6
- *
7
- * Copyright 2011-2014 Jovan Popovic, all rights reserved.
8
- *
9
- * This source file is free software, under either the GPL v2 license or a
10
- * BSD style license, as supplied with this software.
11
- *
12
- * This source file is distributed in the hope that it will be useful, but
13
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14
- * or FITNESS FOR A PARTICULAR PURPOSE.
15
- *
16
- * Parameters:"
17
- * @sPlaceHolder String Place where inline filtering function should be placed ("tfoot", "thead:before", "thead:after"). Default is "tfoot"
18
- * @sRangeSeparator String Separator that will be used when range values are sent to the server-side. Default value is "~".
19
- * @sRangeFormat string Default format of the From ... to ... range inputs. Default is From {from} to {to}
20
- * @aoColumns Array Array of the filter settings that will be applied on the columns
21
- */
22
- (function ($) {
23
-
24
-
25
- $.fn.columnFilter = function (options) {
26
-
27
- var asInitVals, i, label, th;
28
-
29
- //var sTableId = "table";
30
- var sRangeFormat = "From {from} to {to}";
31
- //Array of the functions that will override sSearch_ parameters
32
- var afnSearch_ = new Array();
33
- var aiCustomSearch_Indexes = new Array();
34
-
35
- var oFunctionTimeout = null;
36
-
37
- var filterTimerId = null;
38
- var filterDelay = 250;
39
-
40
- var fnOnFiltered = function () { };
41
-
42
- function _fnGetColumnValues(oSettings, iColumn, bUnique, bFiltered, bIgnoreEmpty) {
43
- ///<summary>
44
- ///Return values in the column
45
- ///</summary>
46
- ///<param name="oSettings" type="Object">DataTables settings</param>
47
- ///<param name="iColumn" type="int">Id of the column</param>
48
- ///<param name="bUnique" type="bool">Return only distinct values</param>
49
- ///<param name="bFiltered" type="bool">Return values only from the filtered rows</param>
50
- ///<param name="bIgnoreEmpty" type="bool">Ignore empty cells</param>
51
-
52
- // check that we have a column id
53
- if (typeof iColumn == "undefined") return new Array();
54
-
55
- // by default we only wany unique data
56
- if (typeof bUnique == "undefined") bUnique = true;
57
-
58
- // by default we do want to only look at filtered data
59
- if (typeof bFiltered == "undefined") bFiltered = true;
60
-
61
- // by default we do not wany to include empty values
62
- if (typeof bIgnoreEmpty == "undefined") bIgnoreEmpty = true;
63
-
64
- // list of rows which we're going to loop through
65
- var aiRows;
66
-
67
- // use only filtered rows
68
- if (bFiltered == true) aiRows = oSettings.aiDisplay;
69
- // use all rows
70
- else aiRows = oSettings.aiDisplayMaster; // all row numbers
71
-
72
- // set up data array
73
- var asResultData = new Array();
74
-
75
- for (var i = 0, c = aiRows.length; i < c; i++) {
76
- var iRow = aiRows[i];
77
- var aData = oTable.fnGetData(iRow);
78
- var sValue = aData[iColumn];
79
-
80
- // ignore empty values?
81
- if (bIgnoreEmpty == true && sValue.length == 0) continue;
82
-
83
- // ignore unique values?
84
- else if (bUnique == true && jQuery.inArray(sValue, asResultData) > -1) continue;
85
-
86
- // else push the value onto the result data array
87
- else asResultData.push(sValue);
88
- }
89
-
90
- return asResultData.sort();
91
- }
92
-
93
- function _fnColumnIndex(iColumnIndex) {
94
- if (properties.bUseColVis)
95
- return iColumnIndex;
96
- else
97
- return oTable.fnSettings().oApi._fnVisibleToColumnIndex(oTable.fnSettings(), iColumnIndex);
98
- //return iColumnIndex;
99
- //return oTable.fnSettings().oApi._fnColumnIndexToVisible(oTable.fnSettings(), iColumnIndex);
100
- }
101
-
102
- function fnCreateInput(oTable, regex, smart, bIsNumber, iFilterLength, iMaxLenght) {
103
- var sCSSClass = "text_filter form-control";
104
- if (bIsNumber)
105
- sCSSClass = "number_filter form-control";
106
-
107
- label = label.replace(/(^\s*)|(\s*$)/g, "");
108
- var currentFilter = oTable.fnSettings().aoPreSearchCols[i].sSearch;
109
- var search_init = 'search_init ';
110
- var inputvalue = label;
111
- if (currentFilter != '' && currentFilter != '^') {
112
- if (bIsNumber && currentFilter.charAt(0) == '^')
113
- inputvalue = currentFilter.substr(1); //ignore trailing ^
114
- else
115
- inputvalue = currentFilter;
116
- search_init = '';
117
- }
118
-
119
-
120
- var input = $('<input type="text" class="' + search_init + sCSSClass + '" placeholder="' + inputvalue + '" value="' + inputvalue + '" rel="' + i + '"/>');
121
- if (iMaxLenght != undefined && iMaxLenght != -1) {
122
- input.attr('maxlength', iMaxLenght);
123
- }
124
- th.html(input);
125
- if (bIsNumber)
126
- th.wrapInner('<span class="filter_column filter_number" />');
127
- else
128
- th.wrapInner('<span class="filter_column filter_text" />');
129
-
130
- asInitVals[i] = label;
131
- var index = i;
132
-
133
- if (bIsNumber && !oTable.fnSettings().oFeatures.bServerSide) {
134
- input.keyup(function () {
135
- /* Filter on the column all numbers that starts with the entered value */
136
- oTable.fnFilter('^' + this.value, _fnColumnIndex(index), true, false); //Issue 37
137
- fnOnFiltered();
138
- });
139
- } else {
140
- input.keyup(function () {
141
- var value = this.value;
142
-
143
- window.clearTimeout(filterTimerId);
144
- filterTimerId = window.setTimeout(function() {
145
- oTable.fnFilter(value, _fnColumnIndex(index), regex, smart); //Issue 37
146
- fnOnFiltered();
147
- }, filterDelay);
148
- });
149
- }
150
-
151
- input.click(function(e) {
152
- e.preventDefault();
153
- return false;
154
- });
155
-
156
- input.focus(function () {
157
- if ($(this).hasClass("search_init")) {
158
- $(this).removeClass("search_init");
159
- this.value = "";
160
- }
161
- });
162
- input.blur(function () {
163
- if (this.value == "") {
164
- $(this).addClass("search_init");
165
- this.value = asInitVals[index];
166
- }
167
- });
168
- }
169
-
170
- function fnCreateRangeInput(oTable) {
171
-
172
- //var currentFilter = oTable.fnSettings().aoPreSearchCols[i].sSearch;
173
- th.html(_fnRangeLabelPart(0));
174
- var sFromId = oTable.attr("id") + '_range_from_' + i;
175
- var from = $('<input type="text" class="number_range_filter form-control" id="' + sFromId + '" rel="' + i + '"/>');
176
- th.append(from);
177
- th.append(_fnRangeLabelPart(1));
178
- var sToId = oTable.attr("id") + '_range_to_' + i;
179
- var to = $('<input type="text" class="number_range_filter form-control" id="' + sToId + '" rel="' + i + '"/>');
180
- th.append(to);
181
- th.append(_fnRangeLabelPart(2));
182
- th.wrapInner('<span class="filter_column filter_number_range form-control" />');
183
- var index = i;
184
- aiCustomSearch_Indexes.push(i);
185
-
186
-
187
-
188
- //------------start range filtering function
189
-
190
-
191
- /* Custom filtering function which will filter data in column four between two values
192
- * Author: Allan Jardine, Modified by Jovan Popovic
193
- */
194
- //$.fn.dataTableExt.afnFiltering.push(
195
- oTable.dataTableExt.afnFiltering.push(
196
- function (oSettings, aData, iDataIndex) {
197
- if (oTable.attr("id") != oSettings.sTableId)
198
- return true;
199
- // Try to handle missing nodes more gracefully
200
- if (document.getElementById(sFromId) == null)
201
- return true;
202
- var iMin = document.getElementById(sFromId).value * 1;
203
- var iMax = document.getElementById(sToId).value * 1;
204
- var iValue = aData[_fnColumnIndex(index)] == "-" ? 0 : aData[_fnColumnIndex(index)] * 1;
205
- if (iMin == "" && iMax == "") {
206
- return true;
207
- }
208
- else if (iMin == "" && iValue <= iMax) {
209
- return true;
210
- }
211
- else if (iMin <= iValue && "" == iMax) {
212
- return true;
213
- }
214
- else if (iMin <= iValue && iValue <= iMax) {
215
- return true;
216
- }
217
- return false;
218
- }
219
- );
220
- //------------end range filtering function
221
-
222
-
223
-
224
- $('#' + sFromId + ',#' + sToId, th).keyup(function () {
225
-
226
- var iMin = document.getElementById(sFromId).value * 1;
227
- var iMax = document.getElementById(sToId).value * 1;
228
- if (iMin != 0 && iMax != 0 && iMin > iMax)
229
- return;
230
-
231
- oTable.fnDraw();
232
- fnOnFiltered();
233
- });
234
-
235
-
236
- }
237
-
238
-
239
- function fnCreateDateRangeInput(oTable) {
240
-
241
- var aoFragments = sRangeFormat.split(/[}{]/);
242
-
243
- th.html("");
244
- //th.html(_fnRangeLabelPart(0));
245
- var sFromId = oTable.attr("id") + '_range_from_' + i;
246
- var from = $('<input type="text" class="date_range_filter form-control" id="' + sFromId + '" rel="' + i + '"/>');
247
- from.datepicker();
248
- //th.append(from);
249
- //th.append(_fnRangeLabelPart(1));
250
- var sToId = oTable.attr("id") + '_range_to_' + i;
251
- var to = $('<input type="text" class="date_range_filter form-control" id="' + sToId + '" rel="' + i + '"/>');
252
- //th.append(to);
253
- //th.append(_fnRangeLabelPart(2));
254
-
255
- for (ti = 0; ti < aoFragments.length; ti++) {
256
-
257
- if (aoFragments[ti] == properties.sDateFromToken) {
258
- th.append(from);
259
- } else {
260
- if (aoFragments[ti] == properties.sDateToToken) {
261
- th.append(to);
262
- } else {
263
- th.append(aoFragments[ti]);
264
- }
265
- }
266
-
267
-
268
- }
269
-
270
-
271
- th.wrapInner('<span class="filter_column filter_date_range" />');
272
- to.datepicker();
273
- var index = i;
274
- aiCustomSearch_Indexes.push(i);
275
-
276
-
277
- //------------start date range filtering function
278
-
279
- //$.fn.dataTableExt.afnFiltering.push(
280
- oTable.dataTableExt.afnFiltering.push(
281
- function (oSettings, aData, iDataIndex) {
282
- if (oTable.attr("id") != oSettings.sTableId)
283
- return true;
284
-
285
- var dStartDate = from.datepicker("getDate");
286
-
287
- var dEndDate = to.datepicker("getDate");
288
-
289
- if (dStartDate == null && dEndDate == null) {
290
- return true;
291
- }
292
-
293
- var dCellDate = null;
294
- try {
295
- if (aData[_fnColumnIndex(index)] == null || aData[_fnColumnIndex(index)] == "")
296
- return false;
297
- dCellDate = $.datepicker.parseDate($.datepicker.regional[""].dateFormat, aData[_fnColumnIndex(index)]);
298
- } catch (ex) {
299
- return false;
300
- }
301
- if (dCellDate == null)
302
- return false;
303
-
304
-
305
- if (dStartDate == null && dCellDate <= dEndDate) {
306
- return true;
307
- }
308
- else if (dStartDate <= dCellDate && dEndDate == null) {
309
- return true;
310
- }
311
- else if (dStartDate <= dCellDate && dCellDate <= dEndDate) {
312
- return true;
313
- }
314
- return false;
315
- }
316
- );
317
- //------------end date range filtering function
318
-
319
- $('#' + sFromId + ',#' + sToId, th).change(function () {
320
- oTable.fnDraw();
321
- fnOnFiltered();
322
- });
323
-
324
-
325
- }
326
-
327
- function fnCreateColumnSelect(oTable, aData, iColumn, nTh, sLabel, bRegex, oSelected, bMultiselect) {
328
- if (aData == null)
329
- aData = _fnGetColumnValues(oTable.fnSettings(), iColumn, true, false, true);
330
- var index = iColumn;
331
- var currentFilter = oTable.fnSettings().aoPreSearchCols[i].sSearch;
332
- if (currentFilter == null || currentFilter == "")//Issue 81
333
- currentFilter = oSelected;
334
-
335
- var r = '<select class="search_init select_filter form-control" rel="' + i + '"><option value="" class="search_init">' + sLabel + '</option>';
336
- if(bMultiselect) {
337
- r = '<select class="search_init select_filter form-control" rel="' + i + '" multiple>';
338
- }
339
- var j = 0;
340
- var iLen = aData.length;
341
- for (j = 0; j < iLen; j++) {
342
-
343
- if (typeof (aData[j]) != 'object') {
344
- var selected = '';
345
- if (escape(aData[j]) == currentFilter
346
- || escape(aData[j]) == escape(currentFilter)
347
- )
348
- selected = 'selected '
349
- r += '<option ' + selected + ' value="' + escape(aData[j]) + '">' + aData[j] + '</option>';
350
- }
351
- else {
352
- var selected = '';
353
- if (bRegex) {
354
- //Do not escape values if they are explicitely set to avoid escaping special characters in the regexp
355
- if (aData[j][0] == currentFilter) selected = 'selected ';
356
- r += '<option ' + selected + 'value="' + aData[j][0] + '">' + aData[j][1] + '</option>';
357
- } else {
358
- if (escape(aData[j][0]) == currentFilter) selected = 'selected ';
359
- r += '<option ' + selected + 'value="' + escape(aData[j][0]) + '">' + aData[j][1] + '</option>';
360
- }
361
- }
362
- }
363
-
364
- var select = $(r + '</select>');
365
- nTh.html(select);
366
- nTh.wrapInner('<span class="filter_column filter_select" />');
367
-
368
- select.click(function(e) {
369
- e.preventDefault();
370
- return false;
371
- });
372
-
373
- if(bMultiselect) {
374
- select.change(function () {
375
- if ($(this).val() != "") {
376
- $(this).removeClass("search_init");
377
- } else {
378
- $(this).addClass("search_init");
379
- }
380
- var selectedOptions = $(this).val();
381
- var asEscapedFilters = [];
382
- if(selectedOptions==null || selectedOptions==[]){
383
- var re = '^(.*)$';
384
- }else{
385
- $.each( selectedOptions, function( i, sFilter ) {
386
- asEscapedFilters.push( fnRegExpEscape( sFilter ) );
387
- } );
388
- var re = '^(' + asEscapedFilters.join('|') + ')$';
389
- }
390
-
391
- oTable.fnFilter( re, index, true, false );
392
- });
393
- } else {
394
- select.change(function () {
395
- //var val = $(this).val();
396
- if ($(this).val() != "") {
397
- $(this).removeClass("search_init");
398
- } else {
399
- $(this).addClass("search_init");
400
- }
401
- if (bRegex)
402
- oTable.fnFilter($(this).val(), iColumn, bRegex); //Issue 41
403
- else
404
- oTable.fnFilter(unescape($(this).val()), iColumn); //Issue 25
405
- fnOnFiltered();
406
- });
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);
412
- }
413
- }
414
-
415
- function fnCreateSelect(oTable, aData, bRegex, oSelected, bMultiselect) {
416
- var oSettings = oTable.fnSettings();
417
- if ( (aData == null || typeof(aData) == 'function' ) && oSettings.sAjaxSource != "" && !oSettings.oFeatures.bServerSide) {
418
- // Add a function to the draw callback, which will check for the Ajax data having
419
- // been loaded. Use a closure for the individual column elements that are used to
420
- // built the column filter, since 'i' and 'th' (etc) are locally "global".
421
- oSettings.aoDrawCallback.push({
422
- "fn": (function (iColumn, nTh, sLabel) {
423
- return function (oSettings) {
424
- // Only rebuild the select on the second draw - i.e. when the Ajax
425
- // data has been loaded.
426
- if (oSettings.iDraw == 2 && oSettings.sAjaxSource != null && oSettings.sAjaxSource != "" && !oSettings.oFeatures.bServerSide) {
427
- return fnCreateColumnSelect(oTable, aData && aData(oSettings.aoData, oSettings), _fnColumnIndex(iColumn), nTh, sLabel, bRegex, oSelected, bMultiselect); //Issue 37
428
- }
429
- };
430
- })(i, th, label),
431
- "sName": "column_filter_" + i
432
- });
433
- }
434
- // Regardless of the Ajax state, build the select on first pass
435
- fnCreateColumnSelect(oTable, typeof(aData) == 'function' ? null: aData, _fnColumnIndex(i), th, label, bRegex, oSelected, bMultiselect); //Issue 37
436
-
437
- }
438
-
439
- function fnRegExpEscape( sText ) {
440
- return sText.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
441
- };
442
-
443
- function fnCreateDropdown(aData) {
444
- var index = i;
445
- var r = '<div class="dropdown select_filter form-control"><a class="dropdown-toggle" data-toggle="dropdown" href="#">' + label + '<b class="caret"></b></a><ul class="dropdown-menu" role="menu"><li data-value=""><a>Show All</a></li>', j, iLen = aData.length;
446
-
447
- for (j = 0; j < iLen; j++) {
448
- r += '<li data-value="' + aData[j] + '"><a>' + aData[j] + '</a></li>';
449
- }
450
- var select = $(r + '</ul></div>');
451
- th.html(select);
452
- th.wrapInner('<span class="filterColumn filter_select" />');
453
- select.find('li').click(function () {
454
- oTable.fnFilter($(this).data('value'), index);
455
- });
456
- }
457
-
458
-
459
- function fnCreateCheckbox(oTable, aData) {
460
-
461
- if (aData == null)
462
- aData = _fnGetColumnValues(oTable.fnSettings(), i, true, true, true);
463
- var index = i;
464
-
465
- var r = '', j, iLen = aData.length;
466
-
467
- //clean the string
468
- var localLabel = label.replace('%', 'Perc').replace("&", "AND").replace("$", "DOL").replace("£", "STERL").replace("@", "AT").replace(/\s/g, "_");
469
- localLabel = localLabel.replace(/[^a-zA-Z 0-9]+/g, '');
470
- //clean the string
471
-
472
- //button label override
473
- var labelBtn = label;
474
- if (properties.sFilterButtonText != null || properties.sFilterButtonText != undefined) {
475
- labelBtn = properties.sFilterButtonText;
476
- }
477
-
478
- var relativeDivWidthToggleSize = 10;
479
- var numRow = 12; //numero di checkbox per colonna
480
- var numCol = Math.floor(iLen / numRow);
481
- if (iLen % numRow > 0) {
482
- numCol = numCol + 1;
483
- };
484
-
485
- //count how many column should be generated and split the div size
486
- var divWidth = 100 / numCol - 2;
487
-
488
- var divWidthToggle = relativeDivWidthToggleSize * numCol;
489
-
490
- if (numCol == 1) {
491
- divWidth = 20;
492
- }
493
-
494
- var divRowDef = '<div style="float:left; min-width: ' + divWidth + '%; " >';
495
- var divClose = '</div>';
496
-
497
- var uniqueId = oTable.attr("id") + localLabel;
498
- var buttonId = "chkBtnOpen" + uniqueId;
499
- var checkToggleDiv = uniqueId + "-flt-toggle";
500
- r += '<button id="' + buttonId + '" class="checkbox_filter btn btn-default" > ' + labelBtn + '</button>'; //filter button witch open dialog
501
- r += '<div id="' + checkToggleDiv + '" '
502
- + 'title="' + label + '" '
503
- + 'rel="' + i + '" '
504
- + 'class="toggle-check ui-widget-content ui-corner-all" style="width: ' + (divWidthToggle) + '%; " >'; //dialog div
505
- //r+= '<div align="center" style="margin-top: 5px; "> <button id="'+buttonId+'Reset" class="checkbox_filter" > reset </button> </div>'; //reset button and its div
506
- r += divRowDef;
507
-
508
- for (j = 0; j < iLen; j++) {
509
-
510
- //if last check close div
511
- if (j % numRow == 0 && j != 0) {
512
- r += divClose + divRowDef;
513
- }
514
-
515
- var sLabel = aData[j];
516
- var sValue = aData[j];
517
-
518
- if (typeof (aData[j]) == 'object') {
519
- sLabel = aData[j].label;
520
- sValue = aData[j].value;
521
- }
522
-
523
- //check button
524
- r += '<input class="search_init checkbox_filter btn btn-default" type="checkbox" id= "' + uniqueId + '_cb_' + sValue + '" name= "' + localLabel + '" value="' + sValue + '" >' + sLabel + '<br/>';
525
-
526
- var checkbox = $(r);
527
- th.html(checkbox);
528
- th.wrapInner('<span class="filter_column filter_checkbox" />');
529
- //on every checkbox selection
530
- checkbox.change(function () {
531
-
532
- var search = '';
533
- var or = '|'; //var for select checks in 'or' into the regex
534
- var resSize = $('input:checkbox[name="' + localLabel + '"]:checked').size();
535
- $('input:checkbox[name="' + localLabel + '"]:checked').each(function (index) {
536
-
537
- //search = search + ' ' + $(this).val();
538
- //concatenation for selected checks in or
539
- if ((index == 0 && resSize == 1)
540
- || (index != 0 && index == resSize - 1)) {
541
- or = '';
542
- }
543
- //trim
544
- search = search.replace(/^\s+|\s+$/g, "");
545
- search = search + $(this).val() + or;
546
- or = '|';
547
-
548
- });
549
-
550
-
551
- if (search != "") {
552
- $('input:checkbox[name="' + localLabel + '"]').removeClass("search_init");
553
- } else {
554
- $('input:checkbox[name="' + localLabel + '"]').addClass("search_init");
555
- }
556
- /* Old code for setting search_init CSS class on checkboxes if any of them is checked
557
- for (var jj = 0; jj < iLen; jj++) {
558
- if (search != "") {
559
- $('#' + aData[jj]).removeClass("search_init");
560
- } else {
561
- $('#' + aData[jj]).addClass("search_init");
562
- }
563
- }
564
- */
565
-
566
- //execute search
567
- oTable.fnFilter(search, index, true, false);
568
- fnOnFiltered();
569
- });
570
- }
571
-
572
- //filter button
573
- $('#' + buttonId).button();
574
- //dialog
575
- $('#' + checkToggleDiv).dialog({
576
- //height: 140,
577
- autoOpen: false,
578
- //show: "blind",
579
- hide: "blind",
580
- buttons: [{
581
- text: "Reset",
582
- click: function () {
583
- //$('#'+buttonId).removeClass("filter_selected"); //LM remove border if filter selected
584
- $('input:checkbox[name="' + localLabel + '"]:checked').each(function (index3) {
585
- $(this).attr('checked', false);
586
- $(this).addClass("search_init");
587
- });
588
- oTable.fnFilter('', index, true, false);
589
- fnOnFiltered();
590
- return false;
591
- }
592
- },
593
- {
594
- text: "Close",
595
- click: function () { $(this).dialog("close"); }
596
- }
597
- ]
598
- });
599
-
600
-
601
- $('#' + buttonId).click(function () {
602
-
603
- $('#' + checkToggleDiv).dialog('open');
604
- var target = $(this);
605
- $('#' + checkToggleDiv).dialog("widget").position({ my: 'top',
606
- at: 'bottom',
607
- of: target
608
- });
609
-
610
- return false;
611
- });
612
-
613
- var fnOnFilteredCurrent = fnOnFiltered;
614
-
615
- fnOnFiltered = function () {
616
- var target = $('#' + buttonId);
617
- $('#' + checkToggleDiv).dialog("widget").position({ my: 'top',
618
- at: 'bottom',
619
- of: target
620
- });
621
- fnOnFilteredCurrent();
622
- };
623
- //reset
624
- /*
625
- $('#'+buttonId+"Reset").button();
626
- $('#'+buttonId+"Reset").click(function(){
627
- $('#'+buttonId).removeClass("filter_selected"); //LM remove border if filter selected
628
- $('input:checkbox[name="'+localLabel+'"]:checked').each(function(index3) {
629
- $(this).attr('checked', false);
630
- $(this).addClass("search_init");
631
- });
632
- oTable.fnFilter('', index, true, false);
633
- return false;
634
- });
635
- */
636
- }
637
-
638
-
639
-
640
-
641
- function _fnRangeLabelPart(iPlace) {
642
- switch (iPlace) {
643
- case 0:
644
- return sRangeFormat.substring(0, sRangeFormat.indexOf("{from}"));
645
- case 1:
646
- return sRangeFormat.substring(sRangeFormat.indexOf("{from}") + 6, sRangeFormat.indexOf("{to}"));
647
- default:
648
- return sRangeFormat.substring(sRangeFormat.indexOf("{to}") + 4);
649
- }
650
- }
651
-
652
-
653
-
654
-
655
- var oTable = this;
656
-
657
- var defaults = {
658
- sPlaceHolder: "foot",
659
- sRangeSeparator: "~",
660
- iFilteringDelay: 500,
661
- aoColumns: null,
662
- sRangeFormat: "From {from} to {to}",
663
- sDateFromToken: "from",
664
- sDateToToken: "to"
665
- };
666
-
667
- var properties = $.extend(defaults, options);
668
-
669
- return this.each(function () {
670
-
671
- if (!oTable.fnSettings().oFeatures.bFilter)
672
- return;
673
- asInitVals = new Array();
674
-
675
- var aoFilterCells = oTable.fnSettings().aoFooter[0];
676
-
677
- var oHost = oTable.fnSettings().nTFoot; //Before fix for ColVis
678
- var sFilterRow = "tr"; //Before fix for ColVis
679
-
680
- if (properties.sPlaceHolder == "head:after") {
681
- var tr = $("tr", oTable.fnSettings().nTHead).detach();
682
- //tr.appendTo($(oTable.fnSettings().nTHead));
683
- if (oTable.fnSettings().bSortCellsTop) {
684
- tr.prependTo($(oTable.fnSettings().nTHead));
685
- //tr.appendTo($("thead", oTable));
686
- aoFilterCells = oTable.fnSettings().aoHeader[1];
687
- }
688
- else {
689
- tr.appendTo($(oTable.fnSettings().nTHead));
690
- //tr.prependTo($("thead", oTable));
691
- aoFilterCells = oTable.fnSettings().aoHeader[0];
692
- }
693
-
694
- sFilterRow = "tr:last";
695
- oHost = oTable.fnSettings().nTHead;
696
-
697
- } else if (properties.sPlaceHolder == "head:before") {
698
-
699
- if (oTable.fnSettings().bSortCellsTop) {
700
- var tr = $("tr:first", oTable.fnSettings().nTHead).detach();
701
- tr.appendTo($(oTable.fnSettings().nTHead));
702
- aoFilterCells = oTable.fnSettings().aoHeader[1];
703
- } else {
704
- aoFilterCells = oTable.fnSettings().aoHeader[0];
705
- }
706
- /*else {
707
- //tr.prependTo($("thead", oTable));
708
- sFilterRow = "tr:first";
709
- }*/
710
-
711
- sFilterRow = "tr:first";
712
-
713
- oHost = oTable.fnSettings().nTHead;
714
-
715
-
716
- }
717
-
718
- //$(sFilterRow + " th", oHost).each(function (index) {//bug with ColVis
719
- $(aoFilterCells).each(function (index) {//fix for ColVis
720
- i = index;
721
- var aoColumn = { type: "text",
722
- bRegex: false,
723
- bSmart: true,
724
- iMaxLenght: -1,
725
- iFilterLength: 0
726
- };
727
- if (properties.aoColumns != null) {
728
- if (properties.aoColumns.length < i || properties.aoColumns[i] == null)
729
- return;
730
- aoColumn = properties.aoColumns[i];
731
- }
732
- //label = $(this).text(); //Before fix for ColVis
733
- label = $($(this)[0].cell).text(); //Fix for ColVis
734
- if (aoColumn.sSelector == null) {
735
- //th = $($(this)[0]);//Before fix for ColVis
736
- th = $($(this)[0].cell); //Fix for ColVis
737
- }
738
- else {
739
- th = $(aoColumn.sSelector);
740
- if (th.length == 0)
741
- th = $($(this)[0].cell);
742
- }
743
-
744
- if (aoColumn != null) {
745
- if (aoColumn.sRangeFormat != null)
746
- sRangeFormat = aoColumn.sRangeFormat;
747
- else
748
- sRangeFormat = properties.sRangeFormat;
749
- switch (aoColumn.type) {
750
- case "null":
751
- break;
752
- case "number":
753
- fnCreateInput(oTable, true, false, true, aoColumn.iFilterLength, aoColumn.iMaxLenght);
754
- break;
755
- case "select":
756
- if (aoColumn.bRegex != true)
757
- aoColumn.bRegex = false;
758
- fnCreateSelect(oTable, aoColumn.values, aoColumn.bRegex, aoColumn.selected, aoColumn.multiple);
759
- break;
760
- case "number-range":
761
- fnCreateRangeInput(oTable);
762
- break;
763
- case "date-range":
764
- fnCreateDateRangeInput(oTable);
765
- break;
766
- case "checkbox":
767
- fnCreateCheckbox(oTable, aoColumn.values);
768
- break;
769
- case "twitter-dropdown":
770
- case "dropdown":
771
- fnCreateDropdown(aoColumn.values);
772
- break;
773
- case "text":
774
- default:
775
- bRegex = (aoColumn.bRegex == null ? false : aoColumn.bRegex);
776
- bSmart = (aoColumn.bSmart == null ? false : aoColumn.bSmart);
777
- fnCreateInput(oTable, bRegex, bSmart, false, aoColumn.iFilterLength, aoColumn.iMaxLenght);
778
- break;
779
-
780
- }
781
- }
782
- });
783
-
784
- for (j = 0; j < aiCustomSearch_Indexes.length; j++) {
785
- //var index = aiCustomSearch_Indexes[j];
786
- var fnSearch_ = function () {
787
- var id = oTable.attr("id");
788
- return $("#" + id + "_range_from_" + aiCustomSearch_Indexes[j]).val() + properties.sRangeSeparator + $("#" + id + "_range_to_" + aiCustomSearch_Indexes[j]).val()
789
- }
790
- afnSearch_.push(fnSearch_);
791
- }
792
-
793
- if (oTable.fnSettings().oFeatures.bServerSide) {
794
-
795
- var fnServerDataOriginal = oTable.fnSettings().fnServerData;
796
-
797
- oTable.fnSettings().fnServerData = function (sSource, aoData, fnCallback) {
798
-
799
- for (j = 0; j < aiCustomSearch_Indexes.length; j++) {
800
- var index = aiCustomSearch_Indexes[j];
801
-
802
- for (k = 0; k < aoData.length; k++) {
803
- if (aoData[k].name == "sSearch_" + index)
804
- aoData[k].value = afnSearch_[j]();
805
- }
806
- }
807
- aoData.push({ "name": "sRangeSeparator", "value": properties.sRangeSeparator });
808
-
809
- if (fnServerDataOriginal != null) {
810
- try {
811
- fnServerDataOriginal(sSource, aoData, fnCallback, oTable.fnSettings()); //TODO: See Issue 18
812
- } catch (ex) {
813
- fnServerDataOriginal(sSource, aoData, fnCallback);
814
- }
815
- }
816
- else {
817
- $.getJSON(sSource, aoData, function (json) {
818
- fnCallback(json)
819
- });
820
- }
821
- };
822
-
823
- }
824
-
825
- });
826
-
827
- };
828
-
829
-
830
-
831
-
832
- })(jQuery);