[Google Maps] Are there some more information on using this? 

[Google Maps] Are there some more information on using this? 

  
Forge Component
(13)
Published on 20 Sep (5 days ago) by OutSystems Labs
13 votes
Published on 20 Sep (5 days ago) by OutSystems Labs
I need to be able to display POI information as one clicks on the location marker and then pass that information out of the map back to my logic. I'm not quite sure how it's done with the available actions and options.

I would greatly appreciate any information on this.
Hello, Andrei,

If I understood correctly, you want something like this:


If so, you can achieve this with a Marker Event, listening to the 'click' event and a function that creates and opens an InfoWindow object. For the marker you saw here, here's the function you could've passed:
"function() {
    var contentString = 
    '<h3 style='margin:0'>Princesa Isabel Vinhos</h3><br>
    <strong>Phone: </strong>(1) 356-5634<br>
    <strong>Fax: </strong><br>
    <br>
    <strong>Address:</strong><br>
    Estrada da saúde n. 58<br>
    Lisboa, 1756<br>
    Portugal';

    var infowindow = new google.maps.InfoWindow({
          content: contentString
      });

    // Access this gMarker's map, set the center
    // to its position and zoom
    this.getMap().setCenter(this.getPosition());
    this.getMap().setZoom(8);    
    infowindow.open(this.getMap(), this);
}"
(notice how the 'contentString' string is HTML; you can use this to display )

As for sending data from this InfoWindow back to the server, there is no straight-forward way, but it can be done. (we did this on 'AddDirections', using JavaScript and a couple of elements in an invisible container)

What exactly are you trying to send back to the server? Do you want to have a form inside this balloon and submit it back? Do you want to change something on the current page? Do you need information from the server?
Well, the idea is this. We do a search in maps and have several markers pop up on the map(this part is working) then we need to be able to click onn the marker to have each marker's info pop up in a bubble as you described above and compare that marker's information with a list of locations in an entity. At this point if an address and name matches our records we do some stuff, if it does not, we do some other stuff. We also need to sort through a separate list of locations and show the closest one or two.
I take it the search is not powered by your OS code? Is it maybe something like this?

If so, I believe you need some way to execute code whenever a marker is added, because from what I've gathered from Google Maps' API doesn't include a JavaScript function to return all the markers on a given map.

Can you be more specific on how you are achieving things so far?

Does this work in outsystems now? I cannot get it to work?
Ok, I got the information bubble to work (sort of)

See the attached pic for the flow layout for a Search action. GetJSON is the response from the Google Places API webservice (To successfully complete that you have to use the service URL in a browser with a search string and then paste the response in the large textarea in the webservice creation dialog)

Then I use the ForEach block to parse the response and assign some local variables which I use in the AddMarkerEvent block. Problem is that Google Places returns already preformatted address and I can't split it into Street and City and Zip... But whatever at this point. Here is my code that creates the info window. I used the above example (Thanks Carlos) and was able to concatenate local variables which I assigned in the Assign block.

Next I need to figure out how to compare the Lat Lng of a clicked POI to a list of our locations' Lat Lng, calculate the distance between them, and then filter our locations to show only two or three closest ones...

The infowindow code:
"function() {
 var contentString = 
    '<p style=\'width:200px; margin:0;\'><h3 style=\'margin:0\'>"+MarkerTitle+"</h3><br><strong>Address:</strong><br>"+markerAddress+"</p>';

    var infowindow = new google.maps.InfoWindow({
          content: contentString
      });
    // Access this gMarker's map, set the center
    // to its position and zoom
    this.getMap().setCenter(this.getPosition());
    this.getMap().setZoom(8);    
    infowindow.open(this.getMap(), this);
}"
Andrei Malyuchik wrote:
Ok, I got the information bubble to work (sort of)

See the attached pic for the flow layout for a Search action. GetJSON is the response from the Google Places API webservice (To successfully complete that you have to use the service URL in a browser with a search string and then paste the response in the large textarea in the webservice creation dialog)

Then I use the ForEach block to parse the response and assign some local variables which I use in the AddMarkerEvent block. Problem is that Google Places returns already preformatted address and I can't split it into Street and City and Zip... But whatever at this point. Here is my code that creates the info window. I used the above example (Thanks Carlos) and was able to concatenate local variables which I assigned in the Assign block.

Next I need to figure out how to compare the Lat Lng of a clicked POI to a list of our locations' Lat Lng, calculate the distance between them, and then filter our locations to show only two or three closest ones...

The infowindow code:
...
Judging from your use case, I would say you can cover this without doing it from the InfoWindow itself.

You are adding the markers through their addresses, right? Why not use the 'AddressToCoordinates' action to translate the address into coordinates? This would enable you to calculate the closest points for each marker right there.

After you have these locations, you say you want to display two or three markers closest to another one, and hide the remaining ones, right? You can do that through the callback you defined on the AddMarkerEvent action:

"function() {
    ...
    infowindow.open(this.getMap(), this);

    // ...now hide all the points from this map, except this one...
    allMarkers = this.getMap().markers;
    for(index = 0, length = allmarkers.length; index < length; index++){
        allMarkers[index].gMarker.setVisible(false);
    }
    this.setVisible(true);

    // ...and add the closest three to the map
    osGoogleMap.addMarker(this.getMap().mapId, 'NearPOI1', {position: new google.maps.LatLng("+Lat1+","+Long1+")});
    osGoogleMap.addMarker(this.getMap().mapId, 'NearPOI2', {position: new google.maps.LatLng("+Lat2+","+Long2+")});
    osGoogleMap.addMarker(this.getMap().mapId, 'NearPOI3', {position: new google.maps.LatLng("+Lat3+","+Long3+")});
}"
Don't forget to also set a Map Event for 'click', so that when you click the map outside the InfoWindow, these nearby locations are removed (use 'osGoogleMap.removeMarker(mapId, 'NearPOIX')') and set the initial markers back to visible.

Does this fit your use case? Please let me know if not, or if you are having trouble getting this to work (or even this last MapEvent part) and we can discuss by Private Message.

Martyn Payne wrote:

Does this work in outsystems now? I cannot get it to work?
 
Which part were you referring to, Martyn?
The marker pop-up (infowindow) that shows the information.
I don't seem to be able to get this to work in Outsystems Now
martyn payne wrote:
The marker pop-up (infowindow) that shows the information.
I don't seem to be able to get this to work in Outsystems Now
That's strange...the example InfoWindow I gave a couple of posts ago is being used on our Mobile Order Management sample app. (even through OutSystems Now)
Can you please describe the issue over PM, so we don't "hijack" this thread?
 
One thing I noticed in Carlos' code, is that I had to escape the single quotes in the style property with a "\" for the info window to work.
Andrei Malyuchik wrote:
One thing I noticed in Carlos' code, is that I had to escape the single quotes in the style property with a "\" for the info window to work.
You're right, Andrei. I was testing my InfoWindow a while ago and it was failing silently. My bad for not testing it. :P
 
Sorry for the double post, guys, but I feel I should clear this up, as more people have had issues with it. Here's the example I gave, only now it works:

"function() {
    var contentString = 
    '<h3 style=\'margin:0\'>Princesa Isabel Vinhos</h3><br>'+
    '<strong>Phone: </strong>(1) 356-5634<br>'+
    '<strong>Fax: </strong><br>'+
    '<br>'+
    '<strong>Address:</strong><br>'+
    'Estrada da saúde n. 58<br>'+
    'Lisboa, 1756<br>'+
    'Portugal';

    var infowindow = new google.maps.InfoWindow({
          content: contentString
      });

    // Access this gMarker's map, set the center
    // to its position and zoom
    this.getMap().setCenter(this.getPosition());
    this.getMap().setZoom(8);    
    infowindow.open(this.getMap(), this);
}"
The next version of Google Maps will feature a working example with InfoHTML baloons, so stay tuned for that! :)
Hi all,

exist a way of when we click in a marker open the infowindow ballon of that specific marker and close other ones that maybe are opened? I tried a lot of things but the problem it's that i don't have access to the list of the markers id to close them before open the one I want.
Using this tool how can we access to markers id without having to load all the map again and built the list of the markers?

Thanks in advance.

Cheers
//Right here is how I access the bubble to close it. I get document by Id and then back out a few parent nodes to get to the actual bubble.
if(document.getElementById('content')){
var info_window = document.getElementById('content').parentNode.parentNode.parentNode.parentNode.parentNode;
//document.getElementById('content').close();
}
var infowindow;
if (info_window){
info_window.removeChild(document.getElementById('content').parentNode.parentNode.parentNode.parentNode);
}


//right here we create a div with an id of "content" so we can find the info bubble later to close it.
 var contentString = '<div id=\'content\'>' +
    '<p style=\'width:200px; margin:0;\'><h3 style=\'margin:0\'>"+MarkerTitle+"</h3><br><strong>Address:</strong><br>"+markerAddress+"</p></div>';
    if (infowindow) infowindow.close();
    infowindow = new google.maps.InfoWindow({
          content: contentString
      });
    


    //Decided not to center the marker because then the map gets jerky trying to center on the yesco locations
    //this.getMap().panTo(this.getPosition());
//No Zooming is nessesary for the same reason as the centering issue

var zoom = this.getMap().getZoom();

//if(this.getMap().getZoom() < 12){
//   this.getMap().setZoom(12); 
//}  
 
    infowindow.open(this.getMap(), this);

var latInput = document.getElementById('"+latInput.Id+"');
latInput.value = "+locationLat_+";
var lngInput = document.getElementById('"+lngInput.Id+"');
lngInput.value = "+locationLng_+";

var BusinessNameField = document.getElementById('"+BusinessNameField.Id+"');
BusinessNameField.value = '"+MarkerTitle+"';

var AddressField = document.getElementById('"+AddressField.Id+"');
AddressField.value = '"+markerAddress+"';

document.getElementById('"+submitLatLng.Id+"').click();
Gonçalo Azambujo wrote:
Hi all,

exist a way of when we click in a marker open the infowindow ballon of that specific marker and close other ones that maybe are opened? I tried a lot of things but the problem it's that i don't have access to the list of the markers id to close them before open the one I want.
Using this tool how can we access to markers id without having to load all the map again and built the list of the markers?

Thanks in advance.

Cheers
 Hey there, Gonçalo,

I haven't throughly analysed Andrei's solution, but it sure looks like he's on right track: if you only want to have one InfoWindow open on the map at a time, then keep a global variable assigned to its object and close it on the 'click' event handler of a marker. Imagine an hypothetical 'createMarker()' function and global 'infowindow' variable [1]:

function createMarker(name, latlng) {
    var marker = new google.maps.Marker({position: latlng, map: map});
    google.maps.event.addListener(marker, "click", function() {
        if (infowindow) infowindow.close();
            infowindow = new google.maps.InfoWindow({content: name});
            infowindow.open(map, marker);
        }
    );
    return marker;
}
Here, we create the marker and add a 'click' event handler that checks for an assigned 'infowindow' variable and calls the 'close()' method to close the previous InfoWindow, before opening one afterwards.

As for your specific question regarding marker identifiers: our Google Maps component creates an 'osGoogleMap' object, which has an array of OSMap objects, each of which has an array OSMarkers. You can then access the marker with something like 'osGoogleMap.OSMaps[<mapId>].markers[<markerId>]'.

If you have used our 'AddMarkerToMap' actions , then 'markerId' will be on the action's return value and 'mapId' is the 'RuntimeId' property of a Map Web Block (don't forget to name it, so it's accessible). You can check out the component's 'MultipleMarkers' WebScreen, on the 'GoogleMapsDemo' eSpace, for an example of referencing both marker and map Ids.

[1] http://www.lootogo.com/googlemapsapi3/markerPlugin.html
Thank you all for you help.

At the moment this implementation it's in "stand by" but in future ,for sure, I will need to get back to it and your tips will help me a lot.
Thanks

Cheers
No problem, Gonçalo, we're glad to help!

Don't hesitate to open a new thread if you have further questions or otherwise want to discuss stuff related to the component.

Cheers!
EDIT: I looked at the demo code of the MultipleMarkersMap and used the code there to fix mine. Sorry. 

Sorry for digging this post up, but I've been trying to get an infoWindow without much luck. I can add markers perfectly (I do this in a ForEach where I get a GMapsResult, add a coordinate based on the info stored in that entity, and after that I run the AddMarkerEvent). See here: 


Here are the AddMarkerEvent details. Could someone tell me what exactly I'm doing wrong? I can't seem to find it (I get no errors in the JS console or in Service Studio).

Kind regards,
Robrecht