Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1038 lines
28 KiB

  1. <PUBLIC:HTC URN="shellctls">
  2. //------------------------------------------------------------------------
  3. // Public methods
  4. //------------------------------------------------------------------------
  5. <METHOD name="SetExecButton" />
  6. <METHOD name="ShowButton" />
  7. <METHOD name="focus" />
  8. <METHOD name="blur" />
  9. //------------------------------------------------------------------------
  10. // Events
  11. //------------------------------------------------------------------------
  12. // The onSelectItem event has the following attributes:
  13. // srcID - the ID of the button passed in from the span
  14. //
  15. <EVENT id=onSelectItem name="onSelectItem" />
  16. // The onExecItem event has the following attributes:
  17. // srcID - the ID of the button passed in from the span
  18. //
  19. <EVENT id=onExecItem name="onExecItem" />
  20. <EVENT id=onComplete name="onComplete" />
  21. //------------------------------------------------------------------------
  22. // Attach to element events
  23. //------------------------------------------------------------------------
  24. <ATTACH event="oncontentready" handler=_OnContentReady />
  25. <ATTACH event="ondragstart" handler=_CancelDragStart />
  26. //------------------------------------------------------------------------
  27. // The code...
  28. //------------------------------------------------------------------------
  29. <SCRIPT language="javascript">
  30. var _bLoading = true; // true if the behavior is still loading
  31. var _iBtnPressed = -1; // currently pressed (selected) button
  32. var _iBtnHot = -1; // current hot button (button the mouse is over)
  33. var _iBtnTabIndex = -1; // button to receive the focus
  34. var _iBtnCapture = -1; // current button that has the capture
  35. var _cButtons = 0; // count of buttons in places bar
  36. var _rgbtn = new Array(); // array of button objects
  37. var _rgdivButtons = new Array(); // array of div references that represent buttons
  38. var _styleinfo = null; // style sheet with rules for this bar
  39. var _mpStyle = new Object(); // a hash of style sheet rules that apply to this bar
  40. var _bHasFocus = false; // true if the element has focus
  41. var _bInternalFocusChange = false; // true if the focus is changed by an internal function
  42. // Button states
  43. var BS_PRESSED = 0x01;
  44. var BS_HOT = 0x02;
  45. var c_szStyle_ButtonNormal =
  46. ' style="' +
  47. 'position:relative; ' +
  48. 'padding:2px; ' +
  49. 'border-style:solid; ' +
  50. 'border-width:1px; ' +
  51. 'border-top-color:threedshadow; ' +
  52. 'border-left-color:threedshadow; ' +
  53. 'border-right-color:threedshadow; ' +
  54. 'border-bottom-color:threedshadow; ' +
  55. '"';
  56. var c_szStyle_ButtonText =
  57. ' style="' +
  58. 'position:relative; ' +
  59. 'color:white; ' +
  60. 'cursor:default; ' +
  61. '"';
  62. var c_szStyle_Background =
  63. ' style="' +
  64. 'position:relative; ' +
  65. 'width:87px; ' +
  66. 'height:100%; ' +
  67. 'padding:2px; ' +
  68. 'background-color:threedshadow; ' +
  69. '"';
  70. element.attachEvent("onerror", _OnError);
  71. _GetPropertyDefaults();
  72. // **********************************************************************
  73. // PROPERTY GET/SET FUNCTIONS
  74. // **********************************************************************
  75. // Property: button = iBtn
  76. //
  77. // Sets the pushed button to the i'th button in the bar.
  78. //
  79. function get_button() { return _iBtnPressed; }
  80. function put_button(iBtn)
  81. {
  82. if (_bLoading)
  83. return;
  84. _PushButton(parseInt(iBtn), 0);
  85. }
  86. // **********************************************************************
  87. // EVENT HANDLERS
  88. // **********************************************************************
  89. /*-------------------------------------------------------------------------
  90. Purpose: When the behavior is completely loaded, set the loading flag to false.
  91. To improve load time, we don't want the put methods on the properties
  92. to be called. We also need to keep events from getting fired while
  93. the behavior is loading.
  94. Also build the HTML for the button elements.
  95. */
  96. function _OnContentReady()
  97. {
  98. _bLoading = false;
  99. _ScanSpecialElements();
  100. _CreateHTML();
  101. }
  102. /*-------------------------------------------------------------------------
  103. Purpose: Fired when the document is loaded. We must refrain from sending
  104. events to the page until it is loaded.
  105. */
  106. function _OnDocumentLoad()
  107. {
  108. _Initialize();
  109. }
  110. // **********************************************************************
  111. // HELPER FUNCTIONS
  112. // **********************************************************************
  113. /*-------------------------------------------------------------------------
  114. Purpose: Called when the behavior is instantiated. Sets up the internal
  115. property values.
  116. */
  117. function _GetPropertyDefaults()
  118. {
  119. if (element.currentButton)
  120. _iBtnPressed = parseInt(element.currentButton);
  121. }
  122. /*-------------------------------------------------------------------------
  123. Purpose: Return a canonical ID name
  124. */
  125. function _IDName(szID, idx)
  126. {
  127. return szID + idx + '_' + uniqueID;
  128. }
  129. /*-------------------------------------------------------------------------
  130. Purpose: Take the span and store it in the button store at iStore
  131. */
  132. function _StoreButton(elem, ibtn)
  133. {
  134. var btn = new Object;
  135. var szBtnIndex = ' _ibtn=' + ibtn;
  136. var L_PlacesGraphic_Text = 'Graphic';
  137. btn.id = elem.id;
  138. btn._idBtn = _IDName('idBtn', ibtn);
  139. btn._ibtn = ibtn;
  140. btn._idBR = _IDName('idBtnBR', ibtn);
  141. btn._bHidden = false;
  142. if ("undefined" != typeof elem.execItem)
  143. btn._bExecButton = true;
  144. else
  145. btn._bExecButton = false;
  146. // If you change this HTML, be sure to update _GetCaptionElem
  147. btn.innerHTML =
  148. '<DIV id=' + btn._idBtn + c_szStyle_ButtonNormal + szBtnIndex + ' _btnState=0> ' +
  149. ' <CENTER id=' + _IDName('idCtr', ibtn) + szBtnIndex + '> ' +
  150. ' <IMG id=' + _IDName('idImg', ibtn) + ' style="position:relative" src=' + elem.img + szBtnIndex + ' title="" alt="' + L_PlacesGraphic_Text + '" >' +
  151. ' <BR>' +
  152. /* use the private nofocusrect so we don't see the focus rect */
  153. ' <SPAN id=' + _IDName('idSpan', ibtn) + c_szStyle_ButtonText + szBtnIndex + ' nofocusrect>' +
  154. elem.innerHTML +
  155. ' </SPAN>' +
  156. ' </CENTER> ' +
  157. '</DIV>';
  158. // Save this button
  159. _rgbtn[ibtn] = btn;
  160. }
  161. /*-------------------------------------------------------------------------
  162. Purpose: Walk thru the element's html and find the specially-tagged spans.
  163. Each span in this element is considered a separate button.
  164. The span may have the following special attributes:
  165. img - The image to show for the particular button
  166. execItem - This button will be skipped when ctrl-tabbing
  167. The contents of the span is the button's display text.
  168. */
  169. function _ScanSpecialElements()
  170. {
  171. var i;
  172. // Scan the element for spans
  173. var rgspan = element.all.tags("SPAN");
  174. var cspan = rgspan.length;
  175. for (i = 0; i < cspan; i++)
  176. {
  177. var span = rgspan[i];
  178. _StoreButton(span, _cButtons++);
  179. span.innerHTML = "";
  180. }
  181. }
  182. /*-------------------------------------------------------------------------
  183. Purpose: Adds the HTML code to the main document to display the places bar.
  184. */
  185. function _CreateHTML()
  186. {
  187. var i;
  188. var szButtons = '';
  189. // Hide the control while we build it
  190. element.style.visibility = 'hidden';
  191. // Construct the html
  192. for (i = 0; i < _cButtons; i++)
  193. {
  194. szButtons = szButtons + _rgbtn[i].innerHTML + '<BR id=' + _rgbtn[i]._idBR + '>';
  195. }
  196. element.innerHTML =
  197. '<DIV ' + c_szStyle_Background + ' _ibtn=-1> ' +
  198. szButtons +
  199. '</DIV>';
  200. // Attach events to the button divs
  201. var rgdivs = element.all.tags("DIV");
  202. for (i = 0; i < _cButtons; i++)
  203. {
  204. var elem = rgdivs[_rgbtn[i]._idBtn];
  205. _rgdivButtons[i] = elem;
  206. elem.attachEvent('onmouseover', _OnMouseOver);
  207. elem.attachEvent('onmouseout', _OnMouseOut);
  208. elem.attachEvent('onmousedown', _OnMouseDown);
  209. elem.attachEvent('onmouseup', _OnMouseUp);
  210. var spanCaption = _GetCaptionElem(i);
  211. spanCaption.attachEvent('onblur', _OnBlurDiv);
  212. spanCaption.attachEvent('onfocus', _OnFocusDiv);
  213. spanCaption.attachEvent('onkeydown', _OnKeyDownDiv);
  214. // Cancel the image's default dragstart behavior
  215. elem.all(_IDName('idCtr', i)).attachEvent('ondragstart', _CancelDragStart);
  216. }
  217. // Now wait until the document is loaded before pushing the
  218. // initial button
  219. window.attachEvent("onload", _OnDocumentLoad);
  220. // Say we're finished in case the page cares
  221. _FireComplete();
  222. // Now show the control
  223. element.style.visibility = 'visible';
  224. }
  225. /*-------------------------------------------------------------------------
  226. Purpose: Final initialization of the bar
  227. */
  228. function _Initialize()
  229. {
  230. if (-1 != _iBtnPressed)
  231. {
  232. var ibtn = _iBtnPressed;
  233. // Avoid wasting time unpressing a button that isn't pressed yet
  234. _iBtnPressed = -1;
  235. _PushButton(ibtn, 0);
  236. }
  237. window.document.attachEvent("onkeydown", _OnKeyDownDocument);
  238. }
  239. /*-------------------------------------------------------------------------
  240. Purpose: Returns the button index given the elem. Returns -1 if the given
  241. elem is not within a button.
  242. All of the button's elements that were created by this behavior have
  243. an _ibtn property that points to the array of button divs. If there
  244. is no _ibtn property, walk up until we find one. If we don't find
  245. one, then the elem is not within this behavior's region.
  246. */
  247. function _BtnFromElement(elem)
  248. {
  249. var ibtn = -1;
  250. if (elem && null == elem._ibtn)
  251. {
  252. // Walk up the tree to find the next element with the internal
  253. // '_ibtn'
  254. while (elem)
  255. {
  256. if (elem._ibtn)
  257. break;
  258. elem = elem.parentElement;
  259. }
  260. }
  261. if (elem)
  262. ibtn = elem._ibtn;
  263. return ibtn;
  264. }
  265. /*-------------------------------------------------------------------------
  266. Purpose: Returns the button index given the id. Returns -1 if the given id
  267. is not in the array of buttons.
  268. */
  269. function _BtnFromID(idBtn)
  270. {
  271. var ibtn;
  272. for (ibtn = 0; ibtn < _rgbtn.length; ibtn++)
  273. {
  274. if (idBtn == _rgbtn[ibtn].id)
  275. return ibtn;
  276. }
  277. return -1;
  278. }
  279. /*-------------------------------------------------------------------------
  280. Purpose: Draws the frame around the button div according to the given state
  281. */
  282. function _DrawButtonFrame(elem, szState)
  283. {
  284. switch (szState)
  285. {
  286. case 'normal':
  287. elem.style.borderTopColor = 'threedshadow';
  288. elem.style.borderLeftColor = 'threedshadow';
  289. elem.style.borderRightColor = 'threedshadow';
  290. elem.style.borderBottomColor = 'threedshadow';
  291. break;
  292. case 'hotitem':
  293. elem.style.borderTopColor = 'threedhighlight';
  294. elem.style.borderLeftColor = 'threedhighlight';
  295. elem.style.borderRightColor = 'threeddarkshadow';
  296. elem.style.borderBottomColor = 'threeddarkshadow';
  297. break;
  298. case 'pushed':
  299. elem.style.borderTopColor = 'threeddarkshadow';
  300. elem.style.borderLeftColor = 'threeddarkshadow';
  301. elem.style.borderRightColor = 'threedhighlight';
  302. elem.style.borderBottomColor = 'threedhighlight';
  303. break;
  304. }
  305. }
  306. /*-------------------------------------------------------------------------
  307. Purpose: Draws the button. Assumes ibtn is valid.
  308. */
  309. function _DrawButton(ibtn, bDown)
  310. {
  311. var div = _rgdivButtons[ibtn];
  312. var bDownCur = (div._btnState & BS_PRESSED) ? true : false;
  313. var elemImg = div.all(_IDName('idImg', div._ibtn));
  314. var elemText = div.all(_IDName('idSpan', div._ibtn));
  315. if (bDownCur == bDown)
  316. return; // no change
  317. if (bDown)
  318. {
  319. _DrawButtonFrame(div, 'pushed');
  320. // Offset the button contents
  321. elemImg.style.pixelLeft = elemImg.style.pixelLeft + 1;
  322. elemImg.style.pixelTop = elemImg.style.pixelTop + 1;
  323. elemText.style.pixelLeft = elemText.style.pixelLeft + 1;
  324. elemText.style.pixelTop = elemText.style.pixelTop + 1;
  325. div._btnState |= BS_PRESSED;
  326. }
  327. else
  328. {
  329. if (ibtn == _iBtnHot)
  330. _DrawButtonFrame(div, 'hotitem');
  331. else
  332. _DrawButtonFrame(div, 'normal');
  333. // De-Offset the button contents
  334. elemImg.style.pixelLeft = elemImg.style.pixelLeft - 1;
  335. elemImg.style.pixelTop = elemImg.style.pixelTop - 1;
  336. elemText.style.pixelLeft = elemText.style.pixelLeft - 1;
  337. elemText.style.pixelTop = elemText.style.pixelTop - 1;
  338. div._btnState &= ~ BS_PRESSED;
  339. }
  340. }
  341. /*-------------------------------------------------------------------------
  342. Purpose: Returns the element that is the button caption.
  343. */
  344. function _GetCaptionElem(ibtn)
  345. {
  346. var spanCaption = null;
  347. var div = _rgdivButtons[ibtn];
  348. if (div)
  349. spanCaption = div.children[0].children[2];
  350. return spanCaption;
  351. }
  352. /*-------------------------------------------------------------------------
  353. Purpose: Sets the tabIndex property on the given button, and removes it
  354. from the button the had the property prior to this call. (This
  355. control only allows one button to have the tabIndex at any given
  356. time.)
  357. The tabIndex is set so MSAA can receive notifications of 'focus'
  358. change.
  359. */
  360. function _SetTabIndex(ibtn, bSetFocus)
  361. {
  362. if (ibtn == _iBtnTabIndex)
  363. return;
  364. var elem = _GetCaptionElem(_iBtnTabIndex);
  365. if (elem)
  366. elem.tabIndex = -1; // Remove this DIV from the taborder list
  367. elem = _GetCaptionElem(ibtn);
  368. if (elem)
  369. {
  370. elem.tabIndex = 0; // Make this DIV be in the taborder list
  371. if (bSetFocus)
  372. {
  373. // Set the focus so the MSAA event is fired
  374. _bInternalFocusChange = true;
  375. elem.focus();
  376. }
  377. }
  378. _iBtnTabIndex = ibtn;
  379. }
  380. // Flags for _PushButton
  381. var PBF_SETFOCUS = 0x01;
  382. var PBF_MOUSE = 0x02;
  383. /*-------------------------------------------------------------------------
  384. Purpose: Pushes the given button. Any other button loses its push state.
  385. */
  386. function _PushButton(ibtn, dwFlags)
  387. {
  388. var btn = _rgbtn[ibtn];
  389. // Is this button hidden?
  390. if (btn && btn._bHidden)
  391. {
  392. // Yes; skip it
  393. return;
  394. }
  395. // Is this button an ExecButton?
  396. if (btn && btn._bExecButton)
  397. {
  398. // Yes; execute it and leave all other button states as they are
  399. _DrawButton(ibtn, false);
  400. _FireExecItem(btn);
  401. }
  402. else
  403. {
  404. // No; push the button down and toggle any other button up
  405. if ((dwFlags & PBF_MOUSE) && ibtn == _iBtnPressed)
  406. return;
  407. // Is there a button already pressed?
  408. if (-1 != _iBtnPressed && ibtn != _iBtnPressed)
  409. {
  410. // Yes; reset it
  411. _DrawButton(_iBtnPressed, false);
  412. }
  413. // Make this button the currently pressed button.
  414. _iBtnPressed = ibtn;
  415. // This button now gets the focus
  416. _SetTabIndex(ibtn, dwFlags & PBF_SETFOCUS);
  417. if (0 <= _iBtnPressed && _iBtnPressed < _cButtons)
  418. {
  419. _DrawButton(_iBtnPressed, true);
  420. _FireSelectItem(btn);
  421. }
  422. }
  423. }
  424. // Flags for _SetHotItem
  425. var SHIF_SETTABINDEX = 0x01;
  426. var SHIF_RESETTABSTOP = 0x02;
  427. var SHIF_MOUSE = 0x04;
  428. /*-------------------------------------------------------------------------
  429. Purpose: Sets the hot button to track. Clears the hot button if ibtn == -1.
  430. */
  431. function _SetHotItem(ibtn, dwFlags)
  432. {
  433. var div;
  434. if (ibtn == _iBtnHot)
  435. return;
  436. // Reset the current hot button first
  437. if (-1 != _iBtnHot && _iBtnHot != ibtn)
  438. {
  439. div = _rgdivButtons[_iBtnHot];
  440. if (_iBtnHot == _iBtnPressed)
  441. _DrawButtonFrame(div, 'pushed');
  442. else
  443. _DrawButtonFrame(div, 'normal');
  444. }
  445. // Set the hot button
  446. if (-1 != ibtn)
  447. {
  448. div = _rgdivButtons[ibtn];
  449. // The currently pressed button never hottracks when the mouse is hovering
  450. // over it.
  451. //
  452. // However, we do allow the keyboard to navigate to the pushed button. We
  453. // do this so the accessibility aides have the ability to survey all the
  454. // available options...including the currently pushed button.
  455. if ( !(dwFlags & SHIF_MOUSE) || ibtn != _iBtnPressed)
  456. _DrawButtonFrame(div, 'hotitem');
  457. }
  458. _iBtnHot = ibtn;
  459. if (dwFlags & SHIF_SETTABINDEX)
  460. {
  461. // Reset the tabstop back to the pressed button?
  462. if (dwFlags & SHIF_RESETTABSTOP)
  463. {
  464. // Yes
  465. _SetTabIndex(_iBtnPressed, false);
  466. }
  467. else
  468. {
  469. // No; set it to the current button
  470. _SetTabIndex(ibtn, true);
  471. }
  472. }
  473. }
  474. /*-------------------------------------------------------------------------
  475. Purpose: Fires 'onSelectItem' to the document
  476. */
  477. function _FireSelectItem(btn)
  478. {
  479. var evt = createEventObject();
  480. evt.srcID = btn.id;
  481. onSelectItem.fire(evt);
  482. }
  483. /*-------------------------------------------------------------------------
  484. Purpose: Fires 'onExecItem' to the document
  485. */
  486. function _FireExecItem(btn)
  487. {
  488. var evt = createEventObject();
  489. evt.srcID = btn.id;
  490. onExecItem.fire(evt);
  491. }
  492. /*-------------------------------------------------------------------------
  493. Purpose: Fires 'onComplete' to the document
  494. */
  495. function _FireComplete()
  496. {
  497. var evt = createEventObject();
  498. onComplete.fire(evt);
  499. }
  500. var LMOUSE_BUTTON = 1
  501. /*-------------------------------------------------------------------------
  502. Purpose: Handles mousedown events. Depress the button.
  503. */
  504. function _OnMouseDown()
  505. {
  506. var ibtn = _BtnFromElement(window.event.srcElement);
  507. var div;
  508. // Only concerned with the left mouse button
  509. if (LMOUSE_BUTTON != window.event.button)
  510. return;
  511. _DrawButton(ibtn, true);
  512. // Take the capture so we can correctly pop the button up if the
  513. // mouse moves out of the places bar.
  514. _iBtnCapture = ibtn;
  515. div = _rgdivButtons[ibtn];
  516. div.setCapture(false);
  517. }
  518. /*-------------------------------------------------------------------------
  519. Purpose: Handles mouseup events.
  520. */
  521. function _OnMouseUp()
  522. {
  523. var ibtn = _BtnFromElement(window.event.srcElement);
  524. // Only concerned with the left mouse button
  525. if (LMOUSE_BUTTON != window.event.button)
  526. return;
  527. // Double-click will result in a "mouse-down, mouse-up, mouse-up" sequence.
  528. // So _iBtnCapture can be -1.
  529. if (-1 != _iBtnCapture)
  530. {
  531. var div = _rgdivButtons[_iBtnCapture];
  532. div.releaseCapture();
  533. if (_iBtnCapture != ibtn)
  534. _DrawButton(_iBtnCapture, (_iBtnPressed == _iBtnCapture));
  535. if (-1 != ibtn && ibtn == _iBtnCapture)
  536. _PushButton(ibtn, PBF_SETFOCUS | PBF_MOUSE);
  537. _iBtnCapture = -1;
  538. }
  539. }
  540. /*-------------------------------------------------------------------------
  541. Purpose: Handle the onMouseOver event.
  542. */
  543. function _OnMouseOver()
  544. {
  545. var ibtnTo = _BtnFromElement(window.event.toElement);
  546. var ibtnFrom = _BtnFromElement(window.event.fromElement);
  547. // if (ibtnTo == ibtnFrom)
  548. // return;
  549. // Is a button pressed down right now?
  550. if (-1 != _iBtnCapture)
  551. {
  552. // Yes; only pay attention to when we reenter that button
  553. if (ibtnTo == _iBtnCapture && ibtnFrom != _iBtnCapture)
  554. {
  555. _DrawButton(_iBtnCapture, true);
  556. }
  557. }
  558. else
  559. {
  560. // No; standard behavior
  561. _SetHotItem(ibtnTo, SHIF_MOUSE);
  562. }
  563. }
  564. /*-------------------------------------------------------------------------
  565. Purpose: Handle the onMouseOut event.
  566. */
  567. function _OnMouseOut()
  568. {
  569. var event = window.event;
  570. var ibtnTo = _BtnFromElement(event.toElement);
  571. var ibtnFrom = _BtnFromElement(event.fromElement);
  572. // Is the mouse moving to an outside element?
  573. if (ibtnTo != ibtnFrom)
  574. {
  575. // Yes
  576. _SetHotItem(-1, SHIF_MOUSE);
  577. if (ibtnFrom == _iBtnCapture && _iBtnCapture != _iBtnPressed)
  578. _DrawButton(_iBtnCapture, false);
  579. }
  580. }
  581. var CYCLE_PUSHED = 1;
  582. var CYCLE_HOT = 2;
  583. /*-------------------------------------------------------------------------
  584. Purpose: Cycles to the next available button. This skips the currently
  585. pressed button, and cycles around on boundary conditions. Returns
  586. the next button.
  587. */
  588. function _CycleButton(bDown, ibtnStart, cycle)
  589. {
  590. var ibtn = ibtnStart;
  591. var n = bDown ? 1 : -1;
  592. var btn;
  593. var cbtns = 0;
  594. while (true)
  595. {
  596. if (++cbtns > _cButtons)
  597. break; // We've completed a full cycle
  598. if (bDown)
  599. ibtn = (ibtn + 1) % _cButtons;
  600. else
  601. ibtn = ((ibtn - 1) + _cButtons) % _cButtons;
  602. btn = _rgbtn[ibtn];
  603. if (CYCLE_PUSHED == cycle)
  604. {
  605. if (ibtn == _iBtnPressed || btn._bExecButton || btn._bHidden)
  606. continue; // Try again
  607. else
  608. break;
  609. }
  610. else // CYCLE_HOT == cycle
  611. {
  612. if (btn._bHidden)
  613. continue; // Try again
  614. else
  615. break;
  616. }
  617. }
  618. return ibtn;
  619. }
  620. /*-------------------------------------------------------------------------
  621. Purpose: Cycles to the next available button.
  622. In earlier designs, this used to skip the currently pressed button.
  623. But accessibility aides require the ability to cycle thru all the
  624. buttons to allow a blind person to survey all the options. Makes sense.
  625. This function cycles around boundary conditions.
  626. */
  627. function _CycleHotItem(bDown)
  628. {
  629. _SetHotItem(_CycleButton(bDown, _iBtnHot, CYCLE_HOT), SHIF_SETTABINDEX);
  630. }
  631. /*-------------------------------------------------------------------------
  632. Purpose: Cycles to the next button and pushes it.
  633. */
  634. function _CyclePushedButton(bDown)
  635. {
  636. _PushButton(_CycleButton(bDown, _iBtnPressed, CYCLE_PUSHED), 0);
  637. }
  638. /*-------------------------------------------------------------------------
  639. Purpose: Tells the places bar to skip this button when ctrl-tabbing.
  640. */
  641. function SetExecButton(idBtn, bVal)
  642. {
  643. var ibtn = _BtnFromID(idBtn);
  644. if (-1 != ibtn)
  645. {
  646. _rgbtn[ibtn]._bExecButton = bVal;
  647. }
  648. }
  649. /*-------------------------------------------------------------------------
  650. Purpose: Tell the places bar to remove a button
  651. */
  652. function ShowButton(idBtn, bShow)
  653. {
  654. var ibtn = _BtnFromID(idBtn);
  655. if (-1 != ibtn)
  656. {
  657. var btn = _rgbtn[ibtn];
  658. if (btn)
  659. {
  660. var idBtnUnique = btn._idBtn;
  661. var elemBtn = element.all[idBtnUnique];
  662. if (bShow)
  663. {
  664. elemBtn.style.display = 'block';
  665. element.all[btn._idBR].style.display = 'block';
  666. }
  667. else
  668. {
  669. elemBtn.style.display = 'none';
  670. element.all[btn._idBR].style.display = 'none';
  671. }
  672. btn._bHidden = !bShow;
  673. }
  674. }
  675. }
  676. /*-------------------------------------------------------------------------
  677. Purpose: Overridden method so we handle focus properly
  678. */
  679. function focus()
  680. {
  681. var div = _rgdivButtons[_iBtnTabIndex];
  682. if (div)
  683. div.focus();
  684. }
  685. /*-------------------------------------------------------------------------
  686. Purpose: Overridden method so we handle blur properly
  687. */
  688. function blur()
  689. {
  690. var div = _rgdivButtons[_iBtnTabIndex];
  691. if (div)
  692. div.blur();
  693. }
  694. // Key codes
  695. var KC_LEFT = 37;
  696. var KC_UP = 38;
  697. var KC_RIGHT = 39;
  698. var KC_DOWN = 40;
  699. var KC_SPACE = 32;
  700. var KC_RETURN = 13;
  701. var KC_TAB = 9;
  702. /*-------------------------------------------------------------------------
  703. Purpose: Handle the onKeyDown event of the document. We have this to catch
  704. the ctrl-tab events when the places bar doesn't have the focus.
  705. */
  706. function _OnKeyDownDocument()
  707. {
  708. var evt = window.event;
  709. // Control-tab?
  710. if (KC_TAB == evt.keyCode && evt.ctrlKey)
  711. {
  712. // Yes
  713. var bDir = evt.shiftKey ? false : true;
  714. _CyclePushedButton(bDir);
  715. // Cancel event so no one else gets it
  716. evt.returnValue = false;
  717. }
  718. }
  719. /*-------------------------------------------------------------------------
  720. Purpose: Handle the onKeyDown event
  721. */
  722. function _OnKeyDownDiv()
  723. {
  724. var keyCode = window.event.keyCode;
  725. // Pay attention to up and down arrows
  726. if (KC_UP == keyCode || KC_LEFT == keyCode)
  727. {
  728. _CycleHotItem(false);
  729. // Cancel event so div doesn't scroll independently
  730. window.event.returnValue = false;
  731. }
  732. else if (KC_DOWN == keyCode || KC_RIGHT == keyCode)
  733. {
  734. _CycleHotItem(true);
  735. // Cancel event so div doesn't scroll independently
  736. window.event.returnValue = false;
  737. }
  738. else if (KC_SPACE == keyCode || KC_RETURN == keyCode)
  739. {
  740. _PushButton(_iBtnHot, PBF_SETFOCUS);
  741. }
  742. }
  743. /*-------------------------------------------------------------------------
  744. Purpose: Handle the onBlur event. Change the selection color so it is clear
  745. the list no longer has the focus.
  746. */
  747. function _OnBlurDiv()
  748. {
  749. // Don't bother if this was caused by the control itself, or it doesn't
  750. // have the focus.
  751. if (false == _bInternalFocusChange && true == _bHasFocus)
  752. {
  753. _bHasFocus = false;
  754. _SetHotItem(-1, SHIF_SETTABINDEX | SHIF_RESETTABSTOP);
  755. }
  756. }
  757. /*-------------------------------------------------------------------------
  758. Purpose: Handle the onFocus event. Change the selection color.
  759. We use an invisible anchor (placed before the div) so we can
  760. receive focus events. When this anchor receives focus, we treat
  761. that as if the bar is getting the focus. This handles the
  762. case when the user tabs around the page.
  763. The second case is if the user uses the mouse to select one
  764. of the items. In this case, the anchor will not receive focus,
  765. but we have to pretend as if it did. This is why _bHasFocus keeps
  766. track of this.
  767. */
  768. function _OnFocusDiv()
  769. {
  770. // Don't bother doing this if the document isn't ready, or if the
  771. // control already has the focus, or if the focus change is caused
  772. // by the control itself.
  773. if (false == _bInternalFocusChange && false == _bHasFocus &&
  774. "complete" == window.document.readyState)
  775. {
  776. _bHasFocus = true;
  777. _CycleHotItem(true);
  778. }
  779. _bInternalFocusChange = false; // Reset
  780. }
  781. /*-------------------------------------------------------------------------
  782. Purpose: Handle the onerror event
  783. */
  784. function _OnError(szMsg, szUrl, iLine)
  785. {
  786. // Prevent scripting errors from displaying ugly messages
  787. alert("An unexpected error occurred.\n\n" + szMsg + "\n" + szUrl + "\nLine: " + iLine);
  788. return true; // Suppress IE error messaging
  789. }
  790. /*-------------------------------------------------------------------------
  791. Purpose: Cancel any drag operation
  792. */
  793. function _CancelDragStart()
  794. {
  795. window.event.returnValue = false;
  796. }
  797. </SCRIPT>
  798. //------------------------------------------------------------------------
  799. // Properties
  800. //------------------------------------------------------------------------
  801. <PROPERTY name="currentButton" get=get_button put=put_button />
  802. </PUBLIC:HTC>