CMTV
CMTV

Reputation: 2851

Mathjax automatic line-breaking when resizing

I read in MathJax docs that automatic line-breaks

are only computed once when the equation is initially typeset, and do not change if the user changes the window size

How to compute them dynamically every time window size is changed?

For example I have the following code:

<!DOCTYPE html>
<html>
<head>
<title>MathJax auto line-breaking</title>
<script type="text/x-mathjax-config">
MathJax.Hub.Config({
  CommonHTML: { linebreaks: { automatic: true } },
  "HTML-CSS": { linebreaks: { automatic: true } },
         SVG: { linebreaks: { automatic: true } }
});
</script>
<script type="text/javascript" async src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS_CHTML"></script>
<style>
#site-content {
    width: 70%;
    margin: 0 auto;
    border: 1px solid black;
}
</style>
</head>
<body>
    <div id="site-content">
    <p>Some cool text about math</p>
    \begin{equation}
        f(u_1) = f(u_0) + hf'(u_0)+{h^2\over 2!}f''(u_0) + \cdots + {h^{n+1}\over (n+1)!}f^{(n+1)}(u_0) + o(h^{n+1})
    \end{equation}
    <p>More cool text</p>
    \begin{equation}
        f(u_1) = f(u_0) + hf'(u_0)+{h^2\over 2!}f''(u_0) + \cdots + {h^{n+1}\over (n+1)!}f^{(n+1)}(u_0) + o(h^{n+1})
    \end{equation}
    <p>More cool text</p>
    \begin{equation}
        f(u_1) = f(u_0) + hf'(u_0)+{h^2\over 2!}f''(u_0) + \cdots + {h^{n+1}\over (n+1)!}f^{(n+1)}(u_0) + o(h^{n+1})
    \end{equation}
    <p>...</p>
    </div>
</body>
</html>

What is happening if I load this page at full width and then resize window:

enter image description here

If it is possible, I would like to dynamically add line breaks:

enter image description here

Upvotes: 1

Views: 2892

Answers (2)

Andry
Andry

Reputation: 16845

The answer from Peter Krautzberger is good, but I would like to improve it. So, please read his answer first, and then continue.

The problem with listening to resize

The issue in Peter's answer is that resize will trigger every time the browser's window changes in size. So, if you start changing the size of the window, every change, will trigger the event. The final result is that your rerender call will be issues many times as the user resizes the window, leading to flickering annoying effect.

Solution

You need to avoid that side effect by using a timeout and performing the action only when the user has finished resizing the window, not while he is in the middle of it:

<script type="text/x-mathjax-config">
  MathJax.Hub.Config({
    "SVG": {linebreaks: { automatic: true }}
  });
window.addEventListener('resize', MJrerender);

let t = -1;
let delay = 1000;
function MJrerender() {
  if (t >= 0) {
    // If we are still waiting, then the user is still resizing =>
    // postpone the action further!
    window.clearTimeout(t);
  }
  t = window.setTimeout(function() {
    MathJax.Hub.Queue(["Rerender",MathJax.Hub]);
    t = -1; // Reset the handle
  }, delay);
};
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js?config=TeX-AMS_SVG-full"></script>

<h1> Line-breaking should happen on window resize</h1>

$$a_1 + a_2 + a_3 + a_4 + a_5 + a_6 + a_7 + a_8 + a_9 + a_{10} + a_{11} + a_{12} + a_{13} + a_{14} + a_{15} + a_{16} + a_{17} + a_{18} + a_{19} + a_{20}$$

This way the experience is smoother :)

Upvotes: 3

Peter Krautzberger
Peter Krautzberger

Reputation: 5285

Essentially, you need to listen to resize events and call on MathJax to re-render when neccessary.

A brute force example might look like the following snippet (note: this doesn't work on SO's snippet rendering, try this codepen version)

<script type="text/x-mathjax-config">
  MathJax.Hub.Config({
    "SVG": {linebreaks: { automatic: true }}
  });
window.addEventListener('resize', MJrerender);
function MJrerender(){
MathJax.Hub.Queue(["Rerender",MathJax.Hub])
};
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js?config=TeX-AMS_SVG-full"></script>

<h1> Line-breaking should happen on window resize</h1>

$$a_1 + a_2 + a_3 + a_4 + a_5 + a_6 + a_7 + a_8 + a_9 + a_{10} + a_{11} + a_{12} + a_{13} + a_{14} + a_{15} + a_{16} + a_{17} + a_{18} + a_{19} + a_{20}$$

Note that this is horribly inefficient -- it re-renders everything at every resize event.

A more sensible approach would throttle the events and would only re-render those elements that are too large to fit into their parent. See this codepen for a an example of this.

Upvotes: 2

Related Questions