RSS Feed

Unordered lists have a number of useful applications.  They are commonly used to structure a site’s navigation.  I have found, in a number of web applications, that the ability to reorder (sort) such lists would be extremely useful.  So, how can this be achieved?

I’m a big fan of the jQuery library.  Since most of the applications I build use jQuery, developing with this library would be the most logical approach.  But wait…  It looks like there are 2 jQuery plugins that allow elements to be sorted.  These are the jQuery Interface plugin and jQuery UI.

At first, I started working with “Interface”.  I soon ran into problems as I started working with styled lists.  For some reason, the list elements lost their styling as they were being dragged.  I just couldn’t quite put my finger on the problem - perhaps I missed something.  I then started working with jQuery UI.  This plugin retained the styling - perfect!

However, neither of these plugins provide a method to easily save and reload the list element order.  Hence, should a user change the order of the list, these changes would be lost as the page is refreshed.


Saving the Reordered List

I determined that the easiest way to accomplish this is through the use of a cookie.  The jQuery UI plugin already allows you to send the ID’s of the list elements (in order) to an array.  Using Klaus Hart’s Cookie plugin, we can easily save the list element order to a cookie.  But how do we retain/reload the element order saved to the cookie?

To restore the element order, I decided to remove all the sortable list elements from the DOM and then immediately append them to their parent element (in the order sepcified by the cookie).  This is all done after the document has loaded.

The HTML Markup

<ul id="list1">
<li id="item-1">List Item 1</li>
<li id="item-2">List Item 2</li>
<li id="item-3">List Item 3</li>
<li id="item-4">List Item 4</li>
<li id="item-5">List Item 5</li>
<li id="item-6">List Item 6</li>
</ul>

The Javascript

/////////////////////////////////////////////////////////////////
/////  EDIT THE FOLLOWING VARIABLE VALUES  //////////////////////
/////////////////////////////////////////////////////////////////
 
// set the list selector
var setSelector = "#list1";
// set the cookie name
var setCookieName = "listOrder";
// set the cookie expiry time (days):
var setCookieExpiry = 7;
 
/////////////////////////////////////////////////////////////////
/////  YOU PROBABLY WON'T NEED TO EDIT BELOW  ///////////////////
/////////////////////////////////////////////////////////////////
 
// function that writes the list order to a cookie
function getOrder() {
	// save custom order to cookie
	$.cookie(setCookieName, $(setSelector).sortable("toArray"), { expires: setCookieExpiry, path: "/" });
}
 
// function that restores the list order from a cookie
function restoreOrder() {
	var list = $(setSelector);
	if (list == null) return
 
	// fetch the cookie value (saved order)
	var cookie = $.cookie(setCookieName);
	if (!cookie) return;
 
	// make array from saved order
	var IDs = cookie.split(",");
 
	// fetch current order
	var items = list.sortable("toArray");
 
	// make array from current order
	var rebuild = new Array();
	for ( var v=0, len=items.length; v<len;>
		rebuild[items[v]] = items[v];
	}
 
	for (var i = 0, n = IDs.length; i &lt; n; i++) {
 
		// item id from saved order
		var itemID = IDs[i];
 
		if (itemID in rebuild) {
 
			// select item id from current order
			var item = rebuild[itemID];
 
			// select the item according to current order
			var child = $("ul.ui-sortable").children("#" + item);
 
			// select the item according to the saved order
			var savedOrd = $("ul.ui-sortable").children("#" + itemID);
 
			// remove all the items
			child.remove();
 
			// add the items in turn according to saved order
			// we need to filter here since the "ui-sortable"
			// class is applied to all ul elements and we
			// only want the very first!  You can modify this
			// to support multiple lists - not tested!
			$("ul.ui-sortable").filter(":first").append(savedOrd);
		}
	}
}
 
// code executed when the document loads
$(function() {
	// here, we allow the user to sort the items
	$(setSelector).sortable({
		axis: "y",
		cursor: "move",
		update: function() { getOrder(); }
	});
 
	// here, we reload the saved order
	restoreOrder();
});

There are 2 functions to be concerned with in the above code.  The first, “getOrder()”, writes the order of the list elements to a cookie.  The second, “restoreOrder()”, fetches the order saved to the cookie and restores that order.  We execute “getOrder()” each time the list order is changed.  We execute “restoreOrder()” after the document has loaded.

Using the code provided above, you should only need to change the variables (at the very top) to get this working with your page.  Just remember to include the jQuery library and jQuery UI plugin!  I hope this is helpful!





<a href="http://www.mysite.com/">some site</a>
<blockquote>quote</blockquote>
<em>some emphasized text</em>
<strong>some bold text</strong>
<pre lang="">some code</pre>
To add code to your comments, simply wrap the code inside <pre> tags. Syntax highlighting will be added if you define the language. Example:
<pre lang="php">some code</pre>

Supported "lang" attribute values: html4strict, css, php, javascript, xml & mysql