diff --git a/public/js/FilterWidget.js b/public/js/FilterWidget.js index caed86594..621129ae8 100644 --- a/public/js/FilterWidget.js +++ b/public/js/FilterWidget.js @@ -10,29 +10,32 @@ */ /** - * Global function used by NavigationWidget JS + * Global function used by NavigationWidget JS to bind events to side menu elements */ function sideMenuHook() { $(".remove-custom-filter").click(function() { - // + + // Ajax call to remove a custom filter FHC_AjaxClient.ajaxCallPost( - 'system/Filters/removeCustomFilter', + "system/Filters/removeCustomFilter", { - filter_id: $(this).attr('value'), + filter_id: $(this).attr("value"), // filter_id of the filter to be removed filter_page: FHC_FilterWidget.getFilterPage() }, { successCallback: function(data, textStatus, jqXHR) { + if (FHC_AjaxClient.isError(data)) { console.log(FHC_AjaxClient.getError(data)); } else { - if (typeof refreshSideMenu == 'function') + // If a success and refreshSideMenu is a valid function then call it to refresh the side menu + if (typeof refreshSideMenu == "function") { - InfocenterPersonDataset.refreshSideMenu(); + refreshSideMenu(); } } } @@ -42,31 +45,34 @@ function sideMenuHook() } /** - * FHC_FilterWidget + * FHC_FilterWidget this object is used to render the GUI of a filter widget and to operate with it */ var FHC_FilterWidget = { //------------------------------------------------------------------------------------------------------------------ // Public methods /** - * + * To display the FilterWidget using the loaded data prenset in the session */ display: function() { + FHC_FilterWidget._getFilter(FHC_FilterWidget._renderFilterWidget); }, /** - * + * To refresh the whole FilterWidget GUI */ refresh: function() { - FHC_FilterWidget._resetAll(); + + FHC_FilterWidget._resetFilterOptions(); FHC_FilterWidget.display(); }, /** - * + * To retrive the page where the FilterWidget is used, using the FHC_JS_DATA_STORAGE_OBJECT */ getFilterPage: function() { + return FHC_JS_DATA_STORAGE_OBJECT.called_path + "/" + FHC_JS_DATA_STORAGE_OBJECT.called_method; }, @@ -74,9 +80,11 @@ var FHC_FilterWidget = { // Private methods /** - * + * Utility method that checks if data contains an error and print that to the console + * otherwise the FilterWidget GUI is refreshed */ _failOrRefresh: function(data, textStatus, jqXHR) { + if (FHC_AjaxClient.isError(data)) { console.log(FHC_AjaxClient.getError(data)); @@ -88,9 +96,11 @@ var FHC_FilterWidget = { }, /** - * + * Utility method that checks if data contains an error and print that to the console + * otherwise the page is reloaded */ _failOrReload: function(data, textStatus, jqXHR) { + if (FHC_AjaxClient.isError(data)) { console.log(FHC_AjaxClient.getError(data)); @@ -102,29 +112,39 @@ var FHC_FilterWidget = { }, /** - * + * To reset the Filter Options GUI */ - _resetAll: function() { - // + _resetFilterOptions: function() { + $("#dragAndDropFieldsArea").html(""); - $("#addField").html(''); - // + $("#addField").html(""); $("#appliedFilters").html(""); - $("#addFilter").html(''); + $("#addFilter").html(""); }, /** - * + * To reset the Filter Table GUI + */ + _resetTableDataset: function() { + + $("#filterTableDataset > thead > tr").html(""); + $("#filterTableDataset > tbody").html(""); + }, + + /** + * To get via Ajax all the data related to the FilterWidget present in the given page + * If the parameter renderFunction is a valid function, is called on success */ _getFilter: function(renderFunction) { + FHC_AjaxClient.ajaxCallGet( - 'system/Filters/getFilter', + "system/Filters/getFilter", { filter_page: FHC_FilterWidget.getFilterPage() }, { successCallback: function(data, textStatus, jqXHR) { - if (FHC_AjaxClient.hasData(data) && typeof renderFunction == 'function') + if (FHC_AjaxClient.hasData(data) && typeof renderFunction == "function") { renderFunction(FHC_AjaxClient.getData(data)); } @@ -134,251 +154,453 @@ var FHC_FilterWidget = { }, /** - * + * This method calls all the other methods needed to rendere the GUI for a FilterWidget + * The parameter data contains all the data about the FilterWidget and it is given as parameter + * to all the methods that here are called */ _renderFilterWidget: function(data) { - FHC_FilterWidget._resetAll(); // + FHC_FilterWidget._initSessionStorage(); // initialize the session storage + FHC_FilterWidget._turnOffEvents(); // turns all the events off - FHC_FilterWidget._setFilterName(data); // + // Reset the entire GUI + FHC_FilterWidget._resetFilterOptions(); + FHC_FilterWidget._resetTableDataset(); - FHC_FilterWidget._renderDragAndDropFields(data); // - - FHC_FilterWidget._renderDropDownFields(data); // - - FHC_FilterWidget._renderAppliedFilters(data); // - - FHC_FilterWidget._renderDropDownFilters(data); // - - FHC_FilterWidget._renderTableDataset(data); // + // Render the GUI for this FilterWidget + FHC_FilterWidget._setFilterName(data); // set the name in the GUI + FHC_FilterWidget._renderDragAndDropFields(data); // render the fields drag and drop GUI + FHC_FilterWidget._renderDropDownFields(data); // render the fields drop-down + FHC_FilterWidget._renderAppliedFilters(data); // render the GUI for the applied filters + FHC_FilterWidget._renderDropDownFilters(data); // render the filters drop-down + FHC_FilterWidget._renderTableDataset(data); // render the table GUI + FHC_FilterWidget._turnOnEvents(); // turns all the events off }, /** - * + * Initialize the session storage + */ + _initSessionStorage: function() { + + // If the browser supports storage + if (typeof(Storage) !== "undefined") + { + // Checks if the "filter-options-status" is present in the session storage and if is equal to "open" + if (sessionStorage.getItem("filter-options-status") && sessionStorage.getItem("filter-options-status") == "open") + { + $(".collapse").collapse("show"); // then open the filter options panel + } + else + { + sessionStorage.setItem("filter-options-status", "closed"); // otherwise set "filter-options-status" to "close" + } + } + }, + + /** + * Turns all the events off + * NOTE: must be aligned to _turnOnEvents + */ + _turnOffEvents: function() { + + $("[data-toggle='collapse']").off("click"); + $(".drag-and-drop-fields-span").off("draggable"); + $(".drag-and-drop-fields-span").off("droppable"); + $(".remove-selected-field").off("click"); + $("#addField").off("change"); + $(".applied-filter-operation").off("change"); + $(".remove-applied-filter").off("click"); + $("#addFilter").off("change"); + $("#applyFilter").off("click"); + $("#saveCustomFilterButton").off("click"); + FHC_FilterWidget._disableTableSorter(); + }, + + /** + * Turns all the events on + * NOTE: must be aligned to _turnOffEvents + */ + _turnOnEvents: function() { + + $("[data-toggle='collapse']").click(FHC_FilterWidget._dataToggleCollapseEvent); // Click event to collapse or to open the filter options panel + $(".drag-and-drop-fields-span").draggable(FHC_FilterWidget._draggableConf); // draggable event on selected fields + $(".drag-and-drop-fields-span").droppable(FHC_FilterWidget._droppableConf); // droppable event on selected fields + $(".remove-selected-field").click(FHC_FilterWidget._revomeSelectedFieldsEvent); // Click event on the "X" link + $("#addField").change(FHC_FilterWidget._addFieldEvent); // Change event on the fields drop-down to add new fields + $(".applied-filter-operation").change(FHC_FilterWidget._appliedFiltersOperationsEvent); // Change event on the operation drop-down + $(".remove-applied-filter").click(FHC_FilterWidget._removeAppliedFiltersEvent); // Click event to the "X" button to remove an applied filter + $("#addFilter").change(FHC_FilterWidget._addFilterEvent); // Click event on the applied filters drop-down to add a new filter to the dataset + $("#applyFilter").click(FHC_FilterWidget._applyFilterEvent); // Click event on the applied filters drop-down to apply filters to the dataset + $("#saveCustomFilterButton").click(FHC_FilterWidget._saveCustomFilterButtonEvent); // Click evento to for the save custom filter button + FHC_FilterWidget._enableTableSorter(); // enable the tablesorter + }, + + /** + * Configuration object used by draggable event on selected fields + */ + _draggableConf: { + containment: "parent", + cursor: "move", + opacity: 0.4, + revert: "invalid", + revertDuration: 200, + drag: function(event, ui) { + + var padding = 20; + var draggedElement = $(this); + + $(".drag-and-drop-fields-span").each(function(i, e) { + + if ($(this).attr("id") != draggedElement.attr("id")) + { + $(this).removeClass("selection-after"); + $(this).removeClass("selection-before"); + + var elementCenter = $(this).offset().left + ((padding + $(this).width()) / 2); + + if (event.pageX > ($(this).offset().left - (padding / 2)) + && event.pageX < ($(this).offset().left + $(this).width() + (padding / 2))) + { + if (event.pageX > elementCenter) + { + $(this).addClass("selection-after"); + $(this).removeClass("selection-before"); + } + else if (event.pageX < elementCenter) + { + $(this).addClass("selection-before"); + $(this).removeClass("selection-after"); + } + } + } + + }); + + } + }, + + /** + * Configuration object used by droppable event on selected fields + */ + _droppableConf: { + accept: ".drag-and-drop-fields-span", + drop: function(event, ui) { + + var padding = 20; + var elementCenter = $(this).offset().left + ((padding + $(this).width()) / 2); + var draggedElement = ui.helper; + + if (event.pageX > elementCenter) + { + draggedElement.insertAfter($(this)); + } + else if (event.pageX < elementCenter) + { + draggedElement.insertBefore($(this)); + } + + $(this).removeClass("selection-before"); + $(this).removeClass("selection-after"); + + draggedElement.css({left: "0px", top: "10px"}); + + var arrayDndId = []; + + $(".drag-and-drop-fields-span").each(function(i, e) { + + arrayDndId[i] = $(this).attr("id").replace("dnd", ""); + + }); + + FHC_AjaxClient.ajaxCallPost( + "system/Filters/sortSelectedFields", + { + selectedFields: arrayDndId, + filter_page: FHC_FilterWidget.getFilterPage() + }, + { + successCallback: function(data, textStatus, jqXHR) { + FHC_FilterWidget._cleanTablesorterLocalStorage(); + FHC_FilterWidget._failOrRefresh(data, textStatus, jqXHR); + } + } + ); + } + }, + + /** + * Event function used to remove selected fields + */ + _revomeSelectedFieldsEvent: function(event) { + + FHC_AjaxClient.ajaxCallPost( + "system/Filters/removeSelectedField", + { + selectedField: $(this).attr("fieldToRemove"), + filter_page: FHC_FilterWidget.getFilterPage() + }, + { + successCallback: function(data, textStatus, jqXHR) { + FHC_FilterWidget._failOrRefresh(data, textStatus, jqXHR); + } + } + ); + }, + + /** + * Event function used by the applied filter operation drop-down to hide others element when thery are not needed + */ + _appliedFiltersOperationsEvent: function(event) { + + if ($(this).val() == "set" || $(this).val() == "nset") + { + $(this).parent().parent().find(".applied-filter-condition").addClass("hidden-control"); + $(this).parent().parent().find(".applied-filter-option").addClass("hidden-control"); + $(this).parent().parent().find(".applied-filter-condition").prop("disabled", true); + $(this).parent().parent().find(".applied-filter-option").prop("disabled", true); + } + else + { + $(this).parent().parent().find(".applied-filter-condition").removeClass("hidden-control"); + $(this).parent().parent().find(".applied-filter-option").removeClass("hidden-control"); + $(this).parent().parent().find(".applied-filter-condition").prop("disabled", false); + $(this).parent().parent().find(".applied-filter-option").prop("disabled", false); + } + }, + + /** + * Event function used by the add field drop-down + */ + _addFieldEvent: function(event) { + + FHC_AjaxClient.ajaxCallPost( + "system/Filters/addSelectedField", + { + selectedField: $(this).val(), + filter_page: FHC_FilterWidget.getFilterPage() + }, + { + successCallback: function(data, textStatus, jqXHR) { + FHC_FilterWidget._cleanTablesorterLocalStorage(); + FHC_FilterWidget._failOrRefresh(data, textStatus, jqXHR); + } + } + ); + }, + + /** + * Event function used by the apply filter button + */ + _applyFilterEvent: function() { + + var appliedFilters = []; + var appliedFiltersOperations = []; + var appliedFiltersConditions = []; + var appliedFiltersOptions = []; + + $("#appliedFilters > div").each(function(i, e) { + appliedFilters.push($(this).find(".hidden-field-name").val()); + appliedFiltersOperations.push($(this).find(".applied-filter-operation").val()); + appliedFiltersConditions.push($(this).find(".applied-filter-condition:enabled").val()); + appliedFiltersOptions.push($(this).find(".applied-filter-option:enabled").val()); + }); + + FHC_AjaxClient.ajaxCallPost( + "system/Filters/applyFilters", + { + appliedFilters: appliedFilters, + appliedFiltersOperations: appliedFiltersOperations, + appliedFiltersConditions: appliedFiltersConditions, + appliedFiltersOptions: appliedFiltersOptions, + filter_page: FHC_FilterWidget.getFilterPage() + }, + { + successCallback: function(data, textStatus, jqXHR) { + FHC_FilterWidget._failOrReload(data, textStatus, jqXHR); + } + } + ); + }, + + /** + * Event function used to remove an applied filter to the dataset + */ + _removeAppliedFiltersEvent: function(event) { + + FHC_AjaxClient.ajaxCallPost( + "system/Filters/removeAppliedFilter", + { + appliedFilter: $(this).attr("filterToRemove"), + filter_page: FHC_FilterWidget.getFilterPage() + }, + { + successCallback: function(data, textStatus, jqXHR) { + FHC_FilterWidget._failOrReload(data, textStatus, jqXHR); + } + } + ); + }, + + /** + * Event function used to add a new filter to the dataset + */ + _addFilterEvent: function(event) { + + FHC_AjaxClient.ajaxCallPost( + "system/Filters/addFilter", + { + filter: $(this).val(), + filter_page: FHC_FilterWidget.getFilterPage() + }, + { + successCallback: function(data, textStatus, jqXHR) { + FHC_FilterWidget._failOrRefresh(data, textStatus, jqXHR); + } + } + ); + }, + + /** + * Event function used to collapse the filter options panel and to store the info into the session storage + */ + _dataToggleCollapseEvent: function() { + + if (typeof(Storage) !== "undefined") + { + if (sessionStorage.getItem("filter-options-status")) + { + if (sessionStorage.getItem("filter-options-status") == "closed") + { + sessionStorage.setItem("filter-options-status", "open"); + } + else + { + sessionStorage.setItem("filter-options-status", "closed"); + } + } + } + }, + + /** + * Event function used to save a custom filter + */ + _saveCustomFilterButtonEvent: function() { + + if ($("#customFilterDescription").val() != "") + { + FHC_AjaxClient.ajaxCallPost( + "system/Filters/saveCustomFilter", + { + customFilterDescription: $("#customFilterDescription").val(), + filter_page: FHC_FilterWidget.getFilterPage() + }, + { + successCallback: refreshSideMenu // NOTE: to be checked + } + ); + } + else + { + alert("Please fill the description of this filter"); + } + }, + + /** + * Retrive the filter name from data and display it in the GUI */ _setFilterName: function(data) { - if (data.hasOwnProperty('filterName')) + + if (data.hasOwnProperty("filterName")) { $(".filter-name-title").html(data.filterName); } }, /** - * + * Renders the drag and drop GUI for the fields of the FilterWidget + * Retrieves the list of used fields, the list of all the fields and + * their possibly present aliases from the parameter data */ _renderDragAndDropFields: function(data) { - $(".remove-selected-field").off('click'); - - var arrayFieldsToDisplay = []; - - if (data.hasOwnProperty('selectedFields') && $.isArray(data.selectedFields)) - { - if (data.hasOwnProperty('columnsAliases') && $.isArray(data.columnsAliases)) - { - for (var i = 0; i < data.selectedFields.length; i++) - { - for (var j = 0; j < data.fields.length; j++) - { - if (data.selectedFields[i] == data.fields[j]) - { - arrayFieldsToDisplay[i] = data.columnsAliases[j]; - } - } - } - } - else - { - arrayFieldsToDisplay = data.selectedFields; - } - } + var arrayFieldsToDisplay = FHC_FilterWidget._getFieldsToDisplay(data); for (var i = 0; i < arrayFieldsToDisplay.length; i++) { var fieldToDisplay = arrayFieldsToDisplay[i]; var fieldName = data.selectedFields[i]; - var strHtml = ''; - strHtml += ' ' + fieldToDisplay + ''; - strHtml += ' '; - strHtml += ' X '; - strHtml += ' '; - strHtml += ''; + var strHtml = ""; + strHtml += " " + fieldToDisplay + ""; + strHtml += " "; + strHtml += " X "; + strHtml += " "; + strHtml += ""; $("#dragAndDropFieldsArea").append(strHtml); } - - $(".drag-and-drop-fields-span").draggable({ - containment: "parent", - cursor: "move", - opacity: 0.4, - revert: "invalid", - revertDuration: 200, - drag: function(event, ui) { - - var padding = 20; - var draggedElement = $(this); - - $(".drag-and-drop-fields-span").each(function(i, e) { - - if ($(this).attr('id') != draggedElement.attr('id')) - { - $(this).removeClass("selection-after"); - $(this).removeClass("selection-before"); - - var elementCenter = $(this).offset().left + ((padding + $(this).width()) / 2); - - if (event.pageX > ($(this).offset().left - (padding / 2)) - && event.pageX < ($(this).offset().left + $(this).width() + (padding / 2))) - { - if (event.pageX > elementCenter) - { - $(this).addClass("selection-after"); - $(this).removeClass("selection-before"); - } - else if (event.pageX < elementCenter) - { - $(this).addClass("selection-before"); - $(this).removeClass("selection-after"); - } - } - } - - }); - - } - }); - - $(".drag-and-drop-fields-span").droppable({ - accept: ".drag-and-drop-fields-span", - drop: function(event, ui) { - - var padding = 20; - var elementCenter = $(this).offset().left + ((padding + $(this).width()) / 2); - var draggedElement = ui.helper; - - if (event.pageX > elementCenter) - { - draggedElement.insertAfter($(this)); - } - else if (event.pageX < elementCenter) - { - draggedElement.insertBefore($(this)); - } - - $(this).removeClass("selection-before"); - $(this).removeClass("selection-after"); - - draggedElement.css({left: '0px', top: '10px'}); - - var arrayDndId = []; - - $(".drag-and-drop-fields-span").each(function(i, e) { - - arrayDndId[i] = $(this).attr('id').replace('dnd', ''); - - }); - - // - FHC_AjaxClient.ajaxCallPost( - 'system/Filters/sortSelectedFields', - { - selectedFields: arrayDndId, - filter_page: FHC_FilterWidget.getFilterPage() - }, - { - successCallback: function(data, textStatus, jqXHR) { - // Tablesorter filter local storage clean - $("#filterTableDataset").trigger("filterResetSaved"); - - FHC_FilterWidget._failOrRefresh(data, textStatus, jqXHR); - } - } - ); - } - }); - - $(".remove-selected-field").click(function(event) { - // - FHC_AjaxClient.ajaxCallPost( - 'system/Filters/removeSelectedField', - { - selectedField: $(this).attr('fieldToRemove'), - filter_page: FHC_FilterWidget.getFilterPage() - }, - { - successCallback: function(data, textStatus, jqXHR) { - FHC_FilterWidget._failOrRefresh(data, textStatus, jqXHR); - } - } - ); - }); - }, - - _renderDropDownFields: function(data) { - - $("#addField").off('change'); - - var strDropDown = ''; - - if (data.hasOwnProperty('fields') && $.isArray(data.fields)) - { - for (var i = 0; i < data.fields.length; i++) - { - var toBeDisplayed = true; - - for (var j = 0; j < data.selectedFields.length; j++) - { - if (data.fields[i] == data.selectedFields[j]) - { - toBeDisplayed = false; - break; - } - } - - if (toBeDisplayed == true) - { - var fieldName = data.fields[i]; - var fieldToDisplay = data.fields[i]; - - if (data.hasOwnProperty('columnsAliases') && $.isArray(data.columnsAliases)) - { - fieldToDisplay = data.columnsAliases[i]; - } - - $("#addField").append(''); - } - } - } - - $("#addField").change(function(event) { - // - FHC_AjaxClient.ajaxCallPost( - 'system/Filters/addSelectedField', - { - selectedField: $(this).val(), - filter_page: FHC_FilterWidget.getFilterPage() - }, - { - successCallback: function(data, textStatus, jqXHR) { - // Tablesorter filter local storage clean - $("#filterTableDataset").trigger("filterResetSaved"); - - FHC_FilterWidget._failOrRefresh(data, textStatus, jqXHR); - } - } - ); - }); }, /** - * + * Renders the drop-down element that contains all the usable fields in the FilterWidget + * The list of all usable fields and their possibly aliases are retrieved from the parameter data + */ + _renderDropDownFields: function(data) { + + if (data.hasOwnProperty("fields") && $.isArray(data.fields)) + { + FHC_FilterWidget._renderDropDown(data, data.selectedFields, 'addField'); + } + }, + + /** + * Renders a dropdown attached to the HTML element ddElementId, using the elements from data.fields + * and excluding the elements that are prenset in the elements parameter + */ + _renderDropDown: function(data, elements, ddElementId) { + + for (var i = 0; i < data.fields.length; i++) + { + var toBeDisplayed = true; + + for (var j = 0; j < elements.length; j++) + { + var elementName = elements[j].hasOwnProperty("name") ? elements[j].name : elements[j]; + + if (data.fields[i] == elementName) + { + toBeDisplayed = false; + break; + } + } + + if (toBeDisplayed == true) + { + var fieldName = data.fields[i]; + var fieldToDisplay = data.fields[i]; + + if (data.hasOwnProperty("columnsAliases") && $.isArray(data.columnsAliases)) + { + fieldToDisplay = data.columnsAliases[i]; + } + + if ($("#" + ddElementId).length) // checks if the element exists + { + $("#" + ddElementId).append(""); + } + } + } + }, + + /** + * Render the GUI to operate with the filters applied to the dataset + * The list of all applied filters is retrieved from the parameter data */ _renderAppliedFilters: function(data) { - if (data.hasOwnProperty('datasetMetadata') && $.isArray(data.datasetMetadata) - && data.hasOwnProperty('filters') && $.isArray(data.filters)) + if (data.hasOwnProperty("datasetMetadata") && $.isArray(data.datasetMetadata) + && data.hasOwnProperty("filters") && $.isArray(data.filters)) { for (var i = 0; i < data.filters.length; i++) { @@ -386,11 +608,11 @@ var FHC_FilterWidget = { { if (data.filters[i].name == data.datasetMetadata[j].name) { - var appliedFilters = '