User Tools

Site Tools


mozilla-devel:nuts_and_bolts

Nuts and Bolts

XUL Runner Start Up

The general file layout is similar to that given for the Alpha release. Namely, you have your chrome/ directory with content/, locale/, and skin/, along with various manifests and preferences and install scripts.

In CVS, we now reside at ILS/Open-ILS/xul/staff_client

I'm going to try to walk through the code this time as if it were actually being executed by XUL Runner. The first (or second) thing XR sees is the application.ini (cvs) file, which gives some metadata about the application, as well as the versions of XR that should run the application.

XR also looks in the defaults/preferences/ directory (relative to the working directory) for Javascript files to execute. XR only executes pref() functions, and possibly user_pref() functions from these files. These set the same sort of preferences you see with about:config in Mozilla. Our preference file is named evergreen.js (cvs), but only the .js part of the filename matters, and you may have more than one.

A pertinent line in our preference file is: pref("toolkit.defaultChromeURI", "chrome:evergreen/content/main/main.xul"); This tells XR where to look next for loading the application. In this case, it'll look for the given URI in chrome/evergreen.jar, which is really a zip file generated by the Makefile (cvs), containing the contents of the chrome/ directory (cvs) ==== Javascript ==== The main.xul file (CVS) contains the login interface (which in Alpha resided in auth/auth.xul). Through a XUL overlay, we pull in some of the Javascript used by the OPAC, currently: utils.js, md5.js, JSON.js, fmall.js, RemoteRequest.js, OrgTree.js, and org_utils.js. For this interface, these are pulled in by the Makefile and bundled into OpenILS/util/ at compile-time, but for non-standalone pages, these will probably be freshly pulled and cached from our servers. We also pull in a main.js (CVS) and JSAN.js (CVS) from main/. We're using JSAN from http://www.openjsan.org/ as an experiment, but its use isn't strictly necessary and even has a few downsides. In Alpha, we associated Javascript with XUL files by use of <script /> tags, and we would abstract groupings of related Javascript by moving them to XUL overlay files. We do this once in main.xul with the Javascript from the OPAC. The XUL directive <?xul-overlay href="chrome:evergreen/content/OpenILS/util_overlay.xul"?> overlays mail.xul with util_overlay.xul. Any elements they have in common (by both element name and id) get merged. In this case, it's <scripts id="openils_util_scripts" />, which contains the aforementioned Javascript. You can have multiple overlays affecting the same XUL. They can be stacked and nested. They can also be applied externally through manipulation of the chrome manifest. I can overlay parts of Firefox, for example, without Firefox being aware of it.

What JSAN does, however, is use tools like XMLHTTPRequest to retrieve JSAN libraries (usually remotely) and then eval them into existence. The downside to this sort of import system is that the line numbers associated with Javascript errors aren't mappable to the actual files. However, the libraries can be usefully checked for correct syntax at least, for example, by passing them through a command line JS engine.

One benefit I received from JSAN was that it pushed me toward thinking more about OOP. JSAN dictates a little stucture for both OO and functional libraries in order to meaningfully import them. I came close to some OO with revision 2 of the staff client, but this version should be more understandable to other developers. It also helps me see things better when I can import object libraries close to where I actually instantiate those objects.

Model View Controller?

We set the onload attribute in main.xul to call the function main_init() from main.js. This sets up an object (a JS primitive, classless) G (affectionately called "Big G"), which I just treat as a hash/dictionary to hang other objects (JSAN or otherwise) and data off of. This might evolve into something like a full-fledged Application object, but right now I don't see the point.

We pull in a few useful object libraries: main/window.js, main/network.js, and util/error.js, and attach them to G.window, G.network, and G.error, respectively.

Of particular interest is auth/controller.js:

JSAN.use('auth.controller');
G.auth = new auth.controller( mw );
 
G.auth.on_login = function() {
 
   JSAN.use('OpenILS.data');
   G.OpenILS.data = new OpenILS.data( G.auth );
   G.OpenILS.data.on_complete = function () {
 
      G.window.open('http://gapines.org/xul/server/test.xul','test','chrome');
 
   }
   G.OpenILS.data.init();
 
}
G.auth.init();

When we instantiate the controller, we pass in a reference to the actual window created by main.xul. When .init() is called, the controller looks for certain DOM node id's and attaches various event listeners that define the behavior for the interface. I'm not sure why I went with .init() instead of just linking the view to the controller on construction, but I think I was worried about the .on_login callback not being assigned first. However, with the single threaded model of Javascript in Mozilla, this shouldn't matter. If anyone has any opinions or preferences, let me know.

Also on init, the controller creates an object with auth/session.js. The controller passes in a reference to the "view" (a collection of references to some pertinent DOM nodes) when this object is constructed. When the session object is .init()'ed (through the controller watching the submit button), it takes some data from the interface/view through the controller, namely the username and password, and communicates with Evergreen servers in an attempt to authenticate the user. On any failure, the .on_error() method is called, which previously in the controller, was set to be identical to the controller's .on_logoff() method. Otherwise, the session's .on_init() method is called, which similarly, was set to be identical to the controller's .on_login() method.

Now, as we see in the code snippet above, the controller's .on_login() method sets other things in motion. In this case, the retrieval of other information, such as the library organization tree, that an authenticated user should have access to. This is also where the main interface will be spawned.

mozilla-devel/nuts_and_bolts.txt · Last modified: 2022/02/10 13:34 by 127.0.0.1

Except where otherwise noted, content on this wiki is licensed under the following license: CC Attribution-Share Alike 4.0 International
CC Attribution-Share Alike 4.0 International Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki

© 2008-2022 GPLS and others. Evergreen is open source software, freely licensed under GNU GPLv2 or later.
The Evergreen Project is a U.S. 501(c)3 non-profit organization.