Apollo Alpha 1 Documentation - collected by Jimbob | Back to MY RESOURCES


Building a text file editor in HTML

Back to: Apollo Documentation home page

The Text Editor sample application shows a number of features of working with files in an HTML-based Apollo application, including the following:

Note: This is a sample application provided, as is, for instructional purposes.

Contents
  1. Installing and testing the application
  2. Files used to build the application
  3. Understanding the code
    1. Pointing a File object to a file
    2. Listing files and subfolders contained in a directory
    3. Reading a file
    4. Writing data to a file

Installing and testing the application

The Text Editor application is intentionally simple. The intent is to show you the basics of how to work with files in Apollo.

The installer (AIR) file for this sample application is available in the Samples directory included with the documentation at the labs.adobe.com site.

The application is a straightforward, but simple, editor of plain text files. The user interface design and HTML code is not optimal, but the intent of the application is to illustrate filesystem-related operations.

The application uses UTF-8 encoded for reading and writing all text files.

Files used to build the application

The application is built from the following source files:

FileDescription
TextEditor.htmlThe main application content. Details of the code are discussed in the Understanding the code section.
FileChooser.htmlAn HTML page the user select a file to open or save.
application.xmlThe Apollo application descriptor file that you use to debug and build the application (using ADL and ADT).
icons/ApolloApp_16.png icons/ApolloApp_32.png icons/ApolloApp_48.png icons/ApolloApp_128.pngSample Apollo icon files.

To download the source files for this example, click here (234K).

For help on building this quick start sample application, see How to build the quick start sample applications.

Understanding the code

The following sections discuss how the Apollo-related code works in the application.

Pointing a File object to a file

The init() method sets the defaultDir File object to point to a pre-defined path:

  defaultDir = runtime.flash.filesystem.File.documentsDirectory;

This code sets the object to point to the user's documents directory. On Windows, this is the "My Documents" directory. On Mac OS, it is the /Users/userName/Documents directory.

The defaultDir File is later referenced by the FileChooser window, if the user has not yet selected a file path.

Listing files and subfolders contained in a directory

When the user clicks the Open button the main window, the openFileDB() method opens a new window containing the FileChooser.html document:

 chooserWindow = window.open("FileChooser.html", 
                             "chooserWindow", 
                             "height=600,width=400,top=10,left=10,resizable=no"); 

Note that for HTML content running in Apollo, the JavaScript window.open() method opens new native (system) window. When HTML content runs in a browser, window.open method opens a new browser window.

When the user clicks the Save As button in the main window, the saveAs() method also opens the FileChooser.html document in a new window, but with slightly different parameters, so that the title of the window and the selection button in the window are named "Save As" rather than "Open."

Note: In future releases, Apollo will include methods for accessing native Open and Save dialog boxes.

The listFiles() method of the script in the FileChooser.html file dynamically generates DIV elements that list the files and the directory in the current directory (passed as the dir parameter of the listFiles() method). In the beginning of the method, code checks to see if the dir directory is at the root of the file system by checking to see if its parent property is null:

 if (dir.parent != null) {
     upDivStr = "<div onclick='parent.selectDiv(-1)' id='listDivRoot' ' height='300' class='listDiv'>" 
                + "<img src='images/folder_icon.png' width='16' height='16' />" 
                    + "<font face='verdana' size='2'>..";
     window.frames.fileList.document.write(upDivStr);
 }

The fileList frame is the scrolling frame that contains the list.

Next the method sets a variable named files to an array of File objects pointing to files and subdirectories of the current directory, by calling the listDirectory() method of the dir object:

 files = dir.listDirectory();

The code then iterates over each member of the files array, and writes an appropriate DIV element in the fileList frame:

 for (i = 0; i < files.length; i++) {
     var imgTxt;
     if (files[i].isDirectory) {
         imgTxt = "<img src='images/folder_icon.png' width='16' height='16' /> ";
     } else {
         imgTxt = "<img src='images/file_icon.png' width='16' height='16' /> ";
     }
     var divStr = "<div onclick='parent.selectDiv(" + i + ")' "
                   + "id='listDiv" + i + "' height='300' class='listDiv'>" 
                   + imgTxt 
                   + "<font face='Verdana, Geneva, Arial, Helvetica, sans-serif' size='2'>" 
                   + files[i].name + ""
                   + "";
     window.frames.fileList.document.write(divStr);
 }

Note that when a user clicks one of these DIV elements, the parent.selectDiv() method is invoked. It either adds the filename of the selected file to the filename text area or loads the contents of the selected directory to the fileList frame (depending on whether a file or a directory was clicked):

 function selectDiv(n) {
     if (n == -1) {
         listFiles(dir.parent);
     } else {
         var node = files[n];
         if (!node.isDirectory) {
             controls.document.getElementById('filename').value = node.name;
         } else {
             listFiles(node);
         }
     }
 }

Reading a file

When the user clicks the Open button in the FileChooser.html page, the openFile() method is invoked. It sets the file property of the main window (the opener of the File Chooser window), and it invokes the openFile() method of the main window:

 function openFile() {
     opener.file = dir.resolve(controls.document.getElementById('filename').value);
     opener.openFile();
     top.window.close(); 
 }

The openFile() method of the main window sets up a new FileStream object, named stream, and

 stream = new runtime.flash.filesystem.FileStream();
 try {
     stream.open(file, runtime.flash.filesystem.FileMode.READ);
     var str = stream.readUTFBytes(stream.bytesAvailable);
     document.getElementById("mainText").value = str;
     document.title = "Text Editor - " + file.name;
 } catch(error) {
     ioErrorHandler()
 }

Note that the code to open and read the file is enclosed in a try/catch structure, so that if there is an I/O error, the ioErrorHandler() method is invoked.

The open() method of the stream object has two parameters:

The readUTFBytes() method reads UTF-8 text data from the file. The parameter of the method is passed stream.bytesAvailable, so that the entire file is read. Once it is read, the data is passed to the mainText TEXTAREA element of the page.

This example uses the open() method, which opens the file for synchronous operations. You could also use the openAsync() method to open the file for asynchronous operations. However, if you did, you would need to set up event listeners to handle complete and ioError events.

The following code replaces the line ending characters from the file with the "\n" newline character, which is used in a TextField object in a SWF file. It then assigns the string to the text property of the Text control:

 var lineEndPattern:RegExp = new RegExp(File.lineEnding, "g");
 str = str.replace(lineEndPattern, "\n");
 mainTextField.text = str;

Writing data to a file

When the user clicks the Save button in the FileChooser.html page, the saveFile() method is invoked. It sets the file property of the main window (the opener of the File Chooser window), and it invokes the saveFile() method of the main window:

 function saveFile() {
     opener.file = dir.resolve(controls.document.getElementById('filename').value);
     opener.saveFile();
     window.close(); 
 }

The saveFile() method of the main window sets up a new FileStream object, named stream, and writes data to the file.

 try {
     stream = new runtime.flash.filesystem.FileStream();
     stream.open(file, runtime.flash.filesystem.FileMode.WRITE);
     var outData = document.getElementById("mainText").value;
     outData = outData.replace(/\n/g, runtime.flash.filesystem.File.lineEnding);
     stream.writeUTFBytes(outData);
     document.title = "Text Editor - " + file.name;
 } catch(error) {
     ioErrorHandler()
 }

Note that the code to open and read the file is enclosed in a try/catch structure, so that if there is an I/O error, the ioErrorHandler() method is invoked.

The open() method of the stream object has two parameters:

The fourth line after the try statement replaces the "\n" newline characters in the TEXTAREA data with the platform-specific line ending character, which is represented by the static File.lineEnding property:

 outData = outData.replace(/\n/g, runtime.flash.filesystem.File.lineEnding);

The writeUTFBytes() method writes UTF-8 text data to the file.

This example uses the open() method, which opens the file for synchronous operations. You could also use the openAsync() method to open the file for asynchronous operations. However, if you did, you would need to set up event listeners to handle outputProgress and ioError events.

Using asynchronous operations can allow other processes, such as a graphical progress status, to take place as files are read and written (asynchronously). For more information, see Synchronous and asynchronous methods.



Back to: Apollo Documentation home page


collected by Jimbob 2007.05