This page tells you how to create a Desktop gadget using JavaScript, XML, and the Gadget API. Many of the details of creating a gadget are handled by the Gadget Designer. Once you're writing code, you'll probably want to refer to the Gadget API Reference.
To develop and distribute a Desktop gadget, you need to do the following (with the help of Gadget Designer):
gadget.gmanifest
file in XML that contains meta-information about the gadget.main.xml
file, which
defines the main view of your gadget. A view consists
of the UI and objects that completely make up one visible
pane of your gadget.options.xml
file, which
defines your gadget's options view.gadget.gmanifest
,
main.xml
, options.xml
(if you have one), and
any separate JavaScript files. If you hand-zip
the file instead of creating it with Gadget Designer,
rename the zipped
file so it has a .gg
suffix (for Google Gadget).When a user installs a .gg
-file-based gadget, their Google Desktop installation
handles unzipping, installing, and registering it, using
information from the gadget.gmanifest
file.
Note: Although you might see some old gadgets in .exe files, all new gadgets must be in .gg files.
Your gadget's gadget.gmanifest
file specifies, in XML format, metadata describing the gadget, as well as components that need to be
installed before gadget creation.
The manifest file content consists of a <gadget>
element, which has an attribute of minimumGoogleDesktopVersion
with a value of
the oldest version of Google Desktop that can run this
gadget. Inside this element, you define a required
<about>
element,
a recommended
<platform>
element,
and an optional
<install>
element.
The following table shows the elements
that the <about>
element can include.
The columns on the right show where the value of each element is used.
For example, the value of the <name>
element
is used
in gadget listings — the Add gadgets window,
online gadget directories,
and the web page automatically generated for each gadget —
as well as
in the Developers' Hall of Fame
and the gadget's user interface.
Note:
You can always specify element values directly,
like this:
<version>1.0.0.0</version>
.
Alternatively,
a few elements
(<name>
,
<description>
, and
<aboutText>
)
can have a value
that refers to a variable
defined in strings.xml
.
For example,
<name>&GADGET_NAME;</name>
refers to the value of the
<GADGET_NAME>
element
in the current locale's strings.xml
file.
Don't use a variable unless the element description
says the value can be a variable.
Element | Description | Where Used | ||||
---|---|---|---|---|---|---|
Listings |
Hall of Fame |
UI |
Other/Notes | |||
<id> |
The gadget's CLSID. Generate this string using a tool such as Gadget Designer, uuidgen, or an online [uuid generator]. | Used by Google Desktop to differentiate between gadgets. This value must be unique for each gadget, and it should remain the same when the gadget is updated. | ||||
<name> |
The gadget's name.
The value can be a variable defined in strings.xml . |
![]() |
![]() |
![]() |
||
<description> |
A short description of what the gadget does.
The value can be a variable defined in strings.xml . |
![]() |
![]() |
Used in the gadget installation dialog, as well as the gadget's automatically generated web page. | ||
<version> |
The gadget's version number.
Example:
<version>1.0.0.0</version>
|
Used by Google Desktop to check whether the online version of the gadget is newer than the cached version. | ||||
<author> |
The name of the person or company that wrote the gadget. |
![]() |
![]() |
Also used as part of the gadget filename
in the user's My Google Gadgets folder. |
||
<authorEmail> |
An email address for contacting the developer. |
![]() |
![]() |
Used by Google and users of your gadget to contact you. Also used to attribute gadgets to the developer for the Developers' Hall of Fame. If you're concerned about receiving spam, consider using an alternate email address. | ||
<category> |
One or two categories that describe the gadget.
A gadget has exactly one <category> tag.
Possible values:
communication ,
finance ,
fun_games ,
google ,
holiday ,
lifestyle ,
news ,
sports ,
technology ,
tools .
Example:
<category>fun_games</category>
Another example: <category>news,sports</category>
|
![]() |
Used in gadget listings.
For example, when the user clicks News
in the Add gadgets dialog or an
online gadget directory,
only gadgets that have the category news appear.
|
|||
<thumbnailUrl> |
The URL for a 80x60-pixel image that represents your gadget. |
![]() |
Used to represent your gadget
in gadget listings where space is limited.
Once your gadget is published, you can update its images in two ways. You can change the values of thumbnailUrl
and screenshotUrl
in the manifest for your gadget's .gg file.
Or you can just update the images,
while retaining the same URLs.
|
|||
<screenshotUrl> |
The URL for a 300x225-pixel image that features a screenshot of your gadget. |
![]() |
Used to represent your gadget in the web page
that's automatically generated for each gadget.
For more information, see the description of <thumbnailUrl> .
|
|||
<authorWebsite>
(optional) |
The URL for a page that describes the gadget. |
![]() |
![]() |
Used for the "Learn more" link in the gadget's listings. | ||
<copyright>
(optional) |
A copyright notice. |
![]() |
||||
<aboutText>
(optional) |
Text for the About dialog.
The value can be a variable defined in strings.xml .
The About text should have at least three lines,
using the following format:
|
![]() |
||||
<smallIcon>
(optional) |
A 24x24-pixel icon, preferably a PNG with transparency. | ![]() |
Used to represent the gadget, such as when the gadget is collapsed. | |||
<icon>
(optional) |
A 32x32-pixel icon. | ![]() |
Used in the gadget's About dialog. | |||
<displayAPI>
(optional) |
When the usesNotifier attribute is set to true,
enables sidebar UI notifications for
content items.
Registration is handled automatically. Example:
<displayAPI usesNotifier="true" /> |
|||||
<eventAPI>
(optional) |
If this element is included, the
gadget can use the
Event API. Registration is handled
automatically. Example:
<eventAPI /> |
|||||
<queryAPI>
(optional) |
When allowModifyIndex is set
to true , allows the gadget to use the
Query API.
Registration is handled automatically. Example:
<queryAPI allowModifyIndex="true" /> |
|||||
<personalizationAPI>
(optional) |
When present, allows the gadget to use a personalization API such as the
Ranking API.
Registration is handled automatically. Example:
<personalizationAPI /> |
Here's an example of a
gadget.gmanifest
file:
<gadget minimumGoogleDesktopVersion="5.1.0.0"> <about> <name>Gadget Name</name> <description>A few words about the gadget</description> <aboutText>Gadget Name Copyright (c) 2008 Some Company, Inc. All Rights Reserved Longer description of the gadget.</aboutText> <smallIcon>icon_small.png</smallIcon> <icon>icon_large.png</icon> <version>1.0.0.0</version> <author>Your Name</author> <authorWebsite>http://somecompany.com/gadgets.html</authorWebsite> <id>YOURCLSID-C739-4685-A470-F4FF5E7F47FB</id> <copyright>Copyright (c) 2008 Some Company, Inc. All Rights Reserved</copyright> <authorEmail>YourName.feedback+GadgetName@gmail.com</authorEmail> <category>fun_games</category> </about> </gadget>
You must include (with values) the <id>
, <name>
, <description>
,
<version>
,
<author>
, and
<authorEmail>
elements.
We urge you to also include
(with values) the
<authorWebsite>
, <copyright>
, <aboutText>
, <smallIcon>
, and <icon>
elements. You may see examples of the latter
set of elements included without a value, such as <copyright>
</copyright>
. This is acceptable, but not preferred.
We suggest that you use a single, dedicated email address for all of your gadgets. Using a dedicated address cuts down on spam to your personal account, and using a single address improves your chances of getting into the Developers' Hall of Fame.
One approach is to
create a Gmail account
with a login name such as helensmith.feedback
.
Then specify an <authorEmail>
value of the form
helensmith.feedback+gadgetname@gmail.com
.
Because Gmail ignores + and anything after it,
email messages for all gadgets go to
helensmith.feedback at gmail.com.
To find the feedback for a particular gadget,
search for to:gadgetname
.
Use the <platform>
element, along with the
minimumGoogleDesktopVersion
attribute
of the <gadget>
element,
to specify the versions of Google Desktop that your gadget works with.
Inside the <platform>
element,
you define one element
for each platform on which the gadget has been tested —
<windows>
, <mac>
, or both.
For each included element, define
minimumGadgetHostVersion
if the gadget works on that platform,
or supported="no"
if it doesn't.
Here are details on the elements that the
<platform>
element can include:
<windows>
<mac>
"1.0.0.0"
.
The following examples show typical uses of the <platform>
element.
Gadget works on both Windows and Mac:
<gadget minimumGoogleDesktopVersion="5.1.0.0"> <platform> <windows minimumGadgetHostVersion="5.1.0.0"/> <mac minimumGadgetHostVersion="1.0.0.0"/> </platform> ... </gadget>
Gadget doesn't work on Mac:
<gadget minimumGoogleDesktopVersion="5.1.0.0"> <platform> <windows minimumGadgetHostVersion="5.1.0.0"/> <mac supported="no"/> </platform> ... </gadget>
Gadget not tested on Mac:
<gadget minimumGoogleDesktopVersion="5.1.0.0"> <platform> <windows minimumGadgetHostVersion="5.1.0.0"/> </platform> ... </gadget>
For more information, see Writing a Cross-Platform Gadget.
The optional
<install>
element lists any package components
that need to be installed before creating the
gadget.
For example to install a fonts package,
include the <font>
element:
<gadget ...> ... <install> <font src="mcfont.ttf"/> </install> </gadget>
To include a COM dll or embed an ActiveX control with your gadget add the dll file to
the package and use the <object>
element to register the object:
<gadget ...> ... <install> <object name="myobject" clsid="OBJCLSID-HERE-..." src="my.dll"/> </install> </gadget>
For the clsid property you can also use a progid in the format "progid:myobj_progid". To call methods on your embedded control from script do:
var obj = new myobject; obj.MyMethod();
The Gadget API Reference
lists the properties,
methods, and events for elements that you can define in a
gadget and its views (where "view" means the overall appearance of a pane). You use these elements in XML view files to specify
the gadget's UI components, layout, and behavior. For your gadget's
main view you
need to write a main.xml
XML file that
defines a <view>
element. If
your gadget has an Options view, you also need to write an options.xml
file which defines a different
<view>
element.
Inside a <view>
definition, you
define the UI elements that make up that view. For example, a
main.xml
file might contain:
<view width="200" height="200"> <button image="button.png" overImage="button_over.png" downImage="button_down.png" onclick="button_clicked()"/> </view>
That defines a 200x200 pixel view that contains a
button. We also specify, by setting the relevant button
object properties, separate images for the button's
normal, mouse-over, and mouse-down states. Via button
's onclick
event,
when a user clicks the button, it calls the button_clicked()
function, defined elsewhere.
To specify a property in XML, add
property="value"
to an element. You can
specify an event scriptlet in XML by adding an
event="script"
to an element.
As with DHTML, you can manipulate elements from a script once they're
created, but only if they have a name
property. For
example:
<button name="sample_button" ... />
When an element has a name, scripts can access and manipulate it, as well as call any methods associated with it:
sample_button.property = "new value"; sample_button.event = "new script"; sample_button.method();
You can either use script
functions defined elsewhere in your .gg
file
package, including in dedicated .js
or
.vbs
files (such as the button_clicked()
function used in the button
example above), or you can include scripted functions within the
<view>
definition. For
example:
<view width="200" height="200" onopen="view_onopen()"> <script language="jscript"><!-- function view_onopen() { foo( "bar()", 1000 ); } function bar() { x = 2 + 2; } --></script> <div background="#FFFFFF" width="200" height="200"/> </view>
Only one contentarea
object can be defined inside a view
object.
Note: For more help on defining views, see the article Using the Options Dialog.
The gadget event model is similar to DHTML. For
some objects — including view
,
basicElement
,
and some elements —
the Gadget API Reference
lists associated events.
To specify how to
handle an event for one of these objects, you put the event and
what to do when it happens in the object's XML definition. For
example, to specify what happens when a view
object has an onmouseover
event, you'd write:
<view onmouseover="do_something_when_mouse_is_over;"/>
...where
do_something_when_mouse_is_over
is a piece of script, such as alert('mouse over!')
,
or a call to a function implemented in a script block, such as
view_onmouseover()
.
As with DHTML, events and their handlers have
no arguments. Instead, the script uses the
view.event
object
to learn about the
event. Since only one event
fires at a time, a view's event
object contains information about the event currently being fired.
The event.returnValue
property can be
used to set a return value. As with DHTML, this value is a boolean
that determines if the event's default behavior is fired. For
example:
event.returnValue = false; // disable the default behavior event.returnValue = true; // enable the default behavior // don't specify a return value, enable the default behavior
In particular, the event.returnValue
property can either:
view.event.returnValue = false; //Disable the view
event's default behavior
view.event.returnValue = true; //Enable the view
event's default behavior
For example:
<edit onkeypress="edit_onkeypress()"/> function edit_onkeypress() { if( event.keyCode == 'j' ) event.returnValue = false; }
Each time you press a key when control is
inside this edit
object, the
edit_onkeypress()
function is called.
If the key you press is j
, then
since the event.returnValue
is set
to false
, the event and its usual return value
are cancelled, making it as if the j
was never pressed.
Effectively, this <edit>
element doesn't allow you to type the letter j.
You should write your gadget to support having its text and labels appear in multiple languages, even if you can't supply any other-language text. Eventually, someone else may be able to do so. You can also specify different images, view layouts, or even scripts for different language users.
First, let's look at languages. To support
multiple languages, all
language-specific strings that will be visible in your gadget's
UI must be placed in a file named strings.xml
under
subfolders named after the appropriate language ID. This
file contains variable assignments for the strings in a particular
language. Instead of using the language-specific strings in your
gadget definition and code, use
the variables instead. For example, Hello World's English
strings.xml
file contains:
<strings> <GADGET_NAME>Hello World Sample Gadget</GADGET_NAME> <GADGET_DESCRIPTION>Demonstrates a simple Google Desktop gadget</GADGET_DESCRIPTION> <GADGET_COPYRIGHT>Copyright (c) 2006 Google Inc. All Rights Reserved</GADGET_COPYRIGHT> <GADGET_WEBSITE>http://desktop.google.com/</GADGET_WEBSITE> <GADGET_ABOUT>Hello World Sample Gadget Copyright (c) 2006 Google Inc. All Rights Reserved This gadget displays the text 'Hello World' on top of a picture using the main.xml design file. If the text is clicked on, a message box will show up as an event.</GADGET_ABOUT> <HELLO_WORLD>Hello World!</HELLO_WORLD> </strings>
In your script code for the Hello World gadget, you'd specify the "Hello World!" string as shown in this method invocation:
view.alert(HELLO_WORLD);
In your XML files you'd specify "Hello World!" as shown in this
<label>
element:
<label>&HELLO_WORLD;</label>
Note that in script code, you just use the element
name from the strings.xml
file. In
XML, you need to preface the element name
with an ampersand (&
)
and end it with a semicolon (;
).
If you wrote your gadget to have both English and French versions, your files should be in the following hierarchy:
YourGadget | |---- main.js | |---- main.xml | |---- other non-language-specific files... | |---- en (identifier for English) | | | `-- strings.xml | `---- fr (identifier for French) | `-- strings.xml
Note:
Previously, this document used numeric codes for languages.
For example, the preceding example used
1033
instead of en
and 1036
instead of fr
.
We now recommend using modified RFC1766 language codes
such as en
,
fr
,
fr_ca
,
and zh_cn
.
You can also provide a default version
under a folder named 1033
,
since that will be used if no language matching
the Google Desktop locale
or the computer's current locale
can be found.
Google Desktop first checks for a folder with
a language ID that matches the installed version of Google Desktop.
For example, the French version of Google Desktop
looks for the fr
folder.
If Google Desktop finds the folder,
it loads that folder's strings.xml
file.
If it cannot find that file,
Google Desktop looks for the file in a folder
whose name matches the computer's current Windows LCID
(for example, 1036\strings.xml
for France).
If Google Desktop still cannot find the file,
it looks for 1033\strings.xml
.
Similarly, you can put images, markup,
script, etc. in the localization folders,
and Google Desktop will attempt
to load them using the above rules. So, for example, if you have
a gadget that requires a different image depending on the local
language, you can use
<img src="some_image.png"/>
.
Google Desktop will first try to load
some_image.png
.
If that fails and you have the French version of Google Desktop,
it will look for the file in the French localization folder (fr\some_image.png
).
If that fails, Google Desktop will look for the file in a folder
that matches the system's Windows LCID
(1036\some_image.png
for France).
If Google Desktop still doesn't find the file,
it will look in the 1033
folder
(1033\some_image.png
).
You can put content in a localization folder instead of the main folder, including:
main.xml
: If you need different layouts in
different languages.options.xml
: If you need different layouts in
different languages.anything.js
: If you need different scripts in
different languages.If you want to create a gadget that supports default behavior in most places but has different behavior in specific languages you can:
gadget.gg
file.1033
folder
of your gadget.gg
file.This document discusses the Gadget API, but that's not the only API that gadgets can use. Any Desktop gadget can also use the following standard interfaces:
Array
,
Date
,
Math
,
and RegExp
.
Example: XMLHttpRequest
(available online and in the SDK)
Article:
Interacting With The Web: The XMLHttpRequest Object
Many powerful gadgets use only the preceding APIs. An advantage of sticking to these APIs is that your gadget can work on multiple platforms. For tips on writing gadgets that work on both Windows and Mac, see Writing a Cross-Platform Gadget.
If you want to tap into the power of Google Desktop, you can use the following Search APIs, which are available for Windows only:
If you want still more APIs, you can include a COM DLL or embed an ActiveX control in your gadget, as described in The install Element. For sample code, see the HybridYesNoCancel example (available online and in the SDK).
In this section, we'll take a look at the various objects in the Gadget API, focusing on what they're used for and how they are related.
gadget
Objectgadget
has two subobjects,
gadget.debug
and gadget.storage
, which
are used for very different purposes at the overall gadget
level.
gadget.debug
helps with debugging by
providing methods that display a string of your choice in the
debug console when running in debug mode. To run in debug mode,
unzip your gadget and, from the file you unzipped it to,
double-click the gadget.gmanifest
file. This lets you
develop your gadget without having to zip it up each time you want
to test it.gadget.storage
works with the files that make up
the overall gadget package. Methods allow you to extract or open a
file from the package. The filename arguments to the storage
object can be any of the following:"foo.xml"
looks for foo.xml
in the
root folder of the .gg
file. If it doesn't find it,
it will look in the localization folders
(e.g. en\foo.xml
)."subfolder\foo.xml"
looks for
foo.xml
in the subfolder
folder
of the .gg
file. If it doesn't find it, it will look
in the subfolder
folder of the localization
folders (e.g. en\subfolder\foo.xml
)."c:\bar.xml"
looks for bar.xml
on
the c:\
drive. You must provide the exact path.view
ObjectYou must define a view
object for
each overall pane appearance your gadget has. Each of these must
be in a separate .XML
file.
view
's properties and methods
define and access the overall behavior of a view pane. These
include what UI elements make up the pane's appearance, the size
of the pane, whether it's resizable by a user, timers that control
script execution, adding or removing UI elements, and
message/confirmation box display.
view
's events fire and run a
function based on various mouse button, key, resizing, property
value change, or cursor actions, as well as when this view is
first opened.
basicElement
and UI ObjectsbasicElement
is the parent object
for the various UI elements that make up the visual appearance of
a particular view. basicElement
itself is never
instantiated; it just provides a set of common properties and
events for its descendant UI objects.
Properties specify the size and position of the element, its name, visibility and opacity, and other general UI element properties.
Events are the usual ones associated with a UI object; actions involving mouse clicks or the scroll wheel, dragging or dropping the element, receiving or losing keyboard focus, keys, and cursor movement.
You can define the following
basicElement
descendants:
button
: Specific properties
let you set various images for the button and its various states.checkbox
: Specific properties
let you set various images for the checkbox and its various
states, as well as determining if the box is checked or not. An
event fires when the box's checked value changes.object
: An embedded windowless
ActiveX control. Used primarily for Windows Media Player embedding.contentarea
: Contains a collection of
contentItem
s.div
: Used to set element
background colors or images.edit
: Specific properties let
you control its text content's appearance and set or retrieve its
text content. An event fires when the content changes.img
: Specific properties
let you set the image to display and get its original
dimensions. It also has an image resizing method.label
: Specific properties let
you control the label text's appearance and position/alignment.a
: A link object with specific
properties that let you control the link's appearance and its URL.progressBar
: Specific
properties control the appearance of the progress bar and its
components, as well as an event that fires when the value changes.There is also the elements
object,
which represents a container of basicElement
-descended objects.
options
ObjectStores options and their values as a standard dictionary/map. You can set a value like this:
options.putValue("key", "value");
You can add items using either the putValue
or the add
method:
options.putValue("key", "value"); //Add or replace the current value. options.add("key", "value"); // Add the value; if it already // exists, do nothing.
The putDefaultValue
method allows keys to return default
values if the key does not have an actual value associated with it
in the dictionary, removing the need for you to check if a value
exists for that key. For example:
options.putDefaultValue("color", "red");
The dictionary now returns "red" whenever "color" is requested and "color" does not actually exist in the dictionary. For example:
options.putDefaultValue("color", "red"); options.putValue("color", "blue"); debug.trace(options.getValue("color")); // displays "blue" options.remove("color"); debug.trace(options.getValue("color")); // displays "red" (the default) options.putValue("texture", "bumpy"); debug.trace(options.getValue("texture")); // displays "bumpy" options.remove("texture"); debug.trace(options.getValue("texture")); // displays "" (no default)
framework
NamespaceThe framework
namespace exposes
APIs that fill in gaps left by the Windows Scripting Host and are
useful for gadget implementation. In particular,
framework.*
objects are not descended from
basicElement
and do not show up in gadget XML UI
object definitions. framework
is basically a
.NET-like namespace of objects used to query for system
information, which are used by scripts called by events on the XML-defined
UI objects.
framework
objects and their
properties and methods allow you to:
Finally, there are two other defined objects
used only for types within the Framework
namespace:
point
: Represents a point, with x- and y-
coordinate properties.size
: Represents an object's size, with height and
width properties.As an example of how you might use
framework
objects, let's write a
simple gadget that shows how much power is left on your laptop's
battery:
<view width="200" height="200" onopen="view_onopen()">
<script language="jscript"><!--
function view_onopen()
{
setInterval( "update_battery()", 1000 );
}
function update_battery()
{
percent_used.innerText = system.power.percentRemaining + "%";
}
--></script>
<div background="#FFFFFF" width="200" height="200"/>
<label name="percent_used" align="center" valign="middle">0%</label>
</view>
We've defined a view that is 200x200 pixels with two elements in it:
<div>
with a background color of white<label>
named percent_used
that initially reads 0%.When the gadget loads, the view onopen
event fires, which calls view_onopen()
. This function sets an
interval so that update_battery()
is called once every second. update_battery()
uses the framework
namespace's system.power.percentRemaining
object and property to
update the innerText
of the percent_used
element.
Note that we didn't have to put
framework.
before system.power.percentRemaining
; it's your choice
whether to do so or not.