notion-enhancer/extension/repo/menu@a6621988-551d-495a-97d8-3c568bca2e9e/router.js

103 lines
3.0 KiB
JavaScript

/*
* notion-enhancer core: menu
* (c) 2021 dragonwocky <thedragonring.bod@gmail.com> (https://dragonwocky.me/)
* (https://notion-enhancer.github.io/) under the MIT license
*/
'use strict';
import { web } from '../../api.js';
export const getSearch = () =>
new Map(
location.search
.slice(1)
.split('&')
.map((query) => query.split('='))
);
let defaultView = '';
const views = new Map(),
filters = new Map();
export function setDefaultView(name) {
defaultView = name;
}
export function addView(name, loader, filter = () => {}) {
views.set(name, loader);
filters.set(name, filter);
}
export function removeView(name) {
views.delete(name);
filters.delete(name);
}
function router(event) {
event.preventDefault();
const anchor = event.path.find((anchor) => anchor.nodeName === 'A');
if (location.search !== anchor.getAttribute('href')) {
window.history.pushState(
{ search: anchor.getAttribute('href'), hash: '' },
'',
anchor.href
);
load();
}
}
function navigator(event) {
event.preventDefault();
const anchor = event.path.find((anchor) => anchor.nodeName === 'A'),
hash = anchor.getAttribute('href').slice(1);
document.getElementById(hash).scrollIntoView(true);
document.documentElement.scrollTop = 0;
history.replaceState({ search: location.search, hash }, null, `#${hash}`);
}
export async function load(force = false) {
const $container = document.querySelector('main'),
search = getSearch(),
fallbackView = () => {
window.history.replaceState(
{ search: `?view=${defaultView}`, hash: '' },
null,
`?view=${defaultView}`
);
return load();
};
if (force || !search.get('view') || document.body.dataset.view !== search.get('view')) {
if (views.get(search.get('view'))) {
const $body = await (views.get(search.get('view')) || (() => void 0))();
if ($body) {
$container.style.opacity = 0;
await new Promise((res, rej) =>
setTimeout(() => {
document.body.dataset.view = search.get('view');
$container.innerHTML = '';
$container.append($body);
requestAnimationFrame(() => {
$container.style.opacity = '';
setTimeout(res, 200);
});
}, 200)
);
} else return fallbackView();
} else return fallbackView();
}
if (filters.get(search.get('view'))) filters.get(search.get('view'))(search);
}
window.addEventListener('popstate', (event) => {
if (event.state) load();
document.getElementById(location.hash.slice(1))?.scrollIntoView(true);
document.documentElement.scrollTop = 0;
});
web.addDocumentObserver((mutation) => {
mutation.target.querySelectorAll('a[href^="?"]').forEach((a) => {
a.removeEventListener('click', router);
a.addEventListener('click', router);
});
mutation.target.querySelectorAll('a[href^="#"]').forEach((a) => {
a.removeEventListener('click', navigator);
a.addEventListener('click', navigator);
});
});