javascript - Solo detectar evento de clic en pseudo-elemento
Por favor, vea este fiddle: http://jsfiddle.net/ZWw3Z/5/
Mi código es:
p {
position: relative;
background-color: blue;
}
p:before {
content: '';
position: absolute;
left:100%;
width: 10px;
height: 100%;
background-color: red;
} <p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate...</p>Me gustaría activar un evento de clic solo en el pseudo-elemento (la parte roja). Es decir, no quiero que el evento de clic se active en la parte azul.
Respuesta #1
Esto no es posible; Los pseudo-elementos no forman parte del DOM, así que no puedes vincular ningún evento directamente a ellos, solo puedes vincularlos a sus elementos padres.
Si debes tener un manejador de clics únicamente en la región roja, tienes que crear un elemento hijo, como un span, colocarlo justo después de la etiqueta de apertura <p>, aplicar estilos a p span en lugar de p:before, y enlazarlo a él.
Respuesta #2
De hecho, es posible mientras tu contenido ::before o ::after no esté posicionado de manera que se superponga con el elemento mismo, mirando la coordenada de la página del evento.
Este ejemplo solo verifica el elemento a la derecha, pero eso debería funcionar en tu caso (en el caso general probablemente quieras trabajar con .getBoundingClientRect() en su lugar).
const span = document.querySelector('span');
span.addEventListener('click', function(e) {
if (e.offsetX > span.offsetWidth) {
span.className = 'c2';
} else {
span.className = 'c1';
}
});div {
margin: 20px;
}
span {
cursor: pointer;
}
span:after {
content: 'AFTER';
position: absolute;
}
span.c1 {
background: yellow;
}
span.c2:after {
background: yellow;
}<div><span>ELEMENT</span></div>JSFiddle
Respuesta #3
En navegadores modernos puedes probar con la propiedad css de pointer-events (pero eso hace imposible detectar eventos del ratón en el nodo padre):
p {
position: relative;
background-color: blue;
color:#ffffff;
padding:0px 10px;
pointer-events:none;
}
p::before {
content: attr(data-before);
margin-left:-10px;
margin-right:10px;
position: relative;
background-color: red;
padding:0px 10px;
pointer-events:auto;
}
Cuando el objetivo del evento es tu elemento "p", sabes que es tu "p:before".
Si aún necesitas detectar eventos del ratón en el párrafo principal, puedes considerar la posibilidad de modificar tu estructura HTML. Puedes agregar una etiqueta span y el siguiente estilo:
p span {
background:#393;
padding:0px 10px;
pointer-events:auto;
}
Los objetivos del evento ahora son tanto los elementos "span" como "p:before".
Ejemplo sin jquery: http://jsfiddle.net/2nsptvcu/
Ejemplo con jquery: http://jsfiddle.net/0vygmnnb/
Aquí está la lista de navegadores que soportan pointer-events: http://caniuse.com/#feat=pointer-events
Respuesta #4
Respuesta breve:
Lo hice. Escribí una función para uso dinámico para todos los pequeños que hay ahí fuera...
Ejemplo funcional que se muestra en la página
Ejemplo funcional registrando en la consola
Respuesta larga:
...Aun así lo hice.
Me costó un tiempo hacerlo, ya que un elemento pseudo no está realmente en la página. Aunque algunas de las respuestas anteriores funcionan en ALGUNOS escenarios, TODAS fallan en ser dinámicas y funcionar en un escenario en el que un elemento es inesperado tanto en tamaño como en posición (como elementos en posición absoluta que se superponen a una parte del elemento padre). El mío no.
Uso:
//some element selector and a click event...plain js works here too
$("div").click(function() {
//returns an object {before: true/false, after: true/false}
psuedoClick(this);
//returns true/false
psuedoClick(this).before;
//returns true/false
psuedoClick(this).after;
});
Cómo funciona:
Obtiene la altura, el ancho, la posición superior y la posición izquierda (basadas en la distancia desde el borde de la ventana) del elemento padre y obtiene la altura, el ancho, la posición superior y la posición izquierda (basadas en el borde del contenedor padre) y compara esos valores para determinar dónde está el pseudoelemento en la pantalla.
Luego compara dónde está el ratón. Mientras el ratón esté en el rango de la variable recién creada, entonces devuelve verdadero.
Nota:
Es prudente hacer que el elemento padre tenga posición RELATIVA. Si tienes un pseudoelemento con posición absoluta, esta función solo funcionará si está posicionado según las dimensiones del padre (así que el padre tiene que ser relativo... tal vez sticky o fixed también funcionarían... no lo sé).
Código:
function psuedoClick(parentElem) {
var beforeClicked,
afterClicked;
var parentLeft = parseInt(parentElem.getBoundingClientRect().left, 10),
parentTop = parseInt(parentElem.getBoundingClientRect().top, 10);
var parentWidth = parseInt(window.getComputedStyle(parentElem).width, 10),
parentHeight = parseInt(window.getComputedStyle(parentElem).height, 10);
var before = window.getComputedStyle(parentElem, ':before');
var beforeStart = parentLeft + (parseInt(before.getPropertyValue("left"), 10)),
beforeEnd = beforeStart + parseInt(before.width, 10);
var beforeYStart = parentTop + (parseInt(before.getPropertyValue("top"), 10)),
beforeYEnd = beforeYStart + parseInt(before.height, 10);
var after = window.getComputedStyle(parentElem, ':after');
var afterStart = parentLeft + (parseInt(after.getPropertyValue("left"), 10)),
afterEnd = afterStart + parseInt(after.width, 10);
var afterYStart = parentTop + (parseInt(after.getPropertyValue("top"), 10)),
afterYEnd = afterYStart + parseInt(after.height, 10);
var mouseX = event.clientX,
mouseY = event.clientY;
beforeClicked = (mouseX >= beforeStart && mouseX <= beforeEnd && mouseY >= beforeYStart && mouseY <= beforeYEnd ? true : false);
afterClicked = (mouseX >= afterStart && mouseX <= afterEnd && mouseY >= afterYStart && mouseY <= afterYEnd ? true : false);
return {
"before" : beforeClicked,
"after" : afterClicked
};
}
Soporte:
No sé... parece que IE es tonto y le gusta devolver 'auto' como un valor calculado a veces. PARECE FUNCIONAR BIEN EN TODOS LOS NAVEGADORES SI LAS DIMENSIONES SE ESTABLECEN EN CSS. Entonces... establece tu altura y ancho en tus elementos pseudo y muévelos solo con top y left. Recomiendo usarlo en cosas con las que estés bien si no funciona. Como una animación o algo así. Chrome funciona... como de costumbre.
