1// Dedicated search form interactions (chips, accordions, select-all) extracted 2jQuery(document).ready(function ($) { 3 // Accordion toggle for new seminar form blocks 4 function bindAccordion(prefix) { 5 $(`#${prefix}-advanced-search-settings-container .elementor-tab-title`).on('click', function (e) { 6 e.preventDefault(); 7 const title = $(this); 8 const content = title.parent().find('.elementor-tab-content'); 9 const expanded = title.attr('aria-expanded') === 'true'; 10 title.attr('aria-expanded', !expanded); 11 if (expanded) { 12 content.slideUp(150).attr('hidden', 'hidden'); 13 } else { 14 content.slideDown(150).removeAttr('hidden'); 15 } 16 }); 17 } 18 19 bindAccordion('seminars'); 20 bindAccordion('events'); 21 22 // Events: show/hide foldable sub-sections based on their parent checkbox. 23 // Fires on user click AND programmatic .prop('checked', ...) changes, 24 // so chip removal correctly hides the section when the parent unchecks. 25 function toggleEventsSubsections() { 26 $('#wppb-events-search-form input[data-toggle-subsection]').each(function () { 27 const slug = $(this).data('toggle-subsection'); 28 const section = $('#events-subsection-' + slug); 29 if (!section.length) return; 30 section.toggle($(this).is(':checked')); 31 }); 32 } 33 34 // Re-check subsection visibility whenever any events checkbox changes 35 // (covers parent toggle, child toggle, and chip-driven unchecks). 36 $('#wppb-events-search-form').on('change', 'input[type="checkbox"]', function () { 37 toggleEventsSubsections(); 38 }); 39 40 // Advanced-Search-Panel für Seminar-Formular toggeln 41 $('#seminars-advanced-search-settings-btn').on('click', function (e) { 42 e.preventDefault(); 43 const panel = $('#seminars-advanced-search-settings-container'); 44 if (panel.is(':visible')) { 45 panel.slideUp(180).attr('hidden', 'hidden'); 46 } else { 47 panel.slideDown(180).removeAttr('hidden'); 48 } 49 }); 50 51 // Advanced-Search-Panel für Events-Formular toggeln 52 $('#events-advanced-search-settings-btn').on('click', function (e) { 53 e.preventDefault(); 54 const panel = $('#events-advanced-search-settings-container'); 55 if (panel.is(':visible')) { 56 panel.slideUp(180).attr('hidden', 'hidden'); 57 } else { 58 panel.slideDown(180).removeAttr('hidden'); 59 } 60 }); 61 62 // Generic select all within seminar form 63 function bindSelectAll(selectorId, name) { 64 const selectAll = $(`#${selectorId}`); 65 if (!selectAll.length) return; 66 selectAll.on('change', function () { 67 const checked = $(this).is(':checked'); 68 $(`input[name='${name}']`).prop('checked', checked).trigger('change'); 69 }); 70 } 71 72 bindSelectAll('seminars-all_certificate_module', 'certificate_module[]'); 73 bindSelectAll('seminars-all_vdoe_zusatzqualifikationen', 'vdoe_zusatzqualifikationen[]'); 74 bindSelectAll('seminars-all_e_zert_bausteine', 'e_zert_bausteine[]'); 75 bindSelectAll('seminars-all_difficulty_level', 'difficulty_level[]'); 76 bindSelectAll('seminars-all_availability', 'availability[]'); 77 bindSelectAll('seminars-all_regions', 'regions[]'); 78 bindSelectAll('seminars-all_advanced_search', 'advanced_search[]'); 79 bindSelectAll('seminars-all_speaker', 'speaker[]'); 80 81 bindSelectAll('events-all_categories', 'categories[]'); 82 bindSelectAll('events-all_regions', 'regions[]'); 83 84 // Build chips of selected filters 85 function rebuildChips(type) { 86 if (type === 'seminars') { 87 /** 88 * ******************************************************************** 89 * ****************************** Seminar ***************************** 90 * ******************************************************************** 91 */ 92 // Seminar Chips 93 const wrap = $('#seminars-selected-filter'); 94 if (!wrap.length) { 95 return; 96 } 97 wrap.empty(); 98 99 // Mapping von Gruppen 100 const groupLabels = { 101 certificate_module: 'Zertifikats-Bausteine', 102 vdoe_zusatzqualifikationen: 'VDOE-Zusatzqualifikationen', 103 e_zert_bausteine: 'E-Zert-Bausteine', 104 difficulty_level: 'Schwierigkeitsgrad', 105 availability: 'Verfügbarkeit', 106 regions: 'Bundesland', 107 advanced_search: 'Erweiterte Suche', 108 online_seminar: 'Onlineseminar', 109 speaker: 'Referent*in', 110 }; 111 112 // Gruppensammlung 113 const groups = {}; 114 function pushToGroup(group, item) { 115 if (!groups[group]) groups[group] = []; 116 groups[group].push(item); 117 } 118 119 // Checkboxen Alle 120 $("#wppb-seminars-search-form input[type='checkbox']:checked").each(function () { 121 const id = $(this).attr('id') || ''; 122 123 let group = ''; 124 if (id.startsWith('seminars-cm-')) group = 'certificate_module'; 125 else if (id.startsWith('seminars-zq-')) group = 'vdoe_zusatzqualifikationen'; 126 else if (id.startsWith('seminars-ezert-')) group = 'e_zert_bausteine'; 127 else if (id.startsWith('seminars-dl-')) group = 'difficulty_level'; 128 else if (id.startsWith('seminars-av-')) group = 'availability'; 129 else if (id.startsWith('seminars-region-')) group = 'regions'; 130 else if (id.startsWith('seminars-adv-')) group = 'advanced_search'; 131 else if (id.startsWith('seminars-speaker-')) group = 'speaker'; 132 133 if (!group) return; // andere ignorieren 134 const value = $(this).val(); 135 const label = $("label[for='" + id + "']") 136 .text() 137 .trim(); 138 pushToGroup(group, { value, label, type: 'checkbox' }); 139 }); 140 141 // Advanced Search (Select) 142 // const adv = $("select[name='advanced_search[]']").val(); 143 // if (adv) { 144 // pushToGroup('advanced_search', { value: adv, label: adv, type: 'select', selectName: 'advanced_search' }); 145 // } 146 147 // // // Speaker (Select) 148 // const speakerVal = $("select[name='speaker[]']").val(); 149 // if (speakerVal) { 150 // const speakerLabel = $("select[name='speaker[]'] option:selected").text().trim(); 151 // pushToGroup('speaker', { value: speakerVal, label: speakerLabel, type: 'select', selectName: 'speaker' }); 152 // } 153 154 // Online Seminar (Radio) 155 const onlineSemVal = $("#wppb-seminars-search-form input[name='online_seminar']:checked").val(); 156 if (onlineSemVal) { 157 pushToGroup('online_seminar', { 158 value: onlineSemVal, 159 label: onlineSemVal === 'yes' ? 'Online: Ja' : 'Online: Nein', 160 type: 'radio', 161 radioName: 'online_seminar', 162 }); 163 } 164 165 // Wenn nichts gewählt -> fertig 166 const groupKeys = Object.keys(groups); 167 if (!groupKeys.length) return; 168 169 groupKeys.forEach((gKey) => { 170 const gItems = groups[gKey]; 171 if (!gItems.length) return; 172 const gLabel = groupLabels[gKey] || gKey; 173 const groupEl = $(`<div class='seminars-chip-group' data-group='${gKey}'></div>`); 174 const header = $(`<div class='seminars-chip-group-header'><span class='group-label'>${gLabel}</span></div>`); 175 const clearBtn = $( 176 `<button type='button' class='group-clear' aria-label='Gruppe ${gLabel} entfernen' title='Alle entfernen'>×</button>` 177 ); 178 clearBtn.on('click', function () { 179 // Gruppe komplett leeren
180 gItems.forEach((item) => { 181 if (item.type === 'checkbox') { 182 $(`#wppb-seminars-search-form input[type='checkbox'][value='${item.value}']`).prop('checked', false); 183 } else if (item.type === 'radio') { 184 $(`#wppb-seminars-search-form input[name='${item.radioName}']`).prop('checked', false); 185 } 186 }); 187 rebuildChips('seminars'); 188 }); 189 header.append(clearBtn); 190 groupEl.append(header); 191 192 const chipsWrap = $('<div class="seminars-chips"></div>'); 193 gItems.forEach((item) => { 194 const chip = $( 195 `<span class='seminars-chip' data-group='${gKey}' data-value='${item.value}' title='Filter entfernen'><span class='chip-label'>${item.label}</span><button type='button' class='chip-remove' aria-label='Filter entfernen'>×</button></span>` 196 ); 197 chip.find('.chip-remove').on('click', function () { 198 if (item.type === 'checkbox') { 199 $(`#wppb-seminars-search-form input[type='checkbox'][value='${item.value}']`).prop('checked', false); 200 } else if (item.type === 'radio') { 201 $(`#wppb-seminars-search-form input[name='${item.radioName}']`).prop('checked', false); 202 } 203 rebuildChips('seminars'); 204 }); 205 chipsWrap.append(chip); 206 }); 207 groupEl.append(chipsWrap); 208 wrap.append(groupEl); 209 }); 210 } else if (type === 'events') { 211 /** 212 * ******************************************************************** 213 * ****************************** EVENTS ****************************** 214 * ******************************************************************** 215 */ 216 // Events Chips 217 const eventsWrap = $('#events-selected-filter'); 218 if (!eventsWrap.length) { 219 return; 220 } 221 eventsWrap.empty(); 222 223 // Mapping von Gruppen 224 const eventsGroupLabels = { 225 categories: 'Veranstaltungskategorie', 226 regions: 'Bundesland', 227 online_events: 'Online-Veranstaltung', 228 }; 229 230 // Gruppensammlung 231 const groupsEvent = {}; 232 function pushToGroupEvent(group, item) { 233 if (!groupsEvent[group]) groupsEvent[group] = []; 234 groupsEvent[group].push(item); 235 } 236 237 // Kategorie 238 $('#wppb-events-search-form input[type="checkbox"]:checked').each(function () { 239 const id = $(this).attr('id') || ''; 240 let group = ''; 241 if (id.startsWith('events-kind-')) group = 'event_kind'; 242 else if (id.startsWith('events-cat-')) group = 'categories'; 243 else if (id.startsWith('events-region-')) group = 'regions'; 244 else if (id.startsWith('events-adv-')) group = 'advanced_search'; 245 if (!group) return; // andere ignorieren 246 const value = $(this).val(); 247 const label = $("label[for='" + id + "']") 248 .text() 249 .trim(); 250 pushToGroupEvent(group, { value, label, type: 'checkbox' }); 251 }); 252 253 // Online Events (Radio) 254 const onlineEvtVal = $("#wppb-events-search-form input[name='online_events']:checked").val(); 255 if (onlineEvtVal) { 256 pushToGroupEvent('online_events', { 257 value: onlineEvtVal, 258 label: onlineEvtVal === 'yes' ? 'Online: Ja' : 'Online: Nein', 259 type: 'radio', 260 radioName: 'online_events', 261 }); 262 } 263 264 // Render Events Chips 265 // Wenn nichts gewählt -> fertig 266 const groupEventKeys = Object.keys(groupsEvent); 267 if (!groupEventKeys.length) return; 268 269 groupEventKeys.forEach((gKey) => { 270 const gItems = groupsEvent[gKey]; 271 if (!gItems.length) return; 272 const gLabel = eventsGroupLabels[gKey] || gKey; 273 const groupEl = $(`<div class='events-chip-group' data-group='${gKey}'></div>`); 274 const header = $(`<div class='events-chip-group-header'><span class='group-label'>${gLabel}</span></div>`); 275 const clearBtn = $( 276 `<button type='button' class='group-clear' aria-label='Gruppe ${gLabel} entfernen' title='Alle entfernen'>×</button>` 277 ); 278 clearBtn.on('click', function () { 279 gItems.forEach((item) => { 280 if (item.type === 'checkbox') { 281 $(`#wppb-events-search-form input[type='checkbox'][value='${item.value}']`).prop('checked', false); 282 } else if (item.type === 'select') { 283 $(`#wppb-events-search-form select[name='${item.selectName}']`).val(''); 284 } else if (item.type === 'radio') { 285 $(`#wppb-events-search-form input[name='${item.radioName}']`).prop('checked', false); 286 } 287 });
288 rebuildChips('events'); 289 toggleEventsSubsections(); 290 }); 291 header.append(clearBtn); 292 groupEl.append(header); 293 294 const chipsWrap = $('<div class="events-chips"></div>'); 295 gItems.forEach((item) => { 296 const chip = $( 297 `<span class='events-chip' data-group='${gKey}' data-value='${item.value}' title='Filter entfernen'><span class='chip-label'>${item.label}</span><button type='button' class='chip-remove' aria-label='Filter entfernen'>×</button></span>` 298 ); 299 chip.find('.chip-remove').on('click', function () { 300 if (item.type === 'checkbox') { 301 $(`#wppb-events-search-form input[type='checkbox'][value='${item.value}']`).prop('checked', false); 302 } else if (item.type === 'select') { 303 $(`#wppb-events-search-form select[name='${item.selectName}']`).val(''); 304 } else if (item.type === 'radio') { 305 $(`#wppb-events-search-form input[name='${item.radioName}'][value='${item.value}']`).prop('checked', false); 306 } 307 rebuildChips('events'); 308 toggleEventsSubsections(); 309 }); 310 chipsWrap.append(chip); 311 }); 312 groupEl.append(chipsWrap); 313 eventsWrap.append(groupEl); 314 }); 315 } 316 } 317 318 $(document).on('change', "#wppb-seminars-search-form input[type='checkbox']", function () { 319 rebuildChips('seminars'); 320 }); 321 322 $(document).on( 323 'change', 324 [ 325 "#wppb-events-search-form input[type='checkbox']", 326 "#wppb-events-search-form input[name='online_events']", 327 ].join(','), 328 function () { 329 rebuildChips('events'); 330 toggleEventsSubsections(); 331 } 332 ); 333 334 // Initiale Aufrufe 335 rebuildChips('seminars'); 336 rebuildChips('events'); 337 toggleEventsSubsections(); 338});
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.