From bad59c66549eb601fed963ed013f9b79305ca003 Mon Sep 17 00:00:00 2001
From: Jake Vanderwerf <get@jakevanderwerf.ca>
Date: Wed, 07 Jan 2026 20:09:14 +0000
Subject: [PATCH] =Feedblock integrated with refactored taxonomy selector
---
assets/js/concise/TaxonomySelector.js | 94 ++++++++++++++++++++++++++++------------------
1 files changed, 57 insertions(+), 37 deletions(-)
diff --git a/assets/js/concise/TaxonomySelector.js b/assets/js/concise/TaxonomySelector.js
index 0565dee..1d84d93 100644
--- a/assets/js/concise/TaxonomySelector.js
+++ b/assets/js/concise/TaxonomySelector.js
@@ -1,3 +1,4 @@
+
class TaxonomySelector {
constructor() {
this.container = document.querySelector('dialog#jvb-selector');
@@ -67,7 +68,7 @@
initElements() {
this.selectors = {
search: {
- input: '[type=search]',
+ input: '[type="search"]',
clear: '.clear-search',
container: '.search-wrapper',
results: '.search-results',
@@ -99,7 +100,7 @@
},
favourites: '.favourite-terms',
field: {
- toggle: 'button.taxonomy-toggle',
+ toggle: 'button.taxonomy-toggle, [data-filter="taxonomy"]',
value: 'input[type="hidden"]',
selected: '.selected-items',
dropdown: {
@@ -147,18 +148,16 @@
}
handleClick(e) {
- const fieldId = (this.container.open) ? this.activeField : this.getFieldId(e.target);
+ const fieldId = this.getFieldId(e.target) || this.activeField;
const field = this.fields.get(fieldId);
if (!fieldId || !field) return;
- const autoComplete = window.targetCheck(e, '[data-autocomplete-select]');
+ const autoComplete = window.targetCheck(e, '.item.autocomplete');
+
if (autoComplete) {
let termId = parseInt(autoComplete.dataset.id);
this.addSelected(termId, fieldId);
- if (field.ui.dropdown.wrapper) {
- field.ui.dropdown.wrapper.hidden = true;
- }
-
+ this.scheduleHideDropdown(fieldId);
if (field.ui.search) {
field.ui.search.value = '';
}
@@ -244,7 +243,7 @@
if (!this.container.contains(e.target)) {
return;
}
- if (e.target.type !== 'checkbox') return;
+ if (!['checkbox', 'button'].includes(e.target.type)) return;
e.preventDefault();
e.stopPropagation();
@@ -262,7 +261,7 @@
if (!fieldId) return;
const field = this.fields.get(fieldId);
if (!field) return;
- if (e.target.type === 'checkbox') return;
+ if (['checkbox', 'button'].includes(e.target.type)) return;
e.preventDefault();
e.stopPropagation();
@@ -334,6 +333,7 @@
const field = this.fields.get(fieldId);
if (!fieldId || ! field) return;
if (!field.hasAutocomplete || this.container.open) return;
+ if (e.relatedTarget && field.ui.dropdown.wrapper?.contains(e.relatedTarget)) return;
this.scheduleHideDropdown(fieldId);
}
@@ -372,7 +372,9 @@
);
this.modal.subscribe((event, data) => {
switch (event) {
-
+ case 'modal-close':
+ this.closeModal()
+ break;
}
});
}
@@ -393,7 +395,7 @@
if (!field) return;
this.setField(fieldId);
- this.ui.modal.title.textContent = `Select ${field.plural}`;
+ this.ui.modal.title.textContent = (field.isFilter) ?`Filter by ${field.singular}` : `Select ${field.plural}`;
if (this.ui.search.container) {
this.ui.search.container.hidden = !field.canSearch;
}
@@ -402,6 +404,7 @@
}
let message = `Opened ${field.singular} selection. Choose from checkboxes, or search to filter results.`;
+ window.removeChildren(this.ui.selected);
window.removeChildren(this.ui.terms.list);
this.modal.handleOpen();
@@ -409,7 +412,6 @@
}
closeModal() {
- this.modal.handleClose();
const field = this.fields.get(this.activeField);
if (!field) return;
this.observer.unobserve(this.ui.terms.sentinel);
@@ -493,7 +495,7 @@
registerField(element, options = {}) {
let input = element.querySelector('input[type="hidden"]');
- if (!input) {
+ if (!input && !Object.hasOwn(element.dataset, 'filter')) {
console.warn('TaxonomySelector: No hidden input found for field', element);
return;
}
@@ -505,7 +507,8 @@
let selectors = this.selectors.field;
- let button = element.querySelector('button.taxonomy-toggle');
+ const isFilter = Object.hasOwn(element.dataset,'filter') && element.dataset.filter === 'taxonomy';
+ let button = (isFilter) ? element : element.querySelector('button.taxonomy-toggle');
if (Object.keys(options).length === 0){
if (!button) return;
@@ -536,6 +539,7 @@
hasAutocomplete: options.autocomplete??false,
canCreate: options.creatable??false,
isRequired: options.required??false,
+ isFilter: isFilter,
toggle: button,
create: {
button: null,
@@ -545,6 +549,10 @@
ui: window.uiFromSelectors(selectors, element),
checked: false,
};
+
+ if (isFilter && !config.ui.toggle) {
+ config.ui.toggle = element;
+ }
if (!config.taxonomy) {
console.error('TaxonomySelector: Field missing taxonomy', element);
return;
@@ -569,17 +577,19 @@
}
setSelectedFromValue(fieldId, input) {
- if (!input) return;
if (!fieldId) return;
let field = this.fields.get(fieldId);
if (!field) return;
+ if (!input && !field.isFilter) return;
let selected = new Set();
- input.value.trim()
- .split(',')
- .map(id => parseInt(id.trim()))
- .filter(id => !isNaN(id))
- .forEach(id => selected.add(id));
+ if (input) {
+ input.value.trim()
+ .split(',')
+ .map(id => parseInt(id.trim()))
+ .filter(id => !isNaN(id))
+ .forEach(id => selected.add(id));
+ }
this.selectedTerms.set(fieldId, selected);
}
@@ -594,7 +604,7 @@
if (field.limit !== 0 && selected.size >= field.limit) return;
selected.add(parseInt(termId));
- if (!this.container.open) {
+ if (!this.container.open && !field.isFilter) {
this.updateFieldValue(fieldId);
}
this.addTermToDisplay(termId, fieldId);
@@ -607,17 +617,17 @@
if (!field || !term) return;
this.selectedTerms.get(fieldId).delete(parseInt(termId));
- const selectedItem = field.ui.selected.querySelector(`[data-id="${termId}"]`);
+ const selectedItem = (field.ui.selected) ? field.ui.selected.querySelector(`[data-id="${termId}"]`) : false;
if (selectedItem) selectedItem.remove();
if (this.container.open) {
- let item = this.ui.selected.querySelector(`[data-id="${termId}"]`);
+ let item = (this.ui.selected) ? this.ui.selected.querySelector(`[data-id="${termId}"]`) : false;
if (item) item.remove();
let checkbox = this.ui.terms.list.querySelector(`[type=checkbox][data-id="${termId}"]`);
if (checkbox) {
checkbox.checked = false;
}
}
- if (!this.container.open) {
+ if (!this.container.open && !field.isFilter) {
this.updateFieldValue(fieldId);
}
@@ -633,7 +643,7 @@
checkLimits(fieldId) {
if (!this.container.open) return;
const field = this.fields.get(fieldId);
- if (!field || field.limit === 0) return;
+ if (!field || !field.isFilter || field.limit === 0) return;
const disabled = this.selectedTerms.get(fieldId).size >= field.limit;
this.setCheckboxes(disabled);
}
@@ -651,7 +661,7 @@
updateFieldUI(fieldId) {
const field = this.fields.get(fieldId);
let selected = this.selectedTerms.get(fieldId)??new Set();
- if (!field || selected.size === 0) return;
+ if (!field || field.isFilter || selected.size === 0) return;
Array.from(selected).forEach(termId => {
this.addTermToDisplay(termId, fieldId);
@@ -665,8 +675,8 @@
.some(term=>term.taxonomy === taxonomy);
fields.forEach(field => {
- field.ui.toggle.disabled = !hasItems && !field.canCreate;
- field.ui.toggle.title = !hasItems
+ field.toggle.disabled = !hasItems && !field.canCreate;
+ field.toggle.title = !hasItems
? `No ${field.singular} available`
: `Select ${field.plural}`;
@@ -690,6 +700,8 @@
}
}
+ this.setCreateButton(true);
+
if (this.ui.terms.sentinel) {
if (this.store.lastResponse?.has_more) {
this.observer.observe(this.ui.terms.sentinel);
@@ -712,7 +724,9 @@
}
});
- this.setMessage(false);
+ if (terms.length > 0) {
+ this.setMessage(false);
+ }
this.ui.terms.list.append(fragment);
}
@@ -793,7 +807,7 @@
}
this.setCreateButton(true);
- if (field.ui.dropdown?.wrapper) {
+ if (field.ui.dropdown.wrapper) {
field.ui.dropdown.wrapper.hidden = false;
}
}
@@ -803,6 +817,7 @@
item.dataset.id = term.id;
item.textContent = term.path || term.name;
+
return item;
}
/******************************************************************
@@ -813,7 +828,7 @@
const field = this.fields.get(fieldId);
if (!term || !field) return;
//if the term already exists in the selected items, bail early
- if (field.ui.selected.querySelector(`[data-id="${termId}"]`)) return;
+ if (field.ui.selected && field.ui.selected.querySelector(`[data-id="${termId}"]`)) return;
const item = window.getTemplate('selectedTerm');
if (!item) return;
@@ -823,7 +838,9 @@
item.querySelector('.item-name').textContent = term.path;
item.querySelector('button').title = `Remove ${term.name}`;
- field.ui.selected.append(item);
+ if (field.ui.selected) {
+ field.ui.selected.append(item);
+ }
if (this.container.open) {
this.addTermToModal(termId);
@@ -929,7 +946,9 @@
}
handleDataLoaded() {
const taxonomy = this.store.filters.taxonomy;
- if (taxonomy?.includes(',')) {
+
+ // Always update fields for loaded taxonomies (handles both single and batch)
+ if (taxonomy) {
const taxonomies = taxonomy.split(',').map(t => t.trim());
taxonomies.forEach(tax => this.updateFieldsForTaxonomy(tax));
}
@@ -1014,7 +1033,6 @@
if (!field || !field.canCreate || !this.creator) return;
const conf = (this.container.open) ? this.ui : field.ui;
-
if (!conf.create?.button || !conf.create?.span) return;
const createButton = conf.create.button;
@@ -1076,9 +1094,12 @@
setMessage(show = true, message = '', type = true) {
const field = this.currentField();
if (!field) return;
+
+ const conf = this.container.open||field.isFilter ? this.ui : (field.isFilter ? null : field.ui);
+ if (!conf?.message?.message) return;
+
message = (message === '') ? `No ${field.plural??'items'} found.` : message;
- const conf = (this.container.open) ? this.ui : field.ui;
const p = conf.message.message;
const pText = conf.message.text;
@@ -1176,4 +1197,3 @@
}
});
});
-
--
Gitblit v1.10.0