1/** 2 * m31 Services â short-mode (kurze_ausgabe) horizontal accordion interaction. 3 * 4 * Desktop (>991px): hover/focus expands (CSS). A click anywhere on the tile 5 * navigates to its anchor (data-href) â the whole tile stays a link. 6 * Mobile (â¤991px): tap on the head button toggles the panel open/closed 7 * (no hover). The anchor link is ONLY the real <a> button inside the panel. 8 * 9 * No-op when the module renders in full mode (no .m31_services_accordion present). 10 */ 11export default class M31Accordion { 12 constructor() { 13 this.init(); 14 } 15 16 bind() { 17 const mq = window.matchMedia( '(max-width: 991px)' ); 18 19 document.querySelectorAll( 'section.m31_services .m31_services_accordion' ).forEach( accordion => { 20 const items = Array.from( accordion.querySelectorAll( '.m31_services_item' ) ); 21 22 const setActive = item => { 23 items.forEach( i => { 24 const on = i === item; 25 i.classList.toggle( 'is_active', on ); 26 const h = i.querySelector( '.m31_services_item_head' ); 27 if ( h ) { 28 h.setAttribute( 'aria-expanded', on ? 'true' : 'false' ); 29 } 30 } ); 31 }; 32 33 items.forEach( item => { 34 const head = item.querySelector( '.m31_services_item_head' ); 35 const href = item.dataset.href; 36 37 item.addEventListener( 'click', e => { 38 // Real anchor button handles its own navigation. 39 if ( e.target.closest( '.m31_services_item_btn' ) ) { 40 return; 41 } 42 if ( mq.matches ) { 43 // Mobile: only the head toggles; nothing else acts. 44 if ( ! e.target.closest( '.m31_services_item_head' ) ) { 45 return; 46 } 47 if ( item.classList.contains( 'is_active' ) ) { 48 item.classList.remove( 'is_active' ); 49 if ( head ) { 50 head.setAttribute( 'aria-expanded', 'false' ); 51 } 52 } else { 53 setActive( item ); 54 } 55 } else if ( href ) { 56 // Desktop: whole tile navigates to the anchor. 57 window.location.href = href; 58 } 59 } ); 60 } ); 61 } ); 62 } 63
64 init() { 65 document.addEventListener( 'DOMContentLoaded', () => { 66 this.bind(); 67 } ); 68 } 69} 70 71new M31Accordion();
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.