Build a Dashboard Widget
Pages: 1, 2
The Default Image
As I said in the "DefaultImage" section of the Info.plist overview, widgets need to have a default background image. This image is displayed while Dashboard loads a widget. For a simple widget, the easiest thing to do is to have this image be the same as the background image that you will have for the widget once it is loaded. Apple's documentation specifies that this image needs to be a PNG file. PNG files can be created with Photoshop, Fireworks, GIMP, or just about any other image-editing software.
To keep things simple, I have named the file for the ManPage project Default.png. Here is what it looks like:

While this file can be as complex or as simple as a developer would like, it is important to remember that the main purpose of this file is to display an image while the widget is loading. This allows the user to see information about the widget, the default footprint of the widget, and other visual information that the developer wants the user to see. To keep things simple for the ManPage widget, this image is the same as the as background for the widget.
The MainHTML File
MainHTML is the file that provides the basic user interface and JavaScript functions for the widget. While complex widgets could include multiple HTML, CSS and .js files, for simplicity's sake, the ManPage widget consolidates all of this into one file.
While MainHTML files are basically HTML files, similar to those for regular web pages, there are some things to keep in mind while developing them. First and foremost, there is no default background for a widget. In order for the widget to have a canvas to draw on, you need to specify a background image. (I am not sure if invisible widgets would work, but it would be cool to try out.) This can be done using a div tag, like in the ManPage HTML section below.
The second thing to keep in mind is that Dashboard conforms to CSS, JavaScript, and DOM web standards. While this article is not intended to be an overview of developing CSS-based HTML pages, I will say that since Dashboard is basically a conforming browser, it is much easier to develop and debug widgets using web standards.
The MainHTML for the ManPage widget is below:
<html>
<head>
<title>Dashboard Man Page</title>
<meta http-equiv="Content-Type"
content="text/html;charset=utf-8" >
<style type="text/css">
<!--
.backStyle {
position:absolute;
width:400px;
height:400px;
left:0px;
top:0px;
z-index:0;
visibility: visible;
}
.textStyle {
font-family: Lucida Grande, Arial, Helvetica, sans-serif;
font-size: 12px;
color: #000000;
position:absolute;
width:111px;
height:22px;
z-index:1;
left: 128px;
top: 26px;
}
.inputStyle{
position:absolute;
width:123px;
height:23px;
z-index:1;
left: 246px;
top: 24px;
visibility: visible;
}
.outputStyle{
position:absolute;
width:324px;
height:400px;
z-index:1;
left: 33px;
top: 72px;
visibility: visible;
}
-->
</style>
<script type='text/javascript'>
<!--
// get man page
function getManPage()
{
if (document.getElementById('programName').value != null)
{
var commandLine =
'groff -mandoc -Tascii -P-b -P-c `/usr/bin/man -w "'
+ document.getElementById('programName').value+'"`'
+ ' | /bin/cat';
var output = widget.system(commandLine, null);
document.getElementById('outputArea').value = output.outputString;
}
}
-->
</script>
</head>
<body>
<div id="BackgroundLayer" class="backStyle">
<img src="Default.png" width="400" height="600">
<div id="TextLayer" class="textStyle">
<div align="right"> Get More Info On:</div>
</div>
</div>
<div id="InputLayer" class="inputStyle">
<input id="programName" type="text"
size="14" border="0" height="23px" width="123px"
onchange='getManPage();'>
</input>
</div>
<div id="OutputLayer" class="outputStyle">
<textarea id="outputArea" cols="42"
rows="25" readonly>
</textarea>
</div>
</body>
</html>
This is about as simple an HTML file as you can get: there is some header information, one JavaScript function, one style, and then some HTML markup. The HTML markup defines three layers: one for the background, one for a box where a user can input the name of the *nix command that they want a man page for, and one for the output of the man page. To trigger the retrieval of the man page, when the value in the programName input box has changed, it calls the getManPage() function via the onchange attribute.
The getManPage() function is where all the heavy lifting of this widget happens. Here is what happens, line by line:
if (document.getElementById('programName').value != null){This checks to make sure the
programNameinput element actually contains text. We need to do this becauseonchangewill trigger thegetManPagemethod any time the text changes, including if it is all deleted.-
var commandLine = 'groff -mandoc -Tascii -P-b -P-c `/usr/bin/man -w "' + document.getElementById('programName').value+'"`' + ' | /bin/cat';This defines the shell command that we will call to get the
manpage. The command looks pretty complex, but like most shell commands, it is actually pretty easy once it is broken down. The first thing to look at is the middle section, because this is the first thing the shell will process.`man -w "' + document.getElementById('programName').value + '`We are building a string here that gets the
manpage for theprogramNamethat we entered. If we inputls, then this command would be:`man -w ls `The back ticks (
`s) that surround the command tell the shell to replace the back-ticked expression with the output of the expression before running the rest of the command line.The output from the
mancommand, once it is replaced on the command line, is sent to thegroffutility via:"groff -mandoc -Tascii -P-b -P-c" +This utility is used to format text for output to various devices. We need to call this command because the output from
manis formatted to be displayed on a terminal screen, including bold and underline control characters. If we did not strip these out, the output would look very strange in the HTML text area in which we are placing it. The parameters togroffare set to interpret the input as output from themancommand and the output as ASCII.The last part of the command line is:
"| cat "This forces the output of the whole command to go to
stdout. Anyone who has used any *nix shell will tell you that this is a weird command to include, and I agree. I needed to include it because of the way that Dashboard's JavaScriptwidget.systemcommand handles output tostdout(we will go overwidget.systemin the next section). var obj = widget.system(commandLine ,null);This command is used to run the command that we defined before in a *nix shell. The first argument is the
commandLinestring that we built before. The second argument is a mystery. Apple only provides one or two samples of this command in any of the documentation that comes with the pre-release version of Tiger and on the developer site. I have Googled the Web and searched all of Apple's documentation to see what exactly thenullspecifies, but I have found nothing. Both of Apple's examples call it with a null value, so I do the same.-
document.getElementById('outputArea').value = obj.outputString;This command takes the
outputStringfrom thewidget.systemcall and puts the value in theoutputAreaelement.
More to Come
While this is not the most complex or useful widget in the world, it does show off some of the capabilities of what Dashboard can do. Since Dashboard gives full access to the *nix shell, it is easy to imagine a widget calling a Perl script that makes database calls or interacts with a local CVS server. This means that, beyond the obvious uses of creating end-user widgets, Dashboard provides developers with a rapid prototype environment where they can try out new ideas with only a little bit of coding required.
The next article will include information on debugging and testing widgets, links to some sites that have sprouted up with widgets to download and bulletin boards for widget developers, and a how-to on writing a widget that uses JavaScript's object to retrieve information from remote web XML servers.
If you are looking for more information on Dashboard widget development, check out Apple's Developing Dashboard Widgets page. The page is kind of sparse, but gives some insight to developing widgets
Andrew Anderson is a software developer and consultant in Chicago who's been using and programming on the Mac as long as he can remember.
Return to MacDevCenter.com.
-
any SEO widgets?
2007-02-16 07:56:32 artem.pugachev [View]
- Trackback from http://www.ogadei.com/node/how-to-create-dashboard-widgets-for-mac-os-x-10.4-tiger/825
How to Create Dashboard Widgets for Mac OS X 10.4 Tiger
2005-06-08 16:45:19 [View]
- Trackback from http://biven.org/?p=217
Widgets, Ta-da lists and Backpack API.
2005-06-02 08:59:02 [View]
-
Thanks for Hanging in There with the Adventure
2005-05-09 13:42:02 Derrick Story |
[View]
-
What the 'null' means
2005-05-09 01:34:19 MWright [View]
-
What the 'null' means
2005-05-09 01:39:02 MWright [View]
-
What the 'null' means
2005-05-09 03:40:31 Andrew Anderson | [View]
-
Widget does not work, I am working on a fix
2005-05-07 18:18:59 Andrew Anderson | [View]
-
Here is the fix!!
2005-05-07 21:01:16 Andrew Anderson | [View]
-
Here is the fix!!
2005-06-08 15:03:18 rayvanderver [View]
-
Example Doesn't Work
2005-05-07 13:36:45 joshuawait [View]
-
I tried it as well and couldn't get it to work.
2005-05-07 12:53:06 maddmike [View]
-
Isn't that a bit dangerous?
2005-05-07 01:55:30 KerryB [View]
-
Isn't that a bit dangerous?
2005-05-09 09:32:39 heyotwell [View]
-
Isn't that a bit dangerous?
2005-05-07 05:15:01 Andrew Anderson | [View]
-
Isn't that a bit dangerous?
2005-05-07 04:57:55 SanjayW [View]
-
Isn't that a bit dangerous?
2005-05-07 12:59:27 KerryB [View]
-
It doesn't work
2005-05-06 18:16:36 kevincranford [View]
-
It doesn't work
2005-06-14 11:33:30 TimGrant [View]
-
It doesn't work
2007-03-23 20:01:10 jeffclough [View]
-
The Working JavaScript Function and Explanation of Error in Article
2005-06-30 00:59:51 maymay [View]
-
It doesn't work
2005-05-07 05:18:46 Andrew Anderson | [View]
-
It doesn't work
2005-05-23 11:14:49 andyinindy [View]
-
re:It doesn't work
2005-05-23 16:11:43 Andrew Anderson | [View]
-
...doesn't work...
2005-05-11 09:18:20 andyinindy [View]
-
...doesn't work...
2005-05-11 10:58:08 Andrew Anderson | [View]
-
It doesn't work
2005-05-07 16:26:30 kevincranford [View]

