ui_Gazetteer.mjs

/**
 * ### mapp.ui.gazetteer()
 * Module to export the gazetteer UI element functions used in mapp.
 * @module /ui/gazetteer
 */

/**
 * Creates a gazetteer component.
 * @function gazetteer
 * @param {Object} gazetteer - The gazetteer configuration object.
 * @param {HTMLElement} gazetteer.target - The target element to append the gazetteer to.
 * @param {string} gazetteer.placeholder - The placeholder text for the search input.
 * @param {string} [gazetteer.provider] - The external gazetteer provider to use for searching.
 * @returns {Object} The gazetteer object.
 */
export default gazetteer => {

  mapp.utils.merge(mapp.dictionaries, {
    en: {
      invalid_lat_long_range: 'Invalid coordinates: Latitude and longitude values must be within valid ranges.',
      invalid_lat_lon: 'The provided Coordinates do not fall within the selected Locale.'
    },
    de: {
      invalid_lat_long_range: 'Falsche Eingabe von Latitude / Longitude.',
      invalid_lat_lon: 'Koordinate liegt außerhalb der Lokale.'
    }
  })

  gazetteer = {...gazetteer, ...mapp.ui.elements.searchbox({
    target: gazetteer.target,
    name: 'gazetteer-search-input',
    placeholder: gazetteer.placeholder,
    searchFunction: search
  })}

  function search(e) {

    // Clear results
    gazetteer.list.innerHTML = ''

    // Only search if value has length.
    if (!e.target.value.length) return;

    // Get possible coordinates from input.
    const ll = e.target.value.split(',').map(parseFloat)

    // Check whether coordinates are valid float values.
    if (ll.length === 2 && ll.every(n => typeof n === 'number' && !isNaN(n) && isFinite(n))) {

      // Check if both coordinates are within valid range (latitude: -90 to 90, longitude: -180 to 180).
      const [lat, lng] = ll;

      if (lat >= -90 && lat <= 90 && lng >= -180 && lng <= 180) {
        gazetteer.list.appendChild(mapp.utils.html.node`
        <li onclick=${e => {
            mapp.utils.gazetteer.getLocation({
              label: `Latitude:${ll[0]}, Longitude:${ll[1]}`,
              source: 'Coordinates',
              lng: ll[1],
              lat: ll[0]
            }, gazetteer);
          }}><span>Latitude:${ll[0]}, Longitude:${ll[1]}</span>`);

        // Do not search if coordinates are provided.
        return;

      } else {

        // Handle the case where coordinates are not within valid ranges.
        // Add the error as a list item
        gazetteer.list.appendChild(mapp.utils.html.node`
          <li style="color: red;">
            <span>${mapp.dictionary.invalid_lat_long_range}</span>`);
        
      }
    }

    // An external gazetteer provider is requested
    if (gazetteer.provider) {

      // Check whether the gazetteer provider is available.
      if (!Object.hasOwn(mapp.utils.gazetteer, gazetteer.provider)) {

        console.warn('Requested gazetteer service not available');
      } else {

        // Query the external gazetteer provider
        mapp.utils.gazetteer[gazetteer.provider](e.target.value, gazetteer)
      }
    }

    // Request datasets gazetteer
    mapp.utils.gazetteer.datasets(e.target.value, gazetteer)
  }

}