Skip navigation.

STICKY POST

About this log

I am an Opera developer working in Linköping, Sweden. Some of the contents will be Opera related, and some will be about things I find interesting. To mix it up even more, I will add some of my not so interesting personal anecdotes.

Go or no Go

As you may already know, Google just released a new systems programming language, Go.

So, what to think about it? First of all, it is ugly. It is so ugly that it will scare away most of the developers right away. It is so ugly that I am starting to wonder if Google is testing if people are so in to the Google cult that they are prepared to use a language, just because it is made by Google.

Well, let's just hope it is a practical joke, since I would really like a new systems programming language, and that I am tired of C++. I also find Go's feature set interesting.

I have been able to install Go in MacOS X. I already had XCode and Mercurial, which was enough. I hope that I will be able to use it some this weekend.

Most of you shouldn't even consider Go, even if it was a beautiful language. Only use a systems programming language when you really need to. So, if you are not implementing an operating system, a web browser, a number crunching library, a dynamic programming language, or audio/video codecs, just skip all systems programming languages. Stay with Python, Ruby, and JavaScript.

If you look at a systems programming language as something that is supposed to replace all the cases where C++ is used, it is a very hard task. But, if you look at it as something that is just to replace C++ where a systems programming language is really needed, it suddenly becomes easier. If a Python interpreter is implemented in Go, you will be able to extend Python in Go, and to avoid to write as much code as possible in the ugliest language of the century. And, yes, you could finally stop using C++.

The speed of the new generation of JavaScript engines

I just made a simple JavaScript performance test, and wanted to compare it to a similar implementation in C. Here is the code:

function testPerformance(a) {
  var len = a.length;
  var pos = 0;
  var start = new Date();
  var sum = 0;
  for (var i = 0; i < 500000000; i++) {
    sum += a[pos++];
    if (pos >= len)
      pos = 0;
  }
  var end = new Date();
  alert("Sum is: " + sum + ", took " + (end - start));
}
testPerformance([2, 3, 1, 4, 5, 1, 1, 3, 5, 1, 4, 6]);


I ran it on my 2.4GHz MacBook. In the new generation of JavaScript engines, the time it took was around 5 seconds, which means that you can do 100 million iterations per second. In C, with -O3, it was about 4 times faster. (two times faster without optimizations)

As a comparison, Opera 10 (which represents the older generation of JavaScript engines) is 20 times slower than the new generation of JavaScript engines.

Carakan, Opera's new generation JavaScript engine still under development, has two modes, one is with machine code generation, and one that only does byte code generation.

I will not tell you how fast Carakan is (that is something that will have to wait until a public version of Opera with Carakan is available), but I compared the two modes, and in this specific performance test, the version that generates machine code is a magnitude faster.

This is of course an extreme test, and does not reflect how JavaScript performs compared to C in general, or the difference between old and new generation of JavaScript engines.

According to my testing, Opera 10 runs this test faster than the equivalent code in Python.

Prototype-based inheritance

As you may already know, JavaScript uses prototype-based inheritance. In my opinion, JavaScript's implementation of prototype-based inheritance is not very good. Fortunately, JavaScript is a very flexible language, and I will here present a way to fix it.

I introduce two functions, $construct and $clone. $construct creates a new object with a defined prototype, and calls a function to initialize the new object. $clone creates a perfect clone of another object. To be able to do this, I add a value $proto to each object, pointing to the prototype object. (in some browsers, the extra property __proto__ exists, which provides even more flexibility than I show in this implementation)

The problem, as I see it, with JavaScript, is the hard connection between a function and a prototype.

I feel that I will not be able to explain what I mean right now, so let's just present the code, and hopefully you will understand anyway.

function $construct(protoobj, initfn, args) {
  var f = function() {};
  f.prototype = protoobj;
  var o = new f;
  o.$proto = protoobj;
  initfn.apply(o, args);
  return o;
}

function $clone(obj) {
  var f = function() {};
  f.prototype = obj.$proto;
  var o = new f;
  for (var x in obj) {
    if (obj.hasOwnProperty(x))
      o[x] = obj[x];
  }
  return o;
}

Do we really need classes in the JavaScript language?

Remember EcmaScript 4, the specification that does not exist. It will be replaced with EcmaScript 5 that is in the works. EcmaScript 5 is much closer to EcmaScript 3 than EcmaScript 4, that added a lot of things. One of the things added to EcmaScript 4 were classes. I thought that was one of the good additions compared to EcmaScript 3, but some of the other changes (like type declarations) I really disliked. So, after using some JavaScript toolkits, and even building my own class implementation, I think that classes as a language construct in JavaScript is not really needed.

As my class implementation Niclass shows, you only need to add 1.4 KB extra JavaScript code to get classes, which is only 0.5KB if you zip it over the wire. The implementation is fast, and does not add much memory overhead either. And I think it is easy enough to use, and the code looks good enough.

Niclass is still just a proof of concept, I haven't used it for any big project yet, not so strange since I wrote the code plus 3 blog posts about it today.

Niclass tutorial (my JavaScript class implementation)

The simplest thing is to create an empty class, that does not really include anything.

var A = $class();

var a = new A();
for (var x in a) {
  alert(x + ", value: " + a[x]);
}


We create a class with $class, and we list its members. The only member is $parent, with the value undefined.

Now, let's add a simple class that has a constructor that sets x to 3.

var A = $class({
  initialize: function() {
    this.x = 3;
  }
});

var a = new A();
alert(a.x);


Alerts 3 as expected.

We add a function, getX, to the class.

var A = $class({
  initialize: function() {
    this.x = 3;
  },
  getX: function() {
    return this.x;
  }
});

var a = new A();
alert(a.getX());


Still alerts 3.

We can let initialize take an argument, and send that argument to initialize through the new operation.

var A = $class({
  initialize: function(x) {
    this.x = x;
  },
  getX: function() {
    return this.x;
  }
});

var a = new A(3);
alert(a.getX());


This code also alerts 3.

We can add a function setX to the class that takes an argument.

var A = $class({
  initialize: function(x) {
    this.x = x;
  },
  getX: function() {
    return this.x;
  },
  setX: function(x) {
    this.x = x;
  }
});

var a = new A(3);
a.setX(5);
alert(a.getX());


Alerts 5, variation!

It is time to inherit. A new class B, inherits A. It implements getY and setY.

var A = $class({
  initialize: function(x) {
    this.x = x;
  },
  getX: function() {
    return this.x;
  },
  setX: function(x) {
    this.x = x;
  }
});

var B = $class(A, {
  getY: function() {
    return this.y;
  },
  setY: function(y) {
    this.y = y;
  }
});

var b = new B(3);
alert(b.getX());


Alerts 3. The argument we supplied to the B constructor was sent to the initialize function in A. This happened because class B didn't have an initialize function. You can also see that B has inherited the function getX.

So, what happens if we add an initialize function in class B?

var A = $class({
  initialize: function(x) {
    this.x = x;
  },
  getX: function() {
    return this.x;
  },
  setX: function(x) {
    this.x = x;
  }
});

var B = $class(A, {
  initialize: function(y) {
    this.y = y;
  },
  getY: function() {
    return this.y;
  },
  setY: function(y) {
    this.y = y;
  }
});

var b = new B(3);
alert(b.getX());
alert(b.getY());


First alerts undefined, then 3. So getX returns undefined, and getY returns 3. The initialize function in B was called, but not the one in class A.

We want to call the initialize function in class A, so we want to use $superinit.

var A = $class({
  initialize: function(x) {
    this.x = x;
  },
  getX: function() {
    return this.x;
  },
  setX: function(x) {
    this.x = x;
  }
});

var B = $class(A, {
  initialize: function(x, y) {
    $superinit(this, x);
    this.y = y;
  },
  getY: function() {
    return this.y;
  },
  setY: function(y) {
    this.y = y;
  }
});

var b = new B(3, 4);
alert(b.getX());
alert(b.getY());


Alerts 3 and 4. Here we can see that the initialize function of class A was called with the help of $superinit. For $superinit to work, you need to supply this as the first argument, and the arguments that you want to send to the parent's initialize function as following arguments. Note that this is a little bit harder than in some other class implementations, but a verbosity that we can live with.

Time to try $super, which is basically the same as $superinit, but for all other functions.

var A = $class({
  initialize: function(x) {
    this.x = x;
  },
  getX: function() {
    return this.x;
  },
  setX: function(x) {
    this.x = x;
  }
});

var B = $class(A, {
  initialize: function(x, y) {
    $superinit(this, x);
    this.y = y;
  },
  getY: function() {
    return this.y;
  },
  setY: function(y) {
    this.y = y;
  },
  getX: function() {
    return $super(this, "getX") + 2;
  }
});

var b = new B(3, 4);
alert(b.getX());


Alerts 5. Class B implements getX by calling class A:s getX function with the help of the $super function, and adds 2 to that value. As in $superinit, the first argument is this. The second argument is "getX", you always need to declare the function that should be called in the super class. If the function that we call need its own arguments, we supply them after the first two arguments. This is also more verbose than in other class implementations, but I think it is good enough.

Time to introduce $extend. Extending a class that has already been created is a powerful concept, you can't do this in C++, but it is possible to do in Ruby. When you extend a class with a new function, you can use that function in already created functions of that class. (and of course, all of its sub classes)

function outputHello() {
  if (a.printHello)
    a.printHello();
  else
    alert("printHello function missing");
}

var A = $class();

var a = new A();

outputHello(a);

$extend(A, {
  printHello: function() {
    alert("Hello");
  }
});

outputHello(a);


Alerts "printHello function missing", then alerts "Hello". First time, printHello does not exist on the a object, and the second time, after the $extend function call, we can call a.printHello(), since the A class now includes the printHello function.

Classes in JavaScript

JavaScript is an prototype-based object-oriented language. This is much less common than class-based object-oriented languages. This makes JavaScript a little bit hard to learn for most experienced programmers. The good thing is that prototypes are more flexible than classes, and you can actually implement class-based object-orientation in a prototype-based language.

There are a number of JavaScript frameworks that among other things also implements class-based object-orientation. Two of these I have been looking closely at, Prototype and MooTools.

I like both of them, but in my opinion, MooTools class implementation looks a little better. However, MooTools class implementation has a lot of overhead per method call. Prototype is faster. But both are too complex in implementation for my taste.

So, with the experience of these two class implementations, I decided to try to come up with my own class implementation. This is what I wanted to accomplish:

  • A compact and easy to understand implementation
  • An implementation that has very little run-time overhead
  • Easy to use
  • Support extending a class after its creation, so you can add functions to already created objects of that class

As always, to accomplish what you want to, you have to compromise. The compromise I decided to do was to make it a little bit harder to call the parent's implementation of the same function, and also that the initialization code of a parent needs to be explicitly called.

There are still a few optimizations left to do, it will not add that many lines, but I decided to keep it a little bit simpler, 50 lines of code is enough for a blog post.

$class: the most important function. It creates and returns a new class. If the first argument is a function, that is treated like this will be the parent class. All remaining arguments are treated like they are objects, and all members (functions as well as other data) are copied to the class. If initialize is one of the members, it will be called when you call new on the new class. All arguments sent to new are sent to the initialize function.

$new is a special member in the class that will be used in the combination with new when the class is used as a parent class. $parent is there to be able to implement the $super and $superinit functions.

$super: call the parent's implementation of a function. self is the this object, and fname is the name of the method that should be called. The rest of the arguments are sent to the parent function.

$superinit: call the parent's initialize implementation. self is the this object. The rest of the arguments are sent to the parent function.

$extend: extend the class klass with new members. These members are available in all current and future objects created from this class. All the arguments except for the first are treated like objects, and all members in those objects are inserted in the class.

function $super(self, fname) {
  var args = [];
  for (var i = 2; i < arguments.length; i++)
    args[i - 2] = arguments[i];
  return $super.caller.$base.$parent.prototype[fname].apply(self, args);
}

function $superinit(self) {
  var args = [];
  for (var i = 1; i < arguments.length; i++)
    args[i - 1] = arguments[i];
  return $superinit.caller.$base.$parent.prototype["initialize"].apply(self, args);
}

function $extend(klass) {
  var dest = klass.prototype;
  for (var i = 1; i < arguments.length; i++) {
    var src = arguments[i];
    for (var x in src) {
      dest[x] = src[x];
      if (typeof dest[x] == "function")
        dest[x].$base = klass.prototype;
    }
  }
}

function $class() {
  var klass = function() { if (this.initialize) return this.initialize.apply(this, arguments); };
  var parent, start, proto_obj;
  if (typeof arguments[0] == "function")
    parent = arguments[0];
  if (parent) {
    proto_obj = new parent.$new;
    start = 1;
  } else {
    proto_obj = {};
    start = 0;
  }
  for (var i = start; i < arguments.length; i++) {
    var src = arguments[i];
    for (var x in src) {
      proto_obj[x] = src[x];
      if (typeof proto_obj[x] == "function")
        proto_obj[x].$base = proto_obj;
    }
  }
  proto_obj.$parent = parent;
  klass.prototype = proto_obj;
  klass.$new = function() {};
  klass.$new.prototype = proto_obj;
  return klass;
}


The code is not well tested yet, so there may be bugs. I will update this blog post when I find something that needs to be changed. I will also add an extra blog post with examples that uses the class library.

Update 1: Had to add $base to each function in a class, to be able to solve the problem with infinite recursion when trying to call the super function.
Update 2: In $superinit, the parameter needs to be called self, not obj.

Unite and UserJS

,

UJS Manager is a new Unite service where you can manage your user js files. I have not been using user js, and just learned today how to develop user scripts. This is a Unite service that is really useful. I have had some small problems with it, but I am so new to user scripts that I need to investigate if it is my fault or not.

When I saw this service, I started thinking of Unite services in combination with user scripts. I think the combination could be used to create at least some of the typical extensions seen in Firefox, I will try to create a proof of concept as soon as possible.

Mini 5 and phones

Since my move to Android, Opera Mini 5 beta has been released. Unfortunately for me, there is no beta for Android. I have not yet tried the Mini 5 beta, but I will blog about it anyway.

Opera Mini has always been a fantastic product. Opera Mini was not the first browser to use servers to transcode the content into something that a simple phone could handle, but it did it very well. Stable servers, very good phone compatibility, nice rendering with the help of Opera's SSR technology, easy to use, and delivered as an easy to install Java application.

Opera Mini kept adding useful features, and in Opera 4, a big change happened. SSR was no longer the default view, now Opera Zoom was added, to make it easier for users to recognize the pages they usually visit. However, the rest of the user interface was pretty much the same.

With Mini 5, Opera Zoom is still there, but so is also a new user interface. The user interface in Opera Mini 5 is more like the user interface in Opera Desktop. There is a graphical speed dial, a password manager, graphical buttons for back and forward, tabs, etc. I think a lot of users will like this change.

Mini 5 is interesting in other ways too, it now supports touch devices, and works better with bigger screens. (I read on the forum that there was some issues with extremely big screens, but iPhone sized screens works well I think)

Opera Mini is a product that always stays fresh. It is there to optimize the web experience for the most popular phones, and that changes over time. One example is the touch devices, another is that screens are getting bigger. Mini 1 was built for the popular phones that existed in 2005. Some of the features in Mini 5 would not make sense on one of the low end phones in 2005, but they do in 2009.

Mini brings the mobile web to anyone, and I think that is a fantastic thing. And still I want to use a native browser. At least in theory. But, the extra speed and the great user experience that Mini brings makes me want to wait another year.

I Robot

Yesterday I got tired of my current mobile phone. Well, actually I got tired of it the first month, and now 14 months later, I decided to try to find a better mobile phone. I had a HTC Touch Diamond, it looks good, Opera Mobile preinstalled, but a completely broken user interface. I did not think that Windows Mobile could be that bad, but it was, and HTC's own improvements to the user interface were actually worse.

What finally made me go looking for a new mobile phone was the release of Spotify for both Android and iPhone. I like my iPod Touch, and hadn't tried Android enough. But, all iPhones sold in Sweden are locked to an operator, and I dislike my current operator, but for cost reasons I have to keep it for 9 more months. I went to a number of stores, and decided to buy an HTC Hero. This time I have all the freedom, since I bought it without a contract, and I also bought 16GB of storage.

So, how good is it? It has a user interface that was rather easy to learn, I have been able to include a number of applications from the Android market, including Spotify. The 3g data traffic worked directly when I inserted my SIM card. Some things, like how to switch between recent applications, I had to watch some videos to discover. I think the iPod Touch is much smoother when scrolling, but the HTC Hero feels much more like it is mine that I can do whatever I want with it, without permission from Apple. HTC Hero is good enough, and it does not make me unhappy when I am using it.

When I install a new application from the Android market, I am informed of the capabilities of the phone that the application will access. This is a feature that should be in all operating systems.

Opera 10, 5 days later

I decided to take a look at how many of the Opera users that are currently running Opera 10. The statistics from yesterday at Statcounter told me that 1.01% of all Internet users are using Opera 10, that is about 32% of the Opera users in total. I think that is ok considering that it has only been 5 days since Opera 10 was released.

As a comparison, Firefox 3.5 is now used by 50% of the Firefox users, 67 days after the release.

The usual disclaimer about Internet statistics. It will be interesting to see how many upgrades the coming weeks. Opera 10 is the best release since Opera 7.5, and a must have for all MacOS X users, looks good, is fast, and very stable.

Morning upgrade

,

While waiting for Opera 10 to arrive this morning, I installed Snow Leopard. The upgrade from Leopard worked, and I was happy to see newer versions of Python, Ruby, and Rails.

When the Snow Leopard install was done, Opera 10 was ready, so I installed that too. There was one problem, The panel was just one or two pixels wide, and I could not get it to work. I removed all old files in Preferences/Opera Preferences and Caches/Opera/, reinstalled, and then everything worked as it should. I do not know if this is a general problem or not, I have been doing a lot of strange things with my Opera installations lately.

I have now adjusted Opera 10 the way I prefer it to look, see screen shot.

JavaScript, Prototype and Ruby

, ,

A privilege I have working on a JavaScript engine is that I get to read a lot of Javascript code. I would like to write more JavaScript code than I currently do, the language is almost perfect for me. Ok, I would like a different syntax (I think that the C syntax family is wrong), but since I have been using C++ for more than ten years, I can live with that. In 2002 or 2003, I had to do some JavaScript related C++ coding, and I tried to understand prototypes (I didn't need to for my assigned task, but I did not really get it). For a long time, I was hoping for classes to be added to JavaScript, but now I am happy with it as it is. Please, no classes, and no static type checking.

I just started looking at the Prototype JavaScript Framework, and I found some things that I liked. First of all, the style of the code was pretty much how I want to code JavaScript. (2 spaces indentation, { on the same line as if/while, spaces in the right places, and the way functions are defined in an object. I would not code single line if/while bodies on the same line as the if/while statement, but I could probably adjust to that to.

One interesting aspect with Prototype is how it implements object orientation. If you read the document about class inheritance, you will see that it refers a lot to Ruby. I think Ruby developers have influenced Prototype a lot. It is basically Ruby inheritance in JavaScript.

This is a strength of prototype based languages. You can adjust the way it does object orientation, it is just more flexible than class based object orientation. But, flexibility usually makes it harder to learn, and you should probably add some kind of library on top of JavaScript. The way Prototype solves this has a rather clean syntax, and is as powerful as Ruby, which is enough for a lot of applications. (a nice thing in Ruby, JavaScript and Prototype is that you can add functions to already created objects of a certain type)

Debugging Unite services with Dragonfly part 2

,

Next challenge, write some Javascript code in the Unite service, and debug its main content. (that is before any user generated event has been triggered)

A simple example:

var a = 3 * 5;
var stop = true;


The second line is just there to make sure that I can inspect the a variable. (maybe there is a nicer way to do that)

If you want to step through the program, you can do the following:

  1. Select Stop at new thread (hand plus left bracket)
  2. Start the Unite service
  3. Select the Unite service in the Dragonfly menu
  4. Press Continue (play button)
  5. Now your script is visible, and you can start to debug


I think that this was rather unintuitive, but, as always, now I know how to do it.

Debugging Unite services with Dragonfly

,

Ok, so you have just developed a Unite service, and you need to debug the server code with Dragonfly.

In the Dragonfly menu, at least I get two Unite services listed as widget://.../index.html, where ... is a lot of numbers that is really hard to remember.

If you want to debug, you want a title. And, it is actually possible, I found out by some trial and error.

<!DOCTYPE html>
<title>My Unite Service</title>
<script src="script.js"></script>


So, what I did was just to add a standard HTML title to index.html in the service. I think that widgetname from the config.xml file should be used by default, but it is not, and using title solved the problem.

Developing services with Unite

I am still a beginner when it comes to Unite, but at least I can share some early experience.

When you want to start working on a new service, drag your config.xml into Opera. Do not install it as a *.us-file, I have got so many problems doing that, so just skip that for now.

When you want to test your new changes, stop and then start your service again.

To avoid problems while developing, go into settings and make sure that you check for new versions of both documents and images always.

If you are sharing files with shareFile, you can always access the changes to the files in the shared directory without restarting your Unite service.

Video on the web part 2

Google is trying to buy On2 Technologies. If this happens, Google will control video compression technology that is one of the better in the industry.

Even if the information is sparse what will happen, I am pretty confident that this will improve the chances of getting a standard video codec that everyone will agree on.

That YouTube starts to support Google's own video format seems like a given thing, and that they do it in the HTML5 video tag is equally likely. After that, more speculation is needed, but I think that they will make it royalty free, since they need to get the codec into all browsers and operating systems to make it successful.

Then, if all the above happens, H.264 will be less relevant. Maybe even H.264 will be made royalty free, to avoid losing the battle for the web.

It is only a few months before we will know the actual plans, I hope it is worth waiting for.

Javascript pattern: isolate init code

Last few weeks, I have been wading through lots of Javascript code, bugs have a tendency to force you to do things that you would normally not want to do. I have seen a lot of bad code, and some good. And, guess what, I still like Javascript a lot, in fact, I like it even more.

A common pattern found on pages on the Internet is using an anonymous function to encapsulate initialization code from polluting the global scope.

In Javascript, the scope of local variables is a function, not a block, as it is in many other popular languages. This is why you would like to use a function for encapsulation.

If you declare an anonymous function, and call it at the same time, it is approximately the same thing as an anonymous block in C++.

(function () {
  function printToScreen(str) {
    document.write("<p>" + str);
  }
  var s = "Hello world";
  printToScreen(s);
})();

// Here, s is not "Hello world", and printToScreen is not available.


You put the anonymous function inside parentheses, otherwise you will not be able to call it (because of Javascript's syntax). Then you call the function by adding (). In Javascript, you always have to add parentheses, since otherwise it is just a function reference, not a function call.

I always try to remember to add ; at the end of each statement. You do not have to do that always, ; is optional in a lot of places. The optional use of ; is one of the worst design mistakes in Javascript. The rules for when you are allowed to omit ; is too complex for most people to remember.

In my opinion, calling an anonymous function directly when it is declared has a quite ugly syntax. I think it is hard to read. If you want to spot if a file is using an anonymous function to encapsulate initialization code, look for the pattern "(function (" at the start of a line. If you match that pattern, it is almost certain that this is encapsulated initialization code. I think I would like to have some sort of support from my text editor for this kind of construct. (color coding or something similar)

Dragonfly and eval

,

I have to confess, I have not used Dragonfly that much. I am not a web developer, so that is not that strange, but Dragonfly is an Opera product, so I should be more familiar with it.

So, after my previous experiments with using eval to load libraries, I started wondering what happens if I try to debug the scripts that is loaded with eval.

This is the example code, I left out the HTML file.

// main.js

function load(name) {
  var s = new XMLHttpRequest();
  s.open("GET", name, false);
  s.send();
  eval(s.responseText);
}

onload = function() {
  load("loaded.js");
  f();
};


// loaded.js

f = function() {
  var a = 3;
  var b = 4;
  var c = a + b;
};


I was surprised to see that I was able to step through the eval code in Dragonfly. This is what I wanted. A problem was that, of course, the script loaded through eval did not have a name. A simple workaround is to add the name of the script at the top of the file. Another problem is that you can't select the eval script when the eval script is not running.

This is good enough to get my work done. I think it could be improved to increase its usefulness, I am sure the Dragonfly people at Opera has run in to this issue before, and I hope they are already working on improvements.

I am impressed with Dragonfly, it is really easy to use.

Libraries in Javascript

You can find a lot of great Javascript toolkits on the web, jQuery, Dojo, etc. This, however, is a mini-tutorial for how to build a system for working with libraries in Javascript.

Using libraries in Javascript is quite hard, since the language lacks both a way to load libraries, and clear namespaces.

Fortunately, Javascript, in combination with other modern web technologies, is very flexible. I have been looking at a number of different ways to use libraries in Javascript, and this is what I found to be easiest.

First, you need to have a framework for loading libraries. I call my framework library. It should be included in the html file, before the rest of your Javascript code. The framework initializes the object library in the global object, where you should put the libraries that you write, and also sets three functions on the global object, load that loads a Javascript library and runs the script, require that only loads a library if it hasn't already been loaded, and write, a function that writes a paragraph to the body of the html document, so that we can easily see what we are doing.

// library.js
library = {};

function load(name) {
  var s = new XMLHttpRequest();
  s.open("GET", name, false);
  s.send();
  eval(s.responseText);
}

function require(name) {
  if (!library[name])
    load(name + ".js");
}

function write(str) {
  var elm = document.createElement('p');
  elm.appendChild(document.createTextNode(str));
  document.getElementsByTagName("body")[0].appendChild(elm);
}


See that we are using XMLHttpRequest in synchronous mode to load Javascript files, and eval to parse and run the library. Make sure that there is not a lot of local variables that shadows global variables when you call require or load.

Then, we need to have an html file, it is an HTML 5 document, with an empty body.

<!DOCTYPE html>
<html>
<head>
<title>Testing library</title>
<script src="library.js" type="text/javascript"></script>
<script src="main.js" type="text/javascript"></script>
</head>
<body></body>
</html>


Our main.js file needs a library to play with, hello.js. hello.js creates the object library.hello, and adds the function helloWorld to that object.

// hello.js
library.hello = {};

library.hello.helloWorld = function() {
  write("Hello World");
};


Then, in main.js, we add our main function as an onload handler, and use the hello library.

// main.js
onload = function() {
  require("hello");
  library.hello.helloWorld();
};


That's it. A library can also use require, since a library can depend on another library. You could also encapsulate things a little bit more, like putting load and require inside the library object, if you put a lot of things in the global object, it will be harder to use since other code might stop working. Using the name library for libraries might also be a bad idea.

Many toolkits use a tree or package structure for their libraries, I left that out.
December 2009
M T W T F S S
November 2009January 2010
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31