Commit 0851f2c8 authored by Clément's avatar Clément

Merge branch 'fix/#26-nav-to-sub-route' into 'master'

Fix/#26 nav to sub route

See merge request !12
parents 2196d04c 41428e4d
Pipeline #2649 passed with stage
in 27 seconds
......@@ -6,6 +6,15 @@
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>SIB test: sib-router</title>
<script type="module" src="../src/index.js"></script>
<a href="." id="reload">reload</a>
<script>
reload.href = location.pathname;
window.addEventListener('keydown', ev => {
if(!ev.ctrlKey || ev.key !== 'r') return;
ev.preventDefault();
reload.click();
});
</script>
<style>
sib-router {
display: block;
......@@ -26,46 +35,67 @@
</head>
<body>
<h1>Musical Instruments</h1>
<sib-router default-route="keyboard">
<sib-route name="keyboard">Keyboard</sib-route>
<sib-route name="string">String</sib-route>
<sib-route name="brass">Brass</sib-route>
</sib-router>
<div id="keyboard" hidden>
<sib-router default-route="piano">
<sib-route name="piano">Piano</sib-route>
<sib-route name="harpsichord">Harpsichord</sib-route>
<sib-route name="organ">Organ</sib-route>
<details>
<summary>use-hash</summary>
<h1>Musical Instruments</h1>
<sib-link next="ukulele">→ Go to ukulele</sib-link>
<sib-link next="brass" data-src="myID">→ Go to brass</sib-link>
<hr>
<sib-router default-route="keyboard" route-prefix="examples/sub-menu.html" use-hash>
<sib-route name="keyboard">Keyboard</sib-route>
<sib-route name="string">String</sib-route>
<sib-route name="brass">Brass</sib-route>
</sib-router>
<div hidden id="piano"><h2>Piano</h2></div>
<div hidden id="harpsichord"><h2>Harpsichord</h2></div>
<div hidden id="organ"><h2>Organ</h2></div>
</div>
<div id="string" hidden>
<sib-router default-route="violin">
<sib-route name="violin">Violin</sib-route>
<sib-route name="contrabass">Contrabass</sib-route>
<sib-route name="guitar">Guitar</sib-route>
<sib-route name="ukulele">Ukulele</sib-route>
</sib-router>
<div hidden id="violin"><h2>Violin</h2></div>
<div hidden id="contrabass"><h2>Contrabass</h2></div>
<div hidden id="guitar"><h2>Guitar</h2></div>
<div hidden id="ukulele"><h2>Ukulele</h2></div>
</div>
<div id="keyboard" hidden>
<sib-router default-route="piano" route-prefix="titi" use-hash>
<sib-route name="piano">Piano</sib-route>
<sib-route name="harpsichord">Harpsichord</sib-route>
<sib-route name="organ">Organ</sib-route>
</sib-router>
<div hidden id="piano"><h2>Piano</h2></div>
<div hidden id="harpsichord"><h2>Harpsichord</h2></div>
<div hidden id="organ"><h2>Organ</h2></div>
</div>
<div id="brass" hidden>
<sib-router default-route="trumpet">
<sib-route name="trumpet">Trumpet</sib-route>
<sib-route name="trombone">Trombone</sib-route>
<sib-route name="tuba">Tuba</sib-route>
</sib-router>
<div hidden id="trumpet"><h2>Trumpet</h2></div>
<div hidden id="trombone"><h2>Trombone</h2></div>
<div hidden id="tuba"><h2>Tuba</h2></div>
</div>
<div id="string" hidden>
<sib-router default-route="violin" use-hash>
<sib-route name="violin">Violin</sib-route>
<sib-route name="contrabass">Contrabass</sib-route>
<sib-route name="guitar">Guitar</sib-route>
<sib-route name="ukulele">Ukulele</sib-route>
</sib-router>
<div hidden id="violin"><h2>Violin</h2></div>
<div hidden id="contrabass"><h2>Contrabass</h2></div>
<div hidden id="guitar"><h2>Guitar</h2></div>
<div hidden id="ukulele"><h2>Ukulele</h2></div>
</div>
<div id="brass" hidden>
<sib-router default-route="trumpet" use-hash>
<sib-route name="trumpet">Trumpet</sib-route>
<sib-route name="trombone">Trombone</sib-route>
<sib-route name="tuba">Tuba</sib-route>
</sib-router>
<div hidden id="trumpet"><h2>Trumpet</h2></div>
<div hidden id="trombone"><h2>Trombone</h2></div>
<div hidden id="tuba"><h2>Tuba</h2></div>
</div>
</details>
<script>
const details0 = document.querySelector('details');
const details = details0.cloneNode(true);
details.querySelector('summary').textContent = 'no use-hash';
Array.from(details.querySelectorAll('[use-hash]')).forEach(elm =>
elm.removeAttribute('use-hash'),
);
['default-route', 'name', 'id', 'next'].forEach(attr => {
Array.from(details.querySelectorAll(`[${attr}]`)).forEach(elm => {
elm.setAttribute(attr, '_' + elm.getAttribute(attr));
});
});
details0.parentElement.insertBefore(details, details0.nextSibling);
</script>
</body>
</html>
......@@ -27,30 +27,24 @@ export default class SIBRoute extends HTMLElement {
return this.closest('sib-router');
}
get resourceId() {
if(this.router.currentURL.split('/')[1]) {
return this.decodeId(this.router.currentURL.split('/')[1]);
}
return '';
const id = this.router.currentURL.split('/')[1];
if(!id || !id.startsWith('@')) return '';
return this.decodeId(id);
}
encodeId(id) {
if (id) {
return encodeURIComponent(id);
}
return;
if (!id) return '';
return '@' + encodeURIComponent(id);
}
decodeId(id) {
if(id) {
return decodeURIComponent(id);
}
return;
if(!id) return '';
return decodeURIComponent(id.replace(/^@/, ''));
}
getPath(prefix, name, id = '') {
const encodedId = this.encodeId(id);
return [prefix, name, encodedId].filter(s=>s).join('/');
return [prefix, name, encodedId].filter(s => s).join('/');
}
updateResource() {
if(this.resourceId) {
......@@ -62,9 +56,12 @@ export default class SIBRoute extends HTMLElement {
}
}
}
updateSubrouter(router) {
router.setAttribute('route-prefix', this.getPath(this.router.prefix, this.name, this.resourceId));
router.display();
updateSubRouters() {
for(let router of this.view.querySelectorAll('sib-router')){
const routePrefix = this.getPath(this.router.prefix, this.name, this.resourceId);
router.setAttribute('route-prefix', routePrefix);
router.display();
}
}
activate() {
if ('HTMLDialogElement' in window && this.view instanceof window.HTMLDialogElement){
......@@ -76,10 +73,7 @@ export default class SIBRoute extends HTMLElement {
}
this.setAttribute('active', '');
this.updateResource();
// Reseting all routers within the selected view
for(let router of this.view.querySelectorAll('sib-router'))
this.updateSubrouter(router);
this.updateSubRouters();
}
hide() {
if ('HTMLDialogElement' in window && this.view instanceof window.HTMLDialogElement){
......
export default class SIBRouter extends HTMLElement {
constructor() {
super();
window.addEventListener('popstate', event => this.display());
window.addEventListener('requestNavigation', event => {
this.navigate(event.detail.route, event.detail.resource);
})
window.addEventListener('DOMContentLoaded', event => this.display());
window.addEventListener('popstate', () => this.display());
window.addEventListener('requestNavigation', ({detail}) =>
this.navigate(detail.route, detail.resource, detail.keepURL)
);
window.addEventListener('DOMContentLoaded', () => {
for (const route of this.routes) {
route.updateSubRouters();
}
this.display();
});
}
get useHash() {
return this.hasAttribute('use-hash');
......@@ -20,12 +25,12 @@ export default class SIBRouter extends HTMLElement {
return this.getAttribute('default-route') || '';
}
get currentURL() {
let url = (this.useHash ? location.hash : location.pathname).slice(1);
if(url.startsWith(this.prefix))
url = url.slice(this.prefix.length);
if(url.startsWith('/'))
url = url.slice(1);
return url;
let url = this.useHash ? location.hash : location.pathname;
url = url.slice(1);
if(url.startsWith(this.prefix)) {
url = url.slice(this.prefix.length);
}
return stripSlashes(url);
}
get currentRouteName() {
return this.currentURL.split('/')[0] || this.defaultRoute;
......@@ -36,14 +41,16 @@ export default class SIBRouter extends HTMLElement {
display(routeName = this.currentRouteName, resource) {
this.dispatchEvent(new CustomEvent('navigate', {detail: {route: routeName, resource}}));
for(let route of this.routes)
if(routeName == route.name)
for(let route of this.routes) {
if(routeName === route.name) {
this.dispatchEvent(new CustomEvent('navigate', {detail: {route: routeName, resource}}));
route.activate();
else
} else {
route.hide();
}
}
}
navigate(routeName = '', resource) {
navigate(routeName = '', resource, keepURL) {
let route
if(routeName) {
route = this.querySelector('sib-route[name="'+routeName+'"]');
......@@ -53,19 +60,27 @@ export default class SIBRouter extends HTMLElement {
}
if(!route) return; //this route is not for me!
if(this.prefix) {
const route = this.prefix.split('/').pop();
setTimeout(() => {
this.dispatchEvent(new CustomEvent('requestNavigation', {
detail: {route: route, keepURL: true},
bubbles: true,
}))
});
}
const id = resource ? resource['@id'] : null;
const path = route.getPath(this.prefix, routeName, id)
//update current URL
const path = route.getPath(this.prefix, routeName, id);
if(!keepURL && !this.hasAttribute('keep-url')) {
//update current URL
const prefix = this.useHash ? '#' : '/';
history.pushState({}, routeName, prefix + path);
}
this.display(routeName, resource);
if(this.hasAttribute('keep-url')) return;
if(this.useHash)
window.location.hash = path;
else
history.pushState({}, routeName, '/' + path);
}
}
customElements.define('sib-router', SIBRouter);
function stripSlashes(str) {
return str.replace(/^\/+|\/+$/g, '');
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment