使用ENTER与单击提交按钮提交表单时的不同行为

时间:2016-06-09 18:06:00

标签: javascript jquery html forms google-maps

我有一个HTML表单输入元素,它使用Google Maps Places API中的SearchBox进行自动完成。在我的JavaScript中,我创建了一个SearchBox实例,如下所示:

var input = $('#spotsearch')[0];  // Refers to a form input with type="text" in my HTML
searchBox = new google.maps.places.SearchBox(input);

稍后在我的JavaScript中,我有以下内容:

$('#searchform').submit(function () {
    var places = searchBox.getPlaces();
    if (places) {
        var spotLat = searchBox.getPlaces()[0].geometry.location.lat();
        var spotLng = searchBox.getPlaces()[0].geometry.location.lng();
        $('#latitude').val(spotLat);
        $('#longitude').val(spotLng);
    }

});

以下是我的问题:选择完成候选人后,当我通过单击表单的提交按钮提交表单时,一切都按预期工作,places将引用具有单个对象的数组。但是,如果我按ENTER提交表单,匿名函数仍会被调用,但places返回一个空数组。在这两种情况下,似乎发送的请求完全相同。我在这里错过了什么?

我是JavaScript和Goggle Maps API的新手,所以我不确定我的错误源自何处。我的直觉是它可能在某种程度上与时间有关,但这实际上只是一种模糊的预感。任何建议,将不胜感激。谢谢!

编辑:

为了提供更多细节,这是我的整个脚本:

var searchBox;
var places;
function initSearchBox() {
    var KCLatLng = new google.maps.LatLng({lat: 39.093201, lng: -94.573419});
    var bounds = new google.maps.LatLngBounds(KCLatLng);

    var input = $('#spotsearch')[0];
    searchBox = new google.maps.places.SearchBox(input);
    searchBox.setBounds(bounds);

    $('#searchform').submit(function () {
        var places = searchBox.getPlaces();
        if (places) {
            var spotLat = searchBox.getPlaces()[0].geometry.location.lat();
            var spotLng = searchBox.getPlaces()[0].geometry.location.lng();
            $('#latitude').val(spotLat);
            $('#longitude').val(spotLng);
        }

    });
}
然后,当我加载Goggle Maps API时,

initSearchBox将作为callback参数传递。

我也尝试过这样做:

var searchBox;
var places;
function initSearchBox() {
    var KCLatLng = new google.maps.LatLng({lat: 39.093201, lng: -94.573419});
    var bounds = new google.maps.LatLngBounds(KCLatLng);

    var input = $('#spotsearch')[0];
    searchBox = new google.maps.places.SearchBox(input);
    searchBox.setBounds(bounds);
    searchBox.addListener('places_changed', function() {
        var places = searchBox.getPlaces();
        if (places) {
            var spotLat = searchBox.getPlaces()[0].geometry.location.lat();
            var spotLng = searchBox.getPlaces()[0].geometry.location.lng();
            $('#latitude').val(spotLat);
            $('#longitude').val(spotLng);
        }
    });
}

但是这给了我相同的结果(点击ENTER没有设置#latitude#longitude的值,但点击提交按钮确实如此。

这是我的表单的HTML(使用Django模板和Bootstrap):

<form method="get" id="searchform" action="{% url 'spot_search' %}"
      class="navbar-form navbar-left plain" role="search">
    <div class="form-group">
        <input id="spotsearch" type="text" class="form-control plain"
               placeholder="Search spots" name="search_query">
    </div>

    <button type="submit" class="btn btn-default plain">
        <span class="glyphicon glyphicon-search"></span> Search
    </button>
    <input id="latitude" name="latitude" type="hidden">
    <input id="longitude" name="longitude" type="hidden">
</form>

3 个答案:

答案 0 :(得分:1)

这是否已提交给服务器?如果是这样,那可能是竞争条件。在提交到服务器之前,表单不等待隐藏字段设置。无论您是在表单提交事件还是SearchBox的CoFlatMapFunction事件中设置值,您仍然需要阻止回车键将表单提交到服务器或阻止通过表单提交表单用户操作,以便您可以在以后设置数据时以编程方式提交。

要禁用回车键以提交表单,请在此处查看: Google Autocomplete - enter to select

要停用表单提交,请按照Juan的建议进行操作并添加places_changed

答案 1 :(得分:0)

我认为当你按下enter按钮但没有place作为空数组时触发提交事件处理程序的原因是因为事件处理程序在initSearchBox函数之前执行。您可能先前执行了initSearchBox,因此您已附加了提交事件处理程序。

我的建议是用这个替换你的代码:

$('#searchform').submit(function (e) {
      var KCLatLng = new google.maps.LatLng({lat: 39.093201, lng: -94.573419});
      var bounds = new google.maps.LatLngBounds(KCLatLng);

      var input = $('#spotsearch')[0];
      var searchBox = new google.maps.places.SearchBox(input);
      searchBox.setBounds(bounds);
      
      var places = searchBox.getPlaces();
      
      if (places) {
            var spotLat = searchBox.getPlaces()[0].geometry.location.lat();
            var spotLng = searchBox.getPlaces()[0].geometry.location.lng();
            $('#latitude').val(spotLat);
            $('#longitude').val(spotLng);
      }

      // Prevent to perform a "real" submit (so page is not reloaded or redirected)
      e.preventDefault();

    });

通过这种方式,所有整个搜索代码将在提交表单时执行。

答案 2 :(得分:0)

感谢@ adam0101指向我this question。我还发现相关问题hereherehere很有用。我在第一次研究这个问题的过程中错过了它们,因为这个问题比我实现的更加具体到谷歌地图自动完成API。

虽然我考虑将我的问题标记为重复,但我决定发布我最终会使用的解决方案,这很大程度上受this高度启发 - 但未被接受 - 的回答。我只是将以下内容添加到现有的JavaScript中:

$('#spotsearch').keydown(function (e) {
    // Don't submit form unless values have been set
    var condition = $('#latitude').val() == "" && $('#longitude').val() == "";
    if (e.which == 13 && condition) {
        return false;
    }
});

这样,用户第一次按下自动完成候选者时,它将选择该候选人(而不是在选择候选人之前提交表格)。然后,用户可以再次按Enter键以提交表单,或单击Search按钮执行相同的操作。模拟的解决方案就是这个:

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

从上面链接的答案。我稍微对此进行了修改,因此它不依赖于具有Google定义的特定类的SearchBox并且不受我的控制。