1- // Update the preview area on input. Lifted directly from mathjax website examples
21class Preview {
3-
4- // Get the preview and buffer DIV's
5- //
62 constructor ( previewId , bufferId , inputId ) {
73 this . preview = document . getElementById ( previewId ) ;
84 this . buffer = document . getElementById ( bufferId ) ;
95 this . input = document . getElementById ( inputId ) ;
106 this . delay = 150 ; // delay after keystroke before updating
11- this . timeout = null ; // store setTimout id
7+ this . timeout = null ; // store setTimeout id
128 this . mjRunning = false ; // true when MathJax is processing
139 this . mjPending = false ; // true when a typeset has been queued
1410 this . oldText = null ; // used to check if an update is needed
1511 }
1612
17- //
18- // Switch the buffer and preview, and display the right one.
19- // (We use visibility:hidden rather than display:none since
20- // the results of running MathJax are more accurate that way.)
21- //
22- SwapBuffers ( ) {
23- var buffer = this . preview , preview = this . buffer ;
13+ // Swap buffer/preview so the freshly typeset one is shown.
14+ swapBuffers ( ) {
15+ let buffer = this . preview , preview = this . buffer ;
2416 this . buffer = buffer ;
2517 this . preview = preview ;
2618 buffer . style . visibility = "hidden" ;
@@ -29,76 +21,80 @@ class Preview {
2921 preview . style . visibility = "" ;
3022 }
3123
32- //
33- // This gets called when a key is pressed in the textarea.
34- // We check if there is already a pending update and clear it if so.
35- // Then set up an update to occur after a small delay (so if more keys
36- // are pressed, the update won't occur until after there has been
37- // a pause in the typing).
38- // The callback function is set up below, after the Preview object is set up.
39- //
40- Update ( ) {
24+ // Debounce: typeset only after a pause in typing.
25+ update ( ) {
4126 if ( this . timeout ) {
4227 clearTimeout ( this . timeout ) ;
4328 }
44- this . timeout = setTimeout ( this . callback , this . delay ) ;
29+
30+ this . timeout = setTimeout ( ( ) => this . createPreview ( ) , this . delay ) ;
4531 }
4632
47- //
48- // Creates the preview and runs MathJax on it.
49- // If MathJax is already trying to render the code, return
50- // If the text hasn't changed, return
51- // Otherwise, indicate that MathJax is running, and start the
52- // typesetting. After it is done, call PreviewDone.
53- //
54- CreatePreview ( ) {
33+ // Render input into the hidden buffer, then typeset it.
34+ createPreview ( ) {
5535 this . timeout = null ;
56- if ( this . mjPending ) return ;
57- var text = this . input . value ;
58- if ( text === this . oldtext ) return ;
59- if ( this . mjRunning ) {
60- this . mjPending = true ;
61- MathJax . Hub . Queue ( [ "CreatePreview" , this ] ) ;
62- } else {
63- this . buffer . innerHTML = this . oldtext = text ;
64- this . mjRunning = true ;
65- MathJax . Hub . Queue (
66- [ "Typeset" , MathJax . Hub , this . buffer ] ,
67- [ "PreviewDone" , this ]
68- ) ;
69- }
36+ this . mjRunning = true ;
37+ this . mjPending = false ;
38+
39+ const text = this . input . value ;
40+ if ( text === this . oldText ) return ;
41+ this . oldText = text ;
42+
43+ let buffer = this . buffer ; // capture: SwapBuffers may run before the promise settles
44+
45+
46+ MathJax . typesetClear ( [ buffer ] ) ; // drop metadata from the previous render
47+
48+ buffer . innerHTML = text ;
49+
50+ MathJax . typesetPromise ( [ buffer ] )
51+ . then ( ( ) => {
52+ this . mjRunning = false ;
53+ if ( this . mjPending ) {
54+ this . update ( ) ;
55+ }
56+ else {
57+ this . previewDone ( ) ;
58+ }
59+ } )
60+ . catch ( ( err ) => console . error ( "MathJax typeset failed:" , err ) ) ;
7061 }
7162
72- //
73- // Indicate that MathJax is no longer running,
74- // and swap the buffers to show the results.
75- //
76- PreviewDone ( ) {
63+ previewDone ( ) {
7764 this . mjRunning = this . mjPending = false ;
78- this . SwapBuffers ( ) ;
65+ this . swapBuffers ( ) ;
7966 }
8067}
8168
8269
8370function initMathJaxPreview ( id ) {
84- window . wagtailMathPreviews = window . wagtailMathPreviews || { } ;
71+ const target = document . getElementById ( id ) ;
72+ if ( ! target ) {
73+ return ;
74+ }
8575
86- window . wagtailMathPreviews [ id ] = new Preview (
87- "MathPreview-" + id ,
88- "MathBuffer-" + id ,
89- id
90- ) ;
76+ const preview = new Preview ( "MathPreview-" + id , "MathBuffer-" + id , id ) ;
9177
92- // Cache a callback to the CreatePreview action
93- window . wagtailMathPreviews [ id ] . callback = MathJax . Callback ( [ "CreatePreview" , window . wagtailMathPreviews [ id ] ] ) ;
94- window . wagtailMathPreviews [ id ] . callback . autoReset = true ; // make sure it can run more than once
95- window . wagtailMathPreviews [ id ] . Update ( ) ;
78+ window . wagtailMathPreviews = window . wagtailMathPreviews || { } ;
79+ window . wagtailMathPreviews [ id ] = preview ;
9680
97- // attach a keyup event listener so we update the preview
98- const target = document . getElementById ( id ) ;
99- if ( target ) {
100- target . addEventListener ( "keyup" , function ( ) {
101- window . wagtailMathPreviews [ id ] . Update ( ) ;
102- } )
81+ if ( target . value ) {
82+ preview . update ( ) ;
10383 }
84+
85+ target . addEventListener ( "keyup" , ( ) => {
86+ if ( this . mjRunning ) {
87+ this . mjPending = true ;
88+ }
89+ else {
90+ preview . update ( )
91+ }
92+ } ) ;
10493}
94+
95+ window . MathJax = {
96+ loader : { load : [ "input/asciimath" ] } , // "AM" isn't in tex-mml-chtml; add it explicitly
97+ tex : {
98+ inlineMath : { '[+]' : [ [ '$' , '$' ] ] }
99+ } ,
100+ } ;
0 commit comments