JavaScript laboratory
frontends/pages-js/app.js
import {Application} from 'gramlot-dom';
import {GramlotBuilder} from 'gramlot-builder';
let application;
function render(code) {
const builder = new GramlotBuilder('main');
let next;
try {
builder.main = new Function('root', code);
const container = document.createElement('div');
next = new Application(container);
next.mountBuilder(builder);
application?.dispose();
document.getElementById('root').replaceChildren(container);
application = next;
} catch (error) {
next?.dispose();
builder.dispose();
throw error;
}
}
window.addEventListener('message', event => {
const editor = parent.document.querySelector('.source-frame-panel iframe');
if (event.origin !== location.origin || event.source !== editor?.contentWindow || event.data?.type !== 'recipe') return;
let error = null;
try { render(event.data.code); } catch (failure) { error = failure.message; }
event.source.postMessage({type: 'recipe-result', error}, location.origin);
});
const recipes = {'hello-world': 'recipe.js', 'data-binding': 'data-binding.js', 'input-widgets': 'input-widgets.js', 'contact-box': 'contact-box.js', 'repeated-contacts': 'repeated-contacts.js', 'contact-colors': 'contact-colors.js'};
const recipe = recipes[location.pathname.split('/').filter(Boolean).at(-1)];
fetch(`/gramlot-js/${recipe}`).then(response => response.text()).then(render).catch(error => {
document.getElementById('bootstrap-error').textContent = error.message;
document.getElementById('bootstrap-error').hidden = false;
});
window.addEventListener('pagehide', () => application?.dispose());