Files
openfoodnetwork/app/webpacker/controllers/popout_controller.js
David Cook 9bc1e873d3 Display summary of the popout values
I couldn't think of a simpler way to hardcode it, so now we have a clever generic method :)

We can assume that hidden elements will stay hidden, but we need to check each time if an element is disabled or not.
2023-11-28 10:44:34 +11:00

85 lines
2.4 KiB
JavaScript

import { Controller } from "stimulus";
// Allows a form section to "pop out" and show additional options
export default class PopoutController extends Controller {
static targets = ["button", "dialog"];
connect() {
this.first_input = this.dialogTarget.querySelector("input");
this.displayElements = Array.from(this.element.querySelectorAll('input:not([type="hidden"]'));
// Show when click or down-arrow on button
this.buttonTarget.addEventListener("click", this.show.bind(this));
this.buttonTarget.addEventListener("keydown", this.showIfDownArrow.bind(this));
// Close when click or tab outside of dialog. Run async (don't block primary event handlers).
this.closeIfOutsideBound = this.closeIfOutside.bind(this); // Store reference for removing listeners later.
document.addEventListener("click", this.closeIfOutsideBound, { passive: true });
document.addEventListener("focusin", this.closeIfOutsideBound, { passive: true });
}
disconnect() {
// Clean up handlers registered outside the controller element.
// (jest cleans up document too early)
if (document) {
document.removeEventListener("click", this.closeIfOutsideBound);
document.removeEventListener("focusin", this.closeIfOutsideBound);
}
}
show(e) {
this.dialogTarget.style.display = "block";
this.first_input.focus();
e.preventDefault();
}
showIfDownArrow(e) {
if (e.keyCode == 40) {
this.show(e);
}
}
close() {
// Close if not already closed
if (this.dialogTarget.style.display != "none") {
this.buttonTarget.innerText = this.#displayValue();
this.dialogTarget.style.display = "none";
}
}
closeIfOutside(e) {
if (!this.dialogTarget.contains(e.target)) {
this.close();
}
}
// Close if checked
closeIfChecked(e) {
if (e.target.checked) {
this.close();
this.buttonTarget.focus();
}
}
// private
// Summarise the active field(s)
#displayValue() {
let values = this.#enabledDisplayElements().map((element) => {
if (element.type == "checkbox") {
if (element.checked && element.labels[0]) {
return element.labels[0].innerText;
}
} else {
return element.value;
}
});
// Filter empty values and convert to string
return values.filter(Boolean).join();
}
#enabledDisplayElements() {
return this.displayElements.filter((element) => !element.disabled);
}
}