TabControl.js 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748
  1. /*
  2. *+------------------------------------------------------------------------+
  3. *| Licensed Materials - Property of IBM
  4. *| IBM Cognos Products: Viewer
  5. *| (C) Copyright IBM Corp. 2014
  6. *|
  7. *| US Government Users Restricted Rights - Use, duplication or
  8. *| disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
  9. *|
  10. *+------------------------------------------------------------------------+
  11. */
  12. function CognosTabControl(container, callback) {
  13. this._init();
  14. this._outsideContainer = container; // Container provisded by the caller
  15. this._callback = callback; // function to call when a tab is clicked
  16. }
  17. CognosTabControl.prototype._init = function() {
  18. this._tabs = null;
  19. this._tabControlNode = null;
  20. this._scrollButtonsVisible = false;
  21. this._scrollLeftButton = null;
  22. this._scrollRightButton = null;
  23. this._selectedTab = null;
  24. this._wrapperDiv = null;
  25. this._topContainer = null;
  26. this._seperator = null;
  27. this._isSavedOutput = false;
  28. this._isHighContrast = false;
  29. };
  30. CognosTabControl.prototype.destroy = function() {
  31. if (this._wrapperDiv) {
  32. this._wrapperDiv.parentNode.removeChild(this._wrapperDiv);
  33. delete this._wrapperDiv;
  34. this._wrapperDiv = null;
  35. }
  36. };
  37. CognosTabControl.prototype.setHighContrast = function(isHighContrast) {
  38. this._isHighContrast = isHighContrast;
  39. };
  40. CognosTabControl.prototype.isHighContrast = function() {
  41. return this._isHighContrast;
  42. };
  43. /**
  44. * In CW we have to save enough room for the absolutly positions tab control
  45. */
  46. CognosTabControl.prototype.setSpaceSaverContainer = function(node) {
  47. this._spaceSaverContainer = node;
  48. };
  49. /**
  50. * Used when we're in BUX so that the tab control is absolutly positioned inside the widget div
  51. */
  52. CognosTabControl.prototype.useAbsolutePosition = function(value) {
  53. this._useAbsolutePosition = value;
  54. };
  55. CognosTabControl.prototype.setScrollAttachNode = function(node) {
  56. this._scrollAttachNode = node;
  57. };
  58. CognosTabControl.prototype.setIsSavedOutput = function(isSavedOutput) {
  59. this._isSavedOutput = isSavedOutput;
  60. };
  61. CognosTabControl.prototype.isSavedOutput = function() {
  62. return this._isSavedOutput;
  63. };
  64. CognosTabControl.prototype.getSelectedTabId = function() {
  65. if (this._selectedTab) {
  66. return this._selectedTab.getId();
  67. }
  68. return null;
  69. };
  70. CognosTabControl.prototype.getSelectedTab = function() {
  71. return this._selectedTab ? this._selectedTab : null;
  72. };
  73. CognosTabControl.prototype.isTopAligned = function() {
  74. return this._isTopAligned;
  75. };
  76. CognosTabControl.prototype.getWrapperDiv = function() {
  77. return this._wrapperDiv;
  78. };
  79. CognosTabControl.prototype.getVisibleWidth = function() {
  80. var scrollButtonWidth = this._scrollRightButton ? this._scrollRightButton.getWidth() + 11 : 0;
  81. return this._wrapperDiv.clientWidth - scrollButtonWidth;
  82. };
  83. CognosTabControl.prototype.getMaxRightScroll = function() {
  84. var scrollButtonWidth = this._scrollRightButton ? this._scrollRightButton.getWidth() + 11 : 0;
  85. return this._totalWrapperWidth + scrollButtonWidth + 8 - this._wrapperDiv.clientWidth;
  86. };
  87. CognosTabControl.prototype.hide = function() {
  88. this._topContainer.style.display = "none";
  89. };
  90. /**
  91. * If we're using absolute positioning then this will reset the left, top and bottom values
  92. */
  93. CognosTabControl.prototype.resetPosition = function() {
  94. if (this._useAbsolutePosition === true) {
  95. this._outsideContainer.srollLeft = "0px";
  96. this._outsideContainer.scrollTop = "0px";
  97. this._topContainer.style.top = "";
  98. this._topContainer.style.bottom = "";
  99. this._topContainer.style.left = "0px";
  100. if (this._isTopAligned) {
  101. this._topContainer.style.top = "0px";
  102. }
  103. else {
  104. this._topContainer.style.bottom = "0px";
  105. }
  106. }
  107. };
  108. /**
  109. Renders all the tabs
  110. **/
  111. CognosTabControl.prototype.render = function(tabControlInfo) {
  112. this._updateTabInfo(tabControlInfo);
  113. if (!this._tabControlNode) {
  114. var tabControl = this;
  115. var scrollAttachNode = this._scrollAttachNode ? this._scrollAttachNode : this._outsideContainer;
  116. if (window.attachEvent) {
  117. window.attachEvent("onresize", function() { tabControl.onResize(); });
  118. if (this._useAbsolutePosition === true) {
  119. scrollAttachNode.attachEvent("onscroll", function() { tabControl.onContainerScroll(); });
  120. }
  121. }
  122. else {
  123. window.addEventListener("resize", function() { tabControl.onResize(); }, false);
  124. if (this._useAbsolutePosition === true) {
  125. scrollAttachNode.addEventListener("scroll", function() { tabControl.onContainerScroll(); }, false);
  126. }
  127. }
  128. this._outsideContainer.originalClassName = this._outsideContainer.className;
  129. this._outsideContainer.className = this._outsideContainer.className + (this._isTopAligned ? " ct_controlTop" : " ct_controlBottom");
  130. this._topContainer = document.createElement("div");
  131. this._topContainer.className = "ct_wrapperDiv";
  132. if (this._useAbsolutePosition === true) {
  133. this._topContainer.style.width = "100%";
  134. this._topContainer.style.position = "absolute";
  135. this._topContainer.style.left = "0px";
  136. if (this._isTopAligned) {
  137. this._topContainer.style.top = "0px";
  138. }
  139. else {
  140. this._topContainer.style.bottom = "0px";
  141. }
  142. }
  143. if (this._isTopAligned && this._outsideContainer.firstChild) {
  144. this._outsideContainer.insertBefore(this._topContainer, this._outsideContainer.firstChild);
  145. }
  146. else {
  147. this._outsideContainer.appendChild(this._topContainer);
  148. }
  149. this._wrapperDiv = document.createElement("div");
  150. this._wrapperDiv.setAttribute("role", "presentation");
  151. this._wrapperDiv.className = "ct_wrapperDiv";
  152. this._topContainer.appendChild(this._wrapperDiv);
  153. this._tabControlNode = document.createElement("div");
  154. this._tabControlNode.setAttribute("role", "tablist");
  155. this._tabControlNode.className = "ct_control";
  156. this._wrapperDiv.appendChild(this._tabControlNode);
  157. this._totalWrapperWidth = 0;
  158. for (var i=0; i < this._tabs.length; i++) {
  159. var tab = this._tabs[i];
  160. tab.render(this._tabControlNode);
  161. this._totalWrapperWidth += this._tabs[i].getWidth();
  162. }
  163. var wrapperDivHeight = 0;
  164. if (this._tabs[0]) {
  165. wrapperDivHeight = this._tabs[0].getHeight();
  166. }
  167. this._wrapperDiv.style.height = wrapperDivHeight + 5 + "px";
  168. if (this._spaceSaverContainer) {
  169. this.spaceSaverDiv = document.createElement("div");
  170. this.spaceSaverDiv.style.height = wrapperDivHeight + 5 + "px";
  171. this.spaceSaverDiv.style.position = "relative";
  172. this.spaceSaverDiv.style.display = "block";
  173. this._spaceSaverContainer.appendChild(this.spaceSaverDiv);
  174. }
  175. this._createSeperator();
  176. }
  177. else {
  178. this.resetPosition();
  179. }
  180. this._topContainer.style.display = "";
  181. this.onResize();
  182. this.selectTab(tabControlInfo.currentTabId, false);
  183. if (this._selectedTab) {
  184. this._selectedTab.scrollIntoView();
  185. this.updateScrollButtons();
  186. }
  187. };
  188. /**
  189. * In BUX when the use scroll the widget container we need to make sure the tab control gets moved horizontally
  190. */
  191. CognosTabControl.prototype.onContainerScroll = function() {
  192. var container = this._scrollAttachNode ? this._scrollAttachNode : this._topContainer;
  193. this._topContainer.style.left = container.scrollLeft + "px";
  194. if (this._isTopAligned) {
  195. this._topContainer.style.top = container.scrollTop + "px";
  196. }
  197. else {
  198. this._topContainer.style.bottom = (-container.scrollTop) + "px";
  199. }
  200. };
  201. CognosTabControl.prototype._resetTabControl = function() {
  202. if (this._outsideContainer.originalClassName) {
  203. this._outsideContainer.className = this._outsideContainer.originalClassName;
  204. }
  205. else {
  206. this._outsideContainer.className = "";
  207. }
  208. if (this._topContainer) {
  209. var node = this._outsideContainer.removeChild(this._topContainer);
  210. node = null;
  211. }
  212. this._init();
  213. };
  214. /**
  215. Creates or updates the tab objects
  216. **/
  217. CognosTabControl.prototype._updateTabInfo = function(tabControlInfo) {
  218. this._isTopAligned = tabControlInfo.position == "topLeft" ? true : false;
  219. var tabs = tabControlInfo.tabs;
  220. // We already have tabs, make sure nothing has changed
  221. if (this._tabs) {
  222. if (this._tabs.length != tabs.length) {
  223. this._resetTabControl();
  224. }
  225. else {
  226. for (var i=0; i < this._tabs.length; i++) {
  227. if (tabs[i].id != this._tabs[i].getId()) {
  228. this._resetTabControl();
  229. break;
  230. }
  231. }
  232. }
  233. }
  234. if (!this._tabs) {
  235. this._tabs = [];
  236. if (!tabs) {
  237. return;
  238. }
  239. for (var ii=0; ii < tabs.length; ii++) {
  240. var tab = new CognosTab(tabs[ii], this, ii);
  241. this._tabs.push(tab);
  242. }
  243. }
  244. };
  245. CognosTabControl.prototype.getScrollPos = function() {
  246. return this._wrapperDiv.scrollLeft;
  247. };
  248. CognosTabControl.prototype.scrollTo = function(scrollPos) {
  249. this._wrapperDiv.scrollLeft = scrollPos;
  250. this.updateScrollButtons();
  251. };
  252. /**
  253. Handles the window resize event to show/hide the scroll buttons
  254. **/
  255. CognosTabControl.prototype.onResize = function(evt) {
  256. if (this._wrapperDiv.offsetWidth < this._totalWrapperWidth) {
  257. this._showScrollButtons();
  258. this.updateScrollButtons();
  259. if (this._selectedTab) {
  260. this._selectedTab.scrollIntoView();
  261. }
  262. if (this._scrollRightButton.isDisabled()) {
  263. this.scrollTo(this.getMaxRightScroll());
  264. }
  265. }
  266. else {
  267. this._hideScrollButtons();
  268. this.scrollTo(0);
  269. }
  270. };
  271. CognosTabControl.prototype._showScrollButtons = function() {
  272. if (this._scrollButtonsVisible) {
  273. return;
  274. }
  275. if (!this._scrollLeftButton) {
  276. var wrapperDivHeight = 0;
  277. if (this._tabs[0]) {
  278. wrapperDivHeight = this._tabs[0].getHeight();
  279. }
  280. this._scrollLeftButton = new CognosScrollButton("left", wrapperDivHeight, this);
  281. this._scrollLeftButton.render(this._topContainer);
  282. this._scrollRightButton = new CognosScrollButton("right", wrapperDivHeight, this);
  283. this._scrollRightButton.render(this._topContainer);
  284. }
  285. this._scrollButtonsVisible = true;
  286. this._scrollLeftButton.show();
  287. this._scrollRightButton.show();
  288. this._tabControlNode.style.left = this._scrollLeftButton.getWidth() - 2 + "px";
  289. };
  290. CognosTabControl.prototype.updateScrollButtons = function() {
  291. if (this._scrollLeftButton) {
  292. this._scrollLeftButton.update();
  293. }
  294. if (this._scrollRightButton) {
  295. this._scrollRightButton.update();
  296. }
  297. };
  298. CognosTabControl.prototype._hideScrollButtons = function() {
  299. if (!this._scrollButtonsVisible) {
  300. return;
  301. }
  302. this._scrollButtonsVisible = false;
  303. this._tabControlNode.style.left = "0px";
  304. this._scrollLeftButton.hide();
  305. this._scrollRightButton.hide();
  306. };
  307. /**
  308. Creates the line seperator that's either above or below the tabs
  309. **/
  310. CognosTabControl.prototype._createSeperator = function() {
  311. this._seperator = document.createElement("div");
  312. this._seperator.setAttribute("role", "presendation");
  313. this._seperator.setAttribute("style", "");
  314. this._seperator.className = "ct_verticalLine";
  315. this._seperator.setAttribute("role", "presentation");
  316. this._tabControlNode.appendChild(this._seperator);
  317. };
  318. /**
  319. Selects one tab while making sure all the other tabs are unselected
  320. **/
  321. CognosTabControl.prototype.selectTab = function(tabId, userInvokved, evt) {
  322. if (!evt) {
  323. evt = window.event;
  324. }
  325. for (var i=0; i < this._tabs.length; i++) {
  326. var tab = this._tabs[i];
  327. var isSelected = tab.getId() == tabId;
  328. tab.select(isSelected);
  329. if (isSelected) {
  330. this._selectedTab = tab;
  331. if (userInvokved && this._callback) {
  332. this._callback(tabId);
  333. }
  334. }
  335. if (userInvokved) {
  336. tab.focus(isSelected);
  337. }
  338. }
  339. if (evt && window.stopEventBubble) {
  340. window.stopEventBubble(evt);
  341. }
  342. return false;
  343. };
  344. CognosTabControl.prototype.handleKeyDown = function(evt, position) {
  345. if (!evt) {
  346. evt = window.event;
  347. }
  348. if (!evt) {
  349. return;
  350. }
  351. if (evt.keyCode == "39" || evt.keyCode == "37") {
  352. if (evt.keyCode == "39") { // left arrow
  353. position++;
  354. if (position >= this._tabs.length) {
  355. position = 0;
  356. }
  357. }
  358. else {
  359. position--;
  360. if (position < 0) {
  361. position = this._tabs.length-1;
  362. }
  363. }
  364. this._tabs[position].focus();
  365. this._tabs[position].scrollIntoView();
  366. }
  367. else if (evt.keyCode == "32" || evt.keyCode == "13") { // space or enter
  368. var tabId = this._tabs[position].getId();
  369. this.selectTab(tabId, true);
  370. }
  371. };
  372. /**
  373. Class that handles one tab in the tabControl
  374. **/
  375. function CognosTab(tabInfo, tabControl, position) {
  376. if (!tabInfo) {
  377. return;
  378. }
  379. this._id = tabInfo.id;
  380. this._label = tabInfo.label;
  381. this._position = position;
  382. this._contentClassName = tabInfo.className;
  383. this._imgURL = tabInfo.img;
  384. this._selected = false;
  385. this._tabControl = tabControl;
  386. this._outerTabDiv = null;
  387. this._focusDiv = null;
  388. }
  389. CognosTab.prototype.getWidth = function() {
  390. return this._outerTabDiv.offsetWidth + 1;
  391. };
  392. CognosTab.prototype.getHeight = function() {
  393. return this._outerTabDiv.clientHeight;
  394. };
  395. CognosTab.prototype.getId = function() {
  396. return this._id;
  397. };
  398. /**
  399. Either selects or deselects the tab
  400. **/
  401. CognosTab.prototype.select = function(selected) {
  402. if (selected != this._selected) {
  403. this._selected = selected;
  404. if (selected) {
  405. this.scrollIntoView();
  406. }
  407. if (this._outerTabDiv) {
  408. this._updateSelectedClass();
  409. this._updateAriaSelected();
  410. }
  411. }
  412. };
  413. /**
  414. Scroll the tab into view if necessary
  415. **/
  416. CognosTab.prototype.scrollIntoView = function() {
  417. var tabRightCoord = this._outerTabDiv.offsetLeft + this._outerTabDiv.clientWidth;
  418. var scrollLength = this._tabControl.getVisibleWidth();
  419. var mainScrollPos = this._tabControl.getScrollPos();
  420. var tabOffsetLeft = this._outerTabDiv.offsetLeft;
  421. if (tabOffsetLeft === 0) {
  422. this._tabControl.scrollTo(0);
  423. }
  424. else if ( (tabOffsetLeft >= mainScrollPos) && (tabRightCoord <= (mainScrollPos + scrollLength))) {
  425. // If the tab is already visible don't move the scroll position
  426. }
  427. else if (tabOffsetLeft < mainScrollPos) {
  428. var scrollTo = tabOffsetLeft < 3 ? 0 : tabOffsetLeft - 3;
  429. this._tabControl.scrollTo(scrollTo);
  430. }
  431. else if (tabRightCoord - scrollLength > 0 || tabRightCoord < mainScrollPos) {
  432. this._tabControl.scrollTo(tabRightCoord - scrollLength + 10);
  433. }
  434. };
  435. /**
  436. Renders a tab
  437. **/
  438. CognosTab.prototype.render = function(parentNode) {
  439. if (!this._outerTabDiv) {
  440. var tabId = this._id;
  441. var tabControl = this._tabControl;
  442. var tab = this;
  443. // Outer div
  444. this._outerTabDiv = document.createElement("div");
  445. this._outerTabDiv.onmousedown = function(event) { tabControl.selectTab(tabId, true, event); };
  446. this._outerTabDiv.onmouseover = function() { this.className = this.className + ' ct_highlight'; };
  447. this._outerTabDiv.onmouseout = function() { tab._updateSelectedClass(); };
  448. this._outerTabDiv.setAttribute("style", "");
  449. this._outerTabDiv.setAttribute("role", "presentation");
  450. this._updateSelectedClass();
  451. parentNode.appendChild(this._outerTabDiv);
  452. // This is the div that takes focus
  453. var textWrapperDiv = document.createElement("div");
  454. textWrapperDiv.className = "ct_content";
  455. textWrapperDiv.setAttribute("role", "presentation");
  456. this._outerTabDiv.appendChild(textWrapperDiv);
  457. // Tab text
  458. this._focusDiv = document.createElement("span");
  459. this._focusDiv.innerHTML = this._label ? this._label : "&nbsp;";
  460. this._focusDiv.className = "ct_text";
  461. this._focusDiv.setAttribute("tabIndex", this._position === 0 ? "0" : "-1");
  462. this._focusDiv.setAttribute("role", "tab");
  463. this._focusDiv.onkeydown = function(event) {tabControl.handleKeyDown(event, tab._position);};
  464. this._updateAriaSelected();
  465. textWrapperDiv.appendChild(this._focusDiv);
  466. // Only needed in IE quirks mode since min-width doesn't work
  467. if (this.isIE() && this.getWidth() < 75) {
  468. this._outerTabDiv.style.width = "75px";
  469. }
  470. }
  471. else {
  472. this._updateSelectedClass();
  473. this._updateAriaSelected();
  474. }
  475. };
  476. CognosTab.prototype.isIE = function() {
  477. return (navigator.userAgent.indexOf('MSIE') != -1 || navigator.userAgent.indexOf('Trident') != -1);
  478. };
  479. CognosTab.prototype.getFocusableDiv = function() {
  480. return this._focusDiv;
  481. };
  482. CognosTab.prototype.focus = function(selected) {
  483. if (typeof selected === "undefined") {
  484. selected = true;
  485. }
  486. this._focusDiv.setAttribute("tabIndex", selected ? "0" : "-1");
  487. if (selected && this._focusDiv.focus) {
  488. this._focusDiv.focus();
  489. }
  490. };
  491. /**
  492. Update the css class attribute depending on if the tab is selected
  493. **/
  494. CognosTab.prototype._updateSelectedClass = function() {
  495. this._outerTabDiv.className = this._selected ? "ct_outerDiv ct_highlight ct_selected" : "ct_outerDiv";
  496. };
  497. /**
  498. Updated the aria-selected attribute
  499. **/
  500. CognosTab.prototype._updateAriaSelected = function() {
  501. this._focusDiv.setAttribute("aria-selected", this._selected ? "true" : "false");
  502. };
  503. function CognosScrollButton(direction, height, tabControl) {
  504. this._direction = direction;
  505. this._height = height;
  506. this._tabControl = tabControl;
  507. this._disabled = true;
  508. this._scrolling = false;
  509. }
  510. CognosScrollButton.prototype.getWidth = function() {
  511. return this._scrollButtonDiv.offsetWidth + 1;
  512. };
  513. CognosScrollButton.prototype.show = function() {
  514. this._wrapperDiv.style.display = "block";
  515. };
  516. CognosScrollButton.prototype.hide = function() {
  517. this._wrapperDiv.style.display = "none";
  518. };
  519. CognosScrollButton.prototype.update = function() {
  520. var wrapperDiv = this._tabControl.getWrapperDiv();
  521. var disableButton = false;
  522. if (this._direction == 'left') {
  523. if (wrapperDiv.scrollLeft === 0) {
  524. disableButton = true;
  525. }
  526. }
  527. else {
  528. if (wrapperDiv.scrollLeft >= (this._tabControl.getMaxRightScroll() - 2)) {
  529. disableButton = true;
  530. }
  531. }
  532. if (disableButton) {
  533. this._disable();
  534. }
  535. else {
  536. this._enable();
  537. }
  538. };
  539. CognosScrollButton.prototype.isDisabled = function() {
  540. return this._disabled;
  541. };
  542. CognosScrollButton.prototype._disable = function() {
  543. this._disabled = true;
  544. this._outerDiv.className = "ct_outerDiv ct_scrollDisabled";
  545. };
  546. CognosScrollButton.prototype._enable = function() {
  547. this._disabled = false;
  548. this._outerDiv.className = "ct_outerDiv ct_scrollEnabled";
  549. };
  550. CognosScrollButton.prototype.scroll = function() {
  551. if (!this._scrolling) {
  552. this._scrolling = true;
  553. var scrollLength = this._tabControl.getWrapperDiv().clientWidth;
  554. this._doAnimateScroll(scrollLength, this._tabControl.getMaxRightScroll());
  555. }
  556. };
  557. CognosScrollButton.prototype._doAnimateScroll = function(scrollLength, maxRightScroll) {
  558. if (scrollLength > 0) {
  559. var scrollOffset = 10;
  560. var wrapperDiv = this._tabControl.getWrapperDiv();
  561. if (this._direction == 'left') {
  562. if (wrapperDiv.scrollLeft > scrollOffset) {
  563. this._tabControl.scrollTo(wrapperDiv.scrollLeft - scrollOffset);
  564. }
  565. else {
  566. this._tabControl.scrollTo(0);
  567. this._scrolling = false;
  568. return;
  569. }
  570. }
  571. else {
  572. if (wrapperDiv.scrollLeft + scrollOffset < maxRightScroll) {
  573. this._tabControl.scrollTo(wrapperDiv.scrollLeft + scrollOffset);
  574. }
  575. else {
  576. this._scrolling = false;
  577. this._tabControl.scrollTo(maxRightScroll);
  578. this._tabControl.updateScrollButtons();
  579. return;
  580. }
  581. }
  582. scrollLength -= scrollOffset;
  583. var scrollButton = this;
  584. setTimeout(function() { scrollButton._doAnimateScroll(scrollLength, maxRightScroll);}, 3);
  585. }
  586. else {
  587. this._scrolling = false;
  588. this._tabControl.updateScrollButtons();
  589. }
  590. };
  591. CognosScrollButton.prototype.isIE = function() {
  592. return (navigator.userAgent.indexOf('MSIE') != -1 || navigator.userAgent.indexOf('Trident') != -1);
  593. };
  594. CognosScrollButton.prototype.render = function(parentNode) {
  595. this._scrollButtonDiv = document.createElement("div");
  596. this._scrollButtonDiv.className = "ct_scrollButton";
  597. var offset = -1;
  598. if (this.isIE() && document.compatMode != 'CSS1Compat') {
  599. // Only needed until we support standards mode. Once we do this work-around for
  600. // proper alignment can be removed
  601. offset = 1;
  602. }
  603. this._scrollButtonDiv.style.height = this._height + offset + "px";
  604. if (this._tabControl.isHighContrast()) {
  605. this._scrollButtonDiv.innerHTML = this._direction == "left" ? "&laquo;" : "&raquo;";
  606. }
  607. this._outerDiv = document.createElement("div");
  608. this._outerDiv.className = "ct_scrollDisabled";
  609. this._outerDiv.appendChild(this._scrollButtonDiv);
  610. this._outerDiv.style.height = this._height + "px";
  611. var scrollButton = this;
  612. this._outerDiv.onclick = function() {scrollButton.scroll();};
  613. this._wrapperDiv = document.createElement("div");
  614. this._wrapperDiv.style.height = this._height + "px";
  615. this._wrapperDiv.className = "ct_scroll " + (this._direction == "left" ? "ct_left" : "ct_right") + (this._tabControl.isHighContrast() ? " a11y" : "");
  616. this._wrapperDiv.appendChild(this._outerDiv);
  617. if (this._direction == "left") {
  618. parentNode.insertBefore(this._wrapperDiv, parentNode.firstChild);
  619. this._wrapperDiv.style.left = "0px";
  620. }
  621. else {
  622. parentNode.appendChild(this._wrapperDiv);
  623. this._wrapperDiv.style.right = "0px";
  624. }
  625. };