谷歌放置自动完成,如何清理pac容器?

时间:2014-01-09 15:17:45

标签: javascript google-places-api

我正在使用google places autocomplete控件,它会使用类pac-container为下拉菜单创建一个元素。

我正在使用ember应用程序中的自动完成功能,当我完成它时,DOM元素自动完成将被删除,但pac-container元素仍然存在,甚至认为它是隐藏的。下次我实例化一个新的自动完成时,会创建一个新的pac-container并保留旧的{{1}}。我似乎无法在API上找到类似于dispose方法的内容,那么有没有正确的方法呢?如果不是,我想我应该使用jquery来清理元素。

5 个答案:

答案 0 :(得分:6)

我遇到了同样的问题,希望Google最终提供正式的清理方法,但是现在我能够通过手动删除pac-container对象来解决问题,可以在自动完成中找到对象的引用返回的类:

var autocomplete = new google.maps.places.Autocomplete(element, options);

可以在以下位置找到对pac容器元素的引用:

autocomplete.gm_accessors_.place.Mc.gm_accessors_.input.Mc.L

我只是从我的widget析构函数中的DOM中删除了它:

$(autocomplete.gm_accessors_.place.Mc.gm_accessors_.input.Mc.L).remove();

希望这有帮助。


<强>更新

我不确定Google的混淆是如何工作的,但上面的部分内容似乎是混淆的,如果API的混淆或内部结构发生变化,显然会失败。对后者无能为力,但对于前者,您至少可以按预期标准搜索对象属性。正如我们所看到的,一些属性名称没有被混淆,而一些属性名称似乎是,例如“Mc”和“L”。为了使其更加健壮,我编写了以下代码:

var obj = autocomplete.gm_accessors_.place;
$.each(Object.keys(obj), function(i, key) {
  if(typeof(obj[key]) == "object" && obj[key].hasOwnProperty("gm_accessors_")) {
    obj = obj[key].gm_accessors_.input[key];
    return false;
  }
});
$.each(Object.keys(obj), function(i, key) {
  if($(obj[key]).hasClass("pac-container")) {
    obj = obj[key];
    return false;
  }
});
$(obj).remove();

代码期望一般结构保持不变,而不依赖于(可能)混淆的名称“Mc”和“L”。丑陋我知道,但希望谷歌很快解决这个问题。

答案 1 :(得分:2)

我没有jquery的code from above的实现。

var autocomplete = new google.maps.places.Autocomplete(element, options);
export function getAutocompletePacContainer(autocomplete) {
 const place: Object = autocomplete.gm_accessors_.place;

 const placeKey = Object.keys(place).find((value) => (
    (typeof(place[value]) === 'object') && (place[value].hasOwnProperty('gm_accessors_'))
 ));

 const input = place[placeKey].gm_accessors_.input[placeKey];

 const inputKey = Object.keys(input).find((value) => (
   (input[value].classList && input[value].classList.contains('pac-container'))
 ));

 return input[inputKey];
}
getAutocompletePacContainer(autocomplete).remove()

答案 2 :(得分:1)

现在适用于Google更改班级名称

autocomplete.addListener('place_changed', function() {

    $('.pac-container').remove();

});

答案 3 :(得分:0)

内置此递归函数以在自动完成对象中定位元素位置。


获取第一个匹配对象

var elementLocator = function(prop, className, maxSearchLevel, level) {

    level++;

    if (level === (maxSearchLevel + 1) || !prop || !(Array.isArray(prop) || prop === Object(prop))) {
        return;
    }

    if (prop === Object(prop) && prop.classList && prop.classList.contains && typeof prop.classList.contains === 'function' && prop.classList.contains(className)) {
        return prop;
    }

    for (const key in prop) {
        if (prop.hasOwnProperty(key)) {
            var element = elementLocator(prop[key], className, maxSearchLevel, level);
            if (element) {
                return element;
            }
        }
    }
};

用法:

var elm = null;
try {
    //set to search first 12 levels, pass -1 to search all levels
    elm = elementLocator(this.autocomplete, 'pac-container', 12, null); 
} catch(e) {
    console.log(e);
}

答案 4 :(得分:0)

我也刚刚遇到了这个问题。这可能与我的输入字段位于flexbox内有关,但我还没有尝试重组我的页面。相反,我在输入字段中添加了onfocus侦听器,并在其容器中添加了onscroll侦听器。在内部,我用getBoundingClientRect获得输入字段的位置,然后用这些值更新样式表。我尝试通过.pac-container直接选择和更新document.querySelctor,但这似乎不起作用。您可能需要setTimeout才能将其首先添加到DOM。

这是我的代码:

let ruleIndex = null;
const form = document.body.querySelector('.form');
const input = document.body.querySelector('.form-input');

const positionAutoComplete = () => {
  const { top, left, height } = inputField.getBoundingClientRect();
  if(ruleIndex) document.styleSheets[0].deleteRule(ruleIndex);
  ruleIndex = document.styleSheets[0].insertRule(`.pac-container { top: ${top + height}px !important; left: ${left}px !important; }`);
}

form.addEventListener('scroll', positionAutoComplete);
input.addEventListener('focus', positionAutoComplete);

如先前的回答中所述,这中断了Google决定重命名.pac-container的时间,因此不是完美的解决方案,但可同时进行。