All posts by scott

Here are links to my public dropbox for the files we used in the tutorials

Step 1
http://dl.dropbox.com/u/34189153/step1.xml

Step 2
http://dl.dropbox.com/u/34189153/Step2.xml

Step 3
http://dl.dropbox.com/u/34189153/step3.xml

Context Info
http://dl.dropbox.com/u/34189153/context.xml

URL Gadget
http://dl.dropbox.com/u/34189153/URL_Example.xml

What’s this Context Info thing?!?!?

The context object is probably one the most important things about creating a gadget, but how do you know what it contains.  Here is a little gadget that can show you what it’s values are.   Just create a new project like you did for the other examples, and add it to all the integration points. When this app runs, it will show you all the values for the Context Object.  When this gadget runs it will output name value pairs in the form of  name : value.  This will all be contained between {}.  This is what is known as JSON notation before it was processed into a JavaScript Object.   For example,  lets take an object Person.  A possible JSON definition would be:

{
name: “bob”,
eyeColor: “red”,
height:”10ft”,
age: 25
}

If this were processed into an object, you could access person.name and get “bob”.  So here is the code!

Enjoy!

<?xml version=”1.0″ encoding=”UTF-8″?>

<Module>
  <ModulePrefs description="Displays the context information made available to the gadget.">
    <Require feature="opensocial-0.9" />
    <Require feature="sciverse" />
    <Require feature="dynamic-height"/>
  </ModulePrefs>
  <UserPref name="secureAuthtoken" datatype="hidden" />
  <Content type="html" view="canvas,profile">
	<![CDATA[
	<script type="text/javascript">

		function getContextInfo(){
			gadgets.sciverse.getContextInfo(contextCallback);
		}

		function contextCallback(obj){

		    var rs = JSON.stringify(obj);

		   //Format the string for display.
		    rs = rs.replace(/",/g,"\",<br>");

		    var contextInfo = document.getElementById("contextInfo");
		    contextInfo.innerHTML = rs;

 		    gadgets.window.adjustHeight();

		}

		gadgets.util.registerOnLoadHandler(getContextInfo);

	</script>

	<p><a href="javascript:void(0);" onclick="getContextInfo();">Reload Context Info</a></p>

	<div>
	  	<span>Secured Authtoken is: </span> <span>__UP_secureAuthtoken__ </span>
	</div>
	<div><u>Context Info:</u></div>
	<div id="contextInfo" style="display:block">

	</div>

	  ]]>

  </Content>
</Module>

The “URL” Gadget

During the workshop I briefly mentioned this illusive URL gadget. So, lets go ahead and give an example of one.  All an URL gadget is, is some web content that already exists and is accessible through an URL.  Ok, so what does that mean?  This means, any website on the web could be made into a possible gadget.   Here is all it takes… In the Content section tag make sure you have the type set to URL and then have an href attribute set to the site you want.  This example won’t look pretty in the profile view, but hit the canvas button and you’ll see the whole site..

<?xml version=”1.0″ encoding=”UTF-8″?>

<Module>
<ModulePrefs
        title="SciVerse Examples - Content API Call 1"
        title_url="http://developer.sciverse.com"
        author_email="you@you.com"
        description="Intro to Gadgets">
    <Require feature="opensocial-0.9" />
    <Require feature="sciverse" />
    <Require feature="hub" />
    <Require feature="dynamic-height"/>
    <Require feature="org.jquery.core-1.4.2" />
    <Optional feature="content-rewrite">
           <Param name="exclude-url">*</Param>
    </Optional>
</ModulePrefs>
<UserPref name="searchTerms" datatype="hidden" />
<Content type="url" view="profile,canvas" href="http://www.reddit.com/r/sydney"></Content>

</Module>

                            
                        
                        

Gadgets Example 3… A big leap forward

The last example was a pretty simple increment from the first.  This one is going to go full throttle and add the content API call and the rendering to deal with it.  Some new stuff you might see is the use of JQuery’s .each() function and the console.log() function. .each() (see here ) is used a lot when using JQuery. It allows you to iterate through arrays and even multiple instances of html objects that match a query. For example, if you have 10 elements that have the class “coolStuff”.  You can use $(“.coolStuff”).each(function(){stuff you want to do}); to iterate through each element.   Note: to access the actual element in your function use the this object.  One other thing that is super helpful is the console.log() call. If you’re using Firebug for FireFox, this call will print to the FireBug Console. If you aren’t using FireBug in FireFox, then you really need to start :) . Get it here!

So here we go..  All I really added was a couple more functions, a  number of results global variable, and my api key as a global variable.  As for the new funcitons, one makes the call to the content API and the other handles the response.  The console.log(text) call will show you what actually comes back from the Content API call. This can be useful to see what the data actually looks like, but once you know, you should probably get rid of it.   If you aren’t familiar with the JSON part of the code, don’t worry, I’ll try to follow up with an intro to basic JSON, or you can ask me tomorrow at the hack :) .

<?xml version=”1.0″ encoding=”UTF-8″?>

<Module>
<ModulePrefs
        title="SciVerse Examples - Content API Call 1"
        title_url="http://developer.sciverse.com"
        author_email="you@you.com"
        description="Intro to Gadgets">
    <Require feature="opensocial-0.9" />
    <Require feature="sciverse" />
    <Require feature="hub" />
    <Require feature="dynamic-height"/>
    <Require feature="org.jquery.core-1.4.2" />
</ModulePrefs>

<Content type="html" view="profile,canvas"><![CDATA[

<style>
	 #content_div{
		padding-top:15px;
	 	text-align:center;
		font-weight:bold;
	 }

	 .red{
	 	color:red;
		text-decoration:underline;

	 }

</style>

<script type="text/javascript" >  

	// global variables
	var myapikey = "30b684c9d37d7c9805e77d106a344df2";
	var context;
	var authTok;
	var searchTerms;
	var numberOfSearchResultsToReturn = 50;

	//The URL for the content API search call
	var apiSearchURL = "http://api.elsevier.com/content/search/index:";

	/**
	 * 'run' is called when the 'onload' event is triggered after the page finished loading
	 */
	function run()
	{
		// the getContextInfo is a framework API call that returns the ContextInfo object.
		// @see http://developer.sciverse.com/framework#context
		gadgets.sciverse.getContextInfo(init);
	}

	/**
	 * 'init' initializes the gadget. it sets the user's search term as the default search term.
	 * this is called when the contextInfo call above succeeds.
	 */
	function init(data){
		context = data;
		searchTerms = context.searchTerms;
		authTok = context.secureAuthtoken;
		makeContentApiCall();
	}

	/**
	* Prepare to make the content api call.
	*/

	function makeContentApiCall()
	{
		//get the search terms
		var SDSearchString = searchTerms;

		//url encode them so they don't mess up the html request
		SDSearchString = encodeURIComponent(SDSearchString);

		var nrOfResults = numberOfSearchResultsToReturn;
		var view = "COMPLETE";

		//the cluster or index we want to search against.
		var cluster = "SCIDIR";

		var search = apiSearchURL + cluster + "?query=" + SDSearchString + "&count="+nrOfResults+"&view="+view;

		//setup the authentication part of the call.
		/**You must have a apikey AND authtoken for content api calls**/
		var requestHeaders = {};
		requestHeaders['X-ELS-APIKey'] = myapikey;
		requestHeaders['X-ELS-Authtoken'] = authTok;
		makeApiRequest(search, apiResponse, requestHeaders);         

	}

	function makeApiRequest(url, callback, requestHeaders)
	{
	    var params = {};
	    params[gadgets.io.RequestParameters.HEADERS] = requestHeaders;
	    gadgets.sciverse.makeRequest(url, callback, params);
	}

	function apiResponse(obj){
	    var output = "";

	    if(obj == null){
		//if there is no response then we had an error
		var display = "<b><font color='red'>return object == null</font></b>";

		//use JQuery to set the html for the div
		$('#content_div').html(display);
		return;
	    }

	    var text = obj['text'];

	    // @see http://wiki.opensocial.org/index.php?title=Gadgets.json_%28v0.9%29
	    var textJson = gadgets.json.parse(text);

	    console.log(text);

	    //is there even any results?
	    if(!textJson){
		var display = "<b><font color='red'>parsing results returned nothing</font></b>"
		$('#content_div').html(display);
		return;
	    }

	    // @see http://www.json.org/js.html
	    var entries = textJson['search-results']['entry'];
	    numberOfEntries = entries.length;
	    output = output + "<b>number of entries: " + numberOfEntries + "</b><br>";

	    // @see http://api.jquery.com/jQuery.each/
	    $.each(entries, function(i1, entry){
		var title = entry['dc:title'];
		output = output + (i1+1) + ". " + title + "<br>";
	    });

	    $('#content_div').html(output);
	}

	// @see http://wiki.opensocial.org/index.php?title=Gadgets.util_%28v0.9%29#gadgets.util.registerOnLoadHandler
	//regester the onload function. When the page is fully loaded it will call this function
	gadgets.util.registerOnLoadHandler(run);

</script>

	<div id="content_div" style="font-size: 10;"></div>

]]></Content>

</Module>

Gadget Example 2. A small step forward.

So, in the last example I showed you how to get a property from the context info object and display it.  This next example is going to go a small step forward and add using user preferences. User Preferences can be used to add custom variables to your code and also pull in values from the frame work.  One of the most important ones you can do this with is the Secured Auth Token.  The Secured Auth Token is one of the required parameters needed to make Content Api Calls.  I’ve also added a call to adjustHeight().  This function will adjust the height of your gadget to fit it’s content.   In order for this to work you need to inlcude the feature “dynamic-height” in the Module Prefs.

On a side note:  One thing that might help new people to using some of the jquery functionality (code with $( ) ), is some JQuery Cheat sheets. Check it out here.  The JQuery Documentation can also be found at JQuery’s Site.

<?xml version="1.0" encoding="UTF-8"?>

<Module>
<ModulePrefs
        title="SciVerse Examples - Content API Call 1"
        title_url="http://developer.sciverse.com"
        author_email="you@you.com"
        description="Intro to Gadgets">
    <Require feature="opensocial-0.9" />
    <Require feature="sciverse" />
    <Require feature="hub" />
    <Require feature="dynamic-height"/>
    <Require feature="org.jquery.core-1.4.2" />
</ModulePrefs>

<UserPref name="secureAuthtoken" datatype="hidden" />
<UserPref name="myPref" datatype="hidden" default_value="This is my custom Pref" />
<Content type="html" view="profile,canvas"><![CDATA[

<style>
	 #content_div{
		padding-top:15px;
	 	text-align:center;
		font-weight:bold;
	 }

	 .red{
	 	color:red;
		text-decoration:underline;

	 }

</style>

<script type="text/javascript" >  

	// global variables
	var myapikey = "your api-key here";
	var context;
	var authTok;
	var searchTerms;

	/**
	 * 'run' is called when the 'onload' event is triggered after the page finished loading
	 */
	function run()
	{
		// the getContextInfo is a framework API call that returns the ContextInfo object.
		// @see http://developer.sciverse.com/framework#context
		gadgets.sciverse.getContextInfo(init);
	}

	/**
	 * 'init' initializes the gadget. it sets the user's search term as the default search term.
	 * this is called when the contextInfo call above succeeds.
	 */
	function init(data){
		context = data;
		searchTerms = context.searchTerms;
		authTok = context.secureAuthtoken;
		makeContentApiCall();
	}

	/**
	* Prepare to make the content api call.
	*/

	function makeContentApiCall()
	{  

		$("#content_div").append("<div>This is an auth Token from Context: <span class='red'> " + authTok + "</span></div><br/>");
		$("#content_div").append("<div>This is an auth Token from User Preferences: <span class='red'> __UP_secureAuthtoken__ </span></div><br/>");
		$("#content_div").append("<div>This is a custom user Preference:<span class='red'> __UP_myPref__ </span></div><br/>");
		$("#content_div").append("<div>The User's search terms:<span class='red'> " + searchTerms + "</span></div>");

		//automatically resize the height of the gadget to fit the content vertically
		//adjustHeight can also take a value like "399px"
		gadgets.window.adjustHeight();

	};

	// @see http://wiki.opensocial.org/index.php?title=Gadgets.util_%28v0.9%29#gadgets.util.registerOnLoadHandler
	//regester the onload function. When the page is fully loaded it will call this function
	gadgets.util.registerOnLoadHandler(run);

</script>
<div id="content_div" style="font-size: 10;"></div>

]]></Content>

</Module>

 

Intro to building gadgets

Ok, so I know everyone is excited to get started on their gadgets.  For those who want to  get something up and running quickly, follow me over the next few blog posts. I’ll slowly build from a basic gadget (printing search terms), to running a content api call to get results from ScienceDirect.  So lets get started.  Well, first you should sign up for a developer account at the developers site.  Then start a new project when you’re done there by clicking on Developers->My Projects-> Start New Application.  Ok, now we can get started.

For this example,  you’ll need to select the ScienceDirect Results page as your integration point when you create the gadget. It should look something like this:

Search Results Integration Point

 

All this gadget will do is print out the user’s search terms.  So to test the gadget, go to ScienceDirect, log in, and run a search. You should see something like this on the left hand side of your screen.  The text in the gadget will match whatever you searched for.

Step 1 Gadget

 

So how do we do this?  Well, here is the xml for our first basic gadget:

<?xml version="1.0" encoding="UTF-8"?>

<Module>
<ModulePrefs
        title="Step 1"
        title_url="http://developer.sciverse.com"
        author_email="you@you.com"
        description="Intro to Gadgets">
    <Require feature="opensocial-0.9" />
    <Require feature="sciverse" />
    <Require feature="hub" />
    <Require feature="org.jquery.core-1.4.2" />
</ModulePrefs>

<Content type="html" view="profile,canvas"><![CDATA[

<style>
	 #content_div{
		padding-top:15px;
	 	text-align:center;
		font-weight:bold;
	 }

</style>

<script type="text/javascript" >  

	// global variables
	var context;
	var searchTerms;
	var docTitle;
	/**
	 * 'run' is called when the 'onload' event is triggered after the page finished loading
	 */
	function run()
	{
		// the getContextInfo is a framework API call that returns the ContextInfo object.
		// @see http://developer.sciverse.com/framework#context
		gadgets.sciverse.getContextInfo(init);
	}

	/**
	 * 'init' initializes the gadget. it sets the user's search term as the default search term.
	 * this is called when the contextInfo call above succeeds.
	 */
	function init(data){
		context = data;
		searchTerms = context.searchTerms;

		$("#content_div").html(searchTerms);

	}

	// @see http://wiki.opensocial.org/index.php?title=Gadgets.util_%28v0.9%29#gadgets.util.registerOnLoadHandler
	//regester the onload function. When the page is fully loaded it will call this function
	gadgets.util.registerOnLoadHandler(run);

</script>

	<div id="content_div" style="font-size: 10;"></div>

]]></Content>

</Module>

 

Gadgets. A first look.

In order to create a gadget for the sciverse platform, you need to understand the structure of the gadget xml file.  There are three main parts.

The Module Preferences section:
<ModulePrefs title=”MyAwesomeGadget” author_email=”you@your.domain”>

  </ModulePrefs>

The user preference section:

<UserPref name=”secureAuthtoken” datatype=”hidden” />

Then the Content sections.  You can have a content section for each type of integration point.  See here for info on integration points.  You can also combine integration point definitions by simply listing them  (i.e. view=”profile, canvas”)

  <Content type="html" view="profile">
  <![CDATA[
     <!-- The code for the view is here. -->
  ]]>
  </Content>

When all of this is combined, you will have the basic skeleton for a gadget:

<?xml version=”1.0″ encoding=”UTF-8″?>

<Module>
  <ModulePrefs title="MyAwesomeGadget" author_email="you@your.domain">

  </ModulePrefs>

  <UserPref name="secureAuthtoken" datatype="hidden" />

  <Content type="html" view="profile">
  <![CDATA[
    <!-- The code for the view is here. -->
  ]]>
  </Content>
</Module>