В Javascript есть методы для имитации взаимодействия с пользователем, такие как .click(), .focus(), .blur(). Но нет .hover(). Может ли JS имитировать наведение/наведение мыши?

Javascript позволяет моделировать взаимодействие с пользователем.

Любой сценарий может имитировать взаимодействие пользователя, например click или focus, с определенным элементом на странице, используя методы .click() и .focus().

Пример:

const square = document.getElementsByClassName('square')[0];

const clickSquare = () => {

  event.target.dataset.receivedAction = 'click';
  event.target.innerHTML = '<p>I\'ve been clicked!</p>';
}

const clearSquare = () => {

  square.removeAttribute('data-received-action');
  square.innerHTML = '';
}

square.addEventListener('click', clickSquare, false);

const clickButton = document.querySelector('[data-deliver-action="click"]');
const clearButton = document.querySelector('[data-deliver-action="clear"]');

clickButton.addEventListener('click', () => square.click(), false);
clearButton.addEventListener('click', clearSquare, false);
.square {
display: block;
width: 120px;
height: 120px;
margin: 12px 6px;
text-align: center;
font-family: arial, helvetica, sans-serif;
font-weight: bold;
font-size: 14px;
text-transform: uppercase;
overflow: hidden;
cursor: pointer;
}

button {
display: block;
width: 160px;
margin: 6px;
cursor: pointer;
}

.square {
color: rgb(255, 0, 0);
background-color: rgb(255, 0, 0);
}

.square[data-received-action="click"] {
background-color: rgb(255, 255, 0);
}
<div class="square" tabindex="0"></div>

<button type="button" data-deliver-action="click">Click the Square</button>
<button type="button" data-deliver-action="clear">Clear Square</button>

Квадрат выше прослушивает click event. Мы можем либо щелкнуть по квадрату напрямую, либо нажать кнопку Click the Square, которая затем щелкнет по самому квадрату с помощью метода .click().

Любое действие приводит к тому, что квадрат получает событие click.

Но это возможно только потому, что метод .click() существует.

Также был бы полезен метод .hover() (или даже .mouseover()), но его не существует.

Можно ли вычислительно смоделировать зависание (или наведение мыши) при отсутствии этих методов?


person Rounin    schedule 02.11.2019    source источник
comment
Возможный дубликат: Чистая замена JavaScript для :hover   -  person Dexygen    schedule 03.11.2019
comment
@GeorgeJempty Это не имеет ничего общего с тем, о чем здесь спрашивают.   -  person Scott Marcus    schedule 03.11.2019
comment
Тогда поверь мне, где-то есть дубликат, по крайней мере, я ищу его.   -  person Dexygen    schedule 03.11.2019
comment
@GeorgeJempty Как насчет потрясающего ответа ниже?   -  person Scott Marcus    schedule 03.11.2019
comment
Конечно, вы можете запускать обработчики событий mouseover с помощью dispatchEvent, но невозможно имитировать реальное наведение курсора, вызванное пользователем.   -  person Bergi    schedule 03.11.2019
comment
Приведенный выше вопрос не является дубликатом вопроса, указанного в дублирующем уведомлении. Последний вопрос касается псевдокласса CSS :hover - этот вопрос связан с компьютерным моделированием взаимодействия человека с пользователем.   -  person Rounin    schedule 03.11.2019


Ответы (1)


Похоже, что это не широко документировано в Интернете, но можно с помощью вычислений смоделировать человека, перемещающего указатель мыши над элементом, таким же образом, как element.click() имитирует человека щелчок по элементу.

Правильный подход заключается в использовании:

eventTarget.dispatchEvent(event)

в сочетании с нативным JS event.

Большинство ссылок на dispatchEvent() связаны с написанным пользователем событием, но, повторяю, можно использовать JS-native event — в данном случае mouseover.

Итак... вместо следующего, используя метод .click():

clickButton.addEventListener('click', () => square.click(), false);

Мы можем развернуть:

clickButton.addEventListener('click', () => {

  let hover = new Event('mouseover');
  square.dispatchEvent(hover);

}, false);

Рабочий пример:

const square = document.getElementsByClassName('square')[0];

const clickSquare = () => {

  event.target.dataset.receivedAction = 'click';
  event.target.innerHTML = '<p>I\'ve been clicked!</p>';
}

const hoverSquare = () => {

  event.target.dataset.receivedAction = 'hover';
  event.target.innerHTML = '<p>I\'ve been hovered over!</p>';
}

const clearSquare = () => {

  square.removeAttribute('data-received-action');
  square.innerHTML = '';
}

square.addEventListener('mouseover', hoverSquare, false);
square.addEventListener('click', clickSquare, false);

const clickButton = document.querySelector('[data-deliver-action="click"]');
const hoverButton = document.querySelector('[data-deliver-action="hover"]');
const clearButton = document.querySelector('[data-deliver-action="clear"]');

clickButton.addEventListener('click', () => square.click(), false);

hoverButton.addEventListener('click', () => {

  let hover = new Event('mouseover');
  square.dispatchEvent(hover);

}, false);

clearButton.addEventListener('click', clearSquare, false);
.square {
display: block;
width: 120px;
height: 120px;
margin: 12px 6px;
text-align: center;
font-family: arial, helvetica, sans-serif;
font-weight: bold;
font-size: 14px;
text-transform: uppercase;
overflow: hidden;
cursor: pointer;
}

button {
display: block;
width: 160px;
margin: 6px;
cursor: pointer;
}

.square {
color: rgb(255, 0, 0);
background-color: rgb(255, 0, 0);
}

.square[data-received-action="click"] {
background-color: rgb(255, 255, 0);
}

.square[data-received-action="hover"] {
color: rgb(255, 255, 255);
background-color: rgb(255, 125, 0);
}
<div class="square" tabindex="0"></div>

<button type="button" data-deliver-action="click">Click the Square</button>
<button type="button" data-deliver-action="hover">Hover over the Square</button>
<button type="button" data-deliver-action="clear">Clear Square</button>

person Rounin    schedule 02.11.2019
comment
Этот ответ объединяет две непохожие вещи: onmouseover != :hover. Он ничего не имитирует, он просто делает обычные вещи. - person Caleb; 04.11.2019
comment
Этот вопрос не имеет ничего общего с CSS. Дело не в :hover. Я обращаюсь к тому, как javascript может имитировать пользователя-человека, расположенного указателем мыши над элементом, таким же образом, как .click() имитирует пользователя-человека, щелкающего по элементу. - person Rounin; 04.11.2019
comment
Мое использование глагола hover сбивает вас с толку псевдоклассом CSS :hover? Если это так, я буду рад изменить глагол на другой, например указатель-касание. - person Rounin; 04.11.2019
comment
Я не путаю это с CSS. Вы можете не использовать CSS и :hover. Та же проблема все еще актуальна, вы смешиваете .hover() с .onmouseover(), один из которых может быть запущен вручную, а другой нет. Это ничего не имитирует, это просто одна из двух вещей, которые вообще можно сделать. - person Caleb; 04.11.2019
comment
Сначала вы пишете: Этот ответ объединяет две непохожие вещи: onmouseover != :hover. Затем, когда я ответил Этот вопрос не имеет ничего общего с CSS, вы написали Вы можете не использовать CSS и :hover. Какой :hover вы имели в виду в первый раз, если не CSS :hover? - person Rounin; 04.11.2019
comment
Re: Это ничего не имитирует. Мы все видим, что это так. Подобно тому, как element.click() вычислительно имитирует человека, щелкающего по элементу, этот метод вычислительно имитирует человека, наводящего указатель на элемент. - person Rounin; 04.11.2019
comment
Соединение A→C и B→C таким образом, что любой метод триггера вызывает выполнение одной и той же функции, отличается от того, что A запускает B. Это различие (и тот факт, что существуют веские причины не чтобы вызвать B чем-либо, кроме фактического B), в этом ответе скрывается, я думаю, за счет людей, имеющих четкое понимание фактических ограничений, с которыми они работают. - person Caleb; 05.11.2019
comment
Вы цените такие методы, как .click(), .focus() и .blur()? Если да, то вы наверняка видите достоинства метода .pointertouch()? Я бы сказал, что есть большая польза в возможности вычислительного выполнения действий мыши, которые обычно выполняются пользователем. Я не уверен, согласны вы с этим или нет. - person Rounin; 05.11.2019