Basics
The Dazzle Workflow
Dazzle uses appcasts to determine if there is a newer version of your widget available. If so, Dazzle displays an alert box to the user, telling them that there is a newer version available.
If the user clicks the "Later" button, nothing happens, and when Dazzle does its next check for updates, it shows the alert box again.
If the user clicks the "Download" button, Dazzle opens the URL of the update in Safari (regardless of the user's default browser). Safari then downloads, unzips, and launches the downloaded widget. Once the user confirms the "Do you want to replace the current version of this widget?" dialog and confirms that they want to keep the widget, the widget is installed.
Creating the Dazzle object
Before Dazzle will do anything, you must create a Dazzle object and assign it to a variable:
var dazzle = new Dazzle();
It is probably best to assign the Dazzle object to a global variable, so that you can access it anywhere in your code. Also, I recommend that you name the variable "dazzle" for neatness (all code samples assume that it is named "dazzle" and that it is a global variable which has already been declared).
Dazzle's Hide and Show Handlers
When the user hides the dashboard, there is no need for Dazzle to automatically check for updates.
Make sure that you call Dazzle's onHide method when the user hides the dashboard:
widget.onhide = function()
{
[Your Code...]
dazzle.onHide();
}
...and make sure that you call Dazzle's onShow method when the user shows the dashboard:
widget.onshow = function()
{
[Your Code...]
dazzle.onShow();
}
Stopping Dazzle from Automatically Checking for Updates
You may want to stop Dazzle from automatically checking for updates and/or displaying an alert box. To accomplish this, call the setShouldAutomaticallyCheckForUpdates method and pass it a value of true/false, depending on whether you want to enable/disable automatic checks (respectively).
// Stop Dazzle from automatically checking for updates dazzle.setShouldAutomaticallyCheckForUpdates(false); // Start Dazzle automatically checking for updates dazzle.setShouldAutomaticallyCheckForUpdates(true);
Options
What are options?
"Options" are used in many JavaScript libraries, such as Prototype, Script.aculo.us, and Mootools, to allow you to provide optional settings (in any order) when you call a function/method or create an object. The way this works is by providing an "options" object that contains all the options as properties of the object. The options object (if provided - the options object should also be optional) is usually provided as the last parameter.
For an example, let's take the Effect.Fade method from the Script.aculo.us JavaScript animation framework. You can simply call this method as follows:
Effect.Fade('myElement');
However, you can also provide options to customise the behaviour of the method:
/* Single Option */
Effect.Fade('myElement', { duration: 2.0 });
/* Multiple Options */
// Since the "options" object is an inline object, multiple properties
// must be separated by commas.
// Also, when providing multiple options, it is often neater
// to put each option on its own line.
Effect.Fade('myElement', {
duration: 2.0,
to: 0.5
});
Options are also used to provide callback functions to be executed at certain points during the code. A very common callback is "onComplete", which is called when the function/method has finished. In Script.aculo.us, it is called "afterFinish":
Effect.Fade('myElement', {
afterFinish: myFunction
});
How does Dazzle use options?
Dazzle also uses "options" to allow you to tweak Dazzle's behaviour to your liking. Most of Dazzle's options are provided when the Dazzle object is initialised. For example, to set the check interval to "daily" and specify that the alert box should never be displayed:
dazzle = new Dazzle({
checkInterval: "daily",
shouldDisplayAlertBox: false
});
There is only one method in Dazzle that support options: checkForUpdateInformation. Here is an example of supplying an onComplete callback to it:
// When "checkForUpdateInformation" has finished, it will call "myFunction"
dazzle.checkForUpdateInformation({ onComplete: myFunction });
Have a look at the Dazzle Reference to see all the available options for the Dazzle object and the checkForUpdateInformation method.
Appcasts
Dazzle uses appcasts to determine whether your widget is up to date.
What are Appcasts?
An Appcast is a special type of RSS Feed, where a new item is posted whenever a new version of your application/widget is released. This new release of your application is included (compressed) with the item using an enclosure.
Connected Flow provides a good general description of appcasting:
Appcasting is the practice of using the 'enclosure' feature of RSS 2.0 feeds to deliver updates and release notes for new software applications. The name Appcasting is by analogy with Podcasting, which is the practice of delivering audio files as RSS 2.0 enclosures.
The idea is this: the developer publishes an RSS 2.0 feed, each item of which describes a new release of a particular software product. The items' descriptions may contain release notes or other information about what's new in this release.
Dazzle Appcasts
Like with Sparkle, you can add extra elements and attributes (not part of the RSS Specification) to your appcast items in order to provide more information to Dazzle.
These custom elements and attributes are namespaced. By default, the namespace is "dazzle" (the xmlns URL for the Dazzle namespace is http://sculptedcode.com/dazzle/dazzle-xmlns/), but you can also set up Dazzle to use the Sparkle namespace instead (see here).
The available elements/attributes are:
version(attribute on the enclosure)shortVersionString(attribute on the enclosure)minimumSystemVersion(attribute on the enclosure)releaseNotesLink(element withinitemelement)
The version attribute provides the version number (CFBundleVersion) of the widget attached (in a compressed format) in the enclosure. If you don't specify the version attribute, you must name your archive in the format "WidgetName_VersionNumber.extension" (e.g. "DazzleDemo_1.2.wdgt.zip"). It is recommended that you supply the version attribute, because then Dazzle won't have to extract the version number from the enclosure URL and you will have more flexibility in naming your archives.
The shortVersionString attribute provides the version number of the widget attached in the enclosure to display to the user. This is relevant if you use a Subversion revision number or some other non-user-friendly number as your CFBundleVersion, and a more user-friendly number (such as 1.2) as your CFBundleShortVersionString.
The minimumSystemVersion attribute provides the minimum version of Mac OS X required for the widget attached in the enclosure to run properly. For example, if you decide to use Leopard-only features in version 2.0 of your widget, hence dropping support for Tiger, you can specify the minimumSystemVersion attribute with a value of "10.5".
The releaseNotesLink element provides a link to a release notes file on your website, and can be placed anywhere inside your item.
How to Create an Appcast
To create an appcast, start with a normal RSS feed:
<?xml version="1.0" encoding="UTF-8"?> <rss version="2.0"> <channel> <title>My Appcast</title> <link>http://sculptedcode.com/dazzle/DazzleDemo/appcast.xml</link> <description>Appcast for DazzleDemo Dashboard Widget</description> <language>en-us</language> <docs>http://blogs.law.harvard.edu/tech/rss</docs> <lastBuildDate>Thu, 4 September 2008 18:35:26 GMT</lastBuildDate> [Items Here...] </channel> </rss>
If you're going to be using any of Dazzle's custom elements or attributes, make sure that you define the Dazzle namespace on the rss element:
<rss version="2.0" xmlns:dazzle="http://sculptedcode.com/dazzle/dazzle-xmlns/">
Every time you release a new version of your widget:
-
Create a archive of your widget in the ZIP format. If you're going to specify a
versionattribute on the enclosure, you can name the archive any way you want; if you're not, you must name the archive in the format "YourWidgetName_VersionNumber.extension" (e.g. "DazzleDemo_1.2.wdgt.zip"). Upload this archive to your website. -
Create a new item in your appcast:
<item> <title>DazzleDemo 1.5 Released</title> <pubDate>Thu, 4 September 2008 18:35:26 GMT</pubDate> <link>http://sculptedcode.com/dazzle/DazzleDemo/</link> <description> DazzleDemo 1.5 has been released today! </description> </item>
-
Attach the archive created in step 1 to the appcast item using an enclosure:
<enclosure url="[...]" length="[...]" type="[...]" />
urlis the URL of the archive that you uploaded to your site.lengthis the size of the archive in bytes (see here for an easy way to find this).typeis the media type of the archive. It should have a value ofapplication/zip, since all your Dazzle archives should be in the ZIP format.
-
If you're going to specify the
versionattribute (recommended, as said before), include it now in the enclosure:<enclosure url="[...]" length="[...]" type="[...]" dazzle:version="[...]" />Also include here any other custom attributes that you want specify on the enclosure. -
If you want Dazzle to display a link to the release notes for your widget, include a
releaseNotesLinkelement somewhere in the item, which contains the URL of your release notes webpage:<dazzle:releaseNotesLink>[...]</dazzle:releaseNotesLink>
Here is an example Dazzle appcast:
<?xml version="1.0" encoding="UTF-8"?> <rss version="2.0" xmlns:dazzle="http://sculptedcode.com/dazzle/dazzle-xmlns/"> <channel> <title>My Appcast</title> <link>http://sculptedcode.com/dazzle/DazzleDemo/appcast.xml</link> <description>Appcast for DazzleDemo Dashboard Widget</description> <language>en-us</language> <docs>http://blogs.law.harvard.edu/tech/rss</docs> <lastBuildDate>Wed, 30 July 2008 17:57:00 GMT</lastBuildDate> <item> <title>DazzleDemo 1.2 Released</title> <pubDate>Wed, 30 July 2008 17:57:00 GMT</pubDate> <link>http://sculptedcode.com/dazzle/DazzleDemo/</link> <description> DazzleDemo 1.2 has been released today! <dazzle:releaseNotesLink>http://sculptedcode.com/dazzle/DazzleDemo/release-notes.html</dazzle:releaseNotesLink> </description> <enclosure url="http://sculptedcode.com/dazzle/DazzleDemo/DazzleDemo_1.2.wdgt.zip" dazzle:version="1.2" length="1234567" type="application/zip" /> </item> </channel> </rss>
Alert Box
Whenever Dazzle checks for updates and finds that a new update is available, it displays an alert box to the user. The default alert box looks like this:
The following illustration shows the anatomy of the alert box:
The alert box displays CFBundleDisplayName if possible, resorting to CFBundleName if CFBundleDisplayName is not available.
The same applies to the current version number: the alert box displays CFBundleShortVersionString if possible, resorting to CFBundleVersion if CFBundleShortVersionString is not available.
The latest version number comes from the appcast: the value of the shortVersionString attribute is displayed if provided; otherwise, the normal version number (obtained from either the version attribute or the enclosure URL) is displayed.
Temporarily Turning Off Alert Boxes
You may not want Dazzle to display an alert box while you are performing some operation in your code. For example, while you were doing a nice, animated resize of your widget, you wouldn't want Dazzle to display an alert box telling the user that a new update is available.
To solve this problem, use the setShouldDisplayAlertBox method, which simply tells Dazzle whether or not it should display the alert box when a new update is available. When you begin an operation, call this method and pass it a value of false:
dazzle.setShouldDisplayAlertBox(false);
...and when you've finished the operation, call it again, passing it a value of true:
dazzle.setShouldDisplayAlertBox(true);
Alternatively, you can use the setShouldAutomaticallyCheckForUpdates method to stop Dazzle from automatically checking for updates during your operation.
Turning Off Alert Boxes
If you never want Dazzle to automatically show the alert box, set the shouldDisplayAlertBox option to false when you initialise the Dazzle object:
dazzle = new Dazzle({
shouldShowAlertBox: false
});
Check Interval
Dazzle automatically checks for updates periodically. The interval between checks (the "check interval") is, by default, 3,600,000 milliseconds (an hour). You can specify your own check interval two ways:
-
As an option when you initialise the Dazzle object:
dazzle = new Dazzle({ checkInterval: interval }); -
By calling the
setCheckIntervalmethod:dazzle.setCheckInterval(interval);
The documentation for setCheckInterval says:
Sets the interval/frequency for automatic checks. This method can either be passed a number in milliseconds, or a preset string such as "hourly" that the method will convert into milliseconds. If it is passed the number zero, Dazzle will never automatically check for updates.
The checkInterval option simply passes the value to the setCheckInterval method, so the input is identical.
// All three statements are identical
dazzle = new Dazzle({ checkInterval: 3600000 });
dazzle.setCheckInterval(3600000);
dazzle.setCheckInterval("Hourly");
More examples of the setCheckInterval method (which will also apply to the checkInterval option) can be found here.
Info.plist Keys
Currently, Dazzle only uses one custom Info.plist key: DUAppcastURL. You can specify this key to tell Dazzle the URL of your appcast:
<key>DUAppcastURL</key> <string>http://mywebsite.com/appcast.xml</string>
However, I recommend that you supply the URL of your appcast to Dazzle using the appcastURL option instead.
Sparkle Integration
By default, Dazzle uses its own namespace in appcasts, which is "dazzle". However, it is possible to tell Dazzle to use the "sparkle" namespace in appcasts.
Why? There are many applications (such as Reinvented Software's Feeder) that generate appcasts with Sparkle namespaces, but do not generate appcasts with Dazzle namespaces. By telling Dazzle to use the Sparkle namespace, you can also generate your Dazzle appcasts with these applications.
To use the Sparkle namespace, set the useSparkleNamespace option to true when you create the Dazzle object:
dazzle = new Dazzle({ useSparkleNamespace: true });