function optional_drop_down_menu(arrow,link,menu,event,arrow_class,arrow_old_class,on_click_callback,off_click_callback)
{
    if (menu.style.display=='none') {
        menu.style.display='block';
        var old_arrow_classname=arrow_old_class?arrow_old_class:arrow.className;
        
        if (link) {
            link.className='active';
        }
        arrow.className=arrow_class?arrow_class:'global_menu_arrow_active';
        var justChanged=true;
        var shim=ge(menu.id+'_iframe');
        if (shim) { 
            shim.style.top=menu.style.top;
            shim.style.right=menu.style.left;
            shim.style.display='block';
            shim.style.width=(menu.offsetWidth+2)+'px';
            shim.style.height=(menu.offsetHeight+2)+'px';
        }


        menu.offclick=function(e) {
            if (!justChanged) { 
            
                hide(this);
                if (link) { 
                    link.className='';
                }
                
                arrow.className=old_arrow_classname;
                var shim=ge(menu.id+'_iframe');
                if (shim) { 
                    shim.style.display='none';
                    shim.style.width=menu.offsetWidth+'px';
                    shim.style.height=menu.offsetHeight+'px';
                }
                
                if (off_click_callback) {
                    off_click_callback(e);
                }
                removeEventBase( document,'click',this.offclick,menu.id );
            } else {
                justChanged=false;
            }
        }.bind(menu);
        
        if (on_click_callback) {
            on_click_callback();
        }
        
        addEventBase(document,'click',menu.offclick,menu.id);
    }
    return false;
}

function hide() 
{   
    for (var i=0;i<arguments.length;i++) {
        var element=ge(arguments[i]);
        if (element&&element.style) 
            element.style.display='none';
    }
    return false;
}

function addEventBase (obj,type,fn,name_hash)
{
    if (obj.addEventListener)
        obj.addEventListener(type,fn,false);
    else if (obj.attachEvent) {
            obj["e"+type+fn+name_hash]=fn;obj[type+fn+name_hash]=function(){
            obj["e"+type+fn+name_hash](window.event);
        }
        obj.attachEvent("on"+type,obj[type+fn+name_hash]);
    }
}

function removeEventBase(obj,type,fn,name_hash)
{
    if (obj.removeEventListener)
        obj.removeEventListener(type,fn,false);
    else if (obj.detachEvent) {
        obj.detachEvent("on"+type,obj[type+fn+name_hash]);
        obj[type+fn+name_hash]=null;
        obj["e"+type+fn+name_hash]=null;
    }
}

function ge(id) 
{
    if (typeof(id)=='undefined') {
        Util.error('Tried to get an undefined element!');
        return null;
    }

    var obj;
    if ( typeof(id)=='string' ) {
        obj=document.getElementById(id);
//        if (!(ua.ie()>=7)) {
//            return obj;
//        }

        
        if (!obj) {
            return null;
        } else if ( typeof(obj.id)=='string'&&obj.id==id) { 
            return obj;
        } else {
            var candidates=document.getElementsByName(id);
            if (!candidates||!candidates.length) {
                return null;
            }
            
            var maybe=[];
            for (var ii=0;ii<candidates.length;ii++) { 
                var c=candidates[ii];
                if(!c.id&&id) {
                    continue;
                }
                if (typeof(c.id)=='string'&&c.id!=id) {
                    continue;
                }
                maybe.push(candidates[ii]);
            }
            
            if (maybe.length!=1) {
                Util.error('ge() failed in a bizarre complicated edge case. Check comments.');
                return null;
            }
            return maybe[0];
        }
    } else {
        return id;
    }
    return null;
}

function bind ( obj,method )
{
    var args=[];
    for (var ii=2;ii<arguments.length;ii++) {
        args.push(arguments[ii]);
    }
    return function() {
        var _obj=obj||this;
        var _args=args.slice();
        for (var jj=0;jj<arguments.length;jj++){
            _args.push(arguments[jj]);
        }
        
        if (typeof(method)=="string") {
            if (_obj[method]) { 
                return _obj[method].apply(_obj,_args);
            }
        } else {
            return method.apply(_obj,_args);
        }
    }
}

Function.prototype.bind = function (context) {
    var argv=[arguments[0],this]
    var argc=arguments.length;
    for (var ii=1;ii<argc;ii++) {
        argv.push(arguments[ii]);
    }
    return bind.apply(null,argv);
}

