@@ -61,6 +61,9 @@ export class Yasqe extends CodeMirror {
6161 private queryBtn : HTMLButtonElement | undefined ;
6262 private saveBtn : HTMLButtonElement | undefined ;
6363 private fullscreenBtn : HTMLButtonElement | undefined ;
64+ private hamburgerBtn : HTMLButtonElement | undefined ;
65+ private hamburgerMenu : HTMLDivElement | undefined ;
66+ private shareBtn : HTMLButtonElement | undefined ;
6467 private isFullscreen : boolean = false ;
6568 private horizontalResizeWrapper ?: HTMLDivElement ;
6669 private snippetsBar ?: HTMLDivElement ;
@@ -318,6 +321,7 @@ export class Yasqe extends CodeMirror {
318321 shareLinkWrapper . setAttribute ( "aria-label" , "Share query" ) ;
319322 shareLinkWrapper . appendChild ( shareIcon ) ;
320323 buttons . appendChild ( shareLinkWrapper ) ;
324+ this . shareBtn = shareLinkWrapper ;
321325 shareLinkWrapper . addEventListener ( "click" , ( event : MouseEvent ) => showSharePopup ( event ) ) ;
322326 shareLinkWrapper . addEventListener ( "keydown" , ( event : KeyboardEvent ) => {
323327 if ( event . code === "Enter" ) {
@@ -609,6 +613,130 @@ export class Yasqe extends CodeMirror {
609613 this . fullscreenBtn . title = "Toggle fullscreen (F11)" ;
610614 this . fullscreenBtn . setAttribute ( "aria-label" , "Toggle fullscreen" ) ;
611615 buttons . appendChild ( this . fullscreenBtn ) ;
616+
617+ /**
618+ * Draw hamburger menu button and dropdown (for mobile)
619+ */
620+ this . hamburgerBtn = document . createElement ( "button" ) ;
621+ addClass ( this . hamburgerBtn , "yasqe_hamburgerButton" ) ;
622+ const hamburgerIcon = document . createElement ( "i" ) ;
623+ addClass ( hamburgerIcon , "fas" ) ;
624+ addClass ( hamburgerIcon , "fa-bars" ) ;
625+ hamburgerIcon . setAttribute ( "aria-hidden" , "true" ) ;
626+ this . hamburgerBtn . appendChild ( hamburgerIcon ) ;
627+ this . hamburgerBtn . title = "More options" ;
628+ this . hamburgerBtn . setAttribute ( "aria-label" , "More options" ) ;
629+ this . hamburgerBtn . setAttribute ( "aria-expanded" , "false" ) ;
630+ buttons . appendChild ( this . hamburgerBtn ) ;
631+
632+ // Create hamburger menu
633+ this . hamburgerMenu = document . createElement ( "div" ) ;
634+ this . hamburgerMenu . className = "yasqe_hamburgerMenu" ;
635+ buttons . appendChild ( this . hamburgerMenu ) ;
636+
637+ // Add menu items
638+ if ( this . config . createShareableLink ) {
639+ const shareItem = document . createElement ( "button" ) ;
640+ shareItem . className = "yasqe_hamburgerMenuItem" ;
641+ const shareIconMenu = document . createElement ( "i" ) ;
642+ addClass ( shareIconMenu , "fas" ) ;
643+ addClass ( shareIconMenu , "fa-share-nodes" ) ;
644+ shareIconMenu . setAttribute ( "aria-hidden" , "true" ) ;
645+ shareItem . appendChild ( shareIconMenu ) ;
646+ const shareLabel = document . createElement ( "span" ) ;
647+ shareLabel . textContent = "Share" ;
648+ shareItem . appendChild ( shareLabel ) ;
649+ shareItem . onclick = ( ) => {
650+ this . closeHamburgerMenu ( ) ;
651+ this . shareBtn ?. click ( ) ;
652+ } ;
653+ this . hamburgerMenu . appendChild ( shareItem ) ;
654+ }
655+
656+ const saveItem = document . createElement ( "button" ) ;
657+ saveItem . className = "yasqe_hamburgerMenuItem" ;
658+ const saveIconMenu = document . createElement ( "i" ) ;
659+ addClass ( saveIconMenu , "fas" ) ;
660+ addClass ( saveIconMenu , "fa-save" ) ;
661+ saveIconMenu . setAttribute ( "aria-hidden" , "true" ) ;
662+ saveItem . appendChild ( saveIconMenu ) ;
663+ const saveLabel = document . createElement ( "span" ) ;
664+ saveLabel . textContent = "Save" ;
665+ saveItem . appendChild ( saveLabel ) ;
666+ saveItem . onclick = ( ) => {
667+ this . closeHamburgerMenu ( ) ;
668+ this . emit ( "saveManagedQuery" ) ;
669+ } ;
670+ this . hamburgerMenu . appendChild ( saveItem ) ;
671+
672+ if ( this . config . showFormatButton ) {
673+ const formatItem = document . createElement ( "button" ) ;
674+ formatItem . className = "yasqe_hamburgerMenuItem" ;
675+ const formatIconMenu = document . createElement ( "i" ) ;
676+ addClass ( formatIconMenu , "fas" ) ;
677+ addClass ( formatIconMenu , "fa-align-left" ) ;
678+ formatIconMenu . setAttribute ( "aria-hidden" , "true" ) ;
679+ formatItem . appendChild ( formatIconMenu ) ;
680+ const formatLabel = document . createElement ( "span" ) ;
681+ formatLabel . textContent = "Format" ;
682+ formatItem . appendChild ( formatLabel ) ;
683+ formatItem . onclick = ( ) => {
684+ this . closeHamburgerMenu ( ) ;
685+ this . format ( ) ;
686+ } ;
687+ this . hamburgerMenu . appendChild ( formatItem ) ;
688+ }
689+
690+ const fullscreenItem = document . createElement ( "button" ) ;
691+ fullscreenItem . className = "yasqe_hamburgerMenuItem" ;
692+ const fullscreenIconMenu = document . createElement ( "i" ) ;
693+ addClass ( fullscreenIconMenu , "fas" ) ;
694+ addClass ( fullscreenIconMenu , "fa-expand" ) ;
695+ fullscreenIconMenu . setAttribute ( "aria-hidden" , "true" ) ;
696+ fullscreenItem . appendChild ( fullscreenIconMenu ) ;
697+ const fullscreenLabel = document . createElement ( "span" ) ;
698+ fullscreenLabel . textContent = "Fullscreen" ;
699+ fullscreenItem . appendChild ( fullscreenLabel ) ;
700+ fullscreenItem . onclick = ( ) => {
701+ this . closeHamburgerMenu ( ) ;
702+ this . toggleFullscreen ( ) ;
703+ } ;
704+ this . hamburgerMenu . appendChild ( fullscreenItem ) ;
705+
706+ // Toggle hamburger menu
707+ this . hamburgerBtn . onclick = ( e ) => {
708+ e . stopPropagation ( ) ;
709+ this . toggleHamburgerMenu ( ) ;
710+ } ;
711+
712+ // Close hamburger menu when clicking outside
713+ document . addEventListener ( "click" , ( e ) => {
714+ if (
715+ this . hamburgerMenu &&
716+ this . hamburgerBtn &&
717+ ! this . hamburgerMenu . contains ( e . target as Node ) &&
718+ ! this . hamburgerBtn . contains ( e . target as Node )
719+ ) {
720+ this . closeHamburgerMenu ( ) ;
721+ }
722+ } ) ;
723+ }
724+
725+ private toggleHamburgerMenu ( ) {
726+ if ( ! this . hamburgerMenu || ! this . hamburgerBtn ) return ;
727+ const isActive = this . hamburgerMenu . classList . contains ( "active" ) ;
728+ if ( isActive ) {
729+ this . closeHamburgerMenu ( ) ;
730+ } else {
731+ addClass ( this . hamburgerMenu , "active" ) ;
732+ this . hamburgerBtn . setAttribute ( "aria-expanded" , "true" ) ;
733+ }
734+ }
735+
736+ private closeHamburgerMenu ( ) {
737+ if ( ! this . hamburgerMenu || ! this . hamburgerBtn ) return ;
738+ removeClass ( this . hamburgerMenu , "active" ) ;
739+ this . hamburgerBtn . setAttribute ( "aria-expanded" , "false" ) ;
612740 }
613741 public toggleFullscreen ( ) {
614742 this . isFullscreen = ! this . isFullscreen ;
0 commit comments