Tweaking Bigfoot footnotes

Like a lot of people, when I saw Chris Sauvé’s Bigfoot footnotes system, I knew it was just what I was looking for. A few years ago, I installed a modified version of Lukas Mathis’s popup footnotes and have been using it ever since. The systems are similar in that they both pop up the footnote text in a little bubble next to the footnote marker, a technique that’s far more dynamic and webby than the standard footnote behavior of linking you down to the bottom of the article.1 Bigfoot promises to be better on touch devices for two reasons:

  1. It brings up the footnote with a click or tap instead of hovering. There’s no hovering on a touch device.
  2. It provides a bigger target for fingers.

I installed Bigfoot yesterday. Generally speaking, it went well, but it had one problem in working with Markdown-generated footnotes that took me a while to figure out. I learned on Twitter that a few others have had similar trouble, so I’m posting my solution.

Bigfoot is a set of JavaScript/jQuery code that searches a page for links that look like the kinds of footnotes MultiMarkdown and PHP Markdown Extra produce and transforms them into a link and a popup balloon. On this blog, which uses a modified version of PHP Markdown Extra, Bigfoot worked perfectly on pages with individual posts, but didn’t work at all on the main page. On the main page, footnotes looked like standard footnotes—it was as if Bigfoot weren’t installed at all.

The problem seemed to stem from a slight difference in the HTML generated for footnotes on the main page. On an individual post page, the footnote HTML looks like this:

… get something that looks halfway decent<sup id="fnref:decent">
<a href="#fn:decent" rel="footnote">1</a></sup> when…

That same footnote on the main page has HTML that looks like this:

… get something that looks halfway decent<sup id="fnref:2172.decent">
<a href="#fn:2172.decent" rel="footnote">1</a></sup> when…

Notice that the <sup>’s id and the <a>’s href have changed to include the number 2172, which happens to be the number used by WordPress to identify the post. That number is inserted into the attributes on the main page to insure that the id and href are unique—not shared by two posts on the same page.

As I was first trying to determine what was going on, Sid O’Neill pointed me to a post of his in which he struggled with a similar problem on a Squarespace site. In his case, the problem came from the regex in the match in Line 128 of bigfoot.js:2

128:  return ($this.attr("href") + relAttr).match(/(fn|footnote|note)[:\-_\d]/gi) && $this.closest("[class*=footnote]:not(a):not(sup)").length < 1;

I spent a lot of time looking at that regex and trying to figure out why it might match the HTML on an individual post page but not on the main page—it seemed like it should work for both. After using the code debugger in Safari, I learned that it did work for both. The problem was elsewhere.

And not too far away. As I scanned further down in bigfoot.js, I came across this line in a callback function that was supposed to collect the text of the footnotes:

142:  relatedFN = $(this).attr("data-footnote-ref").replace(":", "\\:");

It was, for reasons I didn’t understand, escaping the colon in #fn:decent and #fn:2172.decent before assigning the string to the relatedFN variable. I wondered if the period in the latter also needed to be escaped. So I changed the line to

142:  relatedFN = $(this).attr("data-footnote-ref").replace(/[:.]/g, "\\$&");

so that both the colon and the period would be escaped, and, miraculously, Bigfoot started transforming the footnotes on my main page.3

This simple change got me the footnote system I wanted, but I doubt that it’s a general solution. The relatedFN variable is used in just one other line, where it’s the argument of a jQuery selector:

143:  $closestFootnoteLi = $(relatedFN).closest("li");

I’m no jQuery expert, but from what I can see in the docs, commas, hashmarks, asterisks, greater-than signs, pluses, and tildes should also be escaped because they all have special meaning in jQuery selectors. I haven’t done that because

I’ll probably get over my cowardice soon and see if I break anything by escaping the other characters. Until then, I’ll just play around with the style settings.

Update 12/23/13
Via Twitter, Allen MacKenzie nags helpfully points out that my footnotes aren’t Bigfootified in the RSS feed and that Marco Arment recently posted an article in which his Bigfoot footnotes did work. I am reminded of something…

I’ve always been under the impression that RSS doesn’t support JavaScript, so I’m wondering if Marco built the footnotes server-side, perhaps using node.js. Or maybe he reimplemented Bigfoot in PHP. I’ll download his feed and look through it for clues, but I’m not confident I’ll be able to do the same thing in WordPress.4

  1. Sending you off to another part of the article just to read a footnote is almost guaranteed to make the reader lose his train of thought. It’s too much like endnotes in a book. 

  2. I apologize for the length of this line. One of the things I definitely don’t like about Bigfoot is that the lines are ridiculously long. One line in the default SASS file is over 200 characters long. I confess I sometimes go over 80 characters, but I never go that far. 

  3. Are you wondering why the replace works when the links I’ve shown above don’t have an attribute with a value of data-footnote-ref? It’s because a function call (cleanFootnoteLinks) between Lines 128 and 142 assigns that attribute to all the footnote links. 

  4. On the other hand, I just looked at the source for Marco’s Bigfootified page, and noticed that it calls Bigfoot in a <script> section within the article itself instead of in the page’s header or footer. If that’s all that’s needed to get it working in RSS, even I can do it.