Google Code offered in: English - Español - 日本語 - 한국어 - Português - Pусский - 中文(简体) - 中文(繁體)
This tutorial covers the basics of API- and event-based programming using the Google AJAX Search API. The pre-requisites include the material covered in our other tutorials on CSS, DHTML and Javascript, and Ajax.
An application programming interface (API) is the set of tools provided by an operating system, library or application which allow programmers to use its services or data. A good example of an API is a graphics library, such as OpenGL. A group of programmers created the OpenGL library by designing and implementing sophisticated graphics capabiliites into a set of functions such as:
glutWireSphere (radius, slices, stacks); glutSolidTeapot(size); glColor3i(red, green, blue);This library of functions make it possible for programmers without graphics expertise to create scenes, animations, and graphical user interfaces which if not for the OpenGL API, they would not have been able to implement. All one needs to do to use the OpenGL API is include its libraries when compiling and linking.
Some APIs (OpenGL is a good example) require quite a bit of knowledge and practice to use correctly. The Google AJAX Search APIs are not nearly as complicated as OpenGL, but there are some things you need to do to get things to work right.
Most of us are familiar with the structured programming paradigm where we work with data
through control structures such as if else, while, for, and so on. For example:
if (value == MAXLIMIT)
value = newValue - oldValue;
else {
while (true) {
...
if (newValue == MINLIMIT) {
for (int i = 0; i < newValue; i++)
...
else
break;
}
}
}
The path through this program is defined by the values of the various data elements and the control structures. Contrast this with an event-based program, where the program sits idly waiting until the user does something. The path through such a program is controlled by user-generated events, as opposed to control structures operating on data.
The most important elements of an event-driven program are the event-handlers. These are functions in the program that are called in response to a user event. The events can occur in any order and at any time, which is quite different from the structured approach. You cannot assume that a user has entered data in some particular order or caused a sequence of events to occur in some particular order. You can't even assume anything at all has happened.
Events are recognized via special structures available in APIs or programming languages. For example, in OpenGL, we have an event loop and callbacks:
// create a window
glutCreateWindow("OpenGL");
....
// register a callback
glutMotionFunc(myMovedMouse);
// wait for events
glutMainLoop();
Some APIs in event-based programming provide functions that allow us to register user-defined functions to be called when
a particular event occurs. These user-defined functions are designated callbacks. In the code above, glutMotionFunc()
is provided by the API, and myMovedMouse is a function that the programmer writes which is called when
the mouse is clicked and dragged.
The API function glutMainLoop() is an event loop that executes continuously until an event occurs. Based
on the event type, the appropriate event handler (callback) is executed. This program does not do anything until an event occurs.
Google engineers have created a set of APIs using the AJAX programming model. This is inherently an event-based model. Let's start by looking at a simple 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" xmlns:v="urn:schemas-microsoft-com:vml">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>Hello World</title>
<!-- std apis -->
<script src="http://www.google.com/uds/solutions/cscintro/stdlib.js" type="text/javascript"></script>
<link href="http://www.google.com/uds/solutions/cscintro/stdlib.css" rel="stylesheet" type="text/css"/>
<!-- base-styles for my demos -->
<link href="base-styles.css" rel="stylesheet" type="text/css"/>
<!-- main -->
<script type="text/javascript">
function main() {
var log;
log = new StdLog(document.getElementById("log"), "stdout");
log.printLine("Hello World");
}
</script>
</head>
<body onload="main()">
<h1>Simple Hello World</h1>
<div id="log">Loading...</div>
</body>
</html>
Notice we are importing two API files: stdlib.js and stdlib.css. The first file contains a set
of standard functions available for us to use in our html files. In main(), we create a StdLog() object and
call its printLine method to place a window on the screen and print a string in the window. We call main()
when the html file is loaded (in the body tag).
The second API file contains a set of css definitions for StdLog().
StdLog object in the file above. Notice the use of DOM, DHTML and CSS in the
methods of this file. You can view http://www.google.com/uds/solutions/cscintro/stdlib.css to see the CSS tags.
In this second example, we print an array. This shows some simple Javascript functionality and printing the results in the stdout window.
<!-- main -->
<script type="text/javascript">
function main() {
var log;
log = new StdLog(document.getElementById("log"), "stdout");
// print array forwards
log.printLine("My array has: " + myArray.length + " entries");
var i;
for (i=0; i < myArray.length; i++) {
log.printLine("[" + i + "] " + myArray[i]);
}
log.printLine("");
}
myArray = ["cat", "dog", "car", "house", "tennis", "skateboard", "baseball"];
</script>
</head>
<body onload="main()">
<h1>Print an Array</h1>
<div id="log">Loading...</div>
</body>
<!-- main -->
<script type="text/javascript">
var gLog;
function main() {
gLog = new StdLog(document.getElementById("log"), "stdout");
}
function printArray(fForward) {
var i;
gLog.printLine("My array has: " + myArray.length + " entries");
if (fForward) {
for (i=0; i < myArray.length; i++) {
gLog.printLine("[" + i + "] " + myArray[i]);
}
gLog.printLine("");
} else {
i=myArray.length - 1;
do {
gLog.printLine("[" + i + "] " + myArray[i]);
i--;
} while ( i >= 0 );
gLog.printLine("");
}
}
myArray = ["cat", "dog", "car", "house", "tennis", "skateboard", "baseball"];
</script>
</head>
<body onload="main()">
<h1>Print an Array</h1>
<input type="button" value="Print Array Forwards" onclick="printArray(true)"/>
<input type="button" value="Print Array Backwards" onclick="printArray(false)"/>
<div id="log">Loading...</div>
</body>
onClick
attributes call the printArray function with the appropriate value to indicate a forward or backward
traversal through the array. Notice that main() is called in the body tag to set up the window.
Now we can take a look at the Search APIs, which are made available through the following:
<!-- google search api -->
<script src="http://www.google.com/uds/api?file=uds.js&v=1.0&key=YOUR_KEY" type="text/javascript"></script>
Here is a program that allows a user to enter a search term, performs the search by calling Google's Search API methods and returns the top eight results. In order to do this search, the API methods use AJAX to send the query terms to the search engine. Then, DOM, DHTML and CSS are used to update the page.
<!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" xmlns:v="urn:schemas-microsoft-com:vml">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>Print Search Results</title>
<!-- google search api -->
<script src="http://www.google.com/uds/api?file=uds.js&v=1.0&key=internal-solution" type="text/javascript"></script>
<!-- std apis -->
<script src="http://www.google.com/uds/solutions/cscintro/stdlib.js" type="text/javascript"></script>
<link href="http://www.google.com/uds/solutions/cscintro/stdlib.css" rel="stylesheet" type="text/css"/>
<!-- base-styles for my demos -->
<link href="base-styles.css" rel="stylesheet" type="text/css"/>
<!-- main -->
<script type="text/javascript">
var gLog;
var gSearch;
function main() {
gLog = new StdLog(document.getElementById("log"), "stdout");
gSearch = new GwebSearch();
gSearch.setResultSetSize(GSearch.LARGE_RESULTSET);
gSearch.setSearchCompleteCallback(null, searchComplete, [null]);
}
function startSearch() {
var input = document.getElementById("input");
if (input.value) {
gLog.printLine("Search Results for: " + input.value);
gSearch.execute(input.value);
} else {
gLog.printLine("*** Error. Enter a Search Term ***");
}
}
function searchComplete() {
if (gSearch.results && gSearch.results.length) {
var i;
for (i=0; i < gSearch.results.length; i++ ) {
var result = gSearch.results[i];
gLog.printLine(result.title + " @ " + result.url);
}
gLog.printLine("");
} else {
gLog.printLine("*** Error. No Search Results ***");
}
}
</script>
</head>
<body onload="main()">
<h1>Print Search Results</h1>
<div class="input-box">
<input type="text" id="input"/> <input type="button" value="search" onclick="startSearch()"/>
</div>
<div id="log">Loading...</div>
</body>
</html>
The main() function sets up the window and then calls the GwebSearch constructor.
We set the result size (to eight) and then define a callback (searchComplete()) which we implement
using stdlib.js methods. Notice that we have access to the results array returned
by the search engine in our callback.
The startSearch() method is called when the button event occurs. The key method call here is
gSearch.execute(input.value) which uses AJAX to send the input value to the search engine
and then calls the callback funtion when the results are returned.
For more information on the Search APIs, check out the API reference.
Finally, check out the following program which shows how to incorporate various searches in any web page, as opposed to printing results in a stdout window. Here is a short tutorial that takes you through building this program.