2

In short words, what I try to accomplish:

  • single InfoWindow on map, because of many markers
  • InfoWindow content attached to marker
  • InfoWindow opens on marker click => content from attached attribute
  • InfoWindow contains 2 buttons => set start, set target
  • if start and target are set, calculate route

I tried a lot and it's quite difficult to attach a handler to a button inside an InfoWindow. The best hint I found was this one: Adding event to element inside Google Maps API InfoWindow

I tried this so far:

<script>
function initialize() {
    var mapOptions = {
        center: new google.maps.LatLng(50.903033, 11.359863),
        zoom: 6,
        mapTypeId: google.maps.MapTypeId.ROADMAP,
        disableDefaultUI: true,
        zoomControl: true,
        scaleControl: true,
        overviewMapControl: true
    };
    var map = new google.maps.Map(document.getElementById('limousine-map'),
        mapOptions);
    var directionsService = new google.maps.DirectionsService();
    var directionDisplay = new google.maps.DirectionsRenderer();
    directionDisplay.setMap(map);
    directionDisplay.setPanel(document.getElementById('route-details'));
    var infoWindow = new google.maps.InfoWindow();
    var endPoint = false;
    var startPoint = false;


var marker = new google.maps.Marker({
    map: map,
    position: new google.maps.LatLng(50.903033, 11.359863),
    title: 'Test1'
});
marker.infoWindowContent = [
    '<div id="infoWindow"><strong>Test</strong>',
    '<button class="button" id="selectStart">Start</button>'+
    '<button class="button" id="selectTarget" style="float: right;">Target</button></div>'
].join('<br>');

google.maps.event.addListener(marker,'click',function(){
    infoWindow.close();
    infoWindow = new google.maps.InfoWindow({
        content: this.infoWindowContent
    });
    infoWindow.open(map,this);
    clickedLocation = this;
    google.maps.event.addListener(infoWindow, 'domready', function() {
        $('#infoWindow button').on('click',function(){
            console.log(clickedLocation);
            if($(this).attr('id') == 'selectStart'){
                startPoint = clickedLocation;
            }
            if($(this).attr('id') == 'selectTarget'){
                endPoint = clickedLocation;
            }
            recalcRoute();
        });
    });
});

var marker2 = new google.maps.Marker({
    map: map,
    position: new google.maps.LatLng(52.903033, 12.359863),
    title: 'Test2'
});
marker2.infoWindowContent = [
    '<div id="infoWindow"><strong>Test2</strong>',
    '<button class="button" id="selectStart">Start</button>'+
            '<button class="button" id="selectTarget" style="float: right;">Target</button></div>'
].join('<br>');

google.maps.event.addListener(marker2,'click',function(){
    infoWindow.close();
    infoWindow = new google.maps.InfoWindow({
        content: this.infoWindowContent
    });
    infoWindow.open(map,this);
    clickedLocation = this;
});



//Route painting
function recalcRoute(){
    if(startPoint != false && endPoint != false){
        var request = {
            origin: startPoint,
            destination: endPoint,
            travelMode: google.maps.TravelMode.DRIVING,
            unitSystem: google.maps.UnitSystem.METRIC
        };
        directionsService.route(request, function(response, status){
            if(status == google.maps.DirectionsStatus.OK){
                $('#route-details').parent().fadeIn();
                directionDisplay.setDirections(response);
            }
        });
    }else{
        directionDisplay.setDirections(null);
    }
}

}
google.maps.event.addDomListener(window, 'load', initialize);
</script>

I got the handler working, but then the route calculation doesn't work. I get an error like

Uncaught Error: Invalid value for property <origin>: [object Object] 
thrown at line: directionsService.route(request, function(response, status){

How can I bind an event to the buttons inside the InfoWindow and still call recalcRoute? I also tried to set onclick on the buttons, but the reference to recalcRoute is unknown.

Why is $('#infoWindow button').on('click',function(){ console.log('test'); }); not working?

Community
  • 1
  • 1
bitscorpion
  • 49
  • 1
  • 4

2 Answers2

0
  1. To access variables from HTML click listeners, they need to be in the global context.
  2. The origin and destination for the directions service need to be google.maps.LatLng objects or strings which can be geocoded as addresses, not google.maps.Marker objects. The google.maps.LatLng of a marker can be retrieved with:

    marker.getPosition().

working example

geocodezip
  • 158,664
  • 13
  • 220
  • 245
0

You should be able to establish the contentWindow's HTML and click actions just once, then use them over and over again.

The only thing in the contentWindow that needs to be changed is the title, to reflect the clicked marker's title.

Something like this should do it :

function initialize() {
    var mapOptions = {
        center: new google.maps.LatLng(50.903033, 11.359863),
        zoom: 6,
        mapTypeId: google.maps.MapTypeId.ROADMAP,
        disableDefaultUI: true,
        zoomControl: true,
        scaleControl: true,
        overviewMapControl: true
    };
    var map = new google.maps.Map(document.getElementById('limousine-map'), mapOptions);
    var directionsService = new google.maps.DirectionsService();
    var directionDisplay = new google.maps.DirectionsRenderer();
    directionDisplay.setMap(map);
    directionDisplay.setPanel(document.getElementById('route-details'));

    var Route = {
        var request = {
            origin: null,
            destination: null,
            travelMode: google.maps.TravelMode.DRIVING,
            unitSystem: google.maps.UnitSystem.METRIC
        };
        this.setOrigin = function(m) { request.origin = m.getPosition(); };
        this.setDestination = function(m) { request.destination = m.getPosition(); };
        this.calc = function() {
            if(request.origin && request.destination) {
                directionsService.route(request, function(response, status) {
                    if(status == google.maps.DirectionsStatus.OK) {
                        $('#route-details').parent().fadeIn();
                        directionDisplay.setDirections(response);
                    }
                });
            } else {
                directionDisplay.setDirections(null);
            }
        }
    };

    var route = new Route();
    var clickedLocation;

    var $infoWindowContent = $([
        '<div class="infoWindowContent">',
        '<h3></h3>',
        '<button class="setOrigin">Start</button>',
        '<button class="setDestination" style="float: right;">Target</button>',
        '</div>'
    ].join(''));
    $infoWindowContent.find(".setOrigin").on('click', function() {
        route.setOrigin(clickedLocation);
        route.calc();
    });
    $infoWindowContent.find(".setDestination").on('click', function() {
        route.setDestination(clickedLocation);
        route.calc();
    });

    var infoWindow = new google.maps.InfoWindow();
    infoWindow.setContent($infoWindowContent.get(0));

    //Assuming array markerData to contain the data necessary for bujilding markers ...
    $.each(markerData, function(i, m) {
        var marker = new google.maps.Marker({
            map: map,
            position: new google.maps.LatLng(m.lat, m.lng),
            title: m.title
        });

        google.maps.event.addListener(marker, 'click', function() {
            clickedLocation = this;
            infoWindow.close();//necessary?
            $infoWindowContent.find("h3").text(this.getTitle());
            infoWindow.open(map, this);
        });
    });

}
google.maps.event.addDomListener(window, 'load', initialize);

untested

Notes:

  • I wrapped up everything to do with the route in a Route() constructor, with a single instance route.
  • I assumed all the marker data to be initially contained in a markerData array, which is looped through to create as many markers as necessary.
Beetroot-Beetroot
  • 18,022
  • 3
  • 37
  • 44