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:
- Setting up a File object to point to a file path.
- Using the FileMode and FileStream classes to read data from the file.
- Using the FileMode and FileStream classes to write data from the file.
- Listing directory contents.
Note: This is a sample application provided, as is, for instructional purposes.
| Contents |
|---|
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:
| File | Description |
|---|---|
| TextEditor.html | The main application content. Details of the code are discussed in the Understanding the code section. |
| FileChooser.html | An HTML page the user select a file to open or save. |
| application.xml | The 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.png | Sample 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 first parameter is the File object to openin this case, the main file object in the application.
- The second parameter is the file mode defined by one of the constants of the FileMode classin this case, the READ constant, which allows for data reading.
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 first parameter is the File object to openin this case, the main file object in the application.
- The second parameter is the file mode defined by one of the constants of the FileMode classin this case, the WRITE constant, which allows for data writing and overwrites any existing data in the file.
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