Autouzupełnianie Google - wprowadź, aby wybrać

80

Mam ustawione autouzupełnianie Google dla pola tekstowego formularza HTML i działa idealnie.

Jednak gdy pojawia się lista sugestii i używasz strzałek do przewijania i wybierania za pomocą klawisza Enter , przesyła on formularz, chociaż nadal są pola do wypełnienia. Jeśli klikniesz, aby wybrać sugestię, działa dobrze, ale naciśnięcie klawisza Enter przesyła .

Jak mogę to kontrolować? Jak mogę powstrzymać Enter przed przesłaniem formularza i zamiast tego wybrać sugestię z autouzupełniania?

Dzięki! {S}

kinkersnick
źródło

Odpowiedzi:

110

Możesz użyć, preventDefaultaby zatrzymać przesyłanie formularza po naciśnięciu klawisza Enter, użyłem czegoś takiego:

  var input = document.getElementById('inputId');
  google.maps.event.addDomListener(input, 'keydown', function(event) { 
    if (event.keyCode === 13) { 
        event.preventDefault(); 
    }
  }); 
sren
źródło
2
Spowoduje to zawsze anulowanie przesyłania z tego pola. Potrzebuję go tylko do anulowania przesyłania, jeśli użytkownik nacisnął intro, aby wybrać opcję autouzupełniania.
A. Matías Quezada
1
Działa jak klejnot. Naciśnięcie i wybranie opcji autouzupełniania z listy klawiszem Enter nie powoduje już przesłania formularza.
Eric L.
To jest bardziej niepodważalne niż rozwiązanie. To samo, co użycie modułu obsługi onClick do przesłania formularza zamiast modułu obsługi onSubmit. Enter powinien przesłać formularz.
Alex Fedoseev
4
Używałem keyupprzez ostatnie pół godziny próbuje rozwiązać mój problem, co zrobiłeś. Więc ludzie, nie używajcie keyupdo łapania zgłoszeń formularzy
Nico
52

Korzystanie z obsługi zdarzeń Google wydaje się być właściwym rozwiązaniem, ale nie działa dla mnie. To rozwiązanie jQuery działa dla mnie:

$('#inputId').keydown(function (e) {
  if (e.which == 13 && $('.pac-container:visible').length) return false;
});

.pac-containerto element div przechowujący dopasowania autouzupełniania. Chodzi o to, że kiedy dopasowania są widoczne, klawisz Enter po prostu wybiera aktywne dopasowanie. Ale gdy mecze zostaną ukryte (tj. Miejsce zostało wybrane), prześle formularz.

mmalone
źródło
działa pięknie, więc dziękuję. proste i skuteczne.
luke_mclachlan
Prawdopodobnie najbardziej eleganckie rozwiązanie. Dziękuję Ci!
Nikolay Traykov
ale czy to nie pozwoliłoby na wprowadzenie, które przesyła formularz w pustym polu? przed wyborem adresu?
amosmos
1
To nie działa w Chrome. Wygląda na to, że zdarzenia kluczy Chrome nie wykrywają Enter, jeśli dane wejściowe znajdują się wewnątrz formularza.
Bruno
1
Jedynym minusem tego rozwiązania jest to, że jeśli Google zdecyduje się zmienić HTML, który wstrzykuje na twoją stronę i zmienić nazwę .pac-containerna inną, to się zepsuje.
Justin Tanner
21

Połączyłem dwie pierwsze odpowiedzi od @sren i @mmalone, aby uzyskać to:

var input= document.getElementById('inputId');
google.maps.event.addDomListener(input, 'keydown', function(e) { 
    if (e.keyCode == 13 && $('.pac-container:visible').length) { 
        e.preventDefault(); 
    }
}); 

działa idealnie na stronie. zapobiega przesłaniu formularza, gdy kontener sugestii (.pac-container) jest widoczny. Tak więc teraz opcja z listy rozwijanej autouzupełniania jest wybierana, gdy użytkownik naciśnie klawisz Enter i muszą nacisnąć go ponownie, aby przesłać formularz.

Moim głównym powodem zastosowania tego obejścia jest to, że stwierdziłem, że jeśli formularz jest wysyłany zaraz po wybraniu opcji, za pomocą klawisza enter, wartości szerokości i długości geograficznej nie były przekazywane wystarczająco szybko do ich ukrytych elementów formularza.

Wszystkie zasługi dla oryginalnych odpowiedzi.

luke_mclachlan
źródło
7

Ten pracował dla mnie:

google.maps.event.addDomListener(input, 'keydown', e => {

  // If it's Enter
  if (e.keyCode === 13) {

    // Select all Google's dropdown DOM nodes (can be multiple)
    const googleDOMNodes = document.getElementsByClassName('pac-container');

    // Check if any of them are visible (using ES6 here for conciseness)
    const googleDOMNodeIsVisible = (
      Array.from(googleDOMNodes).some(node => node.offsetParent !== null)
    );

    // If one is visible - preventDefault
    if (googleDOMNodeIsVisible) e.preventDefault();

  }

});

Można go łatwo przekonwertować z ES6 na dowolny kod zgodny z przeglądarką.

Alex Fedoseev
źródło
Podoba mi się twoja odpowiedź, ale musiałem ją trochę poprawić, żeby zadziałała. Wysłałem moje rozwiązanie.
schulwitz
4

Problem, który miałem z odpowiedzią @ sren polegał na tym, że zawsze blokuje zdarzenie przesyłania. Podobała mi się odpowiedź @ mmalone, ale zachowywała się losowo, ponieważ czasami, gdy klikałem, ENTERaby wybrać lokalizację, program obsługi uruchamiał się po ukryciu kontenera. Oto, co ostatecznie zrobiłem

var location_being_changed,
    input = document.getElementById("js-my-input"),
    autocomplete = new google.maps.places.Autocomplete(input),
    onPlaceChange = function () {
        location_being_changed = false;
    };

google.maps.event.addListener( this.autocomplete,
                               'place_changed',
                               onPlaceChange );

google.maps.event.addDomListener(input, 'keydown', function (e) {
    if (e.keyCode === 13) {
        if (location_being_changed) {
            e.preventDefault();
            e.stopPropagation();
        }
    } else {
        // means the user is probably typing
        location_being_changed = true;
    }
});

// Form Submit Handler
$('.js-my-form').on('submit', function (e) {
    e.preventDefault();
    $('.js-display').text("Yay form got submitted");
});
<p class="js-display"></p>
<form class="js-my-form">
    <input type="text" id="js-my-input" />
    <button type="submit">Submit</button>
</form>

<!-- External Libraries -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="//maps.googleapis.com/maps/api/js?sensor=false&libraries=places"></script>

Flaga zapewnia, że ​​w przypadku zmiany lokalizacji i wejścia użytkownika, zdarzenie jest blokowane. Ostatecznie flaga jest ustawiana falseprzez place_changedzdarzenie mapy google , które następnie umożliwia przesłanie formularza po naciśnięciu klawisza Enter.

Mudassir Ali
źródło
Ten kod faktycznie działał dla mnie, dziękuję za wysiłek!
Aimal Khan,
Ten kod unika przesyłania, jeśli użytkownik pisze, wciska enter, a następnie strzałkę w dół (lub dowolny klawisz, który nie uruchamia autouzupełniania). Po tym powrót zostanie zablokowany.
Natxet
1

Oto prosty kod, który działał dobrze dla mnie (nie używa jquery).

const googleAutcompleteField = this.renderer.selectRootElement(this.elem.nativeElement);
this.selectOnEnter(googleAutcompleteField);

Ten fragment kodu, zgodnie z powyższym kodem, służy do implementacji autouzupełniania map Google (z lub bez funkcji klawisza Enter poszukiwanej w tym pytaniu):

this.autocomplete = new google.maps.places.Autocomplete(googleAutcompleteField, this.googleMapsOptions);
this.autocomplete.setFields(['address_component', 'formatted_address', 'geometry']);
this.autocomplete.addListener('place_changed', () => {
  this.zone.run(() => {
    this.googleMapsData.emit([this.autocomplete.getPlace()]);
  })
})

selectOnEnter (wywołany powyżej w pierwszym fragmencie kodu) zdefiniowano:

selectOnEnter(inputField) {
  inputField.addEventListener("keydown", (event) => {
    const selectedItem = document.getElementsByClassName('pac-item-selected');
    if (event.key == "Enter" && selectedItem.length != 0) {
      event.preventDefault();
    }
  })
}

Ten kod sprawia, że ​​pole autouzupełniania map Google wybiera dowolny element, który użytkownik wybierze za pomocą klawisza strzałki w dół. Gdy użytkownik wybierze opcję za pomocą naciśnięcia klawisza Enter, nic się nie dzieje. Użytkownik musi ponownie nacisnąć klawisz Enter, aby wywołać onSubmit () lub inne polecenie

coder101
źródło
0

Poprawiłem kod Alexa, ponieważ zepsuł się w przeglądarce. To działa idealnie dla mnie:

google.maps.event.addDomListener(
    document.getElementById('YOUR_ELEMENT_ID'),
    'keydown',
    function(e) {
          // If it's Enter
          if (e.keyCode === 13) {
            // Select all Google's dropdown DOM nodes (can be multiple)
            const googleDOMNodes = document.getElementsByClassName('pac-container');
            //If multiple nodes, prevent form submit.
            if (googleDOMNodes.length > 0){
                e.preventDefault();
            }
            //Remove Google's drop down elements, so that future form submit requests work.
            removeElementsByClass('pac-container');
          }
    }
);

function removeElementsByClass(className){
    var elements = document.getElementsByClassName(className);
    while(elements.length > 0){
        elements[0].parentNode.removeChild(elements[0]);
    }
}
schulwitz
źródło
0

Wypróbowałem powyższe krótkie odpowiedzi, ale nie zadziałały dla mnie, a długich odpowiedzi nie chciałem ich wypróbować, więc stworzyłem następujący kod, który działał dla mnie całkiem dobrze. Zobacz Demo

Załóżmy, że to jest twój formularz:

<form action="" method="">
      <input type="text" name="place" id="google-places-searchbox" placeholder="Enter place name"><br><br>
      <input type="text" name="field-1" placeholder="Field 1"><br><br>
      <input type="text" name="field-2" placeholder="Field 2"><br><br>
      <button type="submit">Submit</button>
</form>

Wtedy poniższy kod javascript rozwiąże problem:

var placesSearchbox = $("#google-places-searchbox");

placesSearchbox.on("focus blur", function() {
    $(this).closest("form").toggleClass('prevent_submit');
});

placesSearchbox.closest("form").on("submit", function(e) {
    if (placesSearchbox.closest("form").hasClass('prevent_submit')) {
        e.preventDefault();
        return false;
    }
});

A oto jak wygląda pełny kod na stronie HTML (pamiętaj, że musisz zamienić na YOUR_API_KEYklucz google api):

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>Prevent form submission when choosing a place from google places autocomplete searchbox</title>
</head>
<body>
  <form action="" method="">
      <input type="text" name="place" id="google-places-searchbox" placeholder="Enter place name"><br><br>
      <input type="text" name="field-1" placeholder="Field 1"><br><br>
      <input type="text" name="field-2" placeholder="Field 2"><br><br>
      <button type="submit">Submit</button>
  </form>

  <!-- jQuery -->
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>

  <!-- Google Maps -->
  <!-- Note that you need to replace the next YOUR_API_KEY with your api key -->
  <script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places"
     async defer></script>
  <script>
    var input = document.getElementById("google-places-searchbox");
    var searchBox = new google.maps.places.SearchBox(input);

    var placesSearchbox = $("#google-places-searchbox");

    placesSearchbox.on("focus blur", function() {
        $(this).closest("form").toggleClass('prevent_submit');
    });

    placesSearchbox.closest("form").on("submit", function(e) {
        if (placesSearchbox.closest("form").hasClass('prevent_submit')) {
            e.preventDefault();
            return false;
        }
    });
  </script>
</body>
</html>
Amr
źródło
0
$("#myinput").on("keydown", function(e) {
if (e.which == 13) {

if($(".pac-item").length>0)
        {
            $(".pac-item-selected").trigger("click");
}

}

Użyj, $('.pac-item:first').trigger('click');jeśli chcesz wybrać pierwszy wynik

Mool Singh
źródło
0

Możesz to zrobić w wanilii:

element.addEventListener('keydown', function(e) {
    const gPlaceChoices = document.querySelector('.pac-container')
    // No choices element ? 
    if (null === gPlaceChoices) {
        return
    }
    // Get choices visivility
    let visibility = window.getComputedStyle(gPlaceChoices).display
    // In this case, enter key will do nothing
    if ('none' !== visibility && e.keyCode === 13) {
        e.preventDefault();
     }
 })
Digivia
źródło