getting to templating better?

Former-commit-id: bb30b5faa1aa282ef20461acabe00368d833783d
This commit is contained in:
Ben
2022-03-19 22:27:37 +02:00
parent a588ee3f0f
commit 1cd0b5f21e
10 changed files with 97 additions and 266 deletions

View File

@@ -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();

View File

@@ -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}`);
}
}

View File

@@ -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);

View File

@@ -1,166 +0,0 @@
import BaseComponent from './components.js';
export default class NotificationBarComponent extends BaseComponent {
constructor() {
super();
this.attachShadow({ mode: 'open' });
}
render() {
this.html = `
<nav class="navbar">
<div class="logo"><img src="res/logo.svg" height="80em" alt="logo"></div>
<div class="push-right">
<!-- https://jonsuh.com/hamburgers/ -->
<button id="menu-toggler" class="hamburger">
<span class="hamburger-line hamburger-line-top"></span>
<span class="hamburger-line hamburger-line-middle"></span>
<span class="hamburger-line hamburger-line-bottom"></span>
</button>
<ul class="primary-menu menu nav-menu">
<li class="menu-item current-menu-item"><a class="nav-link" href="#">New</a></li>
<li class="menu-item dropdown"><a class="nav-link" href="#">Sets▾</a>
<!-- TODO: Going to need to dynamically generate this -->
<ul class = "sub-nav">
<li><a class="sub-nav-link" href="#">1</a></li>
<li><a class="sub-nav-link" href="#">2</a></li>
<li><a class="sub-nav-link" href="#">3</a></li>
</ul>
</li>
<li class="menu-item dropdown"><a class="nav-link" href="#">Bricks▾</a>
<ul class="sub-nav" >
<li><a class="sub-nav-link" href="#">1</a></li>
<li><a class="sub-nav-link" href="#">2</a></li>
<li><a class="sub-nav-link" href="#">3</a></li>
</ul>
</li>
<li class="menu-item"><a class="nav-link" href="#">My Account</a>
</ul>
<ul class="secondary-menu menu push-down">
<span class="search-wrapper">
<input id="search-bar" class="menu-item" type="text" placeholder="search..."/>
</span>
<img id="fave-icon" class="menu-item" src="https://www.svgrepo.com/show/25921/heart.svg" width="27px" stroke="#222" stroke-width="2px" alt="">
<span id="cart-wrapper">
<img id="cart-icon" class="menu-item" src="https://www.svgrepo.com/show/343743/cart.svg" width="30px" stroke="#222" stroke-width="2px" alt="">
<span id="cart-number" class="menu-item">5</span>
</span>
</ul>
</div>
</nav>`;
}
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%);
}
}`;
}
}

View File

@@ -8,12 +8,9 @@
<!-- ask rich about loading fonts elsewhere -->
<link href="https://fonts.googleapis.com/css2?family=Londrina+Solid&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Josefin+Sans&display=swap" rel="stylesheet">
<script type="module" src="components/components.js"></script>
<script src="brick-renderer/webgl-debug.js"></script>
<script type="module" src="brick-renderer/glm/glm.mjs"></script>
<script type="module" src="brick-renderer/shader.mjs"></script>
<script type="module" src="brick-renderer/index.mjs"></script>
<script type="module" src="components/components.mjs"></script>
<script type="module" src="components/navbar.mjs"></script>
<script type="module" src="index.mjs"></script>
</head>
@@ -34,7 +31,7 @@
</content-margin>
<canvas id="webglviewer" width="300" height="300"></canvas>
<!-- <canvas id="webglviewer" width="300" height="300"></canvas> -->
<!-- <canvas id="webglviewer" width="300" height="300"></canvas>
<canvas id="webglviewer" width="300" height="300"></canvas>
<canvas id="webglviewer" width="300" height="300"></canvas>

View File

@@ -1,12 +1,13 @@
import { RendererPreInit, BrickRenderer } from './brick-renderer/index.mjs';
// import { RendererPreInit, BrickRenderer } from './brick-renderer/index.mjs';
async function main() {
await RendererPreInit();
// await RendererPreInit();
// const canvas = document.querySelectorAll('#webglviewer');
// for (let i = 0; i < canvas.length; i++) {
// const Renderer = new BrickRenderer(canvas[i]);
// }
const canvas = document.querySelectorAll('#webglviewer');
for (let i = 0; i < canvas.length; i++) {
const Renderer = new BrickRenderer(canvas[i]);
}
}
window.onload = main;

0
docs/CLIENT-FRAMEWORK.md Normal file
View File