254 lines
7.8 KiB
JavaScript
254 lines
7.8 KiB
JavaScript
// Sort button
|
|
class BrickGridSortButton {
|
|
constructor(button, grid) {
|
|
this.button = button;
|
|
this.grid = grid;
|
|
this.data = this.button.dataset;
|
|
|
|
// Setup
|
|
button.addEventListener("click", ((grid, button) => (e) => {
|
|
grid.sort(button);
|
|
})(grid, this));
|
|
}
|
|
|
|
// Active
|
|
active() {
|
|
this.button.classList.remove("btn-outline-primary");
|
|
this.button.classList.add("btn-primary");
|
|
}
|
|
|
|
// Inactive
|
|
inactive() {
|
|
delete this.button.dataset.sortOrder;
|
|
this.button.classList.remove("btn-primary");
|
|
this.button.classList.add("btn-outline-primary");
|
|
}
|
|
|
|
// Toggle sorting
|
|
toggle(order) {
|
|
// Cleanup
|
|
delete this.button.dataset.sortOrder;
|
|
|
|
let icon = this.button.querySelector("i.ri");
|
|
if (icon) {
|
|
this.button.removeChild(icon);
|
|
}
|
|
|
|
// Set order
|
|
if (order) {
|
|
this.active();
|
|
|
|
this.button.dataset.sortOrder = order;
|
|
|
|
icon = document.createElement("i");
|
|
icon.classList.add("ri", "ms-1", `ri-sort-${order}`);
|
|
|
|
this.button.append(icon);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Grid class
|
|
class BrickGrid {
|
|
constructor(id) {
|
|
this.id = id;
|
|
|
|
// Grid elements (built based on the initial id)
|
|
this.html_grid = document.getElementById(id);
|
|
this.html_sort = document.getElementById(`${id}-sort`);
|
|
this.html_search = document.getElementById(`${id}-search`);
|
|
this.html_filter = document.getElementById(`${id}-filter`);
|
|
this.html_theme = document.getElementById(`${id}-theme`);
|
|
|
|
// Sort buttons
|
|
this.html_sort_buttons = {};
|
|
if (this.html_sort) {
|
|
this.html_sort.querySelectorAll("button[data-sort-attribute]").forEach(button => {
|
|
this.html_sort_buttons[button.id] = new BrickGridSortButton(button, this);
|
|
});
|
|
}
|
|
|
|
// Clear button
|
|
this.html_clear = document.querySelector("button[data-sort-clear]")
|
|
if (this.html_clear) {
|
|
this.html_clear.addEventListener("click", ((grid) => (e) => {
|
|
grid.clear(e.currentTarget)
|
|
})(this))
|
|
}
|
|
|
|
// Filter setup
|
|
if (this.html_search) {
|
|
this.html_search.addEventListener("keyup", ((grid) => () => {
|
|
grid.filter();
|
|
})(this));
|
|
}
|
|
|
|
if (this.html_filter) {
|
|
this.html_filter.addEventListener("change", ((grid) => () => {
|
|
grid.filter();
|
|
})(this));
|
|
}
|
|
|
|
if (this.html_theme) {
|
|
this.html_theme.addEventListener("change", ((grid) => () => {
|
|
grid.filter();
|
|
})(this));
|
|
}
|
|
|
|
// Cookie setup
|
|
const cookies = document.cookie.split(";").reduce((acc, cookieString) => {
|
|
const [key, value] = cookieString.split("=").map(s => s.trim().replace(/^"|"$/g, ""));
|
|
if (key && value) {
|
|
acc[key] = decodeURIComponent(value);
|
|
}
|
|
return acc;
|
|
}, {});
|
|
|
|
// Initial sort
|
|
if ("sort-id" in cookies && cookies["sort-id"] in this.html_sort_buttons) {
|
|
const current = this.html_sort_buttons[cookies["sort-id"]];
|
|
|
|
if("sort-order" in cookies) {
|
|
current.button.setAttribute("data-sort-order", cookies["sort-order"]);
|
|
}
|
|
|
|
this.sort(current, true);
|
|
}
|
|
}
|
|
|
|
// Clear
|
|
clear(current) {
|
|
// Cleanup all
|
|
for (const [id, button] of Object.entries(this.html_sort_buttons)) {
|
|
button.toggle();
|
|
button.inactive();
|
|
}
|
|
|
|
// Clear cookies
|
|
document.cookie = `sort-id=""; Path=/; SameSite=strict`;
|
|
document.cookie = `sort-order=""; Path=/; SameSite=strict`;
|
|
|
|
// Reset sorting
|
|
tinysort(current.dataset.sortTarget, {
|
|
selector: "div",
|
|
attr: "data-index",
|
|
order: "asc",
|
|
});
|
|
|
|
}
|
|
|
|
// Filter
|
|
filter() {
|
|
var filters = {};
|
|
|
|
// Check if there is a search filter
|
|
if (this.html_search && this.html_search.value != "") {
|
|
filters["search"] = this.html_search.value.toLowerCase();
|
|
}
|
|
|
|
// Check if there is a set filter
|
|
if (this.html_filter && this.html_filter.value != "") {
|
|
if (this.html_filter.value.startsWith("-")) {
|
|
filters["filter"] = this.html_filter.value.substring(1);
|
|
filters["filter-target"] = "0";
|
|
} else {
|
|
filters["filter"] = this.html_filter.value;
|
|
filters["filter-target"] = "1";
|
|
}
|
|
}
|
|
|
|
// Check if there is a theme filter
|
|
if (this.html_theme && this.html_theme.value != "") {
|
|
filters["theme"] = this.html_theme.value;
|
|
}
|
|
|
|
// Filter all cards
|
|
if (this.html_grid) {
|
|
const cards = this.html_grid.querySelectorAll("div > div.card");
|
|
cards.forEach(current => {
|
|
// Set filter
|
|
if ("filter" in filters) {
|
|
if (current.getAttribute("data-" + filters["filter"]) != filters["filter-target"]) {
|
|
current.parentElement.classList.add("d-none");
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Theme filter
|
|
if ("theme" in filters) {
|
|
if (current.getAttribute("data-theme") != filters["theme"]) {
|
|
current.parentElement.classList.add("d-none");
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Check all searchable fields for a match
|
|
if ("search" in filters) {
|
|
for (let attribute of ["data-name", "data-number", "data-parts", "data-theme", "data-year"]) {
|
|
if (current.getAttribute(attribute).includes(filters["search"])) {
|
|
current.parentElement.classList.remove("d-none");
|
|
return;
|
|
}
|
|
}
|
|
|
|
// If no match, we need to hide it
|
|
current.parentElement.classList.add("d-none");
|
|
return;
|
|
}
|
|
|
|
// If we passed all filters, we need to display it
|
|
current.parentElement.classList.remove("d-none");
|
|
})
|
|
}
|
|
}
|
|
|
|
// Sort
|
|
sort(current, no_flip=false) {
|
|
const target = current.data.sortTarget;
|
|
const attribute = current.data.sortAttribute;
|
|
const natural = current.data.sortNatural;
|
|
|
|
// Cleanup all
|
|
for (const [id, button] of Object.entries(this.html_sort_buttons)) {
|
|
if (button != current) {
|
|
button.toggle();
|
|
button.inactive();
|
|
}
|
|
}
|
|
|
|
// Sort
|
|
if (target && attribute) {
|
|
let order = current.data.sortOrder;
|
|
|
|
// First ordering
|
|
if (!no_flip) {
|
|
if(!order) {
|
|
if (current.data.sortDesc) {
|
|
order = "desc"
|
|
} else {
|
|
order = "asc"
|
|
}
|
|
} else {
|
|
// Flip the sorting order
|
|
order = (order == "desc") ? "asc" : "desc";
|
|
}
|
|
}
|
|
|
|
// Toggle the ordering
|
|
current.toggle(order);
|
|
|
|
// Store cookies
|
|
document.cookie = `sort-id="${encodeURIComponent(current.button.id)}"; Path=/; SameSite=strict`;
|
|
document.cookie = `sort-order="${encodeURIComponent(order)}"; Path=/; SameSite=strict`;
|
|
|
|
// Do the sorting
|
|
tinysort(target, {
|
|
selector: "div",
|
|
attr: "data-" + attribute,
|
|
natural: natural == "true",
|
|
order: order,
|
|
});
|
|
}
|
|
}
|
|
}
|