fwebc.js

Toy framework for learning web components
git clone git://git.finwo.net/lib/fwebc.js
Log | Files | Refs | README

commit d06776dadf8e263919b4460e3d8f0f1603587907
parent 64c8901abce610c8f458d41d3da4313dfa27231b
Author: finwo <finwo@pm.me>
Date:   Thu, 29 Oct 2020 09:29:16 +0100

Added rendering a state

Diffstat:
Mindex.js | 59+++++++++++++++++++++++++++++++++++++++++++++--------------
Mtest/partial/my-app.tag | 14+++++++++++++-
2 files changed, 58 insertions(+), 15 deletions(-)

diff --git a/index.js b/index.js @@ -16,6 +16,15 @@ base: '/partial', }; + const util = fwebc.util = { + isObject(obj) { + if (null === obj) return false; + if ('object' !== typeof obj) return false; + if (Array.isArray(obj)) return false; + return true; + } + }; + // Override configs fwebc.cfg = cfg => { Object.assign(config, cfg); @@ -37,18 +46,34 @@ // Register a component fwebc.register = (name, source) => { if (window.customElements.get(name)) return; + + // Remove nested template tags + let template = document.createElement('template'); + template.innerHTML = source; + if (template.content.firstChild instanceof HTMLTemplateElement) { + template = template.content.firstChild; + } + + // Extract scripts + let code = ''; + for(const child of [...template.content.children]) { + if (!(child instanceof HTMLScriptElement)) continue; + code += child.innerHTML; + template.content.removeChild(child); + } + + // Template should be a string + template = template.innerHTML; + + // Register the actual element window.customElements.define(name, class extends HTMLElement { constructor() { super(); - // Build shadowroot - let template = document.createElement('template'); - template.innerHTML = source; - if (template.content.firstChild instanceof HTMLTemplateElement) { - template = template.content.firstChild; - } + this.state = {}; + + // Initialize shadow root this.root = this.attachShadow({ mode: 'open' }); - this.root.appendChild(template.content); // Run plugins for (const plugin of plugins) { @@ -56,25 +81,31 @@ } // Run component code - (new Function([...this.root.children] - .filter(el => el instanceof HTMLScriptElement) - .map(el => el.innerHTML) - .join('') - )).call(this); + (new Function(code)).call(this); + this.root.innerHTML = this.render(); // Load dependencies if (this.dependencies) { dependencies.forEach(fwebc.load); } + + + } + + render() { + const fn = new Function(...Object.keys(this.state), "return `"+ template.replace(/`/g,'\\`') + "`;"); + return fn(...Object.values(this.state)); } update(data) { Object.entries(data) .forEach(([key, value]) => { - this.state[key] = this.isObject(this.state[key]) && - this.isObject(value) ? {...this.state[key], ...value} : value; + this.state[key] = util.isObject(this.state[key]) && + util.isObject(value) ? {...this.state[key], ...value} : value; }); + this.root.innerHTML = this.render(); } + }); }; diff --git a/test/partial/my-app.tag b/test/partial/my-app.tag @@ -1,8 +1,20 @@ <template> - <h2>Bird is the word!</h2> + <h2>Bird is the ${subject}!</h2> + <p> Currently running for ${n} seconds</p> <style> h2 { color: #555; } </style> + <script> + this.state = { + n: 0, + subject: 'WORD', + }; + setInterval(() => { + this.update({ + n: this.state.n + 1, + }); + }, 1000); + </script> </template>