【问题标题】:Associate Google Places Autocomplete pac-container with input field将 Google Places Autocomplete pac-container 与输入字段相关联
【发布时间】:2014-05-31 17:13:51
【问题描述】:

有什么方法可以将自动完成的 pac-container div 与它所附加的输入元素相关联?理想情况下,我希望能够将每个 pac-container 的 ID 设置为“pac-”之类的东西,这样我可以在输入消失时删除它们,并且更容易使用 Selenium 测试自动完成。

This question 的回答有一个解决方案,但它不是遥不可及的,因为 Google 倾向于更改各种缩小的属性名称(例如,曾经的 Mc 现在是 Rc)

每当添加新的自动完成功能时,我也尝试修改页面上的最后一个 pac-container div,如下所示:

function attachAutocomplete(id) {
    var input = document.getElementById(id);
    var autocomplete = new google.maps.places.Autocomplete(input);
    $(".pac-container:last").attr("id", "pac-" + id);
}

这适用于页面加载后的新自动完成功能,但由于某种原因,在分配前几个自动完成功能和它们的 pac 容器出现之间存在延迟。 (Here's a fiddle that should illustrate this approach and how it fails)

有什么我缺少的方法吗?

【问题讨论】:

    标签: javascript autocomplete google-places-api


    【解决方案1】:

    如果您不愿意对属性名称/结构做出假设(完全合理),那么您基本上只能在自动完成对象本身中查询具有属性 className:"pac-container"(或其他一些识别功能)的对象。

    有一些库可以帮助您解决此问题,例如 JSONPath、JSONQuery 以及更多可以帮助您执行此操作的库。不过,在不添加任何其他库的情况下,我们可以通过自动完成对象的嵌套层次结构滚动我们自己的广度优先搜索,但需要注意的是我不是 Javascript 专家,虽然这现在可以工作,但我不能保证我不会错过任何会在未来打破这种情况的边缘案例。

    不幸的是,由于您指出的时间问题,您需要在 Autocomplete 对象的初始实例化后的某个时间点运行它。好消息是,如果您不立即需要 pac-container 对象引用,您可以推迟找到它,直到您需要它,只要您将自动完成对象引用保持在范围内。

    函数最终看起来像这样:

    var autocompleteDropdown = breadthFirstSearch(autocomplete, function(val) {
        return val.className === "pac-container";
    }
    

    其中breadthFirstSearch函数定义为:

    function breadthFirstSearch(object, matchesCriteria) {
        var queue = [];
        var visited = [];
        queue.push(object);
        visited.push(object);
        while (queue.length) {
            var val = queue.shift();
            if (val && typeof val == "object") {
                if (matchesCriteria(val)) {
                    return val;
                }
                if (Object.prototype.toString.call(val) == "[object Array]") {
                    for (var i=0; i<val.length; i++) {
                        breadthFirstSearchProcessValue(val[i], queue, visited);
                    }
                }
                else if (val instanceof Node) {
                    if (val.hasChildNodes()) {
                        var children = val.childNodes;
                        for (var i=0; i<children.length; i++) {
                            breadthFirstSearchProcessValue(children[i], queue, visited);
                        }
                    }
                }
                else {
                    for (var property in val) {
                        breadthFirstSearchProcessValue(val[property], queue, visited);
                    }
                }
            }
        }
    }
    function breadthFirstSearchProcessValue(val, queue, visited) {
        for (var i=0; i<visited.length; i++) {
            if (visited[i] === val) {
                return;
            }
        }
        queue.push(val);
        visited.push(val);
    }
    

    总而言之,这显然是一种仅访问属性的非常密集的方式(Google 应该在本机上使其可见,grumble grumble)。我建议从您链接的 StackOverflow 问题中尝试一种更“天真”但速度更快的方法,并在该方法返回 null/empty 时回退到此。

    【讨论】:

    • 我正在使用 JQuery,如果这样可以简化流程
    • 我不知道 JQuery 在这里有多大帮助。这段代码和我自己的代码(我也在使用 JQuery)之间的唯一区别是我使用$.isArray(val) 而不是Object.prototype.toString.call(val) == "[object Array]",因为前者更可靠。
    • 实际上,现在我想起来了,在val instanceof Node 的情况下,您可以可能以某种方式使用$(val).find(...)。也许,您可以将任何 Node 值推迟到最后,然后在最后为它们中的每一个推迟$(val).find(".pac-container")。事实上,整个分支目前不是必需的,但可以用于未来验证(以防 Google 开始存储 pac-container 的父级而不是 pac-container 本身)。
    【解决方案2】:

    我不是通过将每个 .pac-container 与其输入类型表单字段相关联来解决该问题,而是在每次聚焦自动完成输入类型时重置所有 .pac-container 项。

    所以基本上:

    1) 假设我们有 3 个设置了 google.maps.places.Autocomplete 的地址输入

    2) 使用 jquery,让我们将焦点事件绑定到这 3 个输入

    $('#address_1, #address_2, #address_2'.focus(function (e) 
    {
        $('.pac-container').each( function() {
            $(this).html( '' );
        });
    });
    

    3) 将focusout事件绑定到这3个输入上,并选择对应的选中地址

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-01-09
      • 1970-01-01
      • 2018-12-30
      • 2016-03-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-01
      相关资源
      最近更新 更多