UNPKG

zephjs-router

Version:

A simple router element for targeting portions of your webpage at specific content based on the URL.

111 lines (90 loc) 3.21 kB
// (c) 2019, The Awesome Engineering Company, https://awesomeneg.com import {ZephComponents,ZephUtils,html,css,attribute,onAdd,onCreate,onAttribute} from "./zeph.min.js"; ZephComponents.define("zephjs-route",()=>{ html("<slot></slot>"); attribute("match",""); attribute("against","url"); // attribute("selected",undefined); attribute("default",undefined); attribute("lazy",undefined); onAttribute("selected",(oldValue,newValue,element)=>{ let lazy = element.getAttribute("lazy") || null; if (lazy) { element.removeAttribute("lazy"); new Promise(async (resolve,reject)=>{ try { let content = await ZephUtils.fetchText(lazy); if (content) element.innerHTML = content; resolve(); } catch (ex) { return reject(ex); } }); } }); }); ZephComponents.define("zephjs-router",()=>{ html(` <slot></slot> `); css(` :host { display: block; } :host ::slotted(*) { display: none; } :host ::slotted(zephjs-route) { display: none; } :host ::slotted(zephjs-route[selected]) { display: block; } `); onCreate((element,content)=>{ window.addEventListener("hashchange",()=>{ stateChange(element,content); }); }); onAdd((element,content)=>{ stateChange(element,content); }); const stateChange = function stateChange(element) { let routes = element.querySelectorAll("zephjs-route"); let found = [...routes].reduce((found,route)=>{ if (found) return found; let against = route.hasAttribute("against") ? route.getAttribute("against") : "path" || "path"; let actual = null; if (against==="hash") actual = document.location.hash && document.location.hash.slice(1) || ""; else if (against==="search") actual = document.location.hash && document.location.hash.slice(1) || ""; else if (against==="url") actual = document.location.href; else if (against==="href") actual = document.location.href; else if (against==="path") actual = document.location.pathname; else if (against==="pathname") actual = document.location.pathname; else if (against==="port") actual = document.location.port; else if (against==="protocol") actual = document.location.protocol; else if (against==="origin") actual = document.location.origin; else if (against==="host") actual = document.location.host; else if (against==="hostname") actual = document.location.hostname; else return null; let match = route.hasAttribute("match") ? route.getAttribute("match") : null || null; let ew = match.endsWith("*"); let sw = match.startsWith("*"); if (match===null || match===undefined || match==="") return null; if (match==="*") return route; else if (ew && !sw && actual.startsWith(match.slice(0,-1))) return route; else if (!ew && sw && actual.endsWith(match.slice(1))) return route; else if (ew && sw && actual.indexOf(match.slice(1,-1))) return route; else if (actual===match) return route; return null; },false); if (!found) found = element.querySelector("zephjs-route[default]") || routes[0]; if (found) { routes.forEach((route)=>{ route.removeAttribute("selected"); if (route===found) route.setAttribute("selected",""); }); } }; });