Entries Tagged as "jQuery"

Revisiting Table Drag and Drop with jQuery and ColdFusion

Last April, I posted an article on how I implemented table row drag and drop functionality using jQuery and ColdFusion. While it was relatively simple, since the time of my original article, I ran into a number of issues with my solution and rethought the whole thing.

The Problems

  1. My solution was based on a jQuery plug-in called TableDnD, which seems to have lost any further development. I found the source up on Google Code, but there's been absolutely no activity since the project was created in June 2008.
  2. In the original solution, after each drop of a table row, an ajax call was made to update the database. While this worked great for sorting a few things, if you wanted sort a bunch rows, the numerous ajax calls just got plain annoying, and (truthfully) probably didn't scale very well.
  3. Later implementations of my project included dynamically adding rows to the table. This pretty much broke the ability of TableDnD to do its thing most of the time. At best, you couldn't move new elements above existing rows.
  4. Finally, it was hard to visualize what you were dragging – it always stayed confined to the table. Additionally, because it was a table, it wasn't always obvious you could drag and drop.

The Solution

As it turned out, the best solution for what I wanted to do didn't involve tables at all, but rather an unordered list and the jQuery UI library. Granted, this really isn't table drag and drop (per se), but just bear with me and I think you'll see what we've done is much cooler than the previous solution. The jQuery UI library includes some basic drag and drop functionality though the use of sortable lists. A simple example of how this works can be found on the jQuery UI website.

What we can do then is create a sortable list, each list item containing a hidden field with the necessary information we need to sort everything. When the form is submitted, it is submitted along with all those hidden fields. The key lies in form.FieldNames, which as most CFers know is a comma-delimited list of all the form fields submitted. It just so happens they are submitted in the order in which they appear on the form.

<form action="index.cfm" method="post">
	<cfoutput>
		<!--- This UL will contain the items we want to sort --->
		<ul id="SortItems" class="sortable">
			<!--- Counter to ensure each hidden field has a unique name --->
			<cfset intCounter = 0 />
			<!--- Loop over list of items to sort -- in real life this is probably a query --->
			<cfloop list="#lstSortItems#" index="strIndex">
				<cfset intCounter++ />
				<li style="cursor: move;">#strIndex#<input type="hidden" name="SortItem_#intCounter#" value="#strIndex#" /></li>
			</cfloop>
		</ul>
	</cfoutput>
	<input type="submit" value="Submit" />
</form>
<!--- This JS enables jQuery UI sorting (see included JS above, they're required) --->
<script type="text/javascript">
	$(function() {
		$("#SortItems").sortable({
			revert: true
		});
	});
</script>

Finally, we loop over the contents of form.FieldNames, looking for our hidden fields using each to update the order of our list. I've attached a very simple example of how this works. Presently, the value of the hidden field is a simple text label, but in real-life would probably be a primary key of whatever it is you're sorting.

The best part these lists can be styled however you like. For example a bit from application I've been working on. See how it looks like a table?

An even better part is because we're using unordered lists and jQuery, it's super easy to add and remove elements on-the-fly. Check out .append() and .remove().

Download attachment

No Comments

Table Drag and Drop with jQuery and ColdFusion

In the Worship Maker project I am toiling away on, I made a decision early on to use jQuery and its user interface components to build a completing user experience. I’d worked with other JavaScript libraries in the past, including Spry (which, embarrassingly, I had an affinity for at one time), however none of them compare to the sheer power and simplicity jQuery offers.

In a particularly JavaScript-heavy section of the application, I found myself wanting to allow the user to drag-and-drop rows within in a tab. After doing a little bit of research, I found an app for that. Eh, a plugin I mean. TableDnD by Isocra Consulting offers this functionality and it is sweet. Here’s how I implemented it.

First, you need a table. My table is generated from a query, like so:



<table width="100%" cellpadding="2" cellspacing="1" id="EventItems">
    <tr class="nodrop nodrag">
        <th width="20%">Type</th>
        <th width="50%">Item</th>
        <th width="30%">Assigned To</th>
        <th colspan="2" class="actions">Actions</th>
    </tr>
    <cfloop query="qryEventItems">
        <tr id="EventItemID_#qryEventItems.EventItemID#">
            <td>#qryEventItems.Type#</td>
            <td>#qryEventItems.Name#</td>
            <td>#qryEventItems.AssignedTo#</td>
            <td class="sort">
                <img src="images/sort.png" width="16" height="16" alt="Click and Drag to Adjust Order" title="Click and Drag to Adjust Order" />
            </td>
            <td class="actions"></td>
        </tr>
    </cfloop>
</table>


Notice the table has an id of “EventItems” and the last td in each row has a class of “sort” -- that’s important because they’re going to use that cell to “grab onto” to move the row up and down. I also included an up-down icon in that cell to give the user some visual indication what it’s for. Also, we have to give the table row a unique ID. I decided to just prepend “EventItemID_” to the primary key of each row.

Next, we need some JavaScript to make the magic work. For portability and resuability, I decided to wrap up everything I needed in a custom tag.



<ui:tablednd
    target="EventItems"
    xhr="#myself#cServices.sortEventItem"
    primarykeyname="EventID"
    primarykeyvalue="#variables.stcFields.EventID#" />


The tag has four parameters:

  • target: the ID of the table
  • xhr: the URL of the AJAX request to be made after a drag-and-drop event
  • primarykeyname and primarykeyvalue: additional information passed to the AJAX request

I should also mention this tool uses the jQuery BlockUI Plugin to prevent users from making other changes to the screen while the AJAX request is execiting. It is included with the TableDND plugin in the attached download.

No Comments