-->
Bookmark and Share

Bride of Windows

See the demo page for the finished version of the code.

Event Handling

Several events are set up for capture either in the Window() constructor function or in the HTML code of the each window. As shown earlier, every window element that is assigned an event handler also has a parentWindow property defined for it. This allows the handler functions to directly reference the window object that the element belongs to.

Like the window methods, almost all the event handlers include a call to the makeActive() method, either directly or indirectly. This is done so that when the user clicks anywhere on a window, or starts a drag operation on it, that window becomes the active one.

Window Button Events

For the buttons, an onclick event handler is specified for each one in the HTML itself, within the corresponding image map AREA tag.

  <img class="titleBarButtons" alt=""
  src="graphics/buttons.gif" usemap="#myMap" />
  <map id="myMap" name="myMap">
    <area shape="rect" coords="0,0,15,13" href=""  title="Minimize"
        onclick="this.parentWindow.minimize();return false;" />
    <area shape="rect" coords="16,0,31,13" href="" title="Restore"
        onclick="this.parentWindow.restore();return false;" />
    <area shape="rect" coords="34,0,49,13" href="" title="Close"
        onclick="this.parentWindow.close();return false;" />
  </map>

Each event handler calls the appropriate window method directly to either minimize, restore or close the window.

Window Client Area Events

When Window() is called to create a new window object, the window's client area is assigned an onclick event handler that points to the function winClientAreaClick().

function winClientAreaClick(event) {

  // Make this window the active one.

  this.parentWindow.makeActive();
}

All this function does is call makeActive() for the parent window. But combined with the calls to makeActive() in most of the other event handlers, the user can now select an inactive window and make it active by clicking just about anywhere on it.

Next we'll look at the event handlers that allow the user to move or resize a window via dragging.

Event Handling For Drag Operations

The remaining event handlers are a little more complicated as they deal with the drag operations to either move or resize a window. Multiple events are involved for each.

Browser Compatibility

Internet Explorer, as of version 6, still doesn't follow the standard DOM event model, so some browser-dependent coding is required. Fortunately, however, these differences are relatively minor, as can be seen in the source code.

Both drag operations rely on the fact that there is one active window on the page at any time. So the move and resize operations are always applied to this window. Likewise, the winCtrl object is used to store information related to the current drag operation, such as the cursor position.

Moving a Window

To enable the user move a window by dragging its titlebar, the mousedown event is captured for that element. When it fires, the winMoveDragStart() function is called.

The function first checks to see if the cursor is on a button and, if so, exits. This prevents it from interfering with the window button events.

  if (browser.isIE)
    target = window.event.srcElement.tagName;
  if (browser.isNS)
    target = event.target.tagName;

  if (target == "AREA")
    return;

Otherwise, it continues on to set up the drag operation.

To initialize the drag operation, makeActive() is called first. Then the function calculates the offset of the cursor relative to the window frame, storing the values in the winCtrl object. These offsets will be used to move the window as the cursor is moved around the page.

  this.parentWindow.makeActive();

  // Get cursor offset from window frame.

  if (browser.isIE) {
    x = window.event.x;
    y = window.event.y;
  }
  if (browser.isNS) {
    x = event.pageX;
    y = event.pageY;
  }
  winCtrl.xOffset = winCtrl.active.frame.offsetLeft - x;
  winCtrl.yOffset = winCtrl.active.frame.offsetTop  - y;

Next it sets up event capturing for mousemove and mouseup events at the document level so it can reposition the window as the mouse is moved around and end the drag when the mouse button is released.

  // Set document to capture mousemove and mouseup events.

  if (browser.isIE) {
    document.onmousemove = winMoveDragGo;
    document.onmouseup   = winMoveDragStop;
  }
  if (browser.isNS) {
    document.addEventListener("mousemove", winMoveDragGo,   true);
    document.addEventListener("mouseup",   winMoveDragStop, true);
    event.preventDefault();
  }

  winCtrl.inMoveDrag = true;

The final act is to set a flag in winCtrl to indicate that a move drag has started.

The winMoveDragGo() function will now execute as the mouse is dragged around the browser window. It simply takes the current cursor position, adds the offset values saved earlier and uses those sums to change the left and top positions of the window frame. The window will appear to move with the cursor, as though it were attached to it at the point where the mouse button was first depressed.

function winMoveDragGo(event) {

  var x, y;

  if (!winCtrl.inMoveDrag)
    return;

  // Get cursor position.

  if (browser.isIE) {
    x = window.event.x;
    y = window.event.y;
    window.event.cancelBubble = true;
    window.event.returnValue = false;
  }
  if (browser.isNS) {
    x = event.pageX;
    y = event.pageY;
    event.preventDefault();
  }

  // Move window frame based on offset from cursor.

  winCtrl.active.frame.style.left = (x + winCtrl.xOffset) + "px";
  winCtrl.active.frame.style.top  = (y + winCtrl.yOffset) + "px";
}

Event bubbling is canceled to prevent the browser's normal action of creating and highlighting a selection on the page.

When the user releases the mouse button, winMoveDragStop() is called. The function clears the move drag flag in winCtrl and removes the mousemove and mouseup event capturing for the document, ending the drag operation.

function winMoveDragStop(event) {

  winCtrl.inMoveDrag = false;

  // Remove mousemove and mouseup event captures on document.

  if (browser.isIE) {
    document.onmousemove = null;
    document.onmouseup   = null;
  }
  if (browser.isNS) {
    document.removeEventListener("mousemove", winMoveDragGo,   true);
    document.removeEventListener("mouseup",   winMoveDragStop, true);
  }
}