Using jQuery to create an overflow menu as seen in Google Wave

One of the features UI that Google wave uses is what I call the "overflow" menu. If you have a wave account you may have noticed that depending on your browser window size not all of the menu options are shown.  The hidden options tucked away nicely in a drop down menu.  On resizing your browser widow, options are added or removed from the menu.  I thought that was pretty slick and thought it would be pretty easy to recreate the functionality using jQuery. So enough with the story on to the code. 

Update: I converted this code over to a jQuery UI widget. Check it out here

The markup is pretty simple. We have to divs that hold the two different "views" for the menu options

 <div id="menuWrapper" class="f2">
    <div class="f2 full">
        <div class="item"><a href="#">option one</a></div>
        <div class="item"><a href="#">option two</a></div>
        <div class="item"><a href="#">option three</a></div>
        <div class="item"><a href="#">option four</a></div>
        <div class="item"><a href="#">option five</a></div>
        <div class="item"><a href="#">option six</a></div>
        <div class="item"><a href="#">option seven</a></div>
    </div>
    <div class="f2 overflowMenuWrapper">
        <div class="handel">more</div>
        <div class="menu"></div>
    </div>
</div>

It doesn't much css to get us up and running. I'm using absolute positioning for the base elements and floats the menu options

    .f2{
        bottom:0;
        left:0px;
        overflow:visible;
        position:absolute;
        right:0px;
        top:0;
    }
    #wrapper{
        top: 30px;
        left: 20px;
        right: 20px;
        min-width: 100px;
        /*width: 300px;*/
    }
    #menuWrapper{
        height: 25px;
    }
    .full{
        overflow: hidden;
        right: 30px;
    }
    .overflowMenuWrapper{
        width: 30px;
        left: auto;
    }
    .full div.item{
        float: left;
        padding: 4px 8px;
    }
    .overflowMenuWrapper .menu{
        background:none repeat scroll 0 0 #FFFFFF;
        border:1px solid black;
        display:none;
        padding:5px;
        position:relative;
        right:125px;
        width:150px;
        z-index:100000;
    }
    .overflowMenuWrapper .handel{
        cursor: pointer;
    }
    .overflowMenuWrapper .disabled{
        color: gray;
    }

Next is the script. Line #28 we check all of the options in the full size menu, the hidden options are cloned and prepended to the overflow menu. If you're looking to attach resizing elements other than window, take a look at Ben Alman's event resize plugin.

$().ready(function(){
    //bind the overflow menu handel
   	$('#menuWrapper').find('.handel').click(function(){
   	    var $this=$(this);
        //dont show the drop down if its disabled
        if($this.hasClass('disabled')===true){
            return false;
        }
        var __temp=$this.next('.menu');
        __temp.fadeIn(500);
        //if the menu is showing and the user clicks anywhere hide the overflow menu dropdown
        $(document).one('click',function(){
               __temp.fadeOut(500); 
            });
          return false;  
          });
          
              $(window).resize(function() {

               var $menuWrapper=$('#menuWrapper'),
               $fullMenu=$menuWrapper.children('.full'),
               $overFlowMenu=$menuWrapper.find('.menu'),
               fullHeight=$fullMenu.innerHeight()
               $handle = $menuWrapper.find('.handel').addClass('disabled');
                //remove all of the actions out of the overflow menu
                $overFlowMenu.children('div').remove();
                //find all of the .items that arent visiable and add/clone them to the overflow menu 
                $fullMenu.children('div.item').filter(function(){
                    return this.offsetTop+$(this).height()>fullHeight;
                }).clone(true).prependTo($overFlowMenu[0]);
                
                
                if($overFlowMenu.children('.item').length!==0){
                   $handle.removeClass('disabled');
                }else{
                    //no options fade out the drop down menu, 
                    $overFlowMenu.fadeOut(500);
                }

            }).trigger('resize');
     
});

Thats it! To see a working demo check out the attachements below.