// clasma.js - Utility library
// Copyright (c) 2008, Clasma Events Inc.

// Define base namespace

if(typeof CLASMA=="undefined") var CLASMA={};

// Define version

CLASMA.ver=1.01;
CLASMA.build=1;

CLASMA.version="1.01.1";

// Namespace functions

// namespace
// Call to create a namespace

CLASMA.namespace=function(ns)
{
	var o=CLASMA;

	// split namespace
	var s=ns.split(".");
	var n=(s[0]=="CLASMA")?1:0;

	while(n<s.length)
	{
		// add if not present
		if(!o[s[n]]) o[s[n]]={};
		o=o[s[n++]];
	}
    return o;
};

// Define path names

CLASMA.libPath="http://www.clasma.net/common/lib/";
CLASMA.cssPath="http://www.clasma.net/common/css/";
CLASMA.resPath="http://www.clasma.net/common/res/";

// Included resources

CLASMA.scripts="";
CLASMA.styles="";

// include
// Call to include a file

CLASMA.include=function(f)
{
	// javascript?
	if(f.indexOf(".js")!=-1)
		return CLASMA.includeScript(CLASMA.libPath+f);

	// stylesheet?
	if(f.indexOf(".css")!=-1)
		return CLASMA.includeStyle(CLASMA.cssPath+f);

	return false;
};

// includeScript
// Call to include a javascript file

CLASMA.includeScript=function(f)
{
	// not already included?
	if(CLASMA.scripts.indexOf(f)==-1)
	{
		// create script element
		var e=document.createElement("script");

		e.setAttribute("language","javascript");
		e.setAttribute("type","text/javascript");
		e.setAttribute("src",f);

		// add to head section
		document.getElementsByTagName("head")[0].appendChild(e);

		// add to scripts list
		CLASMA.scripts+=f+";";
	}
	return true;
};

// includeStyle
// Call to include a stylesheet

CLASMA.includeStyle=function(f)
{
	// not already included?
	if(CLASMA.styles.indexOf(f)==-1)
	{
		// create stylesheet element
		var e=document.createElement("link");

		e.setAttribute("rel","stylesheet");
		e.setAttribute("type","text/css");
		e.setAttribute("href",f);

		// add to head section
		document.getElementsByTagName("head")[0].appendChild(e);

		// add to styles list
		CLASMA.styles+=f+";";
	}
	return true;
};

// Extend String object

// String trimming

String.prototype.ltrim=function() {return this.replace(/^\s+/g,"");};
String.prototype.rtrim=function() {return this.replace(/\s+$/g,"");};
String.prototype.trim=function() {return this.replace(/^\s\s*/,"").replace(/\s\s*$/,"");};

String.prototype.trimsplit=function(c) {return this.trim().split(new RegExp("\\s*"+c+"\\s*"));};

// HTML tags

String.prototype.escapeHtml=function() {return this.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;");};
String.prototype.unescapeHtml=function() {return this.replace(/&amp;/g,"&").replace(/&lt;/g,"<").replace(/&gt;/g,">");};

String.prototype.stripTags=function() {return this.replace(/<([^>]+)>/g,"");};

// String parsing

// parseUrl
// Call to split parts of url

String.prototype.parseUrl=function()
{
	var e=/^((http|ftp):\/)?\/?([^:\/\s]+)((\/\w+)*\/)([\w\-\.]+\.[^#?\s]+)(#[\w\-]+)?$/;
	var m=this.match(e);

	// return match?
	return m?{url:RegExp['$&'],protocol:RegExp.$2,host:RegExp.$3,path:RegExp.$4,file:RegExp.$6,hash:RegExp.$7}:null;
};

// parseFile
// Call to split parts of file

String.prototype.parseFile=function()
{
	var e=/(.*)\/([^\/\\]+)(\.\w+)$/;
	var m=this.match(e);

	// return match?
	return m?{path:m[1],file:m[2],ext:m[3]}:null;
};

// parseEmail
// Call to split parts of email address

String.prototype.parseEmail=function()
{
	// split email address
	var m=this.split("@");
	return (m && m.length==2)?{local:m[0],domain:m[1]}:null;
};

// validEmail
// Call to check for valid email address

String.prototype.validEmail=function()
{
	var len=this.length-1;

	// has at sign and not at start/end?
	var at=this.lastIndexOf("@");
	if(at<1 || at==len) return false;

	// has dot after at sign?
	var dot=this.lastIndexOf(".");
	if(dot<=at+1 || dot==len) return false;

	return true;
};

// Find and replace

// oneOf
// Return index of string in array

String.prototype.oneOf=function(ar)
{
	// run down string array
	for(var n=0;n<ar.length;n++)
	{
		// return match?
		if(this.toLowerCase()==ar[n].toLowerCase())
			return n;
	}
	return -1;
};

// supplant
// Call to supplant fields in a string

String.prototype.supplant=function(o)
{
	var fn=function(a,b)
	{
		var r=o[b];
		return typeof r==="string" || typeof r==="number"?r:a;
	};
	return this.replace(/{([^{}]*)}/g,fn);
};

// toTitle
// Call to capitalize first letter

String.prototype.toTitle=function()
{
	// lower case and cap first
	return this.toLowerCase().replace(/\b[a-z]/g,fn);
	function fn() {return arguments[0].toUpperCase();}
};

// toCaption
// Call to capitalize each major word

String.prototype.toCaption=function()
{
	// replace functions
	function fn1()
	{
		if(arguments[arguments.length-2]!=0)
		{
			// dont cap these
			var e=/^(a|after|an|and|at|by|for|from|in|into|of|on|onto|over|the|to|up|with|within)$/;
			if(e.test(arguments[0])) return arguments[0];
		}
		// cap first letter
		return arguments[0].replace(/^[a-z]/,fn2);
	}

	function fn2() {return arguments[0].toUpperCase();}

	// switch to lower
	return this.toLowerCase().replace(/\b\w+\b/g,fn1);
};

// Define namespace

CLASMA.namespace("CLASMA.lang");

// Define object

CLASMA.lang=function() {

// Private data

var number="0123456789";
var lower="abcdefghijklmnopqrstuvwxyz";
var upper="ABCDEFGHIJKLMNOPQRSTUVWXYZ";

// Private functions

// isValid
// Return true if all chars in s are in v

var isValid=function(s,v)
{
	// string exists?
	if(s && s!="")
	{
		// run down string
		for(var n=0;n<s.length;n++)
		{
			// check for validity
			if(v.indexOf(s.charAt(n))==-1)
				return false;
		}
	}
	return true;
};

// Private end

return {

// Public data

// Public functions

// Type checking

isUndefined:function(o) {return typeof o=="undefined";},
isNull:function(o) {return o===null;},

isBoolean:function(o) {return typeof o=="boolean";},
isString:function(o) {return typeof o=="string";},
isNumber:function(o) {return typeof o=="number" && isFinite(o);},
isObject:function(o) {return typeof o=="object";},
isFunction:function(o) {return typeof o=="function";},

// Character checking

isNum:function(s) {return isValid(s,number);},
isUpper:function(s) {return isValid(s,upper);},
isLower:function(s) {return isValid(s,lower);},
isAlpha:function(s) {return isValid(s,upper+lower);},
isAlphaNum:function(s) {return isValid(s,upper+lower+number);},

// Math functions

tween:function(t,b,c,d) {return b+((c-b)*(t/d));}

// Public end

}; }();

// Define namespace

CLASMA.namespace("CLASMA.detect");

// Define object

CLASMA.detect=function() {

// Private data

var ua=navigator.userAgent.toLowerCase();

// Private functions

// Private end

return {

// Public data

opera:(ua.indexOf("opera")!=-1),
safari:(ua.indexOf("safari")!=-1),
gecko:(!this.opera && !this.safari && ua.indexOf("gecko")!=-1),
firefox:(!this.gecko && ua.indexOf("firefox")!=-1),
ie:(!this.opera && ua.indexOf("msie")!=-1)

// Public functions

// Public end

}; }();

// Element functions

function $(id) {return document.getElementById(id);}
if(!Object.prototype.toJSONString){Array.prototype.toJSONString=function(w){var a=[],i,l=this.length,v;for(i=0;i<l;i+=1){v=this[i];switch(typeof v){case "object":if(v){if(typeof v.toJSONString==="function"){a.push(v.toJSONString(w));}}else{a.push("null");}break;case "string":case "number":case "boolean":a.push(v.toJSONString());}}return "["+a.join(",")+"]";};Boolean.prototype.toJSONString=function(){return String(this);};Date.prototype.toJSONString=function(){function f(n){return n<10?"0"+n:n;}return "\""+this.getUTCFullYear()+"-"+f(this.getUTCMonth()+1)+"-"+f(this.getUTCDate())+"T"+f(this.getUTCHours())+":"+f(this.getUTCMinutes())+":"+f(this.getUTCSeconds())+"Z\"";};Number.prototype.toJSONString=function(){return isFinite(this)?String(this):"null";};Object.prototype.toJSONString=function(w){var a=[],k,i,v;if(w){for(i=0;i<w.length;i+=1){k=w[i];if(typeof k==="string"){v=this[k];switch(typeof v){case "object":if(v){if(typeof v.toJSONString==="function"){a.push(k.toJSONString()+":"+v.toJSONString(w));}}else{a.push(k.toJSONString()+":null");}break;case "string":case "number":case "boolean":a.push(k.toJSONString()+":"+v.toJSONString());}}}}else{for(k in this){if(typeof k==="string"&&Object.prototype.hasOwnProperty.apply(this,[k])){v=this[k];switch(typeof v){case "object":if(v){if(typeof v.toJSONString==="function"){a.push(k.toJSONString()+":"+v.toJSONString());}}else{a.push(k.toJSONString()+":null");}break;case "string":case "number":case "boolean":a.push(k.toJSONString()+":"+v.toJSONString());}}}}return "{"+a.join(",")+"}";};(function(s){var m={"\b":"\\b","\t":"\\t","\n":"\\n","\f":"\\f","\r":"\\r","\"":"\\\"","\\":"\\\\"};s.parseJSON=function(_8){var j;function walk(k,v){var i;if(v&&typeof v==="object"){for(i in v){if(Object.prototype.hasOwnProperty.apply(v,[i])){v[i]=walk(i,v[i]);}}}return _8(k,v);}if(/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/.test(this.replace(/\\./g,"@").replace(/"[^"\\\n\r]*"/g,""))){j=eval("("+this+")");return typeof _8==="function"?walk("",j):j;}throw new SyntaxError("parseJSON");};s.toJSONString=function(){if(/["\\\x00-\x1f]/.test(this)){return "\""+this.replace(/[\x00-\x1f\\"]/g,function(a){var c=m[a];if(c){return c;}c=a.charCodeAt();return "\\u00"+Math.floor(c/16).toString(16)+(c%16).toString(16);})+"\"";}return "\""+this+"\"";};})(String.prototype);}window.dhtmlHistory={isIE:false,isOpera:false,isSafari:false,isKonquerer:false,isGecko:false,isSupported:false,create:function(_1){var _2=this;var UA=navigator.userAgent.toLowerCase();var _4=navigator.platform.toLowerCase();var _5=navigator.vendor||"";if(_5==="KDE"){this.isKonqueror=true;this.isSupported=false;}else{if(typeof window.opera!=="undefined"){this.isOpera=true;this.isSupported=true;}else{if(typeof document.all!=="undefined"){this.isIE=true;this.isSupported=true;}else{if(_5.indexOf("Apple Computer, Inc.")>-1){this.isSafari=true;this.isSupported=(_4.indexOf("mac")>-1);}else{if(UA.indexOf("gecko")!=-1){this.isGecko=true;this.isSupported=true;}}}}}window.historyStorage.setup(_1);if(this.isSafari){this.createSafari();}else{if(this.isOpera){this.createOpera();}}var _6=this.getCurrentLocation();this.currentLocation=_6;if(this.isIE){this.createIE(_6);}var _7=function(){_2.firstLoad=null;};this.addEventListener(window,"unload",_7);if(this.isIE){this.ignoreLocationChange=true;}else{if(!historyStorage.hasKey(this.PAGELOADEDSTRING)){this.ignoreLocationChange=true;this.firstLoad=true;historyStorage.put(this.PAGELOADEDSTRING,true);}else{this.ignoreLocationChange=false;this.fireOnNewListener=true;}}var _8=function(){_2.checkLocation();};setInterval(_8,100);},initialize:function(){if(this.isIE){if(!historyStorage.hasKey(this.PAGELOADEDSTRING)){this.fireOnNewListener=false;this.firstLoad=true;historyStorage.put(this.PAGELOADEDSTRING,true);}else{this.fireOnNewListener=true;this.firstLoad=false;}}},addListener:function(_9){this.listener=_9;if(this.fireOnNewListener){this.fireHistoryEvent(this.currentLocation);this.fireOnNewListener=false;}},addEventListener:function(o,e,l){if(o.addEventListener){o.addEventListener(e,l,false);}else{if(o.attachEvent){o.attachEvent("on"+e,function(){l(window.event);});}}},add:function(_d,_e){if(this.isSafari){_d=this.removeHash(_d);historyStorage.put(_d,_e);this.currentLocation=_d;window.location.hash=_d;this.putSafariState(_d);}else{var _f=this;var _10=function(){if(_f.currentWaitTime>0){_f.currentWaitTime=_f.currentWaitTime-_f.waitTime;}_d=_f.removeHash(_d);if(document.getElementById(_d)&&_f.debugMode){var e="Exception: History locations can not have the same value as _any_ IDs that might be in the document,"+" due to a bug in IE; please ask the developer to choose a history location that does not match any HTML"+" IDs in this document. The following ID is already taken and cannot be a location: "+_d;throw new Error(e);}historyStorage.put(_d,_e);_f.ignoreLocationChange=true;_f.ieAtomicLocationChange=true;_f.currentLocation=_d;window.location.hash=_d;if(_f.isIE){_f.iframe.src="blank.html?"+_d;}_f.ieAtomicLocationChange=false;};window.setTimeout(_10,this.currentWaitTime);this.currentWaitTime=this.currentWaitTime+this.waitTime;}},isFirstLoad:function(){return this.firstLoad;},getVersion:function(){return "0.6";},getCurrentLocation:function(){var r=(this.isSafari?this.getSafariState():this.getCurrentHash());return r;},getCurrentHash:function(){var r=window.location.href;var i=r.indexOf("#");return (i>=0?r.substr(i+1):"");},PAGELOADEDSTRING:"DhtmlHistory_pageLoaded",listener:null,waitTime:200,currentWaitTime:0,currentLocation:null,iframe:null,safariHistoryStartPoint:null,safariStack:null,safariLength:null,ignoreLocationChange:null,fireOnNewListener:null,firstLoad:null,ieAtomicLocationChange:null,createIE:function(_15){this.waitTime=400;var _16=(historyStorage.debugMode?"width: 800px;height:80px;border:1px solid black;":historyStorage.hideStyles);var _17="rshHistoryFrame";var _18="<iframe frameborder=\"0\" id=\""+_17+"\" style=\""+_16+"\" src=\"blank.html?"+_15+"\"></iframe>";document.write(_18);this.iframe=document.getElementById(_17);},createOpera:function(){this.waitTime=400;var _19="<img src=\"javascript:location.href='javascript:dhtmlHistory.checkLocation();';\" style=\""+historyStorage.hideStyles+"\" />";document.write(_19);},createSafari:function(){var _1a="rshSafariForm";var _1b="rshSafariStack";var _1c="rshSafariLength";var _1d=historyStorage.debugMode?historyStorage.showStyles:historyStorage.hideStyles;var _1e=(historyStorage.debugMode?"width:800px;height:20px;border:1px solid black;margin:0;padding:0;":historyStorage.hideStyles);var _1f="<form id=\""+_1a+"\" style=\""+_1d+"\">"+"<input type=\"text\" style=\""+_1e+"\" id=\""+_1b+"\" value=\"[]\"/>"+"<input type=\"text\" style=\""+_1e+"\" id=\""+_1c+"\" value=\"\"/>"+"</form>";document.write(_1f);this.safariStack=document.getElementById(_1b);this.safariLength=document.getElementById(_1c);if(!historyStorage.hasKey(this.PAGELOADEDSTRING)){this.safariHistoryStartPoint=history.length;this.safariLength.value=this.safariHistoryStartPoint;}else{this.safariHistoryStartPoint=this.safariLength.value;}},getSafariStack:function(){var r=this.safariStack.value;return historyStorage.fromJSON(r);},getSafariState:function(){var _21=this.getSafariStack();var _22=_21[history.length-this.safariHistoryStartPoint-1];return _22;},putSafariState:function(_23){var _24=this.getSafariStack();_24[history.length-this.safariHistoryStartPoint-1]=_23;this.safariStack.value=historyStorage.toJSON(_24);},fireHistoryEvent:function(_25){var _26=historyStorage.get(_25);this.listener.call(null,_25,_26);},checkLocation:function(){if(!this.isIE&&this.ignoreLocationChange){this.ignoreLocationChange=false;return;}if(!this.isIE&&this.ieAtomicLocationChange){return;}var _27=this.getCurrentLocation();if(_27==this.currentLocation){return;}this.ieAtomicLocationChange=true;if(this.isIE&&this.getIframeHash()!=_27){this.iframe.src="blank.html?"+_27;}else{if(this.isIE){return;}}this.currentLocation=_27;this.ieAtomicLocationChange=false;this.fireHistoryEvent(_27);},getIframeHash:function(){var doc=this.iframe.contentWindow.document;var _29=String(doc.location.search);if(_29.length==1&&_29.charAt(0)=="?"){_29="";}else{if(_29.length>=2&&_29.charAt(0)=="?"){_29=_29.substring(1);}}return _29;},removeHash:function(_2a){var r;if(_2a===null||_2a===undefined){r=null;}else{if(_2a===""){r="";}else{if(_2a.length==1&&_2a.charAt(0)=="#"){r="";}else{if(_2a.length>1&&_2a.charAt(0)=="#"){r=_2a.substring(1);}else{r=_2a;}}}}return r;},iframeLoaded:function(_2c){if(this.ignoreLocationChange){this.ignoreLocationChange=false;return;}var _2d=String(_2c.search);if(_2d.length==1&&_2d.charAt(0)=="?"){_2d="";}else{if(_2d.length>=2&&_2d.charAt(0)=="?"){_2d=_2d.substring(1);}}window.location.hash=_2d;this.fireHistoryEvent(_2d);}};window.historyStorage={setup:function(_2e){if(typeof _2e!=="undefined"){if(_2e.debugMode){this.debugMode=_2e.debugMode;}if(_2e.toJSON){this.toJSON=_2e.toJSON;}if(_2e.fromJSON){this.fromJSON=_2e.fromJSON;}}var _2f="rshStorageForm";var _30="rshStorageField";var _31=this.debugMode?historyStorage.showStyles:historyStorage.hideStyles;var _32=(historyStorage.debugMode?"width: 800px;height:80px;border:1px solid black;":historyStorage.hideStyles);var _33="<form id=\""+_2f+"\" style=\""+_31+"\">"+"<textarea id=\""+_30+"\" style=\""+_32+"\"></textarea>"+"</form>";document.write(_33);this.storageField=document.getElementById(_30);if(typeof window.opera!=="undefined"){this.storageField.focus();}},put:function(key,_35){this.assertValidKey(key);if(this.hasKey(key)){this.remove(key);}this.storageHash[key]=_35;this.saveHashTable();},get:function(key){this.assertValidKey(key);this.loadHashTable();var _37=this.storageHash[key];if(_37===undefined){_37=null;}return _37;},remove:function(key){this.assertValidKey(key);this.loadHashTable();delete this.storageHash[key];this.saveHashTable();},reset:function(){this.storageField.value="";this.storageHash={};},hasKey:function(key){this.assertValidKey(key);this.loadHashTable();return (typeof this.storageHash[key]!=="undefined");},isValidKey:function(key){return (typeof key==="string");},showStyles:"border:0;margin:0;padding:0;",hideStyles:"left:0px;top:0px;width:1px;height:1px;border:0;position:absolute;",debugMode:false,storageHash:{},hashLoaded:false,storageField:null,assertValidKey:function(key){var _3c=this.isValidKey(key);if(!_3c&&this.debugMode){throw new Error("Please provide a valid key for window.historyStorage. Invalid key = "+key+".");}},loadHashTable:function(){if(!this.hashLoaded){var _3d=this.storageField.value;if(_3d!==""&&_3d!==null){this.storageHash=this.fromJSON(_3d);this.hashLoaded=true;}}},saveHashTable:function(){this.loadHashTable();var _3e=this.toJSON(this.storageHash);this.storageField.value=_3e;},toJSON:function(o){return o.toJSONString();},fromJSON:function(s){return s.parseJSON();}};// dom.js - Dom library
// Copyright (c) 2008, Clasma Events Inc.

// Define namespace

CLASMA.namespace("CLASMA.dom");

// Define object

CLASMA.dom=function() {

// Private data

// Private functions

var getE=function(id) {return CLASMA.lang.isString(id)?$(id):id;};
var getS=function(id) {var e=getE(id); return e?e.style:null;};

// Private end

return {

// Public data

// Public functions

// Object fetching

getDocument:function() {return document;},

getHead:function(doc) {if(!doc) doc=document; return doc.getElementsByTagName("head")[0];},
getBody:function(doc) {if(!doc) doc=document; return doc.getElementsByTagName("body")[0];},

getObject:function(id) {return getE(id);},
getStyle:function(id) {return getS(id);},

// Element manipulation

setId:function(id,name) {var e=getE(id); if(e) e.id=name;},
setClass:function(id,name) {var e=getE(id); if(e) {e.setAttribute("class",name); e.setAttribute("className",name);}},
setHtml:function(id,html) {var e=getE(id); if(e) e.innerHTML=html;},

setTop:function(id,t) {var s=getS(id); if(s) s.top=t+"px";},
setLeft:function(id,l) {var s=getS(id); if(s) s.left=l+"px";},
setWidth:function(id,w) {var s=getS(id); if(s) s.width=w+"px";},
setHeight:function(id,h) {var s=getS(id); if(s) s.height=h+"px";},

setShow:function(id,show) {var s=getS(id); if(s) s.display=show?"block":"none";},
isVisible:function(id) {var s=getS(id); return s && s.display!="none";},

// createElement
// Call to create an element

createElement:function()
{
	var a=arguments;
	var n=0;

	// use optional doc?
	var doc=CLASMA.lang.isString(a[n])?document:a[n++];
	var e=doc.createElement(a[n++]);

	if(e)
	{
		// add attributes
		while(n<a.length)
		{
			o=a[n++].trimsplit("=");
			if(o.length==2) e.setAttribute(o[0],o[1]);
		}
	}
	return e;
},

// getElements
// Call to get element array

getElements:function(tag,from,cls)
{
	// defaults
	if(!tag) tag="*";

	if(from) from=getE(from);
	else from=document;

	if(from)
	{
		// get elements
		var scan=(tag=="*" && from.all)?from.all:from.getElementsByTagName(tag);

		if(cls)
		{
			// search for class name
			var elms=new Array();
			var rexp=new RegExp("(^|\\s)"+cls+"(\\s|$)");

			var e;

			for(var n=0;n<scan.length;n++)
			{
				e=scan[n];

				if(rexp.test(e.className))
					elms.push(e);
			}
			return elms;
		}
		return scan;
	}
	return new Array();
},

// getElementById
// Call for better version of document get

getElementById:function(from,id)
{
	// use orig
	if(!from || from==document)
		return document.getElementById(id);

	// get from address
	from=getE(from);

	if(from)
	{
		// get elements
		var scan=from.all?from.all:from.getElementsByTagName("*");

		if(scan)
		{
			var e;

			// try to find in list
			for(var n=0;n<scan.length;n++)
			{
				e=scan[n];
				if(e.id==id) return(e);
			}
		}
	}
	return null;
},

// enableFormElements
// Call to enable all form elements

enableFormElements:function(form,enable,exempt)
{
	// default params
	if(typeof enable=="undefined") enable=true;
	if(typeof exempt=="undefined") exempt=null;

	// get form object
	form=getE(form);

	if(form)
	{
		// enable all controls
		for(var n=0;n<form.elements.length;n++)
		{
			var e=form.elements[n];
			if(e) e.disabled=!enable;
		}

		if(exempt)
		{
			// disable exempt controls
			var ex=exempt.split(",")

			for(n=0;n<ex.length;n++)
				$(ex[n]).disabled=enable;
		}
	}
},

// getBoundingBox
// Call to get element bounding box

getBoundingBox:function(id)
{
	// get element object
	var e=getE(id);

	if(e)
	{
		var box={top:0,left:0,bottom:0,right:0,width:0,height:0};

		// Firefox, etc
		if(document.getBoxObjectFor)
		{
			var bo=document.getBoxObjectFor(e);

			box.top=bo.y;
			box.left=bo.x;
			box.bottom=bo.y+bo.height;
			box.right=bo.x+bo.width;
			box.width=bo.width;
			box.height=bo.height;

			return box;
		}

		// IE
		if(e.getBoundingClientRect)
		{
			var br=e.getBoundingClientRect();

			box.top=br.top;
			box.left=br.left;
			box.bottom=br.bottom;
			box.right=br.right;
			box.width=br.right-br.left;
			box.height=br.bottom-br.top;

			return box;
		}

		// Safari
		box.width=e.offsetWidth;
		box.height=e.offsetHeight;

		while(e)
		{
			box.left+=e.offsetLeft;
			box.top+=e.offsetTop;

			e=e.offsetParent;
		}

		box.right=box.left+box.width;
		box.bottom=box.top+box.height;

		return box;
	}
	return null;
},

// ptInBoundingBox
// Return true if point in bounding box

ptInBoundingBox:function(id,pt)
{
	// get bounding box
	var b=this.getBoundingBox(id);

	// point within it?
	return pt.top>=b.top && pt.top<b.bottom &&
		pt.left>=b.left && pt.left<b.right;
},

// isChild
// Return true if e is a child of p

isChild:function(p,e)
{
	// run up through parents
	while(e)
	{
		// parent matches?
		if(e==p) return true;
		e=e.parentNode;
	}
	return false;
},

// addEvent
// Call to add event handler

addEvent:function(id,name,fn,capture)
{
	// get element object
	var e=getE(id);

	if(e)
	{
		// set default params
		if(typeof capture=="undefined") capture=false;

		// event listener method?
		if(e.addEventListener) e.addEventListener(name,fn,capture);
		else
		{
			// attach event method?
			if(e.attachEvent) e.attachEvent("on"+name,fn);
			else e["on"+name]=fn;
		}
	}
},

// removeEvent
// Call to remove event handler

removeEvent:function(id,name,fn,capture)
{
	// get element object
	var e=getE(id);

	if(e)
	{
		// set default params
		if(typeof capture=="undefined") capture=false;

		// event listener method?
		if(e.removeEventListener) e.removeEventListener(name,fn,capture);
		else
		{
			// detach event method?
			if(e.detachEvent) e.detachEvent("on"+name,fn);
			else e["on"+name]=null;
		}
	}
},

// Dom load event

// triggerContentLoaded
// Call to trigger dom content loaded

triggerContentLoaded:function()
{
	// add event listener?
	if(document.addEventListener)
		document.addEventListener("DOMContentLoaded",this.oncontentloaded,false);

	// safari?
	if(CLASMA.detect.safari)
	{
		// setup timer
		var timer=setInterval(function()
		{
			// document ready?
			if(/loaded|complete/.test(document.readyState))
			{
				// reset timer/fire event
				clearInterval(timer);
				CLASMA.dom.oncontentloaded();
			}
		},10);
	}
	
	// IE?
	if(CLASMA.detect.ie)
	{
		// write last tag
		document.write("<script id='__ie_load' defer='defer' src='javascript:void(0)'></script>");

		// setup state change event
		$("__ie_load").onreadystatechange=function()
		{
			if(this.readyState=="complete")
				CLASMA.dom.oncontentloaded();
		}
	}
	// others
	window.onload=this.oncontentloaded;
},

// oncontentloaded
// Called when DOM is loaded

oncontentloaded:function()
{
	// already been called?
	if(!arguments.callee.done)
	{
		// no, flag it and start
		arguments.callee.done=true;

		var fn=window.ondomload;
		if(fn) fn();
	}
},

// addDomLoadEvent
// Call to add listener for dom load

addDomLoadEvent:function(fn)
{
	// remember old
	var pfn=window.ondomload;

	window.ondomload=function()
	{
		// call old and new
		if(pfn) pfn();
		fn();
	}
},

// addLoadEvent
// Call to add listener for load

addLoadEvent:function(fn)
{
	// remember old
	var pfn=window.onload;

	window.onload=function()
	{
		// call old and new
		if(pfn) pfn();
		fn();
	}
}

// Public end

}; }();

// Call dom loader

CLASMA.dom.triggerContentLoaded();
// framework.js - Framework library
// Copyright (c) 2008, Clasma Events Inc.

// Define namespace

CLASMA.namespace("CLASMA.framework");

// Define object

CLASMA.framework=function() {

// Class helpers

var cdd=CLASMA.detect;
var cd=CLASMA.dom;

// Private data

var hint="";

var printing=false;

// Private functions

// isExemptTag
// Call to check for exempt tags

var isExemptTag=function(e)
{
	// get tag name
	var n=e.tagName.toLowerCase();

	// select under safari exempt
	if(n=="select" && cdd.safari)
		return true;

	// text areas are exempt
	if(n=="textarea")
		return true;

	// input fields
	if(n=="input")
	{
		// of this type are exempt
		var t=e.getAttribute("type");

		if(t=="text" || t=="password")
			return true;
	}
	return false;
};

// Private end

return {

// Public data

helpApp:null,

// Keyboard codes

K_BREAK:3,
K_BS:8,
K_TAB:9,
K_RETURN:13,
K_SHIFT:16,
K_CTRL:17,
K_ALT:18,
K_PAUSE:19,
K_CAPSLOCK:20,
K_ESCAPE:27,
K_SPACE:32,
K_PREV:33,
K_NEXT:34,
K_END:35,
K_HOME:36,
K_LEFT:37,
K_UP:38,
K_RIGHT:39,
K_DOWN:40,
K_PRINT:44,
K_INSERT:45,
K_DELETE:46,
K_F1:112,
K_F2:113,
K_F3:114,
K_F4:115,
K_F5:116,
K_F6:117,
K_F7:118,
K_F8:119,
K_F9:120,
K_F10:121,
K_F11:122,
K_F12:123,
K_NUMLOCK:145,
K_SCROLL:145,

// Help functions

// help
// Call to open help window

help:function(chapter)
{
	// set help file
	var url="http://www.clasma.net/common/help/default.asp";
	var args="";

	// add application
	if(CLASMA.framework.helpApp)
		args+="a="+CLASMA.framework.helpApp;

	// add chapter
	if(chapter && chapter!=0)
	{
		if(args!="") args+="&";
		args+="c="+chapter;
	}

	if(args!="") url+="?"+args;

	// set window args
	var s="";

	s+="width=680,";
	s+="height=500,";
	s+="toolbar=no,";
	s+="menubar=no,";
	s+="scrollbars=no,";
	s+="status=no,";
	s+="resizable=yes,";
	s+="location=no,";
	s+="directories=no";

	// open window
	window.open(url,"CLASMA_help",s).focus();

	return false;
},

// Effect functions

// gradient
// Call to put gradient behind element

gradient:function(id,start,end,type)
{
	// resolve object
	var e=id?cd.getObject(id):cd.getBody();

	// use clasma colours?
	if(typeof start=="undefined") start="black";
	if(typeof end=="undefined") end="white";
	if(typeof type=="undefined") type="0";

	// only for explorer
	if(cdd.ie)
	{
		// put filter on element
		var a="startColorstr='"+start+"',endColorstr='"+end+"',gradientType='"+type+"'";
		e.style.filter="progid:DXImageTransform.Microsoft.Gradient("+a+")";
	}
},

// opacity
// Call to set element opacity

opacity:function(id,level)
{
	// resolve object
	var e=cd.getObject(id);

	// set default
	if(typeof level=="undefined") level=0.25;

	if(cdd.ie)
	{
		// put filter on element
		var a="Opacity='"+(level*100)+"',Style='0'";
		e.style.filter="progid:DXImageTransform.Microsoft.Alpha("+a+")";
	}
	else e.style.opacity=level;
},

// shadow
// Call to put shadow under element

shadow:function(id)
{
	// only for explorer
	if(cdd.ie)
	{
		// resolve object
		var e=id?cd.getObject(id):cd.getBody();

		// put filter on element
		var a="Color='#303030',Strength=3,Direction=135";
		e.style.filter="progid:DXImageTransform.Microsoft.Shadow("+a+")";
	}
},

// fade
// Call to fade element in or out

fade:function(id,from,to,duration)
{
	// get defaults
	if(typeof from=="undefined") from=1;
	if(typeof to=="undefined") to=0;
	if(typeof duration=="undefined") duration=250;

	// set initial timeout
	CLASMA.framework.onfadetimer(id,from,to,duration,0);
},

// Fade helpers

fadeIn:function(e) {CLASMA.framework.fade(e,0,1);},
fadeOut:function(e) {CLASMA.framework.fade(e);},

// Event functions

// getTarget
// Call to get target of event

getTarget:function(e)
{
	if(!e) e=event;
	return e.target?e.target:e.srcElement;
},

// getCoords
// Call to get event coordinates

getCoords:function(e)
{
	if(!e) e=event;
	return {left:e.clientX,top:e.clientY};
},

// getButtons
// Call to get button states

getButtons:function(e)
{
	if(!e) e=event;
	return e.button;
},

// getShift
// Call to get shift key state

getShift:function(e)
{
	if(!e) e=event;
	return e.shiftKey==1;
},

// getKey
// Call to get key of event

getKey:function(e)
{
	if(!e) e=event;
	return e.keyCode?e.keyCode:e.which;
},

// cancelBubble
// Call to cancel event bubble

cancelBubble:function(e)
{
	if(!e) e=event;

	if(e.stopPropagation) e.stopPropagation();
	if(cdd.ie) e.cancelBubble=true;
},

// cancelDefault
// Call to cancel default event action

cancelDefault:function(e)
{
	if(!e) e=event;

	if(e.preventDefault) e.preventDefault();
	if(cdd.ie) e.returnValue=false;
},

// Screen dimentions

getScreenWidth:function() {return screen.width;},
getScreenHeight:function() {return screen.height;},

// Client dimentions

getClientWidth:function() {return document.documentElement.clientWidth;},
getClientHeight:function() {return document.documentElement.clientHeight;},

// Scroll functions

// getScrollPos
// Return scrollbar positions

getScrollPos:function()
{
	var sp={top:0,left:0};

	// ie and firefox
	if(document.body && document.body.scrollTop)
	{
		sp.top=document.body.scrollTop;
		sp.left=document.body.scrollLeft;

		return sp;
	}

	// explorer 6
	if(document.documentElement && document.documentElement.scrollTop)
	{
		sp.top=document.documentElement.scrollTop;
		sp.left=document.documentElement.scrollLeft;

		return sp;
	}

	// netscape
	if(window.pageXOffset)
	{
		sp.top=window.pageYOffset;
		sp.left=window.pageXOffset;

		return sp;
	}

	return sp; 
},

// Cursor functions

// setCursor
// Call to set body cursor

setCursor:function(c)
{
	if(typeof c=="undefined" || !c) c="default";
	CLASMA.dom.getBody().style.cursor=c;
},

// Browser disable functions

// disableBrowser
// Call to disable unwanted functions

disableBrowser:function()
{
	// override context menu
	cd.addEvent(document,"contextmenu",CLASMA.framework.oncheckexempt);

	// override selection
	if(cdd.ie) cd.addEvent(document,"selectstart",CLASMA.framework.oncheckexempt);
	else
	{
		cd.addEvent(document,"mousedown",CLASMA.framework.onmousedown);
		cd.addEvent(document,"mouseup",CLASMA.framework.onmouseup);

		cd.addEvent(document,"dblclick",CLASMA.framework.ondblclick);
	}
},

// Framework events

// oncheckexempt
// Called to check exempt state

oncheckexempt:function(e)
{
	// get target and check tag
	var t=CLASMA.framework.getTarget(e);

	if(isExemptTag(t))
		return true;

	// remove anoying selection
	if(cdd.safari && window.getSelection)
	{
		var s=window.getSelection();
		if(s && s.removeAllRanges) s.removeAllRanges();
	}

	// cancel default action
	CLASMA.framework.cancelBubble(e);
	CLASMA.framework.cancelDefault(e);

	return false;
},

// onmousedown
// Called when mouse pressed

onmousedown:function(e)
{
	// firefox method?
	if(!cdd.ie)
	{
		// diable select if not exempt
		if(!CLASMA.framework.oncheckexempt(e))
			CLASMA.dom.getBody().style.MozUserSelect="none";

		return true;
	}
	return false;
},

// onmouseup
// Called when mouse released

onmouseup:function(e)
{
	// re-enable select
	if(!cdd.ie)
		CLASMA.dom.getBody().style.MozUserSelect="";

	return true;
},

// ondblclick
// Called when mouse double clicked

ondblclick:function(e)
{
	// element is exempt?
	if(!CLASMA.framework.oncheckexempt(e))
	{
		// remove document selection
		if(document.selection && document.selection.empty)
			document.selection.empty();

		// remove window selection
		if(window.getSelection)
		{
			var sel=window.getSelection();

			if(sel && sel.removeAllRanges)
				sel.removeAllRanges();
		}
	}
	return true;
},

// onenable
// Called to return true

onenable:function()
{
	// always return true
	return true;
},

// ondisable
// Called to return false

ondisable:function()
{
	// always return false
	return false;
},

// onfadetimer
// Called to process fade

onfadetimer:function(id,from,to,duration,time,callback)
{
	// resolve object
	var e=cd.getObject(id);

	// set opacity level
	var level=CLASMA.lang.tween(time,from,to,duration);
	CLASMA.framework.opacity(e,level);

	// show initial?
	if(time==0 && from==0)
		cd.setShow(e,true);

	// got there yet?
	if(time>=duration)
	{
		// hide after?
		if(to==0) cd.setShow(e,false);
		if(callback) callback();

		return;
	}

	// setup timer for next
	setTimeout(function(){CLASMA.framework.onfadetimer(id,from,to,duration,time+50);},50);
},

// onhintfocus
// Called when hint gets focus

onhintfocus:function(e)
{
	// reset value
	hint=e.value;
	e.value="";
},

// onhintblur
// Called when hint loses focus

onhintblur:function(e)
{
	// set value
	e.value=hint;
}

// Public end

}; }();
// ajax.js - Ajax service library
// Copyright (c) 2008, Clasma Events Inc.

// Define namespace

CLASMA.namespace("CLASMA.ajax");

// Define object

CLASMA.ajax=function() {

// Class helpers

var cdd=CLASMA.detect;

// Ajax message

var msg="<table cellspacing='0' cellpadding='0'><tr><td><img src='{img}' width='16' height='16' style='margin-right:4px'/></td><td style='white-space:nowrap'>{msg}</td></tr></table>";

// Session timeout

var timeout=0;
var timeoutUrl=0;

var timerId=null;

// Private functions

// createRequest
// Call to create XML Http object

var createRequest=function()
{
	var r;

	// create native object?
	try {r=new XMLHttpRequest();}
	catch(e)
	{
		// create for IE6 and above?
		try {r=new ActiveXObject("Microsoft.XMLHTTP");}
		catch(e)
		{
			if(cdd.ie) return null;
		    throw new Error('Ajax not supported.');
		}
	}
	return r;
};

// setMsg
// Call to display message

var setMsg=function(id,o)
{
	// set message response
	o.img=CLASMA.resPath+o.img;
	CLASMA.ajax.setResponse(id,msg.supplant(o));
};

// Private end

return {

// Public data

// Request methods

GET:"GET",
POST:"POST",
HEAD:"HEAD",

// Ready states

RS_UNINITIALIZED:0,
RS_LOADING:1,
RS_LOADED:2,
RS_INTERACTIVE:3,
RS_COMPLETED:4,

// Status codes

S_OFFLINE:0,
S_OK:200,
S_NOTFROUND:404,

// Security

user:null,
password:null,

// Frames fetch

frames:new Array,
framescb:new Array,

// Public functions

// Helper functions

isReady:function(r) {return r.readyState==this.RS_COMPLETED;},
isValid:function(r) {return r.status==this.S_OK;},

setWait:function(id) {setMsg(id,{img:"wait.gif",msg:"Requesting content..."});},
setError:function(id,err) {setMsg(id,{img:"error.gif",msg:err});},

// request
// Call to send request to server

request:function(url,method,args,callback,async)
{
	// ready params
	if(typeof method=="undefined" || !method) method=this.GET;
	if(typeof args=="undefined" || !args) args="";
	if(typeof async=="undefined") async=true;

	// create request object?
	var r=createRequest();

	if(r)
	{
		if(callback)
		{
			// set response handler
			r.onreadystatechange=function()
			{
				// request is ready?
				if(CLASMA.ajax.isReady(r))
				{
					// reset timeout and call callback
					CLASMA.ajax.resetSessionTimeout();
					callback(r);

				/*	r.onreadystatechange=null;
					r=null; */
				}
			}
		}
		// open request
		r.open(method,url,async,this.user,this.password);

		// set post header?
		if(method==this.POST)
			r.setRequestHeader("Content-Type","application/x-www-form-urlencoded");

		/* r.setRequestHeader("If-Modified-Since","Wed, 15 Nov 1995 00:00:00 GMT");*/

		// send request to server
		r.send(args);

		return r;
	}
	// try using frame
	return CLASMA.ajax.requestFrame(url,args,callback);
},

// include
// Call to request url and insert into tag

include:function(url,id,args,callback)
{
	// setup callback
	var cb=function(r)
	{
		// request status ok?
		if(CLASMA.ajax.isValid(r)) CLASMA.ajax.setResponse(id,r.responseText);
		else CLASMA.ajax.setError(id,"Ajax: #"+r.status+" "+r.statusText);

		// execute callback
		if(callback) callback(r);
	}

	// post request?
	try {this.request(url,this.POST,args,cb);}
	catch(e) {this.setError(id,e.message);}
},

// requestFrame
// Call to send request via frame

requestFrame:function(url,args,callback)
{
	// find free frame?
	for(var f=0;f<CLASMA.ajax.frames.length;f++)
		if(!CLASMA.ajax.frames[f]) break;

	// add args to url?
	if(args) url=url+"?"+args;

	// add frame element
	var e=document.createElement("<iframe id='XMLHTTP_frame"+f+"' src='"+url+"' style='display:none'></iframe>");
	document.body.appendChild(e);

	CLASMA.ajax.frames[f]=e;
	CLASMA.ajax.framescb[f]=callback;

	// check for reply
	setTimeout("CLASMA.ajax.checkFrame("+f+",2);",2);

	return null;
},

// checkFrame
// Call to check frame for reply

checkFrame:function(f,delay)
{
	// frame ready?
	var e=CLASMA.ajax.frames[f];

	if(e.readyState=="complete")
	{
		// reset session timeout
		CLASMA.ajax.resetSessionTimeout();

		var fid="XMLHTTP_frame"+f;

		// frame within frame needs to hold
		var d=document.frames[fid].document;
		var hold=(d.frames.length>0);

		// build result
		var r={};

		r.readyState=CLASMA.ajax.RS_COMPLETED;

		r.status=CLASMA.ajax.S_OK;
		r.statusText="";

		try
		{
			// get response and callback
			r.responseText=document.frames[fid].document.body.innerHTML;
			CLASMA.ajax.framescb[f](r);

			// remove frame element?
			if(!hold) e.parentNode.removeChild(e);
		}
		catch(e) {}

		// clear frame buffer
		CLASMA.ajax.frames[f]=null;
		CLASMA.ajax.framescb[f]=null;

		return;
	}
	
	// add delay and try again
	delay*=1.5;

	setTimeout("CLASMA.ajax.checkFrame("+f+","+delay+");",delay);
},

// setResponse
// Call to set request response

setResponse:function(id,s)
{
	// set element contents
	var e=$(id);
	if(e) e.innerHTML=s;
},

// Session timeout

// setSessionTimeout
// Call to set session timeout

setSessionTimeout:function(tm,url)
{
	// set timeout args
	timeout=tm;
	timeoutUrl=url;

	// start timeout
	CLASMA.ajax.resetSessionTimeout();
},

// resetSessionTimeout
// Call to reset session timeout

resetSessionTimeout:function()
{
	// clear old timer, set new
	if(timerId) clearTimeout(timerId);
	if(timeout>0) timerId=setTimeout(CLASMA.ajax.onsessiontimeout,timeout);
},

// onsessiontimeout
// Called by session timeout timer

onsessiontimeout:function()
{
	// Residrect to timeout url
	window.location=timeoutUrl;
}

// Public end

}; }();
// site.js - Site library
// Copyright (c) 2008, Clasma Events Inc.

// Define namespace

CLASMA.namespace("CLASMA.site");

// Define object

CLASMA.site=function() {

// Class helpers

var cdd=CLASMA.detect;
var cd=CLASMA.dom;
var cf=CLASMA.framework;
var ca=CLASMA.ajax;

// Private data

// Private functions

// pullContent
// Call to pull content from server

var pullContent=function(hash)
{
	// remove hash mark
	if(hash) hash=hash.replace(/#/g,"");

	// goto default?
	if(!hash || hash=="") hash="home";

	// has arguments?
	var args=null;

	if(hash.indexOf("_")!=-1)
	{
		// split argument
		var s=hash.split("_");

		hash=s[0];
		args="id="+escape(s[1]);
	}

	// is it a menu option?
	var a=CLASMA.site.menu.getOption(hash);
	CLASMA.site.menu.setCurrent(a);

	// pull content
	var url="content/"+hash+".asp";

	var callback=function(r) {window.scrollTo(0,0);};
	ca.include(url,"content",args,callback);
};

// Private end

return {

// Public data

// Public handlers

// onload
// Called on page load

onload:function()
{
	// initialize the history framework
	dhtmlHistory.initialize();
	dhtmlHistory.addListener(CLASMA.site.historyChange);

	// pull initial content
	pullContent(window.location.hash);
},

// Public functions

// historyChange
// Called when history changes

historyChange:function(hash,url)
{
	// pull from server
	pullContent(hash);
},

// pull
// Call to pull page from server

pull:function(a)
{
	// get hash value
	var hash=a.href;
	var n=hash.indexOf("#");

	if(n!=-1) hash=hash.substr(n);
	else hash=null;

	// add history and pull
	dhtmlHistory.add(hash,a.href);
	pullContent(hash);

	return true;
}

// Public end

}; }();

// create history object
window.dhtmlHistory.create(); /*{debugMode:true}*/

// initialise page
window.onload=CLASMA.site.onload;
// menu.js - Menu library
// Copyright (c) 2008, Clasma Events Inc.

// Define namespace

CLASMA.namespace("CLASMA.site.menu");

// Define object

CLASMA.site.menu=function() {

// Class helpers

var cd=CLASMA.dom;

// Private data

// Private functions

// Private end

return {

// Public data

// Public functions

// setCurrent
// Call to set current menu selection

setCurrent:function(a)
{
	// get current
	var n=this.getCurrent();

	// remove current, set new
	if(n) cd.setId(n,"");
	if(a) cd.setId(a.parentNode,"current");
},

// getCurrent
// Call to get current menu selection

getCurrent:function()
{
	// get current
	return $("current");
},

// getOption
// Call to find menu anchor from text

getOption:function(text)
{
	// use lowercase
	var t=text.toLowerCase();

	// run down menu options
	var a=cd.getElements("a","menu");

	for(var n=0;n<a.length;n++)
	{
		// found it?
		if(t==a[n].innerHTML.toLowerCase())
			return(a[n]);
	}
	return null;
}

// Public end

}; }();
