Geoapify Address Autocomplete

Address autocomplete example using Geoapify Geocoding API

by Geoapify

HTML

<div class="autocomplete-container" id="autocomplete-container"></div>
<div class="autocomplete-container" id="autocomplete-container-country"></div>
<div class="autocomplete-container" id="autocomplete-container-city"></div>

CSS

body {
  font: 16px;
  background: #f3f5f6;
}

.autocomplete-container {
  /*the container must be positioned relative:*/
  position: relative;
  
  margin-bottom: 20px;
}

.autocomplete-container input {
  width: calc(100% - 43px);
  outline: none;
  
  border: 1px solid rgba(0, 0, 0, 0.2);
  padding: 10px;
  padding-right: 31px;
  font-size: 16px;
}

.autocomplete-items {
  position: absolute;
  border: 1px solid rgba(0, 0, 0, 0.1);
  box-shadow: 0px 2px 10px 2px rgba(0, 0, 0, 0.1);
  border-top: none;
  z-index: 99;
  /*position the autocomplete items to be the same width as the container:*/
  top: calc(100% + 2px);
  left: 0;
  right: 0;
  
  background-color: #fff;
}

.autocomplete-items div {
  padding: 10px;
  cursor: pointer;
}

.autocomplete-items div:hover {
  /*when hovering an item:*/
  background-color: rgba(0, 0, 0, 0.1);
}

.autocomplete-items .autocomplete-active {
  /*when navigating through the items using the arrow keys:*/
  background-color: rgba(0, 0, 0, 0.1);
}

.clear-button {
  color: rgba(0, 0, 0, 0.4);
  cursor: pointer;
  
  position: absolute;
  right: 5px;
  top: 0;

  height: 100%;
  display: none;
  align-items: center;
}

.clear-button.visible {
  display: flex;
}


.clear-button:hover {
  color: rgba(0, 0, 0, 0.6);
}

JavaScript

/* 
	The addressAutocomplete takes as parameters:
  - a container element (div)
  - callback to notify about address selection
  - geocoder options:
  	 - placeholder - placeholder text for an input element
     - type - location type
*/
function addressAutocomplete(containerElement, callback, options) {
  // create input element
  var inputElement = document.createElement("input");
  inputElement.setAttribute("type", "text");
  inputElement.setAttribute("placeholder", options.placeholder);
  containerElement.appendChild(inputElement);

  // add input field clear button
  var clearButton = document.createElement("div");
  clearButton.classList.add("clear-button");
  addIcon(clearButton);
  clearButton.addEventListener("click", (e) => {
    e.stopPropagation();
    inputElement.value = '';
    callback(null);
    clearButton.classList.remove("visible");
    closeDropDownList();
  });
  containerElement.appendChild(clearButton);

  /* Current autocomplete items data (GeoJSON.Feature) */
  var currentItems;

  /* Active request promise reject function. To be able to cancel the promise when a new request comes */
  var currentPromiseReject;

  /* Focused item in the autocomplete list. This variable is used to navigate with buttons */
  var focusedItemIndex;

  /* Execute a function when someone writes in the text field: */
  inputElement.addEventListener("input", function(e) {
    var currentValue = this.value;

    /* Close any already open dropdown list */
    closeDropDownList();

    // Cancel previous request promise
    if (currentPromiseReject) {
      currentPromiseReject({
        canceled: true
      });
    }

    if (!currentValue) {
      clearButton.classList.remove("visible");
      return false;
    }

    // Show clearButton when there is a text
    clearButton.classList.add("visible");

    /* Create a new promise and send geocoding request */
    var promise = new Promise((resolve, reject) => {
      currentPromiseReject = reject;

      var apiKey...