One of the things that amazed me ever since I started working for Yahoo is the amount of free services the company offers to web developers (internally we even have more!). Nearly every service Yahoo provides (Search, Flickr, Upcoming.org, Weather, deli.cio.us) is available as a REST API, which means that you can access the data via a URL. For example if you wanted to search the web with Yahoo for the term "JavaScript", you can get the search results in XML format by simply calling the following URL:
http://api.search.yahoo.com/WebSearchService/V1/webSearch?appid=chrisdabbles&query=JavaScript
The appid is the Yahoo developer application ID you can get for free at http://api.search.yahoo.com/webservices/register_application - in this case "chrisdabbles" - which is mine. If you want to use your own simply replace the "chrisdabbles" with your newly acquired ID once you signed up as a developer.
If you wanted to show less than ten results - say five - or you don't want to start at zero - but instead at ten - you can set more parameters to the query, namely start and results:
http://api.search.yahoo.com/WebSearchService/V1/webSearch?appid=chrisdabbles&query=JavaScript&start=10&results=5
This is pretty cool, but you cannot easily use it in a JavaScript, as the output is XML and if you use XMLHttpRequest() for Ajax (and not a hidden IFRAME) you cannot reach content outside your own domain. And even if you reach it - you have to convert the data from XML into a format you can use in JavaScript.
The really nice service of Yahoo is that you don't need to get the results in XML format, but you can also choose JSON - which is a JavaScript object you can use directly in a SCRIPT tag.
In order to get the results of the earlier search to use in JavaScript immediately, you set the output to JSON and define a callback function - in this case called eureka() - aptly named as you found something.
http://api.search.yahoo.com/WebSearchService/V1/webSearch?appid=chrisdabbles&query=JavaScript&start=10&results=5&output=JSON&callback=eureka
In order to use it you need to define the function eureka() before you apply the SCRIPT element with the search URL as the src attribute:
<script type="text/javascript">
function eureka(data){
alert(data);
}
</script>
<script type="text/javascript" src="http://api.search.yahoo.com/WebSearchService/V1/webSearch?appid=chrisdabbles&query=JavaScript&start=10&results=5&output=JSON&callback=eureka"></script>
Check this example in your browser
In the function eureka() you can loop over all the search results and show their values. The loop is dependent on the object and its properties. In the search example this is:
for( var i in data.ResultSet.Result ) {
url = data.ResultSet.Result[i].ClickUrl;
title = data.ResultSet.Result[i].Title;
summary = data.ResultSet.Result[i].Summary;
alert( 'Title: ' + title + '\nURL :' + url + '\nSummary: ' + summary );
}
Check this example in your browser
As you can see when you test the script the URLs are pretty lengthy as the API adds some tracking data. If you want to have shorter URLs, you could use some regular expressions to get rid of the excessive data:
function eureka(data){
for( var i in data.ResultSet.Result ) {
url = data.ResultSet.Result[i].ClickUrl;
url = url.replace(/.*\*\*/,'');
url = url.replace(/%3a/,':');
title = data.ResultSet.Result[i].Title;
summary = data.ResultSet.Result[i].Summary;
alert( 'Title: ' + title + '\nURL :' + url + '\nSummary: ' + summary );
}
}
Check this example in your browser
You can test the structure of the data by viewing the XML in a browser. In search, it is a ResultSet object with a Result array. Each Result item has a Title, a Summary and a ClickUrl (amongst other attributes).
By using DOM methods to create HTML it is pretty easy to have a search results panel in your web site:
function eureka( data ) {
var item, itemlink, itemsummary, itemtitle;
var outputElement = document.getElementById('results');
if( ! outputElement ) { return; }
outputElement.innerHTML = '';
var list=document.createElement( 'ul' );
for( var i in data.ResultSet.Result ) {
item = document.createElement( 'li' );
itemtitle = document.createElement( 'h3' );
itemlink = document.createElement( 'a' );
itemlink.setAttribute( 'href', data.ResultSet.Result[i].ClickUrl );
itemlink.appendChild( document.createTextNode( data.ResultSet.Result[i].Title ) );
itemtitle.appendChild( itemlink );
itemsummary = document.createElement( 'p' );
itemsummary.appendChild( document.createTextNode( data.ResultSet.Result[i].Summary ) );
item.appendChild( itemtitle );
item.appendChild( itemsummary );
list.appendChild( item )
}
outputElement.appendChild( list );
}
Check this example in your browser
This is pretty cool, but what if you wanted to offer several searches? Easy, you don't even need to resort to XMLhttpRequest() or hidden frames - all you need to do is to create a new script element in the head using DOM methods and set its src attribute to the search URL:
function dynamicSearch(term){
var url = 'http://api.search.yahoo.com/WebSearchService/V1/webSearch?appid=chrisdabbles&start=10&results=5&output=JSON&callback=eureka
';
url += '&query=' + term;
var newsearch = document.createElement( 'script' );
newsearch.src = url;
document.getElementsByTagName( 'head' )[0].appendChild( newsearch );
}
You could use this function for example in a link that links to the normal Yahoo! search service (to make sure that visitors without JavaScript also get the results):
<a href="http://search.yahoo.com?p=JavaScript" onclick=" dynamicSearch('JavaScript');return false">Search Yahoo! for JavaScript</a>
Remember that the URL used here uses the callback function eureka(), which is why you don't need anything else in terms of functions.
You can even offer a search form that allows your visitors to enter their own search terms:
<form action="http://search.yahoo.com/search"
onsubmit="dynamicSearch(this.elements['p'].value);return false" method="get">
<p>
<label for="p">Search Yahoo:</label>
<input type="text" size="30" id="p" name="p" />
<input type="submit" value="Go" /></p>
</p>
</form>
Check this example in your browser
This works, but it is not really unobtrusive. I created a better example using the utility methods of the Yahoo User Library, that you can use in your own sites. All you need to do is to embed the YUI libraries and the file YJSONsearch.js in the head of your document:
<script type="text/javascript" src="yahoo-min.js"></script>
<script type="text/javascript" src="dom-min.js"></script>
<script type="text/javascript" src="event-min.js"></script>
<script type="text/javascript" src="YJSONsearch.js"></script>
Furthermore you need to give the elements you want to load the results into the results element a class of YJSONsearch:
<p><a href="http://search.yahoo.com/search?p=JavaScript" class="YJSONsearch">Search Yahoo! for JavaScript</a></p>
<p><a href="http://search.yahoo.com/search?p=DOMscripting" class="YJSONsearch">Search Yahoo! for DOM scripting</a></p>
<form action="http://search.yahoo.com/search" class="YJSONsearch" method="get">
<p>
<label for="p">Search Yahoo:</label>
<input type="text" size="30" id="p" name="p" />
<input type="submit" id="YJSONsubmit" value="Go" /></p>
</p>
</form>
<div id="YJSONresults"></div>
Check this example in your browser
Notice that you need an element with the ID YSONresults and a field with the ID p for it to work. The script gets the search term from this field in the case of the form and retrieves everything after the "p=" string from link URLs as the search term.
You can change the presets of the script in the properties at the beginning of YJSONresults.js:
indicatorClass : 'YJSONsearch',
searchAPIURL : 'http://api.search.yahoo.com/WebSearchService/V1/webSearch?output=JSON&callback=YJSONsearch.eureka',
yourAppID : 'chrisdabbles',
start : 0,
amount : 5,
resultElementID : 'YJSONresults',
loadingMessage : 'loading...',
Care for a detailed explanation of the script? Drop a comment