1 // Copyright (c) 2005 spinelz.org (http://script.spinelz.org/)
\r
3 // Permission is hereby granted, free of charge, to any person obtaining
\r
4 // a copy of this software and associated documentation files (the
\r
5 // "Software"), to deal in the Software without restriction, including
\r
6 // without limitation the rights to use, copy, modify, merge, publish,
\r
7 // distribute, sublicense, and/or sell copies of the Software, and to
\r
8 // permit persons to whom the Software is furnished to do so, subject to
\r
9 // the following conditions:
\r
11 // The above copyright notice and this permission notice shall be
\r
12 // included in all copies or substantial portions of the Software.
\r
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
\r
15 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
\r
16 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
\r
17 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
\r
18 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
\r
19 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
\r
20 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\r
22 var MenuBar = Class.create();
\r
23 MenuBar.cssNames = {
\r
24 container: 'menubar',
\r
25 menu: 'menubar_menu',
\r
26 menuBody: 'menubar_menuBody',
\r
27 menuBodyHover: 'menubar_menuBodyHover',
\r
28 subMenu: 'menubar_subMenu',
\r
29 subMenuBody: 'menubar_subMenuBody',
\r
30 subMenuBodyHover: 'menubar_subMenuBodyHover',
\r
31 subMenuContainer: 'menubar_menuContainer',
\r
32 dirMark: 'menubar_dirMark'
\r
39 MenuBar.prototype = {
\r
41 initialize: function(element) {
\r
42 this.options = Object.extend({
\r
43 hideOnClickSubmenu: true
\r
46 this.element = $(element);
\r
47 Element.setStyle(this.element, {visibility: 'hidden'});
\r
48 Element.hide(this.element);
\r
50 var options = Object.extend({
\r
51 cssPrefix: 'custom_'
\r
52 }, arguments[1] || {});
\r
54 var customCss = CssUtil.appendPrefix(options.cssPrefix, MenuBar.cssNames);
\r
55 this.classNames = new CssUtil([MenuBar.cssNames, customCss]);
\r
59 var nodes = this.element.childNodes;
\r
61 for (var i = 0; i < nodes.length; i++) {
\r
62 if (nodes[i].nodeType == 1) {
\r
63 this.build(nodes[i], 'menu');
\r
64 topMenus.push(nodes[i]);
\r
68 this.menubar = Builder.node('DIV', topMenus)
\r
69 this.classNames.addClassNames(this.menubar, 'container');
\r
70 this.element.appendChild(this.menubar);
\r
72 Event.observe(document, "click", this.hideAllTrigger(this.menubar).bindAsEventListener(this));
\r
73 Element.setStyle(this.element, {visibility: 'visible'});
\r
74 Element.show(this.element);
\r
77 build: function(element, className) {
\r
78 this.classNames.addClassNames(element, className);
\r
80 var bodyContents = new Array();
\r
81 var subMenus = new Array();
\r
82 var nodes = element.childNodes;
\r
84 for (var i = 0; i < nodes.length; i++) {
\r
85 if (nodes[i].nodeType == 1 && nodes[i].tagName == 'DIV') {
\r
86 this.build(nodes[i], 'subMenu');
\r
87 subMenus.push(nodes[i]);
\r
89 bodyContents.push(nodes[i]);
\r
93 var bodyClass= className + 'Body';
\r
94 var body = Builder.node('DIV', bodyContents);
\r
95 this.classNames.addClassNames(body, bodyClass);
\r
97 element.appendChild(body);
\r
99 if (subMenus.length > 0) {
\r
100 if (className == 'subMenu') {
\r
101 var subMenu = Builder.node('DIV', [MenuBar.mark.dir]);
\r
102 this.classNames.addClassNames(subMenu, 'dirMark');
\r
103 body.appendChild(subMenu);
\r
106 var container = Builder.node('DIV', subMenus);
\r
107 this.classNames.addClassNames(container, 'subMenuContainer');
\r
108 element.appendChild(container);
\r
110 this.hide(container);
\r
112 Event.observe(element, "click", this.onClick.bindAsEventListener(this, body));
\r
115 onClick: function(event, menuBody) {
\r
116 var menu = menuBody.parentNode;
\r
117 var parentContainer = this.getParentContainer(menu);
\r
119 var container = this.getContainer(menu);
\r
120 var className = MenuBar.cssNames.menu;
\r
121 if (Element.hasClassName(menu, className)) {
\r
122 if (this.clicked.length > 0) {
\r
123 this.hideAll(this.menubar);
\r
126 if (container) this.showAtBottom(container, menuBody);
\r
130 var lastMenuBody = this.clicked.pop();
\r
131 var lastMenu = lastMenuBody.parentNode;
\r
132 var lastContainer = this.getContainer(lastMenu);
\r
133 var lastParentContainer = this.getParentContainer(lastMenu);
\r
135 if (lastMenu == menu) {
\r
136 this.hide(container);
\r
138 } else if (Element.hasClassName(lastContainer, MenuBar.cssNames.container)) {
\r
139 this.clicked.push(last);
\r
141 } else if (lastParentContainer == parentContainer) {
\r
142 this.hide(lastContainer);
\r
145 this.clicked.push(lastMenuBody);
\r
147 this.showAtLeft(container, menu);
\r
148 } else if (this.options.hideOnClickSubmenu) {
\r
149 this.hideAll(this.menubar);
\r
153 if (container) this.clicked.push(menuBody);
\r
157 showAtBottom: function(contents, menuBody) {
\r
158 var offset = Position.positionedOffset(menuBody);
\r
161 if (menuBody.style.height) height = Element.getHeight(menuBody);
\r
162 else height = menuBody.clientHeight;
\r
163 height += offset[1];
\r
164 height += (document.all) ? 4 : 3;
\r
166 contents.style.top = height + 'px';
\r
167 contents.style.left = offset[0] + 'px';
\r
169 this.show(contents);
\r
172 showAtLeft: function(contents, menuBody) {
\r
173 var offset = Position.positionedOffset(menuBody);
\r
175 contents.style.top = (offset[1] - 1) + 'px';
\r
176 contents.style.left = (offset[0] + menuBody.offsetWidth + 2) + 'px';
\r
178 this.show(contents);
\r
181 hideAllTrigger: function(element) {
\r
182 return function(event) {
\r
183 if (!this.isMenuElement(Event.element(event))) this.hideAll(element);
\r
187 hideAll: function(element) {
\r
188 var nodes = element.childNodes;
\r
189 for (var i = 0; i < nodes.length; i++) {
\r
190 if (nodes[i].nodeType == 1) {
\r
191 if (Element.hasClassName(nodes[i], MenuBar.cssNames.subMenuContainer)) {
\r
192 this.hide(nodes[i]);
\r
195 this.hideAll(nodes[i]);
\r
200 show: function(element) {
\r
201 element.style.visibility = 'visible';
\r
204 hide: function(element) {
\r
205 element.style.visibility = 'hidden';
\r
208 getContainer: function(element) {
\r
210 if (!element) return;
\r
211 return document.getElementsByClassName(MenuBar.cssNames.subMenuContainer, element)[0];
\r
214 getParentContainer: function(element) {
\r
215 var container = Element.getParentByClassName(MenuBar.cssNames.subMenuContainer, element);
\r
217 container = Element.getParentByClassName(MenuBar.cssNames.container, element);
\r
223 isMenuElement: function(element) {
\r
224 return Element.hasClassName(element, MenuBar.cssNames.menuBodyHover)
\r
225 || Element.hasClassName(element, MenuBar.cssNames.subMenuBodyHover)
\r
226 || Element.hasClassName(element, MenuBar.cssNames.dirMark);
\r