Сегодня мне захотелось построить что-то очень простое. Элемент, который можно закрыть с помощью маленькой кнопки, всплывающей при наведении курсора мыши. Однако кнопка не должна находиться в HTML/DOM, поэтому вместо нее я использовал псевдоэлемент ::after. Эта часть до сих пор была довольно простой.

Я подготовил пример в CodePen. Это очень простой код, который позволяет элементу ::after с символом x появляться в элементе .dismissable, когда он :hovered.



CodePen Embed — Кликабельный псевдоэлемент
Настройка для понимания того, с чем мы имеем делоcodepen.io



Теперь самое сложное — сделать его кликабельным. На самом деле вы не можете выбрать псевдоэлемент, и он также не отображается в событии щелчка при прослушивании события щелчка на .dismissable.

Естественно, я обратился к Интернету и наткнулся на именно тот вопрос, который у меня был: jquery обнаружить :: после события щелчка селектора CSS.» Этот вопрос является ярким примером того, насколько на самом деле плох SO, и ситуация меня сильно угнетает до такой степени, что я больше не задаю никаких вопросов. Вопрос был закрыт как дубликат, хотя упомянутый вопрос совершенно другой.

Ни исходный вопрос, ни вопрос, на который есть ссылка, не имели ответов, которые могли бы решить мою проблему. Мне по-прежнему нравились и исходный вопрос, и единственный ответ, поскольку они могли быть ценны для других, и я хотел показать этим людям немного любви к их времени и усилиям.

Обнаружение того, что псевдоэлемент был нажат

Итак, теперь давайте перейдем к делу. Основная идея представляет собой смесь двух идей.

  1. Получите атрибуты псевдоэлемента с помощью getComputedStyle
  2. Проверьте положение мыши относительно псевдоэлемента

Мы можем получить стиль псевдоэлементов с помощью getComputedStyle(elem, ":after"), это чрезвычайно полезно в нашей ситуации.

Затем с помощью .getPropertyValue мы можем получить вычисленные значения top, height, left и width, которые позволяют нам ограничить псевдоэлемент. Важно отметить, что вычисленные значения представляют собой просто строки, имеющие вид {num}px. Чтобы получить только число, мы отсекаем два последних символа, а затем анализируем строки как Numbers.

Мы получаем положение мыши относительно .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 и получайте удовольствие:



Выписка,

Рашид Харви