无法将焦点事件添加到具有 javascript 的元素
Trouble adding focus event to element with javascript
我刚刚开始学习 Javascript(刚开始),我在尝试将焦点应用到某个元素时显示隐藏的 "sub navigation" 菜单时遇到问题。我保持它非常基本(我认为)。
这个想法与悬停时显示隐藏的 "sub navigation" 菜单相同。当用户切换到元素并应用焦点时,菜单显示并且菜单中的 links 变得可聚焦。当用户离开菜单时,菜单会再次隐藏。我希望这种情况发生在任意数量的导航元素上。
HTML:
<nav role="navigation">
<ul>
<li><a href="#">Link 1</a></li>
<li><a href="#" class="has-dropdown">Link 2</a>
<ul class="dropdown">
<li><a href="#">Link 2a</a></li>
<li><a href="#">Link 2b longer</a></li>
<li><a href="#">Link 2c longest text</a></li>
</ul>
</li>
<li><a href="#">Link 3</a></li>
<li><a href="#">Link 4</a></li>
</ul>
</nav>
不确定您是否需要它,但这是 CSS:
nav[role=navigation] {
width: 100%;
background: #505050;
font-family: Oswald,sans-serif;
font-weight: 200;
}
nav[role=navigation] ul {
margin: 0;
padding: 0;
list-style: none;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-wrap: wrap;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
-webkit-justify-content: flex-start;
-ms-flex-pack: start;
justify-content: flex-start;
}
nav[role=navigation] ul li {
-webkit-flex: 0 1 auto;
-ms-flex: 0 1 auto;
flex: 0 1 auto;
text-align: center;
padding: .8333rem;
border-right: 1px solid #252525;
position: relative;
}
nav[role=navigation] ul li:last-of-type {
border-right: none;
}
nav[role=navigation] ul li:hover a + ul {
display: block;
}
nav[role=navigation] ul ul {
list-style: none;
position: absolute;
top: 100%;
left: 0;
background: #252525;
padding: 0;
width: 200%;
text-align: left;
display: none;
}
nav[role=navigation] ul ul.active {
display: block;
}
nav[role=navigation] ul a {
padding: 0 1rem;
color: #fff;
text-decoration: none;
}
nav[role=navigation] ul a:focus,
nav[role=navigation] ul a:hover {
text-decoration: underline;
color: #ccc;
}
Javascript:
var topLevel = document.getElementsByClassName("has-dropdown");
for (var i = 0; i < topLevel.length; i++) {
topLevel[i].onfocus = function() {
console.log("you have activated the dropdown");
topLevel.nextElementSibling.className = "active";
}
}
当我切换到触发此操作的 link 时,我在任何具有子菜单但不显示子菜单的 link 上正确地收到日志消息。当我从控制台 运行 时,出现错误:
"Cannot set property "className" of undefined."
我相信这与变量是数组有关,因为如果我设置 topLevel 的索引,例如 topLevel[0],它会完美地工作。
我想使用原生 JS。没有JQuery.
我已经搜索过类似的问题,但找不到任何超出我理解范围的答案或只能给出 JQuery 解决方案。
我看过:
Drop down menu to hide on click event
For-each over an array in JavaScript? --> 这个让我脑袋出血。
Target items in an array on click?
答案可能隐藏在上述帖子之一中,但即使是,我也找不到。
我在项目中遇到了同样的问题https://github.com/arthurdd/scales/blob/master/index.js#L60
基本上我所做的就是定义一个函数add_listeners_all
(如果你只做一次,你可能不需要这样的函数)
这是代码
function add_listeners_all( selector, fun ) {
Array.prototype.slice.apply(document.querySelectorAll(selector)).forEach(el) {
el.addEventListener('click', fun);
});
});
我不记得我是如何做到这一点的语义,但它工作得很好,正如你在现场演示中看到的那样http://backtick.town/~jay/scales(正在开发中,不要指望它还没工作)
如您所见,您可以将 document.querySelectorAll(selector)
替换为 toplevel
数组,将 fun
替换为您的函数。
同样,这段记忆对我来说非常模糊,所以这可能行不通。如果它不起作用,请随意投票并向我发泄你的愤怒。
在现代浏览器中,您应该添加一个侦听器:
var topLevel = document.getElementsByClassName("has-dropdown");
for (var i = 0; i < topLevel.length; i++) {
topLevel[i].addEventListener('focus',function(event) {
console.log("you have activated the dropdown");
event.currentTarget.nextElementSibling.className = "active";
},false);
}
参考:addEventListener not working in IE8
较旧的浏览器
var topLevel = document.getElementsByClassName("has-dropdown");
for (var i = 0; i < topLevel.length; i++) {
if (topLevel[i].addEventListener) {
topLevel[i].addEventListener('focus',function(event) {
console.log("you have activated the dropdown");
event.currentTarget.nextElementSibling.className = "active";
},false);
}
else {
topLevel[i].attachEvent("focus", function(event) {
console.log("you have activated the dropdown");
event.currentTarget.nextElementSibling.className = "active";
});
}
我刚刚开始学习 Javascript(刚开始),我在尝试将焦点应用到某个元素时显示隐藏的 "sub navigation" 菜单时遇到问题。我保持它非常基本(我认为)。
这个想法与悬停时显示隐藏的 "sub navigation" 菜单相同。当用户切换到元素并应用焦点时,菜单显示并且菜单中的 links 变得可聚焦。当用户离开菜单时,菜单会再次隐藏。我希望这种情况发生在任意数量的导航元素上。
HTML:
<nav role="navigation">
<ul>
<li><a href="#">Link 1</a></li>
<li><a href="#" class="has-dropdown">Link 2</a>
<ul class="dropdown">
<li><a href="#">Link 2a</a></li>
<li><a href="#">Link 2b longer</a></li>
<li><a href="#">Link 2c longest text</a></li>
</ul>
</li>
<li><a href="#">Link 3</a></li>
<li><a href="#">Link 4</a></li>
</ul>
</nav>
不确定您是否需要它,但这是 CSS:
nav[role=navigation] {
width: 100%;
background: #505050;
font-family: Oswald,sans-serif;
font-weight: 200;
}
nav[role=navigation] ul {
margin: 0;
padding: 0;
list-style: none;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-wrap: wrap;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
-webkit-justify-content: flex-start;
-ms-flex-pack: start;
justify-content: flex-start;
}
nav[role=navigation] ul li {
-webkit-flex: 0 1 auto;
-ms-flex: 0 1 auto;
flex: 0 1 auto;
text-align: center;
padding: .8333rem;
border-right: 1px solid #252525;
position: relative;
}
nav[role=navigation] ul li:last-of-type {
border-right: none;
}
nav[role=navigation] ul li:hover a + ul {
display: block;
}
nav[role=navigation] ul ul {
list-style: none;
position: absolute;
top: 100%;
left: 0;
background: #252525;
padding: 0;
width: 200%;
text-align: left;
display: none;
}
nav[role=navigation] ul ul.active {
display: block;
}
nav[role=navigation] ul a {
padding: 0 1rem;
color: #fff;
text-decoration: none;
}
nav[role=navigation] ul a:focus,
nav[role=navigation] ul a:hover {
text-decoration: underline;
color: #ccc;
}
Javascript:
var topLevel = document.getElementsByClassName("has-dropdown");
for (var i = 0; i < topLevel.length; i++) {
topLevel[i].onfocus = function() {
console.log("you have activated the dropdown");
topLevel.nextElementSibling.className = "active";
}
}
当我切换到触发此操作的 link 时,我在任何具有子菜单但不显示子菜单的 link 上正确地收到日志消息。当我从控制台 运行 时,出现错误:
"Cannot set property "className" of undefined."
我相信这与变量是数组有关,因为如果我设置 topLevel 的索引,例如 topLevel[0],它会完美地工作。
我想使用原生 JS。没有JQuery.
我已经搜索过类似的问题,但找不到任何超出我理解范围的答案或只能给出 JQuery 解决方案。
我看过:
Drop down menu to hide on click event
For-each over an array in JavaScript? --> 这个让我脑袋出血。
Target items in an array on click?
答案可能隐藏在上述帖子之一中,但即使是,我也找不到。
我在项目中遇到了同样的问题https://github.com/arthurdd/scales/blob/master/index.js#L60
基本上我所做的就是定义一个函数add_listeners_all
(如果你只做一次,你可能不需要这样的函数)
这是代码
function add_listeners_all( selector, fun ) {
Array.prototype.slice.apply(document.querySelectorAll(selector)).forEach(el) {
el.addEventListener('click', fun);
});
});
我不记得我是如何做到这一点的语义,但它工作得很好,正如你在现场演示中看到的那样http://backtick.town/~jay/scales(正在开发中,不要指望它还没工作)
如您所见,您可以将 document.querySelectorAll(selector)
替换为 toplevel
数组,将 fun
替换为您的函数。
同样,这段记忆对我来说非常模糊,所以这可能行不通。如果它不起作用,请随意投票并向我发泄你的愤怒。
在现代浏览器中,您应该添加一个侦听器:
var topLevel = document.getElementsByClassName("has-dropdown");
for (var i = 0; i < topLevel.length; i++) {
topLevel[i].addEventListener('focus',function(event) {
console.log("you have activated the dropdown");
event.currentTarget.nextElementSibling.className = "active";
},false);
}
参考:addEventListener not working in IE8
较旧的浏览器
var topLevel = document.getElementsByClassName("has-dropdown");
for (var i = 0; i < topLevel.length; i++) {
if (topLevel[i].addEventListener) {
topLevel[i].addEventListener('focus',function(event) {
console.log("you have activated the dropdown");
event.currentTarget.nextElementSibling.className = "active";
},false);
}
else {
topLevel[i].attachEvent("focus", function(event) {
console.log("you have activated the dropdown");
event.currentTarget.nextElementSibling.className = "active";
});
}