Jump to content

Autocomplete Location on Form

Recommended Posts

Is there a way to create a Squarespace form with a location field that autocompletes as a person types in their address? My client wants this feature so people will enter more accurate addresses. I know how to do this when I'm building a form from scratch, but I can't figure out if this can be done with a Squarespace form. I would greatly appreciate any advice!

Link to comment

It may be possible. Its depends on the form.

In general you will need to attach a handler to the field of interest to handle the auto-complete.

Please post the URL for a page on your site where we can see your issue.

If your site is not public please set up a site-wide password, if you've not already done so.

Post the password here.

Adding a site-wide password does not allow anyone to alter your site. It only allows those with the password to see your site. Please read the documentation at the link provided to understand how it works.

Please read the documentation at the link provided on how to share a link to your site to understand how it works. A link to the backend of the your site won’t work for us, i.e. a url that contains /config/.

We can then take a look at your issue.

Find my contributions useful? Please like, upvote, mark my answer as the best ( solution ), and see my profile. Thanks for your support! I am a Squarespace ( and other technological things ) consultant open for new projects.

Link to comment

This is not a solution but a shell of a script that can get you started.

<script>

  /*
  
    begin title of effect here
    
    Version     : 0.1.0
    
    SS Versions : 7.1, 7.0
    
    By          : Thomas Creedon < http://www.tomsWeb.consulting/ >
    
    no user serviceable parts below
    
    */
    
    document.addEventListener ( 'DOMContentLoaded', ( ) => {
    
      const selector =
      
        '#textarea-yui_3_17_2_1_1520795615602_101969-field';
        
      const element = document.querySelector ( selector );
      
      element.addEventListener ( 'input', event => {
      
        console.log ( 'event : ', event );
        
        console.log ( 'event.target : ', event.target );
        
        } );
        
      } );
      
    /* end title of effect here */
    
  </script>

This shows how you can wait for the page to be mostly loaded. Then add an event listener to an input element.

Let us know how it goes.

Edited by creedon

Find my contributions useful? Please like, upvote, mark my answer as the best ( solution ), and see my profile. Thanks for your support! I am a Squarespace ( and other technological things ) consultant open for new projects.

Link to comment
  • 11 months later...

Since I spent a few hours on this, I figured I'd give back to the community. Here is the JS you have to inject in the "Advanced" header section of the page with the form - this will need extra work if you have more than the form as an input field on the page and this is tailored for Canada but you get the idea. I make no apologies for the beginner code 🙂

 

<script>
let input_line = null
let componentForm = {
  street_number: ['short_name', null],
  route: ['long_name', null],
  locality: ['long_name', null],
  administrative_area_level_1: ['short_name', null],
  country: ['long_name', null],
  postal_code: ['short_name', null]
};

const options = {
  componentRestrictions: { country: "ca" },
  fields: ["address_components", "geometry", "icon", "name"],
  strictBounds: false,
};

let line1 = null;
let line2 = null;
let city = null;
let state = null;
let zip = null;

let autocomplete = null
let mapsLibLoaded = false;
document.addEventListener ( 'DOMContentLoaded', ( ) => {
  window.addEventListener('load', function(){
    const selector2 = 'input[id*="address-"]';
    const elements = document.querySelectorAll ( selector2 );
    if (elements != null) {
      Array.prototype.forEach.call(elements, function(element) {
        console.log( " adding a listener to " + element.id)
        if (element.id.includes("line1")) line1 = element;
        else if (element.id.includes("line2")) {
          line2 = element;
          line2.disabled = true
        }
        else if (element.id.includes("city")) {
          city = element;
          city.disabled = true;
        }
        else if (element.id.includes("state")) {
          state = element;
          state.disabled = true
        }
        else if (element.id.includes("zip")) {
          zip = element;
          zip.disabled = true
        }
      });
    } else {
      console.log("Didn't find the element");
    }
    //lazy load initialize google maps because the fields in sqarespace dont seem to exist before this.
    let script = document.createElement('script');
    script.onload = function() {
      mapsLibLoaded = true;
    };
    script.src = "https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false&libraries=places&callback=initialize&key=<YOUR KEY HERE>";
    document.head.appendChild(script);
  } );
  } );

function initialize() {
  if (line1 != null) {
    console.log("Loading google");
    autocomplete = new google.maps.places.Autocomplete(line1, options);
    autocomplete.addListener('place_changed', fillInAddress);
  } else {
    console.log("Unable to load google");
  }
}

function fillInAddress() {
  // Get the place details from the autocomplete object.
  var place = autocomplete.getPlace();
  if (place == null) {
    console.log("No place");
    return;
  }

  //don't bother clearing value since this is managed by react
  line1.disabled = false;
  line2.disabled = false;
  city.disabled = false;
  state.disabled = false;
  zip.disabled = false;


  for (var i = 0; i < place.address_components.length; i++) {
    var addressType = place.address_components[i].types[0];
    if (componentForm[addressType]) {
      var val = place.address_components[i][componentForm[addressType][0]];
      console.log("Found " + componentForm[addressType][0] + " " + val)
      componentForm[addressType][1] = val
    }
  }

  var street_num = componentForm['street_number'][1]; //street number
  var street_name = componentForm['route'][1]; //route
  var city_name = componentForm['locality'][1]; //locality
  var province_name = componentForm['administrative_area_level_1'][1]; //admin region
  var postal_code = componentForm['postal_code'][1]; //post code

  //Remove the listener while we update the component via react. You only get one chance since i'm not sure how to add again...
  google.maps.event.clearInstanceListeners(line1);
  set_value(line1, street_num + " " + street_name);
  set_value(city, city_name);
  set_value(state, province_name);
  set_value(zip, postal_code);

  autocomplete = new google.maps.places.Autocomplete(line1, options);
  autocomplete.addListener('place_changed', fillInAddress);
}

function set_value(component, value_string) {
  //Deal with React shenanigans
  var nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, "value").set;
  nativeInputValueSetter.call(component, value_string);
  var inputEvent = new Event('input', { bubbles: true});
  component.dispatchEvent(inputEvent);
}

</script>

 

Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

×
×
  • Create New...

Squarespace Webinars

Free online sessions where you’ll learn the basics and refine your Squarespace skills.

Hire a Designer

Stand out online with the help of an experienced designer or developer.