【问题标题】:jQuery autocomplete - clicking submit button does not count as "change"jQuery 自动完成 - 单击提交按钮不算作“更改”
【发布时间】:2010-07-27 12:54:43
【问题描述】:

是的,这确实是我关于 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(隐藏)输入已经有一个值,输入一个无效的名称,然后在输入框上跳动或单击会清除这个值,但是如果您立即点击表单 @987654322 @ 按钮,它似乎不算作“更改”,POST 数据包括以前的 EmployeeNumber 值 - 使不正确的输入“有点”正确!

是否有某种方法可以让 jQuery 认识到单击“提交”也是一种更改,或者我可以通过某种方法获得 Submit 按钮来通知 jQuery Resource 输入已被点击关闭的?

更新

最后,我通过使用我认为相当老套的方法解决了这个问题——我放弃了自动完成框的“更改”事件,并在用户单击提交时手动匹配自己。它现在的工作方式是,如果用户通过单击自动完成下拉菜单选择名称,则 EmployeeNumber 值将由自动完成 jQuery 代码填充。如果用户只是键入名称并点击提交,则匹配由 forceCheck() 函数完成。当然,无论是否有第二个相同的名字,这个函数都会自动匹配第一个名字,但不幸的是,在我见过的 weirdest 怪癖中,结束后的任何代码即使循环中没有“return”语句,该 for 循环的 not 也会被执行。循环完成后,提交请求继续......这太奇怪了。

<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 函数的其余部分可能无法运行...否则,我将发布这篇文章作为我自己的答案明天提出问题,并在可能的情况下接受(我相信两天后)。

最终更新

嗯,已经超过 24 小时(更多),所以我将我的解决方案发布为“答案”。我会再放几天,如果仍然没有其他答案,我会接受它。

【问题讨论】:

  • 有点困惑。甚至从提交按钮的onclick 事件尝试手动触发资源输入onblur。在 change 函数中添加了 alert 语句以查看它是否有效。当我点击Submit 时,警报触发了,但 EmployeeNumber 在 POST 中没有更改 - 就像在 onclick 事件触发之前,或者至少在 change 事件触发之前已经记录了它一样。
  • 确实如此。通过向change 函数添加多个“警报”来测试代码。只需单击关闭,它们都会运行。当change 函数由于单击提交按钮而运行时,唯一运行的是第一个。即使我连续放置两个alerts,也只有第一个运行 - 如果我不先发出警报,我不知道是否有任何运行......
  • 啊,我错了。强制onblur 事件不会 启动change 事件 - 我收到警告框的原因是自动完成确实注册了change,就在提交方法已经开始之后加工。我通常设法获得一个警报框的原因是由于在处理发生时离开页面之前的延迟......

标签: javascript jquery html jquery-autocomplete jquery-ui-autocomplete


【解决方案1】:

更改处理程序被延迟调用(在提交之后)的原因是自动完成是异步编码的(有很多 setTimeout(...))。 在 blur-event 之后 150 ms 调用 change-event。

我的解决方案也有点老套,但您可以将自动完成代码与提交分开。如果以更同步的方式重写自动完成小部件,这也很容易删除。

$("#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】:

    我知道这是旧的,但这是我在尝试解决同样的问题时最终的结果,我认为我有一个独特的解决方案。这当然不是一个完美的解决方案,因为它涉及访问“私有”功能,但它可以工作(到目前为止)并且看起来更干净。

    我在提交之前强制触发了change事件:

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

    我的提交继续验证我的更改回调设置的自定义属性。他们可能会共享一个范围并只使用一个 var...

    【讨论】:

      【解决方案3】:

      我知道一个问题大约过了一年,但我遇到了同样的问题。我现在使用最后一个 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
      });
      

      代码很丑,但它应该显示这个想法。

      【讨论】:

        【解决方案4】:

        显然,jquery-ui 1.8.4 某种解决了这个问题(见changelog):

        • 固定:组合框/自动完成不 保存价值,除非控制失去焦点

        你能测试它吗?因为它不适合我。

        【讨论】:

        • 我使用的是 1.8.5,但仍然遇到同样的问题。在我的情况下,如果有人输入了不匹配的内容然后按 Enter,则在提交表单之前不会触发 change() 事件。
        【解决方案5】:

        我有办法解决这个问题,

        首先,将此脚本添加到您的脚本中

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

        然后在您的提交点击验证脚本中,添加如下脚本,

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

        我发现它确实有效,但我认为这不是最好的方法。

        抱歉,这是一种解决方法。

        【讨论】:

          【解决方案6】:

          为了扩展 Tvartom 的答案,这是我在页面加载代码中输入的内容:

          $('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') 是否为 false,则什么也不做。

          【讨论】:

            【解决方案7】:

            你可以添加

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

            【讨论】:

            • jQuery UI 自动完成没有submit 事件...见here
            【解决方案8】:

            使用blur 代替change。就我而言,它有效!

            【讨论】:

              猜你喜欢
              • 2012-05-17
              • 2016-01-21
              • 2023-03-06
              • 1970-01-01
              • 2012-01-12
              • 1970-01-01
              • 1970-01-01
              • 2017-04-26
              • 1970-01-01
              相关资源
              最近更新 更多