@@ -4,21 +4,21 @@ import { Component } from '../abstract/component'
4
4
/** @type {string } The primary navigation block name. */
5
5
const BLOCK_PRIMARY_NAVIGATION = 'primary-navigation'
6
6
7
- /** @type {NodeList<HTMLElement> } The primary navigation block name. */
8
- const PRIMARY_NAVIGATIONS = BEM . getBEMNodes ( BLOCK_PRIMARY_NAVIGATION )
9
-
10
7
/** @type {string } The dismissed modifier state, overrides focus/hover. */
11
8
const MODIFIER_DISMISSED = 'dismissed'
12
9
13
- /** Handler to bypass Safari bug */
14
- const navigationToggle = document . querySelectorAll (
15
- '.primary-navigation--toggle'
16
- )
17
-
18
10
/**
19
11
* Controls the primary navigation and dismissing it using the escape key.
20
12
*/
21
13
class PrimaryNavigation extends Component {
14
+ constructor ( node , initialState = { dismissed : false } ) {
15
+ super ( node , initialState )
16
+ /** Handler to bypass Safari bug */
17
+ this . navigationToggle = this . node . querySelectorAll (
18
+ '.primary-navigation--desktop .primary-navigation--toggle'
19
+ )
20
+ }
21
+
22
22
/**
23
23
* Binds events to callbacks.
24
24
* Callbacks should trigger `setState` which in turn triggers `render`.
@@ -36,54 +36,71 @@ class PrimaryNavigation extends Component {
36
36
* Focusin and Focusout are used instead of Focus for Safari
37
37
*/
38
38
onFocusOut ( ) {
39
- this . node . classList . remove ( 'primary-navigation--open' )
39
+ if ( this . node ) {
40
+ BEM . removeModifier ( this . node , 'open' )
41
+ }
42
+ this . navigationToggle . forEach ( ( toggle ) => {
43
+ toggle . setAttribute ( 'aria-expanded' , 'false' )
44
+ } )
40
45
}
41
46
42
47
/**
43
48
* Gets called when `node` is clicked.
44
49
* Clears the dismissed state, (prevents overriding focus/toggle).
45
50
*/
46
51
toggleDesktopNavOpen ( ) {
47
- this . node . classList . toggle ( 'primary-navigation--open' )
48
- // Safari specific
49
- this . node . classList . remove ( 'primary-navigation--dismissed' )
50
- this . node . classList . remove ( 'primary-navigation__main--dismissed' )
52
+ if ( this . node ) {
53
+ const isOpen = BEM . hasModifier ( this . node , 'open' )
54
+ BEM . toggleModifier ( this . node , 'open' , ! isOpen )
55
+ BEM . toggleModifier ( this . node , MODIFIER_DISMISSED )
56
+
57
+ if ( BLOCK_PRIMARY_NAVIGATION ) {
58
+ BEM . removeModifier ( this . node , MODIFIER_DISMISSED )
59
+ }
60
+ // Safari specific
61
+ this . navigationToggle . forEach ( ( toggle ) => {
62
+ toggle . setAttribute ( 'aria-expanded' , isOpen ? 'false' : 'true' )
63
+ } )
64
+ }
51
65
}
52
66
53
67
/**
54
68
* Gets called when a key is released.
55
69
* If key is escape key, explicitly dismiss the menu (overriding focus/hover).
56
- // * @param {KeyboardEvent } event
70
+ * @param {KeyboardEvent } event
57
71
*/
58
72
onKeyUp ( event ) {
59
73
if ( event . key === 'Escape' ) {
60
74
this . setState ( { dismissed : true } )
61
- this . node . blur ( )
62
- this . node . classList . remove ( 'primary-navigation--open' )
63
- // Safari specific
64
- navigationToggle . forEach ( ( elem ) => {
65
- elem . blur ( )
66
- } )
75
+ if ( this . node ) {
76
+ this . node . blur ( )
77
+ // Safari specific
78
+ this . navigationToggle . forEach ( ( elem ) => elem . blur ( ) )
79
+ }
67
80
}
68
81
}
69
82
70
83
/**
71
84
* Persists state to DOM.
72
85
* Rendering should be one-way traffic and not inspect any current values in DOM.
73
- // * @param {Object } state State to render.
86
+ * @param {Object } state State to render.
74
87
*/
75
88
render ( state ) {
76
- BEM . toggleModifier ( this . node , MODIFIER_DISMISSED , state . dismissed )
77
-
78
- if ( state . dismissed ) {
79
- this . node . blur ( )
89
+ if ( this . node ) {
90
+ BEM . toggleModifier ( this . node , MODIFIER_DISMISSED , state . dismissed )
80
91
81
- return this . node . querySelector ( '.primary-navigation--toggle' )
92
+ if ( state . dismissed ) {
93
+ this . node . blur ( )
94
+ }
82
95
}
83
96
}
84
97
}
85
98
86
99
// Start!
87
- ; [ ...PRIMARY_NAVIGATIONS ] . forEach (
88
- ( node ) => new PrimaryNavigation ( node , { dismissed : false } )
89
- )
100
+ document . addEventListener ( 'DOMContentLoaded' , ( ) => {
101
+ BEM . getBEMNodes ( BLOCK_PRIMARY_NAVIGATION ) . forEach ( ( node ) => {
102
+ if ( node ) {
103
+ new PrimaryNavigation ( node , { dismissed : false } )
104
+ }
105
+ } )
106
+ } )
0 commit comments