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
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
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
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 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
#### 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
### Use 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.
### 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](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM).
```css
:root {
--histhub-h3-maring: 0 0 0 0.5rem;
......
......@@ -74,7 +74,7 @@
<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>
</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>
Additional comment
</histhub-widget>
......
(function() {
const defaultTemplate = document.createElement('template');
defaultTemplate.innerHTML = `
(function () {
const defaultTemplate = document.createElement('template');
defaultTemplate.innerHTML = `
<style>
:host{
--histhub-h3-maring: 0 0 0 0.5rem;
......@@ -56,169 +56,185 @@
<div id="links">Loading data...</div>
<slot></slot>`;
class HisthubWidget extends HTMLElement {
constructor() {
super();
this.attachShadow({mode: "open"});
}
class HisthubWidget extends HTMLElement {
constructor() {
super();
this.attachShadow({mode: "open"});
}
/**
* Observable attributes
**/
static get observedAttributes() {
return ["loading", "links", "template"];
}
/**
* Observable attributes
**/
static get observedAttributes() {
return ["loading", "links", "template"];
}
/**
* Get loading attribute
*/
get loading() {
return JSON.parse(this.getAttribute("loading"));
}
/**
* Get loading attribute
*/
get loading() {
return JSON.parse(this.getAttribute("loading"));
}
/**
* Set loading attribute
**/
set loading(v) {
this.setAttribute("loading", JSON.stringify(v));
}
/**
* Set loading attribute
**/
set loading(v) {
this.setAttribute("loading", JSON.stringify(v));
}
/**
* Get links attribute
**/
get links() {
return JSON.parse(this.getAttribute("links"));
}
/**
* Get links attribute
**/
get links() {
return JSON.parse(this.getAttribute("links"));
}
/**
* Set links attribute
**/
set links(v) {
this.setAttribute("links", JSON.stringify(v));
}
/**
* Set links attribute
**/
set links(v) {
this.setAttribute("links", JSON.stringify(v));
}
get template() {
return this.getAttribute('template');
get 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){
this.setAttribute('template', template);
} else {
this.removeAttribute('template');
/**
* Fetch the links from the endpoint
* @param url string
* @param resolver string
* @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
* @param url string
* @param resolver string
* @param location string
* @return {Promise<void>}
*/
async fetchLinks(url, resolver, location) {
this.loading = true;
// todo: more dynamic
const response = await fetch(`${url}${location}`);
const json = await response.json();
this.links = json.data[resolver].links;
this.loading = false;
}
/**
* Start the component
* @return {Promise<void>}
*/
async connectedCallback() {
this.addShadowDom();
// set defaults html attributes
if (!this.hasAttribute('role')) {
this.setAttribute('role', 'complementary');
}
if (!this.hasAttribute('tabindex')) {
this.setAttribute('tabindex', 0);
}
/**
* Start the component
* @return {Promise<void>}
*/
async connectedCallback() {
// set defaults html attributes
if (!this.hasAttribute('role')) {
this.setAttribute('role', 'complementary');
}
if (!this.hasAttribute('tabindex')) {
this.setAttribute('tabindex', 0);
}
const url = this.getAttribute('endpoint');
const resolver = this.getAttribute('resolver');
// optional attributes
const language = this.getAttribute('language') || null;
const timeout = this.getAttribute('timeout') || null;
const location = this.getAttribute('location') || window.location.href;
if (typeof url === 'undefined' || typeof resolver === 'undefined' || typeof location === 'undefined') {
throw new Error("Missing required parameters");
}
try {
await this.fetchLinks(url, resolver, location, {language, timeout});
} catch(error) {
console.log(error);
}
}
const url = this.getAttribute('endpoint');
const resolver = this.getAttribute('resolver');
const location = this.getAttribute('location') || window.location.href;
if (typeof url === 'undefined' || typeof resolver === 'undefined' || typeof location === 'undefined') {
throw new Error("Missing required parameters");
}
this.addShadowDom();
await this.fetchLinks(url, resolver, location);
}
/**
* Destroy the component
**/
disconnectedCallback() {
}
/**
* Destroy the component
**/
disconnectedCallback() {}
/**
* Render if the attributes changes
* @param attrName
* @param oldVal
* @param newVal
*/
attributeChangedCallback(attrName, oldVal, newVal) {
if(oldVal !== newVal) {
this.render();
}
}
/**
* Render if the attributes changes
* @param attrName
* @param oldVal
* @param newVal
*/
attributeChangedCallback(attrName, oldVal, newVal) {
if (oldVal !== newVal && attrName !== 'template') {
this.render();
}
}
addShadowDom() {
const { shadowRoot, template } = this;
const templateNode = document.getElementById(template);
shadowRoot.innerHTML = '';
if (templateNode) {
const content = document.importNode(templateNode.content, true);
shadowRoot.appendChild(content);
} else {
this.shadowRoot.appendChild(defaultTemplate.content.cloneNode(true));
}
addShadowDom() {
const { template} = this;
const templateNode = document.getElementById(template);
this.shadowRoot.innerHTML = '';
if (templateNode) {
const content = document.importNode(templateNode.content, true);
this.shadowRoot.appendChild(content);
} else {
this.shadowRoot.appendChild(defaultTemplate.content.cloneNode(true));
}
// shortcut for slots
this._titleSlot = this.shadowRoot.querySelector('slot[name=title]');
this._linksSlot = this.shadowRoot.querySelector('#links');
}
// shortcut for slots
this._titleSlot = this.shadowRoot.querySelector('slot[name=title]');
this._linksSlot = this.shadowRoot.querySelector('#links');
}
/**
* Render the component
*/
render() {
if (!this.loading) {
if(this.links.length === 0) {
// hide if there is no data
this._linksSlot.style.display = 'none';
this._titleSlot.style.display = 'none';
} else {
// small util to build the links
const buildLinks = () => this.links.map((link) => {
let anchor = null;
let href = null;
// check f we get an array (v1) or an object (v1.1)
if (typeof link === "object") {
const provider = Object.keys(link)[0];
// often we do not have information about the provider
if (typeof provider === "string" && provider !== "") {
anchor = provider;
} else {
anchor = link[provider];
}
href = link[provider];
} else {
href = link;
anchor = link;
}
// build the list
return `<li><a href="${href}"> ${anchor}</a></li>`;
});
this._linksSlot.innerHTML = `<ul>${buildLinks().join("")}</ul>`;
}
/**
* Render the component
*/
render() {
if (!this.loading) {
if (this.links === null || this.links.length === 0 ) {
// hide if there is no data
this._linksSlot.style.display = 'none';
this._titleSlot.style.display = 'none';
} else {
// small util to build the links
const buildLinks = () => this.links.map((link) => {
let anchor = null;
let href = null;
// check f we get an array (v1) or an object (v1.1)
if (typeof link === "object") {
const provider = Object.keys(link)[0];
// often we do not have information about the provider
if (typeof provider === "string" && provider !== "") {
anchor = provider;
} else {
anchor = link[provider];
}
href = link[provider];
} else {
href = link;
anchor = link;
}
// build the list
return `<li><a href="${href}"> ${anchor}</a></li>`;
});
this._linksSlot.innerHTML = `<ul>${buildLinks().join("")}</ul>`;
}
}
}
}
// register the component
window.customElements.define('histhub-widget', HisthubWidget);
// register the component
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