Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Suggestions #32

Open
wants to merge 15 commits into
base: master
Choose a base branch
from
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