Web Development investigate

Use jQuery for sortable UI elements

Dragging, dropping, and reordering block objects is easy with jQuery.

Sortable sidebar objects are the sort of features that add a little "wow" to your site — WordPress users have seen them on the right-hand side of their screen for years — and the best part: it's not hard to do.

We start out with a page that has a text area in the main column and a series of "modules" on the right:

<html>

<head>

<style>

ul { list-style-type: none; margin: 0; padding: 0; }

ul > li { margin: 0 0 0.5em 0; padding: 0 0 0.5em 0; border: 1px black solid; border-radius:10px 0; background:white; }

ul h2{ cursor: move; margin:0 0 1em 0; padding: 0 0 0 0.4em;background:#aaa; border-radius: 10px 0 0 0;}

ul form, ul p { padding-left:0.4em;}

</style>

</head>

<body>

<div style="float:right;width:300px;">

<ul>

<li><h2>Item 1</h2><p>Here is another thing.</p></li>

<li><h2>Item 2</h2><form><input type="text" name="demo"/><button>Submit</button></form></li>

<li><h2>Item 3</h2><ol><li>Sub-item a</li><li>Sub-item b</li></ol></li>

<li><h2>Item 4</h2></li>

<li><h2>Item 5</h2></li>

<li><h2>Item 6</h2></li>

<li><h2>Item 7</h2></li>

</ul>

</div>

<div><textarea style="width:600px;height:20em;"></textarea></div>

</body>

</html>

This page is hardly going to win any design prizes, but it serves our purposes.

First thing, we need to pull in the jQuery libraries and set up the sorting declarations.

Add to the head:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>

<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.18/jquery-ui.min.js"></script>

<script>

$(function() {

$( "#sortable" ).sortable();

$( "#sortable" ).disableSelection();

});

</script>

Now, add to the ul element the following Id:
<ul id="sortable">

At this point, you should be able to drag and reorder the right-side elements .

If the JavaScript is confusing you, I recommend you check out Ryan Boudreaux's articles on getting started with jQuery.

After dragging a few of the list items around, you may notice that it is possible to drag the items around with any part of it. We can fix that by changing the call of the sortable function to use a handle, which in this case will be each item's h2 element.

$( "#sortable" ).sortable({handle: "h2"});

This is all fine and dandy, but the order of the sorting is lost when the page is refreshed. Bringing in some PHP, and adding an AJAX call and a cookie will fix this.

Firstly, we will extract the modules code into a number of variables, and have a default ordering. At the top of the file, add:

<?php

$i_1 = '<li class="item" id="i_1"><h2>Item 1</h2><p>Here is another thing.</p></li>';

$i_2 = '<li class="item" id="i_2"><h2>Item 2</h2><form><input type="text" name="demo"/><button>Submit</button></form></li>';

$i_3 = '<li class="item" id="i_3"><h2>Item 3</h2><ol><li>Sub-item a</li><li>Sub-item b</li></ol></li>';

$i_4 = '<li class="item" id="i_4"><h2>Item 4</h2></li>';

$i_5 = '<li class="item" id="i_5"><h2>Item 5</h2></li>';

$i_6 = '<li class="item" id="i_6"><h2>Item 6</h2></li>';

$i_7 = '<li class="item" id="i_7"><h2>Item 7</h2></li>';

$order = [$i_1, $i_2, $i_3, $i_4, $i_5, $i_6, $i_7];

?>

Replace the unordered list with:

<ul id="sortable">

<?php

foreach($order as $o) {

echo $o;

}

?>

</ul>

Now change the JavaScript sortable call to include a function call that will fire off an AJAX request, which will do nothing, other than set the current order in a cookie. This call will happen when the update event is triggered, which occurs when sorting has stopped and the DOM position is modified.

$( "#sortable" ).sortable({

handle: "h2",

update: function(event, ui) {

$.post("setorder.php", { order: $('#sortable').sortable('toArray') } );

},

});

Now the code for setorder.php:

<?php

setcookie('moduleorder', json_encode($_POST['order']));

?>

Back in our main file, we need to add the final piece of code that will use the cookie to rebuild the order array, if the cookie is present. Add this to the end of the .php code.

if(isset($_COOKIE['moduleorder'])){

$order = [];

foreach(json_decode($_COOKIE['moduleorder']) as $mo){

if(in_array($mo, ['i_1', 'i_2', 'i_3', 'i_4', 'i_5', 'i_6', 'i_7']))

$order[] = $$mo;

}

}

And, that's that. You could add database storage via the setorder file, if you wanted permanent storage, but in this instance, a cookie is more than sufficient.

Now go impress your users.

About

Some would say that it is a long way from software engineering to journalism, others would correctly argue that it is a mere 10 metres according to the floor plan.During his first five years with CBS Interactive, Chris started his journalistic advent...

2 comments
dperolio
dperolio

Hey Chris, thanks a lot for this! I got my list set up and it stores cookies great. Now I'm trying to set up a 2nd list on the same page, and I figured I could just do the exact same thing, but changing the variables ($order, moduleorder, $i_x, $mo) but it doesn't seem to be working... I keep getting back Warning: Invalid argument supplied for foreach(). Unfortunately, I don't know anything about PHP really. I've been trying to figure this out for hours though. >.< So the first sortable list works while the 2nd gives that error. If I switch the variables around though, the 2nd list works while the first gives the error... EDIT: Hmm... It magically started working. :| Thanks again.

dperolio
dperolio

So I've noticed some of the sections are disappearing on refresh sometimes... And they don't come back until you clear your cookies. Any idea what could cause this? My sections are quite large, could that be causing problems?