You might remember.
This Tab Pane control is.
The Tab Pane.
To.
The.
Below is the code for a simple tab pane with the tab pages.
<div class="tab-pane" id="tab-pane-1"> <div class="tab-page"> <h2 class="tab">General</h2> This is text of tab 1. This is text of tab 1. This is text of tab 1. This is text of tab 1. </div> <div class="tab-page"> <h2 class="tab">Privacy</h2> This is text of tab 2. This is text of tab 2. This is text of tab 2. This is text of tab 2. </div> </div>
Notice that the id
is not needed unless two or more tab panes
are present in the same document and you are using the persistence feature.
The best way to.
This is the
new WebFXTabPane(oElement [, bUseCookie])
Name | Type | Descripton |
oElement |
HTMLElement |
The html element that represents the tab pane |
bUseCookie |
Boolean |
Optional.
If this is set to true then the selected tab is persisted.
The default value is true .
|
Name | Description | ||||||||||||
setCookieSyntax
Arguments
Return Type
|
Sets a cookie | ||||||||||||
getCookieSyntax
Arguments
Return Type
|
Retrieves a cookie by name | ||||||||||||
removeCookieSyntax
Arguments
Return Type
|
Removes a cookie by name |
Name | Type | Descripton |
None. |
Name | Description | ||||||
addTabPageSyntax
Arguments
Return Type
|
Adds a tab page by passing an html element | ||||||
getSelectedIndexSyntax
ArgumentsNo Arguments. Return Type
|
The index of the selected tab page | ||||||
setSelectedIndexSyntax
Arguments
Return Type
|
Sets the selected tab page by index |
Name | Type | Descripton |
classNameTag |
String |
This string is added to the class name to tag the tab pane as beeing created |
element |
HTMLElement |
Read only.The html element being that represents the tab pane |
pages |
WebFXTabPages[] |
Read only.An array containing the tab pages |
selectedIndex |
Number |
Read only.The index of the selected tab page |
tabRow |
HTMLElement |
Read only.The html element that encloses all tabs |
useCookie |
Boolean |
Is used to decide if the selected tab page index should be persisted using a cookie. |
None.
This is the class representing a tab page.
new WebFXTabPage(oElement, oTabPane, nIndex)
Name | Type | Descripton |
oElement |
HTMLElement |
The html element that represents the tab page |
oTabPane |
WebFXTabPane |
The tab pane to add the page to |
nIndex |
Number |
The index of the tab page |
Name | Description |
None. |
Name | Type | Descripton |
None. |
Name | Description |
hideSyntax
ArgumentsNo Arguments. Return Type
|
Hides the tab page |
selectSyntax
ArgumentsNo Arguments. Return Type
|
Selects the tab page |
showSyntax
ArgumentsNo Arguments. Return Type
|
Makes the tab page visible |
Name | Type | Descripton |
element |
HTMLElement |
Read only.The html element being used as the page |
index |
Number |
Read only. The index of the tab page in the tab pane pages array. |
tab |
HTMLElement |
Read only.The html element being used as the tab. |
Do not use this constructor manually. Use addTabPage of the WebFXTabPane class instead.
Name | Description |
hasSupportSyntax
ArgumentsNo Arguments. Return Type
|
Returns whether the browser is supported or not |
setupAllTabsSyntax
ArgumentsNo Arguments. Return Type
|
Initializes all tab panes and tab pages that have not been initialized already. |
Name | Type | Descripton |
None. |
The way to check the browser whether it support a certain feature in the
DOM is to use the method document.implementation.hasFeature
.
However since IE5.5 supports all the features that this script needs but it
does not support this way of checking for support we have to add a separate
check for IE55.
function hasSupport() { if (typeof hasSupport.support != "undefined") return hasSupport.support; var ie55 = /msie 5\.[56789]/i.test( navigator.userAgent ); hasSupport.support = ( typeof document.implementation != "undefined" && document.implementation.hasFeature( "html", "1.0" ) || ie55 ) // IE55 has a serious DOM1 bug... Patch it! if ( ie55 ) { document._getElementsByTagName = document.getElementsByTagName; document.getElementsByTagName = function ( sTagName ) { if ( sTagName == "*" ) return document.all; else return document._getElementsByTagName( sTagName ); }; } return hasSupport.support; }
As you can see in the code above IE55 has a bug an therefore we also patch that. Too many people are still using IE55 to just ignore it.
The constructor for the tab pane creates the tabRow
div
that is used to place all the actual tabs in. It also checks the cookie
state so that the selected tab can be persisted. Besides from this it
sets up some properties needed to keep track of the states. Last but not
least it checks the childNodes
of the element and adds
the found tab pages.
function WebFXTabPane( el, bUseCookie ) { if ( !hasSupport() || el == null ) return; this.element = el; this.element.tabPane = this; this.pages = []; this.selectedIndex = null; this.useCookie = bUseCookie != null ? bUseCookie : true; // add class name tag to class name this.element.className = this.classNameTag + " " + this.element.className; // add tab row this.tabRow = document.createElement( "div" ); this.tabRow.className = "tab-row"; el.insertBefore( this.tabRow, el.firstChild ); var tabIndex = 0; if ( this.useCookie ) { tabIndex = Number( WebFXTabPane.getCookie( "webfxtab_" + this.element.id ) ); if ( isNaN( tabIndex ) ) tabIndex = 0; } this.selectedIndex = tabIndex; // loop through child nodes and add them var cs = el.childNodes; var n; for (var i = 0; i < cs.length; i++) { if (cs[i].nodeType == 1 && cs[i].className == "tab-page") { this.addTabPage( cs[i] ); } } }
There are a few methods added to the WebFXTabPane
class and one of the
more important ones is the method addTabPage
. This method takes the element
that represents the tab page and uses that to create a WebFXTabPage
object that is added to the pages
array. Once the tab page has been
added it also checks if this page is the selected one and if it is it shows it.
WebFXTabPane.prototype = { ... addTabPage: function ( oElement ) { if ( !hasSupport() ) return; if ( oElement.tabPage == this ) // already added return oElement.tabPage; var n = this.pages.length; var tp = this.pages[n] = new WebFXTabPage( oElement, this, n ); tp.tabPane = this; // move the tab out of the box this.tabRow.appendChild( tp.tab ); if ( n == this.selectedIndex ) tp.show(); else tp.hide(); return tp; } };
This class is used to keep track of the actual tab page. Once created it moves
the tab element to the tabRow
of the tab pane. It also adds
an anchor around the text so that the user can use the keyboard to activate the
tabs.
function WebFXTabPage( el, tabPane, nIndex ) { if ( !hasSupport() || el == null ) return; this.element = el; this.element.tabPage = this; this.index = nIndex; var cs = el.childNodes; for (var i = 0; i < cs.length; i++) { if (cs[i].nodeType == 1 && cs[i].className == "tab") { this.tab = cs[i]; break; } } // insert a tag around content to support keyboard navigation var a = document.createElement( "A" ); a.href = "javascript:void 0;"; while ( this.tab.hasChildNodes() ) a.appendChild( this.tab.firstChild ); this.tab.appendChild( a ); // hook up events, using DOM0 var oThis = this; this.tab.onclick = function () { oThis.select(); }; this.tab.onmouseover = function () { WebFXTabPage.tabOver( oThis ); }; this.tab.onmouseout = function () { WebFXTabPage.tabOut( oThis ); }; }
The initialization uses the global function setupAllTabs
that
goes through all elements and checks their class names and if the class names
match the classes used by the tab pane controls it checks whether this element
belongs to an uninitialized control and in that case it initializes it now.
function setupAllTabs() { if ( !hasSupport() ) return; var all = document.getElementsByTagName( "*" ); var l = all.length; var tabPaneRe = /tab\-pane/; var tabPageRe = /tab\-page/; var cn, el; var parentTabPane; for ( var i = 0; i < l; i++ ) { el = all[i] cn = el.className; // no className if ( cn == "" ) continue; // uninitiated tab pane if ( tabPaneRe.test( cn ) && !el.tabPane ) new WebFXTabPane( el ); // unitiated tab page wit a valid tab pane parent else if ( tabPageRe.test( cn ) && !el.tabPage && tabPaneRe.test( el.parentNode.className ) ) { el.parentNode.tabPane.addTabPage( el ); } } }
This function can be called manually at any time but the script makes hooks
to the load
event for the window. This is done using DOM level 2
events if available. If not we test if it supports the IE5 way of attaching events
and last we fall back on classic way of setting events.
// DOM2 if ( typeof window.addEventListener != "undefined" ) window.addEventListener( "load", setupAllTabs, false ); // IE else if ( typeof window.attachEvent != "undefined" ) window.attachEvent( "onload", setupAllTabs ); else { if ( window.onload != null ) { var oldOnload = window.onload; window.onload = function ( e ) { oldOnload( e ); setupAllTabs(); }; } else window.onload = setupAllTabs; }
To be able to change the look and feel one needs to understand the structure
of the tab pane. When the original XHTML source tree is transformed into the
tab pane the class name of the element representing the tab pane is tagged with
the property classNameTag
. The default tag is
dynamic-tab-pane-control
and therefore all your css rules should
take this into account. If you want different look on different tab panes in
the same document this tag can be changed to make the css rules easier to set
up.
<div class="dynamic-tab-pane-control tab-pane" id="tab-pane-1"> <div class="tab-row"> <h2 class="tab selected"><a ... >General</a></h2> <h2 class="tab hover"><a ... >Privacy</a></h2> </div> <div class="tab-page"> This is text of tab 1. This is text of tab 1. This is text of tab 1. This is text of tab 1. </div> <div class="tab-page"> This is text of tab 2. This is text of tab 2. This is text of tab 2. This is text of tab 2. </div> </div>
The selected tab will have the class name tab selected
and the
tab that the mouse hovers over will have the class name tab hover
. If the selected
tab is hovered it will have the class name tab selected hover
. These
rules allow you to differentiate the look of tabs between the different
states.
Here we will walk through the Windows Classic css file. First we set the width and position of the tab pane to prevent a few rendering bugs in IE6.
.dynamic-tab-pane-control.tab-pane { position: relative; width: 100%; } .dynamic-tab-pane-control .tab-row { z-index: 1; white-space: nowrap; }
Then we setup the css for the tab. Notice how the position is set to relative to allow the top position to be slightly changed and to allow the z-index property to be changed to position the tabs below the tab pages.
.dynamic-tab-pane-control .tab-row .tab { font: Menu; cursor: Default; display: inline; margin: 1px -2px 1px 2px; float: left; padding: 2px 5px 3px 5px; background: ThreeDFace; border: 1px solid; border-color: ThreeDHighlight ThreeDDarkShadow ThreeDDarkShadow ThreeDHighlight; border-bottom: 0; z-index: 1; position: relative; top: 0; }
For the selected tab we set the z-index to 3 to put it above the tab pages. We also move it a little and change some other properties to make it look more like the classic window tab control.
.dynamic-tab-pane-control .tab-row .tab.selected { border-bottom: 0; z-index: 3; padding: 2px 6px 5px 7px; margin: 1px -3px -2px 0px; top: -2px; }
Then we override the text properties on the tabs as well
as for the .hover
rule.
.dynamic-tab-pane-control .tab-row .tab a { font: Menu; color: WindowText; text-decoration: none; cursor: default; } .dynamic-tab-pane-control .tab-row .hover a { color: blue; }
Then we set the z-index for the tab pages to 2 so that it will be shown above tabs but below the selected tab. We also set the borders and and a few other properties.
.dynamic-tab-pane-control .tab-page { clear: both; border: 1px solid; border-color: ThreeDHighlight ThreeDDarkShadow ThreeDDarkShadow ThreeDHighlight; background: ThreeDFace; z-index: 2; position: relative; top: -2px; color: WindowText; font: MessageBox; font: Message-Box; padding: 10px; }
Author: Erik Arvidsson