I want to have a list that is sortable, but I also want the elements in that list to be droppable to the divs I have defined as droppable. I can't seem to find a way to do it. Any ideas?
I think this is what you're looking for: http://docs.jquery.com/UI/Draggable#option-connectToSortable
I've spent all day on this, and I've gotten a lot closer, but still not doing as well as I'd like. I now have the functionality I need, but a Javascript error is getting thrown.
The issue is getting the sortable list to return to its previous position if the element is dropped in the droppable, rather than in the list. Currently, I'm saving the html onmousedown, then rewriting the html in the drop function of the droppable. This works, but its giving me a jquery variable is null error. Can anyone find a better solution?
Code:
<html>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/jquery-ui.js"></script>
<script type="text/javascript">
var templateHtml;
$(document).ready(function(){
$("#sortable").sortable();
$("#sortable li").addClass("drop").bind('mousedown',function(){
templateHtml = $("#sortable").html();
});
$("#droppable").droppable({
activeClass: 'active',
hoverClass:'hovered',
accept:".drop",
drop:function(event,ui){
$("#sortable").sortable('destroy').html(templateHtml);
$("#sortable").sortable();
$("#sortable li").addClass("drop").bind('mousedown',function(){
templateHtml = $("#sortable").html();
});
}
});
});
</script>
<style type="text/css">
#sortable li{
clear:both;
float:left;
}
#droppable {
clear:both;
height:300px;
width:400px;
background-color:#CCC;
}
#droppable.active {
background-color:#CFC;
}
#droppable.hovered {
background-color:#CCF;
}
</style>
</head>
<body>
<ul id="sortable">
<li id="one">One</li>
<li id="two">Two</li>
<li id="three">Three</li>
<li id="four">Four</li>
<li id="five">Five</li>
<li id="six">Six</li>
</ul>
<div id="droppable">
Drop Here
</div>
</body>
As far as I could tell, the issue with the previous code I posted is that the drop function of the droppable was getting called before the mouseup of the sortable, and since I rewrote the list the sortable was getting angry (for lack of better terms). That's somewhat a guess.
Looking at the final code:
<html>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/jquery-ui.js"></script>
<script type="text/javascript">
var dropped = false;
var templateHtml;
$(document).ready(function(){
setSortable();
$("#droppable").droppable({
activeClass: 'active',
hoverClass:'hovered',
accept:".drop",
drop:function(event,ui){
dropped = true;
//alert(ui.draggable.text());
}
});
});
function setSortable(){
$("#sortable").sortable({
stop:function(event,ui){
if(dropped){
$("#sortable").sortable('destroy').html(templateHtml);
dropped = false;
setSortable();
}
}
});
$("#sortable li").addClass("drop").bind('mousedown',function(){
templateHtml = $("#sortable").html();
});
}
</script>
<style type="text/css">
#sortable li{
clear:both;
float:left;
}
#droppable {
clear:both;
height:300px;
width:400px;
background-color:#CCC;
}
#droppable.active {
background-color:#CFC;
}
#droppable.hovered {
background-color:#CCF;
}
</style>
</head>
<body>
<ul id="sortable">
<li id="one">One</li>
<li id="two">Two</li>
<li id="three">Three</li>
<li id="four">Four</li>
<li id="five">Five</li>
<li id="six">Six</li>
</ul>
<div id="droppable">
Drop Here
</div>
</body>
Tons of quirks are involved here.
I tried to save the #sortable html on the start event of sortable, but that get's called after all of the ui-css gets applied, and ended up placing list elements in crazy places. So, I needed to use the mousedown function on the LIs.
The setSortable is in a function because the stop event rewrites the sortable, which is "recursive" I guess. Not sure the exact terminology here, but we can go with annoyingly confusing.
Fortunately, the droppable's drop function gets called before the sortables stop function, so I was able to set a global "dropped" variable that was used to see if the element was dropped.
I'm still surprised this wasn't easier to do, I thought jQuery would have functions to handle it a lot better. Perhaps I'm missing something?
I've been working on something practically identical. I created this originally in prototype, and its working flawlessly but recently decided because of upcoming functionality that JQuery should be used if possible so I've been trying to rewrite exactly what you describe here in JQuery. I psudo-solved the problem of returning sortable items by setting the "tolerance:" attribute for the sortable and droppable.
By setting tolerence: fit on the Sortable and Tolerance: touch on the droppable it is preventing any sort once the LI is moved outside the bounds of its parent UL. so once released over the droppable it snaps right back. The issue i've been running into now is accessing content of a textarea inside the sortable once dropped.