javascript 谷歌放置自动完成,如何清理pac-container?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21024090/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Google places autocomplete, how to clean up pac-container?
提问by Charlie
I'm using the google places autocomplete control, and it creates an element for the drop down with a class pac-container
.
我正在使用 google 位置自动完成控件,它为下拉列表创建了一个带有 class 的元素pac-container
。
I'm using the autocomplete in an ember app, and when I'm done with it the DOM element the autocomplete is bound to gets removed, but the pac-container
element remains, even thought its hidden. Next time I instantiate a new autocomplete, a new pac-container
is created and the old one remains. I can't seem to find anything like a dispose method on the API, so is there a way of doing this correctly? If not I guess I should just use jquery to clear up the elements.
我在 ember 应用程序中使用自动完成功能,当我完成它时,自动完成功能的 DOM 元素必然会被删除,但该pac-container
元素仍然存在,即使认为它是隐藏的。下次我实例化一个新的自动完成时,一个新的pac-container
被创建,旧的保留。我似乎在 API 上找不到类似 dispose 方法的东西,那么有没有办法正确地做到这一点?如果不是,我想我应该只使用 jquery 来清理元素。
回答by Lachlan
I was having the same problem, and hopefully Google eventually provides an official means of cleanup, but for now I was able to solve the problem by manually removing the pac-container object, a reference to which can be found in the Autocomplete class returned from:
我遇到了同样的问题,希望谷歌最终提供官方的清理方法,但现在我能够通过手动删除 pac-container 对象来解决问题,该对象的引用可以在从返回的 Autocomplete 类中找到:
var autocomplete = new google.maps.places.Autocomplete(element, options);
The reference to the pac-container element can be found at:
可以在以下位置找到对 pac-container 元素的引用:
autocomplete.gm_accessors_.place.Mc.gm_accessors_.input.Mc.L
Which I simply removed from the DOM in my widget destructor:
我只是在我的小部件析构函数中从 DOM 中删除了它:
$(autocomplete.gm_accessors_.place.Mc.gm_accessors_.input.Mc.L).remove();
Hope this helps.
希望这可以帮助。
Update
更新
I'm not sure how Google's obfuscation works, but parts of the above seem obfuscated, and obviously will fail if the obfuscation or internal structures of the API change. Can't do much about the latter, but for the former you could at least search the object properties by expected criteria. As we can see, some of the property names are not obfuscated, while some appear to be, such as "Mc" and "L". To make this a little more robust, I wrote the following code:
我不确定 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();
The code expects the general structure to remain the same, while not relying on the (possibly) obfuscated names "Mc" and "L". Ugly I know, but hopefully Google fixes this issue soon.
代码期望一般结构保持不变,同时不依赖(可能)混淆的名称“Mc”和“L”。丑我知道,但希望谷歌尽快解决这个问题。
回答by Driver
My implementation of code from abovewithout jquery.
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()
回答by Milk Man
This works for now until Google changes the class name.
这暂时有效,直到 Google 更改 class name。
autocomplete.addListener('place_changed', function() {
$('.pac-container').remove();
});
回答by rovercoder
Built this recursive function to locate element position inside autocomplete object.
构建此递归函数以定位自动完成对象内的元素位置。
Get first matching object
获取第一个匹配对象
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;
}
}
}
};
Usage:
用法:
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);
}