Skip to content

Commit b918cda

Browse files
committed
refactor: simplify Nav logic + try to patch up some nav / route related issues with pattern keys not always matching up with the3 generated navigation / query string
1 parent 71f4654 commit b918cda

File tree

4 files changed

+129
-73
lines changed

4 files changed

+129
-73
lines changed
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
export const getParents = (elem, selector) => {
2+
// Element.matches() polyfill
3+
if (!Element.prototype.matches) {
4+
Element.prototype.matches =
5+
Element.prototype.matchesSelector ||
6+
Element.prototype.mozMatchesSelector ||
7+
Element.prototype.msMatchesSelector ||
8+
Element.prototype.oMatchesSelector ||
9+
Element.prototype.webkitMatchesSelector ||
10+
function(s) {
11+
var matches = (this.document || this.ownerDocument).querySelectorAll(s),
12+
i = matches.length;
13+
while (--i >= 0 && matches.item(i) !== this) {}
14+
return i > -1;
15+
};
16+
}
17+
18+
// Set up a parent array
19+
var parents = [];
20+
21+
// Push each parent element to the array
22+
for (; elem && elem !== document; elem = elem.parentNode) {
23+
if (selector) {
24+
if (elem.matches(selector)) {
25+
parents.push(elem);
26+
}
27+
continue;
28+
}
29+
parents.push(elem);
30+
}
31+
32+
// Return our parent array
33+
return parents;
34+
};

packages/uikit-workshop/src/scripts/components/pl-nav/pl-nav.js

Lines changed: 27 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { h } from 'preact';
44

55
const classNames = require('classnames');
66

7+
import { getParents } from './get-parents';
78
import { store } from '../../store.js'; // redux store
89
import { BaseComponent } from '../base-component.js';
910
import Mousetrap from 'mousetrap';
@@ -230,16 +231,12 @@ class Nav extends BaseComponent {
230231
this.layoutMode = state.app.layoutMode || '';
231232
}
232233

233-
if (this.currentPattern !== state.app.currentPattern) {
234-
if (
235-
state.app.currentPattern !== '' &&
236-
this.currentPattern !== state.app.currentPattern &&
237-
this._hasInitiallyRendered === true
238-
) {
239-
this.handleURLChange(); // so the nav logic is always correct (ex. layout changes)
240-
}
241-
234+
if (
235+
state.app.currentPattern &&
236+
this.currentPattern !== state.app.currentPattern
237+
) {
242238
this.currentPattern = state.app.currentPattern;
239+
this.handleURLChange(); // so the nav logic is always correct (ex. layout changes)
243240
}
244241
}
245242

@@ -317,70 +314,35 @@ class Nav extends BaseComponent {
317314
}
318315

319316
handleURLChange() {
320-
const shouldAutoOpenNav = true;
321-
322317
const currentPattern = this.currentPattern;
323-
const activeLink = document.querySelector(
318+
this.activeLink = document.querySelector(
324319
`[data-patternpartial="${currentPattern}"]`
325320
);
326-
const self = this;
327321

328322
if (this.previousActiveLinks) {
329-
this.previousActiveLinks.forEach(function(link, index) {
330-
self.previousActiveLinks[index].classList.remove('pl-is-active');
323+
this.previousActiveLinks.forEach((link, index) => {
324+
this.previousActiveLinks[index].classList.remove('pl-is-active');
331325
});
332326
}
333327
this.previousActiveLinks = [];
334328

335-
if (activeLink) {
336-
activeLink.classList.add('pl-is-active');
337-
this.previousActiveLinks.push(activeLink);
338-
339-
if (
340-
activeLink.parentNode.classList.contains(
341-
'pl-c-nav__link--overview-wrapper'
342-
)
343-
) {
344-
activeLink.parentNode.classList.add('pl-is-active');
345-
this.previousActiveLinks.push(activeLink.parentNode);
346-
}
329+
if (this.activeLink) {
330+
const triggers = [this.activeLink];
331+
const panels = Array.from(
332+
getParents(this.activeLink, '.pl-js-acc-panel')
333+
);
347334

348-
const parentDropdown = activeLink.closest('.pl-js-acc-panel');
349-
let parentDropdownTrigger;
350-
351-
if (parentDropdown) {
352-
if (parentDropdown.previousSibling) {
353-
parentDropdownTrigger = parentDropdown.previousSibling;
354-
355-
if (
356-
parentDropdown.previousSibling.classList.contains(
357-
'pl-c-nav__link--overview-wrapper'
358-
) &&
359-
shouldAutoOpenNav
360-
) {
361-
parentDropdown.previousSibling.classList.add('pl-is-active');
362-
this.previousActiveLinks.push(parentDropdown.previousSibling);
363-
parentDropdownTrigger = parentDropdown.previousSibling.querySelector(
364-
'.pl-js-acc-handle'
365-
);
366-
}
367-
368-
const grandparentDropdown = parentDropdown.closest(
369-
'.pl-c-nav__sublist--dropdown'
370-
);
371-
const grandparentDropdownTrigger =
372-
grandparentDropdown.previousSibling;
373-
374-
if (grandparentDropdownTrigger && shouldAutoOpenNav) {
375-
if (shouldAutoOpenNav) {
376-
grandparentDropdownTrigger.classList.add('pl-is-active');
377-
}
378-
this.previousActiveLinks.push(grandparentDropdownTrigger);
379-
}
335+
panels.forEach(panel => {
336+
const panelTrigger = panel.previousSibling;
337+
if (panelTrigger) {
338+
triggers.push(panelTrigger);
380339
}
381-
}
382-
} else {
383-
this.cleanupActiveNav();
340+
});
341+
342+
triggers.forEach(trigger => {
343+
trigger.classList.add('pl-is-active');
344+
this.previousActiveLinks.push(trigger);
345+
});
384346
}
385347
}
386348

@@ -416,7 +378,9 @@ class Nav extends BaseComponent {
416378
this._hasInitiallyRendered = true;
417379
}
418380

419-
this.handleURLChange();
381+
if (!this.activeLink) {
382+
this.handleURLChange();
383+
}
420384

421385
if (this.layoutMode !== 'vertical' && window.innerWidth > 670) {
422386
this.cleanupActiveNav(true);
@@ -443,7 +407,6 @@ class Nav extends BaseComponent {
443407
>
444408
{item.patternTypeUC}
445409
</ButtonTitle>
446-
447410
<ol
448411
id={item.patternSubtypeUC}
449412
className={`pl-c-nav__sublist pl-c-nav__sublist--dropdown pl-js-acc-panel`}

packages/uikit-workshop/src/scripts/components/pl-nav/pl-nav.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ pl-nav {
199199
width: 100%;
200200
}
201201

202-
&:not(.pl-c-nav__link--title).pl-is-active {
202+
&:not(.pl-c-nav__link--title):not(.pl-c-nav__link--dropdown).pl-is-active {
203203
box-shadow: inset 4px 0 0 #6c79d9;
204204

205205
// move the "active" border style to the bottom on ONLY the top level links (ex. "All")

packages/uikit-workshop/src/scripts/lit-components/pl-viewport/pl-viewport.js

Lines changed: 67 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ class IFrame extends BaseLitComponent {
2121
super();
2222
this.handlePageChange = this.handlePageChange.bind(this);
2323
this.handlePageLoad = this.handlePageLoad.bind(this);
24-
// this.receiveIframeMessage = this.receiveIframeMessage.bind(this);
24+
this.receiveIframeMessage = this.receiveIframeMessage.bind(this);
2525
this.handleResize = this.handleResize.bind(this);
2626
this.handleMouseDown = this.handleMouseDown.bind(this);
2727
this.handleIframeLoaded = this.handleIframeLoaded.bind(this);
@@ -32,12 +32,6 @@ class IFrame extends BaseLitComponent {
3232
iframeLoaderStyles.use();
3333
styles.use();
3434

35-
if (trackingPageChange === false) {
36-
trackingPageChange = true;
37-
document.addEventListener('patternPartial', this.handlePageLoad);
38-
window.addEventListener('popstate', this.handlePageChange);
39-
}
40-
4135
const state = store.getState();
4236
this.themeMode = state.app.themeMode || 'dark';
4337
this.isViewallPage = state.app.isViewallPage || false;
@@ -47,7 +41,7 @@ class IFrame extends BaseLitComponent {
4741
this.sizeiframe(state.app.viewportPx, false);
4842
}
4943

50-
// window.addEventListener('message', this.receiveIframeMessage, false);
44+
window.addEventListener('message', this.receiveIframeMessage, false);
5145
window.addEventListener('resize', this.handleResize);
5246
this.handleOrientationChange();
5347

@@ -455,6 +449,71 @@ class IFrame extends BaseLitComponent {
455449

456450
return false;
457451
}
452+
453+
receiveIframeMessage(event) {
454+
// does the origin sending the message match the current host? if not dev/null the request
455+
if (
456+
window.location.protocol !== 'file:' &&
457+
event.origin !== window.location.protocol + '//' + window.location.host
458+
) {
459+
return;
460+
}
461+
462+
let data = {};
463+
try {
464+
data =
465+
typeof event.data !== 'string' ? event.data : JSON.parse(event.data);
466+
} catch (e) {
467+
// @todo: how do we want to handle exceptions here?
468+
}
469+
470+
// try to auto-correct for currentPattern data that doesn't always match with url
471+
// workaround for certain pages (especially view all pages) not always matching up internally with the expected current pattern key
472+
if (data.event !== undefined && data.event === 'patternLab.pageLoad') {
473+
try {
474+
if (event.data.patternpartial) {
475+
let currentPattern = event.data.patternpartial;
476+
if (
477+
!document.querySelector(`[data-patternpartial="${currentPattern}"]`)
478+
) {
479+
currentPattern = currentPattern.replace(/[-][0-9][0-9]/g, '');
480+
}
481+
const currentUrl = urlHandler.getFileName(currentPattern);
482+
483+
if (currentPattern !== null) {
484+
document.title = 'Pattern Lab - ' + currentPattern;
485+
486+
const addressReplacement =
487+
window.location.protocol === 'file:'
488+
? null
489+
: window.location.protocol +
490+
'//' +
491+
window.location.host +
492+
window.location.pathname.replace('index.html', '') +
493+
'?p=' +
494+
currentPattern;
495+
496+
window.history.replaceState(
497+
{
498+
currentPattern: currentPattern,
499+
},
500+
null,
501+
addressReplacement
502+
);
503+
504+
store.dispatch(updateCurrentPattern(currentPattern));
505+
506+
// don't update state or upddate the URL for non-existent patterns
507+
if (currentUrl) {
508+
store.dispatch(updateCurrentUrl(currentUrl));
509+
}
510+
}
511+
}
512+
} catch (error) {
513+
console.log(error);
514+
}
515+
}
516+
}
458517
}
459518

460519
export { IFrame };

0 commit comments

Comments
 (0)