Zoek

Uitgebreid zoeken Artikelen per auteur

  

Developing Vista Gadgets met Visual Studio 2008

Developing Vista Gadgets met Visual Studio 2008

Ben jij een JavaScript developer? Als je ooit iets voor een webapplicatie hebt ontwikkeld, dan zul je zeker in aanraking zijn gekomen met JavaScript. Bedoeld of onbedoeld ben je gebombardeerd tot JavaScript developer. Als je al wat onderzoek hebt gedaan naar het ontwikkelen van Vista Gadgets - weet je wel, die handige tools die in je Vista Sidebar zitten - dan weet je dat die gadgets eigenlijk niet meer dan HTML en JavaScript zijn. Hmmm... weer dat JavaScript. Dat zal Microsoft ook gedacht hebben, want met de introductie van Visual Studio 2008 wordt als onderdeel van de HTML editor een JavaScript debugger meegeleverd. Eindelijk de mogelijkheid om stap voor stap door je JavaScript te debuggen en om er nog een schepje bovenop te doen heeft JavaScript nu ook Intellisense.

In dit artikel zullen we met behulp van VS2008 een gadget ontwikkelen om random een Champions League video van Internet te plukken en deze in onze sidebar te tonen. Nu is het afstruinen van Internet, op zoek naar een video, iets te veel van het goede om te implementeren in een Vista Gadget, en we zullen dus gebruik moeten maken van een search engine. In mijn gadget maak ik gebruik van Truveo, de video search engine van AOL. Ik heb wel eens gelezen dat deze beter is dan die van Google en bovendien heb ik die API al eens eerder gebruikt om een ander gadget te maken.

Script Debugging

Om te debuggen is het nodig om de juiste instellingen in Internet Explorer te hebben. Je moet namelijk de optie ‘Disable script debugging’ uit zetten (zie figuur 1).

EnableDebugging.png

Fig. 1: Enable Script debugging

Om te beginnen met debuggen moet je eigenlijk je gadget al hebben geïnstalleerd. Laten we even vooruitlopen op de zaken en er vanuit gaan dat er een draaiende versie van de gadget is. Je kunt nu Visual Studio 2008 opstarten en door te kiezen voor de menuoptie ‘Debug’ en dan ‘Attach to Process’ het proces selecteren dat je wilt debuggen.

SelectProcess.png

Fig. 2: Selecteer te debuggen proces

We kiezen voor onze UEFA Champions League Video of the Day gadget. Merk op dat de procesnaam ‘sidebar.exe’ is en dat het type op script staat. Indien er geen ‘Script’ staat onder type, dan heb waarschijnlijk je Internet Explorer settings nog niet goed staan.

Vervolgens moet je zorgen dat je de HTML-source van de gadget opent. Om die te vinden moet je weten waar gadgets geïnstalleerd worden. Ga naar je user folder, normaliter ‘c:\users\’. Hierbinnen zit een hidden folder ‘appdata’. Je ziet hem standaard niet in je Explorer, maar als je als foldernaam ‘c:\users\\appdata’ intikt, kun je er gewoon naar toe. De folder waar je naar toe wilt is ‘c:\users\\appdata\local\Microsoft\Windows Sidebar\Gadgets\’ (in mijn geval dus ‘c:\users\Mark\appdata\local\Microsoft\Windows Sidebar\Gadgets\UEFA.gadget’).

Je opent het HTML-file en kunt nu een breakpoint zetten.

Debug.png

Fig. 3: Debugging Javascript

Ok, genoeg vooruit gekeken, tijd om terug naar het begin te gaan en de gadget te gaan bouwen.

De Champions Leaque gadget

Laten we eerst even kijken hoe de gadget eruit zal zien als die af is. Dat geeft tenminste een beeld van waar we naar toe zullen werken. We willen een gadget dat random een link aanbiedt naar een recent geplaatste Champions League video. We willen dit graag in onze Windows Vista sidebar hebben zitten zodat we op momenten dat we even een korte break nodig hebben naar het gadget kunnen kijken, zien of er iets interessants te bekijken valt en direct naar de video klikken. Als er niks interessant getoond wordt, zullen we door middel van een klik op het UEFA logo een nieuwe random search doen. De gadget ziet er zo uit:

Gadget.JPG

Fig. 4: De uiteindelijke gadget

Als je de gadget wilt installeren, ga dan naar http://gadgets.develop-one.com. 

Truveo RSS API

Truveo biedt een uitgebreide API zodat je zoekopdrachten kunt geven via XML, Ruby, Flash of AJAX. De Truveo website biedt echter ook de mogelijkheid om op basis van zoektermen een custom RSS feed aan te maken. Dit leek me op het eerste oog wel makkelijk, dus heb ik deze methode gebruikt voor m’n Champions League gadget.

Om te komen tot de juiste feed ben ik naar de Truveo site gegaan en heb ik een zoekopdracht gedaan naar ‘UEFA’. Hierbij kwamen wel wat interessante links voorbij, maar weinig recente videos. De meest recente was 2 dagen oud, dus heb ik even geprobeerd om te zoeken naar ‘champions league’ en jawel … legio hits! Om te zorgen dat ik alleen de recente videos zie, heb ik de resultaten gesorteerd op ‘Most Recent’. Door op het aanwezige RSS feed icon te klikken, krijg je vervolgens toegang tot de URL die je nodig hebt om de RSS XML te benaderen. In ons geval is de URL http://xml.truveo.com/rss?query=champions%20league%20sort%3AmostRecent.

Door de URL te openen in je browser kun je de feed bekijken: Internet Explorer parst te XML en acteert als een blogreader. Door ‘View Source’ te kiezen kun je naar de onderliggende XML kijken. Met een beetje copy-en-paste werk hebben we de informatie van een individuele video te pakken:



Week 11:  Vince Young highlights

 http://xml.truveo.com/rd?i=1828017150&a=rss&p=2


 http://xml.truveo.com/rd?i=1828017150&a=rss&p=2

<img
 src="http://thumbnail.search.aolcdn.com/truveo/images/
   thumbnails/6D/C5/6DC54186D81E95.jpg">
 <br>
 Highlights of Vince Young in the Titans 34-20 loss to
 the Broncos.

Tue, 20 Nov 2007 02:26:27 -0500
NFL.com
 url="http://xml.truveo.com/rd?i=1828017150&
   a=rss&p=2"
 duration="143" lang="en-US" medium="video" />
NFL Films

  © 2007 NFL Enterprises LLC

Sports

  Tennessee Titans, Denver Broncos, Vince Young

 url="http://thumbnail.search.aolcdn.com/truveo/images/
   thumbnails/6D/C5/6DC54186D81E95.jpg"/>

Dit is de XML waar we later de link, thumbnail en description uit zullen parsen.

De gadget bouwen

Zoals al eerder gezegd: Windows Vista gadgets zijn gewoon HTML en JavaScript. De HTML in de sidebar beschikt echter wel over een aantal extra objecten en events om te kunnen interacteren met de Sidebar omgeving.

We beginnen met een zeer basale HTML layout, in een file Main.htm.


 
    
    


    

 

Deze HTML zal gerenderd worden in de sidebar. Nog wel een beetje saai, niet? Alle code voor de gadget wordt geïmplementeerd in JavaScript en de layout wordt verder ingevuld met behulp van Cascading Style Sheets. Je ziet dat in het onload event van de body een methode wordt aangeroepen genaamd Page_onLoad(). Dit is de entry point voor onze code. Verder valt op dat we een tag gebruiken. Dit is een van de bijzondere sidebar objecten. Voordeel van dit object is dat het de achtergrond van onze gadget transparant maakt, en tja... dat ziet er gewoon net iets mooier uit.

Tip: Soms wil de debugger niet lekker aan het proces attachen. Het is dan handig om een backup mogelijkheid voor tracing te hebben. Hiervoor is de DIV tag met als id divStatus. Die kun je dan gebruiken om status te loggen op cruciale plekken. Als de gadget bijna klaar is maak ik vervolgens het divStatus object onzichtbaar en ziet de gebruiker er niks van. Mocht er een bug optreden, hoef ik maar 1 regel actief te maken en de tracing werkt weer.

De onLoad method ziet er zo uit:

// Eventhandler, will fire when the body of our gadget
// has completed loading.
function Page_onLoad()
{
  // Enable next line when gadget is complete  
  // divStatus.style.display = "none";
  System.Gadget.settingsUI = "Settings.html";
  UpdateGadget();
}

// Update gadget by async firing of a HTTP request
function UpdateGadget()
{
  var url =
   'http://xml.truveo.com/rss?
     query=champions%20league%20sort%3AmostRecent';
  request = new XMLHttpRequest();
  request.onreadystatechange =
    request_onReadyStateChange;
  request.open("GET", url);
  request.send();   

  window.setTimeout(UpdateGadget, (1000 * 60 * 60 ));
}

De Page_onload() roept UpdateGadget() aan. In deze functie wordt vervolgens een XMLHttpRequest opgebouwd die de URL die we eerder gevonden hebben, aanroept. We willen niet dat onze gadget de opbouw van de user-interface blokkeert en dus implementeren we de call als een asynchronous call. De methode die aangeroepen moet worden zodra de ready state van de request bereikt wordt, is request_onReadyStateChange().

Verder valt op dat we de UpdateGadget method eindigen met een call naar window.setTimeout(UpdateGadget, (1000 * 60 * 60 )). Hiermee zorgen we ervoor dat de UpdateGadget methode elk uur opnieuw aangeroepen wordt. Deze recursie is tevens de reden om de implementatie van UpdateGadget los te trekken van de eventhandler Page_onLoad().

Als laatste valt te vermelden dat we een regel in de code hebben die de divStatus onzichtbaar maakt. Deze regel is gedurende het ontwikkelen uitgecommentarieerd, maar zal als laatste stap in het proces actief gemaakt worden, zodat trace informatie runtime niet getoond wordt.

Dus hoe ziet request_onReadyStateChange() eruit?

// Convert status of request-object to description
function getStatusDescription(status)
{
  var description;
   
  switch(status)
  {
    case 0:
      description = "Uninitialized";
      break;   
    case 1:
      description = "Open";
      break;
    case 2:
      description = "Sent";
      break;
    case 3:
      description = "Receiving";
      break;
    case 4:
      description = "Loaded";
      break;     
    default:
      description = "Error";
  }
  return description;


// Eventhandler, will be fired for every state change
// on our XMLHttpRequest
function request_onReadyStateChange()
{
  var status = request.readyState;
  divStatus.innerText = getStatusDescription( status );
  if ( status == 4 )
  {
    showItemOfTheDay();
  }
}

De eventhandler logt de status van de request in de hiervoor aangemaakt DIV. Ik heb even een conversie methode toegevoegd zodat direct zichtbaar is wat de betekenis van elke waarde is. Dit is tevens een handige manier om zelf documenterende code te maken :-).

Vervolgens controleren we of the status van de request ‘Loaded’ (4) is; zo ja, dan gaan we verder met het tonen van de video van de dag. Mocht het overigens niet zijn opgevallen, request is als een globale variabele gedefinieerd.

// Generate a random number where the number
// will be maxed by the 'max' parameter.
function getRandomNumber( max )
{
  var random = Math.floor(Math.random()*max);
  return random;
}
   
function showItemOfTheDay()
{
  var xmlDocument = request.responseXML;
  var nodes = xmlDocument.selectNodes( '//item' );
  var numberOfItems = nodes.length;
  if ( numberOfItems > 0 )
  {
    var randomNumber = getRandomNumber( numberOfItems );
    var selectedNode = nodes[randomNumber];
    var thumbnail = selectedNode.selectSingleNode(
      'media:thumbnail//@url' );
    var title = selectedNode.selectSingleNode( 'title' );
    var link = selectedNode.selectSingleNode( 'link' );
    divLink.innerHTML = '      target="_blank">      width="90" height="60" alt="' + title.text + '"
      border="0"/>
';
  }
}

De showItemOfTheDay() method leest de XML uit de request en selecteert vervolgens alle nodes in de RSS feed. Het object dat wordt teruggegeven door de request.responseXML property is geen string, maar een XMLDocument en beschikt dus over de benodigde methodes om selects op de XML te doen. Helaas herkent de VS2008 editor niet wat het type van het object is, en ontbreek de Intellisense dus op het request object.

De juiste positionering van de HTML elementen wordt overigens gedaan met de volgende CSS:

body
{
  background-repeat: no-repeat;
  width: 130px;
  height: 120px;
}
       
#divStatus
{
  color: White;
  position: absolute;
  top: 95px;
  left: 10px
}
       
#divLink
{
  position: absolute;
  top: 35px;
  left: 10px
}
        
#imgUEFAlogo
{
  position: absolute;
  top: 0px;
  left: 80px
}

Package deployment

Tot nu toe hebben we alles in Main.htm gedaan, maar er is ook een Settings.html, alleen hebben we geen instellingen voor dit gadget. Die settings bevatten alleen een link en wat reclame. Gadgets worden verspreid als .gadget files. Dit zijn echter gewoon zip-files (of .cab files als je elektronisch wilt signen). Download maar een willekeurige gadget, hernoem het naar een zip-file en je kunt het nu gewoon openen. Er is echter wel een bijzondere eis die wordt gesteld aan de zip-file: er moet een gadget manifest zijn. Dit is een XML file met de naam gadget.xml en het ziet er als volgt uit:



  UEFA Champions League Video of the Day
 
    DevelopOne.Windows.Vista.Gadgets.UEFA
 

  1.0.0.0
 
   
   
 

  © 2008, Develop-One
  This gadget will display a random
    new Champions League video every hour.
 

 
   
 

 
   
              src="Main.htm" />
      Full
     
   

 

Voeg dit bestand toe aan de folder waar je Main.htm hebt staan, zip alle bestanden en hernoem de file van .zip naar .gadget. Dubbelklik op de file en Vista zal de gadget voor je installeren.

Wrap up

In dit artikel hebben we gekeken naar het debuggen van gadgets met behulp van Visual Studio 2008. Ondanks alle mogelijkheden is het nog steeds handig om een trace optie in je gadget te hebben. Het deployen van een gadget is weinig meer dan een zip-file maken en de file hernoemen, en vergeet niet om het manifest bij te voegen.

We hebben gebruik gemaakt van de Truveo RSS feed. Er is ook een Truveo API die je de mogelijkheid biedt om het gebruik van je applicatie te monitoren via de ‘My API Account’-page, dus dan zou je kunnen zien hoeveel installaties er van je gadget zijn.

Links

  • UEFA Video of the Day gadget: http://gadgets.develop-one.com
  • Truveo: http://www.truveo.com
  • UEFA: http://www.uefa.com
  • MSDN Gadget Reference Manual: http://msdn2.microsoft.com/en-us/library/aa965850.aspx
  • AOL Blog over .NET en Gadgets: http://dev.aol.com/blog/22109
Geef feedback:
Verzend Commentaar