简体   繁体   中英

jQuery Google Maps - open infowindow on click

I am running a google map from HTML data and I really need to be able to click on rows (divs) to open the relevant marker. I was hoping to add an onclick within an .each() function but I cant get anything I have tried to work.

Basically if clicking on each row could open the relevant infowindow it would solve all my problems :)

Help would be much appreciated.

<script type="text/javascript" language="javascript">
        var infowindow = new google.maps.InfoWindow();
        var myOptions = {
           zoom: 4,
           center: new google.maps.LatLng(-40.900557, 174.885971),
           mapTypeId: google.maps.MapTypeId.ROADMAP,
           disableDefaultUI: true
        };
        var icon = "img/marker.png";
        $(function() {
            map = new google.maps.Map(document.getElementById("map"), myOptions);
            // grab data attributes from html
            $('.row').each(function( index ){
                var rLat = $(this).data("coordinates").lat;
                var rLong = $(this).data("coordinates").long;
                var rTitle = $(this).find('.itemtitle a').html();
                var rTel = $(this).find('.tel').html();
                var rAdd = $(this).find('.add').html();
                var contentString = '<div style="text-align:left"><h4 style="color:#0068a6;font-size:16px;margin:0px 0px 10px 0px;">' + rTitle + '</h4><strong>' + rTel + '</strong><br /><br />' + rAdd + '</div>';
                var myLatLng = new google.maps.LatLng( rLat, rLong );
                var otherMarkers = new google.maps.Marker({
                    position: myLatLng,
                    map: map,
                    icon: icon
                });
                // click actions
                google.maps.event.addListener(otherMarkers, 'click', (function(otherMarkers, index) {
                    return function() {
                        infowindow.setContent( contentString );
                        infowindow.open( map, otherMarkers );
                    }
                })(otherMarkers, index));               
            });
        });

        $(function() {
            $(".leftblock .ctrlholder:nth-child(2)").addClass("last");
            $(".leftblock .ctrlholder:nth-child(3)").addClass("last");
        });
    </script>

HTML

<div class="row" data-coordinates='{"lat" : -41.407493, "long" : 174.584122}'>
    <h4 class="itemtitle"><a href="">Title</a></h4>
    <p class="centralregion">Address</p>
    <ul>
        <li class="add">Post Address</li>
        <li class="tel">tel</li>
    </ul>
    <span class="filter3"></span>
</div>

Thanks in advance.

Since you already loop over all the rows to create markers you can add a click handler to each row that will click on the marker

after adding marker event listener:

 google.maps.event.addListener(otherMarkers......);

Add a row click handler that triggers a marker click:

/* "this" is the row instance*/
$(this).click(function(){
 google.maps.trigger( otherMarkers ,'click')
})

The following approach is slightly convoluted but has the advantage of being economical of memory.

$(function() {
    var myOptions = {
       zoom: 4,
       center: new google.maps.LatLng(-40.900557, 174.885971),
       mapTypeId: google.maps.MapTypeId.ROADMAP,
       disableDefaultUI: true
    };
    var map = new google.maps.Map(document.getElementById("map"), myOptions);
    var infowindow = new google.maps.InfoWindow();
    var icons = {
        'dflt': "../images/map_icons/beach-certified.png",
        'selected': "../images/map_icons/harbour-guest.png"
    };
    var infoTemplate = '<div style="text-align:left"><h4 style="color:#0068a6;font-size:16px;margin:0px 0px 10px 0px;">%Title</h4><strong>%Tel</strong><br /><br />%Add</div>';
    var seletedMarker = null;

    //Function for composing the info string on the fly.
    //This avoids needing to store fully composed info strings in a closure,
    //on the offchance that they will be viewed.
    function composeInfoString(row) {
        var $row = $(row);
        return infoTemplate
            .replace('%Title', $row.find('.itemtitle a').html())
            .replace('%Tel', $row.find('.tel').html())
            .replace('%Add', $row.find('.add').html());
    }

    //closure-forming function to trap row and marker
    function clickHandler(row, marker) {
        return function() {
            if(seletedMarker) {
                seletedMarker.setIcon(icons.dflt);//revert seletedMarker's icon to .dflt
            }
            infowindow.setContent( composeInfoString(row) );
            infowindow.open( map, marker );
            marker.setIcon(icons.selected);//Set marker's icon to .seleted
            seletedMarker = marker;//Remember the currently selected marker so it can be reverted to default next time round.
        };
    }

    $('.row').each(function( index, row ) {
        var $row = $(row);
        var coords = $row.data("coordinates");
        //console.log([coords.lat, coords.lng].join());
        var marker = new google.maps.Marker({
            position: new google.maps.LatLng( Number(coords.lat), Number(coords.lng) ),
            icon: icons.dflt,
            map: map
        });
        var fn = clickHandler(row, marker);
        google.maps.event.addListener(marker, 'click', fn);
        $row.data('clickFn', fn);//associate fn with row.
    });

    //Delegate handling of row clicks upward (to closest common row container).
    $(document).on('click', '.row', function() {
        var fn = $(this).data('clickFn');
        if(fn) fn();//this is the functionality you seek
    });
});

The economies are twofold :

  • By composing the info-string on the fly, you avoid the need to store fully composed info strings in closures (one per marker/row), on the off-chance that they will be viewed.
  • By attaching fn (pragmatically speaking, a "closure") to each row as a .data() item, and delegating click handling upwards, you can exploit the same closure used when clicking the marker directly without the need for an additional function wrapper per marker/row.

These kinds of economies can be significant when working with many markers, and otherwise do no harm.

Also, you might like to consider changing your coordinate longitude property from long to lng . In the code, this will avoid .long , which can give problems in some browsers. long is one of many underlying language keywords that should be avoided as js object property identifiers.

Edit

Now tested - See updated fiddle . Various fixes are reflected above.

Edit 2

Code modified to swap-out selected marker icon- See updated fiddle .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM