Event Listener on a CSS Pseudo-Element, Such as ::After and ::Before

Event listener on a CSS pseudo-element, such as ::after and ::before?

No. The pseudo-element does not exist in the DOM so it has no HTMLElementNode object representing it.

Only detect click event on pseudo-element

This is not possible; pseudo-elements are not part of the DOM at all so you can't bind any events directly to them, you can only bind to their parent elements.

If you must have a click handler on the red region only, you have to make a child element, like a span, place it right after the opening <p> tag, apply styles to p span instead of p:before, and bind to it.

Is it possible to detect a click of an :after or :before pseudo element with jQuery?

Maybe. Depending on how you structure your pseudo content you would have to rely on calculating mouse position for clicks on the actual div. The event handlers would all go on the div, and not the pseudo element because it doesn't exist in the DOM.

See Manipulating CSS :before and :after pseudo-elements using jQuery
for some more info. Especially BoltClock's answer.

Also see Felix's comment for another possible solution without mouse position: Only detect click event on pseudo-element

Add onclick with css pseudo-element after

Is it possible in my css file to do something like [see code above]?

No

The important question to ask is why.

HTML has control of the data within the webpage. Any CSS or JS is specified via the HTML. It's the Model.

CSS has control of the styles, there is no link between CSS and HTML or JavaScript. It's the View.

JavaScript has control of the interactions within the webpage, and has hooks to any and all DOM nodes. It's the Controller.

Because of this MVC structure: HTML belongs in .html files, CSS belongs in .css files, and JS belongs in .js files.

CSS pseudo-elements do not create DOM nodes. There is no direct way for JavaScript to access a pseudo-element defined in CSS, and there's no way to attach an event to said pseudo-elements.

If you've got a set structure in place, and can't add the additional content necessary to produce new links within the HTML, JavaScript can dynamically add the new elements necessary which can then be styled via CSS.

jQuery makes this very simple:

$('<span class="click-me">click me</span>').appendTo('.myclass').click(my_function);

To anonymous element add pseudo element and cursor style and event listeners

It doesn't seem like these nested, anonymous xul:image nodes support (::before) pseudo-elements at all. Or maybe it is because the toolbarbutton binding is display="xul:button"... Somewhere deep inside the layout engine the parent element outright refused to adopt the generated ::before pseudo-element, my debugger says. Remember that XUL != HTML.

However, you can bind and/or rebind stuff to a new binding.

I used this CSS to re-bind and style the sync button (analog to your example from the question comments, but not meant to be a pixel-perfect reproduction):

#PanelUI-fxa-status {
-moz-binding: url(toolbarbutton.xml#toolbarbutton);
}
#PanelUI-fxa-status .toolbarbutton-badge {
list-style-image: url(chrome://browser/skin/places/query.png);
transform: translate(8px,8px) scale(0.7);
border: 1px solid red;
}

And the new binding, based on the default binding:

<?xml version="1.0"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->

<bindings
xmlns="http://www.mozilla.org/xbl"
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:xbl="http://www.mozilla.org/xbl">

<binding id="toolbarbutton" display="xul:button" role="xul:toolbarbutton"
extends="chrome://global/content/bindings/button.xml#button-base">
<resources>
<stylesheet src="chrome://global/skin/toolbarbutton.css"/>
</resources>

<content>
<children includes="observes|template|menupopup|panel|tooltip"/>
<xul:stack>
<xul:image class="toolbarbutton-icon" xbl:inherits="validate,src=bage,label"/>
<xul:image class="toolbarbutton-badge" xbl:inherits="validate,src=image,label"/>
</xul:stack>
<xul:label class="toolbarbutton-text" crop="right" flex="1"
xbl:inherits="value=label,accesskey,crop,wrap"/>
<xul:label class="toolbarbutton-multiline-text" flex="1"
xbl:inherits="xbl:text=label,accesskey,wrap"/>
</content>
</binding>
</bindings>

You could either set the badge with CSS, as I did, or using <toolbarbutton ... badge="{url}"/> (i.e. the src=badge inheritance in the binding).

Regarding the addEventListener/cursor stuff: It is not quite clear here what exactly you are asking for?

You can use all the usual methods with the toolbar button (addEventListener, command=/oncommand=, ...), but not with child elements of it.

You can use cursor: styles with the toolbarbutton, but not with child elements of it.

Both are due to display="xul:button" in the binding. If you don't want that, you'll need to modify the binding not to use a display= and fix any stuff that breaks.

JQuery select pseudo-element :after

It's not possible to bind directly to pseudo-elements, since those are not part of the DOM, but the desired effect can be approximated by binding to a parent element and testing for an offset related to the element that the :after acts upon:

The following renders as ELEMENT++, where clicking on "ELEMENT" and "++" each triggers different behavior:

<span>ELEMENT</span>
span::after {
content: '++';
position: absolute;
}

span.c1 {
background: yellow;
}

span.c2::after {
background: orange;
}
const span = document.querySelector('span');

span.addEventListener('click', function (e) {
if (e.offsetX > span.offsetWidth) {
span.className = 'c2';
} else {
span.className = 'c1';
}
});

Interactive: http://jsfiddle.net/wC2p7/1/

jQuery event listener fires before selector applied

@icecub answer as snippet:

$(document).ready(function() {
$(".unarmed").css("filter", "grayscale(1)");
$(".unarmed").click(function(e) {
if ($(this).hasClass("armed")) {
console.log("boom");
}
$(this).css("filter", "").removeClass("unarmed").addClass("armed");
}).mouseout(function() {
$(this).css("filter", "grayscale(1)").removeClass("armed").addClass("unarmed");
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<img class="unwait unarmed" src="https://kns.im/include/img/plus.png" style="width:50px">


Related Topics



Leave a reply



Submit