After some more testing I came to a solution, but it still puzzles me that
my original code did not work as expected.
I found that ui.item changes to the item I need in the "sortdeactivate"
callback. I can now add a delete image to the item, but now I have to first
test it to make sure it doesn't already have one. This condition is required
because "sortdeactivate" is fired each time to sortable is deactivated.

The new bind looks like this, and replaces my previous bind:

$('.selected').bind('sortdeactivate', function(event, ui) {
    // Add "delete" image to item
    var item = ui.item;
    if (!item.find('img.delete').length) {
        var img = $('<img src="delete.png" class="delete");
        img.click(function(event) {
            item.remove();
        });
        item.append(img);
    }
});

This now properly creates a delete button on new items that are dragged onto
the sortable and they are removed when the image is clicked.

But I also noticed a new bug. If I begin to drag a draggable from the
"available" container but release the mouse button before dragging it onto
the sortable, the "sortdeactivate" is fired and the delete button is placed
on the draggable! This is really puzzling because the cursor was never
placed over the selectable, yet the selectable event is firing. I also
noticed that the related event "sortactivate" fires immediately upon
dragging.

One thing I found that can help me determine if the draggable was dropped
onto a sortable is to check for a ui.sender property. It's not an elegant
solution, but it works.

The final working bind looks like this:

$('.selected').bind('sortdeactivate', function(event, ui) {
    // Return early if the item did not come from another list
    if (!ui.sender) return;

    // Add "delete" image to item
    var item = ui.item;
    if (!item.find('img.delete').length) {
        var img = $('<img src="delete.png" class="delete");
        img.click(function(event) {
            item.remove();
        });
        item.append(img);
    }
});

--
Hector


On Mon, Jul 6, 2009 at 9:38 AM, Hector Virgen <djvir...@gmail.com> wrote:

> I am building a basic draggable+sortable page based on this demo:
> http://jqueryui.com/demos/draggable/#sortable
>
> <http://jqueryui.com/demos/draggable/#sortable>My sortable list will start
> out empty and the user can drag various draggables onto the sortable.
>
> I want to add a "delete" icon to each of the items that are dragged onto
> the sortable so they can be removed. I've tried observing the "sortreceive"
> event and manipulating ui.item, but unfortunately ui.item points to the
> original draggable instead of the new element that was added to the
> sortable.
>
> Here is my code:
>
> $('ul.selected').sortable({
>     revert: true
> });
>
> $('ul.available li').draggable({
>     connectToSortable: '.selected',
>     helper: 'clone',
>     revert: 'invalid'
> });
>
> $('ul.selected, ul.available').disableSelection();
>
> // Attempt to add image to new item in sortable list
> $('.selected').bind('sortreceive', function(event, ui) {
>     $(ui.item).append('<img src="delete.png" />'); // Does not work --
> image is added to the draggable, not to the sortable's received item
> });
>
> Is there another way to get the item that was just added to the sortable?
>
> --
> Hector
>

Reply via email to