Note Heading

Index

Sections

html

Code

<html> 

head - start

Code

<head>

script - start

Code

<script>

test

Code

function test()
{
	clear();

	try
	{
		var n = new nest();
		n.runAsync(app, "main");

	}
	catch(e)
	{
		show(e.message || e.description);
	}
}

clear()

Page1

function clear()
{
	document.getElementById("leftinput").value = "";
	document.getElementById("rightinput").value = "";

}

show(s)

Page1

function show(s)
{
	var out = document.getElementById("rightinput");

//alert(s);

	out.value += "\r\n--------------------\r\n" + s + "\r\n";
}

showLeft(s)

Page1

function showLeft(s)
{
	var out = document.getElementById("leftinput");

//alert(s);

	out.value += "\r\n--------------------\r\n" + s + "\r\n";
}

showObject()

Page1

function showObject(m)
{
	var out = document.getElementById("testoutput");

	var s = "";
	for (var k in m)
	{
		if (!m.hasOwnProperty(k)) continue;

		s += k + " : " + m[k] + "\r\n";
	}

	show(s);
}

nest([moduleSource : Function|Object|String, async : Boolean]) [: Object]

Code

/*********************************************
 *********************************************
 * NEST
 * 
 * A crazy JavaScript module system
 *
 * Version 0.2
 *
 * Copyright Julian Turner 2009
 *
 *********************************************
 *********************************************/

function nest(
	moduleSource /*: (Function,Object,String)*/ /* OPTIONAL*/ 
) /*: Object*/
{
	copyright : "Julian Turner 2009";
	version : "0.2";
	namespace : "nest";

Notes

nest (

[moduleSource : Function|Object|String]

[async : Boolean]

) [: Any]

Purpose

The principal function container for the nest module system.

It is activated by direct calling new nest(). Alternatively just calling nest() will return a new nest() created by the function for you.

Arguments

moduleSource : Function|Object|String [OPTIONAL]

You can supply an initial module which nest will immediately start loading.

async : Boolean [OPTIONAL]

Whether to load moduleSource on an asynchronous basis. You should do this if the moduleSource is specified as a file name, or if any of its dependencies still need to be downloaded.

Returns

Object

Returns a copy of the new nest() instance created to contain your modules.

Requires

Nothing.

Remarks

None

Example

None

Internal Constants

Code

var NEST_GLOBAL /*: (Window,Any)*/ = (function(){return this;})();  
var NEST_FUNCTION /*: Function*/ = arguments.callee || NEST_GLOBAL.nest;
var NEST_IS_IE /*: Boolean*/ = false /*@cc_on || true @*/;  

Notes

Internal Variables - global

GLOBAL

A reference to the Window or other global object hosting the ECMAScript instance.

NEST_FUNCTION

A reference to the nest Function. This is because the name nest is overwritten internally to refer to the instance of nest created by calling new nest(), which is the root of the nest namespace.

Instantiation

Code

// Option 1
var nest /*: Object*/ = (this instanceof NEST_FUNCTION) ? this : new NEST_FUNCTION(); 

// Option 2
// NEST_GLOBAL.nest /*: Object*/ = (this instanceof nest) ? this : new nest();
// for (var k /*: String*/ in NEST_FUNCTION) { nest[k] = NEST_FUNCTION[k]; }

Notes

Instantiation

To function, nest needs to be activated.

Option 1

Creates a new nest() instantiation as an internal variable, and returns this object. This option lets you re-use the nest function for multiple instantiations.

Option 2

Overwrites the global nest function with the new nest() instance object, so that you have only one nest instantiation in your application.

Private Variables - module loading

Code

var NEST_FATAL_ERROR /*: Boolean*/ = false;
var NEST_LAST_CLOSURE /*: Function*/;
var NEST_LOADING_MODULE_INSTANCE /*: Object*/ = nest;

Notes

Private Variables - module loading

Purpose

NEST_FATAL_ERROR : Boolean

Used to record fatal errors, particularly for module loading, to cancel timeouts.

NEST_LOADING_MODULE_INSTANCE : Object

This represents the current module object that is being instantiated. Each module overwrites this variable when it is loading. In effect it always stores the last instantiated module object.

NEST_LAST_CLOSURE : Function

Each module has its own nested closure function inside which the next module is instantiated. This represents effectively the closure function of the last instantiated module.

closure(jsSource : String) : Any

Code

function closure (jsSource /*: String*/) /*: Any*/
{
	var returnValue;
	eval(jsSource);
	return returnValue;
}
NEST_LAST_CLOSURE = closure;

Notes

closure (

jsSource : String

) : Any

Purpose

nest and each module has one of these. Each module is loaded by eval'ing new module_identifier() in the closure function of the previous module.

E.g. a closure stack of nest [nest_util [nest_dom [nest_gui [app]]]]

app then has internal scope chain access to the other modules and can access them with or without a namespace prefix if you wish.

Arguments

jsSource : String

Module source.

It can also be used for inspecting the internal variables and function declarations of modules.

Returns

Any

The eval'd code can set an external variable returnValue which is then returned by the function.

Requires

Nothing

Remarks

None

Example

None

loadModule(moduleSource : Function|Object|String) : Module

Code

function loadModule(
	moduleSource /*: (Function, String, Object)*/
) /*: Module*/
{
	NEST_FATAL_ERROR = false;
	var module /*: Module*/ = new Module(moduleSource);
	module.loadRequires();  // synchronous
	module.load();
	return module;
}
exports(loadModule);

Notes

loadModule (

module : Function|Object|String

) : Module

Purpose

This performs a basic synchronous load of the supplied module and all its dependencies.

It assumes that the module's source (and that of all its dependencies) are fully loaded at the point it is called.

Use loadModuleAsync for all other situations.

Arguments

moduleSource : Function|Object|String

The module can either be supplied as a function (in which case toString is called), or the function already in toString form, or an Object which has the module source as one of its properties. See the separate entry on module format.

Returns

Module

An internal object created to process information about a Module as part of the module loading process.

Requires

nest.Module
nest.Module.loadRequires
nest.Module.load

Remarks

None

Example

None

loadModuleAsync(module : Function|Object|String) : Module

Code

function loadModuleAsync(
	moduleSource /*: (Function, String, Object)*/
) /*: Object*/
{
	NEST_FATAL_ERROR = false;	
	var module /*: Module*/ = new Module(moduleSource);
	module.loadAsync();  // requires are loaded through this function
	return module;
}
exports(loadModuleAsync);

Notes

loadModuleAsync (

module : Function|Object|String

) : Object

Purpose

This is the entry function for asynchronous loading. If any dependency needs to be asynchronously loaded, then the whole dependency chain must be asynchronously loaded.

Arguments

module : Function|Object|String

A module Function.

The source code of a module Function

A module specification Object

A file name pointing to one of the above. The file name must end in ".js".

Returns

Module

An internal object created to process information about a Module as part of the module loading process.

Requires

nest.exports
nest.Module
nest.Module.loadAsync

Remarks

None

Example

None

run(moduleSource : Function|Object|String, mainFunction : String) : Any

Code

function run(
	moduleSource /*: (Function,Object,String)*/, 
	mainFunction /*: String*/
) /*: Module*/
{

	mainFunction = (typeof mainFunction == "string") ? mainFunction : "main";
	var module /*: Module*/ = loadModule(moduleSource);
	module.instance[mainFunction](); 
	return module;
}
exports(run);

Notes

run (

moduleSource : Function|Object|String

[mainFunction : String]

) : Any

Purpose

An alternative means of running your application. It is effectively the same as loadModule, but (a) assumes that you are referring to the final application module (so that all dependencies are loaded implicitly), and (b) calls a method of your application module called main or whatever mainFunction refers to.

Synchronous only.

Arguments

moduleSource : Function|Object|String

Your final application module source.

mainFunction : String [OPTIONAL] [DEFAULT "main()"]

A module exported method to call when it has finished loadined.

Returns

Module

The Module object of the application module.

Requires

nest.exports
nest.loadModule

Remarks

None

Example

None

runAsync(moduleSource : Function|Object|String, mainFunction : String) : Any

Code

function runAsync(
	moduleSource /*: (Function,Object,String)*/, 
	mainFunction /*: String*/
) /*: Any*/
{
	mainFunction = (typeof mainFunction == "string") ? mainFunction : "main";
	var module /*: Module*/ = loadModuleAsync(moduleSource);

	call("show", "Application '" + (module.filePath || module.identifier) + "' started loading on " + new Date());

	NEST_GLOBAL.setTimeout(deferred, 1);

	function deferred() 
	{
		if (NEST_FATAL_ERROR)
		{
			return;
		}

		if (module.isLoaded)
		{
			call("show", "Application '" + (module.filePath || module.identifier) + "' finished loading on " + new Date());

			module.instance[mainFunction]();
		}
		else
		{
			NEST_GLOBAL.setTimeout(deferred, 1);
		}
	}

	return module;
}
exports(runAsync);

Notes

runAsync (

moduleSource : Function|Object|String

mainFunction : String

) : Any

Purpose

An alternative means of running your application. It is effectively the same as loadModuleAsync, but (a) assumes that you are referring to the final application module (so that all dependencies are loaded implicitly), and (b) calls a method of your application module called main or whatever mainFunction refers to.

Arguments

moduleSource : Function|Object|String

A module Function.

The source code of a module Function

A module specification Object

A file name pointing to one of the above. The file name must end in ".js".

mainFunction : String [OPTIONAL] [DEFAULT "main()"]

A module exported method to call when it has finished loadined.

Returns

Module

Requires

nest.exports
nest.loadModuleAsync

Remarks

None

Example

None

inspect(findName : String) : Any

Code

function inspect(findName /*: String*/) /*: Any*/
{
	var source = "returnValue = " + findName;
	return NEST_LAST_CLOSURE(source);
}
exports(inspect);  // if you want to share the innards to the world

Notes

inspect (

findName : String

) : Any

Purpose

Allows you to retrieve any internally declared variable or function declaration.

Arguments

findName : String

Identifier for the property.

Returns

Any

Requires

Nothing

Remarks

None

Example

None

exports(exportItem : Any, alias : String) : void

Code

function exports(
	exportItem /*: Any*/, 
	alias /*: String*/
) /*: void*/
{
	if (alias)
	{		
		NEST_LOADING_MODULE_INSTANCE[alias] = exportItem;
	}

	if (exportItem instanceof Function)
	{
		var identifier /*: String*/ = Function_GetIdentifier(exportItem);
		NEST_LOADING_MODULE_INSTANCE[identifier] = exportItem;
		exportItem.ownerModule = NEST_LOADING_MODULE_INSTANCE; // for some reflection
	}	
}

Notes

exports (

exportItem : Any

alias : String

) : void

Purpose

Manages the exporting of items from a module.

Used to provide some meta-data

The items are added as properties to an internal object called NEST_LOADING_MODULE_INSTANCE which is set to the this value of the currently loading module.

Arguments

exportItem : Any

Function or variable to export.

alias : String

Property name to give it.

Returns

void

Requires

nest.Function_GetIdentifier

Remarks

None

Example

None

Function_GetIdentifier(f : Function|String) : String

Code

function Function_GetIdentifier(
	f /*: (Function,String)*/
) /*: String*/
{
	if (f instanceof Function)
	{
		f = f.toString();
	}

	var funcPattern /*: RegExp*/ = /^\s*function\s+([A-Za-z0-9_$]+)\s*\(/;	
	var execResult /*: Array.<String>*/ = funcPattern.exec(f);
		
	if (!execResult)
	{
		return "";
	}

	var functionIdentifier /*: String*/ = execResult[1];
	
	if (functionIdentifier == "anonymous")
	{
		return "";
	}

	return functionIdentifier;
}
exports(Function_GetIdentifier)

Notes

Function_GetIdentifierFromString (

functionSource : String

) : String

Purpose

Extracts the function identifier from a supplied Functionm.

Arguments

f : Function|String

If a Function, then toString is called.

If a String, then the result of calling toString on the function.

Returns

String

The identifier, or anonymous

Requires

Nothing

Remarks

None

Example

None

LoadScript(src : String, callBack : Function, loadedIdentifier : String, timeout : Number, timeout : Function) : void

Code

function LoadScript(
	src /*: String*/,
	callBack /*: Function*/,
	loadIdentifier /*: String*/,
	waitForMS /*: Number*/,
	timeout /*: Function*/
) /*: void*/
{
 	var head /*: HTMLHeadElement*/ = NEST_GLOBAL.document.getElementsByTagName('head')[0];
  	var scr /*: HTMLScriptElement*/ = NEST_GLOBAL.document.createElement('script');
	var loaded /*: Boolean*/ = false;

	scr.type = "text/javascript";
		
	if (callBack)
	{
		scr.onreadystatechange = function ()
		{
			call("show", "Ready State for '" + src + "' is '" +  scr.readyState + "'");

      			if (!loaded && (scr.readyState == 'complete' || (NEST_IS_IE ? scr.readyState == 'loaded' : false)))
			{
				loaded = true;
				callBack();
			}
   		}

  		scr.onload = function ()
		{
			call("show", "Onload for '" + src + "' just fired.");

      			if (!loaded)
			{
				loaded = true;
				callBack();
			}
   		}
	}

   	scr.src = src;
   	head.appendChild(scr);

	if (loadIdentifier)
	{
		if (!waitForMS)
		{
			waitForMS = 30000;  // thirty seconds
		}

		var started /*: Date*/ = new Date();

		var loadCheck /*: Function*/ = function () 
		{
			call("show", "Load check for '" + src + "' identifier '" + loadIdentifier + "' on " +  new Date());

			if (loaded == true)
			{
				return;
			}

			if (NEST_GLOBAL[loadIdentifier])
			{
				call("show", "Source code for file '" + src + "' identifier '" + loadIdentifier + "' available on " +  new Date());

				loaded = true;
				callBack();
				return;
			}

			var now /*: Date*/ = new Date();

			if (now - started > waitForMS)
			{
				loaded = true;
				timeout();
			}

			NEST_GLOBAL.setTimeout(loadCheck, 1); 
		};

		NEST_GLOBAL.setTimeout(loadCheck, 1);
	}
}
exports(LoadScript);

Notes

LoadScript (

src : String

[callBack : Function]

[loadIdentifier : String

waitForMS : Number

timeout : Function]

) : void

Purpose

Inserts a script element in into the head of the document and loads the resource pointed to be the src attribute.

Arguments

src : String

The URL (absolute or relative) for a resource that returns a JavaScript file.

callBack : Function

Optional callback function.

loadIdentifier : String
waitForMS : Number   miliseconds
timeout : Function

Optional name of a global identifier that the script will create if it loads and runs correctly. Supplying this will trigger a setTimeout which will keep looking for the identifier for the waitFor miliseconds and call timeout on failure.

Returns

void

Requires

nest.GLOBAL

Remarks

None

Example

None

Module - Start

Code

var Module /*: Function*/ = (function(){

Notes

Module

A simple object used to manage the module you are loading.

Module(moduleSource : Function|String|Object) : void

Code

function Module(
	moduleSource /*: (Function,String,Object)*/
) /*: void*/
{
	// PUBLIC
	this.isNestModule /*: Boolean*/ = true;
	this.author /*: String*/ = "";
	this.version /*: String*/ = "";
	this.identifier /*: String*/ = "";
	this.filePath /*: String*/ = "";
	this.fileName /*: String*/ = "";
	this.namespace /*: String*/ = "";
	this.requires /*: Array.<String>*/ = [];
	this.source /*: (Function,String)*/ = "";

	// PRIVATE
	this.isDownloaded /*: Boolean*/ = false;
	this.isPreProcessed /*: Boolean*/ = false;
	this.requiresInitiatied /*: Boolean*/ = false;
	this.isLoaded /*: Boolean*/ = false;
	this.instance /*: Object*/ = null;  // created on load
	this.namespaceChain /*: Array.<String>*/ = [];
	this.requiresFileNames /*: Array.<String>*/ = [];
	this.requiresModuleIdentifiers /*: Array.<String>*/ = [];

	if (moduleSource)
	{
		this.initialise(moduleSource);
	}
}

var constr /*: Function*/ = Module;
var proto /*: Object*/ = Module.prototype;

Notes

Module (

[moduleSource : Function|String|Object]

) : void

Purpose

The constructor function.

Arguments

moduleSource : Function|String|Object [OPTIONAL]

A function, string or object containing the module source, or a file path.

Alternatively you can call initialise(moduleSource) yourself at any time.

Returns

void

Requires

nest.Module.initialise

Remarks

None

Example

None

initialise(moduleSource : Function|String|Object) : void

Code

function initialise(
	moduleSource /*: (Function,String,Object)*/
) /*: String*/
{
	// Pointing to variable or function identifier containing the module source

	if (typeof moduleSource == "string" && NEST_LOADING_REQUIRE_REGEXP.test(moduleSource)) 
	{
		var execResult /*: RegExp*/ = NEST_LOADING_REQUIRE_REGEXP.exec(moduleSource);
		this.filePath = execResult[0];
		this.fileName = execResult[6];

		if (/\.js$/.test(this.fileName))
		{
			this.identifier = this.fileName.substring(0, this.fileName.length - 3);
		}
		else
		{
			this.identifier = this.fileName;
			this.fileName = this.fileName + ".js";
		}
		
		this.identifier = this.identifier.split(".").join("_");
		return;
	}

	if (moduleSource instanceof Function)
	{
		this.source /*: String*/ = moduleSource.toString();
	}
	else if (typeof moduleSource == "string") // function source code
	{
		this.source /*: String*/ = moduleSource;
	}
	else if (moduleSource instanceof Module || (moduleSource instanceof Object && moduleSource.isNestModule))
	{	
		for (var k /*: String*/ in moduleSource)
		{
			this[k] = moduleSource[k];
		}
	}
	else
	{
		NEST_FATAL_ERROR = false;	
		throw new Error("Error > nest > Module > initialise() > Supplied argument does not appear to be a valid moduleSource. Argument supplied was: " + moduleSource);
	}


	this.preProcess(moduleSource);
}

proto.initialise = initialise;

Notes

initialise (

moduleSource : Function|String|Object

) : void

Purpose

Carries out some basic initialisation. Will call preProcess if the full module source code is supplied. Otherwise it will just parse the file name for use in dynamic script loading.

Arguments

moduleSource : Function|String|Object

A module function or object, or a file name.

Returns

void

Requires

nest.Module.preProcess

Remarks

None

Example

None

Variables - NEST_LOADING

Code

var NEST_LOADING_MODULE_TIMEOUT /*: int*/ = 30000;
var NEST_LOADING_STACK /*: Array.<Object>*/ = [];
//var NEST_LOADING_REQUIRE_REGEXP /*: RegExp*/ = /^\s*(((http|https|file):[\/\\]{2,3})?(([^\\\/\? ]*[\\\\/])*)([^\\\/\? ]+)(\?[^\? ]+)?)\s*$/; // paren 6
//var NEST_LOADING_REQUIRE_REGEXP /*: RegExp*/ = /^\s*(((http|https|file):[\/\\]{2,3})?(([^\\\/\? ]*[\\\\/])*)([A-Za-z0-9\.]+)(\?[^\? ]+)?)\s*$/; // paren 6
var NEST_LOADING_REQUIRE_REGEXP /*: RegExp*/ = /^\s*(((http|https|file):[\/\\]{2,3}|[\/\\]{1,2})?(([^\\\/\? ]*[\\\\/])*)([A-Za-z0-9\.]+)(\?[^\? ]+)?)\s*$/; // paren 6

var NEST_LOADED_MODULES /*: Object.<Object>*/ = {"nest" : nest};

Notes

Stattic - Private - Variables - MODULE_LOADING

Purpose

NEST_LOADING_MODULE_TIMEOUT : Number [DEFAULT 30000 MS]

How long to wait to load a module before a fatal error.

NEST_LOADING_STACK : Array.<Object>

Each module and its require modules are put on the stack. A module is not loaded until its requires have been successfully loaded. The process is recursive, as any requires of requires are added to the stack, etc. Requires always put at the top of the stack.

NEST_LOADING_REQUIRE_REGEXP : RegExp

Simply regular expression to process http, https, file and normal file paths.

NEST_LOADED_MODULES : Object.<Object>

Stores each instance of a module, under both its namespace, and its function constructor identifier.

preProcess() : void

Code

function preProcess() /*: void*/
{
	this.isPreProcessed = true; // major crash without this
	this.preProcessIdentifier();
	this.preProcessClosure();
	this.preProcessInstanceReference();
	this.preProcessNamespace();
	this.preProcessRequires();

	this.isDownloaded = true;

	if (NEST_LOADED_MODULES[this.namespace] || NEST_LOADED_MODULES[this.identifier]) 
	{ 
		this.isLoaded = true;
	}	
}

proto.preProcess = preProcess;

Notes

preProcess (

) : void

Purpose

Carries out some pre-processing of the source code of a module, prior to evaluation.

Arguments

Returns

void

Requires

nest.Module.preProcessClosure
nest.Module.preProcessIdentifier
nest.Module.preProcessInstanceReference
nest.Module.preProcessNamespace
nest.Module.preProcessRequires

Remarks

None

Example

None

load() : void

Code

function load() /*: void*/
{
	if (this.isLoaded) 
	{ 
		return; 
	}

	if (NEST_LOADED_MODULES[this.namespace] || NEST_LOADED_MODULES[this.identifier]) 
	{ 
		this.isLoaded = true;
		return; 
	}

	call("show", "Loaded module '" + this.identifier + "' with namespace '" + this.namespace + "'.");
	
	var evalSource /*: String*/ = this.source + "; returnValue = new " + this.identifier + "();" + this.identifier + " = null;";
	var returnValue /*: Any*/;

	try
	{
		returnValue = NEST_LAST_CLOSURE(evalSource);

		if (!returnValue)
		{
			throw new Error("Module '" + this.identifier + "' does not refer to valid module function.");
		}
	}
	catch(e)
	{
		NEST_FATAL_ERROR = true;
		throw new Error("nest > Module > load > Module name '" + this.identifier + "' threw an error when loaded. Error was '" + (e.message || e.description) + "'.");
	}

	NEST_LOADED_MODULES[this.namespace] = NEST_LOADING_MODULE_INSTANCE;
	NEST_LOADED_MODULES[this.identifier] = NEST_LOADING_MODULE_INSTANCE;

	this.createNamespaceObjects();

	this.isLoaded = true;
	this.instance = NEST_LOADING_MODULE_INSTANCE;
}

proto.load = load;

Notes

load (

) : void

Purpose

This is the final step in the loading chain. When the source code for a module and its dependency chain has been downloaded and processed, this function instantiates the module.

Arguments

None

Returns

void

Requires

nest.NEST_LAST_CLOSURE
nest.Module.createNamespaceObjects

Remarks

None

Example

None

loadAsync() : void

Code

function loadAsync() /*: void*/
{
	var me /*: Module*/ = this;
	var timeout /*: int*/ = NEST_LOADING_MODULE_TIMEOUT;

	NEST_LOADING_STACK.push(this);

	if (!this.isDownloaded && this.filePath)
	{
		this.loadAsyncFile();
	}

	call("show", "Async observer started for module '" + me.identifier + "' on " +  new Date());

	NEST_GLOBAL.setTimeout(observe, 1);

	function observe()
	{

		if (NEST_FATAL_ERROR)
		{
			return;
		}

		if (me.isDownloaded && !me.isPreProcessed)
		{
			me.preProcess();
			me.loadRequires(true);
		}

		if (me.isDownloaded && me.isPreProcessed && !me.requiresInitiated)
		{
			me.loadRequires(true);
		}
		
		if (me.isPreProcessed && NEST_LOADING_STACK[NEST_LOADING_STACK.length - 1] === me)
		{
			call("show", "Async observer completed for module '" + me.identifier + "' on " +  new Date());

			NEST_LOADING_STACK.pop();
			me.load();
			return;
		}
			
		if (timeout - 1 < 0)
		{
			NEST_FATAL_ERROR = true;
			throw new Error("Error > nest > Module > loadAsync() > Failed to load '" + me.identifier + "'. Timed out.");
			return;
		}

		NEST_GLOBAL.setTimeout(observe, 1);
	}
}

proto.loadAsync = loadAsync;

Notes

loadAsync (

) : void

Purpose

Starts an asynchronous loading process for a module, so that a watcher is started to watch for when the module source has been downloaded. A separate watcher is started for each dependency. The load for a module is only called when it is at the top of the stack (i.e. any dependencies have been loaded.

Arguments

Returns

void

Requires

nest.Module.load
nest.Module.loadAsyncFile
nest.Module.loadRequires
nest.Module.preProcess

Remarks

None

Example

None

loadRequires(async : Boolean) : void

Code

function loadRequires(
	async /*: Boolean*/
) /*: void*/
{
	this.requiresInitiated = true;

	if (!this.requires.length) 
	{ 
		return; 
	}
	
	var extension /*: RegExp*/ = /\.js$/; 
	var moduleFilePath /*: String*/ = "";
	var moduleFileName /*: String*/ = "";
	var moduleIdentifier /*: String*/ = "";
	var moduleSource /*: (Function,String,Object)*/;
	var module /*: Module*/;

	for (var i /*: int*/ = 0; i < this.requires.length; i++)
	{
		moduleIdentifier = this.requiresModuleIdentifiers[i];

		call("show", "Loading require for module '" + this.identifier + "' : '" + moduleIdentifier + "'");

		if (NEST_LOADED_MODULES[moduleIdentifier])
		{
			call("show", "Already loaded.");
			continue;
		}

		moduleSource = NEST_GLOBAL[moduleIdentifier] || NEST_FUNCTION[moduleIdentifier];

		if (moduleSource)
		{
			call("show", "Dependency '" + moduleIdentifier + "' for module  '" + this.identifier + "' : source available.");

			module = new Module(moduleSource);

			if (async)
			{
				module = new Module(moduleSource);
				module.loadAsync();
			}
			else
			{	
				module = new Module(moduleSource);
				module.loadRequires();
				module.load();
			}

			continue;
		}

		moduleFilePath = this.requires[i];
		moduleFileName = this.requiresFileNames[i];

		call("show", "Loadling require file '" + moduleFilePath + "' for module '" + this.identifier + "'.");

		if (!async || !extension.test(moduleFileName))
		{
			NEST_FATAL_ERROR = true;
			throw new Error("nest > Module > loadRequires > Module '" + this.requires[i] + "' is either not a valid file name, or it does not refer to an already loaded module, or it is a file name and you are not loading in asynchronous mode.");
		}

		module = new Module(moduleFilePath);
		module.loadAsync();
	}
}

proto.loadRequires = loadRequires;

Notes

loadRequires (

async : Boolean

) : void

Purpose

Initiates separate loading of each require in a module. This will be on an async basis if async is true. When loading requires, nest will first check to see if (a) the module has already been fully loaded, or (b) if the module source is at least available.

Arguments

async : Boolean

All requires loaded on an asynchronous basis.

Returns

void

Requires

nest.Module.load
nest.Module.loadAsync

Remarks

None

Example

None

preProcessIdentifier() : void

Code

function preProcessIdentifier() /*: void*/
{

	if (this.identifier)
	{
		return;
	}

	this.identifier  = Function_GetIdentifier(this.source);

	if (!this.identifier || this.identifier == "anonymous")
	{
		NEST_FATAL_ERROR = true;
		throw new Error("nest > Module > preProcessIdentifier > Module does not have a valid identifier for the module function.  Module source : " + this.source);
	}

	// optional to recover memory?
	//if (NEST_GLOBAL[this.identifier])
	//{
	//	NEST_GLOBAL[this.identifier] = null;  	
	//}
	//if (NEST_FUNCTION[this.identifier])
	//{
	//	NEST_FUNCTION[this.identifier] = null;
	//}
}

proto.preProcessIdentifier = preProcessIdentifier;

Notes

preProcessIdentifier (

) : void

Purpose

Extract the function identifier from the module source.

Arguments

Returns

void

Requires

nest.Function_GetIdentifier

Remarks

None

Example

None

preProcessClosure() : void

Code

function preProcessClosure() /*: void*/
{
	var start /*: int*/ = 0;

	start = this.source.indexOf("{");
	
	if (start == -1)
	{
		NEST_FATAL_ERROR = true;
		throw new Error("nest > Module > preProcessInstanceReference > Module source may not be a function.  Source : " + this.source.substring(0, 40) + "...");
	}

	this.source = this.source.substring(0, start + 1) + "function closure (jsSource \/*: String*\/) \/*: Any*\/ { var returnValue \/*: Any*\/; eval(jsSource); return returnValue; }NEST_LAST_CLOSURE = closure;" + this.source.substring(start + 1, this.source.length);	
}

proto.preProcessClosure = preProcessClosure;

Notes

preProcessClosure (

) : void

Purpose

Inject a function into the module source which is the modules sub-closure used by nest.

Arguments

None

Returns

void

Requires

Remarks

None

Example

None

preProcessInstanceReference() : void

Code

function preProcessInstanceReference() /*: void*/
{
	var ref /*: RegExp*/ = /NEST_LOADING_MODULE_INSTANCE/;
	var start /*: int*/ = 0;

	if (ref.test(this.source))
	{
		return;
	}

	start = this.source.indexOf("{");
	
	if (start == -1)
	{
		NEST_FATAL_ERROR = true;
		throw new Error("nest > Module > preProcessInstanceReference > Module source may not be a function.  Source : " + this.source.substring(0, 40) + "...");
	}

	
	this.source = this.source.substring(0, start + 1) + "NEST_LOADING_MODULE_INSTANCE = this;" + this.source.substring(start + 1, this.source.length);	
}

proto.preProcessInstanceReference = preProcessInstanceReference;

Notes

preProcessInstanceReference (

) : void

Purpose

Inject into the module source a reference to NEST_LOADING_MODULE_INSTANCE = this.

Arguments

None

Returns

void

Requires

Remarks

None

Example

None

preProcessNamespace() : void

Code

function preProcessNamespace() /*: void*/
{
	var declaration /*: RegExp*/ = /(\{|\}|;|\r|\n)\s*namespace\s*:\s*"\s*(([A-Za-z0-9_]+)(\.([A-Za-z0-9_]+))*)\s*"\s*;/;
	var namespace /*: RegExp*/ = /\s*(([A-Za-z0-9_]+)(\.([A-Za-z0-9_]+))*)\s*$/;

	if (this.namespace && namespace.test(this.namespace))
	{
		this.namespaceChain = this.namespace.split(".");

		if (!/^nest\./.test(this.namespace))
		{
			this.namespace = "nest." + this.namespace;
			this.namespaceChain.unshift("nest");
		}

		return;
	}

	if (this.source && declaration.test(this.source))
	{
		this.namespace = declaration.exec(this.source)[2];
		this.namespaceChain = this.namespace.split(".");

		if (!/^nest\./.test(this.namespace))
		{
			this.namespace = "nest." + this.namespace;
			this.namespaceChain.unshift("nest");
		}

		return;
	}


	NEST_FATAL_ERROR = true;
	throw new Error("Module '" + this.identifier + "' does not declare a namespace or the namespace is invalid. Namespace = '" + this.namespace + "'.");
}

proto.preProcessNamespace = preProcessNamespace;

Notes

preProcessNamespace (

) : void

Purpose

Look for "namespace my.namespace"; in the module source and capture its value.

Arguments

None.

Returns

void

Requires

Remarks

None

Example

None

Old

	var declaration /*: RegExp*/ = /"\s*namespace\s*(([A-Za-z0-9_]+)(\.([A-Za-z0-9_]+))*)\s*";/;
	var namespace /*: RegExp*/ = /\s*(([A-Za-z0-9_]+)(\.([A-Za-z0-9_]+))*)\s*$/;

preProcessRequires() : void

Code

function preProcessRequires() /*: void*/
{
	var requires /*: Array.<String>*/ = [];
	var requiresFileNames /*: Array.<String>*/ = [];
	var requiresModuleIdentifiers /*: Array.<String>*/ = [];
	var requirePattern /*: RegExp*/ = /(\{|\}|;|\r|\n)\s*requires?\s*:\s*"\s*([^\s]+)\s*"\s*;/g;
	var execResult /*: Array.<String>*/;
	var require /*: String*/ = "";

	if (this.requires && this.requires.length > 0)
	{
		requires = this.requires;

		for (var i /*: int*/ = 0; i < requires.length; i++) 
		{
	
			require = requires[i];
			
			execResult = NEST_LOADING_REQUIRE_REGEXP.exec(require);

			if (!execResult)
			{
				NEST_FATAL_ERROR = true;
				throw new Error("Error > nest > Module > preProcessRequires() > Require string is invalid for module '" + this.identifier + "'.  Require was '" + requires[i] + "'.  The actual file name can only have the characters A-Z a-z 0-9 and DOT, and should be a valid ECMAScript identifier.");

			}

			require = execResult[6];

			requiresFileNames[i] = require;

			if (/\.js$/.test(require))
			{
				require = require.substring(0, require.length - 3);
			}

			require = require.split(".").join("_");
	
			requiresModuleIdentifiers[i] = require;
		}
	}
	else
	{	
		requirePattern.lastIndex = 0;
		requires = this.source.match(requirePattern) || [];

		if (!requires || !requires.length) 
		{ 
			return; 
		}
		
		for (var i /*: int*/ = 0; i < requires.length; i++) 
		{
			requirePattern.lastIndex = 0;
			require = requirePattern.exec(requires[i])[2];

			if (!NEST_LOADING_REQUIRE_REGEXP.test(require))
			{
				NEST_FATAL_ERROR = true;
				throw new Error("Error > nest > Module > preProcessRequires() > Require string is invalid for module '" + this.identifier + "'.  Require was '" + requires[i] + "'");
			}

			requires[i] = require;
		
			require = NEST_LOADING_REQUIRE_REGEXP.exec(require)[6];

			requiresFileNames[i] = require;

			if (/\.js$/.test(require))
			{
				require = require.substring(0, require.length - 3);
			}

			require = require.split(".").join("_");

			requiresModuleIdentifiers[i] = require;
		}
	}

	this.requires = requires;
	this.requiresFileNames = requiresFileNames;
	this.requiresModuleIdentifiers = requiresModuleIdentifiers;
}

proto.preProcessRequires = preProcessRequires;

Notes

preProcessRequires (

) : void

Purpose

Look for "require my.require.js"; in the module source and capture its value.

Arguments

Returns

void

Requires

Remarks

None

Example

None

Old

	var requirePattern /*: RegExp*/ = /"\s*requires?\s*([^\s]+)\s*";/g;

loadAsyncFile() : void

Code

function loadAsyncFile() /*: void*/
{
	var me /*: Module*/ = this;

	function callBack()
	{
		if (!NEST_GLOBAL[me.identifier] && !NEST_FUNCTION[me.identifier])
		{
			NEST_FATAL_ERROR = true;
			throw new Error("Error > nest > Module > loadAsyncFile() > Failed to load '" + me.filePath + "'.  Could not find module called '" + me.identifier + "'.");
		}

		me.initialise(NEST_GLOBAL[me.identifier] || NEST_FUNCTION[me.identifier]);   
	}

	function timeout()
	{
		NEST_FATAL_ERROR = true;
		throw new Error("Error > nest > Module > loadAsyncFile() > Failed to load '" + me.filePath + "'. Timed out.");
	}

	LoadScript(me.filePath, callBack, me.identifier, NEST_LOADING_MODULE_TIMEOUT, timeout); 
}

proto.loadAsyncFile = loadAsyncFile;

Notes

loadAsyncFile (

) : void

Purpose

If you are using loadAsync and a file name is encountered, this function handles the actual asynchronous loaading of that module file.

Arguments

None

Returns

void

Requires

nest.LoadScript
nest.Module.initialise

Remarks

None

Example

None

createNamespaceObjects() : void

Code

function createNamespaceObjects() /*: void*/
{
	var chain /*: Array.<String>*/ = this.namespaceChain;
	var link /*: String*/;
	var namespace /*: Object*/ = nest;
	var start /*: int*/ = 0;
	var existing /*: Boolean*/ = false;
		
	if (!chain.length || (chain.length == 1 && chain[0] == "nest"))
	{
		existing = true;
	}
	else
	{
		if (chain[0] == "nest") 
		{
			start = 1;
		}
			
		for (var i = start; i < chain.length - 1; i++) 
		{
			link = chain[i];
			namespace[link] = namespace[link] || {};
			namespace = namespace[link];
		}

		link = chain[chain.length - 1];

		if (namespace[link]) 
		{
			namespace = namespace[link];
			existing = true;
		}
		else
		{
			namespace[link] = namespace = NEST_LOADING_MODULE_INSTANCE;
		}
	}

	if (existing)
	{
		for (var k /*: String*/ in NEST_LOADING_MODULE_INSTANCE) 
		{
			namespace[k] = NEST_LOADING_MODULE_INSTANCE[k];
		}
	} 
}

proto.createNamespaceObjects = createNamespaceObjects;

Notes

createNamespaceObjects (

) : void

Purpose

This is used to create each object in the namespace chain you specify. If you load a module which uses a parent namespace, e.g. nest.util and nest.util.String then the util object will be a merged object.

Arguments

None

Returns

void

Requires

None

Remarks

None

Example

None

Module - End

Code

	return constr;
})();

call(f)

Code

function call(
	functionName /*: String*/
) /*: Any*/
{	

	var f /*: Function*/ = NEST_GLOBAL[functionName];

	if (!f) { return; }
	
	switch(arguments.length)
	{
		default:
			/* Fall through*/
		case 1:
			return f.call(null);
			break;

		case 2:
			return f.call(null, arguments[1]);
			break;

		case 3:
			return f.call(null, arguments[1], arguments[2]);
			break;
	}
}

NOTES

This is for temporary debugging use only.  Anything called using this will be stripped from the final code.

Return

Code

return moduleSource ? async ? nest.runAsync(moduleSource) : nest.run(moduleSource) : nest;

nest() - END

Code

}

nest_util()

Page1

function nest_util()
{
	namespace : "nest.util";

	function ExportedFunctionFromUTIL()
	{
		show("Hello from util");
	}
	exports(ExportedFunctionFromUTIL);
}

nest_dom()

Page1

var nest_dom = 
{ 
	isNestModule : true,
	author : "Julian Turner",
	version : "1",
	identifier : "nest_dom",
	namespace : "nest.dom",
	requires : ["nest.util.js"],
	source : "function nest_dom(){function ExportedFunctionFromDOM(){show(\"Hello from dom\");ExportedFunctionFromUTIL()}exports(ExportedFunctionFromDOM);}"
};

nest_gui()

Page1

nest["nest_gui"] = 
{ 
	isNestModule : true,
	author : "Julian Turner",
	version : "1",
	identifier : "nest_gui",
	namespace : "nest.gui",
	requires : ["nest.dom.js"],
	source : "function nest_gui(){function ExportedFunctionFromGUI(){show(\"Hello from gui\");ExportedFunctionFromDOM()}exports(ExportedFunctionFromGUI);function PrivateFunctionToInspect(){show(\"You found me\")}};"
};

nest_app()

Page1

function app()
{
	namespace : "apps.test";
	requires : "nest.lib.js";

	function main()
	{
		show("Hello from app");
		ExportedFunctionFromLIB();
		inspect("PrivateFunctionToInspect")();
		show(nest.util.ExportedFunctionFromUTIL);
		show(nest.apps.test.main);

	}
	exports(main);
}

script - end

Code

</script>

Notes

head - end

Code

</head>

Notes

body - start

Code

<body>

Notes

test - start

Code

<p style="color:blue; text-decoration:underline; font-bold"  onclick="test()" style="cursor:pointer">Test</p>

<div style="float:left;">

	<h4>Input</h4>

	<textarea id=leftinput style="width:470px; height:250px;"></textarea>

</div>

<div style="float:right;">

	<h4>Output</h4>
	
	<textarea id=rightinput style="width:470px; height:250px;"></textarea>

</div>

Notes

<v:shape style='width:200;height:200' strokecolor="blue" strokeweight="1px"

coordorigin="0 0" coordsize="200 200">

<v:path id=testPath v="m 0,0 l 0,10, 20,20 e"/>

</v:shape>

<v:curve

from="0px,0px" to="200px,0px"

control1="0px,200px" control2="100px,0px">

</v:curve>

body - end

Code

</body>

Notes

html - end

Code

</html>

Notes

Code

Page1

function nest_lib()
{
	namespace : "nest.lib";
	requires : "nest.gui";

	function ExportedFunctionFromLIB()
	{
		show("Hello from lib");
		ExportedFunctionFromGUI();
	}
	exports(ExportedFunctionFromLIB);
}