micronotes

micronotes

Sometimes when I need a certain functionality when programming, the best solution is to use a pre-existing library. Instead of coding something myself, which could take dozens of hours, it is likely that someone else has already done the same thing better. But sometimes, even with the vast resources available on the internet, it is difficult to find specifically what I am looking for, or a tool that has all the features that I am looking for. In those cases, the best solution may be to adapt an existing solution to my needs, or to build something from scratch. This is also a great way to gain experience and learn how to build a tool that is easy to use and actually useful.

This was the case with micronotes, the result of my search for an efficient and stylish footnote1 system for HTML-based web pages. On this site, I use the great Easy Footnotes plugin, which works well with WordPress2. However, I also wanted a solution that would be easy to use on a plain HTML page with no external libraries, scripts, or stylesheets.

One good option I found when researching potential options was this script from ignore the code. It’s a great option because it supports displaying the content of a footnote on hover (a wonderful user experience feature), but it was missing a couple things that I wanted – the main two things being a shortcode for easily inserting a footnote without writing any HTML code3 and a nice sliding animation down to the list of footnotes when a footnote number is clicked on. Another is Footnotes Popover4, but I didn’t like the style of the footnotes or that it requires jQuery to work5 (or that it hasn’t been updated in over 4 years).

Since I didn’t like any of the existing options, I decided to create my own footnotes tool. This took the form of a JavaScript plugin that can be added to a web page with a <script> tag.

<script type="text/javascript" src="https://cdn.jsdelivr.net/gh/generic-github-user/micronotes/micronotes.js"></script>

Footnotes are added using an opening tag: {note} and a closing tag: {/note}. These tags surround the content of your footnote. They can be used for citations, extra information, or additional thoughts that don’t fit in with the main text6. When the number corresponding to a given footnote is hovered over, a box with the content of that footnote is displayed – the box disappears when the cursor is moved away. The content in the footnotes can be any kind of text, including links and styled HTML content.

Feel free to add any CSS you want to text inside footnotes. They pretty much can’t be broken.

Images can be put inside of footnotes, too.

Videos, embedded content, and interactive elements can be used too. Footnotes work with pretty much any type of HTML content.

These footnotes can also be nested as much as you want:

If a footnote’s number is clicked, the page will be automatically scrolled down to the footnotes section where all the footnotes are listed.

A full demo is available here. For more usage information, see the micronotes GitHub repository. Now I’ll explain how the plugin works.

When the script is run, all the footnote tags on the page are found and replaced with div elements. These are styled and numbers are added that display the content of each footnote when they are hovered on. Instead of having a separate script and styling information, I included the CSS classes as a string in the script.

// Define global style information and transitions for footnotes and numbers
const styles = "\n\
* {\n\
	box-sizing: border-box;\n\
	-moz-box-sizing: border-box;\n\
	-webkit-box-sizing: border-box;\n\
}\n\
.number {\n\
      text-decoration: none;\n\
      color: #2b5cad;\n\
      transition: color 1s ease;\n\
}\n\
.number:hover {\n\
      color: #6799ea;\n\
      transition: color 1s ease;\n\
}\n\
.number:active {\n\
      color: #96beff;\n\
      transition: color 0.1s ease;\n\
}\n\
.note {\n\
      background-color: #efefef;\n\
      border-radius: 5px;\n\
      box-shadow: 4px 4px 10px 2px #999;\n\
      \n\
      opacity: 0;\n\
      \n\
      padding: 1vw;\n\
      margin: 0.1vw;\n\
      position: absolute;\n\
      visibility: hidden;\n\
      \n\
      transition: background-color 1s ease 0.25s, border-radius 1s ease 0.25s, box-shadow 1s ease 0.25s, opacity 1s ease, visibility 0s ease 1s;\n\
}\n\
.note:hover {\n\
      background-color: #ffffff;\n\
      border-radius: 15px;\n\
      /* box-shadow: 6px 6px 16px 2px #888; */\n\
      \n\
      opacity: 1;\n\
      visibility: visible;\n\
      transition: background-color 1s ease 0s, border-radius 1s ease 0s, box-shadow 1s ease 0s, opacity 1s ease;\n\
}\n\
\n";

The style information is then added to the header section of the page with JavaScript:

// Check if style element exists in page
if (document.querySelector("style")) {
	// If a style element already exists, add the style information defined above
      document.head.querySelector("style").innerHTML += styles;
}
else {
	// If the style element does not exist, create it
      var style = document.createElement("style");
	// Add the defined CSS style information to the style element
      style.innerHTML += styles;
	// Add the style element to the header section of the page
      document.head.appendChild(style);
}

All the {note} tags are then iterated through using a do…while loop. Some more styles are added to the page header so that when an individual footnote number is hovered over, the correct footnote is displayed.

// Add style information to head of page that defines what should happen to what note box when what number is hovered over
document.head.querySelector("style").innerHTML += "\n\
	#number-" + note_index + ":hover ~ #note-" + note_index + "{\n\
		  background-color: #f9f9f9;\n\
		  border-radius: 10px;\n\
		  /* box-shadow: 4px 4px 10px 2px #888; */\n\
		  \n\
		  opacity: 1;\n\
		  visibility: visible;\n\
		  transition: background-color 1s ease 0.25s, border-radius 1s ease 0.25s, box-shadow 1s ease 0.25s, opacity 1s ease;\n\
	}\n\
\n";

A div is added around the content of the footnote so that it can be styled to only appear when the correct number is hovered over. It is also linked to the corresponding footnote in the footnotes section at the bottom of the page.

// Replace opening footnote tag ({note}) with note box HTML content
  document.body.innerHTML = replace(
		document.body.innerHTML,
	// Footnote opening tag
		"{note}",
	// Superscript with current footnote number, link to footnote in footnote listing, and opening <span> tag that will contain the content of the footnote
		"<sup class='number' id='number-" + note_index + "' onclick='jump_down(" + note_index + ");'>" + note_index + "</sup><span class='note' id='note-" + note_index + "'>"
  );
// Add closing HTML for note box element in place of closing footnote tag ({/note})
  document.body.innerHTML = replace(
		document.body.innerHTML,
		"{/note}",
	// Closing <span> tag for footnote box content
		"</span>"
  );

Finally, all the footnotes are added to the bottom of the page, with links back to the number of that footnote in the main content of the page.

// Loop through all note boxes in the page
for (var i = 1; i < document.body.getElementsByClassName("note").length + 1; i ++) {
	// Get HTML content from footnote
    var footnote_content = document.body.querySelector("#note-" + i).innerHTML;
	// Add footnote to listing at the bottom of page, including footnote number and HTML content
    footnotes.innerHTML += "<span class='number' id='footnote-" + i + "' onclick='jump_up(" + i + ")'>" + i + ". </span><span class='footnote-content'>" + footnote_content + "</span>";
	// Add line break in between footnotes
    footnotes.innerHTML += "<br />";
}

I actually did most of the development on this program about 4 months ago7, but it’s one of many projects that I never shared on this blog and wanted to write a post about it. I’ll probably do some more work on it eventually, as there are a couple tings that I planned to implement but never did8. Hopefully someone finds it useful; feel free to open an issue if you find any problems or have an idea for a new feature.

If you’re wondering, I said footnote 55 times in this post. As always, thanks for reading, and Merry Christmas9!

  1. In case you didn’t know what a footnote is, this is a footnote.
  2. alliteration!
  3. Is HTML code really code?
  4. I just found out that it is based on the ignore the code footnote script.
  5. jQuery is a standard for almost every website, but a simple footnotes script shouldn’t be dependent on anything else, in my opinion

  6. and it is the reader’s choice to look at the content in a footnote or just keep reading
  7. So it’s already pretty much ancient.
  8. As is the case with most of my projects. Caesium currently has the most issues, with 52 (48 have been closed, for a total of 100).
  9. I used “Happy Holidays” on the last two posts, calm down.