Commit 0e6977cf authored by Tobias Steiner's avatar Tobias Steiner
Browse files

Add language and timemout as optional parameter

parent becc06a3
...@@ -47,16 +47,20 @@ For the `similarto` endpoint the geolinker provides a `elasticsearchresolver`. T ...@@ -47,16 +47,20 @@ For the `similarto` endpoint the geolinker provides a `elasticsearchresolver`. T
The location is an optional parameter. By default the widget uses the current window.location.href to make the request. You can specify the url to look for over the url parameter The location is an optional parameter. By default the widget uses the current window.location.href to make the request. You can specify the url to look for over the url parameter
### Template ### Template
The `tempate` is an optional parameter. You can provide your own template to modify the structure and styles of the widget. The `tempate` is an optional parameter. You can provide your own template to modify the structure and styles of the widget.
### language (beta)
The `language` parameter is optional (default=de) and let you define the language of the provider. We resolve the name of the provider over the url pattern. Possible languages are `de`, `fr`, `it` and `en`.
### Timeout
The architecture of the `geolinker` waits for a certain timeout (default=2000) for the microservices to find an answer to the query. You can define that timeout. If you often get 404 try to set a higher timeout
## Styling ## Styling
The webcomponent uses a shadow dom and encapsulate the styles. So it will not use your sites default css styles but also not change any other styles in your site. There are two option to override the component default styles The webcomponent uses a shadow dom and encapsulate the styles. So it will not use your sites default css styles but also not change any other styles in your site. There are two option to override the component default styles
### Slots ### Slots
Slots provides the possibility to override some part of the webcomponent. The histhub-widget provides a `title` and a `defaut` slot. Slots provides the possibility to override some part of the webcomponent. The histhub-widget provides a `title` and a `defaut` slot.
### Heading (slot) #### Heading (slot)
You can change the Heading of the widget with the `title` slot. This slot will override the default title. In allmost all examples we use this slot to change the title. If you override a slot your site css rules applies for this element. Example #6 changes the color of the heading You can change the Heading of the widget with the `title` slot. This slot will override the default title. In allmost all examples we use this slot to change the title. If you override a slot your site css rules applies for this element. Example #6 changes the color of the heading
#### Default Slot #### Default Slot
If you want to display some additional text beneath the links you can use the default slot. Just put the content inside the histhub-widget element. Example #7 adds additional information under the links If you want to display some additional text beneath the links you can use the default slot. Just put the content inside the histhub-widget element. Example #7 adds additional information under the links
### Use css Variables ### Css Variables
To change basic visual aspects of the component you can define css variables and override default settings. You have the following options to change the styles of the shadow dom. To change basic visual aspects of the component you can define css variables and override default settings. You have the following options to change the styles of the [shadow dom](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM).
```css ```css
:root { :root {
--histhub-h3-maring: 0 0 0 0.5rem; --histhub-h3-maring: 0 0 0 0.5rem;
......
...@@ -74,7 +74,7 @@ ...@@ -74,7 +74,7 @@
<histhub-widget endpoint="//api.geolinker.histhub.ch/v1-1/similarto/" resolver="resolverelasticsearch" location="https://dodis.ch/G82"> <histhub-widget endpoint="//api.geolinker.histhub.ch/v1-1/similarto/" resolver="resolverelasticsearch" location="https://dodis.ch/G82">
<h3 slot="title" id="custom-title-color">Example 6: Links (similarto) from geolinker dodis: Diedenhofen and custom title color</h3> <h3 slot="title" id="custom-title-color">Example 6: Links (similarto) from geolinker dodis: Diedenhofen and custom title color</h3>
</histhub-widget> </histhub-widget>
<histhub-widget endpoint="//api.geolinker.histhub.ch/v1-1/similarto/" resolver="resolverelasticsearch" location="https://dodis.ch/G82"> <histhub-widget endpoint="//api.geolinker.histhub.ch/v1-1/similarto/" resolver="resolverelasticsearch" location="https://dodis.ch/G82" language="fr" timeout="50000">
<h3 slot="title">Example 7: Links (similarto) from geolinker dodis: Diedenhofen</h3> <h3 slot="title">Example 7: Links (similarto) from geolinker dodis: Diedenhofen</h3>
Additional comment Additional comment
</histhub-widget> </histhub-widget>
......
(function() { (function () {
const defaultTemplate = document.createElement('template'); const defaultTemplate = document.createElement('template');
defaultTemplate.innerHTML = ` defaultTemplate.innerHTML = `
<style> <style>
:host{ :host{
--histhub-h3-maring: 0 0 0 0.5rem; --histhub-h3-maring: 0 0 0 0.5rem;
...@@ -56,169 +56,185 @@ ...@@ -56,169 +56,185 @@
<div id="links">Loading data...</div> <div id="links">Loading data...</div>
<slot></slot>`; <slot></slot>`;
class HisthubWidget extends HTMLElement { class HisthubWidget extends HTMLElement {
constructor() { constructor() {
super(); super();
this.attachShadow({mode: "open"}); this.attachShadow({mode: "open"});
} }
/** /**
* Observable attributes * Observable attributes
**/ **/
static get observedAttributes() { static get observedAttributes() {
return ["loading", "links", "template"]; return ["loading", "links", "template"];
} }
/** /**
* Get loading attribute * Get loading attribute
*/ */
get loading() { get loading() {
return JSON.parse(this.getAttribute("loading")); return JSON.parse(this.getAttribute("loading"));
} }
/** /**
* Set loading attribute * Set loading attribute
**/ **/
set loading(v) { set loading(v) {
this.setAttribute("loading", JSON.stringify(v)); this.setAttribute("loading", JSON.stringify(v));
} }
/** /**
* Get links attribute * Get links attribute
**/ **/
get links() { get links() {
return JSON.parse(this.getAttribute("links")); return JSON.parse(this.getAttribute("links"));
} }
/** /**
* Set links attribute * Set links attribute
**/ **/
set links(v) { set links(v) {
this.setAttribute("links", JSON.stringify(v)); this.setAttribute("links", JSON.stringify(v));
} }
get template() { get template() {
return this.getAttribute('template'); return this.getAttribute('template');
}
set template(template) {
if (template) {
this.setAttribute('template', template);
} else {
this.removeAttribute('template');
} }
this.addShadowDom();
}
set template(template) { /**
if (template){ * Fetch the links from the endpoint
this.setAttribute('template', template); * @param url string
} else { * @param resolver string
this.removeAttribute('template'); * @param location string
* @param options {Object}
* @return {Promise<void>}
*/
async fetchLinks(url, resolver, location, options) {
let params = [];
this.loading = true;
if (Object.keys(options).length > 0) {
for(let key in options) {
if(options.hasOwnProperty(key) && options[key] !== null) {
params.push(`${key}=${options[key]}`);
} }
this.addShadowDom();
} }
}
const response = await fetch(`${url}${location}?${params.join('&')}`);
const json = await response.json();
this.links = json.data[resolver].links;
this.loading = false;
}
/** /**
* Fetch the links from the endpoint * Start the component
* @param url string * @return {Promise<void>}
* @param resolver string */
* @param location string async connectedCallback() {
* @return {Promise<void>} this.addShadowDom();
*/ // set defaults html attributes
async fetchLinks(url, resolver, location) { if (!this.hasAttribute('role')) {
this.loading = true; this.setAttribute('role', 'complementary');
// todo: more dynamic }
const response = await fetch(`${url}${location}`); if (!this.hasAttribute('tabindex')) {
const json = await response.json(); this.setAttribute('tabindex', 0);
this.links = json.data[resolver].links; }
this.loading = false;
}
/** const url = this.getAttribute('endpoint');
* Start the component const resolver = this.getAttribute('resolver');
* @return {Promise<void>} // optional attributes
*/ const language = this.getAttribute('language') || null;
async connectedCallback() { const timeout = this.getAttribute('timeout') || null;
// set defaults html attributes const location = this.getAttribute('location') || window.location.href;
if (!this.hasAttribute('role')) { if (typeof url === 'undefined' || typeof resolver === 'undefined' || typeof location === 'undefined') {
this.setAttribute('role', 'complementary'); throw new Error("Missing required parameters");
} }
if (!this.hasAttribute('tabindex')) { try {
this.setAttribute('tabindex', 0); await this.fetchLinks(url, resolver, location, {language, timeout});
} } catch(error) {
console.log(error);
}
}
const url = this.getAttribute('endpoint'); /**
const resolver = this.getAttribute('resolver'); * Destroy the component
const location = this.getAttribute('location') || window.location.href; **/
if (typeof url === 'undefined' || typeof resolver === 'undefined' || typeof location === 'undefined') { disconnectedCallback() {
throw new Error("Missing required parameters"); }
}
this.addShadowDom();
await this.fetchLinks(url, resolver, location);
}
/** /**
* Destroy the component * Render if the attributes changes
**/ * @param attrName
disconnectedCallback() {} * @param oldVal
* @param newVal
/** */
* Render if the attributes changes attributeChangedCallback(attrName, oldVal, newVal) {
* @param attrName if (oldVal !== newVal && attrName !== 'template') {
* @param oldVal this.render();
* @param newVal }
*/ }
attributeChangedCallback(attrName, oldVal, newVal) {
if(oldVal !== newVal) {
this.render();
}
}
addShadowDom() { addShadowDom() {
const { shadowRoot, template } = this; const { template} = this;
const templateNode = document.getElementById(template); const templateNode = document.getElementById(template);
shadowRoot.innerHTML = ''; this.shadowRoot.innerHTML = '';
if (templateNode) { if (templateNode) {
const content = document.importNode(templateNode.content, true); const content = document.importNode(templateNode.content, true);
shadowRoot.appendChild(content); this.shadowRoot.appendChild(content);
} else { } else {
this.shadowRoot.appendChild(defaultTemplate.content.cloneNode(true)); this.shadowRoot.appendChild(defaultTemplate.content.cloneNode(true));
} }
// shortcut for slots // shortcut for slots
this._titleSlot = this.shadowRoot.querySelector('slot[name=title]'); this._titleSlot = this.shadowRoot.querySelector('slot[name=title]');
this._linksSlot = this.shadowRoot.querySelector('#links'); this._linksSlot = this.shadowRoot.querySelector('#links');
} }
/** /**
* Render the component * Render the component
*/ */
render() { render() {
if (!this.loading) { if (!this.loading) {
if(this.links.length === 0) { if (this.links === null || this.links.length === 0 ) {
// hide if there is no data // hide if there is no data
this._linksSlot.style.display = 'none'; this._linksSlot.style.display = 'none';
this._titleSlot.style.display = 'none'; this._titleSlot.style.display = 'none';
} else { } else {
// small util to build the links // small util to build the links
const buildLinks = () => this.links.map((link) => { const buildLinks = () => this.links.map((link) => {
let anchor = null; let anchor = null;
let href = null; let href = null;
// check f we get an array (v1) or an object (v1.1) // check f we get an array (v1) or an object (v1.1)
if (typeof link === "object") { if (typeof link === "object") {
const provider = Object.keys(link)[0]; const provider = Object.keys(link)[0];
// often we do not have information about the provider // often we do not have information about the provider
if (typeof provider === "string" && provider !== "") { if (typeof provider === "string" && provider !== "") {
anchor = provider; anchor = provider;
} else { } else {
anchor = link[provider]; anchor = link[provider];
} }
href = link[provider]; href = link[provider];
} else { } else {
href = link; href = link;
anchor = link; anchor = link;
}
// build the list
return `<li><a href="${href}"> ${anchor}</a></li>`;
});
this._linksSlot.innerHTML = `<ul>${buildLinks().join("")}</ul>`;
}
} }
// build the list
return `<li><a href="${href}"> ${anchor}</a></li>`;
});
this._linksSlot.innerHTML = `<ul>${buildLinks().join("")}</ul>`;
} }
}
} }
}
// register the component // register the component
window.customElements.define('histhub-widget', HisthubWidget); window.customElements.define('histhub-widget', HisthubWidget);
})(); })();
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