1export function filterMenuInit() { 2 initClearButton() 3 changeIconOnOpen() 4 addTagStyling() 5 syncSelectedTagChips() 6} 7 8function initClearButton() { 9 const form = document.querySelector(".filter-form") 10 if (!form) return 11 const clearButton = form.querySelector(".button-filter-clear") 12 if (!clearButton) return 13 14 clearButton.addEventListener('click', () => { 15 const checkboxes = form.querySelectorAll('input[type="checkbox"]:not(.hidden)'); 16 17 checkboxes.forEach(checkbox => { 18 checkbox.checked = false; 19 }); 20 }) 21} 22 23function changeIconOnOpen() { 24 const form = document.querySelector(".filter-form") 25 if (!form) return 26 const filterToggle = form.querySelector("#filter-toggle") 27 if (!filterToggle) return 28 29 if (filterToggle.checked) { 30 form.querySelector(".filter-closed").classList.add("hidden") 31 form.querySelector(".filter-open").classList.remove("hidden") 32 } else { 33 form.querySelector(".filter-closed").classList.remove("hidden") 34 form.querySelector(".filter-open").classList.add("hidden") 35 } 36 37 filterToggle.addEventListener("change", () => { 38 if (filterToggle.checked) { 39 form.querySelector(".filter-closed").classList.add("hidden") 40 form.querySelector(".filter-open").classList.remove("hidden") 41 } else { 42 form.querySelector(".filter-closed").classList.remove("hidden") 43 form.querySelector(".filter-open").classList.add("hidden") 44 } 45 }) 46} 47 48function addTagStyling() { 49 const form = document.querySelector(".filter-form") 50 if (!form) return 51 52 const labelsToStyle = form.querySelectorAll(".label-tag") 53 54 function updateLabelClasses() { 55 labelsToStyle.forEach(label => { 56 const attrValue = label.getAttribute('for'); 57 const checkbox = form.querySelector(`input[type="checkbox"][id="${attrValue}"]`); 58 59 // selected = filled, unselected = outlined (same as the deployed site) 60 if (checkbox && checkbox.checked) { 61 label.classList.add("bg-colored-80"); 62 label.classList.add("border-transparent"); 63 label.classList.remove("border-black"); 64 } else { 65 label.classList.remove("bg-colored-80"); 66 label.classList.remove("border-transparent"); 67 label.classList.add("border-black"); 68 } 69 }); 70 } 71 72 form.querySelectorAll('input[type="checkbox"]:not(.hidden)').forEach(checkbox => { 73 checkbox.addEventListener('change', updateLabelClasses); 74 }); 75 76 updateLabelClasses(); 77 78} 79 80// selected tags â removable chips under the tag row; the tags[] checkboxes remain the source of truth 81function syncSelectedTagChips() { 82 const form = document.querySelector(".filter-form") 83 if (!form) return 84 const strip = form.querySelector(".filter-selected-tags") 85 if (!strip) return 86 const template = strip.querySelector(".filter-tag-chip-template") 87 if (!template) return 88 89 const clearAll = strip.querySelector(".filter-selected-tags-clear") 90 const status = form.querySelector(".filter-selected-tags-status") 91 const tagInputs = () => form.querySelectorAll('input[type="checkbox"][name="tags[]"]') 92 93 function announce(message) { 94 if (!status) return 95 status.textContent = "" 96 // re-set after a tick so identical consecutive messages are still announced 97 setTimeout(() => { status.textContent = message }, 50) 98 } 99 100 // after a chip is removed its button is gone; move focus to the neighbouring chip, 101 // then the clear button, and finally the visible submit button when the strip hides 102 function focusAfterRemoval(index) { 103 const chips = strip.querySelectorAll(".filter-tag-chip") 104 const next = chips[index] || chips[chips.length - 1] 105 if (next) return next.focus() 106 const submit = Array.from(form.querySelectorAll('button[type="submit"]')).find(button => button.offsetParent !== null) 107 if (submit) submit.focus() 108 } 109 110 function render() {
111 strip.querySelectorAll(".filter-tag-chip").forEach(chip => chip.remove()) 112 113 const checked = Array.from(tagInputs()).filter(input => input.checked) 114 checked.forEach((input, index) => { 115 const chip = template.content.firstElementChild.cloneNode(true) 116 chip.dataset.tag = input.value 117 chip.setAttribute("aria-label", `ÐÑибÑаÑи ÑÐµÐ¼Ñ ${input.value}`) 118 chip.querySelector(".filter-tag-chip-name").textContent = input.value 119 chip.addEventListener("click", () => { 120 uncheck([input]) 121 announce(`Ð¢ÐµÐ¼Ñ Â«${input.value}» пÑибÑано`) 122 focusAfterRemoval(index) 123 }) 124 // chips go before the "СкинÑÑи вÑе" button, in checkbox order 125 strip.insertBefore(chip, clearAll || template) 126 }) 127 128 strip.classList.toggle("hidden", checked.length === 0) 129 strip.classList.toggle("flex", checked.length > 0) 130 // desktop: the chips take the place of the two quick-pick tags, and the tag area gets a fixed width so the trigger stays put 131 form.querySelectorAll(".label-tag").forEach(label => label.classList.toggle("md:block", checked.length === 0)) 132 const area = form.querySelector(".filter-tags-area") 133 if (area) area.classList.toggle("md:w-xl", checked.length > 0) 134 } 135 136 function uncheck(inputs) { 137 inputs.forEach(input => { 138 input.checked = false 139 // notify addTagStyling() so the quick-pick label drops its selected border 140 input.dispatchEvent(new Event("change", { bubbles: true })) 141 }) 142 render() 143 } 144 145 tagInputs().forEach(input => input.addEventListener("change", render)) 146 147 if (clearAll) clearAll.addEventListener("click", () => { 148 uncheck(Array.from(tagInputs())) 149 announce("УÑÑ Ð¾Ð±ÑÐ°Ð½Ñ Ñеми ÑкинÑÑо") 150 focusAfterRemoval(0) 151 }) 152 153 // mobile "СкинÑÑи" unchecks everything without firing change events 154 const clearButton = form.querySelector(".button-filter-clear") 155 if (clearButton) clearButton.addEventListener("click", render) 156 157 render() 158}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.