]> git.openstreetmap.org Git - nominatim-ui.git/commitdiff
Components for internal links (#69)
authorSarah Hoffmann <lonvia@denofr.de>
Fri, 12 Feb 2021 01:03:22 +0000 (02:03 +0100)
committerGitHub <noreply@github.com>
Fri, 12 Feb 2021 01:03:22 +0000 (02:03 +0100)
* add component for link to details page

* introduce components for reverse and generic internal links

Supersedes the generic click handler that was looking for
internal links.

13 files changed:
src/components/DetailsIndex.svelte
src/components/DetailsLink.svelte [new file with mode: 0644]
src/components/DetailsOneRow.svelte
src/components/Header.svelte
src/components/PageLink.svelte [new file with mode: 0644]
src/components/ResultsList.svelte
src/components/ReverseBar.svelte
src/components/ReverseLink.svelte [new file with mode: 0644]
src/components/SearchBar.svelte
src/lib/helpers.js
src/main.js
src/pages/DeletablePage.svelte
src/pages/DetailsPage.svelte

index 1b199677ea776ba19ce36b00d7ac9a73273350c6..21835974c1f501b39bc6d0469c730ac16bf9a004 100644 (file)
@@ -91,4 +91,4 @@
     margin-right: 5px;
     width: 30em;
   }
-</style>
\ No newline at end of file
+</style>
diff --git a/src/components/DetailsLink.svelte b/src/components/DetailsLink.svelte
new file mode 100644 (file)
index 0000000..51a0c8c
--- /dev/null
@@ -0,0 +1,42 @@
+<script>
+  import { refresh_page } from '../lib/stores.js';
+
+  export let extra_classes = '';
+  export let feature = null;
+
+  let url_params = '';
+
+  function formatShortOSMType(sType) {
+    if (sType === 'node') return 'N';
+    if (sType === 'way') return 'W';
+    if (sType === 'relation') return 'R';
+    return '';
+  }
+
+  function handleClick() {
+    window.history.pushState([], '', 'details.html' + url_params);
+    refresh_page();
+  }
+
+  $: {
+    if (feature !== null && feature.osm_type) {
+      let param = '?osmtype=';
+      if (feature.osm_type.length == 1) {
+        param += encodeURIComponent(feature.osm_type);
+      } else {
+        param += formatShortOSMType(feature.osm_type);
+      }
+      param += '&osmid=' + encodeURIComponent(feature.osm_id);
+      if (feature.class) {
+        param += '&class=' + encodeURIComponent(feature.class);
+      } else if (feature.category) {
+        param += '&class=' + encodeURIComponent(feature.category);
+      }
+      url_params = param
+    } else {
+        url_params = '';
+    }
+ }
+</script>
+
+<a on:click|preventDefault|stopPropagation={handleClick} href="details.html{url_params}" class={extra_classes}><slot></slot></a>
index cde2ac2411f83d44ac8267735bc3e2b47a6cf50d..1ab566d57f70101595daa78bf8c84ad8f9ee1736 100644 (file)
@@ -1,4 +1,5 @@
 <script>
+  import DetailsLink from '../components/DetailsLink.svelte';
 
   export let addressLine;
   export let bDistanceInMeters;
@@ -6,7 +7,7 @@
   $: bAddressLineUsed = addressLine.isaddress;
 
   import {
-    formatPlaceType, osmLink, formatAdminLevel, formatDistance, detailsURL
+    formatPlaceType, osmLink, formatAdminLevel, formatDistance
   } from '../lib/helpers.js';
 
 </script>
@@ -24,7 +25,7 @@
   <td>{addressLine.rank_address}</td>
   <td>{formatAdminLevel(addressLine.admin_level)}</td>
   <td>{@html formatDistance(addressLine.distance, bDistanceInMeters)}</td>
-  <td>{#if addressLine.osm_id}<a href="{detailsURL(addressLine)}">details</a>{/if}</td>
+  <td>{#if addressLine.osm_id}<DetailsLink feature={addressLine}>details</DetailsLink>{/if}</td>
 </tr>
 
 <style>
index 63e2a4454cf1e9c4b164bb4731716482ae98ba2d..5000cd67cd71e6724a7033b84528835dccabcd44 100644 (file)
@@ -1,5 +1,6 @@
 <script>
   import LastUpdated from './LastUpdated.svelte';
+  import PageLink from './PageLink.svelte';
 </script>
 
 <style>
@@ -13,7 +14,7 @@
     white-space: nowrap;
   }
 
-  .brand a:hover{
+  .brand :global(a:hover) {
     text-decoration: none;
   }
 
   <div class="row">
     <div class="col-4">
       <div class="brand">
-        <a href="search.html">
+        <PageLink page="search">
           <img alt="logo" src="images/osm_logo.120px.png" width="30" height="30"/>
           <h1>Nominatim</h1>
-        </a>
+        </PageLink>
       </div>
     </div>
     <div class="col-4">
diff --git a/src/components/PageLink.svelte b/src/components/PageLink.svelte
new file mode 100644 (file)
index 0000000..d70c3f0
--- /dev/null
@@ -0,0 +1,12 @@
+<script>
+import { refresh_page } from '../lib/stores.js';
+
+export let page;
+
+function handleClick() {
+  window.history.pushState([], '', page + '.html');
+  refresh_page();
+}
+</script>
+
+<a on:click|preventDefault|stopPropagation={handleClick} href="{page}.html"><slot></slot></a>
index 668f33070458a988f5165163e3c767b1b3acb1e0..2fc6828e7f9034ce5ab9cec5bdef8c7c1a698d88 100644 (file)
@@ -1,7 +1,8 @@
 <script>
   import { results_store } from '../lib/stores.js';
-  import { formatLabel, detailsURL } from '../lib/helpers.js';
+  import { formatLabel } from '../lib/helpers.js';
 
+  import DetailsLink from './DetailsLink.svelte';
   import Welcome from './Welcome.svelte';
   import MapIcon from './MapIcon.svelte';
 
@@ -61,9 +62,9 @@
         </div>
         <span class="name">{aResult.display_name}</span>
         <span class="type">{formatLabel(aResult)}</span>
-        <p class="coords">{aResult.lat},{aResult.lon}</p>  
+        <p class="coords">{aResult.lat},{aResult.lon}</p>
 
-        <a class="details btn btn-outline-secondary btn-sm" href="{detailsURL(aResult)}">details</a>
+        <DetailsLink extra_classes="btn btn-outline-secondary btn-sm" feature={aResult}>details</DetailsLink>
       </div>
     {/each}
 
     background-color: #D9E7F7;
     border-color: #9DB9E4;
   }
-  .result.highlight .details {
+  .result.highlight :global(a) {
     margin: 10px auto;
     display: block;
     max-width: 10em;
     padding: 1px;
+    background-color: white;
   }
   .result .type{
     color: gray;
     font-size: 0.8em;
   }
-  .result .details {
+  .result :global(a) {
     display: none;
   }
 
     margin-top: 1em;
   }
 
-  .btn-outline-secondary {
-    background-color: white;
-  }
-
-  .btn-outline-secondary:hover {
+  .result.highlight :global(a):hover {
     color: #111;
   }
 </style>
index c7f081dd3428e77c8dc18574871deed908af0479..53d7bffe2187fb2768ef19da61b0a64282e5f1a9 100644 (file)
@@ -1,5 +1,7 @@
 <script>
   import UrlSubmitForm from '../components/UrlSubmitForm.svelte';
+  import DetailsLink from '../components/DetailsLink.svelte';
+  import PageLink from '../components/PageLink.svelte';
 
   import { zoomLevels } from '../lib/helpers.js';
   import { map_store } from '../lib/stores.js';
@@ -70,8 +72,8 @@
       </button>
     </div>
     <div class="search-type-link">
-      <a href="details.html" class="mr-2">search by id</a>
-      <a href="search.html">forward search</a>
+      <DetailsLink extra_classes="mr-2">search by id</DetailsLink>
+      <PageLink page="search">forward search</PageLink>
     </div>
   </UrlSubmitForm>
 </div>
diff --git a/src/components/ReverseLink.svelte b/src/components/ReverseLink.svelte
new file mode 100644 (file)
index 0000000..5289999
--- /dev/null
@@ -0,0 +1,31 @@
+<script>
+import { refresh_page } from '../lib/stores.js';
+
+export let lat;
+export let lon;
+export let zoom = null;
+
+let params = '';
+
+$: {
+  if (lat && lon) {
+    let new_params = '?lat=' + encodeURIComponent(lat);
+    new_params += '&lon=' + encodeURIComponent(lon);
+
+    if (zoom) {
+      new_params += '&zoom=' + encodeURIComponent(zoom);
+    }
+
+    params = new_params;
+  } else {
+    params = '';
+  }
+}
+
+function handleClick() {
+  window.history.pushState([], '', 'reverse.html' + params);
+  refresh_page();
+}
+</script>
+
+<a on:click|preventDefault|stopPropagation={handleClick} href="reverse.html{params}"><slot></slot></a>
index 306ce6e2c08701bf63afc45561c7b93e1efeff96..dca6161ad7b187a3924a70d593056ce04d30f277 100644 (file)
@@ -1,5 +1,7 @@
 <script>
   import UrlSubmitForm from '../components/UrlSubmitForm.svelte';
+  import DetailsLink from '../components/DetailsLink.svelte';
+  import ReverseLink from '../components/ReverseLink.svelte';
 
   import { map_store } from '../lib/stores.js';
   import { get } from 'svelte/store';
@@ -7,6 +9,8 @@
   export let bStructuredSearch = false;
   export let api_request_params = {};
   let sViewBox;
+  let lat;
+  let lon;
 
   function map_viewbox_as_string(map) {
     var bounds = map.getBounds();
   }
 
   function update_reverse_link(map) {
-    let link = document.getElementById('switch-to-reverse');
-    if (link) {
-      let center_lat_lng = map.wrapLatLng(map.getCenter());
-      link.href = 'reverse.html?lat=' + center_lat_lng.lat.toFixed(5)
-                   + '&lon=' + center_lat_lng.lng.toFixed(5);
-    }
+    let center_lat_lng = map.wrapLatLng(map.getCenter());
+    lat = center_lat_lng.lat.toFixed(5);
+    lon = center_lat_lng.lng.toFixed(5);
   }
 
   map_store.subscribe(map => {
@@ -88,8 +89,8 @@
       <a class="nav-link" class:active={bStructuredSearch} data-toggle="tab" href="#structured">structured</a>
     </li>
     <div class="search-type-link">
-      <a href="details.html" class="mr-2">search by id</a>
-      <a id="switch-to-reverse" href="reverse.html">reverse search</a>
+      <DetailsLink extra_classes="mr-2">search by id</DetailsLink>
+      <ReverseLink lat={lat} lon={lon}>reverse search</ReverseLink>
     </div>
   </ul>
   <div class="tab-content p-2">
index e55cbf0ab2a7adbf851ceee4bab701cb1b68d936..cbbdbc98ed81822d718d26523855ba0d1a6a9de1 100644 (file)
@@ -1,8 +1,6 @@
 module.exports.formatOSMType = formatOSMType;
-module.exports.formatShortOSMType = formatShortOSMType;
 module.exports.osmLink = osmLink;
 module.exports.formatLabel = formatLabel;
-module.exports.detailsURL = detailsURL;
 module.exports.wikipediaLink = wikipediaLink;
 module.exports.coverageType = coverageType;
 module.exports.isAdminBoundary = isAdminBoundary;
@@ -28,13 +26,6 @@ function formatOSMType(sType, bExcludeExternal) {
   return '';
 }
 
-function formatShortOSMType(sType) {
-  if (sType === 'node') return 'N';
-  if (sType === 'way') return 'W';
-  if (sType === 'relation') return 'R';
-  return '';
-}
-
 function osmLink(aPlace) {
   if (!aPlace.osm_type) return '';
   var sOSMType = formatOSMType(aPlace.osm_type, false);
@@ -59,25 +50,6 @@ function formatLabel(aPlace) {
   return '';
 }
 
-// 'details.html?osmtype=R&osmid=2181874&class=boundary'
-function detailsURL(aFeature) {
-  if (!aFeature) return '';
-
-  var sOSMType = aFeature.osm_type;
-  if (sOSMType && sOSMType.length !== 1) {
-    sOSMType = formatShortOSMType(aFeature.osm_type, false); // node => N
-  }
-  if (!sOSMType) return '';
-
-  var sURL = 'details.html?osmtype=' + sOSMType + '&osmid=' + aFeature.osm_id;
-  if (aFeature.class) {
-    sURL = sURL + '&class=' + encodeURIComponent(aFeature.class);
-  } else if (aFeature.category) {
-    sURL = sURL + '&class=' + encodeURIComponent(aFeature.category);
-  }
-  return sURL;
-}
-
 /* en:London_Borough_of_Redbridge => https://en.wikipedia.org/wiki/London_Borough_of_Redbridge */
 function wikipediaLink(aPlace) {
   if (!aPlace.calculated_wikipedia) return '';
index 8445501a86496b636799eb00791dbadc4fa31b26..3b17bed03a416e02cd5111054fb7ffbfad398bd8 100644 (file)
@@ -1,44 +1,5 @@
 import App from './App.svelte';
-import { refresh_page } from './lib/stores.js';
-
-let myhistory = [];
 
 const app = new App({ // eslint-disable-line no-unused-vars
   target: document.body
 });
-
-
-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;
-}
-
-
-// load page after click on relative URL
-document.addEventListener('click', function (e) {
-
-  // loop parent nodes from the target to the delegation node
-  for (var target = e.target; target && target !== this; target = target.parentNode) {
-
-    if (target.matches('a') && target.href) {
-      // target.href always contains the full absolute URL, inspect the raw value instead
-      var target_url = target.attributes.href.value;
-
-      if (!is_relative_url(target_url)) return;
-
-      e.preventDefault();
-      e.stopPropagation();
-
-      window.history.pushState(myhistory, '', target_url);
-
-      refresh_page();
-      break;
-    }
-  }
-});
index 27e881a21dc2cd46e4f47bc79ad578acbc562f00..1d6b91eb8f6dd92f05fc5af8483214a5167cbcf9 100644 (file)
@@ -1,7 +1,9 @@
 <script>
   import { onMount } from 'svelte';
   import { fetch_from_api, update_html_title } from '../lib/api_utils.js';
-  import { detailsURL, osmLink } from '../lib/helpers.js';
+  import { osmLink } from '../lib/helpers.js';
+
+  import DetailsLink from '../components/DetailsLink.svelte';
 
   let aPolygons = [];
 
@@ -36,7 +38,7 @@
         <tbody>
           {#each aPolygons as polygon}
           <tr>
-            <td><a href="{detailsURL(polygon)}">{polygon.place_id}</a></td>
+            <td><DetailsLink feature={polygon}>{polygon.place_id}</DetailsLink></td>
             <td>{polygon.country_code}</td>
             <td>{polygon.name}</td>
             <td>{@html osmLink(polygon)}</td>
index 5d6e6637105e0da451ee69ea7da57504973dea3b..e9c74828add4584e16df51bb42abb317a88847b6 100644 (file)
@@ -1,14 +1,16 @@
 <script>
-  import { onMount } from 'svelte';
+  import { onMount, onDestroy } from 'svelte';
   import { fetch_from_api, update_html_title } from '../lib/api_utils.js';
+  import { page } from '../lib/stores.js';
 
   import {
-    osmLink, detailsURL, wikipediaLink, coverageType, isAdminBoundary,
+    osmLink, wikipediaLink, coverageType, isAdminBoundary,
     formatAddressRank, formatKeywordToken
   } from '../lib/helpers.js';
   import MapIcon from '../components/MapIcon.svelte';
   import DetailsIndex from '../components/DetailsIndex.svelte';
   import DetailsOneRow from '../components/DetailsOneRow.svelte';
+  import DetailsLink from '../components/DetailsLink.svelte';
   import Map from '../components/Map.svelte';
 
   let aPlace;
       aPlace = undefined;
     }
   }
-  onMount(loaddata);
+
+  let page_subscription;
+  onMount(() => { page_subscription = page.subscribe(loaddata); });
+  onDestroy(() => { page_subscription(); });
 
 </script>
 
@@ -67,7 +72,7 @@
       <div class="col-sm-10">
         <h1>
           {aPlace.localname}
-          <small><a href="{detailsURL(aPlace)}">link to this page</a></small>
+          <small><DetailsLink feature={aPlace}>link to this page</DetailsLink></small>
         </h1>
       </div>
       <div class="col-sm-2 text-right">
     padding-left: 8px;
   }
 
-  h1 small a {
+  h1 small :global(a) {
     font-size: 0.5em;
     white-space: nowrap;
   }