How to allow for a default submenu on a jQuery hov

2019-02-20 02:04发布

This started from a related question. After getting a brilliant answer I ran into an unforeseen gap in functionality: how can I show a menu open by default?

More specifically if a user lands on a page that exists in my sub-nav I want to have that sub-nav open with the current page highlighted. If they use the menu to browse around it will change accordingly, but always go back to the default state if they don't make a selection.

The code I'm basing this off can be found in this jsfiddle.

The menu structure is like:

<div id="mnav">
    <ul id="buttons">
        <li class="one"><a href="#">Main 1</a></li>
        <li class="two"><a href="#">Main 2</a></li>
        <li class="three"><a href="#">Main 3</a></li>
        <li class="four nav-dark"><a href="#">Main 4</a></li>
    </ul>
</div><!-- /mnav -->
<div id="snav">
    <ul class="snav-one">
        <li><a href="#">Sub 1.1</a></li>
        <li><a href="#">Sub 1.2</a></li>
        <li><a href="#">Sub 1.3</a></li>
    </ul>
    <ul class="snav-two">
        <li><a href="#">Sub 2.1</a></li>
        <li><a href="#">Sub 2.2</a></li>
    </ul>
</div><!-- /snav -->


It was suggested that the basic idea is on hover-out to set things back to the way they were and that makes perfect sense, but how do you save the initial state the menu is in?

1条回答
Melony?
2楼-- · 2019-02-20 02:59

Based on that jsFiddle code, one approach would be:

  1. The server sets a global variable in the page GBL_bNoDefaultMenu to true or false depending on whether that page has a default sub-menu. (JS could set the variable in ajaxified pages.)

  2. The server also marks the default sub-menu with the class defaultMenu.
    EG: <ul class="snav-two defaultMenu">

  3. Be sure the page has a style like:

    #snav ul.defaultMenu {
        display: block;  /* Or the correct visible display mode.*/
    }
    
  4. Then code like the following should work.
    Notice that all of the main-nav buttons need a hover now. Also, Everything's been consolidated into one hover() call. And depending on the production page, further simplification may be possible.

See the demo at jsFiddle.

$("#buttons li, #snav ul").hover (function (zEvent) {MenuOpenCloseErgoTimer (zEvent); } );

function MenuOpenCloseErgoTimer (zEvent)
{
    var dDelay;
    var ActionFunction = null;

    if (zEvent.type == 'mouseenter')
    {
        if (zEvent.currentTarget.nodeName  == 'LI')        //-- Main nav.
        {
            dDelay          = 300;
            ActionFunction  = function (node) {
                //--- The first class is a special tie to a submenu, if it exists
                var subnav = 'ul.snav-' + $(node).attr ('class').split (' ')[0];
                $("#snav ul").hide ();
                $("#snav").find (subnav).show ();

                //--- Not sure what's going on with the "open" class.  It's irrelevant to this demo.
                if (GBL_bNoDefaultMenu)
                    $("#snav").stop (true, true).slideDown ('fast').addClass ("open");
            };
        }
        else //-- zEvent.currentTarget.nodeName  == 'UL'   //-- Sub nav.
        {
            dDelay          = 0;
            ActionFunction  = function (node) {
                $(node).show ();

                if (GBL_bNoDefaultMenu)
                    $("#snav").stop (true, true).slideDown ('fast').addClass ("open");
            };
        }
    }
    else //-- zEvent.type == 'mouseleave'
    {
        //--- Actions for main nav and sub nav are the same.
        dDelay          = 200;
        ActionFunction  = function (node) {
            if (GBL_bNoDefaultMenu)
                $("#snav").stop (true, true).slideUp ('fast').removeClass ("open");
            $("#snav ul").hide ();
            $("#snav ul.defaultMenu").show ();
        }
    }

    if (typeof this.delayTimer == "number")
    {
        clearTimeout (this.delayTimer);
    }
    this.delayTimer     = setTimeout (function() { ActionFunction (zEvent.currentTarget); }, dDelay);
}
查看更多
登录 后发表回答