support for native svg drag-and-drop

Several developers have been asking whether SVG supports html5 drag-and-drop. Until now, I usually answered: “no way, the SVG specification predates the HTML5 specification and does not mention drag-and-drop, so there is no chance that will work”. The goods news is that things are starting to evolve in several major browsers.

What is supported exactly ? At the moment, only Firefox and Chromium seem to implement SVG drag-and-drop. Both implementations are not fully working yet, though Firefox seems closer to the goal that Chromium. Both implementations have a problem with SVG drag sources (see: https://bugzilla.mozilla.org/show_bug.cgi?id=691796), bug drop works well, even on arbitrary elements inside an svg element. Chromium does not seem to support drag images.

I have uploaded a new development snapshot of lib-gwt-svg on the new githhub repository which includes this feature. There is also a new sample demonstrating the feature, available on github also: https://github.com/laaglu/lib-gwt-svg-samples.

Adding this feature caused quite a change in the way I implement event handling. When I first created the library, I was confronted with the need to add support for SVG-specific DOM events to the GWT stack. Since the GWT is not designed to allow adding custom DOM events, I had to re-create my own classes to process all SVG DOM events. I did that the conservative way, using a design largely inspired by GWT itself: every DOM element has a custom integer bit mask used to keep track of the kinds of event sunk by that element ; event handlers are set-up by converting the event name to an integer mask, checking the proper bit value associated with the mask and setting the on<eventname> property associated with that event. It turns out a drag and drop adds seven new events to the list, which brought that total number of supported events to 34, greater than 32 bits of a java integer. After some head-scratching, I have decided to go my own way and use something much simpler: no more event masks, no more bitfields, etc… Maybe at a point in time they were required to make it work, but this is no longer the case. Modern browsers with SVG support all support addEventListener and removeEventListener; thus, since registering and event handler always starts with the event name anyway, why not use these functions instead ? I have updated all my applications and have not detected any regression so far. Before committing to a release build, I would like to have feedback from other users.

Another interesting side effect of the change is that I changed the code to actually remove the DOM event listener when an element no longer has any handlers listening to a particular event anymore. This is done with a specially modified kind of EventBus. Before that, it was not the case. Removing an event handler left the DOM event listener connected. This event listener kept firing events in the void, since there was not anybody connected any more at the other end of the event bus.

One more thing: since not all browsers support SVG drag-and-drop events, I was again confronted with the need to provide a run-time function applications can check to determine if support is present or not. A pattern began to form (I had just done that for touch events), and I thought that SVG natively has a means to check that features are available. Why not reuse that instead of adding extra functions to the API ? Therefore, there are two new constants defined in SVGConstants.

public static final String SVG_FEATURE_TOUCH_EVENTS = "http://www.vectomatic.org/TR/SVG11/feature#SVGTouchEvents";
public static final String SVG_FEATURE_DND_EVENTS = "http://www.vectomatic.org/TR/SVG11/feature#SVGDndEvents";

The proper way to check for feature availability is to call:

if (DOMHelper.hasFeature(SVGConstants.SVG_FEATURE_DND_EVENTS)) {
   ...
}

The method DOMHelper.supportsSvgDndEvents is deprecated (it will become private in an upcoming release and be invoked from DOMHelper.hasFeature).

Leave a Reply

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>