Событие мобильного события jQuery запускается дважды

Я тестировал событие jquery mobile 'tap' и обнаружил, что он запускал два раза, каждый раз, когда он запускается. Код, как показано ниже для страницы html:

<!DOCTYPE html>
<html>
<head>
    <title>Demo</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">    
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>    
    <script src="http://code.jquery.com/mobile/1.1.0/jquery.mobile-1.1.0.js"></script>      
    <style>
        #box{
            background-color:red;
            width:200px;
            height:200px;
        }   
    </style>
</head>
<body>
    <div id="box">
        tapped me
    </div>
    <script type="text/javascript">
        $(document).ready(function() {
            $('#box').bind('tap',function(event) {
                alert('why');
            }); 
        });
    </script>
</body>
</html>

Больше иронии, когда я проверяю это на jsfiddle, он только запускал событие для один раз.

Здесь ссылка. http://jsfiddle.net/mochatony/tzQ6D/6/

После дальнейшего тестирования я узнал, что ошибка ушла с размещением javascript в разделе заголовка.

<!DOCTYPE html>
<html>
<head>
    <title>Demo</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">    
    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js">
    </script>
    <script type="text/javascript" src="http://code.jquery.com/mobile/1.1.0/jquery.mobile-1.1.0.js">
    </script>
    <style type="text/css">
        #box{ background-color:red; width:200px; height:200px; }
    </style>
    <script type="text/javascript">
        $(document).ready(function() {
            $('#box').bind('tap', function(event) {
                alert('halo');
            });
        });
    </script>        
</head>
<body>
    <div id="box">
        tapped me
    </div>
</body>
</html>

Я не мог объяснить, почему размещение в разделе body и header делает это другим.

Ответ 1

Я забыл, где я это видел, но проблема в том, что jQuery Mobile привязан к событиям касания и мыши, чтобы имитировать "кран", и в некоторых случаях Android будет запускать оба.

Трюк, который работал у меня, - это вызвать preventDefault в событии в обработчике событий. Это предотвратит срабатывание дублирующего события.

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

Ответ 2

У вас возникает проблема с призрачным щелчком... Это известная "ошибка" и трудно решить.

Дополнительная информация:

http://forum.jquery.com/topic/tap-fires-twice-with-live-tap https://developers.google.com/mobile/articles/fast_buttons http://philosopherdeveloper.wordpress.com/2011/11/01/ghost-clicks-in-jquery-mobile/

В первой ссылке вы найдете хак, который делает трюк. Насколько я знаю, нет простого решения: (

Кстати: даже если это не решит вашу проблему, @Sagiv прав. JQuery mobile часто использует ajax для изменения страницы и поэтому не запускает событие document.ready.

Ответ 3

на странице jQuery Mobile:

Важно: используйте $(document).bind('pageinit'), а не $(document).ready()
Первое, что вы узнали в jQuery, - это вызвать код внутри $(document).ready(), поэтому все будет выполняться, как только Загружается DOM. Однако в jQuery Mobile Ajax используется для загрузки содержимое каждой страницы в DOM при навигации и готовность DOM обработчик выполняется только для первой страницы. Выполнять код всякий раз, когда новая страница загружается и создается, вы можете привязываться к событию pageinit. Это событие подробно описано в нижней части этой страницы.

поэтому пропустите $(document).ready(). подробнее здесь.

Ответ 4

связанный с этим вопросом, я получал два события 'tap' и 'click' один сразу после другого. Все идеи здесь вдохновляли, но я нашел другое решение. Я добавил следующий код к моему контроллеру JavaScript, чтобы различать последовательные дублированные события на основе временной метки, которая, к счастью, точно такая же для двух повторяющихся событий. В основном, я делаю это, чтобы сохранить последнюю использованную метку времени, если я решаю использовать это событие. Во второй раз, когда событие с той же меткой времени я просто отбросил.

var _lastEventTimestamp;
var checkAndPreventDuplicatedEvent = function (e) {
    if (e.timeStamp === _lastEventTimestamp) return true;
    else _lastEventTimestamp = e.timeStamp;
    return false;
}

Ответ 5

$("#buttonID").tap(function(event){
        if(localStorage.JQMGostClick == 0 || localStorage.JQMGostClick == "" || typeof(localStorage.JQMGostClick) === "undefined")
            localStorage.JQMGostClick = 1;
        else if(localStorage.JQMGostClick == 1){
            localStorage.JQMGostClick = 0;
            return false;
        }
.....
});

Он работает для меня, поскольку, если вы используете мобильную среду, то, вероятно, вы используете своего рода хранилище

Ответ 6

Я узнал, что в моем случае добавление data-role="page" к моему контейнеру страницы предотвращало дважды срабатывание событий крана.

Ответ 7

Я испытал нечто подобное раньше, и это произошло из-за того, что моя форма не была внутри data-role="page"

То, что я хотел бы предложить, - это обернуть свой код с помощью html-структуры jQuery Mobile, чтобы ваш вариант мог выглядеть так:

<div data-role="page" class="ui-page ui-page-theme-a ui-page-active">
  <div class="ui-content">
    <div id="box">
        tapped me
    </div>
    <script type="text/javascript">
        $(document).ready(function() {
            $('#box').bind('tap',function(event) {
                alert('why');
            }); 
        });
    </script>
   </div>
</div>

Ответ 8

Это может быть не лучшее решение и будет работать только в некоторых случаях, но то, что сработало для меня, было сразу же после того, как началось событие click, чтобы установить "указатель-события" CSS для этого элемента в "none". Затем с помощью JS setTimeout reset "указатели-события" будут автоматически после 500 мс.

Для меня достаточно 300 мкс для устройств Android, но для iPhone требуется 500 мс, чтобы предотвратить двойной щелчок.

function yourEvent(evt){

  $(el).css('pointer-events', 'none');
  
  setTimeout(function(){
      $(el).css('pointer-events', 'auto');
  }, 500);
  
  //do you stuff

}