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