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