通过编程触发Hover CSS伪类

16

我需要以编程方式触发悬停伪类(如果可能带有冒泡效果,否则我将被迫调用更改所有元素父级的更改)。

我无法控制html页面,因此无法将css从:hover更改为.hover以更新HTMLElement的类为.hover。

这是否可能?

请不要使用jQuery。 我不能在我的项目中使用JQuery。

提前致谢。

更新

我创建了一个类似于CSS加载器的代理,因此现在在加载css之前,它会经过我的“代理”,并将规则从:hover更改为.hoverclass。

好吧,现在悬停效果运行得很好,但是由于悬停模拟的冒泡,我有一些严重的性能问题。

以下是一些代码:

var actualHoveredElements = new Array();
var hoverAddedCount = 0;
var maxHoveredElems = 5;

function changeHover(newElement, oldElement){
    var oldHoveredElements = actualHoveredElements.slice();

    var remainingElements = setHoverForParentsOfElement(newElement, oldHoveredElements);

    for(var i = 0; i < remainingElements.length; i++){
        var notHoveredElement = remainingElements[i];
        var actualIndex = actualHoveredElements.indexOf(notHoveredElement);

        if(actualIndex > -1){
            actualHoveredElements.splice(actualIndex, 1);
        }
        notHoveredElement.classList.remove("hoverclass");
    }

    hoverAddedCount = 0;
    changeHoverTimeout = null;
}


function setHoverForParentsOfElement(element, oldHoveredElements){
    var index = -1;

    if(oldHoveredElements != "undefined" && oldHoveredElements.length > 0)
        index = oldHoveredElements.indexOf(element);

    if(index > -1){
        oldHoveredElements.splice(index, 1);
    } else {
        actualHoveredElements.push(element);
        element.classList.add("hoverclass");
    }

    if(element.tagName != "BODY" && element.tagName != "HTML"){
        if(hoverAddedCount < maxHoveredElems-1){
            hoverAddedCount ++;
            oldHoveredElements = setHoverForParentsOfElement(element.parentNode, oldHoveredElements);
        }
    }

    return oldHoveredElements;
}

你可以看到,我也尝试限制悬停冒泡的数量为N,但性能问题仍然存在。


我在stackoverflow上查找重复内容,但是所有的解决方案都涉及到jQuery……点个赞给你。 - Derek 朕會功夫
你能贴一些相关的代码吗? - anurupr
你想要使用onmouseover和onmouseout事件吗? - Sora
@GiuseppeLanza - 我有一个想法,既然在JS中“不可能”触发hover状态,为什么不通过JS手动获取:hover的CSS规则并应用于元素呢? - Derek 朕會功夫
@Derek 我已完成研究。在對元素進行類添加和刪除時出現性能問題冒泡。 - Giuseppe Lanza
显示剩余12条评论
2个回答

4
不可以使用JavaScript直接使元素注册为悬停,以便在没有鼠标悬停在该元素上时触发:hover CSS。最接近的方法是使用JavaScript查找应用于:hover期间将应用的CSS规则,然后手动应用它们,如此代码片段所示(以下重复显示):
// Find all css properties for the :hover you want
var applyHoverStyle = function() {
  var div = document.getElementsByTagName("div")[0];
  var i,j, sel = /div:hover/, aProperties = [];
  for(i = 0; i < document.styleSheets.length; ++i){
    // console.log(document.styleSheets[i]);
    if(document.styleSheets[i]. cssRules !== null) {
      for(j = 0; j < document.styleSheets[i].cssRules.length; ++j){    
        if(sel.test(document.styleSheets[i].cssRules[j].selectorText)){
          aProperties.push(document.styleSheets[i].cssRules[j].style.cssText);
          // console.log(document.styleSheets[i].cssRules[j].selectorText, document.styleSheets[i].cssRules[j].style.cssText);
        }
      }
    }
  }
  //console.log(aProperties);
  div.style.cssText = aProperties.join(' ');
};

0
你可以尝试这样做,尽管这并不被推荐:

http://jsfiddle.net/DerekL/N2GK9/

function triggerCSS(ele, selector) {
  whole: for (var i = 0; i < document.styleSheets.length; i++) {
    for (var j = 0; j < document.styleSheets[i].rules.length; j++) {
      if (document.styleSheets[i].rules[j].selectorText == selector) {
        var style = document.styleSheets[i].cssRules[j].style;
        for (var k = 0; k < style.length; k++) {
          ele.style[toCC(style[k])] = style[toCC(style[k])];
        }
        break whole;
      }

    }
  }

  function toCC(input) {
    return input.toLowerCase().replace(/-(.)/g, function(match, group1) {
      return group1.toUpperCase();
    });
  }
}

triggerCSS(document.getElementById("s"), "span:hover");
span:hover {
  color: red;
  text-decoration: underline;
}
<span id="s">ABC</span>


这是一个糟糕的想法,即使添加不同的样式表并使用类选择器复制悬停样式也更好。这会严重影响性能,并且可能经常被调用... 为什么不使用简单的“return”而不是那个“break”呢? - kapa
@kapa - 当然我知道这是一个糟糕的想法,这就是为什么我在答案中声明“不推荐”。然而,重点是它完成了工作,这才是最重要的。 - Derek 朕會功夫
这种方法不如我在问题更新中提到的添加类的方式好。从性能上讲似乎更糟糕了。很抱歉,但这并没有回答我的问题。:( - Giuseppe Lanza
@GiuseppeLanza - 是的,如果您可以像您所做的那样修改样式表,那么添加一个类肯定更好。但是请记住,您一开始并没有说我可以这样做,所以我坚持使用纯JS解决方案。(事实上,您明确表示无法将css从:hover更改为.hover。)无论您是否认为这回答了您的问题,我都会把它留在这里。 - Derek 朕會功夫
这是一个很好的解决方案。但现在我做了这个“代理”,所以我正在关注性能。:( 目前它们并不令人鼓舞。改变元素的类非常耗费资源!(iPhone 4s上的UIWebView性能非常糟糕。)不管怎样,谢谢。 - Giuseppe Lanza

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接