Category Archives: APIs

Migrate Google Maps from V2 to V3

Google maps v2 has been deprecated since May 19, 2010 and will stop working on May 19, 2013, so here is a little guide on how to migrate.

On V3 we don’t need an API key, but it’s useful to keep track of your API calls (25,000 free), so to get the API key, log into https://code.google.com/apis/console/, click on services and activate google maps v3, once is done click on API access on the left, and go to Simple API at the very bottom, then click on edit allow referers, and set up like *.mysite.com/* that will allow all your subdomains and folders on your site.

Now that you have your API key, is time to replace the old URL, by the new one:

  1.  
  2. <!– V2 –>
  3.  
  4. <script src="http://maps.google.com/maps?file=api&amp;v=2&amp;key=$yourKey" ></script>
  5.  
  6. <!– V3 –>
  7.  
  8. <script src="https://maps.googleapis.com/maps/api/js?key=$youKeu&v=3&sensor=true" type="text/javascript" ></script>
  9.  
  10. <!– "sensor" is required an indicates if a device (like GPS) is used to determine the user’s location –>
  11.  

First get rid of the old unload function, is not needed anymore.

  1.  
  2. /* V2 */
  3. window.onunload=function(){
  4.         GUnload();
  5. }
  6.  

Also get rid of old code used to load Vector Markup Language(VML) just needed for IE, VML has been deprecated on IE9 in favor Scalable Vector Graphic (SVG)

  1.  
  2. <!DOCTYPE html>
  3. <html lang="en" xmlns:v="urn:schemas-microsoft-com:vml>
  4. <head>
  5.         <style type="text/css">
  6.         v\:* {
  7.         behavior:url(#default#VML);
  8.         }
  9.         </style>

Now lets load the map itself.

  • First take out GBrowserIsCompatible is not supported anymore.
  • Replace GMmap2 by google.maps.Map.
  • GLatLng has been replaced by google.maps.LatLng.
  • Now take out addControl, setMapType, now all of these are passed as an object when map is created
  • For V2 we use these map types G_NORMAL_MAP,G_SATELLITE_MAP,G_HYBRID_MAP on V3 they have been replace by google.maps.MapTypeId.ROADMAP, google.maps.MapTypeId.SATELLITE, google.maps.MapTypeId.HYBRID ,google.maps.MapTypeId.TERRAIN
  1.  
  2. /* V2 */
  3. if( GBrowserIsCompatible() ) {
  4.         map = new GMap2( $( ‘map’ ) );
  5.         map.addControl(new GMapTypeControl());
  6.         map.addControl(new GOverviewMapControl());
  7.         map.addControl(new GScaleControl());
  8.         map.addControl(new GLargeMapControl());
  9.         map.setCenter( new GLatLng( myLatitude, myLongitude ), 9 /*zoomLevel*/ );
  10.         map.setMapType( G_NORMAL_MAP );
  11.         //map.setMapType( G_SATELLITE_MAP );
  12.         //map.setMapType( G_HYBRID_MAP );
  13. }
  14.  
  15. /* V3 */
  16.  
  17. var mapOptions = {
  18.         zoom: 9 ),
  19.         center: new google.maps.LatLng(myLatitude, myLongitude),
  20.         scaleControl: true,
  21.         overviewMapControl: true,
  22.         overviewMapControlOptions:{opened:true},
  23.         mapTypeId: google.maps.MapTypeId.ROADMAP
  24. };
  25. map = new google.maps.Map($( ‘map’ ), mapOptions);
  26.  

In V3 creating custom icons is a lot easier, instead of creating a special icon object now we can just pass image as url.

  1.  
  2. /* v2 */
  3.  
  4. myIcon = new GIcon();
  5. myIcon.image = "http://labs.google.com/ridefinder/images/mm_20_red.png";
  6. myIcon.shadow = "http://labs.google.com/ridefinder/images/mm_20_shadow.png";
  7. myIcon.iconSize = new GSize(12, 20);
  8. myIcon.shadowSize = new GSize(22, 20);
  9. myIcon.iconAnchor = new GPoint(6, 20);
  10. myIcon.infoWindowAnchor = new GPoint(5, 1);
  11. var point = new GLatLng( myLatitude, myLongitude );
  12. myMarker = new GMarker( point, myIcon );
  13.  
  14. /* v3 */
  15.  
  16. var properties = {
  17.         position: new google.maps.LatLng(myLatitude, myLongitude),
  18.         map: map,
  19.         title:‘Testing Icon’,
  20.         icon:‘icon.jpg’,
  21.         shadow:‘shadow.jpg’
  22. };
  23. var marker = new google.maps.Marker(properties);
  24.  
  25. /* icon and shadow can be just a string containg  the image file url, for must complex icons just pass and object with all the properties
  26.   var image = {
  27.     url: ‘images/icon.png’,
  28.     size: new google.maps.Size(20, 32),
  29.     origin: new google.maps.Point(0,0),
  30.     anchor: new google.maps.Point(0, 32)
  31.   };
  32. more info: https://developers.google.com/maps/documentation/javascript/overlays?hl=en#ComplexIcons
  33. */
  34.  
  35.  

clearOverlays has been removed from v3, so if you want remove all your markers from your map, now you have to manually keep track your markers an remove them.

  1.  
  2. /* v2 */
  3. map.clearOverlays();
  4.  
  5. /* v3 */
  6.  
  7. var overlays =  []; // Global array to store marker
  8.  
  9. overlays[overlays.length] = new google.maps.Marker(properties); // store a reference to the marker each time you create one
  10.  
  11. // delete all the markers on the array
  12. function clearOverlays() {
  13.         while(overlays[0]){
  14.                 var overlay = overlays.pop();
  15.                 overlay.setMap(null);
  16.                 overlay = null;
  17.         }
  18. }
  19.  

To create overlay on Google maps V3 now we have to use google.maps.Polyline inseatd of GPolyline.

  1.  
  2. /* V2 */
  3.  
  4. var points = [];
  5. points.push( new GLatLng( latitude1, longitude1 ) );
  6. points.push( new GLatLng( latitude2, longitude2 ) );
  7. points.push( new GLatLng( latitude3, longitude3 ) );
  8. map.addOverlay( new GPolyline( points ) );
  9.  
  10.  
  11. /* V3 */
  12.  
  13. var points = [];
  14. points.push( new google.maps.LatLng( latitude1, longitude1 ) );
  15. points.push( new google.maps.LatLng( latitude2, longitude2 ) );
  16. points.push( new google.maps.LatLng( latitude3, longitude3 ) );
  17. var area = new google.maps.Polyline({path: points, strokeColor: "#FF0000",strokeOpacity: 1.0,strokeWeight: 2});
  18. area.setMap(map);
  19.  
  20.  

On google maps v3 is a lot easier to create custom controls, now we only create a div element an insert it on Google maps.

  1.  
  2. /* V2 */
  3.  
  4. /* we used to create the custom control like */
  5.  
  6. SaveMapsStatus.prototype = new GControl();
  7.        
  8. SaveMapsStatus.prototype.initialize = function(map) {
  9.         var container = document.createElement("div");
  10.         container.id = ‘myId’;
  11.         container.innerHTML = ‘<a href="save.php" ><img src="icon_save.gif" /></a>’;
  12.         map.getContainer().appendChild(container);
  13.         return container;
  14. }
  15. SaveMapsStatus.prototype.getDefaultPosition = function() {
  16.         return new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(80, 7));
  17. }
  18.  
  19. map.addControl(new SaveMapsStatus()); /* we used to add to the map, after it was created */
  20.  
  21. /* v3 */
  22. var container = document.createElement("div"); /* To change look, just add some style like container.style.border=” */
  23. container.id = ‘myId’;
  24. container.innerHTML = ‘<a href="save.php" ><img src="icon_save.gif" /></a>’; /* Custom HTML code */
  25. map.controls[google.maps.ControlPosition.TOP_LEFT].push(container);
  26.  

Prototype Compressed

I am a prototype user, but i want to save some bandwidth using a compressed version, so i start looking for it and i found a compressed version called
protopack it includes different versions, just spaces removed ( no eval required ), encrypted(eval required) and gziped version for both. i prefere the just spaces removed version since it dosen’t require use of eval.

Another good option is to use the Google AJAX Libraries API that serves a compressed version of prototype that will be cached by a year and sent with compression headers , you can include it using the full url or the Googles’s API

  1.  
  2. <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/prototype/1.6.0.2/prototype.js"></script>
  3.  
  4. OR
  5.  
  6. <script type="text/javascript" src="http://www.google.com/jsapi"></script>
  7. <script type="text/javascript">
  8. google.load("prototype", "1.6.0.2");
  9. </script>
  10.  
  11.  

You can find compressed versions of scriptaculous, jQuery, MooTools, dojo as well.
The bad thing is there are no https support so it wont work for secure sites.

Show videos on your site using PERL and Youtube API

This tutorial uses an old Youtube API, after google acquired Youtube a new API was released

In this brief tutorial i will show you how to show videos from youtube on you web page using PERL and Youtube API, the idea of the script is that it will show by default the favorites videos of some users, and you will be able to navigate to the tags you specify.

For this script we will use some libraries from the CPAN:

  • CGI we will use to get the data send by GET
  • Template toolkit This is an excellent template library
  • XML:DOM this library will help us to parse the XML file that is returned by youtube
  • LWP::UserAgent This is needed by XML:DOM to parse the files in remote locations
  • Unicode::String We will use this to convert data to UTF8

Click here to see this script in action.

Download the code

index.pl this is the perl script.

  1. #!/usr/bin/perl
  2.  
  3. use CGI;
  4. use Template;
  5. use XML::DOM;
  6. use LWP::UserAgent;
  7. use POSIX qw(strftime);
  8. use Unicode::String;
  9.  
  10. # you have to sign up to get a developer id
  11. my $devId = ‘developerid’;
  12. # we will show the favorites videos of this user as front page
  13. my $userFavorites = ‘someuser’;
  14. # this is an array of the tags we will allow to navigate throw
  15. my %tags = (
  16.         ‘tlaxcala’=>‘Tlaxcala’,
  17.         ‘huamantla’=>‘Huamantla’,
  18.         ‘huamantlada’=>‘Huamantlada’,
  19.         ‘feria huamantla’=>‘Feria Huamantla’,
  20.         ‘cacaxtla’=>‘Cacaxtla’,
  21.         ‘apizaco’=>‘Apizaco’,
  22.         ‘tlaxco’=>‘Tlaxco’,
  23.         ‘feria tlaxcala’=>‘Feria Tlaxcala’
  24. );
  25.  
  26. my $query = new CGI;
  27. my $action = $query->param(‘action’);
  28.  
  29. my @videos = ();
  30. my $total = 0;
  31. my $values = {};
  32. my $url;
  33. my $tt = Template->new;
  34.  
  35. print "Content-type: text/html;charset=UTF-8\n\n";
  36.  
  37. SWITCH:{
  38.         if( $action eq ‘view’ ) {
  39.                 $values{‘video’}=$query->param(‘video’);
  40.                 my @comments = ();
  41.                
  42.                 # here we start parsing the XML
  43.                 my $parser = XML::DOM::Parser->new();
  44.                 my $doc = $parser->parsefile(‘http://www.youtube.com/api2_rest?method=youtube.videos.get_details&dev_id=FIq6LWxC3RE&video_id=’ . $values{‘video’} );
  45.                 # we put this on eval to avoid errors
  46.                 eval{
  47.                         # here i add all the commets to an array
  48.                         foreach my $comment ($doc->getElementsByTagName(‘comment’)){
  49.                                 my @date = localtime( $comment->getElementsByTagName(‘time’)->item(0)->getFirstChild->getNodeValue );
  50.                                 push @comments, {
  51.                                         author=>Unicode::String::utf8($comment->getElementsByTagName(‘author’)->item(0)->getFirstChild->getNodeValue),
  52.                                         text=>Unicode::String::utf8($comment->getElementsByTagName(‘text’)->item(0)->getFirstChild->getNodeValue),
  53.                                         time=>strftime( ‘%r’, @date ),
  54.                                         date=>strftime( ‘%d-%m-%Y’, @date )
  55.                                 };
  56.                         }
  57.                        
  58.                         # here i format the video time
  59.                         my( $seconds,$hours,$minutes );
  60.                         $seconds = $doc->getElementsByTagName(‘length_seconds’)->item(0)->getFirstChild->getNodeValue;
  61.                         ( $hours, $seconds ) = ( int( $seconds/3600 ), $seconds % 3600 );
  62.                         ( $minutes, $seconds ) = ( int( $seconds/60 ), $seconds % 60 );
  63.                        
  64.                         # here i create an array of the data i will use and show the page using template toolkit
  65.                         my %data = (
  66.                                 video=>$values{‘video’},
  67.                                 title=>Unicode::String::utf8($doc->getElementsByTagName(‘title’)->item(0)->getFirstChild->getNodeValue),
  68.                                 author=>Unicode::String::utf8($doc->getElementsByTagName(‘author’)->item(0)->getFirstChild->getNodeValue),
  69.                                 rating_avg=>$doc->getElementsByTagName(‘rating_avg’)->item(0)->getFirstChild->getNodeValue,
  70.                                 tags=>Unicode::String::utf8($doc->getElementsByTagName(‘tags’)->item(0)->getFirstChild->getNodeValue),
  71.                                 description=>Unicode::String::utf8($doc->getElementsByTagName(‘description’)->item(0)->getFirstChild->getNodeValue),
  72.                                 time=>sprintf( ‘%02s:%02s:%02s’, $hours,$minutes, $seconds),
  73.                                 comments=>\@comments
  74.                         );
  75.                                
  76.                         $tt->process( ‘videos_view.tt’, \%data ) || die $tt->error;
  77.                 };
  78.                 last SWITCH;
  79.         }
  80.  
  81.         $values{‘page’}=$query->param(‘page’);
  82.         $values{‘tag’}=$query->param(‘tag’);
  83.  
  84.         if( $values{‘tag’} eq ) {
  85.                 # i show the favorites of the user
  86.                 $url=‘http://www.youtube.com/api2_rest?method=youtube.users.list_favorite_videos&dev_id=FIq6LWxC3RE&user=’ . $userFavorites;
  87.         } else {
  88.                 $values{‘page’}=‘1’ if( $values{‘page’} eq );
  89.                 # here i get videos by tab
  90.                 $url=‘http://www.youtube.com/api2_rest?method=youtube.videos.list_by_tag&dev_id=FIq6LWxC3RE&tag=’ . $values{‘tag’} . ‘&page=’ . $values{‘page’} . ‘&per_page=20’;
  91.                 # since the api dosent support paging, i see if the next xml has data, to show next link
  92.                 $nextXML=‘http://www.youtube.com/api2_rest?method=youtube.videos.list_by_tag&dev_id=FIq6LWxC3RE&tag=’ . $values{‘tag’} . ‘&page=’ . ( $values{‘page’} + 1 ) . ‘&per_page=20’;
  93.         }
  94.         my $parser = XML::DOM::Parser->new();
  95.         # we put this on eval to avoid errors
  96.         eval {
  97.                 my $doc = $parser->parsefile($url);
  98.                
  99.                 # here i create an array with the info for videos
  100.                 foreach $video ($doc->getElementsByTagName(‘video’)){
  101.                         push @videos, {
  102.                                 ‘author’=>Unicode::String::utf8($video->getElementsByTagName(‘author’)->item(0)->getFirstChild->getNodeValue),
  103.                                 ‘id’=>$video->getElementsByTagName(‘id’)->item(0)->getFirstChild->getNodeValue,
  104.                                 ‘title’=>Unicode::String::utf8($video->getElementsByTagName(‘title’)->item(0)->getFirstChild->getNodeValue),
  105.                                 ‘length_seconds’=>$video->getElementsByTagName(‘length_seconds’)->item(0)->getFirstChild->getNodeValue,
  106.                                 ‘rating_avg’=>$video->getElementsByTagName(‘rating_avg’)->item(0)->getFirstChild->getNodeValue,
  107.                                 ‘rating_count’=>$video->getElementsByTagName(‘rating_count’)->item(0)->getFirstChild->getNodeValue,
  108.                                 ‘description’=>Unicode::String::utf8($video->getElementsByTagName(‘description’)->item(0)->getFirstChild->getNodeValue),
  109.                                 ‘view_count’=>$video->getElementsByTagName(‘view_count’)->item(0)->getFirstChild->getNodeValue,
  110.                                 ‘upload_time’=>$video->getElementsByTagName(‘upload_time’)->item(0)->getFirstChild->getNodeValue,
  111.                                 ‘comment_count’=>$video->getElementsByTagName(‘comment_count’)->item(0)->getFirstChild->getNodeValue,
  112.                                 ‘tags’=>Unicode::String::utf8($video->getElementsByTagName(‘tags’)->item(0)->getFirstChild->getNodeValue),
  113.                                 ‘url’=>$video->getElementsByTagName(‘url’)->item(0)->getFirstChild->getNodeValue,
  114.                                 ‘thumbnail_url’=>$video->getElementsByTagName(‘thumbnail_url’)->item(0)->getFirstChild->getNodeValue
  115.                         };
  116.                 }
  117.                 if( defined( $nextXML ) ){
  118.                         my $doc2 = $parser->parsefile($nextXML);
  119.                         $total = @{ $doc2->getElementsByTagName(‘video’) };
  120.                 }
  121.                
  122.         };
  123.         my %data = (
  124.                 total=>$total,
  125.                 tag=>$values{‘tag’},
  126.                 tags=>\%tags,
  127.                 videos=>\@videos,
  128.                 page=>$values{‘page’}
  129.         );
  130.         # i show the page using template toolkit
  131.         $tt->process( ‘videos_list.tt’, \%data ) || die $tt->error;
  132.  
  133. }
  134.  

videos_list.tt The template where we see the list of videos.

  1.  
  2. <ul id="videosList">
  3. [% FOREACH videos %]
  4.   <a href="index.pl?action=view&amp;video=[% id %]"><img src="[% thumbnail_url %]" /></a>
  5.   <h2><a href="index.pl?action=view&amp;video=[% id %]">[% title %]</a></h2>
  6.   <p>[% description %]</p>
  7.  </li>
  8. [% END %]
  9. </ul>
  10.  
  11.  
  12. <div align="center">
  13.  [% IF tag || ( page>1 && total>0 ) %]
  14.  [% IF ( page > 1 ) %]
  15.   <a href="index.pl?tag=[% tag %]&amp;page=[% (page – 1) %]" alt="Previous" title="Previous">Previous</a>
  16.   [% END %]
  17.   [% IF total>0 %]
  18.    <a href="index.pl?tag=[% tag %]&amp;page=[% (page + 1) %]" alt="Next" title=‘Next’>Next</a>
  19.   [% END %]
  20.  
  21.  
  22.  
  23.  [% END %]
  24.  
  25.  [% IF tag == ” %]Favorites[% ELSE %]<a href="index.pl">Favorites</a>[% END %]
  26.  [% FOREACH key = tags.keys %]
  27.   || [% IF tag == key %][% tags.$key %][% ELSE %]<a href="index.pl?tag=[% key %]">[% tags.$key %]</a>[% END %]
  28.  [% END %]
  29. </div>
  30.  

videos_view.tt The template where we see a specific video.

  1.  
  2. <h1>[% title %]</h1>
  3.  
  4. <div align="center">
  5. <object width="425" height="350"><param name="movie" value="http://www.youtube.com/v/[% video %]"></param><param name="wmode" value="transparent"></param><embed src="http://www.youtube.com/v/[% video %]" type="application/x-shockwave-flash" wmode="transparent" width="425" height="350"></embed></object>
  6. </div>
  7.  
  8. <strong>Author:</strong> <a href="http://www.youtube.com/user/[% author %]" target="_blank">[% author %]</a>
  9.  
  10. <strong>Rating:</strong> [% rating_avg %]
  11.  
  12. <strong>Tags:</strong> [% tags %]
  13.  
  14. <strong>Time:</strong> [% time %]
  15.  
  16. [% description %]
  17. </p>
  18.  
  19. [% IF comments.size > 0 %]
  20.  <h2>Comments</h2>
  21.   [% FOREACH comment=comments %]
  22.    <div class=‘textoComentarios’>[% comment.text %]</div>
  23.  
  24.    <div class=‘pieComentarios’>
  25.    | By <a href=‘http://www.youtube.com/user/[% comentario.author %]’>[% comment.author %]</a> | [% comment.date %] | [% comment.time %] |
  26.  
  27.  
  28.   </div>
  29.  [% END %]
  30. [% END %]
  31.