At the behest of [[Sandy Peardon]], [[Dan James]] and I met with Sam Punnett of FAD Research this afternoon.
Sam is a “interactive media researcher” from Toronto (he calls it “the city”) and he’s been engaged by [[ITAP]] to “develop a broadly consultative 3-year growth strategy for the New Media Sector” on Prince Edward Island (read the RFP here).
As a rule, I avoid any exercise that has “broadly consultative 3-year growth strategy” in its description, but Sandy dangled the carrot of an opportunity to “bring your ‘grassroots growth rather than a large grandiose public initiatives’ perspective to him” and, heck, who am I to turn down a chance like that.
Initial signs were not good, as Sam used the words “space” about half a dozen times in the first five minutes (“new media space,” “digital space,” and so on). Consultants use the word “space” to refer to “an area of economic activity” in the same that hipsters use “joint” to refer to “marijuana-packed cigarette” — it makes them sound all cool and with-it and from San Jose.
Things improved markedly, however, as the meeting progressed: Sam seemed to grok the “organic network of loosely coupled operators” model of the economy that we tried to spin (and that I tried to describe here), and seemed willing and able to accurately reflect our approach back to his minders. Which is a lot more than the usual “ah, your answers didn’t fit the model so we had to leave them out” approach the previous researchers have taken.
While I’m still a strong advocate of “leave the economy alone and it will figure itself out on its own” approach to economic development, I think Dan and I managed to send back some useful feedback, the central element of which was the suggestion that what the industry needs, more than “3-year growth strategies,” monolithic technology infrastructure and IT sweatshops imported from away, is a support network more akin to crop scouts than chess players. Those making decisions about the industry should participate in the life of the industry — get out in the fields, smell the earth, talk to the farmers, so to speak. Rather than trying to sculpt great visions out of nothing.
Sam is here until the end of next week, and he’s open to meeting with anyone who’s got ideas about, well, the development of a “3-year growth strategy for the New Media Sector.” He’s a good listener, and it might be worth your while to take 30 minutes and tell him where you’re at and what you’re doing. Here’s his contact information.
[[Technorati]] has become infamous of late for have severe performance problems, especially their feature that allows weblog authors to see what links back to them, which would often fail to complete. Something’s happened today, though: Technorati is blazing along like never before. Let’s hope it lasts!
The Danish Ministry of Science, Technology and Innovation has a website called Work in Denmark created, they say, because:
Denmark needs foreign knowledge workers to contribute new expertise and thereby strengthen trade and industry, innovation and research in Denmark.
What’s nice about the site is that it isn’t the usual “we’re a world-class destination with leading-edge technology infrastructure that can be leveraged to maximize.” At least not entirely. There’s actually useful information there, like how to register for Kindergarten, how to get divorced and how to get your teeth fixed.
Here on Prince Edward Island, the excellent InfoPEI directory has much the same information; I like the Danish site, however, for its concise text, exclusive focus on foreign workers (like me), and clear organization.
It says here that The Amazing Race: The Family Edition will premiere on September 27, 2005:
This child-friendly season will see a shorter race route, as we see more legs set in the United States of America, with a strong focus on historically significant cities and locations.
The CBS Amazing Race 8 page confirms this date, and has bios for ten teams of four.
Episode 14 of commandN, [[Amber MacArthur]]’s tech vidcast has just been posted. This is the episode where Amber interviews me about [[Plazes]].
Intuit offers a free 30-day trial of their QuickBooks for Mac. To download this, you “purchase” the product, for $0, from their web store. At which point you get the following “error” message:
Read the whole thing.
My friend [[Stephen Regoczei]] is stoking the fires of his new weblog. I never knew that Stephen was so great at pith:
Terrorists are relatively harmless. They do very little damage when compared to other hazzards such as food poisoning, malaria, or car accidents. Looking at the damage that the inaction of the US Government caused in New Orleans after Katrina, I can not see why why we bother with, or even notice, so-called “terrorists” at all.
[[Oliver]] and I have come to the office this Sunday morning to get out of [[Catherine]]’s hair while she puts down a couple of dozen cobs of corn for the winter. We stopped at [[Timothy’s]] on our way in for a bagel with swiss and tomato, a cup of tea and a glass of orange juice. And as I type Oliver is out front in the lounge playing with the mysterious Lego that appeared there this spring. And I am blogging, at least for this minute.
And suddenly I’m flooded with memories of [[CCIW]], where my [[Dad]] worked for more than 30 years, and visits there with him on Sundays. I remember signing in with the Commissionaire at the front desk, the “sciencey” smell of the place, getting to draw with pencils and pens on reams of old line printer paper (with lines and lines of discarded sedimentological data on the other side), and taking a walk down to the hydraulics lab to see the giant water tanks.
And, if the moon was in the right place, getting to stop at Tim Horton Donuts on the way home for a Dutchie.
I decided this afternoon that it was time to try my hand at creating an OS X Dashboard widget to show me live sales information from one of my client’s online stores. To my surprise, I found that this was a lot easier than I thought it was going to be: everyone should be making Dashboard widgets! So here’s how I did it.
Getting the Sales Information
First, I needed a way of getting sales and revenue information for the current day. My client’s online store is a custom PHP application, so it was easy to extract this from a database. I created a little PHP script to do this and called it dashboard.php. Here’s the important part of the PHP code:
<?php
$today = strftime("%Y-%m-%d");
if ($return == "sales") {
$query = "SELECT count(*) as sales from onlinesales where
saledate between '$today 00:00:00' and '$today 23:59:59'";
$result = MYSQL_QUERY($query);
$currentrecord = 0;
$sales = trim(MYSQL_RESULT($result,$currentrecord,"sales"));
$retval = sprintf("%3.0f",$sales);
}
else if ($return == "revenue") {
$query = "SELECT sum(amount) as revenue from onlinesales where
saledate between '$today 00:00:00' and '$today 23:59:59'";
$result = MYSQL_QUERY($query);
$currentrecord = 0;
$revenue = trim(MYSQL_RESULT($result,$currentrecord,"howmuch"));
$retval = "\$" . sprintf("%6.2f",$revenue);
}
$retval = str_replace(" "," ",$retval);
print $retval;
This script returns the number of sales if it’s called like this:
http://www.example.com/dashboard.php?return=sales
Similarly, it returns total revenue if it’s called like this:
http://www.example.com/dashboard.php?return=revenue
What gets returned is a pre-formatted number, ready for magical insertion into my Dashboard widget.
Designing the Widget
Apple provides excellent documentation on how to create widgets, including a Hello World! application. If you have the OS X 10.4 Developer Tools installed, you’ll also find some handy sample code at:
/Developer/Examples/Dashboard/Sample Code/
To start out, I copied the contents of the “Blank Widget” example widget into a new folder called Online Sales:
mkdir "Online Sales"
cd "Online Sales"
cp "/Developer/Examples/Dashboard/Sample Code/Blank Widget/"* .
sudo chown peter:peter *
The last step is required because the permissions on the sample code don’t allow it to be modified; changing ownership to my user and group (peter) let me make changes.
Next, I renamed the sample files for my new widget:
mv BlankWidget.css OnlineSales.css
mv BlankWidget.html OnlineSales.html
mv BlankWidget.js OnlineSales.js
Then I edited the HTML file OnlineSales.html — it’s where the widget gets “drawn” — so that it looks like this:
<html>
<head>
<style type="text/css">
@import "OnlineSales.css";
</style>
<script type='text/javascript' src='OnlineSales.js' charset='utf-8'/>
</head>
<body onload='setup();'>
<img src="Default.png">
<span id="sales" class="salesText"></span>
<span id="revenue" class="revenueText"></span>
</body>
</html>
I now had a simple HTML file with a hole for the sales figure (the span called sales) and a hole for the revenue figure (the span called revenue). The CSS file called OnlineSales.css is used to style the HTML, and I modified it so that it looks like this:
body {
margin: 0;
}
.salesText {
font: 40px "verdana";
font-weight: bold;
color: black;
position: absolute;
top: 7px;
left: 25px;
}
.revenueText {
font: 18px "verdana";
font-weight: normal;
color: black;
position: absolute;
top: 53px;
left: 29px;
}
I dropped some “dummy” values into the HTML file and then loaded it up in Safari to see what it would look like; then I tweaked the CSS until it looked like I wanted:
Now I had my widget designed. All that remained was a way of getting the sales and revenue data from the webserver into the widget.
Getting the Web Data
Although Apple has a number of ways to get external data into a widget, the simplest one, and the one that required no learning curve for me, was to use the System Method, a Javascript function available automatically to widgets that allows OS X command line scripts to be run and their results returned to JavaScript.
By default, OS X includes a handy utility called cURL that can act as a sort of “command line browser,” connecting to web servers and retrieving what they return. To run cURL from the command line to grab my sales data is as simple as:
/usr/bin/curl http://www.example.com/dashboard.php?return=sales
This script simply returns something like:
14
…the current number of sales, ready for popping into the hole I’ve created in the widget for this piece of information. The glue that binds all this together lives in the JavaScript OnlineSales.js, that looks like this:
function setup()
{
UpdateData();
return 0;
}
if (window.widget)
{
widget.onshow = UpdateData;
}
function UpdateData () {
sales = widget.system("/usr/bin/curl
http://www.example.com/dashboard.php?return=sales",
null).outputString;
revenue = widget.system("/usr/bin/curl
http://www.example.com/dashboard.php?return=revenue",
null).outputString;
document.getElementById("sales").innerHTML = sales;
document.getElementById("revenue").innerHTML = revenue;
}
The JavaScript function UpdateData uses cURL, through the widget.system method, to grab the sales and revenue data from the server, and then updates the widget’s sales and revenue spans with what it retrieved. This is automatically updated whenever Dashboard is activated by gluing the method to the widget.onshow property.
Modifying the Property List
The final step in creating the widget is to modify the Info.plist file, that contains some important settings information. If you double-click on this file in OS X, the Property List Editor will load the file. Here are the settings I set for my widget:
In addition to customizing the defaults already in Info.plist, I added the AllowSystem setting, that, as explained here, you must specify if “your widget requires access to command-line utilities using the widget script object.” I saved the modified Info.plist, and then I was ready to test my widget out.
Testing the Widget
After all of the above, I was left with six files in my Online Sales folder:
- Default.png
- Icon.png
- Info.plist
- OnlineSales.css
- OnlineSales.html
- OnlineSales.js
To turn these into a widget is as simple as renaming the Online Sales folder to Online Sales.wdgt. This automagically bundles the files together into a “widget package” that will look like this:
To ease the debugging process, the best way to proceed from here, I found, is to make a duplicate of the widget (select it in the Finder and press “Command+D”) and then double click on the duplicate. If all goes according the plan (and, amazingly enough, it actually did for me), you’ll be prompted to choose whether to install the widget or not, and if you say “Yes,” then the widget should appear on the Dashboard, with live sales information:
A couple things you might want to note:
- It’s a good idea to thoroughly test each step of the process, especially the server-side script, before assembling and testing the widget itself; although there are debugging assists built in to Dashboard, it’s much easier to debug earlier, especially the widget.system call.
- In my real world implementation, my sales data talks to a secure webserver using SSL; to encode username and password data into a cURL call is as easy as modifying the JavaScript to use the form /usr/bin/curl -u username:password.
- I didn’t do any customizing of the icon or the default “Blank Widget” look and feel; obviously if I was going to make a widget for distribution, I would do that.
Following the steps I went through, it should be easy to make a Dashboard widget to display almost any sort of “up to the minute” kind of data. If you go ahead and do this, please post a comment with your experiences.
From today’s Jane Siberry email newsletter:
I just put Calling All Angels on my website for free. People have been contacting me recently wondering how the song could be sent out in a wider way in these difficult times. One person wanted to burn copies for relief workers. I said yes. Then I thought that feels so right. And better yet, if i also make it available as a free website download the gesture would be more Earth-loving with no plastic created. Then I thought, heck, why don’t i just make everything free (that I have rights to). Something feels forced about withholding (music) until one gets something (money). People could pay what they want or not pay at all. That would be more authentic, pure. And probably bring more positivity to all. I think the music would be happier, too.
Grab the MP3. It’s a good song.