UNPKG

native-spa-route

Version:

provide SPA route's experience with native web component

109 lines (108 loc) 4.15 kB
export function hook_a_link() { document.body.addEventListener('click', (e) => { const target = e.composedPath()[0]; if (target.tagName === 'A') { const href = target.getAttribute('href'); if (typeof href === 'string') { if (href.startsWith('http')) { return; } e.preventDefault(); history.pushState({}, target.getAttribute('title') ?? '', href); } } }); } function _hook_3_params_func(lifecycle, func_name) { window.history[func_name] = new Proxy(window.history[func_name], { apply: (target, thisArg, argArray) => { const arg0 = argArray[0]; const arg1 = argArray[1]; const arg2 = argArray[2]; let _url = arg2; if (typeof lifecycle?.url_adapter === 'function') { _url = lifecycle.url_adapter(_url); } lifecycle?.before?.(func_name, arg0, arg1, _url); const ret = target.apply(thisArg, [arg0, arg1, _url]); lifecycle?.after?.(func_name, arg0, arg1, _url); window.dispatchEvent(new CustomEvent(`history:${func_name}`, { detail: { type: func_name, data: arg0, unused: arg1, url: _url, }, })); return ret; }, }); } function _hook_0_params_func(lifecycle, func_name) { window.history[func_name] = new Proxy(window.history[func_name], { apply: (target, thisArg) => { lifecycle?.before?.(func_name, undefined, '', undefined); const ret = target.apply(thisArg, []); lifecycle?.after?.(func_name, undefined, '', undefined); window.dispatchEvent(new CustomEvent(`history:${func_name}`, { detail: { type: func_name, }, })); return ret; }, }); } function _hook_1_params_func(lifecycle, func_name) { window.history[func_name] = new Proxy(window.history[func_name], { apply: (target, thisArg, argArray) => { lifecycle?.before?.(func_name, argArray[0], '', undefined); const ret = target.apply(thisArg, argArray); lifecycle?.after?.(func_name, argArray[0], '', undefined); window.dispatchEvent(new CustomEvent(`history:${func_name}`, { detail: { type: func_name, delta: argArray[0] }, })); return ret; }, }); } let hook_history_change_hooked = false; export function hook_history_change(lifecycle = {}) { if (hook_history_change_hooked) return; hook_history_change_hooked = true; _hook_3_params_func(lifecycle, 'pushState'); _hook_3_params_func(lifecycle, 'replaceState'); _hook_0_params_func(lifecycle, 'back'); _hook_0_params_func(lifecycle, 'forward'); _hook_1_params_func(lifecycle, 'go'); } export function hook_route_change(callback) { window.addEventListener('history:pushState', callback); window.addEventListener('history:replaceState', callback); window.addEventListener('history:back', callback); window.addEventListener('history:forward', callback); window.addEventListener('history:go', callback); window.addEventListener('popstate', callback, false); } export function unhook_route_change(callback) { window.removeEventListener('history:pushState', callback); window.removeEventListener('history:replaceState', callback); window.removeEventListener('history:back', callback); window.removeEventListener('history:forward', callback); window.removeEventListener('history:go', callback); window.removeEventListener('popstate', callback, false); } export function redirect(from, to) { if (location.pathname === from) { history.pushState(null, '', to); } hook_route_change(() => { if (location.pathname === from) { history.pushState(null, '', to); } }); }