Filterable tables – MochiKit-style

A recent post on the MochiKit mailing list inspired me to have a little more fun with MochiKit, which I use a lot professionally and privately. The task was to see how simply a filtering for tables could be done using MochiKit.

The first task was to identify all the problems of the original script. Then comes setting up the basics, and finally implementing the necessary functionality. And as always MochiKit supplies so many convenient functions, that only the fun part is left. Furthermore this article suggest some simple extensions to the concept of filtering.

Current problems with the existing script include, that the de-highlighter ignores sibling (non-text) nodes of the text node that contained the highlighted term (and removes their markup). That is, if there is a cell like:

<td>here is a <strong>bold</strong> text</td>

Then if we search for is, the script will correctly highlight this word in the text, and the result looks like:

<td>here <span class="highlight">is</span> a <strong>bold</strong> text</td>

But if we then de-highlight this highlighted word, all markup from the entire cell (the cell is the direct parent of the text node containing the searched word) will be removed. Thus the resulting cell will look like:

<td>here is a bold text</td>

And this does matter. Because it does not only remove presentational markup like <strong> but (of course) also structural or functional markup like headers or links.

I needed an example table for this, and I used the one html table on the entire net, that I frequent the most – the IMDB top 250. Though I expected the script to be quite heavy, so I only used the top 10 actually for the base example. But later I will show other examples using longer tables for doing different searches.

The script is built around a basic onload-hook putting everything in closure (good for later inclusion in foreign pages) and this function sets up a few utility functions as well as the main hook for all filterable tables (tables including the class filterable). All these filterable tables are prefixed with a form containing a single input field. This input field’s onkeyup-event is then connected to the filtering function. When a key is released in the input field, the search term is extracted, the current highlights are removed, the lines not containing the word are hidden, and the remaining lines are sent through the highlighter. If the search term is empty, all lines are shown without highlights.

The script has many nice displays of how MochiKit really makes programming in JavaScript easier, and less sucky – I especially enjoy this simple function extracting all text nodes beneath a given node (depth-first, children before siblings):

// get all text nodes below current
function getTextNodes(node) {
	if (node.nodeType == 3) return [node];
	return reduce(extend, map(arguments.callee, node.childNodes));
}

This simple version of the script can be viewed here.

As mentioned, this isn’t a complete solution. For larger tables, it is very slow. It can be optimized a bit though. First thing is to do the scrapeText(row).toLowerCase() only once per row and store it as an attribute on the node. But for large tables, this isn’t enough. This could be fixed by adding more classes and creating special handling of these. Here I suggest the following two extra classes:

  • filterable-onsubmit
  • filterable-nohighlight

If the first class is given, the filtering will only be applied, when the form is submitted (instead of the input changed, user has to press enter to search) and if the second class is given, the filter will not highlight the search term – only show or hide rows with the given term. These can of course be combined. This can be seen in effect here.

Have fun and feel free to use under the given license.

No related posts.

Category: JavaScript 4 comments »

4 Responses to “Filterable tables – MochiKit-style”

  1. Daniel Fetchinson

    Hey, this is really cool, thanks!

  2. Jamie

    Very cool. Thanks for the examples. There is a shortage of targeted examples like this.

  3. Daniel Fetchinson

    Hi, a small improvement in case one has other functions that are hooked up to the load event:

    Instead of using an anonymous function hooked up to onload, create a named function with the same code and at the end add a hook:

    addLoadEvent( filtermanager );

    where filtermanager is the name of the function. In this way not only this function will be hooked but anything else that were added in maybe other scripts or along the way somewhere else.

  4. Barklund

    Daniel, of course. For production, I would wrap the whole thing in connect(window, "onload", function(){...});, but for now, it is still only proof-of-concept :)


Leave a Reply



Back to top

     

Get Adobe Flash playerPlugin by wpburn.com wordpress themes