Blog

Javascript Controller

Article Quicklinks

Wha?

What exactly do I mean when I say “javascript controller”? What I have in mind is a program/script that resides on the server side which controls the way the javascript is passed to the browser (or whoever requests it).

Let’s have a couple of examples to illustrate what I think a basic javascript controller should be able to do.

Consider the following HTML code example showing how to load two javascript files using only one <script> tag:

<html>
<head>
	<script type="text/javascript" src="scripts/script1+script2"></script>
</head>
<body>
	Hello!
</body>
</html>
Example1.html: Example showing two javascript files being included in the same script tag.

And consider the following javascript code example showing how to include/require another file:

/* REQUIRE: Coordinates */

var Circle = function()
{
	this.coords = new Coordinates();

	this.setCoords = function(x,y)
	{
	this.coords.set(x,y);
	}

	this.draw = function()
	{
		// ...
	}
}
Circle.js: Example showing a simple require statement.

And finally consider another javascript code example of a file loading another javascript file from some javascript code library.

/* REQUIRE: lib/Animation */

Animation.fadeOut('some_div_id');
FadeSomeDiv.js: Example showing a require statement from some predefined javascript library.

Why?

At the bare minimum, what I ultimately wanted was to have a script that would be able to require/include other files, especially from a reusable library or framework. But there are so many side benefits that come along with it.

  • the ability to (re)use a library or framework across all projects
  • less server calls (that is, the browser only grabs one big javascript file instead of a bunch of smaller ones)
  • organization (no more massive 100k files to work with)
  • sweet inheritance possibilities
  • future possible addons: caching; and compression, things like removing comments and whitespace, and maybe even variable name shortening

The point is that there are a ton of advantages in creating such a script – or, I suppose, in having someone else create one for you.

How?

So, if all of this sounds interesting enough to try out for yourself, let’s try get it setup.

You can download the controller, including the examples files, here:

Download Javascript Controller + Examples

Unzip that business to your server (or on your home xampp setup). Here’s a running example of example.html.

Included in the .zip are these files (a more thorough investigation of these files can be found in the next section):

example.html
The example html file showing how to include/require files.
scripts/.htaccess
This is a configuration file which tells Apache to route all requests from scripts/some/request/ to scripts/index.php (that is, route them to the javascript controller).
scripts/index.php
This is the controller. You can set the path to your own library in this file.
scripts/Examples/ShapesExample.js
This is the example javascript file that the example html file opens.
scripts/My Library/Shape/Circle.js
A circle object in the library.
scripts/My Library/Shape/Rectangle.js
A rectangle object in the library.
Contents of javascript-controller.zip

But there are a couple things to note about how the controller works:

  • The library path is set inside of the javascript controller (index.php); in the example case the library path is “My Library”. Just change the value of the $libdir variable to the path of your library, and you should be good.
  • The extension .js is always appended to the end of the requested script files, so just something to be aware of.
  • If a file is “required” twice, it will only be included once (the controller keeps track of the included files and checks for duplicates).
  • When a file is required (R), it will appear before the file that required it (A), but if another file (B) which appears before the first file (A) and which requires the same file (R), the required file (R) will always appear before both files which required it (A and B). (I get the feeling that could have been said much more simply..)

An explanation of what’s going on in the example included in the .zip

Alright, so if we take a look at this html file:

<html>
<head>
<script type="text/javascript" src="scripts/Examples/ShapesExample"></script>
</head>
<body>
	<input type="button" onclick="circle1.report()" value="Call method circle1.report()">
	<input type="button" onclick="rectangle1.report()" value="Call method rectangle1.report()">
</body>
</html>
	
example.html: showing off how to include files in the html file

We can see that the script is “scripts/Examples/Shapes”, but what’s actually going on is that there is a PHP script located at “scripts/index.php” which gets executed, and checks to see if there is a file on the system called “Examples/Shapes.js”.

Our example script “Examples/ShapesExample.js” looks like this:

/* REQUIRE: lib/Shape/Circle */
/* REQUIRE: lib/Shape/Rectangle */

var rectangle1 = new Rectangle();
rectangle1.setCoords(0,0,30,40);

var circle1 = new Circle();
circle1.setRadius(9);
circle1.setCoords(30,30);
Examples/ShapesExample.js: the shapes example includes the files circle and rectangle from the library

The Javascript controller reads in this file and parses it, looking for REQUIRE statements surrounded by comments, like the ones above. It then loads those files in the same way (reading and parsing), including more files.

The special case, like the one above (e.g. lib/Shape/Circle), is when something from the “lib” (the library) is specified. The library path is set inside of the javascript controller; in this example case the library path is “My Library”.

The javascript controller thus looks for the files My Library\Shape\Circle.js, which looks like this:

var Circle = function()
{
	this.x = 0;
	this.y = 0;
	this.radius = 0;

	this.setRadius = function(r) { this.radius = r; }
	this.setCoords = function(x,y) {
		this.x = x;
		this.y = y;
	}

	this.report = function()
	{
		alert("I am a Circle with a radius of " + this.radius + " and which sits at co-ordinates " + this.x + ", " + this.y + ".");
	}
}
My Library/Shape/Circle.js: a circle object, located in the library

And, it looks for My Library\Shape\Rectangle.js, which looks like this:

var Rectangle = function()
{
	this.x1 = 0;
	this.y1 = 0;
	this.x2 = 0;
	this.y2 = 0;

	this.setCoords = function(x1,y1,x2,y2) {
		this.x1 = x1;
		this.y1 = y1;
		this.x2 = x2;
		this.y2 = y2;
	}

	this.report = function()
	{
		alert("I am a Rectangle which sits at co-ordinates (" + this.x1 + ", " + this.y1 + ") are (" + this.x2 + ", " + this.y2 + ").");
	}
}
My Library/Shape/Rectangle.js: a rectangle object, located in the library

It then puts all the files together and spits out one big Javascript file, which looks like this:

var Circle = function()
{
	this.x = 0;
	this.y = 0;
	this.radius = 0;

	this.setRadius = function(r) { this.radius = r; }
	this.setCoords = function(x,y) {
		this.x = x;
		this.y = y;
	}

	this.report = function()
	{
		alert("I am a Circle with a radius of " + this.radius + " and which sits at co-ordinates " + this.x + ", " + this.y + ".");
	}
}
var Rectangle = function()
{
	this.x1 = 0;
	this.y1 = 0;
	this.x2 = 0;
	this.y2 = 0;

	this.setCoords = function(x1,y1,x2,y2) {
		this.x1 = x1;
		this.y1 = y1;
		this.x2 = x2;
		this.y2 = y2;
	}

	this.report = function()
	{
		alert("I am a Rectangle which sits at co-ordinates (" + this.x1 + ", " + this.y1 + ") are (" + this.x2 + ", " + this.y2 + ").");
	}
}

var rectangle1 = new Rectangle();
rectangle1.setCoords(0,0,30,40);

var circle1 = new Circle();
circle1.setRadius(9);
circle1.setCoords(30,30);
This is the generated javascript file that’s sent to the browser.

Hopefully there should be no surprises with that result.

And let me know what you think — it might be inspiring enough to write some of those future addons!

One Response to Javascript Controller

  1. smt says:

    absolutly interesting, i will study your solution soon.

*
To prove that you're not a bot, enter this code
Anti-Spam Image