import { FilterUi } from "./FilterUi.js";
import { CheckboxGroup } from "../../../ui/CheckboxGroup.js"
import { FilterSettings } from "../FilterSettings.js";
import { EditableTable } from "../../../ui/table/EditableTable.js";
import "./CheckboxFilter.css";
export { CheckboxFilter };
/**
* A class that defines the UI for the CheckboxGroup Attribute Filter
*
* @author sjaswal <shahzeib.jaswal@awi.de>
* @author rhess <robin.hess@awi.de>
*
* @memberof vef.map.filters.ui
*/
class CheckboxFilter extends FilterUi {
/**
* @param {HTMLElement | string} target
* @param {object} options filter specific options
* @param {LayerManager} layers Used for included/excluded layers
*/
constructor(target, options, layers) {
// apply default options
options = Object.assign({
title: "Checkbox Filter",
allowShowNullValues: true,
showNullValues: true,
multiColumn: true,
sortFields: true,
fields: [],
uniqueValueSource: null
}, options || {});
// fallback for old wps option
if (options.wps) {
options.uniqueValueSource = options.wps;
delete options.wps;
}
super(target, options, layers);
this.searchMode_ = false;
this.addSearchBar(this.element_.children[1]);
this.getElement().classList.add("checkbox-filter");
this.validateFields_(options.fields);
this.settingsClass_ = CheckboxFilterSettings;
this.checkBoxGroup_ = this.initCheckboxGroup_({
nodes: [],
singleSelect: options.singleSelect,
multiColumn: options.multiColumn
});
this.addToolButtons_();
this.initShowNullButton_();
this.addTool("fas fa-search search-button", (enabled) => this.enableSearch_(enabled), "Searching for Checkbox", true);
this.reloadOptions_();
}
async getfields_() {
let fields = this.options_.fields.slice(0);
if (!this.options_.uniqueValueSource) return fields;
const layer = this.layers_.getLayerById(this.options_.uniqueValueSource.layer);
if (!layer) return fields;
const values = await layer.getUniqueValues(this.options_.uniqueValueSource.column);
if (values.length == 0) return fields;
// merge cache and fields and remove duplicates
for (let i = 0; i < values.length; ++i) {
const value = values[i];
if (!fields.find(field => (field.column == this.options_.uniqueValueSource.column) && (field.operator == "eq") && (field.values == value))) {
fields.push({
column: this.options_.uniqueValueSource.column,
operator: "eq",
values: value,
title: value
});
}
}
return fields;
}
/**
* Initiates the Checkbox Group for Attribute Filter
*
* @param {object} options
*/
initCheckboxGroup_(options) {
const group = new CheckboxGroup(this.getContentContainer(), options);
group.on("changed", (e) => {
this.fire("change", this);
});
return group;
}
/**
* Validates the fields
*/
validateFields_(fields) {
for (let i = 0; i < fields.length; ++i) {
const field = fields[i];
if (!field.type) field.type = "string";
if (!field.operator) field.operator = "eq";
}
}
/**
* @private
*/
addToolButtons_() {
this.addTool("vef vef-deselect-all", () => this.checkBoxGroup_.deselectAll(), "Deselect All");
if (!this.options_.singleSelect) this.addTool("vef vef-select-all", () => this.checkBoxGroup_.selectAll(), "Select All");
}
/**
* Returns the active values in the Attribute Filter
*
* @returns values
*/
getActiveValues() {
const selectedItems = this.checkBoxGroup_.getSelected();
const filterValues = [];
for (let i = 0; i < selectedItems.length; ++i) {
const item = selectedItems[i];
const column = item.config.column;
const operator = item.config.operator;
let values = item.config.values;
if (!Array.isArray(values)) values = [values];
for (let i = 0; i < values.length; ++i) {
filterValues.push([operator, column, values[i]]);
}
}
return filterValues;
}
/**
* Returns the Active Filter Values
*
* @override
* @returns {object} Filter Object
*/
getActiveFilter() {
const activeAttributeFilter = this.getActiveValues();
let activeFilter = {
type: "attribute",
excludedLayers: this.getExcludedLayers(),
values: []
};
const columns = []
for (let i = 0; i < activeAttributeFilter.length; ++i) {
const activeItem = activeAttributeFilter[i];
if (activeItem.length < 2) continue;
const operator = activeItem[0];
const column = activeItem[1];
if (!columns.includes(column)) columns.push(column);
if (operator == "null") {
activeFilter.values.push([operator, column]);
} else if (["eq", "gt", "gteq", "lt", "lteq", "like"].includes(operator) && activeItem.length == 3) {
activeFilter.values.push([operator, column, activeItem[2]]);
}
}
if (this.options_.showNullValues) {
columns.forEach(column => {
activeFilter.values.push(["null", column]);
});
}
return activeFilter;
}
/**
* Get the filter's options-object
*/
getOptions() {
const options = Object.assign({}, this.options_);
return options;
}
/**
* method to reload options after applying settings
*/
reloadOptions_() {
this.setTitle(this.options_.title);
this.toggleToolVisibility("btn-power", this.options_.deactivatable);
this.toggleToolVisibility("btn-show-null", this.options_.allowShowNullValues);
this.getfields_().then(fields => {
if (this.options_.sortFields) fields.sort((a, b) => a.title.localeCompare(b.title));
this.checkBoxGroup_.setNodes(fields);
this.fire("change", this);
});
}
addSearchBar(element) {
if (element.classList[0] != "sidebar-element-content") return;
const input = document.createElement('div');
input.classList.add("search_checkbox_area")
input.innerHTML = '<input class="search_checkbox" type="text" placeholder="Search ...">'
element.prepend(input)
input.addEventListener("keyup", (e) => {
this.searching(e.target.value);
})
this.enableSearch_(this.searchMode_)
}
searching(search_word) {
//set
const arr = this.checkBoxGroup_.nodes;
search_word = search_word.toLowerCase();
//set to zero
arr.forEach(element => {
element.element.style.display = "none";
});
//searching
arr.forEach(element => {
if (element.config.column.toLowerCase().includes(search_word) || element.config.operator.toLowerCase().includes(search_word) || element.config.title.toLowerCase().includes(search_word) || element.config.values.toLowerCase().includes(search_word)) {
element.element.style.display = "flex";
}
});
}
enableSearch_(enabled) {
const a = this.content_.querySelector(".search_checkbox_area")
if (enabled) {
a.style.display = "flex";
console.log(this)
} else {
a.style.display = "none";
}
this.searchMode_ = enabled;
}
}
/**
* A class that defines the UI for the CheckboxGroup Attribute Filter
*
* @memberof vef.map.filters.ui
* @private
*/
export class CheckboxFilterSettings extends FilterSettings {
htmlExtension = `
<div>
<div class="table-container"></div>
<label><input type="checkbox" name="unique-values-enabled"/> Load unique values from a layer</label>
<div class="unique-values-wrapper">
<div class="unique-values-info"><i class="fas fa-file-import" style="color:var(--primary-color);"></i> Drag & Drop
a Layer here</div>
<div class="unique-values-inputs">
<label>Layer</label><span class="unique-layer-name"/></span><br>
<label>Column</label><select class="unique-column"></select>
</div>
</div>
<label><input type="checkbox" name="allow-show-null-values"/> Show "include NULL values" Button</label>
</div>
`;
uniqueValuesLayer = null;
/**
* @param {FilterUi} filter
*/
constructor(filter) {
super(filter);
this.query("form").insertAdjacentHTML("beforeend", this.htmlExtension);
this.table = new EditableTable(this.query(".table-container"), [
{
key: "title",
name: "Title"
},
{
key: "column",
name: "Column"
},
{
key: "operator",
name: "Operator"
},
{
key: "values",
name: "Value"
}
], filter.options_.fields);
this.setTitleEditable();
// Unique Values checkbox
const uniqueValuesCheckbox = this.query("input[name='unique-values-enabled']");
uniqueValuesCheckbox.addEventListener("change", () => {
this.query(".unique-values-wrapper").style.display = (uniqueValuesCheckbox.checked) ? "block" : "none";
});
this.query(".unique-values-wrapper").addEventListener("dragover", e => e.preventDefault());
this.query(".unique-values-wrapper").addEventListener('drop', e => {
e.preventDefault();
e.stopPropagation();
const layer = this.filter.layers_.getLayerById(e.dataTransfer.getData("layer_id"));
if (layer) this.setUniqueValuesLayer(layer);
});
}
setUniqueValuesLayer(layer) {
this.uniqueValuesLayer = layer;
this.query(".unique-values-wrapper .unique-layer-name").innerText = layer.title;
this.query(".unique-values-wrapper .unique-values-inputs").style.display = "block";
this.query(".unique-column").innerHTML = "";
const columns = layer.getAttributeNames();
let option = document.createElement("option");
option.value = "";
option.innerText = "-- Please select a column --";
this.query(".unique-column").appendChild(option);
for (let i = 0; i < columns.length; ++i) {
const column = columns[i];
option = document.createElement("option");
option.value = column;
option.innerText = column;
this.query(".unique-column").appendChild(option);
}
this.query(".unique-column").value = "";
}
/**
* Get the currently configured filter options
*/
getFilterOptions() {
const options = super.getFilterOptions();
options.allowShowNullValues = this.query("form input[name='allow-show-null-values']").checked;
options.fields = this.table.getValues();
if (this.query("input[name='unique-values-enabled']").checked && this.uniqueValuesLayer) {
options.uniqueValueSource = {
layer: this.uniqueValuesLayer.uniqueId,
column: this.query(".unique-column").value
};
} else {
options.uniqueValueSource = null;
}
return options;
}
/**
* Update Ui based on the filters current options
*/
updateFilterOptions() {
super.updateFilterOptions();
const options = this.filter.options_;
// clear function
this.table.clearTable();
this.table.Row(options.fields);
this.query("form input[name='allow-show-null-values']").checked = options.allowShowNullValues;
if (options.uniqueValueSource) {
const layer = this.filter.layers_.getLayerById(options.uniqueValueSource.layer);
if (layer) {
this.query("input[name='unique-values-enabled']").checked = true;
this.setUniqueValuesLayer(layer);
this.query(".unique-column").value = options.uniqueValueSource.column;
return;
}
}
this.query("input[name='unique-values-enabled']").checked = false;
this.query(".unique-values-wrapper").style.display = "none";
this.query(".unique-values-wrapper .unique-values-inputs").style.display = "none";
}
}