2

I'm trying to prevent certain user (mouse) events from firing on an instance of the Google Maps API I'm using on my website. I'm adding event listeners to events on the API instance like so:

google.maps.event.addListener(map, 'click', mapClickHandler);

Then defining the mapClickHandler event very simply like so:

function mapClickHandler (e) { e.preventDefault(); }

I have also tried the following variations:

function mapClickHandler (e) { e.stopPropagation(); }
// or //
function mapClickHandler (e) { e.stopImmediatePropagation(); }

For all three of the above, I get the error: TypeError: e.preventDefault / e.stopPropagation / e.stopImmediatePropagation is not a function

However, the event does seem to be prevented from firing on the Google Maps instance loaded into my page when I use this technique.

I tried this with all of the following cases as well:

google.maps.event.addListener(map, 'contextmenu', mapContextMenuHandler);
google.maps.event.addListener(map, 'dblclick', mapDoubleClickHandler);
google.maps.event.addListener(map, 'mousedown', mapMouseDownHandler);
google.maps.event.addListener(map, 'mouseup', mapMouseUpHandler);
google.maps.event.addListener(map, 'mousemove', mapMoveHandler);

They all give me the exact same problem with similar handler definitions as above. I later learned that this is because an event fired by mouse activity on a google.maps.event is a MouseEvent that is different from normal browser/DOM events, and doesn't even have these other event types associate with it - although I'm not getting any errors for trying to add listeners of these types for some reason.

So is there any other way to use preventDefault, stopPropagation, stopImmediatePropagation, or anything like them on mouse events on a Maps API instance? What alternative can I use that doesn't throw an error?

Finally, though these functions have been successful at blocking mouse-click, double-mouse-click, and mouse-move events, I've found that right-click events are not being blocked. In other words, none of the above listeners including click, mouseup, mousedown, contextmenu, etc have been able to prevent me from double-right-clicking on the Maps API instance to zoom out.

What am I missing? It doesn't seem like it should be this hard. Here is my entire code with JS and CSS embedded.

<!doctype html>
<html>
    <head>
        <meta charset='utf-8'>

        <!-- embedded CSS styles -->
        <style type="text/css">
            #mapCanvas {
                background: transparent;
                height: 450px; width: 250px;
                position: absolute;
                top: 0; left: 0;
                pointer-events: none;
            }
            #mapElement {
                height: 450px; width: 250px;
                position: absolute;
                top: 0; left: 0;
            }
        </style>

        <!-- JavaScript includes and embedded custom source -->
        <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
        <script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?sensor=false"></script>
        <script type="text/javascript">

            var map;

            function init() {
                var mapOptions = {
                    zoom: 15,
                    <!-- coords in order lon, lat despite function name -->
                    <!-- note: smaller longitudes move the CAMERA north (BEWARE negatives!) -->
                    <!-- note: smaller latitudes move the CAMERA east -->
                    center: new google.maps.LatLng(34.243, -118.5285),
                    mapTypeId: google.maps.MapTypeId.SATELLITE
                };

                map = new google.maps.Map(document.getElementById("mapElement"), 
                                        mapOptions);

                google.maps.event.addListener(map, 'click', mapClickHandler);
                google.maps.event.addListener(map, 'contextmenu', mapContextMenuHandler);
                google.maps.event.addListener(map, 'dblclick', mapDoubleClickHandler);
                google.maps.event.addListener(map, 'mousedown', mapMouseDownHandler);
                google.maps.event.addListener(map, 'mouseup', mapMouseUpHandler);
                google.maps.event.addListener(map, 'mousemove', mapMoveHandler);

                $("#mapCanvas").attr('width', 250);
                $("#mapCanvas").attr('height', 450);
                var mapContext = $("#mapCanvas").get(0).getContext("2d");
                mapContext.strokeStyle = "#00FF00";
                mapContext.lineWidth = 3;
                mapContext.rect(20,20,150,100);
                mapContext.stroke();
            }

            function mapClickHandler (e) { e.stopImmediatePropagation(); }
            function mapContextMenuHandler (e) { e.preventDefault(); }
            function mapDoubleClickHandler (e) { e.preventDefault(); }
            function mapMouseDownHandler (e) { e.preventDefault(); }
            function mapMouseUpHandler (e) { e.preventDefault(); }
            function mapMoveHandler (e) { e.preventDefault(); }

            window.addEventListener('load', init, false);
        </script>
    </head>
    <body>
        <div id="mapElement"></div>
        <canvas id="mapCanvas"></canvas>
    </body>
</html>

Update:

Maybe it's worth mentioning that my goal is to prevent all mouse input to the Maps API EXCEPT for single clicks. I used the solution to this other question to prevent the mouse input . . .

disable zooming dragging in Google maps by clicking on a button

. . . but I want to be able to let a single mouse click go through and do something custom with my custom handler, and block the typical Google Maps API functionality. Is this even possible?

My ultimate goal, maybe unrelated but to provide some context, is to convert latitude/longitude coords to x/y coords on the the map lives in. This is so that any slight variations in map data in the future won't cause any drawing I do on the canvas to be drawn off center of the actual map data. Maybe I'm overthinking it. But it's hard to believe they've made it so hard to get this data/not provided a simple way to get this data.

Update 2:

Helpful commenters suggested using an HTML overlay of some kind to catch and block the mouse events, and using the Google Maps object properties to turn off specific chunks of the map functionality as needed. These work, and I'm thankful to have functional workarounds, but I am yet frustrated by the inability to work cleanly and directly with the event objects fired by the mouse, as I might in ordinary browser behavior.

Also tested was the stop() function provided by the Google Maps API itself in lieu of preventDefault() et al, but it seems that Google's own API does not offer the promised functionality either, or offers it in an unuseful way, because it seems others are having as much trouble as I am using the stop() function as well:

Google Map's Double Click Event Propagation

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Steverino
  • 2,099
  • 6
  • 26
  • 50
  • as it sounds it should be sufficient when you add the map-options `disableDoubleClickZoom:true` and `draggable:false` – Dr.Molle Mar 29 '15 at 21:25
  • In the documentation for google.maps.MouseEvent it says that stop() prevents the mouse event from propagating further. – brenzy Mar 30 '15 at 00:31
  • @brenzy I saw that, but it does not seem to work in the code above, using stop() instead of preventDefault(). Or if I'm supposed to use stop() with a specific event to disable double-click zooming in and out, any idea what it might be? Right now, all the intercepts used above still allow double-right-click zoom-out. – Steverino Mar 30 '15 at 02:51
  • 1
    [http://stackoverflow.com/questions/17373677/google-maps-double-click-event-propagation](http://stackoverflow.com/questions/17373677/google-maps-double-click-event-propagation) implies that there isn`t a good solution for this. One approach you could try is to put a transparent div on top of the map, to catch the mouse events, and just send through the ones you want. – brenzy Mar 30 '15 at 10:31
  • @brenzy thanks for linking. I've already implemented both your solution and the one in the posted link for comparison, but it's great to see confirmation from other users that the initial goal is not reachable (handling the event itself). – Steverino Mar 30 '15 at 14:48

0 Answers0