I have an input field for locations with jquery-ui-autocomplete.
After some additional research and many tries, I found a way to do it. This is specific for Django, so any other more generic proposal is of course more than welcome.
The solution is based on this tutorial, although with some modifications.
First of all, import jQuery and jQueryUI in the template:
<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>
Afterwards, in the template itself, you need to assign an id to the input tag. Note that this id is how jquery will identify in which form to run the autocomplete.
<div class="ui-widget">
<label for="cities">City: </label>
<input id="autocomplete-cities">
</div>
The javascript code is as follows:
<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>
And urls.py
file needs to be modified accordingly:
# urls.py
import yourapp.views
urlpatterns = [
...,
url(r'^api/get_city_names/', yourapp.views.get_city_names),
...,
]
And finally create the django view. The name of the function has to be the same as the one written in urls.py
and the one written in the source
of the javascript.
#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)
And the autocomplete should work.
You are almost there. You can use the response
function (see in API) to remove the alternate spellings from the results. Also put the best spelling ("Mallorca" in this case) last. Check this out, I hope the comments are enough to get the logic. Try to type "Ma", or "Maj" and select the only option. In both cases it will display "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>