123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748 |
- /*
- *+------------------------------------------------------------------------+
- *| Licensed Materials - Property of IBM
- *| IBM Cognos Products: Viewer
- *| (C) Copyright IBM Corp. 2014
- *|
- *| US Government Users Restricted Rights - Use, duplication or
- *| disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
- *|
- *+------------------------------------------------------------------------+
- */
- function CognosTabControl(container, callback) {
- this._init();
- this._outsideContainer = container; // Container provisded by the caller
- this._callback = callback; // function to call when a tab is clicked
- }
- CognosTabControl.prototype._init = function() {
- this._tabs = null;
- this._tabControlNode = null;
- this._scrollButtonsVisible = false;
- this._scrollLeftButton = null;
- this._scrollRightButton = null;
- this._selectedTab = null;
- this._wrapperDiv = null;
- this._topContainer = null;
- this._seperator = null;
- this._isSavedOutput = false;
- this._isHighContrast = false;
- };
- CognosTabControl.prototype.destroy = function() {
- if (this._wrapperDiv) {
- this._wrapperDiv.parentNode.removeChild(this._wrapperDiv);
- delete this._wrapperDiv;
- this._wrapperDiv = null;
- }
- };
- CognosTabControl.prototype.setHighContrast = function(isHighContrast) {
- this._isHighContrast = isHighContrast;
- };
- CognosTabControl.prototype.isHighContrast = function() {
- return this._isHighContrast;
- };
- /**
- * In CW we have to save enough room for the absolutly positions tab control
- */
- CognosTabControl.prototype.setSpaceSaverContainer = function(node) {
- this._spaceSaverContainer = node;
- };
- /**
- * Used when we're in BUX so that the tab control is absolutly positioned inside the widget div
- */
- CognosTabControl.prototype.useAbsolutePosition = function(value) {
- this._useAbsolutePosition = value;
- };
- CognosTabControl.prototype.setScrollAttachNode = function(node) {
- this._scrollAttachNode = node;
- };
- CognosTabControl.prototype.setIsSavedOutput = function(isSavedOutput) {
- this._isSavedOutput = isSavedOutput;
- };
- CognosTabControl.prototype.isSavedOutput = function() {
- return this._isSavedOutput;
- };
- CognosTabControl.prototype.getSelectedTabId = function() {
- if (this._selectedTab) {
- return this._selectedTab.getId();
- }
-
- return null;
- };
- CognosTabControl.prototype.getSelectedTab = function() {
- return this._selectedTab ? this._selectedTab : null;
- };
- CognosTabControl.prototype.isTopAligned = function() {
- return this._isTopAligned;
- };
- CognosTabControl.prototype.getWrapperDiv = function() {
- return this._wrapperDiv;
- };
- CognosTabControl.prototype.getVisibleWidth = function() {
- var scrollButtonWidth = this._scrollRightButton ? this._scrollRightButton.getWidth() + 11 : 0;
- return this._wrapperDiv.clientWidth - scrollButtonWidth;
- };
- CognosTabControl.prototype.getMaxRightScroll = function() {
- var scrollButtonWidth = this._scrollRightButton ? this._scrollRightButton.getWidth() + 11 : 0;
- return this._totalWrapperWidth + scrollButtonWidth + 8 - this._wrapperDiv.clientWidth;
- };
- CognosTabControl.prototype.hide = function() {
- this._topContainer.style.display = "none";
- };
- /**
- * If we're using absolute positioning then this will reset the left, top and bottom values
- */
- CognosTabControl.prototype.resetPosition = function() {
- if (this._useAbsolutePosition === true) {
- this._outsideContainer.srollLeft = "0px";
- this._outsideContainer.scrollTop = "0px";
- this._topContainer.style.top = "";
- this._topContainer.style.bottom = "";
-
- this._topContainer.style.left = "0px";
- if (this._isTopAligned) {
- this._topContainer.style.top = "0px";
- }
- else {
- this._topContainer.style.bottom = "0px";
- }
- }
- };
- /**
- Renders all the tabs
- **/
- CognosTabControl.prototype.render = function(tabControlInfo) {
- this._updateTabInfo(tabControlInfo);
- if (!this._tabControlNode) {
-
- var tabControl = this;
- var scrollAttachNode = this._scrollAttachNode ? this._scrollAttachNode : this._outsideContainer;
- if (window.attachEvent) {
- window.attachEvent("onresize", function() { tabControl.onResize(); });
- if (this._useAbsolutePosition === true) {
- scrollAttachNode.attachEvent("onscroll", function() { tabControl.onContainerScroll(); });
- }
- }
- else {
- window.addEventListener("resize", function() { tabControl.onResize(); }, false);
- if (this._useAbsolutePosition === true) {
- scrollAttachNode.addEventListener("scroll", function() { tabControl.onContainerScroll(); }, false);
- }
- }
- this._outsideContainer.originalClassName = this._outsideContainer.className;
- this._outsideContainer.className = this._outsideContainer.className + (this._isTopAligned ? " ct_controlTop" : " ct_controlBottom");
-
- this._topContainer = document.createElement("div");
- this._topContainer.className = "ct_wrapperDiv";
- if (this._useAbsolutePosition === true) {
- this._topContainer.style.width = "100%";
- this._topContainer.style.position = "absolute";
- this._topContainer.style.left = "0px";
- if (this._isTopAligned) {
- this._topContainer.style.top = "0px";
- }
- else {
- this._topContainer.style.bottom = "0px";
- }
- }
-
- if (this._isTopAligned && this._outsideContainer.firstChild) {
- this._outsideContainer.insertBefore(this._topContainer, this._outsideContainer.firstChild);
- }
- else {
- this._outsideContainer.appendChild(this._topContainer);
- }
-
- this._wrapperDiv = document.createElement("div");
- this._wrapperDiv.setAttribute("role", "presentation");
- this._wrapperDiv.className = "ct_wrapperDiv";
- this._topContainer.appendChild(this._wrapperDiv);
-
- this._tabControlNode = document.createElement("div");
- this._tabControlNode.setAttribute("role", "tablist");
- this._tabControlNode.className = "ct_control";
- this._wrapperDiv.appendChild(this._tabControlNode);
-
- this._totalWrapperWidth = 0;
- for (var i=0; i < this._tabs.length; i++) {
- var tab = this._tabs[i];
- tab.render(this._tabControlNode);
- this._totalWrapperWidth += this._tabs[i].getWidth();
- }
-
- var wrapperDivHeight = 0;
- if (this._tabs[0]) {
- wrapperDivHeight = this._tabs[0].getHeight();
- }
- this._wrapperDiv.style.height = wrapperDivHeight + 5 + "px";
-
- if (this._spaceSaverContainer) {
- this.spaceSaverDiv = document.createElement("div");
- this.spaceSaverDiv.style.height = wrapperDivHeight + 5 + "px";
- this.spaceSaverDiv.style.position = "relative";
- this.spaceSaverDiv.style.display = "block";
-
- this._spaceSaverContainer.appendChild(this.spaceSaverDiv);
- }
-
- this._createSeperator();
- }
- else {
- this.resetPosition();
- }
- this._topContainer.style.display = "";
-
- this.onResize();
- this.selectTab(tabControlInfo.currentTabId, false);
-
- if (this._selectedTab) {
- this._selectedTab.scrollIntoView();
- this.updateScrollButtons();
- }
- };
- /**
- * In BUX when the use scroll the widget container we need to make sure the tab control gets moved horizontally
- */
- CognosTabControl.prototype.onContainerScroll = function() {
- var container = this._scrollAttachNode ? this._scrollAttachNode : this._topContainer;
- this._topContainer.style.left = container.scrollLeft + "px";
- if (this._isTopAligned) {
- this._topContainer.style.top = container.scrollTop + "px";
- }
- else {
- this._topContainer.style.bottom = (-container.scrollTop) + "px";
- }
- };
- CognosTabControl.prototype._resetTabControl = function() {
- if (this._outsideContainer.originalClassName) {
- this._outsideContainer.className = this._outsideContainer.originalClassName;
- }
- else {
- this._outsideContainer.className = "";
- }
-
- if (this._topContainer) {
- var node = this._outsideContainer.removeChild(this._topContainer);
- node = null;
- }
-
- this._init();
- };
- /**
- Creates or updates the tab objects
- **/
- CognosTabControl.prototype._updateTabInfo = function(tabControlInfo) {
- this._isTopAligned = tabControlInfo.position == "topLeft" ? true : false;
- var tabs = tabControlInfo.tabs;
-
- // We already have tabs, make sure nothing has changed
- if (this._tabs) {
- if (this._tabs.length != tabs.length) {
- this._resetTabControl();
- }
- else {
- for (var i=0; i < this._tabs.length; i++) {
- if (tabs[i].id != this._tabs[i].getId()) {
- this._resetTabControl();
- break;
- }
- }
- }
- }
-
- if (!this._tabs) {
- this._tabs = [];
- if (!tabs) {
- return;
- }
-
- for (var ii=0; ii < tabs.length; ii++) {
- var tab = new CognosTab(tabs[ii], this, ii);
- this._tabs.push(tab);
- }
- }
- };
- CognosTabControl.prototype.getScrollPos = function() {
- return this._wrapperDiv.scrollLeft;
- };
- CognosTabControl.prototype.scrollTo = function(scrollPos) {
- this._wrapperDiv.scrollLeft = scrollPos;
- this.updateScrollButtons();
- };
- /**
- Handles the window resize event to show/hide the scroll buttons
- **/
- CognosTabControl.prototype.onResize = function(evt) {
- if (this._wrapperDiv.offsetWidth < this._totalWrapperWidth) {
- this._showScrollButtons();
- this.updateScrollButtons();
- if (this._selectedTab) {
- this._selectedTab.scrollIntoView();
- }
-
- if (this._scrollRightButton.isDisabled()) {
- this.scrollTo(this.getMaxRightScroll());
- }
- }
- else {
- this._hideScrollButtons();
- this.scrollTo(0);
- }
- };
- CognosTabControl.prototype._showScrollButtons = function() {
- if (this._scrollButtonsVisible) {
- return;
- }
- if (!this._scrollLeftButton) {
- var wrapperDivHeight = 0;
- if (this._tabs[0]) {
- wrapperDivHeight = this._tabs[0].getHeight();
- }
-
- this._scrollLeftButton = new CognosScrollButton("left", wrapperDivHeight, this);
- this._scrollLeftButton.render(this._topContainer);
-
- this._scrollRightButton = new CognosScrollButton("right", wrapperDivHeight, this);
- this._scrollRightButton.render(this._topContainer);
- }
-
- this._scrollButtonsVisible = true;
-
- this._scrollLeftButton.show();
- this._scrollRightButton.show();
-
- this._tabControlNode.style.left = this._scrollLeftButton.getWidth() - 2 + "px";
- };
- CognosTabControl.prototype.updateScrollButtons = function() {
- if (this._scrollLeftButton) {
- this._scrollLeftButton.update();
- }
-
- if (this._scrollRightButton) {
- this._scrollRightButton.update();
- }
- };
- CognosTabControl.prototype._hideScrollButtons = function() {
- if (!this._scrollButtonsVisible) {
- return;
- }
-
- this._scrollButtonsVisible = false;
-
- this._tabControlNode.style.left = "0px";
- this._scrollLeftButton.hide();
- this._scrollRightButton.hide();
- };
- /**
- Creates the line seperator that's either above or below the tabs
- **/
- CognosTabControl.prototype._createSeperator = function() {
- this._seperator = document.createElement("div");
- this._seperator.setAttribute("role", "presendation");
- this._seperator.setAttribute("style", "");
- this._seperator.className = "ct_verticalLine";
- this._seperator.setAttribute("role", "presentation");
- this._tabControlNode.appendChild(this._seperator);
- };
- /**
- Selects one tab while making sure all the other tabs are unselected
- **/
- CognosTabControl.prototype.selectTab = function(tabId, userInvokved, evt) {
- if (!evt) {
- evt = window.event;
- }
-
- for (var i=0; i < this._tabs.length; i++) {
- var tab = this._tabs[i];
- var isSelected = tab.getId() == tabId;
-
- tab.select(isSelected);
-
- if (isSelected) {
- this._selectedTab = tab;
- if (userInvokved && this._callback) {
- this._callback(tabId);
- }
- }
- if (userInvokved) {
- tab.focus(isSelected);
- }
- }
-
- if (evt && window.stopEventBubble) {
- window.stopEventBubble(evt);
- }
-
- return false;
- };
- CognosTabControl.prototype.handleKeyDown = function(evt, position) {
- if (!evt) {
- evt = window.event;
- }
-
- if (!evt) {
- return;
- }
- if (evt.keyCode == "39" || evt.keyCode == "37") {
- if (evt.keyCode == "39") { // left arrow
- position++;
- if (position >= this._tabs.length) {
- position = 0;
- }
- }
- else {
- position--;
- if (position < 0) {
- position = this._tabs.length-1;
- }
- }
-
- this._tabs[position].focus();
- this._tabs[position].scrollIntoView();
- }
- else if (evt.keyCode == "32" || evt.keyCode == "13") { // space or enter
- var tabId = this._tabs[position].getId();
- this.selectTab(tabId, true);
- }
-
- };
- /**
- Class that handles one tab in the tabControl
- **/
- function CognosTab(tabInfo, tabControl, position) {
- if (!tabInfo) {
- return;
- }
- this._id = tabInfo.id;
- this._label = tabInfo.label;
- this._position = position;
- this._contentClassName = tabInfo.className;
- this._imgURL = tabInfo.img;
- this._selected = false;
- this._tabControl = tabControl;
- this._outerTabDiv = null;
- this._focusDiv = null;
- }
- CognosTab.prototype.getWidth = function() {
- return this._outerTabDiv.offsetWidth + 1;
- };
- CognosTab.prototype.getHeight = function() {
- return this._outerTabDiv.clientHeight;
- };
- CognosTab.prototype.getId = function() {
- return this._id;
- };
- /**
- Either selects or deselects the tab
- **/
- CognosTab.prototype.select = function(selected) {
- if (selected != this._selected) {
- this._selected = selected;
- if (selected) {
- this.scrollIntoView();
- }
- if (this._outerTabDiv) {
- this._updateSelectedClass();
- this._updateAriaSelected();
- }
- }
- };
- /**
- Scroll the tab into view if necessary
- **/
- CognosTab.prototype.scrollIntoView = function() {
- var tabRightCoord = this._outerTabDiv.offsetLeft + this._outerTabDiv.clientWidth;
- var scrollLength = this._tabControl.getVisibleWidth();
- var mainScrollPos = this._tabControl.getScrollPos();
- var tabOffsetLeft = this._outerTabDiv.offsetLeft;
- if (tabOffsetLeft === 0) {
- this._tabControl.scrollTo(0);
- }
- else if ( (tabOffsetLeft >= mainScrollPos) && (tabRightCoord <= (mainScrollPos + scrollLength))) {
- // If the tab is already visible don't move the scroll position
- }
- else if (tabOffsetLeft < mainScrollPos) {
- var scrollTo = tabOffsetLeft < 3 ? 0 : tabOffsetLeft - 3;
- this._tabControl.scrollTo(scrollTo);
- }
- else if (tabRightCoord - scrollLength > 0 || tabRightCoord < mainScrollPos) {
- this._tabControl.scrollTo(tabRightCoord - scrollLength + 10);
- }
- };
- /**
- Renders a tab
- **/
- CognosTab.prototype.render = function(parentNode) {
- if (!this._outerTabDiv) {
- var tabId = this._id;
- var tabControl = this._tabControl;
- var tab = this;
- // Outer div
- this._outerTabDiv = document.createElement("div");
- this._outerTabDiv.onmousedown = function(event) { tabControl.selectTab(tabId, true, event); };
- this._outerTabDiv.onmouseover = function() { this.className = this.className + ' ct_highlight'; };
- this._outerTabDiv.onmouseout = function() { tab._updateSelectedClass(); };
- this._outerTabDiv.setAttribute("style", "");
- this._outerTabDiv.setAttribute("role", "presentation");
- this._updateSelectedClass();
- parentNode.appendChild(this._outerTabDiv);
- // This is the div that takes focus
- var textWrapperDiv = document.createElement("div");
- textWrapperDiv.className = "ct_content";
- textWrapperDiv.setAttribute("role", "presentation");
- this._outerTabDiv.appendChild(textWrapperDiv);
-
- // Tab text
- this._focusDiv = document.createElement("span");
- this._focusDiv.innerHTML = this._label ? this._label : " ";
- this._focusDiv.className = "ct_text";
- this._focusDiv.setAttribute("tabIndex", this._position === 0 ? "0" : "-1");
- this._focusDiv.setAttribute("role", "tab");
-
- this._focusDiv.onkeydown = function(event) {tabControl.handleKeyDown(event, tab._position);};
- this._updateAriaSelected();
-
- textWrapperDiv.appendChild(this._focusDiv);
-
- // Only needed in IE quirks mode since min-width doesn't work
- if (this.isIE() && this.getWidth() < 75) {
- this._outerTabDiv.style.width = "75px";
- }
-
- }
- else {
- this._updateSelectedClass();
- this._updateAriaSelected();
- }
- };
- CognosTab.prototype.isIE = function() {
- return (navigator.userAgent.indexOf('MSIE') != -1 || navigator.userAgent.indexOf('Trident') != -1);
- };
- CognosTab.prototype.getFocusableDiv = function() {
- return this._focusDiv;
- };
- CognosTab.prototype.focus = function(selected) {
- if (typeof selected === "undefined") {
- selected = true;
- }
- this._focusDiv.setAttribute("tabIndex", selected ? "0" : "-1");
- if (selected && this._focusDiv.focus) {
- this._focusDiv.focus();
- }
- };
- /**
- Update the css class attribute depending on if the tab is selected
- **/
- CognosTab.prototype._updateSelectedClass = function() {
- this._outerTabDiv.className = this._selected ? "ct_outerDiv ct_highlight ct_selected" : "ct_outerDiv";
- };
- /**
- Updated the aria-selected attribute
- **/
- CognosTab.prototype._updateAriaSelected = function() {
- this._focusDiv.setAttribute("aria-selected", this._selected ? "true" : "false");
- };
- function CognosScrollButton(direction, height, tabControl) {
- this._direction = direction;
- this._height = height;
- this._tabControl = tabControl;
- this._disabled = true;
- this._scrolling = false;
- }
- CognosScrollButton.prototype.getWidth = function() {
- return this._scrollButtonDiv.offsetWidth + 1;
- };
- CognosScrollButton.prototype.show = function() {
- this._wrapperDiv.style.display = "block";
- };
- CognosScrollButton.prototype.hide = function() {
- this._wrapperDiv.style.display = "none";
- };
- CognosScrollButton.prototype.update = function() {
- var wrapperDiv = this._tabControl.getWrapperDiv();
- var disableButton = false;
- if (this._direction == 'left') {
- if (wrapperDiv.scrollLeft === 0) {
- disableButton = true;
- }
- }
- else {
- if (wrapperDiv.scrollLeft >= (this._tabControl.getMaxRightScroll() - 2)) {
- disableButton = true;
- }
- }
- if (disableButton) {
- this._disable();
- }
- else {
- this._enable();
- }
- };
- CognosScrollButton.prototype.isDisabled = function() {
- return this._disabled;
- };
- CognosScrollButton.prototype._disable = function() {
- this._disabled = true;
- this._outerDiv.className = "ct_outerDiv ct_scrollDisabled";
- };
- CognosScrollButton.prototype._enable = function() {
- this._disabled = false;
- this._outerDiv.className = "ct_outerDiv ct_scrollEnabled";
- };
- CognosScrollButton.prototype.scroll = function() {
- if (!this._scrolling) {
- this._scrolling = true;
- var scrollLength = this._tabControl.getWrapperDiv().clientWidth;
- this._doAnimateScroll(scrollLength, this._tabControl.getMaxRightScroll());
- }
- };
- CognosScrollButton.prototype._doAnimateScroll = function(scrollLength, maxRightScroll) {
- if (scrollLength > 0) {
- var scrollOffset = 10;
-
- var wrapperDiv = this._tabControl.getWrapperDiv();
- if (this._direction == 'left') {
- if (wrapperDiv.scrollLeft > scrollOffset) {
- this._tabControl.scrollTo(wrapperDiv.scrollLeft - scrollOffset);
- }
- else {
- this._tabControl.scrollTo(0);
- this._scrolling = false;
- return;
- }
- }
- else {
- if (wrapperDiv.scrollLeft + scrollOffset < maxRightScroll) {
- this._tabControl.scrollTo(wrapperDiv.scrollLeft + scrollOffset);
- }
- else {
- this._scrolling = false;
- this._tabControl.scrollTo(maxRightScroll);
- this._tabControl.updateScrollButtons();
- return;
- }
- }
- scrollLength -= scrollOffset;
-
- var scrollButton = this;
- setTimeout(function() { scrollButton._doAnimateScroll(scrollLength, maxRightScroll);}, 3);
- }
- else {
- this._scrolling = false;
- this._tabControl.updateScrollButtons();
- }
- };
- CognosScrollButton.prototype.isIE = function() {
- return (navigator.userAgent.indexOf('MSIE') != -1 || navigator.userAgent.indexOf('Trident') != -1);
- };
- CognosScrollButton.prototype.render = function(parentNode) {
- this._scrollButtonDiv = document.createElement("div");
- this._scrollButtonDiv.className = "ct_scrollButton";
- var offset = -1;
- if (this.isIE() && document.compatMode != 'CSS1Compat') {
- // Only needed until we support standards mode. Once we do this work-around for
- // proper alignment can be removed
- offset = 1;
- }
- this._scrollButtonDiv.style.height = this._height + offset + "px";
-
- if (this._tabControl.isHighContrast()) {
- this._scrollButtonDiv.innerHTML = this._direction == "left" ? "«" : "»";
- }
-
- this._outerDiv = document.createElement("div");
-
- this._outerDiv.className = "ct_scrollDisabled";
- this._outerDiv.appendChild(this._scrollButtonDiv);
- this._outerDiv.style.height = this._height + "px";
- var scrollButton = this;
- this._outerDiv.onclick = function() {scrollButton.scroll();};
- this._wrapperDiv = document.createElement("div");
- this._wrapperDiv.style.height = this._height + "px";
- this._wrapperDiv.className = "ct_scroll " + (this._direction == "left" ? "ct_left" : "ct_right") + (this._tabControl.isHighContrast() ? " a11y" : "");
- this._wrapperDiv.appendChild(this._outerDiv);
- if (this._direction == "left") {
- parentNode.insertBefore(this._wrapperDiv, parentNode.firstChild);
- this._wrapperDiv.style.left = "0px";
- }
- else {
- parentNode.appendChild(this._wrapperDiv);
- this._wrapperDiv.style.right = "0px";
- }
- };
|