X-Git-Url: https://git.openstreetmap.org/nominatim-ui.git/blobdiff_plain/5de297f31b68eb92019f3d4c973a837a368a83af..a410d476a22053a8e7ffda483efbb1959be9d713:/dist/assets/js/nominatim-ui.js diff --git a/dist/assets/js/nominatim-ui.js b/dist/assets/js/nominatim-ui.js index d213626..54eaa75 100644 --- a/dist/assets/js/nominatim-ui.js +++ b/dist/assets/js/nominatim-ui.js @@ -3,13 +3,33 @@ var map; var last_click_latlng; +// ********************************************************* +// DEFAULTS +// ********************************************************* + +var Nominatim_Config_Defaults = { + Nominatim_API_Endpoint: 'http://localhost/nominatim/', + Images_Base_Url: '/mapicons/', + Search_AreaPolygons: 1, + Reverse_Default_Search_Zoom: 18, + Map_Default_Lat: 20.0, + Map_Default_Lon: 0.0, + Map_Default_Zoom: 2, + Map_Tile_URL: 'https://{s}.tile.osm.org/{z}/{x}/{y}.png', + Map_Tile_Attribution: 'OpenStreetMap contributors' +}; // ********************************************************* // HELPERS // ********************************************************* + function get_config_value(str, default_val) { - return (typeof Nominatim_Config[str] !== 'undefined' ? Nominatim_Config[str] : default_val); + var value = ((typeof Nominatim_Config !== 'undefined') + && (typeof Nominatim_Config[str] !== 'undefined')) + ? Nominatim_Config[str] + : Nominatim_Config_Defaults[str]; + return (typeof value !== 'undefined' ? value : default_val); } function parse_and_normalize_geojson_string(part) { @@ -60,29 +80,52 @@ function map_viewbox_as_string() { // PAGE HELPERS // ********************************************************* -function fetch_from_api(endpoint_name, params, callback) { +function generate_full_api_url(endpoint_name, params) { + // // `&a=&b=&c=1` => '&c=1' - var param_names = Object.keys(params); for (var i = 0; i < param_names.length; i += 1) { - var val = param_names[i]; + var val = params[param_names[i]]; if (typeof (val) === 'undefined' || val === '' || val === null) { - delete param_names[i]; + delete params[param_names[i]]; } } var api_url = get_config_value('Nominatim_API_Endpoint') + endpoint_name + '.php?' + $.param(params); - if (endpoint_name !== 'status') { - $('#api-request-link').attr('href', api_url); + return api_url; +} + +function update_last_updated(endpoint_name, params) { + if (endpoint_name === 'status') return; + + var api_url = generate_full_api_url(endpoint_name, params); + $('#last-updated').show(); + + $('#api-request a').attr('href', api_url); + $('#api-request').show(); + + if (endpoint_name === 'search' || endpoint_name === 'reverse') { + $('#api-request-debug a').attr('href', api_url + '&debug=1'); + $('#api-request-debug').show(); + } else { + $('#api-request-debug').hide(); } +} + +function fetch_from_api(endpoint_name, params, callback) { + var api_url = generate_full_api_url(endpoint_name, params); $.get(api_url, function (data) { + if (endpoint_name !== 'status') { + update_last_updated(endpoint_name, params); + } callback(data); }); } function update_data_date() { fetch_from_api('status', { format: 'json' }, function (data) { + $('#last-updated').show(); $('#data-date').text(data.data_updated); }); } @@ -111,16 +154,21 @@ function hide_error() { } -$(document).ajaxError(function (event, jqXHR, ajaxSettings/* , thrownError */) { - // console.log(thrownError); - // console.log(ajaxSettings); - var url = ajaxSettings.url; - show_error('Error fetching results from ' + url + ''); -}); - - jQuery(document).ready(function () { hide_error(); + + $('#last-updated').hide(); + + $(document).ajaxStart(function () { + $('#loading').fadeIn('fast'); + }).ajaxComplete(function () { + $('#loading').fadeOut('fast'); + }).ajaxError(function (event, jqXHR, ajaxSettings/* , thrownError */) { + // console.log(thrownError); + // console.log(ajaxSettings); + var url = ajaxSettings.url; + show_error('Error fetching results from ' + url + ''); + }); }); // ********************************************************* // DETAILS PAGE @@ -178,8 +226,7 @@ function init_map_on_detail_page(lat, lon, geojson) { } -jQuery(document).ready(function () { - if (!$('#details-page').length) { return; } +function details_page_load() { var search_params = new URLSearchParams(window.location.search); // var place_id = search_params.get('place_id'); @@ -188,6 +235,7 @@ jQuery(document).ready(function () { place_id: search_params.get('place_id'), osmtype: search_params.get('osmtype'), osmid: search_params.get('osmid'), + class: search_params.get('class'), keywords: search_params.get('keywords'), addressdetails: 1, hierarchy: (search_params.get('hierarchy') === '1' ? 1 : 0), @@ -235,7 +283,7 @@ jQuery(document).ready(function () { alert('invalid input'); } }); -}); +} // ********************************************************* // FORWARD/REVERSE SEARCH PAGE @@ -283,7 +331,7 @@ function display_map_position(mouse_lat_lng) { }; $('#switch-to-reverse').attr('href', 'reverse.html?' + $.param(reverse_params)); - $('input#use_viewbox').trigger('change'); + $('input.api-param-setting').trigger('change'); } function init_map_on_search_page(is_reverse_search, nominatim_results, request_lat, @@ -355,7 +403,7 @@ function init_map_on_search_page(is_reverse_search, nominatim_results, request_l var container = L.DomUtil.create('div', 'my-custom-control'); $(container).text('show map bounds') - .addClass('leaflet-bar btn btn-sm btn-default') + .addClass('leaflet-bar btn btn-sm btn-outline-secondary') .on('click', function (e) { e.preventDefault(); e.stopPropagation(); @@ -408,7 +456,21 @@ function init_map_on_search_page(is_reverse_search, nominatim_results, request_l update_viewbox_field(); }); + $('input#option_bounded').on('change', function () { + $('input[name=bounded]') + .val($('input#option_bounded') + .prop('checked') ? '1' : ''); + }); + + $('input#option_dedupe').on('change', function () { + $('input[name=dedupe]') + .val($('input#option_dedupe') + .prop('checked') ? '' : '0'); + }); + $('input[data-api-param]').on('change', function (e) { + $('input[name=' + $(e.target).data('api-param') + ']').val(e.target.value); + }); function get_result_element(position) { @@ -533,15 +595,9 @@ function init_map_on_search_page(is_reverse_search, nominatim_results, request_l +function search_page_load() { - - - -jQuery(document).ready(function () { - // - if (!$('#search-page,#reverse-page').length) { return; } - - var is_reverse_search = !!($('#reverse-page').length); + var is_reverse_search = window.location.pathname.match(/reverse/); var search_params = new URLSearchParams(window.location.search); @@ -586,6 +642,7 @@ jQuery(document).ready(function () { aPlace = null; } + context.bSearchRan = true; context.aPlace = aPlace; render_template($('main'), 'reversepage-template', context); @@ -619,39 +676,69 @@ jQuery(document).ready(function () { } else { api_request_params = { q: search_params.get('q'), - polygon_geojson: search_params.get('polygon_geojson') ? 1 : 0, + street: search_params.get('street'), + city: search_params.get('city'), + county: search_params.get('county'), + state: search_params.get('state'), + country: search_params.get('country'), + postalcode: search_params.get('postalcode'), + polygon_geojson: get_config_value('Search_AreaPolygons', false) ? 1 : 0, viewbox: search_params.get('viewbox'), + bounded: search_params.get('bounded'), + dedupe: search_params.get('dedupe'), + 'accept-language': search_params.get('accept-language'), + countrycodes: search_params.get('countrycodes'), + limit: search_params.get('limit'), + polygon_threshold: search_params.get('polygon_threshold'), exclude_place_ids: search_params.get('exclude_place_ids'), format: 'jsonv2' }; context = { - // aSearchResults: aResults, sQuery: api_request_params.q, sViewBox: search_params.get('viewbox'), - env: Nominatim_Config - // sMoreURL: 'x' + sBounded: search_params.get('bounded'), + sDedupe: search_params.get('dedupe'), + sLang: search_params.get('accept-language'), + sCCode: search_params.get('countrycodes'), + sLimit: search_params.get('limit'), + sPolyThreshold: search_params.get('polygon_threshold'), + env: {} }; - if (api_request_params.q) { + if (api_request_params.street || api_request_params.city || api_request_params.county + || api_request_params.state || api_request_params.country || api_request_params.postalcode) { + context.hStructured = { + street: api_request_params.street, + city: api_request_params.city, + county: api_request_params.county, + state: api_request_params.state, + country: api_request_params.country, + postalcode: api_request_params.postalcode + }; + } + + if (api_request_params.q || context.hStructured) { fetch_from_api('search', api_request_params, function (aResults) { + context.bSearchRan = true; context.aSearchResults = aResults; - if (aResults.length >= 10) { - var aExcludePlaceIds = []; - if (search_params.has('exclude_place_ids')) { - aExcludePlaceIds.search_params.get('exclude_place_ids').split(','); - } - for (var i = 0; i < aResults.length; i += 1) { - aExcludePlaceIds.push(aResults[i].place_id); - } - - var parsed_url = new URLSearchParams(window.location.search); - parsed_url.set('exclude_place_ids', aExcludePlaceIds.join(',')); - context.sMoreURL = '?' + parsed_url.toString(); + // lonvia wrote: https://github.com/osm-search/nominatim-ui/issues/24 + // I would suggest to remove the guessing and always show the link. Nominatim only returns + // one or two results when it believes the result to be a good enough match. + // if (aResults.length >= 10) { + var aExcludePlaceIds = []; + if (search_params.has('exclude_place_ids')) { + aExcludePlaceIds = search_params.get('exclude_place_ids').split(','); } + for (var i = 0; i < aResults.length; i += 1) { + aExcludePlaceIds.push(aResults[i].place_id); + } + var parsed_url = new URLSearchParams(window.location.search); + parsed_url.set('exclude_place_ids', aExcludePlaceIds.join(',')); + context.sMoreURL = '?' + parsed_url.toString(); render_template($('main'), 'searchpage-template', context); update_html_title('Result for ' + api_request_params.q); @@ -680,4 +767,125 @@ jQuery(document).ready(function () { ); } } +} + + +// ********************************************************* +// DELETABLE PAGE +// ********************************************************* + +function deletable_page_load() { + + var api_request_params = { + format: 'json' + }; + + fetch_from_api('deletable', api_request_params, function (aPolygons) { + var context = { aPolygons: aPolygons }; + + render_template($('main'), 'deletable-template', context); + update_html_title('Deletable objects'); + + update_data_date(); + }); +} +// ********************************************************* +// BROKEN POLYGON PAGE +// ********************************************************* + +function polygons_page_load() { + // + var api_request_params = { + format: 'json' + }; + + fetch_from_api('polygons', api_request_params, function (aPolygons) { + var context = { aPolygons: aPolygons }; + + render_template($('main'), 'polygons-template', context); + update_html_title('Broken polygons'); + + update_data_date(); + }); +} +jQuery(document).ready(function () { + var myhistory = []; + + function parse_url_and_load_page() { + // 'search', 'reverse', 'details' + var pagename = window.location.pathname.replace('.html', '').replace(/^.*\//, ''); + + if (pagename === '') pagename = 'search'; + + $('body').attr('id', pagename + '-page'); + + if (pagename === 'search' || pagename === 'reverse') { + search_page_load(); + } else if (pagename === 'details') { + details_page_load(); + } else if (pagename === 'deletable') { + deletable_page_load(); + } else if (pagename === 'polygons') { + polygons_page_load(); + } + } + + function is_relative_url(url) { + if (!url) return false; + if (url.indexOf('?') === 0) return true; + if (url.indexOf('/') === 0) return true; + if (url.indexOf('#') === 0) return false; + if (url.match(/^http/)) return false; + if (!url.match(/\.html/)) return true; + + return false; + } + + // remove any URL paramters with empty values + // '&empty=&filled=value' => 'filled=value' + function clean_up_url_parameters(url) { + var url_params = new URLSearchParams(url); + var to_delete = []; // deleting inside loop would skip iterations + url_params.forEach(function (value, key) { + if (value === '') to_delete.push(key); + }); + for (var i = 0; i < to_delete.length; i += 1) { + url_params.delete(to_delete[i]); + } + return url_params.toString(); + } + + parse_url_and_load_page(); + + // load page after form submit + $(document).on('submit', 'form', function (e) { + e.preventDefault(); + + var target_url = $(this).serialize(); + target_url = clean_up_url_parameters(target_url); + + window.history.pushState(myhistory, '', '?' + target_url); + + parse_url_and_load_page(); + }); + + // load page after click on relative URL + $(document).on('click', 'a', function (e) { + var target_url = $(this).attr('href'); + if (!is_relative_url(target_url)) return; + if ($(this).parents('#last-updated').length !== 0) return; + + e.preventDefault(); + e.stopPropagation(); + + window.history.pushState(myhistory, '', target_url); + + parse_url_and_load_page(); + }); + + // deal with back-button and other user action + window.onpopstate = function () { + parse_url_and_load_page(); + }; }); +