I hate sites whose pages are cluttered with links and graphics. Too much information. Too much scrolling. It's like the designer sneezed on a piece of paper and said, "that looks pretty good." Tabbed interfaces are a great way to dynamically hide and show content, but every implementation of tabs have left accessibility concerns, even the A List Apart article "Let Them Eat Cake."
Accessibility Concerns with Tabs
Must be keyboard navigable
Since people using screen readers might not know they are using tabs, how do you jump them to the tabs after they are done reading the content in a tab box?
At the end of a long tab box, what's the easiest method of jumping to the next tab? Scrolling back up? Using a jump link?
The script cannot manipulate the tag styles directly. It should only change class names so user agents in different media can decide how best to display these tabs. Tabs should be media independant.
What if you want to bookmark the page on the current tab?
What happens if I want more than one set of tabs on the same page?
1. Keyboard Navigation This is pretty easy to solve. Most tab solutions use the anchor element, or the common <a> tag as the tabs. Using these for the tabs was a no-brainer. However, a little care has to be taken when using <A> tags, since they actually represent a link to another document, or to an anchor point on the current page.
The href for each tab link jumps to the appropriate tab box, making the tab links DO something if JavaScript is disabled. And with a little JavaScript, the link click can be disabled so the page doesn't reload. Problem 1 solved.
2. How to Get Back to the Tabs No DHTMLtabs I've seen so far provide an easy way to jump the user back up to the tabs using the keyboard. At first I thought access keys would be perfect, but instead opted for another link tag. It is placed below the markup for the entire tab structure so it provides "back to top" functionality when scripting is disabled, and also when it is enabled.
3. Navigating Long Tab Boxes Scrolling is kind of a pain, especially if you can't see well or don't have a scroll wheel on your mouse. If a tab box is particularly long, it would be annoying to scroll back up to the tabs, and switch to the next tab. This was easily solved by placing links at the bottom of each tab box that, when clicked, switch to the next tab, AND jump the system focus to the new tab box. This scrolls the top of the tab box into view after switching to the new tab.
4. JavaScript Doesn't Mess With the Style Since JavaScript can be read by any device that supports it, conceivably a hand held device could handle tabs too, but it might not be the best method for displaying that information on a 2 or 3 inch wide screen. The script must be media independant. The JavaScript only changes class names so CSS styles handle the visual changes, from non-tabbed, to tabbed, to switching tabs, every step of the way.
Now, user agents in any media can use the script to change the class names. Tabs will appear only if CSS styles for that media have been written, otherwise the page acts like the JavaScript never existed.
5. Bookmarking Tabs "Let Them Eat Cake" from A List Apart made a great point. If you've got a long page, break it up and use JavaScript to hide and show only what you need. A problem creeps up when you want to bookmark the page on a certain tab. This implementation searches for the ID of a tab box in the window location when the page loads, then switches to the appropriate tab.
6. Support For Multiple Tab Boxes Lastly, a tab class was created so you can have any number of tab structures on the same page. In AccessibleTabs 1.0, you can even nest tabs, however if you bookmark a tab, only one tab gets switched active. If you bookmarked a tab inside of a tab, the proper tabs wouldn't be made active. Right now this only works if you bookmark a page one tab deep.
/*
* This File: TAB_styles.css
* Contains all CSS declarations to visually format AccessibleTabs. Contains
* CSS 1.0 and 2.0 styles and is hidden from 4.0 and older browsers by being
* imported via the @import method.
*
* Version - AccessibleTabs: 1.0
* By Greg Burghardt
* greg_burghardt@yahoo.com
*/
/* The UL element containing the tabs when JavaScript is enabled. */
.tabbedNavOn {
list-style-type: none;
margin: 0;
padding: 0;
}
/*************** Common styles for both .tabOff and .tabOn *****************/
.tabbedNavOn a {
display: block;
}
.tabbedNavOn a:link,
.tabbedNavOn a:visited,
.tabbedNavOn a:active,
.tabbedNavOn a:hover,
.tabbedNavOn a:focus {
text-decoration: none;
}
.tabbedNavOn a span {
display: block;
}
.tabbedNavOn a span span {
padding: .33em .75em;
}
/*************** End common styles for .tabOff and .tabOn ******************/
/* This class is a tab when it is not active. */
.tabOff {
cursor: pointer;
cursor: hand;
display: block;
}
/* Non active Tab text color when in the visited and non visited states. */
.tabOff:link,
.tabOff:visited {
color: #c60;
}
/* Non active tab background color & graphic when in the visited or non
* visited states. */
.tabOff:link span,
.tabOff:visited span {
background: #FFC489 url(images/Tab_Left.gif) no-repeat scroll 0 0;
}
/* Non active tab's right background graphic when the tab is in a visited or
* non visited state. */
.tabOff:link span span,
.tabOff:visited span span {
background: transparent url(images/Tab_Right.gif) no-repeat scroll 100% 0;
}
/* Non active tab's text color in the active, focus, an hover states. */
.tabOff:active,
.tabOff:focus,
.tabOff:hover {
color: #fff;
}
/* Non active tab's background color and left background graphic when in the
* active, focus and hover states. */
.tabOff:active span,
.tabOff:focus span,
.tabOff:hover span {
background: #f93 url(images/Tab_Left.gif) no-repeat scroll 0 -500px;
}
/* Non active tab's background graphic when in the active, focus and hover
* states. */
.tabOff:active span span,
.tabOff:focus span span,
.tabOff:hover span span {
background: transparent url(images/Tab_Right.gif) no-repeat scroll 100% -500px;
}
/* This class is a tab that is switched "on" */
.tabOn {
cursor: default;
display: block;
}
/* Active tab text color when in the visited and non visited states. */
.tabOn:link,
.tabOn:visited,
.tabOn:active,
.tabOn:hover {
color: #fff;
}
/* Active tab background color & graphic when in the visited, non visited,
* active, and hover states. */
.tabOn:link span,
.tabOn:visited span,
.tabOn:active span,
.tabOn:hover span {
background: #c60 url(images/Tab_Left.gif) no-repeat scroll 0 -1000px;
}
/* Active tab's right background graphic when in the visited, non visited,
* active, and hover states. */
.tabOn:link span span,
.tabOn:visited span span,
.tabOn:active span span,
.tabOn:hover span span {
background: transparent url(images/Tab_Right.gif) no-repeat scroll 100% -1000px;
}
/* The active tab when it has the system focus. */
.tabOn:focus {
color: #fff;
}
/* The active tab's BG color & graphic when it has the system focus. */
.tabOn:focus span {
background: #f93 url(images/Tab_Left.gif) no-repeat scroll 0 -500px;
}
/* The active Tab's right BG graphic when it has the system focus. */
.tabOn:focus span span {
background: transparent url(images/Tab_Right.gif) no-repeat scroll 100% -500px;
}
.tabbedNavOn li {
float: left;
margin-right: 1px;
}
/* Tab boxes when JavaScript is disabled. */
.tabBox {
font-family: "Palatino Linotype", Palatino, Georgia, "Times New Roman", Times, serif;
font-size: 1.25em;
}
.tabBox .tabBoxNav {
display: none;
}
/* Hide the tab boxes when they are turned off. */
.tabBoxOff {
display: none;
}
/* The tab box is switched "on" */
.tabBoxOn {
background-color: #FFEEDB;
margin-top: -1px;
zoom: 1;
}
/* Padding and borders around the tab content. */
.tabBoxOn .tabBoxGutter {
border: 1px solid #c60;
padding: 0 12px;
}
/* The tab's bottom text links for Next and Previous */
.tabBoxOn .tabBoxNav {
background-color: #c60;
display: block;
margin: 0;
padding: .33em 5px 0 5px;
}
/* The tab's bottom text links when the link is visited and non visited. */
.tabBoxOn .tabBoxNav a:link,
.tabBoxOn .tabBoxNav a:visited {
color: #fff;
text-decoration: none;
}
/* The tab's bottom text links when the link is active, hovered on, or has
* the system focus. */
.tabBoxOn .tabBoxNav a:active,
.tabBoxOn .tabBoxNav a:hover,
.tabBoxOn .tabBoxNav a:focus {
color: #fff;
text-decoration: underline;
}
/* Gap below the tab's bottom links, and the bottom of the tab box. */
.tabBoxOn .tabBoxNav .tabSpacer {
height: .33em;
}
.tabBoxOn .tabBoxNavLeft {
float: left;
padding-right: 5px;
}
.tabBoxOn .tabBoxNavRight {
float: right;
padding-left: 5px;
}
/* When JavaScript is disabled, hide the link to jump back to the tabs. */
.tabOptionsOff {
display: none;
}
/* The link to jump back to the tabs when JavaScript is enabled. */
.tabOptionsOn {
margin: 0;
}
.tabOptionsOn a {
margin: -1.5em 0 0 0;
position: absolute;
text-align: center;
width: 100%;
}
.tabOptionsOn a:link,
.tabOptionsOn a:visited {
color: #fff;
z-index: -1;
}
.tabOptionsOn a:active,
.tabOptionsOn a:focus,
.tabOptionsOn a:hover {
color: #fff;
z-index: 1;
}
/* Spacer DIV under the tabs when JavaScript is disabled. */
.tabSpacerOff {
display: none;
}
/* Spacer DIV under the tabs when JavaScript is enabled. The 1px font size
* fixes an IE-Win bug that sizes the height too high in certain cases. */
.tabSpacerOn {
background-color: #c60;
clear: both;
font-size: 1px;
height: 2px;
overflow: hidden;
width: 350px; /* Width required by Safari and IE5-Mac */
}
/* The DIV tag that encapsulates one entire tab structure. */
.tabWrapper {
position: relative;
width: 350px;
z-index: 1;
}
/****************************************************************************
* AccessibleTabs 1.0
* Written by Greg Burghardt
* greg_burghardt@yahoo.com
*
* This was created as open source software and is free to download and
* distribute. Please include this JavaScript code in its entirety.
****************************************************************************/
// Determines whether any occurence of the TAB class can parse the window
// location to detect if a tab box should be switched to active. When false,
// the TAB.detectTabByURL() function will search the window location for a
// page anchor and switch the proper tab and tab box on if that ID is found
// in the this.tabBoxIDs[] array.
var TAB_Found_In_URL = false;
/****************************************************************************
* Declare the TAB class.
****************************************************************************/
function TAB() {
// Version string
this.version = "AccessibleTabs: Version 1.0";
// Detect standard DOM
this.DOM = document.getElementById;
this.name = ""; // ID of tab wrapper
this.isInitialized = false; // Whether or not the initialization function has been called
this.tabIDs = new Array(); // Array of IDs for individual tabs
this.tabNodes = new Array(); // Node references to tab links
this.activeTabID = ""; // ID of the active tab
this.activeTabIndex = 0; // Array indice of the active tab
this.boxIDs = new Array(); // Array of tab box IDs
this.boxNodes = new Array(); // Array of node references to tab boxes
this.makeUniformHeight = false; // Flag to make all tab boxes a uniform height
this.size = 0; // Number of tab boxes in tab structure
this.tabSpacerID = ""; // ID of the spacer DIV under the tabs
this.tabRootID = ""; // ID of the OL or UL tag which directly holds the tabs
this.tabOptionsID = ""; // ID of the element containing the tab options link at the bottom
/***************************************************************************
* Declare the prototypes for the member functions.
***************************************************************************/
if (typeof(_tab_prototype_called) == 'undefined') {
_tab_prototype_called = true;
TAB.prototype.initialize = initialize;
TAB.prototype.initializeWithIDs = initializeWithIDs;
TAB.prototype.uninitialize = uninitialize;
TAB.prototype.switchTab = switchTab;
TAB.prototype.detectTabByURL = detectTabByURL;
TAB.prototype.getVersion = getVersion;
TAB.prototype.getTabIndexByID = getTabIndexByID;
TAB.prototype.getTabBoxIndexByID = getTabBoxIndexByID;
}
/***************************************************************************
* Initializes the tab box. It does not take any parameters and assumes
* you've given the data structure a name, at least one ID for a tab, the
* active tab's ID and at least one tab box ID. This function activates the
* default tab (as denoted by this.activeTabID).
***************************************************************************/
function initialize() {
if (this.DOM &&
this.name != "" &&
this.tabIDs[0] != "" &&
this.boxIDs[0] != "" &&
this.tabSpacerID != "" &&
this.tabOptionsID != "" &&
this.tabRootID != "") {
// Get a node reference to the tabs' root element and activate it
var TabRoot = document.getElementById(this.tabRootID);
TabRoot.className = "tabbedNavOn";
this.size = this.tabIDs.length;
this.activeTabID = this.tabIDs[0];
for (var i = 0; i < this.size; i++) {
this.tabNodes[i] = document.getElementById(this.tabIDs[i]);
this.boxNodes[i] = document.getElementById(this.boxIDs[i]);
if (this.tabNodes[i].id == this.activeTabID) {
this.boxNodes[i].className = "tabBoxOn";
this.tabNodes[i].className = "tabOn";
this.activeTabIndex = i;
} else {
this.boxNodes[i].className = "tabBoxOff";
this.tabNodes[i].className = "tabOff";
}
}
TabRoot = document.getElementById(this.tabSpacerID);
if (TabRoot != "undefined")
TabRoot.className = "tabSpacerOn";
TabRoot = document.getElementById(this.tabOptionsID);
if (TabRoot != "undefined")
TabRoot.className = "tabOptionsOn";
TabRoot = null;
this.isInitialized = true;
// If a page anchor pointing to a tab box exists in the window location,
// find it and switch to the proper tab.
this.detectTabByURL();
}
}
/***************************************************************************
* Initializes the entire tab structure by passing variables to this function
* for all needed IDs
***************************************************************************/
function initializeWithIDs(Name, RootID, SpacerID, OptionsID) {
if (this.DOM) {
this.name = Name;
this.tabRootID = RootID;
this.tabSpacerID = SpacerID;
this.tabOptionsID = OptionsID;
this.initialize();
}
}
/***************************************************************************
* Removes all node references for this instance of the TAB class. This
* should occur when the window.onunload event is fired to clean up any node
* references that might be double-referenced, which should prevent memory
* leaks in Internet Explorer 5.01 - 6.0.
***************************************************************************/
function uninitialize(override) {
if (this.isInitialized || override) {
for (var i = 0; i < this.size; i++) {
this.tabNodes[i] = null;
this.boxNodes[i] = null;
}
this.isInitialized = false;
}
}
/***************************************************************************
* Switches to a new tab. Gets the ID of the active Tab and whether or not a
* null value should be returned to nullify a tab link's click (and
* consequent browser location change).
***************************************************************************/
function switchTab(ActiveID, ReturnValue) {
if (this.isInitialized) {
this.activeTabID = ActiveID;
this.tabNodes[this.activeTabIndex].className = "tabOff";
this.boxNodes[this.activeTabIndex].className = "tabBoxOff";
for (var i = 0; i < this.size; i++) {
if (this.tabNodes[i].id == this.activeTabID) {
this.tabNodes[i].className = "tabOn";
this.boxNodes[i].className = "tabBoxOn";
this.activeTabIndex = i;
if (ReturnValue != null)
return ReturnValue;
}
}
return true;
}
}
/***************************************************************************
* Detects if a tab box has been referenced in the window location and
* switches to the correct tab. This makes it so you can bookmark the page
* under a given tab, and return to the page via the bookmark or link and
* have the appropriate tab active.
***************************************************************************/
function detectTabByURL() {
if (!TAB_Found_In_URL) {
var fullurl = "" + window.location;
var hashPos = 0;
var activeTabBoxID = "";
var newActiveTabIndex = 0;
hashPos = fullurl.indexOf("#");
if (hashPos > 0) {
// Get the page anchor, which is the ID of the soon-to-be active tab box.
activeTabBoxID = fullurl.substring(hashPos + 1, fullurl.length);
newActiveTabIndex = this.getTabBoxIndexByID(activeTabBoxID);
if (newActiveTabIndex > -1) {
// Switch to the appropriate tab.
this.switchTab(this.tabIDs[this.getTabBoxIndexByID(activeTabBoxID)], null);
// Prevent other occurences of the TAB class from trying to detect the
// active tab if a URL has a page anchor in it.
TAB_Found_In_URL = true;
}
}
}
}
/***************************************************************************
* Returns the current version of AccessibleTabs.
***************************************************************************/
function getVersion() {
return this.version;
}
/***************************************************************************
* Given a tab's ID, this will return it's indice in the TAB.tabIDs array.
***************************************************************************/
function getTabIndexByID(id) {
for (var i = 0; i < this.size; i++) {
if (this.tabIDs[i] == id)
return i;
}
return -1;
}
/***************************************************************************
* Given a tab boxe's ID, this will return it's indice in the TAB.tabBoxIDs
* array.
***************************************************************************/
function getTabBoxIndexByID(id) {
for (var i = 0; i < this.size; i++) {
if (this.boxIDs[i] == id)
return i;
}
return -1;
}
}
/****************************************************************************
* Global tab function to uninitialize an array containing instances of the
* TAB class. This is mainly to prevent memory leaks in Internet Explorer.
* This function should always be used when the page unloads.
****************************************************************************/
function TAB_GLOBAL_UNINITIALIZE(Tabs) {
for (i = 0; i < Tabs.length; i++) {
Tabs[i].uninitialize(true);
}
}
Once you've got the markup, CSS and JavaScript in place, follow the steps below to set the tab box up for use.
Step 1.Create as many tabs and tab boxes as you want. You can give any of the HTML tags custom IDs. Only the class names matter.
Step 2.Declare an instance of the TAB class, and give it the information it needs. This will be added to the HTML file.
HTML Code:
</div><!-- end example --><p class="tabOptionsOff" id="example_options"> ... </p><script type="text/javascript"><!--
// Declare a new instance of the TAB class
var Example = new TAB();
// Set IDs needed to create tab structure.
Example.name = "example";
Example.tabSpacerID = "example_spacer";
Example.tabOptionsID = "example_options";
Example.tabRootID = "example_tabs";
// IDs of the tabs themselves
Example.tabIDs[0] = "tabsample1";
Example.tabIDs[1] = "tabsample2";
Example.tabIDs[2] = "tabsample3";
// IDs of the tab boxes
Example.boxIDs[0] = "firstTabBox";
Example.boxIDs[1] = "secondTabBox";
Example.boxIDs[2] = "thirdTabBox";
// Initialize the tabs
Example.initialize();
// --></script>
var Example = new TAB(); This declares a new instance of the TAB class. You can reference all properties and methods for the tabs by using the keyword Example.
Example.property;
Example.method();
If you had a series of tabs for types of products, whose tabs are category names, you could call this instance of the TAB class ProductCategories.
var ProductCategories = new TAB();
Then you could access the class properties and methods by typing ProductCategories.property or ProducCategories.method(). Now, back to our Example tabs.
Example.name: The ID of the DIV tag that encapsulates all of the tabs and tab boxes.
Example.tabSpacerID: The ID of the spacer DIV under the Tabs.
Example.tabOptionsID: The ID of the link at the bottom of the tab box structure that allows you to jump back to the tabs.
Example.tabRootID: The ID of the UL or OL tag that contains the tabs.
Example.tabIDs: This is an array containing the IDs of all the tabs.
Example.boxIDs: Another array that contains IDs to all of the tab boxes.
A quick note about the .tabIDs and .boxIDs arrays. They are called synchronous arrays, meaning the information in a .tabIDs array slot is related to the information in the same array slot in the .boxIDs array. For instance, the ID in .tabIDs[0] is the ID of the first tab. The ID stored in .boxIDs[0] is the ID of the first tab box. The ID of a tab, and the ID of its cooresponding tab box must be in the same index number of the .tabIDs and .boxIDs arrays.
Example.initialize(); This takes the information you gave the tab class, and activates the whole tab structure — including setting the default tab, which is the first item in the .tabIDs array.
If all goes well, your tabs should show up on screen just fine.
Cleaning Up After Internet Explorer
The MSDN article "Understanding And Solving Internet Explorer Leak Patterns" states that the basis for most memory leaks in the popular browser are a result of a DOM node being double-referenced. If you store a reference to one DOM node in two variables, Internet Explorer will not release that memory back to the operating system when the page unloads. For this reason, a TAB global function was created to clean up any node references used in AccessibleTabs when the page unloads. Simply insert the code below in the body tag of the HTML document:
The TAB_GLOBAL_UNINITIALIZE() function taks an array of the TAB classes you declared on the page. For instance, say you have three instances of the TAB class on your page to create three tabbed interfaces.
Code:
<script type="text/javascript">
<!--
var ProductTypes = new TAB();
// -->
</script>
...
<script type="text/javascript">
<!--
var SiteHighlights = new TAB();
// -->
</script>
...
<script type="text/javascript">
<!--
var TechSupportOptions = new TAB();
// -->
</script>
The onunload event handler in the body tag would be set up as follows:
Current Issues With AccessibleTabs 1.0
There are still a couple things I'd like to build into this tab class. The biggest thing I'd like to do is add support to bookmark a page more than one tab deep. This would involve adding a .parentTab property, which could be a reference to another instance of the TAB class on the page. In this case, you could bookmark the current page any number of tabs deep.
The .detectTabByURL() function could recursively go up the chain of tabs and switch that tab on, but I decided to release what I've got so far to the public. Chances are real good that you won't need to nest tab boxes.
Lastly, I'd like to build in support for making each tab box within a set of tabs equal heights. It would be set with the .makeUniformHeight property, but currently this does nothing.
If you have any additional concerns about the functionality or accessibility of this script, please reply to this thread.
Download An Example And PSD File
Attached to this post is a ZIP file that contains the CSS, JavaScript, HTML, and image files used as an example. I've also included the PSD file I used to create the tab graphics. Feel free to edit them as needed, and keep in mind that you may not need the graphics the same widths that I used.
Last edited by toicontien; 05-18-2006 at 10:39 AM.
All I can say to all that is wow! I am sure that is very important code so I saved it. Looks like it will save me months of work. Thanks a lot toicontien. That was extremely nice of you. Rianna
Thanks Rianna. I actually created this in response to the Accessible Scripting 101 sticky in this forum. If you need help getting this set up any where, just Private Message me or reply to this thread. I'll do all I can.
2. Your mark-up. While mark-up of the tabs is debatable (I am proponent of the fact that tab itself is the header for its content, but separating them into a navigation block also has its merits), the set of tabs is a list with each tab being a list item.
Working web site is not the one that looks the same in a few graphical browsers, but the one that adequately delivers its content to any device accessing it.
But the solution you linked to doesn't degrade when javascript is disabled
Actually, I considered using headings for the tabs, but in the end I found this to be a much more flexible solution. It was really inspired by the A List Apart article "Let Them Eat Cake" -- and in some ways could be considered an expansion of that method. I wanted something that: A) Screen readers could easily navigate; B) Is keyboard accessible; C) Does not require JavaScript to view the content of the tab structure; D) All styling is controlled by the style sheets; and E) is bookmarkable.
No styling is applied by JavaScript to the DOM. Class names get switched, so if a device happens to support the W3C DOM, but doesn't have as powerfull a display as a desktop monitor, styles can simply be omitted for that device's media type. The operation of the tabs is completely transparent to devices that do not receive style sheets with the proper styles written.
This can also be used to break up a large page into sections, not just small tidbits of information.
It is an interesting thought about each tab box being a list item. I can see that being good for tab structures where the information is closely related and where there isn't much information, but when the tab structure contains lots of information, or complex information, I see having a separate navigation system being the optimal approach. I guess it all boils down to how you're using a tab structure: To break up small pieces of related information, or break up a longer page into more human readable chunks.
What is the advantage of providing IDs for every tab and its content and then using them to initialize object properties, versus relying on defined HTML structure (mark up you spacer as hr):
Code:
/* Tabs Wrapper is passed to constructor */
new TAB(document.getElementById('example'));
/* In constructor: */
function TAB(wrapper)
{
this.tabContentNodes = new Array();
for(var i=0; i<wrapper.childNodes.length; i++)
{ if(/ul/i.test(wrapper.childNodes[i].nodeName))
this.tabRoot = wrapper.childNodes[i];
if(/div/i.test(wrapper.childNodes[i].nodeName))
this.tabContentNodes.push(wrapper.childNodes[i];
}
}
Working web site is not the one that looks the same in a few graphical browsers, but the one that adequately delivers its content to any device accessing it.
Looked more closely at your code and have a couple of questions:
What is the advantage of
Code:
if (typeof(_tab_prototype_called) == 'undefined') {
_tab_prototype_called = true;
TAB.prototype.initialize = initialize;
/*more*/
}
function initialize()
{ /*body*/}
To be quite honest, this was my first experiment with JavaScript classes. I read an article about this on about.com or javascript.com. Something like that. And they used the if (typeof(...)) code, so I did. I could go back and just to CLASS.prototype.FUNCTION and it would work just as well.
Originally Posted by Vladdy
What is the advantage of providing IDs for every tab and its content and then using them to initialize object properties, versus relying on defined HTML structure...
"Relying on defined HTML structure(s)" is exactly why I opted to not do that. With a little extra footwork on the JavaScript side, this implimentation of DHTMLtabs should be markup independant. If you want to use a different tag structure, you can. Each tab box doesn't have to be a DIV tag. It could be a FIELDSET tag in a large form. It could be a table in a series of tables condensed into a tab structure: http://www.mygoodfriends.com/ (You'll have to be a logged in member to view the example). So I should add an E) Be fairly markup independant.
Hi .. I am Mohan Dass. I have created the tab concept. But i want to do one intresting thig in this... if any one know the idea pleaset tell to me.. my id is:indrajith_md@yahoo.co.in.
That is i would like to change the name of the tabs at run time.. i.e i like to change the tab name dynamically.. as i wish... if any one have knowledge or any idea please sent ot me...
Bookmarks