mirror of
https://github.com/rio-labs/rio.git
synced 2026-01-01 10:49:58 -06:00
73 lines
2.3 KiB
TypeScript
73 lines
2.3 KiB
TypeScript
import { ComponentBase, ComponentState } from './componentBase';
|
|
|
|
export type HtmlState = ComponentState & {
|
|
_type_: 'Html-builtin';
|
|
html?: string;
|
|
};
|
|
|
|
export class HtmlComponent extends ComponentBase {
|
|
state: Required<HtmlState>;
|
|
|
|
private containerElement: HTMLElement;
|
|
|
|
createElement(): HTMLElement {
|
|
let element = document.createElement('div');
|
|
|
|
this.containerElement = document.createElement('div');
|
|
element.appendChild(this.containerElement);
|
|
|
|
return element;
|
|
}
|
|
|
|
runScriptsInElement(element: HTMLElement): void {
|
|
for (let oldScriptElement of this.containerElement.querySelectorAll(
|
|
'script'
|
|
)) {
|
|
console.debug('Running script', oldScriptElement.innerText);
|
|
|
|
// Create a new script element
|
|
const newScriptElement = document.createElement('script');
|
|
|
|
// Copy over all attributes
|
|
for (let i = 0; i < oldScriptElement.attributes.length; i++) {
|
|
const attr = oldScriptElement.attributes[i];
|
|
newScriptElement.setAttribute(attr.name, attr.value);
|
|
}
|
|
|
|
// And the source itself
|
|
newScriptElement.appendChild(
|
|
document.createTextNode(oldScriptElement.innerHTML)
|
|
);
|
|
|
|
// Finally replace the old script element with the new one so
|
|
// the browser executes it
|
|
oldScriptElement.parentNode!.replaceChild(
|
|
newScriptElement,
|
|
oldScriptElement
|
|
);
|
|
}
|
|
}
|
|
|
|
updateElement(
|
|
deltaState: HtmlState,
|
|
latentComponents: Set<ComponentBase>
|
|
): void {
|
|
super.updateElement(deltaState, latentComponents);
|
|
|
|
if (deltaState.html !== undefined) {
|
|
// If the HTML hasn't actually changed from last time, don't do
|
|
// anything. This is important so scripts don't get re-executed each
|
|
// time the component is updated.
|
|
if (deltaState.html === this.state.html) {
|
|
return;
|
|
}
|
|
|
|
// Load the HTML
|
|
this.containerElement.innerHTML = deltaState.html;
|
|
|
|
// Just setting the innerHTML doesn't run scripts. Do that manually.
|
|
this.runScriptsInElement(this.containerElement);
|
|
}
|
|
}
|
|
}
|