jquery-datatables 1.10.12 → 1.10.13
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/.gitignore +1 -0
- data/app/assets/javascripts/datatables/dataTables.bootstrap.js +2 -2
- data/app/assets/javascripts/datatables/dataTables.bootstrap4.js +5 -5
- data/app/assets/javascripts/datatables/dataTables.foundation.js +1 -1
- data/app/assets/javascripts/datatables/dataTables.material.js +1 -1
- data/app/assets/javascripts/datatables/dataTables.semanticui.js +1 -1
- data/app/assets/javascripts/datatables/extensions/AutoFill/dataTables.autoFill.js +63 -31
- data/app/assets/javascripts/datatables/extensions/Buttons/buttons.colVis.js +2 -3
- data/app/assets/javascripts/datatables/extensions/Buttons/buttons.flash.js +145 -55
- data/app/assets/javascripts/datatables/extensions/Buttons/buttons.html5.js +224 -206
- data/app/assets/javascripts/datatables/extensions/Buttons/buttons.print.js +14 -8
- data/app/assets/javascripts/datatables/extensions/Buttons/dataTables.buttons.js +54 -24
- data/app/assets/javascripts/datatables/extensions/KeyTable/dataTables.keyTable.js +137 -68
- data/app/assets/javascripts/datatables/extensions/Responsive/dataTables.responsive.js +30 -7
- data/app/assets/javascripts/datatables/extensions/Responsive/responsive.bootstrap.js +6 -2
- data/app/assets/javascripts/datatables/extensions/Responsive/responsive.bootstrap4.js +6 -2
- data/app/assets/javascripts/datatables/extensions/RowReorder/dataTables.rowReorder.js +64 -6
- data/app/assets/javascripts/datatables/extensions/Select/dataTables.select.js +40 -15
- data/app/assets/javascripts/datatables/jquery.dataTables.js +246 -217
- data/app/assets/javascripts/datatables/plugins/api/average.js +32 -0
- data/app/assets/javascripts/datatables/plugins/api/sum.js +51 -0
- data/app/assets/javascripts/datatables/plugins/pagination/input.js +224 -0
- data/app/assets/javascripts/datatables/plugins/search/alphabetSearch.js +368 -0
- data/app/assets/javascripts/datatables/plugins/sorting/file-size.js +43 -0
- data/app/assets/javascripts/datatables/plugins/sorting/ip-address.js +103 -0
- data/app/assets/stylesheets/datatables/dataTables.bootstrap.css +0 -1
- data/app/assets/stylesheets/datatables/dataTables.semanticui.css +0 -1
- data/app/assets/stylesheets/datatables/extensions/Responsive/responsive.bootstrap.css +4 -4
- data/app/assets/stylesheets/datatables/extensions/Responsive/responsive.bootstrap4.css +4 -4
- data/app/assets/stylesheets/datatables/extensions/Responsive/responsive.dataTables.css +4 -4
- data/app/assets/stylesheets/datatables/extensions/Responsive/responsive.foundation.css +4 -4
- data/app/assets/stylesheets/datatables/extensions/Responsive/responsive.jqueryui.css +4 -4
- data/app/assets/stylesheets/datatables/extensions/Responsive/responsive.semanticui.css +4 -4
- data/app/assets/stylesheets/datatables/extensions/Select/select.bootstrap.css +9 -4
- data/app/assets/stylesheets/datatables/extensions/Select/select.bootstrap4.css +9 -4
- data/app/assets/stylesheets/datatables/extensions/Select/select.dataTables.css +9 -4
- data/app/assets/stylesheets/datatables/extensions/Select/select.foundation.css +9 -4
- data/app/assets/stylesheets/datatables/extensions/Select/select.jqueryui.css +9 -4
- data/app/assets/stylesheets/datatables/extensions/Select/select.semanticui.css +9 -4
- data/app/assets/stylesheets/datatables/plugins/search/alphabetSearch.css +43 -0
- data/lib/jquery-datatables/version.rb +1 -1
- metadata +10 -3
@@ -0,0 +1,32 @@
|
|
1
|
+
/**
|
2
|
+
* It can sometimes be useful to get the average of data in an API result set,
|
3
|
+
* be it from a column, or a collection of cells. This method provides exactly
|
4
|
+
* that ability.
|
5
|
+
*
|
6
|
+
* @name average()
|
7
|
+
* @summary Average the values in a data set.
|
8
|
+
* @author [Allan Jardine](http://sprymedia.co.uk)
|
9
|
+
* @requires DataTables 1.10+
|
10
|
+
*
|
11
|
+
* @returns {Number} Calculated average
|
12
|
+
*
|
13
|
+
* @example
|
14
|
+
* // Average a column
|
15
|
+
* var table = $('#example').DataTable();
|
16
|
+
* table.column( 3 ).data().average();
|
17
|
+
*
|
18
|
+
* @example
|
19
|
+
* // Average two cells
|
20
|
+
* var table = $('#example').DataTable();
|
21
|
+
* table.cells( 0, [3,4] ).data().average();
|
22
|
+
*/
|
23
|
+
|
24
|
+
jQuery.fn.dataTable.Api.register( 'average()', function () {
|
25
|
+
var data = this.flatten();
|
26
|
+
var sum = data.reduce( function ( a, b ) {
|
27
|
+
return (a*1) + (b*1); // cast values in-case they are strings
|
28
|
+
}, 0 );
|
29
|
+
|
30
|
+
return sum / data.length;
|
31
|
+
} );
|
32
|
+
|
@@ -0,0 +1,51 @@
|
|
1
|
+
/**
|
2
|
+
* Fairly simply, this plug-in will take the data from an API result set
|
3
|
+
* and sum it, returning the summed value. The data can come from any data
|
4
|
+
* source, including column data, cells or rows.
|
5
|
+
*
|
6
|
+
* Note that it will attempt to 'deformat' any string based data that is passed
|
7
|
+
* into it - i.e. it will strip any non-numeric characters in order to make a
|
8
|
+
* best effort attempt to sum all data types. This can be useful when working
|
9
|
+
* with formatting numbers such as currency. However the trade-off is that no
|
10
|
+
* error is thrown if non-numeric data is passed in. You should be aware of this
|
11
|
+
* in case unexpected values are returned - likely the input data is not what is
|
12
|
+
* expected.
|
13
|
+
*
|
14
|
+
* @name sum()
|
15
|
+
* @summary Sum the values in a data set.
|
16
|
+
* @author [Allan Jardine](http://sprymedia.co.uk)
|
17
|
+
* @requires DataTables 1.10+
|
18
|
+
*
|
19
|
+
* @returns {Number} Summed value
|
20
|
+
*
|
21
|
+
* @example
|
22
|
+
* // Simply get the sum of a column
|
23
|
+
* var table = $('#example').DataTable();
|
24
|
+
* table.column( 3 ).data().sum();
|
25
|
+
*
|
26
|
+
* @example
|
27
|
+
* // Insert the sum of a column into the columns footer, for the visible
|
28
|
+
* // data on each draw
|
29
|
+
* $('#example').DataTable( {
|
30
|
+
* drawCallback: function () {
|
31
|
+
* var api = this.api();
|
32
|
+
* $( api.table().footer() ).html(
|
33
|
+
* api.column( 4, {page:'current'} ).data().sum()
|
34
|
+
* );
|
35
|
+
* }
|
36
|
+
* } );
|
37
|
+
*/
|
38
|
+
|
39
|
+
jQuery.fn.dataTable.Api.register( 'sum()', function ( ) {
|
40
|
+
return this.flatten().reduce( function ( a, b ) {
|
41
|
+
if ( typeof a === 'string' ) {
|
42
|
+
a = a.replace(/[^\d.-]/g, '') * 1;
|
43
|
+
}
|
44
|
+
if ( typeof b === 'string' ) {
|
45
|
+
b = b.replace(/[^\d.-]/g, '') * 1;
|
46
|
+
}
|
47
|
+
|
48
|
+
return a + b;
|
49
|
+
}, 0 );
|
50
|
+
} );
|
51
|
+
|
@@ -0,0 +1,224 @@
|
|
1
|
+
/**
|
2
|
+
* Sometimes for quick navigation, it can be useful to allow an end user to
|
3
|
+
* enter which page they wish to jump to manually. This paging control uses a
|
4
|
+
* text input box to accept new paging numbers (arrow keys are also allowed
|
5
|
+
* for), and four standard navigation buttons are also presented to the end
|
6
|
+
* user.
|
7
|
+
*
|
8
|
+
* @name Navigation with text input
|
9
|
+
* @summary Shows an input element into which the user can type a page number
|
10
|
+
* @author [Allan Jardine](http://sprymedia.co.uk)
|
11
|
+
* @author [Gordey Doronin](http://github.com/GDoronin)
|
12
|
+
*
|
13
|
+
* @example
|
14
|
+
* $(document).ready(function() {
|
15
|
+
* $('#example').dataTable( {
|
16
|
+
* "pagingType": "input"
|
17
|
+
* } );
|
18
|
+
* } );
|
19
|
+
*/
|
20
|
+
|
21
|
+
(function ($) {
|
22
|
+
function calcDisableClasses(oSettings) {
|
23
|
+
var start = oSettings._iDisplayStart;
|
24
|
+
var length = oSettings._iDisplayLength;
|
25
|
+
var visibleRecords = oSettings.fnRecordsDisplay();
|
26
|
+
var all = length === -1;
|
27
|
+
|
28
|
+
// Gordey Doronin: Re-used this code from main jQuery.dataTables source code. To be consistent.
|
29
|
+
var page = all ? 0 : Math.ceil(start / length);
|
30
|
+
var pages = all ? 1 : Math.ceil(visibleRecords / length);
|
31
|
+
|
32
|
+
var disableFirstPrevClass = (page > 0 ? '' : oSettings.oClasses.sPageButtonDisabled);
|
33
|
+
var disableNextLastClass = (page < pages - 1 ? '' : oSettings.oClasses.sPageButtonDisabled);
|
34
|
+
|
35
|
+
return {
|
36
|
+
'first': disableFirstPrevClass,
|
37
|
+
'previous': disableFirstPrevClass,
|
38
|
+
'next': disableNextLastClass,
|
39
|
+
'last': disableNextLastClass
|
40
|
+
};
|
41
|
+
}
|
42
|
+
|
43
|
+
function calcCurrentPage(oSettings) {
|
44
|
+
return Math.ceil(oSettings._iDisplayStart / oSettings._iDisplayLength) + 1;
|
45
|
+
}
|
46
|
+
|
47
|
+
function calcPages(oSettings) {
|
48
|
+
return Math.ceil(oSettings.fnRecordsDisplay() / oSettings._iDisplayLength);
|
49
|
+
}
|
50
|
+
|
51
|
+
var firstClassName = 'first';
|
52
|
+
var previousClassName = 'previous';
|
53
|
+
var nextClassName = 'next';
|
54
|
+
var lastClassName = 'last';
|
55
|
+
|
56
|
+
var paginateClassName = 'paginate';
|
57
|
+
var paginateOfClassName = 'paginate_of';
|
58
|
+
var paginatePageClassName = 'paginate_page';
|
59
|
+
var paginateInputClassName = 'paginate_input';
|
60
|
+
|
61
|
+
$.fn.dataTableExt.oPagination.input = {
|
62
|
+
'fnInit': function (oSettings, nPaging, fnCallbackDraw) {
|
63
|
+
var nFirst = document.createElement('span');
|
64
|
+
var nPrevious = document.createElement('span');
|
65
|
+
var nNext = document.createElement('span');
|
66
|
+
var nLast = document.createElement('span');
|
67
|
+
var nInput = document.createElement('input');
|
68
|
+
var nPage = document.createElement('span');
|
69
|
+
var nOf = document.createElement('span');
|
70
|
+
|
71
|
+
var language = oSettings.oLanguage.oPaginate;
|
72
|
+
var classes = oSettings.oClasses;
|
73
|
+
|
74
|
+
nFirst.innerHTML = language.sFirst;
|
75
|
+
nPrevious.innerHTML = language.sPrevious;
|
76
|
+
nNext.innerHTML = language.sNext;
|
77
|
+
nLast.innerHTML = language.sLast;
|
78
|
+
|
79
|
+
nFirst.className = firstClassName + ' ' + classes.sPageButton;
|
80
|
+
nPrevious.className = previousClassName + ' ' + classes.sPageButton;
|
81
|
+
nNext.className = nextClassName + ' ' + classes.sPageButton;
|
82
|
+
nLast.className = lastClassName + ' ' + classes.sPageButton;
|
83
|
+
|
84
|
+
nOf.className = paginateOfClassName;
|
85
|
+
nPage.className = paginatePageClassName;
|
86
|
+
nInput.className = paginateInputClassName;
|
87
|
+
|
88
|
+
if (oSettings.sTableId !== '') {
|
89
|
+
nPaging.setAttribute('id', oSettings.sTableId + '_' + paginateClassName);
|
90
|
+
nFirst.setAttribute('id', oSettings.sTableId + '_' + firstClassName);
|
91
|
+
nPrevious.setAttribute('id', oSettings.sTableId + '_' + previousClassName);
|
92
|
+
nNext.setAttribute('id', oSettings.sTableId + '_' + nextClassName);
|
93
|
+
nLast.setAttribute('id', oSettings.sTableId + '_' + lastClassName);
|
94
|
+
}
|
95
|
+
|
96
|
+
nInput.type = 'text';
|
97
|
+
nPage.innerHTML = 'Page ';
|
98
|
+
|
99
|
+
nPaging.appendChild(nFirst);
|
100
|
+
nPaging.appendChild(nPrevious);
|
101
|
+
nPaging.appendChild(nPage);
|
102
|
+
nPaging.appendChild(nInput);
|
103
|
+
nPaging.appendChild(nOf);
|
104
|
+
nPaging.appendChild(nNext);
|
105
|
+
nPaging.appendChild(nLast);
|
106
|
+
|
107
|
+
$(nFirst).click(function() {
|
108
|
+
var iCurrentPage = calcCurrentPage(oSettings);
|
109
|
+
if (iCurrentPage !== 1) {
|
110
|
+
oSettings.oApi._fnPageChange(oSettings, 'first');
|
111
|
+
fnCallbackDraw(oSettings);
|
112
|
+
}
|
113
|
+
});
|
114
|
+
|
115
|
+
$(nPrevious).click(function() {
|
116
|
+
var iCurrentPage = calcCurrentPage(oSettings);
|
117
|
+
if (iCurrentPage !== 1) {
|
118
|
+
oSettings.oApi._fnPageChange(oSettings, 'previous');
|
119
|
+
fnCallbackDraw(oSettings);
|
120
|
+
}
|
121
|
+
});
|
122
|
+
|
123
|
+
$(nNext).click(function() {
|
124
|
+
var iCurrentPage = calcCurrentPage(oSettings);
|
125
|
+
if (iCurrentPage !== calcPages(oSettings)) {
|
126
|
+
oSettings.oApi._fnPageChange(oSettings, 'next');
|
127
|
+
fnCallbackDraw(oSettings);
|
128
|
+
}
|
129
|
+
});
|
130
|
+
|
131
|
+
$(nLast).click(function() {
|
132
|
+
var iCurrentPage = calcCurrentPage(oSettings);
|
133
|
+
if (iCurrentPage !== calcPages(oSettings)) {
|
134
|
+
oSettings.oApi._fnPageChange(oSettings, 'last');
|
135
|
+
fnCallbackDraw(oSettings);
|
136
|
+
}
|
137
|
+
});
|
138
|
+
|
139
|
+
$(nInput).keyup(function (e) {
|
140
|
+
// 38 = up arrow, 39 = right arrow
|
141
|
+
if (e.which === 38 || e.which === 39) {
|
142
|
+
this.value++;
|
143
|
+
}
|
144
|
+
// 37 = left arrow, 40 = down arrow
|
145
|
+
else if ((e.which === 37 || e.which === 40) && this.value > 1) {
|
146
|
+
this.value--;
|
147
|
+
}
|
148
|
+
|
149
|
+
if (this.value === '' || this.value.match(/[^0-9]/)) {
|
150
|
+
/* Nothing entered or non-numeric character */
|
151
|
+
this.value = this.value.replace(/[^\d]/g, ''); // don't even allow anything but digits
|
152
|
+
return;
|
153
|
+
}
|
154
|
+
|
155
|
+
var iNewStart = oSettings._iDisplayLength * (this.value - 1);
|
156
|
+
if (iNewStart < 0) {
|
157
|
+
iNewStart = 0;
|
158
|
+
}
|
159
|
+
if (iNewStart >= oSettings.fnRecordsDisplay()) {
|
160
|
+
iNewStart = (Math.ceil((oSettings.fnRecordsDisplay()) / oSettings._iDisplayLength) - 1) * oSettings._iDisplayLength;
|
161
|
+
}
|
162
|
+
|
163
|
+
oSettings._iDisplayStart = iNewStart;
|
164
|
+
fnCallbackDraw(oSettings);
|
165
|
+
});
|
166
|
+
|
167
|
+
// Take the brutal approach to cancelling text selection.
|
168
|
+
$('span', nPaging).bind('mousedown', function () { return false; });
|
169
|
+
$('span', nPaging).bind('selectstart', function() { return false; });
|
170
|
+
|
171
|
+
// If we can't page anyway, might as well not show it.
|
172
|
+
var iPages = calcPages(oSettings);
|
173
|
+
if (iPages <= 1) {
|
174
|
+
$(nPaging).hide();
|
175
|
+
}
|
176
|
+
},
|
177
|
+
|
178
|
+
'fnUpdate': function (oSettings) {
|
179
|
+
if (!oSettings.aanFeatures.p) {
|
180
|
+
return;
|
181
|
+
}
|
182
|
+
|
183
|
+
var iPages = calcPages(oSettings);
|
184
|
+
var iCurrentPage = calcCurrentPage(oSettings);
|
185
|
+
|
186
|
+
var an = oSettings.aanFeatures.p;
|
187
|
+
if (iPages <= 1) // hide paging when we can't page
|
188
|
+
{
|
189
|
+
$(an).hide();
|
190
|
+
return;
|
191
|
+
}
|
192
|
+
|
193
|
+
var disableClasses = calcDisableClasses(oSettings);
|
194
|
+
|
195
|
+
$(an).show();
|
196
|
+
|
197
|
+
// Enable/Disable `first` button.
|
198
|
+
$(an).children('.' + firstClassName)
|
199
|
+
.removeClass(oSettings.oClasses.sPageButtonDisabled)
|
200
|
+
.addClass(disableClasses[firstClassName]);
|
201
|
+
|
202
|
+
// Enable/Disable `prev` button.
|
203
|
+
$(an).children('.' + previousClassName)
|
204
|
+
.removeClass(oSettings.oClasses.sPageButtonDisabled)
|
205
|
+
.addClass(disableClasses[previousClassName]);
|
206
|
+
|
207
|
+
// Enable/Disable `next` button.
|
208
|
+
$(an).children('.' + nextClassName)
|
209
|
+
.removeClass(oSettings.oClasses.sPageButtonDisabled)
|
210
|
+
.addClass(disableClasses[nextClassName]);
|
211
|
+
|
212
|
+
// Enable/Disable `last` button.
|
213
|
+
$(an).children('.' + lastClassName)
|
214
|
+
.removeClass(oSettings.oClasses.sPageButtonDisabled)
|
215
|
+
.addClass(disableClasses[lastClassName]);
|
216
|
+
|
217
|
+
// Paginate of N pages text
|
218
|
+
$(an).children('.' + paginateOfClassName).html(' of ' + iPages);
|
219
|
+
|
220
|
+
// Current page numer input value
|
221
|
+
$(an).children('.' + paginateInputClassName).val(iCurrentPage);
|
222
|
+
}
|
223
|
+
};
|
224
|
+
})(jQuery);
|
@@ -0,0 +1,368 @@
|
|
1
|
+
/*! AlphabetSearch for DataTables v1.1.2
|
2
|
+
* 2014 SpryMedia Ltd - datatables.net/license
|
3
|
+
* Gyrocode - MIT License
|
4
|
+
*/
|
5
|
+
|
6
|
+
/**
|
7
|
+
* @summary AlphabetSearch
|
8
|
+
* @description Show an set of alphabet buttons alongside a table providing
|
9
|
+
* search input options
|
10
|
+
* @version 1.1.1
|
11
|
+
* @file dataTables.alphabetSearch.js
|
12
|
+
* @author SpryMedia Ltd (www.sprymedia.co.uk)
|
13
|
+
* @contact www.sprymedia.co.uk/contact
|
14
|
+
* @copyright Copyright 2014 SpryMedia Ltd.
|
15
|
+
* @author Gyrocode (www.gyrocode.com)
|
16
|
+
* @contact www.gyrocode.com/contacts
|
17
|
+
* @copyright Copyright (c) Gyrocode
|
18
|
+
*
|
19
|
+
* License MIT - http://datatables.net/license/mit
|
20
|
+
*
|
21
|
+
* For more detailed information please see:
|
22
|
+
* http://www.gyrocode.com/articles/jquery-datatables-alphabetical-search
|
23
|
+
*/
|
24
|
+
(function(){
|
25
|
+
|
26
|
+
|
27
|
+
// Search function
|
28
|
+
$.fn.dataTable.Api.register( 'alphabetSearch()', function ( searchTerm ) {
|
29
|
+
this.iterator( 'table', function ( context ) {
|
30
|
+
context.alphabetSearch.letter = searchTerm;
|
31
|
+
} );
|
32
|
+
|
33
|
+
return this;
|
34
|
+
} );
|
35
|
+
|
36
|
+
// Recalculate the alphabet display for updated data
|
37
|
+
$.fn.dataTable.Api.register( 'alphabetSearch.recalc()', function ( searchTerm ) {
|
38
|
+
this.iterator( 'table', function ( context ) {
|
39
|
+
draw(
|
40
|
+
new $.fn.dataTable.Api( context ),
|
41
|
+
$('div.alphabet', this.table().container()),
|
42
|
+
context
|
43
|
+
);
|
44
|
+
} );
|
45
|
+
|
46
|
+
return this;
|
47
|
+
} );
|
48
|
+
|
49
|
+
|
50
|
+
// Search plug-in
|
51
|
+
$.fn.dataTable.ext.search.push( function ( context, searchData ) {
|
52
|
+
// Ensure that there is a search applied to this table before running it
|
53
|
+
if ( ! context.alphabetSearch.letterSearch ) {
|
54
|
+
return true;
|
55
|
+
}
|
56
|
+
|
57
|
+
var letter = searchData[context.alphabetSearch.column]
|
58
|
+
.toString()
|
59
|
+
.replace(/<.*?>/g, '')
|
60
|
+
.charAt(0).toUpperCase();
|
61
|
+
|
62
|
+
|
63
|
+
if(context.alphabetSearch.letterSearch !== '#'){
|
64
|
+
if ( letter === context.alphabetSearch.letterSearch ) {
|
65
|
+
return true;
|
66
|
+
}
|
67
|
+
} else {
|
68
|
+
if(/\d/.test(letter)){
|
69
|
+
return true;
|
70
|
+
}
|
71
|
+
}
|
72
|
+
|
73
|
+
return false;
|
74
|
+
} );
|
75
|
+
|
76
|
+
|
77
|
+
// Order plug-in
|
78
|
+
//
|
79
|
+
// NOTES: If sorting by alphabetized column
|
80
|
+
// there would be two calls to this method
|
81
|
+
$.fn.dataTable.ext.order['alphabetSearch'] = function ( context, col )
|
82
|
+
{
|
83
|
+
var order_col = this.api().order()[0][0];
|
84
|
+
var order_method = this.api().order()[0][1];
|
85
|
+
|
86
|
+
// If sorting by column other than the one being alphabetized
|
87
|
+
if(order_col !== context.alphabetSearch.column){
|
88
|
+
context.alphabetSearch.pass = 0;
|
89
|
+
}
|
90
|
+
|
91
|
+
var data = this.api().column( col, { order: 'index' } ).data().map( function (value, index) {
|
92
|
+
// If sorting by alphabetized column
|
93
|
+
return (order_col === context.alphabetSearch.column)
|
94
|
+
? (
|
95
|
+
// If first pass
|
96
|
+
( !context.alphabetSearch.pass )
|
97
|
+
// Ignore
|
98
|
+
?
|
99
|
+
''
|
100
|
+
// Otherwise, if it's a second pass
|
101
|
+
:
|
102
|
+
(
|
103
|
+
// If method is ascending sort
|
104
|
+
( order_method === 'asc' )
|
105
|
+
// Return first letter
|
106
|
+
? value.charAt(0)
|
107
|
+
: String.fromCharCode(65535 - value.charCodeAt(0))
|
108
|
+
)
|
109
|
+
)
|
110
|
+
// Otherwise, if sorting by column other than the one being alphabetized,
|
111
|
+
// return first letter
|
112
|
+
: value.charAt(0);
|
113
|
+
|
114
|
+
} );
|
115
|
+
|
116
|
+
// If sorting by alphabetized column
|
117
|
+
if(order_col === context.alphabetSearch.column){
|
118
|
+
// If pass is not defined, set it to 0
|
119
|
+
if(!context.alphabetSearchPass){ context.alphabetSearch.pass = 0; }
|
120
|
+
// Increment pass counter and reset it to 0 if it's a second pass
|
121
|
+
context.alphabetSearch.pass = (context.alphabetSearch.pass + 1) % 2;
|
122
|
+
}
|
123
|
+
|
124
|
+
return data;
|
125
|
+
};
|
126
|
+
|
127
|
+
|
128
|
+
// Private support methods
|
129
|
+
function bin ( data ) {
|
130
|
+
var letter, bins = {};
|
131
|
+
|
132
|
+
for ( var i=0, ien=data.length ; i<ien ; i++ ) {
|
133
|
+
letter = data[i]
|
134
|
+
.toString()
|
135
|
+
.replace(/<.*?>/g, '')
|
136
|
+
.charAt(0).toUpperCase();
|
137
|
+
|
138
|
+
if(/\d/.test(letter)){ letter = '#'; }
|
139
|
+
|
140
|
+
if ( bins[letter] ) {
|
141
|
+
bins[letter]++;
|
142
|
+
}
|
143
|
+
else {
|
144
|
+
bins[letter] = 1;
|
145
|
+
}
|
146
|
+
}
|
147
|
+
|
148
|
+
return bins;
|
149
|
+
}
|
150
|
+
|
151
|
+
function draw ( table, alphabet, context )
|
152
|
+
{
|
153
|
+
alphabet.empty();
|
154
|
+
alphabet.append( context.oLanguage.alphabetSearch.infoDisplay + ': ' );
|
155
|
+
|
156
|
+
var columnData = table.column(context.alphabetSearch.column, { search: 'applied' } ).data();
|
157
|
+
var bins = bin( columnData );
|
158
|
+
|
159
|
+
$('<span class="alphabet-clear' + ((!context.alphabetSearch.letter) ? ' active' : '') + '"/>')
|
160
|
+
.data( 'letter', '' )
|
161
|
+
.data( 'match-count', columnData.length )
|
162
|
+
.html( context.oLanguage.alphabetSearch.infoAll )
|
163
|
+
.appendTo( alphabet );
|
164
|
+
|
165
|
+
for ( var i=0 ; i<context.oLanguage.alphabetSearch.alphabet.length ; i++ ) {
|
166
|
+
var letter = context.oLanguage.alphabetSearch.alphabet[i];
|
167
|
+
|
168
|
+
$('<span/>')
|
169
|
+
.data( 'letter', letter )
|
170
|
+
.data( 'match-count', bins[letter] || 0 )
|
171
|
+
.addClass(
|
172
|
+
(! bins[letter] ? 'empty' : '')
|
173
|
+
+ ((context.alphabetSearch.letter === letter) ? ' active' : '')
|
174
|
+
)
|
175
|
+
.html(
|
176
|
+
(letter === '#') ? '0-9' : letter
|
177
|
+
)
|
178
|
+
.appendTo( alphabet );
|
179
|
+
}
|
180
|
+
|
181
|
+
$('<div class="alphabet_info"></div>')
|
182
|
+
.appendTo( alphabet );
|
183
|
+
|
184
|
+
|
185
|
+
// Perform second rendering
|
186
|
+
// needed to filter search results by letter
|
187
|
+
// NOTE: Future optimization is needed to avoid rendering twice
|
188
|
+
// when no search is performed
|
189
|
+
|
190
|
+
// If letter is selected
|
191
|
+
if(context.alphabetSearch.letter){
|
192
|
+
// Apply filtering by letter
|
193
|
+
context.alphabetSearch.letterSearch = context.alphabetSearch.letter;
|
194
|
+
|
195
|
+
// Redraw table
|
196
|
+
table.draw();
|
197
|
+
|
198
|
+
// Remove filtering by letter
|
199
|
+
context.alphabetSearch.letterSearch = '';
|
200
|
+
}
|
201
|
+
|
202
|
+
// Handle search event here only once
|
203
|
+
// when alphabet panel has been drawn
|
204
|
+
// because we are performing two-step rendering
|
205
|
+
// that could trigger search hanlder when not needed
|
206
|
+
table.one('search', function (e, context) {
|
207
|
+
var api = new $.fn.dataTable.Api( context );
|
208
|
+
|
209
|
+
// Redraw alphabet panel
|
210
|
+
api.alphabetSearch.recalc();
|
211
|
+
});
|
212
|
+
}
|
213
|
+
|
214
|
+
|
215
|
+
$.fn.dataTable.AlphabetSearch = function ( context ) {
|
216
|
+
var table = new $.fn.dataTable.Api( context );
|
217
|
+
var alphabet = $('<div class="alphabet"/>');
|
218
|
+
|
219
|
+
// Language
|
220
|
+
context.oLanguage.alphabetSearch =
|
221
|
+
$.extend(
|
222
|
+
{
|
223
|
+
'alphabet': '#ABCDEFGHIJKLMNOPQRSTUVWXYZ',
|
224
|
+
'infoDisplay': 'Display',
|
225
|
+
'infoAll': 'All'
|
226
|
+
},
|
227
|
+
((context.oLanguage.alphabetSearch)
|
228
|
+
? context.oLanguage.alphabetSearch
|
229
|
+
: {}
|
230
|
+
)
|
231
|
+
);
|
232
|
+
// Convert alphabet to uppercase
|
233
|
+
context.oLanguage.alphabetSearch.alphabet.toUpperCase();
|
234
|
+
|
235
|
+
context.alphabetSearch =
|
236
|
+
$.extend(
|
237
|
+
{
|
238
|
+
column: 0
|
239
|
+
},
|
240
|
+
$.isPlainObject(context.oInit.alphabetSearch) ? context.oInit.alphabetSearch : {},
|
241
|
+
{
|
242
|
+
letter: '',
|
243
|
+
letterSearch: '',
|
244
|
+
pass: 0
|
245
|
+
}
|
246
|
+
);
|
247
|
+
|
248
|
+
// Set required "orderDataType" ("sSortDataType") for a column
|
249
|
+
if(context.alphabetSearch.column >= 0 && context.alphabetSearch.column < context.aoColumns.length){
|
250
|
+
context.aoColumns[context.alphabetSearch.column].sSortDataType = 'alphabetSearch';
|
251
|
+
}
|
252
|
+
|
253
|
+
// Add column containing names to a list of columns
|
254
|
+
// where ordering will be always applied to the table
|
255
|
+
if( context.hasOwnProperty('aaSortingFixed')
|
256
|
+
&& typeof context.aaSortingFixed === 'object' )
|
257
|
+
{
|
258
|
+
if( $.isArray(context.aaSortingFixed) ){
|
259
|
+
if( context.aaSortingFixed.length && !$.isArray( context.aaSortingFixed[0] ) ) {
|
260
|
+
// 1D array
|
261
|
+
context.aaSortingFixed = [[context.alphabetSearch.column, 'asc'], context.aaSortingFixed];
|
262
|
+
|
263
|
+
} else {
|
264
|
+
// 2D array
|
265
|
+
context.aaSortingFixed.unshift([context.alphabetSearch.column, 'asc']);
|
266
|
+
}
|
267
|
+
} else {
|
268
|
+
if( !context.aaSortingFixed.hasOwnProperty('pre') ){
|
269
|
+
context.aaSortingFixed.pre = [];
|
270
|
+
}
|
271
|
+
|
272
|
+
if( context.aaSortingFixed.pre.length && !$.isArray( context.aaSortingFixed.pre[0] ) ) {
|
273
|
+
// 1D array
|
274
|
+
context.aaSortingFixed.pre = [[context.alphabetSearch.column, 'asc'], context.aaSortingFixed.pre];
|
275
|
+
|
276
|
+
} else {
|
277
|
+
// 2D array
|
278
|
+
context.aaSortingFixed.pre.unshift([context.alphabetSearch.column, 'asc']);
|
279
|
+
}
|
280
|
+
}
|
281
|
+
|
282
|
+
} else {
|
283
|
+
context.aaSortingFixed = [context.alphabetSearch.column, 'asc'];
|
284
|
+
}
|
285
|
+
|
286
|
+
|
287
|
+
draw( table, alphabet, context );
|
288
|
+
|
289
|
+
|
290
|
+
// Trigger a search
|
291
|
+
alphabet.on( 'click', 'span', function () {
|
292
|
+
alphabet.find( '.active' ).removeClass( 'active' );
|
293
|
+
$(this).addClass( 'active' );
|
294
|
+
|
295
|
+
table
|
296
|
+
.alphabetSearch( $(this).data('letter') )
|
297
|
+
.draw();
|
298
|
+
} );
|
299
|
+
|
300
|
+
// Mouse events to show helper information
|
301
|
+
alphabet
|
302
|
+
.on( 'mouseenter', 'span', function () {
|
303
|
+
alphabet
|
304
|
+
.find('div.alphabet_info')
|
305
|
+
.css( {
|
306
|
+
opacity: 1,
|
307
|
+
left: $(this).position().left,
|
308
|
+
width: $(this).width()
|
309
|
+
} )
|
310
|
+
.html( $(this).data('match-count') );
|
311
|
+
} )
|
312
|
+
.on( 'mouseleave', 'span', function () {
|
313
|
+
alphabet
|
314
|
+
.find('div.alphabet_info')
|
315
|
+
.css('opacity', 0);
|
316
|
+
} );
|
317
|
+
|
318
|
+
table.on('draw', function (e, context) {
|
319
|
+
var api = new $.fn.dataTable.Api( context );
|
320
|
+
|
321
|
+
// Total number of column nodes
|
322
|
+
var col_total = api.columns().nodes().length;
|
323
|
+
|
324
|
+
var rows = api.rows({ page: 'current' }).nodes();
|
325
|
+
var group_last = null;
|
326
|
+
|
327
|
+
api.column(context.alphabetSearch.column, { page: 'current' }).data().each(function (name, index){
|
328
|
+
var group = name.charAt(0).toUpperCase();
|
329
|
+
|
330
|
+
if (group_last !== group) {
|
331
|
+
$(rows).eq(index).before(
|
332
|
+
'<tr class="alphabet_group"><td colspan="' + col_total + '">' + group + '</td></tr>'
|
333
|
+
);
|
334
|
+
|
335
|
+
group_last = group;
|
336
|
+
}
|
337
|
+
});
|
338
|
+
|
339
|
+
// If there are no rows found and letter is selected
|
340
|
+
if(!rows.length && context.alphabetSearch){
|
341
|
+
var letter = (context.alphabetSearch.letter === '#') ? '0-9' : context.alphabetSearch.letter;
|
342
|
+
|
343
|
+
$(api.table().body()).prepend(
|
344
|
+
'<tr class="alphabet_group"><td colspan="' + col_total + '">' + letter + '</td></tr>'
|
345
|
+
);
|
346
|
+
}
|
347
|
+
});
|
348
|
+
|
349
|
+
// API method to get the alphabet container node
|
350
|
+
this.node = function () {
|
351
|
+
return alphabet;
|
352
|
+
};
|
353
|
+
};
|
354
|
+
|
355
|
+
$.fn.DataTable.AlphabetSearch = $.fn.dataTable.AlphabetSearch;
|
356
|
+
|
357
|
+
|
358
|
+
// Register a search plug-in
|
359
|
+
$.fn.dataTable.ext.feature.push( {
|
360
|
+
fnInit: function ( settings ) {
|
361
|
+
var search = new $.fn.dataTable.AlphabetSearch( settings );
|
362
|
+
return search.node();
|
363
|
+
},
|
364
|
+
cFeature: 'A'
|
365
|
+
} );
|
366
|
+
|
367
|
+
|
368
|
+
}());
|