views:

86

answers:

1

How do I integrate Salesforce with Google Maps? I'm just looking for information on how to...

  1. Search for contacts in Salesforce
  2. Plot those on a google map.
+3  A: 

This is an example from a workshop I've hosted recently, should get you started.

You can see how it should look like here: http://yfrog.com/9dgooglemapintegrationp

You'll need a Apex controller to search for accounts/contacts:

public class mapController2 {
    public String address {get;set;}
    private List<Account> accounts;

    public void find() {
        // Normal, ugly query.
        /*String addr = '%' + address + '%';
        accounts = [SELECT Id, Name, BillingStreet, BillingCity, BillingCountry FROM Account 
        WHERE Name LIKE :addr OR BillingStreet LIKE :addr OR BillingCity LIKE :addr OR BillingCountry LIKE :addr];
        */

        String addr = '*' + address + '*';
        // Or maybe a bit better full-text search query.
        List<List<SObject>> searchList = [FIND :addr IN ALL FIELDS RETURNING 
            Account (Id, Name, BillingStreet, BillingCity, BillingCountry)];
        accounts = (List<Account>)searchList[0];
    }

    public List<Account> getAccounts() {
        return accounts;
    }
}

Then you'll have to create a Visualforce page that will use this controller. Sorry, the example is a bit full-blown, I can help you later with understanding it if needed.

<apex:page controller="mapController2" tabStyle="Account">
<head>
    <script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"&gt;&lt;/script&gt;
<style>
#map {
  height:350px;
}
</style>
</head>
<apex:form >
    <apex:pageBlock title="Search by Address">
        <apex:inputText value="{!address}"/>
        <apex:commandButton value="Search" action="{!find}"/>
        <p>Examples: "USA", "Singapore", "Uni", "(336) 222-7000". 
           Any text data (free text, not picklists, checkboxes etc.) will do.
        </p>
    </apex:pageBlock>
    <apex:pageBlock title="Matching Accounts" rendered="{!address != null}">
        <apex:pageBlockTable value="{!accounts}" var="account" id="accountTable">
            <apex:column >
                <apex:facet name="header"><b>Name</b></apex:facet>
                <apex:outputLink value="../{!account.Id}">{!account.Name}</apex:outputLink>
            </apex:column>
            <apex:column >
                <apex:facet name="header"><b>Address</b></apex:facet>
                {!account.BillingStreet}, {!account.BillingCity}, {!account.BillingCountry}
            </apex:column>
        </apex:pageBlockTable>
    </apex:pageBlock>

    <apex:pageBlock title="Map" rendered="{!address != null}">
        <div id="log"></div>
        <p>Tip: hover mouse over marker to see the Account name. Click to show the baloon.</p>
        <div id="map">Placeholder - map will be created here.</div>
        <script type="text/javascript">
// First we need to extract Account data (name and address) from HTML into JavaScript variables.
var names = new Array();
var addresses = new Array();

var htmlTable = document.getElementById('j_id0:j_id2:j_id7:accountTable').getElementsByTagName("tbody")[0].getElementsByTagName("tr");
for (var i = 0; i < htmlTable.length; ++i) {
    names.push(htmlTable[i].getElementsByTagName("td")[0]);

    // We need to sanitize addresses a bit (remove newlines and extra spaces).
    var address = htmlTable[i].getElementsByTagName("td")[1].innerHTML;
    addresses.push(address.replace(/\n/g, "").replace(/^\s+/,"").replace(/\s+$/,""));
}

var coordinates = new Array();    // Array of latitude/longitude coordinates.
var markers = new Array();        // Red things we pin to the map.
var baloons = new Array();        // Comic-like baloons that can float over markers.
var counter = 0;

var mapOptions = {
    zoom: 5,
    mapTypeId: google.maps.MapTypeId.ROADMAP,
    navigationControl: true,
    navigationControlOptions: {
        style: google.maps.NavigationControlStyle.ZOOM_PAN
    }
};
var map = new google.maps.Map(document.getElementById("map"), mapOptions);

if(addresses.length > 0) {
    geocodeOneAddress();
}

function geocodeOneAddress(){
    var geocoder = new google.maps.Geocoder();
    geocoder.geocode({address: addresses[counter]}, processGeocodingResults);
}

function processGeocodingResults(results, status) {
    ++counter;
    if (status == google.maps.GeocoderStatus.OK) {
        coordinates.push(results[0].geometry.location);
    } else {
        logError(addresses[counter] + " could not be found, reason: " + status);
    }

    if(counter == addresses.length) {
        finalizeDrawingMap();
    } else {
        geocodeOneAddress();
    }
}

function finalizeDrawingMap() {
    // Compute min/max latitude and longitude so we know where is the best place to center map & zoom.
    var minLat = coordinates[0].b;
    var maxLat = coordinates[0].b;
    var minLong = coordinates[0].c;
    var maxLong = coordinates[0].c;

    for(i=0;i < coordinates.length; i++){
        markers.push(new google.maps.Marker({ position: coordinates[i], map: map, title: names[i].getElementsByTagName("a")[0].innerHTML, zIndex:i}));
        baloons.push(new google.maps.InfoWindow({content: '<b>'+names[i].innerHTML + '</b><br/>' + addresses[i]}));

        google.maps.event.addListener(markers[i], 'click', function() {
            baloons[this.zIndex].open(map,this);
        });

        minLat = Math.min(minLat, coordinates[i].b);
        maxLat = Math.max(maxLat, coordinates[i].b);
        minLong = Math.min(minLong, coordinates[i].c);
        maxLong = Math.max(maxLong, coordinates[i].c);
    }
    map.setCenter(new google.maps.LatLng(minLat + (maxLat-minLat) / 2, minLong + (maxLong-minLong) / 2));

    // All that is left is to possibly change the zoom. Let us compute the size of our rectangle.
    // This is just a rough indication calculation of size of rectangle that covers all addresses.
    var size = (maxLat-minLat) * (maxLong-minLong);
    var zoom = 13;

    if(size > 7100) {
        zoom = 2;
    }
    else if(size > 6000) {
        zoom = 3;
    }
    else if(size > 550) {
        zoom = 4;
    }
    else if(size > 20) {
        zoom = 6;
    }
    else if(size > 0.12) {
        zoom = 9;
    }
    map.setZoom(zoom);
}

function logError(msg) {
    var pTag = document.createElement("p");
    pTag.innerHTML = msg;
    document.getElementById('log').appendChild(pTag);
}
        </script>
    </apex:pageBlock>
</apex:form>
</apex:page>

The map should be accessible on a link (your organisation)/apex/mapTab2, for example https://na5.salesforce.com/apex/mapTab2

eyescream