JAVASCRIPT   41

flexdropdown js

Guest on 20th August 2022 12:53:43 AM

  1. /* Flex Level Drop Down Menu v1.1
  2. * Created: Jan 5th by DynamicDrive.com. This notice must stay intact for usage
  3. * Author: Dynamic Drive at http://www.dynamicdrive.com/
  4. * Visit http://www.dynamicdrive.com/ for full source code
  5. */
  6.  
  7. //Version 1.1: Each flex menu (UL) can now be associated with a link dynamically, and/or defined using JavaScript instead of as markup.
  8.  
  9. //Usage: $(elementselector).addflexmenu('menuid', options)
  10. //ie:
  11. //jQuery(document).ready(function($){
  12.         //$('a.mylinks').addflexmenu('flexmenu1') //apply flex menu with ID "flexmenu1" to links with class="mylinks"
  13. //})
  14.  
  15. //jQuery.noConflict()
  16.  
  17. var flexdropdownmenu={
  18.         arrowpath: 'arrow.gif', //full URL or path to arrow image
  19.         animspeed: 200, //reveal animation speed (in milliseconds)
  20.         showhidedelay: [150, 150], //delay before menu appears and disappears when mouse rolls over it, in milliseconds
  21.  
  22.         //***** NO NEED TO EDIT BEYOND HERE
  23.         startzindex:1000,
  24.         builtflexmenuids: [], //ids of flex menus already built (to prevent repeated building of same flex menu)
  25.  
  26.         positionul:function($, $ul, e, $anchor){
  27.                 var istoplevel=$ul.hasClass('jqflexmenu') //Bool indicating whether $ul is top level flex menu DIV
  28.                 var docrightedge=$(document).scrollLeft()+$(window).width()-40 //40 is to account for shadows in FF
  29.                 var docbottomedge=$(document).scrollTop()+$(window).height()-40
  30.                 if (istoplevel){ //if main flex menu DIV
  31.                         var offsets=$anchor.offset()
  32.                         var anchorsetting=$anchor.data('setting')
  33.                         var x=offsets.left+anchorsetting.useroffsets[0]+(anchorsetting.dir=="h"? $anchor.outerWidth() : 0) //x pos of main flex menu UL
  34.                         var y=offsets.top+anchorsetting.useroffsets[1]+(anchorsetting.dir=="h"? 0 : $anchor.outerHeight())
  35.                         x=(x+$ul.data('dimensions').w > docrightedge)? x-(anchorsetting.useroffsets[0]*2)-$ul.data('dimensions').w+$anchor.outerWidth()+(anchorsetting.dir=="h"? -($anchor.outerWidth()*2) : 0) : x //if not enough horizontal room to the ridge of the cursor
  36.                         y=(y+$ul.data('dimensions').h > docbottomedge)? y-(anchorsetting.useroffsets[1]*2)-$ul.data('dimensions').h-$anchor.outerHeight()+(anchorsetting.dir=="h"? ($anchor.outerHeight()*2) : 0) : y
  37.                 }
  38.                 else{ //if sub level flex menu UL
  39.                         var $parentli=$ul.data('$parentliref')
  40.                         var parentlioffset=$parentli.offset()
  41.                         var x=$ul.data('dimensions').parentliw //x pos of sub UL
  42.                         var y=0
  43.                         x=(parentlioffset.left+x+$ul.data('dimensions').w > docrightedge)? x-$ul.data('dimensions').parentliw-$ul.data('dimensions').w : x //if not enough horizontal room to the ridge parent LI
  44.                         y=(parentlioffset.top+$ul.data('dimensions').h > docbottomedge)? y-$ul.data('dimensions').h+$ul.data('dimensions').parentlih : y
  45.                 }
  46.                 $ul.css({left:x, top:y})
  47.         },
  48.        
  49.         showbox:function($, $flexmenu, e){
  50.                 clearTimeout($flexmenu.data('timers').hidetimer)
  51.                 $flexmenu.data('timers').showtimer=setTimeout(function(){$flexmenu.show(flexdropdownmenu.animspeed)}, this.showhidedelay[0])
  52.         },
  53.  
  54.         hidebox:function($, $flexmenu){
  55.                 clearTimeout($flexmenu.data('timers').showtimer)
  56.                 $flexmenu.data('timers').hidetimer=setTimeout(function(){$flexmenu.hide(100)}, this.showhidedelay[1]) //hide flex menu plus all of its sub ULs
  57.         },
  58.  
  59.  
  60.         buildflexmenu:function($, $menu, $target){
  61.                 $menu.css({display:'block', visibility:'hidden', zIndex:this.startzindex}).addClass('jqflexmenu').appendTo(document.body)
  62.                 $menu.bind('mouseenter', function(){
  63.                         clearTimeout($menu.data('timers').hidetimer)
  64.                 })             
  65.                 $menu.bind('mouseleave', function(){ //hide menu when mouse moves out of it
  66.                         flexdropdownmenu.hidebox($, $menu)
  67.                 })
  68.                 $menu.data('dimensions', {w:$menu.outerWidth(), h:$menu.outerHeight()}) //remember main menu's dimensions
  69.                 $menu.data('timers', {})
  70.                 var $lis=$menu.find("ul").parent() //find all LIs within menu with a sub UL
  71.                 $lis.each(function(i){
  72.                         var $li=$(this).css({zIndex: 1000+i})
  73.                         var $subul=$li.find('ul:eq(0)').css({display:'block'}) //set sub UL to "block" so we can get dimensions
  74.                         $subul.data('dimensions', {w:$subul.outerWidth(), h:$subul.outerHeight(), parentliw:this.offsetWidth, parentlih:this.offsetHeight})
  75.                         $subul.data('$parentliref', $li) //cache parent LI of each sub UL
  76.                         $subul.data('timers', {})
  77.                         $li.data('$subulref', $subul) //cache sub UL of each parent LI
  78.                         $li.children("a:eq(0)").append( //add arrow images
  79.                                 '<img src="'+flexdropdownmenu.arrowpath+'" class="rightarrowclass" style="border:0;" />'
  80.                         )
  81.                         $li.bind('mouseenter', function(e){ //show sub UL when mouse moves over parent LI
  82.                                 var $targetul=$(this).css('zIndex', ++flexdropdownmenu.startzindex).addClass("selected").data('$subulref')
  83.                                 if ($targetul.queue().length<=1){ //if 1 or less queued animations
  84.                                         clearTimeout($targetul.data('timers').hidetimer)
  85.                                         $targetul.data('timers').showtimer=setTimeout(function(){
  86.                                                 flexdropdownmenu.positionul($, $targetul, e)
  87.                                                 $targetul.show(flexdropdownmenu.animspeed)
  88.                                         }, flexdropdownmenu.showhidedelay[0])
  89.                                 }
  90.                         })
  91.                         $li.bind('mouseleave', function(e){ //hide sub UL when mouse moves out of parent LI
  92.                                 var $targetul=$(this).data('$subulref')
  93.                                 clearTimeout($targetul.data('timers').showtimer)
  94.                                 $targetul.data('timers').hidetimer=setTimeout(function(){$targetul.hide(100).data('$parentliref').removeClass('selected')}, flexdropdownmenu.showhidedelay[1])
  95.                         })
  96.                 })
  97.                 $menu.find('ul').andSelf().css({display:'none', visibility:'visible'}) //collapse all ULs again
  98.                 this.builtflexmenuids.push($menu.get(0).id) //remember id of flex menu that was just built
  99.         },
  100.  
  101.        
  102.  
  103.         init:function($, $target, $flexmenu){
  104.                 if (this.builtflexmenuids.length==0){ //only bind click event to document once
  105.                         $(document).bind("click", function(e){
  106.                                 if (e.button==0){ //hide all flex menus (and their sub ULs) when left mouse button is clicked
  107.                                         $('.jqflexmenu').find('ul').andSelf().hide()
  108.                                 }
  109.                         })
  110.                 }
  111.                 if (jQuery.inArray($flexmenu.get(0).id, this.builtflexmenuids)==-1) //if this flex menu hasn't been built yet
  112.                         this.buildflexmenu($, $flexmenu, $target)
  113.                 if ($target.parents().filter('ul.jqflexmenu').length>0) //if $target matches an element within the flex menu markup, don't bind onflexmenu to that element
  114.                         return
  115.                 var useroffsets=$target.attr('data-offsets')? $target.attr('data-offsets').split(',') : [0,0] //get additional user offsets of menu
  116.                 useroffsets=[parseInt(useroffsets[0]), parseInt(useroffsets[1])]
  117.                 $target.data('setting', {dir: $target.attr('data-dir'), useroffsets: useroffsets}) //store direction (drop right or down) of menu plus user offsets
  118.                 $target.bind("mouseenter", function(e){
  119.                         $flexmenu.css('zIndex', ++flexdropdownmenu.startzindex)
  120.                         flexdropdownmenu.positionul($, $flexmenu, e, $target)
  121.                         flexdropdownmenu.showbox($, $flexmenu, e)
  122.                 })
  123.                 $target.bind("mouseleave", function(e){
  124.                         flexdropdownmenu.hidebox($, $flexmenu)
  125.                 })
  126.         }
  127. }
  128.  
  129. jQuery.fn.addflexmenu=function(flexmenuid, options){
  130.         var $=jQuery
  131.         return this.each(function(){ //return jQuery obj
  132.                 var $target=$(this)
  133.                 if (typeof options=="object"){ //if options parameter defined
  134.                         if (options.dir)
  135.                                 $target.attr('data-dir', options.dir) //set/overwrite data-dir attr with defined value
  136.                         if (options.offsets)
  137.                                 $target.attr('data-offsets', options.offsets) //set/overwrite data-offsets attr with defined value
  138.                 }
  139.                 if ($('#'+flexmenuid).length==1) //check flex menu is defined
  140.                         flexdropdownmenu.init($, $target, $('#'+flexmenuid))
  141.         })
  142. };
  143.  
  144. //By default, add flex menu to anchor links with attribute "data-flexmenu"
  145. jQuery(document).ready(function($){
  146.         var $anchors=$('*[data-flexmenu]')
  147.         $anchors.each(function(){
  148.                 $(this).addflexmenu(this.getAttribute('data-flexmenu'))
  149.         })
  150. })
  151.  
  152.  
  153. //ddlistmenu: Function to define a UL list menu dynamically
  154.  
  155. function ddlistmenu(id, className){
  156.         var menu=document.createElement('ul')
  157.         if (id)
  158.                 menu.id=id
  159.         if (className)
  160.                 menu.className=className
  161.         this.menu=menu
  162. }
  163.  
  164. ddlistmenu.prototype={
  165.         addItem:function(url, text, target){
  166.                 var li=document.createElement('li')
  167.                 li.innerHTML='<a href="'+url+'" target="'+target+'">'+text+'</a>'
  168.                 this.menu.appendChild(li)
  169.                 this.li=li
  170.                 return this
  171.         },
  172.         addSubMenu:function(){
  173.                 var s=new ddlistmenu(null, null)
  174.                 this.li.appendChild(s.menu)
  175.                 return s
  176.  
  177.         }
  178. }

Raw Paste


Login or Register to edit or fork this paste. It's free.