【问题标题】:How do I DRY up this script?我如何干掉这个脚本?
【发布时间】:2015-05-14 22:00:36
【问题描述】:

我一直在关注这个导航代码,终于让我的菜单的第一层开始工作了。耶!但我注意到我的代码仅适用于第一层。嗯,有点。当您单击不同的菜单时,打开的菜单应该关闭。它适用于我的顶级导航选项,但不适用于我的子菜单选项。我很想复制/粘贴代码,以便一切都适用于所有级别,但我知道编码中的一个重要规则是不要重复自己(DRY)。那么有人可以看看这个,看看是否有一种方法可以将第一个 If/Else 语句的规则应用于我的所有子菜单? (子菜单、下拉菜单、幻灯片菜单)。

另外,如果我的顶级导航开始换行,当您单击第 2 行的其中一个链接时,子菜单将显示在顶级链接上方,几乎无法关闭。有没有办法解决这个问题?

这是我的jsFiddle

jQuery

$(document).ready(function(){ 

$(".nav-tabs span").click(function(){



            var activeTab = $(".nav-tabs > li span.open");
            var submenu = $(this).siblings("ul");
            var thisParent = $(this).closest("ul");

            if (thisParent.hasClass("nav-tabs")){

                if (!$(this).is(activeTab)){
                    /*
                    alert("this link was not active yet");
                    */
                    activeTab.siblings("ul").slideUp(); 
                    submenu.find("span+ul").hide();
                    activeTab.removeClass("open");
                    $(this).addClass("open");
                    submenu.slideDown();

                } else {
                    /*
                    alert("this link is already active");
                    */
                    submenu.slideUp();
                    submenu.find("span+ul").hide();
                    $(this).removeClass("open");
                }
            } else {
                $(this).toggleClass("open");
                submenu.slideToggle("fast", function(){
                    if (!$(this).is(".open")){
                        submenu.find("span+ul").removeClass("open").hide();
                    }
                });

            }


        });

        });

HTML

<div id="navbar">
    <ul class="nav-tabs">
        <li><span>Home</span></li>
        <li id="active"><span>Dogs <div class="arrow-down"></div></span>
            <ul class="sub-menu">
                <li><span>Meet the Breeds<div class="arrow-down"></div></span>
                    <ul class="drop-menu">
                        <li><span>Sort A - Z ~ </span>
                            <ul class="slide-menu">
                                <li>Breeds A - F</li>
                                <li>Breeds G - L</li>
                                <li>Breeds M - R</li>
                                <li>Breeds S - Z</li>
                            </ul>
                        </li>
                        <li><span>Sort by AKC Group ~</span>
                            <ul class="slide-menu">
                                <li>Sporting Group</li>
                                <li>Working Group</li>
                                <li>Herding Group</li>
                                <li>Hound Group</li>
                                <li>Terrier Group</li>
                                <li>Non-Sporting Group</li>
                                <li>Toy Group</li>
                            </ul>
                        </li>
                        <li><span>Sort by Size ~</span>
                            <ul class="slide-menu">
                                <li>X-Small (&le 10in)</li>
                                <li>Small (10in &gt &lt 15in)</li>
                                <li>Medium (15in &ge &lt 21in)</li>
                                <li>Large (21in &ge &lt 28in)</li>
                                <li>X-Large (28in +)</li>
                            </ul>
                        </li>
                        <li><span>Sort by Coat ~</span>
                            <ul class="slide-menu">
                                <li>Very Short/Hairless</li>
                                <li>Short Coat</li>
                                <li>Medium Coats</li>
                                <li>Long Coats</li>
                                <li>Non-Shedding Coats</li>
                                <li>Curly Coats</li>
                            </ul>
                        </li>
                        <li><span>Sort by Trait ~</span>
                            <ul class="slide-menu">
                                <li>Apartment Suitable</li>
                                <li>Laid Back</li>
                                <li>Athletic</li>
                                <li>Protective</li>
                                <li>Extroverted</li>
                                <li>Pet Friendly</li>
                                <li>Cuddle-Buddies</li>
                            </ul>
                        </li>
                    </ul>
                </li>
                <li><span>Supplies<div class="arrow-down"></div></span>
                    <ul class="drop-menu">
                        <li><span>Crates & Kennels</li>
                        <li><span>Bowls & Dishes</li>
                        <li><span>Collars & Leashes</li>
                        <li><span>Toys & Games</li>
                        <li><span>Grooming</li>
                        <li><span>Apparal & Accessories</li>
                    </ul>
                </li>
                <li><span>Finding a Dog<div class="arrow-down"></div></span></li>
            </ul>

        </li>
        <li><span>Cats<div class="arrow-down"></div></span>
            <ul class="sub-menu">
                <li><span>Cat Links<div class="arrow-down"></div></span></li>
                <li><span>Cat Links<div class="arrow-down"></div></span></li>
                <li><span>Cat Links<div class="arrow-down"></div></span></li>
                <li><span>Cat Links<div class="arrow-down"></div></span></li>
                <li><span>Cat Links<div class="arrow-down"></div></span></li>
                <li><span>Cat Links<div class="arrow-down"></div></span></li>
            </ul>
        </li>
        <li><span>Birds<div class="arrow-down"></div></span>
            <ul class="sub-menu">
                <li><span>Bird Links<div class="arrow-down"></div></span></li>
                <li><span>Bird Links<div class="arrow-down"></div></span></li>
                <li><span>Bird Links<div class="arrow-down"></div></span></li>
                <li><span>Bird Links<div class="arrow-down"></div></span></li>
                <li><span>Bird Links<div class="arrow-down"></div></span></li>
                <li><span>Bird Links<div class="arrow-down"></div></span></li>
            </ul>
        </li>
        <li><span>Small Mammals<div class="arrow-down"></div></span>
            <ul class="sub-menu">
                <li><span>Sm.Mammal Links<div class="arrow-down"></div></span></li>
                <li><span>Sm.Mammal Links<div class="arrow-down"></div></span></li>
                <li><span>Sm.Mammal Links<div class="arrow-down"></div></span></li>
                <li><span>Sm.Mammal Links<div class="arrow-down"></div></span></li>
                <li><span>Sm.Mammal Links<div class="arrow-down"></div></span></li>
                <li><span>Sm.Mammal Links<div class="arrow-down"></div></span></li>
            </ul>
        </li>
        <li><span>Articles<div class="arrow-down"></div></span>
            <ul class="sub-menu">
                <li><span>Article Links<div class="arrow-down"></div></span></li>
                <li><span>Article Links<div class="arrow-down"></div></span></li>
                <li><span>Article Links<div class="arrow-down"></div></span></li>
                <li><span>Article Links<div class="arrow-down"></div></span></li>
                <li><span>Article Links<div class="arrow-down"></div></span></li>
                <li><span>Article Links<div class="arrow-down"></div></span></li>
            </ul>
        </li>
        <li><span>Videos<div class="arrow-down"></div></span>
            <ul class="sub-menu">
                <li><span>Video Links<div class="arrow-down"></div></span></li>
                <li><span>Video Links<div class="arrow-down"></div></span></li>
                <li><span>Video Links<div class="arrow-down"></div></span></li>
                <li><span>Video Links<div class="arrow-down"></div></span></li>
                <li><span>Video Links<div class="arrow-down"></div></span></li>
                <li><span>Video Links<div class="arrow-down"></div></span></li>
            </ul>
        </li>
        <li><span>Updates<div class="arrow-down"></div></span>
            <ul class="sub-menu">
                <li><span>More Links<div class="arrow-down"></div></span></li>
                <li><span>More Links<div class="arrow-down"></div></span></li>
                <li><span>More Links<div class="arrow-down"></div></span></li>
                <li><span>More Links<div class="arrow-down"></div></span></li>
                <li><span>More Links<div class="arrow-down"></div></span></li>
                <li><span>More Links<div class="arrow-down"></div></span></li>
            </ul>
        </li>
    </ul>
</div>

CSS 包含在 jsFiddle 中

【问题讨论】:

  • 问题的第二部分(在菜单换行到下一行时使其工作)是一个简单的 css 更改 - 在 .sub-menu 规则中更改 'top: 41px;'到'顶部:100%;'这将使子菜单始终显示在顶级菜单下方,无论顶级菜单的高度如何
  • @Philippe - 谢谢,这有助于提高可用性(甚至是一个词吗?),但现在子菜单已从大多数顶级链接中删除。如果您缩小屏幕使其环绕两次,则狗的子菜单会在第 3 行下方打开。我正在尝试做的是直接在其父链接下方打开子菜单,无论它在哪里。如果它以任何其他方式发生,它要么看起来很奇怪,要么不能很好地工作。还有其他建议吗?
  • 发布带有所需输出图片的编辑。

标签: jquery css navigation dry


【解决方案1】:

哈!我能够自己想出一个答案!

我在这里定义了变量:

var activeTab = $(".nav-tabs > li span.open");
var submenu = $(this).siblings("ul");
var thisParent = $(this).closest("ul");

我所要做的就是将 activeTab 变量更改为:

var thisParent = $(this).closest("ul");
var activeTab = thisParent.children().children("span.open");
var submenu = $(this).siblings("ul");

完美运行!现在这段代码对所有菜单都适用,我不必重复自己!

【讨论】:

    【解决方案2】:

    您在寻找$(this).offset(); 它会告诉您元素相对于文档的位置,因此您需要减去导航栏的位置才能获得元素的 TOP 位置。由于您想在点击的元素下方显示菜单,您还必须将点击的元素的高度添加到 TOP 位置以将其推到下方。请参阅此 sn-p 以了解工作和注释代码

    编辑:这是作为答案发布的部分问题(由 OP 在 cmets 中提出)的答案,因此我可以添加可运行的 sn-p。还折叠了代码 sn-p 所以它不会占用太多空间。

    $(document).ready(function() {
    
      $(".nav-tabs span").click(function() {
        var activeTab = $(".nav-tabs > li span.open");
        var submenu = $(this).siblings("ul");
        var thisParent = $(this).closest("ul");
        /*calculate the offset*/
        var offset = $(this).offset(); //gets the offset relative to document
        var parentOffset = $('#navbar').offset(); //get the navbar offset relative to doc
        var heightOfClickedElement = $(this).outerHeight();
        var relativeOffsetTop = offset.top - parentOffset.top + heightOfClickedElement;
        $('.sub-menu').css('top', relativeOffsetTop + 'px');
        /*done calculating the offset */
        if (thisParent.hasClass("nav-tabs")) {
    
          if (!$(this).is(activeTab)) {
            /*
    					alert("this link was not active yet");
    					*/
            activeTab.siblings("ul").slideUp();
            submenu.find("span+ul").hide();
            activeTab.removeClass("open");
            $(this).addClass("open");
            submenu.slideDown();
    
          } else {
            /*
    					alert("this link is already active");
    					*/
            submenu.slideUp();
            submenu.find("span+ul").hide();
            $(this).removeClass("open");
          }
        } else {
          $(this).toggleClass("open");
          submenu.slideToggle("fast", function() {
            if (!$(this).is(".open")) {
              submenu.find("span+ul").removeClass("open").hide();
            }
          });
    
        }
    
    
      });
    
    });
    #navbar {
      display: block;
      clear: both;
      width: 100%;
      height: auto;
      margin: 0px;
      padding: 0%;
      background-color: #29568F;
      border-bottom: 3px solid #29568F;
    }
    .nav-tabs {
      display: inline-block;
      position: relative;
      width: 100%;
      background: #29568F;
      margin: 0px 0px;
      padding: 0px;
      list-style-type: none;
      color: white;
      text-decoration: none;
      text-shadow: 2px 2px #000000;
      font: 18px arial, verdana, sans-serif;
    }
    .nav-tabs li {
      cursor: pointer;
      float: left;
      padding: 10px 20px;
      text-align: center;
      border-right: 1px solid lightgrey;
    }
    .nav-tabs li:last-child {
      border: 0px;
    }
    .nav-tabs li:hover {
      background-color: #3399CC;
    }
    #active {
      background-color: #3399CC;
    }
    .nav-tabs li a {
      color: white;
      text-decoration: none;
      text-shadow: 2px 2px #000000;
      font: 18px arial, verdana, sans-serif;
    }
    /*
    	.arrow-down {
    		display: inline-block;
    		float: right;
    		margin: 8px 0px 0px 8px;
    		content: url("/images/arrow-down.png");
    	}*/
    
    <----------Horizontal Sub-Menu-----------------------> .nav-tabs li .sub-menu {
      display: none;
    }
    /*
    	.nav-tabs li:hover .sub-menu {
    		display: block;
    	}*/
    
    .sub-menu {
      display: none;
      z-index: 200;
      width: 100%;
      background-color: #3399CC;
      position: absolute;
      top: 41px;
      left: 0px;
      padding: 0px;
      border-bottom: 3px solid #29568F;
    }
    .sub-menu li {
      list-style-type: none;
      position: relative;
      border: 0px;
      left: 5%;
    }
    .sub-menu li:hover {
      background-color: #C9EAF3;
    }
    .sub-menu li:hover a {
      color: #000000;
      text-shadow: 2px 2px #ffffff;
    }
    <---------------Drop Down Sub-Menu----------------------> .sub-menu li .drop-menu {
      display: none;
    }
    /*
    	.sub-menu li:hover .drop-menu {
    		display: block;
    	}*/
    
    .drop-menu {
      display: none;
      position: absolute;
      top: 100000px;
      left: -3px;
      margin: 0px;
      padding: 0px;
      background-color: #C9EAF3;
      /*
    		width: 120%;*/
      min-width: 220px;
      z-index: 200;
    }
    .drop-menu li {
      border-bottom: 1px solid #ffffff;
      border-right: 3px solid #29568F;
      border-left: 3px solid #29568F;
      list-style-type: none;
      position: relative;
      left: 0px;
      margin: 0px;
      padding: 10px 1%;
      width: 95%;
      text-indent: 10px;
      text-align: left;
      text-shadow: none !important;
      color: black;
      font-size: 15px;
    }
    .drop-menu li a {
      text-shadow: none !important;
      color: black;
      font-size: 15px;
    }
    .drop-menu li:last-child {
      border-bottom: 3px solid #29568F;
      border-right: 3px solid #29568F;
      border-left: 3px solid #29568F;
    }
    .drop-menu li:hover {
      background-color: #ffffff;
    }
    <-----------------Slide Out Sub-Menu------------------------> .drop-menu li .slide-menu {
      display: none;
    }
    /*
    	.drop-menu li:hover .slide-menu {
    		display: block;
    	}*/
    
    .slide-menu {
      display: none;
      position: absolute;
      top: 0px;
      left: 213px;
      margin: 0px;
      padding: 0px;
      width: 120%;
      background-color: white;
      border-top: 3px solid #29568F;
    }
    .slide-menu:first-child {
      border-top: 0px;
    }
    .slide-menu li {
      border-right: 3px solid #29568F;
      border-left: 3px solid #29568F;
      list-style-type: none;
      margin: 0px;
      padding: 10px 1%;
      width: 96%;
      text-indent: 10px;
    }
    .slide-menu li:first-child {
      border-left: 0px;
      position: relative;
      left: 3px;
    }
    .slide-menu li:hover a {
      text-decoration: underline;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <div id="navbar">
      <ul class="nav-tabs">
        <li><span>Home</span>
        </li>
        <li id="active"><span>Dogs <div class="arrow-down"></div></span>
    
          <ul class="sub-menu">
            <li><span>Meet the Breeds<div class="arrow-down"></div></span>
    
              <ul class="drop-menu">
                <li><span>Sort A - Z ~ </span>
    
                  <ul class="slide-menu">
                    <li>Breeds A - F</li>
                    <li>Breeds G - L</li>
                    <li>Breeds M - R</li>
                    <li>Breeds S - Z</li>
                  </ul>
                </li>
                <li><span>Sort by AKC Group ~</span>
    
                  <ul class="slide-menu">
                    <li>Sporting Group</li>
                    <li>Working Group</li>
                    <li>Herding Group</li>
                    <li>Hound Group</li>
                    <li>Terrier Group</li>
                    <li>Non-Sporting Group</li>
                    <li>Toy Group</li>
                  </ul>
                </li>
                <li><span>Sort by Size ~</span>
    
                  <ul class="slide-menu">
                    <li>X-Small (&le 10in)</li>
                    <li>Small (10in &gt &lt 15in)</li>
                    <li>Medium (15in &ge &lt 21in)</li>
                    <li>Large (21in &ge &lt 28in)</li>
                    <li>X-Large (28in +)</li>
                  </ul>
                </li>
                <li><span>Sort by Coat ~</span>
    
                  <ul class="slide-menu">
                    <li>Very Short/Hairless</li>
                    <li>Short Coat</li>
                    <li>Medium Coats</li>
                    <li>Long Coats</li>
                    <li>Non-Shedding Coats</li>
                    <li>Curly Coats</li>
                  </ul>
                </li>
                <li><span>Sort by Trait ~</span>
    
                  <ul class="slide-menu">
                    <li>Apartment Suitable</li>
                    <li>Laid Back</li>
                    <li>Athletic</li>
                    <li>Protective</li>
                    <li>Extroverted</li>
                    <li>Pet Friendly</li>
                    <li>Cuddle-Buddies</li>
                  </ul>
                </li>
              </ul>
            </li>
            <li><span>Supplies<div class="arrow-down"></div></span>
    
              <ul class="drop-menu">
                <li><span>Crates & Kennels</li>
                            <li><span>Bowls & Dishes</li>
                            <li><span>Collars & Leashes</li>
                            <li><span>Toys & Games</li>
                            <li><span>Grooming</li>
                            <li><span>Apparal & Accessories</li>
                        </ul>
                    </li>
                    <li><span>Finding a Dog<div class="arrow-down"></div></span>
                </li>
              </ul>
            </li>
            <li><span>Cats<div class="arrow-down"></div></span>
    
              <ul class="sub-menu">
                <li><span>Cat Links<div class="arrow-down"></div></span>
                </li>
                <li><span>Cat Links<div class="arrow-down"></div></span>
                </li>
                <li><span>Cat Links<div class="arrow-down"></div></span>
                </li>
                <li><span>Cat Links<div class="arrow-down"></div></span>
                </li>
                <li><span>Cat Links<div class="arrow-down"></div></span>
                </li>
                <li><span>Cat Links<div class="arrow-down"></div></span>
                </li>
              </ul>
            </li>
            <li><span>Birds<div class="arrow-down"></div></span>
    
              <ul class="sub-menu">
                <li><span>Bird Links<div class="arrow-down"></div></span>
                </li>
                <li><span>Bird Links<div class="arrow-down"></div></span>
                </li>
                <li><span>Bird Links<div class="arrow-down"></div></span>
                </li>
                <li><span>Bird Links<div class="arrow-down"></div></span>
                </li>
                <li><span>Bird Links<div class="arrow-down"></div></span>
                </li>
                <li><span>Bird Links<div class="arrow-down"></div></span>
                </li>
              </ul>
            </li>
            <li><span>Small Mammals<div class="arrow-down"></div></span>
    
              <ul class="sub-menu">
                <li><span>Sm.Mammal Links<div class="arrow-down"></div></span>
                </li>
                <li><span>Sm.Mammal Links<div class="arrow-down"></div></span>
                </li>
                <li><span>Sm.Mammal Links<div class="arrow-down"></div></span>
                </li>
                <li><span>Sm.Mammal Links<div class="arrow-down"></div></span>
                </li>
                <li><span>Sm.Mammal Links<div class="arrow-down"></div></span>
                </li>
                <li>
                  <="#" <span>More Links
                    <div class="arrow-down"></div>
                    </span>
                </li>
              </ul>
            </li>
            <li><span>Articles<div class="arrow-down"></div></span>
    
              <ul class="sub-menu">
                <li><span>Article Links<div class="arrow-down"></div></span>
                </li>
                <li><span>Article Links<div class="arrow-down"></div></span>
                </li>
                <li><span>Article Links<div class="arrow-down"></div></span>
                </li>
                <li><span>Article Links<div class="arrow-down"></div></span>
                </li>
                <li><span>Article Links<div class="arrow-down"></div></span>
                </li>
                <li><span>Article Links<div class="arrow-down"></div></span>
                </li>
              </ul>
            </li>
            <li><span>Videos<div class="arrow-down"></div></span>
    
              <ul class="sub-menu">
                <li><span>Video Links<div class="arrow-down"></div></span>
                </li>
                <li><span>Video Links<div class="arrow-down"></div></span>
                </li>
                <li><span>Video Links<div class="arrow-down"></div></span>
                </li>
                <li><span>Video Links<div class="arrow-down"></div></span>
                </li>
                <li><span>Video Links<div class="arrow-down"></div></span>
                </li>
                <li><span>Video Links<div class="arrow-down"></div></span>
                </li>
              </ul>
            </li>
            <li><span>Updates<div class="arrow-down"></div></span>
    
              <ul class="sub-menu">
                <li><span>More Links<div class="arrow-down"></div></span>
                </li>
                <li><span>More Links<div class="arrow-down"></div></span>
                </li>
                <li><span>More Links<div class="arrow-down"></div></span>
                </li>
                <li><span>More Links<div class="arrow-down"></div></span>
                </li>
                <li><span>More Links<div class="arrow-down"></div></span>
                </li>
                <li><span>More Links<div class="arrow-down"></div></span>
                </li>
              </ul>
            </li>
          </ul>
    </div>

    【讨论】:

    • 哎呀!这不是很好。我运行代码,然后每次单击子菜单项时,它都会在页面下方移动。但我会看看这个 offset() 的东西。
    • 似乎对我有用 - 我使用的是 chrome,你使用的是什么浏览器?
    • 哦,我明白你在说什么,我只在回答中提到了第一级菜单 - 我没有提到“更多项目”链接。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多