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

时间:2013-01-28 22:57:56

标签: jquery jquery-ui jquery-autocomplete jquery-ui-autocomplete

我正在努力扩展jQuery自动完成功能,以便特定项目默认具有焦点。开箱即用的功能非常好用,但并不完美。使用autoFocus选项,我可以自动关注第一项。

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

但是,我希望能够更好地控制关注哪个项目。如果用户输入“eng”并且我的来源返回的相关项目是:

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

我希望第三项英语默认处于焦点(即实际以用户输入开头的项目,即使我想显示其他结果)。理想情况下,我的源代码 - autocomplete.php - 能够指出哪个项目是默认焦点。

有什么想法吗?我甚至不确定如何开始。

2 个答案:

答案 0 :(得分:3)

利用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/(尝试搜索 E nglish或 S cots English)

代码使用本地数据源,但它应该与远程源一样好。


从服务器上选择的术语开始的焦点

扩展上面的示例,您可以调整发送数据的方式,以便在每次搜索时,服务器端代码决定选择哪个项目。您只需在要选择的项目上指定其他属性即可。例如,您的JSON响应可能如下所示:

[{"label":"American English","select":true},{"label":"British English"},{"label":"English"},{"label":"Scots 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,所以我不能说你将如何实现将select属性添加到JSON。看起来它会非常简单,甚至可能看起来像第一个使用正则表达式的示例中的JavaScript代码。

答案 1 :(得分:1)

我建议您应该以不同的方式查看映射数据,以便首先显示更高优先级的项目,例如以搜索词开头的单词。

然后,您可以按照自动完成/类别演示来分隔结果。这比尝试创建代码以更改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
        )

)

您必须进行一些排序,以便在发送到自动填充之前按等级对数据进行分组