4

I have a google map that I am populating with real estate listings from a database. I have set it up to refresh the listings when the map is panned or zoomed. I am using the dragend & zoom_changed events to accomplish this so that it is not automatically triggered when the map shifts to open an infowindow. I have also added a list of the properties to the side which, when hovered, will open the corresponding marker's infowindow. Finally I have added a click event to the markers to also open the infowindow.

The problem I am having is that when I have the mouse over the map, it always shows the "ready to drag" hand cursor and I have to click on a pin to have it switch to the pointer and then click it a second time to actually open the infowindow. Marker mouseenter and mouseout events do not even register for the same reason. I have tried turning off listeners and different effects, but nothing seems to get rid of whatever it is that the mouse is interacting with by default on the map.

I am at a loss as to what the issue is. Relevant javascript below. You can see the site at http://staging.obs.jacksonholehost.com/properties/.


I have noticed that sometimes when hovering over the map, a marker title will appear for a marker that I am not hovering over. In fact it appears when I am not hovering over any marker. It seems like until I click the map the first time the map goes not know where the markers are located?


I have also noticed that this issue does not seem to impact touch devices, at least not iOS devices, they behave as expected. It seems to be related to the ability to drag the map. It seems like I need to click once to get out of the default drag mode and then a second time to activate a click event.


I have now also noticed that this seems to be an intermittent problem. Sometimes I can get the click events to fire with 1 click and sometimes it takes 2.

function addMapMarkers(map, bounds, markers, alternateMarkers, markersIcon, infowindow ) {
    jQuery('.property-details','#property-list').each(function() {
        var infowindowWidth = parseInt(jQuery('#map-settings').data('infowindow-width'));
        //var iconHeight = parseInt(jQuery('#map-settings').data('icon-height'));
        //var iconWidth = parseInt(jQuery('#map-settings').data('icon-width'));
        var $this = jQuery(this);
        if($this.data('latitude') === '') {return;}
        var contentString = $this.find('.infowindow-contents').html();
        var markerLatLng = new google.maps.LatLng($this.data('latitude'), $this.data('longitude'));

        var image = {
            url: $this.data('marker-icon'),         
            scaledSize: new google.maps.Size(parseInt($this.data('marker-icon-width')),parseInt($this.data('marker-icon-height'))),
        };
        //var image = customIcon($this.data('count'), 1,  $this.data('marker-icon'), iconHeight, iconWidth, iconHeight, iconWidth, 10, 7, 7);
        var altImage = {
            url: $this.data('marker-icon-alt'),
            scaledSize: new google.maps.Size(parseInt($this.data('marker-icon-alt-width')),parseInt($this.data('marker-icon-alt-height'))),
        };
        //var altImage = customIcon($this.data('count'), 1,  $this.data('marker-icon-alt'), iconHeight, iconWidth, iconHeight, iconWidth, 10, 7, 7);
        var marker = new google.maps.Marker({
            position: markerLatLng,
            map: map,
            title : $this.data('pin-title'),
            brief: jQuery(this).children(".marker_brief").text(),
            icon: image
        });

        google.maps.event.addListener(marker, 'click', function() {         
            contentString = contentString.replace(/(<span class="src">([^<]+)<\/span>)/gi, '<img src="$2" style="max-width:100%;max-height:100%">');
            infowindow.setContent('<div class="mls-map-infowindow-content">' + contentString + '</div>');
            var re = /data-mlsid="([^"]+)"/; 
            var m;               
            if ((m = re.exec(contentString)) !== null) {
                if (m.index === re.lastIndex) {
                    re.lastIndex++;
                }
            }
            var mlsid = m[1];
            jQuery('#map-view').scrollTop(0);
            var pos = jQuery('#map-view').find('#' + mlsid).position().top;
            jQuery('#map-view').scrollTop(pos);
            infowindow.open(map, marker);
        });

        google.maps.event.addListener(marker, 'zindex_changed', function() {
            contentString = contentString.replace(/(<span class="src">([^<]+)<\/span>)/gi, '<img src="$2" style="max-width:100%;max-height:100%">');
            infowindow.setContent('<div class="mls-map-infowindow-content">' + contentString + '</div>');           
            infowindow.open(map, marker);
        });

        markers.push(marker);
        markersIcon.push(image);
        alternateMarkers.push(altImage);
        //add to bounds for auto center and zoom
        bounds.extend(markerLatLng);
    });
}

function clearMarkers(map, markers) {
    for (var i = 0; i < markers.length; i++) {
        markers[i].setMap(null);
    }
}

jQuery(function( $ ){
    var map, 
    infowindow = new google.maps.InfoWindow(),
    bounds = new google.maps.LatLngBounds(), 
    markers=[], 
    alternateMarkers=[], 
    markersIcon=[];
    var center;
    //googleMapTester();/>/first check for bounds set in url
    var mlscrit = window.location.pathname;
    var ne = '';
    var re = /\/\(([^\/]+)\)-ne/; 
    var m;               
    if ((m = re.exec(mlscrit)) !== null) {
        if (m.index === re.lastIndex) {
            re.lastIndex++;
        }
        ne = m[1];
        ne = ne.split(',');
    }
    //console.log(ne);
    var sw = '';
    re = /\/\(([^\/]+)\)-sw/;            
    if ((m = re.exec(mlscrit)) !== null) {
        if (m.index === re.lastIndex) {
            re.lastIndex++;
        }
        sw = m[1];
        sw = sw.split(',');
    }


    var scrollwheel = $('#map-settings').data('scrollwheel');
    scrollwheel = scrollwheel === "true";
    var maptype = $('#map-settings').data('maptypeid'); //google.maps.MapTypeId.
    var mapzoom = $('#map-settings').data('zoom');
    if(mapzoom !== '' && $.isArray(ne) === false) {
        mapzoom = parseInt(mapzoom);
    }
    else {
        mapzoom = 0;
    }


    var map_options = {
        zoom: mapzoom
    };

    if(maptype === 'ROADMAP') {
        map_options.mapTypeId = google.maps.MapTypeId.ROADMAP;
    }
    else if(maptype === 'SATELLITE') {
        map_options.mapTypeId = google.maps.MapTypeId.SATELLITE;
    }
    else if(maptype === 'HYBRID') {
        map_options.mapTypeId = google.maps.MapTypeId.HYBRID;
    }
    else if(maptype === 'TERRAIN') {
        map_options.mapTypeId = google.maps.MapTypeId.TERRAIN;
    }

    if(typeof scrollwheel !== 'undefined') {
        map_options.scrollwheel = scrollwheel;
    }

    map = new google.maps.Map(document.getElementById('map'), map_options);

    if(ne === 'undefined' || ne === '') {
        center = $('#map-settings').data('map-center');
        if(typeof center !== 'undefined' && center !== '') {    
            center = center.split(',');
            var lat = parseFloat(center[0]);
            var lng = parseFloat(center[1]);
            var mapCenter = new google.maps.LatLng(lat,lng);
            map.setCenter(mapCenter); 
        }
    }
    else {
        var myLatLng = new google.maps.LatLng(parseFloat(ne[0]),parseFloat(ne[1]));
        bounds.extend(myLatLng);
        myLatLng = new google.maps.LatLng(parseFloat(sw[0]),parseFloat(sw[1]));
        bounds.extend(myLatLng);
    }

    if(mapzoom === '' || mapzoom === 0 || mapzoom === 'undefined') {
        //now fit the map to the newly inclusive bounds
        map.fitBounds(bounds);
    }

    var markerZindex;
    $("#property-list").on('mouseenter', '.property-details', function(){
        var id=$(this).data('count');
        markerZindex = markers[id].getZIndex();
        markers[id].setZIndex(1000);
        markers[id].setIcon(alternateMarkers[id]);
        //google.maps.event.trigger(markers[id], 'dblclick');
    }).on('mouseleave', '.property-details', function(){
        var id=$(this).data('count');
        markers[id].setIcon(markersIcon[id]);
        markers[id].setZIndex(markerZindex);      
    });

    $(window).on('resize', function(){
        google.maps.event.trigger(map, "resize");
        google.maps.event.trigger(map, 'dragend');
    });

    //var viewportBox;

    //var mls_property_count = $('.mls-property-count').first().text();

    $('form.fls-mls-property-search').append('<input type="hidden" name="northeast" id="northeast" /><input type="hidden" name="southwest" id="southwest"/>');

    var firing = false;
    google.maps.event.addListener(map, 'dragend', function() {
        //$('.main-content-container').on('click','#refresh-map, #loading-map', function(){
        if(firing === true) { return; }
        firing = true;
        bounds = map.getBounds();
        //console.log('fired');

        if(typeof bounds !== 'undefined') {
            var n,s,e,w;
            if($('#map').is(':visible')) {
                var ne = bounds.getNorthEast();
                $('#northeast').val(ne);       
                var sw = bounds.getSouthWest();
                $('#southwest').val(sw);
                n = ne.lat(); 
                s = sw.lat();
                e = ne.lng();
                w = sw.lng();
            }
            else {
                n = 0;
                s = 0;
                e = 0;
                w = 0;
            }
            var sort = $('#mls-listing-sort-by').val();
            mlscrit = window.location.pathname;


            $('.loading-map').removeClass('hidden');
            $.ajax({
                type: 'POST',
                url: ajaxparams.ajaxurl,
                data: {
                    'action': 'fls_mls_get_map_properties',
                    'data':   [n, s, e, w, sort, mlscrit],
                },
                success: function(response){
                    //console.log(response);        
                    if(response !== '' && response.success === true && response.data !== "[]" ) {
                        //console.log(response.data);
                        var properties = response.data;
                        clearMarkers(map, markers);
                        markers=[];
                        alternateMarkers=[];
                        markersIcon=[];

                        $('#property-list').empty();
                        $.each(properties, function(index, value){
                            $('#property-list').append(value);
                        });
                        addMapMarkers(map, bounds, markers, alternateMarkers, markersIcon, infowindow );

                        $('.property-stats','.fls-options-top').empty().html('Showing '+ properties.length + ' properties').removeClass('hidden');
                        contentHeight = $("#property-list","#map-view").outerHeight();
                    }
                    else {
                        console.log(response);
                    }
                },
                complete: function() {
                    $('.loading-map').addClass('hidden');
                    //$('#refresh-map').remove();
                    firing = false;
                }
            });
        }
    });
    google.maps.event.addListener(map, 'tilesloaded', function() {
        if($('#mls_area').val() !== '') {
            //console.log('tilesloaded trigger');
            $('#mls_area').trigger('change');           
        }
        else {
            //console.log('normal tilesloaded');
            google.maps.event.trigger(this, 'dragend');
        }
        //$('#loading-map').click();
        google.maps.event.clearListeners(map, 'tilesloaded');
    });

    google.maps.event.addListener(map, 'zoom_changed', function() {
        setTimeout(function() {
            google.maps.event.trigger(map, 'dragend');
        }, 200);
    });
});
7
  • Had the same problem. Try to remove the title attribute for the marker.
    – user55526
    Commented Jul 21, 2015 at 13:24
  • I have a similar problem with a web app I'm creating using Google Earth. Rather than markers I am using KML files. Commented Jul 21, 2015 at 17:41
  • @krille, thanks for the suggestion. I removed the title, but the problem presists.
    – MatthewLee
    Commented Jul 23, 2015 at 13:24
  • @CameronSloan, I am looking into KML files now. It would be interesting if it was in fact an issue with the markers. I have had a lot of versions of this code and going back through I have noticed that this has been a persistent problem for a long time even though many things have changed.
    – MatthewLee
    Commented Jul 23, 2015 at 13:54
  • very nice site - congrats. For what it's worth, I'm not seeing any problems with the infoWindow - hovering on a graphic shows the popup, and clicking once shows the infoWindow. Using Chrome on Windows 7 Commented Jul 24, 2015 at 2:27

2 Answers 2

1

I primarily work with KML Layers to display any features/information on Google Maps (and Google Earth). I have had better success with the API recognizing them over its own markers.

I use ArcGIS to create them, using the Layer to KML tool, and they will take on any symbology/pop up info that you have displayed with them upon conversion. So once they are how I want the user of the web app to view them, I create the KML files. Then I store them on the ArcGIS Online Server (however any server will work) to be hosted. Once they are shared with the public (still working on ways to not have to share publicly from server and require identification to view the web app) they can be called into the Google Maps JS API with the following code:

var LayerName = new google.maps.KmlLayer({
    url: 'http://InsertLayerURLHere.kml'
 });
 LayerName.setMap(map);

Google Maps and Google Earth (slightly different code to bring in KMLs) have worked well with recognizing the layers and displayed the information once clicked on. This should eliminate a lot of the additional code that may lead to these hard to find issues/errors.

9
  • Thanks for the answer. I tried adding that to the end of the addMapMarkers function and it changes the open hand cursor to a crosshair, but does not solve the issue where I have to click twice to activate the click event on the markers. Thanks again for taking a look
    – MatthewLee
    Commented Jul 17, 2015 at 22:44
  • I adjusted the answer, see if that works for you. Commented Jul 20, 2015 at 17:31
  • Thanks for the updated idea. But actually I don't even have the drawing library turned on and do not have drawing circles or other shapes enabled on the site. I have played around with the event that I am using to trigger the hover effect on the property list shown on the left. I have it on the zindex_change for the marker since I have it set up to move the marker to the top when someone hovers the property description on the left. I made that change to avoid tying it to any type of click event on the map itself which I think addresses the same issue you are thinking about?
    – MatthewLee
    Commented Jul 20, 2015 at 17:59
  • Hmm, it seems like the problem is that the map is ordered before the pins/tools are. I would try to set the map back so it prioritizes the markers and tools before it looks at the maps (maybe a negative z value for the map). Commented Jul 20, 2015 at 19:44
  • I tried playing around with the zindex on the markers including setting it extremely high without success. The map element does not seem to support setting a zindex. I can't do it using regular css because I would only be able to set it for the entire containing element which wouldn't change their relative placement.
    – MatthewLee
    Commented Jul 21, 2015 at 5:46
1

After doing some more searching, it looks like there could be an issue with how Firefox is trying to read your scripts. In the HTML header be sure to include:

<!DOCTYPE html>
<meta charset="utf-8">

I know that denoting HTML5 and utf-8 is a little bit of overkill but my only guess is that there may be some form of characters that could be causing some issues with marker recognition.

1
  • Hmm, Overkill or not, I have both of those tags set already...
    – MatthewLee
    Commented Jul 24, 2015 at 16:24

Your Answer

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

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