【问题标题】:How to suggest similar words in autocomplete如何在自动完成中建议相似的词
【发布时间】:2017-02-14 11:09:29
【问题描述】:

我有一个带有 jquery-ui-autocomplete 的位置输入字段。

<script type="text/javascript">
    $(document).ready(function(){
        var location_input=$('input[id="location-autocomplete"]');
        var cityNames = [
            { value: 'Mallorca' },
            { value: 'Berlin' },
            { value: 'London' },
            // many other elements
        ];
        location_input.autocomplete({
          source: cityNames,
          minLength: 2
        });
      } );

    //   keeps same width as box
      jQuery.ui.autocomplete.prototype._resizeMenu = function () {
          var ul = this.menu.element;
          ul.outerWidth(this.element.outerWidth());
        }
</script>

但是,我不喜欢同一个位置可以有不同名称的情况。

例如,假设用户想要寻找马略卡岛。他可以写:MallorcaMajorcaPalma de MallorcaPMIPalma .

我的第一个想法是使用label 属性

var cityNames = [
    { value: 'Mallorca', label: 'Palma de Mallorca' },
    { value: 'Mallorca', label: 'Mallorca' },
    { value: 'Mallorca', label: 'Majorca' },
    // etc
    ];

但是,这可能非常令人困惑。编写 Ma 自动完成将显示 MallorcaPalma de MallorcaMajorca,即使它们是同一个地方。

我希望在键入 Ma 时,用户只会得到一个建议。同样,无论用户输入 MajMal 还是 Pal,他都应该只得到一个关于 Mallorca 的建议词。

理想情况下,一个名为input 的附加属性作为要搜索的输入关键字会是完美的。然后,拥有一个属性为valueinput 的数组就可以了。不幸的是,我在文档中没有找到这样的东西。

如您所见,我使用array 作为源类型。对于我读到的内容,也许function 类型可以让我做这样的事情,但我不清楚如何做,因为我对 js 不是很熟悉,也没有找到任何明确的例子。

我怎样才能以简单的方式实现这一目标?

【问题讨论】:

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


    【解决方案1】:

    经过一些额外的研究和多次尝试,我找到了一种方法。这是特定于 Django 的,因此任何其他更通用的提议当然都非常受欢迎。

    该解决方案基于this tutorial,但进行了一些修改。


    首先在模板中导入jQuery和jQueryUI:

    <link rel="stylesheet" href="http://code.jquery.com/ui/1.8.18/themes/base/jquery-ui.css" type="text/css" media="all" />
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/jquery-ui.min.js" type="text/javascript"></script>
    

    然后,在模板本身中,您需要为输入标签分配一个 id。请注意,此 id 是 jquery 将如何识别以哪种形式运行自动完成的方式。

    <div class="ui-widget">
      <label for="cities">City: </label>
      <input id="autocomplete-cities">
    </div>
    

    javascript代码如下:

    <script type="text/javascript">
        $(document).ready(function(){
            var location_input=$('input[id="autocomplete-city"]');
            location_input.autocomplete({
              source: "/api/get_city_names/",
              minLength: 2
            });
          } );
    
        //   keeps same width as box
          jQuery.ui.autocomplete.prototype._resizeMenu = function () {
              var ul = this.menu.element;
              ul.outerWidth(this.element.outerWidth());
            }
    </script>
    

    并且urls.py文件需要相应修改:

    # urls.py
    
    import yourapp.views
    
    urlpatterns = [
        ...,
        url(r'^api/get_city_names/', yourapp.views.get_city_names),
        ...,
    ]
    

    最后创建 django 视图。函数名必须和javascript的urls.py写的和source写的一样。

    #views.py
    
    import json
    
    def get_city_names(request):
    
        #what was in the question an array is now a python list of dicts.
        #it can also be in some other file and just imported.
        all_city_names = [
        { good_name: 'Mallorca', input_name: 'Palma de Mallorca' },
        { good_name: 'Mallorca', input_name: 'Mallorca' },
        { good_name: 'Mallorca', input_name: 'Majorca' },
        # etc
        ]
    
        if request.is_ajax():
            q = request.GET.get('term', '')
    
            city_names = [c['good_name'] for c in all_city_names if q in c["input_name"]]
            city_names = set(city_names) #removing duplicates
    
            results = []
            for cn in city_names:
                cn_json = {'value': cn}
                results.append(cn_json)
            data = json.dumps(results)
        else:
            data = 'fail'
        mimetype = 'application/json'
        return HttpResponse(data, mimetype)
    

    自动完成功能应该可以工作。

    【讨论】:

      【解决方案2】:

      你快到了。您可以使用 response 函数 (see in API) 从结果中删除替代拼写。还要将最好的拼写(在这种情况下为“Mallorca”)放在最后。看看这个,我希望 cmets 足以理解逻辑。尝试输入“Ma”或“Maj”并选择唯一的选项。在这两种情况下,它都会显示“Mallorca”

       $( function() {
          var availableTags = [      
          { value: 'Mallorca', label: 'Palma de Mallorca' },
          { value: 'Mallorca', label: 'Majorca' },
          { value: 'Mallorca', label: 'Mallorca' },
          { value: 'Madrid', label: 'Madrid' }
          ];
          $( "#tags" ).autocomplete({
            source: availableTags,      
            response: function( event, ui ) {
              var added = [];//Keep here the unique labels that are already in the list
              for(var i=ui.content.length-1;i>=0;i--){//Start a loop, itterate all items backwards
                var cur = ui.content[i].value;//Value of the item
                if($.inArray(cur,added)==-1){//If not already loaded
                  added.push(cur);//Put the new item in the list
                }else{            
                  ui.content.splice(i,1);//If already loaded remove it from the results
                }
              }        
            }
          });
        } );
      <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
      <link href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css" rel="stylesheet"/>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
      <div class="ui-widget">
        <label for="tags">Tags: </label>
        <input id="tags">
      </div>

      【讨论】:

      • 感谢您的回答!我只是在想出另一种方法后才看到它。无论如何,您的 sn-p 似乎有效,并且该解决方案不仅适用于 django,就像我的一样,所以我会将其标记为已接受的答案。
      猜你喜欢
      • 2013-10-20
      • 1970-01-01
      • 2011-08-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-22
      相关资源
      最近更新 更多