如何选择具有以下内容的HTML DOM元素:hover子类?

时间:2017-03-05 12:07:39

标签: javascript html css html5 css3

CSS

p:hover { ... }
div { ... }
.something { ... }
#content a:hover { ... }

HTML

<div id="content">
    <p>
        <a href="#">Test</a>
    </p>
</div>

我需要选择所有在CSS中定义了:hover子类的元素。对于此示例,它将是<p><a>元素。

是否可以在JavaScript中执行此操作?

2 个答案:

答案 0 :(得分:0)

有一组函数,即所谓的“选择器api”https://developer.mozilla.org/en/docs/Web/API/Document/querySelectorhttps://developer.mozilla.org/en/docs/Web/API/Document/querySelectorAll等。但是,几乎唯一不能用这些函数做的就是选择伪类(例如:hover)。

我担心您将需要监控鼠标悬停和鼠标移动事件,并将当前悬停的元素存储在单独的变量中。通过使用其parentNode属性(及其父级的parentNode属性),您将可以访问父链。

我会建议这样的事情:

var hoveredElement = null;
document.addEventListener( "mouseover", function(e){
    hoveredElement = e.target;
});

答案 1 :(得分:0)

起初我不认为这是可能的,但经过一番思考后,我想出了这个。我用ES2015语法编写了它,因为有一些东西(比如在非数组上使用forEach)更容易使用它,但如果需要它也可以用ES5语法编写。

let getElementsWithHoverRule = () => {
  let getSelectors = rule => {
  // get everything upto the first curly bracket 
  let selectorText = rule.cssText.match(/^[^{]+/)[0];

  // in case a rule has multiple selectors,
  // we will want to filter them separately
  // so we don't capture elements that share
  // styling but have different selectors
  return selectorText.split(',');
},
selectors = [],
rxHover = /:hover/;

  // loop through all the style sheets
  [...document.styleSheets].forEach(sheet => {
// and all of the rules in those style sheets
let rules = sheet.cssRules || sheet.rules;
if (rules !== null) {
  [...rules].forEach(rule => {
    let ruleSelectors = getSelectors(rule);
    selectors = selectors.concat(ruleSelectors);
  });
}
  });

  // find all of the rules that contain hover
  selectors = selectors.filter(selector => rxHover.test(selector));

  // remove the :hover from the selectors so we can select them without the user
  // hovering their mouse over them
  selectors = selectors.map(selector => selector.replace(rxHover, ''))

  return document.querySelectorAll(selectors.join(', '));
};

let hoverElement = getElementsWithHoverRule();
console.log(hoverElement);
// put red box around matched elements when the page is clicked
document.addEventListener('click', () => {
  [...hoverElement].forEach(el => el.style.border = '5px outset #f00');
}, false);
p:hover { background: #eef }
span, a:hover { background: #000; color: #fff; }
div { color: #000; }
.something { color: #00f }
#content a:hover { color: #ff0 }
<div id="content">
    <p>
        <a href="#">Test</a> non-link text
    </p>
</div>

<p>another <span>paragraph</span>. <a href="#">A link that is not inside of content</a></p>
<br>
<br>
<br>

它的作用是使用document.styleSheets获取所有样式表的列表,然后循环遍历它们中提取其选择器的所有规则。然后,它会过滤掉不包含:hover的规则,然后从执行的规则中删除悬停并使用这些新规则来选择元素。

修改

在原始代码中,如果规则有多个选择器,例如.foo, #bar:hover,则会同时返回.foo#bar。我已更新代码,因此它只会返回#bar,因为这是包含:hover的规则的唯一选择器