将Google Places自动完成pac容器与输入字段关联

Associate Google Places Autocomplete pac-container with input field

本文关键字:输入 关联 字段 pac Places Google      更新时间:2023-09-26

有没有任何方法可以将自动完成的pac容器div与它所附加的输入元素关联起来?理想情况下,我希望能够将每个pac容器的ID设置为类似"pac-"的值,这样,如果输入消失,我就可以删除它们,并更容易地使用Selenium测试自动完成。

这个问题的答案有一个解决方案,但它是不可持续的,因为谷歌倾向于更改各种缩小的房地产名称(例如,曾经的Mc现在是Rc)

每当添加新的自动完成时,我还尝试修改页面上的最后一个pac容器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容器之间存在延迟。(这里有一个小提琴应该说明这种方法以及它是如何失败的)

我缺少什么方法吗?

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

所以基本上:

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个输入,并选择相应的选定地址

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

有一些库可以帮助您做到这一点,例如JSONPath、JSONQuery等。不过,在不添加任何额外库的情况下,我们可以在Autocomplete对象的嵌套层次结构中滚动我们自己的广度优先搜索,但需要注意的是,我不是Javascript专家,虽然这目前有效,但我不能保证我没有错过一个在未来会打破这一局面的边缘案例

不幸的是,由于您指出的时间问题,您将需要在Autocomplete对象的初始实例化之后的某个时刻运行此操作。好消息是,如果您不立即需要pac-container对象引用,那么只要您将Autocomplete对象引用保持在范围内,就可以推迟到需要时再查找。

功能最终看起来是这样的:

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

总之,这显然是一种非常密集的访问属性的方式(谷歌应该使其在本地可见,抱怨抱怨)。我建议您尝试您链接的StackOverflow问题中一个更"天真"但速度更快的方法,当该方法返回null/empty时,就回到这个方法。