Quick and Easy AIR Apps with Dreamweaver CS3
Join the DZone community and get the full member experience.
Join For FreeThe Adobe AIR extension for Dreamweaver CS3 makes it easy to build, package, and preview Adobe AIR applications with Adobe Dreamweaver CS3. You can use your existing web and Ajax development skills to build AIR applications that interact with the desktop in ways that web applications can not.
This tutorial demonstrates how to build a simple To Do List application with custom chrome. It also explain the functionality behind the application. The application is based on a single HTML page and JavaScript. Because it is also built on AIR, it can save and open to do lists using the local file system. It will use XML both internally to remember data and to be saved to the local file system as to do lists that can be shared.
Requirements
In order to make the most of this article, you need the following software and files:
Prerequisite knowledge
Basic knowledge of Dreamweaver, HTML, and Ajax development. If you haven't used the Adobe AIR extension for Dreamweaver CS3 yet, you may also want to refer to Scott Fegette's demo of how to set up and configure Adobe Dreamweaver CS3 to build, deploy, and preview Adobe AIR applications.
Starting off
Note: Be sure to download and install the Adobe AIR runtime and the Adobe AIR Extension for Dreamweaver CS3 before you start this project.
As is the case with most development environments, you begin by defining your project. In Dreamweaver, this means you create a new site for your AIR project.
Note: The samples ZIP file that accompanies this article includes the finished site files and assets for this project as well as the finished AIR application (todoit.air). You can import the finished site (to_do_list) files into Dreamweaver if you want to follow along with this tutorial without creating the files from scratch.
- Start Dreamweaver and select Site > Manage Sites to open the Manage Sites dialog box.
- Click the New button and select Site. The Site Definition dialog box appears.
- Specify a name for your site project (for example, to_do_list).
- Specify the Local root folder. Click the folder icon beside the input text box to browse your system for a folder.
- Click OK to close the dialog box. Click Done in the Manage Sites dialog box.
The next step is to create the user interface using a default HTML document. Later, you need to configure the AIR project, but I find it is quicker to create the default HTML document first.
To create a standard HTML document for the application's user interface, choose File > New > Basic Page > HTML, and then click Create to edit the document. Select File > Save and specify the file name for the document. This is the default interface that will be used when the application opens.
I named the default document ui.html, but you can name it anything you want. This document will be the first (and likely only) document that AIR loads for your application.
Here is the basic HTML structure for the project:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>To Do List</title>
<link type="text/css" href="todo.css" rel="stylesheet" />
<script type="text/javascript" src="assets/AIRAliases.js"></script>
<script type="text/javascript" src="assets/todo.js"></script>
</head>
<body>
</body>
</html>
Starting with the default HTML, you add the title (To Do List) and link in the resources needed by the application; for this application, you use the following three resources:
<link type="text/css" href="todo.css" rel="stylesheet" />
<script type="text/javascript" src="assets/AIRAliases.js"></script>
<script type="text/javascript" src="assets/todo.js"></script>
The todo.css style sheet controls the look and feel of the application as well as basic feedback such as changing colors when moving the mouse over a button. The todo.js file provides the interactive portion of your application, including responding to events, handling files, and working with data internally. The AIRAliases.js file is provided by Adobe to allow shortcuts to most of the AIR API. This will save you time in typing out long object names.
Note: You can find the todo.css and todo.js files in the assets folder of the to_do_list site sample files. The AIRAliases.js file is included with Adobe AIR Extension for Dreamweaver CS3—it will be automatically generated when you create an Adobe AIR project in Dreamweaver CS3.
Building and styling the user interface
The interface for the To Do List application is straightfoward. It has a text box for entering list items, two buttons on top and two buttons on the bottom. The buttons on top replace the interface widgets normally found in a desktop application, that is the minimize and close buttons. The buttons on the bottom are for adding new items to the list and to save the list to a file.
[img_assist|nid=2903|title=Figure 1. The To Do List user interface.|desc=|link=none|align=none|width=250|height=131]
In the default HTML document, define the text box, the buttons, and a document element for storing the items as follows:
<div id="nav">
<button id="btnmin"><img src="assets/min.jpg" /></button>
<button id="btnclose"><img src="assets/close.jpg" /></button>
</div>
<div id="dataentry">
<input id="itemtext" type="text" />
<input id="btnadd" type="submit" value="Add" />
<input id="btnsave" type="submit" value="Save" />
</div>
<div id="items"></div>
Because the To Do List application is based on an HTML document, you can use normal CSS to make it look and feel as you wish. Building the application on AIR provides even more flexibility. The Adobe AIR HTML rendering engine is powered by WebKit, which has a number of CSS extensions, including border radii and multiple backgrounds, that can make it easier to develop your user interface without complicated markup.
This application uses -webkit-border-radius
to give the application a rounded feel without the use of graphics. It also
uses a background graphic for a simple gradient on the entry and item elements.
You can prevent the background from tiling by setting -webkit-background-size
to 100%
, which stretches the
gradient to the size of the element.
#nav {
text-align:right;
padding-right:5px;
position:absolute;
right:0;
top:-4px;
}
#nav button {
color:#999;
background-color:#555;
-webkit-border-radius: 3px;
border:1px inset #777;
border-width:0 1px 1px;
padding:6px 6px 3px;
line-height:1;
cursor:pointer;
}
#dataentry {
background:url(bg.png) repeat-x 0 0;
padding:19px 5px 5px;
-webkit-background-size: 100%;
-webkit-border-radius: 5px;
text-align:center;
}
input[type=text] {
-webkit-border-radius: 5px;
font-size:14px;
width:95%;
padding:5px;
}
input[type=submit] {
color:#FFF;
background-color:#333;
border: 1px outset #999;
-webkit-border-radius: 9px;
width:50px;
border-color: #999 #000 #000 #999;
}
input[type=submit]:hover {
color:#FFF;
background-color:#912A2A;
}
.item {
margin:0 5px;
overflow:hidden;
padding:5px;
background:url(bg.png) repeat-x 0 0;
-webkit-background-size: 100%;
}
To give the buttons a "button" feel, the border-color
along with the border-style
rule creates the illusion of a bezel with light gray on the top and
left edges and black on the right and bottom edges. You can also see
the use of attribute selectors for your CSS rules. If you're not
familiar with an attribute selector, it allows for elements to be
styled based on the value of a particular attribute. For example, input[type=submit]
will style any input where the type
attribute is equal to submit, that is, <input type="submit" value="Save">
.
Working within an isolated environment like AIR can be an extremely liberating experience since you can take advantage of these modern CSS features without having to worry about cross-browser support. You can also feel good knowing that your application should look the same on Windows, Mac OS X, and Linux. Just don't get frustrated when you go back into the browser world!
Adding interactivity
The To Do List application is relatively straightforward and the extended functionality provided by AIR and WebKit makes it easy to pull it together quickly and easily.
The application is structured with a single object named ToDo
(defined in todo.js), which
contains all the methods the application needs. Also, the following two helper
functions have been added to simplify development:
var ToDo = { }
// Shortcut function to retrieve elements by ID
function $(id){
return document.getElementById(id);
}
// bind function for binding objects to function calls
Function.prototype.bind = function(o, args){
var fn = this;
return function(){
fn.apply(o, args || arguments);
}
}
The application has only a few interaction points: add,
save, minimize application, close application, and remove item. When the
application first opens, the init()
function of the ToDo
object adds
event handlers for these events.
init:function(){
// perform any event bindings
$('btnadd').onclick = ToDo.addEvent.bind(ToDo);
$('btnsave').onclick = ToDo.save.bind(ToDo);
$('btnclose').onclick = ToDo.close.bind(ToDo);
$('btnmin').onclick = ToDo.minimize;
air.NativeApplication.nativeApplication.addEventListener(air.InvokeEvent.INVOKE,ToDo.open.bind(ToDo));
window.nativeWindow.addEventListener(air.Event.CLOSING,ToDo.close.bind(ToDo))
// initialize XML which auto-creates ITEMS root node
ToDo.items = document.implementation.createDocument("","items", null);
// add event handling to handle moving the application
document.body.onmousedown = function(e){
if(e.target.tagName != 'INPUT')
nativeWindow.startMove();
};
ToDo.fixAppSize();
}
Next, the init()
function adds two important event handlers that handle the INVOKE
and CLOSING
events. The INVOKE
event occurs any time a user clicks a .todo file to
open it. The event is bound to the open()
method of the ToDo
object. The CLOSING
event occurs any time a user tries to close the application using a keyboard
shortcut or the taskbar. The application captures this event so that it can
prompt the user to save any unsaved changes before the window is closed.
The init()
function also creates an XML document to hold the list items. The
createDocument
method takes three parameters. The first is an XML namespace,
which you won't need. The second is the name of the root node; in this case,
it's items
. The final parameter
is for specifying a custom document type definition, which we also don't need.
An onmousedown
event handler is added, which allows the user to drag the application around.
Finally, init()
calls fixAppSize()
to adjust the
size of the native Window to match that of the HTML document. As items are
added to or removed from the list, the HTML document will change size. The nativeWindow
must change with it to keep the HTML document from getting clipped.
fixAppSize:function(){
// set the height to the length of the HTML
nativeWindow.height = document.body.offsetHeight;
}
Adding an item
Adding an item to the list invokes the add()
event handler.
add:function(txt){
var id = 'a' + (new Date()).va lueOf();
if(txt == '') return false;
// create a new item shell
var item = document.createElement('div');
item.className = 'item';
item.id = id ;
var closeWidget = document.createElement('div');
closeWidget.className = 'close';
closeWidget.onclick = ToDo.remove.bind(ToDo);
item.appendChild(closeWidget);
var itemText = document.createElement('div');
itemText.className = 'text';
itemText.innerHTML = txt;
item.appendChild(itemText);
$('items').appendChild(item);
// create the XML node
var xmlItem = document.createElement('item');
xmlItem.setAttribute('id', id );
xmlItem.appendChild( document.createTextNode(txt) );
ToDo.items.getElementsByTagName('items')[0].appendChild( xmlItem );
// reset the text box
$('itemtext').value = '';
ToDo.hasChanged = true;
ToDo.fixAppSize();
}
The add()
event handler does two things. First, it adds the new DOM elements to the HTML
document and then it adds a new XML node to the items
XML object. When a to do list is saved, this internal representation of the to
do list is written to a file.
The event handler then clears the input text box, preparing
it to accept the next list item. The handler sets the hasChanged
property to true.
When the application is closed, this property is used to determine if
the user should be prompted to save changes.
Removing an item
Removing an item from the list is straightforward. The remove()
event handler simply removes
the element from the HTML DOM and from the XML DOM.
remove:function(evt){
// grab the event target and then go to its parent, the Item
var id = evt.target.parentNode.getAttribute('id');
evt.target.parentNode.parentNode.removeChild(evt.target.parentNode);
var xmlNode = ToDo.items.evaluate("//item[@id='"+ id +"']", ToDo.items).iterateNext()
xmlNode.parentNode.removeChild( xmlNode );
ToDo.hasChanged = true;
ToDo.fixAppSize();
}
Removing the node from the XML DOM is different than you
might expect. You're using XPath to retrieve an item from the document where the
id
attribute matches. Then you remove that node using the removeChild
method of the parentNode
. In XML terms, the id
attribute doesn't have any special meaning like it does in XHTML where it's
used as a unique identifier. For that reason, getElementById
won't work and
you'll get a Node not found error. XPath lets you address parts of an XML document.
Opening a file
When a user double-clicks a .todo file, the To Do List
application is launched if it is not already open, and the open()
method is invoked.
open:function(evt){
if( evt.arguments.length == 1 )
{
if(evt.currentDirectory)
{
ToDo.currentDirectory = evt.currentDirectory;
}
ToDo.currentFile = evt.arguments[0];
var file = new air.File(ToDo.currentFile);
if(file.exists)
{
var fileStream = new air.FileStream();
var byteData = new air.ByteArray();
fileStream.open(file, air.FileMode.READ);
fileStream.readBytes(byteData, 0, file.size);
fileStream.close();
if(byteData.length > 0)
{
var s = byteData.readUTFBytes(byteData.length);
var parser=new DOMParser();
var doc=parser.parseFromString(s,"text/xml");
var items = doc.getElementsByTagName('item');
for(var i=0;i<items.length;i++)
{
ToDo.add(items[i].childNodes[0].data);
}
}
}
}
ToDo.hasChanged = false;
}
When the application is launched by double-clicking an
existing .todo file the file
object of the .todo file is passed as an argument to open()
. If the file does indeed exist, open()
uses the FileStream and
ByteArray objects of the AIR API to read in the file. Once the document is
loaded, the DOMParser
class
(from WebKit) is used to parse the string into an XML object. From there, the
code loops through the items, adding them to the list.
Because the add()
method sets the hasChanged
property to true
, open()
must
explicitly set it back to false
after adding the items.
Saving a file
Saving a file is handled in two parts. The first displays a browse dialog box that allows the user to specify where to save the file. This is a standard OS dialog box that you do not have much control over.
save:function(){
var fileFilter = new air.FileFilter("To Do Lists", "*.todo");
ToDo.currentDirectory.addEventListener(air.Event.SELECT, ToDo.fileSaved.bind(ToDo) );
ToDo.currentDirectory.browseForSave("Save To-do List");
}
When the user specifies a file, the fileSaved
event handler is invoked.
fileSaved:function(evt){
var newFile = evt.target;
var serializer = new XMLSerializer();
var packet = serializer.serializeToString(ToDo.items);
var fileStream = new air.FileStream();
var bytes = new air.ByteArray();
bytes.writeUTFBytes(packet);
fileStream.open(newFile, air.FileMode.WRITE);
fileStream.writeBytes(bytes, 0, bytes.length);
fileStream.close();
ToDo.hasChanged = false;
if(ToDo.closeAfterSave) ToDo.close();
}
The event handler uses the WebKit class XMLSerializer
to convert the internal
XML representation of the list into a string that can be written to a file. If
the event handler was invoked because the user clicked the Close button, then
the application will close.
Minimizing the application
Minimizing the application is straightforward. As
mentioned above, you've attached an event handler to the minimize button to
run a minimize function. The minimize function runs the minimize method on the
nativeWindow
object.
minimize:function(){
window.nativeWindow.minimize();
}
Closing the application
The last piece to this puzzle is handling the closing of the application.
close:function(evt){
if(ToDo.hasChanged)
{
var shouldSave = confirm("Do you want to save your changes?");
if(shouldSave)
{
ToDo.closeAfterSave = true;
evt.preventDefault();
ToDo.save.call(ToDo);
return;
}
}
air.NativeApplication.nativeApplication.exit();
}
When a user closes the application, close()
checks to see if any changes have been made. If
not, it just proceeds to close the application. If changes have been made, it
prompts the user using a standard JavaScript confirm dialog box. If the user
clicks OK, the application prevents the default action—stopping the application
from closing right away—to allow the save process to complete. Once the save is
complete, the close()
function
is called again by fileSaved()
.
This time, there are no changes and the application closes immediately.
Specifying the AIR application and installer settings
Now that the HTML document is built and ready to go, the next step is to configure the AIR application. Choose Site > AIR Application Settings to open the AIR Application and Installer Settings dialog box (see Figure 2).
[img_assist|nid=2904|title=|desc=Figure 2. The AIR Application and Settings dialog box.|link=none|align=none|width=536|height=666]
Although only the fields marked with an asterisk (*) are required, there are several others that you'll likely want to edit.
- The ID text box can be in any format, but many developers use the domain name reversed with the application name added to the end. For example, the To Do List application would use "com.example.todoit" as the ID.
- The Version detail, which also can be in any format, is an identifier that tells users what version of the application they are installing and using.
- The Select icon images button enables you to include custom images for your application.
-
Any files that you add to your project must be added through the Included files section of this dialog box. You can specify a folder to include in your project by clicking the folder icon and selecting where your assets are stored. For this project, the following files will be placed in the assets folder:
- AIRAliases.js: Provides shortcuts to the AIR API.
- bg.jpg: This graphic will be used as a background for the entry interface and for each item on the list.
- close.jpg and min.jpg: These are the graphics for the close and minimize buttons.
- todo.css: The is the style sheet for the application. The look and feel of the application is defined via CSS.
- todo.js: The is the JavaScript file that makes the application actually do what you want it to do.
- Because the To Do List application uses custom chrome, select Custom Chrome (transparent) as the Window style. There are two style options available: opaque and transparent. Transparency is required for the custom shapes used in this application.
Most importantly, you need to specify a digital certificate for the application. Every application must be digitally signed to identify the person or company who built it. To specify a digital signature, click the Digital Signature: Set button in the AIR Application and Installer Settings dialog box. This opens the Digital Signature dialog box (see Figure 3).
Note: Signing your application is important to instill trust, much like an SSL certificate for a web server allows for secure web sites and instills trust in users providing private information like their credit card information. People will feel more comfortable installing an application if it comes from a source they trust. For more information on obtaining digital certificates, refer to Todd Prekaski's Digitally signing Adobe AIR applications.
[img_assist|nid=2905|title=|desc=Figure 3. The Digital Signature dialog box.|link=none|align=none|width=650|height=323]
If you don't have a certificate already, you can create a self-signed certificate, by clicking the Create button on the Digital Signature dialog box (see Figure 4).
[img_assist|nid=2906|title=|desc=Figure 4. The Self-Signed Digital Certificate dialog box.|link=none|align=none|width=581|height=405]
To sign a publicly released AIR application, you should use a certificate from an authority such as Verisign or Thawte, which confirms your identity to users of your application.
The To Do List application uses files for saving and opening to do lists. To set up a custom file type association for these files, click the Edit list button next to the Associated File Types option, then click the plus (+) button to add a file type. Enter the name for the file type and the extension (do not include the preceding dot), for example, todo (see Figure 5).
[img_assist|nid=2907|title=|desc=Figure 5. The Associated File Types dialog box.|link=none|align=none|width=409|height=247]
That's it. You've specified the key settings for your AIR application.
Debugging and packaging the application
As you develop your application, you'll need to test it to ensure that everything is working properly. This is typically done periodically during development. Rarely has there been a developer who could develop an application in its entirety and run it without an error to be found.
In Dreamweaver CS3 you can preview the application in two ways:
-
Choose Site > AIR Application Settings, and then click Preview to test the application.
You can use this option no matter which document is active, but no errors are shown in the Results pane.
-
Choose File > Preview in Browser, and then select Preview in Adobe AIR.
When using this option, JavaScript errors will appear in the Results pane. However, you have to make sure an HTML document from your project is the currently active document.
Note: The AIRIntrospector.js file is part of the Adobe AIR SDK. You can find a copy of the AIRIntrospector.js file in the assets folder of the sample files that accompany this article. The Adobe AIR SDK also includes everything you need to use the seamless badge install feature, explained in David Tucker's article, Deploying Adobe AIR applications seamlessly with badge install.
<script type="text/javascript" src="AIRIntrospector.js"></script>
The AIR Introspector can be accessed while the application is running using the F12 key. Any error messages thrown from within the application will appear in the Console tab of AIR Introspector. The AIR Introspector also provides functions for inspecting code during the execution process.
You can use the log()
method to send objects to the console tab. For example:
var test = "Debug message";
air.Introspector.Console.log(test);
In addition to log()
, there are warn()
, info()
,
and error()
methods that work like log()
but
also display a color-coded icon.
You should remove AIRIntrospector.js before distributing a packaged AIR application.
Packaging the application for distribution
The last critical step to the process is packaging the application for distribution.
Here again, the Adobe AIR extension for Dreamweaver CS3 simplifies the process. Choose Site > AIR Application Settings, and then click Create AIR File. You can also choose Site > Create AIR File.
The application is compiled and packaged into a redistributable AIR file (with the .air extension) using the application and installer settings and the certificate you specified.
Note: For more information on deploying your application to the web, including using the badge install feature, see Deploying Adobe AIR applications seamlessly with badge install.
Where to go from here
You've gone through the steps of creating a To Do list application using Dreamweaver CS3 along with the Adobe AIR extension for Dreamweaver CS3. You've seen how to apply custom chrome, work with opening and saving files to the local file system, and learned how to package your file to share with others.
Don't stop there, though. There's plenty more that you can add to this application. You could add a date field to remind yourself when items are due and add alerts to let you know when you're getting behind. Or take the interface to the next level by adding animation to the add and remove process. You can use the jQuery, Mootools, YUI, and ExtJS libraries to add new functionality quickly and easily. Also be sure to check out Christian Cantrell's inspirational experiments with Adobe AIR.
About the author
Jonathan Snook is a freelance developer from Ottawa, Canada. With over a decade of experience on the web, Jonathan continues to design and build web and desktop applications for clients around the world. He's also author of Accelerated DOM Scripting with Ajax, APIs, and Libraries and co-author of The Art & Science of CSS. Jonathan contributes to magazines online and off such as UK's .net magazine and Digital Web Magazine. He also contributes regularly to his own blog at Snook.ca.
Published at DZone with permission of Jonathan Snook. See the original article here.
Opinions expressed by DZone contributors are their own.
Trending
-
Top 10 Pillars of Zero Trust Networks
-
Front-End: Cache Strategies You Should Know
-
Apache Kafka vs. Message Queue: Trade-Offs, Integration, Migration
-
Observability Architecture: Financial Payments Introduction
Comments