Wednesday, October 30, 2013

Fixing the Z Index For Draggables

It's not often that jQuery UI developers find themselves worrying about reading and setting the z-index CSS property. That's because it's not all that relevant - it controls the ordering of elements on the stack. For instance, items with higher values will move toward the front of the screen when overlapped with another element with a lower z-index value. When you're designing your web page, or some part of your web application, you're going to statically align and layout the various components at design time. Responsive design let's our elements respond to varying client browser environments - think of different screen sizes and the user changing the orientation or the dimensions of the browser window. Beyond this, unless the user is directly rearranging elements on the page, we're not too worried about the ordering of overlapping elements. But users do rearrange jQuery UI elements.

For example, dialog widgets are movable by default. That is, the user has the ability to grab the dialog by the title bar, and drag the dialog around on the screen. What's more, the jQuery UI code implementing the dialog widget needs to account for the possibility of multiple dialogs on the screen, and how they'll interact and interfere with one another. Specifically, the dialog widget needs to deal with moving to the top of the stack, so as to appear on top of any other dialogs on the page. In fact, there's a method to deal with this called moveToTop(). Developers rarely need to call this method directly since it's used internally when the user starts moving the dialog. And the reason this method is needed is because the draggable component doesn't provide this capability.

Imagine you're only using the draggable component, so the user can move various elements around on the page. Out of the box, you're going to experience some issues with stack ordering since draggable doesn't have a moveToTop() method. Here is an example of how we can address this situation using a callback function for the start event, triggered when the user starts dragging. Without this code, the stack ordering is fixed, which means that the user could be dragging an element that isn't at the top.
We can literally fix the z-index issue with one line of code in our start callback function. All we're saying here is that the ui.helper element being dragged by the user gets a higher z-index that the other draggables on the page. This definitely isn't a perfect solution, and the moveToTop() approach of the dialog widget is much more robust than this approach. We could also refine the context for the other draggables that we push down on the stack. That's fine. If all you need is to manage is simple draggable elements, this code is compact and easy to maintain.