Google Autocomplete - введіть, щоб вибрати


80

У мене налаштовано автозаповнення Google для текстового поля форми HTML, і воно працює чудово.

Однак, коли список пропозицій з'являються, і використовувати стрілки для прокрутки і вибору з допомогою введення, він відправляє форму, хоча все ще є ящики для заповнення. Якщо ви оберете пропозицію він працює нормально, але пресинг ввести ПРЕДСТАВЛЯЄ .

Як я можу це контролювати? Як я можу зупинити введення від подання форми, а замість цього вибрати вибір пропозиції з автозаповнення?

Дякую! {S}

Відповіді:


110

Ви можете використовувати, preventDefaultщоб зупинити надсилання форми при натисканні клавіші enter, я використав щось подібне:

  var input = document.getElementById('inputId');
  google.maps.event.addDomListener(input, 'keydown', function(event) { 
    if (event.keyCode === 13) { 
        event.preventDefault(); 
    }
  }); 

2
Це завжди скасовує подання з поля. Мені він потрібен лише для скасування подання, якщо користувач натиснув вступ, щоб вибрати параметр автозавершення.
A. Matías Quezada

1
Працює як самоцвіт. Натискання та вибір параметра автозаповнення зі списку за допомогою enter більше не подає форму.
Ерік Л.,

Це швидше, ніж рішення. Те саме, що використання обробника onClick для подання форми замість обробника onSubmit. Enter повинен подати форму.
Олексій Федосєєв

4
Я користувався keyupпротягом останніх півгодини, намагаючись вирішити свою проблему, що ви і зробили. Отже, люди, не використовуйте keyupдля лову подань
Ніко

52

Використання обробки подій Google здається правильним рішенням, але це не працює для мене. Це рішення jQuery працює для мене:

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

.pac-containerє div, який зберігає збіги автозавершення. Ідея полягає в тому, що коли збіги видно, клавіша Enter просто вибере активний збіг. Але коли матчі приховані (тобто вибрано місце), він подасть форму.


працює чудово, тому дякую. простий та ефективний.
luke_mclachlan

Мабуть, найелегантніше рішення. Дякую!
Микола Трайков

але хіба це не допускає введення, яке подає форму на порожнє поле? перед вибором адреси?
amosmos

1
Це не працює в Chrome. Схоже, події клавіш Chrome не виявляють Enter, якщо введення знаходиться всередині форми.
Бруно

1
Єдиним недоліком цього рішення є те, що якщо Google вирішить змінити HTML, який вони вводять на вашу сторінку та перейменовують .pac-containerна щось інше, це зламається.
Джастін Таннер,

21

Я об’єднав перші дві відповіді від @sren та @mmalone, щоб створити це:

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

чудово працює на сторінці. запобігає надсиланню форми, коли видно контейнер пропозицій (.pac-container). Отже, зараз із випадаючого списку автозаповнення вибирається параметр, коли користувачі натискають клавішу Enter, і вони повинні натиснути її ще раз, щоб надіслати форму.

Моя основна причина використання цього обхідного шляху полягає в тому, що я виявив, що якщо форма надсилається, як тільки вибрано параметр, за допомогою клавіші enter значення широти та довготи передаються недостатньо швидко в свої приховані елементи форми.

Всім заслуга оригінальних відповідей.


7

Цей працював у мене:

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();

  }

});

Можна легко перетворити з ES6 на будь-який сумісний з браузером код.


Мені подобається ваша відповідь, але мені довелося трохи її налаштувати, щоб вона запрацювала. Опублікував своє рішення.
Schulwitz

4

Проблема у мене з відповіддю @ sren полягала в тому, що вона завжди блокує подію submit. Мені сподобалась відповідь @ mmalone, але вона поводилася випадково, оскільки іноді, коли я натискав, ENTERщоб вибрати місце, обробник запускався після того, як контейнер приховано. Отже, ось що я в підсумку зробив

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>

Прапор гарантує, що якщо місце розташування змінюється та входять користувацькі звернення, подія блокується. Врешті-решт для прапора встановлюється подія falsegoogle map place_changed, що дозволяє подавати форму після натискання клавіші Enter.


Цей код насправді спрацював для мене, дякую за зусилля!
Aimal Khan

Цей код уникає подання, якщо користувач пише, натискає клавішу Enter, а потім стрілку вниз (або будь-яку клавішу, яка не запускає автозаповнення). Після цього повернення блокується.
Natxet

1

Ось простий код, який мені добре працював (не використовує jquery).

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

Цей фрагмент коду, щоб слідувати наведеному вище коду, використовується для реалізації автозаповнення карт Google (з функцією клавіші Enter або без неї, яку шукають у цьому питанні):

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 (викликається вище в першій частині коду) визначено:

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

Цей код робить поле автозаповнення карт Google вибором того елемента, який користувач вибере натисканням клавіші зі стрілкою вниз. Коли користувач вибирає опцію натисканням клавіші Enter, нічого не відбувається. Користувач повинен натиснути Enter ще раз, щоб запустити onSubmit () або іншу команду


0

Я докоригував код Алекса, оскільки він зламався в браузері. Це мені ідеально підходить:

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]);
    }
}

0

Я спробував вищезазначені короткі відповіді, але вони не працювали для мене, а довгі відповіді я не хотів їх випробовувати, тому я створив наступний код, який у мене працював досить добре. Див. Демо

Припустимо, це ваша форма:

<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>

Тоді наступний код JavaScript вирішить проблему:

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;
    }
});

А ось як виглядає повний код на HTML-сторінці (Зверніть увагу, що вам потрібно замінити на YOUR_API_KEYсвій ключ API Google):

<!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>

0
$("#myinput").on("keydown", function(e) {
if (e.which == 13) {

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

}

Використовуйте, $('.pac-item:first').trigger('click');якщо ви хочете вибрати перший результат


0

Ви можете зробити це у ванілі:

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();
     }
 })
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.