Semi working conditions for the new ui
This commit is contained in:
375
public/js/multiselect.js
Normal file
375
public/js/multiselect.js
Normal file
@@ -0,0 +1,375 @@
|
||||
/*
|
||||
* Created by David Adams
|
||||
* https://codeshack.io/multi-select-dropdown-html-javascript/
|
||||
*
|
||||
* Released under the MIT license
|
||||
*/
|
||||
class MultiSelect {
|
||||
|
||||
constructor(element, options = {}) {
|
||||
let defaults = {
|
||||
searchText: 'Search...',
|
||||
placeholder: 'Select item(s)',
|
||||
max: null,
|
||||
min: null,
|
||||
disabled: false,
|
||||
search: true,
|
||||
selectAll: true,
|
||||
listAll: true,
|
||||
closeListOnItemSelect: false,
|
||||
name: '',
|
||||
width: '',
|
||||
height: '',
|
||||
dropdownWidth: '',
|
||||
dropdownHeight: '',
|
||||
data: [],
|
||||
onChange: function() {},
|
||||
onSelect: function() {},
|
||||
onUnselect: function() {},
|
||||
onMaxReached: function() {}
|
||||
};
|
||||
this.options = Object.assign(defaults, options);
|
||||
this.selectElement = typeof element === 'string' ? document.querySelector(element) : element;
|
||||
this.originalSelectElement = this.selectElement.cloneNode(true);
|
||||
for(const prop in this.selectElement.dataset) {
|
||||
if (this.options[prop] !== undefined) {
|
||||
if (typeof this.options[prop] === 'boolean') {
|
||||
this.options[prop] = this.selectElement.dataset[prop] === 'true';
|
||||
} else {
|
||||
this.options[prop] = this.selectElement.dataset[prop];
|
||||
}
|
||||
}
|
||||
}
|
||||
this.name = this.selectElement.getAttribute('name') ? this.selectElement.getAttribute('name') : 'multi-select-' + Math.floor(Math.random() * 1000000);
|
||||
if (!this.options.data.length) {
|
||||
let options = this.selectElement.querySelectorAll('option');
|
||||
for (let i = 0; i < options.length; i++) {
|
||||
this.options.data.push({
|
||||
value: options[i].value,
|
||||
text: options[i].innerHTML,
|
||||
selected: options[i].selected,
|
||||
html: options[i].getAttribute('data-html')
|
||||
});
|
||||
}
|
||||
}
|
||||
this.originalData = JSON.parse(JSON.stringify(this.options.data));
|
||||
this.element = this._template();
|
||||
this.selectElement.replaceWith(this.element);
|
||||
this.outsideClickHandler = this._outsideClick.bind(this);
|
||||
this._updateSelected();
|
||||
this._eventHandlers();
|
||||
if (this.options.disabled) {
|
||||
this.disable();
|
||||
}
|
||||
}
|
||||
|
||||
_template() {
|
||||
let optionsHTML = '';
|
||||
for (let i = 0; i < this.data.length; i++) {
|
||||
const isSelected = this.data[i].selected;
|
||||
optionsHTML += `
|
||||
<div class="multi-select-option${isSelected ? ' multi-select-selected' : ''}" data-value="${this.data[i].value}" role="option" aria-selected="${isSelected}" tabindex="-1">
|
||||
<span class="multi-select-option-radio"></span>
|
||||
<span class="multi-select-option-text">${this.data[i].html ? this.data[i].html : this.data[i].text}</span>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
let selectAllHTML = '';
|
||||
if (this.options.selectAll) {
|
||||
selectAllHTML = `<div class="multi-select-all" role="option" tabindex="-1">
|
||||
<span class="multi-select-option-radio"></span>
|
||||
<span class="multi-select-option-text">Select all</span>
|
||||
</div>`;
|
||||
}
|
||||
let template = `
|
||||
<div class="multi-select ${this.name}"${this.selectElement.id ? ' id="' + this.selectElement.id + '"' : ''} style="${this.width ? 'width:' + this.width + ';' : ''}${this.height ? 'height:' + this.height + ';' : ''}" role="combobox" aria-haspopup="listbox" aria-expanded="false">
|
||||
${this.selectedValues.map(value => `<input type="hidden" name="${this.name}[]" value="${value}">`).join('')}
|
||||
<div class="multi-select-header" style="${this.width ? 'width:' + this.width + ';' : ''}${this.height ? 'height:' + this.height + ';' : ''}" tabindex="0">
|
||||
<span class="multi-select-header-max">${this.options.max ? this.selectedValues.length + '/' + this.options.max : ''}</span>
|
||||
<span class="multi-select-header-placeholder">${this.placeholder}</span>
|
||||
</div>
|
||||
<div class="multi-select-options" style="${this.options.dropdownWidth ? 'width:' + this.options.dropdownWidth + ';' : ''}${this.options.dropdownHeight ? 'height:' + this.options.dropdownHeight + ';' : ''}" role="listbox">
|
||||
${this.options.search ? '<input type="text" class="multi-select-search" placeholder="' + this.searchText + '" role="searchbox">' : ''}
|
||||
${selectAllHTML}
|
||||
${optionsHTML}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
let element = document.createElement('div');
|
||||
element.innerHTML = template;
|
||||
return element.firstElementChild;
|
||||
}
|
||||
|
||||
_eventHandlers() {
|
||||
let headerElement = this.element.querySelector('.multi-select-header');
|
||||
const toggleDropdown = (forceClose = false) => {
|
||||
if (this.element.classList.contains('disabled')) return;
|
||||
if (forceClose || headerElement.classList.contains('multi-select-header-active')) {
|
||||
headerElement.classList.remove('multi-select-header-active');
|
||||
this.element.setAttribute('aria-expanded', 'false');
|
||||
} else {
|
||||
headerElement.classList.add('multi-select-header-active');
|
||||
this.element.setAttribute('aria-expanded', 'true');
|
||||
}
|
||||
};
|
||||
this.element.querySelectorAll('.multi-select-option').forEach(option => {
|
||||
option.onclick = (e) => {
|
||||
e.stopPropagation();
|
||||
if (this.element.classList.contains('disabled')) return;
|
||||
let selected = true;
|
||||
if (!option.classList.contains('multi-select-selected')) {
|
||||
if (this.options.max && this.selectedValues.length >= this.options.max) {
|
||||
this.options.onMaxReached(this.options.max);
|
||||
return;
|
||||
}
|
||||
option.classList.add('multi-select-selected');
|
||||
option.setAttribute('aria-selected', 'true');
|
||||
this.element.insertAdjacentHTML('afterbegin', `<input type="hidden" name="${this.name}[]" value="${option.dataset.value}">`);
|
||||
this.data.find(data => data.value == option.dataset.value).selected = true;
|
||||
} else {
|
||||
option.classList.remove('multi-select-selected');
|
||||
option.setAttribute('aria-selected', 'false');
|
||||
this.element.querySelector(`input[value="${option.dataset.value}"]`).remove();
|
||||
this.data.find(data => data.value == option.dataset.value).selected = false;
|
||||
selected = false;
|
||||
}
|
||||
this._updateHeader();
|
||||
if (this.options.search) {
|
||||
this.element.querySelector('.multi-select-search').value = '';
|
||||
this.element.querySelectorAll('.multi-select-option').forEach(opt => opt.style.display = 'flex');
|
||||
}
|
||||
if (this.options.closeListOnItemSelect) {
|
||||
toggleDropdown(true);
|
||||
}
|
||||
this.options.onChange(option.dataset.value, option.querySelector('.multi-select-option-text').innerHTML, option);
|
||||
if (selected) {
|
||||
this.options.onSelect(option.dataset.value, option.querySelector('.multi-select-option-text').innerHTML, option);
|
||||
} else {
|
||||
this.options.onUnselect(option.dataset.value, option.querySelector('.multi-select-option-text').innerHTML, option);
|
||||
}
|
||||
this._validate();
|
||||
};
|
||||
});
|
||||
headerElement.onclick = () => toggleDropdown();
|
||||
if (this.options.search) {
|
||||
let search = this.element.querySelector('.multi-select-search');
|
||||
search.oninput = () => {
|
||||
this.element.querySelectorAll('.multi-select-option').forEach(option => {
|
||||
const text = option.querySelector('.multi-select-option-text').innerHTML.toLowerCase();
|
||||
option.style.display = text.includes(search.value.toLowerCase()) ? 'flex' : 'none';
|
||||
});
|
||||
};
|
||||
}
|
||||
if (this.options.selectAll) {
|
||||
let selectAllButton = this.element.querySelector('.multi-select-all');
|
||||
selectAllButton.onclick = (e) => {
|
||||
e.stopPropagation();
|
||||
if (this.element.classList.contains('disabled')) return;
|
||||
let allSelected = selectAllButton.classList.contains('multi-select-selected');
|
||||
this.element.querySelectorAll('.multi-select-option').forEach(option => {
|
||||
let dataItem = this.data.find(data => data.value == option.dataset.value);
|
||||
if (dataItem && ((allSelected && dataItem.selected) || (!allSelected && !dataItem.selected))) {
|
||||
option.click();
|
||||
}
|
||||
});
|
||||
selectAllButton.classList.toggle('multi-select-selected');
|
||||
};
|
||||
}
|
||||
if (this.selectElement.id && document.querySelector('label[for="' + this.selectElement.id + '"]')) {
|
||||
document.querySelector('label[for="' + this.selectElement.id + '"]').onclick = () => {
|
||||
toggleDropdown();
|
||||
};
|
||||
}
|
||||
document.addEventListener('click', this.outsideClickHandler);
|
||||
headerElement.addEventListener('keydown', (e) => {
|
||||
if (['Enter', ' ', 'ArrowDown', 'ArrowUp'].includes(e.key)) {
|
||||
e.preventDefault();
|
||||
toggleDropdown();
|
||||
const firstElement = this.element.querySelector('[role="searchbox"]') || this.element.querySelector('[role="option"]');
|
||||
if (firstElement) firstElement.focus();
|
||||
}
|
||||
});
|
||||
this.element.addEventListener('keydown', (e) => {
|
||||
if (e.key === 'Escape') {
|
||||
toggleDropdown(true);
|
||||
headerElement.focus();
|
||||
}
|
||||
});
|
||||
const optionsContainer = this.element.querySelector('.multi-select-options');
|
||||
optionsContainer.addEventListener('keydown', (e) => {
|
||||
const currentFocused = document.activeElement;
|
||||
if (currentFocused.closest('.multi-select-options')) {
|
||||
if (['ArrowDown', 'ArrowUp'].includes(e.key)) {
|
||||
e.preventDefault();
|
||||
const direction = e.key === 'ArrowDown' ? 'nextElementSibling' : 'previousElementSibling';
|
||||
let nextElement = currentFocused[direction];
|
||||
while (nextElement && (nextElement.style.display === 'none' || !nextElement.matches('[role="option"], [role="searchbox"]'))) {
|
||||
nextElement = nextElement[direction];
|
||||
}
|
||||
if (nextElement) nextElement.focus();
|
||||
} else if (['Enter', ' '].includes(e.key) && currentFocused.matches('[role="option"]')) {
|
||||
e.preventDefault();
|
||||
currentFocused.click();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
_updateHeader() {
|
||||
this.element.querySelectorAll('.multi-select-header-option, .multi-select-header-placeholder').forEach(el => el.remove());
|
||||
if (this.selectedValues.length > 0) {
|
||||
if (this.options.listAll) {
|
||||
this.selectedItems.forEach(item => {
|
||||
const el = document.createElement('span');
|
||||
el.className = 'multi-select-header-option';
|
||||
el.dataset.value = item.value;
|
||||
el.innerHTML = item.text;
|
||||
this.element.querySelector('.multi-select-header').prepend(el);
|
||||
});
|
||||
} else {
|
||||
this.element.querySelector('.multi-select-header').insertAdjacentHTML('afterbegin', `<span class="multi-select-header-option">${this.selectedValues.length} selected</span>`);
|
||||
}
|
||||
} else {
|
||||
this.element.querySelector('.multi-select-header').insertAdjacentHTML('beforeend', `<span class="multi-select-header-placeholder">${this.placeholder}</span>`);
|
||||
}
|
||||
if (this.options.max) {
|
||||
this.element.querySelector('.multi-select-header-max').innerHTML = this.selectedValues.length + '/' + this.options.max;
|
||||
}
|
||||
}
|
||||
|
||||
_updateSelected() { this._updateHeader(); }
|
||||
|
||||
_validate() {
|
||||
if (this.options.min && this.selectedValues.length < this.options.min) {
|
||||
this.element.classList.add('multi-select-invalid');
|
||||
} else {
|
||||
this.element.classList.remove('multi-select-invalid');
|
||||
}
|
||||
}
|
||||
|
||||
_outsideClick(event) {
|
||||
if (!this.element.contains(event.target) && !event.target.closest('label[for="' + this.selectElement.id + '"]')) {
|
||||
let headerElement = this.element.querySelector('.multi-select-header');
|
||||
if (headerElement.classList.contains('multi-select-header-active')) {
|
||||
headerElement.classList.remove('multi-select-header-active');
|
||||
this.element.setAttribute('aria-expanded', 'false');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
select(value) {
|
||||
const option = this.element.querySelector(`.multi-select-option[data-value="${value}"]`);
|
||||
if (option && !option.classList.contains('multi-select-selected')) {
|
||||
option.click();
|
||||
}
|
||||
}
|
||||
|
||||
unselect(value) {
|
||||
const option = this.element.querySelector(`.multi-select-option[data-value="${value}"]`);
|
||||
if (option && option.classList.contains('multi-select-selected')) {
|
||||
option.click();
|
||||
}
|
||||
}
|
||||
|
||||
setValues(values) {
|
||||
this.data.forEach(item => {
|
||||
item.selected = values.includes(item.value);
|
||||
});
|
||||
this.refresh();
|
||||
}
|
||||
|
||||
disable() {
|
||||
this.element.classList.add('disabled');
|
||||
this.element.querySelector('.multi-select-header').removeAttribute('tabindex');
|
||||
const searchInput = this.element.querySelector('.multi-select-search');
|
||||
if (searchInput) searchInput.disabled = true;
|
||||
}
|
||||
|
||||
enable() {
|
||||
this.element.classList.remove('disabled');
|
||||
this.element.querySelector('.multi-select-header').setAttribute('tabindex', '0');
|
||||
const searchInput = this.element.querySelector('.multi-select-search');
|
||||
if (searchInput) searchInput.disabled = false;
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this.element.replaceWith(this.originalSelectElement);
|
||||
document.removeEventListener('click', this.outsideClickHandler);
|
||||
}
|
||||
|
||||
refresh() {
|
||||
const newElement = this._template();
|
||||
this.element.replaceWith(newElement);
|
||||
this.element = newElement;
|
||||
this._updateSelected();
|
||||
this._eventHandlers();
|
||||
this._validate();
|
||||
}
|
||||
|
||||
addItem(item) {
|
||||
this.options.data.push(item);
|
||||
this.refresh();
|
||||
}
|
||||
|
||||
addItems(items) {
|
||||
this.options.data.push(...items);
|
||||
this.refresh();
|
||||
}
|
||||
|
||||
async fetch(url, options = {}) {
|
||||
const response = await fetch(url, options);
|
||||
const data = await response.json();
|
||||
this.addItems(data);
|
||||
if (this.options.onload) {
|
||||
this.options.onload(data, this.options);
|
||||
}
|
||||
}
|
||||
|
||||
removeItem(value) {
|
||||
this.options.data = this.options.data.filter(item => item.value !== value);
|
||||
this.refresh();
|
||||
}
|
||||
|
||||
clear() {
|
||||
this.options.data = [];
|
||||
this.refresh();
|
||||
}
|
||||
|
||||
reset() {
|
||||
this.data = JSON.parse(JSON.stringify(this.originalData));
|
||||
this.refresh();
|
||||
}
|
||||
|
||||
selectAll() {
|
||||
this.data.forEach(item => item.selected = true);
|
||||
this.refresh();
|
||||
}
|
||||
|
||||
get selectedValues() { return this.data.filter(d => d.selected).map(d => d.value); }
|
||||
get selectedItems() { return this.data.filter(d => d.selected); }
|
||||
get data() { return this.options.data; }
|
||||
set data(value) { this.options.data = value; }
|
||||
|
||||
set selectElement(value) { this.options.selectElement = value; }
|
||||
get selectElement() { return this.options.selectElement; }
|
||||
|
||||
set element(value) { this.options.element = value; }
|
||||
get element() { return this.options.element; }
|
||||
|
||||
set searchText(value) { this.options.searchText = value; }
|
||||
get searchText() { return this.options.searchText; }
|
||||
|
||||
set placeholder(value) { this.options.placeholder = value; }
|
||||
get placeholder() { return this.options.placeholder; }
|
||||
|
||||
set name(value) { this.options.name = value; }
|
||||
get name() { return this.options.name; }
|
||||
|
||||
set width(value) { this.options.width = value; }
|
||||
get width() { return this.options.width; }
|
||||
|
||||
set height(value) { this.options.height = value; }
|
||||
get height() { return this.options.height; }
|
||||
|
||||
}
|
||||
document.querySelectorAll('[data-multi-select]').forEach(select => new MultiSelect(select));
|
||||
@@ -1,54 +1,67 @@
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
// ---------- DOM Elements ----------
|
||||
const shell = document.getElementById("shell");
|
||||
const topbar = document.getElementById("topbar");
|
||||
const shell = document.getElementById("pexpo-core-shell");
|
||||
const topbar = document.getElementById("pexpo-core-topbar");
|
||||
|
||||
const filterWrap = document.getElementById("filterWrap");
|
||||
const filterBtn = document.getElementById("filterBtn");
|
||||
const filterDrawer = document.getElementById("filterDrawer");
|
||||
const drawerBackdrop = document.getElementById("drawerBackdrop");
|
||||
const filterWrap = document.getElementById("pexpo-core-filterWrap");
|
||||
const filterBtn = document.getElementById("pexpo-core-filterBtn");
|
||||
const filterDrawer = document.getElementById("pexpo-core-filterDrawer");
|
||||
const drawerBackdrop = document.getElementById("pexpo-core-drawerBackdrop");
|
||||
|
||||
const filterJson = document.getElementById("filterJson");
|
||||
const jsonError = document.getElementById("jsonError");
|
||||
const filterLabel = document.getElementById("filterLabel");
|
||||
// const filterBody = document.getElementById("pexpo-core-filterBody");
|
||||
// const filterLabel = document.getElementById("pexpo-core-filterLabel");
|
||||
const filterFTag = document.getElementById("pexpo-core-tag-toggle");
|
||||
const filterTags = document.getElementById("pexpo-core-tags");
|
||||
|
||||
const qInput = document.getElementById("q");
|
||||
const masonry = document.getElementById("masonry");
|
||||
const measure = document.getElementById("measure");
|
||||
const qInput = document.getElementById("pexpo-core-q");
|
||||
const masonry = document.getElementById("pexpo-core-masonry");
|
||||
const measure = document.getElementById("pexpo-core-measure");
|
||||
|
||||
const count = document.getElementById("count");
|
||||
const layoutMeta = document.getElementById("layoutMeta");
|
||||
const sortSelect = document.getElementById("sortSelect");
|
||||
const count = document.getElementById("pexpo-core-count");
|
||||
const layoutMeta = document.getElementById("pexpo-core-layoutMeta");
|
||||
const sortSelect = document.getElementById("pexpo-core-sortSelect");
|
||||
|
||||
// ---------- State ----------
|
||||
let filters = {
|
||||
q: "",
|
||||
sort: "relevance",
|
||||
status: ["active", "archived"],
|
||||
tags: ["ui", "mock"],
|
||||
maxResults: 20
|
||||
force_tags: false,
|
||||
tags: [],
|
||||
resultsPerPage: 20,
|
||||
page: 1,
|
||||
};
|
||||
|
||||
let activeSortKey = "relevance";
|
||||
let results = []; // Fills via Ajax
|
||||
let results = [];
|
||||
|
||||
// ---------- Sort Definitions ---------- LEFTOVER FROM TESTING REMOVE IN PROD
|
||||
// ---------- Initialize MultiSelect Library ----------
|
||||
if (typeof MultiSelect !== 'undefined') {
|
||||
new MultiSelect(filterTags, {
|
||||
// max: 20,
|
||||
search: true,
|
||||
selectAll: false,
|
||||
onSelect: function(value) {
|
||||
if (!filters.tags.includes(value)) {
|
||||
filters.tags.push(value);
|
||||
}
|
||||
console.log('Updated filters.tags:', filters.tags);
|
||||
},
|
||||
onUnselect: function(value) {
|
||||
filters.tags = filters.tags.filter(tag => tag !== value);
|
||||
console.log('Updated filters.tags:', filters.tags);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
console.warn("MultiSelect library not found. Filters will not work without it.");
|
||||
}
|
||||
|
||||
// ---------- Sort Definitions ----------
|
||||
const SORTS = {
|
||||
relevance: {
|
||||
label: "Relevance",
|
||||
compare: (a, b) => (b.relevance - a.relevance) || (b.score - a.score)
|
||||
},
|
||||
score_desc: {
|
||||
label: "Score (high → low)",
|
||||
compare: (a, b) => (b.score - a.score)
|
||||
},
|
||||
date_desc: {
|
||||
label: "Date (new → old)",
|
||||
compare: (a, b) => new Date(b.updated) - new Date(a.updated)
|
||||
},
|
||||
title_asc: {
|
||||
label: "Title (A → Z)",
|
||||
compare: (a, b) => (a.title || "").localeCompare(b.title || "")
|
||||
}
|
||||
relevance: "Relevánsság (legjobb → legrosszabb)",
|
||||
date_desc: "Dátum (új → régi)",
|
||||
date_asc: "Dátum (régi → új)",
|
||||
title_asc: "Cím (A → Z)",
|
||||
title_desc: "Cím (Z → A)",
|
||||
};
|
||||
|
||||
// ---------- Helpers ----------
|
||||
@@ -58,6 +71,13 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
}[s]));
|
||||
}
|
||||
|
||||
function encodeDataToURL(data) {
|
||||
return Object
|
||||
.keys(data)
|
||||
.map(value => `${value}=${encodeURIComponent(data[value])}`)
|
||||
.join('&');
|
||||
}
|
||||
|
||||
function cardEl(r) {
|
||||
const div = document.createElement("div");
|
||||
div.className = "pexpo-core-card";
|
||||
@@ -86,12 +106,12 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
}
|
||||
|
||||
// ---------- Ajax Function ----------
|
||||
async function fetchData(query = "") {
|
||||
async function fetchData() {
|
||||
// 1. Show loading state if needed
|
||||
masonry.style.opacity = "0.5";
|
||||
|
||||
try {
|
||||
const response = await fetch(`/wp-json/pexpo/v1/query?q=${encodeURIComponent(query)}&limit=${filters.maxResults}`);
|
||||
const response = await fetch(`/wp-json/pexpo/v1/query?${encodeDataToURL(filters)}`);
|
||||
const data = await response.json();
|
||||
|
||||
results = data;
|
||||
@@ -106,21 +126,6 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
}
|
||||
}
|
||||
|
||||
// FOR TESTING ONLY REMOVE IN PROD
|
||||
// function computeLocalRelevance(query) {
|
||||
// if (!query) {
|
||||
// results.forEach(r => r.relevance = r.score);
|
||||
// return;
|
||||
// }
|
||||
// const q = query.toLowerCase();
|
||||
// results.forEach(r => {
|
||||
// let hits = 0;
|
||||
// if (r.title.toLowerCase().includes(q)) hits += 50;
|
||||
// if (r.desc.toLowerCase().includes(q)) hits += 20;
|
||||
// r.relevance = hits + r.score;
|
||||
// });
|
||||
// }
|
||||
|
||||
// ---------- Layout & Masonry Logic ----------
|
||||
const minCard = () => Number(getComputedStyle(document.documentElement).getPropertyValue("--cardMin")) || 240;
|
||||
const gap = () => Number(getComputedStyle(document.documentElement).getPropertyValue("--gap")) || 12;
|
||||
@@ -215,7 +220,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
colEls[p.col].appendChild(cardEl(p.item.r));
|
||||
}
|
||||
|
||||
layoutMeta.textContent = `${cols} cols • ${SORTS[activeSortKey]?.label || "Relevance"}`;
|
||||
// layoutMeta.textContent = `${cols} oszlop • ${SORTS[activeSortKey]?.label || "Relevance"}`;
|
||||
}
|
||||
|
||||
// ---------- UI Events ----------
|
||||
@@ -223,22 +228,35 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
// Sort Dropdown
|
||||
if (sortSelect) {
|
||||
sortSelect.innerHTML = Object.entries(SORTS)
|
||||
.map(([k, def]) => `<option value="${escapeHtml(k)}">${escapeHtml(def.label)}</option>`)
|
||||
.map(([k, label]) => `<option value="${escapeHtml(k)}">${escapeHtml(label)}</option>`)
|
||||
.join("");
|
||||
sortSelect.value = activeSortKey;
|
||||
sortSelect.addEventListener("change", () => {
|
||||
activeSortKey = sortSelect.value;
|
||||
requestLayout();
|
||||
filters.sort = activeSortKey;
|
||||
fetchData();
|
||||
});
|
||||
}
|
||||
|
||||
// Search
|
||||
qInput.addEventListener("keydown", (e) => {
|
||||
if (e.key === "Enter") {
|
||||
fetchData(qInput.value.trim());
|
||||
filters.q = qInput.value.trim();
|
||||
fetchData();
|
||||
}
|
||||
});
|
||||
|
||||
// Tag Toggle
|
||||
filterFTag.addEventListener("change", () => {
|
||||
filters.force_tags = filterFTag.checked;
|
||||
});
|
||||
|
||||
// Tags multiselect
|
||||
filterTags.addEventListener("change", (value, text, element) => {
|
||||
console.log('Change:', value, text, element);
|
||||
});
|
||||
|
||||
|
||||
// Filter Drawer Logic
|
||||
function syncTopbarHeight() {
|
||||
const h = topbar.offsetHeight;
|
||||
@@ -256,7 +274,6 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
shell.classList.toggle("pexpo-core-drawerOpen", open);
|
||||
|
||||
syncTopbarHeight();
|
||||
if (open) filterJson.focus();
|
||||
}
|
||||
|
||||
filterBtn.addEventListener("click", () => setOpen(!filterDrawer.classList.contains("pexpo-core-open")));
|
||||
@@ -265,30 +282,31 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
if (e.key === "Escape" && filterDrawer.classList.contains("pexpo-core-open")) setOpen(false);
|
||||
});
|
||||
|
||||
// Apply JSON Filter
|
||||
function applyJson() {
|
||||
try {
|
||||
const parsed = JSON.parse(filterJson.value);
|
||||
jsonError.classList.remove("pexpo-core-show");
|
||||
filters = parsed;
|
||||
filterLabel.textContent = (filters.category || "Custom");
|
||||
// // Apply JSON Filter
|
||||
// function applyJson() {
|
||||
// try {
|
||||
// const parsed = JSON.parse(filterJson.value);
|
||||
// jsonError.classList.remove("pexpo-core-show");
|
||||
// filters = parsed;
|
||||
// filterLabel.textContent = (filters.category || "Custom");
|
||||
|
||||
// Trigger new search with new filters
|
||||
fetchData(qInput.value.trim());
|
||||
// // Trigger new search with new filters
|
||||
// filters.q = qInput.value.trim();
|
||||
// fetchData();
|
||||
|
||||
// Close drawer on success (optional)
|
||||
// setOpen(false);
|
||||
} catch (err) {
|
||||
jsonError.classList.add("pexpo-core-show");
|
||||
}
|
||||
}
|
||||
// // Close drawer on success (optional)
|
||||
// // setOpen(false);
|
||||
// } catch (err) {
|
||||
// jsonError.classList.add("pexpo-core-show");
|
||||
// }
|
||||
// }
|
||||
|
||||
filterJson.addEventListener("keydown", (e) => {
|
||||
if (e.key === 'Enter' && (e.ctrlKey || e.metaKey)) {
|
||||
e.preventDefault();
|
||||
applyJson();
|
||||
}
|
||||
});
|
||||
// filterJson.addEventListener("keydown", (e) => {
|
||||
// if (e.key === 'Enter' && (e.ctrlKey || e.metaKey)) {
|
||||
// e.preventDefault();
|
||||
// applyJson();
|
||||
// }
|
||||
// });
|
||||
|
||||
// Resize Observer
|
||||
const ro = new ResizeObserver(() => {
|
||||
@@ -299,8 +317,9 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
ro.observe(masonry);
|
||||
|
||||
// Initial Load
|
||||
initFilters();
|
||||
syncTopbarHeight();
|
||||
fetchData("");
|
||||
fetchData();
|
||||
|
||||
// --- Temporary Mock Response Generator (DELETE ME IN PRODUCTION) ---
|
||||
function simulateBackendResponse(q) {
|
||||
|
||||
Reference in New Issue
Block a user