jQuery自动完成

10
我有一个自动完成文本框需要响应两个事件:
1. 当用户在文本框中输入完毕时(我目前使用“focusout”来假定用户输入完毕。因此,如果用户从文本框中切换到其他地方,表示用户已经输入完毕。)
2. 当用户选择自动完成值列表中的项目时(我使用自动完成的“select”事件来确定)
问题:
当用户在自动完成值列表中选择一个项目时,事件链是这样的:首先调用“focusout”,然后是“select”。当处于“focusout”状态时,我只能访问用户输入的内容,而无法访问用户在自动完成值列表中选择的内容——这正是我所需要的。如何解决这个问题?
复现问题的步骤:
  1. In the text box, type the letter a
  2. Select ActionScript from the autocomplete list of values
  3. Observe console.debug messages:

    focusout event called
    a
    select event called
    ActionScript
    
以下是代码示例:
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
        <link href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/themes/base/jquery-ui.css" rel="stylesheet" type="text/css"/>
        <title>Data Matching</title>
    </head>
    <body>
        <form>
            <input id="1" type="text"></input>
            <input id="2" type="submit"></input>
        </form>

        <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.5/jquery.min.js"></script>
        <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/jquery-ui.min.js"></script>

        <script>
        $('#1').autocomplete(
        {
            select: function (event, ui)
            {
                "use strict";
                console.debug('select event called');
                console.debug(ui.item.value);
            },
            source: ["ActionScript", "AppleScript", "Asp", "BASIC", "C", "C++", "Clojure", "COBOL", "ColdFusion", "Erlang", "Fortran", "Groovy", "Haskell", "Java", "JavaScript", "Lisp", "Perl", "PHP", "Python", "Ruby", "Scala", "Scheme"],

            minLength: 1
        });

        $('#1').focusout(function ()
        {
            "use strict";
            console.debug('focusout event called');
            console.debug($(this).attr('value')); //  At this point, I need the value that was selected from autocomplete. I only get the value that the user typed, though
        });
        </script>
    </body>
</html>
2个回答

8
这正是为什么jQueryUI为autocomplete引入了一个特殊的change事件的原因:

如果值已更改,则在字段模糊时触发;ui.item指向所选项目。

此事件可以同时满足您的两个要求:

$("#1").autocomplete({
    /* snip */
    change: function(event, ui) {
        if (ui.item) {
            console.log("ui.item.value: " + ui.item.value);
        } else {
            console.log("ui.item.value is null");
        }
        console.log("this.value: " + this.value);
    }
});
  • 如果用户没有从自动完成候选列表中选择值,则ui.item将不被定义。
  • 另一方面,this.value将始终是正确的。

这是一个示例:http://jsfiddle.net/33GJb/


1
这个有效。我已经摆脱了focusout事件处理程序。谢谢。 - StackOverflowNewbie
我说这个好像不太符合要求:“当用户在自动完成值列表中选择一个项目”——因为更改事件只有在失焦时才会触发(即在从建议列表中选择项目后不会立即触发)。 - Jon Burgess
@JonoB:不是“完全”如此,但我相信(已经有一段时间了),OP的主要问题是他想要响应用户选择项目或手动输入项目。您也可以成功地将“更改”与“选择”结合使用。 - Andrew Whitaker
@AndrewWhitaker 好的,谢谢,正是我想的 - 只是想确认我没有写太多的代码。 - Jon Burgess

0
首先,仅供教育目的,重要的是让任何人都了解这些特定事件将始终按此顺序触发。在这种情况下,我认为有几种不同的方法可以解决问题,以下是我想出的两种方法:
一:构建应用程序,使用户选择的多个值(类型或已选)不会互相干扰。例如,如果应用程序正在自动更正拼写,并且有人在失去焦点时键入了“orphanag”,则查找最接近的拼写的代码将使用“orphanage”替换该值,然后如果有人实际上选择了“orphanages”,则它将使用所选值替换该值。除过度优化的愿望外,这里最可能没有问题。
二:在Javascript或Html元素(“data-corrected=false”)中设置一个标记值。在失去焦点时设置一个SetTimeout等待一段时间。然后,如果用户选择了一个值,则将您的标记值设置为true。当持续时间结束时,请检查标记值,如果为true,则不执行任何操作,否则使用输入字段中的值进行某些操作。

Erik,我正在考虑像你建议的那样的解决方案。我希望我不必走这条路,因为对我来说感觉有点hackish(但也许不是,也许这就是事情的本质,我必须处理它)。还有其他想法吗? - StackOverflowNewbie
不是真的,如果你不喜欢一个,那么两个就是一种信号传递方法,有点像线程的工作方式。 - Erik Philips
是的... #2 可能更适合我的问题。 - StackOverflowNewbie
如果你不急需,或许你可以等一两天再看看是否有其他解决方案。 - Erik Philips

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接