I’m looking a way to binding the snap event.
When I’m dragging an element over my surface and the draggable element is snapped to a declared snap position I want to trigger an event.
Something like this:
$(".drag").draggable({
snap: ".grid",
snaped: function( event, ui ) {}
});
Bonus point: with a reference to the .grid element where the draggable element was snapped.
The
draggablewidget does not expose such an event out of the box (yet). You could modify it and maintain your custom version or, better, derive a new widget from it and implement the new event there. There is, however, a third way.From this question, we know the widget stores an array of the potentially “snappable” elements in its
snapElementsproperty. In turn, each element in this array exposes asnappingproperty that istrueif the draggable helper is currently snapped to this element andfalseotherwise (the helper can snap to several elements at the same time).The
snapElementsarray is updated for everydragevent, so it is always up-to-date indraghandlers. From there, we only have to obtain thedraggablewidget instance from the associated element with data(), and call its_trigger()method to raise our ownsnappedevent (actuallydragsnappedunder the hood). In passing, we can $.extend() theuiobject with a jQuery object wrapping the snapped element:The code above, however, can still be improved. As it stands, a
snappedevent will be triggered for everydragevent (which occurs a lot) as long as the draggable helper remains snapped to an element. In addition, no event is triggered when snapping ends, which is not very practical, and detracts from the convention for such events to occur in pairs (snapped-in,snapped-out).Luckily, the
snapElementsarray is persistent, so we can use it to store state. We can add asnappingKnownproperty to each array element in order to track that we already have triggered asnappedevent for that element. Moreover, we can use it to detect that an element has been snapped out since the last call and react accordingly.Note that rather than introducing another
snapped-outevent, the code below chooses to pass an additionalsnappingproperty (reflecting the element’s current state) in theuiobject (which is, of course, only a matter of preference):You can test this solution here.
In closing, another improvement might be to make the
snappedevent cancelable, as thedragevent is. To achieve that, we would have to returnfalsefrom ourdraghandler if one of the calls to_trigger()returnsfalse. You may want to think twice before implementing this, though, as canceling a drag operation on snap-in or snap-out does not look like a very user-friendly feature in the general case.Update: From jQuery UI 1.9 onwards, the
data()key becomes the widget’s fully qualified name, with dots replaced by dashes. Accordingly, the code used above to obtain the widget instance becomes:Instead of:
Using the unqualified name is still supported in 1.9 but is deprecated, and support will be dropped in 1.10.