Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Google Autocomplete Places API not triggering event on change via TAB

Per the Google Autocomplete Places API documentation, the getPlace() call should return a Places object with all the location data, or, if that place doesn't exist (i.e. - the user ignored the suggestions), it should return a stub with just the name element of the Places object filled in. However, it only does this latter operation when the user hits ENTER, not if they TAB out of the field.

I've tried looking at the change event, the keyup, keydown events. I've tried triggering a keydown event with keycode 13 on blur, etc. etc. Nothing seems to work.

Has anyone overcome this issue? It seems pretty obvious that a user would tab through a form, and there's always the possibility they ignore the suggestions.

like image 496
afithings Avatar asked Dec 06 '22 23:12

afithings


2 Answers

pac-input being your place search input, you can do the following:

// Trigger search on blur
document.getElementById('pac-input').onblur = function () {

    google.maps.event.trigger(this, 'focus', {});
    google.maps.event.trigger(this, 'keydown', {
        keyCode: 13
    });
};

Or with a google maps event listener:

// Trigger search on blur
google.maps.event.addDomListener(document.getElementById("pac-input"), 'blur', function() {

    google.maps.event.trigger(this, 'focus', {});
    google.maps.event.trigger(this, 'keydown', {
        keyCode: 13
    });
});

Edit: As mentioned in the comments, this messes up with the "normal behavior" of a user selecting a place by mouse click.

Below is a complete example using pure Javascript. For a (simpler) jQuery solution, look at @ChrisSnyder's answer.

function initialize() {

  var ac = new google.maps.places.Autocomplete(
    (document.getElementById('autocomplete')), {
      types: ['geocode']
    });

  ac.addListener('place_changed', function() {

    var place = ac.getPlace();

    if (!place.geometry) {

      // User entered the name of a Place that was not suggested and
      // pressed the Enter key, or the Place Details request failed.
      console.log("No details available for input: '" + place.name + "'");
      return;
    }

    console.log("You selected: '" + place.formatted_address + "'");
  });

  // Trigger search on blur
  google.maps.event.addDomListener(document.getElementById("autocomplete"), 'blur', function() {

    // Find the pac-container element
    var pacContainer = nextByClass(this, 'pac-container');

    // Check if we are hovering on one of the pac-items
    // :hover propagates to parent element so we only need to check it on the pac-container
    // We trigger the focus and keydown only if :hover is false otherwise it will interfere with a place selection via mouse click
    if (pacContainer.matches(':hover') === false) {

      google.maps.event.trigger(this, 'focus', {});
      google.maps.event.trigger(this, 'keydown', {
        keyCode: 13
      });
    }

  });
}

function hasClass(elem, cls) {
  var str = " " + elem.className + " ";
  var testCls = " " + cls + " ";
  return (str.indexOf(testCls) != -1);
}

function nextByClass(node, cls) {
  while (node = node.nextSibling) {
    if (hasClass(node, cls)) {
      return node;
    }
  }
  return null;
}
#autocomplete {
  width: 300px;
}
<script src="https://maps.googleapis.com/maps/api/js?libraries=places&callback=initialize&key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk" async defer></script>
<input id="autocomplete" placeholder="Enter your address" type="text"></input>
like image 200
MrUpsidown Avatar answered Feb 17 '23 04:02

MrUpsidown


The following expands on @MrUpsidown's solution but tries to avoid messing with the user when they click on an item in the dropdown as mentioned by @Jkk.jonah

// Trigger search on blur
google.maps.event.addDomListener(document.getElementById("pac-input"), 'blur', function() {
  if (jQuery('.pac-item:hover').length === 0 ) {
    google.maps.event.trigger(this, 'focus', {});
    google.maps.event.trigger(this, 'keydown', {
        keyCode: 13
    });
  } 
});
like image 22
Chris Snyder Avatar answered Feb 17 '23 04:02

Chris Snyder