Member Junction
    Preparing search index...

    Variable WHITEBOARD_SUBMIT_HELPERConst

    WHITEBOARD_SUBMIT_HELPER: string = ...

    The ONE helper script prepended to every widget srcdoc — defines MJWhiteboard.submit (explicit input path), installs the passive ambient-interaction recorder, AND answers the host's two-way commands (inspect / operate / call / restoreState / hello — see whiteboard-widget-protocol.ts). Hand-written ES5 in seven IIFE sections (bridge, author, inspect, operate, actions, state, commands) that share the helper-private MJWhiteboard.__h namespace; every handler is try/catch-wrapped. '*' as the target origin is acceptable here: the sandboxed frame has an opaque origin (there is nothing else to address), and the HOST validates marker + event.source.

    The widget-facing API: MJWhiteboard.submit(data), onAction(name, handler, description?), offAction(name), setState(obj), onRestore(fn), and configure({ agentOperable?, autoState? }). data-mj-agent="off" on a control (or an ancestor) keeps the agent from operating it; data-mj-keep-live on <html> / <body> turns off automatic form state.

    AUTHORSHIP: submit messages and interaction batches carry by: 'agent' when the helper attributes them to an agent command (PLAN §6.6); absent means the user. It is a CLAIM — the host applies its own time-window gate before trusting it.

    The recorder, in widget-side terms:

    • click — buttons / links / labels / role=button / aria-labeled elements only (body/div noise without a label is ignored); records the tag + best label (aria-label || name || id || trimmed textContent, ≤40 chars).
    • change — select / radio / checkbox / text fields: field label + new value (checkbox → 'checked'/'unchecked').
    • input — debounced per-field (800 ms): field label + current value.
    • focusin / focusout — field label only.
    • PRIVACY: type="password" / type="hidden" and protected (card / PIN / OTP / SSN / account …) fields are skipped entirely; every recorded value is truncated to 120 chars BEFORE leaving the frame.
    • BATCHING: events queue and flush via postMessage every 1500 ms or at 12 queued.
    • RESILIENCE: every handler body is try/catch-wrapped — recorder errors never leak into widget code.

    AUTO-SUBMIT FALLBACK: agent-generated widgets don't always wire MJWhiteboard.submit — a plain <form> submit would NAVIGATE the sandboxed frame (blanking the widget) and an inert Submit button goes nowhere. The helper therefore:

    • intercepts every submit event (preventDefault — the frame never navigates) and forwards the form's serialized fields as { __auto: true, fields };
    • watches clicks on submit-ish buttons (type=submit, or labeled submit/send/done/…) and, shortly after, forwards the nearest form's (or document's) fields the same way. The submit-ish test reads the type ATTRIBUTE: a typeless <button> reports type === 'submit' as a PROPERTY, which auto-submitted "Show hint" / "Play" buttons;
    • DEDUPES: an explicit MJWhiteboard.submit (or a prior auto-forward) within 600 ms suppresses the fallback, so well-built widgets never double-submit.
    • Serialization (collectFields) respects the recorder's privacy rules (password/hidden skipped, values clipped) and only checked radios/checkboxes contribute: text, select and textarea values as strings, the checked radio as a string, and every ticked checkbox of a group as an ARRAY of their values under the group's label — one stable shape whatever the count, so the agent can react to a multi-select answer. A ticked box or radio with NO value attribute reports its own label text (<label> wrapper or for=) instead of the native "on", so valueless agent HTML still says WHICH box; a non-blank value always wins (an empty or whitespace-only attribute counts as absent), and a box with neither keeps "on".