谷歌自动完成 - 输入选择

Posted

技术标签:

【中文标题】谷歌自动完成 - 输入选择【英文标题】:Google Autocomplete - enter to select 【发布时间】:2012-07-08 10:48:08 【问题描述】:

我为 html 表单的文本字段设置了 Google 自动完成,它运行良好。

但是,当建议列表出现时,您使用箭头滚动并使用 enter 选择,它会提交表单,尽管仍有一些框要填写。如果您单击选择建议,它可以正常工作,但是按 enter 提交。

我该如何控制呢?如何停止输入提交表单,而是从自动完成中选择建议?

谢谢! S

【问题讨论】:

【参考方案1】:

您可以使用preventDefault 在输入时停止提交表单,我使用了这样的东西:

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

【讨论】:

这将始终取消从字段提交。如果用户按下介绍以选择自动完成选项,我只需要它来取消提交。 像宝石一样工作。按下回车键并从列表中选择自动完成选项不再提交表单。 这比解决方案更不合时宜。与使用 onClick 处理程序提交表单而不是 onSubmit 处理程序的用法相同。 Enter 应该提交表单。 过去半小时我一直在使用keyup 来解决我的问题,而你做到了。所以,人们,不要使用keyup 来捕获表单提交【参考方案2】:

使用 Google 事件处理似乎是正确的解决方案,但它对我不起作用。这个 jQuery 解决方案对我有用:

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

.pac-container 是保存自动完成匹配的 div。这个想法是,当匹配可见时,Enter 键将只选择活动匹配。但是当匹配项被隐藏(即选择了一个地方)时,它会提交表单。

【讨论】:

效果很好,谢谢。简单有效。 可能是最优雅的解决方案。谢谢! 但这不会允许在空字段上提交表单的输入吗?在选择地址之前? 这在 Chrome 中不起作用。如果输入在表单内,Chrome 键事件似乎不会检测到 Enter。 此解决方案的唯一缺点是,如果 Google 决定更改它们注入您页面的 HTML 并将 .pac-container 重命名为其他名称,则会中断。【参考方案3】:

我已经合并了@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) 可见时提交表单。所以现在,当用户按下回车键时,自动完成下拉菜单中的一个选项被选中,他们必须再次按下它才能提交表单。

我使用此解决方法的主要原因是因为我发现如果通过回车键选择选项后立即发送表单,则纬度和经度值没有足够快地传递到其隐藏的表单元素中。

所有功劳归于原始答案。

【讨论】:

【参考方案4】:

这个对我有用:

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 转换为任何与浏览器兼容的代码。

【讨论】:

我喜欢您的回答,但我必须对其进行一些调整才能使其正常工作。发布我的解决方案。【参考方案5】:

我对@sren 的回答的问题是它总是阻止提交事件。我喜欢@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>

该标志确保如果位置正在更改并且用户点击回车,则事件被阻止。最终,谷歌地图的place_changed 事件将标志设置为false,然后允许在按下回车键时提交表单。

【讨论】:

这段代码确实对我有用,谢谢你的努力! 如果用户写,按回车键,然后向下箭头(或任何不触发自动完成的键),此代码将避免提交。在此之后,返回被阻止。【参考方案6】:

这是一个对我很有效的简单代码(不使用 jquery)。

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

按照上面的代码,这段代码用于实现谷歌地图自动完成(有或没有本问题中寻求的 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();
    
  )

此代码使谷歌地图自动完成字段选择用户使用向下箭头键选择的任何项目。一旦用户按下 Enter 键选择了一个选项,什么也不会发生。用户必须再次按 Enter 才能触发 onSubmit() 或其他命令

【讨论】:

【参考方案7】:

你可以在原版中做到这一点:

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

【讨论】:

由于getComputedStyle 的使用,我认为这个答案的代码最清晰。谢谢! 可以添加哪个元素作为例子。【参考方案8】:

我调整了 Alex 的代码,因为它在浏览器中损坏了。这对我来说很完美:

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

【讨论】:

【参考方案9】:

我已经尝试了上面的简短答案,但它们对我不起作用,而我不想尝试的长答案,所以我创建了以下代码,对我来说效果很好。 See Demo

假设这是你的表单:

<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 替换为您的 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>

【讨论】:

【参考方案10】:
$("#myinput").on("keydown", function(e) 
if (e.which == 13) 

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



如果要选择第一个结果,请使用$('.pac-item:first').trigger('click');

【讨论】:

以上是关于谷歌自动完成 - 输入选择的主要内容,如果未能解决你的问题,请参考以下文章

谷歌地图API地方自动完成getPlace()不起作用

谷歌地图自动完成,修复输入

谷歌中的正确事件用鼠标自动完成选择

如何更改谷歌自动完成的输入字段

谷歌地图自动完成动态数组

使用 jQuery Mobile 自动完成谷歌地图