jquery-datatables 1.10.12 → 1.10.13

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/app/assets/javascripts/datatables/dataTables.bootstrap.js +2 -2
  4. data/app/assets/javascripts/datatables/dataTables.bootstrap4.js +5 -5
  5. data/app/assets/javascripts/datatables/dataTables.foundation.js +1 -1
  6. data/app/assets/javascripts/datatables/dataTables.material.js +1 -1
  7. data/app/assets/javascripts/datatables/dataTables.semanticui.js +1 -1
  8. data/app/assets/javascripts/datatables/extensions/AutoFill/dataTables.autoFill.js +63 -31
  9. data/app/assets/javascripts/datatables/extensions/Buttons/buttons.colVis.js +2 -3
  10. data/app/assets/javascripts/datatables/extensions/Buttons/buttons.flash.js +145 -55
  11. data/app/assets/javascripts/datatables/extensions/Buttons/buttons.html5.js +224 -206
  12. data/app/assets/javascripts/datatables/extensions/Buttons/buttons.print.js +14 -8
  13. data/app/assets/javascripts/datatables/extensions/Buttons/dataTables.buttons.js +54 -24
  14. data/app/assets/javascripts/datatables/extensions/KeyTable/dataTables.keyTable.js +137 -68
  15. data/app/assets/javascripts/datatables/extensions/Responsive/dataTables.responsive.js +30 -7
  16. data/app/assets/javascripts/datatables/extensions/Responsive/responsive.bootstrap.js +6 -2
  17. data/app/assets/javascripts/datatables/extensions/Responsive/responsive.bootstrap4.js +6 -2
  18. data/app/assets/javascripts/datatables/extensions/RowReorder/dataTables.rowReorder.js +64 -6
  19. data/app/assets/javascripts/datatables/extensions/Select/dataTables.select.js +40 -15
  20. data/app/assets/javascripts/datatables/jquery.dataTables.js +246 -217
  21. data/app/assets/javascripts/datatables/plugins/api/average.js +32 -0
  22. data/app/assets/javascripts/datatables/plugins/api/sum.js +51 -0
  23. data/app/assets/javascripts/datatables/plugins/pagination/input.js +224 -0
  24. data/app/assets/javascripts/datatables/plugins/search/alphabetSearch.js +368 -0
  25. data/app/assets/javascripts/datatables/plugins/sorting/file-size.js +43 -0
  26. data/app/assets/javascripts/datatables/plugins/sorting/ip-address.js +103 -0
  27. data/app/assets/stylesheets/datatables/dataTables.bootstrap.css +0 -1
  28. data/app/assets/stylesheets/datatables/dataTables.semanticui.css +0 -1
  29. data/app/assets/stylesheets/datatables/extensions/Responsive/responsive.bootstrap.css +4 -4
  30. data/app/assets/stylesheets/datatables/extensions/Responsive/responsive.bootstrap4.css +4 -4
  31. data/app/assets/stylesheets/datatables/extensions/Responsive/responsive.dataTables.css +4 -4
  32. data/app/assets/stylesheets/datatables/extensions/Responsive/responsive.foundation.css +4 -4
  33. data/app/assets/stylesheets/datatables/extensions/Responsive/responsive.jqueryui.css +4 -4
  34. data/app/assets/stylesheets/datatables/extensions/Responsive/responsive.semanticui.css +4 -4
  35. data/app/assets/stylesheets/datatables/extensions/Select/select.bootstrap.css +9 -4
  36. data/app/assets/stylesheets/datatables/extensions/Select/select.bootstrap4.css +9 -4
  37. data/app/assets/stylesheets/datatables/extensions/Select/select.dataTables.css +9 -4
  38. data/app/assets/stylesheets/datatables/extensions/Select/select.foundation.css +9 -4
  39. data/app/assets/stylesheets/datatables/extensions/Select/select.jqueryui.css +9 -4
  40. data/app/assets/stylesheets/datatables/extensions/Select/select.semanticui.css +9 -4
  41. data/app/assets/stylesheets/datatables/plugins/search/alphabetSearch.css +43 -0
  42. data/lib/jquery-datatables/version.rb +1 -1
  43. 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
+ }());