Sunday, December 03, 2006

Map Your Travels in Blogger Beta

UPDATE: 02-04-2006 - I have redone much of this hack by using the Blogger JSON feeds. You can see the latest version here.

UPDATE: 01-20-2006 - I am working on a new version of this feature that utilizes the Blogger JSON feeds and AJAX (or more properly speaking, I guess, AJAJ). This will reduce the lines of code to a minimum, and hence be simpler to implement. It will also work better and overcome the issue I mention in my 12/22 update below. Check back soon for the new version!

UPDATE: 12-22-2006 - Something screwy is going on with this. I just noticed this week that when initially loading the map page, several all-important links won't display. (The links allowing you to pick a country, then city, region, and/or place associated with that country.) This makes the whole thing non-functional and certainly unimpressive.

YET, oddly enough, if you simply reload the page, it will display correctly. Why would a static webpage display one way on the initial load, and another way when you reload? I don't know if this is caused by a change on Blogger's end, or if this might even be a bug in Firefox 2.0.1 which I recently upgraded to. Any ideas?

Here's how, for some reason, it looks now on initial load:



Here's how it's supposed to look, and how it's been looking all along until recently. Again, if you refresh the page, everything's magically okay:



----------------Original Post----------------


A few weeks ago while surfing around for some Blogger Beta hacks, I came across Hoctro's Place and saw how he had integrated Google Map Search with his blog. Very cool, I thought, and as I was at that time starting a post relating some of my travels in China, the idea soon occurred to me to try to use Google Maps to show various places I've been in the last few years. With satellite maps I can show all sorts of details like where I lived, worked, ate, went to school, got treated for dysentery, went skinny-dipping, etc. Now's the time to mark these places, while my memory is still fresh and I can still wind through various city streets in my mind.

And knowing how the times they are a-changing (especially in China), it will be great 20 years later to be able to revisit these places and say with certainty, "right here, in this parking lot, is where my apartment used to be."

So I pondered this for a while, thinking about how I wanted it to look and function, and trying to get it to look and function that way in Blogger Beta. Right away I must say thanks to Ramani from Hackosphere, from whose hacks I learned how to mix widget loops and JavaScript, and thanks to Mike for his online tutorial on using the Google Maps API. You can see what I finally came up with, after lots of fretting and sweating, by clicking on the "places I've been" link below my profile.

NOTE: this does not work in Internet Explorer (v6.0, sp2). I have used conditional tags to disable the link in IE, since it otherwise results in a DNS error that forces IE to shut down. I have no idea what causes the error, and I'm very tired of trying to figure out how to "trick" IE into displaying what I want, so I have left it as is. The web can't wait for IE. But if anyone can figure out how to resolve this error, I would be much obliged. Here's a link that's not disabled to this section of my blog. Again, if you're using IE, it will force IE to shut down.

The code for this functionality is below. I offer it for anyone who might want to use it, and more importantly, for anyone who can improve it, as I feel it might be a little over-engineered.

In brief, I decided to use a label search result page to display the map, and all the individual posts dealing with various locations. This allows me to use a simple label to tie all of these posts together, and also allows me to display the different locations without having to reload the page. I also use labels, as well as part of the post title, to set up a hierarchy of world, country, region, city, and place posts. Each location, no matter at what level, is a separate post. Thus, with the code in place, I am able to easily manage everything through the Posts dashboard.

In order to work, posts must be composed as follows:

Post Title

At the country level, the title must have the country name, latitude, longitude, zoom level, and H S or M map type (Hybrid, Satellite, or Map), all separated by commas. For instance:
China,35.86166,104.195397,3,H
How does one get the latitude and longitude? The easiest way is to go to Google Maps, find the place you're looking for, and click on "Link to this page." You'll see the page reload, and in the address bar, you'll see part that goes "&ll=" followed by two numbers:


This is the latitude and longitude, and you can copy them directly from there. Incidentally, the zoom level will be just before this, where it says "&z=".

At the region, city, and place level, the title is exactly the same, except that you need to type in the name of a higher level first. For instance:
China,Great Wall,40.355595,116.009375,17,S
China,Wuhan,30.579997,114.269829,12,S
Wuhan,York Bar,30.589035,114.297032,18,S
This associates the post to the higher level. Thus, after I click on China, which is at the country level, I will then see a link for the Great Wall, which is at the place level. Also, I will see a link for Wuhan, which is at the city level. When I click on Wuhan, I will see a link for the York Bar, which is at the place level. As you can see, the different levels can be associated with each other in different ways, so you don't always have to go from country to region to city to place.

Post Body

The post body has no special requirements. However, if you want a marker or markers to appear for a location, you must have the following in your post body:

<span id="markers3317635477131100617" class="markers">39.930011,116.399975,Beijing|31.229999,121.470001,Shanghai</span>

This is what I part of what I have for my country level "China" post. When I click on "China," the map will show China, and there will be markers at the above coordinates. Clicking on a marker will open an info window which says, for instance, "Beijing".

The CSS will make this <span> invisible, but the data inside will be used to display the markers when the location loads. The data consists of the latitude, longitude, and info box description. If there are multiple places to mark, they should be separated by a pipe | . Also, the id for this span must be the word "markers" plus the post ID. I get this by saving the post first as a draft, then opening it again, and copying it from the address bar:


In addition, you can have some optional links in your post body which, when clicked, will move to a nearby location and place a marker there. This is so you don't have to clutter the map with too many markers (e.g., my apartment, the coffee shop next door, the vendor across the street, the restaurant at the corner), but can still point out these places for anyone who wants to see them. Here's a link I had for the post on my school in China:

<a href="javascript:void(0);" onclick="javascript:showaround('30.593126','114.291678','Trust Mart');">Behind</a> the school is the Trust-Mart supermarket where I did most of my shopping my first year in China.

When I click the link, it will pan to the new location, and place a marker there. These locations need to be fairly close by to smoothly pan; otherwise, the map will simply reload. Again, you need the latitude, longitude, and the info window description.

Post Labels

Each post should have two labels. Every post should have the label, atravelmap. Then, each post should have another label depending on what level it's on: countrymap, regionmap, citymap, or placemap. The atravelmap label page is the main page used to display the map and posts. The other labels are there to help with sorting the posts into the right hierarchy.

The CSS will prevent these labels from appearing in the labels widget.

Post Date

Before you publish the post, you need to backdate it. Usually I save the post as a draft first (to get the post ID), then change the date and publish it. With the code I have, the posts should be backdated to 1985 (I just arbitrarily chose this year). The code will prevent this year from appearing in the Blog Archive widget.

Also, the code will prevent any of the posts from appearing via the "Older" link. Note: if you don't have very many posts currently, you may need to modify your Blog Settings (Formatting) to only display a certain number of posts on your home page. This will prevent the travel posts, with their funky titles, from appearing on your homepage.

Blogger will display the post titles from later to earlier, so you will need to play with the months and days a bit to get them to show up alphabetically. For instance, I have my posts on China dated to October 1985, Greece dated to August 1985, and Hungary dated to June 1985. This makes them display in alphabetical order: China, Greece, and Hungary.

I also disable comments for my travel posts, and the code I have does not allow for comments to even be displayed for these posts, but that could be fairly easily changed.

World Post

You might have noticed, there was one level that I haven't talked about yet: the world level. This level consists of a single post, and this post is what is displayed when initially going to the map page. It controls the markers that are initially shown at the world level, and allows anyone to go back up to the world level without having to reload the page.

The world post title is similar to the country-level post. Here's what I use on my blog:
world,35.704857,-6.926808,1,S
The latitude and longitude can be whatever center of the world you choose.

The world post label is worldmap (and, of course, atravelmap).

The date doesn't really matter, as long as it's in 1985.

To show markers at the world level, you'll put a hidden span in your post body, just as I described above for other posts:

<span id="markers1100387009350392250" class="markers">35.86166,104.195397,China|38.278603,23.80708,Greece|47.162494,19.503304,Hungary|23.200961,-102.700195,Mexico</span>


And that's it. It does seem like a lot, as there's a fair amount of data to sift through, but once you do it some it's easy to get used to.

Here's the code:

1. Go here to get a Google Maps API key for your blog. There's no limit on the number of URL's you can register for a key, so I'd highly recommend getting one for a test blog first.

2. Copy the following somewhere between the tags: <b:skin><![CDATA[/* and ]]></b:skin> :

.markers {
display:none;}

a.countrymap:link, a.regionmap:link, a.citymap:link {
text-decoration:none; color:#3a80b4;}

a.regionmap, a.citymap, li.placemap {
text-decoration:none; display:none;}

.travelsection {
font-weight:bold;}

/* This prevents the map posts from
showing up in the label widget */
li#atravelmap, li#worldmap, li#countrymap,
li#regionmap, li#citymap, li#placemap {
display:none;}

#placelist li {
list-style-type: disc; text-align: left;}

/* You will need to modify these margins to
get them to display right in your blog.
This is what I have: */
#placelist {
margin-left:13px;}

#countrydiv, #regiondiv, #citydiv {
margin-left: 5px;}


3. Next there are a series of JavaScript functions you'll need to copy between the tags: ]]></b:skin> and </head> . This is where I might have over-engineered some stuff. If any JavaScript experts see ways to simplify, let me know.

<script src="http://maps.google.com/maps?file=api&v=2&key=YOUR_KEY_HERE" type="text/javascript">
</script>


<script type="text/javascript">
// Thanks to Mike at http://www.econym.demon.co.uk/ for his tutorial, which included this bit:
function createMarker(point,html) {
var marker = new GMarker(point);
GEvent.addListener(marker, "click", function() {
marker.openInfoWindowHtml(html);
});
return marker;
}
</script>

<script type='text/javascript'>
// Thanks to Dustin Diaz at http://www.dustindiaz.com/ for this great JavaScript function
function getElementsByClass(searchClass,node,tag) {
var classElements = new Array();
if ( node == null )
node = document;
if ( tag == null )
tag = '*';
var els = node.getElementsByTagName(tag);
var elsLen = els.length;
var pattern = new RegExp("(^|\\s)"+searchClass+"(\\s|$)");
for (i = 0, j = 0; i < elsLen; i++) {
if ( pattern.test(els[i].className) ) {
classElements[j] = els[i];
j++;
}
}
return classElements;
}
</script>

<script type='text/javascript'>
// This function displays the appropriate post body, and makes all others disappear
function showtravelpost(a) {
var e=getElementsByClass('travelpost',document,'div');
for(var i=0;i < e.length;i++){
e[i].style.display="none";
}
document.getElementById(a).style.display="block";
}
</script>


<script type='text/javascript'>
// This function displays the next links in the hierarchy,
// makes links belonging to another hierarchy disappear,
// and permanently highlights and unhighlights the appropriate level(s).
var count = 0;
function shownext (a,b,c) {
var allplace=getElementsByClass('placemap');
for(var i=0;i < allplace.length;i++){
allplace[i].style.display="none";
}
var allcity=getElementsByClass('citymap');
for(var i=0;i < allcity.length;i++){
allcity[i].style.background="#efefef";
allcity[i].style.color="#387fb5";
}
if (b == "regionmap" || b == "countrymap") {
var allcity=getElementsByClass('citymap');
for(var i=0;i < allcity.length;i++){
allcity[i].style.display="none";
}
var allregion=getElementsByClass('regionmap');
for(var i=0;i < allregion.length;i++){
allregion[i].style.background="#efefef";
allregion[i].style.color="#387fb5";
}
}
if (b == "countrymap") {
var allregion=getElementsByClass('regionmap');
for(var i=0;i < allregion.length;i++){
allregion[i].style.display="none";
}
var allcountry=getElementsByClass('countrymap');
for(var i=0;i < allcountry.length;i++){
allcountry[i].style.background="#efefef";
allcountry[i].style.color="#387fb5";
}
}
document.getElementById(c).style.backgroundColor="#c0c0c0";
document.getElementById(c).style.color="#000000";
var e=getElementsByClass(a);
for(var i=0;i < e.length;i++){
e[i].style.display="inline";
}
var f=getElementsByClass('placemap');
for (var i=0;i < f.length;i++){
if (f[i].style.display!="none") {
f[i].style.display="list-item"
}
}
count++;
}
</script>

<script type = "text/javascript">
// This function is for the "world" link to get you back where you started.
// Could have been combined with the above, but I was too lazy at that point.
function showworld() {
var allplace=getElementsByClass('placemap');
for(var i=0;i < allplace.length;i++){
allplace[i].style.display="none";
}
var allcity=getElementsByClass('citymap');
for(var i=0;i < allcity.length;i++){
allcity[i].style.display="none";
}
var allregion=getElementsByClass('regionmap');
for(var i=0;i < allregion.length;i++){
allregion[i].style.display="none";
}
var allcountry=getElementsByClass('countrymap');
for(var i=0;i < allcountry.length;i++){
allcountry[i].style.background="#efefef";
allcountry[i].style.color="#387fb5";
}
}
</script>

<script type="text/javascript">
// This function controls mouseover highlighting. The count
// variable here comes from the shownext() function above.
function highlightmap (a) {
if (document.getElementById(a).style.backgroundColor=="rgb(192, 192, 192)") {
count++;
}
else {
document.getElementById(a).style.backgroundColor="#c0c0c0";
document.getElementById(a).style.color="#000000";
count=0;
}
}

function unhighlightmap (a) {
if (count == 0) {
document.getElementById(a).style.backgroundColor="#efefef";
document.getElementById(a).style.color="#387fb5";
}
}
</script>

<script type="text/javascript">
// This function allows you to enter a single letter in the post title
// to determine what map type you want.
function getType (a) {
var typeparameter ="";
var maptype = a;
if (maptype == "H") {
typeparameter = "G_HYBRID_MAP"
}
else if (maptype == "S") {
typeparameter = "G_SATELLITE_MAP"
}
else if (maptype == "M") {
typeparameter = "G_NORMAL_MAP"
}
return typeparameter;
}
</script>

<script type='text/javascript'>
// This function shows a set of markers for any given level.
function showmarkers (a) {
if (document.getElementById(a)){
var spandata = document.getElementById(a).innerHTML;
var setmarker = spandata.split("|");
var markernum = setmarker.length;
for (i = 0; i < markernum; i++) {
var onemarker = setmarker[i].split(",");
var qdescription = onemarker[2]
var point = new GLatLng(onemarker[0],onemarker[1]);
var marker = createMarker(point,qdescription);
map.addOverlay(marker);
}
}
}
</script>

<script type='text/javascript'>
// This function is for if you want to show a few places in a small area
// (like "the cool coffeeshop next to the hotel that I went to every morning").
// Puts a marker in, and moves smoothly (most of the time) to that marker.
// Needs some improvement.
function delay(a,b) {
map.panTo(new GLatLng(a,b));
}

function showaround (a,b,c) {
var point = new GLatLng (a,b);
var qdescription = c;
var marker = createMarker (point, qdescription);
map.addOverlay(marker);
var currentzoom = map.getZoom();
if (currentzoom < 18) {
map.panTo(new GLatLng(a,b));
}
else {
var currentcenter = map.getCenter();
var midlat = (currentcenter.lat() - ((currentcenter.lat() - a)/2));
var midlng = (currentcenter.lng() - ((currentcenter.lng() - b)/2));
map.panTo(new GLatLng(midlat,midlng));
setTimeout("delay(" +a+ "," +b+ ")",600);
}
}
</script>


4. Copy the following widget just above this widget:

<b:widget id='Blog1' locked='false' title='Blog Posts' type='Blog'>

Be sure to check your template for any other HTML widgets first. If you already have a widget with an id of HTML1, change the id here to HTML2 or 3 or whatever. This is the widget which will contain the map.

<b:widget id='HTML1' locked='false' title='Google Map' type='HTML'>
<b:includable id='main'>
<b:if cond='data:blog.url == "http://your-blog-name.blogspot.com/search/label/atravelmap?max-results=200"'>
<div class='widget-content'>
<data:content/>
</div>
<b:include name='quickedit'/>
</b:if>
</b:includable>
</b:widget>

Note that here and below you might need to add "?max-results=" to the label page URL, as by default Blogger will only display 20 or so on one page. I set the links here with max-results of 200.

5. Copy the following just after these tags:

<b:includable id='main' var='top'>
<!-- posts -->
<div id='blog-posts'>


<b:if cond='data:blog.url == "http://your-blog-name.blogspot.com/search/label/atravelmap?max-results=200"'>
<script type="text/javascript">
var worlddata="";
var worldpostbody="";
var worldmarkerset="";
var countrydata="";
var regiondata="";
var citydata="";
var placedata="";
<b:loop values='data:posts' var='post'>
<b:loop values='data:post.labels' var='label'>
<b:if cond='data:label.isLast == "true"'>
<b:if cond='data:label.name == "worldmap"'>
var title = "<data:post.title/>";
splittitle = title.split(",");
var postbody = "\"travelpost<data:post.id/>\"";
worldpostbody = "travelpost<data:post.id/>";
var markerset = "\"markers<data:post.id/>\"";
worldmarkerset = "markers<data:post.id/>";
t = getType(splittitle[4]);
worlddata = worlddata + "<a class='worldmap' href='javascript:void(0);' onclick='javascript:showworld(); showtravelpost(" +postbody+ "); map.clearOverlays(); map.setCenter(new GLatLng(" +splittitle[1]+"," +splittitle[2]+ ")," +splittitle[3]+ "," +t+ "); showmarkers(" +markerset+ ");'>"+splittitle[0]+"</a>";
<b:else />
<b:if cond='data:label.name == "countrymap"'>
var title = "<data:post.title/>";
var splittitle = title.split(",");
var qsplittitle = "\"" + splittitle[0] + "\""
var label = "\"<data:label.name/>\""
var postbody = "\"travelpost<data:post.id/>\"";
var markerset = "\"markers<data:post.id/>\"";
var travellink = "link<data:post.id/>";
var qtravellink = "\"link<data:post.id/>\"";
var t = getType(splittitle[4]);
countrydata = countrydata + " <a class='countrymap' id='" +travellink+ "' href='javascript:void(0);' onMouseOver = 'javascript:highlightmap(" +qtravellink+ ")' onMouseOut='javascript:unhighlightmap(" +qtravellink+ ")' onclick='javascript:shownext(" +qsplittitle+ "," +label+ "," +qtravellink+ "); showtravelpost(" +postbody+ "); map.clearOverlays(); map.setCenter(new GLatLng(" +splittitle[1]+"," +splittitle[2]+ ")," +splittitle[3]+ "," +t+ "); showmarkers(" +markerset+ ");'>"+splittitle[0]+"</a> ";
<b:else />
<b:if cond='data:label.name == "regionmap"'>
var title = "<data:post.title/>";
var splittitle = title.split(",");
var qsplittitle = "\"" + splittitle[1] + "\""
var label = "\"<data:label.name/>\""
var postbody = "\"travelpost<data:post.id/>\"";
var markerset = "\"markers<data:post.id/>\"";
var travellink = "link<data:post.id/>";
var qtravellink = "\"link<data:post.id/>\"";
var t = getType(splittitle[5]);
regiondata = regiondata + " <a class='" +splittitle[0]+ " regionmap' id='" +travellink+ "' href='javascript:void(0);' onMouseOver = 'javascript:highlightmap(" +qtravellink+ ")' onMouseOut='javascript:unhighlightmap(" +qtravellink+ ")' onclick='javascript:shownext(" +qsplittitle+ "," +label+ "," +qtravellink+ "); showtravelpost(" +postbody+ "); map.clearOverlays(); map.setCenter(new GLatLng(" +splittitle[2]+"," +splittitle[3]+ ")," +splittitle[4]+ "," +t+ "); showmarkers(" +markerset+ ");'>"+splittitle[1]+"</a> ";
<b:else />
<b:if cond='data:label.name == "citymap"'>
var title = "<data:post.title/>";
var splittitle = title.split(",");
var qsplittitle = "\"" + splittitle[1] + "\""
var label = "\"<data:label.name/>\""
var postbody = "\"travelpost<data:post.id/>\"";
var markerset = "\"markers<data:post.id/>\"";
var travellink = "link<data:post.id/>";
var qtravellink = "\"link<data:post.id/>\"";
var t = getType(splittitle[5]);
citydata = citydata + " <a class='" +splittitle[0]+ " citymap' id='" +travellink+ "' href='javascript:void(0);' onMouseOver = 'javascript:highlightmap(" +qtravellink+ ")' onMouseOut='javascript:unhighlightmap(" +qtravellink+ ")' onclick='javascript:shownext(" +qsplittitle+ "," +label+ "," +qtravellink+ "); showtravelpost(" +postbody+ "); map.clearOverlays(); map.setCenter(new GLatLng(" +splittitle[2]+"," +splittitle[3]+ ")," +splittitle[4]+ "," +t+ "); showmarkers(" +markerset+ ");'>"+splittitle[1]+"</a> ";
<b:else />
<b:if cond='data:label.name == "placemap"'>
var title = "<data:post.title/>";
var splittitle = title.split(",");
var qsplittitle = "\"" + splittitle[1] + "\""
var postbody = "\"travelpost<data:post.id/>\"";
var markerset = "\"markers<data:post.id/>\"";
var t = getType(splittitle[5]);
placedata = placedata + "<li class='" +splittitle[0]+ " placemap'><a href='javascript:void(0);' onclick='javascript:showtravelpost(" +postbody+ "); map.clearOverlays(); map.setCenter(new GLatLng(" +splittitle[2]+"," +splittitle[3]+ ")," +splittitle[4]+ "," +t+ "); showmarkers(" +markerset+ ");'>"+splittitle[1]+"</a></li>";
</b:if>
</b:if>
</b:if>
</b:if>
</b:if>
</b:if>
</b:loop>
</b:loop>
</script>

<hr />
<b:loop values='data:posts' var='post'>
<div expr:id='"travelpost" + data:post.id' class='travelpost' style='display:none;'>
<data:post.body/>
<hr />
</div>
</b:loop>
<b:else />
<b:loop values='data:posts' var='post'>
<b:if cond='data:post.dateHeader'>
<h2 class='date-header'><data:post.dateHeader/></h2>
</b:if>
<b:include data='post' name='post'/>
<b:if cond='data:blog.pageType == "item"'>
<b:if cond='data:post.allowComments'>
<b:include data='post' name='comments'/>
</b:if>
</b:if>
</b:loop>
</b:if>


5. Look for these two items in your template:

<!-- navigation -->
<b:include name='nextprev'/>
<!-- feed links -->
<b:include name='feedLinks'/>

Before it, enter this:

<b:if cond='data:blog.url != "http://your-blog-name.blogspot.com/search/label/atravelmap?max-results=200"'>

After it, enter this:

</b:if>

This will prevent the Newer, Older, and Home links from appearing on your map page.

6. Find this includable:

<b:includable id='nextprev'>

Then look for the anchor <a> with the following href:

expr:href='data:olderPageUrl'

Change the href as follows:

expr:href='data:olderPageUrl + "&updated-min=2005-08-31T00%3A00%3A00-00%3A00"'

This prevents your travel posts from appearing when anyone clicks on the Older link in your blog. You may need choose an earlier year. I started my blog just a couple of months ago, so I obviously don't have any posts older than 2005. Note: some months didn't work here. I seem to recall that June or July didn't work, but August did.

7. There were several widgets I didn't want displaying on my map page, so I added the following after the main includable (<b:includable id='main'>) for each widget I didn't want to display:

<b:if cond='data:blog.url != "http://your-blog-name.blogspot.com/search/label/atravelmap?max-results=200"'>

Just before the end of the includable (</b:includable>), you of course need </b:if> .

8. I use the hierarchy-type archive, and the following prevents my travel map posts from appearing in the archive. (I'm not sure how to prevent them from appearing for the other archive types.)

Just after these lines:

<b:includable id='interval' var='intervalData'>
<b:loop values='data:intervalData' var='i'>

Copy this:

<b:if cond='data:i.name != "1985"'> <!--you'll make this whatever year you backdate your posts to-->

Then just after the </ul> tag, you'll add the closing if tag </b:if> .

9. Add the following to your sidebar, below this:

<b:section class='sidebar' id='sidebar' preferred='yes'>

This widget will contain the post titles, displayed in the proper hierarchy. These post titles are what you click on to display the location on the map, and display the corresponding post body. Again, be sure to check your other HTML widgets to get the appropriate id.

<b:widget id='HTML2' locked='false' title='Places I've Been' type='HTML'>
<b:includable id='main'>
<b:if cond='data:blog.url == "http://your-blog-name.blogspot.com/search/label/atravelmap?max-results=200"'>
<!-- only display title if it's non-empty -->
<b:if cond='data:title != ""'>
<h2 class='title'><data:title/></h2>
</b:if>
<div class='widget-content'>
<data:content/>
</div>
<b:include name='quickedit'/>
</b:if>
</b:includable>
</b:widget>


10. Add the following widget near the very end of your template, just before the final </b:section> tag.

<b:widget id='HTML3' locked='false' title='Map Script' type='HTML'>
<b:includable id='main'>
<b:if cond='data:blog.url == "http://your-blog-name.blogspot.com/search/label/atravelmap?max-results=200"'>
<div class='widget-content'>
<data:content/>
</div>
<b:include name='quickedit'/>
</b:if>
</b:includable>
</b:widget>


11. This is the final change to the actual template itself. Add the following to the sidebar to create a link to your travel map page. I put mine just below my profile widget:

<b:widget id='HTML4' locked='false' title='Travel Link' type='HTML'>
<b:includable id='main'>
<b:if cond='data:blog.url != "http://your-blog-name.blogspot.com/search/label/atravelmap?max-results=200"'>
<div class='widget-content'>
<data:content/>
</div>
<b:include name='quickedit'/>
</b:if>
</b:includable>
</b:widget>


12. Now, after you save your new template, go to the Layout view. (Note: you will get a pop-up every time you view the Layout stating that the API is registered to another URL. This is because the template is being loaded to render the Page Layout section, and the URL there is "http://beta.blogger.com.....")

Find the Google Map widget, click Edit, and add the following to it:

<div id="map" style="width: 100%; height: 400px"></div>

<noscript>JavaScript must be enabled for Google Maps. JavaScript is either disabled or not supported by your browser.
</noscript>

<script type="text/javascript">
if (GBrowserIsCompatible()) {
// Display the map, with some controls and set the initial location
var map = new GMap2(document.getElementById("map"));
map.addControl(new GLargeMapControl());
map.addControl(new GMapTypeControl());
map.setCenter(new GLatLng(35.704857,-6.926808),1,G_SATELLITE_MAP);
map.enableContinuousZoom();
}
else {
alert("The Google Maps API is not compatible with this browser");
}
</script>

The coordinates above is what I chose to be the center of the map of the world when the map page first loads. I chose zoom level 1 (the highest), and a satellite map type.

13. Find the Travel Link widget, click Edit, and add the following to it:

<!--[if IE]>
<script type="text/javascript">
function iealert() {
alert("Internet Explorer does not support this function. Get the better browser. Get Firefox at http://www.mozilla.com");
}
</script>
<p>
<a href="javascript:void(0);" onclick="javascript:iealert();">places I've been</a>
</p>
<![endif]-->

<![if !ie]>
<p>
<a href="http://your-blog-here.blogspot.com/search/label/atravelmap?max-results=200">places I've been</a>
</p>
<![endif]></![endif]></![if>

Since this doesn't work in Internet Explorer, this will prevent people using IE from clicking on this link and then having to shut down their browser.

14. Find the Places I've Been widget, and add the following to it. You can obviously customize how you want it to look, but this is what I did:

<table width="100%">
<tr>
<td id="worldtd">
</td>
<td style="text-align:right;">
<a href="http://your-blog-name.blogspot.com/">back home</a>
</td>
</tr>
</table>
<p>
<ul>
<li><span class="travelsection">country:</span>
<div id="countrydiv">
</div>
</li>
<li><span class="travelsection">region:</span>
<div id="regiondiv">
</div>
</li>
<li><span class="travelsection">city:</span>
<div id="citydiv">
</div>
</li>
<li><span class="travelsection">place:</span>
<div id="placediv">
<ul id="placelist">
</ul>
</div>
</li>
</ul>
</p>


15. Finally find the widget named Map Script. Click Edit, and add the following:

<script type="text/javascript">
obj = document.getElementById('worldtd');
obj.innerHTML = worlddata;
obj = document.getElementById('countrydiv');
obj.innerHTML = countrydata;
obj = document.getElementById('regiondiv');
obj.innerHTML = regiondata;
obj = document.getElementById('citydiv');
obj.innerHTML = citydata;
obj = document.getElementById('placelist');
obj.innerHTML = placedata;
showtravelpost(worldpostbody);
showmarkers(worldmarkerset);
</script>
A Blogger Beta hack that integrates Google Maps with your blog, and allows you to show the locations of your travels.