webps - v .20 Release Notes (1/2) | WebReference

webps - v .20 Release Notes (1/2)

current pageTo page 2
[next]

webps Release Notes: v.20

By Dan Ragle

[This is a release bulletin for webps. For general information pertaining to the script, including the latest release download, system requirements, etc., visit the webps main page.]

New and improved in this version of webps: New administrator options on the back end, and a healthy dose of drag-n-drop on the front end.

Drag and Drop Column Reordering

The most extensive changes in this webps release were implemented in the main browser display template, mainpage.tmpl, and allow the end user to reorder the display columns by clicking a column header and dragging it to its new location. Drag-n-drop functionality is a staple in nearly all GUI applications, functionality easily understood (and often expected) by end users as a simple means to accomplish their goals. In webps, I've tried to make the drag-n-drop action as intuitive as possible without slowing down the visual display. I've also taken the liberty of dresssing up the main display table to make the table column headers look a bit more like... well, table column headers. Check out the drag and drop action in our webps demo.

Drag and drop in JavaScript is a relatively straightforward thing: You capture the onmousedown event on the item you wish to drag, and when you get it, you immediately register onmousemove (to move the dragged object simultaneously as the mouse itself moves), and onmouseup (to kill the drag action by removing the onmousemove) handlers to provide the actual logic that will control the drag action itself. The central component of the drag-n-drop display is the onmousemove handler, which moves the dragged object in the same direction and amount that the mouse itself moved since the last time it fired. In webps, our drag handler looks like this:

function dragItem(el, ev) {
   if (!el) return;
   if (!ev) ev = window.event;
   if ((ev.clientX != dragItem.previousX) ||
       (ev.clientY != dragItem.previousY)) {
      dragItem.dragged = 1;
      var newX = (parseInt(el.style.left) + 
                 (ev.clientX - dragItem.previousX));
      var newY = (parseInt(el.style.top)  + 
                 (ev.clientY - dragItem.previousY));
      el.style.left = newX + "px";
      el.style.top  = newY + "px";
      dragItem.previousX = ev.clientX;
      dragItem.previousY = ev.clientY;
   }
}

and then we set it up with code that looks something like this (remember that this code is being called from within an onmousedown handler):

...
   dragItem.previousX = ev.clientX;
   dragItem.previousY = ev.clientY;
   dragItem.dragged   = 0;
   document.onmousemove = function(event) {
                     dragItem(dragDiv, event);
                     return false;};

where dragDiv is the object that's actually being dragged. Aside from the onmouseup logic, the above represents the basic idea of drag and drop programming in JavaScript. If you took a peek at the actual webps code you might have noticed that there's more going on than what's listed here.

First, in order to move an object around the screen, it has to be a positioned object; one where we can apply specific x,y coordinates. None of my table column headers were positioned objects; and to convert them on-the-fly would cause problems in the table display where they came from. To avoid this, I create a brand new 'disposable' object (it's destroyed as part of the onmouseup logic) which is more-or-less a clone of the table column header that was selected. This disposable object is created and initially positioned as part of the dragsetup code in the onmousedown handler.

Next, to make the drag drop logic as intuitive as possible, I wanted to limit the object from being dragged outside the display table itself. The easiest way to do this was to create a shim object, which is absolutely positioned over the top of the display table with overflow: hidden, and then to create the draggable object as a child element of this shim. This effectively keeps the object from being dragged outside of the table, which might confuse the end user into thinking the object could be dragged somewhere else. The shim is actually created as part of the page initialization (since it only needs to be created once) but is resized, repositioned, and made "visible" (with its display property changed to block) as part of the drag setup.

Finally, the mouse cursor is changed to the familiar object movement cursor; roll your mouse over this paragraph to see what I mean.

All of these happen as part of the drag setup routine called on the onmousedown of the column header's themselves; and are backed out of in the onmouseup which is subsequently assigned. Additionally, the onmouseup logic calls the routine that examines the final position of the dragged object and reorders (redraws) the table based on the column's new position. Additional logic allows the column headers to retain their previous onclick capabilities. i.e., if the user just clicks the column header without dragging it, then the column is sorted (with an ascending/descending toggle on subsequent clicks). Compatibility with this previous onclick functionality is the reason for the setup and monitoring of the dragItem.dragged static function variable.

While we're on the topic, note this important point regarding the assigning of the mousemove/mouseup logic. We found that for the most consistent results it was necessary to assign the mousemove/mouseup handlers directly to the document, as opposed to what you might think is the more logical choice for the shim. When assigning the logic to the shim, we found that some browsers were confused by the layered aspects of the mouse events themselves (i.e., the onmousedown triggers the creation of a div which is then inserted directly beneath the mouse cursor itself; so the original object should never actually see the subsequent onmousemove or onmouseup events) which produced inconsistent results. Assigning these handlers to the high level document itself (which then contains all the layers) seemed to straighten out the mess.

And if drag-n-drop isn't your thing (or if you're just curious), you might find some of the other enhancements in this release of webps--which I discuss on the next page--more interesting...


current pageTo page 2
[next]

Created: August 29, 2007
Revised: August 29, 2007

URL: http://webreference.com/programming/perl/webps/v.20/index.html