(function (app) { 'use strict'; // Friendly empty-state shown when the form is opened standalone // (file:// or otherwise without a server-injected #form-context // payload). The form renderer is always driven by the host — // zddc-server's form handler injects schema+ui+data; the tool has // no client-side picker because there's nothing it could pick from // outside that contract. function renderStandaloneWelcome(root) { if (!root) return; root.innerHTML = ''; const wrap = document.createElement('div'); wrap.className = 'form-welcome'; wrap.innerHTML = [ '
This tool renders a form spec injected by zddc-server',
' at <name>.form.html URLs. There is no schema',
' to render here — most likely you opened the standalone HTML directly.
zddc-server against an archive that contains a',
' <name>.form.yaml spec.<path>/<name>.form.html in the browser.See ', 'zddc.varasys.io/reference.html for the full ZDDC reference.
' ].join(''); root.appendChild(wrap); const submitBtn = document.getElementById('submit-btn'); if (submitBtn) submitBtn.hidden = true; } function boot() { // When this bundle is hosted by the unified tables.html, the // mode dispatcher decides which app paints. Skip when mode is // not "form" — table-mode requests are handled by tablesApp. // (Standalone form/dist/form.html has no zddcMode global; treat // undefined as form-mode for back-compat.) if (window.zddcMode && window.zddcMode !== 'form') { return; } app.context = app.modules.context.load(); if (app.context.title) { // Standalone form.html has #form-title in its header; unified // tables.html bundle has #table-title (shared across modes). // Whichever exists, write to it. const t = document.getElementById('form-title') || document.getElementById('table-title'); if (t) { t.textContent = app.context.title; } document.title = app.context.title + ' — ZDDC'; } const root = document.getElementById('form-root'); if (root && app.context.schema) { app.rootWidget = app.modules.render.mount( root, app.context.schema, app.context.ui || {}, app.context.data ); } else if (root) { // No schema — server-injected context is empty. Most common // when the standalone form.html is opened from file:// without // a host. Show a friendly explanation instead of a blank page. renderStandaloneWelcome(root); return; } if (app.context.errors && app.context.errors.length) { app.modules.errors.apply(app.context.errors); app.modules.post.showStatus('Please correct the errors below.', 'error'); } const submitBtn = document.getElementById('submit-btn'); if (submitBtn) { submitBtn.addEventListener('click', app.modules.post.submit); // Pre-flight gate: hide Submit when the cascade denies // create at the submission directory. Server still // enforces on POST — this just avoids dangling an // affordance that would 403. Submission directory is the // parent of submitUrl; fall back to the page URL when // submitUrl is absent (file:// / no-context mode). if (window.zddc && window.zddc.cap && app.context && app.context.submitUrl) { const subUrl = app.context.submitUrl; const dir = subUrl.replace(/\/[^\/]*$/, '/') || subUrl; window.zddc.cap.at(dir).then(function (view) { if (!view) return; const verbs = view.path_verbs || ''; if (verbs.indexOf('c') === -1) { submitBtn.hidden = true; const status = document.getElementById('form-status'); if (status) { status.textContent = "You don't have permission to submit here."; status.hidden = false; status.classList.add('is-error'); } } }); } } } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', boot, { once: true }); } else { boot(); } })(window.formApp);