изменение jQuery и время события щелчка

Кажется, у меня проблема с синхронизацией с моим изменением jQuery и событиями щелчка. На моем сайте у меня есть сообщение Ajax вместо предупреждения, но его легче воспроизвести с помощью предупреждения. У меня есть простая HTML-страница с использованием jQuery версии 1.7.1.

Сценарий редактирует текстовое поле, а затем непосредственно щелкает кнопку. Событие изменения всегда запускается, но если оно содержит предупреждение, событие щелчка никогда не вызывается. Если я обманываю и устанавливаю тайм-аут вокруг предупреждения (возможно, вам придется немного поиграть со значениями там), событие щелчка вызывается нормально.

/ ** РЕДАКТИРОВАТЬ ** / Если вы установите точку останова где-нибудь в событии изменения и подождите несколько секунд, событие щелчка также не сработает.

<script type="text/javascript">
$(document).ready(function ()
{
    $("input[type=text]").change(function () {
        //alert('changed');

        $("#text").text('changed');

        setTimeout(function () {
            $("#text").text('changed timeout');
            alert('changed');
        }, 100);

    });

    $("input[type=submit]").click(function () {
        alert('clicked');
        $("#text").text('clicked');
    });
});
  </script>
  <div id="main">
    <div class="container">
        <input type="text" />
        <input type="submit" value="click me" />
        <div id="text" >bla</div>
    </div>
  </div>

Мой вызов Ajax с сохранением поведения выглядит следующим образом:

$.ajax({
        type: 'POST',
        url: postUrl,
        data: form.serialize(),
        beforeSend: function () {
            // display overlay for work in progress
        },
        success: function (result) {
            updateTableSuccess();
        },
        complete: function () {
            // hide overlay for work in progress
        },
        error: function (jqXHR) {
            if (jqXHR.responseText.length > 0) {
                showErrorMessage(jqXHR.responseText);
            }
        }
    });

Оверлей просто добавляет 2 блока к тегу body.

/ ** Изменить ** / Похоже, что реальная проблема заключается в наложении, которое вызывает такое же поведение, как и предупреждение, и останавливает активацию события клика.

showWorkInProgress = function (message, elementId)
{
    if ($("#overlay").length == 0)
    {
        $("<div id='overlay' class='ui-widget-overlay'></div>").appendTo("body");
    }

    if ($("#workInProgress").length == 0)
    {
        $("<div id='workInProgress'></div>").appendTo("body");
    }

    $("#workInProgress").html(message);
    if (elementId != null)
    {
        $("#workInProgress").center(elementId);
    }
    else
    {
        $("#workInProgress").center();
    }
    $("#overlay").show();
    $("#workInProgress").show();
};

Может ли кто-нибудь объяснить, почему jQuery ведет себя так и как я мог бы сделать это лучше без взлома setTimeout?

Спасибо за любую помощь =)


person Nischo    schedule 07.01.2013    source источник
comment
При чем тут оповещение? Оповещения не меняют способ выполнения кода, они просто блокируют браузер, пока вы не нажмете ОК. Когда ввод теряет фокус, происходит событие изменения, в результате чего появляется окно предупреждения, которое блокирует браузер, что предотвращает взаимодействие с кнопкой отправки (я предполагаю). Выполняйте отладку с помощью console.log () или, может быть, даже лучше, выполняйте ее построчно с помощью отладчика.   -  person Kevin B    schedule 07.01.2013
comment
Если я отлаживаю и устанавливаю точку останова на $ (# text) .text ('changed'); и подождите несколько секунд, событие щелчка также не запускается. Отредактирую пост для этого ..   -  person Nischo    schedule 07.01.2013
comment
Ваш код работает нормально. jsfiddle.net/w9Thc/5 Перестаньте застревать в предупреждении. Приступите к реальной проблеме.   -  person Kevin B    schedule 07.01.2013
comment
Вы используете async: false со своим запросом ajax?   -  person Kevin B    schedule 07.01.2013
comment
Нет, это значение по умолчанию, так что правда.   -  person Nischo    schedule 07.01.2013


Ответы (3)


Нишо, я не могу реплицировать блокировку при вставке вашего AJAX кода в функцию change. Если вы хотите заблокировать AJAX при выполнении, когда click запускается при отправке, посмотрите здесь.

jQuery - Как я могу временно отключить прослушиватель событий onclick после того, как событие было запущено?

Удачи.


После вашего объяснения я понимаю, о чем вы говорите, поскольку событие change требует потери фокуса для запуска вашей функции click, переопределено в результате блокировки, вызванной потерей фокуса при нажатии.

Вы можете использовать timeOut, как вы указали, или вы можете выполнить рефакторинг до метода keydown на вводе text. Увидеть ниже:

$(document).ready(function () 
{
   $("input[type=submit]").click(function () {
      $("#text").text('clicked');
   });

   $("input[type=text]").keydown(function () {
      alert('changed');
      $("#text").text('changed');
   });
});

Fiddle: http://jsfiddle.net/9WXBe/2/


Нишо,

После того, как вы взяли ваш код и поместили его в jsFiddle, я не вижу никаких проблем с запуском события изменения. Даже с alert в коде.

$("input[type=text]").change() не сработает, пока текстовое поле не потеряет фокус, другие элементы, такие как select, radio, выполнят это действие сразу после выбора или изменения.

Вот скрипка: http://jsfiddle.net/w9Thc/1/

person John Gerdsen    schedule 07.01.2013
comment
Извините, возможно, я недостаточно ясно понял. Проблема не в событии изменения, а в событии щелчка, которое больше не запускается. Событие изменения всегда запускается нормально. - person Nischo; 07.01.2013
comment
Обновленное решение для вас выше, чтобы отразить эту проблему, используйте keydown () - person John Gerdsen; 07.01.2013
comment
Спасибо, я бы предпочел не использовать keydown, потому что в вызове ajax я получаю данные из базы данных, и у него, вероятно, не будет такой лучшей производительности, как это, иначе я бы запустил 6 запросов и немедленно прервал их. Я до сих пор не понимаю, почему он не будет блокировать событие, если он только устанавливает текст на странице, но блокирует его примерно через 10 мс. - person Nischo; 07.01.2013
comment
Правда, про весь вызов AJAX забыл. Итак, вы планируете сделать вызов AJAX, когда человек убирает фокус с поля, проблема в том, что они обычно сначала нажимают «Отправить». - person John Gerdsen; 07.01.2013
comment
Ага, точно. В лучшем случае я хотел бы каким-то образом узнать, была ли нажата кнопка при вызове измененного события, и если это так, даже не выполняйте ajax, а только событие щелчка. Но я бы с удовольствием прервал звонок и позже =) - person Nischo; 07.01.2013
comment
Нишо, используя ваш код и применяя AJAX в коде для события Change, я не вижу никаких блокировок в событии Click для отправки. Проверьте мое решение, я добавил ссылку, которая может вам помочь. Если вы создаете объект для себя AJAX, вы также сможете отменить его, щелкнув кнопку отправки. - person John Gerdsen; 07.01.2013
comment
Спасибо за вашу помощь, похоже, проблема в моем наложении во время вызова ajax, которое приводит к тому же поведению, что и предупреждение, блокируя запуск щелчка. Я обновлю свой пост инфой =) - person Nischo; 08.01.2013

Просто для краткого ответа, если у кого-то еще есть такая же проблема: проблема действительно заключается в наложении, которое блокирует всю страницу, что вызывает то же поведение, что и предупреждение.

Я объясняю это тем, что событие изменения запускается, блокирует пользовательский интерфейс, и событие щелчка больше не может быть запущено из-за этого, как было предложено https://stackoverflow.com/users/1861269/john-gerdsen.

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

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

person Nischo    schedule 14.01.2013

Проблема возникает только с Firefox. В других браузерах проблема не возникает. Я исправил свою проблему, переписав вещи, чтобы не использовать событие изменения текстового поля. К сожалению, у меня есть другой фрагмент кода, в котором я не могу этого сделать. Событие изменения, похоже, блокирует пользовательский интерфейс, потому что я не нахожу никаких событий на кнопке «щелкнуть».

person Keith Davenport    schedule 12.12.2013