Mitul Lakhani
Mitul Lakhani

Reputation: 192

Google Places Autocomplete - Click first result on blur

I'm using a Google Places Autocomplete and I simply want it to fire click event on the top item in the results list when blur event fire in the form field and suggestions exist.

var pac_input = document.getElementById('pick-auto');

                (function pacSelectFirst(input) {
                  // store the original event binding function
                  var _addEventListener = (input.addEventListener) ? input.addEventListener : input.attachEvent;

                  function addEventListenerWrapper(type, listener) {
                    // Simulate a 'down arrow' keypress on hitting 'return' when no pac suggestion is selected,
                    // and then trigger the original listener.
                    if (type == "keydown" || type == "blur") {
                      var orig_listener = listener;
                      listener = function(event) {
                        var suggestion_selected = $(".pac-item-selected").length > 0;
                        var keyCode = event.keyCode || event.which;
                        if ((keyCode === 13 || keyCode === 9) && !suggestion_selected) {
                          var simulated_downarrow = $.Event("keydown", {
                            keyCode: 40,
                            which: 40
                          });
                          orig_listener.apply(input, [simulated_downarrow]);
                        } else if(event.type === 'blur') {
                            pac_input.value =
                             $(".pac-container .pac-item:first-child").text();
                            // $(".pac-container").delegate(".pac-item:first-child","click",function(){
                            //  console.log("success");
                            // });

                            $(".pac-container .pac-item:first-child").bind('click',function(){
                                console.log("click");
                            });

                        }
                        orig_listener.apply(input, [event]);
                      };
                    }

                    // add the modified listener
                    _addEventListener.apply(input, [type, listener]);
                  }

                  if (input.addEventListener)
                    input.addEventListener = addEventListenerWrapper;
                  else if (input.attachEvent)
                    input.attachEvent = addEventListenerWrapper;

                })(pac_input);


                $(function() {
                  var autocomplete = new google.maps.places.Autocomplete(pac_input);
                });

Upvotes: 3

Views: 5555

Answers (4)

Patrick Kahl
Patrick Kahl

Reputation: 11

With this answer i created some code to choose the first item on blur and also on enter:

_addSelectFirstEvents() {
  const autoSelectFirstEntry = (e) => {
    if (e.type === 'keydown' && e.keyCode === 13) event.preventDefault()

  const isSuggestionSelected =
    document.querySelectorAll('.pac-item-selected').length > 0 ||
    document.querySelectorAll('.pac-container .pac-item:hover').length > 0

    if (
      !isSuggestionSelected &&
      ((e.keyCode === 13 && !e.triggered) || e.type === 'blur')
    ) {
      let arrowDownKeyEvent = new KeyboardEvent('keydown', {
        bubbles: true,
        cancelable: true,
        key: 'Down',
        code: 'Down',
        keyCode: 40,
        which: 40,
      })
      google.maps.event.trigger(e.target, 'keydown', arrowDownKeyEvent)

      const enterKeyEvent = new KeyboardEvent('keydown', {
        bubbles: true,
        cancelable: true,
        key: 'Enter',
        code: 'Enter',
        keyCode: 13,
        which: 13,
        triggered: true,
      })
      google.maps.event.trigger(e.target, 'keydown', enterKeyEvent)
    }
  }

  google.maps.event.addDomListener(this.input, 'blur', autoSelectFirstEntry)
  google.maps.event.addDomListener(this.input, 'keydown', autoSelectFirstEntry)
}

Upvotes: 1

2caffe
2caffe

Reputation: 51

I did this in my project:

    function initAutocomplete() {
        autocomplete = new google.maps.places.Autocomplete(document.getElementById('autocomplete'), {types: ['geocode']});
        autocomplete.setFields(['address_component']);
        // "standard" place_changed event
        autocomplete.addListener('place_changed', fillInAddress);
        // custom blur event
        $("#autocomplete").on('blur', function () {
            var $hover = $(".pac-container .pac-item:hover");
            // if an item has been clicked, do nothing, otherwise get first solution and use Geocoder to get the place
            if ($hover.length === 0) {
                var firstResult = $(".pac-container .pac-item:first").text();
                var geocoder = new google.maps.Geocoder();
                geocoder.geocode({
                    address: firstResult
                }, function (results, status) {
                    if (status === google.maps.GeocoderStatus.OK) {
                        fillInAddress(results[0]);
                    }
                });
            }
        });
    }

    function fillInAddress(place) {
        if (!place) {
            place = autocomplete.getPlace();
        }
        if (place && place.address_components) {
            // ... do what you need with the place
        }
    }

Upvotes: 3

Leandro
Leandro

Reputation: 190

In the event of blur, after a lot of wasted time i figured the blur executes before anything else (like simulated keydowns). Also,

pac_input.value = $(".pac-container .pac-item:first-child").text();

$(".pac-container .pac-item:first-child").bind('click',function(){
  console.log("click");
});

this binds the text value that is horrible to the autocomplete. So as an alternative, I did this in the else part(blur):

} else if (event.type == 'blur' && $(".pac-item").length > 0) {
                                var search = $('.pac-container:eq( '+$scope.$index+' ) .pac-item:first-child').text();
                                var autocompleteService = new google.maps.places.AutocompleteService();
                                autocompleteService.getPlacePredictions({
                                    'input': search,
                                    'offset': search.length,
                                    'componentRestrictions': { 'country': 'ar' }
                                }, function listentoresult(list, status) {
                                    if (list == null || list.length == 0) {
                                       //error!
                                    } else {
                                        //do what u want with the first autocomplete, it is the first result that the service will give you. If you want the same result with places, you must ask for the placesServices from googleapi
                                    }
                                });
                            }

NOTE:

$('.pac-container:eq( '+$scope.$index+' ) .pac-item:first-child').text()

I use this cause I have multiple autocompletes and there are many pac-containers, but if you have only one,

$('.pac-container .pac-item:first-child').text()

should suffice.

Upvotes: 2

Jayesh Chitroda
Jayesh Chitroda

Reputation: 5039

Try this:

DEmo: http://jsfiddle.net/q7L8bawe/

Add this event :

$("#pick-auto").blur(function (e) {
        if (e.which == 13) {
            var firstResult = $(".pac-container .pac-item:first").text();

            var geocoder = new google.maps.Geocoder();
            geocoder.geocode({"address":firstResult }, function(results, status) {
                if (status == google.maps.GeocoderStatus.OK) {
                    var lat = results[0].geometry.location.lat(),
                        lng = results[0].geometry.location.lng(),
                        placeName = results[0].address_components[0].long_name,
                        latlng = new google.maps.LatLng(lat, lng);

                        $(".pac-container .pac-item:first").addClass("pac-selected");
                        $(".pac-container").css("display","none");
                        $("#pick-auto").val(firstResult);
                        $(".pac-container").css("visibility","hidden");

                }
            });
        } else {
            $(".pac-container").css("visibility","visible");
        }

    });

Upvotes: 3

Related Questions