1import { Controller } from '@hotwired/stimulus'; 2 3export default class extends Controller { 4 static targets = ['menu']; 5 6 connect() { 7 this.onDocumentClick = this.onDocumentClick.bind(this); 8 this.onDocumentKeydown = this.onDocumentKeydown.bind(this); 9 } 10 11 disconnect() { 12 this.removeDocumentListeners(); 13 } 14 15 toggle(event) { 16 event.preventDefault(); 17 event.stopPropagation(); 18 19 if (this.menuTarget.classList.contains('hidden')) { 20 this.open(); 21 } else { 22 this.close(); 23 } 24 } 25 26 open() { 27 this.menuTarget.classList.remove('hidden'); 28 this.buttonElement.setAttribute('aria-expanded', 'true'); 29 document.addEventListener('click', this.onDocumentClick); 30 document.addEventListener('keydown', this.onDocumentKeydown); 31 } 32 33 close() { 34 this.menuTarget.classList.add('hidden'); 35 this.buttonElement.setAttribute('aria-expanded', 'false'); 36 this.removeDocumentListeners(); 37 } 38 39 onDocumentClick(event) { 40 if (!this.element.contains(event.target)) { 41 this.close(); 42 } 43 } 44 45 onDocumentKeydown(event) { 46 if (event.key === 'Escape') { 47 this.close(); 48 } 49 } 50 51 removeDocumentListeners() { 52 document.removeEventListener('click', this.onDocumentClick); 53 document.removeEventListener('keydown', this.onDocumentKeydown); 54 } 55 56 get buttonElement() { 57 return this.element.querySelector('[data-user-menu-target="button"]'); 58 } 59}
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.