/** * @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; } }