Ask a Jedi: Click a CFMAP to get Longitude/Latitude

This post is more than 2 years old.

A reader asked:

cfmap is very new to me. Could it allow me to get click a map and set variables for the longitude and latitude of the point where I clicked? If so, how? That would be great for recording bird sightings!

I had not really looked much at Google Maps before ColdFusion 9 introduced it to me, but if there is one thing I've learned - Google Maps can do pretty much about anything. This particular request is actually really darn easy. Here is one way to solve the problem.

First, let's create a simple map and listen for the page to be complete. We will then grab the Map object using ColdFusion's JavaScript API. This will give us a hook to the proper Google Map object.

<html>

<head> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>

<script>

function init() { map = ColdFusion.Map.getMapObject('mainMap') } </script> </head>

<body> <h2>Bird Spotting Form</h2>

<cfmap name="mainMap" centeraddress="Lafayette, LA" showcentermarker="false" zoomlevel="13"> <p> Click on the map to record where you saw a bird. </p>

<form id="mainForm"> <input type="submit" value="Send Report" id="submitButton" style="display:none"> </form>

</body> </html> <cfset ajaxOnLoad("init")>

I've got a simple map centered on my home town. I put a form at the bottom which is empty for now. The last line, ajaxOnLoad, simple tells ColdFusion what JavaScript I need to run when the page is done loaded. Right now my init() function simply grabs the Google Map object.

I then did a quick Google (is it weird to use Google to search for Google docs?) on map events and came across a pretty nice set of documentation. As powerful as Google's APIs are, I'm not always quite as pleased with their docs or ease of use. In this case, it looks like all we need to do is add a simple event listener. This event listener will be called with either an overlay object or a longitude/latitude pair:

GEvent.addListener(map, "click", function(overlay,latlng) { })

For my demo I decided that each click would simply take the longitude and latitude and add them as text fields to a form. I whipped up the following JavaScript:

<script> var counter;

function init() { counter = 0 map = ColdFusion.Map.getMapObject('mainMap') GEvent.addListener(map, "click", function(overlay,latlng) { if(latlng) { counter++; var s = '<b>Report '+counter+'</b>: ' s += '<input type="text" name="siteport_' + counter + '" value="'+latlng+'" size="50"><br/>' $("#submitButton").before(s) $("#submitButton").show() } }) } </script>

For the most part this should be pretty trivial. I keep a counter so I can have unique numbers for each sighting. I used a text field with a dynamic name and value... and that's it. Here is a quick screen shot:

You can play with a demo here. Right now it isn't very exciting. We should probably add markers, and make the form a bit more complex. For example, most users probably don't need to see the actual latitude/longitude, but they probably want to enter data ("The bird was awesome, man. It had wings. And it flew. Cool."). In my next entry I'll add these features to the form.

Raymond Camden's Picture

About Raymond Camden

Raymond is a senior developer evangelist for Adobe. He focuses on document services, JavaScript, and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support. You can even buy me a coffee!

Lafayette, LA https://www.raymondcamden.com

Archived Comments

Comment 1 by Bob posted on 3/19/2010 at 9:09 PM

Waiting for more goodness with part two. Wondering if there is a way to measure the distance between each lat/long pair and then add a pointer to the map with a line connecting them?

Comment 2 by Raymond Camden posted on 3/19/2010 at 9:53 PM

I kinda forgot about this one. I'll definitely do a part 2 though. You can also do lines. I don't think lines make sense in this example, but I wanted to show that as well (err, what I mean is, it doesn't make sense for the 'Bird Watching' demo).

Comment 3 by Ben Nadel posted on 3/30/2010 at 11:02 PM

Very cool - I've only played around with Google maps and I am also impressed with how easy they make a lot of stuff.

Comment 4 by Jody Fitzpatrick posted on 4/10/2010 at 7:26 PM

I have a question, assume that we have placement markers throughout the cfmap. When we zoom out or in it will load more markers or less based on the location.

For Example.)

Marker one location is in NY, marker two is in Louisiana, and marker three is in California, While NY is only in few it will only show NY, but if CALI comes in view it will show the marker in Cali, as well if it was two show Louisiana in view.

Comment 5 by Raymond Camden posted on 4/11/2010 at 7:03 PM

Are you asking if that is possible? The answer is absolutely yes. Google has support for something called a Marker Manager. It is built to better handle large sets of markers and one of the specific features is support for 'show these markers at zoom x'

I'm rereading your comment and I think that may not _exactly_ match what you mean. Obviously if you set a marker to show at a 'low' zoom, then you would only see the CA one if you were zoomed in low enough. You can also notice when the view port changes. You could say, "If I'm in a range of these long/lat, I'm over CA so show marker X." Not sure how efficient it would be.

Comment 6 by Mike posted on 9/16/2011 at 2:36 AM

Hi Ray,

How would you adapt the js here to simply populate 1 existing input field and update it each time? I know its probably trivial but I cant figure it out...

thanks man.

Mike

Comment 7 by Raymond Camden posted on 9/16/2011 at 7:44 PM

Instead of adding a new field, you would append to the old field like so (assume old field has id of 'simple')

$("#simple").append(latln)

Append should append to the value.... but double check that. If it doesn't, just do

$("#simple").val($("#simple").val() + "," +latlng)

Actually that second one is better as it adds the comma to keep it separate.

Actually (grin), that's bad since the lat and lng are separated with a comma. You REALLY don't want to use one field. But if you insist, use another delimiter like a @ sign. Or consider a textarea and use line breaks.

Comment 8 by Misty posted on 12/17/2011 at 8:43 AM

Hi ray, What if we want to calculate the difference between the two locations and hightlight the one to use which is the shortest route.

is this possible

Comment 9 by Raymond Camden posted on 12/17/2011 at 8:04 PM

You need to look at Google's Directions API. It supports finding routes, finding quickest, etc. I've blogged on this before, and of course, Google has a bunch of docs on it. It's a rather nice service actually.

Comment 10 by Ahmad Bakri posted on 1/8/2012 at 12:44 PM

Thanks Ray,

This is damn useful, very simple. I even manage to retrieve address with little GClientGeocoder()tweak.

<script>
var counter;

function init() {
counter = 0;

var geocoder = null;
geocoder = new GClientGeocoder();

map = ColdFusion.Map.getMapObject('mainMap')
GEvent.addListener(map, "click", function(overlay,latlng) {
if(latlng) {

geocoder.getLocations(latlng, function(addresses) {
if(addresses.Status.code != 200) {
alert("reverse geocoder failed to find an address for " + latlng.toUrlValue());
}
else {
address = addresses.Placemark[0];
var myHtml = address.address;
document.getElementById("myaddress").innerHTML = myHtml;
}
});
}
})
}</script>

<span id="myaddress"></span>

Comment 11 by Raymond Camden posted on 1/8/2012 at 6:23 PM

Slick - thanks for sharing that.