|
1 /* |
|
2 * MyAMS extensions to jquery-dataTables plug-in |
|
3 * Version 0.1.0 |
|
4 * ©2014 Thierry Florac <tflorac@ulthar.net> |
|
5 */ |
|
6 |
|
7 |
|
8 (function($) { |
|
9 |
|
10 /** |
|
11 * Update default values for DataTables initialization |
|
12 */ |
|
13 $.extend(true, $.fn.dataTable.defaults, { |
|
14 "sDom": "R<'dt-top-row'CLF>r<'dt-wrapper't><'dt-row dt-bottom-row'<'row'<'col-sm-6'i><'col-sm-6 text-right'p>>", |
|
15 "sPaginationType": "bootstrap", |
|
16 "oLanguage": { |
|
17 "sLengthMenu": "_MENU_", |
|
18 "sSearch": "_INPUT_" |
|
19 } |
|
20 }); |
|
21 |
|
22 |
|
23 /** |
|
24 * Default class modification |
|
25 */ |
|
26 $.extend($.fn.dataTableExt.oStdClasses, { |
|
27 "sWrapper": "dataTables_wrapper form-inline" |
|
28 }); |
|
29 |
|
30 |
|
31 /** |
|
32 * API method to get paging information |
|
33 */ |
|
34 $.fn.dataTableExt.oApi.fnPagingInfo = function (oSettings) { |
|
35 return { |
|
36 "iStart": oSettings._iDisplayStart, |
|
37 "iEnd": oSettings.fnDisplayEnd(), |
|
38 "iLength": oSettings._iDisplayLength, |
|
39 "iTotal": oSettings.fnRecordsTotal(), |
|
40 "iFilteredTotal": oSettings.fnRecordsDisplay(), |
|
41 "iPage": oSettings._iDisplayLength === -1 ? 0 : Math.ceil( oSettings._iDisplayStart / oSettings._iDisplayLength ), |
|
42 "iTotalPages": oSettings._iDisplayLength === -1 ? 0 : Math.ceil( oSettings.fnRecordsDisplay() / oSettings._iDisplayLength ) |
|
43 }; |
|
44 }; |
|
45 |
|
46 |
|
47 /** |
|
48 * Bootstrap style pagination control |
|
49 */ |
|
50 $.extend($.fn.dataTableExt.oPagination, { |
|
51 "bootstrap": { |
|
52 "fnInit": function(oSettings, nPaging, fnDraw) { |
|
53 var oLang = oSettings.oLanguage.oPaginate; |
|
54 var fnClickHandler = function (e) { |
|
55 e.preventDefault(); |
|
56 if (oSettings.oApi._fnPageChange(oSettings, e.data.action)) |
|
57 fnDraw(oSettings); |
|
58 }; |
|
59 |
|
60 $(nPaging).append( |
|
61 '<ul class="pagination">' + |
|
62 '<li class="prev disabled"><a href="#">' + oLang.sPrevious + '</a></li>' + |
|
63 '<li class="next disabled"><a href="#">' + oLang.sNext + '</a></li>' + |
|
64 '</ul>' |
|
65 ); |
|
66 var els = $('a', nPaging); |
|
67 $(els[0]).on('click.DT', { action: "previous" }, fnClickHandler); |
|
68 $(els[1]).on('click.DT', { action: "next" }, fnClickHandler); |
|
69 }, |
|
70 |
|
71 "fnUpdate": function (oSettings, fnDraw) { |
|
72 var iListLength = 5; |
|
73 var oPaging = oSettings.oInstance.fnPagingInfo(); |
|
74 var an = oSettings.aanFeatures.p; |
|
75 var i, |
|
76 j, |
|
77 sClass, |
|
78 iStart, |
|
79 iEnd, |
|
80 iLen, |
|
81 iHalf=Math.floor(iListLength/2); |
|
82 |
|
83 if (oPaging.iTotalPages < iListLength) { |
|
84 iStart = 1; |
|
85 iEnd = oPaging.iTotalPages; |
|
86 } else if (oPaging.iPage <= iHalf) { |
|
87 iStart = 1; |
|
88 iEnd = iListLength; |
|
89 } else if (oPaging.iPage >= (oPaging.iTotalPages-iHalf)) { |
|
90 iStart = oPaging.iTotalPages - iListLength + 1; |
|
91 iEnd = oPaging.iTotalPages; |
|
92 } else { |
|
93 iStart = oPaging.iPage - iHalf + 1; |
|
94 iEnd = iStart + iListLength - 1; |
|
95 } |
|
96 |
|
97 for (i=0, iLen=an.length ; i<iLen ; i++) { |
|
98 // Remove the middle elements |
|
99 $('li:gt(0)', an[i]).filter(':not(:last)').remove(); |
|
100 |
|
101 // Add the new list items and their event handlers |
|
102 for (j=iStart ; j<=iEnd ; j++) { |
|
103 sClass = (j==oPaging.iPage+1) ? 'class="active"' : ''; |
|
104 $('<li '+sClass+'><a href="#">'+j+'</a></li>') |
|
105 .insertBefore( $('li:last', an[i])[0] ) |
|
106 .on('click', function (e) { |
|
107 e.preventDefault(); |
|
108 oSettings._iDisplayStart = (parseInt($('a', this).text(),10)-1) * oPaging.iLength; |
|
109 fnDraw( oSettings ); |
|
110 }); |
|
111 } |
|
112 |
|
113 // Add / remove disabled classes from the static elements |
|
114 if (oPaging.iPage === 0) |
|
115 $('li:first', an[i]).addClass('disabled'); |
|
116 else |
|
117 $('li:first', an[i]).removeClass('disabled'); |
|
118 |
|
119 if (oPaging.iPage === oPaging.iTotalPages-1 || oPaging.iTotalPages === 0) |
|
120 $('li:last', an[i]).addClass('disabled'); |
|
121 else |
|
122 $('li:last', an[i]).removeClass('disabled'); |
|
123 } |
|
124 } |
|
125 } |
|
126 }); |
|
127 |
|
128 |
|
129 /** |
|
130 * Bootstrap style full pagination control |
|
131 */ |
|
132 $.extend( $.fn.dataTableExt.oPagination, { |
|
133 "bootstrap_full": { |
|
134 "fnInit": function(oSettings, nPaging, fnDraw) { |
|
135 var oLang = oSettings.oLanguage.oPaginate; |
|
136 var fnClickHandler = function (e) { |
|
137 e.preventDefault(); |
|
138 if (oSettings.oApi._fnPageChange(oSettings, e.data.action)) |
|
139 fnDraw(oSettings); |
|
140 }; |
|
141 |
|
142 $(nPaging).append( |
|
143 '<ul class="pagination">' + |
|
144 '<li class="first disabled"><a href="#">' + oLang.sFirst + '</a></li>' + |
|
145 '<li class="prev disabled"><a href="#">' + oLang.sPrevious + '</a></li>' + |
|
146 '<li class="next disabled"><a href="#">' + oLang.sNext + '</a></li>' + |
|
147 '<li class="last disabled"><a href="#">' + oLang.sLast + '</a></li>' + |
|
148 '</ul>' |
|
149 ); |
|
150 var els = $('a', nPaging); |
|
151 $(els[0]).on('click.DT', { action: "first" }, fnClickHandler); |
|
152 $(els[1]).on('click.DT', { action: "previous" }, fnClickHandler); |
|
153 $(els[2]).on('click.DT', { action: "next" }, fnClickHandler); |
|
154 $(els[3]).on('click.DT', { action: "last" }, fnClickHandler); |
|
155 }, |
|
156 |
|
157 "fnUpdate": function (oSettings, fnDraw) { |
|
158 var iListLength = 5; |
|
159 var oPaging = oSettings.oInstance.fnPagingInfo(); |
|
160 var an = oSettings.aanFeatures.p; |
|
161 var i, |
|
162 j, |
|
163 sClass, |
|
164 iStart, |
|
165 iLen, |
|
166 iEnd, |
|
167 iHalf=Math.floor(iListLength/2); |
|
168 |
|
169 if (oPaging.iTotalPages < iListLength) { |
|
170 iStart = 1; |
|
171 iEnd = oPaging.iTotalPages; |
|
172 } else if (oPaging.iPage <= iHalf) { |
|
173 iStart = 1; |
|
174 iEnd = iListLength; |
|
175 } else if (oPaging.iPage >= (oPaging.iTotalPages-iHalf)) { |
|
176 iStart = oPaging.iTotalPages - iListLength + 1; |
|
177 iEnd = oPaging.iTotalPages; |
|
178 } else { |
|
179 iStart = oPaging.iPage - iHalf + 1; |
|
180 iEnd = iStart + iListLength - 1; |
|
181 } |
|
182 |
|
183 for (i=0, iLen=an.length ; i<iLen ; i++) { |
|
184 // Remove the middle elements |
|
185 $('li', an[i]).filter(":not(.first)").filter(":not(.last)").filter(":not(.prev)").filter(":not(.next)").remove(); |
|
186 |
|
187 // Add the new list items and their event handlers |
|
188 for (j=iStart ; j<=iEnd ; j++) { |
|
189 sClass = (j==oPaging.iPage+1) ? 'class="active"' : ''; |
|
190 $('<li '+sClass+'><a href="#">'+j+'</a></li>') |
|
191 .insertBefore( $('li.next', an[i])[0] ) |
|
192 .on('click', function (e) { |
|
193 e.preventDefault(); |
|
194 oSettings._iDisplayStart = (parseInt($('a', this).text(),10)-1) * oPaging.iLength; |
|
195 fnDraw( oSettings ); |
|
196 } ); |
|
197 } |
|
198 |
|
199 // Add / remove disabled classes from the static elements |
|
200 if (oPaging.iPage === 0) { |
|
201 $('li.first', an[i]).addClass('disabled'); |
|
202 $('li.prev', an[i]).addClass('disabled'); |
|
203 } else { |
|
204 $('li.prev', an[i]).removeClass('disabled'); |
|
205 $('li.first', an[i]).removeClass('disabled'); |
|
206 } |
|
207 |
|
208 if (oPaging.iPage === oPaging.iTotalPages-1 || oPaging.iTotalPages === 0) { |
|
209 $('li.last', an[i]).addClass('disabled'); |
|
210 $('li.next', an[i]).addClass('disabled'); |
|
211 } else { |
|
212 $('li.next', an[i]).removeClass('disabled'); |
|
213 $('li.last', an[i]).removeClass('disabled'); |
|
214 } |
|
215 } |
|
216 } |
|
217 } |
|
218 } ); |
|
219 |
|
220 |
|
221 /* |
|
222 * TableTools Bootstrap compatibility |
|
223 * Required TableTools 2.1+ |
|
224 */ |
|
225 if ($.fn.DataTable.TableTools) { |
|
226 // Set the classes that TableTools uses to something suitable for Bootstrap |
|
227 $.extend( true, $.fn.DataTable.TableTools.classes, { |
|
228 "container": "DTTT btn-group", |
|
229 "buttons": { |
|
230 "normal": "btn btn-default btn-sm", |
|
231 "disabled": "disabled" |
|
232 }, |
|
233 "collection": { |
|
234 "container": "DTTT_dropdown dropdown-menu", |
|
235 "buttons": { |
|
236 "normal": "", |
|
237 "disabled": "disabled" |
|
238 } |
|
239 }, |
|
240 "print": { |
|
241 "info": "DTTT_print_info modal" |
|
242 }, |
|
243 "select": { |
|
244 "row": "active" |
|
245 } |
|
246 } ); |
|
247 |
|
248 // Have the collection use a bootstrap compatible dropdown |
|
249 $.extend(true, $.fn.DataTable.TableTools.DEFAULTS.oTags, { |
|
250 "collection": { |
|
251 "container": "ul", |
|
252 "button": "li", |
|
253 "liner": "a" |
|
254 } |
|
255 }); |
|
256 } |
|
257 |
|
258 |
|
259 /** |
|
260 * Length and filter extensions |
|
261 * Just replace 'l' and 'f' in sDom property by 'L' and 'F' to use them |
|
262 */ |
|
263 |
|
264 /** |
|
265 * Bootstrap length factory |
|
266 */ |
|
267 var bl_factory = function($, DataTable) { |
|
268 |
|
269 var BootstrapLength = function(oSettings, oInit) { |
|
270 |
|
271 if (!this.CLASS || this.CLASS != 'BootstrapLength') |
|
272 alert("Warning: BootstrapLength must be initialized with the 'new' keyword"); |
|
273 if (typeof(oInit) == 'undefined') |
|
274 oInit = {}; |
|
275 if ($.fn.dataTable.camelToHungarian) |
|
276 $.fn.dataTable.camelToHungarian(BootstrapLength.defaults, oInit); |
|
277 |
|
278 this.s = { |
|
279 dt: null, |
|
280 oInit: oInit, |
|
281 hidden: true, |
|
282 abOriginal: [] |
|
283 }; |
|
284 this.dom = { |
|
285 wrapper: null, |
|
286 input: null |
|
287 }; |
|
288 BootstrapLength.aInstances.push(this); |
|
289 |
|
290 this.s.dt = $.fn.dataTable.Api |
|
291 ? new $.fn.dataTable.Api(oSettings).settings()[0] |
|
292 : oSettings; |
|
293 |
|
294 this._fnConstruct(oInit); |
|
295 return this; |
|
296 }; |
|
297 |
|
298 BootstrapLength.prototype = { |
|
299 |
|
300 input: function() { |
|
301 return this.dom.wrapper; |
|
302 }, |
|
303 |
|
304 fnRebuild: function() { |
|
305 return this.rebuild(); |
|
306 }, |
|
307 |
|
308 rebuild: function() { |
|
309 }, |
|
310 |
|
311 _fnConstruct: function(init) { |
|
312 var self = this; |
|
313 var dt = self.s.dt; |
|
314 if (dt.oScroll.bInfinite) |
|
315 return; |
|
316 var sName = dt.sTableId + '_length'; |
|
317 var sMenu = $('<select size="1"></select>').attr('name', sName); |
|
318 var i, iLen; |
|
319 var aLengthMenu = dt.aLengthMenu; |
|
320 if (aLengthMenu.length == 2 && typeof(aLengthMenu[0]) == 'object' && typeof(aLengthMenu[1]) == 'object') { |
|
321 for (i=0, iLen=aLengthMenu[0].length; i < iLen; i++) |
|
322 $('<option />').attr('value', aLengthMenu[0][i]) |
|
323 .text(aLengthMenu[1][i]) |
|
324 .appendTo(sMenu); |
|
325 } else { |
|
326 for (i=0, iLen=aLengthMenu.length; i < iLen; i++) |
|
327 $('<option />').attr('value', aLengthMenu[i]) |
|
328 .text(aLengthMenu[i]) |
|
329 .appendTo(sMenu); |
|
330 } |
|
331 var nLength = $('<div>').addClass(dt.oClasses.sLength) |
|
332 .append($('<span></span>').addClass('ams-form') |
|
333 .append($('<label></label>').addClass('select') |
|
334 .css('width', 60) |
|
335 .append(sMenu) |
|
336 .append($('<i></i>')))); |
|
337 if (!dt.aanFeatures.L) |
|
338 nLength.attr('id', dt.sTableId + '_length'); |
|
339 this.dom.wrapper = nLength.get(0); |
|
340 |
|
341 $('select option[value="' + dt._iDisplayLength + '"]', nLength).attr("selected", true); |
|
342 $("select", nLength).on('change.DT', function(e) { |
|
343 var iVal = $(this).val(); |
|
344 var n = dt.aanFeatures.L; |
|
345 for (i = 0, iLen = n.length; i < iLen; i++) { |
|
346 if (n[i] != this.parentNode) |
|
347 $("select", n[i]).val(iVal); |
|
348 } |
|
349 dt._iDisplayLength = parseInt(iVal, 10); |
|
350 dt.oInstance._fnCalculateEnd(dt); |
|
351 if (dt.fnDisplayEnd() == dt.fnRecordsDisplay()) { |
|
352 dt._iDisplayStart = dt.fnDisplayEnd() - dt._iDisplayLength; |
|
353 if (dt._iDisplayStart < 0) |
|
354 dt._iDisplayStart = 0; |
|
355 } |
|
356 if (dt._iDisplayLength == -1) |
|
357 dt._iDisplayStart = 0; |
|
358 dt.oInstance._fnDraw(); |
|
359 }); |
|
360 $("select", nLength).attr("aria-controls", dt.sTableId); |
|
361 } |
|
362 }; |
|
363 |
|
364 BootstrapLength.fnRebuild = function(oTable) {}; |
|
365 |
|
366 BootstrapLength.defaults = {}; |
|
367 BootstrapLength.aInstances = []; |
|
368 BootstrapLength.prototype.CLASS = 'BootstrapLength'; |
|
369 |
|
370 BootstrapLength.VERSION = '1.0.0'; |
|
371 BootstrapLength.prototype.VERSION = BootstrapLength.VERSION; |
|
372 |
|
373 if ((typeof($.fn.dataTable) == 'function') && |
|
374 (typeof($.fn.dataTableExt.fnVersionCheck) == 'function') && |
|
375 $.fn.dataTableExt.fnVersionCheck('1.7.0')) { |
|
376 $.fn.dataTableExt.aoFeatures.push({ |
|
377 fnInit: function(oSettings) { |
|
378 var init = oSettings.oInit; |
|
379 var Length = new BootstrapLength(oSettings, init.bootstrapLength || init.oBootstrapLength || {}); |
|
380 return Length.input(); |
|
381 }, |
|
382 cFeature: 'L', |
|
383 sFeature: "BootstrapLength" |
|
384 }); |
|
385 } else { |
|
386 alert("Warning: BootstrapLength required DataTables 1.7 or greater..."); |
|
387 } |
|
388 |
|
389 $.fn.dataTable.BootstrapLength = BootstrapLength; |
|
390 return BootstrapLength; |
|
391 |
|
392 }; |
|
393 |
|
394 if (!jQuery.fn.dataTable.BootstrapLength) { |
|
395 bl_factory($, $.fn.dataTable); |
|
396 } |
|
397 |
|
398 |
|
399 /** |
|
400 * Bootstrap filter factory |
|
401 */ |
|
402 var bf_factory = function($, DataTable) { |
|
403 |
|
404 var BootstrapFilter = function(oSettings, oInit) { |
|
405 |
|
406 if (!this.CLASS || this.CLASS != 'BootstrapFilter') |
|
407 alert("Warning: BootstrapFilter must be initialized with the 'new' keyword"); |
|
408 if (typeof(oInit) == 'undefined') |
|
409 oInit = {}; |
|
410 if ($.fn.dataTable.camelToHungarian) |
|
411 $.fn.dataTable.camelToHungarian(BootstrapFilter.defaults, oInit); |
|
412 |
|
413 this.s = { |
|
414 dt: null, |
|
415 oInit: oInit, |
|
416 hidden: true, |
|
417 abOriginal: [] |
|
418 }; |
|
419 this.dom = { |
|
420 wrapper: null, |
|
421 input: null |
|
422 }; |
|
423 BootstrapFilter.aInstances.push(this); |
|
424 |
|
425 this.s.dt = $.fn.dataTable.Api |
|
426 ? new $.fn.dataTable.Api(oSettings).settings()[0] |
|
427 : oSettings; |
|
428 |
|
429 this._fnConstruct(oInit); |
|
430 return this; |
|
431 }; |
|
432 |
|
433 BootstrapFilter.prototype = { |
|
434 |
|
435 input: function() { |
|
436 return this.dom.wrapper; |
|
437 }, |
|
438 |
|
439 fnRebuild: function() { |
|
440 return this.rebuild(); |
|
441 }, |
|
442 |
|
443 rebuild: function() { |
|
444 }, |
|
445 |
|
446 _fnConstruct: function(init) { |
|
447 var self = this; |
|
448 var dt = self.s.dt; |
|
449 var oPreviousSearch = dt.oPreviousSearch; |
|
450 var sSearchStr = '<input type="text">'; |
|
451 var nFilter = $('<div>').addClass(dt.oClasses.sFilter) |
|
452 .html('<div class="input-group">' + |
|
453 '<span class="input-group-addon"><i class="fa fa-search"></i></span>' + |
|
454 sSearchStr + |
|
455 '</div>'); |
|
456 if (!dt.aanFeatures.F) |
|
457 nFilter.attr('id', dt.sTableId + '_filter'); |
|
458 this.dom.wrapper = nFilter.get(0); |
|
459 |
|
460 var jqFilter = $('input[type="text"]', nFilter); |
|
461 nFilter.data('DT_Input', jqFilter[0]); |
|
462 jqFilter.val(oPreviousSearch.sSearch.replace('"', """)) |
|
463 .addClass('form-control') |
|
464 .attr('placeholder', dt.oLanguage.sSearch) |
|
465 .attr('aria-control', dt.sTableId) |
|
466 .on('keyup.DT', function(e) { |
|
467 var n = dt.aanFeatures.F; |
|
468 var val = $(this).val(); |
|
469 for (var i = 0, iLen = n.length; i < iLen; i++) { |
|
470 if (n[i] != $(this).parents("div.dataTables_filter")[0]) |
|
471 $(n[i]).data('DT_Input').val(val); |
|
472 } |
|
473 if (val != oPreviousSearch.sSearch) { |
|
474 dt.oInstance._fnFilterComplete({ |
|
475 sSearch: val, |
|
476 bRegex: oPreviousSearch.bRegex, |
|
477 bSmart: oPreviousSearch.bSmart, |
|
478 bCaseInsensitive: oPreviousSearch.bCaseInsensitive |
|
479 }); |
|
480 } |
|
481 }) |
|
482 .on('keypress.DT', function(e) { |
|
483 if (e.keyCode == 13) { |
|
484 return false; |
|
485 } |
|
486 }); |
|
487 } |
|
488 }; |
|
489 |
|
490 BootstrapFilter.fnRebuild = function(oTable) {}; |
|
491 |
|
492 BootstrapFilter.defaults = {}; |
|
493 BootstrapFilter.aInstances = []; |
|
494 BootstrapFilter.prototype.CLASS = 'BootstrapFilter'; |
|
495 |
|
496 BootstrapFilter.VERSION = '1.0.0'; |
|
497 BootstrapFilter.prototype.VERSION = BootstrapFilter.VERSION; |
|
498 |
|
499 if ((typeof($.fn.dataTable) == 'function') && |
|
500 (typeof($.fn.dataTableExt.fnVersionCheck) == 'function') && |
|
501 $.fn.dataTableExt.fnVersionCheck('1.7.0')) { |
|
502 $.fn.dataTableExt.aoFeatures.push({ |
|
503 fnInit: function(oSettings) { |
|
504 var init = oSettings.oInit; |
|
505 var filter = new BootstrapFilter(oSettings, init.bootstrapFilter || init.oBootstrapFilter || {}); |
|
506 return filter.input(); |
|
507 }, |
|
508 cFeature: 'F', |
|
509 sFeature: "BootstrapFilter" |
|
510 }); |
|
511 } else { |
|
512 alert("Warning: BootstrapFilter required DataTables 1.7 or greater..."); |
|
513 } |
|
514 |
|
515 $.fn.dataTable.BootstrapFilter = BootstrapFilter; |
|
516 return BootstrapFilter; |
|
517 |
|
518 }; |
|
519 |
|
520 if (!jQuery.fn.dataTable.BootstrapFilter) { |
|
521 bf_factory($, $.fn.dataTable); |
|
522 } |
|
523 |
|
524 })(jQuery); |