如何在纯JavaScript中模拟鼠标悬停以激活CSS":hover"?

Don*_*mmy 67 javascript css jquery

我一直试图找到mouseover在Chrome中模拟的代码,但即使"mouseover"监听器被触发,CSS"悬停"声明也永远不会被设置!

我也尝试过:

//Called within mouseover listener
theElement.classList.add("hover");
Run Code Online (Sandbox Code Playgroud)

但似乎没有任何东西可以将元素更改为其hover声明中声明的内容.

这可能吗?

Ben*_*aum 94

你不能.这不是一个值得信赖的事件.

由用户代理生成的事件,或者作为用户交互的结果,或者作为DOM更改的直接结果,由用户代理信任的事件具有通过DocumentEvent.createEvent脚本生成的事件所不具有的权限("Event")方法,使用Event.initEvent()方法修改,或通过EventTarget.dispatchEvent()方法调度.受信任事件的isTrusted属性值为true,而不受信任事件的isTrusted属性值为false.

大多数不受信任的事件不应触发默认操作,但click或DOMActivate事件除外.

您必须手动添加一个类并在mouseover/mouseout事件上添加/删除它.

  • @Tim,它实际上并没有回答**为什么**.它只是[更改问题](http://stackoverflow.com/questions/6406976/how-to-trigger-css-hover-state-using-javascript/6407065#comment46517728_6407065). (4认同)
  • @Pacerier它不是一个受信任的事件,因为它不是由用户发起的.在我的回答中,它在上面的引文中说得那么正确.这就是答案的开头. (4认同)
  • @BenjaminGruenbaum,我引用*“除了点击或 DOMActivate 事件”*。“hover”有什么特别之处以至于它不在这个例外列表中?为什么我们可以[允许调用“焦点”](http://stackoverflow.com/a/6407021/632951)而不是“悬停”?这些是我们必须回答的问题,回答其他任何问题都只是“改变问题”。 (3认同)
  • 是的,听起来很荒谬,您可以使焦点看起来像是由用户交互引起的,而实际上并不是由用户交互引起的。在实践中-浏览器API会很乐意违反规范,而忽略焦点并单击是不受信任的事件(至少是Chrome)。尝试例如模拟对chrome扩展程序的扩展程序安装按钮的单击,看看会发生什么:) (2认同)

lbp*_*ers 19

您可以像这样模拟鼠标悬停事件:

HTML

<div id="name">My Name</div>
Run Code Online (Sandbox Code Playgroud)

JavaScript的

var element = document.getElementById('name');
element.addEventListener('mouseover', function() {
  console.log('Event triggered');
});

var event = new MouseEvent('mouseover', {
  'view': window,
  'bubbles': true,
  'cancelable': true
});

element.dispatchEvent(event);
Run Code Online (Sandbox Code Playgroud)

  • 谢谢,我所需要的只是气泡!右键单击开发人员控制台检查器中的元素,然后执行“在控制台中使用”(Firefox) 或“存储为全局变量”(Chrome)。然后你可以,例如 `temp0.dispatchEvent(new MouseEvent('mouseover', {bubbles: true}))` 对于设置工具提示或仅在鼠标悬停时出现的其他内容的样式非常有用。 (2认同)
  • @DenisHowe 对于该用例,您应该查看 devtools 中样式检查器顶部的 `:hov` 按钮。它允许您在正在检查的元素上激活您喜欢的任何伪类。 (2认同)

Ams*_*utz 17

背景

我在尝试编写自动化测试时偶然发现了这个问题,以验证给定页面上的某些元素集合都接收到由css为悬停事件设置的一些css属性.

虽然上面的答案完美地解释了,为什么不可能简单地通过JS触发悬停事件然后证明一些感兴趣的css值,它确实回答了最初的问题"如何在纯JavaScript中模拟鼠标悬停激活CSS":悬停"?" 只是部分.

放弃

这不是一个高效的解决方案.我们仅将其用于自动化测试,其中性能不是问题.

simulateCssEvent = function(type){
    var id = 'simulatedStyle';

    var generateEvent = function(selector){
        var style = "";
        for (var i in document.styleSheets) {
            var rules = document.styleSheets[i].cssRules;
            for (var r in rules) {
                if(rules[r].cssText && rules[r].selectorText){
                    if(rules[r].selectorText.indexOf(selector) > -1){
                        var regex = new RegExp(selector,"g")
                        var text = rules[r].cssText.replace(regex,"");
                        style += text+"\n";
                    }
                }
            }
        }
        $("head").append("<style id="+id+">"+style+"</style>");
    };

    var stopEvent = function(){
        $("#"+id).remove();
    };

    switch(type) {
        case "hover":
            return generateEvent(":hover");
        case "stop":
            return stopEvent();
    }
}
Run Code Online (Sandbox Code Playgroud)

说明

generateEvent读取所有css文件,替换:用空字符串悬停并应用它.这具有以下效果:应用所有:悬停样式.现在,可以通过停止模拟来探测啸叫风格并恢复到初始状态.

为什么我们将悬停效果应用于整个文档,而不仅仅是通过从工作表中获取感兴趣的元素然后执行element.css(...)?

完成后,样式将内联应用,这将覆盖其他样式,这些样式可能不会被原始的css悬停样式覆盖.

我现在如何模拟单个元素的悬停?

这不是高效的,所以最好不要.如果必须,可以使用element.is(selectorOfInterest)检查样式是否适用于您的元素并仅使用这些样式.

在Jasmine你现在可以执行:

describe("Simulate CSS Event", function() {
    it("Simulate Link Hover", function () {
      expect($("a").css("text-decoration")).toBe("none");
      simulateCssEvent('hover');
      expect($("a").css("text-decoration")).toBe("underline");
      simulateCssEvent('stop');
      expect($("a").css("text-decoration")).toBe("none");
    });
});
Run Code Online (Sandbox Code Playgroud)

  • 这个答案太棒了!不幸的是,由于 Chrome 限制对跨源请求的访问,在最新版本的 Chrome 上,在具有其他主机提供的样式表的页面上,它会失败。请参阅我的答案以获取支持此功能的解决方案:) (2认同)

FTh*_*son 7

您可以使用pseudo:styler,这是一个可以将CSS伪类应用于元素的库。

(async () => {
  let styler = new PseudoStyler();
  await styler.loadDocumentStyles();
  document.getElementById('button').addEventListener('click', () => {
    const element = document.getElementById('test')
    styler.toggleStyle(element, ':hover');
  })
})();
Run Code Online (Sandbox Code Playgroud)

免责声明:我是该库的合著者。我们设计它还支持跨源样式表,特别是在您可能无法控制页面 CSS 规则的 Chrome 扩展中使用。


Yot*_*mer 5

我最常做在这种情况下是使用JavaScript添加类..和将相同CSS:hover这一类

尝试使用

theElement.addEventListener('onmouseover', 
    function(){ theElement.className += ' hovered' });
Run Code Online (Sandbox Code Playgroud)

或者对于旧浏览器:

theElement.onmouseover = function(){theElement.className += ' hovered'};
Run Code Online (Sandbox Code Playgroud)

onmouseout当你离开元素时,你必须用它去除"悬停"类...

  • 还不够好?它是“纯” JavaScript,实际上它将附加一个函数作为事件的处理程序。在Internet Explorer中,将使用(几乎)等效的`attachEvent()`。 (2认同)