Thursday, March 5, 2009

Vista Sidebar Gadget for SiteMeter

This post provides a Vista Sidebar gadget to report on sitemeter information for a web site being monitored. In a previous post I’ve provided a command-line PowerShell method to retrieve the same information, but I thought I’d try this GUI thing people keep talking about.

This is a very simple Vista sidebar gadget, it doesn’t have settings, or fly-outs, or links, or any other bits of cleverness, it was really just my first look into how Vista gadgets work. All I did was take the Microsoft hello-world example gadget and add a bit of javascript to (badly) scrape the sitemeter web page.

The gadget:
  1. Has a transparent PNG background image and writes the text in white on two lines, with a gadget size of 128x64
  2. Uses the MSXML DOM to issue a HTTP GET and for the sitemeter URL, using an asynchronous callback
  3. Parses the HTTP response, looking for the first index of the word ‘Today’ and extracts the number
  4. Updates the second field in the gadget with the current date/time to tell when the last successful get occurred
  5. Uses the SetTimeout method to sleep for an hour before calling the getData() function again
What the gadget doesn’t do that could make this better:
  1. Have the URL and timeouts stored in a settings file to save having to modify the JS when scraping a different URL or changing the timeout.
  2. Have a flyout or something which shows the other summary information on the sitemeter page
  3. Use a separate CSS and init() function rather than the in-line code from the example
To create this:
  1. Download the gadget samples from http://www.microsoft.com/downloads/details.aspx?FamilyID=b1e14e4f-3108-4c57-8b78-1157ca40dcc2
  2. Copy SDK_HelloWorld.gadget to *.zip
  3. Unzip the contents of the gadget zip file to a working directory and remove the read-only attribute from the files
  4. Create a transparent PNG background 64x64 in size (or use the one provided in this post), and overwrite Background.png
  5. Update images\aerologo.PNG with the png from this post
  6. Update HelloWorld.html with the contents below:
  7. Update the height and width to 128x64
    - Add the script tag:
    - Update the in-place init() funciton to call getData()
    - Create SiteMeter.js with the contents below
  8. Create a new directory and copy all of the gadget files to "%Systemdrive%\users\%username%\appdata\local\microsoft\Windows Sidebar\gadgets\SiteMeterCounter.gadget"
  9. Update the URL in SiteMeter.js with the page to scrape
  10. Add the gadget

HelloWorld.html

<!--
 *************************************************************************
 *
 * Name: SiteMeter.html
 *
 * Description: 
 * Simple SiteMeter counter
 * Displays the current count of today's visitors from the provided SiteMeter URL
 * 
 *
 * Modified from the 'Hello World' Microsoft example 
 ************************************************************************
-->
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
     <title>SiteMeter Count</title>
     <style type="text/css">
      body
      {
          width: 128px;
          height: 64px;
                        font-family: calibri;
                        color: white; 
      }
      #gadgetContent
      {
          width: 128px;
                        top: 3px;
          text-align: center;
                        overflow: hidden;
                        font-weight: bold;
                        font-size: 14px;
      }
      #lastUpdate
      {
          width: 128px;
                        top: 20px;
          text-align: center;
                        overflow: hidden;

                        font-size: 9px;
      }
     </style>
     <script type="text/javascript" src="SiteMeter.js"></script>
     <script type="text/jscript" language="jscript">


        // --------------------------------------------------------------------
        // Initialize the gadget.
        // --------------------------------------------------------------------
     function init()
     {
         var oBackground = document.getElementById("imgBackground");
         oBackground.src = "url(images/background.png)";
                getData();
        }
     </script>
    </head>
 
<body onload="init()">
    <g:background id="imgBackground">
 <span id="gadgetContent">-</span>
 <span id="lastUpdate">-</span>
 </g:background>
</body>
</html>



SiteMeter.js

var globalURL = "http://www.sitemeter.com/default.asp?a=stats&s=s451qaz2wsx";              // URL for lookup
var globalTimeoutId;
var globalError;
var XMLHttp;

function getData()
{
    try 
        { XMLHttp = new ActiveXObject("Msxml2.XMLHTTP"); 
    } 
    catch (e) 
        { XMLHttp = new ActiveXObject("Microsoft.XMLHTTP"); 
    }

    // Timeout, if call not come back in 30 seconds, abort with the default error message.
    globalTimeoutId = setTimeout(function() {
                                         XMLHttp.abort();
                                         document.getElementById("gadgetContent").innerHTML = "Timeout";
                                         }, 30000); 
        
    // Asynchronous get
    XMLHttp.open("GET", globalURL, true);

    XMLHttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
    XMLHttp.setRequestHeader("Connection", "close");

    // Callback for when the page has loaded
    XMLHttp.onreadystatechange = parseData

    // Send the request
    XMLHttp.send(null);

}

function parseData()
{
    var Results;
    var td;

    gadgetContent.innerHTML = XMLHttp.status;

    if (XMLHttp.readyState == 4 && XMLHttp.status == 200)
    {

        var date = new Date();
        lastUpdate.innerHTML = date.getDate() + "/" + (date.getMonth() +1)  + "/" + date.getYear() + " " + date.getHours() + ":" + date.getMinutes() + ":" + date.getSeconds();

        globalError = 0;

        Results = XMLHttp.responsetext;
        if (Results.indexOf("Today") >= 0)
        {

            td = Results.substring(Results.indexOf("Today")+20, Results.indexOf("Today")+80);
            td = td.substring(td.indexOf("<font"), td.length);
            td = td.substring(0, td.indexOf("</font>")+7);

            gadgetContent.innerHTML = td;
        }
        else
        {   
            globalError = 1;
            document.getElementById("gadgetContent").innerHTML = "Error";
        }

        // Set a callback for the getData function in one hour
        clearTimeout(globalTimeoutId);
        globalTimeoutId = setTimeout(getData, 3600000);
    }

} 


Wayne's World of IT (WWoIT), Copyright 2009 Wayne Martin.

No comments:

Post a Comment