Skip to content
Open
25 changes: 25 additions & 0 deletions dist/assets/css/suggest.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
.list-group-item {
padding: .25rem 0.25rem !important;
font-size: small !important;
}

.selected {
background: #e2e2e2;
}

.list-group-item:hover {
background: #f1f1f1;
}

.fas {
height: 100%;
}

.dropdown-menu {
z-index: 2000 !important;
}

.dropdown-menu {
padding-top: 0;
padding-bottom: 0;
}
140 changes: 140 additions & 0 deletions dist/assets/js/suggest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
var liSelected;

document.addEventListener("keydown", event => {
if(event.keyCode === 40){
if(liSelected){
liSelected.removeClass('selected');
next = liSelected.next();
if(next.length > 0){
liSelected = next.addClass('selected');
}else{
liSelected = $('.list-group-item').eq(0).addClass('selected');
}
}else{
liSelected = $('.list-group-item').eq(0).addClass('selected');
}
}else if(event.keyCode === 38){
if(liSelected){
liSelected.removeClass('selected');
next = liSelected.prev();
if(next.length > 0){
liSelected = next.addClass('selected');
}else{
liSelected = $('.list-group-item').last().addClass('selected');
}
}else{
liSelected = $('.list-group-item').last().addClass('selected');
}
}
if(liSelected && (event.keyCode === 40 || event.keyCode === 38)){
console.log(liSelected[0].innerText);
document.getElementById('q').value = liSelected[0].innerText;
}

});

// This function provides suggestions in the form of unordered list.
function suggester() {

// If suggestions end-point is not configured, return without any computation
if(get_config_value('Suggestions_Url') == "")
return;

// List of languages to search for
languages = ['zh', 'sp', 'en', 'ar', 'fr', 'ru', 'pt', 'de', 'ja', 'ko'];
// Finding the browser language
browser_lang = navigator.language;
browser_lang = browser_lang.substr(0,2);
tags = ['addr'];
languages.forEach(function(language, index){
tags.push('addr:' + language);
});

var query = document.getElementById("q").value;
var xmlhttp = new XMLHttpRequest();

// The API url to get suggestions - Update this with your server URL
var url = encodeURI(get_config_value('Suggestions_Url') + query);

// This is executed after the results are fetched
xmlhttp.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
var hits = JSON.parse(this.responseText);
length =Object.keys(hits).length;
// list_items string will be used to form the unordered list entries.
var list_items = '';
for (var i = 0; i < length; i++) {
added = false;
// This part adds one tag for each of the received results. Addresss in Broweser default language is returned in paranthesis for clarity.
tags.forEach(function (value, index) {
if(hits[i][value] && hits[i][value].includes(query) && hits[i]['addr:'+browser_lang] && !added)
{
res = ''
if(value.slice(2) != browser_lang)
{
res += '(' + hits[i]['addr:'+browser_lang] + ') ';
}
else
return;
res += hits[i][value];
if(hits[i].country_code)
res += ', ' + hits[i].country_code;
if(hits[i].postcode)
res += ', ' + hits[i].postcode;
if (getIcon({'category': hits[i].category, 'type': hits[i].type}))
{
icon_path = get_config_value('Images_Base_Url') + getIcon({'category': hits[i].category, 'type': hits[i].type}) + '.p.20.png';
list_items += "<li class='list-group-item' onclick='putText("+ i +")'><div class='row'><div class='col' id="+i+">" + res + "</div><img class='fas mr-4 mapicons' src='" + icon_path + "'></div></li>";added = true;
}
else
{
list_items += "<li class='list-group-item' onclick='putText("+ i +")'><div class='row'><div class='col' id="+i+">" + res + "</div></div></li>";added = true;

}
}
});
// This is to handle cases where no returned language text matches straightaway.
// Then we return browser default language or default `addr`.
if(!added)
{
if(hits[i]['addr:'+browser_lang])
res = hits[i]['addr:'+browser_lang];
else
res = hits[i].addr;
if(hits[i].country_code)
res += ', ' + hits[i].country_code;
if(hits[i].postcode)
res += ', ' + hits[i].postcode;
if (getIcon({'category': hits[i].category, 'type': hits[i].type}))
{
icon_path = get_config_value('Images_Base_Url') + getIcon({'category': hits[i].category, 'type': hits[i].type}) + '.p.20.png';
list_items += "<li class='list-group-item' onclick='putText("+ i +")'><div class='row'><div class='col' id="+i+">" + res + "</div><img class='fas mr-4 mapicons' src='" + icon_path + "'></div></li>";added = true;
}
else
{
list_items += "<li class='list-group-item' onclick='putText("+ i +")'><div class='row'><div class='col' id="+i+">" + res + "</div></div></li>";added = true;

}
}
}

// We are setting the unordered list's inner HTML as the list_items
document.getElementById('suglist').innerHTML = list_items;

// Making sure the dropdown is expanded
document.getElementById("dd").classList.add("open");
document.getElementById("dd").classList.add("show");
document.getElementById("suglist").classList.add("show");
document.getElementById("q").setAttribute("aria-expanded", true);
}
};

xmlhttp.open("GET", url, true);
xmlhttp.send();
}

// Utility to put text on the search bar when clicked on a suggestion
function putText(id)
{
document.getElementById("q").value = document.getElementById(id).innerHTML;
}
3 changes: 3 additions & 0 deletions dist/config.example.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ var Nominatim_Config = [];

// Nominatim_Config['Images_Base_Url'] = '/mapicons/';

// Url to provide suggestions
// Nominatim_Config['Suggestions_Url'] = '';

// If the API should return polygons to be displayed on the map
// Nominatim_Config['Search_AreaPolygons'] = 1;
// Nominatim_Config['Reverse_Default_Search_Zoom'] = 18;
Expand Down
12 changes: 10 additions & 2 deletions dist/search.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
<link href="assets/css/common.css" rel="stylesheet" />
<link href="assets/css/search.css" rel="stylesheet" type="text/css" />
<link href="assets/css/details.css" rel="stylesheet" type="text/css" />
<link href="assets/css/suggest.css" rel="stylesheet" type="text/css" />
</head>
<body id="BODYID">

Expand Down Expand Up @@ -110,6 +111,7 @@ <h4 class="modal-title">Report a problem</h4>
<script src="assets/js/Control.MiniMap.min.js"></script>
<script src="assets/js/handlebars.min.js"></script>
<script src="assets/js/url-search-params.js"></script>
<script src="assets/js/suggest.js"></script>

<script src="config.js"></script>
<script src="handlebar_helpers.js"></script>
Expand Down Expand Up @@ -144,12 +146,18 @@ <h4 class="modal-title">Report a problem</h4>
<div class="tab-content p-2">
<div class="tab-pane {{#unless hStructured}}active{{/unless}}" id="simple" role="tabpanel">
<form class="form-inline" role="search" accept-charset="UTF-8" action="">
<input id="q"
<div id="dd" class="dropdown">
<input id="q"
name="q"
type="text"
oninput="suggester()"
class="form-control form-control-sm"
placeholder="Search"
placeholder="Search with suggestions"
autocomplete="off"
data-toggle="dropdown"
value="{{sQuery}}" />
<ul id="suglist" class="dropdown-menu"></ul>
</div>

<div class="form-group search-button-group">
<button type="submit" class="btn btn-primary btn-sm mx-1">Search</button>
Expand Down