当没有选择自动完成选项时,如何禁用enter:谷歌地图搜索框

时间:2021-07-18 21:17:03

Using Google Maps Searchbox with autocomplete:

使用谷歌地图搜索框自动完成:

If a user enters a name that displays results, and hit Enter before selecting an actual result, the 'places_matched' event still fires and the API chooses a result for them.

如果用户输入显示结果的名称,并在选择实际结果之前单击Enter,则“places_matches”事件仍然会触发,API为它们选择结果。

How can I force the user to select/highlight an autocomplete result, or at least detect somewhere that they didn't actually select a result and block the request?

如何强制用户选择/突出显示自动完成的结果,或者至少检测到他们实际上没有选择结果并阻止请求的某个地方?

See the jsfiddle here: http://jsfiddle.net/4rs1mgno/2/

请参阅这里的jsfiddle: http://jsfiddle.net/4rs1mgno/2/

In the text input, enter anything, and hit enter. I type 'testing' and it outputs "BYU Testing Center". I want nothing to happen, since they didn't actually select an option.

在文本输入中,输入任何内容,然后单击enter。输入‘testing’,输出为“BYU test Center”。我不希望发生任何事情,因为他们实际上没有选择一个选项。

Here's the JS code from the fiddle:

以下是小提琴的JS代码:

 $(function(){      
 var input = document.getElementById('pac-input');
    var options = {
      keyword: 'establishment'
    }
    var searchBox = new google.maps.places.SearchBox(input, options);

    searchBox.addListener('places_changed',     function(evt) {
      console.log('changed');

      var places = searchBox.getPlaces();

      if (places.length == 0) {
        return;
      }
      places.forEach(function(place) {
        $('#output').append(place['name']);
      });
    });
});

Thanks!

谢谢!

There are a lot of similar questions here on SO, but none that match this.

这里有很多类似的问题,但是没有一个与之匹配。

3 个解决方案

#1


6  

You can use the Autocomplete Service and the Places Service and mimic the behavior of the SearchBox. Using getPlacePredictions you can easily control the behavior of your search field and the search results items.

您可以使用自动完成服务和Places服务并模拟SearchBox的行为。使用getplace预测值可以很容易地控制搜索字段的行为和搜索结果项。

This example already has a bit of CSS that makes it look "like" the SearchBox. You can adapt and enhance of course. The code is commented so it should speak for itself.

这个例子已经有了一些CSS,使它看起来“像”搜索框。你当然可以适应和提高。代码被注释,因此它应该为自己辩护。

var autocompleteService, placesService, results, map;

function initialize() {

  results = document.getElementById('results');

  var mapOptions = {
    zoom: 5,
    center: new google.maps.LatLng(50, 50)
  };

  map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);

  // Bind listener for address search
  google.maps.event.addDomListener(document.getElementById('address'), 'input', function() {

    results.style.display = 'block';
    getPlacePredictions(document.getElementById('address').value);
  });

  // Show results when address field is focused (if not empty)
  google.maps.event.addDomListener(document.getElementById('address'), 'focus', function() {

    if (document.getElementById('address').value !== '') {

      results.style.display = 'block';
      getPlacePredictions(document.getElementById('address').value);
    }
  });

  // Hide results when click occurs out of the results and inputs
  google.maps.event.addDomListener(document, 'click', function(e) {

    if ((e.target.parentElement.className !== 'pac-container') && (e.target.parentElement.className !== 'pac-item') && (e.target.tagName !== 'INPUT')) {

      results.style.display = 'none';
    }
  });

  autocompleteService = new google.maps.places.AutocompleteService();
  placesService = new google.maps.places.PlacesService(map);
}

// Get place predictions
function getPlacePredictions(search) {

  autocompleteService.getPlacePredictions({
    input: search,
    types: ['establishment', 'geocode']
  }, callback);
}

// Get place details
function getPlaceDetails(placeId) {

  var request = {
    placeId: placeId
  };

  placesService.getDetails(request, function(place, status) {

    if (status === google.maps.places.PlacesServiceStatus.OK) {

      var center = place.geometry.location;
      var marker = new google.maps.Marker({
        position: center,
        map: map
      });

      map.setCenter(center);

      // Hide autocomplete results
      results.style.display = 'none';
    }
  });
}

// Place search callback
function callback(predictions, status) {

  // Empty results container
  results.innerHTML = '';

  // Place service status error
  if (status != google.maps.places.PlacesServiceStatus.OK) {
    results.innerHTML = '<div class="pac-item pac-item-error">Your search returned no result. Status: ' + status + '</div>';
    return;
  }

  // Build output for each prediction
  for (var i = 0, prediction; prediction = predictions[i]; i++) {

    // Insert output in results container
    results.innerHTML += '<div class="pac-item" data-placeid="' + prediction.place_id + '" data-name="' + prediction.terms[0].value + '"><span class="pac-icon pac-icon-marker"></span>' + prediction.description + '</div>';
  }

  var items = document.getElementsByClassName("pac-item");

  // Results items click
  for (var i = 0, item; item = items[i]; i++) {

    item.onclick = function() {

      getPlaceDetails(this.dataset.placeid);
    };
  }
}

google.maps.event.addDomListener(window, 'load', initialize);
body,
html {
  font-family: Arial, sans-serif;
  padding: 0;
  margin: 0;
  height: 100%;
}

#map-canvas {
  height: 150px;
  width: 200px;
  margin-bottom: 10px;
}

.search {
  width: 200px;
  padding: 5px;
  float: left;
}

label {
  display: block;
  width: 160px;
  font-size: 11px;
  color: #777;
  margin-bottom: 5px;
}

input {
  border: 1px solid #ccc;
  width: 170px;
  padding: 3px 5px;
  box-sizing: border-box;
  -moz-box-sizing: border-box;
  -webkit-box-sizing: border-box;
  box-shadow: 0 2px 6px rgba(0, 0, 0, .1);
}

.pac-container {
  background-color: #fff;
  z-index: 1000;
  border-radius: 2px;
  font-size: 11px;
  box-shadow: 0 2px 6px rgba(0, 0, 0, .3);
  -moz-box-sizing: border-box;
  -webkit-box-sizing: border-box;
  box-sizing: border-box;
  overflow: hidden;
  width: 170px;
}

.pac-icon {
  width: 15px;
  height: 20px;
  margin-right: 7px;
  margin-top: 6px;
  display: inline-block;
  vertical-align: top;
  background-image: url(https://maps.gstatic.com/mapfiles/api-3/images/autocomplete-icons.png);
  background-size: 34px;
}

.pac-icon-marker {
  background-position: -1px -161px;
}

.pac-item {
  cursor: pointer;
  padding: 0 4px;
  text-overflow: ellipsis;
  overflow: hidden;
  white-space: nowrap;
  line-height: 30px;
  vertical-align: middle;
  text-align: left;
  border-top: 1px solid #e6e6e6;
  color: #999;
}

.pac-item:hover {
  background-color: #efefef;
}

.pac-item-error,
.pac-item-error:hover {
  color: #aaa;
  padding: 0 5px;
  cursor: default;
  background-color: #fff;
}
<div class="search">
  <label for="address">Address:</label>
  <input id="address" placeholder="Enter address" type="text" tabindex="1" />
  <br />
  <div id="results" class="pac-container"></div>
</div>
<div id="map-canvas"></div>

<script src="https://maps.googleapis.com/maps/api/js?libraries=places"></script>

#2


2  

Here is the updated fiddle with the solution. The idea is quite simple after knowing the searchbox caches up to 5 results everytime you have a key stroke locally in your DOM tree until you have a match. They are cached in the div.pac-container element.

这是最新的解决方案。在知道searchbox每次在DOM树中本地执行一次按键操作,直到找到匹配的结果后,这个想法非常简单。它们缓存在div.pac-container元素中。

 $(function(){      
   var input = document.getElementById('pac-input');
   var options = {
      keyword: 'establishment'
   }
   var searchBox = new google.maps.places.SearchBox(input, options);

   searchBox.addListener('places_changed',  function(evt) {

     var places = searchBox.getPlaces();

     if ($('.pac-item').length > 0) {
       return;
     }

     places.forEach(function(place) {
       $('#output').append(place['name']);
     });
   });
});

#3


2  

If user press enter nothing will happen.
Edit 3:

如果用户按下输入,则不会发生任何事情。编辑3:

$(function(){      
 var input = document.getElementById('pac-input');
    var options = {
      keyword: 'establishment'
    }
    var searchBox = new google.maps.places.Autocomplete(input, options);
    
    google.maps.event.addListener(searchBox, 'place_changed', function () {

      var place = searchBox.getPlace();
      if(place.address_components != null && place.address_components.length >= 1){
        console.log(place.address_components.length);
        $('#output').append(place['name']);
      }
      

  });
    
});
body {         
    font:14px sans-serif;           
} 
input {
    margin: 0.6em 0.6em 0; 
    width:398px;
}
#map_canvas {         
    height: 400px;         
    width: 400px;         
    margin: 0.6em;       
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://maps.google.com/maps/api/js?libraries=places&region=us&language=en&sensor=false"></script>
<input id="pac-input" type="text" size="50">             
<div id="output"></div>

#1


6  

You can use the Autocomplete Service and the Places Service and mimic the behavior of the SearchBox. Using getPlacePredictions you can easily control the behavior of your search field and the search results items.

您可以使用自动完成服务和Places服务并模拟SearchBox的行为。使用getplace预测值可以很容易地控制搜索字段的行为和搜索结果项。

This example already has a bit of CSS that makes it look "like" the SearchBox. You can adapt and enhance of course. The code is commented so it should speak for itself.

这个例子已经有了一些CSS,使它看起来“像”搜索框。你当然可以适应和提高。代码被注释,因此它应该为自己辩护。

var autocompleteService, placesService, results, map;

function initialize() {

  results = document.getElementById('results');

  var mapOptions = {
    zoom: 5,
    center: new google.maps.LatLng(50, 50)
  };

  map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);

  // Bind listener for address search
  google.maps.event.addDomListener(document.getElementById('address'), 'input', function() {

    results.style.display = 'block';
    getPlacePredictions(document.getElementById('address').value);
  });

  // Show results when address field is focused (if not empty)
  google.maps.event.addDomListener(document.getElementById('address'), 'focus', function() {

    if (document.getElementById('address').value !== '') {

      results.style.display = 'block';
      getPlacePredictions(document.getElementById('address').value);
    }
  });

  // Hide results when click occurs out of the results and inputs
  google.maps.event.addDomListener(document, 'click', function(e) {

    if ((e.target.parentElement.className !== 'pac-container') && (e.target.parentElement.className !== 'pac-item') && (e.target.tagName !== 'INPUT')) {

      results.style.display = 'none';
    }
  });

  autocompleteService = new google.maps.places.AutocompleteService();
  placesService = new google.maps.places.PlacesService(map);
}

// Get place predictions
function getPlacePredictions(search) {

  autocompleteService.getPlacePredictions({
    input: search,
    types: ['establishment', 'geocode']
  }, callback);
}

// Get place details
function getPlaceDetails(placeId) {

  var request = {
    placeId: placeId
  };

  placesService.getDetails(request, function(place, status) {

    if (status === google.maps.places.PlacesServiceStatus.OK) {

      var center = place.geometry.location;
      var marker = new google.maps.Marker({
        position: center,
        map: map
      });

      map.setCenter(center);

      // Hide autocomplete results
      results.style.display = 'none';
    }
  });
}

// Place search callback
function callback(predictions, status) {

  // Empty results container
  results.innerHTML = '';

  // Place service status error
  if (status != google.maps.places.PlacesServiceStatus.OK) {
    results.innerHTML = '<div class="pac-item pac-item-error">Your search returned no result. Status: ' + status + '</div>';
    return;
  }

  // Build output for each prediction
  for (var i = 0, prediction; prediction = predictions[i]; i++) {

    // Insert output in results container
    results.innerHTML += '<div class="pac-item" data-placeid="' + prediction.place_id + '" data-name="' + prediction.terms[0].value + '"><span class="pac-icon pac-icon-marker"></span>' + prediction.description + '</div>';
  }

  var items = document.getElementsByClassName("pac-item");

  // Results items click
  for (var i = 0, item; item = items[i]; i++) {

    item.onclick = function() {

      getPlaceDetails(this.dataset.placeid);
    };
  }
}

google.maps.event.addDomListener(window, 'load', initialize);
body,
html {
  font-family: Arial, sans-serif;
  padding: 0;
  margin: 0;
  height: 100%;
}

#map-canvas {
  height: 150px;
  width: 200px;
  margin-bottom: 10px;
}

.search {
  width: 200px;
  padding: 5px;
  float: left;
}

label {
  display: block;
  width: 160px;
  font-size: 11px;
  color: #777;
  margin-bottom: 5px;
}

input {
  border: 1px solid #ccc;
  width: 170px;
  padding: 3px 5px;
  box-sizing: border-box;
  -moz-box-sizing: border-box;
  -webkit-box-sizing: border-box;
  box-shadow: 0 2px 6px rgba(0, 0, 0, .1);
}

.pac-container {
  background-color: #fff;
  z-index: 1000;
  border-radius: 2px;
  font-size: 11px;
  box-shadow: 0 2px 6px rgba(0, 0, 0, .3);
  -moz-box-sizing: border-box;
  -webkit-box-sizing: border-box;
  box-sizing: border-box;
  overflow: hidden;
  width: 170px;
}

.pac-icon {
  width: 15px;
  height: 20px;
  margin-right: 7px;
  margin-top: 6px;
  display: inline-block;
  vertical-align: top;
  background-image: url(https://maps.gstatic.com/mapfiles/api-3/images/autocomplete-icons.png);
  background-size: 34px;
}

.pac-icon-marker {
  background-position: -1px -161px;
}

.pac-item {
  cursor: pointer;
  padding: 0 4px;
  text-overflow: ellipsis;
  overflow: hidden;
  white-space: nowrap;
  line-height: 30px;
  vertical-align: middle;
  text-align: left;
  border-top: 1px solid #e6e6e6;
  color: #999;
}

.pac-item:hover {
  background-color: #efefef;
}

.pac-item-error,
.pac-item-error:hover {
  color: #aaa;
  padding: 0 5px;
  cursor: default;
  background-color: #fff;
}
<div class="search">
  <label for="address">Address:</label>
  <input id="address" placeholder="Enter address" type="text" tabindex="1" />
  <br />
  <div id="results" class="pac-container"></div>
</div>
<div id="map-canvas"></div>

<script src="https://maps.googleapis.com/maps/api/js?libraries=places"></script>

#2


2  

Here is the updated fiddle with the solution. The idea is quite simple after knowing the searchbox caches up to 5 results everytime you have a key stroke locally in your DOM tree until you have a match. They are cached in the div.pac-container element.

这是最新的解决方案。在知道searchbox每次在DOM树中本地执行一次按键操作,直到找到匹配的结果后,这个想法非常简单。它们缓存在div.pac-container元素中。

 $(function(){      
   var input = document.getElementById('pac-input');
   var options = {
      keyword: 'establishment'
   }
   var searchBox = new google.maps.places.SearchBox(input, options);

   searchBox.addListener('places_changed',  function(evt) {

     var places = searchBox.getPlaces();

     if ($('.pac-item').length > 0) {
       return;
     }

     places.forEach(function(place) {
       $('#output').append(place['name']);
     });
   });
});

#3


2  

If user press enter nothing will happen.
Edit 3:

如果用户按下输入,则不会发生任何事情。编辑3:

$(function(){      
 var input = document.getElementById('pac-input');
    var options = {
      keyword: 'establishment'
    }
    var searchBox = new google.maps.places.Autocomplete(input, options);
    
    google.maps.event.addListener(searchBox, 'place_changed', function () {

      var place = searchBox.getPlace();
      if(place.address_components != null && place.address_components.length >= 1){
        console.log(place.address_components.length);
        $('#output').append(place['name']);
      }
      

  });
    
});
body {         
    font:14px sans-serif;           
} 
input {
    margin: 0.6em 0.6em 0; 
    width:398px;
}
#map_canvas {         
    height: 400px;         
    width: 400px;         
    margin: 0.6em;       
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://maps.google.com/maps/api/js?libraries=places&region=us&language=en&sensor=false"></script>
<input id="pac-input" type="text" size="50">             
<div id="output"></div>