/**
* @project CWC2
* @revision $Id: cwc_button.js,v 1.8 2005/05/16 11:26:27 bartvde Exp $
* @purpose Java Script for managed, multi-state HTML buttons
* @author DM Solutions Group (pspencer@dmsolutions.ca)
* @copyright
* Copyright (c) 2003, DM Solutions Group Inc.
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
/**
* the purpose of this code is to conveniently manage fancy javascript buttons
* for the application. It provides three types of buttons managed via a
* button manager. The global button manager is created when this file is
* included. The name of the global button manager is goCWCButtonManager.
*
* Buttons are created as javascript objects and added to the button manager.
* The CWCButton constructor is described in comments just above the CWCButton
* function, but here is a quick example of how to construct a button object:
*
* button = new CWCButton( "MyButton", "MyGroup" , MyFunction, null
* "images/tool_zoombounds_off.gif",
* "images/tool_zoombounds_over.gif",
* "images/tool_zoombounds_on.gif" );
*
* goCWCButtonManager.AddButton( button );
*
* This builds a new button object with its user interface controlled by the
* HTML image object named "MyButton" and adds it to the manager.
*
* Note that it is important for cross-browser compatibility to provide both
* a name and an id in your images. Here is an example image to work with this
* button:
*
*
*
* The button will belong to a group called MyGroup. When a button belongs to
* a group, it is automatically converted from a normal button to a radio
* button (the types of buttons are described below).
*
* MyFunction is the name of a function to call when the button is activated.
* Note that it is just the name of the function, and does not have quotes
* around it. This passes a function object to the button object so that when
* the button is clicked, MyFunction is called. When MyFunction is called, the
* button object that called MyFunction is passed as the one and only argument
* to the function. A sample MyFunction would be:
*
* function MyFunction( oButton, aMyValues )
* {
* alert( oButton.szImageName );
* }
*
* The fourth argument is some value to pass to MyFuction. This can null, a
* single value, or an array of values and is completely dependent on how this
* button is intended to be used.
*
* The fourth parameter is the "normal" state image, the image to be displayed
* when the button is not activated in any way. This is a URL to the image and
* can be relative or absolute depending on your requirements.
*
* The remaining images are optional and will only be used if provided. If
* additional images are provided, then when the button would change to a
* particular state (see below), then the button image will be replaced with
* the associated image.
*
* Buttons can be one of three types:
*
* CWCBUTTONTYPE_CLICK - this is a button that is in the SELECTED state while
* the mouse button is down, and in NORMAL state when it is up. The function
* associated with this type of button is called once when the mouse is
* released.
*
* CWCBUTTONTYPE_TOGGLE - this is a sticky button that stays down after it is
* clicked, and pops up when it is clicked again. The function associated with
* toggle buttons is called when the button is activated and disactivated.
*
* CWCBUTTON_RADIO - this is a sticky button that operates like a toggle button
* except that it is part of a group of buttons of which only one can be active
* at a time. Clicking a radio button deselects all other buttons in the same
* group. Unlike toggle buttons, the function associated with radio buttons is
* called only when the button is pressed. Buttons that are deactivated when
* another button in the same group is activated do not call their function.
* Providing a group name in the constructor of a button automatically makes
* the button a RADIO button.
*
* Buttons have a variety of states.
*
* CWCBUTTONSTATE_NORMAL - the button is not activated
* CWCBUTTONSTATE_HOVER - the mouse is over the button but it is not activated
* CWCBUTTONSTATE_SELECTED - the button is selected (pressed in)
* CWCBUTTONSTATE_DISABLED - the button is unresponsive
*/
//button states
var CWCBUTTONSTATE_NORMAL = 0;
var CWCBUTTONSTATE_HOVER = 1;
var CWCBUTTONSTATE_SELECTED = 2;
var CWCBUTTONSTATE_DISABLED = 3;
//button types
var CWCBUTTONTYPE_CLICK = 0;
var CWCBUTTONTYPE_TOGGLE = 1;
var CWCBUTTONTYPE_RADIO = 2;
//capture events in nav browsers
if (CWCIsNav4 || CWCIsNav6)
{
document.captureEvents(Event.MOUSEDOWN);
document.captureEvents(Event.MOUSEUP);
document.captureEvents(Event.MOUSEMOVE);
}
var goCWCButtonManager = new CWCButtonManager();
/**
* CWCButtonManager manages all the buttons and groups of buttons.
* A single global instance of the CWCButtonManager should be created
* to manage all the buttons in an application. Adding buttons to the
* button manager allows them to be organized into groups and managed
* in an intelligent (radio button) manner
*/
function CWCButtonManager()
{
this.aButtons = new Array();
this.aGroups = new Array();
this.oForm = null;
this.currentButton = null;
this.AddButton = CWCButtonManager_AddButton;
this.GetButton = CWCButtonManager_GetButton;
}
/**
* Return a CWCButton instance given a button name (which is the
* image name, actually)
* @param szImage the name of the button to retrieve
* @return the CWCButton instance or null if not found
*/
function CWCButtonManager_GetButton( szImageName )
{
var oImage = CWCDHTML_GetImage( szImageName );
if (oImage != null && oImage.cwcButton != null)
return oImage.cwcButton;
else
return null;
}
/**
* Add a button to the button manager
* @param oButton - the CWCButton instance to add
*/
function CWCButtonManager_AddButton( oButton )
{
oButton.oManager = this;
oButton.index = this.aButtons.length;
this.aButtons[this.aButtons.length] = oButton;
if (oButton.szGroupName != null && oButton.szGroupName != "null" && oButton.szGroupName != "")
{
var i, theGroup = null;
for (i=0; i < this.aGroups.length; i++)
{
if (this.aGroups[i].szGroupName == oButton.szGroupName)
{
theGroup = this.aGroups[i];
break;
}
}
if (theGroup == null)
{
theGroup = new CWCButtonGroup( oButton.szGroupName );
this.aGroups[this.aGroups.length] = theGroup;
}
theGroup.AddButton( oButton );
}
}
/**
* a group of CWCButton objects managed as a mutually exclusive set.
* Activating one button in the group deactivates the rest.
* @param szGroupName - the name of this group
*/
function CWCButtonGroup( szGroupName )
{
this.szGroupName = szGroupName;
this.aButtons = new Array();
//function prototypes
this.AddButton = CWCButtonGroup_AddButton;
this.ActivateButton = CWCButtonGroup_ActivateButton;
}
/**
* Add a CWCButton object to this group
* @param oButton the button to add to this group
*/
function CWCButtonGroup_AddButton( oButton )
{
oButton.oGroup = this;
oButton.type = CWCBUTTONTYPE_RADIO;
this.aButtons[this.aButtons.length] = oButton;
}
/**
* Activate one button in the group, deactivating all others.
* @param oButton the button to activate
*/
function CWCButtonGroup_ActivateButton( oButton )
{
var i;
for( i=0; i < this.aButtons.length; i++ )
{
if (this.aButtons[i].szImageName != oButton.szImageName)
{
this.aButtons[i].SetState( CWCBUTTONSTATE_NORMAL );
this.aButtons[i].bActive = false;
if (oButton.oForm != null)
{
oButton.oForm['BUTTON_TOOLSET_' + this.szGroupName].value = oButton.szImageName;
}
}
}
}
/*
* construct a new button object
* @param szImageName - the name in the image tag in the page, used
* to grab the image object
* @param nType - the button type (see definitions at start of file).
* @param szGroup - the name of the group to put this button in, or null if no group. Note
* that an empty string is considered a group.
* @param onClick - function to call when the button is clicked. For toggle buttons, this will
* be called when the button is activated and deactivated. For radio buttons,
* this will be called only when the button is activated (not when it is deactivated
* by the button group as part of activating another button).
* @param xValues - an unstructured value that is passed, as is, to the onClick
* as the second value.
* @param szNormalURL - the URL to use when the button is in normal state
* @param szHoverURL - (opt) the URL to use when the button is in normal state
* @param szSelectedlURL - (opt) the URL to use when the button is in normal state
* @param szDisabledURL - (opt) the URL to use when the button is in normal state
*/
function CWCButton( szImageName, nType, szGroup, onClick, xValues, szNormalURL /* szHoverURL, szSelectedURL, szDisabledURL */ )
{
this.szGroupName = szGroup;
this.oGroup = null;
//hidden feature to enable the button to control the visibility of an associated div
this.szDivName = '';
this.aImages = new Array( szNormalURL, null, null, null );
//the index at which option arguments appear.
var optIdx = 6;
if (arguments.length > optIdx)
{
this.aImages[CWCBUTTONSTATE_HOVER] = arguments[optIdx ++];
}
if (arguments.length > optIdx)
{
this.aImages[CWCBUTTONSTATE_SELECTED] = arguments[optIdx ++];
}
if (arguments.length > optIdx)
{
this.aImages[CWCBUTTONSTATE_DISABLED] = arguments[optIdx ++];
}
this.szImageName = szImageName;
this.oImage = CWCDHTML_GetImage( szImageName );
if (this.oImage != null)
{
this.oImage.onmouseover = CWCButton_OnMouseOver;
this.oImage.onmouseout = CWCButton_OnMouseOut;
//this.oImage.onclick = CWCButton_OnMouseClick;
//IE specific handlers
this.oImage.onmousedown = null; //CWCButton_OnMouseDown;
this.oImage.onmouseup = null; //CWCButton_OnMouseUp;
//in IE, this cancels the drag action
this.oImage.ondragstart = CWCButton_OnDragStart;
this.oImage.cwcButton = this;
}
else
{
//alert( "image object for " + this.szImageName + " not found?" );
}
this.onClick = onClick;
this.xValues = xValues;
this.currentState = CWCBUTTONSTATE_NORMAL;
this.bActive = false; //set to true when selected.
//used to track old event handlers so they can be restored.
this.oldMouseDown = null;
this.oldMouseUp = null;
this.oldMouseMove = null;
this.oManager = null;
this.index = 0;
this.type = nType;
this.bMouseDown = false;
//function prototypes
this.GetState = CWCButton_GetState;
this.IsDisabled = CWCButton_IsDisabled;
this.IsSelected = CWCButton_IsSelected;
this.SetState = CWCButton_SetState;
}
/**
* return the state of this button
*/
function CWCButton_GetState()
{
return this.currentState;
}
/**
* return true if the button is disabled
*/
function CWCButton_IsDisabled()
{
return this.currentState == CWCBUTTONSTATE_DISABLED;
}
/**
* return true if the button is selected
*/
function CWCButton_IsSelected()
{
return this.currentState == CWCBUTTONSTATE_SELECTED;
}
/**
* set the state of this button
* @param nState the state to set
*/
function CWCButton_SetState( nState )
{
if (!this.oImage) return false;
var previousState = this.currentState;
if (nState >=0 && nState <= CWCBUTTONSTATE_DISABLED)
{
//HOVER is a transient state, ignore it so toggle buttons work
this.currentState = nState;
if (this.aImages[nState] != null)
{
this.oImage.src = this.aImages[nState];
}
else
{
this.oImage.src = this.aImages[0];
}
}
if (this.szDivName != '' && !this.bMouseDown )
{
if (this.currentState == CWCBUTTONSTATE_SELECTED)
{
//alert( 'showing div ' + this.szDivName );
CWCDHTML_ShowLayer( this.szDivName );
//if (this.oGroup != null)
//{
// this.oGroup.ActivateButton( this );
//}
}
else if (this.currentState == CWCBUTTONSTATE_NORMAL )
{
//alert( 'hiding div ' + this.szDivName );
CWCDHTML_HideLayer( this.szDivName );
}
}
}
//global functions for handling events
function CWCButton_OnMouseOver( e )
{
var target;
if (CWCIsIE)
{
e = event;
target = event.srcElement;
e.cancelBubble = true;
e.returnValue = false;
}
else
{
target = e.target
}
//catch the occasional error in IE
if (target.cwcButton == null)
{
return;
}
if (!target.cwcButton.IsDisabled())
{
if (target.cwcButton.bMouseDown)
{
target.cwcButton.SetState( CWCBUTTONSTATE_SELECTED );
}
else if (!target.cwcButton.IsSelected())
{
target.cwcButton.SetState( CWCBUTTONSTATE_HOVER );
}
}
if (!CWCIsIE)
{
//capture events if we are using netscape so we can grab mouse clicks
target.cwcButton.oldMouseDown = document.onmousedown;
document.onmousedown = CWCButton_OnMouseDown;
target.cwcButton.oldMouseUp = document.onmouseup;
document.onmouseup = CWCButton_OnMouseUp;
}
else
{
target.cwcButton.oImage.onmousedown = CWCButton_OnMouseDown;
target.cwcButton.oImage.onmouseup = CWCButton_OnMouseUp;
}
target.cwcButton.oldMouseMove = document.onmousemove;
document.onmousemove = null;
return false;
}
/*
* handle mouse out events by setting the image state to the appropriate
* state depending on the type of the button. If the image was not set
* active then we reset it and don't generate a click when the mouse button
* is released.
*/
function CWCButton_OnMouseOut( e )
{
var target;
if (CWCIsIE)
{
e = event;
target = event.srcElement;
e.cancelBubble = true;
e.returnValue = false;
}
else
{
target = e.target
}
//catch the occasional error in IE
if (target.cwcButton == null)
{
return;
}
if (!target.cwcButton.IsDisabled())
{
if( !target.cwcButton.bActive || target.cwcButton.type == CWCBUTTONTYPE_CLICK)
{
target.cwcButton.SetState( CWCBUTTONSTATE_NORMAL );
}
}
target.cwcButton.bMouseDown = false;
//remove event handlers if necessary
if (!CWCIsIE)
{
document.onmouseup = target.cwcButton.oldMouseUp;
target.cwcButton.oldMouseUp = null;
document.onmousedown = target.cwcButton.oldMouseDown;
target.cwcButton.oldMouseDown = null;
}
else
{
target.cwcButton.oImage.onmousedown = null;
target.cwcButton.oImage.onmouseup = null;
}
document.onmousemove = target.cwcButton.oldMouseMove;
target.cwcButton.oldMouseMove = null;
return false;
}
/*
* handle the onclick event on the image, note that in NN4 we are
* faking this by calling this function from the onmouseup handler.
*/
function CWCButton_OnMouseClick( e )
{
var target;
if (CWCIsIE)
{
e = event;
target = event.srcElement;
e.cancelBubble = true;
e.returnValue = false;
}
else
{
target = e.target
}
if (target.cwcButton.onClick != null)
{
target.cwcButton.onClick( target.cwcButton, target.cwcButton.xValues );
}
return false;
}
/*
* handle mouse down events by setting the image state to the appropriate
* state depending on the type of the button.
*/
function CWCButton_OnMouseDown( e )
{
var target;
if (CWCIsIE)
{
e = event;
target = event.srcElement;
e.cancelBubble = true;
e.returnValue = false;
}
else
{
target = e.target
}
//catch the occasional error in IE
if (target.cwcButton == null)
{
return;
}
if (!target.cwcButton.IsDisabled())
{
target.cwcButton.bMouseDown = true;
target.cwcButton.SetState( CWCBUTTONSTATE_SELECTED );
}
return false;
}
/*
* handle mouse up events by setting the image state to the appropriate
* state depending on the type of the button. Note that if this is a
* Netscape Navigator 4 browser, then we are faking an onclick event
* because it doesn't support onclick on images.
*/
function CWCButton_OnMouseUp( e )
{
var target;
var bNeedClick = false;
if (CWCIsIE)
{
e = event;
target = event.srcElement;
e.cancelBubble = true;
e.returnValue = false;
}
else
{
target = e.target
if (e.cancelable)
e.cancelBubble = true;
}
//catch the occasional error in IE
if (target.cwcButton == null)
{
return;
}
if (!target.cwcButton.bMouseDown)
{
return;
}
target.cwcButton.bMouseDown = false;
if (!target.cwcButton.IsDisabled())
{
if (target.cwcButton.IsSelected() ) //&& CWCIsNav4)
{
bNeedClick = true;
}
if (target.cwcButton.type == CWCBUTTONTYPE_CLICK)
{
target.cwcButton.SetState( CWCBUTTONSTATE_SELECTED );
}
if (target.cwcButton.type == CWCBUTTONTYPE_RADIO)
{
target.cwcButton.SetState( CWCBUTTONSTATE_SELECTED );
target.cwcButton.bActive = true;
if (target.cwcButton.oGroup != null)
{
target.cwcButton.oGroup.ActivateButton( target.cwcButton );
}
}
if (target.cwcButton.type == CWCBUTTONTYPE_TOGGLE)
{
if (target.cwcButton.bActive)
{
target.cwcButton.SetState( CWCBUTTONSTATE_NORMAL );
target.cwcButton.bActive = false;
}
else
{
target.cwcButton.SetState( CWCBUTTONSTATE_SELECTED );
target.cwcButton.bActive = true;
}
}
}
if (bNeedClick)
{
CWCButton_OnMouseClick( e );
}
return false;
}
/**
*
*/
function CWCButton_OnDragStart( e )
{
//alert( "ondragstart" );
var target;
if (CWCIsIE)
{
e = event;
target = event.srcElement;
e.cancelBubble = true;
e.returnValue = false;
}
else
{
target = e.target;
if (e.cancelable)
e.cancelBubble = true;
}
}