When ui.helper is null: a jQuery sortable quirk

November 22, 2009
 

At the same time I’ve been rebuilding Mealstrom (it’s coming along slowly but thoroughly, and I’m excited), I’ve been working on a project with my husband, a yoga site to accompany his studies. While working on that tonight, I discovered a quirk with jQuery UI draggables and sortables: if you set the revert option on both a draggable and the sortable its linked to, the sortable’s receive(event, ui) event callback will never get a value for ui.helper. It’ll always be null when you drop the draggable into the sortable.

(Also, jQuery creates a whole new copy of the item for the sortable, rather than using the original or its helper, another thing I learned tonight.  Just FYI.)

Here’s some code.  Say you have a set of draggable elements (“.listItems”), and a sortable (“#list”):

$("#addableItems div.draggableItem").draggable({   
  connectToSortable: "#list",
  cursor: "move",
  revert: "invalid",
  revertDuration: 300,
  helper: "clone" 
});

$("#list").sortable({
  items: "div.draggableItem",
  receive: listItemReceived, // function w/ signature (event, ui)
  helper: "clone",
  snap: true,
  revert: true,
  axis: "y"
});

listItemReceived has a line that commands the browser to yield up console.log(“UI: ” + ui.toSource()). With the configuration above, Firefox gives me the following output:

UI: ({helper:null, placeholder:{length:0}, ...})

When you comment out the second revert statement (the one in the sortable declaration), you get the following output:

UI: ({helper:{length:1, 0:{}, prevObject:#3={0:#1={}, length:1,
context:#1#}, context:#1#}, placeholder:{length:0}, ...})

For whatever reason, the sortable’s revert breaks the helper.

It’s not a huge important bug for me — as mentioned above, jQuery uses a new clone of the dragged element, so I don’t need access to the helper and can use revert.  I’m writing this up mainly in the hope that it save someone else the time I spent investigating it.

Well, that’s it.  Back to the sites.  As soon as I’ve finished rebuilding meal editing (my first Mealstrom 3 project), I’ll let you know.  I’ve been writing unit tests :)

Cheers,

Alex

5 Responses to “When ui.helper is null: a jQuery sortable quirk”

  1. [...] Read this entry on blog.twoalex.com Categories: tech, website Tags: Comments (0) Trackbacks (0) Leave a comment Trackback [...]

  2. Appreciate it, I’m having the same problem. Is there a way to get that new element that’s being created?

    Nick

  3. Hey Nick,

    That’s a good question. Since jQuery creates a whole new clone of the object, you could potentially search for it by class name or other identifying feature (aside from ID, where jQuery only returns the first value), and then somehow analyze the results to see which one it is. If you find a way, let me know — that could be useful in the future.

    I’m glad the article was useful to you!

    Alex

  4. I do thanks!

    This is what I ended up doing:

    $(document).ready(function() {

    $(‘.drag-element’).draggable({
    revert: ‘invalid’,
    helper: ‘clone’,
    connectToSortable: ‘#the-grid’
    });

    $(‘#the-grid’).sortable({
    // revert: true,
    tolerance: ‘pointer’,
    update: function(event, ui) {
    if( $(ui.item).has(‘.close’).length == 0 ) {
    $(ui.item).prepend(‘x‘);
    $(‘.close’).click(function(event, ui) { $(event.target).parent().remove(); });
    }
    }
    });

    $(‘#update-list’).click(updateList);
    });

    I used the update function instead of receive. What I was trying to do is add a close link to the div when it’s placed in the sortable. So I just checked to see if it was already there, and if not added it.

    I know it’s probably not the best to create a new click event for each .close link, but that’s not the point ;) . I’ll fix that part later.

    Nick

  5. I found this:
    http://bugs.jqueryui.com/ticket/4559

    It says: “Not a bug – use the beforeStop callback if you need ui.helper.”

    Might help someone

Leave a Reply