What is jsLib?

jsLib is javaScript library that can be easily installed on Mozilla and Firefox.  The goal is simple, make life easier for Mozilla application developers by providing a general purpose library that is simple and easy to use. The Mozilla architecture is based on a variant of COM called XPCOM which stands for cross platform COM. XPCOM is real nifty in the sense that the architecture abstracts the API from the implementation which lays the groundwork for a very extensible and compartmentalized system. This also adds the unintended side effect of being somewhat complex. Mozilla has literally thousands of interfaces (approximately 2,607), most of which were created for very specific tasks and not for general purpose consumption. Why you ask? Well, the original goal of Mozilla was to implement a browser suite, it was only later on in the evolution of the project that it was discovered the architecture lends itself nicely to being an application development platform.

  Below is a good example why jsLib was created. Let's say you want to write the string "This is a test" to a file from javaScript using XPCOM, this is how you would do it:

try {
  var file = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);

  // local file path for windows
  file.initWithPath("c:\\tmp\\foo.dat");

  if (!file.exists())
    file.create(file.NORMAL_FILE_TYPE, 0644);

  var ioService = Components.classes["@mozilla.org/network/io-service;1"].getService(Components.interfaces.nsIIOService);
  var uri = ioService.newFileURI(file);
  var channel = ioService.newChannelFromURI(uri);
  var outputStream = Components.classes["@mozilla.org/network/file-output-stream;1"].createInstance(Components.interfaces.nsIFileOutputStream);

  outputStream.init(file, 0x20|0x02, 00004, null);
  var buffer = "This is a test\n";

  outputStream.write(buffer, buffer.length);
  outputStream.flush();
  outputStream.close();
} catch (e) { dump(e); }


The above example is called XPConnect wrapper code. It is used to instantiate the various required XPCOM objects needed to write the line "This is a test\n" to a local file from javaScript. It's actually not that big a deal, something most developers can deal with. In fact you may be the type of developer who actually enjoys this type of hacking. I on the other hand do not. The above code sample clearly makes a lot of assumptions. If you take a count, there are three interfaces used - "nsILocalFile", "nsIIOservice", "nsIFileOutputStream". Each of these interfaces or "API's" have methods that are called upon in our example - "initWithPath", "exists", "newFileURI", "newChannelFromURI", "init", "write", "flush", "close". Each of these methods have arguments that are required. Now if you are a "studly" experienced Mozilla hacker, you will probably say "this is a very easy way to create a file". I on the other hand don't get very excited about writing code this way, to be honest I find it very tedious and annoying. I muddies up my application logic w/ unnecessary "infrastructure" code. I like code to be easy on the eyes so the logic can be better discerned at a glance. Why on earth do I need this type of mental overhead when all I'm trying to do is write some data to a file? Why must I need to know that there are 3 idl interfaces I need to use? Why must I know the magic XPCOM contract ID's - "@mozilla.org/network/io-service;1",  "@mozilla.org/network/file-output-stream;1"? Why must I need to know what interfaces go with what classes? I actually find this very laborious - so call me lazy, I admit it. If you are a developer who is new to Mozilla, trying to do something simple like write to a file, this could consume an entire day trying to understand the architecture and how everything is interrelated. Also, it requires you to understand how a COM architecture works. You may be asking yourself - Is this what I'm in for when using Mozilla as an application development platform? The answer is yes. The problem may appear obvious now, Mozilla can be complex and has no easy to use general purpose library.

This is where jsLib comes in. Using jsLib, you would accomplish the above example like this:

  jslib.init(this);
  include (jslib_file);
  var file = new File("c:\\tmp\\foo.dat");
  file.open("w");
  file.write("This is a test\n");
  file.close();


"Whew" you might be saying. This should indeed be a more palatable approach to writing code and more of what you are probably use to when working with other languages and development environments. If your Mozilla application needs to call on general purpose routines to achieve tasks like file I/O, with a simple to use, clean, API, then you may want to consider using jsLib.  As you can see from the examples above, 21 lines of messy "glue" code were reduced to 6 easy to read and understand lines using jsLib. It is my opinion that a platform is the most successful when the barrier to entry is kept low. This is the fundamental goal of jsLib.

Being that Mozilla is still evolving as a development platform, jsLib is evolving as well. Although we have not reached version 1.0, there are still libraries that are mature, stable, and widely used by Mozilla applications and extensions. So if I've perked your interest some, then read on.

Installing jsLib

If you are not already using a Mozilla or Firefox browser, you will need to go to mozilla.org and grab one.  To install jsLib, go to http://jslib.mozdev.org/installation.html and click on the link "jslib_current.xpi". This will install jsLib on your version of Mozilla or Firefox. The jslib distribution is bundled as an xpi package, xpi stand for "cross platform install" which is the way Mozilla based modules are distributed and installed.  There are three different jslib xpi packages, "full", "lite", and "archive". The "full" version contains libraries, images, and samples. Libraries are zipped up into a jar file and about 200k in file size. The "lite" version is essentially the same without the the images and samples. It is really just the core library with a smaller download size of about 115K. The "archive" distro is the same as the "full" version except that the jslib chrome package is not in compressed jar format. This is provided as a convenience so developers who would like access to the jsLib files can do so.

Running some jsLib Samples
Now that you have jsLib installed, let's run a few of the installed samples.

From your Mozilla installation directory you can run the sample from the command line like this:

   # on unix and OSX
   ./mozilla -jslib samples/file.xul

   # on windows
   mozilla.exe -jslib samples/file.xul

You can also run the samples from your browser location bar by typing the chrome URL below:

  chrome://jslib/content/samples/file.xul

or just type jslib:samples.file

The above is a sample of some calls to the jsLib File library.

Here is the XUL source code:
<?xml version="1.0"?>
<!DOCTYPE  window>

<window
  id="file-window"
  title="File"
  width="200"
  height="200"
  style="background-color: #cccccc;"
  onload="init();"
  xmlns:html="http://www.w3.org/1999/xhtml"
  xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">


<script type="application/x-javascript">

var gFile;
function init()
{
  jslib.init(this);
  include (jslib_file);

  var platform = navigator.platform;
  var localFile;
  if (/win/i.test(platform)) {
    // a local file for windows systems
    localFile = "c:\\tmp\\fubar.dat";
  } else {
    // a local file for unix or osx type systems
    localFile = "/tmp/fubar.dat";
  }

  gFile = new File(localFile);
}
</script>

<hbox flex="1" pack="center">
  <spacer flex="1" />
  <vbox>
    <spacer flex="1" />
    <button label="Function List" oncommand="alert(gFile.help);" />
    <button label="path"   oncommand="alert(gFile.path);" />
    <button label="exists" oncommand="alert(gFile.exists());" />
    <button label="create" oncommand="if (!gFile.exists()) gFile.create();" />
    <button label="remove" oncommand="if (gFile.exists()) gFile.remove();" />
    <spacer flex="1" />
  </vbox>
  <spacer flex="1" />
</hbox>

</window>

 
This sample contains five XUL buttons, "Function List, path, exists, create, remove".  If you click on "Function List", a list of the public methods for the File library will be displayed. If you click on "path", a preset local file path string will be displayed. "exists" will display a bool value indicating whether the file exists or not. "create" will create the file. "remove" will delete it.

jsLib include

As you have probably figured out already, jsLib libraries are loaded using a top level function called "include()".  This function is the easiest and most common way of loading libraries into your application script context. Another way of loading libraries is to use the <script> tag.

The example below loads the base jsLib library and the File library.

<script type="application/x-javascript" src="chrome://jslib/content/jslib.js" />
<script type="application/x-javascript" src="chrome://jslib/content/io/file.js" />

This has the same effect as the code sample below.

jslib.init(this);
include(jslib_file);

When you include code using the script tag, the library file is cached, it is not cached when loading libraries using the include method. Using the include method, you have the flexibility of loading the library only when it is needed. When you load using the script tag, the library is loaded when the XUL document is loaded, similar to using the script tag in an HTML page.

jsLib Module Identifiers

jsLib is broken down into logical modules that are loaded when they are needed.  So as you write code in your XUL documents, you load the libraries you need using module identifiers.  The current complete list of module identifiers can be found at http://jslib.mozdev.org/modules.html or just type "jslib:modules" into your location bar.

Here are the modules for the io library.
// io library modules
jslib_io
jslib_filesystem
jslib_file
jslib_fileutils
jslib_dir
jslib_dirutils

For example if you want to load the entire io library, you would do this:

  include (jslib_io);

Using the File library to see if a file exists:

  jslib.init(this);
  include (jslib_file);
  var f = new File("c:\\WINDOWS\\system32\\notepad.exe");
  alert(f.exists());


If you want to run notepad.exe you can do this:

  jslib.init(this);
  include (jslib_fileutils);
  var fu = new FileUtils();
  fu.run("c:\\WINDOWS\\system32\\notepad.exe");



As you can see, things are easy to use and there is a considerable amount of flexibility using jsLib. That's the way we like it.

Using jsliblive to create and run some code

Ok, if you are like me, you are probably impatient and don't want to waste your time w/ verbose descriptions and details. So let's jump in and start writing some code that actually runs and works so you can evaluate if this is even worth your valuable time.

Let's get started:

Ensure jsLib is installed
Type into your browser location bar jslib:about, you should see the jsLib about dialog. Now type jslib:version, you should see the jsLib splash page. If you see these dialogs, then jsLib is ready to go. If not, then you will need to go to back to the Installing jsLib section and follow the instructions there to install jsLib.

Create a XUL file to run from jsliblive
Now let's create a XUL file which we will run from your jsliblive chrome folder. The chrome url chrome://jsliblive/content/ is provided as part of the jsLib install so that developers can drop in XUL files for testing. Since most packages are installed in compressed jar file format, it is handy to have a folder to drop and run test files. The jsliblive folder is installed in different places depending on what operating system you are using and what distribution of Mozilla you are running.

To find out the path to jslib and jsliblive, just type jslib:about and these paths should be displayed for you.

So first let's create a XUL file that is a client of jsLib.

Based on where jsliblive is installed on your system, copy and paste the code below into your jsliblive folder in a new file called "test.xul".

test.xul
<?xml version="1.0"?>

<!DOCTYPE window>

<window
  id="jslib-test"
  title="jsliblive test"
  style="background-color: #cccccc; width: 100px; height: 100px;"
  xmlns:html="http://www.w3.org/1999/xhtml"
  xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">


<script type="application/x-javascript">
function test ()
{
  jslib.init(this);

  if (typeof(JS_LIB_LOADED)=='boolean')
    alert(JS_LIB_HELP);
  else
    alert("jslib failed to initialize");
}
</script>

<vbox flex="1" pack="center">
  <spacer flex="1" />
  <button label="my jsLib test" oncommand="test();" />
  <spacer flex="1" />
</vbox>

</window>


Now type this chrome url into your location bar.

  chrome://jsliblive/content/test.xul

You should see a XUL page with a button that says "my jsLib test". Click on that button and an alert should appear that displays some info about jsLib. Now you have a good place to experiment immediately with the library.

Now let's try using the network library to check the content type of a web page.

Using the same file above, let's just past in the javaScript code below.

<script type="application/x-javascript">
function test ()
{
  jslib.init(this);
  include(jslib_remotefile);
  var rf = new RemoteFile("http://www.mozdev.org");
  alert(rf.contentType);
}
</script>


This example will launch an alert dialog that will display the content type of the url http://www.mozdev.org.

Now let's try obtaining the pages actual content.
 
<script type="application/x-javascript">
function test ()
{
  jslib.init(this);
  include(jslib_remotefile);
  var rf = new RemoteFile("http://www.mozdev.org");
  rf.open();
  var content = rf.read();
  alert(content);
}
</script>

This example will launch an alert dialog which displays the html source code for the url http://www.mozdev.org.

If you would like to learn more about the RemoteFile library, just type jslib:remotefile into your browser location bar.

Now lets try getting and setting some prefs using jsLib Prefs library found in the utils module.

<script type="application/x-javascript">
function test ()
{
  jslib.init(this);
  include(jslib_prefs);
  var pref = new Prefs();
  var homePage = pref.getChar("browser.startup.homepage");
  alert(homePage);
}
</script>



Running this sample, if you get a "browser.properties", then your home page hasn't been set.

Would you like to change your home page?  Try this:

<script type="application/x-javascript">
function test ()
{
  jslib.init(this);
  include(jslib_prefs);
  var pref = new Prefs();
  pref.setChar("
browser.startup.homepage", "www.mozdev.org");
  var homePage = pref.getChar("browser.startup.homepage");
  alert(homePage);
}
</script>


How about creating a brand new pref for your app and then saving it?

<script type="application/x-javascript">
function test ()
{
  jslib.init(this);
  include(jslib_prefs);
  var pref = new Prefs();
  var prefID = "jslib.my.brand.new.pref";
  pref.setChar(prefID, "hey there");
  var myPref = pref.getChar(prefID);
  alert(myPref);
}
</script>


Yea but Is it actually stored in your pref file? Check it out. Type about:config into your browser locationbar. Then under "Filter", type "jslib" and you should see the pref appear.

Ok, now how do I remove it?

<script type="application/x-javascript">
function test ()
{
  jslib.init(this);
  include(jslib_prefs);
  var pref = new Prefs();
  var prefID = "jslib.my.brand.new.pref";
  pref.clear(prefID);
  alert("pref should now be gone");
}
</script>


Don't believe it's gone? Don't take my word for it. Type about:config into your locationbar and filter "jslib" and see if it comes up.

To find out more about the Prefs library just type jslib:prefs.

It's been a while, maybe we should use the date library and and see what time it is.

<script type="application/x-javascript">
function test ()
{
  jslib.init(this);
  include(jslib_date);
  // this will return something like - December 12th, 2004, 5:22 pm
  var d =
jslibDate("F jS, Y, g:i a");
  alert(d);
}
</script>

For more information about the date library, just type jslib:date into your browser locationbar.

Well, time to go make dinner ...

These quick samples should give you some hands on experience using jsLib. The library is still in the pre 1.0 stages of development, however, the libraries that are implemented can save you a lot of time, and work. Mozilla as a "mature, robust, development platform" has an exciting road ahead of it. A road shaped by developers like you who choose to take it. Lots of problems are being solved today using these technologies by the open source community and businesses alike. A hybrid development platform is emerging, one that fuses web development with traditional software development. The choice and freedom this combination provides, is one that is starting to reshape the way browser based development is done.