getting to templating better?
Former-commit-id: bb30b5faa1aa282ef20461acabe00368d833783d
This commit is contained in:
@@ -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();
|
||||
68
client/public/components/components.mjs
Normal file
68
client/public/components/components.mjs
Normal 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}`);
|
||||
}
|
||||
}
|
||||
18
client/public/components/navbar.mjs
Normal file
18
client/public/components/navbar.mjs
Normal 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);
|
||||
@@ -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%);
|
||||
}
|
||||
}`;
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
@@ -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
0
docs/CLIENT-FRAMEWORK.md
Normal file
Reference in New Issue
Block a user