1/* SpryTabbedPanels.js - Revision: Spry Preview Release 1.4 */ 2 3// Copyright (c) 2006. Adobe Systems Incorporated. 4// All rights reserved. 5// 6// Redistribution and use in source and binary forms, with or without 7// modification, are permitted provided that the following conditions are met: 8// 9// * Redistributions of source code must retain the above copyright notice, 10// this list of conditions and the following disclaimer. 11// * Redistributions in binary form must reproduce the above copyright notice, 12// this list of conditions and the following disclaimer in the documentation 13// and/or other materials provided with the distribution. 14// * Neither the name of Adobe Systems Incorporated nor the names of its 15// contributors may be used to endorse or promote products derived from this 16// software without specific prior written permission. 17// 18// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 22// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28// POSSIBILITY OF SUCH DAMAGE. 29 30var Spry; 31if (!Spry) Spry = {}; 32if (!Spry.Widget) Spry.Widget = {}; 33 34Spry.Widget.TabbedPanels = function(element, opts) 35{ 36 this.element = this.getElement(element); 37 this.defaultTab = 0; // Show the first panel by default. 38 this.bindings = []; 39 this.tabSelectedClass = "TabbedPanelsTabSelected"; 40 this.tabHoverClass = "TabbedPanelsTabHover"; 41 this.tabFocusedClass = "TabbedPanelsTabFocused"; 42 this.panelVisibleClass = "TabbedPanelsContentVisible"; 43 this.focusElement = null; 44 this.hasFocus = false; 45 this.currentTabIndex = 0; 46 this.enableKeyboardNavigation = true; 47 48 Spry.Widget.TabbedPanels.setOptions(this, opts); 49 50 // If the defaultTab is expressed as a number/index, convert 51 // it to an element. 52 53 if (typeof (this.defaultTab) == "number") 54 { 55 if (this.defaultTab < 0) 56 this.defaultTab = 0; 57 else 58 { 59 var count = this.getTabbedPanelCount(); 60 if (this.defaultTab >= count) 61 this.defaultTab = (count > 1) ? (count - 1) : 0; 62 } 63 64 this.defaultTab = this.getTabs()[this.defaultTab]; 65 } 66 67 // The defaultTab property is supposed to be the tab element for the tab content 68 // to show by default. The caller is allowed to pass in the element itself or the 69 // element's id, so we need to convert the current value to an element if necessary. 70 71 if (this.defaultTab) 72 this.defaultTab = this.getElement(this.defaultTab); 73 74 this.attachBehaviors(); 75}; 76 77Spry.Widget.TabbedPanels.prototype.getElement = function(ele) 78{ 79 if (ele && typeof ele == "string") 80 return document.getElementById(ele); 81 return ele; 82} 83 84Spry.Widget.TabbedPanels.prototype.getElementChildren = function(element) 85{ 86 var children = []; 87 var child = element.firstChild; 88 while (child) 89 { 90 if (child.nodeType == 1 /* Node.ELEMENT_NODE */) 91 children.push(child); 92 child = child.nextSibling; 93 } 94 return children; 95}; 96 97Spry.Widget.TabbedPanels.prototype.addClassName = function(ele, className) 98{ 99 if (!ele || !className || (ele.className && ele.className.search(new RegExp("\\b" + className + "\\b")) != -1)) 100 return; 101 ele.className += (ele.className ? " " : "") + className; 102}; 103 104Spry.Widget.TabbedPanels.prototype.removeClassName = function(ele, className) 105{ 106 if (!ele || !className || (ele.className && ele.className.search(new RegExp("\\b" + className + "\\b")) == -1)) 107 return; 108 ele.className = ele.className.replace(new RegExp("\\s*\\b" + className + "\\b", "g"), ""); 109};
110 111Spry.Widget.TabbedPanels.setOptions = function(obj, optionsObj, ignoreUndefinedProps) 112{ 113 if (!optionsObj) 114 return; 115 for (var optionName in optionsObj) 116 { 117 if (ignoreUndefinedProps && optionsObj[optionName] == undefined) 118 continue; 119 obj[optionName] = optionsObj[optionName]; 120 } 121}; 122 123Spry.Widget.TabbedPanels.prototype.getTabGroup = function() 124{ 125 if (this.element) 126 { 127 var children = this.getElementChildren(this.element); 128 if (children.length) 129 return children[0]; 130 } 131 return null; 132}; 133 134Spry.Widget.TabbedPanels.prototype.getTabs = function() 135{ 136 var tabs = []; 137 var tg = this.getTabGroup(); 138 if (tg) 139 tabs = this.getElementChildren(tg); 140 return tabs; 141}; 142 143Spry.Widget.TabbedPanels.prototype.getContentPanelGroup = function() 144{ 145 if (this.element) 146 { 147 var children = this.getElementChildren(this.element); 148 if (children.length > 1) 149 return children[1]; 150 } 151 return null; 152}; 153 154Spry.Widget.TabbedPanels.prototype.getContentPanels = function() 155{ 156 var panels = []; 157 var pg = this.getContentPanelGroup(); 158 if (pg) 159 panels = this.getElementChildren(pg); 160 return panels; 161}; 162 163Spry.Widget.TabbedPanels.prototype.getIndex = function(ele, arr) 164{ 165 ele = this.getElement(ele); 166 if (ele && arr && arr.length) 167 { 168 for (var i = 0; i < arr.length; i++) 169 { 170 if (ele == arr[i]) 171 return i; 172 } 173 } 174 return -1; 175}; 176 177Spry.Widget.TabbedPanels.prototype.getTabIndex = function(ele) 178{ 179 var i = this.getIndex(ele, this.getTabs()); 180 if (i < 0) 181 i = this.getIndex(ele, this.getContentPanels()); 182 return i; 183}; 184 185Spry.Widget.TabbedPanels.prototype.getCurrentTabIndex = function() 186{ 187 return this.currentTabIndex; 188}; 189 190Spry.Widget.TabbedPanels.prototype.getTabbedPanelCount = function(ele) 191{ 192 return Math.min(this.getTabs().length, this.getContentPanels().length); 193}; 194 195Spry.Widget.TabbedPanels.addEventListener = function(element, eventType, handler, capture) 196{ 197 try 198 { 199 if (element.addEventListener) 200 element.addEventListener(eventType, handler, capture); 201 else if (element.attachEvent) 202 element.attachEvent("on" + eventType, handler); 203 } 204 catch (e) {} 205}; 206 207Spry.Widget.TabbedPanels.prototype.onTabClick = function(e, tab) 208{ 209 this.showPanel(tab); 210}; 211 212Spry.Widget.TabbedPanels.prototype.onTabMouseOver = function(e, tab) 213{ 214 this.addClassName(tab, this.tabHoverClass); 215}; 216 217Spry.Widget.TabbedPanels.prototype.onTabMouseOut = function(e, tab) 218{ 219 this.removeClassName(tab, this.tabHoverClass); 220}; 221 222Spry.Widget.TabbedPanels.prototype.onTabFocus = function(e, tab) 223{ 224 this.hasFocus = true; 225 this.addClassName(this.element, this.tabFocusedClass); 226}; 227 228Spry.Widget.TabbedPanels.prototype.onTabBlur = function(e, tab) 229{ 230 this.hasFocus = false; 231 this.removeClassName(this.element, this.tabFocusedClass); 232}; 233 234Spry.Widget.TabbedPanels.ENTER_KEY = 13; 235Spry.Widget.TabbedPanels.SPACE_KEY = 32; 236 237Spry.Widget.TabbedPanels.prototype.onTabKeyDown = function(e, tab) 238{ 239 var key = e.keyCode; 240 if (!this.hasFocus || (key != Spry.Widget.TabbedPanels.ENTER_KEY && key != Spry.Widget.TabbedPanels.SPACE_KEY)) 241 return true; 242 243 this.showPanel(tab); 244 245 if (e.stopPropagation) 246 e.stopPropagation(); 247 if (e.preventDefault) 248 e.preventDefault(); 249 250 return false; 251}; 252 253Spry.Widget.TabbedPanels.prototype.preorderTraversal = function(root, func) 254{ 255 var stopTraversal = false; 256 if (root) 257 { 258 stopTraversal = func(root); 259 if (root.hasChildNodes()) 260 { 261 var child = root.firstChild; 262 while (!stopTraversal && child) 263 { 264 stopTraversal = this.preorderTraversal(child, func); 265 try { child = child.nextSibling; } catch (e) { child = null; } 266 } 267 } 268 } 269 return stopTraversal; 270}; 271 272Spry.Widget.TabbedPanels.prototype.addPanelEventListeners = function(tab, panel) 273{ 274 var self = this; 275 Spry.Widget.TabbedPanels.addEventListener(tab, "click", function(e) { return self.onTabClick(e, tab); }, false); 276 Spry.Widget.TabbedPanels.addEventListener(tab, "mouseover", function(e) { return self.onTabMouseOver(e, tab); }, false); 277 Spry.Widget.TabbedPanels.addEventListener(tab, "mouseout", function(e) { return self.onTabMouseOut(e, tab); }, false); 278 279 if (this.enableKeyboardNavigation) 280 { 281 // XXX: IE doesn't allow the setting of tabindex dynamically. This means we can't 282 // rely on adding the tabindex attribute if it is missing to enable keyboard navigation 283 // by default. 284 285 // Find the first element within the tab container that has a tabindex or the first 286 // anchor tag. 287 288 var tabIndexEle = null; 289 var tabAnchorEle = null; 290 291 this.preorderTraversal(tab, function(node) { 292 if (node.nodeType == 1 /* NODE.ELEMENT_NODE */) 293 { 294 var tabIndexAttr = tab.attributes.getNamedItem("tabindex"); 295 if (tabIndexAttr) 296 { 297 tabIndexEle = node; 298 return true; 299 } 300 if (!tabAnchorEle && node.nodeName.toLowerCase() == "a") 301 tabAnchorEle = node; 302 } 303 return false; 304 }); 305 306 if (tabIndexEle) 307 this.focusElement = tabIndexEle; 308 else if (tabAnchorEle) 309 this.focusElement = tabAnchorEle; 310 311 if (this.focusElement) 312 { 313 Spry.Widget.TabbedPanels.addEventListener(this.focusElement, "focus", function(e) { return self.onTabFocus(e, tab); }, false); 314 Spry.Widget.TabbedPanels.addEventListener(this.focusElement, "blur", function(e) { return self.onTabBlur(e, tab); }, false); 315 Spry.Widget.TabbedPanels.addEventListener(this.focusElement, "keydown", function(e) { return self.onTabKeyDown(e, tab); }, false); 316 } 317 } 318}; 319 320Spry.Widget.TabbedPanels.prototype.showPanel = function(elementOrIndex) 321{ 322 var tpIndex = -1; 323 324 if (typeof elementOrIndex == "number") 325 tpIndex = elementOrIndex; 326 else // Must be the element for the tab or content panel. 327 tpIndex = this.getTabIndex(elementOrIndex); 328 329 if (!tpIndex < 0 || tpIndex >= this.getTabbedPanelCount()) 330 return; 331 332 var tabs = this.getTabs();
333 var panels = this.getContentPanels(); 334 335 var numTabbedPanels = Math.max(tabs.length, panels.length); 336 337 for (var i = 0; i < numTabbedPanels; i++) 338 { 339 if (i != tpIndex) 340 { 341 if (tabs[i]) 342 this.removeClassName(tabs[i], this.tabSelectedClass); 343 if (panels[i]) 344 { 345 this.removeClassName(panels[i], this.panelVisibleClass); 346 panels[i].style.display = "none"; 347 } 348 } 349 } 350 351 this.addClassName(tabs[tpIndex], this.tabSelectedClass); 352 this.addClassName(panels[tpIndex], this.panelVisibleClass); 353 panels[tpIndex].style.display = "block"; 354 355 this.currentTabIndex = tpIndex; 356}; 357 358Spry.Widget.TabbedPanels.prototype.attachBehaviors = function(element) 359{ 360 var tabs = this.getTabs(); 361 var panels = this.getContentPanels(); 362 var panelCount = this.getTabbedPanelCount(); 363 364 for (var i = 0; i < panelCount; i++) 365 this.addPanelEventListeners(tabs[i], panels[i]); 366 367 this.showPanel(this.defaultTab); 368};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.