2

在 JavaScript 中,当其中一个被鼠标悬停时,是否可以突出显示具有相同类的所有项目?

例如,如果我有两个带有 class 的段落p1和两个带有 class 的段落p2,我希望p1在鼠标悬停时突出显示 的两个元素,并且我还希望在鼠标悬停时突出显示 p2 的两个元素。

<p class = "p1">This should be highlighted on mouseover</p>
<p class = "p2">This should be highlighted on mouseover</p>
<p class = "p1">This should be highlighted on mouseover</p>
<p class = "p2">This should be highlighted on mouseover</p>
4

3 回答 3

2

这是一个工作示例(需要 JQuery)。当鼠标悬停在一个成员上p1时,所有其他元素p1也将突出显示。也是如此p2

JavaScript:

function highlightAllOnMouseover(className){
    $(className).mouseover(function() {
  $(className).css("opacity", 0.4); 
  $(className).css("opacity", 1);
}).mouseleave(function() { 
    $(className).css("opacity", 0.4);
});
}
highlightAllOnMouseover(".thing1");
highlightAllOnMouseover(".thing2");

HTML:

<p class = "thing1">This is thing1.</p>
<p class = "thing2">This is thing2.</p>
<p class = "thing1">This is also thing1.</p>
<p class = "thing2">This is also thing2.</p>

要使具有特定类的所有元素在鼠标悬停时突出显示,您只需调用highlightAllOnMouseover(className)我在此处创建的函数。

于 2013-04-11T23:21:36.067 回答
2

我不禁觉得这应该更简洁(使用三个 for (...)循环感觉不必要地昂贵),但是一种方法:

Object.prototype.classHighlight = function (over, out) {
    var that = this.length ? this : [this];
    function onOver() {
        for (var i = 0, len = that.length; i < len; i++) {
            that[i].style.backgroundColor = over;
        }
    }
    function onOut() {
        for (var i = 0, len = that.length; i < len; i++) {
            that[i].style.backgroundColor = out;
        }
    }
    for (var i = 0, len = that.length; i < len; i++) {
        that[i].onmouseover = onOver;
        that[i].onmouseout = onOut;
    }
};

document.getElementsByClassName('test').classHighlight('#f90', '#fff');

JS 小提琴演示

六年后,在链接到这个问题和答案之后,我正在编辑以更新上述方法,并添加片段和参考。

更新代码:

// extending the Object prototype to allow chaining of this method,
// 'over' : String, the class-name to add when the element(s) of the
// HTMLCollection/NodeList are hovered-over. We also set the default
// value of the 'over' variable in order that a class-name will always
// be present:
Object.prototype.classHighlight = function(over = 'over') {

  // taking the 'this' and using the spread operator to expand
  // the iterable collection to an Array:
  const that = [...this],

    // creating a named function to act as the event-handler for
    // 'mouseenter' and 'mouseleave':
    toggleHighlight = (event) => {
      // iterating over the array using Array.prototype.forEach():
      that.forEach(

        // we're not using 'this' in here, so using an Arrow function
        // to use the Element.classList API to toggle the supplied
        // class on each element of the collection. If the event-type
        // is exactly equal to 'mouseenter' we add the class otherwise
        // we remove the class:
        (el) => el.classList.toggle(over, event.type === 'mouseenter')
      );
    };
  // iterating over the collection, again using Array.prototype.forEach():
  that.forEach(
    // and another Arrow function:
    (element) => {

      // here we bind the toggleHighlight function - created above - as
      // the event-handler for both the 'mouseenter' and 'mouseleave'
      // events:
      element.addEventListener('mouseenter', toggleHighlight);
      element.addEventListener('mouseleave', toggleHighlight);
    });
};

// here we use document.getElementsByClassName() to retrieve an HTMLCollection
// of elements matching the supplied class-name; and then using chaining - which
// is why we extended the Object prototype - to pass that HTMLCollection to
// the classHighlight() function:
document.getElementsByClassName('test').classHighlight('whenOver');
.whenOver {
  background-color: #f90;
}
<p class="test">Testing</p>
<div>No classes here</div>
<ul>
  <li class="test">Something in a 'test' element</li>
</ul>

请注意,这种更新的方法,因为我们正在切换类名——而不是在元素的style属性中添加和清除内联样式——意味着选择器的特定性可能会干扰样式的应用,例如:

// extending the Object prototype to allow chaining of this method,
// 'over' : String, the class-name to add when the element(s) of the
// HTMLCollection/NodeList are hovered-over. We also set the default
// value of the 'over' variable in order that a class-name will always
// be present:
Object.prototype.classHighlight = function(over = 'over') {

  // taking the 'this' and using the spread operator to expand
  // the iterable collection to an Array:
  const that = [...this],

    // creating a named function to act as the event-handler for
    // 'mouseenter' and 'mouseleave':
    toggleHighlight = (event) => {
      // iterating over the array using Array.prototype.forEach():
      that.forEach(

        // we're not using 'this' in here, so using an Arrow function
        // to use the Element.classList API to toggle the supplied
        // class on each element of the collection. If the event-type
        // is exactly equal to 'mouseenter' we add the class otherwise
        // we remove the class:
        (el) => el.classList.toggle(over, event.type === 'mouseenter')
      );
    };
  // iterating over the collection, again using Array.prototype.forEach():
  that.forEach(
    // and another Arrow function:
    (element) => {

      // here we bind the toggleHighlight function - created above - as
      // the event-handler for both the 'mouseenter' and 'mouseleave'
      // events:
      element.addEventListener('mouseenter', toggleHighlight);
      element.addEventListener('mouseleave', toggleHighlight);
    });
};

// here we use document.getElementsByClassName() to retrieve an HTMLCollection
// of elements matching the supplied class-name; and then using chaining - which
// is why we extended the Object prototype - to pass that HTMLCollection to
// the classHighlight() function:
document.getElementsByClassName('test').classHighlight('whenOver');
li.test {
  background-color: fuchsia;
}
.whenOver {
  background-color: #f90;
}
<p class="test">Testing</p>
<div>No classes here</div>
<ul>
  <li class="test">Something in a 'test' element</li>
</ul>

这可以通过增加指定类名的选择器特异性来解决:

li.test {
  background-color: fuchsia;
}

html body .whenOver {
  background-color: #f90;
}

Object.prototype.classHighlight = function(over = 'over') {

  const that = [...this],

    toggleHighlight = (event) => {
      that.forEach(
        (el) => el.classList.toggle(over, event.type === 'mouseenter')
      );
    };
  that.forEach(
    (element) => {
      element.addEventListener('mouseenter', toggleHighlight);
      element.addEventListener('mouseleave', toggleHighlight);
    });
};

document.getElementsByClassName('test').classHighlight('whenOver');
li.test {
  background-color: fuchsia;
}

html body .whenOver {
  background-color: #f90;
}
<p class="test">Testing</p>
<div>No classes here</div>
<ul>
  <li class="test">Something in a 'test' element</li>
</ul>

或者,您可以改为使用!important关键字来强制!important应用该 -ified 属性,而不管具体性如何(除非另一个规则也使用!important并且本身更具体),例如:

/* Note the ridiculous and overly-specific selector: */
html > body > ul > li.test {
  background-color: fuchsia;
}

.whenOver {
  / and here, as the demo shows, !important still
    wins: */
  background-color: #f90 !important;
}

Object.prototype.classHighlight = function(over = 'over') {

  const that = [...this],

    toggleHighlight = (event) => {
      that.forEach(
        (el) => el.classList.toggle(over, event.type === 'mouseenter')
      );
    };
  that.forEach(
    (element) => {
      element.addEventListener('mouseenter', toggleHighlight);
      element.addEventListener('mouseleave', toggleHighlight);
    });
};

document.getElementsByClassName('test').classHighlight('whenOver');
html > body > ul > li.test {
  background-color: fuchsia;
}

.whenOver {
  background-color: #f90 !important;
}
<p class="test">Testing</p>
<div>No classes here</div>
<ul>
  <li class="test">Something in a 'test' element</li>
</ul>

但是,当涉及到!important时,请尽量避免使用它,因为正如 MDN 所指出的:

但是,使用!important是不好的做法,应该避免使用,因为它会破坏样式表中的自然 [级联],从而使调试变得更加困难。

例外” !important MDN

参考:

于 2013-04-12T15:52:24.770 回答
0

这是一个零依赖解决方案,应该适用于非常旧的 JS 版本:

  1. 添加class = 'grp_N hovergrp'到应在悬停时突出显示的所有元素,替换N为唯一描述一组元素的数字(或 id)。这些组可能不相交,每个具有hovergrp类的元素都应该属于一个grp_N类。

  2. 将以下JS代码段附加<script>...</script>到您的末尾<html>

  // collect all highlighted elements and group them by their group 
  // name for faster access;
  // Attach onmouseover and onmouseout listeners.
  var groups = {};
  var hovergrp = document.getElementsByClassName("hovergrp"); 
  for (var i = 0; i < hovergrp.length; i++) {
    var e = hovergrp.item(i);
    var eClasses = e.classList;
    for (var j = 0; j < eClasses.length; j++) {
      var c = eClasses[j];
      if (c.startsWith("grp_")) {
        if (!groups[c]) {
          groups[c] = [];
        }
        groups[c].push(e);
        e.onmouseover = (function(c_capture) {
          return function(_event) {
            highlightGroup(c_capture, "orange");
          };
        })(c);
        e.onmouseout = (function(c_capture) {
          return function(_event) {
            highlightGroup(c_capture, "transparent");
          };
        })(c);
        break;
      }
    }
  }
  
  function highlightGroup(groupName, color) {
    var g = groups[groupName];
    for (var i = 0; i < g.length; i++) {
      g[i].style.backgroundColor = color;
    }
  }
  <pre><code>
    // hover over variable names `<span class='grp_0 hovergrp'>x</span>` and `<span class='grp_1 hovergrp'>f</span>`
    kroneckerDelta(<span class='grp_0 hovergrp'>x</span>) {
      return function(<span class='grp_1 hovergrp'>f</span>) {
        <span class='grp_1 hovergrp'>f</span>(<span class='grp_0 hovergrp'>x</span>)
      }
    }
  </code></pre>

<p class = "grp_p1 hovergrp">This should be highlighted on mouseover</p>
<p class = "grp_p2 hovergrp">This should be highlighted on mouseover</p>
<p class = "grp_p1 hovergrp">This should be highlighted on mouseover</p>
<p class = "grp_p2 hovergrp">This should be highlighted on mouseover</p>

HTML 片段显示了使用示例:<pre>带有变量的小格式代码片段被分为两组。每当您将鼠标悬停在变量上时,该变量的所有用法以及绑定站点都会突出显示。

于 2018-11-08T20:07:55.020 回答