Archives for: May 2009
Site Search Google Ajax API
This is a working example of Google Ajax Search API with custom form. The intended usage of the code is for running your own fully customised site restricted search with the help of Google API. Do not wish to read the full article? Just grab the code at the end of this post, replace words "your-API-key-there" with real Google API key and change "webdnes.cz" to the url of your website
I have been considering the possible solutions for implementing the full site search for the websites based on the CMS WebDnes. Suprisingly, although this is a general problem, I was unable to Google out a solution directly fitting my needs. Anyway, what are the possibilities?
Searching over a database.
It seems like a nice solution, but it makes sense mostly in cases when we can rely on a consistent structure of individual items, e.g. for eshops. But for a flexible CMS it means relying on a suboptimal MySQL full text search performance. So this is not the way.
So called parasite forms, e.g Google
Apparently, this solution is very easy to implement. But I have certain doubts that website owners would enjoy search results routed OUTSIDE the website and interlaced with the ads of their competitors. Thus big NO again.
Google Search AJAX API
This solution feels really better. After a minor effort, I was able to google out a nice
example. After a little tweaking, the code worked approximately in the way I intended. If you copy paste the following code, it should work. Just add the proper API key and do not overlook the line options.setRoot, indicating the element to be filled by the results should go.
<script src="http://www.google.com/jsapi?key=vas-api-key-patri-sem" type="text/javascript"></script>
<script language="Javascript" type="text/javascript">
//<![CDATA[
google.load("search", "1", {"language" : "cs"});
function OnLoad() {
// Create a search control
var searchControl = new google.search.SearchControl();
searchControl.setResultSetSize(google.search.Search.LARGE_RESULTSET);
// site restricted web search with custom label
// and class suffix
var siteSearch = new google.search.WebSearch();
siteSearch.setUserDefinedLabel("Webdnes.cz");
siteSearch.setUserDefinedClassSuffix("siteSearch");
siteSearch.setSiteRestriction("webdnes.cz");
options = new google.search.SearcherOptions();
options.setExpandMode(google.search.SearchControl.EXPAND_MODE_OPEN);
options.setRoot(document.getElementById("search"));
searchControl.addSearcher(siteSearch, options);
// tell the searcher to draw itself and tell it where to attach
searchControl.draw(document.getElementById("searchcontrol"));
}
google.setOnLoadCallback(OnLoad);
//]]>
</script>
<div id="searchcontrol">Loading...</div>
<div id="search"></div>
Custom form using Google Search Ajax API
There are still some minor problems with the code above.
- Google will create a nice form, but there are no tools for customising its appearance
- Google logo - well I personally like it but would not the website owners mind displying the log even in cases where no search was performed
- Finally we can use options.setRoot to specify the element used for displaying the results. Sometimes, it would be convenient to replace the page content itself with the search results. Unfortunately, if we setRoot to the div element used to display the content of the page, it is set to zero, even if no search was made
Unfortunately it appears that the only way to get rid of these nuisances is to us the the crude search API. Originally I thought that it will be pretty easy to google out a working example, but it was not the case. The only code I found was this one and it did not work properly - for every search term, the same set of results was returned. Not encouraging. Soon I gave up attempts to fix this code and decided to make my own using Google AJAX search API documentation and the image search example. The code below should work properly, just enter your API key. You can see the code in action there
<!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>
<title>My Google AJAX Search API Application</title>
<style type="text/css">
.qw2 {color:#ff0000;font-weight:600;}
.qw3 {color:#aa0000;font-weight:300;}
</style>
</head>
<body>
<script src="http://www.google.com/jsapi?key=your-API-key-there" type="text/javascript"></script>
<script language="Javascript" type="text/javascript">
//<![CDATA[
/*
* The SearchControl manages searchers and draws a UI for them. However,
* searchers can be used by themselves without the SearchControl. This is
* called using a "Raw Searcher". When doing this, you must handle and draw
* the search results manually.
*/
google.load('search', '1');
var webSearch;
var gSearch;
function addPaginationLinks() {
// The cursor object has all things to do with pagination
var cursor = webSearch.cursor;
var curPage = cursor.currentPageIndex; // check what page the app is on
var pagesDiv = document.createElement('div');
for (var i = 0; i < cursor.pages.length; i++) {
var page = cursor.pages[i];
if (curPage == i) { // if we are on the curPage, then don't make a link
var label = document.createTextNode(' ' + page.label + ' ');
pagesDiv.appendChild(label);
} else {
// If we aren't on the current page, then we want a link to this page.
// So we create a link that calls the gotoPage() method on the searcher.
var link = document.createElement('a');
link.href = 'javascript:webSearch.gotoPage('+i+');';
link.innerHTML = page.label;
link.style.marginRight = '2px';
pagesDiv.appendChild(link);
}
}
var contentDiv = document.getElementById('content');
contentDiv.appendChild(pagesDiv);
}
function searchComplete() {
// Check that we got results
var contentDiv = document.getElementById('content');
contentDiv.innerHTML = '';
if (webSearch.results && webSearch.results.length > 0) {
// Grab our content div, clear it.
// Loop through our results, printing them to the page.
var results = webSearch.results;
for (var i = 0; i < results.length; i++) {
var result = results[i];
var resContainer = document.createElement('div');
resContainer.className='gw1';
var title = document.createElement('div');
title.className='gw2';
titulek='<a href="' + result.url + '">' + result.title + '</a>';
title.innerHTML = titulek;
var content = document.createElement('div');
content.className='gw3';
content.innerHTML = result.content;
/*
var newImg = document.createElement('img');
// There is also a result.url property which has the escaped version
newImg.src = result.tbUrl;
*/
resContainer.appendChild(title);
resContainer.appendChild(content);
// imgContainer.appendChild(newImg);
// Put our title + image in the content
contentDiv.appendChild(resContainer);
}
// Now add the paging links so the user can see more results.
addPaginationLinks(webSearch);
// setResultSetSize
var b= gSearch.getBranding();
contentDiv.insertBefore(b, contentDiv.firstChild);
}
else {
contentDiv.innerHTML = 'no results';
}
}
function OnLoad() {
gSearch= google.search.Search;
// Our ImageSearch instance.
// imageSearch = new google.search.ImageSearch();
webSearch = new google.search.WebSearch();
// Restrict to extra large images only
webSearch.setSiteRestriction('www.webdnes.cz');
// Here we set a callback so that anytime a search is executed, it will call
// the searchComplete function and pass it our WebSearch searcher.
webSearch.setResultSetSize(gSearch.LARGE_RESULTSET);
//searchControl.setResultSetSize(google.search.Search.LARGE_RESULTSET);
//gSearch.setNoResultsString(gSearch.NO_RESULTS_DEFAULT_STRING);
webSearch.setSearchCompleteCallback(this, searchComplete, null);
var query = document.getElementById("q");
webSearch.execute(query.value);
}
//google.setOnLoadCallback(OnLoad);
//]]> </script>
<form onSubmit="OnLoad();return false;">
<input type="text" id="q">
<input type="submit" value="vyhledat" name="cmdSubmit">
</form>
<div id="content">original content of this page</div>
