聚焦于jQuery自动完成结果(不一定是第一个)

4

我在尝试扩展jQuery自动完成功能,使得默认情况下特定的项目获得焦点。开箱即用的功能效果还不错,但并非完美。使用autoFocus选项,可以自动将焦点放在第一个项目上。

$( "#input" ).autocomplete({
    source: "autocomplete.php",
    minLength: 1,
    autoFocus: true
});

不过,我希望能够更好地控制哪个项目获得焦点。如果用户输入“eng”,而我的数据源返回的相关项目如下:

  • 美式英语
  • 英式英语
  • 英语
  • 苏格兰英语

我希望第三项英语默认获得焦点(即实际以用户输入开头的项目,即使我想显示其他结果)。理想情况下,我的数据源autocomplete.php将能够指示哪个项目应该是默认焦点。

有任何想法吗?我甚至不知道如何开始。

2个回答

4
有一个简单的方法可以实现这个,利用open事件。你可以让客户端代码处理选择默认项,或者附加一个属性来选中你想要的项。我将介绍这两种选择:

聚焦于以某个术语开头的建议,并在客户端进行选择:

$("input").autocomplete({
    source: /* ... */,
    open: function (event, ui) {
        var menu = $(this).data("uiAutocomplete").menu
            , i = 0
            , $items = $('li', menu.element)
            , item
            , text
            , startsWith = new RegExp("^" + this.value, "i");

        for (; i < $items.length && !item; i++) {
            text = $items.eq(i).text();
            if (startsWith.test(text)) {
                item = $items.eq(i);
            }
        }

        if (item) {
            menu.focus(null, item);
        }
    }
});

基本思路是在自动完成菜单打开时执行以下操作:
  • 构建一个正则表达式来查找以搜索词开头的单词。
  • 遍历每个菜单项,并测试其文本与正则表达式匹配。如果找到匹配项,则停止遍历并存储该值。
  • 如果我们检索到一个值,请使用菜单上的focus方法突出显示该项。

示例:http://jsfiddle.net/J5rVP/40/(尝试搜索英语苏格兰英语

代码使用本地数据源,但远程源也应该同样适用。


聚焦于以搜索词开头的建议,在服务器上选择

在上述示例的基础上,您可以调整发送数据的方式,以便在每次搜索时您的服务器端代码决定选择哪个项目。您可以通过仅在要选择的项目上指定附加属性来实现此目的。例如,您的JSON响应可能如下所示:

[{"label":"American English","select":true},{"label":"British English"},{"label":"English"},{"label":"Scots English"}]

请注意 "American English" 上的 select 属性。这告诉自动完成我们想默认选择该项。
然后,您需要更新小部件初始化代码以利用上述 open 事件。不过,这一次我们只是在搜索具有 select 属性的项。
$("input").autocomplete({
    source: "autocomplete.php",
    open: function (event, ui) {
        var menu = $(this).data("uiAutocomplete").menu,
            i = 0,
            $items = $('li', menu.element),
            item,
            data;

        for (; i < $items.length && !item; i++) {
            data = $items.eq(i).data("ui-autocomplete-item");
            if (data.select) {
                item = $items.eq(i);
            }
        }

        if (item) {
            menu.focus(null, item);
        }
    }
});
示例: http://jsfiddle.net/J5rVP/42/ 请注意,在上述示例中,始终选择美式英语。由于自动完成每次用户键入时都会发出新请求,因此您的服务器将响应不同的建议数据,因此选择的项目将不同。
此外,我不知道PHP,因此无法说明如何实现向JSON添加select属性。看起来这很简单,甚至可能类似于第一个示例中使用正则表达式的JavaScript代码。

类型错误:$(...).data(...)未定义var menu = $(this).data(“uiAutocomplete”).menu这是在Firebug中的 =(,当我尝试实现第一个解决方案时。 - justian17
@Andrew Whitaker,抱歉翻出了一篇旧帖子,但这是在搜索时出现的。我想在此版本的组合框小部件中实现类似于此的东西,但无法弄清楚...您有可能看一下并查看如何可能吗?http://jsfiddle.net/7jf7cngd/102/ - JoMojo

2
我建议您以不同的方式查看映射数据,以便首先显示优先级更高的项目,例如以搜索词开头的单词。
然后,您可以按照自动完成/类别演示进行操作,以分离结果。这比尝试创建代码来更改autoFocus要容易得多,您的更高排名将位于顶部,并且焦点将从那里开始。

http://jqueryui.com/autocomplete/#categories

这是一个你可以使用的概念来对结果进行排名:
function rankResult($str, $term){
     /* 0 is first letters, 1 is in first word, 2 is starts another word, 3 is in word not first word*/
     $words=explode(' ', $str); 
     if(stripos($words[0],$term) !==false){
        return stripos($words[0],$term)==0 ? 0 : 1;
     }else{
        $rank=3;
        for( $i=1; $i< count( $words); $i++){
            if(stripos($words[$i],$term)===0){
                $rank=2;
            }
        }
        return $rank;
     }      
}

 $rank = rankResult('English', 'eng'); /*=> 0 */

循环遍历:
  array('American English','British English','English','Scots English','HasEngInIt');

返回:
Array
(
    [0] => Array
        (
            [label] => American English
            [rank] => 2
        )

    [1] => Array
        (
            [label] => British English
            [rank] => 2
        )

    [2] => Array
        (
            [label] => English
            [rank] => 0
        )

    [3] => Array
        (
            [label] => Scots English
            [rank] => 2
        )

    [4] => Array
        (
            [label] => HasEngInIt
            [rank] => 1
        )

)

你需要进行一些排序,使数据按照等级分组后再发送到自动完成功能。

我考虑过这个问题,但最后决定保持字母顺序的重要性,因为列表中可能有数百个项目。 - Mike C
我的想法是保持组内字母顺序。另一件事情是可以在每个结果中突出显示术语。无论如何,不确定您将如何管理“数百”个结果的演示文稿。发送太多结果不会很用户友好。 - charlietfl

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