网页导航

问题描述

在为每个单独的列表项实现下拉菜单时,我陷入了困境,将焦点悬停在任何一个列表项上,现在将鼠标悬停在任何单个列表项上时,所有下拉菜单都将显示

这是我的笔:https://codepen.io/apeandme/pen/GRZOxJQ

和JS:

// main navigation interaction

'use strict';

var navbar;
var triggerContainer;
var triggerLink;
var toggleButton;
var lastMenuItem;

var mouSEOutTimer; // timer used to delay hiding of menu after mouse leaves
var mouSEOutHideDelay = 0; // time (in ms) before menu is closed after mouse leaves
var menuVisible = false;

var i = 0;

window.addEventListener('DOMContentLoaded',function(e) {
  navbar = document.querySelector('nav');
  triggerContainer = document.querySelectorAll('nav > ul > li.with-dd');
  triggerLink = document.querySelectorAll('nav > ul > li.with-dd > a');
  toggleButton = document.querySelectorAll('nav > ul > li.with-dd > .toggle-button');
  lastMenuItem = document.querySelectorAll('nav > ul > li.with-dd > ul > li:last-of-type > a');

  // Show the menu on mouse hover of the trigger
  triggerContainer.forEach(item => {
    item.addEventListener('mouSEOver',function(e) {
      showMenu();
      clearTimeout(mouSEOutTimer);
    });
  });



  // Hide the menu when mouse hover leaves both the trigger and menu fly-out,but only after a short delay to help people jerky mouse movements (like those using head/eye trackers)
  triggerContainer.forEach(item => {
    item.addEventListener('mouSEOut',function(e) {
      mouSEOutTimer = setTimeout(function() {
        hideMenu();
      },mouSEOutHideDelay);
    });
  });

  // Hide the menu when the user tabs out of it
  triggerContainer.forEach(item => {
    item.addEventListener('keydown',triggerKeydownHandler);
  });

  // Toggle the menu when the trigger is activated
  toggleButton.forEach(item => {
    item.addEventListener('click',toggleMenu);
  });

  // Close the menu when the user activates something outside the navbar.
  document.body.addEventListener('click',handleBodyClick);
});


/**
  Menu visibility
**/
function showMenu() {
  triggerLink.forEach(item => {
    item.setAttribute('aria-expanded',true);
  });

  toggleButton.forEach(item => {
    item.setAttribute('aria-expanded',true);
  });
  menuVisible = true;
}

function hideMenu() {
  triggerLink.forEach(item => {
    item.setAttribute('aria-expanded',false);
  });
  toggleButton.forEach(item => {
    item.setAttribute('aria-expanded',false);
  });
  menuVisible = false;
}

function toggleMenu() {
  if (menuVisible) {
    hideMenu();
  } else {
    showMenu();
  }
}


/**
  Event handlers
*/
function handleBodyClick(e) {
  if (!navbar.contains(e.target)) {
    hideMenu();
  }
}

function triggerKeydownHandler(e) {
  // Hide the menu a keyboard user tabs out of it or presses Escape
  if ((e.key === 'Tab' && !e.shiftKey && e.target === lastMenuItem) || e.key == 'Escape') {
    hideMenu();

    // Move focus back to the menu toggle button if Escape was pressed
    if (e.key == 'Escape') {
      toggleButton.focus();
    }
  }
}

解决方法

您需要将'hover'事件传递给函数,而不是立即悬停所有的下拉列表,以便知道哪些触发器已被悬停:

triggerContainer.forEach((item) => {
    item.addEventListener("mouseover",function (event) { // catch the 'hover' event
        showMenu(event); // pass the event to your function
        clearTimeout(mouseOutTimer);
    });
});


function showMenu(event) {
  event.target.setAttribute("aria-expanded",true); // know which element whas hovered
  event.target.nextElementSibling.setAttribute("aria-expanded",true); // open the corresponding dropdown
  menuVisible = true;
}
,

感谢您的帮助。已经更改了showMenu和hideMenu的代码,以及mouseover和mouseout事件的代码,现在将单个下拉菜单悬停在单个菜单项上时会显示下拉菜单,但是只要我够到下拉菜单中的最后一个菜单项,这些下拉菜单就会隐藏起来。我是否缺少任何内容,并且现在将鼠标悬停在下拉菜单中的最后一个菜单项上时,控制台中就会出现此错误-

未捕获的TypeError:无法读取null的属性“ setAttribute” 在hideMenu(main.js:68) 在main.js:38

    //main navigation interaction

"use strict";

var navbar;
var triggerContainer;
var triggerLink;
var toggleButton;
var lastMenuItem;

var mouseOutTimer; // timer used to delay hiding of menu after mouse leaves
var mouseOutHideDelay = 1000; // time (in ms) before menu is closed after mouse leaves
var menuVisible = false;

window.addEventListener("DOMContentLoaded",function (e) {
    navbar = document.querySelector("nav");
    triggerContainer = document.querySelectorAll("nav > ul > li.with-dd");
    triggerLink = document.querySelectorAll("nav > ul > li.with-dd > a");
    toggleButton = document.querySelectorAll(
        "nav > ul > li.with-dd > .toggle-button"
    );
    lastMenuItem = document.querySelectorAll(
        "nav > ul > li.with-dd > ul > li:last-of-type > a"
    );

    // Show the menu on mouse hover of the trigger
    triggerContainer.forEach((item) => {
        item.addEventListener("mouseover",function (e) {
            showMenu(e);
            clearTimeout(mouseOutTimer);
        });
    });

    // Hide the menu when mouse hover leaves both the trigger and menu fly-out,but only after a short delay to help people jerky mouse movements (like those using head/eye trackers)
    triggerContainer.forEach((item) => {
        item.addEventListener("mouseout",function (e) {
            mouseOutTimer = setTimeout(function () {
                hideMenu(e);
            },mouseOutHideDelay);
        });
    });

    // Hide the menu when the user tabs out of it
    triggerContainer.forEach((item) => {
        item.addEventListener("keydown",triggerKeydownHandler);
    });

    // Toggle the menu when the trigger is activated
    toggleButton.forEach((item) => {
        item.addEventListener("click",toggleMenu);
    });

    // Close the menu when the user activates something outside the navbar.
    document.body.addEventListener("click",handleBodyClick);
});

/**
  Menu visibility
**/
function showMenu(e) {  
    e.target.setAttribute("aria-expanded",true);
    e.target.nextElementSibling.setAttribute("aria-expanded",true);    
    menuVisible = true;
}

function hideMenu(e) {    
    e.target.setAttribute("aria-expanded",false);
    e.target.nextElementSibling.setAttribute("aria-expanded",false);    
    menuVisible = false;
}

function toggleMenu() {
    if (menuVisible) {
        hideMenu(e);
    } else {
        showMenu(e);
    }
}

/**
  Event handlers
*/
function handleBodyClick(e) {
    if (!navbar.contains(e.target)) {
        hideMenu();
    }
}

function triggerKeydownHandler(e) {
    // Hide the menu a keyboard user tabs out of it or presses Escape
    if (
        (e.key === "Tab" && !e.shiftKey && e.target === lastMenuItem) ||
        e.key == "Escape"
    ) {
        hideMenu();

        // Move focus back to the menu toggle button if Escape was pressed
        if (e.key == "Escape") {
            toggleButton.focus();
        }
    }
}