Tuesday, April 30, 2013

Figure 2 shows my MSDN Magazine Ticker gadget (that shows scrolling article headlines from the most recent issue) and a weather gadget (that ships with Windows Vista) in both their docked and floating states. The weather gadget is an excellent example of a gadget that provides a richer experience when floatingit goes from giving just the current temperature to giving a detailed three day forecast. The MSDN Magazine Ticker gadget doesnt display any additional information; it simply expands to show the same information in a wider format.

If you plan on doing anything interesting within your gadget, youd better brush up on your JavaScript. You can code with any scripting language that is supported by Internet Explorer 7, but you will find that most of the gadget samples on the Internets are written in JavaScript.

In the sample presented here, all of the HTML for the gadget is created dynamically from within the gadget.js JavaScript file. You could include most of the markup in the main HTML file, but what fun would that be?

I settled on the idea for an RSS reader that displays news headlines. As this sample is for an MSDN Magazine article, it seemed like an obvious choice to use the RSS feed for all articles in the current issue of the magazine (this is available at msdn.microsoft.com/msdnmag/rss/rss.aspx). Imagine how dynamic and informative you could make this gadget if you were to use a feed of news or sports headlines, or even multiple feeds federated into one data source.

This uses the Cabarc.exe utility to generate a CAB file. (Cabarc.exe is a free Microsoft tool that is installed with Visual Studio. Its also available separately as part of the Cabinet SDK, which you can download from support.microsoft.com/kb/.)

In this article, I explore the major parts of a Sidebar gadget and then demonstrate how these elements come together to create a sample gadget: an MSDN Magazine Ticker for the Windows Vista Sidebar. Note that I focus strictly on developing Windows Vista Sidebar gadgets. Thus, when I use the term gadget, I am referring specifically to a Sidebar gadget. (If youre interested in developing SideShow gadgets, see Jeffrey Richters article in the January 2007 issue of MSDN Magazine.)

Debugging JavaScript has always been tricky. Many developers have resorted to placing alerts in their code to display the values of certain variables. This, however, is not an elegant solution. A better method involves using Visual Studio (or even the free Visual Web Developer™ 2005 Express Edition).

Next, I set up the onunload event that will be called as the gadget is destroyedeither as the user closes the gadget or when Sidebar is shut down. Again, this is done to free up any references that may cause memory leaks. It is also your last chance to save any settings if need be. Ill talk all about settings a little later in the article.

Keep in mind that you cannot control the location of the flyout. Sidebar determines the location based on screen real estate and the position of the gadget itself. For example, the flyout could be displayed to the left or to the right of the gadget. Or even below it.

My sample gadget is also a lot more compact that the feed gadget that ships with Windows Vistaits a mere 57 pixels high (versus 175 pixels for the deult gadget). This is great for on a smaller screen (or a cluttered Sidebar) where real estate is at a premium.

A Sidebar gadget can be a powerful and handy little tool. So you might be surprised by how easy they are to create. In ct, if you know HTML, CSS, and JavaScript (and I suspect many of you already do), youre well on your way.

Then create a file that contains the code shown in Figure 7 and name it alert.vbs. Now you can continue to use alert and confirm as you wish.

Note that Sidebar gadget flyouts are system modalonly one can be displayed at a time. If the user clicks on Gadget A, causing a flyout, and then clicks on Gadget B, causing another flyout, Gadget As flyout will close. Furthermore, when a gadget loses focus, its flyout will close.

Lint was the original name given to a tool that flagged problem areas in C source code. It is now a general term applied to many source languages. One of the better lint applications for JavaScript is a free online tool called JSLint (available at

The gadget follows all of the recommendations given in this article: it uses a flyout to display detailed information when you click on a headline, it lets you select from three different feed reload times in the Options dialog, it changes size when moved to a floating state, and it supports several languages through the use of localization folders.

As you can see, your code will react differently depending on which local.js file is loaded by Sidebar. Cool, huh?

There are a few different methods you can use if you want to programmatically generate a gadget. In my projects, I create the following batch file called make.bat:

A user can access the options dialog by clicking on the wrench icon in the gadgets (see Figure 3), which appears when you hover over the gadget. When a user opens the options dialog of a gadget, Sidebar takes a snapshot of the gadget and displays the image as a small icon (see Figure 6).

Receive the MSDN Flash e-mail newsletter every other week, with news and information personalized to your interests and areas of focus.

The MSDN Magazine Ticker

System.Gadget.settingsUI = settings.html; System.Gadget.onSettingsClosed = settingsClosed; function settingsClosed(p_event) //OK clicked? if (p_event.closeAction == p_event.Action.commit) //yes, read settings here

Language is obviously important, but why is location important? Location is actually very important for certain gadgets. Consider the weather gadget. You may display the word sunny to users in both the United States and the United Kingdom, but the location will determine whether you should display the temperature in Fahrenheit (US) or Celsius (UK).

Sidebar gadgets support localization by way of localized folders. Whenever Sidebar tries to load an asset (a gadget manifest, style sheet, image file, JavaScript file), it searches for the file in folders in the following order:

The flyout APIs are exposed from the System.Gadget.Flyout object. A flyout lives in a completely isolated window (with its own DOM) from that of the main HTML window. As such, you need to provide a separate flyout HTML file, along with any other necessary supporting files. The flyout file is specified by setting System.Gadget.Flyout.file to the name of the flyout HTML file.

What Is a Sidebar Gadget?

Localization

Windows Vista Sidebar already ships with a feed headlines gadget. What makes my sample unique is the way the information is presented. The headlines are displayed in a news ticker shion, like you see at the bottom of your TV screen on news channels.

The May 2007 issue of MSDN Magazine has an excellent feature on JavaScript titled Create Advanced Web Applications with Object Oriented Techniques by Ray Djajadinata. You should check it out if you havent already done so. This article will go a long way to helping you write a better gadget.

Im sure some of you are saying, No body onload? How will my code execute? I suggest that you get in the habit of attaching a function to the onload event of the window object. This code snippet shows how to attach to the onload and onunload events:

Figure 1 shows a typical skeleton XML definition file. As you can see, it is a standard XML file with a base element of gadget. Here is a list of the elements you should be most concerned with:

When I started developing Sidebar gadgets, I found this very refreshing. Over time, I began to take this for granted and when I recently had to design a Web page, I found myself getting vGadgetsery aggravated when I had to deal with cross-browser issues once again.

Donavon West is an independent consultant, CTO for LiveGadgets.net, and a Microsoft MVP for Windows Live Development. Originally from Chicago, he now lives in the Baltimore/Washington DC area. He is very active in the gadget development community, both with Windows Vista Sidebar and Web gadgets. You can reach him through his Web site at

// called when the docked state changes function dockStateChanged() if (System.Gadget.docked) System.Gadget.background = images/background.png; document.body.style.width = 130 else System.Gadget.background = images/background-undocked.png; document.body.style.width = 230

You can query the current state of a gadget with System.Gadget.docked. It returns true if docked, lse if undocked. There are also two events that you can monitor, System.Gadget.onDock and System.Gadget.onUndock, to determine when the docking state changes.

Reading and Writing Settings

There is an API you can use to cilitate communication between the main and flyout windows. System.Gadget.Flyout.document returns the Document object of the flyout window. You can use this from the main gadget window to dynamically generate HTML in the flyout window.

You can also package your gadget as a CAB file, which is the Microsoft native compressed archive format. Just generate the CAB file and then rename it with a .gadget extension. (By the way, if you ever try renaming a .gadget file with a .zip extension and Windows Explorer complains when you try to open this ZIP file, try renaming the file with a .cab extension instead.)

element.innerHTML = L_Hello; if (L_Degrees === 0) //load the Fahrenheit feed else //load the Celsius feed

Note that with the English local.js in the gadget root, the gadget will still function for non-supported locales, albeit in the llback language (in this case English). It is very important to support a deult language in your gadgets root folder. If you dont provide a deult language and someone uses a language that isnt supported by your gadget (meaning a language for which you have not created a subfolder), your gadget will display blank strings.

You cannot simply change the class of the document.body from within an onDocked or onUndocked event to change the height, width, or background image of a gadget (this is contrary to my initial expectations). Instead, you must specifically set the properties of the style object of the body element. To change the background image, use the System.Gadget.background API to set the filename of the background image. Heres an example:

function pageLoad() window.detachEvent(onload, pageLoad); window.attachEvent(onunload, pageUnload); //page initalization here function pageUnload() window.detachEvent(onunload, pageUnload); //gadget is closing, clean up window.attachEvent(onload, pageLoad);

simulate JavaScript alert() function sub alert(prompt) MsgBox prompt, 48 , Sidebar Gadget end sub simulate JavaScript confirm() function function confirm(prompt) dim res res = MsgBox (prompt, 33, Sidebar Gadget) if res=1 then confirm = true else confirm = lse end if end function

Note that there is an undocumented minimum height of 57 pixels for a gadget (whether docked or floating). The reason for this minimum is : the height of the when a gadget is in its floating state is 57 pixels (see Figure 3).

Settings are written using System.Gadget.Settings.write or System.Gadget.Settings.writeString. Both are passed a key/value pair.

Debugging

As you look at the HTML for a gadget, youll notice that there is absolutely nothing that distinguishes it from HTML that you would code for a regular Web page. Here is the HTML code I use to start practically all of my Sidebar gadget projects:

In its st form, a gadget is made up of nothing more than an HTML file and an XML definition file. Of course, most gadgets include other files, such as image files (PNG and JPG), Gadgets style sheets (CSS), and scripting (JavaScript and VBScript source files). All of the content is stored in a ZIP file that is renamed with a .gadget extension. If you want, you can grab a gadget online, rename it with a .zip extension, and easily explore its contents. I recommend this as a good way to peek into other gadgets and see what theyre made up of.

?xml version=1.0 encoding=utf-8 ? gadget nameGadget Name Here/name namespaceYourCompanyNameHere/namespace version1.0.0.0/version author name=Company Name Here info url= text=Vist our Web site / logo src=logo.png / /author copyright 2007/copyright descriptionyour gadget description/description icons icon width=64 height=64 src=icon.png / /icons hosts host name=sidebar base type=HTML apiVersion=1.0.0 src=gadget.html / permissionsfull/permissions platform minPlatformVersion=0.3 / /host /hosts /gadget

Now that Ive covered all the basic components of a gadget, Id like to present a sample gadget that pulls all the parts together. The MSDN Magazine Ticker gadget is available as a download so you can install it or simply explore its contents.

Weve all been on Web sites and received the Invalid input, please try again alert and the Delete record. Are you sure? confirmation dialog. Developers often want to pop up informational messages like these.

Figure 9 shows a section of debugged code where the value of the variable refreshRate is 24. This form of debugging is very powerful. Once you try it, youll never go back to spattering your code with alert statements. Note that JavaScript debugging is vastly improved in the next version of Visual Studio code-named Orcas. You can read more about these new features at JScript Debugging in Visual Web Developer Orcas, and you can download Orcas Beta 1 at msdn2.microsoft.com/aa.

By using this method, function pageLoad is called well after the page loads (when the DOM is complete). Notice that the first thing I do in pageLoad is detatch the event. It is always a good idea to clean up after yourself in JavaScript to prevent memory leaks.

I should point out that while developing the main HTML file for a gadget is entirely like building a page that will be deployed online, the gadget implementation has a major advantage. You dont have to worry about cross-browser issues. Since your gadget will always be run under Internet Explorer, you can rely on support for Internet Explorer features, such as native PNG alpha support,new york escort and theres no need to write code to account for browser incompatibilities.

You need to instruct the gadget to enable the options icon. This is done by setting System.Gadget.settingsUI to the name of the HTML file, generally in the gadget initialization area of your script. You also need to set up a callback function for when the options dialog closes (so your gadget can read the new user preferences). You do this by setting System.Gadget.onSettingsClosed to the name of your handler, as shown here:

You may have noticed by now that Im a bit of a stickler for writing good, clean JavaScript, so please indulge me one more time on the subject. I strongly suggest that you lint your code before deployment. This will not only make your code better, but it may even root out some bugs before they happen.

Youve probably heard a lot of buzz lately about gadgetsthese are the lightweight applications that youve seen, for example, sitting on a Windows Vista™ desktop. There are actually three different types of gadgets supported by Microsoft. Sidebar gadgets are the ones that run on the Windows Vista desktop. Web gadgets are similar, but run on Live.com and Windows Live Spaces pages. SideShow gadgets run on devices such as secondary displays on laptops, remote controls, and computer keyboards.

The XML definition file, or manifest, is the glue that holds a gadget together. I am not sure about calling this file a manifest since it does not contain links to all of the files in the gadget; it only contains links to the main HTML file (which has links to the other files), a few icon files, and the gadget authors Web site.

Options Dialog

Docked and Floating

JavaScript is not a strongly typed language and if you use write and read, Sidebar will attempt type conversion. If you want to be absolutely sure what is written and read, consider using writeString and readString as these will assume strings. Depending on the type of data in question, you will have to determine which methods will work best.

I was a bit surprised to find that user settings are stored in a circa 1990 INI file instead of a more modern XML file. Fortunately, there are gadget APIs to read and write settings, so where and how the settings are stored is of little concern to you or your application.

There are a few caveats when it comes to creating your options UI. The width of the user area of the dialog is limited to a maximum of 300 pixels. There is no height limit, but the Microsoft UX Guide for Windows Vista Gadgets recommends a maximum width of 278 pixels and a height of no more than 400 pixels. If you need more room, you should probably create a tabbed dialog. I wont talk about how to implement a tabbed UI in this article, but there are plenty of resources on the Web to learn how you can do this.

Packaging Your Gadget

Notice that I use CSS style sheets. This is what will drive the look of my gadget. As with any Web page, style sheets are an essential part of designing good-looking gadgets. Thus a good understanding of CSS is critical when producing a professional-looking gadget.

The Main HTML File

Ive only scratched the suce of Sidebar gadgets to demonstrate how easy it is to get started. Theres so much more you can do. The Additional Resources sidebar has more information.

echo off rem remove/create a test gadget folder rd %LOCALAPPDATA%\Microsoft\Windows Sidebar\ Gadgets\MSDNSample.gadget\ /s /q md %LOCALAPPDATA%\Microsoft\Windows Sidebar\Gadgets\MSDNSample.gadget\ rem copy all of the files into test area xcopy . %LOCALAPPDATA%\Microsoft\Windows Sidebar\ Gadgets\MSDNSample.gadget\ /y /s /q /EXCLUDE:exclude.txt cd %LOCALAPPDATA%\Microsoft\Windows Sidebar\Gadgets\MSDNSample\ cabarc -r -p n %HOMEPATH%\Documents\MSDNSample.gadget

Many developers will likely support an English-only gadget, but if locale is important to you I recommend that you put all of your language-specific strings and location-specific variables in a single JavaScript file called local.js and place this file in the gadget root folder. Then create a folder for each locale that you are going to support and copy the translated versions of local.js into their respective folders. Here is an example of a local.js file in the root folder, representing en-us:

There are also events that can be captured by both the main and flyout code. These include onShow, which is called just after the flyout document has been created, and onHide, which is called just before the flyout document is destroyed.

You can programmatically show or hide the flyout by setting System.Gadget.Flyout.show to true or lse, respectively. And reading this value will tell you the current state of the flyout window.

The st way to create a package is with Windows Explorer. Select the files that make up your gadget, right-click, and select Send To Compressed (zipped) Folder.

Flyouts

Most of the elements in the definition file are used for displaying the gadget in the gallery. The one truly functional element is the src attribute of the base elementthis points to the HTML file that will kickstart the gadget. I make it a practice to name this file gadget.html, but any valid filename will do.

Now that you understand why you should never use eval, Im going to amend that rule to include that you should never place JavaScript text in an attribute inside of your HTML nor pass a string to setInterval or setTimeout. And when I say that you should never place JavaScript text in an attribute inside your HTML, this includes the body onload attribute, as this is interpreted internally just as an eval statement would be.

Simply place debugger statements in your code, wherever you need to check the value of a variable, then run the gadget. When JavaScript executes the debugger statement, you should see a popup that asks if you want to debug the application (see Figure 8). Choosing Yes will allow you to browse the entire gadget environment, including the DOM, and view the value of any variable created. Your gadget is essentially frozen in time.

As you can see from this example, when the handler is called, it is passed an event object specifically the System.Gadget.Settings.ClosingEvent event object. If the closeAction property of the ClosingEvent object contains a value of commit, this means the user selected OK and you will likely want to read the new settings. Otherwise, the options dialog was canceled and you can bypass reading of the preferences.

If you have worked with JavaScript for any time at all, you have probably heard the phrase eval is evil. If not, go ahead and look it up online. Ill wait.

For example, if you are running a US version of Windows Vista and your preferences are set to Spanish, Sidebar will first look in the folder es-us. If the file is not found there, Sidebar will then search the es folder. And finally, if the file is still not found, Sidebar will search the gadget root folder.

You can also use APIs from the Sidebar Gadget Object Model. These APIs provide a way for your gadget to intece with the system. For example, you can read the signal strength of your wireless network card, play a sound file, or determine the CPU usage.

From within Visual Studio 2005, I run make.bat, which I have set up as an external tool. The batch file creates a folder under the user gadgets folder (which is where gadgets are created when installed) and copies all of the gadget files into the new folder. My batch file also generates a .gadget file that is ready for distribution and places it in the Documents folder. When you use this method, there is no need to double-click on the .gadget file to install the gadget on your development machine. I love the technique as it allows me to keep other source files in my Visual Studio project folder (such as Photoshop PSD files) that I dont want to package with the gadget. If you do this, just be sure to place the names of the files you want to exclude in the exclude.txt file.

A flyout extends the user intece outside of the gadgets own borders. You can use this window for anything you wish. (There is no maximum size imposed for flyout windows.) A good example of a gadget that uses a flyout is the Stocks gadget that ships with Windows Vista. Clicking on a stock causes a window to fly out to the side of the gadget, displayinGadgets Build Your Own Windows Vista Sidebar Gg a graph of that stocks activity (see Figure 4). The Live Search gadget also uses a flyout, displaying search results for the query you entered. Figure 5 shows a flyout from our MSDN Magazine Ticker gadget. Notice that when a headline is clicked, the UI extends out from the docked gadget to show the article title, a description, and the authors name.

When you want to display Hello, you would use the variable L_Hello rather than the hardcoded string. And when querying the weather feed, you would use L_Degrees to request the proper format. This produces a greeting in the appropriate language and gives the temperature according to the users preferences. In your main JavaScript code, when you want to use a string or determine what to use for degrees, you would do something like this:

!DOCTYPE html PUBLIC -//W3C//DTD XHTML 1.0 Transitional//EN html xmlns= head title/title meta http-equiv=Content-Type content=text/html; charset=utf-8 / link href=style.css rel=stylesheet type=text/css / script src=local.js type=text/javascript/script script src=gadget.js type=text/javascript/script /head body div id=gadget class=gadget/div /body /html

XML Definition File

When a gadget is nestled in the Sidebar, it is considered to be in the docked state. Once dragged onto the desktop, it is floating or undocked. As I mentioned, the maximum width for a docked gadget is 130 pixels. An undocked gadget has no restriction on width, allowing you to design an expanded view. You can take advantage of this extra room to provide a richer experience. (Microsoft recommends that you dont exceed 400 pixels square for an undocked gadget.)

What Happened to Alert and Confirm?

The implementation of a gadget is nothing more than an HTML page that is a maximum of 130 pixels wide. Though this isnt readily evident, the main HTML file (the one referenced in the XML definition file) is actually loaded into an Internet Explorer 7 window. There is, of course, no chrome surrounding this window and its location is controlled by Sidebar, but everything inside is basically a Web application. You have access to the DOM and most of the APIs as you would with a standard Web page. This means you can use AJAX techniques, create dynamic HTML elements, trap events, and so on. I will do all of these things, and more, as I walk you through the process of building my sample gadget.

I wanted my sample gadget to use all of the major features of a Sidebar gadget (flyouts, docked versus floating states, options, localization, and so on). But I also wanted the sample gadget to be . And it had to be somewhat useful.

I would like to point out that there is some ambiguity when it comes to the name of this dialog. When you right-click on a gadget, the gadget UI presents a menu that refers to this as Options. The API, however, refers to this as settings.

JavaScript

Sidebar, however, has disabled these JavaScript functions. Using popup dialogs goes against the Windows Vista UX guidelines for Sidebar gadgets. If you still feel compelled to use popups, you can emulate these functions.

Conversely, settings are read with System.Gadget.Settings.read or System.Gadget.Settings.readString. Both of these functions take a key and return a value. If the key does not exist (for instance if it has never been written) both will return a value of undefined.

The options dialog allows you to present the user with a list of gadget preferences. The user experience can be most anything you want. The dialog can be just like a regular Web page with radio buttons, checkboxes, and textboxes.

No comments:

Post a Comment