【问题标题】:How do I simulate a mouseover in pure JavaScript that activates the CSS ":hover"?如何在激活 CSS“:hover”的纯 JavaScript 中模拟鼠标悬停?
【发布时间】:2013-06-18 01:54:15
【问题描述】:

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

我也尝试过:

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

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

这可能吗?

【问题讨论】:

  • @PSL 我想他想做的就是在一个元素上强制:hover 状态。
  • @BenjaminGruenbaum 是的,你是对的。我误会了。
  • 这不是重复的。另一个问题是关于 jQuery 的。这个问题是关于纯 JS 的。
  • @Monk OQ 包含 jQuery 标签。这是重复的。
  • @JasonMArcher 这个问题(及其答案)是关于纯 JS 的。你不认为更有可能是他们弄错了。

标签: javascript jquery css


【解决方案1】:

你不能。这不是trusted event

由用户代理生成的事件,无论是作为用户交互的结果,还是作为对 DOM 更改的直接结果,都受到用户代理的信任,其权限是脚本通过DocumentEvent.createEvent("Event") 方法,使用 Event.initEvent() 方法修改,或通过 EventTarget.dispatchEvent() 方法调度。可信事件的 isTrusted 属性值为 true,而非可信事件的 isTrusted 属性值为 false。

大多数不受信任的事件不应触发默认操作,点击或 DOMActivate 事件除外。

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

【讨论】:

  • @Tim,它实际上并没有回答 为什么。它只是changes the question
  • @Pacerier 这不是一个受信任的事件,因为它不是由用户发起的。在我的回答中上面的引用中说 就在那里。这就是答案的开头。
  • @BenjaminGruenbaum,我引用 “除了点击或 DOMActivate 事件”。 “悬停”有什么特别之处以至于它不在这个例外列表中?为什么我们是allowed to call "focus" 而不是“悬停”?这些是我们必须回答的问题,回答其他任何问题都只是改变问题
  • 我会假设悬停(并结合单击或鼠标上下进行拖放)的行为或看起来就像劫持用户的系统(如果您忽略自动化案例),所以它不是理想的支持。单击我不能说,但焦点将允许自动聚焦到站点设计者希望用户关注的目标表单字段或元素,例如缺少或不正确数据的文本字段(例如表单字段验证检查)。但这只是我的假设。
  • 是的,尽管听起来很荒谬,但您可以使焦点看起来是由用户交互引起的,而实际上并非如此。在实践中 - 浏览器 API 会很乐意违反规范并忽略焦点并作为不受信任的事件单击(至少 Chrome 是这样)。尝试例如模拟单击 chrome 扩展的扩展安装按钮,看看会发生什么:)
【解决方案2】:

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

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

【讨论】:

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

背景

我在尝试编写自动化测试时偶然发现了这个问题,以验证给定页面上的特定元素集是否都具有 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();
    }
}

说明

generateEvent 读取所有 css 文件,将 :hover 替换为空字符串并应用它。这具有应用所有 :hover 样式的效果。现在可以通过停止模拟来探索一种风格并返回初始状态。

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

这样做后,样式将被内联应用,这将覆盖其他样式,这些样式可能不会被原始 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");
    });
});

【讨论】:

  • 这个答案很棒!不幸的是,由于 Chrome 限制了对跨域请求的访问,它在最近版本的 Chrome 页面上使用其他主机提供的样式表失败。请参阅我的答案以获得支持此的解决方案:)
【解决方案4】:

在这种情况下,我通常做的是使用 javascript 添加一个类.. 并将与 :hover 相同的 CSS 附加到该类

尝试使用

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

或者对于旧版浏览器:

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

当您离开元素时,您当然必须使用onmouseout 删除“悬停”类...

【讨论】:

  • 这不会按照 OP 的要求执行,尽管它可能或多或少是正确的。最好使用现代事件处理程序附件技术。
  • 对不起,问题误解了
  • @Pointy 问题要求纯 javascript .. 否则如何附加事件?
  • 不够好?它是“纯”JavaScript,实际上它会附加一个函数作为事件的处理程序。在 Internet Explorer 中,将使用(几乎)等效的 attachEvent()
  • 值得一提。 IE9 和 10 支持 addEventListener,这是附加事件的最佳方式,仅在 IE8(及以下)中需要填充 attachEvent。 Yotam,如果他通过直接设置属性(而不是添加事件侦听器)向onmouseover 添加另一个处理程序,它将覆盖当前设置的事件。请参阅this question 了解差异。
【解决方案5】:

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

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

【讨论】:

  • 这似乎实际上工作得很好,即使在设置伪样式后与window.getComputedStyle(&lt;youElement&gt;) 结合使用也是如此。谢谢!
【解决方案6】:

我假设您想在 dom 操作后检查 CSS,但是一旦您将鼠标移回 devtools,该事件就不再在该 html 元素上处于活动状态。您可能希望在 devtools 中为您的 javascript 事件提供类似 :hover 选项的内容。那不存在,但你可以模拟它。

  1. 打开您的开发工具并单击它以使其处于活动状态。
  2. 在您感兴趣的元素上触发事件。
  3. 在不移动鼠标的情况下,使用 ctrl + shift + p 打开 devtools 命令面板,然后使用键盘选择“禁用 javascript”。

由于 javascript 被禁用,它没有机会再次修改元素。您可以转到 devtools 并检查 css 和 html,就好像您在悬停、单击或用它做其他事情一样。完成后,再次进入命令面板并选择“启用 javascript”。

【讨论】:

  • 简洁的技术,但除非我误解了你的意图,否则这确实已经存在于开发工具中!在 Chrome/Chromium 和 Firefox 的开发工具中,样式检查器的顶部(“过滤器”输入框旁边)都有一个 :hov 按钮。单击:hov 会展开一系列复选框,每个复选框都标有一个伪类::active:focus:focus-within:hover:visited。选中其中任何一个框都会在被检查的元素上激活其各自的伪类。
猜你喜欢
  • 2018-10-21
  • 2010-10-11
  • 1970-01-01
  • 1970-01-01
  • 2013-07-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多