Address Typeahead

by Christian Unigarro

HTML

<!DOCTYPE html>
<html lang="es">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Address autocomplete</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css" integrity="sha384-9gVQ4dYFwwWSjIDZnLEWnxCjeSWFphJiwGPXr1jddIhOegiu1FwO5qRGvFXOdJZ4" crossorigin="anonymous">
  </head>
  <body>
    <div class="container">
      <div class="row">
        <div class="col-12 col-sm-6">
          <div id="example" class="mt-5">
            <input class="typeahead form-control" type="text" placeholder="Cra. 1 #23-45, Ciudad, Departamento">
          </div>
        </div>
      </div>
			
			<div class="geocode mt-4">
				<h4>
					Resultado:
				</h4>

				<ul>
					<li>
						<span class="d-block">
							<strong>
								Dirección:
							</strong>

							<span class="js-address"></span>
						</span>
					</li>

					<li>
						<span class="d-block">
							<strong>
								Latitud:
							</strong>

							<span class="js-latitude"></span>
						</span>
					</li>

					<li>
						<span class="d-block">
							<strong>
								Longitud:
							</strong>

							<span class="js-longitude"></span>
						</span>
					</li>
				</ul>
			</div>
    </div>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.0/umd/popper.min.js" integrity="sha384-cs/chFZiN24E4KMATLdqdvsezGxaGsi4hLGOzlXwp5UZB1LY//20VyM2taTB4QvJ" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/js/bootstrap.min.js" integrity="sha384-uefMccjFJAIv6A+rW+L4AHf99KvxDjWSu1z9VI8SKNVmz4sk7buKt/6v9KI65qnm" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/typeahead.js/0.11.1/typeahead.bundle.min.js"></script>
    <script...

CSS

span.twitter-typeahead .tt-menu,
span.twitter-typeahead .tt-dropdown-menu {
  cursor: pointer;
  position: absolute;
  top: 100%;
  left: 0;
  z-index: 1000;
  display: none;
  float: left;
  min-width: 160px;
  padding: 5px 0;
  margin: 2px 0 0;
  list-style: none;
  font-size: 14px;
  text-align: left;
  background-color: #ffffff;
  border: 1px solid #cccccc;
  border: 1px solid rgba(0, 0, 0, 0.15);
  border-radius: 4px;
  -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);
  box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);
  background-clip: padding-box;
}
span.twitter-typeahead .tt-suggestion {
  display: block;
  padding: 3px 20px;
  clear: both;
  font-weight: normal;
  line-height: 1.42857143;
  color: #333333;
  white-space: nowrap;
}
span.twitter-typeahead .tt-suggestion.tt-cursor,
span.twitter-typeahead .tt-suggestion:hover,
span.twitter-typeahead .tt-suggestion:focus {
  color: #ffffff;
  text-decoration: none;
  outline: 0;
  background-color: #337ab7;
}
.input-group.input-group-lg span.twitter-typeahead .form-control {
  height: 46px;
  padding: 10px 16px;
  font-size: 18px;
  line-height: 1.3333333;
  border-radius: 6px;
}
.input-group.input-group-sm span.twitter-typeahead .form-control {
  height: 30px;
  padding: 5px 10px;
  font-size: 12px;
  line-height: 1.5;
  border-radius: 3px;
}
span.twitter-typeahead {
  width: 100%;
}
.input-group span.twitter-typeahead {
  display: block !important;
  height: 34px;
}
.input-group span.twitter-typeahead .tt-menu,
.input-group span.twitter-typeahead .tt-dropdown-menu {
  top: 32px !important;
}
.input-group span.twitter-typeahead:not(:first-child):not(:last-child) .form-control {
  border-radius: 0;
}
.input-group span.twitter-typeahead:first-child .form-control {
  border-top-left-radius: 4px;
  border-bottom-left-radius: 4px;
  border-top-right-radius: 0;
  border-bottom-right-radius: 0;
}
.input-group span.twitter-typeahead:last-child .form-control {
  border-top-left-radius: 0;
  border-bottom-left-radius:...

JavaScript

function initAddressTa () {
  var autocompleteService = new google.maps.places.AutocompleteService();
  var $addressTa = $('#example .typeahead');
  var $addressContainer = $('.js-address');
  var $latitudeContainer = $('.js-latitude');
  var $longitudeContainer = $('.js-longitude');
  var currentAddress = '';

  $addressTa.typeahead({
    hint: true,
    highlight: true
  },
                       {
    name: 'states',
    limit: 4,
    display: function(item) {
      return item.name;
    },
    source: function(q, cb, fc) {
      var c = [];
      autocompleteService.getPlacePredictions({
        types: ['address'],
        componentRestrictions: {
          country: "co"
        },
        placeIdOnly: true,
        input : q
      },
                                              function(predictions, status) {
        var address = '';
        var city = '';

        if (status == google.maps.places.PlacesServiceStatus.OK) {
          $.map(predictions, function(prediction) {
            for(var i = 0; i < prediction.types.length; i++) {
              if(prediction.types[i] == 'street_address' || prediction.types[i] == 'route') {
                address = prediction.structured_formatting.main_text;
                city = prediction.structured_formatting.secondary_text.substring(prediction.structured_formatting.secondary_text.indexOf(', Colombia'), 0);
                c.push({
                  name: address + ' ' + city,
                  placeId: prediction.place_id
                });
              }
            }
          });
        } else {
          c = [];
        }

        fc(c);
      });
    },
    templates: {
      notFound: '<div class="tt-suggestion tt-notfound">Lo sentimos, no se encontró ningún resultado para tu búsqueda.</div>'
    }
  });

  $addressTa
    .typeahead('val', currentAddress)
    .on('typeahead:select', function(ev, suggestion) {
    ev.preventDefault();
    $.ajax({
      type: "GET",
      url:...