4

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

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

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

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

我希望第三个项目English默认成为焦点(即,实际上以用户输入开头的项目,即使我想显示其他结果)。理想情况下,我的来源 - autocomplete.php - 将能够指示哪个项目将成为默认焦点。

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

4

2 回答 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/(尝试搜索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 代码。

于 2013-01-29T02:52:00.023 回答
2

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

然后,您可以按照 AutoComplete/categories 演示来分离您的结果。这将比尝试创建代码来更改要容易得多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
        )

)

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

于 2013-01-29T02:41:12.793 回答