Reputation: 192
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
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
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
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
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