5

I was trying to use querySelector to find active elements in a page. I assumed that a handler bound to a mousedown event on the document would trigger after the event had bubbled its way back from the target, which means the :active pseudoclass should already be applied.

document.addEventListener("mousedown",function(e){

    console.log(document.querySelector("*:active"));// logs null

    // expected value was the target of the mousedown event, that is,
    console.log(e.target);

});

My question is: at what point exactly does the the :active pseudo-class apply? Note that when I log the value, the mousedown event has already triggered on the target.

See http://jsfiddle.net/tK67w/2/ for an example. An interesting thing to note here is that if you set a breakpoint within the handler, you can see the css rule I defined for a:active already applying, although querySelector is returning null

EDIT:

Credit goes to TJ for coming up with a much better demonstration. The problem still stands though: in browsers other than IE and Chrome, how can I get an HTMLCollection of all active elements as they become active?

4

2 回答 2

2

我相信问题在于,当您使用querySelector时,您只会获得第一个活动元素。但是你的锚在树的下方更远。

更新:有趣的是,我没有使用 Firefox 或 Opera,但我使用的是 Chrome。以下是 Chrome 结果。请参阅下面的更多内容。

考虑(实时副本):

document.addEventListener("mousedown", handler, false);
function handler(e){
    console.log(
        "event " + e.type + ": " +
        Array.prototype.join.call(document.querySelectorAll("*:active")));
}​

当我单击锚点时,我会在控制台中看到:

事件 mousedown: [object HTMLHtmlElement],[object HTMLBodyElement],[object HTMLDivElement],http://fiddle.jshell.net/_display/#

请注意末尾的 URL,这是实例的默认toString值,由.HTMLAnchroElementjoin

由于querySelectorAll需要按文档顺序返回元素,因此如果您想要最具体的活动元素,您将使用最后一个。示例(实时副本):

(function() {
    document.addEventListener("mousedown",handler, false);

    function handler(e){
        var active = document.querySelectorAll("*:active");
        var specific = active && active.length && active[active.length-1];
        display("Most specific active element: " +
                (specific ? specific.tagName : "(none)"));
    }

    function display(msg) {
        var p = document.createElement('p');
        p.innerHTML = String(msg);
        document.body.appendChild(p);
    }
})();
​

在我的情况下(使用 Chrome),我看到了最具体元素的标签名称(如果我单击链接,则为锚点等)。


似乎 Chrome 正在遵循规范,而 Firefox 和 Opera 却没有。从CSS3 选择器规范的第 6.6.1.2 节:

:active伪类在用户激活元素时应用。例如,在用户按下鼠标按钮并释放它的时间之间。

因此,在我看来,这:active应该适用于上述情况。如果我们使用这个 CSS,这个断言就会被备份:

*:active {
    background-color: red;
}

...使用此 JavaScript:

(function() {
    document.addEventListener("mousedown", mouseDown, false);
    document.addEventListener("mouseup", mouseUp, false);

    function mouseDown(){
        var active = document.querySelectorAll("*:active");
        var specific = active && active.length && active[active.length-1];
        display("Mouse down: Most specific active element: " +
                (specific ? specific.tagName : "(none)"));
    }

    function mouseUp() {
        display("Mouse up");
    }

    function display(msg) {
        var p = document.createElement('p');
        p.innerHTML = String(msg);
        document.body.appendChild(p);
    }
})();

实时复制

在我尝试过的所有三种浏览器(Chrome、Firefox、Opera)中,当鼠标按下时元素会变成红色背景,当我释放它时又会变成白色;但mousedown处理程序在 Firefox 或 Opera 中看不到该:active元素,只有 Chrome。

但我不是 CSS 规范律师。:-)

于 2012-11-10T13:58:08.467 回答
0

似乎是在帧被渲染之后设置的,或者可能是在当前执行队列之后设置的,至少 Firefox 是这样。

立即使用得到结果setTimeoutrequestAnimationFrame也可以使用):

document.addEventListener('mousedown', e => {

  setTimeout(_ => console.log(document.querySelectorAll(':active')));

});
于 2019-03-02T21:53:23.653 回答