diff --git a/airtime_mvc/application/controllers/ApiController.php b/airtime_mvc/application/controllers/ApiController.php
index 20fdbf9b6..95ca8a4e8 100644
--- a/airtime_mvc/application/controllers/ApiController.php
+++ b/airtime_mvc/application/controllers/ApiController.php
@@ -337,6 +337,7 @@ class ApiController extends Zend_Controller_Action
$this->_helper->viewRenderer->setNoRender(true);
$data = Application_Model_Schedule::getSchedule();
+ header("Content-Type: application/json");
echo json_encode($data, JSON_FORCE_OBJECT);
}
diff --git a/airtime_mvc/application/models/Preference.php b/airtime_mvc/application/models/Preference.php
index a2f563b11..d157bc9bf 100644
--- a/airtime_mvc/application/models/Preference.php
+++ b/airtime_mvc/application/models/Preference.php
@@ -31,12 +31,6 @@ class Application_Model_Preference
$result = Application_Common_Database::prepareAndExecute($sql, $paramMap, 'column');
- if ($value == "") {
- $value = "NULL";
- } else {
- $value = "$value";
- }
-
$paramMap = array();
if ($result == 1) {
// result found
diff --git a/airtime_mvc/application/models/Webstream.php b/airtime_mvc/application/models/Webstream.php
index b1d4b2b77..4f721c567 100644
--- a/airtime_mvc/application/models/Webstream.php
+++ b/airtime_mvc/application/models/Webstream.php
@@ -262,7 +262,6 @@ class Application_Model_Webstream implements Application_Model_LibraryEditable
private static function getPlsUrl($url)
{
$content = self::getUrlData($url);
-
$ini = parse_ini_string($content, true);
if ($ini !== false && isset($ini["playlist"]) && isset($ini["playlist"]["File1"])) {
diff --git a/airtime_mvc/public/js/airtime/library/library.js b/airtime_mvc/public/js/airtime/library/library.js
index 276551d6a..8024b827c 100644
--- a/airtime_mvc/public/js/airtime/library/library.js
+++ b/airtime_mvc/public/js/airtime/library/library.js
@@ -479,14 +479,13 @@ var AIRTIME = (function(AIRTIME) {
"fnServerData": function ( sSource, aoData, fnCallback ) {
var type;
-
aoData.push( { name: "format", value: "json"} );
//push whether to search files/playlists or all.
type = $("#library_display_type").find("select").val();
type = (type === undefined) ? 0 : type;
aoData.push( { name: "type", value: type} );
-
+
$.ajax( {
"dataType": 'json',
"type": "POST",
@@ -970,3 +969,145 @@ function addQtipToSCIcons(){
}
});
}
+
+/*
+ * This function is called from dataTables.columnFilter.js
+ */
+function validateAdvancedSearch(divs) {
+ var valid = true,
+ fieldName,
+ fields,
+ searchTerm = Array(),
+ searchTermType,
+ regExpr,
+ timeRegEx = "\\d{2}[:]([0-5]){1}([0-9]){1}[:]([0-5]){1}([0-9]){1}([.]\\d{1,6})?",
+ dateRegEx = "\\d{4}[-]\\d{2}[-]\\d{2}?",
+ integerRegEx = "^\\d+$",
+ numericRegEx = "^\\d+[.]?\\d*$";
+
+ searchTerm[0] = "";
+ searchTerm[1] = "";
+
+ $.each(divs, function(i, div){
+ fieldName = $(div).children(':nth-child(2)').attr('id');
+ fields = $(div).children().find('input');
+ searchTermType = validationTypes[fieldName];
+
+ $.each(fields, function(i, field){
+ searchTerm[i] = $(field).val();
+
+ if (searchTerm[i] !== "") {
+
+ if (searchTermType === "l") {
+ regExpr = new RegExp("^" +timeRegEx+ "$");
+ } else if (searchTermType === "t") {
+ var pieces = searchTerm[i].split(" ");
+ if (pieces.length === 2) {
+ regExpr = new RegExp("^" +dateRegEx+ " " +timeRegEx+ "$");
+ } else if (pieces.length === 1) {
+ regExpr = new RegExp("^" +dateRegEx+ "$");
+ }
+ } else if (searchTermType === "i") {
+ regExpr = new RegExp(integerRegEx);
+ } else if (searchTermType === "n") {
+ regExpr = new RegExp(numericRegEx);
+ if (searchTerm[i].charAt(0) === "-") {
+ searchTerm[i] = searchTerm[i].substr(1);
+ }
+ }
+
+ //string fields do not need validation
+ if (searchTermType !== "s") {
+ valid = regExpr.test(searchTerm[i]);
+ }
+
+ addRemoveValidationIcons(valid, $(field));
+
+ /* Empty fields should not have valid/invalid indicator
+ * Range values are considered valid even if only the
+ * 'From' value is provided. Therefore, if the 'To' value
+ * is empty but the 'From' value is not empty we need to
+ * keep the validation icon on screen.
+ */
+ } else if (searchTerm[0] === "" && searchTerm[1] !== "" ||
+ searchTerm[0] === "" && searchTerm[1] === ""){
+ if ($(field).closest('div').children(':last-child').hasClass('checked-icon') ||
+ $(field).closest('div').children(':last-child').hasClass('not-available-icon')) {
+ $(field).closest('div').children(':last-child').remove();
+ }
+ }
+
+ if (!valid) {
+ return false;
+ }
+ });
+
+ if (!valid) {
+ return false;
+ }
+ });
+
+ return valid;
+}
+
+function addRemoveValidationIcons(valid, field) {
+ var validIndicator = "",
+ invalidIndicator = "";
+
+ if (valid) {
+ if (!field.closest('div').children(':last-child').hasClass('checked-icon')) {
+ //remove invalid icon before adding valid icon
+ if (field.closest('div').children(':last-child').hasClass('not-available-icon')) {
+ field.closest('div').children(':last-child').remove();
+ }
+ field.closest('div').append(validIndicator);
+ }
+ } else {
+ if (!field.closest('div').children(':last-child').hasClass('not-available-icon')) {
+ //remove valid icon before adding invalid icon
+ if (field.closest('div').children(':last-child').hasClass('checked-icon')) {
+ field.closest('div').children(':last-child').remove();
+ }
+ field.closest('div').append(invalidIndicator);
+ }
+ }
+}
+
+/* Validation types:
+ * s => string
+ * i => integer
+ * n => numeric (positive/negative, whole/decimals)
+ * t => timestamp
+ * l => length
+ */
+var validationTypes = {
+ "album_title" : "s",
+ "artist_name" : "s",
+ "bit_rate" : "i",
+ "bpm" : "i",
+ "comments" : "s",
+ "composer" : "s",
+ "conductor" : "s",
+ "copyright" : "s",
+ "utime" : "t",
+ "mtime" : "t",
+ "lptime" : "t",
+ "disc_number" : "i",
+ "genre" : "s",
+ "isrc_number" : "s",
+ "label" : "s",
+ "language" : "s",
+ "length" : "l",
+ "lyricist" : "s",
+ "mood" : "s",
+ "name" : "s",
+ "orchestra" : "s",
+ "owner_id" : "i",
+ "rating" : "i",
+ "replay_gain" : "n",
+ "sample_rate" : "i",
+ "track_title" : "s",
+ "track_number" : "i",
+ "info_url" : "s",
+ "year" : "i"
+};
diff --git a/airtime_mvc/public/js/datatables/plugin/AIRTIME_DEV_README b/airtime_mvc/public/js/datatables/plugin/AIRTIME_DEV_README
new file mode 100644
index 000000000..a86836562
--- /dev/null
+++ b/airtime_mvc/public/js/datatables/plugin/AIRTIME_DEV_README
@@ -0,0 +1,108 @@
+Before you overwrite dataTables.columnFilter.js, note that we have changed a few lines
+in this file.
+
+Running a diff between the original column filter plugin (dataTables.columnFilter_orig.js) and
+our modified one (dataTables.columnFilter.js):
+
+denise@denise-DX4860:~/airtime/airtime_mvc/public/js/datatables/plugin$ diff -u dataTables.columnFilter_orig.js dataTables.columnFilter.js
+--- dataTables.columnFilter_orig.js 2012-09-10 14:26:30.041095663 -0400
++++ dataTables.columnFilter.js 2012-09-10 17:04:21.017464447 -0400
+@@ -103,7 +103,8 @@
+ label = label.replace(/(^\s*)|(\s*$)/g, "");
+ var currentFilter = oTable.fnSettings().aoPreSearchCols[i].sSearch;
+ var search_init = 'search_init ';
+- var inputvalue = label;
++ //var inputvalue = label;
++ var inputvalue = '';
+ if (currentFilter != '' && currentFilter != '^') {
+ if (bIsNumber && currentFilter.charAt(0) == '^')
+ inputvalue = currentFilter.substr(1); //ignore trailing ^
+@@ -133,29 +134,32 @@
+ });
+ } 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);
++ var advSearchFields = $("div#advanced_search").children(':visible');
++ if(validateAdvancedSearch(advSearchFields)){
++ 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();
+ }
+- /* Filter on the column (the index) of this element */
+- oTable.fnFilter(this.value, _fnColumnIndex(index), regex, smart); //Issue 37
+- fnOnFiltered();
+ });
+ }
+
+@@ -168,7 +172,8 @@
+ input.blur(function () {
+ if (this.value == "") {
+ $(this).addClass("search_init");
+- this.value = asInitVals[index];
++ //this.value = asInitVals[index];
++ this.value = "";
+ }
+ });
+ }
+@@ -228,14 +233,16 @@
+
+
+ $('#' + 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();
++ var advSearchFields = $("div#advanced_search").children(':visible');
++ if(validateAdvancedSearch(advSearchFields)){
++ 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();
++ }
+ });
+
+
diff --git a/airtime_mvc/public/js/datatables/plugin/dataTables.columnFilter.js b/airtime_mvc/public/js/datatables/plugin/dataTables.columnFilter.js
index 4f36c9a71..1bab38a3c 100644
--- a/airtime_mvc/public/js/datatables/plugin/dataTables.columnFilter.js
+++ b/airtime_mvc/public/js/datatables/plugin/dataTables.columnFilter.js
@@ -1,733 +1,740 @@
-/*
-* File: jquery.dataTables.columnFilter.js
-* Version: 1.4.8.
-* 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) {
- ///
- ///Return values in the column
- ///
- ///DataTables settings
- ///Id of the column
- ///Return only distinct values
- ///Return values only from the filtered rows
- ///Ignore empty cells
-
- // 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++) {
- 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 = $('');
- if (iMaxLenght != undefined && iMaxLenght != -1) {
- input.attr('maxlength', iMaxLenght);
- }
- th.html(input);
- if (bIsNumber)
- th.wrapInner('');
- else
- th.wrapInner('');
-
- 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 = $('');
- th.append(from);
- th.append(_fnRangeLabelPart(1));
- var sToId = oTable.attr("id") + '_range_to_' + i;
- var to = $('');
- th.append(to);
- th.append(_fnRangeLabelPart(2));
- th.wrapInner('');
- 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) {
- th.html(_fnRangeLabelPart(0));
- var sFromId = oTable.attr("id") + '_range_from_' + i;
- var from = $('');
- from.datepicker();
- th.append(from);
- th.append(_fnRangeLabelPart(1));
- var sToId = oTable.attr("id") + '_range_to_' + i;
- var to = $('');
- th.append(to);
- th.append(_fnRangeLabelPart(2));
- th.wrapInner('');
- 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) {
- if (aData == null)
- aData = _fnGetColumnValues(oTable.fnSettings(), iColumn, true, false, true);
- var index = iColumn;
- var currentFilter = oTable.fnSettings().aoPreSearchCols[i].sSearch;
-
- var r = '');
- nTh.html(select);
- nTh.wrapInner('');
- 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();
- });
- }
-
- function fnCreateSelect(oTable, aData, bRegex) {
- 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); //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); //Issue 37
-
- }
-
- 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
- if (properties.sFilterButtonText != null || properties.sFilterButtonText != undefined) {
- labelBtn = properties.sFilterButtonText;
- } else {
- labelBtn = label;
- }
-
- 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 = '
';
- var divClose = '
';
-
- var uniqueId = oTable.attr("id") + localLabel;
- var buttonId = "chkBtnOpen" + uniqueId;
- var checkToggleDiv = uniqueId + "-flt-toggle";
- r += ''; //filter button witch open dialog
- r += ''; //dialog div
- //r+= '
'; //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 += '
' + aData[j] + '
';
-
- var checkbox = $(r);
- th.html(checkbox);
- th.wrapInner('
');
- //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);
- }
- }
-
-
-
-
- oTable = this;
-
- var defaults = {
- sPlaceHolder: "foot",
- sRangeSeparator: "~",
- iFilteringDelay: 500,
- aoColumns: null,
- sRangeFormat: "From {from} to {to}"
- };
-
- properties = $.extend(defaults, options);
-
- return this.each(function () {
-
- if (!oTable.fnSettings().oFeatures.bFilter)
- return;
- asInitVals = new Array();
-
- 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);
- break;
- case "number-range":
- fnCreateRangeInput(oTable);
- break;
- case "date-range":
- fnCreateDateRangeInput(oTable);
- break;
- case "checkbox":
- fnCreateCheckbox(oTable, 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)
- });
- }
- };
-
- }
-
- });
-
- };
-
-
-
-
+/*
+* File: jquery.dataTables.columnFilter.js
+* Version: 1.4.8.
+* 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) {
+ ///
+ ///Return values in the column
+ ///
+ ///
DataTables settings
+ ///
Id of the column
+ ///
Return only distinct values
+ ///
Return values only from the filtered rows
+ ///
Ignore empty cells
+
+ // 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++) {
+ 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;
+ var inputvalue = '';
+ if (currentFilter != '' && currentFilter != '^') {
+ if (bIsNumber && currentFilter.charAt(0) == '^')
+ inputvalue = currentFilter.substr(1); //ignore trailing ^
+ else
+ inputvalue = currentFilter;
+ search_init = '';
+ }
+
+ var input = $('
');
+ if (iMaxLenght != undefined && iMaxLenght != -1) {
+ input.attr('maxlength', iMaxLenght);
+ }
+ th.html(input);
+ if (bIsNumber)
+ th.wrapInner('
');
+ else
+ th.wrapInner('
');
+
+ 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 () {
+ var advSearchFields = $("div#advanced_search").children(':visible');
+ if(validateAdvancedSearch(advSearchFields)){
+ 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];
+ this.value = "";
+ }
+ });
+ }
+
+ function fnCreateRangeInput(oTable) {
+
+ //var currentFilter = oTable.fnSettings().aoPreSearchCols[i].sSearch;
+ th.html(_fnRangeLabelPart(0));
+ var sFromId = oTable.attr("id") + '_range_from_' + i;
+ var from = $('
');
+ th.append(from);
+ th.append(_fnRangeLabelPart(1));
+ var sToId = oTable.attr("id") + '_range_to_' + i;
+ var to = $('
');
+ th.append(to);
+ th.append(_fnRangeLabelPart(2));
+ th.wrapInner('
');
+ 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 advSearchFields = $("div#advanced_search").children(':visible');
+ if(validateAdvancedSearch(advSearchFields)){
+ 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) {
+ th.html(_fnRangeLabelPart(0));
+ var sFromId = oTable.attr("id") + '_range_from_' + i;
+ var from = $('
');
+ from.datepicker();
+ th.append(from);
+ th.append(_fnRangeLabelPart(1));
+ var sToId = oTable.attr("id") + '_range_to_' + i;
+ var to = $('
');
+ th.append(to);
+ th.append(_fnRangeLabelPart(2));
+ th.wrapInner('
');
+ 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) {
+ if (aData == null)
+ aData = _fnGetColumnValues(oTable.fnSettings(), iColumn, true, false, true);
+ var index = iColumn;
+ var currentFilter = oTable.fnSettings().aoPreSearchCols[i].sSearch;
+
+ var r = '
');
+ nTh.html(select);
+ nTh.wrapInner('
');
+ 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();
+ });
+ }
+
+ function fnCreateSelect(oTable, aData, bRegex) {
+ 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); //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); //Issue 37
+
+ }
+
+ 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
+ if (properties.sFilterButtonText != null || properties.sFilterButtonText != undefined) {
+ labelBtn = properties.sFilterButtonText;
+ } else {
+ labelBtn = label;
+ }
+
+ 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 = '
';
+ var divClose = '
';
+
+ var uniqueId = oTable.attr("id") + localLabel;
+ var buttonId = "chkBtnOpen" + uniqueId;
+ var checkToggleDiv = uniqueId + "-flt-toggle";
+ r += '
'; //filter button witch open dialog
+ r += '
'; //dialog div
+ //r+= '
'; //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 += '
' + aData[j] + '
';
+
+ var checkbox = $(r);
+ th.html(checkbox);
+ th.wrapInner('
');
+ //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);
+ }
+ }
+
+
+
+
+ oTable = this;
+
+ var defaults = {
+ sPlaceHolder: "foot",
+ sRangeSeparator: "~",
+ iFilteringDelay: 500,
+ aoColumns: null,
+ sRangeFormat: "From {from} to {to}"
+ };
+
+ properties = $.extend(defaults, options);
+
+ return this.each(function () {
+
+ if (!oTable.fnSettings().oFeatures.bFilter)
+ return;
+ asInitVals = new Array();
+
+ 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);
+ break;
+ case "number-range":
+ fnCreateRangeInput(oTable);
+ break;
+ case "date-range":
+ fnCreateDateRangeInput(oTable);
+ break;
+ case "checkbox":
+ fnCreateCheckbox(oTable, 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);
\ No newline at end of file