Commit 3914e373 authored by Sylvain Le Bon's avatar Sylvain Le Bon

Merge branch 'newname' into 'master'

Newname

See merge request startinblox/sib-router!1
parents 488ca64e 61099628
......@@ -12,102 +12,50 @@ An full app example can be found in index.html:
You first need to load the webcomponents polyfill for the browsers that have not implemented them yet, and import the components you want to use in your HTML file:
```html
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/webcomponentsjs/1.0.20/webcomponents-loader.js"></script>
<link rel="import" href="https://cdn.happy-dev.fr/ldp-display/ldp-display.html" />
<link rel="import" href="https://cdn.happy-dev.fr/ldp-display/ldp-form.html" />
<link rel="import" href="https://cdn.happy-dev.fr/ldp-display/ldp-router.html" />
<link rel="import" href="https://cdn.happy-dev.fr/ldp-display/ldp-calendar.html" />
<link rel="import" href="https://cdn.happy-dev.fr/ldp-display/ldp-map.html" />
<link rel="import" href="https://cdn.happy-dev.fr/sib-router/sib-router.html" />
```
Then you can use the new tags in your markup, for instance : `<ldp-display>`. More details on each component in the following section.
Then you can use the new tags in your markup, for instance : `<sib-router>`.
More details on each component in the following section.
## Components documentation
### ldp-display &nbsp;&&nbsp; ldp-form
### sib-router &nbsp;&&nbsp; sib-route
**`<sib-router>` accepts the following attributes:**
**These components accept the following attributes:**
- **data-src**: The uri of the LDP resource you want to display. If this resource is a container, `<ldp-display>` will create a child `<ldp-display>` for each resource it contains, and `<ldp-form>` will display a blank form with appropriate fields to create a new resource.
- **value-xyz**: To display a string not contained within the data.
- **set-xyz**: To group fields within a `<div>` tag that will have the `name` attribute set up to `xyz`. By default, all displayed fields are direct children of `<ldp-display>`. Make sure you don't give your set the same name as a field as it would result in an infinite loop.
- **data-fields**: the ordered list of fields to be displayed, separated by commas. By default, all the fields of the resource are displayed.
- **widget-xyz**: the widgets to be used to display the `xyz` field. By default, the widget used is `<ldp-display-div>`. Cf the **Widgets** section below for more info.
**`<ldp-display>` also has the following attributes:**
- **search-fields**: It is possible to search/filter your list by choosing the fields you want to filter it with. To be able to filter my users by `name` for instance, I can set `search-fields="name"`. This will display a form with the appropriate inputs to filter the list.
- **next**: `name` attribute of the `<ldp-route>` that should be accessed when a `<ldp-display>` element is clicked. See the documentation of `<ldp-router>` for more details.
**Example :**
```html
<ldp-display
id="list"
data-src="http://localhost:8000/todos/"
set-info="task, date"
value-created="Created by :"
set-author="created, name"
set-status="state"
data-fields="image, status, author, deadline"
widget-image="ldp-display-img"
search-fields="name, author"
next="detail"
></ldp-display>
```
**`<ldp-form>` also has the following attributes:**
- **label-xyz**: When displaying a form, the default labels are the fields names of the model. If you want something fancier, you can set this attribute, for instance : `label-username="Your name"`.
```html
<ldp-form
data-src="http://localhost:8000/todos/"
></ldp-form>
```
This shows the list of todos listed by the container, and a form to create a new one.
### ldp-router &nbsp;&&nbsp; ldp-route
**`<ldp-router>` accepts the following attributes:**
- **default-route**: The `name` attribute of the default `<ldp-route>` displayed.
- **default-route**: The `name` attribute of the default `<sib-route>` displayed.
- **route-prefix**: If you app is not run from the root of your domain name, for instance `www.your-domain.com/some-uri`, you should set `route-prefix` to "some-uri".
- **use-hash**: If you can't rewrite the URLs on your server, you might want to set this attribute to `true` to use `location.hash` instead of `location.pathname` as URLs.
**`<ldp-route>` accepts the following attributes:**
**`<sib-route>` accepts the following attributes:**
- **id-prefix**: TO BE WRITTEN
- **active**: This attribute is present on route being displayed by `<ldp-router>`. It is automatically added/removed by `<ldp-router>` and should not be tinkered manually.
- **active**: This attribute is present on route being displayed by `<sib-router>`. It is automatically added/removed by `<sib-router>` and should not be tinkered manually.
**Example :**
```html
<ldp-router
<sib-router
default-route="list"
route-prefix="my-app"
use-hash="true"
>
<ldp-route name="list">List</ldp-route>
<ldp-route name="form">Form</ldp-route>
<ldp-route name="detail">Details</ldp-route>
</ldp-router>
<sib-route name="list">List</sib-route>
<sib-route name="form">Form</sib-route>
<sib-route name="detail">Details</sib-route>
</sib-router>
```
## Widgets
The following widgets are available :
- **ldp-display-div** (default) : Displays the value inside a `<div>` HTML tag.
- **ldp-display-img** : Inserts the value as the src attribute value of an `<img>` HTML tag.
- **ldp-form-text** : Inserts an `<input/>` HTML tag of type "text".
## Events
The componend ldp-display fires a "select" event when the user clicks an child in the list, with the resource as a detail of the event.
The componend ldp-form fires a "save" event when the user validates the form.
Coming soon...
## License
No licence yet. Please wait...
Licence MIT
......@@ -3,11 +3,11 @@
<head>
<meta charset="UTF-8">
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/webcomponentsjs/1.0.20/webcomponents-loader.js"></script>
<link rel="import" href="https://cdn.happy-dev.fr/ldp-display/ldp-display.html" />
<link rel="import" href="https://cdn.happy-dev.fr/ldp-display/ldp-form.html" />
<link rel="import" href="ldp-router.html" />
<link rel="import" href="https://cdn.happy-dev.fr/sib-core/sib-display.html" />
<link rel="import" href="https://cdn.happy-dev.fr/sib-core/sib-form.html" />
<link rel="import" href="sib-router.html" />
<style>
ldp-display {
sib-display {
display: flex;
}
#detail {
......@@ -21,52 +21,74 @@
.text {
font-weight: bold;
}
[active] {
color: orange;
}
</style>
</head>
<body>
<div id="loader" style="display:none">Chargement...</div>
<ldp-router default-route="list">
<ldp-route name="list">Voir la liste</ldp-route>
<ldp-route name="form">Voir le formulaire</ldp-route>
</ldp-router>
<ldp-router route-prefix="list">
<ldp-route name="detail" id-prefix="http://localhost:8000/todos/">Voir le détail</ldp-route>
</ldp-router>
<sib-router default-route="list">
<sib-route name="list">Voir la liste</sib-route>
<sib-route name="form">Voir le formulaire</sib-route>
</sib-router>
<main>
<div id="detail">
<ldp-display
bind-resources
loader-id="loader"
data-src="http://localhost:8000/todos/6/"
data-fields="name, author, text, assignees"
value-text="Ceci est un détail"
widget-assignees="ldp-display-list"
></ldp-display>
<div id="list">
<sib-router>
<sib-route name="detail" id-prefix="http://localhost:8000/members/">Voir le détail</sib-route>
</sib-router>
<div id="detail">
<sib-router>
<sib-route name="detail-red" id-prefix="http://localhost:8000/members/">en rouge</sib-route>
<sib-route name="detail-blue" id-prefix="http://localhost:8000/members/">en bleu</sib-route>
</sib-router>
<sib-display
id="detail-red"
style="color:red"
bind-resources
loader-id="loader"
data-src="http://localhost:8000/members/3/"
data-fields="firstname, author, text, assignees"
value-text="Ceci est un détail"
widget-assignees="sib-display-list"
></sib-display>
<sib-display
id="detail-blue"
style="color:blue"
bind-resources
loader-id="loader"
data-src="http://localhost:8000/members/3/"
data-fields="firstname, author, text, assignees"
value-text="Ceci est un détail"
widget-assignees="sib-display-list"
></sib-display>
</div>
<sib-display
id="list"
data-src="http://localhost:8000/members/"
data-fields="set1, author"
set-set1="firstname, lastname"
value-text="youpi"
search-fields="firstname, lastname"
next="detail"
></sib-display>
</div>
<ldp-display
id="list"
data-src="http://localhost:8000/todos/"
data-fields="set1, author"
set-set1="name, text"
value-text="youpi"
search-fields="name, author"
next="detail"
></ldp-display>
<div id="form">
<ldp-router route-prefix="form">
<ldp-route name="create">Nouveau</ldp-route>
<ldp-route name="edit">Modifier</ldp-route>
</ldp-router>
<sib-router default-route="create">
<sib-route name="create">Nouveau</sib-route>
<sib-route name="edit">Modifier</sib-route>
</sib-router>
<section id="form-root">
<ldp-form id="create" data-src="http://localhost:8000/todos/"></ldp-form>
<ldp-form
<sib-form id="create" data-src="http://localhost:8000/members/"></sib-form>
<sib-form
id="edit"
data-src="http://localhost:8000/todos/6/"
data-src="http://localhost:8000/members/3/"
next="list"
widget-done="ldp-form-checkbox"
widget-done="sib-form-checkbox"
label-name="What's your name, honey?"
range-author="http://localhost:8000/users/"
></ldp-form>
range-author="http://localhost:8000/members/"
></sib-form>
</section>
</div>
</main>
......
<script>
(function(){
class LDPRoute extends HTMLElement {
get name() {
return this.getAttribute('name');
}
set name(name) {
this.setAttribute('name', name);
}
connectedCallback() {
this.addEventListener('click', function(event) {
this.closest('ldp-router').navigate(this.name);
}.bind(this));
}
}
class LDPRouter extends HTMLElement {
constructor() {
super();
window.addEventListener('popstate', event => this.display());
window.addEventListener('navigate', event => this.navigate(event.detail.route, event.detail.resource));
if(document.readyState=="complete") window.addEventListener('WebComponentsReady', event => this.display());
else document.addEventListener("DOMContentLoaded", event => this.display());
}
get useHash() {
return this.hasAttribute('use-hash');
}
get prefix() {
if(this.hasAttribute('route-prefix'))
return this.getAttribute('route-prefix') + '/';
else
return '';
}
get defaultRoute() {
return this.getAttribute('default-route') || '';
}
get currentRoute() {
const url = (this.useHash ? location.hash : location.pathname).slice(1);
if(url.startsWith(this.prefix))
return url.slice(this.prefix.length);
else
return null;
}
display(name) {
name = name || this.currentRoute || this.defaultRoute;
for(let route of this.querySelectorAll('ldp-route')) {
const view = document.getElementById(route.name);
if(view) {
if(name.split('/')[0] == route.name) {
view.style.display = 'block';
route.setAttribute('active', '');
//handle resource id
if(route.hasAttribute('id-prefix') && name.split('/')[1]) {
const id = route.getAttribute('id-prefix') + name.split('/')[1] + '/';
if(view.hasAttribute('bind-resources'))
view.setAttribute('data-src', id);
for(let element of view.querySelectorAll('[bind-resources]'))
element.setAttribute('data-src', id);
}
} else {
view.style.display = 'none';
route.removeAttribute('active');
// Reseting all routers within the selected view
for(let router of view.querySelectorAll('ldp-router'))
router.display();
}
}
}
}
navigate(name, resource) {
name = name || '';// of the route
let id='', url = this.prefix + name;
const route = this.querySelector('ldp-route[name='+name+']');
if(!route) return; //this route is not for me!
//if there is a resource, add its id to the url
if(resource && route.hasAttribute('id-prefix'))
id = '/' + resource['@id'].replace(route.getAttribute('id-prefix'), '');
if(this.useHash)
window.location.hash = url + id;
else
history.pushState({}, name, '/' + url + id);
this.display(name + id);
}
}
customElements.define('ldp-router', LDPRouter);
customElements.define('ldp-route', LDPRoute);
}());
</script>
<script>
(function(){
class SIBRoute extends HTMLElement {
connectedCallback() {
this.addEventListener('click', event => this.router.navigate(this.name));
}
get name() {
return this.getAttribute('name');
}
set name(name) {
this.setAttribute('name', name);
}
get router() {
return this.closest('sib-router');
}
get resourceId() {
//get resource id from url
if(this.hasAttribute('id-prefix') && this.router.currentURL.split('/')[1])
return this.getAttribute('id-prefix') + this.router.currentURL.split('/')[1] + '/';
}
getPath(prefix, name, id) {
if(id && this.hasAttribute('id-prefix'))
id = id.replace(this.getAttribute('id-prefix'), '');
return [prefix, name, id].filter(s=>s).join('/');
}
updateResource(view) {
if(this.resourceId) {
if(view.hasAttribute('bind-resources'))
view.setAttribute('data-src', this.resourceId);
for(let element of view.querySelectorAll('[bind-resources]'))
element.setAttribute('data-src', this.resourceId);
}
}
updateSubrouter(router) {
router.setAttribute('route-prefix', this.getPath(this.router.prefix, this.name, this.resourceId));
router.display();
}
activate() {
const view = document.getElementById(this.name);
if(view) {
view.style.display = 'block';
this.setAttribute('active', '');
this.updateResource(view);
view.scrollIntoView();
// Reseting all routers within the selected view
for(let router of view.querySelectorAll('sib-router'))
this.updateSubrouter(router);
}
}
hide() {
const view = document.getElementById(this.name);
view.style.display = 'none';
this.removeAttribute('active');
}
}
customElements.define('sib-route', SIBRoute);
class SIBRouter extends HTMLElement {
constructor() {
super();
window.addEventListener('popstate', event => this.display());
window.addEventListener('navigate', event => this.navigate(event.detail.route, event.detail.resource));
window.addEventListener('WebComponentsReady', event => 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.slice(1));
if(url.startsWith(this.prefix))
url = url.slice(this.prefix.length);
if(url.startsWith('/'))
url = url.slice(1);
return url;
}
get currentRouteName() {
return this.currentURL.split('/')[0] || this.defaultRoute;
}
get routes() {
return this.querySelectorAll('sib-route');
}
display(name) {
name = name || this.currentRouteName;
for(let route of this.routes)
if(name == route.name)
route.activate();
else
route.hide();
}
navigate(name, resource) {
name = name || '';// of the route
const route = this.querySelector('sib-route[name='+name+']');
if(!route) return; //this route is not for me!
const id = resource ? resource['@id'] : null;
//update current URL
if(this.useHash)
window.location.hash = route.getPath(this.prefix, name, id);
else
history.pushState({}, name, '/' + route.getPath(this.prefix, name, id));
this.dispatchEvent(new CustomEvent('navigate', {detail: {route: name, resource: resource}}));
this.display(name);
}
}
customElements.define('sib-router', SIBRouter);
}());
</script>
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