MediaWiki:Gadget-FDCodeEditor.js: Difference between revisions

FDCodeEditor gadget: attach CodeMirror 6 to the FlexDiagrams Mermaid/DOT edit textarea
 
FDCodeEditor: debounce the synthetic preview keyup (upstream DOT preview stacks async renders)
Line 37: Line 37:
// Mermaid's own documentation, and every diagram on this wiki, indents by two.
// Mermaid's own documentation, and every diagram on this wiki, indents by two.
var INDENT = '  ';
var INDENT = '  ';
// How long to sit on the synthetic `keyup` that drives the live preview.
//
// This is not cosmetic. FlexDiagrams' DOT preview has an upstream race:
// ext.flexdiagrams.dot.js clears the pane with a synchronous $( '.dot' ).empty()
// but renders through an ASYNCHRONOUS Viz.instance().then( ... appendChild ),
// and unlike the Mermaid path it has no debounce of its own. So N keyups in
// flight produce N stacked copies of the diagram after the last empty(). That
// is reproducible on a plain textarea with this gadget disabled - it is not
// ours - but we synthesise these events, so we should not make it worse.
//
// The textarea value is still updated SYNCHRONOUSLY below; only the preview
// nudge is delayed. Hitting save mid-debounce therefore still saves the
// current text.
var PREVIEW_DEBOUNCE_MS = 250;


function attach( require, textarea ) {
function attach( require, textarea ) {
Line 43: Line 58:
var $textarea = $( textarea );
var $textarea = $( textarea );
var cm = new CodeMirror( textarea );
var cm = new CodeMirror( textarea );
var previewTimer = null;


cm.initialize( [
cm.initialize( [
Line 62: Line 78:
return;
return;
}
}
// Synchronous, every time: this is what save and the
// unsaved-changes warning read.
$textarea
$textarea
.val( update.state.doc.toString() )
.val( update.state.doc.toString() )
.trigger( 'keyup' )      // FlexDiagrams live preview
.trigger( 'keypress' );  // FD_editWarning unsaved-changes flag
.trigger( 'keypress' );  // FD_editWarning unsaved-changes flag
// Debounced: drives the live preview. See PREVIEW_DEBOUNCE_MS.
clearTimeout( previewTimer );
previewTimer = setTimeout( function () {
$textarea.trigger( 'keyup' );
}, PREVIEW_DEBOUNCE_MS );
} )
} )
] );
] );