Я пытаюсь обработать нажатие кнопки. «Кнопка» - это настраиваемый div, который также может содержать детей. Обратный вызов клика должен срабатывать, когда пользователь щелкнул и выпустил внутри элемента. Если пользователь нажимает внутри, а затем перетаскивает и отпускает снаружи, обработчик не должен запускаться. Мне нужно, чтобы это работало как на рабочем столе, так и на мобильных устройствах, поэтому я использую mousedown/mouseup
и touchstart/touchend
событий.Как обнаружить событие touchhend вне элемента
Мне нужно изменить класс кнопки от «нажата» к «нормальной», даже если пользователь отпускает снаружи, так что мне нужно добавить слушателя, чтобы захватить рилизинг событие над документом:
var $myElement = $("#myelement"); //This is a div and can also contain children.
$myElement.on("mousedown touchstart", function(e){
$(this).addClass("pressed");
$(document).on("mouseup touchend", function listener(e){
$myElement.removeClass("pressed");
$(document).off("mouseup touchend", listener);
var $target = $(e.target);
if ($target.is($myElement) || $target.parents().is($myElement)){
//FIXME
alert("Inside!");
//do something here
return false;
} else {
//FIXME
alert("Outside!");
//let event bubble
}
});
return false;
});
It отлично работает с кликами, но с сенсорными событиями он не работает должным образом. Я тестировал это в Chrome для Android и при нажатии над элементом, а затем перетаскивая «Внутри!». отображается предупреждение.
Проблема находится в этом состоянии:
if ($target.is($myElement) || $target.parents().is($myElement)){
Я пытаюсь проверить, является ли touchend
событие произошло в кнопке или какой-либо из детей. Если у кнопки нет детей, при нажатии на нее и последующем выпуске снаружи первая часть предложения OR разрешает true. Если у кнопки есть дочерние элементы, и я нажимаю на дочерние элементы, затем отпустите ее в любой другой части экрана, вторая часть предложения верна.
Что не так с этим кодом?
Спасибо заранее.
ОБНОВЛЕНИЕ
Я тестировал его также в BlackBerry 10 с теми же результатами. Очевидно, целью для события touchend
является кнопка (или дети), даже когда я щелкнул снаружи. Так ли это должно работать?
ОБНОВЛЕНИЕ
И вот почему. Это what the W3C docs say about the event:
Цель этого события должен быть тот же элемент, который получил это событие touchstart, когда эта точка соприкосновения была размещена на поверхности, даже если точка касания с тех пор перемещается за пределы интерактивной области из целевой элемент.
Это не имеет для меня никакого смысла, но в любом случае это объясняет мою проблему. Я предполагал, что событие touchend
будет вызываться над элементом, где был отпущен палец. Можно ли обнаружить отпечаток пальца снаружи с использованием другого подхода?
UPDATE
Я пытался получить координаты touchevent
, чтобы получить элемент там с помощью document.elementFromPoint
. Проблема в том, что это событие не содержит координат (списки changedTouches
и touches
пустые). Я точно осмотрел событие в отладчике, и нет способа извлечь из него координаты, кроме оригинального события. Тогда я подумал, что могу кэшировать последнее событие touchmove
и получить из него коорды, но опять же это событие не имеет собственных координат! Почему на Земле эти два события существуют, когда они бесполезны? И я протестировал этот подход в iOS, Android и BB10 с одинаковыми результатами.
Я отказался. Я вызову обратный вызов, даже если пользователь щелкнул снаружи.Я не могу поверить, что это ребята из 2013 года, и нет (простого) способа сделать это? Я мог бы использовать drag & drop api, но в соответствии с this он не поддерживается на мобильных устройствах (Gotta love mobile web development).
Хотя это может и не помочь вам, я собрал скрипт VanillaJS, который делает почти то же самое, и разместил упрощенную версию этого кода [здесь] (http://stackoverflow.com/questions/13030210/onclick-event-is-occending-two-times-in-iphone-hybrid-app/13030622 # 13030622) –
@EliasVanOotegem спасибо, я прочитал его, но я еще не смог его протестировать. Теперь я читаю источник некоторых из библиотек, которые вы связали. Может быть, я пытаюсь изобрести колесо здесь. –