It would be nice to be able to listen to an event which fires once KaTeX is done rendering, and also have a reference to the DOM node in which KaTeX rendered.
My use case for this is following:
Sometimes we use KaTeX inside elements which need to have explicit height set based on their content. If we calculate height on DOM ready it is different than after rendering KaTeX. I have no way of knowing when KaTex is done rendering...
This could also have different uses, for example to show a progress loader until all math is rendered, or something like that
Maybe something like:
renderMathInElement(body, {
mathRenderer: (element, index, data) => {
const bounds = element.getBoundingClientRect();
const parent = element.parentNode;
parent.style.height = `${bounds.height}px`;
parent.style.width = `${bounds.width}px`;
},
});
where data is the output of splitWithDelimiters.
Also having this problem - any ideas on how to handle it? I'm currently rendering using katex.render() and have tried a few different ways of getting an accurate height. Stuck with calculating after a delay unfortunately, but it's obviously not reliable.
I believe KaTeX renders fully synchronously, so once render or renderMathInElement completes, you can do any postprocessing you want. For example:
renderMathInElement('body', options);
document.getElementsByClassName('katex').forEach(function (element) {
...
});
Does this suffice for your purposes? An event might still be nice, if the render call and the cleanup code are separated from each other...
Oh interesting - I'm not sure what's going on then. I'm using KaTeX in a WKWebView in Swift - essentially loading it through the equivalent of an iframe. So after rendering, I'm getting document.body.scrollHeight to see how big it should be. But if I do it right after rendering, it's cut off or too big some of the time and if I wait 1 second, it's the right size most of the time. Any idea what might be happening?
After KaTeX renders, the DOM will be updated, but the browser might need to actually render the DOM before it sets scrollHeight etc. This should happen after 0 seconds (via setImmediate(callback) or setTimeout(callback, 0). A 1-second delay should also always work. Does it really work only some of the time? What happens if you set the delay to 0?
In addition to waiting for the browser to apply styles, we may also have to wait for fonts to finish loading.
Oh, good idea. You should be able to catch the load event for those.
The tricky thing is knowing which fonts need to be loaded to render a particular piece of math.
Thanks for helping figure this out! Turns out it was a combination of a) needing to wait for the browser to render the DOM and b) sometimes the document would load before the webview would be fully rendered, so I needed to wait until both were done before calculating height.
In case anyone stumbles across this problem and this post, I'm setting my controller as both the navigation delegate for WKWebView and as a script message handler to receive a message from the DOM after katex.render has been called (with the 0 second timeout that edmaine@ mentioned). I'm waiting to calculate the height until after the message has been received AND navigation has completed.
Most helpful comment
Thanks for helping figure this out! Turns out it was a combination of a) needing to wait for the browser to render the DOM and b) sometimes the document would load before the webview would be fully rendered, so I needed to wait until both were done before calculating height.
In case anyone stumbles across this problem and this post, I'm setting my controller as both the navigation delegate for WKWebView and as a script message handler to receive a message from the DOM after katex.render has been called (with the 0 second timeout that edmaine@ mentioned). I'm waiting to calculate the height until after the message has been received AND navigation has completed.