11/*!
22 * @license MIT (https://github.com/geotrev/undernet/blob/master/LICENSE)
3- * Undernet v3.3.6 (https://undernet.io)
3+ * Undernet v3.3.7 (https://undernet.io)
44 * Copyright 2017-2019 George Treviranus
55 */
66const KeyCodes = {
@@ -21,6 +21,19 @@ const Events = {
2121 CLICK : "click" ,
2222} ;
2323
24+ /**
25+ * Creates a string of element selector patterns using common elements.
26+ * @param {String } container - The enclosing container's class, attribute, etc.
27+ * @return {String }
28+ */
29+ const getFocusableElements = container => {
30+ const focusables = Selectors . FOCUSABLE_TAGS . map (
31+ element => `${ container } ${ element } ${ Selectors . NOT_VISUALLY_HIDDEN } `
32+ ) . join ( ", " ) ;
33+
34+ return document . querySelectorAll ( focusables )
35+ } ;
36+
2437/**
2538 * Utility methods for DOM traversal and focus trapping.
2639 * @module Utils
@@ -50,7 +63,7 @@ class Utils {
5063 */
5164 captureFocus ( container , options ) {
5265 this . _focusContainerSelector = container ;
53- this . _focusableChildren = this . getFocusableElements ( this . _focusContainerSelector ) ;
66+ this . _focusableChildren = getFocusableElements ( this . _focusContainerSelector ) ;
5467 this . _focusableFirstChild = this . _focusableChildren [ 0 ] ;
5568 this . _focusableLastChild = this . _focusableChildren [ this . _focusableChildren . length - 1 ] ;
5669
@@ -94,30 +107,6 @@ class Utils {
94107 }
95108 }
96109
97- /**
98- * Because IE does not recognize NodeList.forEach(),
99- * we use a cross-browser solution for returning an array of DOM nodes every time.
100- * @param {String } element - A DOM node's class, attribute, etc., to search the document.
101- * @return {Array }
102- */
103- getElements ( element ) {
104- const nodeList = document . querySelectorAll ( element ) ;
105- return Array . apply ( null , nodeList )
106- }
107-
108- /**
109- * Creates a string of element selector patterns using common elements.
110- * @param {String } container - The enclosing container's class, attribute, etc.
111- * @return {String }
112- */
113- getFocusableElements ( container ) {
114- const focusables = Selectors . FOCUSABLE_TAGS . map (
115- element => `${ container } ${ element } ${ Selectors . NOT_VISUALLY_HIDDEN } `
116- ) . join ( ", " ) ;
117-
118- return this . getElements ( focusables )
119- }
120-
121110 // private
122111
123112 /**
@@ -267,6 +256,8 @@ class Modal extends Utils {
267256 constructor ( ) {
268257 super ( ) ;
269258
259+ this . _iosMobile = / ( i p h o n e | i p o d ) / i. test ( navigator . userAgent ) ;
260+
270261 // events
271262 this . _render = this . _render . bind ( this ) ;
272263 this . _handleClose = this . _handleClose . bind ( this ) ;
@@ -297,10 +288,10 @@ class Modal extends Utils {
297288 * Begin listening to elements with [data-modal-button]
298289 */
299290 start ( ) {
300- this . _modals = this . getElements ( this . _modalContainerAttr ) ;
301- this . _modalButtons = this . getElements ( `[${ Selectors$1 . DATA_MODAL_BUTTON } ]` ) ;
291+ this . _modals = document . querySelectorAll ( this . _modalContainerAttr ) ;
292+ this . _modalButtons = document . querySelectorAll ( `[${ Selectors$1 . DATA_MODAL_BUTTON } ]` ) ;
302293
303- this . getFocusableElements ( this . _modalContainerAttr ) . forEach ( element => {
294+ getFocusableElements ( this . _modalContainerAttr ) . forEach ( element => {
304295 element . setAttribute ( Selectors$1 . TABINDEX , "-1" ) ;
305296 } ) ;
306297
@@ -351,12 +342,12 @@ class Modal extends Utils {
351342
352343 this . _activeModalSelector = `${ this . _activeModalOverlayAttr } ${ this . _modalContainerAttr } ` ;
353344 this . _activeModal = document . querySelector ( this . _activeModalSelector ) ;
354- this . _activeModalCloseButtons = this . getElements (
345+ this . _activeModalCloseButtons = document . querySelectorAll (
355346 `${ this . _activeModalOverlayAttr } [${ Selectors$1 . DATA_CLOSE } ]`
356347 ) ;
357348
358349 // allow focusable elements to be focused
359- this . getFocusableElements ( this . _activeModalSelector ) . forEach ( element => {
350+ getFocusableElements ( this . _activeModalSelector ) . forEach ( element => {
360351 element . setAttribute ( Selectors$1 . TABINDEX , "0" ) ;
361352 } ) ;
362353
@@ -373,6 +364,11 @@ class Modal extends Utils {
373364 // offset slight scroll caused by this._activeModal.focus()
374365 this . _activeModalOverlay . scrollTop = 0 ;
375366
367+ // on ios devices, let the modal close on overlay click
368+ if ( this . _iosMobile ) {
369+ this . _activeModalOverlay . style . cursor = "pointer" ;
370+ }
371+
376372 // begin listening to events
377373 document . addEventListener ( Events$1 . KEYDOWN , this . _handleEscapeKeyPress ) ;
378374 document . addEventListener ( Events$1 . CLICK , this . _handleOverlayClick ) ;
@@ -415,10 +411,14 @@ class Modal extends Utils {
415411 this . _activeModalOverlay . setAttribute ( Selectors$1 . ARIA_HIDDEN , "true" ) ;
416412 this . _activeModal . removeAttribute ( Selectors$1 . TABINDEX ) ;
417413
418- this . getFocusableElements ( this . _activeModalSelector ) . forEach ( element => {
414+ getFocusableElements ( this . _activeModalSelector ) . forEach ( element => {
419415 element . setAttribute ( Selectors$1 . TABINDEX , "-1" ) ;
420416 } ) ;
421417
418+ if ( this . _iosMobile ) {
419+ this . _activeModalOverlay . style . cursor = "auto" ;
420+ }
421+
422422 // stop listening to events
423423 document . removeEventListener ( Events$1 . KEYDOWN , this . _handleEscapeKeyPress ) ;
424424 document . removeEventListener ( Events$1 . CLICK , this . _handleOverlayClick ) ;
@@ -549,7 +549,7 @@ class Accordion extends Utils {
549549 const accordionButtonSelector = this . _getPossibleAccordionButtonAttrs (
550550 `[${ Selectors$2 . DATA_ACCORDION } ]`
551551 ) ;
552- this . _accordionButtons = this . getElements ( accordionButtonSelector ) ;
552+ this . _accordionButtons = document . querySelectorAll ( accordionButtonSelector ) ;
553553
554554 if ( this . _accordionButtons . length ) {
555555 this . _accordionButtons . forEach ( button => {
@@ -570,6 +570,42 @@ class Accordion extends Utils {
570570
571571 // private
572572
573+ /**
574+ * Open accordion content associated with an accordion button.
575+ * @param {Object } event - The event object
576+ */
577+ _render ( event ) {
578+ event . preventDefault ( ) ;
579+
580+ this . _activeButton = event . target ;
581+ this . _activeAccordionRowId = this . _activeButton . getAttribute ( Selectors$2 . DATA_TARGET ) ;
582+
583+ this . _activeRowAttr = this . _getAccordionRowAttr ( this . _activeAccordionRowId ) ;
584+ this . _activeRow = document . querySelector ( this . _activeRowAttr ) ;
585+
586+ if ( ! this . _activeButton . getAttribute ( Selectors$2 . DATA_PARENT ) ) {
587+ return console . error ( Messages$1 . NO_PARENT_ERROR ( this . _activeAccordionRowId ) )
588+ }
589+
590+ this . _activeContainerId = this . _activeButton . getAttribute ( Selectors$2 . DATA_PARENT ) ;
591+ this . _activeContainerAttr = `[${ Selectors$2 . DATA_ACCORDION } ='${ this . _activeContainerId } ']` ;
592+
593+ if ( ! document . querySelector ( this . _activeContainerAttr ) ) {
594+ return console . error ( Messages$1 . NO_ACCORDION_ERROR ( this . _activeContainerId ) )
595+ }
596+
597+ this . _activeContainer = document . querySelector ( this . _activeContainerAttr ) ;
598+ this . _activeContent = document . getElementById ( this . _activeAccordionRowId ) ;
599+
600+ const accordionButtonState = this . _activeRow . getAttribute ( Selectors$2 . DATA_VISIBLE ) ;
601+
602+ this . _activeButtonExpandState = accordionButtonState === "true" ? "false" : "true" ;
603+ this . _activeContentHiddenState = this . _activeButtonExpandState === "false" ? "true" : "false" ;
604+
605+ this . _closeAllIfToggleable ( ) ;
606+ this . _toggleSelectedAccordion ( ) ;
607+ }
608+
573609 /**
574610 * Add initial attributes to accordion elements.
575611 * @param {Element } button - A button element that triggers an accordion.
@@ -590,13 +626,13 @@ class Accordion extends Utils {
590626
591627 const accordionRow = document . querySelector ( accordionRowAttr ) ;
592628 const buttonHeaderAttr = this . _getPossibleAccordionHeaderAttrs ( accordionRowAttr ) ;
593- const buttonHeader = this . getElements ( buttonHeaderAttr ) [ 0 ] ;
629+ const buttonHeader = document . querySelectorAll ( buttonHeaderAttr ) [ 0 ] ;
594630
595631 if ( ! buttonHeader || ! buttonHeader . id ) {
596632 console . error ( Messages$1 . NO_HEADER_ID_ERROR ( buttonId ) ) ;
597633 }
598634
599- const buttonContentChildren = this . getFocusableElements ( `#${ buttonContent . id } ` ) ;
635+ const buttonContentChildren = getFocusableElements ( `#${ buttonContent . id } ` ) ;
600636
601637 button . setAttribute ( Selectors$2 . ARIA_CONTROLS , buttonId ) ;
602638 buttonContent . setAttribute ( Selectors$2 . ARIA_LABELLEDBY , buttonHeader . id ) ;
@@ -653,42 +689,6 @@ class Accordion extends Utils {
653689 return `[${ Selectors$2 . DATA_ACCORDION_ROW } ='${ id } ']`
654690 }
655691
656- /**
657- * Open accordion content associated with an accordion button.
658- * @param {Object } event - The event object
659- */
660- _render ( event ) {
661- event . preventDefault ( ) ;
662-
663- this . _activeButton = event . target ;
664- this . _activeAccordionRowId = this . _activeButton . getAttribute ( Selectors$2 . DATA_TARGET ) ;
665-
666- this . _activeRowAttr = this . _getAccordionRowAttr ( this . _activeAccordionRowId ) ;
667- this . _activeRow = document . querySelector ( this . _activeRowAttr ) ;
668-
669- if ( ! this . _activeButton . getAttribute ( Selectors$2 . DATA_PARENT ) ) {
670- return console . error ( Messages$1 . NO_PARENT_ERROR ( this . _activeAccordionRowId ) )
671- }
672-
673- this . _activeContainerId = this . _activeButton . getAttribute ( Selectors$2 . DATA_PARENT ) ;
674- this . _activeContainerAttr = `[${ Selectors$2 . DATA_ACCORDION } ='${ this . _activeContainerId } ']` ;
675-
676- if ( ! document . querySelector ( this . _activeContainerAttr ) ) {
677- return console . error ( Messages$1 . NO_ACCORDION_ERROR ( this . _activeContainerId ) )
678- }
679-
680- this . _activeContainer = document . querySelector ( this . _activeContainerAttr ) ;
681- this . _activeContent = document . getElementById ( this . _activeAccordionRowId ) ;
682-
683- const accordionButtonState = this . _activeRow . getAttribute ( Selectors$2 . DATA_VISIBLE ) ;
684-
685- this . _activeButtonExpandState = accordionButtonState === "true" ? "false" : "true" ;
686- this . _activeContentHiddenState = this . _activeButtonExpandState === "false" ? "true" : "false" ;
687-
688- this . _closeAllIfToggleable ( ) ;
689- this . _toggleSelectedAccordion ( ) ;
690- }
691-
692692 /**
693693 * If toggling multiple rows at once isn't enabled, close all rows except the selected one.
694694 * This ensures the selected one can be closed if it's already open.
@@ -697,17 +697,19 @@ class Accordion extends Utils {
697697 if ( this . _activeContainer . hasAttribute ( Selectors$2 . DATA_TOGGLE_MULTIPLE ) ) return
698698
699699 const allContentAttr = `${ this . _activeContainerAttr } [${ Selectors$2 . ARIA_HIDDEN } ]` ;
700- const allRows = this . getElements ( `${ this . _activeContainerAttr } [${ Selectors$2 . DATA_VISIBLE } ]` ) ;
701- const allContent = this . getElements ( allContentAttr ) ;
700+ const allRows = document . querySelectorAll (
701+ `${ this . _activeContainerAttr } [${ Selectors$2 . DATA_VISIBLE } ]`
702+ ) ;
703+ const allContent = document . querySelectorAll ( allContentAttr ) ;
702704
703705 const accordionButtonSelector = this . _getPossibleAccordionButtonAttrs ( this . _activeContainerAttr ) ;
704- const allButtons = this . getElements ( accordionButtonSelector ) ;
706+ const allButtons = document . querySelectorAll ( accordionButtonSelector ) ;
705707
706708 allContent . forEach ( content => {
707709 if ( content !== this . _activeContent ) content . style . maxHeight = null ;
708710 } ) ;
709711
710- this . getFocusableElements ( allContentAttr ) . forEach ( element => {
712+ getFocusableElements ( allContentAttr ) . forEach ( element => {
711713 element . setAttribute ( Selectors$2 . TABINDEX , "-1" ) ;
712714 } ) ;
713715
@@ -725,7 +727,7 @@ class Accordion extends Utils {
725727 this . _activeContent . setAttribute ( Selectors$2 . ARIA_HIDDEN , this . _activeContentHiddenState ) ;
726728
727729 const activeContentBlock = `#${ this . _activeAccordionRowId } ` ;
728- this . getFocusableElements ( activeContentBlock ) . forEach ( element => {
730+ getFocusableElements ( activeContentBlock ) . forEach ( element => {
729731 const value = this . _activeButtonExpandState === "true" ? "0" : "-1" ;
730732 element . setAttribute ( Selectors$2 . TABINDEX , value ) ;
731733 } ) ;
@@ -780,7 +782,6 @@ const Selectors$3 = {
780782const Events$3 = {
781783 KEYDOWN : "keydown" ,
782784 CLICK : "click" ,
783- TOUCHEND : "touchend" ,
784785} ;
785786
786787const Messages$2 = {
@@ -798,6 +799,8 @@ class Dropdown extends Utils {
798799 constructor ( ) {
799800 super ( ) ;
800801
802+ this . _iosMobile = / ( i p h o n e | i p o d ) / i. test ( navigator . userAgent ) ;
803+
801804 // events
802805 this . _render = this . _render . bind ( this ) ;
803806 this . _handleFirstTabClose = this . _handleFirstTabClose . bind ( this ) ;
@@ -833,8 +836,8 @@ class Dropdown extends Utils {
833836 * Begin listening to dropdowns for events.
834837 */
835838 start ( ) {
836- this . _dropdowns = this . getElements ( `${ this . _dropdownContainerAttr } ` ) ;
837- this . _dropdownButtons = this . getElements (
839+ this . _dropdowns = document . querySelectorAll ( `${ this . _dropdownContainerAttr } ` ) ;
840+ this . _dropdownButtons = document . querySelectorAll (
838841 `${ this . _dropdownContainerAttr } > ${ this . _dropdownTargetAttr } `
839842 ) ;
840843
@@ -907,7 +910,11 @@ class Dropdown extends Utils {
907910
908911 document . addEventListener ( Events$3 . KEYDOWN , this . _handleEscapeKeyPress ) ;
909912 document . addEventListener ( Events$3 . CLICK , this . _handleOffMenuClick ) ;
910- document . addEventListener ( Events$3 . TOUCHEND , this . _handleOffMenuClick ) ;
913+
914+ // make click events work on mobile iOS
915+ if ( this . _iosMobile ) {
916+ document . body . style . cursor = "pointer" ;
917+ }
911918
912919 this . _activeDropdownLinks = this . _getDropdownLinks ( this . _activeDropdownAttr ) ;
913920
@@ -988,8 +995,12 @@ class Dropdown extends Utils {
988995 this . _activeDropdownButton . addEventListener ( Events$3 . CLICK , this . _render ) ;
989996
990997 document . removeEventListener ( Events$3 . KEYDOWN , this . _handleEscapeKeyPress ) ;
998+
999+ if ( this . _iosMobile ) {
1000+ document . body . style . cursor = "auto" ;
1001+ }
1002+
9911003 document . removeEventListener ( Events$3 . CLICK , this . _handleOffMenuClick ) ;
992- document . removeEventListener ( Events$3 . TOUCHEND , this . _handleOffMenuClick ) ;
9931004
9941005 if ( this . _allowFocusReturn ) {
9951006 this . _handleReturnFocus ( ) ;
@@ -1033,7 +1044,7 @@ class Dropdown extends Utils {
10331044 * @return {String } - Selector for possible menu item links.
10341045 */
10351046 _getDropdownLinks ( attr ) {
1036- return this . getElements ( `${ attr } > ul > li > a, ${ attr } > ul > li > button` )
1047+ return document . querySelectorAll ( `${ attr } > ul > li > a, ${ attr } > ul > li > button` )
10371048 }
10381049
10391050 /**
@@ -1057,7 +1068,7 @@ class Dropdown extends Utils {
10571068 dropdownButton . setAttribute ( Selectors$3 . ARIA_EXPANDED , "false" ) ;
10581069 dropdownMenu . setAttribute ( Selectors$3 . ARIA_LABELLEDBY , dropdownButton . id ) ;
10591070
1060- const dropdownMenuItems = this . getElements ( dropdownMenuItemsAttr ) ;
1071+ const dropdownMenuItems = document . querySelectorAll ( dropdownMenuItemsAttr ) ;
10611072 dropdownMenuItems . forEach ( item => item . setAttribute ( Selectors$3 . ROLE , "none" ) ) ;
10621073
10631074 this . _getDropdownLinks ( dropdownIdAttr ) . forEach ( link => {
0 commit comments