Bride of Windows
See the demo page for the finished version of the code.Initialization Code
The script first defines two global variables: winList,
for the
array of Window
objects, and winCtrl
which is used
to hold various data values used throughout the code.
var winList = new Array(); var winCtrl = new Object();
winCtrl
is defined as a generic JavaScript Object.
By adding user-defined properties to this object, several values can be made
globally accessible using only a single variable.
The script also sets the window.onload
event to run its
initialization function once the page has finished loading.
window.onload = winInit;
The winInit()
functions first sets some values in the
winCtrl
variable including the colors to be used for inactive
windows, constants and flags used during the move and resize drag
operations.
// Initialize window control object. winCtrl.maxzIndex = 0; winCtrl.resizeCornerSize = 16; winCtrl.minimizedTextWidth = 100; winCtrl.inactiveFrameBackgroundColor = "#c0c0c0"; winCtrl.inactiveFrameBorderColor = "#f0f0f0 #505050 #404040 #e0e0e0"; winCtrl.inactiveTitleBarColor = "#808080"; winCtrl.inactiveTitleTextColor = "#c0c0c0"; winCtrl.inactiveClientAreaBorderColor = "#404040 #e0e0e0 #f0f0f0 #505050"; winCtrl.inactiveClientAreaScrollbarColor = ""; winCtrl.inMoveDrag = false; winCtrl.inResizeDrag = false;
The property maxzIndex
is used for the z-index
property of the currently active window. It will simply be incremented every
time the active window changes so it can be placed at the top of the stacking
order. The initial value can be changed if other positioned elements are used
on the page.
The resizeCornerSize
property determines how close the cursor
must be to a corner of a window to set off a diagonal resize drag (i.e., a
resize in both the horizontal or vertical directions).
The minimizedTextWidth
determines how wide minimized windows
will be.
Other properties are defined for winCtrl
as well, but these are
added dynamically as needed. They will be noted as the relevant code section is
discussed.
Identifying the Windows
The next step in winInit()
is to find all the windows defined
on the page and create Window
objects for them.
var elList; // Initialize windows and build list. elList = document.getElementsByTagName("DIV"); for (var i = 0; i < elList.length; i++) if (elList[i].className == "window") winList[elList[i].id] = new Window(elList[i]);
Calling document.getElementsByTagName("DIV")
gives a list of
all the DIV elements on the page. The script then loops through these and looks
for any that use the window
CSS class. When such and element is
found, it creates a new Window
object for it and then adds it to
the global winList
array.
The Window
Constructor
The Window()
function takes one argument, the DOM node
corresponding to outer, window
-class DIV element of the window.
The first thing it does is locate the sub elements of that DIV which make up
the window components, like the title bar, client area, etc. These are saved as
properties of the object so that they can be easily referenced later.
// Get window components. this.frame = el; this.titleBar = winFindByClassName(el, "titleBar"); this.titleBarText = winFindByClassName(el, "titleBarText"); this.titleBarButtons = winFindByClassName(el, "titleBarButtons"); this.clientArea = winFindByClassName(el, "clientArea");
The function winFindByClassName()
is a utility function that
searches the child nodes of a given element to find one that is assigned a
given CSS class. Since all of the window components use a specific style class,
this can be used to locate the various window elements
function winFindByClassName(el, className) { var i, tmp; if (el.className == className) return el; // Search for a descendant element assigned the given class. for (i = 0; i < el.childNodes.length; i++) { tmp = winFindByClassName(el.childNodes[i], className); if (tmp != null) return tmp; } return null; }
The function is recursive, so it will not only search the element's child nodes, but any child nodes they have as well. As soon as it finds a match, it returns that element node.
The next step is to find the image map assigned to the window's control buttons.
// Find matching button image map. mapName = this.titleBarButtons.useMap.substr(1); mapList = document.getElementsByTagName("MAP"); for (i = 0; i < mapList.length; i++) if (mapList[i].name == mapName) this.titleBarMap = mapList[i];
Again, document.getElementsByTagName()
is used to find all the
MAP elements on the page. It then checks them to find one whose name matches
the USEMAP attribute value on the button image tag.
The Window()
function then saves the original element colors
that will be altered whenever the window is inactivated so that they can be
properly restored whenever it becomes active again.
// Save colors. this.activeFrameBackgroundColor = this.frame.style.backgroundColor; this.activeFrameBorderColor = this.frame.style.borderColor; this.activeTitleBarColor = this.titleBar.style.backgroundColor; this.activeTitleTextColor = this.titleBar.style.color; this.activeClientAreaBorderColor = this.clientArea.style.borderColor; if (browser.isIE) this.activeClientAreaScrollbarColor = this.clientArea.style.scrollbarBaseColor;
It also saves the button image SRC and LONGDESC values so these can be easily referenced when switching between active to inactive states.
// Save images. this.activeButtonsImage = this.titleBarButtons.src; this.inactiveButtonsImage = this.titleBarButtons.longDesc;
Next it sets up a couple of flags and assigns the window methods.
// Set flags. this.isOpen = false; this.isMinimized = false; // Set methods. this.open = winOpen; this.close = winClose; this.minimize = winMinimize; this.restore = winRestore; this.makeActive = winMakeActive;
These flags are used by several functions to track the window's current state.