Parsing the JSON News Result Set
The results that are returned as the response from the news search are accessible via the request object. To access these results, we need to access the Ajax request’s responseText property and then parse the results into a valid JSON string. With the jsonparser included, this is very simple: all we do to parse the response as JSON is:
var gnews = this.request.responseText.parseJSON();
With the parsed response, we can access the results, which are always included in a responseData object. The responseData object includes an array named results, which can be iterated to access the properties of each news result and create an HTML structure to render the news results onto the web page.
var results = gnews.responseData.results;
Table 4Specific Google News Search Properties
Property |
Description |
---|---|
title |
Title of the news result. |
titleNoFormatting |
Title of the news result with no HTML. |
unescapedUrl |
URL of the result. |
url |
Escaped version of the URL of the result. |
clusterUrl |
A landing page that points to related stories. |
content |
Part of the content from the news story. |
publisher |
The news story publisher. |
location |
List of comma-delimited locations. |
publishedDate |
Published date of news story. |
relatedStories[] |
An optional array property that only appears when a story has related stories. If the property is present, the array will contain a subset of properties specific to those related stories. |
image{} |
Optional property that only appears when an image is present that relates to the group of news articles related to the search result. If one exists, the following properties are available for the image: title - Title of image titleNoFormatting - Title of image with no HTML formatting url - URL of the image in the article originalContextUrl - URL of the article that contains the image publisher - Publisher of the news article related to the image tbUrl - URL of a thumbnail for the image tbWidth - Width of the thumbnail image tbHeight - Height of the thumbnail image |
language |
Optional property that indicates the language of the news story. |
When the news service has been searched and the results have been parsed into JSON, we can start to iterate and render the results as HTML. The example we’re going to create is a simple list of news titles with the publisher, published date, and a link to related stories, if any exist. Each post will have its own containing div element that is tied to a CSS class named post.
To render the titles, we are creating an anchor tag that links to the unescapedUrl property and has an innerHTML value of titleNoFormatting property. This will give us a title that links to the original story in a new window. To render the publisher and published date, we’ll create an italic element and set the innerHTML to the publisher and publishedDate properties. With the title and publisher/date elements created, we can add them to the post div. Next, we’ll check to see if there are any related stories to the current news result by checking the value of the clusterUrl property. If this property has a value, an anchor tag is created that links to the clusterUrl and is then added to the post div. Once the post is complete, it’s finally added to the gNews element.
To page through results, we simply add an anchor element that will be used to increase the start argument in the search. To create this functionality, we create an onclick event that increases the GoogleAPI.Index property by four and triggers a new search via the GoogleAPI.SearchNews function. The reason we increase the GoogleAPI.Index property by four is because there are four results in the rsz argument because it is set to small, so we want to get the next four results each time we click more news.
Listing 2: The GoogleAPI Object Makes Ajax Requests to the Google Search API, Parses Results and Renders the Widget as HTML (GoogleAPI.js)
document.write('<script type="text/javascript" src="assets/js/jsonparser.js"></script>'); var GoogleAPI = new Object(); GoogleAPI.SearchNews = function() { GoogleAPI.callback = GoogleAPI.onNewsSearched; var gateway = "service/gateway.php?feed="+ escape("http://ajax.googleapis.com/ ajax/services/search/news?v=1.0&rsz=small&start="+ GoogleAPI.Index +"&q=")+ GoogleAPI.Query; GoogleAPI.makeRequest(gateway); } GoogleAPI.onNewsSearched = function(request) { var divNews = document.getElementById('gnews'); divNews.innerHTML = ''; if(this.request.responseText) { var gnews = this.request.responseText.parseJSON(); var results = gnews.responseData.results; if(results.length > 0) { for(var i=0; i<results.length; i++) { var post = document.createElement('div'); post.className = 'post'; var postHref = document.createElement('a'); postHref.href = results[i].unescapedUrl; postHref.className = 'title'; postHref.target = "_blank"; postHref.innerHTML = results[i].titleNoFormatting; var postDate = document.createElement('i'); postDate.innerHTML = 'from '+ results[i].publisher + ' posted '+ results[i].publishedDate; post.appendChild(postHref); post.appendChild(postDate); if(results[i].clusterUrl) { var clusterHref = document.createElement('a'); clusterHref.href = results[i].clusterUrl; clusterHref.className = 'related'; clusterHref.target = "_blank"; clusterHref.innerHTML = 'Related Stories'; post.appendChild(clusterHref); } divNews.appendChild(post); } var moreBtn = document.createElement('a'); moreBtn.href = "#"+(GoogleAPI.Index+4); moreBtn.className = "more"; moreBtn.innerHTML = "More News >"; moreBtn.onclick = function() { GoogleAPI.Index+=4; GoogleAPI.SearchNews(); } divNews.appendChild(moreBtn); } else GoogleAPI.ThrowError("There were no news results"); } else GoogleAPI.ThrowError("There was an error receiving the news feed"); } GoogleAPI.makeRequest = function(gw) { this.request = (window.XMLHttpRequest) ? new XMLHttpRequest(): new ActiveXObject("Microsoft.XMLHTTP"); this.request.onreadystatechange = function() { GoogleAPI.checkReadyState(); }; this.request.open('GET', gw, true); this.request.send(gw); } GoogleAPI.ThrowError = function(msg) { alert(msg); } GoogleAPI.checkReadyState = function() { switch(this.request.readyState) { case 1: break; case 2: break; case 3: break; case 4: this.callback(this.request); } } window.onload = function() { GoogleAPI.Index = 0; GoogleAPI.Query = "Peachpit"; GoogleAPI.SearchNews(); }