nsw-design-system 3.9.0 → 3.9.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/css/main.css +1 -1
- package/dist/js/main.js +78 -82
- package/package.json +1 -1
- package/src/components/filters/_filters.scss +18 -11
- package/src/components/filters/filters.js +1 -1
- package/src/components/main-nav/_main-nav.scss +10 -1
- package/src/components/main-nav/main-nav.js +82 -83
- package/src/main.js +4 -2
package/dist/js/main.js
CHANGED
|
@@ -141,16 +141,15 @@
|
|
|
141
141
|
};
|
|
142
142
|
|
|
143
143
|
class Navigation {
|
|
144
|
-
constructor() {
|
|
144
|
+
constructor(element) {
|
|
145
|
+
this.nav = element;
|
|
146
|
+
this.navID = this.nav.id;
|
|
145
147
|
this.openNavButton = document.querySelector('.js-open-nav');
|
|
146
|
-
this.closeNavButtons =
|
|
147
|
-
this.
|
|
148
|
-
this.
|
|
149
|
-
this.
|
|
150
|
-
this.isMegaMenuElement = !!document.querySelector('.js-mega-menu');
|
|
148
|
+
this.closeNavButtons = this.nav.querySelectorAll('.js-close-nav');
|
|
149
|
+
this.closeSubNavButtons = this.nav.querySelectorAll('.js-close-sub-nav');
|
|
150
|
+
this.isMegaMenuElement = this.nav.classList.contains('js-mega-menu');
|
|
151
|
+
this.mainNavIsOpen = false;
|
|
151
152
|
this.transitionEvent = whichTransitionEvent();
|
|
152
|
-
this.mobileToggleMainNavEvent = e => this.mobileToggleMainNav(e);
|
|
153
|
-
this.mobileToggleSubNavEvent = () => this.closeSubNav();
|
|
154
153
|
this.mobileShowMainTransitionEndEvent = e => this.mobileShowMainNav(e);
|
|
155
154
|
this.mobileHideMainTransitionEndEvent = e => this.mobileHideMainNav(e);
|
|
156
155
|
this.showSubNavTransitionEndEvent = e => this.showSubNav(e);
|
|
@@ -159,48 +158,52 @@
|
|
|
159
158
|
this.desktopButtonClickEvent = e => this.buttonClickDesktop(e);
|
|
160
159
|
this.desktopButtonKeydownEvent = e => this.buttonKeydownDesktop(e);
|
|
161
160
|
this.checkFocusEvent = e => this.checkIfContainsFocus(e);
|
|
162
|
-
this.escapeCloseEvent = e => this.escapeClose(e);
|
|
163
|
-
this.outsideClickEvent = e => this.handleOutsideClick(e);
|
|
164
161
|
this.openSubNavElements = [];
|
|
165
162
|
this.breakpoint = window.matchMedia('(min-width: 62em)');
|
|
166
|
-
this.body = document.body;
|
|
167
163
|
}
|
|
168
164
|
init() {
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
this.breakpoint.
|
|
173
|
-
this.addOutsideClickListener();
|
|
165
|
+
this.initEvents();
|
|
166
|
+
this.responsiveCheck(this.breakpoint);
|
|
167
|
+
if (this.nav) {
|
|
168
|
+
this.breakpoint.addEventListener('change', event => this.responsiveCheck(event));
|
|
174
169
|
}
|
|
175
170
|
}
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
document.removeEventListener('click', this.outsideClickEvent, false);
|
|
181
|
-
}
|
|
182
|
-
handleOutsideClick(event) {
|
|
183
|
-
const isOutsideNav = !this.mainNavElement.contains(event.target);
|
|
184
|
-
if (isOutsideNav) {
|
|
185
|
-
this.saveElements(event);
|
|
186
|
-
this.toggleSubNavDesktop(true);
|
|
187
|
-
event.preventDefault();
|
|
171
|
+
initEvents() {
|
|
172
|
+
if (this.isMegaMenuElement) {
|
|
173
|
+
document.addEventListener('click', this.handleOutsideClick.bind(this), false);
|
|
174
|
+
document.addEventListener('keydown', this.escapeClose.bind(this), false);
|
|
188
175
|
}
|
|
176
|
+
this.openNavButton.addEventListener('click', this.mobileToggleMainNav.bind(this), false);
|
|
177
|
+
this.closeNavButtons.forEach(element => {
|
|
178
|
+
element.addEventListener('click', this.mobileToggleMainNav.bind(this), false);
|
|
179
|
+
});
|
|
180
|
+
this.closeSubNavButtons.forEach(element => {
|
|
181
|
+
element.addEventListener('click', this.closeSubNav.bind(this), false);
|
|
182
|
+
});
|
|
189
183
|
}
|
|
190
|
-
responsiveCheck(
|
|
184
|
+
responsiveCheck(event) {
|
|
191
185
|
let megaMenuListItems = [];
|
|
192
|
-
if (
|
|
193
|
-
megaMenuListItems = [].slice.call(this.
|
|
194
|
-
|
|
186
|
+
if (event.matches) {
|
|
187
|
+
megaMenuListItems = [].slice.call(this.nav.querySelectorAll('ul > li'));
|
|
188
|
+
document.body.classList.remove('main-nav-active');
|
|
195
189
|
} else {
|
|
196
|
-
megaMenuListItems = [].slice.call(this.
|
|
190
|
+
megaMenuListItems = [].slice.call(this.nav.querySelectorAll('li'));
|
|
197
191
|
}
|
|
198
192
|
this.tearDownNavControls();
|
|
199
193
|
this.setUpNavControls(megaMenuListItems);
|
|
200
194
|
}
|
|
195
|
+
handleOutsideClick(event) {
|
|
196
|
+
// removes handleOutsideClick functionality from docs site
|
|
197
|
+
if (this.nav.closest('.nsw-docs')) return;
|
|
198
|
+
if (!this.mainNavIsOpen) return;
|
|
199
|
+
const isOutsideNav = !this.nav.contains(event.target);
|
|
200
|
+
if (isOutsideNav) {
|
|
201
|
+
this.toggleSubNavDesktop(true);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
201
204
|
tearDownNavControls() {
|
|
202
205
|
if (this.isMegaMenuElement) {
|
|
203
|
-
const listItems = [].slice.call(this.
|
|
206
|
+
const listItems = [].slice.call(this.nav.querySelectorAll('li'));
|
|
204
207
|
listItems.forEach(item => {
|
|
205
208
|
const submenu = item.querySelector('[id^=sub-nav-]');
|
|
206
209
|
const link = item.querySelector('a');
|
|
@@ -214,19 +217,6 @@
|
|
|
214
217
|
});
|
|
215
218
|
}
|
|
216
219
|
}
|
|
217
|
-
setUpMobileControls() {
|
|
218
|
-
this.openNavButton.addEventListener('click', this.mobileToggleMainNavEvent, false);
|
|
219
|
-
this.closeNavButtons.forEach(element => {
|
|
220
|
-
element.addEventListener('click', this.mobileToggleMainNavEvent, false);
|
|
221
|
-
});
|
|
222
|
-
this.closeSubNavButtons.forEach(element => {
|
|
223
|
-
element.addEventListener('click', this.mobileToggleSubNavEvent, false);
|
|
224
|
-
});
|
|
225
|
-
}
|
|
226
|
-
mobileMainNavTrapTabs(e) {
|
|
227
|
-
const elemObj = getFocusableElementBySelector(this.mainNavElement.id, ['> div button', '> ul > li > a']);
|
|
228
|
-
trapTabKey(e, elemObj);
|
|
229
|
-
}
|
|
230
220
|
setUpNavControls(listItems) {
|
|
231
221
|
if (this.isMegaMenuElement) {
|
|
232
222
|
listItems.forEach(item => {
|
|
@@ -238,29 +228,32 @@
|
|
|
238
228
|
link.setAttribute('aria-controls', submenu.id);
|
|
239
229
|
link.addEventListener('click', this.desktopButtonClickEvent, false);
|
|
240
230
|
link.addEventListener('keydown', this.desktopButtonKeydownEvent, false);
|
|
241
|
-
document.addEventListener('keydown', this.escapeCloseEvent, false);
|
|
242
231
|
}
|
|
243
232
|
});
|
|
244
233
|
}
|
|
245
234
|
}
|
|
235
|
+
mobileMainNavTrapTabs(e) {
|
|
236
|
+
const elemObj = getFocusableElementBySelector(this.navID, ['> div button', '> ul > li > a']);
|
|
237
|
+
trapTabKey(e, elemObj);
|
|
238
|
+
}
|
|
246
239
|
mobileShowMainNav(_ref) {
|
|
247
240
|
let {
|
|
248
241
|
propertyName
|
|
249
242
|
} = _ref;
|
|
250
|
-
if (
|
|
251
|
-
getFocusableElementBySelector(this.
|
|
252
|
-
this.
|
|
253
|
-
this.
|
|
254
|
-
this.
|
|
255
|
-
this.
|
|
243
|
+
if (propertyName !== 'transform') return;
|
|
244
|
+
getFocusableElementBySelector(this.navID, ['> div button', '> ul > li > a']).all[1].focus();
|
|
245
|
+
this.nav.classList.add('active');
|
|
246
|
+
this.nav.classList.remove('activating');
|
|
247
|
+
this.nav.removeEventListener(this.transitionEvent, this.mobileShowMainTransitionEndEvent, false);
|
|
248
|
+
this.nav.addEventListener('keydown', this.mobileTrapTabKeyEvent, false);
|
|
256
249
|
}
|
|
257
250
|
mobileHideMainNav(_ref2) {
|
|
258
251
|
let {
|
|
259
252
|
propertyName
|
|
260
253
|
} = _ref2;
|
|
261
|
-
if (
|
|
262
|
-
this.
|
|
263
|
-
this.
|
|
254
|
+
if (propertyName !== 'transform') return;
|
|
255
|
+
this.nav.classList.remove('active');
|
|
256
|
+
this.nav.classList.remove('closing');
|
|
264
257
|
while (this.openSubNavElements.length > 0) {
|
|
265
258
|
const {
|
|
266
259
|
submenu
|
|
@@ -270,8 +263,8 @@
|
|
|
270
263
|
submenu.classList.remove('closing');
|
|
271
264
|
this.openSubNavElements.pop();
|
|
272
265
|
}
|
|
273
|
-
this.
|
|
274
|
-
this.
|
|
266
|
+
this.nav.removeEventListener(this.transitionEvent, this.mobileHideMainTransitionEndEvent, false);
|
|
267
|
+
this.nav.removeEventListener('keydown', this.mobileTrapTabKeyEvent, false);
|
|
275
268
|
}
|
|
276
269
|
mobileToggleMainNav(e) {
|
|
277
270
|
const {
|
|
@@ -279,29 +272,29 @@
|
|
|
279
272
|
} = e;
|
|
280
273
|
const isExpanded = currentTarget.getAttribute('aria-expanded') === 'true';
|
|
281
274
|
if (isExpanded) {
|
|
282
|
-
|
|
275
|
+
document.body.classList.remove('main-nav-active');
|
|
283
276
|
this.openNavButton.focus();
|
|
284
|
-
this.
|
|
285
|
-
this.
|
|
277
|
+
this.nav.classList.add('closing');
|
|
278
|
+
this.nav.addEventListener(this.transitionEvent, this.mobileHideMainTransitionEndEvent, false);
|
|
286
279
|
} else {
|
|
287
|
-
|
|
288
|
-
this.
|
|
289
|
-
this.
|
|
280
|
+
document.body.classList.add('main-nav-active');
|
|
281
|
+
this.nav.classList.add('activating');
|
|
282
|
+
this.nav.addEventListener(this.transitionEvent, this.mobileShowMainTransitionEndEvent, false);
|
|
290
283
|
}
|
|
291
284
|
}
|
|
292
|
-
buttonClickDesktop(
|
|
285
|
+
buttonClickDesktop(event) {
|
|
293
286
|
const isDesktop = this.breakpoint.matches;
|
|
294
|
-
if (!isDesktop || !
|
|
295
|
-
this.saveElements(
|
|
287
|
+
if (!isDesktop || !event.target.closest('.nsw-main-nav__sub-nav')) {
|
|
288
|
+
this.saveElements(event);
|
|
296
289
|
this.toggleSubNavDesktop();
|
|
297
|
-
|
|
290
|
+
event.preventDefault();
|
|
298
291
|
}
|
|
299
292
|
}
|
|
300
|
-
buttonKeydownDesktop(
|
|
301
|
-
if (
|
|
302
|
-
this.saveElements(
|
|
293
|
+
buttonKeydownDesktop(event) {
|
|
294
|
+
if (event.key === ' ' || event.key === 'Enter' || event.key === 'Spacebar') {
|
|
295
|
+
this.saveElements(event);
|
|
303
296
|
this.toggleSubNavDesktop();
|
|
304
|
-
|
|
297
|
+
event.preventDefault();
|
|
305
298
|
}
|
|
306
299
|
}
|
|
307
300
|
escapeClose(e) {
|
|
@@ -335,7 +328,7 @@
|
|
|
335
328
|
const {
|
|
336
329
|
submenu
|
|
337
330
|
} = this.whichSubNavLatest();
|
|
338
|
-
if (
|
|
331
|
+
if (propertyName !== 'transform') return;
|
|
339
332
|
getFocusableElementBySelector(submenu.id, ['> div button', '> .nsw-main-nav__title a', '> ul > li > a']).all[2].focus();
|
|
340
333
|
submenu.removeEventListener(this.transitionEvent, this.showSubNavTransitionEndEvent, false);
|
|
341
334
|
}
|
|
@@ -347,9 +340,9 @@
|
|
|
347
340
|
if (this.breakpoint.matches) {
|
|
348
341
|
link.setAttribute('aria-expanded', false);
|
|
349
342
|
link.classList.remove('active');
|
|
350
|
-
this.
|
|
343
|
+
this.nav.removeEventListener('focus', this.checkFocusEvent, true);
|
|
351
344
|
// fix: workaround for safari because it doesn't support focus event
|
|
352
|
-
this.
|
|
345
|
+
this.nav.removeEventListener('click', this.checkFocusEvent, true);
|
|
353
346
|
} else {
|
|
354
347
|
link.focus();
|
|
355
348
|
submenu.removeEventListener('keydown', this.mobileSubNavTrapTabKeyEvent, false);
|
|
@@ -366,9 +359,9 @@
|
|
|
366
359
|
if (this.breakpoint.matches) {
|
|
367
360
|
link.setAttribute('aria-expanded', true);
|
|
368
361
|
link.classList.add('active');
|
|
369
|
-
this.
|
|
362
|
+
this.nav.addEventListener('focus', this.checkFocusEvent, true);
|
|
370
363
|
// fix: workaround for safari because it doesn't support focus event
|
|
371
|
-
this.
|
|
364
|
+
this.nav.addEventListener('click', this.checkFocusEvent, true);
|
|
372
365
|
} else {
|
|
373
366
|
submenu.addEventListener('keydown', this.mobileSubNavTrapTabKeyEvent, false);
|
|
374
367
|
submenu.addEventListener(this.transitionEvent, this.showSubNavTransitionEndEvent, false);
|
|
@@ -383,8 +376,10 @@
|
|
|
383
376
|
} = this.whichSubNavLatest();
|
|
384
377
|
const isExpanded = link.getAttribute('aria-expanded') === 'true';
|
|
385
378
|
if (isExpanded) {
|
|
379
|
+
this.mainNavIsOpen = false;
|
|
386
380
|
this.closeSubNav();
|
|
387
381
|
} else {
|
|
382
|
+
this.mainNavIsOpen = true;
|
|
388
383
|
this.openSubNav();
|
|
389
384
|
}
|
|
390
385
|
}
|
|
@@ -592,7 +587,7 @@
|
|
|
592
587
|
this.filtersItems = element.querySelectorAll('.nsw-filters__item');
|
|
593
588
|
/* eslint-disable max-len */
|
|
594
589
|
this.focusableEls = this.filtersWrapper.querySelectorAll('a[href]:not([disabled]), button:not([disabled]), textarea:not([disabled]), input[type="text"]:not([disabled]), input[type="radio"]:not([disabled]), input[type="checkbox"]:not([disabled]), select:not([disabled])');
|
|
595
|
-
this.checkIcon = '<span class="material-icons nsw-material-icons" focusable="false" aria-hidden="true">check_circle</span>';
|
|
590
|
+
this.checkIcon = '<span class="material-icons nsw-material-icons nsw-material-icons--valid" focusable="false" aria-hidden="true">check_circle</span>';
|
|
596
591
|
this.arrowIcon = '<span class="material-icons nsw-material-icons" focusable="false" aria-hidden="true">keyboard_arrow_right</span>';
|
|
597
592
|
/* eslint-ensable max-len */
|
|
598
593
|
this.showEvent = e => this.showFilters(e);
|
|
@@ -3188,6 +3183,7 @@
|
|
|
3188
3183
|
// Header Search
|
|
3189
3184
|
const openSearchButton = document.querySelectorAll('.js-open-search');
|
|
3190
3185
|
const closeSearchButton = document.querySelectorAll('.js-close-search');
|
|
3186
|
+
const navigation = document.getElementById('main-nav');
|
|
3191
3187
|
const accordions = document.querySelectorAll('.js-accordion');
|
|
3192
3188
|
const dialogs = document.querySelectorAll('.js-dialog');
|
|
3193
3189
|
const fileUpload = document.querySelectorAll('.js-file-upload');
|
|
@@ -3204,9 +3200,9 @@
|
|
|
3204
3200
|
closeSearchButton.forEach(element => {
|
|
3205
3201
|
new SiteSearch(element).init();
|
|
3206
3202
|
});
|
|
3207
|
-
|
|
3208
|
-
|
|
3209
|
-
|
|
3203
|
+
if (navigation) {
|
|
3204
|
+
new Navigation(navigation).init();
|
|
3205
|
+
}
|
|
3210
3206
|
accordions.forEach(element => {
|
|
3211
3207
|
new Accordion(element).init();
|
|
3212
3208
|
});
|
package/package.json
CHANGED
|
@@ -368,19 +368,26 @@
|
|
|
368
368
|
span:not(.nsw-material-icons) {
|
|
369
369
|
display: flex;
|
|
370
370
|
align-items: center;
|
|
371
|
-
|
|
371
|
+
}
|
|
372
372
|
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
373
|
+
.nsw-material-icons {
|
|
374
|
+
font-size: rem(map-get($nsw-icon-sizes, 20));
|
|
375
|
+
margin-left: rem(8px);
|
|
376
|
+
border-radius: 50%;
|
|
377
|
+
width: rem(16px);
|
|
378
|
+
height: rem(16px);
|
|
379
|
+
display: flex;
|
|
380
|
+
justify-content: center;
|
|
381
|
+
align-items: center;
|
|
382
|
+
|
|
383
|
+
&--error {
|
|
384
|
+
background-color: var(--nsw-status-error-bg);
|
|
385
|
+
color: var(--nsw-status-error);
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
&--valid {
|
|
389
|
+
background-color: var(--nsw-status-success-bg);
|
|
376
390
|
color: var(--nsw-status-success);
|
|
377
|
-
margin-left: rem(8px);
|
|
378
|
-
border-radius: 50%;
|
|
379
|
-
width: rem(16px);
|
|
380
|
-
height: rem(16px);
|
|
381
|
-
display: flex;
|
|
382
|
-
justify-content: center;
|
|
383
|
-
align-items: center;
|
|
384
391
|
}
|
|
385
392
|
}
|
|
386
393
|
|
|
@@ -19,7 +19,7 @@ class Filters {
|
|
|
19
19
|
this.filtersItems = element.querySelectorAll('.nsw-filters__item')
|
|
20
20
|
/* eslint-disable max-len */
|
|
21
21
|
this.focusableEls = this.filtersWrapper.querySelectorAll('a[href]:not([disabled]), button:not([disabled]), textarea:not([disabled]), input[type="text"]:not([disabled]), input[type="radio"]:not([disabled]), input[type="checkbox"]:not([disabled]), select:not([disabled])')
|
|
22
|
-
this.checkIcon = '<span class="material-icons nsw-material-icons" focusable="false" aria-hidden="true">check_circle</span>'
|
|
22
|
+
this.checkIcon = '<span class="material-icons nsw-material-icons nsw-material-icons--valid" focusable="false" aria-hidden="true">check_circle</span>'
|
|
23
23
|
this.arrowIcon = '<span class="material-icons nsw-material-icons" focusable="false" aria-hidden="true">keyboard_arrow_right</span>'
|
|
24
24
|
/* eslint-ensable max-len */
|
|
25
25
|
this.showEvent = (e) => this.showFilters(e)
|
|
@@ -81,6 +81,14 @@
|
|
|
81
81
|
position: relative;
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
+
> li {
|
|
85
|
+
@include breakpoint($nsw-desktop-breakpoint) {
|
|
86
|
+
&.active {
|
|
87
|
+
box-shadow: inset 0 -4px 0 var(--nsw-brand-dark);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
84
92
|
> li > a {
|
|
85
93
|
@include breakpoint($nsw-desktop-breakpoint) {
|
|
86
94
|
.nsw-material-icons {
|
|
@@ -90,6 +98,7 @@
|
|
|
90
98
|
|
|
91
99
|
&.active {
|
|
92
100
|
background-color: var(--nsw-white);
|
|
101
|
+
box-shadow: inset 0 -4px 0 var(--nsw-brand-dark);
|
|
93
102
|
}
|
|
94
103
|
|
|
95
104
|
&.active .nsw-material-icons {
|
|
@@ -261,7 +270,7 @@
|
|
|
261
270
|
}
|
|
262
271
|
|
|
263
272
|
&:nth-last-child(-n+3) {
|
|
264
|
-
|
|
273
|
+
box-shadow: inset 0 -1px 0 var(--nsw-grey-04);
|
|
265
274
|
}
|
|
266
275
|
|
|
267
276
|
a {
|
|
@@ -3,16 +3,15 @@ import {
|
|
|
3
3
|
} from '../../global/scripts/helpers/utilities'
|
|
4
4
|
|
|
5
5
|
class Navigation {
|
|
6
|
-
constructor() {
|
|
6
|
+
constructor(element) {
|
|
7
|
+
this.nav = element
|
|
8
|
+
this.navID = this.nav.id
|
|
7
9
|
this.openNavButton = document.querySelector('.js-open-nav')
|
|
8
|
-
this.closeNavButtons =
|
|
9
|
-
this.
|
|
10
|
-
this.
|
|
11
|
-
this.
|
|
12
|
-
this.isMegaMenuElement = !!document.querySelector('.js-mega-menu')
|
|
10
|
+
this.closeNavButtons = this.nav.querySelectorAll('.js-close-nav')
|
|
11
|
+
this.closeSubNavButtons = this.nav.querySelectorAll('.js-close-sub-nav')
|
|
12
|
+
this.isMegaMenuElement = this.nav.classList.contains('js-mega-menu')
|
|
13
|
+
this.mainNavIsOpen = false
|
|
13
14
|
this.transitionEvent = whichTransitionEvent()
|
|
14
|
-
this.mobileToggleMainNavEvent = (e) => this.mobileToggleMainNav(e)
|
|
15
|
-
this.mobileToggleSubNavEvent = () => this.closeSubNav()
|
|
16
15
|
this.mobileShowMainTransitionEndEvent = (e) => this.mobileShowMainNav(e)
|
|
17
16
|
this.mobileHideMainTransitionEndEvent = (e) => this.mobileHideMainNav(e)
|
|
18
17
|
this.showSubNavTransitionEndEvent = (e) => this.showSubNav(e)
|
|
@@ -21,55 +20,64 @@ class Navigation {
|
|
|
21
20
|
this.desktopButtonClickEvent = (e) => this.buttonClickDesktop(e)
|
|
22
21
|
this.desktopButtonKeydownEvent = (e) => this.buttonKeydownDesktop(e)
|
|
23
22
|
this.checkFocusEvent = (e) => this.checkIfContainsFocus(e)
|
|
24
|
-
this.escapeCloseEvent = (e) => this.escapeClose(e)
|
|
25
|
-
this.outsideClickEvent = (e) => this.handleOutsideClick(e)
|
|
26
23
|
this.openSubNavElements = []
|
|
27
24
|
this.breakpoint = window.matchMedia('(min-width: 62em)')
|
|
28
|
-
this.body = document.body
|
|
29
25
|
}
|
|
30
26
|
|
|
31
27
|
init() {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
this.
|
|
28
|
+
this.initEvents()
|
|
29
|
+
this.responsiveCheck(this.breakpoint)
|
|
30
|
+
|
|
31
|
+
if (this.nav) {
|
|
32
|
+
this.breakpoint.addEventListener('change', (event) => this.responsiveCheck(event))
|
|
37
33
|
}
|
|
38
34
|
}
|
|
39
35
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
36
|
+
initEvents() {
|
|
37
|
+
if (this.isMegaMenuElement) {
|
|
38
|
+
document.addEventListener('click', this.handleOutsideClick.bind(this), false)
|
|
39
|
+
document.addEventListener('keydown', this.escapeClose.bind(this), false)
|
|
40
|
+
}
|
|
43
41
|
|
|
44
|
-
|
|
45
|
-
document.removeEventListener('click', this.outsideClickEvent, false)
|
|
46
|
-
}
|
|
42
|
+
this.openNavButton.addEventListener('click', this.mobileToggleMainNav.bind(this), false)
|
|
47
43
|
|
|
48
|
-
|
|
49
|
-
|
|
44
|
+
this.closeNavButtons.forEach((element) => {
|
|
45
|
+
element.addEventListener('click', this.mobileToggleMainNav.bind(this), false)
|
|
46
|
+
})
|
|
50
47
|
|
|
51
|
-
|
|
52
|
-
this.
|
|
53
|
-
|
|
54
|
-
event.preventDefault()
|
|
55
|
-
}
|
|
48
|
+
this.closeSubNavButtons.forEach((element) => {
|
|
49
|
+
element.addEventListener('click', this.closeSubNav.bind(this), false)
|
|
50
|
+
})
|
|
56
51
|
}
|
|
57
52
|
|
|
58
|
-
responsiveCheck(
|
|
53
|
+
responsiveCheck(event) {
|
|
59
54
|
let megaMenuListItems = []
|
|
60
|
-
if (
|
|
61
|
-
megaMenuListItems = [].slice.call(this.
|
|
62
|
-
|
|
55
|
+
if (event.matches) {
|
|
56
|
+
megaMenuListItems = [].slice.call(this.nav.querySelectorAll('ul > li'))
|
|
57
|
+
document.body.classList.remove('main-nav-active')
|
|
63
58
|
} else {
|
|
64
|
-
megaMenuListItems = [].slice.call(this.
|
|
59
|
+
megaMenuListItems = [].slice.call(this.nav.querySelectorAll('li'))
|
|
65
60
|
}
|
|
66
61
|
this.tearDownNavControls()
|
|
67
62
|
this.setUpNavControls(megaMenuListItems)
|
|
68
63
|
}
|
|
69
64
|
|
|
65
|
+
handleOutsideClick(event) {
|
|
66
|
+
// removes handleOutsideClick functionality from docs site
|
|
67
|
+
if (this.nav.closest('.nsw-docs')) return
|
|
68
|
+
|
|
69
|
+
if (!this.mainNavIsOpen) return
|
|
70
|
+
|
|
71
|
+
const isOutsideNav = !this.nav.contains(event.target)
|
|
72
|
+
|
|
73
|
+
if (isOutsideNav) {
|
|
74
|
+
this.toggleSubNavDesktop(true)
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
70
78
|
tearDownNavControls() {
|
|
71
79
|
if (this.isMegaMenuElement) {
|
|
72
|
-
const listItems = [].slice.call(this.
|
|
80
|
+
const listItems = [].slice.call(this.nav.querySelectorAll('li'))
|
|
73
81
|
listItems.forEach((item) => {
|
|
74
82
|
const submenu = item.querySelector('[id^=sub-nav-]')
|
|
75
83
|
const link = item.querySelector('a')
|
|
@@ -84,23 +92,6 @@ class Navigation {
|
|
|
84
92
|
}
|
|
85
93
|
}
|
|
86
94
|
|
|
87
|
-
setUpMobileControls() {
|
|
88
|
-
this.openNavButton.addEventListener('click', this.mobileToggleMainNavEvent, false)
|
|
89
|
-
|
|
90
|
-
this.closeNavButtons.forEach((element) => {
|
|
91
|
-
element.addEventListener('click', this.mobileToggleMainNavEvent, false)
|
|
92
|
-
})
|
|
93
|
-
|
|
94
|
-
this.closeSubNavButtons.forEach((element) => {
|
|
95
|
-
element.addEventListener('click', this.mobileToggleSubNavEvent, false)
|
|
96
|
-
})
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
mobileMainNavTrapTabs(e) {
|
|
100
|
-
const elemObj = getFocusableElementBySelector(this.mainNavElement.id, ['> div button', '> ul > li > a'])
|
|
101
|
-
trapTabKey(e, elemObj)
|
|
102
|
-
}
|
|
103
|
-
|
|
104
95
|
setUpNavControls(listItems) {
|
|
105
96
|
if (this.isMegaMenuElement) {
|
|
106
97
|
listItems.forEach((item) => {
|
|
@@ -112,26 +103,31 @@ class Navigation {
|
|
|
112
103
|
link.setAttribute('aria-controls', submenu.id)
|
|
113
104
|
link.addEventListener('click', this.desktopButtonClickEvent, false)
|
|
114
105
|
link.addEventListener('keydown', this.desktopButtonKeydownEvent, false)
|
|
115
|
-
document.addEventListener('keydown', this.escapeCloseEvent, false)
|
|
116
106
|
}
|
|
117
107
|
})
|
|
118
108
|
}
|
|
119
109
|
}
|
|
120
110
|
|
|
111
|
+
mobileMainNavTrapTabs(e) {
|
|
112
|
+
const elemObj = getFocusableElementBySelector(this.navID, ['> div button', '> ul > li > a'])
|
|
113
|
+
trapTabKey(e, elemObj)
|
|
114
|
+
}
|
|
115
|
+
|
|
121
116
|
mobileShowMainNav({ propertyName }) {
|
|
122
|
-
if (
|
|
123
|
-
getFocusableElementBySelector(this.
|
|
124
|
-
this.
|
|
125
|
-
this.
|
|
126
|
-
this.
|
|
127
|
-
this.
|
|
117
|
+
if (propertyName !== 'transform') return
|
|
118
|
+
getFocusableElementBySelector(this.navID, ['> div button', '> ul > li > a']).all[1].focus()
|
|
119
|
+
this.nav.classList.add('active')
|
|
120
|
+
this.nav.classList.remove('activating')
|
|
121
|
+
this.nav.removeEventListener(this.transitionEvent, this.mobileShowMainTransitionEndEvent, false)
|
|
122
|
+
this.nav.addEventListener('keydown', this.mobileTrapTabKeyEvent, false)
|
|
128
123
|
}
|
|
129
124
|
|
|
130
125
|
mobileHideMainNav({ propertyName }) {
|
|
131
|
-
if (
|
|
126
|
+
if (propertyName !== 'transform') return
|
|
127
|
+
|
|
128
|
+
this.nav.classList.remove('active')
|
|
129
|
+
this.nav.classList.remove('closing')
|
|
132
130
|
|
|
133
|
-
this.mainNavElement.classList.remove('active')
|
|
134
|
-
this.mainNavElement.classList.remove('closing')
|
|
135
131
|
while (this.openSubNavElements.length > 0) {
|
|
136
132
|
const { submenu } = this.whichSubNavLatest()
|
|
137
133
|
submenu.removeEventListener('keydown', this.mobileSubNavTrapTabKeyEvent, false)
|
|
@@ -139,39 +135,40 @@ class Navigation {
|
|
|
139
135
|
submenu.classList.remove('closing')
|
|
140
136
|
this.openSubNavElements.pop()
|
|
141
137
|
}
|
|
142
|
-
|
|
143
|
-
this.
|
|
138
|
+
|
|
139
|
+
this.nav.removeEventListener(this.transitionEvent, this.mobileHideMainTransitionEndEvent, false)
|
|
140
|
+
this.nav.removeEventListener('keydown', this.mobileTrapTabKeyEvent, false)
|
|
144
141
|
}
|
|
145
142
|
|
|
146
143
|
mobileToggleMainNav(e) {
|
|
147
144
|
const { currentTarget } = e
|
|
148
145
|
const isExpanded = currentTarget.getAttribute('aria-expanded') === 'true'
|
|
149
146
|
if (isExpanded) {
|
|
150
|
-
|
|
147
|
+
document.body.classList.remove('main-nav-active')
|
|
151
148
|
this.openNavButton.focus()
|
|
152
|
-
this.
|
|
153
|
-
this.
|
|
149
|
+
this.nav.classList.add('closing')
|
|
150
|
+
this.nav.addEventListener(this.transitionEvent, this.mobileHideMainTransitionEndEvent, false)
|
|
154
151
|
} else {
|
|
155
|
-
|
|
156
|
-
this.
|
|
157
|
-
this.
|
|
152
|
+
document.body.classList.add('main-nav-active')
|
|
153
|
+
this.nav.classList.add('activating')
|
|
154
|
+
this.nav.addEventListener(this.transitionEvent, this.mobileShowMainTransitionEndEvent, false)
|
|
158
155
|
}
|
|
159
156
|
}
|
|
160
157
|
|
|
161
|
-
buttonClickDesktop(
|
|
158
|
+
buttonClickDesktop(event) {
|
|
162
159
|
const isDesktop = this.breakpoint.matches
|
|
163
|
-
if (!isDesktop || !
|
|
164
|
-
this.saveElements(
|
|
160
|
+
if (!isDesktop || !event.target.closest('.nsw-main-nav__sub-nav')) {
|
|
161
|
+
this.saveElements(event)
|
|
165
162
|
this.toggleSubNavDesktop()
|
|
166
|
-
|
|
163
|
+
event.preventDefault()
|
|
167
164
|
}
|
|
168
165
|
}
|
|
169
166
|
|
|
170
|
-
buttonKeydownDesktop(
|
|
171
|
-
if (
|
|
172
|
-
this.saveElements(
|
|
167
|
+
buttonKeydownDesktop(event) {
|
|
168
|
+
if (event.key === ' ' || event.key === 'Enter' || event.key === 'Spacebar') {
|
|
169
|
+
this.saveElements(event)
|
|
173
170
|
this.toggleSubNavDesktop()
|
|
174
|
-
|
|
171
|
+
event.preventDefault()
|
|
175
172
|
}
|
|
176
173
|
}
|
|
177
174
|
|
|
@@ -200,7 +197,7 @@ class Navigation {
|
|
|
200
197
|
|
|
201
198
|
showSubNav({ propertyName }) {
|
|
202
199
|
const { submenu } = this.whichSubNavLatest()
|
|
203
|
-
if (
|
|
200
|
+
if (propertyName !== 'transform') return
|
|
204
201
|
getFocusableElementBySelector(submenu.id, ['> div button', '> .nsw-main-nav__title a', '> ul > li > a']).all[2].focus()
|
|
205
202
|
submenu.removeEventListener(this.transitionEvent, this.showSubNavTransitionEndEvent, false)
|
|
206
203
|
}
|
|
@@ -210,9 +207,9 @@ class Navigation {
|
|
|
210
207
|
if (this.breakpoint.matches) {
|
|
211
208
|
link.setAttribute('aria-expanded', false)
|
|
212
209
|
link.classList.remove('active')
|
|
213
|
-
this.
|
|
210
|
+
this.nav.removeEventListener('focus', this.checkFocusEvent, true)
|
|
214
211
|
// fix: workaround for safari because it doesn't support focus event
|
|
215
|
-
this.
|
|
212
|
+
this.nav.removeEventListener('click', this.checkFocusEvent, true)
|
|
216
213
|
} else {
|
|
217
214
|
link.focus()
|
|
218
215
|
submenu.removeEventListener('keydown', this.mobileSubNavTrapTabKeyEvent, false)
|
|
@@ -227,9 +224,9 @@ class Navigation {
|
|
|
227
224
|
if (this.breakpoint.matches) {
|
|
228
225
|
link.setAttribute('aria-expanded', true)
|
|
229
226
|
link.classList.add('active')
|
|
230
|
-
this.
|
|
227
|
+
this.nav.addEventListener('focus', this.checkFocusEvent, true)
|
|
231
228
|
// fix: workaround for safari because it doesn't support focus event
|
|
232
|
-
this.
|
|
229
|
+
this.nav.addEventListener('click', this.checkFocusEvent, true)
|
|
233
230
|
} else {
|
|
234
231
|
submenu.addEventListener('keydown', this.mobileSubNavTrapTabKeyEvent, false)
|
|
235
232
|
submenu.addEventListener(this.transitionEvent, this.showSubNavTransitionEndEvent, false)
|
|
@@ -243,8 +240,10 @@ class Navigation {
|
|
|
243
240
|
const { link } = this.whichSubNavLatest()
|
|
244
241
|
const isExpanded = link.getAttribute('aria-expanded') === 'true'
|
|
245
242
|
if (isExpanded) {
|
|
243
|
+
this.mainNavIsOpen = false
|
|
246
244
|
this.closeSubNav()
|
|
247
245
|
} else {
|
|
246
|
+
this.mainNavIsOpen = true
|
|
248
247
|
this.openSubNav()
|
|
249
248
|
}
|
|
250
249
|
}
|