@@ -13,7 +13,9 @@ export var ContextMenu = L.Handler.extend({
1313
1414 initialize : function ( map ) {
1515 L . Handler . prototype . initialize . call ( this , map ) ;
16-
16+ this . activeIndex = 0 ; //current fous index on menu
17+ this . excludedIndices = [ 4 , 7 ] ; //menu indexes that are --------
18+ this . isRunned = false ; //variable for tracking edge case
1719 //setting the items in the context menu and their callback functions
1820 this . _items = [
1921 {
@@ -639,6 +641,8 @@ export var ContextMenu = L.Handler.extend({
639641 this . _layerMenu . setAttribute ( 'hidden' , '' ) ;
640642 this . _map . fire ( 'contextmenu.hide' , { contextmenu : this } ) ;
641643 setTimeout ( ( ) => this . _map . _container . focus ( ) , 0 ) ;
644+ this . activeIndex = 0 ;
645+ this . isRunned = false ;
642646 }
643647 } ,
644648
@@ -704,6 +708,54 @@ export var ContextMenu = L.Handler.extend({
704708 delete this . _elementInFocus ;
705709 } ,
706710
711+ _setActiveItem : function ( index ) {
712+ if ( document . activeElement . shadowRoot === null && this . noActiveEl === true ) {
713+ //bug fix when theres no active element
714+ this . noActiveEl = false ;
715+ //setting this._items[9] is just for preventing some diabled index, it will be override by later code.
716+ this . _items [ 9 ] . el . el . focus ( ) ;
717+ }
718+ if ( document . activeElement . shadowRoot . activeElement . innerHTML === this . _items [ index ] . el . el . innerHTML ) {
719+ //edge case where pressing shift f10 focuses the first element on contextmenu (if already focused, have to press arrow twice to go down)
720+ let next = index + 1 ;
721+ while ( this . _items [ next ] . el . el . disabled ) {
722+ next ++ ;
723+ if ( next >= this . _items . length ) {
724+ next = 0 ;
725+ }
726+ }
727+ this . _setActiveItem ( next ) ;
728+ } else {
729+ if ( this . excludedIndices . includes ( index ) ) {
730+ // find the next or previous non-excluded item
731+ let nextIndex = index + 1 ;
732+ let prevIndex = index - 1 ;
733+ while ( this . excludedIndices . includes ( nextIndex ) || this . _items [ nextIndex ] . el . el . disabled ) {
734+ nextIndex ++ ;
735+ if ( nextIndex >= this . _items . length ) {
736+ nextIndex = 0 ;
737+ }
738+ }
739+ while ( this . excludedIndices . includes ( prevIndex ) || this . _items [ prevIndex ] . el . el . disabled ) {
740+ prevIndex -- ;
741+ if ( prevIndex < 0 ) {
742+ prevIndex = this . _items . length - 1 ;
743+ }
744+ }
745+ // set the active item to the next or previous non-excluded item
746+ if ( this . activeIndex < index ) {
747+ this . _setActiveItem ( nextIndex ) ;
748+ } else {
749+ this . _setActiveItem ( prevIndex ) ;
750+ }
751+ } else {
752+ // set the focus item
753+ this . _items [ index ] . el . el . focus ( ) ;
754+ this . activeIndex = index ;
755+ }
756+ }
757+ } ,
758+
707759 _onKeyDown : function ( e ) {
708760 if ( ! this . _mapMenuVisible ) return ;
709761
@@ -723,13 +775,132 @@ export var ContextMenu = L.Handler.extend({
723775 L . DomEvent . stop ( e ) ;
724776 this . _focusOnLayerControl ( ) ;
725777 }
778+ } else if ( key === 38 ) { //up arrow
779+ if ( ! this . _coordMenu . hasAttribute ( 'hidden' ) &&
780+ ( document . activeElement . shadowRoot === null || //null happens when the focus is on submenu and when mouse hovers on main menu, submenu disappears
781+ document . activeElement . shadowRoot . activeElement . innerHTML === this . _coordMenu . children [ 0 ] . innerHTML ) ) { //"map" on submenu
782+ this . _coordMenu . children [ 2 ] . focus ( ) ;
783+ } else if ( ! this . _coordMenu . hasAttribute ( 'hidden' ) &&
784+ document . activeElement . shadowRoot . activeElement . innerHTML === this . _coordMenu . children [ 1 ] . innerHTML ) { //"extent" on submenu
785+ this . _coordMenu . children [ 0 ] . focus ( ) ;
786+ } else if ( ! this . _coordMenu . hasAttribute ( 'hidden' ) &&
787+ document . activeElement . shadowRoot . activeElement . innerHTML === this . _coordMenu . children [ 2 ] . innerHTML ) { //"Location" on submenu
788+ this . _coordMenu . children [ 1 ] . focus ( ) ;
789+ } else if ( ! this . _layerMenu . hasAttribute ( 'hidden' ) &&
790+ document . activeElement . shadowRoot . activeElement . innerHTML === this . _layerMenu . children [ 0 ] . innerHTML ) { //"zoom to layer" on layermenu
791+ this . _layerMenu . children [ 1 ] . focus ( ) ;
792+ } else if ( ! this . _layerMenu . hasAttribute ( 'hidden' ) ) {
793+ this . _layerMenu . children [ 0 ] . focus ( ) ;
794+ } else {
795+ if ( this . activeIndex > 0 ) {
796+ let prevIndex = this . activeIndex - 1 ;
797+ while ( this . _items [ prevIndex ] . el . el . disabled ) {
798+ prevIndex -- ;
799+ if ( prevIndex < 0 ) {
800+ prevIndex = this . _items . length - 1 ;
801+ }
802+ }
803+ this . _setActiveItem ( prevIndex ) ;
804+ } else {
805+ this . _setActiveItem ( this . _items . length - 1 ) ;
806+ }
807+ }
808+ } else if ( key === 40 ) { //down arrow
809+ if ( ! this . _coordMenu . hasAttribute ( 'hidden' ) &&
810+ ( document . activeElement . shadowRoot === null ||
811+ document . activeElement . shadowRoot . activeElement . innerHTML === this . _coordMenu . children [ 2 ] . innerHTML ) ) { //"map" on submenu
812+ this . _coordMenu . children [ 0 ] . focus ( ) ;
813+ } else if ( ! this . _coordMenu . hasAttribute ( 'hidden' ) &&
814+ document . activeElement . shadowRoot . activeElement . innerHTML === this . _coordMenu . children [ 1 ] . innerHTML ) { //"extent" on submenu
815+ this . _coordMenu . children [ 2 ] . focus ( ) ;
816+ } else if ( ! this . _coordMenu . hasAttribute ( 'hidden' ) &&
817+ document . activeElement . shadowRoot . activeElement . innerHTML === this . _coordMenu . children [ 0 ] . innerHTML ) { //"Location" on submenu
818+ this . _coordMenu . children [ 1 ] . focus ( ) ;
819+ } else if ( ! this . _layerMenu . hasAttribute ( 'hidden' ) &&
820+ document . activeElement . shadowRoot . activeElement . innerHTML === this . _layerMenu . children [ 0 ] . innerHTML ) { //"zoom to layer" on layermenu
821+ this . _layerMenu . children [ 1 ] . focus ( ) ;
822+ } else if ( ! this . _layerMenu . hasAttribute ( 'hidden' ) ) {
823+ this . _layerMenu . children [ 0 ] . focus ( ) ;
824+ } else {
825+ if ( this . activeIndex < this . _items . length - 1 ) {
826+ //edge case at index 0
827+ if ( ! this . isRunned && this . activeIndex === 0 && ! this . _items [ this . activeIndex ] . el . el . disabled ) {
828+ this . _setActiveItem ( 0 ) ;
829+ this . isRunned = true ;
830+ } else { //edge case over
831+ let nextIndex = this . activeIndex + 1 ;
832+ while ( this . _items [ nextIndex ] . el . el . disabled ) {
833+ nextIndex ++ ;
834+ if ( nextIndex >= this . _items . length ) {
835+ nextIndex = 0 ;
836+ }
837+ }
838+ this . _setActiveItem ( nextIndex ) ;
839+ }
840+ } else {
841+ let nextIndex = 0 ;
842+ while ( this . _items [ nextIndex ] . el . el . disabled ) {
843+ nextIndex ++ ;
844+ if ( nextIndex >= this . _items . length ) {
845+ nextIndex = 0 ;
846+ }
847+ }
848+ this . _setActiveItem ( nextIndex ) ;
849+ }
850+ }
851+ } else if ( key === 39 ) { //right arrow
852+ if ( document . activeElement . shadowRoot !== null &&
853+ document . activeElement . shadowRoot . activeElement . innerHTML ===
854+ this . _items [ 5 ] . el . el . innerHTML && //'copy'
855+ this . _coordMenu . hasAttribute ( 'hidden' ) ) {
856+ this . _showCoordMenu ( ) ;
857+ this . _coordMenu . children [ 0 ] . focus ( ) ;
858+ } else if ( document . activeElement . shadowRoot . activeElement . innerHTML === this . _items [ 5 ] . el . el . innerHTML &&
859+ ! this . _coordMenu . hasAttribute ( 'hidden' ) ) {
860+ this . _coordMenu . children [ 0 ] . focus ( ) ;
861+ }
862+ } else if ( key === 37 ) { //left arrow
863+ if ( ! this . _coordMenu . hasAttribute ( 'hidden' ) &&
864+ document . activeElement . shadowRoot !== null ) {
865+ if ( document . activeElement . shadowRoot . activeElement . innerHTML === this . _coordMenu . children [ 0 ] . innerHTML ||
866+ document . activeElement . shadowRoot . activeElement . innerHTML === this . _coordMenu . children [ 1 ] . innerHTML ||
867+ document . activeElement . shadowRoot . activeElement . innerHTML === this . _coordMenu . children [ 2 ] . innerHTML ) {
868+ this . _coordMenu . setAttribute ( 'hidden' , '' ) ;
869+ this . _setActiveItem ( 5 ) ;
870+ }
871+ }
872+ } else if ( key === 27 ) { //esc key
873+ if ( document . activeElement . shadowRoot === null ) {
874+ this . _hide ( ) ;
875+ } else {
876+ if ( ! this . _coordMenu . hasAttribute ( 'hidden' ) ) {
877+ if ( document . activeElement . shadowRoot . activeElement . innerHTML === this . _coordMenu . children [ 0 ] . innerHTML ||
878+ document . activeElement . shadowRoot . activeElement . innerHTML === this . _coordMenu . children [ 1 ] . innerHTML ||
879+ document . activeElement . shadowRoot . activeElement . innerHTML === this . _coordMenu . children [ 2 ] . innerHTML ) {
880+ this . _coordMenu . setAttribute ( 'hidden' , '' ) ;
881+ this . _setActiveItem ( 5 ) ;
882+ }
883+ } else {
884+ this . _hide ( ) ;
885+ }
886+ }
726887 } else if ( key !== 16 && key !== 9 &&
727888 ! ( ! ( this . _layerClicked . className . includes ( 'mapml-layer-item' ) ) && key === 67 ) &&
728- ( path [ 0 ] . innerText !== ( M . options . locale . cmCopyCoords + " (C)" ) || key === 27 ) ) {
889+ ( path [ 0 ] . innerText !== ( M . options . locale . cmCopyCoords + " (C)" ) ) ) {
729890 this . _hide ( ) ;
730891 }
731892 switch ( key ) {
732893 case 13 : //ENTER KEY
894+ if ( document . activeElement . shadowRoot . activeElement . innerHTML === this . _items [ 5 ] . el . el . innerHTML ) {
895+ this . _copyCoords ( {
896+ latlng :this . _map . getCenter ( )
897+ } ) ;
898+ this . _coordMenu . firstChild . focus ( ) ;
899+ } else {
900+ if ( this . _map . _container . parentNode . activeElement . parentNode . classList . contains ( "mapml-contextmenu" ) )
901+ this . _map . _container . parentNode . activeElement . click ( ) ;
902+ }
903+ break ;
733904 case 32 : //SPACE KEY
734905 if ( this . _map . _container . parentNode . activeElement . parentNode . classList . contains ( "mapml-contextmenu" ) )
735906 this . _map . _container . parentNode . activeElement . click ( ) ;
@@ -738,6 +909,7 @@ export var ContextMenu = L.Handler.extend({
738909 this . _copyCoords ( {
739910 latlng :this . _map . getCenter ( )
740911 } ) ;
912+ this . _coordMenu . firstChild . focus ( ) ;
741913 break ;
742914 case 68 : //D KEY
743915 this . _toggleDebug ( e ) ;
@@ -790,7 +962,6 @@ export var ContextMenu = L.Handler.extend({
790962
791963 menu . style . top = 100 - 22 + 'px' ;
792964 menu . style . bottom = 'auto' ;
793- if ( this . _keyboardEvent ) menu . firstChild . focus ( ) ;
794965 } ,
795966
796967 _hideCoordMenu : function ( e ) {
@@ -800,6 +971,7 @@ export var ContextMenu = L.Handler.extend({
800971 let menu = this . _coordMenu , copyEl = this . _items [ 4 ] . el . el ;
801972 copyEl . setAttribute ( "aria-expanded" , "false" ) ;
802973 menu . setAttribute ( 'hidden' , '' ) ;
974+ this . noActiveEl = true ; //variable to keep track of no focus element on contextmenu, bug fix for arrow key navigation
803975 } ,
804976
805977 _onItemMouseOver : function ( e ) {
0 commit comments