Posts Tagged ‘HTML’

Non–blocking Facebook and Twitter buttons

Friday, November 19th, 2010

On all the posts on this blog (like on most other websites you probably visit) you’ll see buttons to ‘Like’ a post (from Facebook) and to ‘Tweet’ about a post (from Twitter or TweetMeme). These buttons are very popular but if you use the iframe versions of the buttons (which are easy to install) you may have noticed a problem.

twitter facebook tweetmeme logos

If either the Facebook, Twitter, or TweetMeme servers don’t respond quickly enough when your browser requests the page content, your page loading may well block. On this site I’ve seen the Facebook Like button delay the page by 1-3 seconds. The bad part about the type of blocking is that in most browsers the rest of the page doesn’t render whilst the browser is waiting for these 3rd party servers to respond. There’s a more in depth explanation of why this is so on Steve Souders’ High Performance Web Sites blog.

Browsers usually start loading resources in the order that they are specified in the HTML. Below is a screenshot of one of the pages on this site (this one in fact). The red line shows the order of loading of the page. This order is typical for blogs.

rml page load order facebook twitter

If you place the social bookmarking buttons before your content then the problem is particularly noticeable as they can block your whole content from loading. During which time your visitor may decide to go elsewhere.

Is there a solution? Yes there is a well understood solution to this problem. Simply load these externally hosted buttons after your content. Here’s how I did it on this site.

Use a div to reserve space for your buttons

You should reserve the correct amount of space for your buttons. If you don’t you’ll cause the page to be re-rendered once the buttons are inserted.

<div class="socialbuttons" style="width:450px; height:28px; text-align: top;">
</div>

In my case I’m including the compact Facebook like button which is 25 pixels high, and either the TweetMeme button (20 pixels), or the Twitter Tweet button which is also 20 pixels high. More about how I decide on which Twitter button to include later.

For this blog I’m including the buttons at the start of my content, and at the end. If you are using WordPress you could add the div to your content either directly in the template (single.php) or by using a plugin such as PostPost.

I’m including the top div in the template, and the bottom div using PostPost. The reason I’m using PostPost for the bottom div is because this plugin gives itself a priority of ‘1’ which means that it inserts the div before most of my other plugins insert their content.

User JavaScript to add the Facebook/Twitter buttons after the content has loaded

You’ll notice that the div has the id ‘socialbuttons’. This allows us to easily find the element and insert the social bookmarking buttons after the content has loaded.

Here is the WordPress specific JavaScript that I’m using. I add it just before the closing </body> tag. For WordPress this means editing the footer.php template.

<script  type='text/javascript' language='javascript'>
<!--
var permalink='<?php echo urlencode(get_permalink()); ?>';
var socialhtml='<iframe src="http://www.facebook.com/plugins/like.php?href=' + permalink + '&amp;layout=standard&amp;show_faces=false&amp;width=300&amp;height=25&amp;action=like&amp;font=arial&amp;colorscheme=light" scrolling="no" frameborder="0" allowTransparency="true" style="border:none; overflow:hidden; width:300px; height:25px; display:inline;"></iframe>';
<?php if (new_twitter()) { ?>
socialhtml += '<iframe allowtransparency="true" frameborder="0" scrolling="no" src="http://platform.twitter.com/widgets/tweet_button.html?url=' + permalink + '&via=reviewmylifeuk&related=reviewmylifeuk&text=<?php echo the_title(); ?>" style="width: 130px; height: 20px;"></iframe>';
<?php } else { ?>
socialhtml += '<iframe src="http://api.tweetmeme.com/button.js?url=' + permalink + '&style=compact&source=reviewmylifeuk&b=2" height="20" width="90" frameborder="0" scrolling="no" style="border:none; overflow:hidden; display:inline;"></iframe>';
<?php } ?>
var divs=document.getElementsByTagName('div');
var divcount=divs.length;
for (var i=0; i<divcount; ++i) {
	if (divs[i].className=='socialbuttons'){
		divs[i].innerHTML=socialhtml;
	}
}
//-->
</script>

This JavaScript works by find all the div tags with the class ‘socialbuttons’ and then inserting the Facebook and Twitter HTML inside the div tags.

I’ve highlighted in red my Twitter account name. You’ll want to change these values to your own Twitter account name. If you aren’t using WordPress you’ll need to replace the get_permalink() function with something that correctly encodes your current page URL.

You may be wondering what the new_twitter() function is.

PHP to select TweetMeme or Twitter Tweet button

TweetMeme is handing over the Tweet button to Twitter. As of July 2010 the recommended button to use (recommended by both TweetMeme and Twitter) is the official Twitter one. Unfortunately the Twitter Tweet counts will only be correct for articles posted after July 2010. Therefore for the moment I’m using the TweetMeme button for articles posted before July, and the Twitter one for articles posted after.

Here is the WordPress specific PHP that checks if the current post is after July 2010 (you could make it a one-liner if you like).

function new_twitter(){
	$twitter_switchover_date = strtotime("2010-07-01");
	$post_date= get_the_time('U');
	if ($post_date > $twitter_switchover_date) {
		return true;
	} else {
		return false;
	}
}

If they ever remove the TweetMeme button completely it will be very easy with this code to change all the Twitter buttons to be the official Twitter ones.

Including hashtags with the TweetMeme button

The old TweetMeme button had the option of specifying hashtags for the Tweet. You can add this in as well if you want. You’ll need to write a function to get the hastags (e.g. called something like get_hashtags()), and include it in the TweetMeme URL.

You can find code for constructing the TweetMeme hashtags in the TweetMeme plugin. Look in tweetmeme.php for the ‘// append the hashtags’ section.

If you manage to create your get_hashtags() function you can replace the TweetMeme line in the JavaScript with.

socialhtml += '<iframe src="http://api.tweetmeme.com/button.js?url=' + permalink + '&style=compact&source=reviewmylifeuk<?php echo get_hashtags() ?>&b=2" height="20" width="90" frameborder="0" scrolling="no" style="border:none; overflow:hidden; display:inline;"></iframe>';

(again don’t forget to replace my Twitter account name with yours!)

Does it make a difference?

From my experience of using this code it definitely makes a difference. The annoying delays (caused mainly by the Facebook Like button) have gone. The button still sometime takes several seconds to load, but at least it isn’t blocking the rest of the page.

More info on how to customise the buttons

If you want to customise the buttons have a look at the developer documentation for each one.


Adding ‘Related Posts’ to WordPress articles and 404 error pages

Tuesday, July 22nd, 2008

Many blogs have a list of related articles after each of their posts. I wanted something similar for my WordPress blog but found it wasn’t as easy to do as I thought it would be.

At the same time I was interested in capturing any access attempts to non-existent pages (causing a 404 error), and showing a list of suggested links. This is something that is useful to do to turn people who get 404 errors into readers of your blog.

I first looked at the WASABI related post plugin. It did what I wanted with the related entries but it requires you to add a tag to each post where you want the related entries to appear. There is also a version of the plugin which can generate sensible links for any 404 errors. It does this by turning the incorrect URL into a list of terms which are then used to find related posts.

The next plugin that I read about was called ‘Aizattos Related Posts’. This plugin was originally based on WASABI but has evolved since. It inserts related links without needed to add any special tags to the posts. A lot of good feedback was given about this plugin but it seems that the author has removed it from the original download site. Fortunately someone has re-posted this plugin to this site.

I therefore have what I need in two separate plugins. I installed the Aizattos Related Posts plugins and then created a modified version of the WASABI 404 handling code. The 404 handler is in one function ‘related_posts_404’. Below is the modified version of the WASABI code which will work with the Aizattos Related Posts plugin. As well as showing the related links it also shows an extract from the post page. Just put this function in the Aizattos Related Posts plugin PHP file.

related_posts_404()
function related_posts_404($limit=5, $len=50,
	$before_title = '', $after_title = '',
	$before_post = '', $after_post = '',
	$show_pass_post = false, $show_excerpt = true) {
    global $wpdb, $post;
    $before_title   = '<span class="aizatto_related_posts_title" >';
    $after_title    = '</span>';
    $before_excerpt = '<div class="aizatto_related_posts_excerpt">';
    $after_excerpt  = '</div><p></p>';
    $before_related = '<li>';
    $after_related  = '</li>';
    $search_term = $_SERVER['REQUEST_URI'];
    $search = array ('@[/]+@', '@(..*)@', '@[-]+@', '@[_]+@', '@[s]+@', '@archives@','@(?.*)@','/d/');
    $replace = array (' ', '', ' ', ' ', ' ', '', '','');
    $search_term = preg_replace($search, $replace, $search_term);
    $search_term = trim($search_term);
    $terms = $search_term;
    $time_difference = get_settings('gmt_offset');
    $now = gmdate("Y-m-d H:i:s",(time()+($time_difference*3600)));
    // Primary SQL query
    $sql = "SELECT ID, post_title, post_content,"
         . "MATCH (post_name, post_content) "
         . "AGAINST ('$terms') AS score "
         . "FROM $wpdb->posts WHERE "
         . "MATCH (post_name, post_content) "
         . "AGAINST ('$terms') "
		 . "AND post_date <= '$now' "
         . "AND (post_status IN ( 'publish',  'static' ) && ID != '$post->ID') ";
    if ($show_pass_post=='false') { $sql .= "AND post_password ='' "; }
    $sql .= "ORDER BY score DESC LIMIT $limit";
    $results = $wpdb->get_results($sql);
    $output = '';
    if ($results) {
        foreach ($results as $result) {
            $title = stripslashes(apply_filters('the_title', $result->post_title));
            $permalink = get_permalink($result->ID);
            $output .= $before_title
                .'<a href="'. $permalink .'" rel="bookmark" title="Permanent Link: '
		. $title . '">'
		. $title . '</a>'
		. $after_title;
            if ($show_excerpt=='true') {
                $post_content = strip_tags($result->post_content);
                $post_content = stripslashes($post_content);
                $words=split(" ",$post_content);
                $post_strip = join(" ", array_slice($words,0,$len));
                $output .= $before_excerpt . $post_strip . $after_excerpt;
                }
        }
        echo $output;
    } else {
        echo $before_title.'Fuzzy ...'.$after_title;
    }
}

Although no code modifications are needed for the related links in your normal posts, you will have to make a modification to your theme’s 404 page if you want related links for any ‘Not Found’ errors. In blue below is the modification I made to my 404.php for the default theme.

blog/wp-content/themes/default/404.php
<?php get_header(); ?>
	<div id="content" class="narrowcolumn">
		<h2 class="center">Error 404 - Not Found</h2>
		<p>We're sorry but the page you are looking
		for isn't at this location. Were you perhaps
		looking for one of these articles?</p>
		<?php related_posts_404(); ?>
	</div>
<?php get_sidebar(); ?>
<?php get_footer(); ?>


Using a common form mail script for multiple websites

Thursday, June 12th, 2008

I run a number of different websites. Most of them have a contact page which is powered by a form mail script. Until recently each of these websites used an almost identical copy of the same form mail script – I use PHPFormMail but you could adapt this solution for other form mail scripts. Each contact us page has very similar HTML in it. I wanted a way of sharing a common form script and wanted to avoid the duplicated HTML without losing the individual styling of each contact us page.

For this to work for you you’ll need:

  1. All your websites to be on a single host. The code on this page is what I used on my 1and1 hosting account, but the solution should be similar for other web hosts.
  2. To be allowed to use .htaccess files.
  3. Have enough technical knowledge to understand what I’m saying and to customise this for your own site. I’ll give you enough information to implement this, but only if you have enough understanding of knowledge of HTML, PHP and .htaccess files.

On my web server I use one directory for each domain. I map my domain names to directories like this:

http://www.advancedhtml.co.uk    ->   /advancedhtml-web/
https://www.reviewmylife.co.uk    ->   /reviewmylife-web/
http://www.interrail-italy.co.uk ->   /interrail-web/

You’ll note that it is not possible to access the root of my web hosting account ‘/’ from the web.

I’ve added a common directory to store the form mail script and the form HTML. This directory is not accessible from any web address. I’ll explain the contents of the formmail.inc later on.

/common/
/common/formmail.php
/common/formmail.inc

The formmail.php is my usual PHPFormMail script.

I then set up a global variable in a .htaccess file in the root of my web server. This .htaccess file is not accessible to any of my website visitors but it is processed.

The contents of the .htaccess look like the below snippet. You’ll need to replace the /kunden… part with the path of your own common directory.

SetEnv COMMON_PATH /kunden/homepages/25/dxxxxxxx/htdocs/common

If you don’t know what your web server path looks like create a file called ‘test.php’ with the following contents – <?PHP phpinfo(); ?> and then load file from your browser. You can use this test.php to verify that your new environmental variable is present. Below is my formmail.inc

formmail.inc
<center>
<form method="post" action="commonformmail.php">
<table width="80%" cellpadding="0" cellspacing="0">
<tr>
  <td><font face="arial">Name</font></td>
  <td><p><input type="text" name="name"></p></td>
</tr>
<tr>
  <td><font face="arial">Email</font></td>
  <td><p><input type="text" name="email"></p></td>
</tr>
<tr>
  <td><font face="arial">Subject</font></td>
  <td><p><input type="text" name="subject"></p></td>
</tr>
<tr>
  <td><font face="arial">Message</font></td>
  <td><p><textarea name="message" rows="15" cols="45"></textarea></p></td>
</tr>
<tr>
  <td></td>
  <td><p><input type="submit" name="Submit" value="Send"></p></td>
</tr>
</table>
<p>
<input type="hidden" name="redirect" value="thanks.htm"></p>
<input type="hidden" name="recipient" value="commonmail">
<?php
print "<input type="hidden" name="referer" value="" . $_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"] . "">n";
?>
<input type="hidden" name="env_report"
 value="REMOTE_HOST,HTTP_USER_AGENT,REMOTE_ADDR">
</form>
</center>

Look at the PHPFormMail documentation for information about the redirect, recipient and env_report fields. You’ll note that I have added a referer field so that I’ll know which of my websites this form was posted from. The value of the recipient field has to be present in the PHPFormMail $recipient_array. If your contact page is a .html rather than a .php you’ll have to make sure that you can use PHP in HTML files.

In your contact us/email HTML file you can include the form like this:

<?php
include_once($_SERVER['REDIRECT_COMMON_PATH'] . '/formmail.inc');
?>

The final part of the solution is to add a commonformmail.php to each of your individual website directories. It will look like this and just includes the shared form mail script.

<?php
include_once($_SERVER['REDIRECT_COMMON_PATH'] . '/formmail.php');
?>

From now on you can change the behaviour and look of all your website forms from one place.

Hidden field spam trap for PHPFormMail

Friday, May 30th, 2008

If you have a form mail script on your website you may find that you reguarly recieve automated spam to your email account. Even worse it is possible that spammers may use your form mail script to send spam to other people.

One well known method of significantly reducing (or even stopping) spam without having any impact on your website visitor is to add a hidden field to your form. Real human visitors will not see this field and leave it blank. Automated spam scripts will fill it in. You can therefore easily tag or reject any emails that have this hidden field filled in. This method of stopping spam has been talked about on many other blogs – for example on modernblue, and horizonweb.

I’m not going to explain the technique in depth – you can read about it on the above links. I’m just going to show you how to apply this form of spam protection if you are using the PHPFormMail script.

You will need to add an entry to your style sheet to hide the spam trapping field. I use two fields with similar names – one to display a field as normal and one to hide a field. I suggest you use different names to me to make it less likely that spam scripts will work around this trap.

style.css
div#formstyle1 { display: inline; }
div#formstyle2 { display: none; visibility: hidden; }

In blue you can see where I have added the spam trap field next to the usual message field.

contactus.html
<tr>
<td><font face="arial">Message</font></td>
<td>
<p>
<div id="formstyle1">
  <textarea name="message" rows="10" cols="40"></textarea>
</div>
<div id="formstyle2">
  <p>Please leave the following field blank: </p><input type="text" name="spamtrap">
</div>
</p>
</td>
</tr>

There are two things I can do in the PHPFormMail script if spam is detected (i.e. if the spamtrap field is not empty). I can either tag the email with a [spam?] tag, or I can reject it.

I have commented out the ’email rejection’ lines so the below modification will tag the email. If you want to enable the ’email rejection’ then you can simply uncomment the relevant two lines.

PHPFormMail.php
function send_mail()
{
	global $form, $invis_array, $valid_env, $fieldname_lookup, $errors;
	$email_replace_array = "r|n|to:|cc:|bcc:";
	### Anti-spam: start - reject email ###
	#if (($form['spamtrap']) != '')
	#	return true;
	### Anti-spam: end                  ###
	if (!isset($form['subject']))
			$form['subject'] = 'WWW Form Submission';
	if (isset($form['subject_prefix']))
			$form['subject'] = $form['subject_prefix'] . $form['subject'];
	if (!isset($form['email']))
			$form['email'] = 'email@example.com';
	### Anti-spam: start - tag email ###
	if (($form['spamtrap']) !='' )
			$form['subject'] = '[SPAM?]: ' . $form['subject'];
	### Anti-spam: end               ###
	switch ($form['mail_newline']) {
		case 2:		$mail_newline = "r";
				break;
		case 3:		$mail_newline = "rn";

Since applying these changes to my various sites, the script has caught all the formmail spam that I was previously getting.

If you do decide to adopt these changes then make sure you test them carefully – first try testing with the spam trap field visible, before making it invisible. I’d also suggest that you adjust the field and style sheet names to make it harder for spammers to bypass.

Adding spacing round an iframe in WordPress

Wednesday, March 5th, 2008

It was whilst writing a review of the book ‘boo hoo’ that I spotted a problem with embedding iframes in WordPress postings. As I was reviewing a book I wanted to add an Amazon Product link. These product links are in the form of iframes. An example of the HTML is below. I added the align="right" myself as I wanted the text to flow around the iframe.

<iframe src="http://rcm-uk.amazon.co.uk/e/cm?t=advancedhtml-
21&o=2&p=8&l=as1&asins=0099418371&fc1=000000&IS2=1
&lt1=_blank&lc1=0000FF&bc1=000000&bg1=FFFFFF&f=ifr"
style="width:120px;height:240px;" scrolling="no"
marginwidth="0" marginheight="0"
frameborder="0" align="right"></iframe>

You can see from the image that in WordPress (in the default theme anyway) there is no spacing between the left edge of the image and the text. This looks wrong so I wanted to find a solution to this.

Amazon iframe problem

It seems that there are no padding tags that you can add to an iframe unless you use style sheets. I wanted a simple solution that I could just embed in the HTML. The solution that I chose was to put the iframe in a table and set the cellspacing attribute of the table to the required amount padding. Instead of using align in the iframe I am now using it in the table. The HTML and result of this change are shown below.

<table border="0" cellspacing="10" align="right"><tr><td>
<iframe src="http://rcm-uk.amazon.co.uk/e/cm?t=rmlcouk-
21&o=2&p=8&l=as1&asins=0099418371&fc1=000000&IS2=1
&lt1=_blank&lc1=0000FF&bc1=000000&bg1=FFFFFF&f=ifr"
style="width:120px;height:240px;" scrolling="no"
marginwidth="0" marginheight="0"
frameborder="0"></iframe>
</td></tr></table>

Amazon iframe fix

You’ll probably agree that the Amazon product links looks much better with the extra spacing.

Improved KML embedding of Google Maps into web pages

Sunday, December 23rd, 2007

I’ve been further improving the code that I described in my previous in my previous post – ‘Adding KML Google Maps overlays to WordPress posts‘.

I’ve made these changes:

  1. Option to specify a latitude / longitude / zoom for the map. This allows you to have one map and then show lots of different views of it
  2. The code is now implemented as a function rather than as included PHP. This means that the full map can be included in one line of PHP and the code only has to be included once in each page.

As before you can include a whole map which will be automatically centred and zoomed for you. The require_once is only needed once on each page, but no harm will come to you if it is included more than once. Only one argument is needed – the full URL to the KML file. A width / height can be included if you want.

<?php
require_once('../data/071223/mapiframe.php');
iframe("https://www.reviewmylife.co.uk/data/071223/track.kml");
?>

In the require_once you can either include an absolute path or a relative path.


View Larger Map
The new options allow you to specify the latitude, longitude and zoom values. When you specify these values you also have to specify the width / height of the map. The argument list is:

  1. Full URL of KML – note this is the full URL not a relative one
  2. Width of map – in pixels
  3. Height of map – in pixels
  4. Latitude
  5. Longitude
  6. Zoom
<?php
require_once('../data/071223/mapiframe.php');
iframe("https://www.reviewmylife.co.uk/data/071223/track.kml",
	450, 400, "51.515339", "-0.054374", 15);
?>


View Larger Map
To get the latitude / longitude / zoom values view your KML file in Google Maps. Click on ‘Link to this page’ as described in the previous post. Alter the zoom and position of the map so it shows that you want. Then copy the latitude / longitude / zoom values from the HTML box. The latitude / longitude are the values in the ‘ll’ parameter (latitude is first). The zoom is the ‘z’ parameter.

So if we are looking at the following page in Google Maps.

Getting latitude, longitude, and zoom values from Google Maps

The latitude is 51.49966, the longitude is -0.053108 and the zoom is 16.

Here are the three files you’ll need.

MapIframe.php
LoadMap.php
GoogleMapLoader.js

You can see a demonstration of these scripts at www.londonphotoproject.co.uk/blog/. Here I have one KML file for my whole walking route, but I include multiple zoomed-in views of the map so I can describe the route in small sections.

For these scripts to work they’ll need to be interpreted as PHP4 rather than PHP5. If your web host is interpreting PHP files as PHP5 by default (which more and more of them are) simply put these PHP files in a separate directory and add a .htaccess with the following contents to that same directory.

# Treat files in this directory as PHP4
AddType x-mapp-php4 .php


Adding KML Google Maps overlays to WordPress posts

Thursday, December 20th, 2007

Embedding basic KML Maps into your blog post

There is an easy way to include Google Maps KML overlays in your WordPress blog if you are willing to have all the size and style information hardcoded into each post. All you have to do is to go to http://maps.google.co.uk/ type the KML location into the search box and then click on ‘Link to this page’.

Embedding KML into your WordPress blog using Google Maps

You can then add the HTML into your blog post by copy / pasting it from the second text box.

HTML for embedding Google Maps in a WordPress blog post

Google make it easy to change simple settings such as the map size by following the ‘Customise…’ link. Below is what the actual embedded map would look like. Handily the map is automatically zoomed into whatever data is in your KML file – In this example we’re looking at a walking track across London.


View Larger Map

This is great for if you want to add the odd maps to your blog, or if you don’t believe you’ll need to alter the style later on. The problem comes if you want to separate all the style information out of the embedded map iframe.

The problem with the Google Maps HTML generator

Imagine if you had a site with dozens or even hundreds of embedded KML files. One day in the future you decide that you want to change the style and look of all the maps. Maybe you want to change the size, add some extra links under each map, or add new features from the Google Maps API to each map. Below is what the actual HTML code embedding this KML file looks like. As you can see it is pretty ugly and it wouldn’t be fun to edit dozens / hundreds of these to change the way they look.

<iframe width="425" height="350" frameborder="0" scrolling="no" marginheight="0" marginwidth="0" src="http://maps.google.co.uk/maps?f=q&amp;hl=en&amp;geocode=&amp;time=&amp;date=&amp;ttype=&amp;q=http:%2F%2Fwww.reviewmylife.co.uk%2Fdata%2F071220%2Ftrack_east_london.kml&amp;ie=UTF8&amp;ll=51.497414,-0.054315&amp;spn=0.044967,0.044325&amp;om=0&amp;output=embed&amp;s=AARTsJozG9M05ndgSB8zlZU1Qavi7qH_cw"></iframe><br /><small><a href="http://maps.google.co.uk/maps?f=q&amp;hl=en&amp;geocode=&amp;time=&amp;date=&amp;ttype=&amp;q=http:%2F%2Fwww.reviewmylife.co.uk%2Fdata%2F071220%2Ftrack_east_london.kml&amp;ie=UTF8&amp;ll=51.497414,-0.054315&amp;spn=0.044967,0.044325&amp;om=0&amp;source=embed" style="color:#0000FF;text-align:left">View Larger Map</a></small>

Under normal circumstances it would be easy to separate out this code into a different file and pass in the KML file URL as a parameter. The problem is that Google have added a security parameter to the argument list (s=AARTsJozG9M05ndgSB8zlZU1Qavi7qH_cw in this case) which locks in the KML URL. You can edit the style parameters (width / height etc) but you can’t change the URL. If you do you get an error saying “Forbidden Your client does not have permission to get URL…”. Google have done this so they can keep a track of how much load individual sites are putting on their server. Unfortunately it means that if you want to use a new KML you have to use the Google Maps site to generate the HTML.

A solution and another problem for WordPress bloggers

There is a way around this, and that is to use the Google Maps API. This will allow you to programatically include as many KMLs as you want without using Google’s HTML generator. To use the API you have to sign up for a Google Maps API Key. There is one final problem – each key can only be used from one individual web directory. This can be a big problem if you are a WordPress user. Bill from the techrageo blog has already written about this so I won’t repeat what he has said. You can read his blog and look at his solution for yourself.

There are however some problems with his solution.

  1. You would need to create a new HTML file for each Google Map you are embedding.
  2. The width and height of the iframe have to be embedded in each map in each blog post or HTML page that you use it on.
  3. The JavaScript in his solution doesn’t quite do what I want.

Here is my solution which is inspired by his but solves these three issues. Please note that as with Bill’s solution this will require some programming knowledge. You will need to make modifications to my scripts to get them to work on your site.

To embed a KML file with my solution all you have to do is include a small section of PHP in your blog post. To allow me to embed PHP in my blog posts I’ve installed the Exec-PHP plugin. This is what the PHP looks like.

<?php
$mapxml="https://www.reviewmylife.co.uk/mymap.kml";
require('../data/kml/mapiframe.php');
?>

You must set the $mapxml variable which points to your KML file – it has to be the full URL, not a relative one. You then load the mapiframe.php file with the ‘require’ command. Optionally you can set a $width and a $height variable for the width/height in pixels, but this will re-introduce problem number 2. If you don’t set these values then default sizes (which you can change) will be used.

Embedding the KML with this PHP means that your blog posts now don’t contain any formatting infomation for the maps. All the formatting can be controlled from the following common scripts.

This is what your mapiframe.php looks like, it contains the common iframe information. You will probably need to fix the link to the loadmap.php file for your own web server.

<?php
/*
Include a KML on WordPress Blog
See www.reviewmylife.co.uk for details.
*/
if (!isset($mapxml))
	{
	print "ERROR: Missing mapxml";
	exit;
	}
if (!isset($width))
	{
	$width = "450";
	}
if (!isset($height))
	{
	$height = "450";
	}
$mapxml = urlencode($mapxml);
$widthparam="width=$width";
$heightparam="height=$height";
print <<<ENDHTML
<iframe width="$width" height="$height" scrolling="no"
frameborder="0" marginheight="0" marginwidth="0"
src="/data/kml/loadmap.php?mapxml=$mapxml&amp;$widthparam&amp;$heightparam">
If you see this, your browser doesn't support iframes.
Please upgrade to a more recent browser.</iframe><br /><small>
<a href="http://maps.google.co.uk/maps?f=q&amp;hl=en&amp;q=$mapxml&amp;ie=UTF8&amp;om=1&amp;source=embed"
style="color:#0000FF;text-align:left">View Larger Map</a></small>
ENDHTML
?>

Here is the code for loadmap.php. You’ll need to replace the Google Maps API key with your own one.

<?php
/*
Include a KML on WordPress Blog
See www.reviewmylife.co.uk for details.
Remember to replace the Google API key with your
own one or this script won't work!
*/
if (!isset($mapxml))
	{
	print "ERROR: Missing mapxml";
	exit;
	}
if (!isset($width))
	{
	$width = "450";
	}
if (!isset($height))
	{
	$height = "450";
	}
print <<<ENDHTML
<html>
<head>
  <title>Google Map Loader - $mapxml</title>
  <script src="http://maps.google.com/maps?file=api&v=2&key=ABQIAAAA6Y9TsXMv7cdqyP8VLw2boRSTFKCAindh81v9qdSRu-QtalZoMBQj6TDiTZizmDy7aoJTqU6iO3pDOQ" type="text/javascript"></script>
  <script src="googlemaploader.js"></script>
</head>
<body onload="initialize()" onunload="GUnload()">
<div id="map" style="width:$width; height:$height"></div>
<span id="mapxml" name="$mapxml"></span>
<script type="text/javascript">
 function initialize() {
  if (GBrowserIsCompatible()){
   LoadGoogleMap();
   }
  }
</script>
</body>
</html>
ENDHTML
?>

This is the googlemaploader.js file which loads the KML using the Google Maps API. It correctly sets the viewport in the map view and adds a few controls to the map.

// Script to load and position a KML/XML Google Map
// See www.reviewmylife.co.uk for details.
var kml;
function LoadGoogleMap(){
  // Find mapinfo span and get name attribute
  var mapxml = document.getElementById('mapxml').getAttribute('name');
  kml = new GGeoXml(mapxml, PositionMapCallback);
}
function PositionMapCallback(){
  var map = new GMap2(document.getElementById("map"));
  map.addControl(new GSmallMapControl());
  map.addControl(new GMapTypeControl());
  kml.gotoDefaultViewport(map);
  map.addOverlay(kml);
}

This is the final result. Yes it looks very similar to the one generated by the Google Maps HTML generator. But if I ever need to change all my embedded maps it will be really easy for me.


View Larger Map
Here are some download links for the three files you need.

MapIframe.php
LoadMap.php
GoogleMapLoader.js

You’ll need to change the Google API key in loadmap.php. You’ll also need to fix the inter-file references so all the scripts reference each other correctly. All three scripts should be placed in the directory that you created the Google API key for.

Update: Make sure you check out my Improved KML embedding of Google Maps into web pages post for some updates to these scripts.