Javascript JS ArrowDown为循环中的多个元素添加了EventListener(演示)

Javascript JS ArrowDown为循环中的多个元素添加了EventListener(演示),javascript,events,loops,listener,arrow-keys,Javascript,Events,Loops,Listener,Arrow Keys,为键盘ArrowDown事件设置以下侦听器(其键代码为40): window.onload=function(){ var itemsContainer=document.getElementById('cities-drop'); document.addEventListener('keyup',函数(事件){ if(event.keyCode==40&&itemsContainer.style.display==block){ event.preventDefault(); 对于(var

为键盘
ArrowDown
事件设置以下侦听器(其键代码为
40
):

window.onload=function(){
var itemsContainer=document.getElementById('cities-drop');
document.addEventListener('keyup',函数(事件){
if(event.keyCode==40&&itemsContainer.style.display==block){
event.preventDefault();

对于(var i=0;i在查看代码并了解您试图执行的操作后,我认为您的错误是使用了
substr
,您应该使用
indexOf
。以下是更新的行:

if (itemsContainer.getAttribute('class').indexOf('hovered') != -1)


更多详细信息: 实际上,您使用的是一个
substr
和一个字符串值作为
start
索引。不确定结果会是什么,但显然不是-1,因为条件每次都返回true,导致下一个元素每次悬停,一直到列表底部。使用
break
语句,它在第一个元素执行if语句(导致第二个元素被“悬停”),然后退出

更正代码后,我会将
break
语句留在那里,以便循环在找到匹配项后停止,而不会不必要地循环其他项


编辑:

我在您的代码中还发现了一些其他问题。下面是一个在IE和FF中适用的示例,至少(没有在Safari、Opera或Chrome中测试过):


.盘旋
{
颜色:红色;
}
功能移动(事件)
{
var itemsContainer=document.getElementById('cities-drop');
if(event.keyCode==40&&itemsContainer.style.display==block)
{
if(event.preventDefault)
event.preventDefault();
if(event.cancelBubble)
event.cancelBubble();
if(事件停止立即复制)
事件。stopImmediatePropagation();

对于(var i=0;i,我可以看到一些事情可能是个问题
itemsContainer.children[i].nextSibling
itemsContainer.children[i+1]
。这就是为什么如果跳过中断,它总是选择最后一个元素。如果有与类匹配的项,itemsContainer[i+1]将始终悬停

第二个问题是Travesty3在他的回答中指出了什么

我还更改了if条件,以检查悬停的类是否在其中一个子类上,而不是容器本身

if (itemsContainer.children[i].getAttribute('class').match('hovered'))
我用以下代码行修改了事件处理程序,这似乎很好:

document.addEventListener('keyup',function(event){
            if (event.keyCode === 40 && itemsContainer.style.display==='block') {
                event.preventDefault();
                for (var i=0,l=itemsContainer.children.length;i<l;++i){
                    if (itemsContainer.children[i].getAttribute('class').match('hovered')){
                        itemsContainer.children[i].setAttribute('class','');
                        itemsContainer.children[i+1].setAttribute('class','hovered');
                        break;
                    }
                }
            }
        });
document.addEventListener('keyup',函数(事件){
if(event.keyCode==40&&itemsContainer.style.display==block){
event.preventDefault();

对于(var i=0,l=itemsContainer.children.length;i您可以尝试一种更简单的方法,而不是使用循环:

window.onload = function() {    
    var itemsContainer = document.getElementById('cities-drop');

    document.addEventListener('keyup',function(event) {
        if (event.keyCode == 40 && itemsContainer.style.display=='block') {
            event.preventDefault();

            var previousHoveredChoice = itemsContainer.querySelector('.hovered');
            previousHoveredChoice.className = '';

            var currentHoveredChoice = previousHoveredChoice.nextSibling;
            if (currentHoveredChoice) {
                currentHoveredChoice.className = 'hovered';
            }
        }
    });

    //following code is copy-pasted from the live example 
    //just to close the onload function handler in this solution
    document.addEventListener('keyup',function(event){
        if (event.keyCode == 27) {

            if (document.getElementById('cities-drop').style.display=='block'){
                document.getElementById('cities-drop').style.display='none';
            }
        }

    });
    //end of copy-pasted code
};

你想实现什么?自定义下拉菜单?@Šime Vidas你完全正确为什么你想自己编写它?有一些库和框架提供这种功能。@Šime Vidas我知道。这是我JS学习计划中的任务。我说的更多-我用纯JS编写它。你想实现什么?你想选择吗列表中的一个项目有向上箭头键和向下箭头键?是的,这是我的错误,我错误地使用了
substr
。无论如何,这对我没有帮助,无论是
indexOf()
,还是
match())
,很抱歉反应太晚。你在这里写的那个版本对我很有效。从另一个角度看,我不需要内联观察者
onkeydown=move(event)
,所以当我尝试使用
addEventListener
时,我会给你fedback@sergionni:请记住,
addEventListener
在IE中不受支持,IE仍然是最常用的浏览器之一。您将在Internet Explorer中遇到一个Javascript错误,即
对象不支持此属性或方法。
。如果您如果不使用此方法,则应首先执行检查以查看函数是否存在。请参见示例。是的,我知道
attachEvent
addEventListener
。这不是问题。主要问题是我需要侦听器,而不是“内联观察者”。@sergionni:我不明白你所说的“内联观察者”是什么意思…使用内联方法附加事件仍将以与使用
addEventListener
相同的方式执行该功能。我所知道的唯一区别是,如果尝试使用内联方法向同一事件添加另一个操作,则会覆盖上一个操作,而使用
addEventListener
,这两个操作都会被覆盖s将执行。因此,内联方法仍然是一个事件侦听器,完全相同。似乎您忘记更新if语句:if(itemsContainer.children[i].getAttribute('class').match('hovered')){
document.addEventListener('keyup',function(event){
            if (event.keyCode === 40 && itemsContainer.style.display==='block') {
                event.preventDefault();
                for (var i=0,l=itemsContainer.children.length;i<l;++i){
                    if (itemsContainer.children[i].getAttribute('class').match('hovered')){
                        itemsContainer.children[i].setAttribute('class','');
                        itemsContainer.children[i+1].setAttribute('class','hovered');
                        break;
                    }
                }
            }
        });
window.onload = function() {    
    var itemsContainer = document.getElementById('cities-drop');

    document.addEventListener('keyup',function(event) {
        if (event.keyCode == 40 && itemsContainer.style.display=='block') {
            event.preventDefault();

            var previousHoveredChoice = itemsContainer.querySelector('.hovered');
            previousHoveredChoice.className = '';

            var currentHoveredChoice = previousHoveredChoice.nextSibling;
            if (currentHoveredChoice) {
                currentHoveredChoice.className = 'hovered';
            }
        }
    });

    //following code is copy-pasted from the live example 
    //just to close the onload function handler in this solution
    document.addEventListener('keyup',function(event){
        if (event.keyCode == 27) {

            if (document.getElementById('cities-drop').style.display=='block'){
                document.getElementById('cities-drop').style.display='none';
            }
        }

    });
    //end of copy-pasted code
};