代码如下 | 复制代码 |
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>无标题文档</title> <script type="text/javascript"> var Spry; if (!Spry) Spry = {}; if (!Spry.Widget) Spry.Widget = {}; Spry.Widget.TabbedPanels = function(element, opts) { this.element = this.getElement(element); this.defaultTab = 0; // Show the first panel by default. this.bindings = []; this.tabSelectedClass = "TabbedPanelsTabSelected"; this.tabHoverClass = "TabbedPanelsTabHover"; this.tabFocusedClass = "TabbedPanelsTabFocused"; this.panelVisibleClass = "TabbedPanelsContentVisible"; this.focusElement = null; this.hasFocus = false; this.currentTabIndex = 0; this.enableKeyboardNavigation = true; Spry.Widget.TabbedPanels.setOptions(this, opts); // If the defaultTab is expressed as a number/index, convert // it to an element. if (typeof (this.defaultTab) == "number") { if (this.defaultTab < 0) this.defaultTab = 0; else { var count = this.getTabbedPanelCount(); if (this.defaultTab >= count) this.defaultTab = (count > 1) ? (count - 1) : 0; } this.defaultTab = this.getTabs()[this.defaultTab]; } // The defaultTab property is supposed to be the tab element for the tab content // to show by default. The caller is allowed to pass in the element itself or the // element's id, so we need to convert the current value to an element if necessary. if (this.defaultTab) this.defaultTab = this.getElement(this.defaultTab); this.attachBehaviors(); }; Spry.Widget.TabbedPanels.prototype.getElement = function(ele) { if (ele && typeof ele == "string") return document.getElementById(ele); return ele; } Spry.Widget.TabbedPanels.prototype.getElementChildren = function(element) { var children = []; var child = element.firstChild; while (child) { if (child.nodeType == 1 /* Node.ELEMENT_NODE */) children.push(child); child = child.nextSibling; } return children; }; Spry.Widget.TabbedPanels.prototype.addClassName = function(ele, className) { if (!ele || !className || (ele.className && ele.className.search(new RegExp("\\b" + className + "\\b")) != -1)) return; ele.className += (ele.className ? " " : "") + className; }; Spry.Widget.TabbedPanels.prototype.removeClassName = function(ele, className) { if (!ele || !className || (ele.className && ele.className.search(new RegExp("\\b" + className + "\\b")) == -1)) return; ele.className = ele.className.replace(new RegExp("\\s*\\b" + className + "\\b", "g"), ""); }; Spry.Widget.TabbedPanels.setOptions = function(obj, optionsObj, ignoreUndefinedProps) { if (!optionsObj) return; for (var optionName in optionsObj) { if (ignoreUndefinedProps && optionsObj[optionName] == undefined) continue; obj[optionName] = optionsObj[optionName]; } }; Spry.Widget.TabbedPanels.prototype.getTabGroup = function() { if (this.element) { var children = this.getElementChildren(this.element); if (children.length) return children[0]; } return null; }; Spry.Widget.TabbedPanels.prototype.getTabs = function() { var tabs = []; var tg = this.getTabGroup(); if (tg) tabs = this.getElementChildren(tg); return tabs; }; Spry.Widget.TabbedPanels.prototype.getContentPanelGroup = function() { if (this.element) { var children = this.getElementChildren(this.element); if (children.length > 1) return children[1]; } return null; }; Spry.Widget.TabbedPanels.prototype.getContentPanels = function() { var panels = []; var pg = this.getContentPanelGroup(); if (pg) panels = this.getElementChildren(pg); return panels; }; Spry.Widget.TabbedPanels.prototype.getIndex = function(ele, arr) { ele = this.getElement(ele); if (ele && arr && arr.length) { for (var i = 0; i < arr.length; i++) { if (ele == arr[i]) return i; } } return -1; }; Spry.Widget.TabbedPanels.prototype.getTabIndex = function(ele) { var i = this.getIndex(ele, this.getTabs()); if (i < 0) i = this.getIndex(ele, this.getContentPanels()); return i; }; Spry.Widget.TabbedPanels.prototype.getCurrentTabIndex = function() { return this.currentTabIndex; }; Spry.Widget.TabbedPanels.prototype.getTabbedPanelCount = function(ele) { return Math.min(this.getTabs().length, this.getContentPanels().length); }; Spry.Widget.TabbedPanels.addEventListener = function(element, eventType, handler, capture) { try { if (element.addEventListener) element.addEventListener(eventType, handler, capture); else if (element.attachEvent) element.attachEvent("on" + eventType, handler); } catch (e) {} }; Spry.Widget.TabbedPanels.prototype.onTabClick = function(e, tab) { this.showPanel(tab); }; Spry.Widget.TabbedPanels.prototype.onTabMouseOver = function(e, tab) { this.addClassName(tab, this.tabHoverClass); }; Spry.Widget.TabbedPanels.prototype.onTabMouseOut = function(e, tab) { this.removeClassName(tab, this.tabHoverClass); }; Spry.Widget.TabbedPanels.prototype.onTabFocus = function(e, tab) { this.hasFocus = true; this.addClassName(this.element, this.tabFocusedClass); }; Spry.Widget.TabbedPanels.prototype.onTabBlur = function(e, tab) { this.hasFocus = false; this.removeClassName(this.element, this.tabFocusedClass); }; Spry.Widget.TabbedPanels.ENTER_KEY = 13; Spry.Widget.TabbedPanels.SPACE_KEY = 32; Spry.Widget.TabbedPanels.prototype.onTabKeyDown = function(e, tab) { var key = e.keyCode; if (!this.hasFocus || (key != Spry.Widget.TabbedPanels.ENTER_KEY && key != Spry.Widget.TabbedPanels.SPACE_KEY)) return true; this.showPanel(tab); if (e.stopPropagation) e.stopPropagation(); if (e.preventDefault) e.preventDefault(); return false; }; Spry.Widget.TabbedPanels.prototype.preorderTraversal = function(root, func) { var stopTraversal = false; if (root) { stopTraversal = func(root); if (root.hasChildNodes()) { var child = root.firstChild; while (!stopTraversal && child) { stopTraversal = this.preorderTraversal(child, func); try { child = child.nextSibling; } catch (e) { child = null; } } } } return stopTraversal; }; Spry.Widget.TabbedPanels.prototype.addPanelEventListeners = function(tab, panel) { var self = this; Spry.Widget.TabbedPanels.addEventListener(tab, "click", function(e) { return self.onTabClick(e, tab); }, false); Spry.Widget.TabbedPanels.addEventListener(tab, "mouseover", function(e) { return self.onTabMouseOver(e, tab); }, false); Spry.Widget.TabbedPanels.addEventListener(tab, "mouseout", function(e) { return self.onTabMouseOut(e, tab); }, false); if (this.enableKeyboardNavigation) { // XXX: IE doesn't allow the setting of tabindex dynamically. This means we can't // rely on adding the tabindex attribute if it is missing to enable keyboard navigation // by default. // Find the first element within the tab container that has a tabindex or the first // anchor tag. var tabIndexEle = null; var tabAnchorEle = null; this.preorderTraversal(tab, function(node) { if (node.nodeType == 1 /* NODE.ELEMENT_NODE */) { var tabIndexAttr = tab.attributes.getNamedItem("tabindex"); if (tabIndexAttr) { tabIndexEle = node; return true; } if (!tabAnchorEle && node.nodeName.toLowerCase() == "a") tabAnchorEle = node; } return false; }); if (tabIndexEle) this.focusElement = tabIndexEle; else if (tabAnchorEle) this.focusElement = tabAnchorEle; if (this.focusElement) { Spry.Widget.TabbedPanels.addEventListener(this.focusElement, "focus", function(e) { return self.onTabFocus(e, tab); }, false); Spry.Widget.TabbedPanels.addEventListener(this.focusElement, "blur", function(e) { return self.onTabBlur(e, tab); }, false); Spry.Widget.TabbedPanels.addEventListener(this.focusElement, "keydown", function(e) { return self.onTabKeyDown(e, tab); }, false); } } }; Spry.Widget.TabbedPanels.prototype.showPanel = function(elementOrIndex) { var tpIndex = -1; if (typeof elementOrIndex == "number") tpIndex = elementOrIndex; else // Must be the element for the tab or content panel. tpIndex = this.getTabIndex(elementOrIndex); if (!tpIndex < 0 || tpIndex >= this.getTabbedPanelCount()) return; var tabs = this.getTabs(); var panels = this.getContentPanels(); var numTabbedPanels = Math.max(tabs.length, panels.length); for (var i = 0; i < numTabbedPanels; i++) { if (i != tpIndex) { if (tabs[i]) this.removeClassName(tabs[i], this.tabSelectedClass); if (panels[i]) { this.removeClassName(panels[i], this.panelVisibleClass); panels[i].style.display = "none"; } } } this.addClassName(tabs[tpIndex], this.tabSelectedClass); this.addClassName(panels[tpIndex], this.panelVisibleClass); panels[tpIndex].style.display = "block"; this.currentTabIndex = tpIndex; }; Spry.Widget.TabbedPanels.prototype.attachBehaviors = function(element) { var tabs = this.getTabs(); var panels = this.getContentPanels(); var panelCount = this.getTabbedPanelCount(); for (var i = 0; i < panelCount; i++) this.addPanelEventListeners(tabs[i], panels[i]); this.showPanel(this.defaultTab); }; </script> <style type="text/css"> <!-- .TabbedPanels { margin: 0px; padding: 0px; clear: none; width:auto; /* IE Hack to force proper layout when preceded by a paragraph. (hasLayout Bug)*/ } /* This is the selector for the TabGroup. The TabGroup container houses * all of the tab buttons for each tabbed panel in the widget. This container * does not contribute anything visually to the look of the widget for our * default style. * * The name of the class ("TabbedPanelsTabGroup") used in this selector is not * necessary to make the widget function. You can use any class name you * want to style the TabGroup container. */ .TabbedPanelsTabGroup { margin: 0px; padding: 0px; width:auto; height:23px; } /* This is the selector for the TabbedPanelsTab. This container houses * the title for the panel. This is also the tab "button" that the user clicks * on to activate the corresponding content panel so that it appears on top * of the other tabbed panels contained in the widget. * * For our default style, each tab is positioned relatively 1 pixel down from * where it wold normally render. This allows each tab to overlap the content * panel that renders below it. Each tab is rendered with a 1 pixel bottom * border that has a color that matches the top border of the current content * panel. This gives the appearance that the tab is being drawn behind the * content panel. * * The name of the class ("TabbedPanelsTab") used in this selector is not * necessary to make the widget function. You can use any class name you want * to style this tab container. */ .TabbedPanelsTab { position: relative; top: 1px; float: left; padding: 13px 0 0 0; margin: 0px 3px 0px 0px; font: bold 14px; background:#c1c1c1; list-style: none; border-left: solid 1px #ddd; border-bottom: solid 1px #ddd; border-top: solid 1px #ddd; border-right: solid 1px #ddd; -moz-user-select: none; -khtml-user-select: none; cursor: pointer; width:146px; height:23px; text-align:center; } /* This selector is an example of how to change the appearnce of a tab button * container as the mouse enters it. The class "TabbedPanelsTabHover" is * programatically added and removed from the tab element as the mouse enters * and exits the container. */ .TabbedPanelsTabHover { background-color: #CCC; } /* This selector is an example of how to change the appearance of a tab button * container after the user has clicked on it to activate a content panel. * The class "TabbedPanelsTabSelected" is programatically added and removed * from the tab element as the user clicks on the tab button containers in * the widget. * * As mentioned above, for our default style, tab buttons are positioned * 1 pixel down from where it would normally render. When the tab button is * selected, we change its bottom border to match the background color of the * content panel so that it looks like the tab is part of the content panel. */ .TabbedPanelsTabSelected { background:#FFF; border-bottom: 1px solid #FFF; } /* This selector is an example of how to make a link inside of a tab button * look like normal text. Users may want to use links inside of a tab button * so that when it gets focus, the text *inside* the tab button gets a focus * ring around it, instead of the focus ring around the entire tab. */ .TabbedPanelsTab a { color: black; text-decoration: none; } /* This is the selector for the ContentGroup. The ContentGroup container houses * all of the content panels for each tabbed panel in the widget. For our * default style, this container provides the background color and borders that * surround the content. * * The name of the class ("TabbedPanelsContentGroup") used in this selector is * not necessary to make the widget function. You can use any class name you * want to style the ContentGroup container. */ .TabbedPanelsContentGroup { clear: both; border: solid 1px #DDD; } .TabbedPanelsContentGroup2 { clear: both; border: solid 1px #DDD; } /* This is the selector for the Content panel. The Content panel holds the * content for a single tabbed panel. For our default style, this container * provides some padding, so that the content is not pushed up against the * widget borders. * * The name of the class ("TabbedPanelsContent") used in this selector is * not necessary to make the widget function. You can use any class name you * want to style the Content container. */ .TabbedPanelsContent { padding: 9px; } /* This selector is an example of how to change the appearnce of the currently * active container panel. The class "TabbedPanelsContentVisible" is * programatically added and removed from the content element as the panel * is activated/deactivated. */ .TabbedPanelsContentVisible { } /* Vertical Tabbed Panels * * The following rules override some of the default rules above so that the * TabbedPanels widget renders with its tab buttons along the left side of * the currently active content panel. * * With the rules defined below, the only change that will have to be made * to switch a horizontal tabbed panels widget to a vertical tabbed panels * widget, is to use the "VTabbedPanels" class on the top-level widget * container element, instead of "TabbedPanels". */ /* This selector floats the TabGroup so that the tab buttons it contains * render to the left of the active content panel. A border is drawn around * the group container to make it look like a list container. */ .VTabbedPanels .TabbedPanelsTabGroup { float: left; width: 10em; height: 20em; background-color: #EEE; position: relative; border-top: solid 1px #999; border-right: solid 1px #999; border-left: solid 1px #CCC; border-bottom: solid 1px #CCC; } /* This selector disables the float property that is placed on each tab button * by the default TabbedPanelsTab selector rule above. It also draws a bottom * border for the tab. The tab button will get its left and right border from * the TabGroup, and its top border from the TabGroup or tab button above it. */ .VTabbedPanels .TabbedPanelsTab { float: none; margin: 0px; border-top: none; border-left: none; border-right: none; } /* This selector disables the float property that is placed on each tab button * by the default TabbedPanelsTab selector rule above. It also draws a bottom * border for the tab. The tab button will get its left and right border from * the TabGroup, and its top border from the TabGroup or tab button above it. */ .VTabbedPanels .TabbedPanelsTabSelected { background-color: #EEE; border-bottom: solid 1px #999; } /* This selector floats the content panels for the widget so that they * render to the right of the tabbed buttons. */ .VTabbedPanels .TabbedPanelsContentGroup { clear: none; float: left; padding: 0px; width: 30em; height: 20em; }--> </style> </head> <body> <div id="TabbedPanels1" class="TabbedPanels"> <ul class="TabbedPanelsTabGroup"> <li class="TabbedPanelsTab" tabindex="0">Tab 1</li> <li class="TabbedPanelsTab" tabindex="0">Tab 2</li> <li class="TabbedPanelsTab" tabindex="0">Tab 3</li> </ul> <div class="TabbedPanelsContentGroup"> <div class="TabbedPanelsContent">内容 1</div> <div class="TabbedPanelsContent">内容 2</div> <div class="TabbedPanelsContent">内容 3</div> </div> </div> <script type="text/javascript"> <!-- var TabbedPanels1 = new Spry.Widget.TabbedPanels("TabbedPanels1"); //--> </script> |
时间: 2024-12-05 02:22:31