From 28ca48667feefca6e9365104803e23cd11262ee0 Mon Sep 17 00:00:00 2001 From: Ambrose Chua Date: Sun, 22 Nov 2020 16:41:58 +0800 Subject: [PATCH] Add basic interaction --- Makefile | 4 +- assets/css/styles.css | 16 +- assets/js/interactive.js | 340 ++++++++++++++++++++++++++++++- templates/icon_solid_plus.svg | 1 + templates/icon_solid_trash.svg | 1 + templates/index.html | 16 +- templates/interactive-icons.html | 24 +++ 7 files changed, 389 insertions(+), 13 deletions(-) create mode 100644 templates/icon_solid_plus.svg create mode 100644 templates/icon_solid_trash.svg create mode 100644 templates/interactive-icons.html diff --git a/Makefile b/Makefile index d331a85..974694e 100644 --- a/Makefile +++ b/Makefile @@ -60,7 +60,9 @@ assets/js/third-party/luxon.min.js: ICONS = \ solid_sun \ solid_moon \ - solid_adjust + solid_adjust \ + solid_trash \ + solid_plus .PHONY: download-icons download-icons: $(foreach icon,$(ICONS),templates/icon_$(icon).svg) diff --git a/assets/css/styles.css b/assets/css/styles.css index 53253f8..919b4fd 100644 --- a/assets/css/styles.css +++ b/assets/css/styles.css @@ -66,6 +66,12 @@ footer { padding: 1.5rem; } +/* Web Component Fixes */ + +template { + display: none; +} + /* Essentials */ .list-inline { @@ -202,7 +208,7 @@ d-zoneerror { } /* Left container */ -d-zoneinfo { +.zoneinfo { flex: 1 1 0; width: 0px; /* Force sizing from zero */ @@ -212,7 +218,7 @@ d-zoneinfo { margin-right: 1rem; } @media (max-width: 319px) { - d-zoneinfo { + .zoneinfo { width: 100%; } } @@ -221,7 +227,7 @@ d-zonename { display: flex; justify-content: flex-start; } -d-zonename d-zonearea { +d-zonename .zonearea { flex: 0 1 auto; display: block; @@ -230,7 +236,7 @@ d-zonename d-zonearea { white-space: nowrap; text-overflow: ellipsis; } -d-zonename d-zonecountry { +d-zonename .zonecountry { flex: 0 0 auto; display: block; @@ -251,7 +257,7 @@ d-date { } /* Right container */ -d-zonefigure { +.zonefigure { display: block; margin-top: 1rem; margin-bottom: 1rem; diff --git a/assets/js/interactive.js b/assets/js/interactive.js index 70b786d..68149a1 100644 --- a/assets/js/interactive.js +++ b/assets/js/interactive.js @@ -1 +1,339 @@ -// TODO +'use strict'; + +/* + * Compatibility Checks + */ + +if (!window.customElements) { + console.warn('Custom Elements API is not available. Thus, interactivity is not available'); +} + +/* + * Custom Elements + */ + +const slotTemplate = document.createElement('template'); +slotTemplate.innerHTML = ` + +`; + +// Icons + +const iconSolidTrashTemplate = document.querySelector('#icon-solid-trash'); +class IconSolidTrashElement extends HTMLElement { + constructor() { + super(); + this.attachShadow({ mode: 'open' }); + this.shadowRoot.appendChild(iconSolidTrashTemplate.content.cloneNode(true)); + } +} + +const iconSolidPlusTemplate = document.querySelector('#icon-solid-plus'); +class IconSolidPlusElement extends HTMLElement { + constructor() { + super(); + this.attachShadow({ mode: 'open' }); + this.shadowRoot.appendChild(iconSolidPlusTemplate.content.cloneNode(true)); + } +} + +// Zone + +const zoneTemplate = document.createElement('template'); +zoneTemplate.innerHTML = ` + + +
+ +
+`; + +class ZoneElement extends HTMLElement { + constructor() { + super(); + + this.attachShadow({ mode: 'open' }); + this.shadowRoot.appendChild(zoneTemplate.content.cloneNode(true)); + } +} + +// ZoneName + +const zoneNameTemplate = document.createElement('template'); +zoneNameTemplate.innerHTML = ` + + +`; + +class ZoneNameElement extends HTMLElement { + constructor() { + super(); + + this.attachShadow({ mode: 'open' }); + this.shadowRoot.appendChild(zoneNameTemplate.content.cloneNode(true)); + } +} + +// ZoneOffset + +const zoneOffsetTemplate = document.createElement('template'); +zoneOffsetTemplate.innerHTML = ` + + +`; + +class ZoneOffsetElement extends HTMLElement { + constructor() { + super(); + + this.attachShadow({ mode: 'open' }); + this.shadowRoot.appendChild(zoneOffsetTemplate.content.cloneNode(true)); + } +} + +// Date + +class DateElement extends HTMLElement { + constructor() { + super(); + + this.attachShadow({ mode: 'open' }); + this.shadowRoot.appendChild(slotTemplate.content.cloneNode(true)); + } +} + +// Time + +class TimeElement extends HTMLElement { + constructor() { + super(); + + this.attachShadow({ mode: 'open' }); + this.shadowRoot.appendChild(slotTemplate.content.cloneNode(true)); + } +} + +// SearchList + +const zoneSearchTemplate = document.createElement('template'); +zoneSearchTemplate.innerHTML = ` + + +
+ + + + +
+`; + +class ZoneSearchElement extends HTMLElement { + constructor() { + super(); + + this.attachShadow({ mode: 'open' }); + this.shadowRoot.appendChild(zoneSearchTemplate.content.cloneNode(true)); + this.shadowRoot.querySelector('input[type=search]').addEventListener('input', this.input.bind(this)); + } + + input() { + const text = this.shadowRoot.querySelector('input[type=search]').value; + const e = new CustomEvent('searchinput', { detail: { text } }); + this.dispatchEvent(e); + } + + show(results) { + const resultsElement = this.shadowRoot.querySelector('#results'); + const template = this.shadowRoot.querySelector('#result-template').content; + + resultsElement.innerHTML = ''; + for (const result of results) { + const resultElement = template.cloneNode(true); + resultElement.querySelector('d-zonename').innerText = result.n; + resultElement.querySelector('d-zoneoffset').innerText = '+to:do'; + resultElement.querySelector('.add').dataset.id = result.id; + resultElement.querySelector('.add').addEventListener('click', (e) => { + this.resultClick(result); + }); + resultsElement.appendChild(resultElement); + } + } + + resultClick(zone) { + console.debug(zone.id); + } +} + +// ZoneAdd + +const zoneAddTemplate = document.createElement('template'); +zoneAddTemplate.innerHTML = ` + + +
+ +
+`; + +class ZoneAddElement extends HTMLElement { + constructor() { + super(); + + this.attachShadow({ mode: 'open' }); + this.shadowRoot.appendChild(zoneAddTemplate.content.cloneNode(true)); + + this.searchElement = this.shadowRoot.querySelector('d-zoneadd-search'); + window.s = this.searchElement; + this.searchElement.show([ + { n: 'St. John\'s, Newfoundland and Labrador, CA', id: 'St_John\'s-Newfoundland_and_Labrador-CA' }, + { n: 'Singapore, SG', id: 'Singapore-SG' }, + ]); + this.searchElement.addEventListener('searchinput', this.input.bind(this)); + } + + input({ detail: { text } }) { + console.debug(text); + } +} + +// Definitions + +window.customElements.define('icon-solid-trash', IconSolidTrashElement); +window.customElements.define('icon-solid-plus', IconSolidPlusElement); + +window.customElements.define('d-zone', ZoneElement); +window.customElements.define('d-zonename', ZoneNameElement); +window.customElements.define('d-zoneoffset', ZoneOffsetElement); +window.customElements.define('d-date', DateElement); +window.customElements.define('d-time', TimeElement); +// TODO: Instead of relying on , render using attributes + +window.customElements.define('d-zoneadd-search', ZoneSearchElement); +window.customElements.define('d-zoneadd', ZoneAddElement); diff --git a/templates/icon_solid_plus.svg b/templates/icon_solid_plus.svg new file mode 100644 index 0000000..c89cf64 --- /dev/null +++ b/templates/icon_solid_plus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/templates/icon_solid_trash.svg b/templates/icon_solid_trash.svg new file mode 100644 index 0000000..baafaa4 --- /dev/null +++ b/templates/icon_solid_trash.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/templates/index.html b/templates/index.html index 9de022c..e8f2d5e 100644 --- a/templates/index.html +++ b/templates/index.html @@ -22,11 +22,11 @@ {{else}} {{$zt := $t.In .Location}} - +
{{if not .IsOffset}} - {{.FirstName}}, -  {{.City.Country.Ref}} + {{.FirstName}}, +  {{.City.Country.Ref}} {{else}} @@ -37,18 +37,22 @@ {{.TimeOffset $t | formatOffset}} {{end}} {{$zt.Format "2006-01-02"}} - - +
+
{{$zt.Format "15:04"}} - +
{{end}} {{end}} {{end}} + + {{template "footer.html"}} + {{template "interactive-icons.html"}} + diff --git a/templates/interactive-icons.html b/templates/interactive-icons.html new file mode 100644 index 0000000..3938171 --- /dev/null +++ b/templates/interactive-icons.html @@ -0,0 +1,24 @@ + +