working filter system
This commit is contained in:
parent
5930fe90a1
commit
eb3d17884a
|
@ -15,10 +15,10 @@ You can select the growth period of interest from the drop-down, which updates t
|
||||||
The chart always reflects the countries selected in the table.
|
The chart always reflects the countries selected in the table.
|
||||||
|
|
||||||
<br/>
|
<br/>
|
||||||
{{< dropdown_filter id="days_ago" options="1 day:1,7 day:7,28 day:28,1 year:365,5 year:1826,10 year:3652,all time:10000" default_selection="7 day" >}}
|
{{< dropdown_filter id="days_ago_dropdown_filter" id_filter="days_ago" options="1 day:1,7 day:7,28 day:28,1 year:365,5 year:1826,10 year:3652,all time:10000" default_selection="7 day" targets="bitcoin-business-growth-chart bitcoin-business-growth-table" >}}
|
||||||
{{< table id="bitcoin_business_growth" endpoint="bitcoin_business_growth_percent_diff" headers="{'country_name': 'Country', 'date_range': 'Date Range', 'last_value': 'Previous #', 'first_value': 'Current #', 'difference': 'Diff', 'percent_difference': '% Diff'}" maxHeight="400px" sortable="true" valueId="country_name" selectableRows="multi" >}}
|
{{< table id="bitcoin-business-growth-table" endpoint="bitcoin_business_growth_percent_diff" headers="{'country_name': 'Country', 'date_range': 'Date Range', 'last_value': 'Previous #', 'first_value': 'Current #', 'difference': 'Diff', 'percent_difference': '% Diff'}" maxHeight="400px" sortable="true" valueId="country_name" selectableRows="multi" targets="bitcoin-business-growth-chart" >}}
|
||||||
|
|
||||||
{{< chart id="bitcoin_business_growth" endpoint="bitcoin_business_growth_timeseries" chartType="line" xAxisField="date" yAxisField="cumulative_value" scaleChart=true >}}
|
{{< chart id="bitcoin-business-growth-chart" endpoint="bitcoin_business_growth_timeseries" chartType="line" xAxisField="date" yAxisField="cumulative_value" scaleChart=true >}}
|
||||||
|
|
||||||
#### Attribution and License
|
#### Attribution and License
|
||||||
Data obtained from © [OpenStreetMap](https://www.openstreetmap.org/copyright)
|
Data obtained from © [OpenStreetMap](https://www.openstreetmap.org/copyright)
|
||||||
|
|
|
@ -39,7 +39,7 @@
|
||||||
for (let objectId in chartData) {
|
for (let objectId in chartData) {
|
||||||
chartDataMap.set(objectId, chartData[objectId]);
|
chartDataMap.set(objectId, chartData[objectId]);
|
||||||
}
|
}
|
||||||
var chartDom = document.getElementById(`${id}--chart`);
|
var chartDom = document.getElementById(`${id}`);
|
||||||
var myChart = echarts.init(chartDom);
|
var myChart = echarts.init(chartDom);
|
||||||
|
|
||||||
var option = {
|
var option = {
|
||||||
|
@ -67,30 +67,29 @@
|
||||||
myChart.setOption(option, true);
|
myChart.setOption(option, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
document.addEventListener("rowSelected", (event) => {
|
// listen for filter events for this target
|
||||||
console.log(
|
document.addEventListener("filterChange", function (event) {
|
||||||
"Row selected:",
|
tableId = document.getElementById(id).id;
|
||||||
event.detail.row.offsetParent.id,
|
console.log(event.detail);
|
||||||
event.detail.row.value,
|
eventDetail = event.detail;
|
||||||
event.detail.valueId,
|
if (eventDetail.filterActions.includes("refresh")) {
|
||||||
event.detail.selectableRows,
|
chartData = [];
|
||||||
);
|
updateChart();
|
||||||
valueId = event.detail.valueId
|
} else {
|
||||||
|
if (eventDetail.filterTargets.includes(tableId)) {
|
||||||
|
if (eventDetail.filterActions.includes("selected")) {
|
||||||
|
valueId = eventDetail.filterId;
|
||||||
let selectedRow = {
|
let selectedRow = {
|
||||||
[valueId]: event.detail.row.value,
|
[valueId]: eventDetail.filterValue,
|
||||||
};
|
};
|
||||||
query = queryConstructor(selectedRow);
|
query = queryConstructor(selectedRow);
|
||||||
fetchDataForChart(query, valueId);
|
fetchDataForChart(query, valueId);
|
||||||
});
|
} else {
|
||||||
|
delete chartData[eventDetail.filterValue];
|
||||||
document.addEventListener("rowDeselected", (event) => {
|
|
||||||
console.log(
|
|
||||||
"Row deselected:",
|
|
||||||
event.detail.row.offsetParent.id,
|
|
||||||
event.detail.row.value,
|
|
||||||
);
|
|
||||||
delete chartData[event.detail.row.value];
|
|
||||||
updateChart();
|
updateChart();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
sortable,
|
sortable,
|
||||||
valueId,
|
valueId,
|
||||||
selectableRows,
|
selectableRows,
|
||||||
|
filterTargets
|
||||||
) {
|
) {
|
||||||
async function fetchDataForTable(query) {
|
async function fetchDataForTable(query) {
|
||||||
try {
|
try {
|
||||||
|
@ -25,7 +26,7 @@
|
||||||
|
|
||||||
function generateTable(data) {
|
function generateTable(data) {
|
||||||
const jsonTableContainer = document.getElementById(
|
const jsonTableContainer = document.getElementById(
|
||||||
`${id}--table-container`,
|
`${id}--container`,
|
||||||
);
|
);
|
||||||
jsonTableContainer.className = "jsonTableContainer";
|
jsonTableContainer.className = "jsonTableContainer";
|
||||||
jsonTableContainer.innerHTML = "";
|
jsonTableContainer.innerHTML = "";
|
||||||
|
@ -35,7 +36,7 @@
|
||||||
tableHeaderKeys = Object.keys(headers);
|
tableHeaderKeys = Object.keys(headers);
|
||||||
|
|
||||||
const table = document.createElement("table");
|
const table = document.createElement("table");
|
||||||
table.id = `${id}--table`;
|
table.id = `${id}`;
|
||||||
const thead = document.createElement("thead");
|
const thead = document.createElement("thead");
|
||||||
const tbody = document.createElement("tbody");
|
const tbody = document.createElement("tbody");
|
||||||
const headerRow = document.createElement("tr");
|
const headerRow = document.createElement("tr");
|
||||||
|
@ -63,51 +64,43 @@
|
||||||
table.appendChild(thead);
|
table.appendChild(thead);
|
||||||
table.appendChild(tbody);
|
table.appendChild(tbody);
|
||||||
|
|
||||||
// selectable rows
|
|
||||||
let currentlySelectedRow = null;
|
|
||||||
|
|
||||||
if (selectableRows === "multi" || selectableRows === "single") {
|
if (selectableRows === "multi" || selectableRows === "single") {
|
||||||
const rows = table.getElementsByTagName("tr");
|
const rows = table.getElementsByTagName("tr");
|
||||||
|
|
||||||
for (let i = 1; i < rows.length; i++) {
|
for (let i = 1; i < rows.length; i++) {
|
||||||
// Skip the header row
|
|
||||||
rows[i].addEventListener("click", function () {
|
rows[i].addEventListener("click", function () {
|
||||||
if (selectableRows === "single") {
|
if (selectableRows === "multi") {
|
||||||
// Deselect the currently selected row, if any
|
|
||||||
if (currentlySelectedRow && currentlySelectedRow !== this) {
|
|
||||||
currentlySelectedRow.classList.remove("selected");
|
|
||||||
const deselectEvent = new CustomEvent("rowDeselected", {
|
|
||||||
detail: { row: currentlySelectedRow },
|
|
||||||
});
|
|
||||||
document.dispatchEvent(deselectEvent);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Toggle the selected class on the clicked row
|
|
||||||
this.classList.toggle("selected");
|
this.classList.toggle("selected");
|
||||||
|
if (this.classList.contains("selected")) {
|
||||||
// Update the currently selected row
|
const event = new CustomEvent("filterChange", {
|
||||||
currentlySelectedRow = this.classList.contains("selected")
|
|
||||||
? this
|
|
||||||
: null;
|
|
||||||
} else {
|
|
||||||
// Multi-select behavior
|
|
||||||
this.classList.toggle("selected");
|
|
||||||
}
|
|
||||||
|
|
||||||
const event = new CustomEvent(
|
|
||||||
this.classList.contains("selected")
|
|
||||||
? "rowSelected"
|
|
||||||
: "rowDeselected",
|
|
||||||
{
|
|
||||||
detail: {
|
detail: {
|
||||||
row: this,
|
filterId: valueId,
|
||||||
selectableRows: selectableRows,
|
filterValue: this.value,
|
||||||
valueId: valueId,
|
filterActions: ["selected"],
|
||||||
|
filterTargets: filterTargets
|
||||||
},
|
},
|
||||||
},
|
});
|
||||||
);
|
|
||||||
|
|
||||||
document.dispatchEvent(event);
|
document.dispatchEvent(event);
|
||||||
|
} else {
|
||||||
|
const event = new CustomEvent("filterChange", {
|
||||||
|
detail: {
|
||||||
|
filterId: valueId,
|
||||||
|
filterValue: this.value,
|
||||||
|
filterActions: ["deselected"],
|
||||||
|
filterTargets: filterTargets
|
||||||
|
},
|
||||||
|
});
|
||||||
|
document.dispatchEvent(event);
|
||||||
|
}
|
||||||
|
} else if (selectableRows === "single") {
|
||||||
|
if (this.classList.contains("selected")) {
|
||||||
|
this.classList.remove("selected");
|
||||||
|
} else {
|
||||||
|
for (let j = 1; j < rows.length; j++) {
|
||||||
|
rows[j].classList.remove("selected");
|
||||||
|
}
|
||||||
|
this.classList.add("selected");
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -116,16 +109,20 @@
|
||||||
// sortable
|
// sortable
|
||||||
if (sortable == "true") {
|
if (sortable == "true") {
|
||||||
table.className = "sortable";
|
table.className = "sortable";
|
||||||
sorttable.makeSortable(document.getElementById(`${id}--table`));
|
sorttable.makeSortable(document.getElementById(`${id}`));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// listen for filter events for this target
|
||||||
document.addEventListener("filterChange", function (event) {
|
document.addEventListener("filterChange", function (event) {
|
||||||
query = queryConstructor()
|
tableId = document.getElementById(id).id
|
||||||
|
if (event.detail.filterTargets.includes(tableId)) {
|
||||||
|
query = queryConstructor();
|
||||||
fetchDataForTable(query);
|
fetchDataForTable(query);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
query = queryConstructor()
|
query = queryConstructor();
|
||||||
fetchDataForTable(query);
|
fetchDataForTable(query);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{{ partial "chart.html" }}
|
{{ partial "chart.html" }}
|
||||||
<section class = 'chart-container'>
|
<section class = 'chart-container'>
|
||||||
<div class = "chart" id='{{ .Get "id" }}--chart'>
|
<div class = "chart" id='{{ .Get "id" }}'>
|
||||||
<script>
|
<script>
|
||||||
document.addEventListener("DOMContentLoaded", function () {
|
document.addEventListener("DOMContentLoaded", function () {
|
||||||
createChart(id={{ .Get "id" }}, endpoint={{ .Get "endpoint" }}, chartType={{ .Get "chartType" }}, xAxisField={{ .Get "xAxisField" }}, yAxisField={{ .Get "yAxisField" }}, sortField={{ .Get "sortField" }}, scaleChart={{ .Get "scaleChart" }})
|
createChart(id={{ .Get "id" }}, endpoint={{ .Get "endpoint" }}, chartType={{ .Get "chartType" }}, xAxisField={{ .Get "xAxisField" }}, yAxisField={{ .Get "yAxisField" }}, sortField={{ .Get "sortField" }}, scaleChart={{ .Get "scaleChart" }})
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
{{ $options_split := split $options "," }}
|
{{ $options_split := split $options "," }}
|
||||||
|
|
||||||
<div class="dropdown-filter-container">
|
<div class="dropdown-filter-container">
|
||||||
<select class="filter dropdown-filter" id="{{ $id }}" onchange="dispatchDropdownEvent(this)">
|
<select class="filter dropdown-filter" id="{{ $id }}" idFilter='{{ .Get "id_filter" }}' onchange="dispatchDropdownEvent(this)">
|
||||||
{{ range $options_split }}
|
{{ range $options_split }}
|
||||||
{{ $parts := split . ":" }}
|
{{ $parts := split . ":" }}
|
||||||
{{ $key := index $parts 0 }}
|
{{ $key := index $parts 0 }}
|
||||||
|
@ -17,8 +17,10 @@
|
||||||
function dispatchDropdownEvent(selectElement) {
|
function dispatchDropdownEvent(selectElement) {
|
||||||
const event = new CustomEvent('filterChange', {
|
const event = new CustomEvent('filterChange', {
|
||||||
detail: {
|
detail: {
|
||||||
filterId: selectElement.id,
|
filterId: '{{ .Get "id_filter" }}',
|
||||||
filterValue: selectElement.value,
|
filterValue: selectElement.value,
|
||||||
|
filterActions: ["refresh"],
|
||||||
|
filterTargets: '{{ .Get "targets" }}'.split(" ")
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
document.dispatchEvent(event);
|
document.dispatchEvent(event);
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
{{ partial "table.html" }}
|
{{ partial "table.html" }}
|
||||||
<div id = '{{ .Get "id" }}--table-container'>
|
<div id = '{{ .Get "id" }}--container'>
|
||||||
<script>
|
<script>
|
||||||
document.addEventListener("DOMContentLoaded", function () {
|
document.addEventListener("DOMContentLoaded", function () {
|
||||||
createTable({{ .Get "endpoint" }}, {{ .Get "id" }}, {{ .Get "headers" | safeJS }}, {{ .Get "maxHeight" }}, {{ .Get "sortable" }}, {{ .Get "valueId" }}, {{ .Get "selectableRows" }})
|
createTable({{ .Get "endpoint" }}, {{ .Get "id" }}, {{ .Get "headers" | safeJS }}, {{ .Get "maxHeight" }}, {{ .Get "sortable" }}, {{ .Get "valueId" }}, {{ .Get "selectableRows" }}, '{{ .Get "targets" }}'.split(" "))
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -5,7 +5,7 @@ function queryConstructor(customFilters = {}) {
|
||||||
Object.assign(queryObject, customFilters);
|
Object.assign(queryObject, customFilters);
|
||||||
|
|
||||||
filters.forEach((filter) => {
|
filters.forEach((filter) => {
|
||||||
const filterId = filter.id;
|
const filterId = filter.getAttribute("idFilter");
|
||||||
const filterValue = filter.value;
|
const filterValue = filter.value;
|
||||||
queryObject[filterId] = filterValue;
|
queryObject[filterId] = filterValue;
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue