【问题标题】:Different behavior when form is submitted with ENTER vs. clicking submit button使用 ENTER 提交表单与单击提交按钮时的不同行为
【发布时间】:2016-10-10 12:50:04
【问题描述】:

我有一个 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);
        }

    });
}

initSearchBox 然后在我加载 Goggle Maps API 时作为 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>

【问题讨论】:

  • 能否分享整个js代码。
  • @HectorBarbossa 我更新了我的帖子。
  • 我们可能还需要 HTML。
  • @adam0101 也添加了!

标签: javascript jquery html forms google-maps


【解决方案1】:

我认为当您按下回车按钮时触发提交事件处理程序但没有地方作为空数组的原因是因为事件处理程序比 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();

    });

这样,当表单提交时,所有的搜索代码都会被执行。

【讨论】:

  • 这对我不起作用。如果我这样做,自动完成功能将不起作用,因为在输入并提交搜索查询之前,SearchBox 不会被实例化。我在我的问题中添加了更多 JS 以展示我尝试过的其他内容。
【解决方案2】:

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

要禁用输入键提交表单,请看这里: Google Autocomplete - enter to select

要禁用表单提交,请按照 Juan 的建议执行并包含 e.preventDefault();

【讨论】:

    【解决方案3】:

    感谢@adam0101 将我指向this question。我还发现相关问题hereherehere 很有用。在我第一次研究这个问题时我错过了它们,因为这个问题比我意识到的更具体到 Google Maps 自动完成 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;
    });
    

    来自上面链接的答案。我对此稍作修改,使其不依赖于SearchBox 具有由谷歌定义的特定类并且不受我的控制。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-03-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-01
      • 1970-01-01
      相关资源
      最近更新 更多