1 /* 2 * ***** BEGIN LICENSE BLOCK ***** 3 * Zimbra Collaboration Suite Web Client 4 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Synacor, Inc. 5 * 6 * The contents of this file are subject to the Common Public Attribution License Version 1.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at: https://www.zimbra.com/license 9 * The License is based on the Mozilla Public License Version 1.1 but Sections 14 and 15 10 * have been added to cover use of software over a computer network and provide for limited attribution 11 * for the Original Developer. In addition, Exhibit A has been modified to be consistent with Exhibit B. 12 * 13 * Software distributed under the License is distributed on an "AS IS" basis, 14 * WITHOUT WARRANTY OF ANY KIND, either express or implied. 15 * See the License for the specific language governing rights and limitations under the License. 16 * The Original Code is Zimbra Open Source Web Client. 17 * The Initial Developer of the Original Code is Zimbra, Inc. All rights to the Original Code were 18 * transferred by Zimbra, Inc. to Synacor, Inc. on September 14, 2015. 19 * 20 * All portions of the code are Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Synacor, Inc. All Rights Reserved. 21 * ***** END LICENSE BLOCK ***** 22 */ 23 24 25 /** 26 * Creates a tab view. 27 * @constructor 28 * @class 29 * This class represents a tabbed view. {@link DwtTabView} manages the z-index of the contained tabs. 30 * 31 * @param {hash} params a hash of parameters 32 * @param {DwtComposite} parent the parent widget 33 * @param {string} className the CSS class 34 * @param {constant} posStyle the positioning style (see {@link DwtControl}) 35 * @param {string} id an explicit ID to use for the control's HTML element 36 * 37 * @author Greg Solovyev 38 * 39 * @extends DwtComposite 40 */ 41 DwtTabView = function(params) { 42 if (arguments.length == 0) return; 43 params = Dwt.getParams(arguments, DwtListView.PARAMS); 44 params.className = params.className || "ZTabView"; 45 params.posStyle = params.posStyle || DwtControl.ABSOLUTE_STYLE; 46 DwtComposite.call(this, params); 47 48 this._stateChangeEv = new DwtEvent(true); 49 this._stateChangeEv.item = this; 50 51 this._tabs = []; 52 this._tabIx = 1; 53 this._createHtml(); 54 55 var tabGroupId = [this.toString(), this._htmlElId].join(" "); 56 this._tabGroup = new DwtTabGroup(tabGroupId); 57 this._tabGroup.addMember(this._tabBar); 58 }; 59 60 DwtTabView.PARAMS = ["parent", "className", "posStyle"]; 61 62 DwtTabView.prototype = new DwtComposite; 63 DwtTabView.prototype.constructor = DwtTabView; 64 65 DwtTabView.prototype.isDwtTabView = true; 66 DwtTabView.prototype.toString = function() { return "DwtTabView"; }; 67 68 DwtTabView.prototype.role = 'tablist'; 69 70 // Constants 71 72 // Z-index consts for tabbed view contents are based on Dwt z-index consts 73 DwtTabView.Z_ACTIVE_TAB = Dwt.Z_VIEW+10; 74 DwtTabView.Z_HIDDEN_TAB = Dwt.Z_HIDDEN; 75 DwtTabView.Z_TAB_PANEL = Dwt.Z_VIEW+20; 76 DwtTabView.Z_CURTAIN = Dwt.Z_CURTAIN; 77 78 DwtTabView.prototype.TEMPLATE = "dwt.Widgets#ZTabView"; 79 80 81 // Public methods 82 83 84 /** 85 * Adds a state change listener. 86 * 87 * @param {AjxListener} listener the listener 88 */ 89 DwtTabView.prototype.addStateChangeListener = 90 function(listener) { 91 this._eventMgr.addListener(DwtEvent.STATE_CHANGE, listener); 92 }; 93 94 /** 95 * Removes a state change listener. 96 * 97 * @param {AjxListener} listener the listener 98 */ 99 DwtTabView.prototype.removeStateChangeListener = 100 function(listener) { 101 this._eventMgr.removeListener(DwtEvent.STATE_CHANGE, listener); 102 }; 103 104 DwtTabView.prototype.getTabGroupMember = function() { 105 return this._tabGroup; 106 }; 107 108 /** 109 * Adds a tab. 110 * 111 * @param {string} title the text for the tab button 112 * @param {DwtTabViewPage|AjxCallback} tabViewOrCallback an instance of the tab view page or callback that returns an instance of {@link DwtTabViewPage} 113 * 114 * @return {string} key for the added tab This key can be used to retrieve the tab using {@link #getTab} 115 * 116 * @see #getTab 117 */ 118 DwtTabView.prototype.addTab = 119 function (title, tabViewOrCallback, buttonId, index) { 120 var tabKey = this._tabIx++; 121 122 // create tab entry 123 this._tabs[tabKey] = { 124 title: title, 125 button: this._tabBar.addButton(tabKey, title, buttonId, index) 126 }; 127 128 // add the page 129 this.setTabView(tabKey, tabViewOrCallback); 130 131 // show the first tab 132 if (tabKey==1) { 133 var tabView = this.getTabView(tabKey); 134 if(tabView) { 135 tabViewOrCallback.showMe(); 136 } 137 this._currentTabKey = tabKey; 138 this.switchToTab(tabKey); 139 } 140 // hide all the other tabs 141 else if (tabViewOrCallback && !(tabViewOrCallback instanceof AjxCallback)) { 142 tabViewOrCallback.hideMe(); 143 Dwt.setVisible(tabViewOrCallback.getHtmlElement(), false); 144 } 145 146 this._tabBar.addSelectionListener(tabKey, new AjxListener(this, DwtTabView.prototype._tabButtonListener)); 147 148 return tabKey; 149 }; 150 151 DwtTabView.prototype.enable = 152 function(enable) { 153 for (var i in this._tabs) { 154 var button = this._tabs[i].button; 155 if (button) { 156 button.setEnabled(enable); 157 } 158 } 159 }; 160 161 /** 162 * Gets the current tab. 163 * 164 * @return {string} the tab key 165 */ 166 DwtTabView.prototype.getCurrentTab = 167 function() { 168 return this._currentTabKey; 169 }; 170 171 /** 172 * Gets the tab count. 173 * 174 * @return {number} the number of tabs 175 */ 176 DwtTabView.prototype.getNumTabs = 177 function() { 178 return (this._tabs.length - 1); 179 }; 180 181 /** 182 * Gets the tab. 183 * 184 * @param {string} tabKey the key for the tab 185 * 186 * @return {DwtTabViewPage} the view tab 187 * 188 * @see #addTab 189 */ 190 DwtTabView.prototype.getTab = 191 function (tabKey) { 192 return (this._tabs && this._tabs[tabKey]) 193 ? this._tabs[tabKey] 194 : null; 195 }; 196 197 /** 198 * Gets the tab bar. 199 * 200 * @return {DwtTabBar} the tab bar 201 */ 202 DwtTabView.prototype.getTabBar = function() { 203 return this._tabBar; 204 }; 205 206 /** 207 * Gets the tab title. 208 * 209 * @param {string} tabKey the tab key 210 * 211 * @return {string} the title 212 */ 213 DwtTabView.prototype.getTabTitle = 214 function(tabKey) { 215 return (this._tabs && this._tabs[tabKey]) 216 ? this._tabs[tabKey]["title"] 217 : null; 218 }; 219 220 /** 221 * Gets the tab button. 222 * 223 * @param {string} tabKey the tab key 224 * 225 * @return {DwtTabButton} the tab button 226 */ 227 DwtTabView.prototype.getTabButton = 228 function(tabKey) { 229 return (this._tabs && this._tabs[tabKey]) 230 ? this._tabs[tabKey]["button"] 231 : null; 232 }; 233 234 /** 235 * Sets the tab view. 236 * 237 * @param {string} tabKey the tab key 238 * @param {DwtTabViewPage|AjxCallback} tabView an instance of the tab view page or callback that returns an instance of {@link DwtTabViewPage} 239 */ 240 DwtTabView.prototype.setTabView = 241 function(tabKey, tabView) { 242 var tab = this.getTab(tabKey); 243 tab.view = tabView; 244 if (tabView && !(tabView instanceof AjxCallback)) { 245 this._pageEl.appendChild(tabView.getHtmlElement()); 246 tabView._tabKey = tabKey; 247 if (tabKey == this._currentTabKey) { 248 var tabGroup = tabView.getTabGroupMember(); 249 this._tabGroup.replaceMember(tab.tabGroup, tabGroup); 250 tab.tabGroup = tabGroup; 251 } 252 } 253 }; 254 255 /** 256 * Gets the tab view. 257 * 258 * @param {string} tabKey the tab key 259 * 260 * @return {DwtTabViewPage} the tab view page 261 */ 262 DwtTabView.prototype.getTabView = 263 function(tabKey) { 264 var tab = this.getTab(tabKey); 265 var tabView = tab && tab.view; 266 if (tabView instanceof AjxCallback) { 267 var callback = tabView; 268 tabView = callback.run(tabKey); 269 this.setTabView(tabKey, tabView); 270 var size = this._getTabSize(); 271 tabView.setSize(size.x, size.y); 272 tabView.setAttribute('aria-labelledby', tab.button.getHTMLElId()); 273 } 274 return tabView; 275 }; 276 277 /** 278 * Switches to the tab view. 279 * 280 * @param {string} tabKey the tab key 281 */ 282 DwtTabView.prototype.switchToTab = 283 function(tabKey) { 284 var ntab = this.getTab(tabKey); 285 if(ntab) { 286 // remove old tab from tab-group 287 var otab = this.getTab(this._currentTabKey); 288 if (otab) { 289 this._tabGroup.removeMember(otab.tabGroup); 290 } 291 // switch tab 292 this._showTab(tabKey); 293 this._tabBar.openTab(tabKey); 294 // add new tab to tab-group 295 if (!ntab.tabGroup && ntab.view) { 296 ntab.tabGroup = ntab.view.getTabGroupMember(); 297 } 298 this._tabGroup.addMember(ntab.tabGroup); 299 // notify change 300 if (this._eventMgr.isListenerRegistered(DwtEvent.STATE_CHANGE)) { 301 this._eventMgr.notifyListeners(DwtEvent.STATE_CHANGE, this._stateChangeEv); 302 } 303 } 304 }; 305 306 DwtTabView.prototype.setBounds = 307 function(x, y, width, height) { 308 DwtComposite.prototype.setBounds.call(this, x, y, width, height); 309 this._resetTabSizes(width, height); 310 }; 311 312 DwtTabView.prototype.getActiveView = 313 function() { 314 return this._tabs[this._currentTabKey].view; 315 }; 316 317 DwtTabView.prototype.getKeyMapName = 318 function() { 319 return DwtKeyMap.MAP_TAB_VIEW; 320 }; 321 322 DwtTabView.prototype.resetKeyBindings = 323 function() { 324 var kbm = this.shell.getKeyboardMgr(); 325 if (kbm.isEnabled()) { 326 var kmm = kbm.__keyMapMgr; 327 if (!kmm) { return; } 328 var num = this.getNumTabs(); 329 var seqs = kmm.getKeySequences(DwtKeyMap.MAP_TAB_VIEW, "GoToTab"); 330 for (var k = 0; k < seqs.length; k++) { 331 var ks = seqs[k]; 332 for (var i = 1; i <= num; i++) { 333 var keycode = 48 + i; 334 var newKs = ks.replace(/NNN/, keycode); 335 kmm.setMapping(DwtKeyMap.MAP_TAB_VIEW, newKs, "GoToTab" + i); 336 } 337 } 338 kmm.reloadMap(DwtKeyMap.MAP_TAB_VIEW); 339 } 340 }; 341 342 DwtTabView.prototype.handleKeyAction = 343 function(actionCode) { 344 DBG.println(AjxDebug.DBG3, "DwtTabView.handleKeyAction"); 345 346 switch (actionCode) { 347 348 case DwtKeyMap.NEXT_TAB: 349 var curTab = this.getCurrentTab(); 350 if (curTab < this.getNumTabs()) { 351 this.switchToTab(curTab + 1); 352 } 353 break; 354 355 case DwtKeyMap.PREV_TAB: 356 var curTab = this.getCurrentTab(); 357 if (curTab > 1) { 358 this.switchToTab(curTab - 1); 359 } 360 break; 361 362 default: 363 // Handle action code like "GoToTab3" 364 var m = actionCode.match(DwtKeyMap.GOTO_TAB_RE); 365 if (m && m.length) { 366 var idx = m[1]; 367 if ((idx <= this.getNumTabs()) && (idx != this.getCurrentTab())) { 368 this.switchToTab(idx); 369 } 370 } else { 371 return false; 372 } 373 } 374 return true; 375 }; 376 377 378 // Protected methods 379 380 DwtTabView.prototype._resetTabSizes = 381 function (width, height) { 382 if (this._tabs && this._tabs.length) { 383 for (var curTabKey in this._tabs) { 384 var tabView = this._tabs[curTabKey].view; 385 if (tabView && !(tabView instanceof AjxCallback)) { 386 var contentHeight; 387 contentHeight = contentHeight || height - Dwt.getSize(this._tabBarEl).y; 388 tabView.resetSize(width, contentHeight); 389 } 390 } 391 } 392 }; 393 394 DwtTabView.prototype._getTabSize = 395 function() { 396 var size = this.getSize(); 397 var width = size.x || this.getHtmlElement().clientWidth; 398 var height = size.y || this.getHtmlElement().clientHeight; 399 var tabBarSize = this._tabBar.getSize(); 400 var tabBarHeight = tabBarSize.y || this._tabBar.getHtmlElement().clientHeight; 401 402 return new DwtPoint(width, (height - tabBarHeight)); 403 }; 404 405 DwtTabView.prototype._createHtml = 406 function(templateId) { 407 this._createHtmlFromTemplate(templateId || this.TEMPLATE, {id:this._htmlElId}); 408 }; 409 410 DwtTabView.prototype._createHtmlFromTemplate = 411 function(templateId, data) { 412 DwtComposite.prototype._createHtmlFromTemplate.call(this, templateId, data); 413 414 this._tabBarEl = document.getElementById(data.id+"_tabbar"); 415 this._tabBar = new DwtTabBar(this); 416 this._tabBar.reparentHtmlElement(this._tabBarEl); 417 this._pageEl = document.getElementById(data.id+"_page"); 418 }; 419 420 DwtTabView.prototype._showTab = 421 function(tabKey) { 422 if (this._tabs && this._tabs[tabKey]) { 423 this._currentTabKey = tabKey; 424 this._hideAllTabs(); // hide all the tabs 425 var tabView = this.getTabView(tabKey); // make this tab visible 426 if (tabView) { 427 tabView.setVisible(true); 428 tabView.showMe(); 429 } 430 } 431 }; 432 433 DwtTabView.prototype._hideAllTabs = 434 function() { 435 if (this._tabs && this._tabs.length) { 436 for (var curTabKey in this._tabs) { 437 var tabView = this._tabs[curTabKey].view; 438 if (tabView && !(tabView instanceof AjxCallback)) { 439 tabView.hideMe(); 440 //this._tabs[curTabKey]["view"].setZIndex(DwtTabView.Z_HIDDEN_TAB); 441 Dwt.setVisible(tabView.getHtmlElement(), false); 442 } 443 } 444 } 445 }; 446 447 DwtTabView.prototype._tabButtonListener = 448 function (ev) { 449 this.switchToTab(ev.item.getData("tabKey")); 450 }; 451 452 453 // 454 // Class 455 // 456 457 /** 458 * Creates a tab view page. 459 * @constructor 460 * @class 461 * DwtTabViewPage abstract class for a page in a tabbed view. 462 * Tab pages are responsible for creating their own HTML and populating/collecting 463 * data to/from any form fields that they display. 464 * 465 * @param {DwtComposite} parent the parent widget 466 * @param {string} className the CSS class 467 * @param {constant} posStyle the positioning style (see {@link DwtControl}) 468 * 469 * @extends DwtPropertyPage 470 */ 471 DwtTabViewPage = function(parent, className, posStyle, id) { 472 if (arguments.length == 0) return; 473 var params = Dwt.getParams(arguments, DwtTabViewPage.PARAMS); 474 params.className = params.className || "ZTabPage"; 475 params.posStyle = params.posStyle || DwtControl.ABSOLUTE_STYLE; 476 params.id = id || null; 477 this._rendered = true; // by default UI creation is not lazy 478 479 DwtPropertyPage.call(this, params); 480 481 this._createHtml(); 482 this.getHtmlElement().style.overflowY = "auto"; 483 this.getHtmlElement().style.overflowX = "visible"; 484 if (params.contentTemplate) { 485 this.getContentHtmlElement().innerHTML = AjxTemplate.expand(params.contentTemplate, this._htmlElId); 486 } 487 }; 488 489 DwtTabViewPage.prototype = new DwtPropertyPage; 490 DwtTabViewPage.prototype.constructor = DwtTabViewPage; 491 492 DwtTabViewPage.prototype.isDwtTabViewPage = true; 493 DwtTabViewPage.prototype.toString = function() { return "DwtTabViewPage"; }; 494 495 DwtTabViewPage.prototype.role = 'tabpanel'; 496 497 498 DwtTabViewPage.prototype.TEMPLATE = "dwt.Widgets#ZTabPage"; 499 500 DwtTabViewPage.PARAMS = DwtPropertyPage.PARAMS.concat("contentTemplate"); 501 502 // Public methods 503 504 /** 505 * Gets the content HTML element. 506 * 507 * @return {Element} the element 508 */ 509 DwtTabViewPage.prototype.getContentHtmlElement = 510 function() { 511 return this._contentEl || this.getHtmlElement(); 512 }; 513 514 /** 515 * Shows the tab view page. 516 * 517 */ 518 DwtTabViewPage.prototype.showMe = 519 function() { 520 this.setZIndex(DwtTabView.Z_ACTIVE_TAB); 521 this.setAttribute('aria-selected', true); 522 if (this.parent.getHtmlElement().offsetHeight > 80) { // if parent visible, use offsetHeight 523 this._contentEl.style.height=this.parent.getHtmlElement().offsetHeight-80; 524 } else { 525 var parentHeight = parseInt(this.parent.getHtmlElement().style.height); // if parent not visible, resize page to fit parent 526 var units = AjxStringUtil.getUnitsFromSizeString(this.parent.getHtmlElement().style.height); 527 if (parentHeight > 80) { 528 this._contentEl.style.height = (Number(parentHeight-80).toString() + units); 529 } 530 } 531 532 this._contentEl.style.width = this.parent.getHtmlElement().style.width; // resize page to fit parent 533 }; 534 535 /** 536 * Hides the tab view page. 537 */ 538 DwtTabViewPage.prototype.hideMe = 539 function() { 540 this.setZIndex(DwtTabView.Z_HIDDEN_TAB); 541 this.setAttribute('aria-selected', false); 542 }; 543 544 /** 545 * Resets the size. 546 * 547 * @param {number|string} newWidth the width of the control (for example: 100, "100px", "75%", {@link Dwt.DEFAULT}) 548 * @param {number|string} newHeight the height of the control (for example: 100, "100px", "75%", {@link Dwt.DEFAULT}) 549 */ 550 DwtTabViewPage.prototype.resetSize = 551 function(newWidth, newHeight) { 552 this.setSize(newWidth, newHeight); 553 }; 554 555 556 // Protected methods 557 558 DwtTabViewPage.prototype._createHtml = 559 function(templateId) { 560 this._createHtmlFromTemplate(templateId || this.TEMPLATE, {id:this._htmlElId}); 561 }; 562 563 DwtTabViewPage.prototype._createHtmlFromTemplate = 564 function(templateId, data) { 565 DwtPropertyPage.prototype._createHtmlFromTemplate.call(this, templateId, data); 566 this._contentEl = document.getElementById(data.id+"_content") || this.getHtmlElement(); 567 }; 568 569 570 // 571 // Class 572 // 573 574 /** 575 * Creates a tab bar. 576 * @constructor 577 * @class 578 * This class represents the tab bar, which is effectively a tool bar. 579 * 580 * @param {DwtComposite} parent the parent widget 581 * @param {string} tabCssClass the tab CSS class 582 * @param {string} btnCssClass the button CSS class 583 * 584 * @extends DwtToolBar 585 */ 586 DwtTabBar = function(parent, tabCssClass, btnCssClass) { 587 if (arguments.length == 0) return; 588 589 this._buttons = []; 590 this._btnStyle = btnCssClass || "ZTab"; // REVISIT: not used 591 this._btnImage = null; 592 this._currentTabKey = 1; 593 var myClass = tabCssClass || "ZTabBar"; 594 595 DwtToolBar.call(this, {parent:parent, className:myClass, posStyle:DwtControl.STATIC_STYLE}); 596 597 //Temp solution for bug 55391 598 //It is caused by float attribute in the td. The best solution is just as the main tab. No td 599 //wrap the div. And this modification shouldn't affect the subclasses DwtTabBarFloat, otherwise, the _CASE_ 600 //xform item will be affect. 601 //To do: modify it as the same as main tab 602 if(AjxEnv.isFirefox){ 603 if(this._prefixEl && this.constructor == DwtTabBar) 604 this._prefixEl.style.cssFloat = "none"; 605 } 606 }; 607 608 DwtTabBar.prototype = new DwtToolBar; 609 DwtTabBar.prototype.constructor = DwtTabBar; 610 611 612 // Constants 613 614 DwtTabBar.prototype.TEMPLATE = "dwt.Widgets#ZTabBar"; 615 616 617 // Public methods 618 619 DwtTabBar.prototype.toString = 620 function() { 621 return "DwtTabBar"; 622 }; 623 624 /** 625 * Gets the current tab. 626 * 627 * @return {string} the tab key 628 */ 629 DwtTabBar.prototype.getCurrentTab = 630 function() { 631 return this._currentTabKey; 632 }; 633 634 /** 635 * Adds a state change listener. 636 * 637 * @param {AjxListener} listener the listener 638 */ 639 DwtTabBar.prototype.addStateChangeListener = 640 function(listener) { 641 this._eventMgr.addListener(DwtEvent.STATE_CHANGE, listener); 642 }; 643 644 /** 645 * Removes a state change listener. 646 * 647 * @param {AjxListener} listener the listener 648 */ 649 DwtTabBar.prototype.removeStateChangeListener = 650 function(listener) { 651 this._eventMgr.removeListener(DwtEvent.STATE_CHANGE, listener); 652 }; 653 654 /** 655 * Adds a selection listener. 656 * 657 * @param {string} tabKey the id used to create tab button in {@link DwtTabBar.addButton} 658 * @param {AjxListener} listener the listener 659 */ 660 DwtTabBar.prototype.addSelectionListener = 661 function(tabKey, listener) { 662 this._buttons[tabKey].addSelectionListener(listener); 663 }; 664 665 /** 666 * Removes a selection listener. 667 * 668 * @param {string} tabKey the id used to create tab button in {@link DwtTabBar.addButton} 669 * @param {AjxListener} listener the listener 670 */ 671 DwtTabBar.prototype.removeSelectionListener = 672 function(tabKey, listener) { 673 this._buttons[tabKey].removeSelectionListener(listener); 674 }; 675 676 /** 677 * Adds a button. 678 * 679 * @param {string} tabKey the the tab key 680 * @param {string} tabTitle the tab title 681 * @param {string} id the id 682 * @param {number} index the index 683 * 684 * @return {DwtTabButton} the newly added button 685 */ 686 DwtTabBar.prototype.addButton = 687 function(tabKey, tabTitle, id, index) { 688 var b = this._buttons[tabKey] = new DwtTabButton(this, id, index); 689 690 this._buttons[tabKey].addSelectionListener(new AjxListener(this, DwtTabBar._setActiveTab)); 691 692 if (this._btnImage != null) { 693 b.setImage(this._btnImage); 694 } 695 696 if (tabTitle != null) { 697 b.setText(tabTitle); 698 } 699 700 b.setEnabled(true); 701 b.setData("tabKey", tabKey); 702 703 if (parseInt(tabKey) == 1) { 704 this.openTab(tabKey, true); 705 } 706 707 // make sure that new button is selected properly 708 var sindex = this.__getButtonIndex(this._currentTabKey); 709 if (sindex != -1) { 710 var nindex = this.__getButtonIndex(tabKey); 711 if (nindex == sindex + 1) { 712 Dwt.addClass(b.getHtmlElement(), DwtTabBar.SELECTED_NEXT); 713 } 714 } 715 716 return b; 717 }; 718 719 /** 720 * Gets the button. 721 * 722 * @param {string} tabKey the id used to create tab button in {@link DwtTabBar.addButton} 723 * 724 * @return {DwtTabButton} the button 725 */ 726 DwtTabBar.prototype.getButton = 727 function (tabKey) { 728 return (this._buttons[tabKey]) 729 ? this._buttons[tabKey] 730 : null; 731 }; 732 733 /** 734 * Opens the tab. 735 * 736 * @param {string} tabKey the id used to create tab button in {@link DwtTabBar.addButton} 737 * @param {boolean} skipNotify if <code>true</code>, do not notify listeners 738 */ 739 DwtTabBar.prototype.openTab = 740 function(tabK, skipNotify) { 741 this._currentTabKey = tabK; 742 var cnt = this._buttons.length; 743 744 for (var ix = 0; ix < cnt; ix ++) { 745 if (ix==tabK) { continue; } 746 747 var button = this._buttons[ix]; 748 if (button) { 749 this.__markPrevNext(ix, false); 750 button.setClosed(); 751 } 752 } 753 754 var button = this._buttons[tabK]; 755 if (button) { 756 button.setOpen(); 757 this.__markPrevNext(tabK, true); 758 } 759 760 if (!skipNotify && this._eventMgr.isListenerRegistered(DwtEvent.STATE_CHANGE)) { 761 this._eventMgr.notifyListeners(DwtEvent.STATE_CHANGE, this._stateChangeEv); 762 } 763 }; 764 765 /** 766 * Greg Solovyev 1/4/2005 767 * changed ev.target.offsetParent.offsetParent to 768 * lookup for the table up the elements stack, because the mouse down event may come from the img elements 769 * as well as from the td elements. 770 * 771 * @private 772 */ 773 DwtTabBar._setActiveTab = 774 function(ev) { 775 var tabK; 776 if (ev && ev.item) { 777 tabK=ev.item.getData("tabKey"); 778 } else if (ev && ev.target) { 779 var elem = ev.target; 780 while (elem.tagName != "TABLE" && elem.offsetParent ) 781 elem = elem.offsetParent; 782 783 tabK = elem.getAttribute("tabKey"); 784 if (tabK == null) 785 return false; 786 } else { 787 return false; 788 } 789 this.openTab(tabK); 790 }; 791 792 793 // 794 // Class 795 // 796 797 /** 798 * Creates a tab button (i.e. a tab in a tab view). 799 * @constructor 800 * @class 801 * This class represents the tab in a tab view. 802 * 803 * @param {DwtComposite} parent the parent widget 804 * @param {string} id the id 805 * @param {number} index the index 806 * @param {string} className the style class name 807 * 808 * @extends DwtButton 809 */ 810 DwtTabButton = function(parent, id, index, className) { 811 if (arguments.length == 0) return; 812 var tabStyle = className || "ZTab"; 813 DwtButton.call(this, {parent:parent, className:tabStyle, id:id, index:index}); 814 }; 815 816 DwtTabButton.prototype = new DwtButton; 817 DwtTabButton.prototype.constructor = DwtTabButton; 818 819 DwtTabButton.prototype.TEMPLATE = "dwt.Widgets#ZTab"; 820 821 DwtTabButton.prototype.isDwtTabButton = true; 822 DwtTabButton.prototype.toString = function() { return "DwtTabButton"; }; 823 824 DwtTabButton.prototype.role = 'tab'; 825 826 // Public methods 827 828 829 /** 830 * Changes the visual appearance to active tab. 831 */ 832 DwtTabButton.prototype.setOpen = 833 function() { 834 this._isSelected = true; 835 this.setDisplayState(DwtControl.SELECTED); 836 }; 837 838 /** 839 * Changes the visual appearance to inactive tab. 840 */ 841 DwtTabButton.prototype.setClosed = 842 function() { 843 this._isSelected = false; 844 this.setDisplayState(DwtControl.NORMAL); 845 }; 846 847 DwtTabButton.prototype.setDisplayState = function(state) { 848 if (this._isSelected && state != DwtControl.SELECTED) { 849 state = [ DwtControl.SELECTED, state ].join(" "); 850 } 851 DwtButton.prototype.setDisplayState.call(this, state); 852 }; 853 854 855 /** 856 * @class 857 * @constructor 858 * 859 * @param {DwtComposite} parent the parent widget 860 * @param {string} tabCssClass the tab CSS class 861 * @param {string} btnCssClass the button CSS class 862 * 863 * @extends DwtTabButton 864 * 865 * @private 866 */ 867 DwtTabBarFloat = function(parent, tabCssClass, btnCssClass) { 868 if (arguments.length == 0) return; 869 DwtTabBar.call(this,parent,tabCssClass,btnCssClass) 870 }; 871 872 DwtTabBarFloat.prototype = new DwtTabBar; 873 DwtTabBarFloat.prototype.constructor = DwtTabBarFloat; 874 875 DwtTabBarFloat.prototype.TEMPLATE = "dwt.Widgets#ZTabBarFloat"; 876 877 /** 878 * Adds a button. 879 * 880 * @param {string} tabKey the the tab key 881 * @param {string} tabTitle the tab title 882 * @param {string} id the id 883 * 884 * @return {DwtTabButton} the newly added button 885 */ 886 DwtTabBarFloat.prototype.addButton = 887 function(tabKey, tabTitle, id) { 888 var b = this._buttons[tabKey] = new DwtTabButtonFloat(this, id); 889 890 this._buttons[tabKey].addSelectionListener(new AjxListener(this, DwtTabBar._setActiveTab)); 891 892 if (this._btnImage != null) { 893 b.setImage(this._btnImage); 894 } 895 896 if (tabTitle != null) { 897 b.setText(tabTitle); 898 } 899 900 b.setEnabled(true); 901 b.setData("tabKey", tabKey); 902 903 if (parseInt(tabKey) == 1) { 904 this.openTab(tabKey, true); 905 } 906 907 // make sure that new button is selected properly 908 var sindex = this.__getButtonIndex(this._currentTabKey); 909 if (sindex != -1) { 910 var nindex = this.__getButtonIndex(tabKey); 911 if (nindex == sindex + 1) { 912 Dwt.addClass(b.getHtmlElement(), DwtTabBar.SELECTED_NEXT); 913 } 914 } 915 916 return b; 917 }; 918 919 DwtTabButtonFloat = function(parent, id) { 920 DwtTabButton.call(this, parent,id, undefined, "ZTab"); 921 }; 922 923 DwtTabButtonFloat.prototype = new DwtTabButton; 924 DwtTabButtonFloat.prototype.constructor = DwtTabButtonFloat; 925 926 DwtTabButtonFloat.prototype.TEMPLATE = "dwt.Widgets#ZTabFloat"; 927