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?
I believe the issue is that as you're using querySelector
, you're only getting the first active element. But your anchor is much further down the tree.
Update: Interesting, I'm not getting anything with Firefox or Opera, but I am with Chrome. The below are Chrome results. See more on that below.
Consider (live copy):
document.addEventListener("mousedown", handler, false);
function handler(e){
console.log(
"event " + e.type + ": " +
Array.prototype.join.call(document.querySelectorAll("*:active")));
}
When I click the anchor, I see this in the console:
event mousedown: [object HTMLHtmlElement],[object HTMLBodyElement],[object HTMLDivElement],http://fiddle.jshell.net/_display/#
Note the URL at the end, which is the default toString
for HTMLAnchroElement
instances, which is triggered by the join
.
Since querySelectorAll
is required to return the elements in document order, if you want the most specific active element, you'd use the last one. Example (live copy):
(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);
}
})();
In my case (using Chrome), I see the tag name of the most specific element (the anchor if I click the link, etc.).
It seems like Chrome is following the spec and taht Firefox and Opera are not. From Section 6.6.1.2 of the CSS3 Selectors spec:
The
:active
pseudo-class applies while an element is being activated by the user. For example, between the times the user presses the mouse button and releases it.
It seems to me that :active
should therefore apply in the above. This assertion is backed up if we use this CSS:
*:active {
background-color: red;
}
...with this 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);
}
})();
Live Copy
With all three browsers I tried (Chrome, Firefox, Opera), the element gets a red background while the mouse is down, and goes white again when I release it; but the mousedown
handler doesn't see the :active
element in Firefox or Opera, just Chrome.
But I'm not a CSS specification lawyer. :-)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With