Coin_op
Coin_op

Reputation: 10718

leaflet.js stops certain events from propagating

I have a problem where my mouseenter, mouseleave, mouseover and mouseout events get swallowed and do not fire.

Basically there's a map on my page which I add markers (divIcons) and draw paths on. Separate from this map, I have a tooltips and context menus that attach to events on the various markers and paths in order to be activated. The map does not know anything about the tooltips or context menu so the events are attached by a configuration file that uses jquerys on method.

Assuming the divIcons have the class markerElement the code looks like this:

$(document).on('mouseenter', '.markerElement', function(){ console.log('ENTER'); });
$(document).on('mouseleave', '.markerElement', function(){ console.log('LEAVE'); });

I've tracked the problem down to the stopPropagation method on line 6484 of leaflet-src.js version 0.7.3. If I comment out e.stopPropagation() my events work, I'm a little confused to the purpose of this method in relation to leaflet.

Is there any other way I can get the mouseenter and mouseleave events to attach to dynamically created elements on the map without the map knowing about it and without changing the leaflet source?

The context menu and tooltip code works on other elements that are not on the map, so a general solution that can dynamically pick out elements based on some kind of selector would be ideal.

Thanks for any ideas

Upvotes: 0

Views: 1482

Answers (1)

iH8
iH8

Reputation: 28638

Perhaps it's an option for you to disable all events on L.Marker and L.Path, you can do that by using 'clickable': false in their options.

It's also possible to disable only certain events by creating a custom marker extended from L.Marker, here i commented out the mouseover and mouseout:

L.CustomMarker = L.Marker.extend({

  _initInteraction: function () {

        if (!this.options.clickable) { return; }

        // TODO refactor into something shared with Map/Path/etc. to DRY it up

        var icon = this._icon,
            events = ['dblclick', 'mousedown', /*'mouseover', 'mouseout',*/ 'contextmenu'];

        L.DomUtil.addClass(icon, 'leaflet-clickable');
        L.DomEvent.on(icon, 'click', this._onMouseClick, this);
        L.DomEvent.on(icon, 'keypress', this._onKeyPress, this);

        for (var i = 0; i < events.length; i++) {
            L.DomEvent.on(icon, events[i], this._fireMouseEvent, this);
        }

        if (L.Handler.MarkerDrag) {
            this.dragging = new L.Handler.MarkerDrag(this);

            if (this.options.draggable) {
                this.dragging.enable();
            }
        }
    }

});

Here's an example on Plunker: http://plnkr.co/edit/naWEPz?p=preview

If you want to remove the stopPropagation on L.Marker's clickevent you can do so also by extending L.Marker in a similar way:

L.CustomMarker = L.Marker.extend({

    _onMouseClick: function (e) {
        var wasDragged = this.dragging && this.dragging.moved();

        /*if (this.hasEventListeners(e.type) || wasDragged) {
            L.DomEvent.stopPropagation(e);
        }*/

        if (wasDragged) { return; }

        if ((!this.dragging || !this.dragging._enabled) && this._map.dragging && this._map.dragging.moved()) { return; }

        this.fire(e.type, {
            originalEvent: e,
            latlng: this._latlng
        });
    }
});

Kind of hackish but it's supposed to work, you can do the same with other method in L.Marker that calls stopPropagation. The same goes for L.Path, just extend it with the methods you want to change and i think you're good to go (didn't know how to test this properly, so i didn't :D) Good luck!

Upvotes: 3

Related Questions