From 1cd0b5f21ed078800190ba62c5e77a188e6e7494 Mon Sep 17 00:00:00 2001 From: Ben <36240171+benkyd@users.noreply.github.com> Date: Sat, 19 Mar 2022 22:27:37 +0200 Subject: [PATCH] getting to templating better? Former-commit-id: bb30b5faa1aa282ef20461acabe00368d833783d --- client/public/components/components.js | 87 --------- client/public/components/components.mjs | 68 +++++++ .../components/{navbar => css}/navbar.css | 0 .../components/{navbar => css}/navbar.js | 0 .../components/{navbar => }/navbar.html | 0 client/public/components/navbar.mjs | 18 ++ client/public/components/notification-bar.js | 166 ------------------ client/public/index.html | 11 +- client/public/index.mjs | 13 +- docs/CLIENT-FRAMEWORK.md | 0 10 files changed, 97 insertions(+), 266 deletions(-) delete mode 100644 client/public/components/components.js create mode 100644 client/public/components/components.mjs rename client/public/components/{navbar => css}/navbar.css (100%) rename client/public/components/{navbar => css}/navbar.js (100%) rename client/public/components/{navbar => }/navbar.html (100%) create mode 100644 client/public/components/navbar.mjs delete mode 100644 client/public/components/notification-bar.js create mode 100644 docs/CLIENT-FRAMEWORK.md diff --git a/client/public/components/components.js b/client/public/components/components.js deleted file mode 100644 index 893ed79..0000000 --- a/client/public/components/components.js +++ /dev/null @@ -1,87 +0,0 @@ -async function sideLoad(path) { - return await fetch(path).then(response => response.text()); -} - -const Components = []; - -export function RegisterComponent(name, component) { - customElements.define(`${name}-component`, component); - Components[name] = component; -} - -export function UpdateComponent(name) { - -} - -export default class BaseComponent extends HTMLElement { - constructor() { - super(); - this.attachShadow({ mode: 'open' }); - } - - - async attatchTemplate(path) { - const template = await sideLoad(path); - this.shadowRoot.innerHTML = template; - } -} - -// other components with behaviour go here -// non-generic components - -class LoadingComponent extends BaseComponent { - async connectedCallback() { - - } -} - -customElements.define('loading-component', LoadingComponent); - - -// some not-so-scalable way to load all the generic template-like components -async function loadComponents() { - // because of "sECuRItY" i can't simply just find everything in the components folder - // there is a way to sideload this with express and have it do all that stuff - // TODO: implement this - const components = [ - 'navbar', - 'notification-bar', - ]; - - for (let i = 0; i < components.length; i++) { - const path = `./components/${components[i]}/${components[i]}.html`; - let component = await sideLoad(path); - - const stylePath = `./components/${components[i]}/${components[i]}.css`; - const styleComponent = await sideLoad(stylePath); - - const scriptPath = `./components/${components[i]}/${components[i]}.js`; - const scriptComponent = await sideLoad(scriptPath); - - const Template = class extends HTMLElement { - connectedCallback() { - // TODO: THIS NEEDS DOCUMENTATION / REFACTORING - // make a kinda generic way to do this - // needs to be before the shadow dom is attatched - component = component.replace('${innerText}', this.innerText); - - const shadow = this.attachShadow({ mode: 'open' }); - - shadow.innerHTML = component; - - const script = document.createElement('script'); - script.text = scriptComponent; - shadow.appendChild(script); - - // always assume global.css is the first css file - const style = document.createElement('style'); - style.textContent = styleComponent; - shadow.appendChild(style); - } - }; - Object.defineProperty(Template, 'name', { value: components[i] }); - customElements.define(`${components[i]}-component`, Template); - } -} - -loadComponents(); diff --git a/client/public/components/components.mjs b/client/public/components/components.mjs new file mode 100644 index 0000000..eeeae7e --- /dev/null +++ b/client/public/components/components.mjs @@ -0,0 +1,68 @@ +export async function SideLoad(path) { + return await fetch(path).then(response => response.text()); +} + +const Components = []; + + +export function RenderComponent(componentClass) { + const name = componentClass.__IDENTIFY(); + if (!Components[name]) { + const newComponent = new componentClass(); + Components[name] = newComponent; + customElements.define(`${name}-component`, newComponent); + } + + Components[name].__INVOKE_RENDER(); +} + +export class BaseComponent extends HTMLElement { + constructor(name) { + super(); + this.root = this.attachShadow({ mode: 'open' }); + this.state = {}; + RegisterComponent(name, this); + } + + // Override this + Render() { this.__WARN('Render'); } + + SetState(newState) { + this.state = newState; + this.__INVOKE_RENDER(Object.bind(this)); + } + + async __INVOKE_RENDER() { + const res = this.Render(Object.bind(this)); + if (!res.template || !res.style) { + this.__ERR('no template or style'); + return; + } + if (res.template.PromiseState) { + res.template = await res.template; + } + if (res.style.PromiseState) { + res.style = await res.style; + } + + // go through and resolve all of the "state" dependancies + const parserRegex = /{.*?}/; + for (let m; (m = parserRegex.exec(res.template)) !== null;) { + if (m.index === parserRegex.lastIndex) { + parserRegex.lastIndex++; + } + + console.log(m[2]); + } + } + + static __IDENTIFY() { this.__WARN('identify'); } + + __WARN(caller) { + console.error(`WARNING: ${caller} is not implemented`); + } + + __ERR(msg) { + console.error(`ERROR: idiot ${msg}`); + } +} diff --git a/client/public/components/navbar/navbar.css b/client/public/components/css/navbar.css similarity index 100% rename from client/public/components/navbar/navbar.css rename to client/public/components/css/navbar.css diff --git a/client/public/components/navbar/navbar.js b/client/public/components/css/navbar.js similarity index 100% rename from client/public/components/navbar/navbar.js rename to client/public/components/css/navbar.js diff --git a/client/public/components/navbar/navbar.html b/client/public/components/navbar.html similarity index 100% rename from client/public/components/navbar/navbar.html rename to client/public/components/navbar.html diff --git a/client/public/components/navbar.mjs b/client/public/components/navbar.mjs new file mode 100644 index 0000000..1a22d9d --- /dev/null +++ b/client/public/components/navbar.mjs @@ -0,0 +1,18 @@ +import { RenderComponent, BaseComponent, SideLoad } from './components.mjs'; + +class SearchBar extends BaseComponent { + +} + +class NavBar extends BaseComponent { + static __IDENTIFY() { return 'navbar'; } + + Render() { + return { + template: SideLoad('./components/navbar.html'), + style: SideLoad('./components/css/navbar.css'), + }; + } +} + +RenderComponent(NavBar); diff --git a/client/public/components/notification-bar.js b/client/public/components/notification-bar.js deleted file mode 100644 index 883379b..0000000 --- a/client/public/components/notification-bar.js +++ /dev/null @@ -1,166 +0,0 @@ -import BaseComponent from './components.js'; - -export default class NotificationBarComponent extends BaseComponent { - constructor() { - super(); - this.attachShadow({ mode: 'open' }); - } - - render() { - this.html = ` - `; - } - - attatchStyle() { - return ` - .notification-bar { - display: inline-block; - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 2em; - background-color: #00B4F5; - box-shadow: #222 0px 0px 5px; - transition: all 0.3s ease-in; - } - - .notification-bar-text { - font-family: 'Josefin Sans', sans-serif; - text-transform: uppercase; - text-align: center; - color: #fff; - padding: 0px 1em; - height: 100%; - line-height: 35px; - font-size: 1.3em; - font-weight: bold; - text-align: center; - } - - .notification-bar-close { - display: inline-block; - padding: 0px 1em; - height: 100%; - line-height: 2em; - color: #fff; - font-size: 1.5em; - font-weight: bold; - text-align: center; - font-family: 'Open Sans', sans-serif; - } - - .notification-bar-close:hover { - color: #fff; - } - - .notification-bar-close:focus { - outline: none; - } - - .notification-bar-close:active { - color: #fff; - } - - .notification-bar-close:hover { - color: #fff; - } - - .notification-bar-close:focus { - outline: none; - } - - .notification-toggler { - position: absolute; - right: 2px; - top: 2px; - background: transparent; - border: none; - cursor: pointer; - outline: none; - height: 2em; - width: 2em; - z-index: 100; - transition: all 0.2s ease-in; - } - - .cross-line { - background: #222; - box-shadow: #222 0px 0px 2px; - position: absolute; - height: 2px; - left: 0; - width: 100%; - } - - #notification-toggler:hover .cross-line { - background: #777; - } - - .cross-line-top { - top: 50%; - transform: rotate(45deg) translatey(-50%); - } - - .cross-line-bottom { - bottom: 50%; - transform: rotate(-45deg) translatey(50%); - } - - /* move it further up the screen than the mobile toggler would */ - .notification-toggled { - transform: translatey(-200%); - } - - /* don's show on mobile or 'small mode' */ - @media (pointer:none), (pointer:coarse), screen and (max-width: 900px) { - .notification-bar { - transform: translatey(-200%); - } - }`; - } -} diff --git a/client/public/index.html b/client/public/index.html index 348b02f..e2fddf4 100644 --- a/client/public/index.html +++ b/client/public/index.html @@ -8,12 +8,9 @@ - - - - - - + + + @@ -34,7 +31,7 @@ - +