Posted in ColdFusion | Posted on 12-27-2009 | 5,329 views
For a while now I've had two line items in my "To write about" notebook. They concerned figuring out how to use CFMAP (and Google Maps in general) to center the map on an address. Out of the box you have an immediate address that acts as the center, but I wanted to see how the center could be changed post map load.
My first attempt was to figure out a way to center the map on an marker. I began with an extremely simple script:
2
3 <cfmapitem address="New Orleans, LA">
4
5</cfmap>
This generated:
Looking over both the ColdFusion docs and the Google Maps API, I began by adding ajaxOnLoad to the bottom of my script:
And used this for my init:
2 ColdFusion.Map.addEvent("mainMap", "click", clickHandler)
3}
This code adds a click handler for the map I created earlier. The click handler does:
2 if (item) {
3 var map = ColdFusion.Map.getMapObject("mainMap")
4 map.setCenter(item.getLatLng())
5 }
6}
Because I've got a click handler for the entire map, it runs whenever you click on it. However, it only passes event data when you click on one of the markers. Either the center marker (St. Louis) or New Orleans. This feels a bit.... fuzzy to me. I should probably check to see if item is an instance of a marker object. But the important part is the setCenter call. I run this on the map object returned by getMapObject. You can get fancy if you want to - change setCenter to panTo and you get a nice animation. View the Demo
Here is the complete code for that example:
2
3<head>
4<script>
5function clickHandler(item){
6 if (item) {
7 var map = ColdFusion.Map.getMapObject("mainMap")
8// map.setCenter(item.getLatLng())
9 map.panTo(item.getLatLng())
10 }
11}
12
13function init(){
14 ColdFusion.Map.addEvent("mainMap", "click", clickHandler)
15}
16</script>
17</head>
18
19
20<body>
21
22
23<cfmap centeraddress="St. Louis, MO" width="400" height="400" name="mainMap">
24
25 <cfmapitem address="New Orleans, LA">
26
27</cfmap>
28
29
30</body>
31</html>
32<cfset ajaxOnLoad("init")>
Ok, that works, but is a bit simplistic. I wanted to step it up a notch and add more interactivity. For my second demo, I created a list of cities. These cities were used as map markers, but I also wanted a simple HTML list as well. Clicking on the text version of the city would center the map. (I skipped making the marker work as well since I had just done that.) To begin, I created my list of cities.
Next I wrote the code to generate the map and HTML list:
2 <cfloop index="address" array="#addresses#">
3 <cfmapitem address="#address#">
4 </cfloop>
5</cfmap>
6
7<p/>
8
9<cfloop index="address" array="#addresses#">
10 <cfoutput>
11 <a class="addressDisplay" href="javascript:center('#jsStringFormat(address)#')">#address#</a>
12 </cfoutput>
13</cfloop>
Notice that for each address I'm calling a JavaScript function center. Let's take a look at that:
2 ColdFusion.Map.setCenter('mainMap',{
3 address: s
4 })
5}
Yeah - pretty simple, right? Unfortunately, something goes wonky when you run this. The first time I ran my code, I ended up with new, green markers on the locations. This was before I added showcentermarker="false" to my map. I clicked a bunch of cities and each time it simply added green markers. It never actually centered.
When I added showcentermarker="false", it did absolutely nothing. You can see this yourself here. I'm guessing it is just a bug.
I decided to switch to the code I used in the first code sample. But to do that - I needed longitude and latitude. Normally I'd recommend always using those values (see my previous article on this linked to below), but I only had string addresses for now. I was lucky though to find a quick solution on the Google Maps API reference. They had this very simple example of using the Geolocation API:
2 var geocoder = new GClientGeocoder();
3
4 geocoder.getLatLng(
5 address,
6 function(point) {
7 if (!point) {
8 alert(address + " not found");
9 } else {
10 map = ColdFusion.Map.getMapObject("mainMap")
11 map.setCenter(point);
12 }
13 }
14 )
15
16}
Now the code creates a new instance of GClientGeocoder and runs getLatLng on the address. Notice the use of the inline function to handle the result and set the center. You can see this demo here: View the Demo
And here is the complete script:
2
3<html>
4
5<head>
6<script>
7function center(address){
8 var geocoder = new GClientGeocoder();
9
10 geocoder.getLatLng(
11 address,
12 function(point) {
13 if (!point) {
14 alert(address + " not found");
15 } else {
16 map = ColdFusion.Map.getMapObject("mainMap")
17 map.setCenter(point);
18 }
19 }
20 )
21
22}
23</script>
24<style>
25.addressDisplay {
26 display: block;
27 background-color: #e0e0e0;
28 padding: 10px;
29 margin: 10px;
30 width:140px;
31}
32</style>
33</head>
34
35
36<body>
37
38
39<cfmap centeraddress="St. Louis, MO" width="400" height="400" name="mainMap" showcentermarker="false">
40 <cfloop index="address" array="#addresses#">
41 <cfmapitem address="#address#">
42 </cfloop>
43</cfmap>
44
45<p/>
46
47<cfloop index="address" array="#addresses#">
48 <cfoutput>
49 <a class="addressDisplay" href="javascript:center('#jsStringFormat(address)#')">#address#</a>
50 </cfoutput>
51</cfloop>
52
53</body>
54</html>
And finally, I decided to get crazy. I knew that Google's Streetview stuff was part of the main API. What I didn't know was how freaking easy it was to use.
2var myPano = new GStreetviewPanorama(document.getElementById("streetView"), panoramaOptions);
In this snippet, point is a valid longitude/latitude pair. The call to GStreetViewPanorama simply creates the streetview within a DOM item. Now, my addresses are pretty vague so this demo ain't great, but you can imagine how cool this would be for your business if you supplied some fuller data points. View the Uber Elite Awesome Demo
Pretty cool, right?



For an example: http://www.coldfusionjedi.com/demos/map122709/test...
Use your mouse wheel or double click... the map icons disappear.
For instance, I've got both a cfgrid and a cfmap on my page. Both are populated with the same records (each record returned in the cfgrid has a lat/long that is displayed on the cfmap).
I can't quite figure out how to do something like hover over a row in the cfgrid and make the map center to the corresponding point... or just temporarily change the color of the icon on the map.
To complicate it, my cfgrid is inside a <cfform> and uses the href, hrefkey, and selectmode='row' attributes. Meaning, a URL is launched when one single clicks on a row. So I can't use the rowclick event of the grid. ugh.... stuck...
[Add Comment] [Subscribe to Comments]