PageSourceSearch

https://osmbuildings.org/js/Search.js

js osmbuildings.org collected 2026-09-24 18:26:56 UTC 3,349 bytes, 118 lines download raw bytes

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.