【发布时间】:2018-08-25 10:04:12
【问题描述】:
在下面的简单菜单代码中,如果子菜单展开/显示,那么我需要子菜单在几个条件下折叠:
- 点击主菜单或子菜单LI时
- 当视口大于定义的最小宽度时
- 当点击发生在屏幕上的其他任何位置时
只要我不为 mainMenuID 元素声明 addEventListener,第 2 号有效,第 1 号有效。出于某种原因,当我为任何 mainMenuID 元素添加该事件侦听器时,它优先于其他任何内容,因此单击 Portfolio 或其子菜单项以外的主菜单项,展开和折叠菜单,但单击 submenuID 或ulID 什么都不做。一旦我删除了 mainMenuID 的事件监听器,点击 submenuID 或 ulID 展开/折叠子菜单。
第二个问题是,如何在页面的其余部分添加点击事件侦听器,以便在显示子菜单时单击折叠子菜单。
谢谢!
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
</head>
<style media="screen">
body{
background-color: black;
}
nav ul {
position: relative;
text-align: left;
}
nav ul li {
display: block; /* WHAT???? REMOVING THIS ACTUALLY MAKES TEXT-DECORATIONS REAPPEAR.... WHY???*/
}
nav a {
text-decoration: none;
}
/* Hide dropdowns by default */
nav ul ul {
position: relative;
display: none;
left: 0;
}
/* Display Dropdowns on Click */
nav ul li.showSubmenu > ul {
display: block;
position: relative;
width: 30%;
}
.menu a {
text-decoration-style: none;
text-decoration: none;
background-color: black;
color: white;
}
.menu a:hover{
background-color: white;
color: black;
}
</style>
<body>
<nav id="mainMenuID" class="menu">
<ul>
<li class="menuItem"><a href="#">Home</a></li>
<li class="menuItem"><a href="#">About</a></li>
<li id="submenuItem" class="submenu_class"><a href="#"><span id="submenuID">Portfolio ▼</span></a>
<ul id="ulID">
<li><a href="#">Landscape</a></li>
<li><a href="#">Architecture</a></li>
<li><a href="#">Animal</a></li>
<li><a href="#">Other</a></li>
</ul>
</li>
<li class="menuItem"><a href="#">Information</a></li>
<li class="menuItem"><a href="#">Contact</a></li>
</ul>
</nav>
<script>
function openSubmenu() {
if (document.getElementsByClassName('showSubmenu').length == 0){
document.getElementById("submenuItem").classList.toggle("showSubmenu");
document.getElementById("submenuID").textContent = "Portfolio ▲";
} else {
document.getElementById("submenuItem").classList.toggle("showSubmenu");
document.getElementById("submenuID").textContent = "Portfolio ▼";
}
}
function resetSubmenu() {
var submenuElements = document.getElementsByClassName('submenu_class showSubmenu');
for (var i = 0; i < submenuElements.length; i++) {
submenuElements[i].setAttribute('class', 'submenu_class');
document.getElementById("submenuID").textContent = "Portfolio ►";
}
}
function screenWidthFunction(x) {
if (x.matches) {//if it's a narrow screen
document.getElementById("submenuID").textContent = "Portfolio ▼";
document.getElementById("ulID").addEventListener("click", openSubmenu, true);
document.getElementById("submenuID").addEventListener("click", openSubmenu, true);
document.getElementById("mainMenuID").addEventListener("click", openSubmenu, true);
} else {
resetSubmenu();
document.getElementById("submenuID").textContent = "Portfolio ►";
document.getElementById("ulID").removeEventListener("click", openSubmenu);
document.getElementById("submenuID").removeEventListener("click", openSubmenu);
document.getElementById("mainMenuID").removeEventListener("click", openSubmenu);
}
}
var x = window.matchMedia("(max-width: 480px)");
screenWidthFunction(x);
x.addListener(screenWidthFunction);
</script>
嗨 Robidu,我让这个菜单只使用 CSS 工作,但我被引导使用 JS 来实现它的某些功能,这使大多数 CSS 停止工作。 所以以冰川的速度,我一直在努力学习 JS。信不信由你,从视频、W3Schools 等中学习……。在 5 到 6 周的大部分时间里,我一直在编写、重新工作并将这个菜单组合在一起。完全荒谬。 看来您了解并且很容易熟悉 JS。我将花费数周的时间来弄清楚如何实施您的所有建议,并且在此过程中,我很可能会破坏已经有效的方法。有什么方法可以请您通过向我提供他们需要去的地方的代码 sn-ps 或更具体的建议来减轻我的痛苦。 我摘录了您的文本中我有疑问的部分(由于 cmets 的字符限制,我必须将它们拆分为多个 cmets):
- “……你应该使用 CSS 来隐藏子菜单,因为我认为这 是默认的。” 问。是的,这是默认设置。我以为我已经在“导航”中这样做了 ul li.showSubmenu > ul {…}”在我的 CSS 中。
- “……实现一个在 DOMContentReady 上触发的初始化阶段 建立支持基础设施。” 问。这一点,我永远不知道如何弄清楚自己。
- “...需要一个指示菜单是否打开的标志,因此 处理程序可以做出相应的反应……为自己省去问题 用“切换”……手头有菜单的状态……” 问。我认为“showSubmenu”类的“切换”正在充当那种“标志”。我将如何以及在何处使用该变量来代替切换?
- “……放过自己……反复附加和删除事件 听众。”,然后是“如果菜单被隐藏,它不会得到任何 事件。” 问。您是说将侦听器分配给 JS 代码中任何位置的变量吗?我是否还需要在我现在使用侦听器的相同位置以相同的方式引用这些变量?
- “……将一个用于检查鼠标事件的事件侦听器附加到 此处打开子菜单的项目。” 问。你的意思是除了我在 id="submenuID" 上的听众吗?您的建议有何不同?
- “…将调整大小事件处理程序附加到执行此操作的窗口 查看...” 问。我从 W3 的示例中裁剪了屏幕宽度代码。使用 innerWidth/innerHeight 有何不同/在哪里?
- “...将冒泡阶段设置为 true 以拦截事件”。 问。如果您将一种应用于菜单系统中的项目,将另一种应用于页面上的其他元素等,我无法找到关于冒泡作品的任何解释。我了解基础知识,但不明白为什么当使用所有三个侦听器时,它无法在这个简单的菜单上工作。
“单击菜单项时折叠菜单...附加事件 每个单独的菜单项的处理程序(最好的位置是菜单内的链接”。 问。我是否必须为每个 LI 分配一个 ID?
总体问题:我使用了带有 UL 和 LI 的 NAV 元素,因为 我被告知这是屏幕阅读器最容易访问的。有没有 更好的方法来做我想要用这个菜单做的事情还是我排序 在正确的轨道上?
我真诚地为所有后续问题/澄清道歉,但我真诚地在这方面旋转我的轮子,在波涛汹涌的大海中兜圈子,戴着眼罩……。以及您可以加入的任何其他类比。
我非常感谢您提供任何具体的编码来展示您的建议的细节。 (或者甚至指给我一些例子,以便我可以尝试找出它们)。
【问题讨论】:
-
您不必为提出后续问题而道歉,因为这是完全有效的。请给我一些时间,我会回答你的问题。我想我还会设计一些测试用例来让它正常运行。
-
但是,仍然存在一个问题:如果窗口足够宽(在您的示例中 >= 480 像素),是否要在主菜单旁边显示子菜单,或者这应该如何工作?我当前的测试用例已经把它放在主菜单旁边,给定足够的窗口宽度......
-
我已经回答了您的后续问题,并提供了一个测试用例,应该可以按照您的要求工作。
标签: javascript html css addeventlistener event-bubbling