Live Spaces: The challenges facing gadget developers

My name is Donavon West, a Live.com and Sidebar gadget developer at LiveGadgets.net and a Microsoft MVP for Windows Live Development. This is my first blog article here at LiveSide. Many of you have written gadgets for Live.com (what Microsoft is now referring to as "web gadgets").  The introduction of gadgets on Windows Live Spaces introduces many new challenges for developers. Here are a few: 

Author vs. Visitor modes

With traditional Live.com gadgets, the person that placed a gadget on the page was the only person to view it. Windows Live Spaces a new paradigm. Now anyone with access to the Internet can view your gadget. But, you don't want to give everyone the right to change the gadget's settings. Because of this, gadgets now operate in one of two modes: author and visitor.

Let's examine the two modes using the iTunes gadget that I recently wrote. It displays album art, song title and artist from the iTunes most popular songs RSS feed. It also allows the user (we'll get to the definition of "user" in a moment) to select from a list of genres to display as well as the color of the virtual "iPod".

When you place the iTunes gadget on a page in Live.com, the user can adjust the various settings. This is what is called "author mode". In author mode, controls are exposed by the gadget to alter it's behavior. For example the user/author could select the genre Hip Hop/Rap. With Live.com there is only one mode: author.

With Windows Live Spaces, the author is the person who "owns" the site (i.e. yoursite.Spaces.Live.com). The "visitor" would be one of the visitors to the site. In many cases you do not want viewers to change certain aspects of the gadget. In the previous example, if you place the iTunes gadget on your space and set it up to display Hip Hop/Rap (because that's the kind of music you like), you may not want your users to alter this. Therefore, in visitor mode, setting controls are hidden (i.e. there is no "Change Genre" button).

setPreference doesn't work!

Normally, when you want to save some user setting (again, like the genre mentioned above) in author mode, you would call p_args.module.setPreference() with the name/value pair that you would like to persist. This works fine when your gadget runs on Live.com. If you try and do the same thing in Live Spaces the underlying HTTP call returns a response code of 500 (SERVER ERROR) and your settings are lost.

What can you do about this? About the only thing you can do (short of praying to the Spaces God, or Gods if you are a BSG fan) is to write and host your own data store. But before you do, consider this; your gadget may end up of thousands of spaces around the world. This means thousands of database records to store the gadget's settings and potentially millions of HTTP hits on your server. If your hosting company charges by the megabyte, this could amount to a costly gadget.

So all you have to do is write a web service and call it with the user data and some unique ID. On Live.com you would do a module.GetId(), but when you try this on Live Spaces, you get some long string something like this:

GadgetGallery:http://somedomain.com/gadget/gadget.xml

Not much good as this is the same ID that you will get on each of the thousands of Live Spaces on which your gadget resides. No, you need something to uniquely identify the Live Space that you gadget is installed on. Fortunately, I know the secret and equally as fortunate for you, I'm going to tell you what the secret is. 

But first, here's a hint. On your Live Space, right-click somewhere on the background of your gadget's iframe and select properties. Take a look at the URL. Do you see anything that might be unique to the particular space you gadget is running on? Yes, you do. There is a "&host=foo.spaces.live.com" in the URL.

Sweet, you say. But how does that help me? Well I thought you might ask that. All you have to do is parse the URL and return all query string and hash (the stuff following the "#") parameters. When you are done, the value for host will be your unique ID. (Note: this ID is unique to the apace and not to an instance on the space; that is to say that you can only have one copy of your gadget on any given Live Space). Oh, I'm not going to write the parsing code for you. You'll have to figure that out for yourself. :)

Transparent background

With Live.com gadget, programmers just got used to setting the backgroundColor of their DIV class to white/#ffffff or leaving it blank to inherit the background color of the body. The body of a non-certified gadget is the controlled by the HTML page that loaded in the iframe. You gadget runs inside of a DIV on this HTML page. As any piece of code running on a web page, you have full control of the document (and thus the body element) of the page.

itunes-transparent Developer

To successfully have a transparent background in an iframe, you need 2 things. 1) the parent iframe element must set attribute allowTransparency="true". As luck would have it, the Live Spaces people have been gracious enough to oblige.

The other part of the equation is to set the backgroundColor of the body element of the HTML page within the iframe to transparent. Here is the code to do just that:

if (window.parent != window.self) {
    document.body.style.backgroundColor = "transparent";
}

If you look at the example shown above, the gadget on the left has the code above applied. The gadget on the right has not. Note that the 2 gadgets also have different background iPod images (one black and one white). This has nothing to do with the backgroundColor code.

 

p_args are different

Arrrrrrg! When a gadget is instantiated, it is passed 3 parameters: p_el, p_args and p_namespace (p_namespace if currently unused). p_el is a pointer to the DIV element where your gadget is bound to or "lives". p_args is an object that contains many useful properties. Here is what p_args looks like in VS2005 with the iTunes gadget running on Live.com compared to Live Spaces:

//Live.com
feed: {…}
feedUrl: "http://localhost/gadgets/itunes2/gadget.xml"
xml: {…}
defaults: {…}
module: {…}
loc: "us"
mkt: "en-us"
lang: "en"
fullMode: false
paramString: "{"uri":"http://localhost/gadgets/itunes2/gadget.xml","listIcon":null}"
mode: "author"
id: "a80d2672-0058-42d1-b952-1e718b6565bd"
gadgetHost: {…}
uri: "http://localhost/gadgets/itunes2/gadget.xml"
listIcon: null
onDashboard: true
xmlSources: {…}

//Live Spaces
xml: {…}
module: {…}
onDashboard: false
ownermkt: "en-us"
alias: undefined
xmlSources: {…}

Wow, that's a big difference. I won't go into the meaning of them all, but some notable standouts include: defaults and feed. Of course it would be nice if id were set to the Live Spaces host name so we wouldn't have to go through all that trouble that we did above. Oh, and the "M" in ownermkt should be capitalized. ;)

Test Platform
gadget

To help to keep tabs on what p_args are supported on Live.com and Live Spaces, I've written a tool called TestPlatform. The manifest URL is:  http://test.livegadgets.net/gadgets/TestPlatform/gadget.xml. It displays 2 of the most important aspects of the gadget framework, p_args and p_args.module.

testplatform Developer

 

Gadget Platform Test Page

If you want to see how your web gadget will look on Live Spaces (both author and view modes) and on Live.com, here is a link you should know about. http://test.livegadgets.net/gadgets/TestPlatform/testpages.htm

testplatformpage Developer

 

As Live Spaces matures and the line between gadget platforms starts to come together as one codebase, many of these issues will go away. Until then, I hope these tips help you develop better gadgets that play well on Live.com and Live Spaces.

donavon