jQuery 自动完成 - 单击提交按钮不算“更改”

发布于 2024-09-11 18:21:38 字数 3950 浏览 7 评论 0原文

是的,这确实是我关于 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(隐藏)输入已经有一个值,则输入无效名称,然后按 Tab 键或单击输入框清除此值,但是如果您立即点击表单Submit按钮,它似乎不算作“更改”并且POST数据包括之前的 EmployeeNumber 值 - 使原本不正确的输入“有点”正确!

有没有什么方法可以让 jQuery 认识到单击“提交”也是一种更改,或者有什么方法可以让 Submit 按钮通知 jQuery Resource输入已经被点击掉了?

更新

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

<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 小时了(相当多),所以我将我的解决方案发布为“答案”。如果仍然没有其他答案,我会再保留几天,然后接受它。

Yeah, this is indeed my third or fourth question about jQuery UI Autocomplete. My latest annoyance is that clicking the 'submit' button in a form does not seem to count as a 'change' for jQuery. When my input box changes, jQuery runs some javascript to force a match against a list of acceptable inputs and their values:

jQuery("#Resource").autocomplete({
   source: function( request, response ) {
    var matcher = new RegExp(jQuery.trim(request.term).replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\
amp;"), "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;
     }
    }
   }

  });

If the EmployeeNumber (hidden) input already has a value, entering an invalid name and then tabbing or clicking off of the input box clears this value, however if you instead immediately hit the form Submit button, it does not seem to count as a 'change' and the POST data includes the previous EmployeeNumber value - making what should be an incorrect input 'sort of' correct!

Is there either some way I can make the jQuery recognise that clicking 'Submit' is also a change, or else some way I can get the Submit button to notify the jQuery that the Resource input has been clicked off of?

UPDATE:

In the end, I got around this by using what I consider a rather hacky method - I abandoned the 'change' event of the auto-complete box and did that matching myself manually when the user clicks submit. The way it work now is that if the user chooses a name by clicking on the auto-complete drop-down menu, the EmployeeNumber value will be filled in by the auto-complete jQuery code. If the user just types a name and hits submit, then the matching is instead done by the forceCheck() function. Of course this function will automatically match against the first name regardless of whether or not there is a second identical name, but unfortunately in what seems like the weirdest quirk I've ever seen, any code after the end of that for loop does not get executed, even if there is no 'return' statement in the loop. After the loop finishes the submit request just continues... it's so very odd.

<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, "\\
amp;"), "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>

If anyone knows a better way than this, I would very much appreciate your answer - or if you know why the remainder of my forceCheck function might not run... Otherwise, I will post this post as an answer to my own question tomorrow, and accept it when I can (2 days afterwards, I believe).

Final Update:

Well, it's been more than 24 hours (quite a lot more), so I've posted my solution up as an "answer". I'll leave it a few more days then accept it if there's still no other answer.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

奢华的一滴泪 2024-09-18 18:21:38

更改处理程序调用较晚(提交后)的原因是自动完成是异步编码的(使用大量 setTimeout(...))。
变化事件在模糊事件发生后 150 毫秒被调用。

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

$("#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
});

The reason that the change handler is called to late (after submit) is that autocomplete is coded asynchronously (with a lot of setTimeout(...)).
The change-event is called 150 ms after the blur-event.

My solution is also a bit hacky, but you can keep the autocomplete-code apart from the submit. This is also easy to remove if the autocomplete-widget is rewritten in a more synchronous way.

$("#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
});
谁的新欢旧爱 2024-09-18 18:21:38

我知道这已经很旧了,但这就是我在尝试解决同一问题时最终遇到的问题,而且我认为我有一个独特的解决方案。这当然不是一个完美的解决方案,因为它涉及访问“私有”函数,但它有效(到目前为止)并且看起来更干净。

我在提交之前强制触发更改事件:

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

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

I know this is old, but this is where I ended up when trying to solve this same issue, and I think I have a unique solution. It's certainly not a perfect solution since it involves accessing 'private' functions, but it works (so far) and it looks much cleaner.

I force trigger the change event before submitting:

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

My submit goes on to verify a custom attribute set by my change callback. They could probably share a scope and just use a var...

呆° 2024-09-18 18:21:38

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

代码很丑陋,但它应该显示出想法。

I understand that about a year pass from a question but I encountered the same problem. I use the last for now jquery ui 1.8.13. I solve the problem this way:

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
});

The code is ugly but it should show the idea.

春庭雪 2024-09-18 18:21:38

显然,jquery-ui 1.8.4某种程度上解决了这个问题(参见更改日志):

  • 修复:组合框/自动完成不
    除非控制失去焦点,否则可以节省价值

您能够测试它吗?因为它对我不起作用。

Apparently, jquery-ui 1.8.4 sort of fixes the problem (see changelog):

  • Fixed: Combobox/Autocomplete doesn't
    save value unless control loses focus

Have you been able to test it? Because it doesn't work for me.

无可置疑 2024-09-18 18:21:38

我有一个方法来解决这个问题,

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

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

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

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

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

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

I have a method to solve this matter,

first, add this script to yours

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

and then in your submit clicking validataion scripts, add the script as below,

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

I found it really works though I think it is not the best way.

Sorry, it'a work-around.

找个人就嫁了吧 2024-09-18 18:21:38

为了扩展 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-subscribed') ,如果为 false,则不执行任何操作。

To exapand on Tvartom's answer, here's what I put in my page load code:

$('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;
  }
});

This automatically applies to all forms that have autocomplete inputs in them. You need to be careful with other form submit event callbacks, though - you need to check if form.data('already-submitted') and if it's false, do nothing.

别理我 2024-09-18 18:21:38

你可以添加吗

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

Can you add

submit: function(event,ui) {
// same thing as your change:
}
您的好友蓝忘机已上羡 2024-09-18 18:21:38

使用模糊而不是更改。就我而言,它有效!

Use blur instead of change. In my case it worked!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文