如何使addEventListener'click'在具有相同类的两个菜单项上起作用 [英] How to make addEventListener 'click' work on two menu items with same class

查看:26
本文介绍了如何使addEventListener'click'在具有相同类的两个菜单项上起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

页面: https://ensjotannklinikk.no/forside-wip

这是小提琴

第一个菜单项称为" Behandlinger ".是使用此JS(由 biberman 提供)设置的,以使子菜单正确出现和收回.

  var子菜单= document.querySelector('.behandlinger-meny');var menuTrigger = document.querySelector('.behandlinger-item');//jQuery isChild()的javascript版本函数isChild(item,parentItem){while(item!= undefined&& item!= null&& item.tagName.toUpperCase()!='BODY'){如果(item == parentItem){返回true;}item = item.parentNode;}返回false;}menuTrigger.addEventListener('click',function(){submenu.style.height ='55px';});document.querySelector('body').addEventListener('click',function(e){if(!isChild(e.target,menuTrigger)&&!isChild(e.target,submenu)){submenu.style.height = 0;}});document.addEventListener('keyup',function(e){如果(e.key =='Escape'){submenu.style.height = 0;}}); 

为什么这在移动设备上不起作用?我希望将菜单中的子菜单( .behandlinger-meny )高度设置为 55px 单击项目Behandlinger( .behandlinger-item ).除了不在菜单项上单击移动设备之外,它运行完美.


意识到移动菜单具有自己的< nav> ,这可能会影响事件侦听器.我已经更新了下面的小提琴和简化结构以及核心问题.现在看来真的接近一个简单的解决方案.

简化的结构:

  .behandlinger-meny {高度:0;过渡:所有.3s三次方bezier(0.4,0.0,0.2,1);溢出:隐藏;} 

 < div id ="wrapper">< header>< nav class =主菜单">< ul>< li class ="behandlinger-item">< a href =#behandlinger"> Behandlinger</a>/li>< li< a>项目2</a>/li>< li> a<项目3</a>/li>< li< a>项目4</a>/li></ul></nav>< nav class =移动主菜单">< ul>< li class =移动项behandlinger-item">< a href =#behandlinger"> Behandlinger</a>/li>< li< a>项目2</a>/li>< li> a<项目3</a>/li>< li< a>项目4</a>/li></ul></nav></header>< section><!-分开以跟随页面滚动->< div id ="behandlinger"><!-滚动到项目单击的位置->< nav class ="behandlinger-meny"< script></script><!-问题脚本->< ul>< li> a<子项目1</a>/li>< li> a<子项目2</a>/li>< li> a<子项目3</a>/li></ul></nav></div></section>< main>…</main></div> 

可运行的版本:

  var子菜单= document.querySelector('.behandlinger-meny');var menuTrigger = document.querySelector('.behandlinger-item');//jQuery isChild()的javascript版本函数isChild(item,parentItem){while(item!= undefined&& item!= null&& item.tagName.toUpperCase()!='BODY'){如果(item == parentItem){返回true;}item = item.parentNode;}返回false;}menuTrigger.addEventListener('click',function(){submenu.style.height ='55px';});document.querySelector('body').addEventListener('click',function(e){if(!isChild(e.target,menuTrigger)&&!isChild(e.target,submenu)){submenu.style.height = 0;}});document.addEventListener('keyup',function(e){如果(e.key =='Escape'){submenu.style.height = 0;}});  

  .behandlinger-meny {高度:0;过渡:所有.3s三次方bezier(0.4,0.0,0.2,1);溢出:隐藏;}  

 < div id ="wrapper">< header>< nav class ="main-menu">< ul>< li class ="behandlinger-item">< a href =#behandlinger"> Behandlinger</a</li>< li< a>项目2</a>/li>< li> a<项目3</a>/li>< li< a>项目4</a>/li></ul></nav>< nav class ="mobile-main-menu">< ul>< li class ="mobile-item behandlinger-item">< a href =#behandlinger"> Behandlinger</a</li>< li< a>项目2</a>/li>< li> a<项目3</a>/li>< li< a>项目4</a>/li></ul></nav></header>< section><!-分开以跟随页面滚动->< div id ="behandlinger"><!-滚动到项目单击的位置->< nav class ="behandlinger-meny">< script></script><!-问题脚本->< ul>< li> a<子项目1</a>/li>< li> a<子项目2</a>/li>< li> a<子项目3</a>/li></ul></nav></div></section>< main>…</main></div>  

解决方案

由于您有两个触发器,并且事件监听器仅通过 querySelector 附加到第一个触发器,因此第二个触发器没有监听器.

您可以使用 querySelectorAll 并将事件侦听器以for循环方式附加到每个选定的触发器.因为您要进行过渡,所以必须使用最大高度"而不是高度",因为过渡不适用于高度.

为了在单击其他地方(触发器或子菜单除外)时关闭子菜单,我创建了一个函数 isRelated(),该函数检查单击目标是触发器本身,子菜单还是两者的子级.

具有多个触发器的工作示例(下面的jQuery示例):

  document.addEventListener('DOMContentLoaded',function(){var submenu = document.querySelector('.behandlinger-meny');var menuTrigger = document.querySelectorAll('.behandlinger-item');函数isRelated(item,parentSelector){while(item!= undefined&& item!= null&& item.tagName.toUpperCase()!='BODY'){父母= document.querySelectorAll(parentSelector);对于(i = 0; i< parents.length; i ++){如果(项目==父母[i]){返回true;}}item = item.parentNode;}返回false;}对于(i = 0; i< menuTrigger.length; i ++){menuTrigger [i] .addEventListener('click',function(){submenu.style.maxHeight ='1000px';});}document.querySelector('body').addEventListener('click',function(e){如果(!isRelated(e.target,'.behandlinger-item')&&!isRelated(e.target,'.behandlinger-meny')){submenu.style.maxHeight = 0;}});document.addEventListener('keyup',function(e){如果(e.key =='Escape'){submenu.style.maxHeight = 0;}});});  

 标头{显示:flex;}.behandlinger-meny {最大高度:0;宽度:150像素;背景颜色:#ddd;过渡:所有.3s三次方bezier(0.4,0.0,0.2,1);溢出:隐藏;}  

 < div id ="wrapper">< header>< nav class ="main-menu">< ul>< li class ="behandlinger-item">< a href =#behandlinger"> Behandlinger</a</li>< li< a>项目2</a>/li>< li> a<项目3</a>/li>< li< a>项目4</a>/li></ul></nav>< nav class ="mobile-main-menu">< ul>< li class ="mobile-item behandlinger-item">< a href =#behandlinger"> Behandlinger</a</li>< li< a>项目2</a>/li>< li> a<项目3</a>/li>< li< a>项目4</a>/li></ul></nav></header>< section>< div id ="behandlinger">< nav class ="behandlinger-meny">< ul>< li> a<子项目1</a>/li>< li> a<子项目2</a>/li>< li> a<子项目3</a>/li></ul></nav></div></section>< main>…</main></div>  

jQuery示例:

  $().ready(function(){var submenu = $('.behandlinger-meny');$('.behandlinger-item').on('click',function(){submenu.css('maxHeight','1000px');});$('body').on('click',function(e){console.log(e.target);如果(!$(e.target).parents().is('.behandlinger-item')&&!$(e.target).parents().is('.behandlinger-meny')){submenu.css('maxHeight',0);}});$(document).on('keyup',function(e){如果(e.key =='Escape'){submenu.css('maxHeight',0);}});});  

 标头{显示:flex;}.behandlinger-meny {最大高度:0;宽度:150像素;背景颜色:#ddd;过渡:所有.3s三次方bezier(0.4,0.0,0.2,1);溢出:隐藏;}  

 < script src ="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js></script>< div id ="wrapper">< header>< nav class ="main-menu">< ul>< li class ="behandlinger-item">< a href =#behandlinger"> Behandlinger</a</li>< li< a>项目2</a>/li>< li> a<项目3</a>/li>< li< a>项目4</a>/li></ul></nav>< nav class ="mobile-main-menu">< ul>< li class ="mobile-item behandlinger-item">< a href =#behandlinger"> Behandlinger</a</li>< li< a>项目2</a>/li>< li> a<项目3</a>/li>< li< a>项目4</a>/li></ul></nav></header>< section>< div id ="behandlinger">< nav class ="behandlinger-meny">< ul>< li> a<子项目1</a>/li>< li> a<子项目2</a>/li>< li> a<子项目3</a>/li></ul></nav></div></section>< main>…</main></div>  

Page: https://ensjotannklinikk.no/forside-wip

Here's a fiddle

The first menu item called "Behandlinger" is set up with this JS (courtesy of biberman) to make the submenu emerge and retract properly.

var submenu = document.querySelector('.behandlinger-meny');
var menuTrigger = document.querySelector('.behandlinger-item');

//javascript version of jQuery isChild()
function isChild(item, parentItem) {
    while (item != undefined && item != null && item.tagName.toUpperCase() != 'BODY'){
        if (item == parentItem){
            return true;
        }
        item = item.parentNode;
    }
    return false;
}

menuTrigger.addEventListener('click', function() {
    submenu.style.height = '55px';
});

document.querySelector('body').addEventListener('click', function(e) {
    if ( !isChild(e.target, menuTrigger) && !isChild(e.target, submenu) ) {
        submenu.style.height = 0;
    }
});

document.addEventListener('keyup', function(e) {
    if ( e.key == 'Escape' ) {
        submenu.style.height = 0;
    }
});

Why is this not working on mobile? I wish for the submenu (.behandlinger-meny) height set to 55px when the menu item Behandlinger (.behandlinger-item) is clicked. It works perfectly, except not on the menu item click on mobile.


Realized the mobile menu has a <nav> of its own, which may affect the event listener. I have updated both the fiddle and the simplified structure below as well as the core question. Seems really close to a simple solution now.

Simplified structure:

.behandlinger-meny {
    height: 0;
    transition: all .3s cubic-bezier(0.4, 0.0, 0.2, 1);
    overflow: hidden;
}

<div id="wrapper">
  <header>

    <nav class="main-menu">
      <ul>
        <li class="behandlinger-item"><a href="#behandlinger">Behandlinger</a></li>
        <li><a>Item 2</a></li>
        <li><a>Item 3</a></li>
        <li><a>Item 4</a></li>
      </ul>
    </nav>

    <nav class="mobile-main-menu">
      <ul>
        <li class="mobile-item behandlinger-item"><a href="#behandlinger">Behandlinger</a></li>
        <li><a>Item 2</a></li>
        <li><a>Item 3</a></li>
        <li><a>Item 4</a></li>
      </ul>
    </nav>

  </header>

  <section> <!-- Separated to follow page scroll -->
    <div id="behandlinger"> <!-- Scroll to position on item click -->
      <nav class="behandlinger-meny">
        <script></script> <!-- Script in question  -->
        <ul>
          <li><a>Sub item 1</a></li>
          <li><a>Sub item 2</a></li>
          <li><a>Sub item 3</a></li>
        </ul>
      </nav>
    </div>
  </section>

  <main>
    …
  </main>
</div>

Runnable version:

var submenu = document.querySelector('.behandlinger-meny');
var menuTrigger = document.querySelector('.behandlinger-item');

//javascript version of jQuery isChild()
function isChild(item, parentItem) {
    while (item != undefined && item != null && item.tagName.toUpperCase() != 'BODY'){
        if (item == parentItem){
            return true;
        }
        item = item.parentNode;
    }
    return false;
}

menuTrigger.addEventListener('click', function() {
    submenu.style.height = '55px';
});

document.querySelector('body').addEventListener('click', function(e) {
    if ( !isChild(e.target, menuTrigger) && !isChild(e.target, submenu) ) {
        submenu.style.height = 0;
    }
});

document.addEventListener('keyup', function(e) {
    if ( e.key == 'Escape' ) {
        submenu.style.height = 0;
    }
});

.behandlinger-meny {
    height: 0;
    transition: all .3s cubic-bezier(0.4, 0.0, 0.2, 1);
    overflow: hidden;
}

<div id="wrapper">
  <header>

    <nav class="main-menu">
      <ul>
        <li class="behandlinger-item"><a href="#behandlinger">Behandlinger</a></li>
        <li><a>Item 2</a></li>
        <li><a>Item 3</a></li>
        <li><a>Item 4</a></li>
      </ul>
    </nav>

    <nav class="mobile-main-menu">
      <ul>
        <li class="mobile-item behandlinger-item"><a href="#behandlinger">Behandlinger</a></li>
        <li><a>Item 2</a></li>
        <li><a>Item 3</a></li>
        <li><a>Item 4</a></li>
      </ul>
    </nav>

  </header>

  <section> <!-- Separated to follow page scroll -->
    <div id="behandlinger"> <!-- Scroll to position on item click -->
      <nav class="behandlinger-meny">
        <script></script> <!-- Script in question  -->
        <ul>
          <li><a>Sub item 1</a></li>
          <li><a>Sub item 2</a></li>
          <li><a>Sub item 3</a></li>
        </ul>
      </nav>
    </div>
  </section>

  <main>
    …
  </main>
</div>

解决方案

Since you have two triggers and your event listener is only attached to the first with querySelector the second trigger has no listener.

You can use querySelectorAll and attach the event listener in a for loop to each selected trigger. Because you want a transition you have to use 'max-height' instead of 'height' since transition doesn't work with height.

For closing the submenu when clicking somewhere else (except trigger or submenu) i made a function isRelated() that checks if the click target is the trigger itself, the submenu or a child of both.

Working example with multiple triggers (jQuery example below):

document.addEventListener('DOMContentLoaded', function() {

  var submenu = document.querySelector('.behandlinger-meny');
  var menuTrigger = document.querySelectorAll('.behandlinger-item');

  function isRelated(item, parentSelector) {
    while (item != undefined && item != null && item.tagName.toUpperCase() != 'BODY') {
      parents = document.querySelectorAll(parentSelector);
      for (i = 0; i < parents.length; i++) {
        if (item == parents[i]) {
          return true;
        }
      }
      item = item.parentNode;
    }
    return false;
  }

  for (i = 0; i < menuTrigger.length; i++) {
    menuTrigger[i].addEventListener('click', function() {
      submenu.style.maxHeight = '1000px';
    });
  }

  document.querySelector('body').addEventListener('click', function(e) {
    if (!isRelated(e.target, '.behandlinger-item') && !isRelated(e.target, '.behandlinger-meny')) {
      submenu.style.maxHeight = 0;
    }
  });

  document.addEventListener('keyup', function(e) {
    if (e.key == 'Escape') {
      submenu.style.maxHeight = 0;
    }
  });

});

header {
  display: flex;
}

.behandlinger-meny {
  max-height: 0;
  width: 150px;
  background-color: #ddd;
  transition: all .3s cubic-bezier(0.4, 0.0, 0.2, 1);
  overflow: hidden;
}

<div id="wrapper">

  <header>
    <nav class="main-menu">
      <ul>
        <li class="behandlinger-item"><a href="#behandlinger">Behandlinger</a></li>
        <li><a>Item 2</a></li>
        <li><a>Item 3</a></li>
        <li><a>Item 4</a></li>
      </ul>
    </nav>

    <nav class="mobile-main-menu">
      <ul>
        <li class="mobile-item behandlinger-item"><a href="#behandlinger">Behandlinger</a></li>
        <li><a>Item 2</a></li>
        <li><a>Item 3</a></li>
        <li><a>Item 4</a></li>
      </ul>
    </nav>
  </header>

  <section>
    <div id="behandlinger">
      <nav class="behandlinger-meny">
        <ul>
          <li><a>Sub item 1</a></li>
          <li><a>Sub item 2</a></li>
          <li><a>Sub item 3</a></li>
        </ul>
      </nav>
    </div>
  </section>

  <main>
    …
  </main>

</div>

jQuery example:

$().ready(function() {

  var submenu = $('.behandlinger-meny');
  
  $('.behandlinger-item').on('click', function() {
    submenu.css('maxHeight', '1000px');
  });

  $('body').on('click', function(e) {
  console.log(e.target);
    if (!$(e.target).parents().is('.behandlinger-item') 
    && !$(e.target).parents().is('.behandlinger-meny')) {
      submenu.css('maxHeight', 0);
    }
  });

  $(document).on('keyup', function(e) {
    if (e.key == 'Escape') {
      submenu.css('maxHeight', 0);
    }
  });

});

header {
  display: flex;
}

.behandlinger-meny {
  max-height: 0;
  width: 150px;
  background-color: #ddd;
  transition: all .3s cubic-bezier(0.4, 0.0, 0.2, 1);
  overflow: hidden;
}

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div id="wrapper">

  <header>
    <nav class="main-menu">
      <ul>
        <li class="behandlinger-item"><a href="#behandlinger">Behandlinger</a></li>
        <li><a>Item 2</a></li>
        <li><a>Item 3</a></li>
        <li><a>Item 4</a></li>
      </ul>
    </nav>

    <nav class="mobile-main-menu">
      <ul>
        <li class="mobile-item behandlinger-item"><a href="#behandlinger">Behandlinger</a></li>
        <li><a>Item 2</a></li>
        <li><a>Item 3</a></li>
        <li><a>Item 4</a></li>
      </ul>
    </nav>
  </header>

  <section>
    <div id="behandlinger">
      <nav class="behandlinger-meny">
        <ul>
          <li><a>Sub item 1</a></li>
          <li><a>Sub item 2</a></li>
          <li><a>Sub item 3</a></li>
        </ul>
      </nav>
    </div>
  </section>

  <main>
    …
  </main>

</div>

这篇关于如何使addEventListener'click'在具有相同类的两个菜单项上起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆