1039 lines
28 KiB
Plaintext
1039 lines
28 KiB
Plaintext
<PUBLIC:HTC URN="shellctls">
|
|
|
|
//------------------------------------------------------------------------
|
|
// Public methods
|
|
//------------------------------------------------------------------------
|
|
|
|
<METHOD name="SetExecButton" />
|
|
<METHOD name="ShowButton" />
|
|
<METHOD name="focus" />
|
|
<METHOD name="blur" />
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
// Events
|
|
//------------------------------------------------------------------------
|
|
|
|
// The onSelectItem event has the following attributes:
|
|
// srcID - the ID of the button passed in from the span
|
|
//
|
|
<EVENT id=onSelectItem name="onSelectItem" />
|
|
|
|
|
|
// The onExecItem event has the following attributes:
|
|
// srcID - the ID of the button passed in from the span
|
|
//
|
|
<EVENT id=onExecItem name="onExecItem" />
|
|
|
|
|
|
<EVENT id=onComplete name="onComplete" />
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
// Attach to element events
|
|
//------------------------------------------------------------------------
|
|
|
|
<ATTACH event="oncontentready" handler=_OnContentReady />
|
|
<ATTACH event="ondragstart" handler=_CancelDragStart />
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
// The code...
|
|
//------------------------------------------------------------------------
|
|
|
|
<SCRIPT language="javascript">
|
|
|
|
var _bLoading = true; // true if the behavior is still loading
|
|
|
|
var _iBtnPressed = -1; // currently pressed (selected) button
|
|
var _iBtnHot = -1; // current hot button (button the mouse is over)
|
|
var _iBtnTabIndex = -1; // button to receive the focus
|
|
var _iBtnCapture = -1; // current button that has the capture
|
|
|
|
var _cButtons = 0; // count of buttons in places bar
|
|
var _rgbtn = new Array(); // array of button objects
|
|
var _rgdivButtons = new Array(); // array of div references that represent buttons
|
|
var _styleinfo = null; // style sheet with rules for this bar
|
|
var _mpStyle = new Object(); // a hash of style sheet rules that apply to this bar
|
|
|
|
var _bHasFocus = false; // true if the element has focus
|
|
var _bInternalFocusChange = false; // true if the focus is changed by an internal function
|
|
|
|
// Button states
|
|
var BS_PRESSED = 0x01;
|
|
var BS_HOT = 0x02;
|
|
|
|
|
|
var c_szStyle_ButtonNormal =
|
|
' style="' +
|
|
'position:relative; ' +
|
|
'padding:2px; ' +
|
|
'border-style:solid; ' +
|
|
'border-width:1px; ' +
|
|
'border-top-color:threedshadow; ' +
|
|
'border-left-color:threedshadow; ' +
|
|
'border-right-color:threedshadow; ' +
|
|
'border-bottom-color:threedshadow; ' +
|
|
'"';
|
|
|
|
var c_szStyle_ButtonText =
|
|
' style="' +
|
|
'position:relative; ' +
|
|
'color:white; ' +
|
|
'cursor:default; ' +
|
|
'"';
|
|
|
|
var c_szStyle_Background =
|
|
' style="' +
|
|
'position:relative; ' +
|
|
'width:87px; ' +
|
|
'height:100%; ' +
|
|
'padding:2px; ' +
|
|
'background-color:threedshadow; ' +
|
|
'"';
|
|
|
|
element.attachEvent("onerror", _OnError);
|
|
|
|
_GetPropertyDefaults();
|
|
|
|
|
|
// **********************************************************************
|
|
// PROPERTY GET/SET FUNCTIONS
|
|
// **********************************************************************
|
|
|
|
|
|
// Property: button = iBtn
|
|
//
|
|
// Sets the pushed button to the i'th button in the bar.
|
|
//
|
|
function get_button() { return _iBtnPressed; }
|
|
function put_button(iBtn)
|
|
{
|
|
if (_bLoading)
|
|
return;
|
|
|
|
_PushButton(parseInt(iBtn), 0);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// **********************************************************************
|
|
// EVENT HANDLERS
|
|
// **********************************************************************
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
Purpose: When the behavior is completely loaded, set the loading flag to false.
|
|
To improve load time, we don't want the put methods on the properties
|
|
to be called. We also need to keep events from getting fired while
|
|
the behavior is loading.
|
|
Also build the HTML for the button elements.
|
|
*/
|
|
|
|
|
|
function _OnContentReady()
|
|
{
|
|
_bLoading = false;
|
|
_ScanSpecialElements();
|
|
_CreateHTML();
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
Purpose: Fired when the document is loaded. We must refrain from sending
|
|
events to the page until it is loaded.
|
|
*/
|
|
function _OnDocumentLoad()
|
|
{
|
|
_Initialize();
|
|
}
|
|
|
|
|
|
|
|
// **********************************************************************
|
|
// HELPER FUNCTIONS
|
|
// **********************************************************************
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
Purpose: Called when the behavior is instantiated. Sets up the internal
|
|
property values.
|
|
*/
|
|
function _GetPropertyDefaults()
|
|
{
|
|
if (element.currentButton)
|
|
_iBtnPressed = parseInt(element.currentButton);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
Purpose: Return a canonical ID name
|
|
*/
|
|
function _IDName(szID, idx)
|
|
{
|
|
return szID + idx + '_' + uniqueID;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
Purpose: Take the span and store it in the button store at iStore
|
|
*/
|
|
function _StoreButton(elem, ibtn)
|
|
{
|
|
var btn = new Object;
|
|
var szBtnIndex = ' _ibtn=' + ibtn;
|
|
var L_PlacesGraphic_Text = 'Graphic';
|
|
|
|
btn.id = elem.id;
|
|
btn._idBtn = _IDName('idBtn', ibtn);
|
|
btn._ibtn = ibtn;
|
|
btn._idBR = _IDName('idBtnBR', ibtn);
|
|
btn._bHidden = false;
|
|
|
|
if ("undefined" != typeof elem.execItem)
|
|
btn._bExecButton = true;
|
|
else
|
|
btn._bExecButton = false;
|
|
|
|
// If you change this HTML, be sure to update _GetCaptionElem
|
|
btn.innerHTML =
|
|
'<DIV id=' + btn._idBtn + c_szStyle_ButtonNormal + szBtnIndex + ' _btnState=0> ' +
|
|
' <CENTER id=' + _IDName('idCtr', ibtn) + szBtnIndex + '> ' +
|
|
' <IMG id=' + _IDName('idImg', ibtn) + ' style="position:relative" src=' + elem.img + szBtnIndex + ' title="" alt="' + L_PlacesGraphic_Text + '" >' +
|
|
' <BR>' +
|
|
/* use the private nofocusrect so we don't see the focus rect */
|
|
' <SPAN id=' + _IDName('idSpan', ibtn) + c_szStyle_ButtonText + szBtnIndex + ' nofocusrect>' +
|
|
elem.innerHTML +
|
|
' </SPAN>' +
|
|
' </CENTER> ' +
|
|
'</DIV>';
|
|
|
|
// Save this button
|
|
_rgbtn[ibtn] = btn;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
Purpose: Walk thru the element's html and find the specially-tagged spans.
|
|
Each span in this element is considered a separate button.
|
|
|
|
The span may have the following special attributes:
|
|
|
|
img - The image to show for the particular button
|
|
execItem - This button will be skipped when ctrl-tabbing
|
|
|
|
The contents of the span is the button's display text.
|
|
|
|
*/
|
|
function _ScanSpecialElements()
|
|
{
|
|
var i;
|
|
|
|
// Scan the element for spans
|
|
|
|
var rgspan = element.all.tags("SPAN");
|
|
var cspan = rgspan.length;
|
|
|
|
for (i = 0; i < cspan; i++)
|
|
{
|
|
var span = rgspan[i];
|
|
|
|
_StoreButton(span, _cButtons++);
|
|
|
|
span.innerHTML = "";
|
|
}
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
Purpose: Adds the HTML code to the main document to display the places bar.
|
|
|
|
*/
|
|
function _CreateHTML()
|
|
{
|
|
var i;
|
|
var szButtons = '';
|
|
|
|
// Hide the control while we build it
|
|
element.style.visibility = 'hidden';
|
|
|
|
// Construct the html
|
|
|
|
for (i = 0; i < _cButtons; i++)
|
|
{
|
|
szButtons = szButtons + _rgbtn[i].innerHTML + '<BR id=' + _rgbtn[i]._idBR + '>';
|
|
}
|
|
|
|
element.innerHTML =
|
|
'<DIV ' + c_szStyle_Background + ' _ibtn=-1> ' +
|
|
szButtons +
|
|
'</DIV>';
|
|
|
|
// Attach events to the button divs
|
|
var rgdivs = element.all.tags("DIV");
|
|
|
|
for (i = 0; i < _cButtons; i++)
|
|
{
|
|
var elem = rgdivs[_rgbtn[i]._idBtn];
|
|
|
|
_rgdivButtons[i] = elem;
|
|
|
|
elem.attachEvent('onmouseover', _OnMouseOver);
|
|
elem.attachEvent('onmouseout', _OnMouseOut);
|
|
elem.attachEvent('onmousedown', _OnMouseDown);
|
|
elem.attachEvent('onmouseup', _OnMouseUp);
|
|
|
|
var spanCaption = _GetCaptionElem(i);
|
|
|
|
spanCaption.attachEvent('onblur', _OnBlurDiv);
|
|
spanCaption.attachEvent('onfocus', _OnFocusDiv);
|
|
spanCaption.attachEvent('onkeydown', _OnKeyDownDiv);
|
|
|
|
// Cancel the image's default dragstart behavior
|
|
elem.all(_IDName('idCtr', i)).attachEvent('ondragstart', _CancelDragStart);
|
|
}
|
|
|
|
// Now wait until the document is loaded before pushing the
|
|
// initial button
|
|
window.attachEvent("onload", _OnDocumentLoad);
|
|
|
|
// Say we're finished in case the page cares
|
|
_FireComplete();
|
|
|
|
// Now show the control
|
|
element.style.visibility = 'visible';
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
Purpose: Final initialization of the bar
|
|
*/
|
|
function _Initialize()
|
|
{
|
|
if (-1 != _iBtnPressed)
|
|
{
|
|
var ibtn = _iBtnPressed;
|
|
|
|
// Avoid wasting time unpressing a button that isn't pressed yet
|
|
_iBtnPressed = -1;
|
|
_PushButton(ibtn, 0);
|
|
}
|
|
|
|
window.document.attachEvent("onkeydown", _OnKeyDownDocument);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
Purpose: Returns the button index given the elem. Returns -1 if the given
|
|
elem is not within a button.
|
|
|
|
All of the button's elements that were created by this behavior have
|
|
an _ibtn property that points to the array of button divs. If there
|
|
is no _ibtn property, walk up until we find one. If we don't find
|
|
one, then the elem is not within this behavior's region.
|
|
*/
|
|
function _BtnFromElement(elem)
|
|
{
|
|
var ibtn = -1;
|
|
|
|
if (elem && null == elem._ibtn)
|
|
{
|
|
// Walk up the tree to find the next element with the internal
|
|
// '_ibtn'
|
|
while (elem)
|
|
{
|
|
if (elem._ibtn)
|
|
break;
|
|
elem = elem.parentElement;
|
|
}
|
|
}
|
|
|
|
if (elem)
|
|
ibtn = elem._ibtn;
|
|
|
|
return ibtn;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
Purpose: Returns the button index given the id. Returns -1 if the given id
|
|
is not in the array of buttons.
|
|
*/
|
|
function _BtnFromID(idBtn)
|
|
{
|
|
var ibtn;
|
|
|
|
for (ibtn = 0; ibtn < _rgbtn.length; ibtn++)
|
|
{
|
|
if (idBtn == _rgbtn[ibtn].id)
|
|
return ibtn;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
Purpose: Draws the frame around the button div according to the given state
|
|
*/
|
|
function _DrawButtonFrame(elem, szState)
|
|
{
|
|
switch (szState)
|
|
{
|
|
case 'normal':
|
|
elem.style.borderTopColor = 'threedshadow';
|
|
elem.style.borderLeftColor = 'threedshadow';
|
|
elem.style.borderRightColor = 'threedshadow';
|
|
elem.style.borderBottomColor = 'threedshadow';
|
|
break;
|
|
|
|
case 'hotitem':
|
|
elem.style.borderTopColor = 'threedhighlight';
|
|
elem.style.borderLeftColor = 'threedhighlight';
|
|
elem.style.borderRightColor = 'threeddarkshadow';
|
|
elem.style.borderBottomColor = 'threeddarkshadow';
|
|
break;
|
|
|
|
case 'pushed':
|
|
elem.style.borderTopColor = 'threeddarkshadow';
|
|
elem.style.borderLeftColor = 'threeddarkshadow';
|
|
elem.style.borderRightColor = 'threedhighlight';
|
|
elem.style.borderBottomColor = 'threedhighlight';
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
Purpose: Draws the button. Assumes ibtn is valid.
|
|
*/
|
|
function _DrawButton(ibtn, bDown)
|
|
{
|
|
var div = _rgdivButtons[ibtn];
|
|
var bDownCur = (div._btnState & BS_PRESSED) ? true : false;
|
|
var elemImg = div.all(_IDName('idImg', div._ibtn));
|
|
var elemText = div.all(_IDName('idSpan', div._ibtn));
|
|
|
|
if (bDownCur == bDown)
|
|
return; // no change
|
|
|
|
if (bDown)
|
|
{
|
|
_DrawButtonFrame(div, 'pushed');
|
|
|
|
// Offset the button contents
|
|
elemImg.style.pixelLeft = elemImg.style.pixelLeft + 1;
|
|
elemImg.style.pixelTop = elemImg.style.pixelTop + 1;
|
|
|
|
elemText.style.pixelLeft = elemText.style.pixelLeft + 1;
|
|
elemText.style.pixelTop = elemText.style.pixelTop + 1;
|
|
|
|
div._btnState |= BS_PRESSED;
|
|
}
|
|
else
|
|
{
|
|
if (ibtn == _iBtnHot)
|
|
_DrawButtonFrame(div, 'hotitem');
|
|
else
|
|
_DrawButtonFrame(div, 'normal');
|
|
|
|
// De-Offset the button contents
|
|
elemImg.style.pixelLeft = elemImg.style.pixelLeft - 1;
|
|
elemImg.style.pixelTop = elemImg.style.pixelTop - 1;
|
|
|
|
elemText.style.pixelLeft = elemText.style.pixelLeft - 1;
|
|
elemText.style.pixelTop = elemText.style.pixelTop - 1;
|
|
|
|
div._btnState &= ~ BS_PRESSED;
|
|
}
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
Purpose: Returns the element that is the button caption.
|
|
*/
|
|
function _GetCaptionElem(ibtn)
|
|
{
|
|
var spanCaption = null;
|
|
var div = _rgdivButtons[ibtn];
|
|
|
|
if (div)
|
|
spanCaption = div.children[0].children[2];
|
|
|
|
return spanCaption;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
Purpose: Sets the tabIndex property on the given button, and removes it
|
|
from the button the had the property prior to this call. (This
|
|
control only allows one button to have the tabIndex at any given
|
|
time.)
|
|
|
|
The tabIndex is set so MSAA can receive notifications of 'focus'
|
|
change.
|
|
*/
|
|
function _SetTabIndex(ibtn, bSetFocus)
|
|
{
|
|
if (ibtn == _iBtnTabIndex)
|
|
return;
|
|
|
|
var elem = _GetCaptionElem(_iBtnTabIndex);
|
|
if (elem)
|
|
elem.tabIndex = -1; // Remove this DIV from the taborder list
|
|
|
|
elem = _GetCaptionElem(ibtn);
|
|
if (elem)
|
|
{
|
|
elem.tabIndex = 0; // Make this DIV be in the taborder list
|
|
|
|
if (bSetFocus)
|
|
{
|
|
// Set the focus so the MSAA event is fired
|
|
_bInternalFocusChange = true;
|
|
elem.focus();
|
|
}
|
|
}
|
|
|
|
_iBtnTabIndex = ibtn;
|
|
}
|
|
|
|
|
|
// Flags for _PushButton
|
|
var PBF_SETFOCUS = 0x01;
|
|
var PBF_MOUSE = 0x02;
|
|
|
|
/*-------------------------------------------------------------------------
|
|
Purpose: Pushes the given button. Any other button loses its push state.
|
|
*/
|
|
function _PushButton(ibtn, dwFlags)
|
|
{
|
|
var btn = _rgbtn[ibtn];
|
|
|
|
// Is this button hidden?
|
|
if (btn && btn._bHidden)
|
|
{
|
|
// Yes; skip it
|
|
return;
|
|
}
|
|
|
|
// Is this button an ExecButton?
|
|
if (btn && btn._bExecButton)
|
|
{
|
|
// Yes; execute it and leave all other button states as they are
|
|
_DrawButton(ibtn, false);
|
|
_FireExecItem(btn);
|
|
}
|
|
else
|
|
{
|
|
// No; push the button down and toggle any other button up
|
|
if ((dwFlags & PBF_MOUSE) && ibtn == _iBtnPressed)
|
|
return;
|
|
|
|
// Is there a button already pressed?
|
|
if (-1 != _iBtnPressed && ibtn != _iBtnPressed)
|
|
{
|
|
// Yes; reset it
|
|
_DrawButton(_iBtnPressed, false);
|
|
}
|
|
|
|
// Make this button the currently pressed button.
|
|
_iBtnPressed = ibtn;
|
|
|
|
// This button now gets the focus
|
|
_SetTabIndex(ibtn, dwFlags & PBF_SETFOCUS);
|
|
|
|
if (0 <= _iBtnPressed && _iBtnPressed < _cButtons)
|
|
{
|
|
_DrawButton(_iBtnPressed, true);
|
|
|
|
_FireSelectItem(btn);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// Flags for _SetHotItem
|
|
var SHIF_SETTABINDEX = 0x01;
|
|
var SHIF_RESETTABSTOP = 0x02;
|
|
var SHIF_MOUSE = 0x04;
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
Purpose: Sets the hot button to track. Clears the hot button if ibtn == -1.
|
|
*/
|
|
function _SetHotItem(ibtn, dwFlags)
|
|
{
|
|
var div;
|
|
|
|
if (ibtn == _iBtnHot)
|
|
return;
|
|
|
|
// Reset the current hot button first
|
|
if (-1 != _iBtnHot && _iBtnHot != ibtn)
|
|
{
|
|
div = _rgdivButtons[_iBtnHot];
|
|
|
|
if (_iBtnHot == _iBtnPressed)
|
|
_DrawButtonFrame(div, 'pushed');
|
|
else
|
|
_DrawButtonFrame(div, 'normal');
|
|
}
|
|
|
|
// Set the hot button
|
|
if (-1 != ibtn)
|
|
{
|
|
div = _rgdivButtons[ibtn];
|
|
|
|
// The currently pressed button never hottracks when the mouse is hovering
|
|
// over it.
|
|
//
|
|
// However, we do allow the keyboard to navigate to the pushed button. We
|
|
// do this so the accessibility aides have the ability to survey all the
|
|
// available options...including the currently pushed button.
|
|
|
|
if ( !(dwFlags & SHIF_MOUSE) || ibtn != _iBtnPressed)
|
|
_DrawButtonFrame(div, 'hotitem');
|
|
}
|
|
|
|
_iBtnHot = ibtn;
|
|
|
|
if (dwFlags & SHIF_SETTABINDEX)
|
|
{
|
|
// Reset the tabstop back to the pressed button?
|
|
if (dwFlags & SHIF_RESETTABSTOP)
|
|
{
|
|
// Yes
|
|
_SetTabIndex(_iBtnPressed, false);
|
|
}
|
|
else
|
|
{
|
|
// No; set it to the current button
|
|
_SetTabIndex(ibtn, true);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
Purpose: Fires 'onSelectItem' to the document
|
|
*/
|
|
function _FireSelectItem(btn)
|
|
{
|
|
var evt = createEventObject();
|
|
evt.srcID = btn.id;
|
|
onSelectItem.fire(evt);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
Purpose: Fires 'onExecItem' to the document
|
|
*/
|
|
function _FireExecItem(btn)
|
|
{
|
|
var evt = createEventObject();
|
|
evt.srcID = btn.id;
|
|
onExecItem.fire(evt);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
Purpose: Fires 'onComplete' to the document
|
|
*/
|
|
function _FireComplete()
|
|
{
|
|
var evt = createEventObject();
|
|
onComplete.fire(evt);
|
|
}
|
|
|
|
|
|
|
|
var LMOUSE_BUTTON = 1
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
Purpose: Handles mousedown events. Depress the button.
|
|
*/
|
|
function _OnMouseDown()
|
|
{
|
|
var ibtn = _BtnFromElement(window.event.srcElement);
|
|
var div;
|
|
|
|
// Only concerned with the left mouse button
|
|
if (LMOUSE_BUTTON != window.event.button)
|
|
return;
|
|
|
|
_DrawButton(ibtn, true);
|
|
|
|
// Take the capture so we can correctly pop the button up if the
|
|
// mouse moves out of the places bar.
|
|
_iBtnCapture = ibtn;
|
|
|
|
div = _rgdivButtons[ibtn];
|
|
div.setCapture(false);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
Purpose: Handles mouseup events.
|
|
*/
|
|
function _OnMouseUp()
|
|
{
|
|
var ibtn = _BtnFromElement(window.event.srcElement);
|
|
|
|
// Only concerned with the left mouse button
|
|
if (LMOUSE_BUTTON != window.event.button)
|
|
return;
|
|
|
|
// Double-click will result in a "mouse-down, mouse-up, mouse-up" sequence.
|
|
// So _iBtnCapture can be -1.
|
|
|
|
if (-1 != _iBtnCapture)
|
|
{
|
|
var div = _rgdivButtons[_iBtnCapture];
|
|
div.releaseCapture();
|
|
|
|
if (_iBtnCapture != ibtn)
|
|
_DrawButton(_iBtnCapture, (_iBtnPressed == _iBtnCapture));
|
|
|
|
if (-1 != ibtn && ibtn == _iBtnCapture)
|
|
_PushButton(ibtn, PBF_SETFOCUS | PBF_MOUSE);
|
|
|
|
_iBtnCapture = -1;
|
|
}
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
Purpose: Handle the onMouseOver event.
|
|
*/
|
|
function _OnMouseOver()
|
|
{
|
|
var ibtnTo = _BtnFromElement(window.event.toElement);
|
|
var ibtnFrom = _BtnFromElement(window.event.fromElement);
|
|
|
|
// if (ibtnTo == ibtnFrom)
|
|
// return;
|
|
|
|
// Is a button pressed down right now?
|
|
if (-1 != _iBtnCapture)
|
|
{
|
|
// Yes; only pay attention to when we reenter that button
|
|
if (ibtnTo == _iBtnCapture && ibtnFrom != _iBtnCapture)
|
|
{
|
|
_DrawButton(_iBtnCapture, true);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// No; standard behavior
|
|
_SetHotItem(ibtnTo, SHIF_MOUSE);
|
|
}
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
Purpose: Handle the onMouseOut event.
|
|
*/
|
|
function _OnMouseOut()
|
|
{
|
|
var event = window.event;
|
|
var ibtnTo = _BtnFromElement(event.toElement);
|
|
var ibtnFrom = _BtnFromElement(event.fromElement);
|
|
|
|
// Is the mouse moving to an outside element?
|
|
if (ibtnTo != ibtnFrom)
|
|
{
|
|
// Yes
|
|
_SetHotItem(-1, SHIF_MOUSE);
|
|
|
|
if (ibtnFrom == _iBtnCapture && _iBtnCapture != _iBtnPressed)
|
|
_DrawButton(_iBtnCapture, false);
|
|
}
|
|
}
|
|
|
|
|
|
var CYCLE_PUSHED = 1;
|
|
var CYCLE_HOT = 2;
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
Purpose: Cycles to the next available button. This skips the currently
|
|
pressed button, and cycles around on boundary conditions. Returns
|
|
the next button.
|
|
*/
|
|
function _CycleButton(bDown, ibtnStart, cycle)
|
|
{
|
|
var ibtn = ibtnStart;
|
|
var n = bDown ? 1 : -1;
|
|
var btn;
|
|
var cbtns = 0;
|
|
|
|
while (true)
|
|
{
|
|
if (++cbtns > _cButtons)
|
|
break; // We've completed a full cycle
|
|
|
|
if (bDown)
|
|
ibtn = (ibtn + 1) % _cButtons;
|
|
else
|
|
ibtn = ((ibtn - 1) + _cButtons) % _cButtons;
|
|
|
|
btn = _rgbtn[ibtn];
|
|
|
|
if (CYCLE_PUSHED == cycle)
|
|
{
|
|
if (ibtn == _iBtnPressed || btn._bExecButton || btn._bHidden)
|
|
continue; // Try again
|
|
else
|
|
break;
|
|
}
|
|
else // CYCLE_HOT == cycle
|
|
{
|
|
if (btn._bHidden)
|
|
continue; // Try again
|
|
else
|
|
break;
|
|
}
|
|
}
|
|
return ibtn;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
Purpose: Cycles to the next available button.
|
|
|
|
In earlier designs, this used to skip the currently pressed button.
|
|
But accessibility aides require the ability to cycle thru all the
|
|
buttons to allow a blind person to survey all the options. Makes sense.
|
|
|
|
This function cycles around boundary conditions.
|
|
*/
|
|
function _CycleHotItem(bDown)
|
|
{
|
|
_SetHotItem(_CycleButton(bDown, _iBtnHot, CYCLE_HOT), SHIF_SETTABINDEX);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
Purpose: Cycles to the next button and pushes it.
|
|
*/
|
|
function _CyclePushedButton(bDown)
|
|
{
|
|
_PushButton(_CycleButton(bDown, _iBtnPressed, CYCLE_PUSHED), 0);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
Purpose: Tells the places bar to skip this button when ctrl-tabbing.
|
|
*/
|
|
function SetExecButton(idBtn, bVal)
|
|
{
|
|
var ibtn = _BtnFromID(idBtn);
|
|
|
|
if (-1 != ibtn)
|
|
{
|
|
_rgbtn[ibtn]._bExecButton = bVal;
|
|
}
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
Purpose: Tell the places bar to remove a button
|
|
*/
|
|
function ShowButton(idBtn, bShow)
|
|
{
|
|
var ibtn = _BtnFromID(idBtn);
|
|
|
|
if (-1 != ibtn)
|
|
{
|
|
var btn = _rgbtn[ibtn];
|
|
if (btn)
|
|
{
|
|
var idBtnUnique = btn._idBtn;
|
|
var elemBtn = element.all[idBtnUnique];
|
|
|
|
if (bShow)
|
|
{
|
|
elemBtn.style.display = 'block';
|
|
element.all[btn._idBR].style.display = 'block';
|
|
}
|
|
else
|
|
{
|
|
elemBtn.style.display = 'none';
|
|
element.all[btn._idBR].style.display = 'none';
|
|
}
|
|
|
|
btn._bHidden = !bShow;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
Purpose: Overridden method so we handle focus properly
|
|
*/
|
|
function focus()
|
|
{
|
|
var div = _rgdivButtons[_iBtnTabIndex];
|
|
|
|
if (div)
|
|
div.focus();
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
Purpose: Overridden method so we handle blur properly
|
|
*/
|
|
function blur()
|
|
{
|
|
var div = _rgdivButtons[_iBtnTabIndex];
|
|
|
|
if (div)
|
|
div.blur();
|
|
}
|
|
|
|
|
|
// Key codes
|
|
var KC_LEFT = 37;
|
|
var KC_UP = 38;
|
|
var KC_RIGHT = 39;
|
|
var KC_DOWN = 40;
|
|
var KC_SPACE = 32;
|
|
var KC_RETURN = 13;
|
|
var KC_TAB = 9;
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
Purpose: Handle the onKeyDown event of the document. We have this to catch
|
|
the ctrl-tab events when the places bar doesn't have the focus.
|
|
*/
|
|
function _OnKeyDownDocument()
|
|
{
|
|
var evt = window.event;
|
|
|
|
// Control-tab?
|
|
if (KC_TAB == evt.keyCode && evt.ctrlKey)
|
|
{
|
|
// Yes
|
|
var bDir = evt.shiftKey ? false : true;
|
|
|
|
_CyclePushedButton(bDir);
|
|
|
|
// Cancel event so no one else gets it
|
|
evt.returnValue = false;
|
|
}
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
Purpose: Handle the onKeyDown event
|
|
*/
|
|
function _OnKeyDownDiv()
|
|
{
|
|
var keyCode = window.event.keyCode;
|
|
|
|
// Pay attention to up and down arrows
|
|
if (KC_UP == keyCode || KC_LEFT == keyCode)
|
|
{
|
|
_CycleHotItem(false);
|
|
|
|
// Cancel event so div doesn't scroll independently
|
|
window.event.returnValue = false;
|
|
}
|
|
else if (KC_DOWN == keyCode || KC_RIGHT == keyCode)
|
|
{
|
|
_CycleHotItem(true);
|
|
|
|
// Cancel event so div doesn't scroll independently
|
|
window.event.returnValue = false;
|
|
}
|
|
else if (KC_SPACE == keyCode || KC_RETURN == keyCode)
|
|
{
|
|
_PushButton(_iBtnHot, PBF_SETFOCUS);
|
|
}
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
Purpose: Handle the onBlur event. Change the selection color so it is clear
|
|
the list no longer has the focus.
|
|
*/
|
|
function _OnBlurDiv()
|
|
{
|
|
// Don't bother if this was caused by the control itself, or it doesn't
|
|
// have the focus.
|
|
if (false == _bInternalFocusChange && true == _bHasFocus)
|
|
{
|
|
_bHasFocus = false;
|
|
|
|
_SetHotItem(-1, SHIF_SETTABINDEX | SHIF_RESETTABSTOP);
|
|
}
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
Purpose: Handle the onFocus event. Change the selection color.
|
|
|
|
We use an invisible anchor (placed before the div) so we can
|
|
receive focus events. When this anchor receives focus, we treat
|
|
that as if the bar is getting the focus. This handles the
|
|
case when the user tabs around the page.
|
|
|
|
The second case is if the user uses the mouse to select one
|
|
of the items. In this case, the anchor will not receive focus,
|
|
but we have to pretend as if it did. This is why _bHasFocus keeps
|
|
track of this.
|
|
*/
|
|
function _OnFocusDiv()
|
|
{
|
|
// Don't bother doing this if the document isn't ready, or if the
|
|
// control already has the focus, or if the focus change is caused
|
|
// by the control itself.
|
|
if (false == _bInternalFocusChange && false == _bHasFocus &&
|
|
"complete" == window.document.readyState)
|
|
{
|
|
_bHasFocus = true;
|
|
|
|
_CycleHotItem(true);
|
|
}
|
|
|
|
_bInternalFocusChange = false; // Reset
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
Purpose: Handle the onerror event
|
|
*/
|
|
function _OnError(szMsg, szUrl, iLine)
|
|
{
|
|
// Prevent scripting errors from displaying ugly messages
|
|
alert("An unexpected error occurred.\n\n" + szMsg + "\n" + szUrl + "\nLine: " + iLine);
|
|
return true; // Suppress IE error messaging
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
Purpose: Cancel any drag operation
|
|
*/
|
|
function _CancelDragStart()
|
|
{
|
|
window.event.returnValue = false;
|
|
}
|
|
|
|
|
|
|
|
</SCRIPT>
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
// Properties
|
|
//------------------------------------------------------------------------
|
|
|
|
<PROPERTY name="currentButton" get=get_button put=put_button />
|
|
|
|
</PUBLIC:HTC>
|