Which event(s) to use with Sortables and connectWith?

Posted on 2008-11-11
Medium Priority
Last Modified: 2012-05-05
I'm trying to create a menu-builder using two unordered lists. I am using jQuery sortables to create the interface.

I have one on the left which contains the site's drop-down menu hierarchy. The list on the right is unused pages not appearing in the navigation. Here are the events I need to track:
1. When an item is dragged from the list on the right and dropped into the list on the left.
2. When an item is dragged from the list on the left and dropped into the list on the right.
3. When an item is dragged up or down in the list on the left.

The problem is the events lists these triggers:
start, sort, change, beforeStop, stop, update, receive, remove, over, out, activate, deactivate

I have tried a ton of combinations and troubleshooted for hours trying figure out the way to handle my events to support the way I'm keeping up with this stuff. Some of these events work for some actions, but not for others, so I must setup multiple events, and by the time I'm done, I end up with several events, occurring in the wrong order.

At this point, I have it just about figure out, however when an item is dragged from the list on the left to the list on the right (removed from menu), the remove event occurs before the stop event and the stop event overwrites what I did on the remove event.

I guess what I'm saying is I'm sure there is a smarter way to do this, so let me explain what i'm doing:
My menu items are stored with its Parent Element ID (menu_parent). If menu_parent IS NULL then it's not in the navigation. If it's 0, then it's part of the root navigation. Any other integer value is the Parent Item's ID.

So, that being said, when an item is dragged from left to right, I need the "remove" event to occur and simply update the element in the DB with a NULL value for menu_parent. All other events need to record the position as well as the parent. Can you please help? I have attached my JS code.

On a side note, does anyone know how to make the left list accept an infinite # of nested lists?  I tried this:
http://code.google.com/p/nestedsortables/wiki/NestedSortableDocumentation However it uses Interface and not jQuery UI. Any other working plugins out there?
// this in the document ready function
$("#sortable-list ul").sortable({
	connectWith: ["#selection-list ul"],
	receive: function(e,ui){
	stop: function(e,ui){
	remove: function(e,ui){
$("#selection-list ul").sortable({
	connectWith: ["#sortable-list ul"]
// this is my main execution function
function sortAction(e,ui,a){
	var proceed = true;
	var el_id = $(ui.item).attr('id');
	id = el_id.replace("ele-","");
	var params = "action=update_menu_item&jsa="+a+"&item_id="+id;
	if($("#"+el_id).parents("li").length > 0){
		var parent_id = $("#"+el_id).parents("li").attr('id');
		parent_id = parent_id.replace("ele-","");
		var parent_el = $("#ele-"+parent_id+" ul");
	} else {
		parent_id = "0";
		var parent_el = $("#sortable-list ul");
	if(a == "remove"){
		parent_id = "NULL";
	} else {
		var new_order = "";
		var kids = parent_el.children("li");
		$.each(kids, function(e){
				var tmp = $(this).attr("id");
				tmp = tmp.replace("ele-","");
				new_order = (new_order == "") ? tmp : new_order + ","+tmp;
		if(a == "stop" && new_order == ""){
			proceed = false;
		} else {
			params += "&new_order="+new_order;
	params += "&parent_id="+parent_id;
			type: "POST",
			url: "/stoneCMS/stone/stone_ajax.php",
			data: params,
			success: function(result){
				if(result != ""){
					if(result.indexOf("<script>") == -1){
						// do something...
					} else {
				} else {
					var newHTML = (a == "remove") ? 'Item removed from menu.' : ((a == "receive") ? 'Item added to menu' : 'Menu updated and sort positions saved.');
					if($("#menu_result").html() == newHTML){
									backgroundColor: "#FFC"
								}, 1000);
							}, 500
					} else {
			} // end success function
		}); // end AJAX
// sample HTML
<h1>Menu Manager</h1>
<div id="sortable-list">
	<h3 class="caption">Website Menu</h3>
	<ul class="first">
		<li class="sortable-element" id="ele-1">Home</li>
		<li class="sortable-element" id="ele-7">Information<ul>
			<li class="sortable-element" id="ele-6">About Us</li>
			<li class="sortable-element" id="ele-8">Business Services</li>
			<li class="sortable-element" id="ele-19">Communications</li>
			<li class="sortable-element" id="ele-40">Records</li>
			<li class="sortable-element" id="ele-23">Youth Services</li>
		<li class="sortable-element" id="ele-37">Events</li>
		<li class="sortable-element" id="ele-38">Statistics</li>
		<li class="sortable-element" id="ele-13">Employees</li>
		<li class="sortable-element" id="ele-14">Resources<ul>
			<li class="sortable-element" id="ele-47">Files</li>
			<li class="sortable-element" id="ele-15">Links</li>
		<li class="sortable-element" id="ele-35">Directory<ul>
			<li class="sortable-element" id="ele-48">Staff</li>
			<li class="sortable-element" id="ele-49">Information Technology</li>
			<li class="sortable-element" id="ele-52">Records</li>
			<li class="sortable-element" id="ele-53">Training</li>
		<li class="sortable-element" id="ele-17">Contact</li>
<div id="selection-list">
	<h3 class="caption">Other Pages</h3>
	<ul class="first">
		<li class="draggable-element" id="ele-12">Radio</li>
		<li class="draggable-element" id="ele-32">News</li>
		<li class="draggable-element" id="ele-33">Site Map</li>

Open in new window

Question by:bdichiara
1 Comment

Accepted Solution

bdichiara earned 0 total points
ID: 23184287
I ended up doing something like this, basically setting up different actions for each event, rather than one global action for the whole thing.
$("#sortable-list ul").sortable({
		connectWith: ["#selection-list ul"],
		receive: function(e,ui){
		remove: function(e,ui){
		stop: function(e,ui){
		out: function(e,ui){
			// secret to nested lists

Open in new window


Featured Post

Vote for the Most Valuable Expert

It’s time to recognize experts that go above and beyond with helpful solutions and engagement on site. Choose from the top experts in the Hall of Fame or on the right rail of your favorite topic page. Look for the blue “Nominate” button on their profile to vote.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Build an array called $myWeek which will hold the array elements Today, Yesterday and then builds up the rest of the week by the name of the day going back 1 week.   (CODE) (CODE) Then you just need to pass your date to the function. If i…
It’s a season to be thankful, and we’re thankful for users like you who engage on site, solve technology problems, and network with others in the industry. What tech are we most thankful for? Keep reading.
The viewer will learn the basics of jQuery, including how to invoke it on a web page. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery.: (CODE)
The viewer will learn how to create a basic form using some HTML5 and PHP for later processing. Set up your basic HTML file. Open your form tag and set the method and action attributes.: (CODE) Set up your first few inputs one for the name and …
Suggested Courses
Course of the Month17 days, 12 hours left to enroll

829 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question