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