Sortable tables in org-mode

Increasingly, when tables are involved, I use Emacs Org mode to do quick-and-dirty generation of HTML files instead of either writing the HTML directly or generating it indirectly from DocBook XML sources.

One thing I wanted to add to the Org-mode-generated HTML tables is the ability for the user to sort the contents of table columns by clicking on the column header.

I found sorttable: Make all your tables sortable and downloaded sorttable.js to my Mac as ~/javascript/sorttable.js.

Here is a table in Org mode without sortability:

#+title: Non-sortable org-mode table
#+style: <link rel="stylesheet" type="text/css" href="file:///Users/wrg/sortable.css" />

| Guy   | Height | Hair  |
| Moe   |    68" | Black |
| Larry |    69" | Brown |
| Curly |    66" | N/A   |

Here is the CSS I used to style the HTML:

  background-color : white;
  font-family      : "Courier", monospace;

h1, title
  font-weight      : bold;

.author, .date, .creator, a[href^='']
  display          : none;

  background       : darkgray;
  color            : white;

The rendered HTML code appears thus in my browser:


Here is the raw HTML code that Org mode generated when exporting:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
<html xmlns="" lang="en" xml:lang="en">
<title>Non-sortable org-mode table</title>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
<meta name="title" content="Non-sortable org-mode table"/>
<meta name="generator" content="Org-mode"/>
<meta name="generated" content="2012-11-18T14:24-0500"/>
<meta name="author" content="Bill Greene"/>
<meta name="description" content=""/>
<meta name="keywords" content=""/>

<link rel="stylesheet" type="text/css" href="file:///Users/wrg/sortable.css" />
<script type="text/javascript">


<div id="preamble">


<div id="content">
<h1 class="title">Non-sortable org-mode table</h1>

<table border="3" cellspacing="0" cellpadding="6" rules="all" frame="box">
<colgroup><col class="left" /><col class="left" /><col class="left" />
<tr><th scope="col" class="left">Guy</th><th scope="col" class="left">Height</th><th scope="col" class="left">Hair</th></tr>
<tr><td class="left">Moe</td><td class="left">68"</td><td class="left">Black</td></tr>
<tr><td class="left">Larry</td><td class="left">69"</td><td class="left">Brown</td></tr>
<tr><td class="left">Curly</td><td class="left">66"</td><td class="left">N/A</td></tr>


<div id="postamble">
<p class="date">Date: 2012-11-18T14:24-0500</p>
<p class="author">Author: Bill Greene</p>
<p class="creator"><a href="">Org</a> version 7.9.2 with <a href="">Emacs</a> version 23</p>
<a href="">Validate XHTML 1.0</a>


The key insight here is that we need to insert the following <script> statement into the <head> section of the generated HTML.

<script src="file:///Users/wrg/javascript/sorttable.js"></script>

The Org mode #+style keyword provides such a means.  But since that it not its intended use, what follows is definitely a hack.

To add sortability to our Org mode source, we need to add two lines to our .org file:

#+title: Sortable org-mode table
#+style: <script src="file:///Users/wrg/javascript/sorttable.js"></script>
#+style: <link rel="stylesheet" type="text/css" href="file:///Users/wrg/sortable.css" />

#+attr_html: class="sortable"
| Guy   | Height | Hair  |
| Moe   |    68" | Black |
| Larry |    69" | Brown |
| Curly |    66" | N/A   |

We also need to add the following to our .css file:

  background-color : darkgray;
  color            : black;
  text-decoration  : none;

Now the rendered HTML code looks like this:


This solution is not perfect.  The user has no visual cue that the columns are sortable, since the arrows only appear on the headers after they are clicked (as in the above picture).  Also, sorttable.js does not support sorting by multiple columns, as some of the jQuery-based solutions do.  For now, I’m leaving these as exercises for the reader.  After all, a perfect solution would arrive with a future release of Org mode.


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s