Автозаполнение jQuery - нажатие кнопки «Отправить» не считается изменением - PullRequest
4 голосов
/ 27 июля 2010

Да, это действительно мой третий или четвертый вопрос об автозаполнении jQuery UI. Мое последнее раздражение в том, что нажатие на кнопку «отправить» в форме, похоже, не считается «изменением» для jQuery. Когда мое поле ввода изменяется, jQuery запускает некоторый javascript для принудительного сопоставления со списком допустимых входных данных и их значений:

jQuery("#Resource").autocomplete({
   source: function( request, response ) {
    var matcher = new RegExp(jQuery.trim(request.term).replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"), "i" );
    var matches = jQuery.grep(resources, function(value) {
     return matcher.test( value.label || value.value || value );
    });
    response(matches.length ? matches : [{ label: "No Result Found", value: "" }]);
   },
   focus: function(event, ui) {
    jQuery('#Resource').val(ui.item.label);
    return false;
   },          
   select: function(event, ui) {
    jQuery('#Resource').val(ui.item.label);
    jQuery('#EmployeeNumber').val(ui.item.value);
    return false;
   },
   change: function(event,ui) {
    for(var i in resources){
     jQuery('#EmployeeNumber').val("");
     if(resources[i].label.toLowerCase()==jQuery('#Resource').val().toLowerCase()) {
      jQuery('#EmployeeNumber').val(resources[i].value);
      break;
     }
    }
   }

  });

Если ввод EmployeeNumber (скрытый) уже имеет значение, ввод недопустимого имени, а затем вставка или щелчок по полю ввода очищает это значение, однако , если вместо этого вы сразу же нажмете на форму Submit кнопка, она не считается «изменением», а данные POST включают предыдущее значение EmployeeNumber - что делает неправильный ввод «своего рода» правильным!

Есть ли какой-нибудь способ, которым я могу заставить jQuery распознавать, что нажатие кнопки «Отправить» также является изменением, или иначе я могу получить кнопку Submit, чтобы уведомить jQuery о том, что вход Resource был отключен из

UPDATE

В конце концов, я справился с этим, используя довольно хакерский метод - я отказался от события 'change' в окне автозаполнения и сделал это вручную, когда пользователь нажимает на кнопку submit. Теперь это работает так: если пользователь выберет имя, щелкнув раскрывающееся меню автозаполнения, значение EmployeeNumber будет заполнено кодом автозаполнения jQuery. Если пользователь просто вводит имя и нажимает submit, то сопоставление выполняется с помощью функции forceCheck (). Конечно, эта функция автоматически сопоставляется с первым именем, независимо от того, существует ли второе идентичное имя или нет, но, к сожалению, в том, что похоже на самую странную причуду, которую я когда-либо видел, любой код после окончания что цикл for выполняет , а не , даже если в цикле нет оператора return. После окончания цикла запрос на отправку просто продолжается ... это очень странно.

<fieldset class="submit">
    <input id="Submit" name="Submit" type="Submit" class="Submit" value ="Submit" onclick="document.getElementById('Resource').value = jQuery.trim(document.getElementById('Resource').value);forceCheck();"/>
</fieldset>

...


<script type="text/javascript">

    ...

    // Force a resource name check when the user hits the submit button. Necessary because if user changes Resoruce
    // input then hits submit directly (no click or tab off), the jQuery 'change' event (see below) isn't fired
    // until *after* the submit button has begun processing, which is too late.
    function forceCheck() {
        for(var i in resources) {
            document.getElementById("EmployeeNumber").value = "";
            if(resources[i].label.toUpperCase() == document.getElementById("Resource").value.toUpperCase()) {
                document.getElementById("EmployeeNumber").value = resources[i].value;
                return;
            }
        }
    }

    jQuery(function(){
        jQuery("#Resource").autocomplete({
            source: function( request, response ) {
                var matcher = new RegExp(jQuery.trim(request.term).replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"), "i" );
                var matches = jQuery.grep(resources, function(value) {
                    return matcher.test( value.label || value.value || value );
                });
                response(matches.length ? matches : [{ label: "No Result Found", value: "" }]);
            },
            focus: function(event, ui) {
                jQuery('#Resource').val(ui.item.label);
                return false;
            },          
            select: function(event, ui) {
                jQuery('#Resource').val(ui.item.label);
                jQuery('#EmployeeNumber').val(ui.item.value);
                return false;
            },  
        });
    }); 
</script>

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

Окончательное обновление :

Что ж, прошло более 24 часов (довольно много), поэтому я разместил свое решение в качестве «ответа». Я оставлю это еще на несколько дней, а затем приму, если другого ответа нет.

Ответы [ 8 ]

4 голосов
/ 19 октября 2011

Причина, по которой обработчик изменений вызывается поздно (после отправки), заключается в том, что автозаполнение кодируется асинхронно (с большим количеством setTimeout (...)). Событие изменения вызывается через 150 мс после события размытия.

Мое решение также немного хакерское, но вы можете оставить код автозаполнения отдельно от отправки. Это также легко удалить, если виджет автозаполнения переписан более синхронно.

$("#mysubmit").click(function (event) {
//Wait for autocomplete to change value
    setTimeout(function() {
        //Do submit
        ...
    }, 250 ); //Make sure delay is greater than 150 ms, as in autocomplete widget.
    event.preventDefault(); //Don't submit now
});
2 голосов
/ 24 марта 2012

Я знаю, что это старо, но на этом я остановился, пытаясь решить эту проблему, и думаю, у меня есть уникальное решение. Это, конечно, не идеальное решение, поскольку оно предполагает доступ к «частным» функциям, но работает (пока) и выглядит намного чище.

Я принудительно инициирую событие изменения перед отправкой:

$('#yourAutoCompleteForm').submit(function() {
    $('#yourAutoCompleteInput').data("autocomplete")._change();
    //the rest of your submit
}

Моя отправка продолжается для проверки пользовательского атрибута, установленного моим обратным вызовом изменения. Возможно, они могли бы разделить область видимости и просто использовать переменную ...

1 голос
/ 10 июня 2011

Я понимаю, что от вопроса доходит около года, но я столкнулся с той же проблемой.Я использую последний на данный момент JQuery UI 1.8.13.Я решаю проблему следующим образом:

var acinaction = false;  // autocomlete in edit stage flag
var needsubmit = false;  // submit action asked
jQuery("#Resource").keypress(function(event) {
    // if any key pressed then we set autocomplete in edit stage flag
    if (event.which == '13') {
        event.preventDefault();
    }
    acinaction = true;
}).autocomplete({
   select: function(event, ui) {
        // user choose an item from dropdown menu
        // do validation here if necessary
        ...
        // unset autocomplete in edit stage flag
        acinaction = false;
    },
    change: function(event,ui) {
        if( acinaction ) {
            // user input some characters into input field and move focus away
            // without choosing any items from dropdown menu
            // may be clicking submit button
            // do validation here if necessary
            ...
            acinaction = false;
            if( form_is_valid && needsubmit ) {
                // if submit flag is set then try submit again
                JQuery('#Form').submit();
            }
        }
    }
});
JQuery('#Form').submit(function() {
    // if autocomplete in edit stage then cancel form submition
    if( acinaction ) {
        needsubmit = true;
        return false;
    }
    // autocomplete change event is done here
});

Код некрасив, но должен показать идею.

0 голосов
/ 24 января 2014

Чтобы пояснить ответ Тварта, вот что я добавил в код загрузки своей страницы:

$('form').submit(function(event) {
  var form = $(this);
  if (form.find('.ui-autocomplete-input').length &&
      !form.data('already-submitted')) {
    // delay the submit by 250 ms
    form.data('already-submitted', true);
    setTimeout(function() {
      form.submit();
      form.data('already-submitted', false);
    }, 250);
    event.stopImmediatePropagation();
    return false;
  }
});

Это автоматически применяется ко всем формам с автозаполнением входов в них. Вы должны быть осторожны с другими обратными вызовами события отправки формы - вам нужно проверить, если form.data('already-submitted'), и если оно ложно, ничего не делать.

0 голосов
/ 19 апреля 2012

Используйте blur вместо change.В моем случае это сработало!

0 голосов
/ 19 ноября 2011

У меня есть метод, чтобы решить эту проблему,

сначала добавьте этот скрипт в ваш

$('#your_form:input').change(function(){
   $('#your_form').data('changed',true);
});

и затем в вашем представлении, щелкающем сценарии проверки, добавьте сценарий, как показано ниже,

 if(!$('#your_form').data('changed'))  return false; 

Я обнаружил, что это действительно работает, хотя я думаю, что это не лучший способ.

Извините, это обходной путь.

0 голосов
/ 15 сентября 2010

Очевидно, jquery-ui 1.8.4 вроде исправляет проблему (см. changelog ):

  • Исправлено: Combobox / Автозаполнение не сохранить значение, если элемент управления не потерял фокус

Удалось ли вам это проверить? Потому что это не работает для меня.

0 голосов
/ 27 июля 2010

Можете ли вы добавить

submit: function(event,ui) {
// same thing as your change:
}
...