web-dev-qa-db-fra.com

Google Places Autocomplete - Choisissez le premier résultat sur la touche Entrée?

J'utilise une saisie semi-automatique de Google Adresses et je veux simplement qu'elle sélectionne le premier élément de la liste des résultats lorsque vous appuyez sur la touche Entrée dans le champ de formulaire et que des suggestions existent. Je sais que cela a déjà été demandé:

Google maps Places Auto-complétion de l'API V3 - Sélectionnez la première option à entrer

Google maps Places API V3 autocomplete - sélectionnez la première option à entrer (et laissez-la rester ainsi)

Mais les réponses à ces questions ne semblent pas réellement fonctionner, ou elles traitent de fonctionnalités ajoutées spécifiques.

Il semble également que quelque chose comme ce qui suit devrait fonctionner (mais cela ne fonctionne pas):

$("input#autocomplete").keydown(function(e) {
  if (e.which == 13) {          
    //if there are suggestions...
    if ($(".pac-container .pac-item").length) {
      //click on the first item in the list or simulate a down arrow key event
      //it does get this far, but I can't find a way to actually select the item
      $(".pac-container .pac-item:first").click();
    } else {
      //there are no suggestions
    }
  }
});

Toutes les suggestions seraient grandement appréciées!

28
NChase

J'ai lu les nombreuses réponses de cette question et des réponses des questions liées tellement de fois avant de trouver que la meilleure réponse est celle-ci (Nota: malheureusement, ce n'est pas la réponse acceptée!).

J'ai modifié 2 ou 3 lignes pour le transformer en une fonction prête à l'emploi que vous pouvez copier/coller dans votre code et appliquer à de nombreux éléments input si nécessaire. C'est ici:

var selectFirstOnEnter = function(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") { 
      var orig_listener = listener;
      listener = function (event) {
      var suggestion_selected = $(".pac-item-selected").length > 0;
        if (event.which == 13 && !suggestion_selected) { var simulated_downarrow = $.Event("keydown", {keyCode:40, which:40}); orig_listener.apply(input, [simulated_downarrow]); }
        orig_listener.apply(input, [event]);
      };
    }
    _addEventListener.apply(input, [type, listener]); // add the modified listener
  }
  if (input.addEventListener) { input.addEventListener = addEventListenerWrapper; } else if (input.attachEvent) { input.attachEvent = addEventListenerWrapper; }
}

Usage:

selectFirstOnEnter(input1);
selectFirstOnEnter(input2);
...
9
Basj

Je republie ma réponse à partir de Google maps Places: la saisie semi-automatique de la V3 - sélectionnez la première option lors de la saisie :

Il semble qu'il existe une solution bien meilleure et plus propre: utiliser google.maps.places.SearchBox au lieu de google.maps.places.Autocomplete. Un code est presque identique, il suffit d'obtenir le premier à partir de plusieurs emplacements. En appuyant sur la touche Entrer, la liste correcte est renvoyée - elle est donc prête à l'emploi et les hacks ne sont plus nécessaires.

Voir l'exemple de page HTML:

http://rawgithub.com/klokan/8408394/raw/5ab795fb36c67ad73c215269f61c7648633ae53e/places-enter-first-item.html

L'extrait de code pertinent est:

var searchBox = new google.maps.places.SearchBox(document.getElementById('searchinput'));

google.maps.event.addListener(searchBox, 'places_changed', function() {
  var place = searchBox.getPlaces()[0];

  if (!place.geometry) return;

  if (place.geometry.viewport) {
    map.fitBounds(place.geometry.viewport);
  } else {
    map.setCenter(place.geometry.location);
    map.setZoom(16);
  }
});

Le code source complet de l'exemple est à: https://Gist.github.com/klokan/8408394

9
Klokan Technologies

Sur mon site, pour obtenir cette même fonctionnalité, j’avais besoin du plugin jQuery simulate ( https://github.com/jquery/jquery-simulate ) puis joignais l’événement

$("input#autocomplete").focusin(function () {
    $(document).keypress(function (e) {
        if (e.which == 13) {
            $("input#autocomplete").trigger('focus');
            $("input#autocomplete").simulate('keydown', { keyCode: $.ui.keyCode.DOWN } ).simulate('keydown', { keyCode: $.ui.keyCode.ENTER });
        }
    });
});

Le plugin va simuler l'action de presser la touche BAS puis ENTER, ENTER lui-même ne fonctionne pas et je ne pouvais pas trouver un autre moyen de sélectionner la première option.

J'espère que cela t'aides

4
Mangiucugna

Solution de travail à l'écoute si l'utilisateur a commencé à naviguer dans la liste avec le clavier au lieu de déclencher la fausse navigation à chaque fois

https://codepen.io/callam/pen/RgzxZB

Voici les bits importants

// search input
const searchInput = document.getElementById('js-search-input');

// Google Maps autocomplete
const autocomplete = new google.maps.places.Autocomplete(searchInput);

// Has user pressed the down key to navigate autocomplete options?
let hasDownBeenPressed = false;

// Listener outside to stop nested loop returning odd results
searchInput.addEventListener('keydown', (e) => {
    if (e.keyCode === 40) {
        hasDownBeenPressed = true;
    }
});

// GoogleMaps API custom eventlistener method
google.maps.event.addDomListener(searchInput, 'keydown', (e) => {

    // Maps API e.stopPropagation();
    e.cancelBubble = true;

    // If enter key, or tab key
    if (e.keyCode === 13 || e.keyCode === 9) {
        // If user isn't navigating using arrows and this hasn't ran yet
        if (!hasDownBeenPressed && !e.hasRanOnce) {
            google.maps.event.trigger(e.target, 'keydown', {
                keyCode: 40,
                hasRanOnce: true,
            });
        }
    }
});

 // Clear the input on focus, reset hasDownBeenPressed
searchInput.addEventListener('focus', () => {
    hasDownBeenPressed = false;
    searchInput.value = '';
});

// place_changed GoogleMaps listener when we do submit
google.maps.event.addListener(autocomplete, 'place_changed', function() {

    // Get the place info from the autocomplete Api
    const place = autocomplete.getPlace();

    //If we can find the place lets go to it
    if (typeof place.address_components !== 'undefined') {          
        // reset hasDownBeenPressed in case they don't unfocus
        hasDownBeenPressed = false;
    }

});
4
Callam

C'est ce que j'ai fait et ça marche:

HTML:

<input name="location" id="autocomplete" autocomplete="off" type="text" class="textbx" placeholder="Enter Destination" required>

googleautocompletecustomized.js:

        function initialize() {
      // Create the autocomplete object, restricting the search
      // to geographical location types.
      if($('#autocomplete').length){
          autocomplete = new google.maps.places.Autocomplete(
              (document.getElementById('autocomplete')),
              {
                types: ['(regions)'],
                componentRestrictions: {country: "in"}
              });
          google.maps.event.addListener(autocomplete, 'place_changed', function() {
            $('#autocomplete').closest('form').data('changed', true);
            fillInAddress();
          });         
      }

    //select first result
        $('#autocomplete').keydown(function (e) {
            if (e.keyCode == 13 || e.keyCode == 9) {
                $(e.target).blur();
                if($(".pac-container .pac-item:first span:eq(3)").text() == "")
                    var firstResult = $(".pac-container .pac-item:first .pac-item-query").text();
                else
                    var firstResult = $(".pac-container .pac-item:first .pac-item-query").text() + ", " + $(".pac-container .pac-item:first span:eq(3)").text();

                var geocoder = new google.maps.Geocoder();
                geocoder.geocode({"address":firstResult }, function(results, status) {
                    if (status == google.maps.GeocoderStatus.OK) {
                        placeName = results[0];
                        e.target.value = firstResult;
                        fillInAddress(placeName);
                        $('#datetimepicker1 .input-group-addon').click();
                    }
                });
            }

        });
    }

// [START region_fillform]
function fillInAddress(place) {
  // Get the place details from the autocomplete object.
  if(!place)
    var place = autocomplete.getPlace();

  for (var component in componentForm) {
    document.getElementById(component).value = '';
    document.getElementById(component).disabled = false;
  }

  // Get each component of the address from the place details
  // and fill the corresponding field on the form.
  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]];
      document.getElementById(addressType).value = val;

    }
  }

}
2
Fronto
0
saravana va

C'est le moyen le plus simple qui me soit résolu:

autocomplete.addListener('place_changed', function() {
  if(event.keyCode == 13 || event.keyCode == 9) { // detect the enter key
    var firstValue = $(".pac-container .pac-item:first").text(); // assign to this variable the first string from the autocomplete dropdown
     }
    $('#search-address').val(firstValue); // add this string to input
    console.log(firstValue); // display the string on your browser console to check what it is
   //(...) add the rest of your code here
  });
}
0
Fillype Farias