Google maps JavaScript API can be used to create visual
force pages with map to enhance the business experience. We can display
partners, contacts and leads on map to identify their locations, find the
routes and display the contacts within the specific range.
JavaScript API V3 is the latest version and all maps API
applications should load the map API using an API key which can be used to
monitor the API usages. We can purchase additional quota if application maps
API exceeds the usage limits.
First Step: To get Google Map API key
1) Go to APIs console https://code.google.com/apis/console and log in with your Google account.
2) Click on create project button
3) Left hand side, click on Services
4) Select the Google Maps API
v3 and Activate it by clicking on “Off” button
it becomes green “On”.
How the given code will work? Lets go one by one..
At the end of <apex:repeat>, we can call the JS method load();
To display marker with info window we can use the code below:
Add content to info window:
For more information: https://developers.google.com/maps/documentation/javascript/reference#InfoWindow
For more information: https://developers.google.com/maps/documentation/javascript/reference#Marker
Add “click” event to marker to display info window onclick:
For more information: https://developers.google.com/maps/documentation/javascript/reference#event
You can copy and paste the controller class and visual force page code if you want to use it but remember to use API KEY in script tag.
JavaScript API V3 is the latest version and all maps API
applications should load the map API using an API key which can be used to
monitor the API usages. We can purchase additional quota if application maps
API exceeds the usage limits.
JavaScript API V3 limits: 25000 maps loads per day, a map load is counted when a map is initialized on web page. User interaction with a map after it has loaded does not have any impact on usages limits.
Let’s start with an example to search Accounts by Name or Postal code and display all results on Google Maps.
First Step: To get Google Map API key
1) Go to APIs console https://code.google.com/apis/console and log in with your Google account.
2) Click on create project button
3) Left hand side, click on Services
4) Select the Google Maps API
v3 and Activate it by clicking on “Off” button
it becomes green “On”.
5) Left hand side, Click on API Access link, In Simple API Access section you will find the API key.
6) By default, a key can be used on any site. You can restrict the use of key to domains to prevent use on unauthorized sites. You can specify which domains are allowed to use your API key by clicking the Edit allowed referrers...
Create a controller to search Accounts:
Visual force
page to display search result on Google Map
<apex:page
showHeader="true" sidebar="false" controller=" AccountSearchController">
<script
type="text/javascript"
src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDjIY5HKM1dAlao6yUU8EzwPzdUh2ZNj0g&sensor=false">
</script>
<script>
var
gAccount = [];
var
map = null;
var
counter = 0;
var
delay = 500;
function
load() {
map = null;
mapDiv =
document.getElementById("map");
var mapOptions = {
center: new
google.maps.LatLng(-34.397, 150.644),
zoom: 4,
mapTypeId:
google.maps.MapTypeId.ROADMAP,
mapMaker: true
};
map = new
google.maps.Map(mapDiv,mapOptions);
finishSearch();
}
function
finishSearch() {
if(counter < gAccount.length){
showAddress(gAccount[counter++],finishSearch);
}
}
function
showAddress(record,finishSearch) {
var
html='';
try{
if(record.Longs != '' && record.Lats
!= ''){
var points = new
google.maps.Point(record.Lats,record.Longs);
var latLongs = new
google.maps.LatLng(record.Lats,record.Longs);
html ='<hr>' + counter
+'. '+ record.Name + '<br/>';
html += record.City +' '+
record.State + ' '+ record.Country + ', ' + record.Zip +
'<br/>';
html
+="<hr><b>URL:<b> <a
href=https://ap1.salesforce.com/" + record.Id + " target=_blank
>account details</a>";
var infowindow = new
google.maps.InfoWindow({
content: html
});
var marker = new google.maps.Marker({
position: latLongs,
map: map,
title: record.Name
});
google.maps.event.addListener(marker,
'click', function() {
infowindow.open(map,marker);
});
//set the center for last flag
if((gAccount.length - 1) == counter)
map.setCenter(latLongs, 3);
}
}catch(error){}
setTimeout(finishSearch,delay);
}
function
Group(id,name,lats,longs,displayNumber,city,state,country,zip) {
this.Id = id;
this.Name = name;
this.Lats = lats;
this.Longs = longs;
this.DisplayNumber = displayNumber;
this.City = city;
this.State = state;
this.Country = country;
this.Zip = zip;
}
function
setFocusOnMap(Lats,Longs){
map.setCenter(new
google.maps.LatLng(Lats,Longs), 3);
}
</script>
<apex:form
>
<apex:actionStatus
id="status" startText='Loading....' />
<apex:outputPanel
id="outMap">
<script
type="text/javascript">
function populateMap(){
gAccount=[];
<apex:repeat
value="{!lstAcc}" var="act" id="TmpLoop" >
gAccount.push(new
Group("{!act.acc.id}","{!act.acc.Name}","{!act.acc.Latitude__c}","{!act.acc.Longitude__c}",true,'{!act.acc.BillingCity}','{!act.acc.BillingState}','{!act.acc.BillingCountry}','{!act.acc.BillingPostalCode}'));
</apex:repeat>
load();
}
</script>
</apex:outputPanel>
<apex:pageBlock
title="Partner Finder">
<apex:pageBlockSection
columns="1">
<apex:pageBlockSectionItem
>
<apex:outputLabel
value="Name:"></apex:outputLabel>
<apex:outputPanel >
<apex:inputText
value="{!selectedAccName}"/>
</apex:outputPanel>
</apex:pageBlockSectionItem>
<apex:pageBlockSectionItem
>
<apex:outputLabel value="Postal
Code:"></apex:outputLabel>
<apex:outputPanel >
<apex:inputText
value="{!selectedZip}"/>
<apex:commandButton
value="Search" action="{!searchAcc}"
status="status" reRender="secMap,outMap" oncomplete="populateMap();"
/>
</apex:outputPanel>
</apex:pageBlockSectionItem>
</apex:pageBlockSection>
<apex:pageBlockSection
id="secMap" title="Search result"
columns="1">
<apex:outputPanel >
<table width="100%">
<tr>
<td width="100%">
<div id="map"
style="height: 600px;"></div>
</td>
</tr>
</table>
</apex:outputPanel>
</apex:pageBlockSection>
</apex:pageBlock>
</apex:form>
</apex:page>
|
How the given code will work? Lets go one by one..
Script
to load the Google Map API:
<script
type="text/javascript"
src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&sensor=false">
</script>
|
The SRC contained in the
script
tag is the location of a JavaScript file
that loads all of the symbols and definitions you need for using the Google
Maps API. This script
tag is required.
The
key
parameter contains your application's API
key. The sensor
parameter of the URL must be included and
indicates whether this application uses a sensor (such as a GPS locator) to
determine the user's location. You must set this value to either true
or false
explicitly.
<apex:pageBlockSection columns="1">
<apex:pageBlockSectionItem >
<apex:outputLabel
value="Name:"></apex:outputLabel>
<apex:outputPanel >
<apex:inputText value="{!selectedAccName}"/>
</apex:outputPanel>
</apex:pageBlockSectionItem>
<apex:pageBlockSectionItem >
<apex:outputLabel value="Postal
Code:"></apex:outputLabel>
<apex:outputPanel >
<apex:inputText value="{!selectedZip}"/>
<apex:commandButton value="Search"
action="{!searchAcc}" status="status"
reRender="secMap,outMap" oncomplete="populateMap();"
/>
</apex:outputPanel>
</apex:pageBlockSectionItem>
</apex:pageBlockSection>
|
This section will be used to
display input fields for name and postal code which are used to filter
accounts, commandButton action {!searchAcc}
is used to call searchAcc method of
controller which returns a list of accounts.
There is a JS method call on
commendButton’s “oncomplete” event which will create an Array of account
records in JavaScript. <apex:repeat> can be used to push records into
Group Object, you can put any name instead of “Group”.
At the end of <apex:repeat>, we can call the JS method load();
<apex:outputPanel id="outMap">
<script
type="text/javascript">
function
populateMap(){
gAccount=[];
<apex:repeat value="{!lstAcc}" var="act"
id="TmpLoop" >
gAccount.push(new
Group("{!act.acc.id}","{!act.acc.Name}","{!act.acc.Latitude__c}","{!act.acc.Longitude__c}",true,'{!act.acc.BillingCity}','{!act.acc.BillingState}','{!act.acc.BillingCountry}','{!act.acc.BillingPostalCode}'));
</apex:repeat>
load();
}
</script>
</apex:outputPanel>
|
Note: Please make sure that data does not contain the single quote.
We can use the JSENCODE().
Group object define in the script section, properties should be
same and must have some value if you want to display on info window of markers.
We can define the a Object in JavaScript, for ex: here is the
code for Group Object.
function
Group(id,name,lats,longs,displayNumber,city,state,country,zip) {
this.Id = id;
this.Name =
name;
this.Lats =
lats;
this.Longs =
longs;
this.DisplayNumber = displayNumber;
this.City =
city;
this.State =
state;
this.Country =
country;
this.Zip = zip;
}
|
Latitudes and Longitudes values must have some values to display
marker on Google Map, We can store these values on Account object using two
custom fields. Salesforce.com is
planning to put these two fields as a standard field for account, contacts,
opportunity and lead. We have another option to create markers using address
but Lat and Long is better to use.
Load Google Map on Visual force:
var gAccount = [];
var map = null;
var counter = 0;
var delay = 500;
|
At the top of the page we
have define few Global variables, gAccount = [] will be used to create a
JavaScript array for markers, which contains the information to point the
markers on maps and display additional info on click of markers, delay will be
used to put some gap between two markers requests.
function load() {
map = null;
mapDiv =
document.getElementById("map");
var mapOptions
= {
center:
new google.maps.LatLng(-34.397, 150.644),
zoom: 4,
mapTypeId: google.maps.MapTypeId.ROADMAP,
mapMaker:
true
};
map = new
google.maps.Map(mapDiv,mapOptions);
finishSearch();
}
function finishSearch() {
if(counter <
gAccount.length){
showAddress(gAccount[counter++],finishSearch);
}
}
|
Once Google Map API script
tag has been added at top of the page, we can start JS code to load map on
Visual force page with Map (mapotions: mapotions)
method. Create a method load() in VF page using this code.
Map
Options:
Center:
display the default center location,
zoom:
map zoom level,
mapTypeId:
define the type of map, it can be roadmap, satellite etc.
For more details you can visit https://developers.google.com/maps/documentation/javascript/reference#MapOptions
finishSearch() will be used to call method showAddress(Account
object,finishSearch); it is a recursive call to display markers on map for all
record of search result.
A <div> should be used
to display map in Visual Force pages as a container, we need to define a
<div> section before loading map through JavaScript.
<apex:pageBlockSection id="secMap"
title="Search result" columns="1">
<apex:outputPanel >
<table
width="100%">
<tr>
<td
width="100%">
<div id="map" style="height:
600px;"></div>
</td>
</tr>
</table>
</apex:outputPanel>
</apex:pageBlockSection>
|
We can set the height and width
as per our display area on visual force page.
To display marker with info window we can use the code below:
function showAddress(record,finishSearch) {
var html='';
if(record.Longs !=
'' && record.Lats != ''){
var points
= new google.maps.Point(record.Lats,record.Longs);
var
latLongs = new google.maps.LatLng(record.Lats,record.Longs);
html
='<hr>' + counter +'. '+ record.Name + '<br/>';
html +=
record.City +' '+ record.State + ' '+ record.Country +
', ' + record.Zip + '<br/>';
html
+="<hr><b>URL:<b> <a
href=https://ap1.salesforce.com/" + record.Id + " target=_blank
>account details</a>";
var
infowindow = new google.maps.InfoWindow({
content: html
});
var marker
= new google.maps.Marker({
position: latLongs,
map:
map,
title:
record.Name
});
google.maps.event.addListener(marker,
'click', function() {
infowindow.open(map,marker);
});
//set the center for last flag
if((gAccount.length - 1) == counter)
map.setCenter(latLongs, 3);
}
setTimeout(finishSearch,delay);
}
|
google.maps.infowindow will
display information onclick on markers. Content can be formatted using HTML
tags in string binding with Group Object properties.
Add content to info window:
html ='<hr>' + counter +'. '+ record.Name
+ '<br/>';
html +=
record.City +' '+ record.State + ' '+ record.Country +
', ' + record.Zip + '<br/>';
html
+="<hr><b>URL:<b> <a
href=https://ap1.salesforce.com/" + record.Id + " target=_blank
>account details</a>";
var
infowindow = new google.maps.InfoWindow({
content: html
});
|
For more information: https://developers.google.com/maps/documentation/javascript/reference#InfoWindow
Create
a marker with position and assign it to map:
var marker = new google.maps.Marker({
position: latLongs,
map:
map,
title:
record.Name
});
|
For more information: https://developers.google.com/maps/documentation/javascript/reference#Marker
Add “click” event to marker to display info window onclick:
google.maps.event.addListener(marker,
'click', function() {
infowindow.open(map,marker);
});
|
For more information: https://developers.google.com/maps/documentation/javascript/reference#event
You can copy and paste the controller class and visual force page code if you want to use it but remember to use API KEY in script tag.
I copied the same code which you have posted here. I created two text fields for latitude and longitude and you i changed the constructorname from PF controller to Accountsearchcontroller . I got the map inside the VF page but the thing is the button action method isnt working. Can you tell me what went wrong please?
ReplyDeleteAttn: Re: Google ZipCode Map API 2014
DeletePlease indicate your fixed fee & time required to install a stand alone
Google Store Locator Map on my website that is similar to this site,
for reference only. Google Zipcode Map v3 See code.
http://www.curves.com/locations Enter Zipcode 19802 See results.
Must install on this website blank page, with an Excel CSV file that
we can manually add new store locations as we get them.
https://sites.google.com/a/mediablitzers.net/ovenus1
Click on Find Us tab - must remove this broken map. Install new map.
Create Map on local server to deterine if it can function flawlessly ?
Please advise us of your possible interest or tell us, who is capable.
Include the URLs for the sites which you have installed this Google
Store Locator Zipcode v3 Map.
Sincerely, JamesBarbone@verizon.net + Thanks
Sample:
http://www.curves.com/find_a_club/locationsresults?lat=39.75715637207&lng=-75.527565002441&code=19802
http://www.lowes.com/LowesStoreSearchCmd Enter Zipcode 19802 or State - Delaware To see the Map Store Locations
Like Nirmal, I changed the constructor name.
DeleteI also added an initialiser for the counter inside populateMap
function populateMap(){
gAccount=[];
counter = 0;
gAccount.push(new Group("{!act.acc.id}","{!act.acc.Name}","{!act.acc.Location__Latitude__S}","{!act.acc.Location__Longitude__s}",true,'{!act.acc.BillingCity}','{!act.acc.BillingState}','{!act.acc.BillingCountry}','{!act.acc.BillingPostalCode}'));
load();
}
I also had to change latitude__c to location__latitude__s (ditto longitude).
For additional debugging aid I added a list Blocksection:
and added its Id to the reRender command
reRender="secMap,outMap,listAccs".
Many thanks for this blog, Pandey.
Dave Roberts.
This comment has been removed by the author.
DeleteThe missing section...it doesn't like <> so stripped every line. Don't forget to add them back.
ReplyDeleteapex:pageBlockSection id="listAccs" title="List of names" columns="1"
apex:repeat value="{!lstAcc}" var="c"
apex:outputText value="Account {0}:{1} has location lat={2}, long={3}...{4}"
apex:param value="{!c.acc.Id}"/
apex:param value="{!c.acc.Name}"/
apex:param value="{!c.acc.location__latitude__s}"/
apex:param value="{!c.acc.location__longitude__s}"/
<pex:param value="{!c.acc.BillingStreet}"/
/apex:outputText
/apex:repeat
apex:pageBlockSection
Found all the information need here. Thanks for sharing the amazing information.
ReplyDeleteSalesforce Integration Services