【问题标题】:Multiple dropdowns: what is the proper way to handle them?多个下拉列表:处理它们的正确方法是什么?
【发布时间】:2012-12-06 04:35:26
【问题描述】:

我必须构建一个由点击触发的小下拉系统。我已经设法处理“点击退出 div”问题(感谢 this 之前发布的问题)。

我可以隐藏 current 下拉菜单,点击另一个下拉菜单的触发器或点击 dropdown 本身的外部。那么问题来了:

  1. 点击当前下拉菜单的触发器没用;当其他事情正常工作时,下拉菜单不会消失
  2. 点击内部当前下拉菜单(例如:.divider 项目),导致下拉菜单消失

所以,这里是 html 代码(假设我在标题中有多个下拉菜单)

    ...
    <div id="header" class="navbar">
        <div class="line">
            <a href="#" class="logo">Site Name</a>
            <ul class="nav right">
                <li>
                    <a href="#" class="has-drop">Item 1</span>
                    <ul class="dropdown-menu">
                        <li><a href="#">Action A</a></li>
                        <li><a href="#">Action B</a></li>
                        <li><a href="#">Action C</a></li>
                        <li class="divider"></li>
                        <li><span>Inline note</span></li>
                    </ul>
                </li>
                <li>
                    <a class="has-drop" href="#">Item 2</a>
                    <ul class="dropdown-menu">
                        <li><a href="#">Action D</a></li>
                        <li><a href="#">Action E</a></li>
                        <li><a href="#">Action F</a></li>
                        <li class="divider"></li>
                        <li><a href="#">Action G</a></li>
                    </ul>
                </li>
            </ul>
        </div>
    </div> <!-- end #header -->
    ...

这实际上是我正在使用的 JS 代码,在一个专用文件中

    $(document).ready(function(){

        $("html").on({
            click: function(e) {
                $(".dropdown-menu.opened").toggleClass("opened");
            }
        });

        $(".nav > li > a").on({
            click: function(e){
                e.stopPropagation();

                $(".dropdown-menu.opened").toggleClass("opened"); // should close each .dropdowns before opening the current one
                $(e.target).siblings(".dropdown-menu").toggleClass("opened");
            }
        });

    });

为什么当我重新点击它的触发器时下拉菜单没有隐藏?因为在$(".nav &gt; li &gt; a").on() 内部实际上做同样的事情?

另外,有一种方法可以防止下拉菜单在单击其中的一些子项时隐藏自身?但也许这与另一个问题更相关,我不知道。

最后但并非最不重要的一点:您认为这是完成整个事情的正确方法吗?

提前谢谢大家


编辑:感谢@Beetroot-Beetroot 我设法解决了这个问题,所以这是当前的工作代码 $(document).ready(function(){

        $("html").on("click", function(e) {
            $(".dropdown-menu.opened").removeClass("opened");
        });

        $(".nav").find("li :first-child").on("click", function(e) {
            e.preventDefault();
            e.stopPropagation();

            var $thisMenu = $(this).siblings(".dropdown-menu").toggleClass("opened");
            $(".dropdown-menu").not($thisMenu).removeClass("opened");
        });

    });

“秘密”是 .not() 的巧妙使用,我现在对此更加了解。

我刚刚将目标(可以&lt;a&gt;&lt;span&gt;)更改为更通用的目标。不确定长期的表现,但肯定是一个很好的起点。

来自

$(".nav").find("a.has-drop").on(...

$(".nav").find("li :first-child").on(...

还有,这里

$(this).closest(".nav").find(".dropdown-menu").not(... 我让它像这样更通用 $(".dropdown-menu").not(... 那是因为我想隐藏 所有 打开的下拉菜单。以前的行为是只考虑一种目标和一个原点区域(例如:也许我需要这些下拉菜单以及标题和某种工具栏内的内容)。


编辑 2:@Beetroot-Beetroot 再次帮助了我。正如他所建议的那样,当我在 jsFiddle 中移植当前代码时,突然解决方案本身就出现了。所以现在$("html").on("click", ... 部分看起来像这样

    $("html").on("click", function(e) {

        if ( $(e.target).hasClass("dropdown-menu") || $(e.target).parents(".dropdown-menu").length ) {
            // do nothing, basically
        } else {
            $(".dropdown-menu.opened").removeClass("opened");
        }
    });

基本上,我只是观察来自$("html") 的点击是否与下拉菜单的宽度有关。如果是,什么也不做。如果不是,那么这确实意味着我点击了任何而不是下拉菜单所在的位置。

【问题讨论】:

    标签: jquery css user-interface drop-down-menu frameworks


    【解决方案1】:

    它认为这样的事情应该可以完成这项工作:

    $(document).ready(function() {
        $("html").on('click', function(e) {
            $(".dropdown-menu.opened").removeClass("opened");
        });
        $(".nav").find("a.has-drop").on('click', function(e) {
            e.preventDefault();
            e.stopPropagation();
            var $thisMenu = $(this).siblings(".dropdown-menu").toggleClass("opened");
            $(this).closest(".nav").find(".dropdown-menu").not($thisMenu).removeClass("opened");
        });
    });
    

    未经测试

    注意事项:

    • removeClass() 在几个地方替换了 toggleClass()
    • 秘诀是先切换$thisMenu,然后在下一行中使用not($thisMenu),以确保$thisMenu 保持在切换到的任何状态。

    【讨论】:

    • 非常感谢@Beetroot-Beetroot。最后,关键是巧妙地使用 .not() 以避免指令重叠并且实际上是相同的。不知道 .not() 会如此强大。真丢人,呵呵。
    • 很抱歉打扰您,但我仍然面临这个问题:在下拉列表中单击 .divider 元素之类的内容会导致下拉列表本身隐藏起来。我以为 e.stopPropagation();可以阻止这种问题。我错了吗?
    • L.v.N. - 你能设置一个我可以玩的工作演示吗?这里的大多数人使用jsFiddle
    • 当然!给我几分钟时间
    • 好的!请参阅“EDIT 2”,那里有我自己最新问题的答案。再次感谢您!
    猜你喜欢
    • 2023-03-25
    • 2020-03-14
    • 2021-09-18
    • 1970-01-01
    • 2011-05-25
    • 1970-01-01
    • 1970-01-01
    • 2016-03-11
    • 1970-01-01
    相关资源
    最近更新 更多