// sprytabbedpanels.js - version 0.7 - spry pre-release 1.6.1 // // copyright (c) 2006. adobe systems incorporated. // all rights reserved. // // redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // * redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // * redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // * neither the name of adobe systems incorporated nor the names of its // contributors may be used to endorse or promote products derived from this // software without specific prior written permission. // // this software is provided by the copyright holders and contributors "as is" // and any express or implied warranties, including, but not limited to, the // implied warranties of merchantability and fitness for a particular purpose // are disclaimed. in no event shall the copyright owner or contributors be // liable for any direct, indirect, incidental, special, exemplary, or // consequential damages (including, but not limited to, procurement of // substitute goods or services; loss of use, data, or profits; or business // interruption) however caused and on any theory of liability, whether in // contract, strict liability, or tort (including negligence or otherwise) // arising in any way out of the use of this software, even if advised of the // possibility of such damage. (function() { // beginsprycomponent if (typeof spry == "undefined") window.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.tabselectedclass = "tabbedpanelstabselected"; this.tabhoverclass = "tabbedpanelstabhover"; this.tabfocusedclass = "tabbedpanelstabfocused"; this.panelvisibleclass = "tabbedpanelscontentvisible"; this.focuselement = null; this.hasfocus = false; this.currenttabindex = 0; this.enablekeyboardnavigation = true; this.nextpanelkeycode = spry.widget.tabbedpanels.key_right; this.previouspanelkeycode = spry.widget.tabbedpanels.key_left; 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.cancelevent = function(e) { if (e.preventdefault) e.preventdefault(); else e.returnvalue = false; if (e.stoppropagation) e.stoppropagation(); else e.cancelbubble = true; return false; }; spry.widget.tabbedpanels.prototype.ontabclick = function(e, tab) { this.showpanel(tab); return this.cancelevent(e); }; spry.widget.tabbedpanels.prototype.ontabmouseover = function(e, tab) { this.addclassname(tab, this.tabhoverclass); return false; }; spry.widget.tabbedpanels.prototype.ontabmouseout = function(e, tab) { this.removeclassname(tab, this.tabhoverclass); return false; }; spry.widget.tabbedpanels.prototype.ontabfocus = function(e, tab) { this.hasfocus = true; this.addclassname(tab, this.tabfocusedclass); return false; }; spry.widget.tabbedpanels.prototype.ontabblur = function(e, tab) { this.hasfocus = false; this.removeclassname(tab, this.tabfocusedclass); return false; }; spry.widget.tabbedpanels.key_up = 38; spry.widget.tabbedpanels.key_down = 40; spry.widget.tabbedpanels.key_left = 37; spry.widget.tabbedpanels.key_right = 39; spry.widget.tabbedpanels.prototype.ontabkeydown = function(e, tab) { var key = e.keycode; if (!this.hasfocus || (key != this.previouspanelkeycode && key != this.nextpanelkeycode)) return true; var tabs = this.gettabs(); for (var i =0; i < tabs.length; i++) if (tabs[i] == tab) { var el = false; if (key == this.previouspanelkeycode && i > 0) el = tabs[i-1]; else if (key == this.nextpanelkeycode && i < tabs.length-1) el = tabs[i+1]; if (el) { this.showpanel(el); el.focus(); break; } } return this.cancelevent(e); }; 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); }; })(); // endsprycomponent