如何在纯JavaScript中模拟鼠标悬停来激活CSS“:hover”?

eagi6jfj  于 2023-05-23  发布在  Java
关注(0)|答案(7)|浏览(326)

我一直试图在Chrome中找到模拟mouseover的代码,但即使“mouseover”侦听器被触发,CSS“hover”声明也从未设置!
我也试着做:

//Called within mouseover listener
theElement.classList.add("hover");

但是似乎没有任何东西将元素更改为hover声明中声明的内容。
这可能吗?

u1ehiz5o

u1ehiz5o1#

您可以像这样模拟mouseover事件:

HTML

<div id="name">My Name</div>

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);
3duebb1j

3duebb1j2#

后台

我在尝试编写自动化测试时偶然发现了这个问题,以验证给定页面上的某组元素是否都接收到css为onhover事件设置的css属性。
虽然上面的答案完美地解释了为什么不可能简单地通过JS触发hover事件,然后探测一些感兴趣的css值,但它确实回答了最初的问题“如何在纯JavaScript中模拟激活CSS的鼠标悬停“:hover”?”“只是部分。

免责声明

这不是一个高性能的解决方案。我们只在自动化测试中使用它,在这种情况下性能不是问题。

解决方案

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();
    }
}

说明

generateEvent读取所有的css文件,将:hover替换为空字符串并应用它。这样做的效果是应用所有:hover样式。现在可以探测一个howered样式,并通过停止模拟设置回初始状态。

  • 为什么我们要对整个文档应用悬停效果,而不仅仅是通过从工作表中获取然后执行元素.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");
    });
});
kyvafyod

kyvafyod3#

在这种情况下,我通常会使用javascript添加一个类。并将与:hover相同的CSS附加到此类
试试用

theElement.addEventListener('onmouseover', 
    function(){ theElement.className += ' hovered' });

或者对于较旧的浏览器:

theElement.onmouseover = function(){theElement.className += ' hovered'};

你当然要使用onmouseout来删除“悬停”类,当你离开元素时…

yvfmudvl

yvfmudvl4#

您可以使用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');
  })
})();

免责声明:我是这个图书馆的合著者。我们将其设计为额外支持跨源样式表,特别是用于Chrome扩展程序,您可能无法控制页面的CSS规则。

dffbzjpn

dffbzjpn5#

我假设您希望在dom操作之后检查CSS,但是一旦您将鼠标移回devtools,该事件在该html元素上就不再活动。你可能希望在devtools中为你的javascript事件设置类似于:hover选项的东西。它不存在,但你可以模拟它。
1.打开你的devtools并点击它使其激活。
1.在您感兴趣的元素上触发事件。
1.不用移动鼠标,用ctrl + shift + p打开devtools命令面板,然后用键盘选择“禁用javascript”。
由于javascript被禁用,它没有机会再次修改元素。你可以去devtools查看css和html,就像你在悬停、点击或做其他事情一样。完成后,再次进入命令面板并选择“启用javascript”。

y1aodyip

y1aodyip6#

我想提一个不同的方法来解决这个问题,只使用css,但我在这里假设:hover将在其中一个父标记发生变化的情况下被触发,如下所示:

function btn_activated(){
      const button = document.querySelector('button.btn');
      if(button.classList.contains('active')){
          button.classList.remove('active');
      }else{
           button.classList.add('active');
      }
  }
.btn{
        width: 100px;
        height: 30px;
    }
    .btn:hover > span.visually-hidden,
    .active> span.visually-hidden{
        display: inline;
    }
    .visually-hidden{
        display: none;
    }
<button class="btn" onClick="btn_activated()">
    <span class="visually-hidden">
       hovered
    </span>
</button>

可以将这个概念应用于任何嵌套的标记,但父标记中的一个至少应该更改其classList。

kzipqqlq

kzipqqlq7#

你不能。这不是一个受信任的事件。
由用户代理生成的事件,无论是作为用户交互的结果,还是作为对DOM的改变的直接结果,都由具有特权的用户代理信任,所述特权不被给予由脚本通过DocumentEvent.createEvent(“Event”)方法生成的事件、使用Event.initEvent()方法修改的事件、或经由EventTarget.dispatchEvent()方法分派的事件。受信任事件的isTrusted属性值为true,而不受信任事件的isTrusted属性值为false。
大多数不可信事件不应触发默认动作,但click或DOMActivate事件除外。
您必须添加一个类,并手动添加/删除mouseover/mouseout事件。

相关问题