Сегодня мне захотелось построить что-то очень простое. Элемент, который можно закрыть с помощью маленькой кнопки, всплывающей при наведении курсора мыши. Однако кнопка не должна находиться в HTML/DOM, поэтому вместо нее я использовал псевдоэлемент ::after
. Эта часть до сих пор была довольно простой.
Я подготовил пример в CodePen. Это очень простой код, который позволяет элементу ::after
с символом x появляться в элементе .dismissable
, когда он :hover
ed.
Теперь самое сложное — сделать его кликабельным. На самом деле вы не можете выбрать псевдоэлемент, и он также не отображается в событии щелчка при прослушивании события щелчка на .dismissable
.
Естественно, я обратился к Интернету и наткнулся на именно тот вопрос, который у меня был: jquery обнаружить :: после события щелчка селектора CSS.» Этот вопрос является ярким примером того, насколько на самом деле плох SO, и ситуация меня сильно угнетает до такой степени, что я больше не задаю никаких вопросов. Вопрос был закрыт как дубликат, хотя упомянутый вопрос совершенно другой.
Ни исходный вопрос, ни вопрос, на который есть ссылка, не имели ответов, которые могли бы решить мою проблему. Мне по-прежнему нравились и исходный вопрос, и единственный ответ, поскольку они могли быть ценны для других, и я хотел показать этим людям немного любви к их времени и усилиям.
Обнаружение того, что псевдоэлемент был нажат
Итак, теперь давайте перейдем к делу. Основная идея представляет собой смесь двух идей.
- Получите атрибуты псевдоэлемента с помощью
getComputedStyle
- Проверьте положение мыши относительно псевдоэлемента
Мы можем получить стиль псевдоэлементов с помощью getComputedStyle(elem, ":after")
, это чрезвычайно полезно в нашей ситуации.
Затем с помощью .getPropertyValue
мы можем получить вычисленные значения top
, height
, left
и width
, которые позволяют нам ограничить псевдоэлемент. Важно отметить, что вычисленные значения представляют собой просто строки, имеющие вид {num}px
. Чтобы получить только число, мы отсекаем два последних символа, а затем анализируем строки как Number
s.
Мы получаем положение мыши относительно .dismissable
, обращаясь к атрибутам layerX
и layerY
.
Последний шаг — простая проверка границ. Если это удастся, мы сможем делать все, что пожелаем. В данном случае я заставил .dismissable
просто исчезнуть, установив для его атрибута display значение "none"
, но обычно вам может потребоваться делать и другие вещи.
const handler = (e)=>{ // First we get the pseudo-elements style const target = e.currentTarget || e.target const after = getComputedStyle(target, ":after") if (after) { // Then we parse out the dimensions const atop = Number(after.getPropertyValue("top").slice(0, -2)) const aheight = Number(after.getPropertyValue("height").slice(0, -2)) const aleft = Number(after.getPropertyValue("left").slice(0, -2)) const awidth = Number(after.getPropertyValue("width").slice(0, -2)) // And get the mouse position const ex = e.layerX const ey = e.layerY // Finally we do a bounds check (Is the mouse inside of the after element) if (ex > aleft && ex < aleft+awidth && ey > atop && ey < atop+aheight) { console.log("Button clicked") target.style.display = "none" } } }
Опять же, попробуйте это в CodePen и получайте удовольствие:
Выписка,
Рашид Харви