The Story Behind HTML5 Sortable

Recently I published a jQuery plugin named HTML5 Sortable and despit its small size, it was one of the most challenging and interesting works that I did recently.

But you might be wondering why I needed another sortable plugin in the first place?

In a recent project I was working on, I needed to create a sortable menu and I was going to use jQuery UI. But when I saw it adds 34KB of JavaScript to the project only to create a sortable list, I decided to write it myself. And now that almost all recent browsers support HTML5 drag and drop, why not to use it? Even better, IE supports this feature since version 5.5. Actually HTML5 DnD API standardized based on IE's implementation.

Well, I didn't want to reinvent the wheel if it was already invented. So I googled and found this jquery-html5sortable plugin and gave it a try. But there was a problem. It didn't work in IE. "What?! IE was supposed to support DnD since version 5.5." I said to myself. Then I looked at its code and I thought I could do it better. So I decided to reinvent a better wheel.

After spending a few minutes googling around, it turns out, IE supports drag and drop only with img and a elements. So I started to look for a workaround and thanks to StackOverflow the question was already answered. Every HTML element in Internet Explorer have a method named dragDrop which we can use to fire the ondragstart event. But where should we call it? The solution proposed on StackOverflow was to use mousemove event and to check the state of the left mouse button to find out if we are in a dragging state. But It wasn't straightforward. Even it has some performance penalties because of the frequent execution of the mousemove event.

I found a better solution, IE has an event named selectstart which is fired when the user starts dragging the mouse on the element. And calling dragDrop inside this event is exactly what we wanted.

So the IE problem was solved. But we are not done yet. I wanted something with the same look and feel of the jQuery UI sortable plugin. Using HTML5 API, when we drag an element, a copy of the element moves along with the mouse and the original one remains in its own place. But in terms of user experience, in a sortable list it's better to replace the original one with an empty placeholder.

At first inside dragstart handler I tried to set the visibility of the dragged element to hidden, but it caused the dragging clone also becomes invisible. Actually every change in the style and visibility of the dragged element was also applied to the dragging clone.

Then I found something interesting. Changes in the style of a dragged item doesn't affect its clone once the clone is created. So the first thing that came to my mind was to hide dragged item with a delay using setTimeout. It worked but it was a little laggy.

Finally I found a better approach. Hiding dragged item in a dragenter handler attached to draggable items was pretty seamless. Actually the dragenter handler being attached to the dragged item itself caused an immediate triggering of dragenter after dragstart.

Well, the result was pretty similar to jQuery UI sortable. I cleaned up the code and made a jquery plugin out of it in less than 50 lines of code.

See the usage docs and examples in here and report any bugs or suggestions on its github page.

Comments