Sash XB for Linux
Home |  Documentation |  Writing Weblications  ... Contact

Writing Sash Code

Once the GUI is finished, you're ready to write some real code. The best way to quickly familiarize yourself with the way things work is to find some sample code that uses the extensions that you want to use. SashXB relies on Mozilla's JavaScript interpreter; Sash code is JavaScript with Sash extensions and objects.

Where to look for examples, inspiration, and help:

Reading an IDL File

Even if documentation exists, knowing how to read an IDL file is very important. IDL files define objects. Objects have attributes and methods, and their exact names and specifications are found in the IDL file.

Each attribute has a type (such as string or boolean). Attributes can also be readonly or read-write. Readonly attributes cannot be written. For example, a client socket object contains an error message string attribute, but it would not make much sense to allow a weblication writer to write this attribute; it is used to let the extension communicate with the weblication when an error occurs.

IDL files also specify the methods that can be executed by a certain object. The types of the arguments and the return value are also included.

You may notice the nsIVariants floating around in IDL files. Variants are special for several reasons.

Extensions and Objects in SashXB

We assume that the weblication writer knows a decent amount of JavaScript (or that he or she can learn it quickly!). It is a relatively simple C-like language, easily picked up if you already know how to program already. A JavaScript book or website will probably be useful.

Variables

One interesting aspect of JavaScript is the absence of data types. Variables can be numbers, strings, booleans, or arrays. In SashXB, variables can also be Sash objects. All variables are declared to be of type 'var':

var x = "some string";
var y = 3.14159;
var z = true;

Accessing extensions and objects in SashXB is extremely easy. Everything is treated as an object, and properties and methods are accessed like they are in C++ (with no pointers to objects - that is, use '.' rather than '->') and Java.

Constructors

Attributes in an IDL file that are declared as sashIGenericConstructor represent objects that can be created and used in JavaScript code. To create a new FTP connection object:

var connection = new Sash.FTP.Connection();

Attributes and Methods

Now we can access connection's attributes and execute its methods. For example, we notice that the connection has two attributes (NotifyInterval_K and NotifyInterval_S) that determine how often progress callbacks are made when a file is transferring (NotifyInterval_K sends notification every time a certain number of kilobytes are transferred, NotifyInterval_S sends notification every time a certain number of seconds have elapsed). Suppose we want to know the progress of the file transfer every 2 seconds:

// connection.NotifyInterval_K = -1 by default,
// which means that it won't trigger any events.

// We can both get and set attributes (as long as they aren't read-only).
connection.NotifyInterval_S = 2;
printsys ("Notify interval: every " + connection.NotifyInterval_S + " seconds.");

We can use the connection object to connect to an ftp site. Checking the documentation or the IDL, we find out what arguments the Connect method accepts, and then call the function:

// Connect takes two arguments: 
// the URL (a string) and a port number (a number).
connection.Connect("ftp.mozilla.org", 21);
connection.Login("anonymous", "password");

One thing that isn't entirely obvious from the IDL file is that Login performs asynchronously; it returns before the user has been logged in. This is important to note because if you try to send FTP commands immediately after the Login, your weblication will not behave as expected. Pay close attention to documentation so that you are aware of important details like this. To use the connection correctly, we must use the OnConnect callback.

Callbacks

You may notice that some of the objects have string attributes like OnSomeEvent. These strings are for callbacks.

Callbacks are triggered when certain events occur. In order to have a particular JavaScript function execute when a certain event happens, simply set the string attribute to the name of the function.

The FTP Connection object has an OnLogin callback, which is called when the login is complete. The arguments that are passed to the function are the connection object that was successfully connected and a boolean variable that is true if the user was logged in successfully.

connection.OnLogin = "on_login";
Elsewhere we define the following function:
function on_login(ftpConn, loggedIn){
    if (loggedIn){
        // Send some commands.
    } else {
        printsys ("Not connected successfully\n");
    }
}

For example, we notice that the FTPConnection object has a (callback) string attribute 'OnFileSent'. The documentation tells us that when a file is sent successfully, The 'OnFileSent' callback will be called with four arguments: the FTPConnection object that finished transferring the file, the name of the file transferred, the total number of bytes transferred, and the total number of seconds elapsed for the transfer.

We'll associate this callback with our own JavaScript 'on_file_sent'.

connection.OnFileSent = "on_file_sent";

Elsewhere, we define the following function:

function on_file_sent(conn, filename, amtTransferred, secondsElapsed){
    printsys ("file " + filename + " transferred successfully");
    printsys ("size (bytes): " + amtTransferred);
    printsys ("time (seconds): " + secondsElapsed);
}		

Notice that the callback is only defined by a string attribute of the object and doesn't check the number of arguments (or their types). The weblication writer must manually verify that the JavaScript function definition expects the right number of parameters in the correct order.

We can also use variables to refer to the extensions and objects. Sometimes this can help us to keep our code clean. For example:

// Create two TCP/IP client sockets.
var sockets = Sash.Comm.Sockets;
var conn1 = new sockets.ClientSocket();
var conn2 = new sockets.ClientSocket();

// instead of:
// var conn1 = new Sash.Comm.Sockets.ClientSocket();
// var conn2 = new Sash.Comm.Sockets.ClientSocket();

Interacting with the GUI

Associating certain Javascript functions with GUI events (like button presses) is quite easy.

For an HTML-based GUI, you can specify an onclick property for some HTML element:

// a button. The printGreeting() function will be called when it is clicked.
<input type="submit" value="OK" onclick="printGreeting()">

// a link. The savefile() function will be called when it is clicked.
<a href="#" onclick="savefile()">Save</a>

See the checkers weblication for a good example of interacting with an HTML-based GUI.

For a Glade-based GUI, associating GUI events with JavaScript functions involves assigning Glade signals. One of the tutorials contains an example of how to do this. Here are the steps, sketched out briefly:

Using the Glade editor (run 'glade'), click on the element that you're interested in (here it's an 'ok' button). Its properties will show up in the Glade properties window.

Click on the 'Signals' tab (the one furthest to the right).

Where it says 'Signals', click on the button with the '..' to bring up a list of possible signals.

Click on 'clicked', then click 'OK'. Once you get back to the properties window, be sure to click add so that 'on_ok_clicked' is added to the list of signals.

Now all that's left to do is write the 'on_ok_clicked' JavaScript function.

If necessary, you can add additional signals for a single element.

Back | Next


Wing Yung
Last modified: Thu Apr 4 14:43:23 EST 2002

  
© Copyright 2002, All Rights Reserved. Contact