X Library Viewer

Download the X Distribution File.

X Short Index

Animation

xAniLine, xAnimation.alphaArc, xAnimation.arc, xAnimation.corner, xAnimation.css, xAnimation.imgSize, xAnimation.line, xAnimation.opacity, xAnimation.para, xAnimation.rgb, xAnimation.rgbByClass, xAnimation.scroll, xAnimation.size, xAnimation.sizeLine, xAnimation, xAniOpacity, xAniRgb, xAniWH, xAniXY, xEllipse, xParaEq, xSequence, xSlideCornerTo, xSlideTo, xWinScrollTo.

DOM

xFirstChild, xFlGet, xFlWrite, xGetElementById, xGetElementsByAttribute, xGetElementsByClassName, xGetElementsByTagName, xLoadLink, xLoadScript, xNextSib, xParent, xParentN, xPrevSib, xSmartLoad, xSmartLoad2, xSmartLoadScript.

Debug

xConsole, xEditable, xName, xParentChain, xSetIETitle.

Event

xAddEventListener, xAddHandlers, xDragInFence, xEnableDrag, xEnableDrop, xEvent, xHttpRequest, xPreventDefault, xRemoveEventListener, xStopPropagation.

Image

xImgAsyncWait, xImgRollSetup, xTriStateImage.

Iteration

xEach, xEachE, xEachN, xEachUntilReturn, xTimes, xWalkToFirst, xWalkToLast, xWalkTree, xWalkTree2, xWalkTree3, xWalkTreeRev, xWalkUL.

Misc

xCookie, xDef, xDeg, xGetURLArguments, xInA, xLibrary, xLinearScale, xNum, xRad, xRound, xStr.

Position

xCardinalPosition, xCen, xCenter, xGetEleAtPoint, xHasPoint, xIntersection, xLeft, xMoveTo, xOffset, xPageX, xPageY, xScrollLeft, xScrollTop, xTop.

Size

xClientHeight, xClientWidth, xClip, xColEqualizer, xDocSize, xHeight, xResizeTo, xWidth.

String

xCamelize, xCapitalize, xHex, xJoin, xPad, xParseColor, xRgbToHex, xSplit, xStrEndsWith, xStrRepeat, xStrReplaceEnd, xStrStartsWith, xTrim.

Style

xAddClass, xDisplay, xFindAfterByClassName, xFindBeforeByClassName, xGetComputedStyle, xGetCSSRules, xGetStyleSheetFromLink, xHasClass, xHasStyleSelector, xHasStyleSheets, xInsertRule, xOpacity, xRemoveClass, xStyle, xTagStyle, xToggleClass, xTraverseDocumentStyleSheets, xTraverseStyleSheet.

Table

xTable, xTableCellVisibility, xTableColDisplay, xTableCursor, xTableCursor2, xTableHeaderFixed, xTableIterate, xTableRowDisplay, xTableSync.

UI

xBar, xCalendar, xCollapsible, xDialog, xFenster, xMenu1, xMenu1A, xMenu1B, xMenu5, xMenu6, xModalDialog, xPersistentDisplay, xPopup, xSelect, xSplitter, xTabPanelGroup, xTextArea, xTooltipGroup.

Window

xWinClass, xWindow, xWinOpen.

X Long Index

Animation

xAniLine
Animate an element's position over a line segment.
xAnimation.alphaArc
Animate an element's opacity and its position over an elliptical arc. This is an xAnimation method.
xAnimation.arc
Animate an element's position over an elliptical arc. This is an xAnimation method.
xAnimation.corner
Animate an element's corner over a line segment. This is an xAnimation method.
xAnimation.css
Animate an element's CSS property that accepts integer pixel values. This is an xAnimation method.
xAnimation.imgSize
Animate an image's width and height. This is an xAnimation method.
xAnimation.line
Animate an element's position over a line segment. This is an xAnimation method.
xAnimation.opacity
Animate an element's opacity. This is an xAnimation method.
xAnimation.para
Animate an element's position over parametric equations. This is an xAnimation method.
xAnimation.rgb
Animate an element's CSS property that accepts color values. This is an xAnimation method.
xAnimation.rgbByClass
Animate a CSS property that accepts color values, for all elements with the given className. This is an xAnimation method.
xAnimation.scroll
Animate the scroll position of a window or element. This is an xAnimation method.
xAnimation.size
Animate an element's width and height. This is an xAnimation method.
xAnimation.sizeLine
Perform a sequence of animations of an element's position and size. This is an xAnimation method.
xAnimation
Using xAnimation is easy. Create an xAnimation object and call one of the animation methods. You can then use the pause/resume methods. The other methods and properties are documented here to help you write your own animation methods. xAnimation provides an animation "engine" which supports unlimited axes of animation, multiple acceleration types and an onEnd handler. The onEnd handler can return true to cause the animation to repeat. It supports a bounce-back feature. Acceleration is implemented as an array of functions so it is easy to add custom acceleration types.
xAniOpacity
Animate an element's opacity.
xAniRgb
Animate an element's CSS property that accepts color values.
xAniWH
Animate an element's size. This is a minimal, time-based implementation - only supports constant velocity.
xAniXY
Animate an element's position over a line segment. This is a minimal, time-based implementation - only supports constant velocity.
xEllipse
Animate an element along an elliptical path.
xParaEq
Parametric Equation Animation. X(t) and Y(t) are expressions that generate the x and y coordinates during the slide. These expressions are evaluated with the javascript eval() function. Within the expression you may use any valid sub-expression that eval allows and that is in scope. For example, you may call methods of the Math object such as Math.sin(), Math.cos(), and Math.tan(). You may also reference any global variables or functions. One variable that is within scope for your expression is the parameter t. That is, t is the argument to the equations you provide. At each iteration, the variable t increments by .008 (default value). The Time argument to parametricEquation() specifies the total time for the slide in milliseconds. If the value is zero, the slide will not timeout. You can stop any slide, at any time, by this assignment: element.stop = true;. The values from your expressions are plotted on a coordinate system with it's origin at the center of the sliding element's container. The coordinates are then translated by the element's container's scrollLeft and scrollTop values. So the animation will remain visible if the user scrolls or resizes the element's container.
xSequence
xSequence is an experiment with time and event based sequences.
xSlideCornerTo
Time-based resize (corner slide) with sinusoidal rate.
xSlideTo
Animated, linear motion with sinusoidal or linear rate. Slide the element to the target position in the given time.
xWinScrollTo
Scroll a window to a point with sinusoidal or linear rate.

DOM

xFirstChild
An enhanced wrapper for element.firstChild.
xFlGet
Returns a reference to a Flash object or null if not found.
xFlWrite
Write Flash HTML into the document.
xGetElementById
Get an object reference to the element object with the passed ID.
xGetElementsByAttribute
Return an array of all sTag elements whose sAtt attribute matches sRE. sAtt can also be a property name but the property must be of type string.
xGetElementsByClassName
Returns an array of elements which are descendants of parentEle and have tagName and clsName. If parentEle is null or not present, document will be used. If tagName is null or not present, "*" will be used.
xGetElementsByTagName
Returns an array of elements which are descendants of parent and have tagName. If parent is null or not present, document will be used. If tagName is null or not present, "*" will be used.
xLoadLink
Dynamically create a LINK element and append it to the HEAD.
xLoadScript
Dynamically load a js file.
xNextSib
Get an element's next sibling which has a specific tagName.
xParent
Returns the nearest ancestor of ele whose nodeName == name. Assumes name is lowercase. Omit name to get the first ancestor.
xParentN
Returns e when n == 0, e.parentNode when n == 1, e.parentNode.parentNode when n == 2, etc.
xPrevSib
Get an element's previous sibling.
xSmartLoad
Load script or style sheet if not loaded before.
xSmartLoad2
Create any number of script or link elements and assign a URL to each.
xSmartLoadScript
Maintains an array of loaded urls to prevent the same Url being loaded twice.

Debug

xConsole
A debugging utility.
xEditable
A simple function to allow in-line editing.
xName
Debugging utility.
xParentChain
Walks up the parent chain building a string suitable for displaying.
xSetIETitle
Debugging utility for running multiple versions of IE. Prepend browser version to document title.

Event

xAddEventListener
Register an event listener on the element.
xAddHandlers
Assign DOM0 event handlers. For each N do: xGetElementById(idN)[ev] = fnN
xDragInFence
Enable dragging for the element. Optionally, dragging can be limited to a rectangular area. If fnDrag is not provided then this code will provide basic dragging. If fnDrag is provided then it must implement the dragging. See xEnableDrag for more info.
xEnableDrag
Enable dragging for the element. If fnDrag is not provided then this code will provide basic dragging. If fnDrag is provided then it must implement the dragging.
xEnableDrop
Enable an element to receive a drop event from any element drag-enabled with xEnableDrag.
xEvent
Resolve browser differences for event properties. This is an object prototype. Create an instance with the 'new' operator.
xHttpRequest
An asynchronous HTTP request object. Features a 'timeout' event, an optional random parameter to prevent caching, detailed error reporting, a 'busy' property for serialization, and more.
xPreventDefault
A cross-browser wrapper for event.preventDefault
xRemoveEventListener
Unregister an event listener previously registered with xAddEventListener.
xStopPropagation
A cross-browser wrapper for event.stopPropagation

Image

xImgAsyncWait
Asynchronously waits (and monitors the status) of newly created or static images. Can be called before or after window.onload, or in the HTML following the last IMG element. During monitoring of image load status, your status function will be called at each iteration. After all images successfully load, your app initialization function is called. If any image fails to load, your error function is called. You can provide error and abort images for those that fail to load.
xImgRollSetup
Image rollover setup. Can not be called before the window onload event. Pass image IDs starting with 4th argument. The only html requirement is for each IMG tag to have an ID. Assumes this image file naming convention: out img = path + imgEleId + fileExt over img = path + imgEleId + ovrSuffix + fileExt
xTriStateImage
Image rollover with a third state - mousedown.

Iteration

xEach
Access each element of a collection sequentially (by its numeric index) and do something with it.
xEachE
For each ele/id, call the callback function passing it the element object and the count. Pass any number of ele/id's as arguments - the callback function must be the last argument.
xEachN
Iterate over all elements with the same sIdPrefix and a sequential, numeric suffix beginning with iStart. fnCallback is called for each element and passed the element, its numeric suffix and oData.
xEachUntilReturn
Access each element of a collection sequentially (by its numeric index) and do something with it. Stop when the called function returns a value.
xTimes
Call a function n times.
xWalkToFirst
Starts from a node and applies fnVisit up to the very first element (or up to a non-null returned value from 'fnVisit'). Children of starting node are not processed since children are consider to be "after" their parent. Optional 'data' and 'skip' work like in xWalkTree2.
xWalkToLast
Starts from a node and applies 'fnVisit' up to the very last element (or up to a non-null returned value from 'fnVisit'). Children of starting node are processed since children are consider to be "after" their parent (this is the opposite to xWalkToFirst). Optional 'data' and 'skip' work like in xWalkTree2.
xWalkTree
Perform a preorder traversal on the subtree starting at oNode and pass each Element node to fnVisit.
xWalkTree2
Traverse a sub-tree.
xWalkTree3
Perform a preorder traversal on the subtree starting at oNode and pass each Element node to fnVisit.
xWalkTreeRev
Traverse a sub-tree in reverse.
xWalkUL
Perform a preorder traversal on nested ULs starting at oUL. If there is a nested UL it must be a direct child of the LI (not neccessarily the first). Only supports having one nested UL in each LI. The callback function is called for every LI.

Misc

xCookie
Set, get or delete a cookie name/value.
xDef
Determine if all arguments are 'defined'.
xDeg
Converts from radians to degrees.
xGetURLArguments
Parses the name/value pairs on the url.
xInA
Return the array index of the element which is === v, else return false if v is not in a.
xLibrary
The version property of this object gives the X Library version string for the distribution in which this file was included. Each X symbol's XML file documents its own revisions. This file (xlibrary.xml) will have summary notes for each X release.
xLinearScale
Get a scaled value
xNum
Determine if the arguments are of type Number.
xRad
Converts from degrees to radians.
xRound
Rounds a number to the specified number of decimal digits.
xStr
Determine if all arguments are of type 'string'.

Position

xCardinalPosition
A convient way to get the coordinates of an element's 'cardinal' (or 'compass') points.
xCen
Center an absolute-positioned element.
xCenter
Center a positioned element within the current client window space. If w,h not specified, then the existing width and height of e are used.
xGetEleAtPoint
Returns a reference to the element with the highest z-index which contains the given absolute point.
xHasPoint
Determines if an element contains an absolute point. The element's boundary is extended (negative clip), or contracted (positive clip) by the clipping parameters.
xIntersection
Determine if two elements intersect and if so determine the intersecting rectangle.
xLeft
Return and optionally set the element's x coordinate.
xMoveTo
Set the element's x and y coordinates.
xOffset
Return an object with x and y properties giving the offset position of child relative to parent.
xPageX
Get the page-relative X position of the element.
xPageY
Get the page-relative Y position of the element.
xScrollLeft
Determine how far the window (or an element) has scrolled horizontally.
xScrollTop
Determine how far the window (or an element) has scrolled vertically.
xTop
Return and optionally set the element's y coordinate.

Size

xClientHeight
The inner height of the window not including any scrollbar - that is, the "viewport".
xClientWidth
The inner width of the window not including any scrollbar - that is, the "viewport".
xClip
Set the element's clipping rectangle. If ele is the only argument then set clip to existing width and height.
xColEqualizer
Equalize the heights of any number of columns. Pass any number of pairs of elements to this function.
xDocSize
Determines the (largest) width and height of the 'document'.
xHeight
Return and optionally set the element's height. It attempts to return and/or set the equivalent of offsetHeight. xHeight provides, effectively, a read/write version of offsetHeight. The border is included, as well as the padding, in the calculations. When returning the existing height, xHeight returns offsetHeight, which is the sum of the border, padding and style.height values. When setting a new height, xHeight finds the current border and padding values of the element and then subtracts those from the height you have specified before assigning the result to style.height.
xResizeTo
Resize an element.
xWidth
Return and optionally set the element's width. It attempts to return and/or set the equivalent of offsetWidth. xWidth provides, effectively, a read/write version of offsetWidth. The border is included, as well as the padding, in the calculations. When returning the existing width, xWidth returns offsetWidth, which is the sum of the border, padding and style.width values. When setting a new width, xWidth finds the current border and padding values of the element and then subtracts those from the width you have specified before assigning the result to style.width.

String

xCamelize
Converts a CSS property name string (dash-separated) to a camel-cased string (style object property name).
xCapitalize
Capitalize the first letter of every word in str.
xHex
Converts an integer to a hex string.
xJoin
Serialize an object. Reverse the operation with xSplit.
xPad
Pad a string, on the left or right, to a specific length using a specific character.
xParseColor
Parse a color string or number into its components.
xRgbToHex
Converts three numbers (representing RGB colors) to a hex string in the form "#RRGGBB".
xSplit
Split str on delim1 then split each substring on delim2. Create an object and add properties where the property name is on the left of delim2 and its value is on the right of delim2. Reverse the operation with xJoin.
xStrEndsWith
Returns true if s ends with end.
xStrRepeat
Repeat a string.
xStrReplaceEnd
Replaces newEnd.length characters at the end of s with newEnd.
xStrStartsWith
Returns true if s begins with beg.
xTrim
Removes leading and trailing white-space from a string.

Style

xAddClass
Adds a class name to an element.
xDisplay
A safe wrapper for element.style.display.
xFindAfterByClassName
Finds the first element after the given one that is from a given class.
xFindBeforeByClassName
Finds the first element before the given one that is from a given class.
xGetComputedStyle
A safe wrapper for getComputedStyle and currentStyle.
xGetCSSRules
Extracts CSS rules from the style sheet object (IE vs. DOM CSS level 2).
xGetStyleSheetFromLink
Extracts style sheet object from the HTML LINK object (IE vs. DOM CSS level 2).
xHasClass
Returns true if an element has a specified class name
xHasStyleSelector
Checks whether any of the stylesheets attached to the document contain the definition of the specified style selector (simple string matching at the moment).
xHasStyleSheets
Checks browser support for stylesheet related objects (IE or DOM compliant).
xInsertRule
Insert a new rule into a styleSheet.
xOpacity
Set or get the opacity of an element.
xRemoveClass
Removes a class name from an element
xStyle
Set any style property for any number of elements. If an exception is thrown, and sProp=='display', and the browser is IE7 or down, and the element is one of the table elements, then assign 'block' or 'inline' based on tagName.
xTagStyle
Set any style property for any number of tags.
xToggleClass
Toggles a class name on or off for an element
xTraverseDocumentStyleSheets
Traverses all stylesheets attached to a document (linked as well as internal).
xTraverseStyleSheet
Traverses all rules in the stylesheet, calling callback function on each rule. Recursively handles stylesheets imported with @import CSS directive. Stops when the callback function returns true (it has found what it's been looking for).

Table

xTable
This is an unobtrusive table enhancement. It freezes the table's first row (or THEAD) and first column while the rest of the table is scrollable. If the table has a CAPTION it is removed and inserted above the frozen header.
xTableCellVisibility
Set the visibility of a table cell.
xTableColDisplay
Set the display of a table column.
xTableCursor
Mouseover highlight on rows and cells.
xTableCursor2
Mouseover highlight on rows and cells. Click to select a cell.
xTableHeaderFixed
xTableHeaderFixed is an unobtrusive table enhancement. It makes a copy of a table's THEAD section. While the table is visible in its container the THEAD copy will be fixed to the top of the container, so you can scroll up and down in a long table and the header will always be visible. The container can be a window or a scrollable element. The position and size of the THEAD copy will be adjusted when the window is resized. The THEAD copy is clipped to its container's inner width. You only need to instantiate one xTableHeaderFixed object for each group of tables that have the same styling - and so those tables should have a common className, which you pass to the constructor. You must assign all of the table's styles relative to this className so that the THEAD copy will be styled just like it. It takes the widths of all THs (not TDs) in the THEAD and assigns them to the corresponding THs in the THEAD copy. When instantiating, you do not have to keep a reference to the object - it keeps a reference to itself, but if you plan on calling the 'init' or 'paint' methods later then you'll need to keep a reference to the object.
xTableIterate
Iterates thru all rows and cols of a table and calls fnCallback for each.
xTableRowDisplay
Sets the display of a table row.
xTableSync
Assign a function to handle events which occur on either table and access corresponding TDs.

UI

xBar
Bar-Graph Object
xCalendar
xCalendar is a popup date-picker. It restricts selection to a range of Dates. Days outside the range are greyed-out. Only days in-range have a mouseover effect and can be selected. If you don't set a range it will default to the current year. When the user selects a date, a date string will be assigned to the input element you specify with the 'setInput' method. When the calendar is shown, it is positioned just to the right of this element. While displayed, the user can cancel the calendar by pressing ESCape or clicking anywhere outside the calendar. If you call xCalendar's 'show' method from a click listener then you should call xStopPropagation to prevent xCalendar from being canceled immediately.
xCollapsible
Creates a collapsible list from nested ULs or nested DIVs. A UL/DIV is a "target" - it will have its display toggled when its "trigger" is clicked (except for the outermost UL/DIV). For ULs the trigger is the UL's previous sibling element. For DIVs the trigger is also the DIV's previous sibling element, but it must be a heading element (H1, H2, etc.).
xDialog
Provides a dialog box framework.
xFenster
xFenster takes an existing DIV or IFRAME element and dynamically encloses it in a draggable, resizeable "window" (fenster). If the DIV or IFRAME does not exist xFenster will create it. The constructor takes a single object as an argument. The properties of this object are documented below in the "Parameters" section.
xMenu1
xMenu1 Object Prototype
xMenu1A
xMenu1A Object Prototype. A variation on xMenu1. The menu slides down and up.
xMenu1B
xMenu1B Object Prototype. A variation on xMenu1A. The menu requires a click to close and opening one closes any others that were open.
xMenu5
Only one branch per level can be open. Assumes btnClass element to be a direct child of an LI, tho it doesn't have to be the first child. Assumes the btn's corresponding UL to be a sibling, tho it doesn't have to be the next sibling.
xMenu6
A UL-based menu with unlimited levels and many other features.
xModalDialog
A simple modal dialog box object.
xPersistentDisplay
xPersistentDisplay provides persistent display or non-display of elements with specific CSS class names.
xPopup
A DHTML alternative to popup windows.
xSelect
Accessible Categories and Sub-Categories. xSelect is another experiment in unobtrusive DHTML. xSelect implements categories and sub-categories as two SELECT controls where the contents of the second control dynamically change depending on the selection in the main control. In your HTML create a SELECT element (which I'll call s0) which contains OPTGROUP elements. Within each OPTGROUP are any number of OPTION elements. Given the id of s0, xSelect creates two SELECT elements: The 'main category' SELECT (s1) contains an OPTION for each OPTGROUP in s0. The 'sub-category' SELECT (s2) is dynamically filled with OPTGROUP OPTIONs depending on which category is selected in s1. s1 and s2 are dynamically created and appended to the same form which contains s0. s0 is hidden, s1 is positioned where s0 was, and s2 is positioned below or to the right of s1. If the browser doesn't support the objects required by xSelect, or if the user has javascript disabled, then the user will get the original SELECT which contains all main categories (as OPTGROUPs) and all sub-categories (as OPTIONs within each OPTGROUP).
xSplitter
This object is a nestable, dual-pane splitter. It can be horizontal or vertical. Each xSplitter has two panes. Pane1 is the left (or top) pane, and pane2 is the right (or bottom) pane. An xSplitter can be nested inside any pane of any other xSplitter. xSplitter makes no assumptions about classnames or id strings - the only requirement is that the xSplitter DIV contain 3 child DIVs in this order: pane1, pane2, and dragBar.
xTabPanelGroup
Downgradeable, accessible, tabbed panels.
xTextArea
A wrapper around an html textarea allowing manipulation of its contents using normal javascript string methods.
xTooltipGroup
Different tooltips applied to groups of elements.

Window

xWinClass
An unobtrusive version of xWindow
xWindow
xWinOpen
A simple alternative to xWindow.

xFenster

Description

xFenster takes an existing DIV or IFRAME element and dynamically encloses it in a draggable, resizeable "window" (fenster). If the DIV or IFRAME does not exist xFenster will create it. The constructor takes a single object as an argument. The properties of this object are documented below in the "Parameters" section.

Syntax

new xFenster(xfArgs);

Parameters

clientIdId string of client element (a DIV or IFRAME). If the element does not exist xFenster will create it. clientId also becomes the property name of a reference to this xFenster in the instances object. (string, no default, clientId is the only required property of xfArgs, the remainder are optional.)
titleInitial title for the title bar. (string, default="")
urlInitial URL to load into the IFRAME. If this is not a string it is assumed the client element is a DIV instead of an IFRAME. (string, default=undefined)
x, yInitial position of fenster. (integer, default=0, 0)
w, hInitial size of fenster. (integer, default=200, 200)
minWWidth when minimized. (integer, default=100)
conBorBorder size applied to container element. (integer, default=1)
conPadPadding applied to container element. (integer, default=1)
cliBorBorder size applied to client element. (integer, default=0)
fenceIdId string (or Element reference) of fence element. The fenster's move, resize, minimize and maximize will be limited to the boundary of the fence element. Only supported for absolute fensters. (string or object, default=undefined)
-
noFixedIf true (and for IE6 and down), the outer container is given position:absolute, else it is given position:fixed. (boolean, default=false)
noMoveIf true, moving (dragging by the titlebar) is disabled, else it is enabled. (boolean, default=false)
noResizeIf true, resizing (dragging by the lower-right corner) is disabled, else it is enabled. (boolean, default=false)
noMinimizeIf true, the minimize button is disabled, else it is enabled. (boolean, default=false)
noMaximizeIf true, the maximize button is disabled, else it is enabled. (boolean, default=false)
noCloseIf true, the close button is disabled, else it is enabled. (boolean, default=false)
noStatusIf true, the status bar is disabled, else it is enabled. (boolean, default=false)
noMenuIf true, the control menu is disabled, else it is enabled. (boolean, default=true. if fnMenu is defined then noMenu defaults to false)
-
fnPaintfnPaint(xf) - Called after a "paint". (function, default=undefined)
fnMovefnMove(xf,x,y) - Called before xf is moved. x,y is target position of xf's outer container. Return true to allow move, false to cancel. (function, default=undefined)
fnResizefnResize(xf,w,h) - Called before xf is resized. w,h is target size of client element. Return true to allow resize, false to cancel. (function, default=undefined)
fnDragEndfnDragEnd(xf) - Called at the end of a drag event for Move and Resize. (function, default=undefined)
fnMinimizefnMinimize(xf) - Called before xf is minimized. Return true to allow minimize, false to cancel. (function, default=undefined)
fnMaximizefnMaximize(xf, w, h) - Called before xf is maximized. w,h is target size of client element. Return true to allow maximize, false to cancel. (function, default=undefined)
fnRestorefnRestore(xf) - Called after xf is restored. (function, default=undefined)
fnClosefnClose(xf) - Called before xf is closed. Return true to allow close, false to cancel. (function, default=undefined)
fnFocusfnFocus(xf) - Called before xf is focused. Return true to allow focus, false to cancel. (function, default=undefined)
fnLoadfnLoad(xf) - Called when IFRAME finishes loading a page. (function, default=undefined)
fnMenufnMenu(xf) - Called before control menu is displayed. See demo 4 for usage. Return true to allow it, false to cancel. (function, default=undefined)
-
clsCon, clsCli, clsMsk, clsMnuClass names for outer container, client, IFRAME mask and control menu elements. (string, default="xfContainer", "xfClient", "xfMask", "xfMenu")
clsTB, clsTBFClass names for title bar default and focused states. (string, default="xfTBar", "xfTBarF")
clsSB, clsSBFClass names for status bar default and focused states. (string, default="xfSBar", "xfSBarF")
clsRszI, clsMinI, clsMaxI, clsRstI, clsCloI, clsMnuIClass names for resize, minimize, maximize, restore, close and control menu icons. (string, default="xfRszIco", "xfMinIco", "xfMaxIco", "xfRstIco", "xfCloIco", "xfMnuIco")
ttResize, ttMinimize, ttMaximize, ttRestore, ttClose, ttMenuText for icon tooltips. (string, default="Resize", "Minimize", "Maximize", "Restore", "Close", "")

Source

// xFenster r21, Copyright 2004-2011 Michael Foster (Cross-Browser.com)
// Part of X, a Cross-Browser Javascript Library, Distributed under the terms of the GNU LGPL

function xFenster(xfArgs)
{
  var _i = this; // private reference to the instance object

  // Public Methods

  _i.paint = function(dw, dh) { xFenster._paint(_i, dw, dh); };
  _i.focus = function() { xFenster._focus(_i); };
  _i.href = function(s) { return xFenster._href(_i, s); };
  _i.hide = function(e) { xFenster._hide(_i, e); };
  _i.show = function() { xFenster._show(_i); };
  _i.status = function(s) { return xFenster._status(_i, s); };
  _i.title = function(s) { return xFenster._title(_i, s); };
  _i.destroy = function() { xFenster._destroy(_i); };
  _i.minimize = function() { return xFenster._minimize(_i); };
  _i.maximize = function() { return xFenster._maximize(_i); };
  _i.restore = function() { return xFenster._restore(_i); };
  _i.resize = function(w, h) { _i.a.w = w; _i.a.h = h; xFenster._paint(_i, 0, 0); };
  _i.mnuHide = function() { xFenster._mnuHide(_i); }; //r21/MENU
  // Event listeners
  _i.drgSL = function() { xFenster._drgSH(_i); }; // Drag start listener
  _i.drgEL = function() { xFenster._drgEH(_i); }; // Drag end listener
  _i.movDL = function(e, mdx, mdy) { xFenster._movDH(_i, e, mdx, mdy); }; // Move drag listener
  _i.rszDL = function(e, mdx, mdy) { xFenster._rszDH(_i, e, mdx, mdy); }; // Resize drag listener
  _i.maxCL = function() { xFenster._maxCH(_i); }; // Maximize click listener
  _i.minCL = function() { xFenster._minCH(_i); }; // Minimize click listener
  _i.mnuCL = function() { xFenster._mnuCH(_i); }; // Menu click listener //r21/MENU
  _i.mnuOL = function(e) { xFenster._mnuOH(_i, this, e); }; // Menu mouseout listener; "this" points to con or mnu //r21/MENU

  // Public Properties

  _i.a = {};
  xFenster._iA(_i, xfArgs);
  // elements
  _i.con = null; // outer container
  _i.cli = xGetElementById(_i.a.clientId); // client element
  _i.msk = null; // iframe mask
  _i.mnu = null; // menu element //r21/MENU
  _i.tB = null; // title bar
  _i.sB = null; // status bar
  _i.rI = null; // resize icon
  _i.nI = null; // minimize icon
  _i.mI = null; // maximize icon
  _i.cI = null; // close icon
  _i.uI = null; // menu icon //r21/MENU
  // bool
  _i.min = false; // true if minimized
  _i.max = false; // true if maximized
  _i.hid = false; // true if hidden
  _i.ifr = (xStr(_i.a.url) && _i.a.url.length); // true if client is iframe
  _i.drg = false; // true if currently being moved or resized
  // restore values
  _i.rX = _i.a.x;
  _i.rY = _i.a.y;
  _i.rW = _i.a.w;
  _i.rH = _i.a.h;
  // misc
  _i.P2 = 2 * _i.a.conPad;
  _i.oB2 = 2 * _i.a.conBor;
  _i.iB2 = 2 * _i.a.cliBor;

  // Constructor
  xFenster._ctor(_i);

} // end xFenster object prototype

/*--------------------- Static Properties and Methods ------------------------*/

xFenster.first = true;  // first instantiation
xFenster.nextZ = 100;   // z-index for next focus
xFenster.rszTmr = null; // window resize timer
xFenster.focused = null;// currently focused fenster
xFenster.instances = {};// all xFenster instances
xFenster.minimized = [];// currently minimized fensters

// Misc Static Methods ---------------------------------------------------------

/* Finish a minimize or a maximize. */
xFenster._finMM = function(xf, b, x, y, w, h, noR)
{
  if (!noR) {
    xf.rW = xf.con.offsetWidth;
    xf.rH = xf.con.offsetHeight;
    if (!xf.a.noFixed) {
      xf.rX = xf.con.offsetLeft;
      xf.rY = xf.con.offsetTop;
    }
    else {
      xf.rX = xPageX(xf.con);
      xf.rY = xPageY(xf.con);
    }
  }
  if (x != -1) {xMoveTo(xf.con, x, y);}
  if (b) {
    b.className = xf.a.clsRstI;
    b.title = xf.a.ttRestore;
    b.onclick = xf.restore;
  }
  if (!xf.a.noMove) {
    xf.tB.style.cursor = 'default';
    xf.tB.xDragEnabled = false;
  }
  if (!xf.a.noResize) {
    xf.rI.style.display = 'none';
    xf.rI.xDragEnabled = false;
  }
  xf.a.w = w;
  xf.a.h = h;
  xFenster._paint(xf, 0, 0);
};

/* Initialize the a (args) object. */
xFenster._iA = function(xf, o)
{
  var p, a;
  // Copy the xfArgs properties
  for (p in o) {
    if (o.hasOwnProperty(p)) {
      xf.a[p] = o[p];
    }
  }
  a = xf.a;
  // Set defaults
  if (!a.noFixed) a.fenceId = false; // fence not supported for fixed fensters
  if (!xDef(a.conBor)) a.conBor = 1;
  if (!xDef(a.conPad)) a.conPad = 1;
  if (!a.cliBor) a.cliBor = 0;
  if (!a.x) a.x = 0;
  if (!a.y) a.y = 0;
  if (!a.w) a.w = 200;
  if (!a.h) a.h = 200;
  if (!a.minW) a.minW = 100;
  if (!a.clsSB) a.clsSB = 'xfSBar';
  if (!a.clsSBF) a.clsSBF = 'xfSBarF';
  if (!a.clsTB) a.clsTB = 'xfTBar';
  if (!a.clsTBF) a.clsTBF = 'xfTBarF';
  if (!a.clsCli) a.clsCli = 'xfClient';
  if (!a.clsCon) a.clsCon = 'xfContainer';
  if (!a.clsMsk) a.clsMsk = 'xfMask';
  if (!a.clsRszI) a.clsRszI = 'xfRszIco';
  if (!xDef(a.ttResize)) a.ttResize = 'Resize';
//[r21/MENU
  if (!a.clsMnuI) a.clsMnuI = 'xfMnuIco';
  if (!a.clsMnu) a.clsMnu = 'xfMenu';
  if (!xDef(a.noMenu)) a.noMenu = !xDef(a.fnMenu);
//r21/MENU]
  if (!a.clsMinI) a.clsMinI = 'xfMinIco';
  if (!xDef(a.ttMinimize)) a.ttMinimize = 'Minimize';
  if (!a.clsMaxI) a.clsMaxI = 'xfMaxIco';
  if (!xDef(a.ttMaximize)) a.ttMaximize = 'Maximize';
  if (!a.clsCloI) a.clsCloI = 'xfCloIco';
  if (!xDef(a.ttClose)) a.ttClose = 'Close';
  if (!a.clsRstI) a.clsRstI = 'xfRstIco';
  if (!xDef(a.ttRestore)) a.ttRestore = 'Restore';
  if (!xDef(a.title)) a.title = '';
};

/* Constructor */
xFenster._ctor = function(xf)
{
  xFenster.instances[xf.a.clientId] = xf;
  // Create elements
  if (!xf.cli) {
    xf.cli = document.createElement( xf.ifr ? 'iframe' : 'div');
    xf.cli.id = xf.a.clientId;
  }
  xf.cli.className += ' ' + xf.a.clsCli;
  xf.con = document.createElement('div');
  xf.con.className = xf.a.clsCon;
  if (xf.ifr) {
    xf.msk = document.createElement('div');
    xf.msk.className = xf.a.clsMsk;
  }
  if (!xf.a.noResize) {
    xf.rI = document.createElement('div');
    xf.rI.className = xf.a.clsRszI;
    xf.rI.title = xf.a.ttResize;
  }
  if (!xf.a.noMinimize) {
    xf.nI = document.createElement('div');
    xf.nI.className = xf.a.clsMinI;
    xf.nI.title = xf.a.ttMinimize;
  }
  if (!xf.a.noMaximize) {
    xf.mI = document.createElement('div');
    xf.mI.className = xf.a.clsMaxI;
    xf.mI.title = xf.a.ttMaximize;
  }
  if (!xf.a.noClose) {
    xf.cI = document.createElement('div');
    xf.cI.className = xf.a.clsCloI;
    xf.cI.title = xf.a.ttClose;
  }
//[r21/MENU
  if (!xf.a.noMenu) {
    xf.uI = document.createElement('div');
    xf.uI.className = xf.a.clsMnuI;
    if (xf.a.ttMenu) xf.uI.title = xf.a.ttMenu;
    xf.mnu = document.createElement('div');
    xf.mnu.className = xf.a.clsMnu;
  }
//r21/MENU]
  xf.tB = document.createElement('div');
  xf.tB.className = xf.a.clsTB;
  xf.title(xf.a.title);
  if (!xf.a.noStatus) {
    xf.sB = document.createElement('div');
    xf.sB.className = xf.a.clsSB;
    xFenster._status(xf, ' ');
  }
  // Append elements
  xf.con.appendChild(xf.tB);
  if (xf.nI) xf.con.appendChild(xf.nI);
  if (xf.mI) xf.con.appendChild(xf.mI);
  if (xf.cI) xf.con.appendChild(xf.cI);
  if (xf.uI) xf.con.appendChild(xf.uI);//r21/MENU
  xf.con.appendChild(xf.cli);
  if (xf.sB) xf.con.appendChild(xf.sB);
  if (xf.rI) xf.con.appendChild(xf.rI);
  if (xf.msk) xf.con.appendChild(xf.msk);
  if (xf.mnu) xf.con.appendChild(xf.mnu);//r21/MENU
  document.body.appendChild(xf.con);
  // Position and paint the fenster
  /*@cc_on
  @if (@_jscript_version <= 5.6) // IE6 or down
      xf.a.noFixed = true;
    @else @*/
      if (!xf.a.noFixed) xf.con.style.position = 'fixed';
  /*@end @*/
  xf.con.style.borderWidth = xf.a.conBor + 'px';
  xf.cli.style.borderWidth = xf.a.cliBor + 'px';
  xf.cli.style.display = 'block'; // do this before paint
  xf.cli.style.visibility = 'visible';
  xf.tB.style.left = xf.tB.style.right = xf.tB.style.top = xf.a.conPad + 'px';
  if (xf.sB) {xf.sB.style.left = xf.sB.style.right = xf.sB.style.bottom = xf.a.conPad + 'px';}
  xf.cli.style.left = xf.a.conPad + 'px';
  if (xf.msk) xf.msk.style.left = xf.cli.style.left;
  if (xf.mnu) xf.mnu.style.left = (xf.a.conPad + xf.a.cliBor) + 'px'; //r21/MENU
  xMoveTo(xf.con, xf.a.x, xf.a.y);
  xFenster._paint(xf, 0, 0);
  // Position the icons
  var t = xf.a.conPad + xf.a.conBor, r = t;
  if (xf.cI) {
    xf.cI.style.top = t + 'px';
    xf.cI.style.right = r + 'px';
    r += xf.cI.offsetWidth + 2;
  }
  if (xf.mI) {
    xf.mI.style.top = t + 'px';
    xf.mI.style.right = r + 'px';
    r += xf.mI.offsetWidth + 2;
  }
  if (xf.nI) {
    xf.nI.style.top = t + 'px';
    xf.nI.style.right = r + 'px';
  }
//[r21/MENU
  if (xf.uI) {
    xf.uI.style.top = t + 'px';
    xf.uI.style.left = t + 'px';
  }
//r21/MENU]
  if (xf.rI) {
    xf.rI.style.right = xf.rI.style.bottom = t + 'px';
  }
  // Register the event listeners
  if (xf.ifr) {
    xFenster._href(xf, xf.a.url);
    if (xf.a.fnLoad) {xAddEventListener(xf.cli, 'load', function(){xf.a.fnLoad(xf);}, false);}
    xf.cli.name = xf.a.clientId;
  }
  if (!xf.a.noMove) xEnableDrag(xf.tB, xf.drgSL, xf.movDL, xf.drgEL);
  if (!xf.a.noResize) xEnableDrag(xf.rI, xf.drgSL, xf.rszDL, xf.drgEL);
  xf.con.onmousedown = xf.focus;
  if (!xf.a.noMenu) xf.uI.onclick = xf.mnuCL;//r21/MENU
  if (!xf.a.noMinimize) xf.nI.onclick = xf.minCL;
  if (!xf.a.noMaximize) xf.mI.onclick = xf.tB.ondblclick = xf.maxCL;
  if (!xf.a.noClose) {
    xf.cI.onclick = xf.hide;
    xf.cI.onmousedown = xStopPropagation;
  }
  if (xFenster.first) {
    xFenster.first = false;
    xAddEventListener(window, 'unload', xFenster._wUL, false);
    xAddEventListener(window, 'resize', xFenster._wRL, false);
  }
  // Make sure the fenster fits its boundaries
  xFenster.fitToBounds(xf);
  // Show the fenster
  xf.con.style.visibility = 'visible';
  xFenster._focus(xf);
};

// Static window event listeners -----------------------------------------------

/* Window resize event listener. */
xFenster._wRL = function()
{
  if (!xFenster.rszTmr) xFenster.rszTmr = setTimeout(xFenster._wRTL, 500);
};

/* Window resize timer listener. Resizes maximized fensters. Calls fitToBounds
   for each fenster. Repositions minimized fensters. */
xFenster._wRTL = function()
{
  var p, o = xFenster.instances;
  if (o) {
    for (p in o) {
      if (o.hasOwnProperty(p)) {
        if (o[p].max) { xFenster._maxCH(o[p], true); }
        xFenster.fitToBounds(o[p]);
      }
    }
    xFenster.fitMinToBounds();
  }
  xFenster.rszTmr = null;
};

/* Window unload event listener. */
xFenster._wUL = function()
{
  var p, o = xFenster.instances;
  if (o) {
    for (p in o) {
      if (o.hasOwnProperty(p)) {
        xFenster._destroy(o[p]);
      }
    }
    xFenster.focused = xFenster.instances = xFenster.minimized = null;
  }
  xRemoveEventListener(window, 'unload', xFenster._wUL, false);
  xRemoveEventListener(window, 'resize', xFenster._wRL, false);
};

// Static handlers for event listener methods ----------------------------------

/* Drag start handler. */
xFenster._drgSH = function(xf)
{
  xf.drg = true;
  xFenster.mask(true);
};

/* Drag end handler. */
xFenster._drgEH = function(xf)
{
  if (xf.msk) { xf.msk.style.display = 'none'; }
  if (xf.a.fnDragEnd) { xf.a.fnDragEnd(xf); }
  xf.drg = false;
};

/* Move drag handler. */
xFenster._movDH = function(xf, e, mdx, mdy)
{
  var x = xf.con.offsetLeft + mdx, y = xf.con.offsetTop + mdy;
  if (xFenster.inBounds(xf, mdx, mdy, 0, 0) && (!xf.a.fnMove || xf.a.fnMove(xf, x, y))) {
    xf.con.style.left = x + 'px';
    xf.con.style.top = y + 'px';
  }
};

/* Resize drag handler. */
xFenster._rszDH = function(xf, e, mdx, mdy)
{
  var w = xf.con.offsetWidth + mdx, h = xf.con.offsetHeight + mdy;
  if (w >= xf.a.minW && h >= 50) { // minimum size allowed
    if (xFenster.inBounds(xf, 0, 0, mdx, mdy) && (!xf.a.fnResize || xf.a.fnResize(xf, xf.cli.offsetWidth + mdx, xf.cli.offsetHeight + mdy))) {
      xFenster._paint(xf, mdx, mdy);
    }
  }
};

/* Maximize click handler. If noCb is true then the fnMaximize callback is not called. */
xFenster._maxCH = function(xf, noCb)
{
  var f, o, tw, th, w, h, x, y;
  if (!xf.a.noFixed) {
    x = y = 0;
    w = xClientWidth();
    h = xClientHeight();
  }
  else if (xf.a.fenceId) {
    f = xGetElementById(xf.a.fenceId);
    x = xPageX(f);
    y = xPageY(f);
    w = f.offsetWidth;
    h = f.offsetHeight;
  }
  else {
    x = y = 0;
    o = xDocSize();
    w = xClientWidth();
    //w = o.w;
    h = o.h;
  }
  tw = w - xf.P2 - xf.oB2; // target size of client element
  th = h - xf.tB.offsetHeight - (xf.sB ? xf.sB.offsetHeight : 0) - xf.P2 - xf.oB2;
  if (noCb || (!xf.a.fnMaximize || xf.a.fnMaximize(xf, tw, th))) {
    if (!xf.max) {xFenster._restore(xf);}
    xFenster._finMM(xf, xf.mI, x, y, w, h, xf.max);
    xf.max = true;
  }
};

/* Minimize click handler. */
xFenster._minCH = function(xf)
{
  if (xf.a.fnMinimize && !xf.a.fnMinimize(xf)) {
    return;
  }
  xFenster._restore(xf);
  xFenster.minimized[xFenster.minimized.length] = xf;
  xf.min = true;
  xf.cli.style.display = 'none';
  if (xf.sB) xf.sB.style.display = 'none';
  xFenster._finMM(xf, xf.nI, xf.con.offsetLeft, xf.con.offsetTop, xf.a.minW, xf.tB.offsetHeight + xf.P2 + xf.oB2);
  xFenster.fitMinToBounds();
};

//[r21/MENU
/* Menu icon click handler. */
xFenster._mnuCH = function(xf)
{
  if (xf.a.fnMenu && !xf.a.fnMenu(xf)) return;
  xf.mnu.style.display = 'block';
  xf.mnu.onmouseout = xf.con.onmouseout = xf.mnuOL;
};

/* Menu mouseout handler. Handles mouseout events on "o", which is either xf.con or xf.mnu. */
xFenster._mnuOH = function(xf, o, ne)
{
  var e = new xEvent(ne);
  var t = e.relatedTarget;
  while (t && t != o) t = t.parentNode;
  if (t != o) xf.mnuHide();
}
//r21/MENU]

// Static handlers for public methods ------------------------------------------

/* dw and dh are added to the existing container size. */
xFenster._paint = function(xf, dw, dh)
{
  xf.a.w += (dw || 0);
  xf.a.h += (dh || 0);
  xf.con.style.width = (xf.a.w - xf.oB2) + 'px';
  xf.con.style.height = (xf.a.h - xf.oB2) + 'px';
  /*@cc_on
  @if (@_jscript)
    xWidth(xf.tB, xf.a.w - xf.P2 - xf.oB2);
    if (!xf.min && xf.sB) {
      xWidth(xf.sB, xf.a.w - xf.P2 - xf.oB2);
      xf.sB.style.top = xf.a.h - xf.sB.offsetHeight - xf.a.conPad - xf.oB2;
    }
  @end @*/
  if (!xf.min) {
    xf.cli.style.top = (xf.a.conPad + xf.tB.offsetHeight) + 'px';
    xf.cli.style.width = (xf.a.w - xf.P2 - xf.oB2 - xf.iB2) + 'px';
    xf.cli.style.height = (xf.a.h - xf.tB.offsetHeight - (xf.sB ? xf.sB.offsetHeight : 0) - xf.P2 - xf.oB2 - xf.iB2) + 'px';
    if (xf.msk) {
      xf.msk.style.top = xf.cli.style.top;
      xf.msk.style.width = xf.cli.style.width;
      xf.msk.style.height = xf.cli.style.height;
    }
  }
  if (xf.mnu) xf.mnu.style.top = (xf.a.conPad + xf.a.cliBor + xf.tB.offsetHeight) + 'px'; //r21/MENU
  if (xf.a.fnPaint) xf.a.fnPaint(xf);
};

xFenster._focus = function(xf)
{
  if (xFenster.focused != xf && (!xf.a.fnFocus || xf.a.fnFocus(xf))) {
    xf.con.style.zIndex = xFenster.nextZ++;
    if (xFenster.focused) {
      xFenster.focused.tB.className = xFenster.focused.a.clsTB;
      if (xFenster.focused.sB) xFenster.focused.sB.className = xFenster.focused.a.clsSB;
    }
    xf.tB.className = xf.a.clsTBF;
    if (xf.sB) xf.sB.className = xf.a.clsSBF;
    xFenster.focused = xf;
    if (!xf.drg) { xFenster.mask(true, xf); }
  }
};

xFenster._href = function(xf, s)
{
  var h = s;
  if (xf.ifr) {
    if (xf.cli.contentWindow) {
      if (s) {xf.cli.contentWindow.location = s;}
      else h = xf.cli.contentWindow.location.href;
    }
    else if (typeof xf.cli.src == 'string') { // for Safari/Apollo/WebKit on Windows (old comment, may be different now?)
      if (s) {xf.cli.src = s;}
      else h = xf.cli.src;
    }
  }
  return h;
};

xFenster._hide = function(xf, e)
{
  var p, o = xFenster.instances, z = 0, hz = 0, f = null;
  if (!xf.a.fnClose || xf.a.fnClose(xf)) {
    xf.con.style.display = 'none';
    xf.hid = true;
    xStopPropagation(e);
    if (xf == xFenster.focused) {
      for (p in o) { // find the next appropriate fenster to focus
        if (o.hasOwnProperty(p) && o[p] && !o[p].hid && o[p] != xf) {
          z = parseInt(o[p].con.style.zIndex);
          if (z > hz) {
            hz = z;
            f = o[p];
          }
        }
      }
      if (f) {xFenster._focus(f);}
    }
  }
};

xFenster._show = function(xf)
{
  xf.con.style.display = 'block';
  xf.hid = false;
  xFenster._focus(xf);
};

xFenster._status = function(xf, s)
{
  if (xf.sB) {
    if (s) {xf.sB.innerHTML = s;}
    else return xf.sB.innerHTML;
  }
};

xFenster._title = function(xf, s)
{
  if (s) xf.tB.innerHTML = s;
  else return xf.tB.innerHTML;
};

xFenster._destroy = function(xf)
{
  if (xf) {
    xFenster._hide(xf);
    xf.con.onmousedown = xf.con.onclick = null;
    if (xf.nI) xf.nI.onclick = null;
    if (xf.mI) xf.mI.onclick = xf.tB.ondblclick = null;
    if (xf.cI) xf.cI.onclick = xf.cI.onmousedown = null;
    xFenster.instances[xf.a.clientId] = null;
    xf.con.parentNode.removeChild(xf.con);
  }
};

xFenster._minimize = function(xf)
{
  if (!xf.min && !xf.hid) {
    xFenster._minCH(xf);
    return true;
  }
  return false;
};

xFenster._maximize = function(xf)
{
  if (!xf.max && !xf.hid) {
    xFenster._maxCH(xf);
    return true;
  }
  return false;
};

xFenster._restore = function(xf)
{
  var b, c, j = -1, l, t;
  if (xf.max) {
    b = xf.mI;
    l = xf.maxCL;
    c = xf.a.clsMaxI;
    t = xf.a.ttMaximize;
    xf.max = false;
  }
  else if (xf.min) {
    b = xf.nI;
    l = xf.minCL;
    c = xf.a.clsMinI;
    t = xf.a.ttMinimize;
    j = xFenster.fitMinToBounds(xf);
    if (j > -1) { xFenster.minimized.splice(j, 1); }
    xf.min = false;
    xf.cli.style.display = 'block';
    if (xf.sB) xf.sB.style.display = 'block';
  }
  else {
    return false;
  }
  xMoveTo(xf.con, xf.rX, xf.rY);
  if (b) {
    b.className = c;
    b.title = t;
    b.onclick = l;
  }
  if (!xf.a.noMove) {
    xf.tB.style.cursor = 'move';
    xf.tB.xDragEnabled = true;
  }
  if (!xf.a.noResize) {
    xf.rI.style.display = 'block';
    xf.rI.xDragEnabled = true;
  }
  xf.a.w = xf.rW;
  xf.a.h = xf.rH;
  xFenster._paint(xf, 0, 0);
  if (xf.a.fnRestore) xf.a.fnRestore(xf);
  return true;
};

//[r21/MENU
xFenster._mnuHide = function(xf)
{
  xf.mnu.style.display = 'none';
  xf.mnu.onmouseout = null;
  xf.con.onmouseout = null;
};
//r21/MENU]

// Static "user" methods -------------------------------------------------------

/* Call a method of all fensters. */
xFenster.all = function(mth)
{
  var p, o = xFenster.instances;
  for (p in o) {
    if (o.hasOwnProperty(p)) {
      o[p][mth]();
    }
  }
};

xFenster.paintAll = function() { xFenster.all('paint'); };
xFenster.showAll = function() { xFenster.all('show'); };
xFenster.hideAll = function() { xFenster.all('hide'); };
xFenster.minimizeAll = function() { xFenster.all('minimize'); };
xFenster.maximizeAll = function() { xFenster.all('maximize'); };
xFenster.restoreAll = function() { xFenster.all('restore'); };

/* Mask (if on is true) or unmask (if on is false) all iframe fensters
   except for xf. */
xFenster.mask = function(on, xf)
{
  var p, o = xFenster.instances;
  for (p in o) {
    //if (o.hasOwnProperty(p) && o[p] && o[p].ifr && !o[p].hid && !o[p].min) {
    if (o.hasOwnProperty(p) && o[p] && o[p].ifr) { // r21
      o[p].msk.style.display = (!on || o[p] == xf) ? 'none' : 'block';
    }
  }
};

/* Return an object whose properties give the position and size of xf and its boundary. */
xFenster.getBounds = function(xf)
{
  var d, f, mm=(xf.max||xf.min), x, y, w, h, bx=0, by=0, bw, bh;
  if (!xf.a.noFixed) { // fixed
    bw = xClientWidth();
    bh = xClientHeight();
    x = xf.con.offsetLeft;
    y = xf.con.offsetTop;
  }
  else { // absolute
    x = xPageX(xf.con);
    y = xPageY(xf.con);
    if (!xf.a.fenceId) { // no fence
      d = xDocSize();
      bw = xClientWidth();
      bh = d.h;
    }
    else { // has fence
      f = xGetElementById(xf.a.fenceId);
      bx = xPageX(f);
      by = xPageY(f);
      bw = f.offsetWidth;
      bh = f.offsetHeight;
    }
  }
  // If minimized or maximized use xf's "restore" values instead of actual values.
  if (mm) {
    x = xf.rX;
    y = xf.rY;
    w = xf.rW;
    h = xf.rH;
  }
  else {
    w = xf.con.offsetWidth;
    h = xf.con.offsetHeight;
  }
  return {x:x, y:y, w:w, h:h, bx:bx, by:by, bw:bw, bh:bh};
};

/* Return true if xf, modified by (dx,dy,dw,dh), is within its boundary. */
xFenster.inBounds = function(xf, dx, dy, dw, dh)
{
  var o = xFenster.getBounds(xf);
  o.x += dx;
  o.y += dy;
  o.w += dw;
  o.h += dh;
  return (!(o.x <= o.bx || o.x + o.w > o.bx + o.bw || o.y <= o.by || o.y + o.h > o.by + o.bh));
};

/* Change xf's position and/or size to fit its boundary. Only decreases.
   This method is still experimental. */
xFenster.fitToBounds = function(xf)
{
  var o, mm=(xf.max||xf.min), xch=false, ych=false, pad = 10;
  // Get position and size of fenster and boundary.
  o = xFenster.getBounds(xf);
  // Find new x and w.
  if (o.x + o.w + pad > o.bx + o.bw) {
    o.x = o.bx + o.bw - o.w - pad;
    xch = true;
  }
  if (o.x < o.bx + pad) {
    o.x = o.bx + pad;
    if (xch) {o.w = o.bw - 2 * pad;}
    xch = true;
  }
  // Find new y and h.
  if (o.y + o.h + pad > o.by + o.bh) {
    o.y = o.by + o.bh - o.h - pad;
    ych = true;
  }
  if (o.y < o.by + pad) {
    o.y = o.by + pad;
    if (ych) {o.h = o.bh - 2 * pad;}
    ych = true;
  }
  // if a change is needed.
  if (xch || ych) {
    if (mm) { // change "restore" values
      xf.rX = o.x;
      xf.rY = o.y;
      xf.rW = o.w;
      xf.rH = o.h;
    }
    else { // change actual values
      xMoveTo(xf.con, o.x, o.y);
      xf.a.w = o.w;
      xf.a.h = o.h;
      xFenster._paint(xf, 0, 0);
    }
  }
};

/* Reposition all minimized fensters. If xf, omit it from the repositioning
   and return its index in the minimized array, else return -1. */
xFenster.fitMinToBounds = function(xf)
{
  var a=[], h=0, i, j=-1, o, p=2, r=1, x, y, xfi=-1, mz=xFenster.minimized;
  if (!mz.length) { return; }
  // First get largest height, and x position and row number for each
  o = xFenster.getBounds(mz[0]); // assumes all fensters have the same bounds
  x = o.bx + p;
  for (i = 0; i < mz.length; ++i) {
    if (xf && xf == mz[i]) {
      xfi = i;
      a[a.length] = null;
    }
    else {
      if (mz[i].con.offsetHeight > h) {
        h = mz[i].con.offsetHeight;
      }
      a[a.length] = {x:x, r:r};
      x += mz[i].con.offsetWidth + p;
      j = i + 1;
      if ((j < mz.length) && (mz[j] != xf) && (x + mz[j].con.offsetWidth + p) >= (o.bx + o.bw)) { // yuck, maybe rethink this method
        ++r; // next row
        x = o.bx + p;
      }
    }
  }
  // Now reposition them
  for (i = 0; i < a.length; ++i) {
    if (a[i]) {
      y = (o.by + o.bh - (( r - a[i].r + 1) * (h + p)));
      xMoveTo(mz[i].con, a[i].x, y);
    }
  }
  return xfi;
};

// end xFenster

Dependencies

xAddEventListener, xClientHeight, xClientWidth, xDef, xDocSize, xEnableDrag, xGetElementById, xMoveTo, xPageX, xPageY, xRemoveEventListener, xResizeTo, xScrollLeft, xScrollTop, xStopPropagation, xWidth

Public Properties

aA copy of the xfArgs object passed to the constructor. Defaults have been assigned to undefined properties.
conThe outermost container element. To resize the fenster, set a.w and a.h then call paint(0,0).
cliThe client element contains the fenster's "content". It is a DIV or IFRAME.
mnuThe control menu element. You must provide its contents in fnMenu. See demo 4 for example usage.
tBThe title bar element.
sBThe status bar element.
minTrue if the fenster is minimized.
maxTrue if the fenster is maximized.
hidTrue if the fenster is hidden (closed).
ifrTrue if the client element is an IFRAME.

Public Methods

paint(dw,dh)Resize the fenster and all its child elements. dw,dh is added to the outer container's current size.
resize(w,h)Resize the fenster and all its child elements. The outer container is resized to w,h.
focus()Bring the fenster to the top and highlight its title and status bars.
href(url)Set or return the contained IFRAME's "location.href" property.
hide()Set the fenster's container to "display:none" and focus the fenster that was previously focused. This method is called when the user clicks the "close" icon.
show()Set the fenster's container to "display:block" and call the fenster's focus method.
status(s)Set or return the fenster's statusbar innerHTML.
title(s)Set or return the fenster's titlebar innerHTML.
destroy()Remove the fenster from the DOM, remove all internal references to the fenster, and unregister all its event listeners. This method is automatically called on each fenster when the window unload event occurs.
minimize()Minimize the fenster.
maximize()Maximize the fenster.
restore()Restore the fenster's pre-maximized or pre-minimized size and position.
mnuHide()Hide the fenster's control menu.

Demos

xfenster-demo - The first of several different xFenster demos.

Discussions & Tests

13Nov2010viewtopic.php?id=25: Forum discussion on xFenster. There are many others.

Notes

16Nov2010 A fenster's move/resize/minimize/maximize is restricted to the boundary of its co-ordinate system. Its position and/or size is adjusted when the window is resized. There are three different co-ordinate systems:
1. Fixed - The boundary is defined by the viewport.
2. Absolute with a fence - The boundary is defined by the
   position and size of the fence element.
3. Absolute with no fence - The boundary's width is defined by
   the viewport and its height is defined by the document.
xFenster "static" properties:
- "xFenster.instances" is an object. When an xFenster is created
  a property is added to the object which references that xFenster
  object. The name of the property is the same as the clientId.
  So you do not have to maintain your own references to instances.
- "xFenster.minimized" is an array of all minimized fensters.
- "xFenster.nextZ" is the next z-index used to focus a fenster.
- "xFenster.focused" is the currently focused fenster.
xFenster "static" methods:
- xFenster.all()
- xFenster.showAll()
- xFenster.hideAll()
- xFenster.paintAll()
- xFenster.restoreAll()
- xFenster.minimizeAll()
- xFenster.maximizeAll()
- xFenster.mask(on,xf)
- xFenster.getBounds(xf)
- xFenster.fitToBounds(xf)
- xFenster.fitMinToBounds(xf)
- xFenster.inBounds(xf,dx,dy,dw,dh)
TODO and Misc. Notes
- Much of the code assumes all fensters have the same boundary.
  This may or may not be a problem - depends on your application.
- fitToBounds works well but only makes fensters smaller, not
  larger. This seems unintuitive.
- Should maximized fensters cover, or not cover, any minimized
  fensters? Currently they do. Perhaps the top of the first
  minimized fenster should be considered the bottom of the
  boundary?
- Tile and cascade could be implemented but there are many
  implications to consider.

Revisions

21: 13Mar2011Added support for a basic "control menu". Also updated "xfenster.css". See: http://cross-browser.com/forums/viewtopic.php?id=828
20: 13Nov2010This object has been completely reworked - it is not backwards-compatible. Many improvements and new features. Used ideas and code from forum members. Updated the demos. Updated the documentation in this file.
19.2: 13Feb2010R19 is still experimental, see '/x/lib/xfenster19.2.js'. Added this on 17Aug2010: I'm afraid I'm getting a little behind on this project. It looks like I started adding some contributions by user 'hmel' - I'm not sure how far I got with it, but it appears to be working. Demos 5 and 6 are now using it. It also looks like I reverted back to using '_i' for the instance reference - I guess I can't make up my mind on that :-)
19: 16Feb09R19 is still experimental, see '/x/lib/xfenster19.1.js'. Arguments are passed as an object and an onDragEnd callback was added.
18: 29jan09Two assignments to ele.style.borderWidth were not appending 'px'.
17: 19Aug07There was a typo on line 27. A ')' where it should not have been.
16: 6Aug07For previous rev history see xFenster2. This rev has many improvements and are documented above.

License

By your use of X and/or CBE and/or any Javascript from this site you consent to the GNU LGPL - please read it. If you have any questions about the license, read the FAQ and/or come to the forums.

Tech Support

Forum support is available at the X Library Support Forums.

About Cross-Browser.com

Cross-Browser.com is the home of X - a cross-browser Javascript library, and many demos, applications, articles and documentation.

Search

Cross-Browser.com

World Wide Web

User Projects

If you are using X, XC or anything from this site, show off your work by posting a link in the X Showcase forum.