Rowspan Supported Table Sorting with Prototype

When I was working with tablesort, I realized that it doesn't support sorting cells with rowspan. And really, fewer table sorting javascript lib support this feature. It's known that table with rowspan attribute is a really messed up structure. It drove my crazy at the first time when I am writing a script to generate this kind of table.

But it would be very cool to support js sorting on rowspan cells! So I patched tablesort to support it. The idea is simple:

1) get rows that either with rowspan cell(s) or wihout rowspan cell at all and not after row with rowspan cell(s);

2) attached SUB-ROWS to row with rowspan cell(s);

3) sort rows get from step 1);

4) append rows get from step 1) to the table; and for each one, append the SUB-ROWS attached to it after.

One small issue left is that since we only sort rows get from step 1), we lose the sorting ability on SUB-ROWS. But I think that would be too difficult to support, and from my project, we happened not want to sort those SUB-ROWS, so I leave it for future. :)

Check the project out on my github. There is also a full demo available.

Posted by Shaokun 03 Dec 2009 at 06:37AM


AJAX loading notice based on Prototype

Loading Notice is a javascript plugin, built on Prototype, which automatically shows an indictor when a slow AJAX is under process. Basically, it’s like the “loading” div appears in gmail when busy. And when the users scroll or resize the window, it will still keep showing on the top of the page.

Check it out here: http://github.com/shaokun/loading_notice/tree/master

HOWTO

1. Install the plugin:

<pre> $ ruby script/plugin install git://github.com/shaokun/loading-notice.git $ rake loading_notice:install </pre>

2. Include the library into your project:

<pre> <%= javascript_include_tag 'prototype', 'loading_notice' %> <%= stylesheet_link_tag 'loading_notice' %> </pre>

3. Add a “loading” div and initialize a javascript object:

<pre> <div id="loading" style="display: none">Loading...</div>


4. That’s all!

Posted by Shaokun 20 Jul 2009 at 05:55AM


Javascript Universal Hierarchical Select

This is our first attempt at implementing hierarchical select based on the Prototype JavaScript framework. Efforts have been made to enable the component to satisfy a range of possible needs, so that it can be widely used with different conditions.

Hierarchical select refers to situations where the select options represent a hierarchical structure of objects. In such cases, we assume that the option list of each select element contains a certain level in the object hierarchy. When an option is chosen, a new select element will appear next to the current one, containing options of children of the selected item, unless it reaches a leaf. We represent such a kind of select as a class, which can be instantiated where a hierarchical select is needed.

If you feel interested in this work, please find it at Kudelabs’ code repository, as well as CONCRETE EXAMPLES which demonstrate how to use our hierarchical select in a webpage environment.

Posted by Yang 28 Oct 2008 at 11:18PM


kudelabs public code repository

We have started a new code repository at http://github.com/kudelabs. We will be using this to host our own plugins, utility files, and example code that we wish to make public. Hopefully, something here is of use to others in the community. If you find ways to improve upon our code, we will be happy incorporate your ideas as well. We'll be posting new code when it is ready, you can use github's "follow" feature to learn about new items.

So far I am impressed with github's features, there really isn't anything quite like it. I look forward to interacting with more developers through the site.

Posted by adevadeh 02 Sep 2008 at 10:41PM


Prototype fix for the IE bug where 204 => 1223

I ran into a strange problem when working on a new polling Ajax feature for one of our projects. Before I get into the issue, I'll set up the context.

I don't like the brute force approach of the PeriodicalUpdater, so instead I wanted to roll my own solution that utilized proper HTTP response codes to manage browser behavior. In particular, if there is nothing to report from the server, I can use the 204 - No Content (See W3C Documents) response code. In this way, I can simply use the onSuccess callback to schedule another check after an interval if there is no response body.

This worked wonderfully in Firefox and Safari, as expected. Of course, on IE, instead of calling onSuccess, it seemed to be calling onError, even though no error occurred. After displaying the status code in the error message, I found that IE was reporting the status code not as 204, but as 1223. As far as I can tell, there is no reason for this. I have found that other JS libraries have addressed the issue, so I went into prototype.js and solved the problem in the code.

I've submitted a patch to the Prototype team through their Lighthouse page, and the fix should get into the 1.6.0.3 release. If you are impatient and need the fix now, or are interested in getting into prototype hacking, here is the simple change:

prototype.js:199

 success: function() {
    var status = this.getStatus();
	// accept 1223 as a successful status, IE interprets 204 as 1223
    return (!status && this._allowStatusZero) || (status >= 200 && status < 300) || (status == 1223);
  },

Posted by adevadeh 03 Jun 2008 at 10:05PM


Javascript Filter on table, ol, ul...

It’s very common to enter a keyword and then filter it in a table or list. The easiest way could be go through each item of the table or list and then compare the keyword with the inner html of that item. But there is a drawback of this method. For instance, how to do filter in a table which has rows whose rowspan are set to bigger than 1? The code will break the layout of that table completely.

The method will come out with is to add a matching keyword to every item that are filterable. In other words, instead of comparing with the inner html, the code do it with the matching keyword. This gives the filter more flexibility. We will discuss the code a little bit belows. Note that it’s built on Prototype and used in Ruby on Rails. So, we have helper function to generate javascript in view too. But here, we just talk about the pure javascript part.

Here is an EXAMPLE

<pre> function strip_spaces(stripee) { return stripee.replace(/(^[ ]*) | ([ ]*$)/g,''); }

function filter(id, criteria) {
var t = $(id);
if (!t) { return; }

t.getElementsByClassName(‘no_matched_notice’).each(function(elem) { elem.remove(); }); var notice_msg = ‘No matching data found!’; criteria = strip_spaces(criteria);

empty_input = criteria.length === 0;

var matched_none = true; t.childElements().each(function(elem) { // if the user doesn’t input anything, then show all the elements if (!elem.matched_strs || empty_input) { Element.show(elem); } else { // else find the element matched = false; elem.matched_strs.each(function(str) { if (str.toUpperCase().indexOf(criteria.toUpperCase()) != -1) { matched = true; matched_none = false; return; } }); matched ? Element.show(elem) : Element.hide(elem); } }); if (matched_none && !empty_input) { var tag = t.tagName; var ins = null; switch (tag) { case “TBODY”: case “TABLE”: ins = new Insertion.Bottom(t, “”no_matched_notice\“>” + notice_msg + “”); break; case “OL”: case “UL”: ins = new Insertion.Bottom(t, “”no_matched_notice\“>” + notice_msg + “”); break; default: ins = new Insertion.Bottom(t, “<” + tag + " class=\“no_matched_notice\”>" + notice_msg + “</” + tag + “>”); break; } }

}

In html, all we need to do are:

1) add an array of keyword to each item which is filterable
<pre> $('tr_01').matched_strs = ["apple", "banana", "pineapple", ..., "pear"]) $('tr_02').matched_strs = ["bamboo", "eggplant", "cabbage", ..., "pepper"]) ... $('tr_02').matched_strs = ["elephant", "tiger", "monkey", ..., "fish"]) </pre>

2) add a text field to enter keyword:
<pre> <input id="keyword" type="text" /> </pre>

3) bind filter function to keyword’s event:
<pre> $('keyword').onkeyup = function() {filter('food', this.value);}; $('keyword').onchange = function() {filter('food', this.value);}; </pre>

That’s it! :)

Posted by Shaokun 04 Dec 2007 at 03:27PM