effective_datatables 1.4.3 → 1.5.0

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