1 2function Search($container) { 3 this.$resultList = $('#search-results'); 4 5 this.$inputField = $container.find('input'); 6 this.$inputField.keydown(function(e) { 7 if (e.keyCode !== 13) { 8 return; 9 } 10 var query = this.$inputField.val(); 11 if (query) { 12 this.$inputField.blur(); // for iOS in order to close the keyboard 13 this.search(query); 14 } 15 e.preventDefault(); 16 }.bind(this)); 17 18 $('#search-trigger-button').click(function(e) { 19 var query = this.$inputField.val(); 20 if (query) { 21 this.search(query); 22 } 23 }.bind(this)); 24 25 this.position = {}; 26 app.on('PARAMS_READY', function(params) { 27 // do initial search 28 if (params.q) { 29 this.$inputField.val(params.q); 30 this.search(params.q); 31 return; 32 } 33 34 // do initial geocoding 35 if (params.lat !== undefined && params.lon !== undefined) { 36 this.position = { lat: params.lat, lon: params.lon }; 37 this.geocode(this.position); 38 } 39 }.bind(this)); 40 41 app.on('MAP_CHANGED', function(params) { 42 if (this.position === undefined || geoDistance(this.position, params)>10) { 43 this.geocode(this.position); 44 } 45 }.bind(this)); 46} 47 48Search.SEARCH_URL = 'https://nominatim.openstreetmap.org/search?format=json&polygon_geojson=1&limit=5&q={query}'; 49Search.GEOCODE_URL = 'https://nominatim.openstreetmap.org/reverse?format=json&lat={lat}&lon={lon}&zoom=18&addressdetails=1'; 50 51Search.prototype = {}; 52 53Search.prototype.search = function(query) { 54 this.$resultList.empty(); 55 this.isLoading = true; 56 $.ajax(Search.SEARCH_URL.replace('{query}', encodeURIComponent(query))).done(function(res) { 57 this.isLoading = false; 58 this.showResults(res); 59 }.bind(this)); 60}; 61 62Search.prototype.selectResult = function(item) { 63 this.position = { lat: item.lat, lon: item.lon }; 64 this.geocode(this.position); 65 app.emit('PLACE_SELECTED', item); 66}; 67 68Search.prototype.showResults = function(res) { 69 // this.$resultList.empty(); 70 71 if (!res.length) { 72 $('<li class="search-error">no results</li>').appendTo(this.$resultList); 73 app.emit('SEARCH_ERROR'); 74 return; 75 } 76 77 res.forEach(function(item) { 78 var type = item.class === 'place' ? item.type : item.type + ' ' + item.class; 79 $('<li><a href="#">' + item.display_name + '</a><div class="search-result-type">' + type + '</div></li>') 80 .appendTo(this.$resultList).click(function(e) { 81 this.selectResult(item); 82 }.bind(this)); 83 }.bind(this)); 84 if (res.length) { 85 this.selectResult(res[0]); 86 } 87 88 app.emit('SEARCH_RESULT', res); 89}; 90 91Search.prototype.geocode = function(position) { 92 if (this.isLoading) { 93 return; 94 } 95 this.isLoading = true; 96 $.ajax(Search.GEOCODE_URL.replace('{lat}', position.lat).replace('{lon}', position.lon)).done(function(res) { 97 this.isLoading = false; 98 if (res) { 99 app.emit('GEOCODE_RESULT', res); 100 } 101 }.bind(this)); 102}; 103 104//*************************************************************************** 105 106function geoDistance(a, b) { 107 var 108 radlat1 = Math.PI*a.lat/180, 109 radlat2 = Math.PI*b.lat/180, 110 theta = a.lon - b.lon, 111 radtheta = Math.PI*theta/180, 112 dist = Math.sin(radlat1)*Math.sin(radlat2) + Math.cos(radlat1)*Math.cos(radlat2)*Math.cos(radtheta); 113 dist = Math.acos(dist); 114 dist = dist*180/Math.PI; 115 dist = dist*60*1.1515; 116 dist = dist*1.609344; // kilometers 117 return dist; 118}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.