function ProtoInherit( cls ) {
	function Mediator(){}
	Mediator.prototype = cls.prototype;
	//Mediator.prototype.parent = new cls();
	return new Mediator;
}

Object.prototype.inheritFrom = function( objType, args ) {
	eval( "var obj = new "+objType+"();" );
	this.inheritInstance( obj, args );
}

Object.prototype.inheritInstance = function( obj, args ) {
	for( var p in obj ) {
		this[p] = obj[p];
	}
	for ( a in args ) {
		this[a] = args[a];
	}
}
Object.prototype.inherit = function( obj, args ) {
	if ( typeof obj == "object" ) {
		this.prototype = new obj();
	}
	else {
		this.prototype = new obj();
	}
	for ( a in args ) {
		this[a] = args[a];
	}
}

Object.prototype.toInt = function() {
	var i = parseInt( this );
	if ( i == "undefined" || isNaN( i ) || i === null ) {
		return 0;
	}
	return i;
}

Array.prototype.last = function() {
	return this[this.length-1];
}

Array.prototype.hasValue = function( value ) {
	var caseSensitive = arguments[1];
	for ( var i=0; i < this.length; i++ ) {
		if ( caseSensitive ) {
			if ( this[i] == value ) return true;
		}
		else {
			if ( this[i].toLowerCase() == value.toLowerCase() ) return true;
		}
	}
	return false;
}

String.prototype.trim = function() { 
	return this.replace(/^\s+|\s+$/g, ''); 
};

function CrossEvent( e ) {
	this.e = 		e;
	this.type = 	e.type;
	this.target = 	(e.target) ? e.target : e.srcElement;
	this.key = 		( e.keyCode ) ? e.keyCode : e.which
	this.e.dump = Object.prototype.dump;
	this.target.dump = Object.prototype.dump;
	
	this.altKey 	= e.altKey;
	this.shiftKey 	= e.shiftKey;
	this.ctrlKey 	= e.ctrlKey;
	
	this.clientX = e.clientX;
	this.clientY = e.clientY;

	this.stopPropagation = function() {
		if ( CrossDom.isFireFox ) {
			this.e.stopPropagation();
		}
		if ( CrossDom.idIE ) {
			this.e.cancelBubble = true;
		}
	}
	
	this.cancel = function() {
		if ( this.e.preventDefault ) {
			this.e.preventDefault()
		}
		else {
			this.e.returnValue = false;
		}
	}
}

/**
 * Provides cross browser DOM access.
 */
function _CrossDOM() {
	this.isExternal = false;
	if ( arguments[0] ) {
		this.document = arguments[0];
		this.isExternal = true;
	}
	else {
		this.document = window.document;
	}
	
	this.nav = navigator.userAgent.toLowerCase();
	this.isIE = (this.nav.indexOf("msie") != -1 && this.document.all);
	this.isFireFox = this.nav.indexOf("firefox") != -1;
	
	this.loadScript = function( url ) {
		var script = this.createElement( "SCRIPT", {src:url} );
		this.appendChild( this.getElementsByTagName( "HEAD" )[0], script );
	}
	
	this.getElementById = function( id ) {
		return this.document.getElementById( id );
	}
	
	this.createElement = function( type ) {
		var el = this.document.createElement( type );
		if ( arguments.length > 1 ) {
			var properties = arguments[1];
			for ( p in properties ) {
				if ( p == "style" ) {
					for ( s in properties[p] ) {
						el.style[s] = properties[p][s];
					}
				}
				else {
					el[p] = properties[p];
				}
			}
		}
		return el;
	}
	
	this.appendChild = function( parent, child ) {
		if ( parent && child ) {
			parent.appendChild( child );
		}
	}
	
	this.appendChildToBody = function( child ) {
		this.document.body.appendChild( child );
	}
	
	this.ancestorNodeOfType = function( child, nodeTagName ) {
		var node = child;
		while ( node && node.nodeName != nodeTagName ) {
			node = node.parentNode;
		}
			
		return node;
	}
	
	this.cloneNode = function( node, cloneChildren ) {
		return node.cloneNode(cloneChildren);
	}
	
	this.insertAtIndex = function( parent, child, index ) {
		var sibling = parent.childNodes[index];
		if ( ! sibling ) {
			this.appendChild( parent, child );
		}
		else {
			//alert( parent.tagName+" - "+sibling.tagName+" - "+child.tagName );
			parent.insertBefore( child, sibling );
		}
	}
	
	this.insertBefore = function( child, sibling ) {
		sibling.parentNode.insertBefore( child, sibling );
	}
	
	this.removeChild = function( parent, child ) {
		parent.removeChild( child );
	}
	
	this.removeNode = function( node ) {
		if ( arguments[1] != undefined ) {
			var removeChildren = arguments[1];
		}
		else {
			var removeChildren = true;
		}
		
		if ( node && node.removeNode ) {
			node.removeNode( removeChildren, removeChildren );
		}
		else if ( node && node.parentNode ) {
			if( removeChildren ) {
				this.removeChild( node.parentNode, node );
			}
			else {
				var range = document.createRange();
				range.selectNodeContents( node );
				node.parentNode.replaceChild( range.extractContents(), node );
			}
		}
	}
	
	this.getNodeIndex = function( parent, node ) {
		for ( var i=0; i < parent.childNodes.length; i++ ) {
			if ( parent.childNodes[i] == node ) {
				return i;
			}
		}
		return -1;
	}
	
	this.hasAsParent = function( child, parent ) {
		var c = child.parentElement;
		while (c) {
			if ( c = parent ) return true;
			c = c.parentElement;
		}
		return false;
	}
	
	this.getEvent = function ( e ) {
		var win = window;
		if ( this.isExternal ) {
			win = win.parent;
		}
		var evt = ( win.event ) ? win.event : e;
		return new CrossEvent( evt );
	}
	
	this.getWindowEvent = function ( win, e ) {
		var evt = ( win.event ) ? win.event : e;
		return new CrossEvent( evt );
	}
	
	this.addEvent = function( obj, evt, callback ) {
		if ( obj.addEventListener ) {
			obj.addEventListener( evt, callback, false );
		}
		else if ( obj.document.attachEvent ) {
			obj.attachEvent( "on"+evt, callback );
		}
		else {
			obj["on"+evt] = callback;
		}
	}
	
	this.absX = function(obj) {
		var curleft = 0;
		if ( obj && obj.offsetParent)
		{
			while (obj.offsetParent)
			{
				curleft += obj.offsetLeft
				obj = obj.offsetParent;
			}
		}
		else if (obj.x)
			curleft += obj.x;
		return curleft;
	}

	this.absY = function( obj ) {
		var curtop = 0;
		if ( obj.offsetParent)
		{
			while (obj.offsetParent)
			{
				curtop += obj.offsetTop
				obj = obj.offsetParent;
			}
		}
		else if (obj.y)
			curtop += obj.y;
		return curtop;
	}
}
var CrossDom = new _CrossDOM();
var CrossDom2 = new _CrossDOM();

function _Debugger() {
	var self = this;
	this._debugMode = false;
	this._debugWin = null;
	
	this.debugMode = function() {
		if ( this._debugMode ) return;
		window.moveTo( 0, 0 );
		window.resizeTo( screen.width-400, 845 );
		this._debugWin = window.open("","debugCanvas", "scrollbars=yes;scrollbars=1;toolbar=no,menubar=no,width=390,height=800,resizable=yes,left="+(screen.width-400)+",top=0");
		this._debugWin.document.open();
		this._debugMode = true; 
	}
	
	this.closeDebugger = function() {
		if ( self._debugWin ) {
			self._debugWin.close();
		}
	}
	
	this.write = function( str ) {
		if ( ! this._debugWin ) { return }
		this._debugWin.document.write( str + "<br>" );
		this._debugWin.document.body.scrollTop = 10000;
	}
	
	this.alert = function( msg ) {
		if ( ! confirm( msg ) ) {
			__STOP__;
		}
	}
	
	this.dump = function ( obj ) {
		if ( obj ) {
			var post_str = "";
			var w = window.open();
			w.document.open();
			for( var p in obj ) {
				if ( obj[p] ) {
					w.document.write( "<b>this."+p+"</b> = "+obj[p]+"<br>" );
				}
				else {
					post_str += "<b>this."+p+"</b> = "+obj[p]+"<br>";
				}
			}
			w.document.write( "<hr>"+post_str );
			w.document.close();
		}
		else {
			alert( "Cannot dump obj: "+obj );
		}
	}
	
}
Debugger = new _Debugger();
	
	
//window.onbeforeunload = this.closeDebugger;
var Debugger = new _Debugger();




var _loadedScripts = new Array();
function is_loaded( scriptsrc ) {
	var scripts = document.getElementsByTagName( "SCRIPT" );
	for( var i=0; i < scripts.length; i++ ) {
		if ( scripts[i].src == scriptsrc ) {
			return true;
		}
	}
	return false;
}

function include( scriptsrc ) {
	if ( ! is_loaded( scriptsrc ) ) {
		var script = document.createElement( "SCRIPT" );
		script.src = scriptsrc;
		var head = document.getElementsByTagName( "HEAD" );
		if( head.length > 0 ) {
			head[0].appendChild( script );
		}
	}	
}

// Encodes special characters
function myxml_fix(data) {
	data = data.replace( /&/g, "&amp;" );
	data = data.replace( />/g, "&gt;" );
	data = data.replace( /</g, "&lt;" );
	data = data.replace( /"/g, "&quot;" );
	return data;
}

// Decodes special characters
function myxml_defix(data) {
	data = data.replace( "&quot;","\"" );
	data = data.replace( "&gt;", "<" );
	data = data.replace( "&lt;", ">" );
	data = data.replace( "&amp;", "&" );
	return data;
}


function Event( method, owner ) {
	var args = arguments[2];
	
	return function( e ) {
		var evt = CrossDom.getEvent( e );
		if ( owner ) {
			owner[method]( evt, args );
		}
		else {
			method( evt, args );
		}
	}
}

function ColorComponents( hexColor ) {
	if ( hexColor.indexOf( "#" ) == 0 ) {
		hexColor = hexColor.substr( 1, 6 );
	}
	
	return {
		hexValue: hexColor,
		intValue: parseInt("0x"+hexColor),
		
		rInt: parseInt("0x"+hexColor.substr( 0, 2 )),
		gInt: parseInt("0x"+hexColor.substr( 2, 2 )),
		bInt: parseInt("0x"+hexColor.substr( 4, 2 )),
		 
		r: hexColor.substr( 0, 2 ),
		g: hexColor.substr( 2, 2 ),
		b: hexColor.substr( 4, 2 )
	}
}

if ( !window.showModalDialog ) {
	window.showModalDialog = function( url, dialogArguments, options ) {
		var optionTranslation = {
			dialogHeight: "height",
			dialogWidth: "width"
		}
		
		var newOptions = "";
		if ( options ) {
			var options = options.split( ";" );
			for ( var i=0; i < options.length; i++ ) {
				var pair = options[i].split( ":" );
				if ( pair.length == 2 ) {
					pair[0] = pair[0].trim();
					pair[1] = pair[1].trim();
					if ( optionTranslation[pair[0]] ) {
						newOptions += optionTranslation[pair[0]]+"="+pair[1]+", ";
					}
				}
			}
		}
		if ( newOptions == "" ) {
			newOptions = "width=432px, height=210px";
		}
		//newOptions = "";
		
		var modalWin = window.open( url, "", newOptions );
		modalWin.dialogArguments = dialogArguments;
	}
}
