Benjamin Esham

How to get MathJax and Bigfoot to work together

This website uses a script called Bigfoot to make fancy pop-up footnotes. It also uses MathJax to render attractive mathematical expressions like this:

If you try to include math markup in a Bigfoot footnote, though, then the math will just disappear; you need to do some extra configuration to get the two scripts to play nicely. Here’s what I came up with.

Bigfoot is typically included in a page using the command

$.bigfoot();

To use Bigfoot with MathJax, specify a custom activateCallback like this:

$.bigfoot({
    activateCallback: function($popover, $button) {
        if (MathJax && !$button.data('mathjax-processed')) {
            var content_wrapper = $popover.find('.bigfoot-footnote__content')[0];
            MathJax.Hub.Queue(['Typeset', MathJax.Hub, content_wrapper]);
            MathJax.Hub.Queue(function () {
                $button.attr('data-bigfoot-footnote', content_wrapper.innerHTML);
                $button.data('mathjax-processed', true);
            });
        }
    }
});

The footnote at the end of this sentence should have some math markup in it.1

For Bigfoot versions 2.0.3 and 2.0.4

The code to use is different by just two strings:

$.bigfoot({
    activateCallback: function($popover, $button) {
        if (MathJax && !$button.data('mathjax-processed')) {
            var content_wrapper = $popover.find('.footnote-content-wrapper')[0];
            MathJax.Hub.Queue(['Typeset', MathJax.Hub, content_wrapper]);
            MathJax.Hub.Queue(function () {
                $button.attr('data-footnote-content', content_wrapper.innerHTML);
                $button.data('mathjax-processed', true);
            });
        }
    }
});

For Bigfoot versions before 2.0.3

In versions of Bigfoot prior to 2.0.3, which was released on July 15, 2014, you’ll need to use this code instead:

$.bigfoot({
    activateCallback: function($popover) {
        if (MathJax) {
            MathJax.Hub.Queue(['Typeset', MathJax.Hub, $popover[0]]);
        }
    }
});

This version has the slight disadvantage that MathJax will have to process each footnote every time it’s opened — the newer version of Bigfoot allows us to do this processing just once per footnote.

How it works

Bigfoot starts off by identifying all of the footnotes and footnote links on the page. It replaces each footnote link with a button and uses an HTML5 data attribute to store a string representation of the original footnote within the button. Since the footnote content is a string within an attribute and not an actual part of the DOM, though, MathJax doesn’t see it and doesn’t typeset the math within it.

When Bigfoot fires the activateCallback, the footnote has been extracted out into real HTML elements again. We use this opportunity to tell MathJax to rescan those elements, and now if there’s any typesetting to do then MathJax will do it.

When the rendering is done, our callback replaces the old, non-rendered copy of the footnote with the rendered version, and sets a flag to indicate that it has done so. This isn’t necessary but it means that each footnote is processed just once, not every time it’s opened.

Running MathJax before Bigfoot

The approach I’ve taken here is to let Bigfoot do its thing with footnotes as soon as the page loads, delaying the MathJax processing of the footnotes until the footnotes are actually opened. Instead, we could let MathJax typeset the entire page before Bigfoot touches the footnotes, only running Bigfoot once MathJax is finished. That HTML looks like this:

<script src=".../jQuery.js"></script>
<script src=".../bigfoot.js"></script>

<script type="text/x-mathjax-config">
    MathJax.Hub.Config({
        // Your configuration options go here, as usual
    });
    MathJax.Hub.Queue(function() {
        $.bigfoot();
    });
</script>
<script src=".../MathJax.js"></script>

Typically you’d run Bigfoot by calling $.bigfoot() right after loading the script. What we’re doing instead is pushing that function call onto MathJax’s event queue. That event queue already contains all of the functions that need to be run for MathJax to render math on the page, so by pushing a function onto this queue we’re guaranteeing that the function will be run as soon as (but no earlier than) MathJax has finished its processing. The effect is that when Bigfoot runs the math markup has already been rendered.

If you don’t have an x-mathjax-config block and you’re just configuring MathJax by specifying a script name that ends with ?config=something, then your code would look like

<script src=".../jQuery.js"></script>
<script src=".../bigfoot.js"></script>

<script type="text/x-mathjax-config">
    MathJax.Hub.Queue(function() {
        $.bigfoot();
    });
</script>
<script src=".../MathJax.js?config=something"></script>

You can put the MathJax block before the jQuery/Bigfoot block if you want to. (You do need to put the <script> tag for jQuery before the one for Bigfoot, though, and you need to put the MathJax configuration before the tag for the MathJax script.)

All of this being said, I prefer to run Bigfoot before MathJax. When Bigfoot runs it significantly changes the layout of the page, and the sooner that happens the sooner it feels like the page is done loading. Moreover, if MathJax knows that your math is going to be displayed in a narrow area then it can make layout choices that are appropriate for that context.

  1. We call $f$ an odd function if $f(x) = -f(-x)$ for every $x$ and $-x$ in the domain of $f$. Real-valued odd functions have the property that $\int_{-a}^a f(x) \: \mathrm{d}x = 0$ for any $a \in \mathbb{R}$. ↩︎