fixing librejs on defectivebydesign.org
[weblabels.fsf.org.git] / crm.fsf.org / 20131203 / files / sites / all / modules / civicrm / packages / jquery / plugins / jquery.menu.js
1 /*
2 * jQuery Menu plugin
3 * Version: 0.0.9
4 *
5 * Copyright (c) 2007 Roman Weich
6 * http://p.sohei.org
7 *
8 * Dual licensed under the MIT and GPL licenses
9 * (This means that you can choose the license that best suits your project, and use it accordingly):
10 * http://www.opensource.org/licenses/mit-license.php
11 * http://www.gnu.org/licenses/gpl.html
12 *
13 * Changelog:
14 * v 0.0.9 - 2008-01-19
15 */
16
17 (function($)
18 {
19 var menus = [], //list of all menus
20 visibleMenus = [], //list of all visible menus
21 activeMenu = activeItem = null,
22 menuDIVElement = $('<div class="menu-div outerbox" style="position:absolute;top:0;left:0;display:none;"><div class="shadowbox1"></div><div class="shadowbox2"></div><div class="shadowbox3"></div></div>')[0],
23 menuULElement = $('<ul class="menu-ul innerbox"></ul>')[0],
24 menuItemElement = $('<li style="position:relative;"><div class="menu-item"></div></li>')[0],
25 arrowElement = $('<img class="menu-item-arrow" />')[0],
26 $rootDiv = $('<div id="root-menu-div" style="position:absolute;top:0;left:0;"></div>'), //create main menu div
27 defaults = {
28 // $.Menu options
29 showDelay : 200,
30 hideDelay : 200,
31 hoverOpenDelay: 0,
32 offsetTop : 0,
33 offsetLeft : 0,
34 minWidth: 0,
35 onOpen: null,
36 onClose: null,
37
38 // $.MenuItem options
39 onClick: null,
40 arrowSrc: null,
41 addExpando: false,
42
43 // $.fn.menuFromElement options
44 copyClassAttr: false
45 };
46
47 $(function(){
48 $rootDiv.appendTo('body');
49 });
50
51 $.extend({
52 MenuCollection : function(items) {
53
54 this.menus = [];
55
56 this.init(items);
57 }
58 });
59 $.extend($.MenuCollection, {
60 prototype : {
61 init : function(items)
62 {
63 if ( items && items.length )
64 {
65 for ( var i = 0; i < items.length; i++ )
66 {
67 this.addMenu(items[i]);
68 items[i].menuCollection = this;
69 }
70 }
71 },
72 addMenu : function(menu)
73 {
74 if ( menu instanceof $.Menu )
75 this.menus.push(menu);
76
77 menu.menuCollection = this;
78
79 var self = this;
80 $(menu.target).hover(function(){
81 if ( menu.visible )
82 return;
83
84 //when there is an open menu in this collection, hide it and show the new one
85 for ( var i = 0; i < self.menus.length; i++ )
86 {
87 if ( self.menus[i].visible )
88 {
89 self.menus[i].hide();
90 menu.show();
91 return;
92 }
93 }
94 }, function(){});
95 }
96 }
97 });
98
99
100 $.extend({
101 Menu : function(target, items, options) {
102 this.menuItems = []; //all direct child $.MenuItem objects
103 this.subMenus = []; //all subMenus from this.menuItems
104 this.visible = false;
105 this.active = false; //this menu has hover or one of its submenus is open
106 this.parentMenuItem = null;
107 this.settings = $.extend({}, defaults, options);
108 this.target = target;
109 this.$eDIV = null;
110 this.$eUL = null;
111 this.timer = null;
112 this.menuCollection = null;
113 this.openTimer = null;
114
115 this.init();
116 if ( items && items.constructor == Array )
117 this.addItems(items);
118 }
119 });
120
121 $.extend($.Menu, {
122 checkMouse : function(e)
123 {
124 var t = e.target;
125
126 //the user clicked on the target of the currenty open menu
127 if ( visibleMenus.length && t == visibleMenus[0].target )
128 return;
129
130 //get the last node before the #root-menu-div
131 while ( t.parentNode && t.parentNode != $rootDiv[0] )
132 t = t.parentNode;
133
134 //is the found node one of the visible menu elements?
135 if ( !$(visibleMenus).filter(function(){ return this.$eDIV[0] == t }).length )
136 {
137 $.Menu.closeAll();
138 }
139 },
140 checkKey : function(e)
141 {
142 switch ( e.keyCode )
143 {
144 case 13: //return
145 if ( activeItem )
146 activeItem.click(e, activeItem.$eLI[0]);
147 break;
148 case 27: //ESC
149 $.Menu.closeAll();
150 break;
151 case 37: //left
152 if ( !activeMenu )
153 activeMenu = visibleMenus[0];
154 var a = activeMenu;
155 if ( a && a.parentMenuItem ) //select the parent menu and close the submenu
156 {
157 //unbind the events temporary, as we dont want the hoverout event to fire
158 var pmi = a.parentMenuItem;
159 pmi.$eLI.unbind('mouseout').unbind('mouseover');
160 a.hide();
161 pmi.hoverIn(true);
162 setTimeout(function(){ //bind again..but delay it
163 pmi.bindHover();
164 });
165 }
166 else if ( a && a.menuCollection ) //select the previous menu in the collection
167 {
168 var pos,
169 mcm = a.menuCollection.menus;
170 if ( (pos = $.inArray(a, mcm)) > -1 )
171 {
172 if ( --pos < 0 )
173 pos = mcm.length - 1;
174 $.Menu.closeAll();
175 mcm[pos].show();
176 mcm[pos].setActive();
177 if ( mcm[pos].menuItems.length ) //select the first item
178 mcm[pos].menuItems[0].hoverIn(true);
179 }
180 }
181 break;
182 case 38: //up
183 if ( activeMenu )
184 activeMenu.selectNextItem(-1);
185 break;
186 case 39: //right
187 if ( !activeMenu )
188 activeMenu = visibleMenus[0];
189 var m,
190 a = activeMenu,
191 asm = activeItem ? activeItem.subMenu : null;
192 if ( a )
193 {
194 if ( asm && asm.menuItems.length ) //select the submenu
195 {
196 asm.show();
197 asm.menuItems[0].hoverIn();
198 }
199 else if ( (a = a.inMenuCollection()) ) //select the next menu in the collection
200 {
201 var pos,
202 mcm = a.menuCollection.menus;
203 if ( (pos = $.inArray(a, mcm)) > -1 )
204 {
205 if ( ++pos >= mcm.length )
206 pos = 0;
207 $.Menu.closeAll();
208 mcm[pos].show();
209 mcm[pos].setActive();
210 if ( mcm[pos].menuItems.length ) //select the first item
211 mcm[pos].menuItems[0].hoverIn(true);
212 }
213 }
214 }
215 break;
216 case 40: //down
217 if ( !activeMenu )
218 {
219 if ( visibleMenus.length && visibleMenus[0].menuItems.length )
220 visibleMenus[0].menuItems[0].hoverIn();
221 }
222 else
223 activeMenu.selectNextItem();
224 break;
225 }
226 if ( e.keyCode > 36 && e.keyCode < 41 )
227 return false; //this will prevent scrolling
228 },
229 closeAll : function()
230 {
231 while ( visibleMenus.length )
232 visibleMenus[0].hide();
233 },
234 setDefaults : function(d)
235 {
236 $.extend(defaults, d);
237 },
238 prototype : {
239 /**
240 * create / initialize new menu
241 */
242 init : function()
243 {
244 var self = this;
245 if ( !this.target )
246 return;
247 else if ( this.target instanceof $.MenuItem )
248 {
249 this.parentMenuItem = this.target;
250 this.target.addSubMenu(this);
251 this.target = this.target.$eLI;
252 }
253
254 menus.push(this);
255
256 //use the dom methods instead the ones from jquery (faster)
257 this.$eDIV = $(menuDIVElement.cloneNode(1));
258 this.$eUL = $(menuULElement.cloneNode(1));
259 this.$eDIV[0].appendChild(this.$eUL[0]);
260 $rootDiv[0].appendChild(this.$eDIV[0]);
261
262 //bind events
263 if ( !this.parentMenuItem )
264 {
265 $(this.target).click(function(e){
266 self.onClick(e);
267 }).hover(function(e){
268 self.setActive();
269
270 if ( self.settings.hoverOpenDelay )
271 {
272 self.openTimer = setTimeout(function(){
273 if ( !self.visible )
274 self.onClick(e);
275 }, self.settings.hoverOpenDelay);
276 }
277 }, function(){
278 if ( !self.visible )
279 $(this).removeClass('activetarget');
280
281 if ( self.openTimer )
282 clearTimeout(self.openTimer);
283 });
284 }
285 else
286 {
287 this.$eDIV.hover(function(){
288 self.setActive();
289 }, function(){});
290 }
291 },
292 setActive : function()
293 {
294 if ( !this.parentMenuItem )
295 $(this.target).addClass('activetarget');
296 else
297 this.active = true;
298 },
299 addItem : function(item)
300 {
301 if ( item instanceof $.MenuItem )
302 {
303 if ( $.inArray(item, this.menuItems) == -1 )
304 {
305 this.$eUL.append(item.$eLI);
306 this.menuItems.push(item);
307 item.parentMenu = this;
308 if ( item.subMenu )
309 this.subMenus.push(item.subMenu);
310 }
311 }
312 else
313 {
314 this.addItem(new $.MenuItem(item, this.settings));
315 }
316 },
317 addItems : function(items)
318 {
319 for ( var i = 0; i < items.length; i++ )
320 {
321 this.addItem(items[i]);
322 }
323 },
324 removeItem : function(item)
325 {
326 var pos = $.inArray(item, this.menuItems);
327 if ( pos > -1 )
328 this.menuItems.splice(pos, 1);
329 item.parentMenu = null;
330 },
331 hide : function()
332 {
333 if ( !this.visible )
334 return;
335
336 var i,
337 pos = $.inArray(this, visibleMenus);
338
339 this.$eDIV.hide();
340
341 if ( pos >= 0 )
342 visibleMenus.splice(pos, 1);
343 this.visible = this.active = false;
344
345 $(this.target).removeClass('activetarget');
346
347 //hide all submenus
348 for ( i = 0; i < this.subMenus.length; i++ )
349 {
350 this.subMenus[i].hide();
351 }
352
353 //set all items inactive (e.g. remove hover class..)
354 for ( i = 0; i < this.menuItems.length; i++ )
355 {
356 if ( this.menuItems[i].active )
357 this.menuItems[i].setInactive();
358 }
359
360 if ( !visibleMenus.length ) //unbind events when the last menu was closed
361 $(document).unbind('mousedown', $.Menu.checkMouse).unbind('keydown', $.Menu.checkKey);
362
363 if ( activeMenu == this )
364 activeMenu = null;
365
366 if ( this.settings.onClose )
367 this.settings.onClose.call(this);
368 },
369 show : function(e)
370 {
371 if ( this.visible )
372 return;
373
374 var zi,
375 pmi = this.parentMenuItem;
376
377 if ( this.menuItems.length ) //show only when it has items
378 {
379 if ( pmi ) //set z-index
380 {
381 zi = parseInt(pmi.parentMenu.$eDIV.css('z-index'));
382 this.$eDIV.css('z-index', (isNaN(zi) ? 1 : zi + 1));
383 }
384 this.$eDIV.css({visibility: 'hidden', display:'block'});
385
386 //set min-width
387 if ( this.settings.minWidth )
388 {
389 if ( this.$eDIV.width() < this.settings.minWidth )
390 this.$eDIV.css('width', this.settings.minWidth);
391 }
392
393 this.setPosition();
394 this.$eDIV.css({display:'none', visibility: ''}).show();
395
396 //IEs default width: auto is bad! ie6 and ie7 have are producing different errors.. (7 = 5px shadowbox + 2px border)
397 if ( $.browser.msie )
398 this.$eUL.css('width', parseInt($.browser.version) == 6 ? this.$eDIV.width() - 7 : this.$eUL.width());
399
400 if ( this.settings.onOpen )
401 this.settings.onOpen.call(this);
402 }
403 if ( visibleMenus.length == 0 )
404 $(document).bind('mousedown', $.Menu.checkMouse).bind('keydown', $.Menu.checkKey);
405
406 this.visible = true;
407 visibleMenus.push(this);
408 },
409 setPosition : function()
410 {
411 var $t, o, posX, posY,
412 pmo, //parent menu offset
413 wst, //window scroll top
414 wsl, //window scroll left
415 ww = $(window).width(),
416 wh = $(window).height(),
417 pmi = this.parentMenuItem,
418 height = this.$eDIV[0].clientHeight,
419 width = this.$eDIV[0].clientWidth,
420 pheight; //parent height
421
422 if ( pmi )
423 {
424 //position on the right side of the parent menu item
425 o = pmi.$eLI.offset();
426 posX = o.left + pmi.$eLI.width();
427 posY = o.top;
428 }
429 else
430 {
431 //position right below the target
432 $t = $(this.target);
433 o = $t.offset();
434 posX = o.left + this.settings.offsetLeft;
435 posY = o.top + $t.height() + this.settings.offsetTop;
436 }
437
438 //y-pos
439 if ( $.fn.scrollTop )
440 {
441 wst = $(window).scrollTop();
442 if ( wh < height ) //menu is bigger than the window
443 {
444 //position the menu at the top of the visible area
445 posY = wst;
446 }
447 else if ( wh + wst < posY + height ) //outside on the bottom?
448 {
449 if ( pmi )
450 {
451 pmo = pmi.parentMenu.$eDIV.offset();
452 pheight = pmi.parentMenu.$eDIV[0].clientHeight;
453 if ( height <= pheight )
454 {
455 //bottom position = parentmenu-bottom position
456 posY = pmo.top + pheight - height;
457 }
458 else
459 {
460 //top position = parentmenu-top position
461 posY = pmo.top;
462 }
463 //still outside on the bottom?
464 if ( wh + wst < posY + height )
465 {
466 //shift the menu upwards till the bottom is visible
467 posY -= posY + height - (wh + wst);
468 }
469 }
470 else
471 {
472 //shift the menu upwards till the bottom is visible
473 posY -= posY + height - (wh + wst);
474 }
475 }
476 }
477 //x-pos
478 if ( $.fn.scrollLeft )
479 {
480 wsl = $(window).scrollLeft();
481 if ( ww + wsl < posX + width )
482 {
483 if ( pmi )
484 {
485 //display the menu not on the right side but on the left side
486 posX -= pmi.$eLI.width() + width;
487 //outside on the left now?
488 if ( posX < wsl )
489 posX = wsl;
490 }
491 else
492 {
493 //shift the menu to the left until it fits
494 posX -= posX + width - (ww + wsl);
495 }
496 }
497 }
498
499 //set position
500 this.$eDIV.css({left: posX, top: posY});
501 },
502 onClick : function(e)
503 {
504 if ( this.visible )
505 {
506 this.hide();
507 this.setActive(); //the class is removed in the hide() method..add it again
508 }
509 else
510 {
511 //close all open menus
512 $.Menu.closeAll();
513 this.show(e);
514 }
515 },
516 addTimer : function(callback, delay)
517 {
518 var self = this;
519 this.timer = setTimeout(function(){
520 callback.call(self);
521 self.timer = null;
522 }, delay);
523 },
524 removeTimer : function()
525 {
526 if ( this.timer )
527 {
528 clearTimeout(this.timer);
529 this.timer = null;
530 }
531 },
532 selectNextItem : function(offset)
533 {
534 var i, pos = 0,
535 mil = this.menuItems.length,
536 o = offset || 1;
537
538 //get current pos
539 for ( i = 0; i < mil; i++ )
540 {
541 if ( this.menuItems[i].active )
542 {
543 pos = i;
544 break;
545 }
546 }
547 this.menuItems[pos].hoverOut();
548
549 do //jump over the separators
550 {
551 pos += o;
552 if ( pos >= mil )
553 pos = 0;
554 else if ( pos < 0 )
555 pos = mil - 1;
556 } while ( this.menuItems[pos].separator );
557 this.menuItems[pos].hoverIn(true);
558 },
559 inMenuCollection : function()
560 {
561 var m = this;
562 while ( m.parentMenuItem )
563 m = m.parentMenuItem.parentMenu;
564 return m.menuCollection ? m : null;
565 },
566 destroy : function() //delete menu
567 {
568 var pos, item;
569
570 this.hide();
571
572 //unbind events
573 if ( !this.parentMenuItem )
574 $(this.target).unbind('click').unbind('mouseover').unbind('mouseout');
575 else
576 this.$eDIV.unbind('mouseover').unbind('mouseout');
577
578 //destroy all items
579 while ( this.menuItems.length )
580 {
581 item = this.menuItems[0];
582 item.destroy();
583 delete item;
584 }
585
586 if ( (pos = $.inArray(this, menus)) > -1 )
587 menus.splice(pos, 1);
588
589 if ( this.menuCollection )
590 {
591 if ( (pos = $.inArray(this, this.menuCollection.menus)) > -1 )
592 this.menuCollection.menus.splice(pos, 1);
593 }
594
595 this.$eDIV.remove();
596 }
597 }
598 });
599
600 $.extend({
601 MenuItem : function(obj, options)
602 {
603 if ( typeof obj == 'string' )
604 obj = {src: obj};
605
606 this.src = obj.src || '';
607 this.url = obj.url || null;
608 this.urlTarget = obj.target || null;
609 this.addClass = obj.addClass || null;
610 this.data = obj.data || null;
611
612 this.$eLI = null;
613 this.parentMenu = null;
614 this.subMenu = null;
615 this.settings = $.extend({}, defaults, options);
616 this.active = false;
617 this.enabled = true;
618 this.separator = false;
619
620 this.init();
621
622 if ( obj.subMenu )
623 new $.Menu(this, obj.subMenu, options);
624 }
625 });
626
627 $.extend($.MenuItem, {
628 prototype : {
629 init : function()
630 {
631 var i, isStr,
632 src = this.src,
633 self = this;
634
635 this.$eLI = $(menuItemElement.cloneNode(1));
636
637 if ( this.addClass )
638 this.$eLI[0].setAttribute('class', this.addClass);
639
640 if ( this.settings.addExpando && this.data )
641 this.$eLI[0].menuData = this.data;
642
643 if ( src == '' )
644 {
645 this.$eLI.addClass('menu-separator');
646 this.separator = true;
647 }
648 else
649 {
650 isStr = typeof src == 'string';
651 if ( isStr && this.url ) //create a link node, when we have an url
652 src = $('<a href="' + this.url + '"' + (this.urlTarget ? 'target="' + this.urlTarget + '"' : '') + '>' + src + '</a>');
653 else if ( isStr || !src.length )
654 src = [src];
655 //go through the passed DOM-Elements (or jquery objects or text nodes.) and append them to the menus list item
656 //this.$eLI.append(this.src) is really slow when having a lot(!!!) of items
657 for ( i = 0; i < src.length; i++ )
658 {
659 if ( typeof src[i] == 'string' )
660 {
661 //we cant use createTextNode, as html entities won't be displayed correctly (eg. &copy;)
662 elem = document.createElement('span');
663 elem.innerHTML = src[i];
664 this.$eLI[0].firstChild.appendChild(elem);
665 }
666 else
667 this.$eLI[0].firstChild.appendChild(src[i].cloneNode(1));
668 }
669 }
670
671 this.$eLI.click(function(e){
672 self.click(e, this);
673 });
674 this.bindHover();
675 },
676 click : function(e, scope)
677 {
678 if ( this.enabled && this.settings.onClick )
679 this.settings.onClick.call(scope, e, this);
680 },
681 bindHover : function()
682 {
683 var self = this;
684 this.$eLI.hover(function(){
685 self.hoverIn();
686 }, function(){
687 self.hoverOut();
688 });
689 },
690 hoverIn : function(noSubMenu)
691 {
692 this.removeTimer();
693
694 var i,
695 pms = this.parentMenu.subMenus,
696 pmi = this.parentMenu.menuItems,
697 self = this;
698
699 //remove the timer from the parent item, when there is one (e.g. to close the menu)
700 if ( this.parentMenu.timer )
701 this.parentMenu.removeTimer();
702
703 if ( !this.enabled )
704 return;
705
706 //deactivate all menuItems on the same level
707 for ( i = 0; i < pmi.length; i++ )
708 {
709 if ( pmi[i].active )
710 pmi[i].setInactive();
711 }
712
713 this.setActive();
714 activeMenu = this.parentMenu;
715
716 //are there open submenus on the same level? close them!
717 for ( i = 0; i < pms.length; i++ )
718 {
719 if ( pms[i].visible && pms[i] != this.subMenu && !pms[i].timer ) //close if there is no closetimer running already
720 pms[i].addTimer(function(){
721 this.hide();
722 }, pms[i].settings.hideDelay);
723 }
724
725 if ( this.subMenu && !noSubMenu )
726 {
727 //set timeout to show menu
728 this.subMenu.addTimer(function(){
729 this.show();
730 }, this.subMenu.settings.showDelay);
731 }
732 },
733 hoverOut : function()
734 {
735 this.removeTimer();
736
737 if ( !this.enabled )
738 return;
739
740 if ( !this.subMenu || !this.subMenu.visible )
741 this.setInactive();
742 },
743 removeTimer : function()
744 {
745 if ( this.subMenu )
746 {
747 this.subMenu.removeTimer();
748 }
749 },
750 setActive : function()
751 {
752 this.active = true;
753 this.$eLI.addClass('active');
754
755 //set the parent menu item active too if necessary
756 var pmi = this.parentMenu.parentMenuItem;
757 if ( pmi && !pmi.active )
758 pmi.setActive();
759
760 activeItem = this;
761 },
762 setInactive : function()
763 {
764 this.active = false;
765 this.$eLI.removeClass('active');
766 if ( this == activeItem )
767 activeItem = null;
768 },
769 enable : function()
770 {
771 this.$eLI.removeClass('disabled');
772 this.enabled = true;
773 },
774 disable : function()
775 {
776 this.$eLI.addClass('disabled');
777 this.enabled = false;
778 },
779 destroy : function()
780 {
781 this.removeTimer();
782
783 this.$eLI.remove();
784
785 //unbind events
786 this.$eLI.unbind('mouseover').unbind('mouseout').unbind('click');
787 //delete submenu
788 if ( this.subMenu )
789 {
790 this.subMenu.destroy();
791 delete this.subMenu;
792 }
793 this.parentMenu.removeItem(this);
794 },
795 addSubMenu : function(menu)
796 {
797 if ( this.subMenu )
798 return;
799 this.subMenu = menu;
800 if ( this.parentMenu && $.inArray(menu, this.parentMenu.subMenus) == -1 )
801 this.parentMenu.subMenus.push(menu);
802 if ( this.settings.arrowSrc )
803 {
804 var a = arrowElement.cloneNode(0);
805 a.setAttribute('src', this.settings.arrowSrc);
806 this.$eLI[0].firstChild.appendChild(a);
807 }
808 }
809 }
810 });
811
812
813 $.extend($.fn, {
814 menuFromElement : function(options, list, bar)
815 {
816 var createItems = function(ul)
817 {
818 var menuItems = [],
819 subItems,
820 menuItem,
821 lis, $li, i, subUL, submenu, target,
822 classNames = null;
823
824 lis = getAllChilds(ul, 'LI');
825 for ( i = 0; i < lis.length; i++ )
826 {
827 subItems = [];
828
829 if ( !lis[i].childNodes.length ) //empty item? add separator
830 {
831 menuItems.push(new $.MenuItem('', options));
832 continue;
833 }
834
835 if ( (subUL = getOneChild(lis[i], 'UL')) )
836 {
837 subItems = createItems(subUL);
838 //remove subUL from DOM
839 $(subUL).remove();
840 }
841
842 //select the target...get the elements inside the li
843 $li = $(lis[i]);
844 if ( $li[0].childNodes.length == 1 && $li[0].childNodes[0].nodeType == 3 )
845 target = $li[0].childNodes[0].nodeValue;
846 else
847 target = $li[0].childNodes;
848
849 if ( options && options.copyClassAttr )
850 classNames = $li.attr('class');
851
852 //create item
853 menuItem = new $.MenuItem({src: target, addClass: classNames}, options);
854 menuItems.push(menuItem);
855 //add submenu
856 if ( subItems.length )
857 new $.Menu(menuItem, subItems, options);
858
859 }
860 return menuItems;
861 };
862 return this.each(function()
863 {
864 var ul, m;
865 //get the list element
866 if ( list || (ul = getOneChild(this, 'UL')) )
867 {
868 //if a specific list element is used, clone it, as we probably need it more than once
869 ul = list ? $(list).clone(true)[0] : ul;
870 menuItems = createItems(ul);
871 if ( menuItems.length )
872 {
873 m = new $.Menu(this, menuItems, options);
874 if ( bar )
875 bar.addMenu(m);
876 }
877 $(ul).hide();
878 }
879 });
880 },
881 menuBarFromUL : function(options)
882 {
883 return this.each(function()
884 {
885 var i,
886 lis = getAllChilds(this, 'LI');
887
888 if ( lis.length )
889 {
890 bar = new $.MenuCollection();
891 for ( i = 0; i < lis.length; i++ )
892 $(lis[i]).menuFromElement(options, null, bar);
893 }
894 });
895 },
896 menu : function(options, items)
897 {
898 return this.each(function()
899 {
900 if ( items && items.constructor == Array )
901 new $.Menu(this, items, options);
902 else
903 {
904 if ( this.nodeName.toUpperCase() == 'UL' )
905 $(this).menuBarFromUL(options);
906 else
907 $(this).menuFromElement(options, items);
908 }
909 });
910 }
911 });
912
913 //faster than using jquery
914 var getOneChild = function(elem, name)
915 {
916 if ( !elem )
917 return null;
918
919 var n = elem.firstChild;
920 for ( ; n; n = n.nextSibling )
921 {
922 if ( n.nodeType == 1 && n.nodeName.toUpperCase() == name )
923 return n;
924 }
925 return null;
926 };
927 //faster than using jquery
928 var getAllChilds = function(elem, name)
929 {
930 if ( !elem )
931 return [];
932
933 var r = [],
934 n = elem.firstChild;
935 for ( ; n; n = n.nextSibling )
936 {
937 if ( n.nodeType == 1 && n.nodeName.toUpperCase() == name )
938 r[r.length] = n;
939 }
940 return r;
941 };
942
943 })(jQuery);