如何在 keydown 上使用 Javascript 模拟悬停?

Posted

技术标签:

【中文标题】如何在 keydown 上使用 Javascript 模拟悬停?【英文标题】:How do I simulate hover with Javascript on keydown? 【发布时间】:2013-01-22 17:43:42 【问题描述】:

首先,我想只使用原生 javascript 来完成这项任务。

假设我要制作一个自定义下拉菜单,html 代码看起来像这样。

<div class="dropdown">
  <span class="dropdown-label" style="display:block">Select a thing</span>
  <ul class="dropdownItemContainer">
    <li>Item 1</li>
    <li>Item 2</li>
    <li>Item 3</li>
    <li>Item 4</li>
    <li>Item 5</li>
    <li>Item 6</li>
  </ul>
</div>

在 CSS 文件中,我有类似的东西:

ul.dropdownItemContainer li:hover 
  background-color: #FF0000;

是的,确实没有下拉行为,但实际上这不是讨论的重点。问题是我想不出一种体面的方法来为此下拉菜单启用键盘控制。期望的结果如下:我按下向下键,第一个选项被突出显示;我再次按下它,第二个选项被突出显示,依此类推。

此时我看到的唯一选择(刚开始学习 JS)是获取所有ul 的孩子,将它们粘贴到一个数组中,并通过 JS 方法以适当的方式为标签分配背景颜色每次按下向下键时的方式。

另一方面,我仍然有鼠标控制的 CSS 中描述的 :hover 行为。有模拟悬停的聪明方法吗?

【问题讨论】:

键盘导航大量使用:focus @AlessandroVendruscolo 是的,但除了 或常规控制元素之外,我真的无法专注于任何事情,可以吗? :) 我只想到了 jQuery 解决方案 :( 添加tabindex 属性,或在lis 内放置锚点——参见this answer @AlessandroVendruscolo 基于 tabindex 的焦点事件不是很可靠。例如。 :focus 伪类不会在某些浏览器中触发。 【参考方案1】:

我会在你的 li 元素上简单地分配一个类,并使用 keydown 处理程序来控制它。以下代码并不完整,而是为您提供一些可以使用的东西。

var active = document.querySelector(".hover") || document.querySelector(".dropdownItemContainer li");

document.addEventListener("keydown",handler);
document.addEventListener("mouseover",handler);

function handler(e)
    console.log(e.which);
        active.classList.remove("hover");
    if (e.which == 40)
        active = active.nextElementSibling || active;
    else if (e.which == 38)      
        active = active.previousElementSibling || active;
    else
        active = e.target;
    
        active.classList.add("hover");

你可以看到一个working example here

【讨论】:

谢谢你们的时间。 非常感谢您的解决方案,我在同一个问题上苦苦挣扎了很长时间。【参考方案2】:

您可能希望使用库而不是从头开始编写代码。

http://vebersol.net/demos/jquery-custom-forms/

http://www.dreamcss.com/2009/05/15-jquery-plugins-to-enhance-your-html.html

【讨论】:

感谢您的回答,但是,正如我所提到的,我正在尝试研究原生 JS,所以我实际上想从头开始编写整个代码。我知道 JQuery 提供了很多可能性和自定义选项,我承认它们很酷而且很有用,但我最终会谈到它:) jsfiddle.net/Hd7X9 - 给你。我已经在 facebook 上给你写信了,我想我需要给你一些背景知识。【参考方案3】:

我建议从 css 中删除 hover 属性。 并且只添加一个应用于按键和鼠标悬停的悬停类

这在代码中可能如下所示

var dropDown = document.getElementsByClassName("dropdownItemContainer")[0]

document.addEventListener("keydown",function (e) 
    if(e.keyCode == 38 || e.keyCode == 40 ) 
        var key = e.keyCode
        var hovered = dropDown.getElementsByClassName("hovered")
        if(hovered.length != 0 ) 
            cur = hovered[0]
            cur.className = ""
            cur = cur[(key==38?"previous":"next")+"ElementSibling"] || dropDown.children[key==38?dropDown.children.length-1:0] 
         else 
            cur = dropDown.children[key==38?dropDown.children.length-1:0]
        
        cur.className="hovered"
    
);


dropDown.addEventListener("mouseover",function (e) 
    for( var i = 0,j; j = dropDown.getElementsByClassName("hovered")[i];i++)
        j.className = "";
    e.srcElement.className = "hovered";
);

这是JSFiddle上的一个例子

【讨论】:

【参考方案4】:

现实你不需要任何 js 来进行下拉,但你可以使用 JavaScript 事件来模拟它。您可以使用 hoverfocusonclick

等事件

在 JS 中你可以用它来设置事件

  document.getElementById('id').addEventListener('focus',function(e)
    //place code that want ran at event happened
    

在 JQuery 中,您可以使用 bindclick、...

  $('#id')bind('focus',function(e)
    //place code that want ran at event happened
  

事件列表

http://www.quirksmode.org/dom/events/index.html

【讨论】:

@Christoph 是的,我们可以使用焦点事件quirksmode.org/dom/events/index.html 好吧,支持焦点元素的事实并没有改变默认情况下只有window、链接和表单域可以被聚焦的事实。否则,您需要在元素上声明 tabindex,即使那样,焦点也不一致支持。

以上是关于如何在 keydown 上使用 Javascript 模拟悬停?的主要内容,如果未能解决你的问题,请参考以下文章

如何检测子窗口上的 WM_KEYDOWN?

如何在 KeyDown 事件中检测 NumberDecimalSeparator (C#)

在捕获keydown事件时如何在文本框中允许退格

VB.NET如何使控件不能响应KeyDown事件

捕获 DIV 元素上的按键(或 keydown)事件

如何在 Ext.Message.Box 中使用 keydown 事件