2

I am trying to create dynamically generated popups in OpenLayers with a mouseover event. According to the documentation, it is recommended that the popups be destroyed after use to avoid memory leaks. I set up an event listener that destroy the popup upon a mouseout event as follow:

marker.events.register("mouseout", marker, function(event) {
    popup.destroy();
});

While testing on jsFiddle upon map initialisation, I am able to create and destroy the popup on the first mouseover and mouseout. Subsequent attempts of mouseout result in a "this.events is null" error appearing on my javascript console log. It seems to me that the first instance of popup.destroy() might have destroyed more than just the popup itself, causing the second instance to fail.

Can anyone enlighten me on how to resolve this issue without deviating too much from the current setup?

1 Answer 1

2

You are registering a new mouseout event listener every time you showPopup. This itself is a memory leak and the root of your problem.

Something like this will work much better:

var map, wmsLayer, point, popup;
function hidePopup(event){
    popup.destroy();
}
function showPopup(event) {
    popup = new OpenLayers.Popup('photo', point, null, 'popup', true);
    map.addPopup(popup);
}
window.onload = function(){
    ...
    markers.addMarker(marker);
    marker.events.register("mouseover", marker, showPopup);
    marker.events.register("mouseout", marker, hidePopup);
    ...
}

Updated jsFiddle LINK

Update per comment:

Storing it in an array is not really a problem, but not ideal in my opinion. If you wanted to save a popup for every single marker, I would attach it to the marker like so marker.myPopup = new new OpenLayers.Popup('photo', point, null, 'popup', true);. No need to consolidate/sync array and markers.

However, There would be no reason for this if are destroying them on mouseout. You would benefit from storing the popups from the 100 markers in ONE single popup var (NOT AN ARRAY). Because you don't plan on having more than one open at any given time. So only ONE will exist at any given time because you are calling destroy() on mouse out. So create the popup and generate its contents on mouseover and destroy it on mouseout.

popup var doesn't need to be global, but it has to be in scope.

The way it is in your jsFiddle, if you console.log(marker.events.listeners); within showPopup(point, marker) you will clearly see that the mouseout has as many listeners as you mouse in and out of your marker. For example, I hovered over your marker 9 times and it is creating a new listener every time: enter image description here

Don't register the mouse out event listener on showPopup unless you plan on clearing the previous listener. Or you will get the above error/memory leak.

4
  • I didn't make popup a global variable because I have 100 markers. Therefore, I created a function to generate the popups and dynamically add listeners to destroy them on a mouseout event. Creating an array to store the event listeners may require more memory. Could the way that I am assigning the listeners be causing the problem? Thanks for your help :) Nov 20, 2012 at 6:47
  • @QuestionOverflow: Please see my updated answer.
    – CaptDragon
    Nov 20, 2012 at 14:45
  • Thanks, really appreciate your help! Think you are quite right, one variable is sufficient. I have a lot of difficulties working with listeners, do you have nifty way of identifying which one for which on the console? Nov 21, 2012 at 5:45
  • No problem. Unfortunately register doesn't return a pointer. So I don't know if it's possible.
    – CaptDragon
    Nov 21, 2012 at 14:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.