Mover

Mover, A Drag & Drop Javascript Library

Project Goals
Create a Javascript/CSS drag & drop library as a solution to a take-home programming assignment for a Yahoo interview: click for larger image
TAKE HOME EXERCISE

Please take a look at the attached GIF image. The highlighted area is the In The News Module. The intended functionality is:

The module is moveable and draggable anywhere on the page. To do this, the user has to position the cursor over the "In The News" tab and hold the mouse button down.

The position of the module should be remembered between browser sessions as well. So if the user navigates to another site, than returns to this page, the module should remain where the user last left it.

The code should be semantically proper and display with visual fidelity in IE5+/NS7.1+ and degrade to a non-stylized layout that still retains some form of information hierarchy and usability for older browsers. Drag functionality should be disabled for older browsers as well. The code should be accessible and retain its aspect ratio if the user changes the browser or platform's text size settings. Optimize for download & render speed.

When you are finished, please send us the code and all associated files. You only need to build the highlighted module. You can choose to place it on its own page or build fake content around it; we will not look at any code other than the highlighted module. You may use fake images for the purposes of this exercise.

Skills used
Javascript, CSS
Details
I'd been doing a bit of online reading about Javascript/CSS drag-n-drop and was curious to write something featuring it, so it was happy coincidence when, as part of a Yahoo job interview, I was asked to turn a page mock-up into a draggable element for a test project. I did a lot of reading in my Javascript book and learned a great deal about DOM Levels 0-2 and the corresponding event-handling models (not to mention the IE and NS4.x variants COUGH idiosyncrasies!). There's some very good example code in the book that I read through thoroughly. I diverged from the book's example by writing my code in OO style, because I wanted to keep the code and presentation (in this case, JS and HTML/CSS) separate. I didn't want any onClick or onMouseDown event handlers mixed in with the HTML, so I designed my Mover class to enscapsulate all of that away -- all the HTML programmer (or dynamic script) needs to do to set up multiple draggable content modules is list the IDs of the modules in a single Javascript array on the page containing those modules.

At first, I wrote the Mover class using nearly all DOM-0 techniques, figuring this would provide the most widespread compatibility with all browsers. While this worked, the resulting dragging action is somewhat clunky; it's possible for the mouse pointer to actually get ahead of the moving module -- and this registers as an onmouseout event which stops the dragging function.

The event handling model used in DOM-2 (and IE somewhat) is a more sophisticated and robust model, providing for event capturing and bubbling. In a nutshell, what this means practically is that the mouse pointer can speed ahead of the dragging module, but the mousemove event won't get cancelled until there's a mouseup event. The final version of the Mover class relies on this event model, and while it does work more smoothly, the tradeoff is more browser-specific code, and therefore potentially reduced compatibility.

One of the requirements of the project is that any dragged modules should display at their new positions on subsequent visits to the web page -- that is, the coordinates of the modules should be somehow stored in between sessions. For portability, I've opted to do this via a browser cookie and an element "relocate" window on-load function within the Mover class. I've written a simple cookie-handling JS library (cookies.js) to handle the cookie setting and retrieval.

A slicker way of addressing this issue would be via an AJAX call to a server-side script, which would store the personalized coordinates in a database table (along with a username). That way, assuming user log-in on a prior page, on subsequent visits to this page these coordinates could be dynamically plugged into the page's CSS directly (say, if the webpage were PHP-based or similar).

Finally, I should note that while the original instructions only required one draggable element, I wanted to generalize the Mover library and make it able to handle multiple elements, so the final version of the demo (DOM-2/IE) contains three moveable modules.

Examples/Links
Mover demo using DOM-0 version (NOTE: module position not stored)
Mover demo using DOM-2/IE version (FINAL VERSION, with correct Yahoo content module plus 2 others)
Selected Source Code
Mover demo page w/DOM-0 JS code (includes HTML + JS)
final Mover demo page using DOM-2/IE (HTML)
final Mover class (JS)
stylesheet for Mover demo page (CSS)
cookie-handling library (JS)