Archive forMarch, 2006

Welcome to COMET

Do you know what COMET is? According to Alex Russell COMET is the next stage of AJAX:

"New services like Jot Live and Meebo are built with a style of data transmission that is neither traditional nor Ajax. Their brand of low-latency data transfer to the browser is unique, and it is becoming ever-more common. Lacking a better term, I’ve taken to calling this style of event-driven, server-push data streaming “Comet”. "

Basically, is a new approach of open channel between web servers and client browsers, or a push technology: servers can send to the clients unsolicited responses. Other important issue is that is event driven.

This technology needed a name. Now is here, coined to Alex Russell, so I'm almost sure we'll read about it almost everywhere, very soon.

I totally agree with this solution because for a powerful web based application there is a need for two way communication: clients need to request information from servers, but also server should need a way to push information to the client.

Problem is that technology is not there, yet. This would be implemented server-side, in web servers, and is not done yet. Don't search for Apache MODs or IIS extensions because you won't find them, but most important is that is possible with actual technology client-side and some implementation server-side. The sites mentioned above already use it, so it's almost here.

I'm pretty sure this technology will spread rapidly as soon as web servers libraries will be available because allows developers to build interesting and catchy web apps.

I've read Ajaxian comments and mention of old 1997 Push technology, but COMET looks very different: it doesn't start with general ideas but with real implementations, based on today's products (web servers & browsers).

The only problem I see is to provide practical anti-spam solutions. I'm sure many spammers would be interested to push their crap in client browsers. If the user will be still in control and everything would be easy to use (no other installations) this technology could have a bright future, I think. I'd expected for it for some time, because I'm almost sure we'll have it in the future, even if is called COMET or something different.

Welcome to COMET.

Comments

Geocoder.us API

Another solution to get latitudes and longitudes for US addresses is geocoder.us. They also have some web APIs to call this service online. Full help files are available here.

You can choose from a few solutions: XML-RPC, SOAP, REST or even RDF or CSV. All of them are ok, as long as they works for you. I'll show you here two solutions: SOAP & CVS, one server side with PHP, the latter client side with XMLHTTPRequest and CVS.

Entry point pages are:

http://geocoder.us/service/xmlrpc
http://geocoder.us/service/soap
http://geocoder.us/service/rest/geocode
http://geocoder.us/service/csv/geocode

Here's PHP sample:

<?php
if($_POST['addr']!='') {
  include 'nusoap.php';
  $soapclient = new soapclient('http://geocoder.us/service/soap');
  $results = $soapclient->call('geocode',array($_POST['addr']));
  if(is_array($results))
    echo "Latitude: {$results[0]['lat']} -
 Longitude: {$results[0]['long']}";
}
?>
<form method=post name=frmgeous >
Address: <input name=addr>
<input type=submit value=Submit name=submit>
</form> 

This page is very basic: just display a form with a text-box for full address and a submit button. When clicked, values are passed to the server, interogating Geocoder.us and display results, if returned. This sample also uses Nusoap.php.

Client-side we can use only JavaScript to achieve the same results. Just add in the form above a simple button that call JavaScript function from a separate include file (uses the same text-box for address), before closing form tag:

<script language="JavaScript" src="/geocoder.us.js" mce_src="/geocoder.us.js" ></script>
<input type=button value=JavaScript onclick="javascript:geocode_us();"> 

Here's the JavaScript code, available for download:

 function geocode_us() {
var xmlhttp=null;
if(window.XMLHttpRequest) {
   xmlhttp = new XMLHttpRequest();
} else if(window.ActiveXObject) {
   xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}

if(xmlhttp) {
  xmlhttp.open("GET", "./load.php?url="+
    escape("geocoder.us/service/csv/geocode?address="+
    document.forms['frmgeous'].addr.value), false);
  xmlhttp.send("");
  arr=xmlhttp.responseText.split(',');
  alert('Latitude: '+arr[0]+'\nLongitude: '+arr[1]);
  }
}

This uses the same loader (load.php) to overcome security limits when accessing pages from another domain, client-side. It uses XMLHTTPRequest() on Firefox and ActiveX XML for IE when interrogating Geocoder.us server. See it at work:

Address:

For commercial requests see their website for prices and terms. This is also simple, isn't it?

Comments

Geocoder.ca API

When comes to Canadian geocoding first option you have is geocoder.ca. You can get longitude & latitude, as well as postal codes online from their website, but also, programmatically, using Geocoder.ca API.

You can request values both by HTTP GET or POST using a few combinations: address + city, or free text location or postal code. Result is returned as XML.

Try this:

http://geocoder.ca/?stno=&addresst=&city=&prov=&locate=1+Yonge+St.%2C+Toronto%2C+CA&postal=&geoit=GeoCode+it%21

As you can see, there are only a few parameters: stno, addressst, city & prov if you want to use full address, or locate for free text search, or postal for postal code. There are the same with POST.

To transform this in a web API you only have to include geoit=XML in your requests. The result is an XML file.

See this PHP sample:

 $location="1 Yonge St., Toronto, ON";
$req=implode('',file(
 'http://geocoder.ca/?geoit=XML&locate='.
 urlencode($location)));

$p = xml_parser_create();
xml_parse_into_struct($p, $req, $vals);
xml_parser_free($p);

if (count($vals)==19) // error occured
{
   $er = $vals[2]['value']." - ".
 $vals[5]['value'];
   $lat = 0;
   $long = 0;
} else { // get values
   $er = '';
   $lat = $vals[1]['value'];
   $long = $vals[4]['value'];
}

echo "Error:{$er}<br>
   Latitude: {$lat}<br>
   Longitude: {$long}";

We are getting the results from strict result format, returned as XML file:

<?xml version="1.0″ encoding="UTF-8″ ?>
<geodata>
        <latt>43.642321123</latt>
        <longt>-79.374806219</longt>
</geodata>

You even don't need to register. There is a limitation per IP address of about 1000 requests per day. For more requests they have commercial licenses.

Comments

Web Services At A Crossroads

I've just read an interesting article by Daryl Plummer: Web Services At A Crossroads. It's an interesting discussion about web services (SOAP, WSDL) vs. new emerging solutions like Plain Old XML (XML) or REST. No word yet about JSON, AJAX or other solutions.

In my opinion, any of these technologies work just fine, as long as they solve real problems. There are quick and easy needs for communication channels, when new solutions are just fine. From the security point of view, I think all of there are the same: they all could enforce rules or have leaks and breaches. And many times security is not even an issue.

The most important issue, in my opinion, would be a standardized solution available on multiple platforms and an assurance that these technologies will be available in next releases of the hosted applications or working interconnected. But these problems are not easy solved for any of these acronyms, either SOAP, WSDL or REST, or others. New solutions rely on specific implementations that can change over time.

Instead of 'web services' I think a more correct term would be 'web API', which include more than just client-server communication. This is reflected by new Web APIs Working Group of W3C and new developing projects from various companies when many times new access solutions are called simply 'API', instead of 'service' (see Google, Yahoo, etc.).

Comments

del.icio.us API

You know what del.icio.us is: a social bookmark service, now bought by Yahoo. You can create a free account and add your website bookmarks, even share with others.

They also released some API, but in my opinion very limited. All you can do is to manage your own bookmarks (links) with their tags and bundles. You can't do searches on popular websites and tags, or last added bookmarks.

To use it from any application or website you need a free account. All API help files are available at del.icio.us/help/api. They also provide HTML, RSS, JSON & JavaScript access (see help page).

The most important function (page), I think, is posts/add, which add a new link to your online account. You can do this operation from your browser openning

http://username:password@del.icio.us//api/posts/add?url=…&description=…URL title…&extended=…URL description…&tags=… tags…

 

You can create such a link even from JavaScript and call this page. One simple solution from JavaScript is to use new Image(), even if the value returned is not an image:

var img=new Image();
img.src='http://..full URL as above …';

When everything was done right is returned

<result code="done" />

otherwise would be:

<result code="something went wrong" />

Here's some PHP code to add a new bookmark to your account, in 2 simple ways:

function deliciousAdd($user, $pass, $url, $description, $extended, $tags) {
  $r=file("http://{$user}:{$pass}@del.icio.us/api/posts/add?url=".urlencode($url).
     "&description=".urlencode($description)."&extended=".urlencode($extended).
     "&tags=".urlencode($tags));
  return ($r[1]=="<result code=\"done\" />");
}

function deliciousAdd2($user, $pass, $url, $description, $extended, $tags)
   {
   $domain="del.icio.us";
   $socketConnection = fsockopen($domain, 80, $errno, $errstr);

   if (!$socketConnection) {
 echo("Network error: $errstr ($errno)");
   } else {
       $tmp = '';
       fputs($socketConnection,
 "GET /api/posts/add?url=".urlencode($url).
 "&description=".urlencode($description)."&extended=".urlencode($extended).
 "&tags=".urlencode($tags).
 " HTTP/1.0\r\nAuthorization: Basic ".base64_encode($user.":".$pass)."\r\n".
 "Host: $domain\r\nConnection: close\r\n\r\n");

       while (!feof($socketConnection)) {
           $tmp .= fgets($socketConnection, 128);
       }

       fclose ($socketConnection);

   }

return(strpos($tmp,"<result code=\"done\" />"));
}

They return TRUE or FALSE, depends on the response and could be use like:

deliciousAdd($username,$password,
    "http://Yahoo.com","Yahoo!","Yahoo","yahoo");

deliciousAdd2($username,$password,
    "http://Yahoo.com","Yahoo!","Yahoo","yahoo"); 

Simple, isn't it?

Comments

MSN Search API

Like other search engines, MSN made public a few APIs, including the most important: web search. They are using SOAP and could be used online from any other programming language and platforms.

As usual, first step is registration. You have to register your free application ID, needed in your web requests. MSN provided some MSDN help files and samples, but only for C# & VB.NET.

Our example here will be in PHP with NuSOAP. See it at work in this small demo (popup window). The PHP source code is this (only for MSN interrogation part):

# Use the NuSOAP php library
require_once('nusoap.php');

# Set parameters
$parameters = array(
  'AppID'=>'…your AppID…',
  'Query' => $_POST['key'],
  'CultureInfo' => 'en-US',
  'SafeSearch' => 'Off',
  'Requests' => array (
     'SourceRequest' => array (
         'Source' => 'Web',
         'Offset' => 0,
         'Count' => 10,
         'ResultFields'  => 'All' )
      )
   );

$soapclient =
    new soapclient('http://soap.search.msn.com/webservices.asmx');

$results = $soapclient->call('Search',array("Request"=>$parameters));

if( is_array($results['Responses']) ) {
  echo "<p><b>Your MSN query for '" . $_POST['key'] . "' found "
 . $results['Responses']['SourceResponse']['Total'] . ":</b></p>";
  foreach ( $results['Responses']['SourceResponse']['Results'] as $result ) {
 echo "<p><a href='" . $result['Url'] .
  "' target='_blank'>".$result['Title'].
  "</a><br />".$result['Description'].
  "<br />". $result['DisplayUrl']."</p>";
  }
 }
}

Don't forget to replace your AppID.

As you can see, the URL for web service is http://soap.search.msn.com/webservices.asmx and function name is 'Search'. You have to build proper parameters before calling function, most important 'Query', 'Source' (for web or local search), 'Offset' and 'Count' (how many results).

Results are returned as associative arrays, containing other arrays, for instance $results['Responses']['SourceResponse']['Results']['Url']. Hint: to see all fields, replace displaying part with a simple

print_r($results).

Usage limit is quite large: up to 10,000 queries a day. For more options see MSDN documentation.

Comments

Yahoo Geocoding API

There are some mapping APIs that accept only geocode coordinates (longitudes & latitudes). You need a solution to get them for all addresses you want. One of the best solution is to use Yahoo Geocoding API. You need to register first then you can request it with your custom parameters and get the results as XML, JSON or serialized PHP.

You can use the form below to get your values:

Street:
City:
State:
Zip:
or
Free Text:

- city, state
- city, state, zip
- zip
- street, city, state
- street, city, state, zip
- street, zip
Longitude:
Latitude:
 

This sample is using JSON and 2 extra files. One is a custom JSON library (json.js) for client side calls, plus a PHP file (load.php) which loads any URL on request based on fetchUrlWithoutHanging() from php.net/file (because XMLHTTP can't open pages from different server because of security restrictions).

The JavaScript function to interogate Yahoo service is here (Update: check new XML version below, JSON version is no more available from Yahoo):

function geocode() { 
var frm=document.forms['frm'];
if(frm.f.value!='')
  tmp="/load.php?url="+escape("api.local.yahoo.com/MapsService/V1/geocode?appid=YahooDemo&street=&city=&state=&location="+frm.f.value+"&output=json");
else
  tmp="/load.php?url="+escape("api.local.yahoo.com/MapsService/V1/geocode?appid=YahooDemo&street="+frm.s.value+"&city="+frm.c.value+"&state="+frm.p.value+"&output=json");
tmp2=json_load(tmp);
var obj=eval('('+tmp2+')');
if(obj) {
  frm.l1.value=obj.ResultSet.Result[0].Longitude;
  frm.l2.value=obj.ResultSet.Result[0].Latitude;
  }
else {
  frm.l1.value="";
  frm.l2.value="";
  }
obj=null;
}

Here's a simple request to Yahoo service: http://api.local.yahoo.com/MapsService/V1/geocode?appid=YahooDemo&street=701+First+Street&city=Sunnyvale&state=CA
This call return JavaScript code to build an object with all requested values as properties.

There may be some problems with this scripts, but generally it should work.

The Yahoo Geocoding service is limited to 50,000 queries per IP address per day. Combined with Yahoo Maps or Google Maps could be a very powerful online tool.

Update (March 22nd): JSON results are no more available from Yahoo Geocoding API, so, we've changed the scripts to use XML files, directly from your browser (IE or FF):

function geocode() { 
var frm=document.forms['frm'];

if(frm.f.value!='')
   tmp="/load.php?format=xml&url="+
       escape("api.local.yahoo.com/MapsService/V1/geocode?appid=cod_xx2006&street=&city=&state=&location="+frm.f.value+"&output=xml");
else
   tmp="/load.php?format=xml&url="+
       escape("api.local.yahoo.com/MapsService/V1/geocode?appid=cod_xx2006&street="+frm.s.value+"&city="+frm.c.value+"&state="+
frm.p.value+"&output=xml");

var xmlDocument=null;

if(window.XMLHttpRequest) {
     // Firefox, Mozilla
     xmlDocument = document.implementation.createDocument("","",null);
     xmlDocument.async = false; 
     xmlDocument.load(tmp);
     lat=xmlDocument.getElementsByTagName("Latitude").item(0).firstChild.nodeValue;
     long=xmlDocument.getElementsByTagName("Longitude").item(0).firstChild.nodeValue;
     err=xmlDocument.getElementsByTagName("Result").item(0).attributes.getNamedItem("warning").firstChild.nodeValue;
} else if(window.ActiveXObject) {
     // IE/Windows ActiveX version
     xmlDocument = new ActiveXObject('Microsoft.XMLDOM');
     xmlDocument.async = false;
     xmlDocument.load(tmp);
     xmlDocument.setProperty("SelectionLanguage", "XPath");
     xmlDocument.setProperty("SelectionNamespaces", "xmlns:my='urn:yahoo:maps'");
     var objNode=xmlDocument.selectSingleNode("//my:Result/@warning");
     err=objNode.text;
     var objNode=xmlDocument.selectSingleNode("//my:Result/my:Latitude");
     lat=objNode.text;
     var objNode=xmlDocument.selectSingleNode("//my:Result/my:Longitude");
     long=objNode.text;
}

if(xmlDocument) {
  frm.l1.value=lat;
  frm.l2.value=long;
  if(err!="") alert('Err: '+err);
  }

You can download YahooGeocode.js file with all client side process (the code above). It uses XML DOM to load Yahoo page using a local proxy (load.php) and then uses different methods to get data: getElementsByTagName() for Firefox & XPath for Internet Explorer.

Comments (1)

New MapQuest OpenAPI

MapQuest has just released their OpenAPI for mapping and routing (press release here). Registration and details are at http://www.mapquest.com/features/main.adp?page=developer_tools_oapi 

Of course, we registered and tried them. See their demos hosted here (popup window). To use them, you need an access key obtained after free registration (be careful to register exactly the domain name AND the folder where you want to use them, otherwise you'll get an invalid key error). You need to use this key in all requests from MapQuest.

Here's a simple demo (see it in popup window):

<html>
<head>
<script src="http://web.openapi.mapquest.com/oapi/transaction?request=script&key=mjtd%7Clu6z2l612h%2Cbx%3Do5-d6z2q" mce_src="http://web.openapi.mapquest.com/oapi/transaction?request=script&key=mjtd%7Clu6z2l612h%2Cbx%3Do5-d6z2q"   type="text/javascript"></script>
<title>OpenAPI Sample - Single Map</title>
</head>
<body style="background-color:rgb(244, 246, 229)" id='body' >
<div id='myMap' class='myMap' style="height:400;width:300″>
</div>

<script type="text/javascript">
 var mq = new MQMap("myMap");
 var loc1 = new MQLocation();
 loc1.setName("poi1″);
 loc1.setAddress("1 Yonge Street");
 loc1.setCity("Toronto");
 loc1.setStateProvince("ON");
 loc1.setPostalCode("M5E1W7″);
 loc1.setCountry("CA");
 loc1.setIconId(244);
 mq.locations.add(loc1);
 mq.setRolloverPopups(false);//To disable the popups
 mq.getMap();
</script>
</body>
</html>

Don't forget to change your access key.
Good news is that you can use full addresses, not only geocodes. 

Documentation and support forums are available after registration.

They are available for non-commercial use for 50,000 combined maps and geocodes and 5,000 routes per day. Business solutions are also available.

Comments

Google Maps API

A well-know service, used by many people is Google Maps API. See them at work at maps.google.com.

You can integrate all these maps directly in your websites or applications. Google Maps API is based on JavaScript. You also need to register your ID key used in all map web pages. First thing, is to include Google JavaScript page from http://maps.google.com/maps :

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

Then you can use all JavaScript objects and functions provided by this API, documented here. Here's a small example:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
 <meta http-equiv="content-type" content="text/html; charset=UTF-8″/>

 <title>Google Maps JavaScript API Example: simple</title>
 <script src="http://maps.google.com/maps?file=api&v=1&key=ABQIAAAAEfCuQGsNiSWxRgf_vfNWaRQjskl1-YgiA_BGX2yRrf7htVrbmBTEB0IH-F489GrwP8-dHLib7cKKIQ" mce_src="http://maps.google.com/maps?file=api&v=1&key=ABQIAAAAEfCuQGsNiSWxRgf_vfNWaRQjskl1-YgiA_BGX2yRrf7htVrbmBTEB0IH-F489GrwP8-dHLib7cKKIQ"
   type="text/javascript">
 </script>

 <script type="text/javascript">
 function onLoad() {
   if (GBrowserIsCompatible()) {
   var map = new GMap(document.getElementById("map"));
   map.centerAndZoom(new GPoint(-122.1419, 37.4419), 4);
   }
 }
</script>
</head>
<body onload="onLoad()">
<div id="map" style="width: 500px; height: 300px"></div>
</body>
</html> 

Idea is simple: create an GMap object based on a GPoint object created from longitude and latitude. Then you can add more objects as layers (GMarker) with their own events (GEvent).

Let's see a little bit more complicated demo with more functionality (popup window). This sample will work only from our website because of the ID key (unless you change it). As you can see, after loading, the maps are independent from your webpage, with their own navigation. All points must be specified by their longitude and latitude, you can't use full addresses. To get this geocodes you can use other websites like www.infosports.com/m/map.htm or www.geocoder.us.

Google API offers much more functionality. You can add markers to the map, with their own events and HTML content. Let's see such an example, with a marker and custom text displayed when click it.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <script src="http://maps.google.com/maps?file=api&v=1&key=ABQIAAAAMWlN5S_pnUghkzaCL6OMMhRPit09n3FXh9HBeHPLQkDYD-WLrxTsecUOe9Urm4gtthzKpsI0hcmToA" mce_src="http://maps.google.com/maps?file=api&v=1&key=ABQIAAAAMWlN5S_pnUghkzaCL6OMMhRPit09n3FXh9HBeHPLQkDYD-WLrxTsecUOe9Urm4gtthzKpsI0hcmToA" type="text/javascript"></script>
  </head>
  <body>
    <div id="map" style="width: 400px; height: 300px"></div>
    <script type="text/javascript">
   
    var map = new GMap(document.getElementById("map"));
    map.addControl(new GSmallMapControl());
    var point = new GPoint(-79.3763, 43.6458);
    map.centerAndZoom(point, 8 );
    var marker = new GMarker(point);
    GEvent.addListener(marker, "click", function() {
      marker.openInfoWindowHtml("Hi there!");
    });
    map.addOverlay(marker);
    </script>
  </body>
</html> 

For a full description of the objects, their methods, events and properties see their documentation (including more complex samples).

Comments

Yahoo Spell Checker API

Another web service available from Yahoo is online spell checker. Thsi service is similar with Yahoo web search: you provide all parameters with REST and get results as XML, JSON or serialized PHP. URL used for this service is http://api.search.yahoo.com/WebSearchService/V1/spellingSuggestion and its description with all parameters is at http://developer.yahoo.net/search/web/V1/spellingSuggestion.html.

Here's an example from JavaScript using JSON:

<script language=JavaScript>
function ws_results(obj) {
alert("Correct spelling of 'someting' is '"+obj.ResultSet.Result+"'");
}
</script>
<script type="text/javascript"
src="http://api.search.yahoo.com/WebSearchService/V1/spellingSuggestion?appid=YahooDemo&query=someting&output=json&callback=ws_results">
</script>

And something similar with serialized PHP:

$request =  'http://api.search.yahoo.com/WebSearchService/V1/spellingSuggestion?appid=YahooDemo&query=someting&output=php';

$response = implode('',file($request));

if ($response === false) {
 die('Request failed');
}

$phpobj = unserialize($response);

echo "Correct spelling of 'someting' is '{$phpobj['ResultSet']['Result']}'"; 

Simply, isn't it? There is the same 5000 queries limit per day per IP for this web service.

Comments

· « Previous entries