1 // Copyright (c) 2005 spinelz.org (http://script.spinelz.org/)
3 // Permission is hereby granted, free of charge, to any person obtaining
4 // a copy of this software and associated documentation files (the
5 // "Software"), to deal in the Software without restriction, including
6 // without limitation the rights to use, copy, modify, merge, publish,
7 // distribute, sublicense, and/or sell copies of the Software, and to
8 // permit persons to whom the Software is furnished to do so, subject to
9 // the following conditions:
11 // The above copyright notice and this permission notice shall be
12 // included in all copies or substantial portions of the Software.
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 SideBarBox = Class.create();
25 SideBarBox.className = {
26 panelContainer : 'sideBarBox_panelContainer',
27 tabContainer : 'sideBarBox_tabContainer',
28 title : 'sideBarBox_tabTitle',
29 tab : 'sideBarBox_tab',
30 tabTopInactive : 'sideBarBox_tabTopInactive',
31 tabTopActive : 'sideBarBox_tabTopActive',
32 tabMiddleInactive : 'sideBarBox_tabMiddleInactive',
33 tabMiddleActive : 'sideBarBox_tabMiddleActive',
34 tabBottomInactive : 'sideBarBox_tabBottomInactive',
35 tabBottomActive : 'sideBarBox_tabBottomActive'
38 SideBarBox.prototype = {
40 initialize: function(element) {
41 var options = Object.extend({
43 beforeSelect: function() {return true},
44 afterSelect: Prototype.emptyFunction,
48 }, arguments[1] || {});
50 this.options = options;
51 this.element = $(element);
52 Element.setStyle(this.element, {visibility: 'hidden'});
54 var customCss = CssUtil.appendPrefix(this.options.cssPrefix, SideBarBox.className);
55 this.classNames = new CssUtil([SideBarBox.className, customCss]);
58 Element.setStyle(this.element, {visibility: 'visible'});
63 this.panelContents = [];
66 this.visible = this.options.visible;
67 this.selected = (this.options.selected > 0) ? this.options.selected - 1 : 0 ;
68 this.selected = (this.visible) ? this.selected : -1;
70 this.tabId = this.element.id + '_tab';
71 this.tabTopId = this.tabId + '_top';
72 this.tabMiddleId = this.tabId + '_middle';
73 this.tabBottomId = this.tabId + '_bottom';
74 this.tabContainerId = this.element.id + '_tabContainer';
75 this.panelId = this.element.id + '_panel';
76 this.panelContainerId = this.element.id + '_panelContainer';
78 this.tabContainer = null;
79 this.panelContainer = null;
84 buildTabBox: function() {
85 this.buildContainers();
87 Element.cleanWhitespace(this.element);
88 this.tabSets = this.element.childNodes;
89 if (this.visible && this.selected >= this.tabSets.length) {
93 while(this.tabSets.length > 0){
94 var tabSet = this.tabSets[0];
95 var tabPanel = $A(tabSet.childNodes).detect(function(c) {
96 return (c.nodeType == 1) && (c.tagName.toLowerCase() == 'div');
98 this.buildPanel(tabPanel, i);
99 this.buildTab(tabSet, i);
102 this.addContainers();
105 buildContainers : function() {
106 this.tabContainer = Builder.node('div',{id:this.tabContainerId});
107 this.classNames.addClassNames(this.tabContainer, 'tabContainer');
108 this.panelContainer = Builder.node('div',
110 id:this.panelContainerId
113 this.classNames.addClassNames(this.panelContainer, 'panelContainer');
116 Element.hide(this.panelContainer);
120 addContainers : function() {
121 this.element.appendChild(this.panelContainer);
122 this.element.appendChild(this.tabContainer);
123 this.element.appendChild(Builder.node('div', {style:'clear: left'}));
126 buildTab: function(tab, i) {
127 var tabTitle = tab.childNodes;
128 tab.id = this.tabId + i;
129 this.classNames.addClassNames(tab, 'tab');
130 var top = Builder.node('div',{id: this.tabTopId + i});
131 var middle = Builder.node('div', {id: this.tabMiddleId + i}, $A(tabTitle));
132 var bottom = Builder.node('div', {id: this.tabBottomId + i});
134 tab.appendChild(top);
135 tab.appendChild(middle);
136 tab.appendChild(bottom);
137 Event.observe(tab, 'click', this.selectTab.bindAsEventListener(this));
140 this.tabContainer.appendChild(tab);
141 if ( i != this.selected) {
142 this.setTabInactive(tab);
144 this.setTabActive(tab);
148 buildPanel: function(panelContent, i) {
149 var panel = Builder.node('div', {id: this.panelId + i});
150 panel.appendChild(panelContent);
151 this.panelContents[i] = panel;
152 if(i != this.selected) {
155 this.panelContainer.appendChild(panel);
158 selectTab: function(e) {
159 if (!this.options.beforeSelect()) return;
161 this.setTabActive(this.tabs[this.selected]);
162 Element.show(this.panelList[this.selected]);
166 var currentPanel = this.panelContents[this.selected];
167 var currentTab = this.tabs[this.selected];
169 var targetElement = null;
173 targetElement = Event.element(e);
175 var targetIndex = this.getTargetIndex(targetElement);
176 var targetPanel = this.panelContents[targetIndex];
177 var targetTab = this.tabs[targetIndex];
179 if (targetTab.id == currentTab.id) {
180 if (this.options.close) {
181 Effect.SlideRightOutOfView(this.panelContainer);
182 this.visible = false;
184 this.setTabInactive(currentTab);
185 Element.toggle(targetPanel);
188 this.setTabActive(targetTab);
189 this.setTabInactive(currentTab);
190 Element.toggle(currentPanel);
191 Element.toggle(targetPanel);
192 this.selected = targetIndex;
195 this.setTabActive(targetTab);
196 Element.toggle(targetPanel);
197 Effect.SlideRightIntoView(this.panelContainer);
199 this.selected = targetIndex;
201 this.options.afterSelect(targetPanel, currentPanel);
204 setTabActive: function(tab) {
205 var tabChildren = tab.childNodes;
207 this.classNames.refreshClassNames(tabChildren[0], 'tabTopActive');
208 this.classNames.refreshClassNames(tabChildren[1], 'tabMiddleActive');
209 this.classNames.refreshClassNames(tabChildren[2], 'tabBottomActive');
212 setTabInactive: function(tab) {
213 var tabChildren = tab.childNodes;
215 this.classNames.refreshClassNames(tabChildren[0], 'tabTopInactive');
216 this.classNames.refreshClassNames(tabChildren[1], 'tabMiddleInactive');
217 this.classNames.refreshClassNames(tabChildren[2], 'tabBottomInactive');
220 getTargetIndex: function(element) {
222 if (element.id && element.id.indexOf(this.tabId, 0) >= 0) {
223 var index = element.id.substring(this.tabId.length);
228 element = element.parentNode;
232 hasNextTab: function() {
233 return this.getNextTab() ? true : false;
236 hasPreviousTab: function() {
237 return this.getPreviousTab() ? true : false;
240 getNextTab: function() {
241 return Element.next(this.getCurrentTab());
244 getPreviousTab: function() {
245 return Element.previous(this.getCurrentTab());
248 selectNextTab: function() {
249 this.selectTab(this.getNextTab());
252 selectPreviousTab: function() {
253 this.selectTab(this.getPreviousTab());
256 tabCount: function() {
257 return this.tabs.inject(0, function(i, t) {
262 getCurrentPanel: function() {
263 return this.panelContents[this.selected];
266 getCurrentTab: function() {
267 return this.tabs[this.selected];