Skip to main content
4 of 15
Realized that real-time editing documents which use MathJax requires nothing extra from the real-time editor.

I had wanted to be able to keep notes on my computer in a basic text file, including math symbols, which is not simple, and sometimes not possible, even using the unicode character set. Then I discovered MathJax. HTML, with extensions like MathJax, seems to be the most general solution to generating free-form notes from an ASCII keyboard. To that goal, I began something like this real-time html editor over a decade ago, but never followed-through with loading and saving the edited files, so this solution is very much appreciated!

Supposing that MathJax is being used in an html page being edited, there arises the complication of writing dynamic content. MathJax normally runs its typesetting function only once, when the page first loads. Dynamic MathJax content requires additional code, and would be a very nice feature to have here.

But, it turns out that this is not really an issue at all!

Reading at MathJax in Dynamic Content, and then at Handling Asynchronous Typesetting, these considerations only apply to a document being modified in place - which is not what is happening here.

After looking more carefully at this real-time editor, the editor itself simply loads the edited document and then the browser renders this version as an entirely new document. The real-time editor is not making incremental changes to the Document Object Model, and there is no "extra" work needed from the real-time editor to manage MathJax.

Still, to avoid re-running the MathJax typesetting function after every character entry, it is easiest to simply uncheck the "Run" check box during editing, and then enable "Run" again to render the modified document, including running the MathJax typesetting function, as always.

An alternative - which requires no change to the real-time editor - involves modifying the user document, with the advantage of not needing to bother with the "Run" checkbox. The idea is to move the mouse cursor outside of the iframe, then run the MathJax typesetting function once and only after the mouse cursor moves back onto the rendered document iframe, using some MathJax code from Configuring and Loading in One Script. This simply requires modifying the user document MathJax head element, for instance, like this:

<head>
...

<!--
<script type="text/javascript" id="MathJax-script" async
  src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml-full.js">
</script>
 -->

<script>
  document.querySelector('html').onmouseenter = function() {
   var scriptx = document.createElement('script');
   scriptx.src = 'https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml-full.js';
//   scriptx.src = 'mathjax/tex-chtml-full.js';
   scriptx.async = true;
   document.head.appendChild(scriptx);
  };
</script>

...
</head>

BTW, I would prefer the traditional movable iframe divider, over the "Textarea size" slider, which can be a bit "twitchy". A simple alternative, still using your clever frame divider solution, is to spread the slider across the entire screen. With a vertical divider, the slider knob and the divider bar track very closely, and the control is then not so "twitchy". This change can be done by leaving off the label and output elements, moving the input element to last in the header, and using this style:

<input type="range" id="textareaSize" style="width:100%;height:5px;">

The same could be done in horizontal mode, first creating a new position for the slider, outside of the header, and adding orient="vertical" to the input style. I'm too lazy to work this out for now, and the full-width horizontal slider is good enough for both display modes.

Also, the footer links, except for "Feedback" and "Created by", are all getting jumbled on top of each other by Firefox Nightly on linux, which does not seem to handle the img alt attribute gracefully. One alternative is to add float: left; overflow: hidden; to the img style. A better looking alternative is to move the img alt attribute text into the anchor content proper, after the img tag.

Hmm - I notice that, with Firefox Nightly, whenever the textarea source is edited, the display position in the rendered iframe jumps to the top of the page. This has the effect of the user never being able to see what has just been edited without having to repeatedly scroll back to the original edit position, which is tiresome in a long document. The solution is to save, and then restore, the iframe scroll position in the preview() function. Also, it can be misleading to have variable names which are exactly the same as element names, so here, const iframe is changed to const iframex


    function preview() {
      if (run.checked) {

        let myIframe = document.querySelector('iframe');
        let xscroll = myIframe.contentWindow.scrollX;
        let yscroll = myIframe.contentWindow.scrollY;

        const iframex = document.createElement('iframe'); // a fresh iframe to delete JavaScript variables
        document.querySelector('iframe').replaceWith(iframex);

        const iframeDoc = iframex.contentDocument;
        iframeDoc.write(textarea.value);
        iframeDoc.close();

        document.querySelector('iframe').contentWindow.scrollTo({
          left: xscroll,
          top: yscroll,
          behavior: "instant",
        });

      }
    }

When running MathJax, restoring the scroll position is not perfect. Apparently, MathJax applies its own scroll position rules after typesetting, including always resetting the horizontal scroll position. Still, the resulting scroll position will be close to same position as before the editing.