diff --git a/src/sib-link.js b/src/sib-link.js index 69ee9e1869f34a5631f46de6c9b63ba4c29d6db4..5884c8d018aabf9dbbcd5af71cd8bf04dd818da6 100644 --- a/src/sib-link.js +++ b/src/sib-link.js @@ -1,19 +1,19 @@ export default class SIBLink extends HTMLElement { - constructor() { - super(); - this.addEventListener('click', event => this.trigger()); - } - trigger() { - const route = this.getAttribute('next') - const resource = this.dataset.src && { '@id': this.dataset.src } - if(!route && !resource) return; - this.dispatchEvent( - new CustomEvent('requestNavigation', { - bubbles: true, - detail: { route, resource }, - }), - ); - } + constructor() { + super(); + this.addEventListener('click', event => this.trigger()); + } + trigger() { + const route = this.getAttribute('next'); + const resource = this.dataset.src && { '@id': this.dataset.src }; + if (!route && !resource) return; + this.dispatchEvent( + new CustomEvent('requestNavigation', { + bubbles: true, + detail: { route, resource }, + }), + ); + } } customElements.define('sib-link', SIBLink); diff --git a/src/sib-route.js b/src/sib-route.js index e26b7200b6d3e96ad03cf68358f9469f4cc8f6c2..14449e43e57b42636fabc3fd075e03a783d41ce9 100644 --- a/src/sib-route.js +++ b/src/sib-route.js @@ -1,88 +1,98 @@ export default class SIBRoute extends HTMLElement { - constructor() { - super(); - } - connectedCallback() { - this.addEventListener('click', event => this.router.navigate(this.name)); - } + constructor() { + super(); + } + connectedCallback() { + this.addEventListener('click', event => this.router.navigate(this.name)); + } - get name() { - return this.getAttribute('name'); - } - set name(name) { - this.setAttribute('name', name); - } - get view(){ - const view = document.getElementById(this.name); - if(!view) { - throw new Error(`view "#${this.name}" is not in document`); - } - this.view = view; - return view; - } - set view(value) { - Object.defineProperty(this, 'view', {value}); - } - get router() { - return this.closest('sib-router'); - } - get resourceId() { - const id = this.router.currentURL.split('/')[1]; - if(!id || !id.startsWith('@')) return ''; - return this.decodeId(id); + get name() { + return this.getAttribute('name'); + } + set name(name) { + this.setAttribute('name', name); + } + get view() { + const view = document.getElementById(this.name); + if (!view) { + throw new Error(`view "#${this.name}" is not in document`); } + this.view = view; + return view; + } + set view(value) { + Object.defineProperty(this, 'view', { value }); + } + get router() { + return this.closest('sib-router'); + } + get resourceId() { + const id = this.router.currentURL.split('/')[1]; + if (!id || !id.startsWith('@')) return ''; + return this.decodeId(id); + } - encodeId(id) { - if (!id) return ''; - return '@' + encodeURIComponent(id); - } + encodeId(id) { + if (!id) return ''; + return '@' + encodeURIComponent(id); + } - decodeId(id) { - if(!id) return ''; - return decodeURIComponent(id.replace(/^@/, '')); - } + decodeId(id) { + if (!id) return ''; + return decodeURIComponent(id.replace(/^@/, '')); + } - getPath(prefix, name, id = '') { - const encodedId = this.encodeId(id); - return [prefix, name, encodedId].filter(s => s).join('/'); - } - updateResource() { - if(this.resourceId) { - if(this.view.hasAttribute('bind-resources')) { - this.view.setAttribute('data-src', this.resourceId); - } - for(let element of this.view.querySelectorAll('[bind-resources]')) { - element.setAttribute('data-src', this.resourceId); - } - } + getPath(prefix, name, id = '') { + const encodedId = this.encodeId(id); + return [prefix, name, encodedId].filter(s => s).join('/'); + } + updateResource() { + if (this.resourceId) { + if (this.view.hasAttribute('bind-resources')) { + this.view.setAttribute('data-src', this.resourceId); + } + for (let element of this.view.querySelectorAll('[bind-resources]')) { + element.setAttribute('data-src', this.resourceId); + } } - 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(); - } + } + 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){ - if(!this.view.hasAttribute('open')) { - this.view.showModal(); - } - } else { - this.view.removeAttribute('hidden'); - } - this.setAttribute('active', ''); - this.updateResource(); - this.updateSubRouters(); + } + activate() { + if ( + 'HTMLDialogElement' in window && + this.view instanceof window.HTMLDialogElement + ) { + if (!this.view.hasAttribute('open')) { + this.view.showModal(); + } + } else { + this.view.removeAttribute('hidden'); } - hide() { - if ('HTMLDialogElement' in window && this.view instanceof window.HTMLDialogElement){ - this.view.close() - } else { - this.view.setAttribute('hidden', ''); - } - this.removeAttribute('active'); + this.setAttribute('active', ''); + this.updateResource(); + this.updateSubRouters(); + } + hide() { + if ( + 'HTMLDialogElement' in window && + this.view instanceof window.HTMLDialogElement + ) { + this.view.close(); + } else { + this.view.setAttribute('hidden', ''); } + this.removeAttribute('active'); + } } customElements.define('sib-route', SIBRoute); diff --git a/src/sib-router.js b/src/sib-router.js index bee8a7de8e891aad0d5eaee6cb147da02e405504..e3906d09ba9427daf268d1332b7b2e8f256c5bc7 100644 --- a/src/sib-router.js +++ b/src/sib-router.js @@ -1,86 +1,92 @@ export default class SIBRouter extends HTMLElement { - constructor() { - super(); - 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'); - } - get prefix() { - let prefix = this.getAttribute('route-prefix') || ''; - if(prefix.slice(-1) == '/') - prefix = prefix.slice(0, -1); - return prefix; - } - get defaultRoute() { - return this.getAttribute('default-route') || ''; - } - get currentURL() { - 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); + constructor() { + super(); + 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'); + } + get prefix() { + let prefix = this.getAttribute('route-prefix') || ''; + if (prefix.slice(-1) == '/') prefix = prefix.slice(0, -1); + return prefix; + } + get defaultRoute() { + return this.getAttribute('default-route') || ''; + } + get currentURL() { + let url = this.useHash ? location.hash : location.pathname; + url = url.slice(1); + if (url.startsWith(this.prefix)) { + url = url.slice(this.prefix.length); } - get currentRouteName() { - return this.currentURL.split('/')[0] || this.defaultRoute; + return stripSlashes(url); + } + get currentRouteName() { + return this.currentURL.split('/')[0] || this.defaultRoute; + } + get routes() { + return this.querySelectorAll('sib-route'); + } + + display(routeName = this.currentRouteName, resource) { + for (let route of this.routes) { + if (routeName === route.name) { + this.dispatchEvent( + new CustomEvent('navigate', { + detail: { route: routeName, resource }, + }), + ); + route.activate(); + } else { + route.hide(); + } } - get routes() { - return this.querySelectorAll('sib-route'); + } + navigate(routeName = '', resource, keepURL) { + let route; + if (routeName) { + route = this.querySelector('sib-route[name="' + routeName + '"]'); + } else if (!routeName && resource && resource['@type']) { + route = this.querySelector( + 'sib-route[rdf-type="' + resource['@type'] + '"]', + ); + routeName = route ? route.attributes.name.value : null; } - - display(routeName = this.currentRouteName, resource) { - for(let route of this.routes) { - if(routeName === route.name) { - this.dispatchEvent(new CustomEvent('navigate', {detail: {route: routeName, resource}})); - route.activate(); - } else { - route.hide(); - } - } + 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, + }), + ); + }); } - navigate(routeName = '', resource, keepURL) { - let route - if(routeName) { - route = this.querySelector('sib-route[name="'+routeName+'"]'); - } else if (!routeName && resource && resource['@type']) { - route = this.querySelector('sib-route[rdf-type="'+resource['@type']+'"]'); - routeName = route ? route.attributes.name.value : null - } - - 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); - if(!keepURL && !this.hasAttribute('keep-url')) { - //update current URL - const prefix = this.useHash ? '#' : '/'; - history.pushState({}, routeName, prefix + path); - } - this.display(routeName, resource); + const id = resource ? resource['@id'] : null; + 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); + } } customElements.define('sib-router', SIBRouter); function stripSlashes(str) { - return str.replace(/^\/+|\/+$/g, ''); + return str.replace(/^\/+|\/+$/g, ''); }