YoYo! India Application Development

Quick Start Guide for Developers

Do you have the cerebral fitness and mental sharpness to develop the next best thing on the YoYo! India social networking platform? Develop a YoYo! and be a winner. Here is your chance to show what you are made of.


Getting Started

Here is a list of things you will need to get started:
  1. - Firefox web browser
  2. - Firebug debugger
  3. - The YoYo India API (which includes the Dojo Framework 0.9)

Firefox web browser

Download the latest version of Firefox from: www.mozilla.com/firefox/. Install the Firefox.

Firebug debugger

- Startup Firefox and go to the following web page: addons.mozilla.org/en-US/firefox/addon/1843
- Click on the "Add to Firefox" button. You will be asked to if you want to install Firebug (an unsigned Firefox add-on).
- Click on the Install button after the security count down and restart Firefox when the installation is complete.

We have found that Firefox verions 2.0 and Firebug version 1.3 is NOT a good combination. Firefox constantly crashed when trying to debug code. Currently we are all using Firefox 2 and FireBug 1.05 with good success.

The YoYo India API

- First download the YYI API from here: yyi-api.zip
The YYI API also includes a stripped down Dojo toolkit version 0.9. (The Dojo examples are not included)
Dojo is a client side Javascript library. For more info on Dojo see: www.dojotoolkit.org
- unzip the yyi-api.zip file into a directory of your choosing.
For example, if you unzip the file into C:\development\yyi, you have the following directory tree:
dtree

The Example Yoyo

Loader

Before we jump into the deep end, let us quickly look at the test harness or wrapper html file that will load the example Yoyo.
Open up the dojo/ref.html file, with your browser. You should see:
ryy

The ref.html file is a wrapper html page that loads the example yoyo.
Open the ref.html file with a text editor. (Preferably with a text error that supports syntax validation and code completion. Look here here for some options.)
The wrapper page is generic and should not contain any specific yoyo code other than shown in orange:


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Test the reference gadget</title>
.
.
.
<!--for debugging purposes: -->
<!--For firebug to find our source code, we have to include it here-->
<script type='text/javascript' src='yoyo/Reference.js'></script>
.
.
.
// this will load the reference yoyo
var cp = g_createContentPane({
url: "yoyo/reference.html"
});
.
.
.

Example Yoyo

When designing new Yoyos you need to follow the template set forth in the reference files:


Now open up the reference.html file with your text editor. In this html file you will see three sections:

  1. - the first, is the includes. Here we load all the Dojo components that we are going to place in the view. The last line in this section loads the controller for this Yoyo.
  2. - the second is the code that initializes the controller and injects the GUI components that we are going to place on the page into the controller.
  3. - lastly, we create and layout our view components.

Includes:

We are using the dojo require function to load include files from the server.
dojo.require will ensure that resources are downloaded only once for the application - thus limiting bandwidth usage and increasing start-up time.
We must include all the necessary include files for the dojo components we use in section 3.

// dojo imports: import the dojo graphical components that we will use
dojo.require("dijit.form.Button");
dojo.require("dijit.form.TextBox");
dojo.require("dijit.form.Form");
dojo.require("dijit.Dialog");
dojo.require("dijit.layout.ContentPane");
dojo.require("dijit.form.CheckBox");
dojo.require("dijit.form.FilteringSelect");

// loads the controller
dojo.require("yoyo.Reference");
You might have noticed that from the reference.html file that you are allowed to include a css file too.

Instantiating the controller and injecting view components

Here we will instantiate the controller and populate it with references to the visual components defined in section three.
The g_addOnLoad function is a global YYI function defined in the script/Util.js file. It will ensure that the code in this section will only be executed after the thrid section has finished loading.

g_addOnLoad(_container_, function() { // only after the html has loaded

// instantiate the controller
var controller = new yoyo.Reference();

try {
// Here we link up the view components with the controller
// see how we use the id of elements and dojo widgets
var view = {
contentPane: _container_,
saveButton: dijit.byId('_uuid_save'), // a widget: dijit.byId
deleteButton: dijit.byId('_uuid_delete'),
addButton: dijit.byId('_uuid_add'),
closeButton: dijit.byId('_uuid_close'),
cityCombo: dijit.byId('_uuid_cityCombo'),
configSection: dojo.byId('_uuid_config'), // a normal div node: dojo.byId
tableContents: dojo.byId('_uuid_contents'),
configure: dojo.byId('_uuid_configure')

}

// pass references of the view components to the controller
controller.setView(view);

// tell the controller to start
controller.afterPropertiesSet();

// will call controller.finalize() when the yoyo is closed
//g_installStandardOnUnload(_container_, controller);

} catch(ex) {
console.error(ex);
alert("unable to initialize gadget");
}
});

View creation and layout

This section defines and positions visual components used by the Yoyo. Many of the components are static html. However, some components will be dynamic. The dynamic components will be modified in run-time by the controller depending on the data it receives from server and on the actions of the user. The controller therefore needs a handle to each dynamic component. We use the id of the visual component to find a handle to it.

The controller will be able to install event handlers to user interaction with visual components (like running a specific function when a button is clicked). The controller will be able to populate a visual component depending on data it retrieves from the server (like populating a list with weather entries).

<!-- Here we define the view components of the MVC app-->
<div class="pageHeading" align="center">Reference YoYo - an example</div>
<div class="yoyo">
This is the reference YoYo. Use it as a template when developing new YoYos. This YoYo will show the temperature and weather. The example shows you how to read information from the server and how to write data to the server by saving your default city.
</div>
<div class="yoyo">
<table width="80%" id="_uuid_contents">
<!--this will be re-generated by the controller-->
<tr>
<td width="12px" style="display:none;"><div dojotype="dijit.form.CheckBox"> </div></td>
<td><div class="cloudy"> </div></td><td>Paris</td><td>12C</td>
</tr>
<tr>
<td width="12px" style="display:none;"><div dojotype="dijit.form.CheckBox"> </div></td>
<td><div class="sunny"> </div></td><td>Monaco</td><td>12C</td>
</tr>
</table>
<br>
<a href="#" id="_uuid_configure">Configure Weather yoyo</a>
</div>
<div class="yoyo" id="_uuid_config" style="display:none;">
<!--this list could have been read from the server (instead of being static)-->
<select dojoType="dijit.form.FilteringSelect" autocomplete="true" id="_uuid_cityCombo">
<option value="none"></option>
<option value="Paternoster">Paternoster</option>
<option value="Detroit">Detroit</option>
<option value="Atlanta">Atlanta</option>
<option value="Minneapolis">Minneapolis</option>
<option value="Lourenco Marques ">Lourenco Marques</option>
<option value="Salisbury">Salisbury</option>
<option value="Los Angeles">Los Angeles</option>
<option value="Buenos Aires">Buenos Aires</option>
<option value="Santiago">Santiago</option>
<option value="Christchurch">Christchurch</option>
<option value="Perth">Perth</option>
<option value="Antwerp">Antwerp</option>
</select>
<button dojoType="dijit.form.Button" iconClass="ok-icon" id="_uuid_add" disabled>Add</button>
<button dojoType="dijit.form.Button" iconClass="cancel-icon" id="_uuid_delete" disabled>Delete</button>
<br><br>
<button dojoType="dijit.form.Button" iconClass="ok-icon" id="_uuid_close">Done</button>
</div>

You will notice the _uuid_ prefix that we use in the id attribute of the elements. The reason for this is that we might want to create more than one instance of a specific Yoyo in our application. And to be able to distinguise between elements on different Yoyos, the DOM ids for the components in the Yoyo must be different. The g_createContentPane method used in the wrapper page will replace the occurences of _uuid_ with a unique number after it has loaded the html file (but before instantiating the controller).

CSS styles are read from the YYI API app.css file and from the YoYo specific reference.css file. If your YoYo needs special image files it can be included inside the yoyo/images directory. Ok and Cancel buttons have predefined icons that can be used by your YoYo and sourced from the dojo/images directory.

Controller code

The YoYo controller is a Javascript 'class' that must define at least the following functions

The setView(view) function is a setter that received a view object. The view object instance (is a javascript object) contains a name-value pair. Each name identifies a graphical component and its value is a handle to the graphical component.

The afterPropertiesSet() function is called after all the necessary setup functions have been called on the controller. Its first task is to ensure that all the necessary parameters were properly configured. If everything checks out ok, it calls the remaining two functions.

The _installCallbacks() function is responsible for assigning callback funcitons (event handlers) to for events generated by graphical components. For example when the add button is clicked we want the _addCity() function to be called on this contoller instance. We use the dojo.hitch function to scope the callback.

The _populateView() function must initiate all the server calls needed to populate the YoYo's view. If you look at the function in the reference.js file you will notice that it firstly, resets some of the view component's states and then it makes a server call. More about server calls next.

Making server calls

It is important to make your server calls in the same way as we discuss here. Lets take a look at some code:

this._populateView = function() {
// reset some view component states
this._view.deleteButton.setDisabled(true);
this._view.cityCombo.setValue("none");
// make a call to the server
try {
console.debug("Reading my weather info");
// retrieve weather data from the server asynchronously
// calls this._populateWeatherData(response) with the weather data
yoyoUtil.showYoYoToasterMessage("Loading weahter data...");
ReferenceServerInterface.getWeather(dojo.hitch(this, this._populateWeatherData));
} catch (ignore) {
// simulate
this._populateWeatherData(this._getWeatherDummyResponse());
}
}

Firstly, take note that we wrap the server call in a try catch block. This allows us to simulate a response from the server. This gives you the ability to develop YoYo's without having to install a server at all! Once you are done with the YoYo, anyone can reference the simulated response and implement the necessary server code for the YoYo.

Secondly, lets look at an actual server call:

ReferenceServerInterface.addCity(selectedCity, dojo.hitch(this, this._populateView));

The ReferenceServerInterface class does not exist at development time but once you are done with the YoYo development this class will be generated.

The addCity function on the server is called. All but the last parameter is passed to the addCity function. Something that is not quite obvious is the fact that we are not telling the server which user is making the call. So you may rightly wonder how the server knows who is adding a city to his weather YoYo... The answer is that the browser session will be associated to a specific user on the server - therefore the server knows who is making the call by looking at the browser session id which is done when the user logs in.

The first parameter selectedCity is the city that the user selected in the combo box.

The very last parameter of the server call must be a callback function. This is the function that will be called when the server call returns successfully. In the example above, the _populateView function will be called.

To illustrate what happens when a function returns from a server call, lets look at another example:

ReferenceServerInterface.getWeather(dojo.hitch(this, this._populateWeatherData));

You can see that this server function call will retrieve the weather information for the calling user from the server. When the call returns it will call the _populateWeatherData function with the weather information that it retreived. Very important is the mirrored function call in the catch block!

this._populateWeatherData(this._getWeatherDummyResponse());

In the catch block you must generate dummy weather information - in exactly the same format as the server would return the weather information. With this generated data you must call the same callback function. This allows you to run your YoYo without any server or server software. Please dont try to simulate the exact server functionality, for example, when you click addCity() you would expect the server to actually add the city to the users list of cities. But for simulation purposes we dont want to mirror that functionality in the client side code because we dont want to polute the client side code with unnecessary code.

Wrapping it up

  1. - Please rename your js, html, css and properties files to a more descriptive name.
  2. - update the properties file with a name and description for your YoYo.
  3. - zip up the yoyo directory and mail it to yyi.subs@yoyoindia.com Place the following text (exactly) in the email subject: YoYo Submissions
We will review your YOYO by running it in simulation mode. If we like what we see we will contact you. You might be the winner of a great prize!