Member Junction
    Preparing search index...

    Variable WHITEBOARD_SUBMIT_HELPERConst

    WHITEBOARD_SUBMIT_HELPER: "<script>window.MJWhiteboard={__lastSubmitAt:0,submit:function(data){window.MJWhiteboard.__lastSubmitAt=Date.now();parent.postMessage({__mjWhiteboardSubmit:true,data:data},'*');}};\n(function(){\nvar VALUE_MAX=120,LABEL_MAX=40,FLUSH_MS=1500,FLUSH_AT=12,TYPE_MS=800;\nvar queue=[],flushTimer=null,typeTimers={};\nfunction flush(){flushTimer=null;if(!queue.length){return;}var batch=queue;queue=[];try{parent.postMessage({__mjWhiteboardInteraction:true,events:batch},'*');}catch(e){}}\nfunction push(ev){queue.push(ev);if(queue.length>=FLUSH_AT){if(flushTimer){clearTimeout(flushTimer);flushTimer=null;}flush();return;}if(!flushTimer){flushTimer=setTimeout(flush,FLUSH_MS);}}\nfunction clip(v,max){v=String(v==null?'':v);return v.length>max?v.slice(0,max):v;}\nfunction isPrivate(el){var t=(el&&el.type?String(el.type):'').toLowerCase();return t==='password'||t==='hidden';}\nfunction labelOf(el){if(!el||!el.getAttribute){return '';}var v=el.getAttribute('aria-label')||el.getAttribute('name')||el.id;if(v){return clip(v,LABEL_MAX);}var t=(el.textContent||'').replace(/\\s+/g,' ').trim();return t?clip(t,LABEL_MAX):'';}\nfunction fieldLabel(el){var own=labelOf(el);if(own){return own;}try{if(el.labels&&el.labels.length){var lt=(el.labels[0].textContent||'').replace(/\\s+/g,' ').trim();if(lt){return clip(lt,LABEL_MAX);}}var wrap=el.closest?el.closest('label'):null;if(wrap){var wt=(wrap.textContent||'').replace(/\\s+/g,' ').trim();if(wt){return clip(wt,LABEL_MAX);}}}catch(e){}return el.tagName?el.tagName.toLowerCase():'field';}\nfunction isField(el){var t=el&&el.tagName?el.tagName.toUpperCase():'';return t==='INPUT'||t==='TEXTAREA'||t==='SELECT';}\nfunction fieldValue(el){if(el.type==='checkbox'){return el.checked?'checked':'unchecked';}return clip(el.value,VALUE_MAX);}\ndocument.addEventListener('click',function(e){try{var el=e.target&&e.target.closest?e.target.closest('button,a,label,input[type=\"button\"],input[type=\"submit\"],[role=\"button\"],[aria-label]'):null;if(!el){return;}var lbl=labelOf(el);if(!lbl){return;}push({kind:'click',target:lbl,tag:el.tagName.toLowerCase()});}catch(err){}},true);\ndocument.addEventListener('change',function(e){try{var el=e.target;if(!isField(el)||isPrivate(el)){return;}var name=fieldLabel(el);if(typeTimers[name]){clearTimeout(typeTimers[name]);delete typeTimers[name];}push({kind:'change',target:name,value:fieldValue(el)});}catch(err){}},true);\ndocument.addEventListener('input',function(e){try{var el=e.target;if(!isField(el)||isPrivate(el)){return;}var t=(el.type||'').toLowerCase();if(t==='checkbox'||t==='radio'){return;}var name=fieldLabel(el);if(typeTimers[name]){clearTimeout(typeTimers[name]);}typeTimers[name]=setTimeout(function(){delete typeTimers[name];try{push({kind:'input',target:name,value:clip(el.value,VALUE_MAX)});}catch(e2){}},TYPE_MS);}catch(err){}},true);\ndocument.addEventListener('focusin',function(e){try{var el=e.target;if(!isField(el)||isPrivate(el)){return;}push({kind:'focus',target:fieldLabel(el)});}catch(err){}});\ndocument.addEventListener('focusout',function(e){try{var el=e.target;if(!isField(el)||isPrivate(el)){return;}push({kind:'blur',target:fieldLabel(el)});}catch(err){}});\nvar AUTO_DEDUPE_MS=600;\nfunction collectFields(scope){var out={},els=(scope&&scope.querySelectorAll?scope:document).querySelectorAll('input,select,textarea');for(var i=0;i<els.length;i++){var el=els[i];if(isPrivate(el)){continue;}var t=(el.type||'').toLowerCase();if((t==='radio'||t==='checkbox')&&!el.checked){continue;}var name=fieldLabel(el);if(t==='checkbox'){out[name]='checked';}else{out[name]=clip(el.value,VALUE_MAX);}}return out;}\nfunction autoSubmit(scope,trigger){try{var last=window.MJWhiteboard.__lastSubmitAt||0;if(Date.now()-last<AUTO_DEDUPE_MS){return;}var fields=collectFields(scope);var payload={__auto:true,trigger:clip(trigger||'submit',LABEL_MAX),fields:fields};window.MJWhiteboard.submit(payload);}catch(err){}}\ndocument.addEventListener('submit',function(e){try{e.preventDefault();autoSubmit(e.target,'form');}catch(err){}},true);\ndocument.addEventListener('click',function(e){try{var b=e.target&&e.target.closest?e.target.closest('button,input[type=\"submit\"],input[type=\"button\"]'):null;if(!b){return;}var label=(labelOf(b)||'')+' '+(b.type||'');if(!/submit|send|done|go\\b|answer|check/i.test(label)){return;}setTimeout(function(){autoSubmit(b.form||document,labelOf(b)||'button');},150);}catch(err){}},true);\n})();</script>" = ...

    The ONE helper script prepended to every widget srcdoc — defines MJWhiteboard.submit (explicit input path) AND installs the passive ambient-interaction recorder. '*' 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 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" 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;
    • DEDUPES: an explicit MJWhiteboard.submit (or a prior auto-forward) within 600 ms suppresses the fallback, so well-built widgets never double-submit.
    • Serialization respects the recorder's privacy rules (password/hidden skipped, values clipped) and only checked radios/checkboxes contribute.