jQuery UI Draggable Revert Callback

While this functionality is built into jQuery UI as of this writing, it is not well documented that you can set a callback function for the revert option of a draggable object.  This allows us to add logic to the revert functionality, e.g. is this droppable object in a position to receive this draggable object in terms of the state of our application?

The simple Answer:

For those familiar with how this should work; you can use a callback in place of the documented boolean/integer value stated in the docs.  Treat your function as if it were being asked “Do you want to revert?”  Return true or false.  You may also be able to return a integer value which would define the length of the revert animation in milliseconds.  I’ve tested the first method but not the second, however I’m pretty sure that it will work either way.

If you’d like a stronger example of this in action, please continue.

Advanced Draggable Revert functionality with a Callback Function:

jQuery UI provides us with a number of useful widgets and behaviors to allow us to build rich user interfaces. In this document I will show you how to better use draggable and droppable by adding a callback function to the default revert behavior.

For the sake of simplicity I like to think of draggable objects as pegs and the droppable objects as sockets.

The revert option of the draggable class can be modified to execute a callback function that allows for greater flexibility in it’s operation. By default the revert option has the following possible values:

revert: ‘invalid’,’valid’,’true’,’false’

Just to briefly co over what each does, the invalid option will cause the draggable object to revert back to it’s previous position (the location it was in before the drag), if the draggable does not get dropped in a valid droppable.

There are a number of cases where we need to provide additional checks in order to determine if an object can be dropped in a specific location after the fact.

Consider the following code for a set of draggable divs given the class “peg”.

  revert: function(socketObj)
     //if false then no socket object drop occurred.
     if(socketObj === false)
        //revert the peg by returning true
        return true;
        //socket object was returned,
        //we can perform additional checks here if we like
        //alert(socketObj.attr('id')); would work fine

        //return false so that the peg does not revert
        return false;
  snap: '.socketInner',
  snapMode: 'inner',
  snapTolerance: 35,
  distance: 8,
  stack: { group: 'pegs', min:50 },
  stop: function()
     draggedOutOfSocket = false;
} );

As you can see that we’ve replaced the usual string or boolean values given to the revert option with a callback function. The functionality is in this form, the same as using ‘invalid’, but it illustrates the concept well, because this is by far the most common usage case for revert.

The anonymous function takes one parameter, I’ve decided on calling it socketObj but the importand bit is that you know that one parameter is sent too the callback. This lone parameter will either be false if the draggable was not dropped into a droppable socket, or it will contain the droppable object if it was successful.

The action taken by revert is determined by what we return from our callback. In the example if the socketObj is false we return true, because we do want to revert position. Conversely if an object was passed to the function then we will return false so that our dragged object will stay where we dragged it.

Note that you can see there is a commented out javascript alert. I placed it there to express that this is a standard jQuery object that has all the usual methods you are used to dealing with such as attr() to read the attributes.

Some common things you might end up doing in this portion of the function would be making additional tests to see if you really want that element where the user dropped it, potentially reverting it (by returning true) even though the drop was valid in the UI sense it might not make sense in your application.

If you have any questions or comments please feel free to make them. I’ll try to provide a more practical real world example of this in action soon.