11import { onSelect } from "../services/dom" ;
2+ import { KeyboardNavigationHandler } from "../services/keyboard-navigation" ;
23import { Component } from "./component" ;
34
45/**
@@ -17,8 +18,9 @@ export class Dropdown extends Component {
1718 this . direction = ( document . dir === 'rtl' ) ? 'right' : 'left' ;
1819 this . body = document . body ;
1920 this . showing = false ;
20- this . setupListeners ( ) ;
21+
2122 this . hide = this . hide . bind ( this ) ;
23+ this . setupListeners ( ) ;
2224 }
2325
2426 show ( event = null ) {
@@ -52,7 +54,7 @@ export class Dropdown extends Component {
5254 }
5355
5456 // Set listener to hide on mouse leave or window click
55- this . menu . addEventListener ( 'mouseleave' , this . hide . bind ( this ) ) ;
57+ this . menu . addEventListener ( 'mouseleave' , this . hide ) ;
5658 window . addEventListener ( 'click' , event => {
5759 if ( ! this . menu . contains ( event . target ) ) {
5860 this . hide ( ) ;
@@ -97,33 +99,25 @@ export class Dropdown extends Component {
9799 this . showing = false ;
98100 }
99101
100- getFocusable ( ) {
101- return Array . from ( this . menu . querySelectorAll ( '[tabindex]:not([tabindex="-1"]),[href],button,input:not([type=hidden])' ) ) ;
102- }
103-
104- focusNext ( ) {
105- const focusable = this . getFocusable ( ) ;
106- const currentIndex = focusable . indexOf ( document . activeElement ) ;
107- let newIndex = currentIndex + 1 ;
108- if ( newIndex >= focusable . length ) {
109- newIndex = 0 ;
110- }
111-
112- focusable [ newIndex ] . focus ( ) ;
113- }
102+ setupListeners ( ) {
103+ const keyboardNavHandler = new KeyboardNavigationHandler ( this . container , ( event ) => {
104+ this . hide ( ) ;
105+ this . toggle . focus ( ) ;
106+ if ( ! this . bubbleEscapes ) {
107+ event . stopPropagation ( ) ;
108+ }
109+ } , ( event ) => {
110+ if ( event . target . nodeName === 'INPUT' ) {
111+ event . preventDefault ( ) ;
112+ event . stopPropagation ( ) ;
113+ }
114+ this . hide ( ) ;
115+ } ) ;
114116
115- focusPrevious ( ) {
116- const focusable = this . getFocusable ( ) ;
117- const currentIndex = focusable . indexOf ( document . activeElement ) ;
118- let newIndex = currentIndex - 1 ;
119- if ( newIndex < 0 ) {
120- newIndex = focusable . length - 1 ;
117+ if ( this . moveMenu ) {
118+ keyboardNavHandler . shareHandlingToEl ( this . menu ) ;
121119 }
122120
123- focusable [ newIndex ] . focus ( ) ;
124- }
125-
126- setupListeners ( ) {
127121 // Hide menu on option click
128122 this . container . addEventListener ( 'click' , event => {
129123 const possibleChildren = Array . from ( this . menu . querySelectorAll ( 'a' ) ) ;
@@ -136,39 +130,9 @@ export class Dropdown extends Component {
136130 event . stopPropagation ( ) ;
137131 this . show ( event ) ;
138132 if ( event instanceof KeyboardEvent ) {
139- this . focusNext ( ) ;
140- }
141- } ) ;
142-
143- // Keyboard navigation
144- const keyboardNavigation = event => {
145- if ( event . key === 'ArrowDown' || event . key === 'ArrowRight' ) {
146- this . focusNext ( ) ;
147- event . preventDefault ( ) ;
148- } else if ( event . key === 'ArrowUp' || event . key === 'ArrowLeft' ) {
149- this . focusPrevious ( ) ;
150- event . preventDefault ( ) ;
151- } else if ( event . key === 'Escape' ) {
152- this . hide ( ) ;
153- this . toggle . focus ( ) ;
154- if ( ! this . bubbleEscapes ) {
155- event . stopPropagation ( ) ;
156- }
157- }
158- } ;
159- this . container . addEventListener ( 'keydown' , keyboardNavigation ) ;
160- if ( this . moveMenu ) {
161- this . menu . addEventListener ( 'keydown' , keyboardNavigation ) ;
162- }
163-
164- // Hide menu on enter press or escape
165- this . menu . addEventListener ( 'keydown ' , event => {
166- if ( event . key === 'Enter' ) {
167- event . preventDefault ( ) ;
168- event . stopPropagation ( ) ;
169- this . hide ( ) ;
133+ keyboardNavHandler . focusNext ( ) ;
170134 }
171135 } ) ;
172136 }
173137
174- }
138+ }
0 commit comments