Address Autocomplete Tutorial

Create an Address Input with suggestions by using Geoapify Address Autocomplete API

by Geoapify

HTML

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

CSS

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

.autocomplete-container {
  margin-bottom: 20px;
}

.input-container {
  display: flex;
  position: relative;
}

.input-container input {
  flex: 1;
  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;
  background-color: #fff;

  z-index: 99;
  top: calc(100% + 2px);
  left: 0;
  right: 0;
}

.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

function addressAutocomplete(containerElement, callback, options) {

  const MIN_ADDRESS_LENGTH = 3;
  const DEBOUNCE_DELAY = 300;

  // create container for input element
  const inputContainerElement = document.createElement("div");
  inputContainerElement.setAttribute("class", "input-container");
  containerElement.appendChild(inputContainerElement);

  // create input element
  const inputElement = document.createElement("input");
  inputElement.setAttribute("type", "text");
  inputElement.setAttribute("placeholder", options.placeholder);
  inputContainerElement.appendChild(inputElement);

  // add input field clear button
  const 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();
  });
  inputContainerElement.appendChild(clearButton);

  /* We will call the API with a timeout to prevent unneccessary API activity.*/
  let currentTimeout;

  /* Save the current request promise reject function. To be able to cancel the promise when a new request comes */
  let currentPromiseReject;

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

  /* Process a user input: */
  inputElement.addEventListener("input", function(e) {
    const currentValue = this.value;

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


    // Cancel previous timeout
    if (currentTimeout) {
      clearTimeout(currentTimeout);
    }

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

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

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

    // Skip empty...