如何在自动完成中建议相似词
How to suggest similar words in autocomplete
我有一个带有 jquery-ui- 自动完成功能的位置输入字段。
<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>
但是,我对同一位置可以有不同名称的情况不满意。
例如,假设用户想要查找 Mallorca。他可以写:Mallorca、Majorca、Palma de Mallorca、PMI 或 帕尔马.
我的第一个想法是使用 label
属性
var cityNames = [
{ value: 'Mallorca', label: 'Palma de Mallorca' },
{ value: 'Mallorca', label: 'Mallorca' },
{ value: 'Mallorca', label: 'Majorca' },
// etc
];
但是,这可能会让人非常困惑。写入 Ma 自动完成将显示 Mallorca、Palma de Mallorca 和 Majorca,即使他们在同一个地方。
我希望用户在键入 Ma 时只会得到一个建议。同样,无论用户输入 Maj、Mal 还是 Pal,他都应该只得到一个马略卡岛的建议术语。
理想情况下,一个名为 input
的附加 属性 作为要搜索的输入关键字将是完美的。然后,拥有一个属性为 value
和 input
的数组就可以了。不幸的是,我没有在文档中找到这样的东西。
如您所见,我使用 array
作为源类型。对于我读到的内容,也许 function
类型可以让我做这样的事情,但我不清楚如何做,因为我对 js 不是很熟悉,也没有找到任何明确的例子。
我怎样才能以简单的方式实现它?
你快到了。您可以使用 response
函数 (see in API) 从结果中删除备选拼写。还要将最佳拼写(在本例中为 "Mallorca")放在最后。看看这个,我希望这些评论足以让你明白逻辑。尝试键入 "Ma" 或 "Maj" 和 select 唯一的选项。在这两种情况下,它都会显示 "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>
经过一些额外的研究和多次尝试,我找到了一种方法。这是 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 视图。函数名必须和urls.py
中写的和javascript中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)
并且自动完成应该可以工作。
我有一个带有 jquery-ui- 自动完成功能的位置输入字段。
<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>
但是,我对同一位置可以有不同名称的情况不满意。
例如,假设用户想要查找 Mallorca。他可以写:Mallorca、Majorca、Palma de Mallorca、PMI 或 帕尔马.
我的第一个想法是使用 label
属性
var cityNames = [
{ value: 'Mallorca', label: 'Palma de Mallorca' },
{ value: 'Mallorca', label: 'Mallorca' },
{ value: 'Mallorca', label: 'Majorca' },
// etc
];
但是,这可能会让人非常困惑。写入 Ma 自动完成将显示 Mallorca、Palma de Mallorca 和 Majorca,即使他们在同一个地方。
我希望用户在键入 Ma 时只会得到一个建议。同样,无论用户输入 Maj、Mal 还是 Pal,他都应该只得到一个马略卡岛的建议术语。
理想情况下,一个名为 input
的附加 属性 作为要搜索的输入关键字将是完美的。然后,拥有一个属性为 value
和 input
的数组就可以了。不幸的是,我没有在文档中找到这样的东西。
如您所见,我使用 array
作为源类型。对于我读到的内容,也许 function
类型可以让我做这样的事情,但我不清楚如何做,因为我对 js 不是很熟悉,也没有找到任何明确的例子。
我怎样才能以简单的方式实现它?
你快到了。您可以使用 response
函数 (see in API) 从结果中删除备选拼写。还要将最佳拼写(在本例中为 "Mallorca")放在最后。看看这个,我希望这些评论足以让你明白逻辑。尝试键入 "Ma" 或 "Maj" 和 select 唯一的选项。在这两种情况下,它都会显示 "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>
经过一些额外的研究和多次尝试,我找到了一种方法。这是 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 视图。函数名必须和urls.py
中写的和javascript中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)
并且自动完成应该可以工作。