Commit 488ca64e authored by Sylvain Le Bon's avatar Sylvain Le Bon

initial commit

## Synopsis
This is a series of web component respecting both the web components standards and the Linked Data Platform convention.
They are aimed at enabling anyone with little development skills to create their own web application by placing these components in an HTML file.
## Code Example
An full app example can be found in index.html:
## Initialization
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:
<script type="text/javascript" src=""></script>
<link rel="import" href="" />
<link rel="import" href="" />
<link rel="import" href="" />
<link rel="import" href="" />
<link rel="import" href="" />
Then you can use the new tags in your markup, for instance : `<ldp-display>`. More details on each component in the following section.
## Components documentation
### ldp-display &nbsp;&&nbsp; ldp-form
**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 :**
set-info="task, date"
value-created="Created by :"
set-author="created, name"
data-fields="image, status, author, deadline"
search-fields="name, author"
**`<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"`.
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.
- **route-prefix**: If you app is not run from the root of your domain name, for instance ``, 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:**
- **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.
**Example :**
<ldp-route name="list">List</ldp-route>
<ldp-route name="form">Form</ldp-route>
<ldp-route name="detail">Details</ldp-route>
## 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.
## License
No licence yet. Please wait...
<!DOCTYPE html>
<meta charset="UTF-8">
<script type="text/javascript" src=""></script>
<link rel="import" href="" />
<link rel="import" href="" />
<link rel="import" href="ldp-router.html" />
ldp-display {
display: flex;
#detail {
float: right;
border: solid blue;
.set1 {
display: flex;
color: orange;
.text {
font-weight: bold;
<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 route-prefix="list">
<ldp-route name="detail" id-prefix="http://localhost:8000/todos/">Voir le détail</ldp-route>
<div id="detail">
data-fields="name, author, text, assignees"
value-text="Ceci est un détail"
data-fields="set1, author"
set-set1="name, text"
search-fields="name, author"
<div id="form">
<ldp-router route-prefix="form">
<ldp-route name="create">Nouveau</ldp-route>
<ldp-route name="edit">Modifier</ldp-route>
<section id="form-root">
<ldp-form id="create" data-src="http://localhost:8000/todos/"></ldp-form>
label-name="What's your name, honey?"
class LDPRoute extends HTMLElement {
get name() {
return this.getAttribute('name');
set name(name) {
this.setAttribute('name', name);
connectedCallback() {
this.addEventListener('click', function(event) {
class LDPRouter extends HTMLElement {
constructor() {
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() {
return this.getAttribute('route-prefix') + '/';
return '';
get defaultRoute() {
return this.getAttribute('default-route') || '';
get currentRoute() {
const url = (this.useHash ? location.hash : location.pathname).slice(1);
return url.slice(this.prefix.length);
return null;
display(name) {
name = name || this.currentRoute || this.defaultRoute;
for(let route of this.querySelectorAll('ldp-route')) {
const view = document.getElementById(;
if(view) {
if(name.split('/')[0] == { = 'block';
route.setAttribute('active', '');
//handle resource id
if(route.hasAttribute('id-prefix') && name.split('/')[1]) {
const id = route.getAttribute('id-prefix') + name.split('/')[1] + '/';
view.setAttribute('data-src', id);
for(let element of view.querySelectorAll('[bind-resources]'))
element.setAttribute('data-src', id);
} else { = 'none';
// Reseting all routers within the selected view
for(let router of view.querySelectorAll('ldp-router'))
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'), '');
window.location.hash = url + id;
history.pushState({}, name, '/' + url + id);
this.display(name + id);
customElements.define('ldp-router', LDPRouter);
customElements.define('ldp-route', LDPRoute);
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