Обработка события JavaScript mouseup вне элемента | by MelkorNemesis
Недавно я работал над личным проектом «Умный дом» / «IoT» и столкнулся с проблемой, с которой, я думаю, могут столкнуться и многие другие люди. В другой форме или форме.
У меня есть внешнее приложение, которое удаленно управляет водяным насосом. Этот водяной насос включается на и на с помощью кнопки.
Проблема возникает, когда я хочу обработать случай отпускания кнопки, то есть событие mouseup , когда не наводится курсор на кнопку. Обработка этого события имеет решающее значение, поскольку насос должен перекрыть поток воды.
Примечание: у меня есть механизм для обработки этого и на бэкенде, но давайте считать, что это не так, и интерфейс управляет всей логикой управления.
Я буду использовать React.js для демонстрации проблемы и решения. Хотя код применим к любой библиотеке JavaScript или ванильному JavaScript практически без изменений.
Рассмотрим следующий код:
Код: Проблемный обработчик события mouseupПопробуйте сами — нажмите и удерживайте левую кнопку мыши над кнопкой Pump water , затем, удерживая кнопку мыши нажатой, оставьте Pump воды и отпустите кнопку мыши:
Игровая площадка: Проблемный обработчик события mouseupСобытие mouseup не обрабатывается. Вода все еще течет. Это потому, что событие не произошло из Насосная вода кнопка, а не какой-то другой элемент, над которым в данный момент находился указатель.
Есть много способов решить эту проблему, но давайте рассмотрим тот, который первым придет на ум.
Код: исправлен обработчик события mouseupЧто нам нужно сделать, так это привязать событие mouseup к документу , когда мы находимся внутри обратного вызова handleMouseDown . Мы привязываем событие к документу, потому что обработчик события запускается, когда вы отпускаете кнопку мыши независимо от того, где вы находитесь в документе. Более того, обработчик события запускается, даже когда вы отпускаете кнопку мыши вне браузера .
Поиграйте сами:
Площадка: Исправлен обработчик события mouseupОбратите внимание:
Код: Добавление прослушивателя событий только один раз с использованием { Once: true }аналогично:
Код: Добавление прослушивателя событий только один раз вручнуюПервый использует параметр ` { Once: true } `, указывающий, что событие должно быть вызвано не более одного раза после добавления. При вызове браузер автоматически удаляет его. Обратите внимание, что `{ Once: true }` не поддерживается в Microsoft Internet Explorer (Microsoft Edge в порядке).
Изображение: поддержка параметра { Once: true } через интернет-браузерыДополнительную информацию см. в веб-документах MDN — EventTarget.addEventListener() .
Как я уже говорил, есть много способов решить эту проблему.
Вместо связывания и удаления обработчика событий mouseup каждый раз, когда вы нажимаете кнопку, вы можете иметь событие mouseup , привязанное к документу на протяжении всего времени существования вашего приложения. На кнопке mousedown вы можете установить логическую переменную isMouseDown = true и проверьте его значение в обработчике событий mouseup . Если это правда, вы справитесь с этим.
Все зависит от того, какое приложение вы создаете и каков ваш вариант использования.
триггер | Документация Cypress
Инициировать событие для элемента DOM.
Небезопасно
цепочка дальнейших команд, которые полагаются на тему после .trigger()
.
Синтаксис
.trigger(eventName)
.trigger(eventName, position)
.trigger(eventName, options)
.trigger(eventName, x, y)
.trigger(eventName, position, options)
.trigger(eventName, x, y, options)
Usage
Правильное использование
cy.get('a').trigger('mousedown') // Инициировать событие mousedown для ссылки
Неверное использование ‘cy’ eventName (Строка) Имя позиция (строка) Позиция, в которой должно инициироваться событие. Центральное положение x (Число) Расстояние в пикселях от левого элемента до запуска события. y (Число) Расстояние в пикселях от верха элемента, на котором должно инициироваться событие.
cy. clock().trigger(‘mouseleave’) // Ошибки, ‘clock’ не дает элементов DOM
Аргументы
события
, которое должно инициироваться в элементе DOM.
— это
положение по умолчанию. Допустимые позиции: topLeft
, top
, topRight
, left
, центр
, справа
, снизу слева
, снизу
и снизу справа
.
параметры (объект)
Передайте объект параметров, чтобы изменить поведение по умолчанию .триггер()
.
Опция | По умолчанию | Описание |
---|---|---|
animationDistanceThreshold | 90804302Расстояние в пикселях, которое элемент должен превысить с течением времени, чтобы считаться анимируемым. | |
пузыри | правда | Является ли событие пузырем |
отменяемым | true | Можно ли отменить событие |
eventConstructor | Event | MouseEvent , KeyboardEvent ) |
принудительно | false | Инициирует действие, отключает ожидание действия |
журнал | true | Отображает команду в журнале команд. |
таймаут | defaultCommandTimeout | Время ожидания разрешения .trigger() до истечения времени ожидания |
waitForAnimations | waitForAnimations | Следует ли ждать завершения анимации элементов перед выполнением команды. |
Вы также можете включить произвольные свойства события (например, clientX
, shiftKey
) и
они будут прикреплены к событию. Передача аргументов координат ( clientX
, pageX
Урожайность
-
.trigger()
дает тот же предмет, который был задан. - Это небезопасно
чтобы связать дальнейшие команды, которые полагаются на тему после
.trigger()
.
Примеры
События мыши
Инициировать
наведение курсора мыши
на кнопкуЭлемент DOM должен быть в «интерактивном» состоянии до запуска события происходит (это должно быть видно и не отключено).
cy.get('button').trigger('mouseover') // возвращает 'button'
Имитация события «длительное нажатие»
cy.get('.target').trigger('mousedown')
cy.wait(1000)
cy.get('.target').trigger('mouseup')
Инициировать
mousedown
от определенной кнопки мыши// Нажата основная кнопка (обычно левая)
cy.get('.target').trigger('mousedown', { button: 0 })
// Нажата вспомогательная кнопка (обычно средняя кнопка)
cy.get('.target').trigger('mousedown', { button: 1 })
// Нажата вторичная кнопка (обычно правая)
cy.get('.target').trigger('mousedown', { button: 2 })
jQuery UI Sortable
свойства вместе с которые:1
.
cy.get('[data-cy=draggable]')
.trigger('mousedown', {который: 1, pageX: 600, pageY: 100})
.trigger('mousemove', {который: 1 , pageX: 600, pageY: 600 })
.trigger('mouseup')
Перетаскивание
Событие изменения
Взаимодействие с входом диапазона (ползунком)
Чтобы взаимодействовать с входом диапазона (ползунком), нам нужно установить его значение, а затем вызвать соответствующее событие, чтобы сигнализировать об изменении.
Ниже мы вызываем метод jQuery val()
для установки значения, затем запускаем изменить
событие.
Обратите внимание, что некоторые реализации могут вместо этого полагаться на событие ввода
, которое
запускается, когда пользователь перемещает ползунок, но не поддерживается некоторыми браузерами.
cy.get('input[type=range]').as('range').invoke('val', 25).trigger('change')cy.get('@range').siblings ('p').should('have.text', '25')
Позиция
Запуск
mousedown
в правом верхнем углу кнопкиcy.get('button'). trigger('mousedown', 'topRight')
Координаты
Укажите явные координаты относительно верхнего левого угла
cy.get('button').trigger('mouseup', 15, 40)
Опции
Укажите, что событие не должно всплывать
По умолчанию событие всплывает вверх по дереву DOM. Это предотвратит событие от пузырения.
cy.get('button').trigger('mouseover', { bubbles: false })
Укажите точный
clientX
и clientY
событие должно быть на основе самого элемента. Полезный
для таких событий, как mousemove
, где вам нужно, чтобы позиция находилась за пределами
сам элемент.cy.get('button').trigger('mousemove', { clientX: 200, clientY: 300 })
Активация других типов событий.
Событие
. Но вы можете
хотите инициировать другие события, такие как MouseEvent
или KeyboardEvent
. В этом случае используйте параметр eventConstructor
.
cy.get('button').trigger('mouseover', { eventConstructor: 'MouseEvent' })
Примечания
Возможность действия
Элемент должен сначала достичь возможности действия Актуальность.
События
Какое событие я должен активировать?
cy.trigger()
предназначена для использования в качестве низкоуровневой утилиты, запускающей события
проще, чем создавать и отправлять их вручную.
Почему я должен вручную устанавливать тип события?
Как вы можете видеть в документации MouseEvent
,
большинство свойств экземпляров класса событий доступны только для чтения. Из-за этого это
иногда невозможно установить значение некоторых свойств, таких как pageX
, pageY
.
Это может быть проблематично при тестировании некоторых ситуаций.
Различия
В чем разница между триггером и событием и вызовом соответствующей команды кипариса?
Другими словами, в чем разница между:
cy.get('button').trigger('focus')
cy.get('button').focus()// ... или .. . команды действия реализуют все действия браузера по умолчанию, и дополнительно выполнять действия низкого уровня, чтобы выполнить то, что определено в спецификации.
.trigger()
будет только запускать соответствующее событие и больше ничего не делать.Это означает, что ваши обратные вызовы прослушивателя событий будут вызываться, но не ожидайте браузер фактически «делает» что-либо для этих событий. По большей части это не должно иметь значения, вот почему
.trigger()
— отличная временная мера, если команда / событие, которое вы ищете, еще не реализовано.Правила
Требования
-
.trigger()
требует привязки команды, которая выдает элемент(ы) DOM.
Утверждения
-
.trigger()
будет автоматически ждать, пока элемент достигнет действенное состояние. -
.trigger()
автоматически повторит попытку пока не будут пройдены все связанные утверждения.
Тайм-ауты действенное состояние.
.trigger()
может истечь время ожидания прохождения утверждений, которые вы добавили.