Google places autocomplete, how to clean up pac-container?

左心房为你撑大大i 提交于 2020-01-01 07:39:21

问题


I'm using the google places autocomplete control, and it creates an element for the drop down with a 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.


回答1:


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:

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

The reference to the pac-container element can be found at:

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

Which I simply removed from the DOM in my widget destructor:

$(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:

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.




回答2:


My implementation of code from above without 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()



回答3:


This works for now until Google changes the class name.

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

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

});



回答4:


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


来源:https://stackoverflow.com/questions/21024090/google-places-autocomplete-how-to-clean-up-pac-container

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!