Search code examples
twitter-bootstrappopoveropenlayers-3onhover

Detecting mouse hover over a popover from openlayers3


I would like to detect when the mouse is hovering over a (bootstrap) popover from an openlayers3 map, so that I can leave the popover open in this case, but destroy it in all other cases. My map has a lot of features with popovers containing links, so the user should be able to move the mouse to a link and click with the popover still open. Putting a timer on the destroy event is really messy with all the different features with popovers I am displaying. I'm not sure if the best solution is to attempt to detect the event via openlayers (is this possible?) or via bootstrap.

Here is a jsfiddle demonstrating the problem.

What is the best way to keep a popover open only when the mouse is over the popover?

Thanks for your help.

// define map
var map = new ol.Map({
    target: "map",
    layers: [
        new ol.layer.Tile({
            source: new ol.source.OSM()
        })
    ],
    view: new ol.View({
        zoom: 1,
        center: ol.proj.transform([0,0], "EPSG:4326", "EPSG:3857"),
    })
});

// define popup overlay
popup = new ol.Overlay({
    element: document.getElementById("popup")
});
map.addOverlay(popup);

// define feature
var FeatureLayer = new ol.FeatureOverlay({
    map: map,
    features:  [new ol.Feature({
        geometry: new ol.geom.Circle([0,0], 1000000),
    })]
})

// define mouse move event
$(map.getViewport()).on("mousemove", function(evt) {
    var pixel = map.getEventPixel(evt.originalEvent);
    var coordinate = map.getCoordinateFromPixel(pixel)
    displayFeatureInfo(pixel, coordinate);
});

// popover display function
var feature_prev
function displayFeatureInfo(pixel, coordinate) 
{
    var feature = map.forEachFeatureAtPixel(pixel, function(feature, layer) {
        return feature;
    });
    if (feature == feature_prev)  // if same feature, leave popup open
    {
        return
    }

    // if (mouse hovering over open popover)  <--------------------- how to detect this?
    //{
    //    return
    //}

    // display popover
    var element = popup.getElement();
    if (feature)  // if mouse is over feature
    {
        coords = ol.proj.transform([0,0], "EPSG:4326", "EPSG:3857"),
        popup.setPosition(coords);
        $(element).popover("destroy")
        $(element).popover({
            "html": true,
            "content":  "<a href='http://www.google.com'>Link 1</a><br>"+
                        "<a href='http://openlayers.org'>Link 2</a>"
        });
        $(element).popover("show");
        feature_prev = feature
    }
    else
    {
        $(element).popover("destroy")
        feature_prev = []
    }
}

Solution

  • As you can see, the popover have class name popover-content, you can check if the mouse event's target is popup and then return to keep the popover open.

    With this approach, the popover will close when you hover on your link in the popover. So, we have to ass extra condition to check for a tag too to keep it open when you are hovering on popup links.

    if (e.target.className == 'popover-content' || e.target.tagName.toLowerCase() === 'a') {
        return;
    }
    

    Here is your working jsFiddle