<!--

$j = jQuery.noConflict();

function $p() {
	var a = arguments;
	if( a.length<1 ) return false;
	if( a.length==1 ) {
		var d = document.getElementById(a[0]);
		return (d==undefined?false:d);
	} 
	var r = [];
	for(var i=0;i<arguments.length;i++) {
		r[i]=document.getElementById(a[i]);
		if(r[i]==undefined)r[i]=false;
	}
	return r;
}

function imgfunc(imgname, filepath) {

	if (filepath){
		window.open(filepath + '/popup_image.php?path=' + imgname,'','scrollbars=no');
	} else {
		window.open('/popup_image.php?path=' + imgname,'','scrollbars=no');
	}
	
}

function addLoadEvent(func) {
  var oldonload = window.onload;
  if (typeof window.onload != 'function') {
    window.onload = func;
  } else {
    window.onload = function() {
      if (oldonload) {
        oldonload();
      }
      func();
    }
  }
}

function getElementsByClassName(theClass,d,c) {
  if(!document.hasChildNodes) return false;
   
  if(!c) var c = new Array();
  if(!d) var d = document.body;
  
  if(d.nodeType == 1 && d.className.match("^" + theClass + "$")) {
    c.push(d);
  }
  
  if(d.hasChildNodes()) {
    
    for(var i = 0; i < d.childNodes.length; i++) {
      getElementsByClassName(theClass,d.childNodes[i],c);
    }
    
    return c;
    
  } else {
    
    return c;
    
  }
}

   function detectFlash(swfName,swfID,flashVer,swfWidth,swfHeight,showErrMsg,paramList) {
      //detect Flash Player X - check the navigator.plugins array exists, IE for Windows will fail on this.

      var paramItms = embedItms = '';
         
      for (var a=0; a<paramList.length; a++) {
         paramItms += '<param name="' + paramList[a][0] + '" value="' + paramList[a][1] + '" />';
         embedItms += paramList[a][0] + '="' + paramList[a][1]+ '" ';
      }

      if(navigator.plugins.length) {
         //variable declarations
         var i;

         var xhtmlContent = '<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=' + flashVer + ',0,0,0" width="' + swfWidth + '" height="' + swfHeight + '" id="' + swfID + '" name="' + swfID + '" align="middle">' +
                            '<param name="movie" value="' + swfName + '" />' +
                            '<param name="allowScriptAccess" value="always" />' +
                            '<param name="quality" value="high" />' +
                            paramItms +
                            '<embed src="' + swfName + '" swLiveConnect="true" allowScriptAccess="always"' + embedItms + ' quality="high" width="' + swfWidth + '" height="' + swfHeight + '" name="' + swfID + '" align="middle" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" />' +
                            '</object>';

         var alternateContent = '<div id="errMsg"><p>This page requires Macromedia Flash Player ' + flashVer + ' or later.<br>Please visit <a href="http://www.macromedia.com/shockwave/download/download.cgi?P1_Prod_Version=ShockwaveFlash" target="_blank">macromedia.com</a> to download the latest plugin.</p></div>';

         //loop through all the plugins installed
         for (i=0; i < navigator.plugins.length; i++) {
            //put the plugin string in a variable
            var pluginIdent = navigator.plugins[i].description.split(" ");

            //The Flash Player identification string is ([] = the array index) [0]Shockwave [1]Flash [2]6.0 [3]r21
            //if Flash Player is detected, run this code.
            if(pluginIdent[0] == "Shockwave" && pluginIdent[1] == "Flash") {
               //set a toggle to show that some sort of Flash Player was found
               var isSwfEnabled = true;

               //an array of the Flash version number (major.minor)
               var versionArray = pluginIdent[2].split(".");

               if(versionArray[0] >= flashVer) {
                  //Minimum Flash Player version has been found, roll out the <object> tag.
                  document.write(xhtmlContent);
               } else if (showErrMsg) {
                  //Generate error message
                  document.write(alternateContent);
               }

               //need to break this loop as some browsers may have two versions installed
               //eg my Firebird release has r65 and r79 installed!
               break;
            }
         }

         //check if no Flash player was detected in the array (no Flash Player installed)
         if(!isSwfEnabled && showErrMsg) {document.write(alternateContent);}
      } else {
         //call vbscript for IE Win
         detectFlashIE(swfName,swfID,flashVer,swfWidth,swfHeight,showErrMsg,paramItms);
      }
   }



function noop() {}
dbg = function() { return false; }
function returntrue() {return true;}
function returnfalse() {return false;}
function def(element) {
	return (element==undefined ? false : true);
}
function danb(element) {
	return ( (def(element)) && element!="" ? true : false );
}
function danf(element) {
	return ( (def(element)) && element!=false ? true : false );
}
function dant(element) {
	return ( (def(element)) && element==false ? true : false );
}
el = function(id) { return $p(id); }

function isFunction( o ) {
	return (def(o) && typeof o == 'function');
}
function isString( o ) {
	return (def(o) && typeof o == 'string');
}
function isArray(testObject,force) {
    if 
	( 
		def(testObject) && 
		!(def(testObject.propertyIsEnumerable) && testObject.propertyIsEnumerable('length')) && 
		(typeof testObject === 'object') && 
		(typeof testObject.length === 'number')
	) { return true; }
	else { return false ; }
}
function isArray2( o ) {
  return ( !o || ( o.constructor && o.constructor.toString().indexOf("Array") == -1 ) ? false : true);
}
function isObject( o ){
	return (typeof(o) != 'undefined' && o != null && typeof(o) == 'object' && o.constructor == Object);
}
function foreach( arr, func ) {
	if( isArray( arr ) ) {
		foreachArray(arr,func);
	} else {
		foreachObject(arr,func);
	}
}
function foreachArray( a, f ) {
	if( !def(a) ) return dbg(f,'foreachArray sez, !a, but func');
	var l = a.length;
	if(l>0&&!def(a[l-1]))return dbg(f,'foreachArray Exception: is this in IE?  Calling this function');
	for(var i=0;i<l;i++) {
		f(i,a[i]);
	}
}
function foreachObject( o, f )
{
	if( !def(o) ) return dbg(f,'foreachObject sez, !o, but func');
	for(var x in o) {
		f(x,o[x]);
	}
}
function foreachNumber( n, f, sn )
{
	if( !def(n) || isNaN(n) ) return dbg(f,'foreachNumber sez, !n, but func or isNaN');
	if( !def(sn) ) sn = 0;
	for(var i=sn;i<n;i++) {
		f(i);
	}
}
var addEvent_counter = 1000;
function addEvent( element, type, func, eventName ){
	if(!element||!danb(type)||!isFunction(func))return false;
	if(!danb(eventName))eventName='event'+addEvent_counter++;
	if(type.indexOf('on')==0)type=type.substr(2);
	if(!element.events)element.events={};
	if(!element.events[type])element.events[type]={};
	element.events[type][eventName] = func;
	element['on'+type] = fireEvent.bind(this,element,type);
	return eventName;
}
function fireEvent( element, type, e ){
	var returnValue;
	for(var eventName in element.events[type]){
		returnValue = element.events[type][eventName](e);
	}
	return returnValue;
}
function removeEvent( element, type, eventName ){
	if(!element||!danb(type))return false;
	if(type.indexOf('on')==0)type=type.substr(2);
	if(!element.events||!element.events[type])return false;
	if( danb(eventName) ) {
		delete element.events[type][eventName];
	} else {
		element.events[type]={};
	}
	return true;
}
function addLoadEvent(func) {
	return addEvent( window, 'load', func );
  var oldonload = window.onload;
  if (typeof window.onload != 'function') {
    window.onload = func;
  } else {
    window.onload = function() {
      if (oldonload) {
        oldonload();
      }
      func();
    }
  }
}
var count=0;
function deepObjectIsEqual(o1,o2,maxdepth,depth)
{
	if( !def(maxdepth) ) maxdepth=3;
	if( !def(depth) ) depth=0;
	if( depth>=maxdepth ) return true;
	for(var x in o1) {
	
		if( !def(o2[x]) ) return false;
	
		if(o1[x]!=o2[x]) {
			return false;
		} else if( ( ( def(o1[x].length)&&def(o2[x].length)) || (typeof(o1[x])=='object'&&typeof(o2[x])=='object') ) && !(isFunction(o1[x]||isFunction(o2[x])) ) ) {
			if(!deepObjectIsEqual(o1[x],o2[x],maxdepth,depth+1))return false;
		}
	}
	for(var x in o2) {
		if( !def(o1[x]) ) return false;
	}
	return true;
}
function deepObjectIsEqual2(o1,o2,s)
{
	var eq=true;
	foreachObject(o1,function(n,v){
		if( eq ) {
			dbg( def(o2[n]),n );
			if( def(o2[n]) ) {
				if( def(v.length) || isObject(v) ) {
					eq=deepObjectIsEqual(n,o2[n]);
				} else if( v!=o2[n] ) {
					eq=false;
					return;
				}
			} else {
				dbg('so here');
				eq=false;
				dbg(eq,'equal');
				return;
			}
		}
	});
	if( !s && eq ) {
		eq = deepObjectIsEqual(o2,o1,1);
	}
	return eq;
}
function deepObjectCopy(dupeObj) {
	var retObj = new Object();
	if (dupeObj&&typeof(dupeObj) == 'object') {
		if (typeof(dupeObj.length) != 'undefined')
			var retObj = new Array();
		for (var objInd in dupeObj) {
			if (typeof(dupeObj[objInd]) == 'object') {
				retObj[objInd] = deepObjectCopy(dupeObj[objInd]);
			} else if (typeof(dupeObj[objInd]) == 'string') {
				retObj[objInd] = dupeObj[objInd];
			} else if (typeof(dupeObj[objInd]) == 'number') {
				retObj[objInd] = dupeObj[objInd];
			} else if (typeof(dupeObj[objInd]) == 'boolean') {
				((dupeObj[objInd] == true) ? retObj[objInd] = true : retObj[objInd] = false);
			}
		}
	}
	return retObj;
}
if (!Array.prototype.indexOf)
{
  Array.prototype.indexOf = function(elt )
  {
    var len = this.length;
    var from = Number(arguments[1]) || 0;
    from = (from < 0)
         ? Math.ceil(from)
         : Math.floor(from);
    if (from < 0)
      from += len;
    for (; from < len; from++)
    {
      if (from in this &&
          this[from] === elt)
        return from;
    }
    return -1;
  };
}
Array.prototype.pushAt = function( i, v ) {
	if( i>=0 ) {
		var indx = this.length;
		while(1) {
			if(indx==i)return this[indx] = v;
			this[indx] = this[--indx];
		}
	}
}
String.prototype.replaceAll = function( reg, withWhat ) {
	var count = 0;
	var s = this;
	while( s.match(reg) ) {
		if( count++>1000 ) {
			try{
				dbg('thrown exception: caught inf_loop ('+reg+' into '+withWhat+')');				
			}catch(e){}
			return s;
		}
		s = s.replace(reg,withWhat);
	}
	return s;
}
var $A = function(iterable) {
  if (!iterable) return [];
  if (iterable.toArray) {
    return iterable.toArray();
  } else {
    var results = [];
    for (var i = 0; i < iterable.length; i++)
      results.push(iterable[i]);
    return results;
  }
}
Function.prototype.bind = function() {
  var __method = this, args = $A(arguments), object = args.shift();
  return function() {
    return __method.apply(object, args.concat($A(arguments)));
  }
}
String.prototype.pad = function(w,n)
{
	var c = n-(''+this).length;
	var nv = this;
	for( ; c>0 ; c-- ){
		nv=w+nv;
	}
	return nv;
}
__rootCreate = crind = function(){
	var a=arguments,o=this;
	for(var i=0;i<a.length;i++) {
		if(o[a[i]]==undefined||!isObject(o[a[i]]))o[a[i]]={};
		o=o[a[i]];
	}
}
EventObject = function(e) {
	if(!e) var e = window.event;
	//dbg(e.type,'event type');
  
	this.evnt = e;
	this.mouseCoords;
	this.target;
	this.mouseWheel;
	this.keyCode;
	this.keyCodeChar;
	
	var me = this;
	
	this.getTarget = function() {
		if( def(me.target) ) return me.target;
		var targ;
		if(me.evnt.target) targ = me.evnt.target;
		else if(me.evnt.srcElement) targ = me.evnt.srcElement;
		if(targ.nodeType == 3) // defeat safari bug
		    targ = targ.parentNode;
		me.target = targ;
		return me.target;
	}
	
	this.getMouseWheel = function() {
		if( def(me.mouseWheel) ) return me.mouseWheel;

		var mpos=this.getMouseCoords();
		var d=0;
		if(mme.evnt.evnt.wheelDelta) { // ie/opera
			d=(me.evnt.wheelDelta>0)?1:-1;
			if(window.opera)
				d=-d;
		} else if(me.evnt.detail) { // mozilla
			d=(me.evnt.delta>0)?-1:1;
		}
		if(me.evnt.preventDefault)
			me.evnt.preventDefault();
		me.evnt.returnValue=true;
		
		me.mouseWheel = d;
		return me.mouseWheel;
	}	

	this.getMouseCoords = function() {
		if( def(me.mouseCoords) ) return me.mouseCoords;

		var evmposx=0;
		var evmposy=0;
		if(me.evnt.pageX||me.evnt.pageY) {
			evmposx=me.evnt.pageX;
			evmposy=me.evnt.pageY;
		}
		else if(me.evnt.clientX||me.evnt.clientY) {
			evmposx=me.evnt.clientX+document.body.scrollLeft+document.documentElement.scrollLeft;
			evmposy=me.evnt.clientY+document.body.scrollTop+document.documentElement.scrollTop;
		}
		
		me.mouseCoords = [evmposx,evmposy];
		return me.mouseCoords;
	}
	
	this.getKeyCode = function() {
		if( def(me.keyCode) ) return me.keyCode;
		//dbg(me.evnt.keyCode,'keycode');
		//dbg(me.evnt.charCode,'charcode');
		me.keyCode = me.evnt.charCode || me.evnt.keyCode;
		//dbg(me.keyCode,'returned keycode');
		if(User.getBrowser()=='Safari'&&User.getOS()=='Mac'){
			// mac safari: 63233(down) and 63232(up)
			if(me.keyCode==63233)me.keyCode=40;
			else if(me.keyCode==63232)me.keyCode=38;
			else if(me.keyCode==63276)me.keyCode=33;
			else if(me.keyCode==63277)me.keyCode=34;
		}
		return me.keyCode;
	}
	
	this.preventDefault = function() {
		if(me.evnt.preventDefault)me.evnt.preventDefault();
		else if(window.event)window.event.returnValue=false;
	}
	
	this.stopPropagation = function() {
		if(me.evnt.stopPropagation)me.evnt.stopPropagation();
		else if(window.event)window.event.cancelBubble=true;
	}

	this.stopprop = function() {
		me.preventDefault();
		me.stopPropagation();
		return false;
	}
}
PHP = 
{
	trim: function( str, charList )
	{
		return PHP.ltrim( PHP.rtrim( str, charList ), charList );
	},
	
	ltrim: function( str, charList )
	{
		if( def(charList) ) {
			str = str.replace( new RegExp('^['+charList+']+') ,'');
		} else {
			str = str.replace( /^[\s\t\n\r\0\x0B]+/, '' );
		}
		return str;
	},
	
	rtrim: function( str, charList )
	{
		if( def(charList) ) {
			str = str.replace( new RegExp('['+charList+']+$') ,'');
		} else {
			str = str.replace( /^[\s\t\n\r\0\x0B]+/, '' );
		}
		return str;
	},
	
	in_array: function( needle, haystack )
	{
		var len = this.length;
		for ( var x = 0 ; x <= len ; x++ ) {
			if ( this[x] == obj ) return true;
		}
		return false;
	}
}
Number = 
{
	getRandom: function( low, high )
	{
		return low+Math.floor(Math.random()*(high-low+1));
	}
}
var OO =
{
	extend: function( extendThis, usingThis )
	{
		extendThis = extendThis || {};
		if( usingThis ) {
			if( isFunction(usingThis) ) {
				usingThis = new usingThis();
			} else if( def(OO.Class.Objects[usingThis]) ) {
				usingThis = OO.Class.instance(usingThis);
			} else {
				dbg(usingThis,'Extender not found for '+extendThis);
			}
		}
		for(var x in usingThis) {
			extendThis[x]=usingThis[x];
		}
		return extendThis;
	},
	
	Class:
	{
		Counter: 1000,
		
		Objects:
		{
			ClassPrototype: 
			{
				extenders:[],
				implementors:[],
				body: function( className )
				{
					this.getClassName = function() { return this.__CLASS__; }
					this.instanceOf = function( testClassName ) { return OO.Class.doesClassXExtendClassY( this.getClassName(), testClassName ); }
					this.__construct = function(){}
				}
			}
		},
		doesClassXExtendClassY: function( x, y )
		{
			if(x==y)return true;
			if(def(OO.Class.Objects[x])) {
				var m=false;
				foreachObject(OO.Class.Objects[x].extenders,function(n,v){
					if(v==y)m=true;
					if(!m&&def(OO.Class.Objects[v])){
						foreachObject(OO.Class.Objects[v].extenders,function(n2,v2){
							m=OO.Class.doesClassXExtendClassY(v2,y);
							if(m)return;
						});
					}
				});
				if(m)return true;
			}
			return false;
		},
		
		replaceVar: function( classFunction, privateOrProtected, replaceThis, withThis )
		{
			return classFunction.replaceAll('this.'+privateOrProtected+'_'+replaceThis,withThis).replaceAll('this.'+replaceThis,withThis);
		},
		
		define: function( className, classFunction )
		{
			var vars = {
				'private': {},
				'protected': {}
			};
			classFunction = new String(classFunction);
			var m = classFunction.match(/\bthis\.(protected|private)_([a-z_]+)\b/);
			var count = 0;
			while( m ) {
				var newVarName = 'this.vz'+OO.Class.Counter++;
				vars[ m[1] ][ m[2] ] = newVarName;
				if(0) {
					classFunction = classFunction.replaceAll(m[0],newVarName);
					classFunction = classFunction.replaceAll('this.'+m[2],newVarName);
				} else {
					classFunction = OO.Class.replaceVar( classFunction, m[1], m[2], newVarName );
				}
 				m = classFunction.match(/\bthis\.(protected|private)_([a-z_]+)\b/);
				if(count++>1000)return ('infite loop '+m[0]+' and '+newVarName);
			}
		
			
			var funcname = 'func'+OO.Class.Counter++;
			window.parent.eval('window["'+funcname+'"] = '+classFunction);
			classFunction = window[funcname];
			
			OO.Class.Objects[ className ] = 
			{
				vars: deepObjectCopy(vars),
				body: classFunction,
				extenders: [],
				implementors: []
			}
			
			return new ( function(className) {
				this.className = className;
				
				this.extend = function() {
					foreachArray($A(arguments),function(i,x){
						OO.Class.Objects[className].extenders.push( x );
						if( !isFunction(x) && def(OO.Class.Objects[x]) ) {
							foreachObject(OO.Class.Objects[x].vars.protected,function(n,v){
								OO.Class.Objects[className].vars.protected[n]=v;
								var funcname = 'func'+OO.Class.Counter++;
								var classFunction = OO.Class.replaceVar( new String(OO.Class.Objects[className].body),'protected',n,v);
								window.parent.eval('window["'+funcname+'"] = '+classFunction);
								OO.Class.Objects[className].body = window[funcname];
							});
						}
					});
				
				}
				
				this.implement = function() {
					foreachArray($A(arguments),function(i,x){
						OO.Class.Objects[className].implementors.push( x );
					});
				}
			} ) ( className );
		},
		
		instance: function()
		{
			var args = $A(arguments), className = args.shift();
			if( !def(OO.Class.Objects[className]) ) return dbg(className,'Class not found');
			var object = new OO.Class.Objects.ClassPrototype.body( className );
			foreachArray(OO.Class.Objects[className].extenders,function(i,x){
				object = OO.extend(object,x);
			});
			object = OO.extend(object,OO.Class.Objects[className].body);
			object.__construct.apply( object, args.concat($A(args)) );
			object.__CLASS__ = className;
			return object;
		}
	}
}
Observer = function() 
{
	this.observers = [];
	
	this.attach = function( obj ) 
	{
		this.observers.push( obj );
	}
	
	this.detach = function( obj ) 
	{
		for(var i=0;i<this.observers.length;i++) {
			if( this.observers[i] == obj ) {
				return this.observers[i].splice( i, 1 );
			}
		}
	}
	
	this.notify = function( arg ) 
	{
		for(var i=0;i<this.observers.length;i++) {
			this.observers[i].update( arg );
		}
	}
	
	this.update = function( args )
	{
	}
}
OO.Class.define('Observer',function() {
	this.private_observers = [];
	
	this.attach = function( obj ) 
	{
		this.observers.push( obj );
	}
	
	this.detach = function( obj ) 
	{
		for(var i=0;i<this.observers.length;i++) {
			if( this.observers[i] == obj ) {
				return this.observers.splice( i, 1 );
			}
		}
		return false;
	}
	
	this.notify = function( arg ) 
	{
	
		for(var i=0;i<this.observers.length;i++) {
			if( !def(this.observers[i].update) ) dbg('Observer does not have update method');
			else this.observers[i].update( arg );
		}
	}
	
	this.update = function()
	{
	}
});
OO.Class.define('View',function(){
	this.protected_element;
	this.protected_data;
	this.protected_parent;
	this.protected_leftSibling;
	this.protected_rightSibling;
	this.protected_pTypeName = '';
	this.protected_autoViewId = true;
	
	this.setViewId = function( id )
	{
		if( def(this.element) && def(newData.id) ) { 
			this.element.id = 'View_'+this.getClassName()+'_'+id;
		}
	}
	
	this.getData = function() { return this.data; }
	this.setData = function(o) { this.data = o; }
	
	this.getAutoViewId = function() { return this.autoViewId; }
	this.setAutoViewId = function(o) { this.autoViewId = o; }
	
	this.getElement = function() { return this.element; }
	this.setElement = function(o) { this.element= o; }
	
	this.getParent = function() { return this.parent; }
	this.setParent = function(o) { this.parent = o; }
	
	this.getLeftSibling = function() { return this.leftSibling; }
	this.setLeftSibling = function(o) { this.leftSibling = o; }
	
	this.getRightSibling = function() { return this.rightSibling; }
	this.setRightSibling = function(o) { this.rightSibling = o; }
	
	this.update = function( newData )
	{
	
		this.preUpdate( newData );
		
		if( !def(newData) ) {
			this.preClear();
			this.setData( newData );
			this.clear();
			this.postClear();
			
		} else if( !def(this.element) || !def(this.data) ) {
			this.preDraw();
			this.setData( newData );
			this.draw();
			this.postDraw();
			
		} else {
			this.preRedraw();
			this.setData( newData );
			this.redraw();
			this.postRedraw();
		}
		if( this.autoViewId ) {
			this.setViewId( newData.id );
		}
		
		this.postUpdate();
	}
	
	this.destroy = function()
	{
		this.removeElement();
		this.update = noop;
		this.notify = noop;
	}
	
	this.removeElement = function()
	{
		if( def(this.element) && def(this.element.parentNode) ) {
			DOM.remove( this.element );
		}
		this.element = undefined;
	}
	
	this.clear = function()
	{
		DOM.hide( this.element );
	}
	
	this.draw = function()
	{
		this.renderElement();
		if( def(this.element) ) {
			if( def(this.parent) ) {
				DOM.insert( this.element ).inside( this.parent );
				DOM.show( this.element );
			} else if ( def(this.leftSibling) ) {
				DOM.insert( this.element ).after( this.leftSibling );
			} else if ( def(this.rightSibling) ) {
				DOM.insert( this.element ).before( this.rightSibling );
			}
		} else if( !def(this.parent) && !def(this.leftSibling) && !def(this.rightSibling) ) {
			dbg('No element, parent or siblings.','View '+this.getClassName());
		}
	}
	
	this.redraw = function()
	{
		if( def(this.parent) || def(this.leftSibling) || def(this.rightSibling) ) {
			var oldElement = this.element;
			this.renderElement();
			if( def(this.element) && def(oldElement) ) {
				DOM.insert( this.element ).after( oldElement );
			}
			DOM.remove( oldElement );
		} else {
			this.renderElement();
		}
	}
	
	this.__construct = function(o)
	{
		if( !def(o) ) return;
		if( def(o.parent) ) this.setParent(o.parent);
		if( def(o.leftSibling) ) this.setLeftSibling(o.leftSibling);
		if( def(o.rightSibling) ) this.setRightSibling(o.rightSibling);
		if( def(o.element) ) this.setElement(o.element);
		if( def(o.pTypeName) ) this.pTypeName = o.pTypeName;
		if( def(o.autoViewId) ) this.autoViewId = o.autoViewId;
		this.initialize( o );
		if( def(o.data) ) {
			this.update(o.data);
		}
	}
	this.initialize = noop;
	this.renderElement = noop;
	this.preUpdate = noop;
	this.postUpdate = noop;
	this.preClear = noop;
	this.postClear = noop;
	this.preDraw = noop;
	this.postDraw = noop;
	this.preRedraw = noop;
	this.postRedraw = noop;
	
}).extend('Observer');
var xDate = 
{
	JANUARY: 1,
	FEBRUARY: 2,
	MARCH: 3,
	APRIL: 4,
	MAY: 5,
	JUNE: 6,
	JULY: 7,
	AUGUST: 8,
	SEPTEMBER: 9,
	OCTOBER: 10,
	NOVEMBER: 11,
	DECEMBER: 12,
	
	SUNDAY: 0,
	MONDAY: 1,
	TUESDAY: 2,
	WEDNESDAY: 3,
	THURSDAY: 4,
	FRIDAY: 5,
	SATURDAY: 6,
	
	parseYear: function( year )
	{
		if( def(year) ) {
			year = parseInt( year, 10 );
			if( isNaN( year ) ) return false;
			if( year>=1900 && year<=3000 )return year;
		}
		return false;
	},
	
	parseMonth: function( month )
	{
		if( def(month) ) {
			month = parseInt( month, 10 );
			if( isNaN( month ) ) return false;
			if( month>0 && month<13 )return month;
		}
		return false;
	},
	
	getStartDayOfMonth: function( year, month )
	{
		return (new Date( year, month-1, 1 )).getDay();
	},
	
	getNumberOfDaysInMonth: function( year, month )
	{
		var numberOfDays = false;
		var x = xDate;
		
		year = xDate.parseYear( year );
		month = xDate.parseMonth( month );
		
		if( year && month ) {
			if( month==x.SEPTEMBER || month==x.APRIL || month==x.JUNE || month==x.NOVEMBER ) {
				numberOfDays = 30;
				
			} else if( month==x.FEBRUARY ) {
				if( year%4==0 ) {
					numberOfDays = 29;
				} else {
					numberOfDays = 28;
				}
				
			} else {
				numberOfDays = 31;
			}
		}
		return numberOfDays;
	},
	
	difference: function( date1, date2 )
	{
		return Math.round((date1.valueOf() - date2.valueOf()) / 86400000);
	}
};
var User = 
{
	Browser: '',
	OS: '',
	Version: '',
	
	getBrowser: function()
	{
		return User.Browser;
	},
	
	getOS: function()
	{
		return User.OS;
	},
	
	getVersion: function()
	{
		return User.Version;
	},
	
	
	getInnerWidth: function() 
	{
		var x,y;
		if (self.innerHeight)
		{
			x = self.innerWidth;
			y = self.innerHeight;
		}
		else if (document.documentElement && document.documentElement.clientHeight)
		
		{
			x = document.documentElement.clientWidth;
			y = document.documentElement.clientHeight;
		}
		else if (document.body)
		{
			x = document.body.clientWidth;
			y = document.body.clientHeight;
		}
		return [x,y];
	},
	
	getScrollOffset: function() 
	{
		var x,y;
		if (self.pageYOffset)
		{
			x = self.pageXOffset;
			y = self.pageYOffset;
		}
		else if (document.documentElement && document.documentElement.scrollTop)
		
		{
			x = document.documentElement.scrollLeft;
			y = document.documentElement.scrollTop;
		}
		else if (document.body)
		{
			x = document.body.scrollLeft;
			y = document.body.scrollTop;
		}
		return [x,y];
	},
	
	getPageHeight2: function() 
	{
		var x,y;
		var test1 = document.body.scrollHeight;
		var test2 = document.body.offsetHeight
		if (test1 > test2)
		{
			x = document.body.scrollWidth;
			y = document.body.scrollHeight;
		}
		else
		    
		{
			x = document.body.offsetWidth;
			y = document.body.offsetHeight;
		}
		return [x,y];
	},
	
	getPageHeight:function() 
	{
	
		var ph;
	
		if( window.innerHeight!=undefined && window.scrollMaxY!=undefined ) 
		{
			ph = [
				window.innerWidth + window.scrollMaxX,
				window.innerHeight + window.scrollMaxY
			];
		}
		else if( document.body.scrollHeight > document.body.offsetHeight )
		{
			ph = [
				document.body.scrollWidth,
				document.body.scrollHeight
			];
		}
		else
		{ 
			ph = [
				document.body.offsetWidth + document.body.offsetLeft, 
				document.body.offsetHeight + document.body.offsetTop 
			];
		}
		return ph;
	},	
	
	init: function()
	{
		if( def(this.inited) ) return;
		this.inited = 1;
		
		var BrowserDetect = function() 
		{
			this.searchString = function (data) 
			{
				for (var i=0;i<data.length;i++)	{
					var dataString = data[i].string;
					var dataProp = data[i].prop;
					this.versionSearchString = data[i].versionSearch || data[i].identity;
					if (dataString) {
						if (dataString.indexOf(data[i].subString) != -1)
							return data[i].identity;
					}
					else if (dataProp)
						return data[i].identity;
				}
			}
			this.searchVersion = function (dataString) 
			{
				var index = dataString.indexOf(this.versionSearchString);
				if (index == -1) return;
				return parseFloat(dataString.substring(index+this.versionSearchString.length+1));
			}
			this.dataBrowser = 
			[
				{ 	string: navigator.userAgent,
					subString: "OmniWeb",
					versionSearch: "OmniWeb/",
					identity: "OmniWeb"
				},
				{
					string: navigator.vendor,
					subString: "Apple",
					identity: "Safari"
				},
				{
					prop: window.opera,
					identity: "Opera"
				},
				{
					string: navigator.vendor,
					subString: "iCab",
					identity: "iCab"
				},
				{
					string: navigator.vendor,
					subString: "KDE",
					identity: "Konqueror"
				},
				{
					string: navigator.userAgent,
					subString: "Firefox",
					identity: "Firefox"
				},
				{
					string: navigator.vendor,
					subString: "Camino",
					identity: "Camino"
				},
				{	
					string: navigator.userAgent,
					subString: "Netscape",
					identity: "Netscape"
				},
				{
					string: navigator.userAgent,
					subString: "MSIE",
					identity: "Explorer",
					versionSearch: "MSIE"
				},
				{
					string: navigator.userAgent,
					subString: "Gecko",
					identity: "Mozilla",
					versionSearch: "rv"
				},
				{ 	
					string: navigator.userAgent,
					subString: "Mozilla",
					identity: "Netscape",
					versionSearch: "Mozilla"
				}
			]
			this.dataOS = 
			[
				{
					string: navigator.platform,
					subString: "Win",
					identity: "Windows"
				},
				{
					string: navigator.platform,
					subString: "Mac",
					identity: "Mac"
				},
				{
					string: navigator.platform,
					subString: "Linux",
					identity: "Linux"
				}
			]
			this.init = function () 
			{
				this.b = this.browser = this.searchString(this.dataBrowser) || "An unknown browser";
				this.v = this.version = this.searchVersion(navigator.userAgent)
					|| this.searchVersion(navigator.appVersion)
					|| "an unknown version";
				this.os = this.o = this.OS = this.searchString(this.dataOS) || "an unknown OS";
			}
			this.init();
		};
		var bd = new BrowserDetect();
		User.Browser = bd.b;
		User.isIE = ( User.Browser == 'Explorer' ? function() { return true; } : function() { return false; } );  
		User.OS= bd.o; 
		User.Version = bd.v; 
	}
}
User.init();
__rootCreate('Data','Store');
OO.extend(Data.Store,
{
	Simple: function( initialObjects )
	{
		this.values = {};
		
		this.set = function(n,v)
		{
			this.values[n] = v;
			return v;
		}
		
		this.get = function(n)
		{
			if( this.values[n]!=undefined ) {
				return this.values[n];
			} else {
				return false;
			}
		}
		
		this.getKey = function(v)
		{
			for(var x in this.values){
				if( this.values[x]==v ) {
					return x;
				}
			}
			return false;
		}
		
		this.getKeys = function(v)
		{
			var r = [];
			for(var x in this.values){
				r.push(x);
			}
			return r;
		}
		
		this.clear = function()
		{
			for(var x in this.values) {
				delete this.values[x];
			}
			this.values= {};
		}
		
		this.del = this.remove = function(n)
		{
			var r = '';
			if( this.values[n]!=undefined ) {
				r=this.values[n]
				delete this.values[n];
			}
			return r;
		}
		
		this.count = this.size = function()
		{
			var count = 0;
			for(var x in this.values) {
				count++;
			}
			return count;
		}
		
		this.getAssociativeArray = function()
		{
			var r = {};
			for(var x in this.values) {
				r[x] = this.values[x];
			}
			return r;
		}
		
		this.foreach = function( func ) 
		{
			return foreachObject( this.values, func );
		}
		
		this.__construct = function( initialObjects )
		{
			if( isObject(initialObjects) ) {
				for(var x in initialObjects) {
					this.set(x,initialObjects[x]);
				}
			}
			dbg('Use the OO.version');
		}
		
		this.__construct( initialObjects );
	}
});
OO.Class.define('Data_Store_Simple',function(){
	this.values = {};
	
	this.set = function(n,v)
	{
		this.values[n] = v;
		return v;
	}
	
	this.get = function(n)
	{
		if( this.values[n]!=undefined ) {
			return this.values[n];
		} else {
			return false;
		}
	}
	
	this.clear = function()
	{
		for(var x in this.values) {
			delete this.values[x];
		}
		this.values= {};
	}
	
	this.del = this.remove = function(n)
	{
		var r = '';
		if( this.values[n]!=undefined ) {
			r=this.values[n]
			delete this.values[n];
		}
		return r;
	}
	
	this.getKey = function(v)
	{
		for(var x in this.values){
			if( this.values[x]==v ) {
				return x;
			}
		}
		return false;
	}
	
	this.getKeys = function(v)
	{
		var r = [];
		for(var x in this.values){
			r.push(x);
		}
		return r;
	}
	
	this.count = this.size = function()
	{
		var count = 0;
		for(var x in this.values) {
			count++;
		}
		return count;
	}
	
	this.getAssociativeArray = function()
	{
		var r = {};
		for(var x in this.values) {
			r[x] = this.values[x];
		}
		return r;
	}
	
	this.foreach = function( func ) 
	{
		return foreachObject( this.values, func );
	}
	
	this.__construct = function( initialObjects )
	{
		if( isObject(initialObjects) ) {
			for(var x in initialObjects) {
				this.set(x,initialObjects[x]);
			}
		}
	}
});
var	DOM = 
{
	Objects:
	{
	},
	
	Class:
	{
		AddRemoveObject: function()
		{
			this.addList = OO.Class.instance('Data_Store_Simple');
			this.removeList = OO.Class.instance('Data_Store_Simple');
			
			this.to = function( element )
			{
				if( !element || !element.className ) return dbg('DOM.Class.AddRemoveObject sez, !element');
				var classArray = element.className.split(/\s+/);
				var classes = new OO.Class.instance('Data_Store_Simple');
				foreachArray( classArray, function(i,v){
					classes.set(v,true);
				});
				foreachArray( this.addList.getKeys(), function(i,v){
					classes.set(v,true);
				});
				foreachArray( this.removeList.getKeys(), function(i,v){
					classes.remove(v,true);
				});
				element.className = classes.getKeys().join(" ");
			}
		},
		
		add: function()
		{
			var o = new DOM.Class.AddRemoveObject();
			for(var i=0;i<arguments.length;i++) {
				o.addList.set( arguments[i], true );
			}
			return o;
		},
		
		remove: function()
		{
			var o = new DOM.Class.AddRemoveObject();
			for(var i=0;i<arguments.length;i++) {
				o.removeList.set( arguments[i], true );
			}
			return o;
		},
		
		hide: function( className )
		{
		},
		
		matching: function( className, parent, tagName )
		{
			var regex = new RegExp( '(^|\s+)'+className+'(\s+|$)' );
			if( !def(parent) || parent=='body' ) parent=DOM.getBody();
			var elements = parent.getElementsByTagName( tagName );
			var r = [], m;
			foreachArray( elements, function(i,n){
				if( danb(n.className) ) {
					m = n.className.match(regex);
					if( m ) {
						m.splice(1,1);
						m.splice(m.length-1,1);
						r.push({
							match: deepObjectCopy(m),
							element: n
						});
					}
				}
			});
			return r;
		} 
	},
	
	Radio:
	{
		get2: function( form, name )
		{
			return DOM.find({
				parent:form,
				tagName:'input',
				attribute:'name',
				string:name,
				elementOnly:true
			});
		},
		
		get: function( form, name )
		{
			var matching = false, radios = DOM.find({
				parent:form,
				tagName:'input',
				attribute:'type',
				string:'radio',
				elementOnly:true
			});
			
			if( radios ) {
				foreachArray( radios, function(i,radio){
					if( radio.name == name ) {
						if( !def(matching.length) ) {
							matching = [];
						}
						matching.push(radio);
					}
				});
			}
			
			return matching;
		},
		
	
		getSelectedIndex: function( formOrRadioArray, name )
		{
			var arr = false;
			if( danb(name) ) {
				arr = DOM.Radio.get( formOrRadioArray, name );
			} else {
				arr = formOrRadioArray;
			}
			var selectedIndex = -1;
			if( arr ){
				foreachArray( arr, function(i,radio){
					if( radio.checked ) {
						selectedIndex = i;
						return;
					}
				}); 
			}
			return selectedIndex;
		},
		
	
		getSelectedValue: function( formOrRadioArray, name )
		{
			var arr = false;
			if( danb(name) ) {
				arr = DOM.Radio.get( formOrRadioArray, name );
			} else {
				arr = formOrRadioArray;
			}
			var selectedValue = false;
			if( arr ){
				foreachArray( arr, function(i,radio){
					if( radio.checked ) {
						selectedValue = radio.value;
						return;
					}
				}); 
			}
			return selectedValue;
		},
		
	
		setSelectedIndex: function( index, formOrRadioArray, name )
		{
			var arr = false;
			if( danb(name) ) {
				arr = DOM.Radio.get( formOrRadioArray, name );
			} else {
				arr = formOrRadioArray;
			}
			var success = false;
			if( arr ){
				foreachArray( arr, function(i,radio){
					if( i==index ) {
						radio.checked = true;
						success = true;
					} else {
						radio.checked = false;
					}
				}); 
			}
			return success;
		},
		
	
		addEvent: function( type, func, formOrRadioArray, name )
		{
			var arr = false;
			if( danb(name) ) {
				arr = DOM.Radio.get( formOrRadioArray, name );
			} else {
				arr = formOrRadioArray;
			}
			if( arr ) {
				foreachArray( arr, function(i,radio){
					addEvent( radio, type, func );
				});
				return true;
			} else {
				return false;
			}
		}
	},
		
	getContainingId2: function( element, regex ) 
	{
		var m;
		while( def(element) && def(element.id) ) {
			m = element.id.match(regex);
			if( m ) {
				return m;
			}
			element = element.parentNode;
		}
		return false;
	},
	
	reverseFind: function(o)
	{
		if(!def(o.element))return false;
		if(danb(o.attr))o.attribute=o.attr;
		if(o.attribute=='class')o.attribute='className';
		if(danb(o.tag))o.tagName=o.tag;
		if(!danb(o.tagName))o.tagName='*';
		if(!def(o.elementOnly))o.elementOnly=false;
		
		var n = o.element;
		var regex = false;
		var string = false;
		
		if( danb(o.regex) ) regex = new RegExp( '(^|\\s+)'+o.regex+'(\\s+|$)' );
		else if( danb(o.string) ) string = o.string;
		
		var m = false;
		
		while( def(n) ) {
			if( regex ) { 
				m = n[ o.attribute ].match( regex );
				if( m ) {
					m.splice(1,1);
					m.splice(m.length-1,1);
					if( o.elementOnly ) {
						return n; 
					} else {
						return {
							match: deepObjectCopy(m),
							element: n
						};
					}
				}
			} else if( string ) {
				m = (new String( n[ o.attribute ] )).indexOf(string);
				if( m>=0 ) {
					if( o.elementOnly ) {
						return n;
					} else {
						return {
							index: m,
							element: n
						};
					}
				}
			}
			n = n.parentNode;
		}
		return false;
	},
	/*
		DOM.find({
		
			string: 'string to match'
			  OR
			regex: 'regex pattern'
			
		
			parent: DOM.get('elment')
			attribute: 'className'
			tagName: 'div' 	
			elementOnly: true||false
								
		}); 
	*/	
	find: function(o)
	{
		if(!def(o.parent)||o.parent=='body')o.parent=DOM.getBody();
		if(danb(o.attr))o.attribute=o.attr;
		if(o.attribute=='class')o.attribute='className';
		if(danb(o.tag))o.tagName=o.tag;
		if(!danb(o.tagName))o.tagName='*';
		if(!def(o.elementOnly))o.elementOnly=false;
		
		var regex = false;
		var string = false;
		
		if( danb(o.regex) ) regex = new RegExp( '(^|\\s+)'+o.regex+'(\\s+|$)' );
		else if( danb(o.string) ) string = o.string;
	
		var elements = o.parent.getElementsByTagName( o.tagName );
		var r = [], m, n, i;
		for(i=0;i<elements.length;i++) {
			n=elements[i];
			if( danb(o.attribute) ) {
				if( danb( n[ o.attribute ] ) ) {
					if( regex ) { 
						m = n[ o.attribute ].match( regex );
						if( m ) {
							m.splice(1,1);
							m.splice(m.length-1,1);
							if( o.elementOnly ) {
								r.push(n);
							} else {
								r.push({
									match: deepObjectCopy(m),
									element: n
								});
							}
						}
					} else if( string ) {
						m = (new String( n[ o.attribute ] )).indexOf(string);
						if( m>=0 ) {
							if( o.elementOnly ) {
								r.push(n);
							} else {
								r.push({
									index: m,
									element: n
								});
							}
						}
					}
				}
			} else {
				if( o.elementOnly ) {
					r.push( n );
				} else {
					r.push({
						element: n
					});
				}
			}
		}
	
		return r;
	},
	
	findFirst: function(o)
	{
		var elements = DOM.find(o), element = false;
		if( elements && def(elements.length) && elements.length > 0 ) {
			if( def(elements[0].element) ) {
				element = elements[0].element;
			} else {
				element = elements[0];
			}
		}
		return element;
	},
	
	getBody: function()
	{
		return document.getElementsByTagName('body')[0];
	},
		
	register: function( niceName, html ) 
	{
		var element;
		if( isString( html ) ) {
			element = $p( html );
		} else {
			element = html;
		}
		DOM.Objects[ niceName ] = element;
		if( !def(element) ) element=false;
		return element;
	},
	
	get: function( niceName )
	{
		if( niceName=='body' ){
			return DOM.getBody();
		} else if( def(DOM.Objects[ niceName ]) ) {
			return DOM.Objects[ niceName ];
		}
		return $p( niceName );
		
		
		if( 1 || !def(DOM.Objects[ niceName ]) ) {
			DOM.Objects[ niceName ] = $p( niceName );
		
		}
		return DOM.Objects[ niceName ];
	},
			
	getElement: function( element ) {
		if( !def(element) || !element ) {
			return false;
		} else if( isString( element ) ) {
			return DOM.get( element );
		} else if ( def(element.nodeName) ) {
			return element;
		}
		return false;
	},
	
	className: function( className, elementType )
	{
		if( !def(elementType) ) var elementType = '*';
		var elements = DOM.getElementsByClassName(document,elementType,className);
		
		elements.hide = function()
		{
			for(var i=0;i<this.length;i++) {
				DOM.hide( this[i] );
			}
		}
		
		return elements;
	},
	
	hideClass: function( className, elementType )
	{
		if( !def(elementType) ) var elementType = '*';
		var elements = DOM.getElementsByClassName(document,elementType,className);
		for(var i=0;i<elements.length;i++) {
			DOM.hide( elements[i] );
		}
	},
	
	/*
		Written by Jonathan Snook, http://www.snook.ca/jonathan
		Add-ons by Robert Nyman, http://www.robertnyman.com
	*/
	getElementsByClassName: function(oElm, strTagName, strClassName)
	{
		if( oElm=='body' ) oElm=document.getElementsByTagName('body');
		var arrElements = (strTagName == "*" && oElm.all)? oElm.all : oElm.getElementsByTagName(strTagName);
		var arrReturnElements = new Array();
		strClassName = strClassName.replace(/\-/g, "\\-");
		var oRegExp = new RegExp("(^|\\s)" + strClassName + "(\\s|$)");
		var oElement;
		for(var i=0; i<arrElements.length; i++){
			oElement = arrElements[i];
			if(oRegExp.test(oElement.className)){
				arrReturnElements.push(oElement);
			}
		}
		return (arrReturnElements)
	},
	
	getElementsByClassName2: function(theClass,d,c) 
	{
		if(!document.hasChildNodes) return false;
		if(!c) var c = new Array();
		if(!d) var d = document.body;
		if(d.nodeType == 1 && d.className.match("^" + theClass + "$")) {
			c.push(d);
		}
		if(d.hasChildNodes()) {
			for(var i = 0; i < d.childNodes.length; i++) {
				DOM.getElementsByClassName(theClass,d.childNodes[i],c);
			}
			return c;
		} else {
			return c;
		}
	},
	removeAllChildren: function( element ) 
	{
		element = DOM.getElement( element );
		if( !def(element) || !def(element.childNodes) ) return;
		while( element.childNodes.length>0 ) {
			element.removeChild( element.childNodes[0] );
		}
	},
		
	insertAfter: function(newChild, refChild) 
	{ 
		refChild.parentNode.insertBefore(newChild,refChild.nextSibling); 
	},
	
	insertBefore: function(newChild, refChild) 
	{ 
		refChild.parentNode.insertBefore(newChild,refChild); 
	},
	
	insert: function( element ) 
	{
		return new ( function(element) {
			this.element = element;
			
			this.before = function( refElement ) {
				refElement = DOM.getElement( refElement );
				if( !refElement ) return false;
				refElement.parentNode.insertBefore( this.element, refElement ); 
				
				return true;
			}
			
			this.after = function( refElement ) {
				refElement = DOM.getElement( refElement );
				if( !refElement ) return false;
				
				refElement.parentNode.insertBefore( this.element, refElement.nextSibling ); 
				
				return true;
			}
		
			this.first = function( refElement ) {
				refElement = DOM.getElement( refElement );
				if( !refElement ) return false;
				
				if( refElement.hasChildNodes ) {
				
					refElement.insertBefore( this.element, refElement.childNodes[0] );
				} else {
					refElement.appendChild( this.element );
				}
				
				return true;
			}
			
			this.inside = this.into = function( refElement ) {
				refElement = DOM.getElement( refElement );
				if( !refElement ) return false;
				
				refElement.appendChild( this.element );
				
				return true;
			}
		} ) ( element );
	},
	
	remove: function( element )
	{
		element = DOM.getElement( element );
		if( !element || !element.parentNode ) return false;
		element.parentNode.removeChild( element );
		return true;
	},
	
	del: function( element )
	{
		return DOM.remove( element );
	},
	
	ElementDisplayTypes: 
	{
		'TBODY':'table-row-group',
		'TABLE':'table',
		'LI':'list-item',
		'A':'inline', 
		'SPAN':'inline' 
	},
	
	hide: function( element )
	{
		element = DOM.getElement( element );
		if( !element || !def(element.style) ) return false;
		element.style.visibility="hidden";
		element.style.display='none';
		return true;
	},
	
	softhide: function( element )
	{
		element = DOM.getElement( element );
		if( !element || !def(element.style) ) return false;
		element.style.visibility="hidden";
		return true;
	},
	
	show: function( element, display )
	{
		element = DOM.getElement( element );
		if( !element || !def(element.style) ) return false;
	
		if(display==undefined) {
			if( def(DOM.ElementDisplayTypes[element.nodeName]) ) {
			
				display = DOM.ElementDisplayTypes[element.nodeName];  
			} else {
				display='block';
			}
		
		}
		element.style.visibility="visible";
		element.style.display=display;
		return true;
	},
	
	findPos: function(obj) 
	{
	
		var curleft = curtop = 0;
		if (obj.offsetParent) {
			while (true) {
				curleft += obj.offsetLeft;
				curtop += obj.offsetTop;
				if(!obj.offsetParent)
				  break;
				obj = obj.offsetParent;
			}
		} 
		
		return [curleft,curtop];
	},
	
	getStyle: function(x,styleProp) 
	{
		
		if (x.currentStyle) {
			styleProp=styleProp.replace(/-([a-z])/g, function(t,a){return a.toUpperCase()} );
			return x.currentStyle[styleProp];
		} else if (window.getComputedStyle) {
			return document.defaultView.getComputedStyle(x,null).getPropertyValue(styleProp);
		}
	},
	
	getBoundary: function( element )
	{
		element = DOM.getElement( element );
		
		var boundary = [0,0,0,0];
		
		if( element && def(element.style) ) {
			var pos = DOM.findPos( element );
			boundary[0] = pos[0];
			boundary[1] = pos[1];
			boundary[2] = pos[0]+DOM.getRealWidth(element);
			boundary[3] = pos[1]+DOM.getRealHeight(element);
		}
		
		return boundary;
	},
	
	doesXcontainY: function( outerX, innerY )
	{
	
		return ( innerY[0]>=outerX[0] && innerY[2]<=outerX[2] && innerY[1]>=outerX[1] && innerY[3]<=outerX[3] );	
	},
	
	getRealWidth: function(el) 
	{
		el = DOM.getElement(el);
		return el.offsetWidth+parseInt(0+DOM.getStyle(el,'margin-left'),10)+parseInt(0+DOM.getStyle(el,'margin-right'),10);
	},
	
	getRealHeight: function(el) 
	{
		el = DOM.getElement(el);
		return el.offsetHeight+parseInt(0+DOM.getStyle(el,'margin-top'),10)+parseInt(0+DOM.getStyle(el,'margin-bottom'),10);
	},
	
	getDims: function(el) 
	{
		el = DOM.getElement(el);
		return [ DOM.getRealWidth(el), DOM.getRealHeight(el) ];
	},
		
	getContainingID: function( element, regex ) 
	{
		var m = false;
		while( def(element) && def(element.id) ) {
			var m = element.id.match(regex);
			if( m ) {
				return m;
			}
			element = element.parentNode;
		}
		return m;
	},
		
	getContainingId: function( element, regex ) 
	{
		var m;
		while( def(element) && def(element.id) ) {
			m = element.id.match(regex);
			if( m ) {
				return m;
			}
			element = element.parentNode;
		}
		return false;
	},
	
	getContaining: function( element, regex )
	{
	},
	
	nextSibling: function( element )
	{
		var sibling = element.nextSibling;
		while( sibling ) {
			if( sibling.nodeName != '#text' ) return sibling;
			sibling = sibling.nextSibling;
		}
		return false;
	},
	
	previousSibling: function( element )
	{
		var sibling = element.previousSibling;
		while( sibling ) {
			if( sibling.nodeName != '#text' ) return sibling;
			sibling = sibling.previousSibling;
		}
		return false;
	},
	
	create: function( obj, parent, recursive )
	{
		parent = DOM.getElement(parent);
		
		if( def(obj.className) ) obj['class'] = obj.className;
		
		if( !def(recursive) ) this.vars = {};
		var d;
		if( def(obj.t) ) {
			obj.t = obj.t.toLowerCase();
		
			var isInput = (obj.t=='input'||obj.t=='option'||obj.t=='textarea');
			if( User.isIE() && isInput ) {
				var inputstring = "<"+obj.t;
				if( def(obj.name) ) {	inputstring+=" name=\""+obj.name+"\"";	}
				if( def(obj.value) ) { inputstring+=" value=\""+obj.value+"\"";	}
				if( def(obj.type) ) { inputstring+=" type=\""+obj.type+"\"";	}
				inputstring+=">";
				d = document.createElement( inputstring );
			} else {
				d = document.createElement( obj.t );
			}
			for(var objx in obj) {
				if( objx=='t' || ( User.isIE() && isInput && (objx=='name' || objx=='value' || objx=='type') ) ) {
				
				} else if( objx=='style' ) {
					DOM.stylize( d, obj[objx] );
				} else if( objx=='options' ) {
					for(var obji=0;obji<obj[objx].length;obji++) {
						if(def(obj[objx][obji]['el'])){
							d.appendChild(obj[objx][obji].el);
						} else if(def(obj[objx][obji]['element'])){
							d.appendChild(obj[objx][obji].element);
						} else {
							obj[objx][obji]['t'] = 'option';
							DOM.create(obj[objx][obji], d, 1 );
						}
					}
				} else if( objx=='kids' ) {
					for(var obji=0;obji<obj[objx].length;obji++) {
						if(def(obj[objx][obji]['el'])){
							d.appendChild(obj[objx][obji].el);
						} else if(def(obj[objx][obji]['element'])){
							d.appendChild(obj[objx][obji].element);
						} else {
							DOM.create( obj[objx][obji], d, 1 );
						}
					}
				} else if( objx=='text' ) {
					d.appendChild( document.createTextNode( obj[objx] ) );
				} else if( objx.indexOf('on') == 0 ) {
					if( typeof obj[objx] == 'string' ) {
						var old = obj[objx];
						d[objx] = function() { try{eval(old)}catch(e){dbg(e)} } 
					} else {
						d[objx] = obj[objx];
					}
				} else if( objx=='variable' ) {
					this.vars[ obj[objx] ] = d;
				} else {
					d.setAttribute( objx, obj[objx] );
				}
			}
		} else if( def(obj.text) ) {
			d = document.createTextNode( obj.text );
			if( def(obj.variable) ) {
				this.vars[ obj['variable'] ] = d;
			}
		}
		if( def(d) && parent ) {
			try {
				parent.appendChild( d );
			} catch(e) {
				foreachObject(e,function(n,v){dbg(v,n);});
			} 
		}
		if( !def(recursive) ) {
			if( def(d.nodeName) && d.nodeName!='#text' ) {
				if( !def(d.vars) ) {
					d['vars'] = {}; 
				}
				for(var x in this.vars) {
					d.vars[x] = this.vars[x];
				}
			}
		}
		return d;
	},
	crel: function(type,id,parent,styles) 
	{
	
		/*
			return creTree({
				t:type,
				id:id,
				href:( def(styles.href) ? styles.href : undefined ),
				style:styles
			}, parent );
		
		*/
		var d = document.createElement(type);
	
	
	
		d.style.visibility='hidden';
	
		if(parent!=undefined&&parent=='body') {
			parent = document.getElementsByTagName('body')[0];
		}
		
		if(id!=undefined) {
			d.id = id;
		}
		
		if(parent!=undefined && parent.appendChild)parent.appendChild(d);
		
		d.style.visibility='visible';
		
		if(styles!=undefined){
		
		
		
		
			if( type.toLowerCase()=='a' && def(styles['href']) ) {
				d.setAttribute('href',styles['href']);
			}
			DOM.stylize(d,styles);
		}
		return d;
	},
	
	stylize: function(element,styles) 
	{
		element = DOM.getElement( element );
		if( !element ) return;
		for(var x in styles) {
			if(x=='className'||x=='src'){
				element[x]=styles[x];
			} else if(x=='colSpan'||x=='href') {
				element.setAttribute(x,styles[x]);
			} else if(x=='cursor') {
				DOM.setCursor(element,styles[x])
			} else if(x=='opacity') {
				DOM.setOpacity( element, styles[x] );
			} else if(x=='text') {
				element.appendChild( document.createTextNode(styles[x]) );
			} else if( x.indexOf('on') == 0 ) {
				element[x] = styles[x];
			} else {
				try{
				element.style[x] = styles[x];
				}catch(e) { alert('DOM.stylize ('+x+' == '+styles[x]+') '+e); }
			}
		}
	},
	
	setCursor: function (el,cursor) 
	{
		if(el==undefined)return;
		try{
			el.style.cursor=cursor;
		} catch(e) {
			try{
				el.style.cursor='default';
			}catch(f) {
			
			}
		}
	},
	
	setOpacity: function(el,n) 
	{
		if(el==""||el==undefined||el.style==undefined)return;
		el.style.filter = "alpha(opacity="+n+")";
		el.style.opacity=''+(n/100);
	}
	
};
DOM['creTree'] = DOM.create; 
var Html =
{
	Extended: 
	{
		create: function( o, p )
		{
			var domObj = DOM.create( o, p );
			if( domObj ) {
				Html.extend( domObj );
			}
			return domObj;
		}
		
	},
	
	extend: function( element )
	{
		var instanceName = false;
		
		if( !def(element) ) return dbg('!def element, html.extend');
		
		if( def(element.nodeName) ) {
			var nn = element.nodeName;
			if( nn=='INPUT' ) {
				if( def(element.type) ) {
					var t = element.type;
					if( t=='text' || t=='hidden' || t=='password' || t=='reset' || t=='submit' || t=='button' ) { 
						instanceName = 'Html_Element_Input';
					} else if( t=='checkbox' ) {
						instanceName = 'Html_Element_Input_Checkable';
					}
				}
			} else if( nn=='TEXTAREA' ) {
				instanceName = 'Html_Element_Input_Textarea';
			} else if( nn=='SELECT' ) {
				instanceName = 'Html_Element_Input_Select';
			} else if( nn=='OPTION' ) {
				instanceName = 'Html_Element_Input_Selectable';
			} else if( nn=='BUTTON' ) {
				instanceName = 'Html_Element_Input';
			}
		}
		if( instanceName ) {
		
			return OO.Class.instance( instanceName, {element:element} );
		} else if( element.type=='radio' ) {
			return;
		}
		
		return dbg(element+ ' (nodeName:'+element.nodeName + ' and type:'+element.type+')','Could not get instanceName');
	}
};
OO.Class.define('Html_Element',function(){
	this.options = {};
	this.element = false;
	
	this.getElement = function() { return this.element; }
	this.setElement = function(element) { 
		this.element=element;
	
		this.element.extended = this; 
	}
	
	this.getId = function() { return this.element.id; }
	this.setId = function(n) { this.element.id = n; }
	
	this.initialize = noop;
	
	this.__construct = function(o)
	{
		if( def(o) ) {
			this.options = o;
			if( def(o.element) ) this.setElement( o.element );
		}
		this.initialize();
	}
});
OO.Class.define('Html_Element_Input_Select',function() {
	
	this.prepend = function( option )
	{
		this.insert( option, 0 );
	}
	
	this.append = function( option )
	{
		this.insert( option );
	}
	
	this.insert = function( option, index )
	{
		if( !def(index) || isNaN( parseInt( index, 10 ) ) ) {
			var index = this.getLength();
		}
		if( index<0 ) index=0;
		
		if( !def(option.getElement) && !def(option.extended) ) {
			Html.extend( option );
		}
		if( option && def(option.extended) ) {
			if( index >= this.getLength() ) {
				DOM.insert( option ).inside( this.element );
			} else {
				DOM.insert( option ).before( this.element.options[index] );
			}
		}
	}
	
	this.select = function( index )
	{
		var option = this.getOption( index );
		if( option ) {
			option.selected = true;
		}
	}
	
	this.deselect = function( index )
	{
		var option = this.getOption( index );
		if( option ) {
			option.selected = false;
		}
	}
	
	this.selectAll = function()
	{
		foreachArray( this.element.options, function(i,option){
			option.selected = true;
		});
	}
	
	this.deselectAll = function()
	{
		foreachArray( this.element.options, function(i,option){
			option.selected = false;
		});
	}
	this.empty = this.clear = function()
	{
		this.element.options.length = 0;
	}
	this.getLength = function()
	{
		return this.element.options.length;
	}
	
	this.setSize = function(b) { this.element.setAttribute('size',b); }
	this.getSize = function() { return this.element.getAttribute('size'); }
	
	this.setMultiple = function(b) { this.element.multiple = b;	}
	this.isMultiple = function() { return this.element.multiple; }
	
	this.setIndex = function( index )
	{
		if( def(index) && index>=0 && index<this.element.options.length ) {
			this.element.selectedIndex = index;
		}
	}
	
	this.setIndices = function( indices )
	{
		var option;
		foreachArray(indices, function(i,index){
			option = this.getOptionElement( index );
			if( option ) {
				option.selected = true;
			}
		}.bind(this));
	}
	
	this.getSelected = function()
	{
		var selected = false;
		if( this.isMultiple() ) {
			foreachArray( this.element.options, function(i,option){
				if( option.selected ) {
					if( !selected ) {
						selected = [];
					}
					selected.push( OO.Class.instance('Html_Element_Input_Selectable',{element:option} ) );
				}
			});
		} else {
			var option = this.getOptionElement( this.element.selectedIndex );
			if( option ) {
				selected = OO.Class.instance('Html_Element_Input_Selectable',{element:option} );
			}
		}
		return selected;
	}
	
	this.getSelectedValues = this.getSelectedValue = function()
	{
		var selected = false;
		if( this.isMultiple() ) {
			foreachArray( this.element.options, function(i,option){
				if( option.selected ) {
					if( !selected ) {
						selected = [];
					}
					selected.push( option.value );
				}
			});
		} else {
			selected = this.getValue( this.element.selectedIndex );
		}
		return selected;
	}
	
	this.getSelectedText = function()
	{
		var selected = false;
		if( this.isMultiple() ) {
			foreachArray( this.element.options, function(i,option){
				if( option.selected ) {
					if( !selected ) {
						selected = [];
					}
					selected.push( option.text );
				}
			});
		} else {
			selected = this.getText( this.element.selectedIndex );
		}
		return selected;
	}
	
	this.getText = function( index )
	{
		var option = this.getOptionElement( index );
		if( option ) {
			return option.text;
		}
		return false;
	}
	this.setValue = function( value ) {
		var index = -1;
		foreachArray( this.element.options, function(i,option){
			if( index<0 && option.value==value ) {
				index = i;
				return;
			}
		});
		this.setIndex( index );
	}
	
	this.getValue = function( index )
	{
		var option = this.getOptionElement( index );
		if( option ) {
			return option.value;
		}
		return false;
	}
	
	this.getOptionElement = function( index )
	{
		if( !def(index) ) return false;
		if( def(index) && index>=0 && index<this.element.options.length ) {
			return this.element.options[ index ];
		}
		return false;
	}
	
	this.getOption = function( index )
	{
		var option = this.getOptionElement( index );
		if( option ) {
			OO.Class.instance('Html_Element_Input_Selectable',{element:option} );
		}
		return option;
	}
	
}).extend('Html_Element_Input');
OO.Class.define('View_Html_Element_Select',function(){
	
	this.setValue = function( value ) 
	{
		if( !def(this.element.extended) ) {
			Html.extend( this.element ); 
		}
		
		if( !def(this.element.extended) ) return dbg(this.element,'cannot extend');
		
		this.element.extended.setValue( value );
	}
	
	this.renderElement = function()
	{
		this.setValue( this.data );
	}
	
	this.getValue = function()
	{
		return this.element.extended.getSelectedValue();
	}
	
	this.onChange = function()
	{
		this.notify( this.getValue() );		
	}
	
	this.initialize = function()
	{
		if( def(this.element) ) {
			Html.extend( this.element );
		}
		
		addEvent( this.element, 'change', this.onChange.bind(this) );
		this.childInitialize();
	}
	
	this.childInitialize = noop;
	
}).extend('View');
OO.Class.define('View_Date_Chooser_Day',function(){
	
	this.oldMonth = false;
	this.oldYear = false;
	
	this.renderElement = function()
	{
		//alert(this.data.year + ' : '+this.data.month + ' : '+this.data.day);
		if( def(this.data.month) && (this.data.month != this.oldMonth || this.data.year != this.oldYear) ) {
			var numberOfDays = xDate.getNumberOfDaysInMonth( this.data.year, this.data.month );
			DOM.removeAllChildren( this.element );
			for(var i=0;i<numberOfDays;i++) {
				DOM.create({
					t:'option',
					value:i+1,
					text:i+1
				},this.element);
			}
			
			this.oldMonth = this.data.month;
			this.oldYear = this.data.year;
		}
		this.setValue( this.data.day );
	}
	
}).extend('View_Html_Element_Select');
OO.Class.define('View_Advance',function(){
	this.private_element1 = false;
	this.private_element2 = false;
	this.private_validator = returnfalse;
	
	this.setElement1 = function(element)
	{
		this.element1 = DOM.getElement( element );
		this.element1.onkeyup = this.onevent.bind(this);
	}
	
	this.setElement2 = function(element)
	{
		this.element2 = DOM.getElement( element );
	}
	
	this.setValidator = function(validator)
	{
		if( !isFunction(validator) ) return dbg('Not a valid validator');
		this.validator = validator;
	}
	
	this.onevent = function(e)
	{
		var eo = new EventObject(e);
		if( eo.getKeyCode()>46 || eo.getKeyCode()==32 ) {
			this.check();
		}
	}
	
	this.check = function()
	{
		if( !danf(this.element2) || !def(this.element2.focus) ) return dbg('no element2');
		
		if( this.validator( this.element1.value, this.element1 ) ) {
			this.element2.focus();
		} 
	}
	
	this.__construct = function(o)
	{
		if( def(o) ) {
			if( def(o.element1) ) this.setElement1( o.element1 );
			if( def(o.element2) ) this.setElement2( o.element2 );
			if( def(o.validator) ) this.setValidator( o.validator );
		}
	}
});
OO.Class.define('View_Date_Chooser',function(){
	this.year = false;
	this.month = false;
	this.day = false;
	this.getYear = function()
	{
		return ( this.year ? this.year.getValue() : false );
	}
	this.getMonth = function()
	{
		return ( this.month ? this.month.getValue() : false );
	}
	this.getDay = function()
	{
		return ( this.day ? this.day.getValue() : false );
	}
	
	this.setDate = function(y,m,d) 
	{
		if( def(y) ) this.setYear(y);
		if( def(m) ) this.setMonth(m);
		if( def(d) ) this.setDay(d);
		this.update();
	}
	
	this.setYear = function(d) 
	{
		if( this.year ) {
			this.year.update( d );
		}		
	}
	
	this.setMonth = function(d) 
	{
		if( this.month ) {
			this.month.update( d );
		}		
	}
	
	this.setDay = function( d ) 
	{
		if( this.day ) {
			var o = {
				day:d,
				month:false,
				year:false
			};
			
			if( this.month ) o.month = this.month.getValue(); 
			if( this.year ) o.year = this.year.getValue(); 
			
			this.day.update(o);
		}		
	}
	
	this.update = function()
	{
		var notifyObject = {};
		
		if( this.year ) notifyObject.year = this.year.getValue();
		if( this.month ) notifyObject.month = this.month.getValue();
		if( this.day ) {
			this.setDay( this.day.getValue() );
			notifyObject.day = this.day.getValue();
		}
		
		this.notify( notifyObject );
	}
	
	this.initialize = function( o ) 
	{
		if( def(o.yearElement) ) this.year = OO.Class.instance('View_Html_Element_Select',{element:o.yearElement});
		if( def(o.monthElement) ) this.month = OO.Class.instance('View_Html_Element_Select',{element:o.monthElement});
		if( def(o.dayElement) ) this.day = OO.Class.instance('View_Date_Chooser_Day',{element:o.dayElement});
		if( this.month ) this.month.attach( this );		
		if( this.year ) this.year.attach( this );		
		
		this.setDate( o.year, o.month, o.day );
	}
	
}).extend('View');
function FunctionFromMarkup( d ) {
	var mapper = {};
	var vars = {};
	this.getCreTreeObject = function( d, depth ) {
		if(!def(d)) return {};
		if(!def(depth)) var depth=0;
		var map = {
			replacers: [],
			kids: []
		};
		if( d.nodeType==3 ) {
			var o = {
				text: d.nodeValue 
			}
			
		
			var ma = d.nodeValue.match(/%([a-zA-Z0-9_]+)%/);
			if( ma ) {
				vars[ ma[1] ] = 1;
			
				map.replacers.push('text');
			}
			
			return [ o, map ];
			
		} else {
			var o = {
				t:d.tagName,
				kids:[]
			};
		}
		
		if( def(d.attributes) ) {
			for(var i=0;i<d.attributes.length;i++) {
				var at = d.attributes[i];
				var nn = at.nodeName;
	
				if( nn == 'style' ) {
					if( !def(o['style']) ) o['style'] = {};
					var styles;
					if( User.getBrowser()=='Safari' ) {
						styles = {};
						for(var j=0;j<d.style.length;j++) {
						
						
							styles[ d.style[j].replace(/-([a-z])/, function(m1,m2){return m2.toUpperCase()}) ] = d.style.getPropertyValue( d.style[j] );
						}
					} else {
						styles = d.style;
					}
					for(var x in styles) {
					
						if( (!(depth==0 && x=='display' && styles[x]=='none')) && danb(styles[x]) && ! x.match(/^(len|parent|accel|css|get|set|remove|\d|item|isprop)/i) ) { 
							o.style[x] = styles[x];
	
							var ma = x.match(/%([a-zA-Z0-9_]+)%/);
							if( ma ) {
								vars[ ma[1] ] = 1;
								map.replacers.push('style.'+x);
							}
						}
					}
				
					
				} else if( at.nodeValue ) {
					try {
						if( d.attributes[i].nodeValue.match ) {
							var ma = d.attributes[i].nodeValue.match(/%([a-zA-Z0-9_]+)%/);
							if( ma || nn!='id' ) {
								o[d.attributes[i].nodeName] = d.attributes[i].nodeValue;
								if( nn == 'class' ) {
									o['className'] = d.attributes[i].nodeValue;
								}
								if( ma ) {
									vars[ ma[1] ] = 1;
									map.replacers.push(nn);
									if( nn=='class') {
										map.replacers.push('className');
									}
								}
							}
						}
					} catch(e) { dbg(e,'lib/funcup: Exception'); }
				} 
			}
		}
		
		for(var i=0;i<d.childNodes.length;i++) {
			var kids = this.getCreTreeObject(d.childNodes[i],depth+1);
			map.kids.push( kids[1] );
			o.kids.push( kids[0] );
		}
		return [ o, map ];
	}
	__construct = function( d ) {
		var kids = this.getCreTreeObject( d );
		var matches = [];
		for(var x in vars) {
			matches.push(x);
		}
		return new FunctionFromMarkup_Species( kids[0], kids[1], matches );
	}
	
	return __construct(d);
}
FunctionFromMarkup_Species = function( creTreeObject, mapper, matches ) {
	this.creTreeObject = creTreeObject;
	this.mapper = mapper;
	this.matches = matches;
	
	this.getMatches = function() {
		return this.matches;
	}
	
	this.getInstance = function() {
		return new FunctionFromMarkup_Particular( deepObjectCopy(this.creTreeObject), this.mapper, this.matches );
	}
}
FunctionFromMarkup_Particular = function( creTreeObject, mapper, matches ) {
	this.creTreeObject = this.originalcreTreeObject = creTreeObject;
	this.mapper = mapper;
	this.replaces = {};
	this.needsRender = 1;
	this.matches = matches;
	
	this.getMatches = function() {
		return this.matches;
	}
	
	this.replace = function( from, to ) {
		this.replaces[from] = to;
		this.needsRender = 1;
	}
	
	this.replaceAll = function( cre, arr ) {
		for(var i=0;i<arr.length;i++) {
			for(var x in this.replaces) {
			
				var m = x.match(/^style\.(.+)/);
				if( m ) {
					if( cre['style'] && cre['style'][ m[1] ] ) {
						cre['style'][ m[1] ] = cre['style'][ m[1] ].replace( '%'+x+'%', this.replaces[x] ); 
					}
				} else {
					if( cre[ arr[i] ] ) {
						cre[ arr[i] ] = cre[ arr[i] ].replace( '%'+x+'%', this.replaces[x] );
					}
				}
			}
		}
		return cre;
	}
	
	this.recurse = function( cre, map ) {
		if( map.replacers ) {
			cre = this.replaceAll( cre, map.replacers );
		}
		if( map.kids && cre.kids ) {
		
			for(var i=0;i<cre.kids.length;i++) {
			
				if( cre.kids[i] && map.kids[i] ) {
					cre.kids[i] = this.recurse( cre.kids[i], map.kids[i] );
				}
			}
		}
		return cre;
	}
	
	this.render = function(  ) {
		this.creTreeObject = this.originalcreTreeObject;
		this.creTreeObject = this.recurse( this.creTreeObject, this.mapper );
		this.needsRender = 0;
	}
	
	this.render2 = function() {
		for(var x in this.replaces) {
		
		
			for(var y in this.domObject.vars) {
				this.domObject.vars[y].nodeValue = this.domObject.vars[y].nodeValue.replace( '%'+x+'%', this.replaces[x] );
			}
		}
		this.needsRender = 0;
	}
	
	this.getDomObject = this.getDomObj = function() {
		if( this.needsRender ) this.render( );
		var domObject = DOM.creTree( this.creTreeObject );
		return domObject;
	}
}
var	PTypes = 
{
	Objects:
	{
	},
	
	register: function( niceName, htmlId ) 
	{
		var element = $p( htmlId );
		if( element ) {
			PTypes.Objects[ niceName ] = FunctionFromMarkup( element );
		}
		DOM.Objects[ niceName ] = element;
		return true;
	},
	
	get: function( niceName )
	{
		if( !def(PTypes.Objects[ niceName ]) ) {
			if( $p( niceName ) ) {
				PTypes.register( niceName, niceName );
			} else {
				return false;
			}
			if( !def(PTypes.Objects[ niceName ]) ) {
				return false;
			}
		}
		return PTypes.Objects[ niceName ].getInstance();
	}
};
OO.Class.define('View_Calendar_Days',function(){
	this.formId = false;
	this.id = false;
	this.pTypeNames = false;
	this.renderElement = function()
	{
		var numberOfDays = xDate.getNumberOfDaysInMonth( this.data.year, this.data.month );
		var startDay = xDate.getStartDayOfMonth( this.data.year, this.data.month );
		
		DOM.removeAllChildren( this.parent );
		
		var dayNumber=1,row=0,cell,week,day;
		for(;row<7;row++) {
			
			week = PTypes.get( this.pTypeNames.Week );
			week.replace('CALENDAR_ID',this.id);
			week = week.getDomObject();
			
			for(cell=0;cell<7;cell++) {
			
				if( dayNumber<=numberOfDays && ( row>0 || cell>=startDay ) ) {
					day = PTypes.get( this.pTypeNames.Day );
					day.replace( 'YEAR_NUMBER', this.data.year );
					day.replace( 'MONTH_NUMBER', this.data.month );
					day.replace( 'DAY_NUMBER', dayNumber );
					dayNumber++;
				} else {
					day = PTypes.get( this.pTypeNames.DayBlank );
				}
				day.replace('FORM_ID',this.formId);
				day.replace('CALENDAR_ID',this.id);
				
				day = day.getDomObject();
				
				week.appendChild( day );
			}
			
			this.parent.appendChild( week );
			if( dayNumber > numberOfDays ) break;
			 			
		}
	}
	
	this.initialize = function(o)
	{
		if( def(o.id) ) this.id = o.id;
		if( def(o.formId) ) this.formId = o.formId;
		if( def(o.pTypeNames) ) this.pTypeNames = o.pTypeNames;
	}
	
}).extend('View');
OO.Class.define('View_Calendar',function(){
	this.options=false;
	this.formId = false;
	this.id = false;
	this.pTypeNames = false;
	this.innards = false;
	this.renderElement = function()
	{
		var main = PTypes.get( this.pTypeNames.Main );
		if( this.formId ) main.replace('FORM_ID', this.formId);
		if( this.id ) main.replace('CALENDAR_ID', this.id);
		main = main.getDomObject();
		
		var weekContainer = DOM.findFirst({
			parent:main,
			attribute:'id',
			string:this.weekContainerId
		});

		if( !weekContainer ) return dbg(this.weekContainerId,'couldnt get week container');
		
		this.innards = OO.Class.instance('View_Calendar_Days',{
			parent:weekContainer,
			pTypeNames:this.pTypeNames,
			id:this.id,
			formId:this.formId
		});
		
		this.innards.update( this.data );
		
		this.element = main;
	}
	
	this.initialize = function(o)
	{
		this.options = o;
		if( def(o.formId) ) this.formId = o.formId;
		if( def(o.id) ) this.id = o.id;
		if( def(o.weekContainerId) ) this.weekContainerId = o.weekContainerId;
		if( def(o.pTypeNames) ) {
			this.pTypeNames = o.pTypeNames;
		
			foreachArray(o.pTypeNames,function(i,pTypeName){
				PTypes.get(pTypeName); 
				
			}.bind(this));
		}
	}
	
}).extend('View');
var Cfs_String =
{
	'en':
	{
		'default_title': 'Title',
		'default_comment': '* Comment',
		'sure_continue': 'Are you sure you would like to continue?',
		'confirm_removal': 'Are you sure you would like to remove this item?',
		'alert_box': 'Alert',
		'popup_ok': 'OK',
		'popup_cancel': 'Cancel',
		'popup_close': 'Close',
		'months_short':
		[
			'Jan', 
			'Feb', 
			'Mar',
			'Apr', 
			'May', 
			'Jun',
			'Jul', 
			'Aug', 
			'Sep',
			'Oct', 
			'Nov', 
			'Dec' 		
		], 
		'months_long':
		[
			'January', 
			'February', 
			'March',
			'April', 
			'May', 
			'June',
			'July', 
			'August', 
			'September',
			'October', 
			'November', 
			'December' 		
		] 
	},
	
	'fr':
	{
		'default_title': '...',
		'default_comment': '...',
		'sure_continue': '...',
		'confirm_removal': '...',
		'alert_box': '...',
		'popup_ok': '...',
		'popup_cancel': '...',
		'popup_close': '...',
		'months_short':
		[
			'Jan', 
			'Fev', 
			'Mar', 
			'Avr', 
			'Mai', 
			'Juin', 
			'Juil', 
			'Aout', 
			'Sep', 
			'Oct', 
			'Nov', 
			'Dec'
		],
		'months_long':
		[
			'Janvier', 
			'Fevrier', 
			'Mars', 
			'Avril', 
			'Mai', 
			'Juin', 
			'Juillet', 
			'Aovt', 
			'Septembre', 
			'Octobre', 
			'Novembre', 
			'Decembre'
		] 
	}
};
OO.Class.define('Cfs_View_Calendar',function(){
	this.startHidden = false;
	
	this.preUpdate = function()
	{
		if( def(this.element) && def(this.element.style) && this.element.style.display=='none' ) {
			this.startHidden = true;
		} else {
			this.startHidden = false;
		}
	}

	this.postUpdate = function()
	{
		var title = DOM.get('calendar_title['+this.formId+']['+this.id+']');
		title.innerHTML = Cfs_String[ lang ]['months_short'][ this.data.month - 1 ] + ' ' + this.data.year;
		
		var closeLink = DOM.get('calendar_close_link['+this.formId+']['+this.id+']');
		closeLink.onclick = this.hide.bind(this);
		
		var dateObject = deepObjectCopy( this.data );
		dateObject.month--;
		if( dateObject.month<1 ) {
			dateObject.month=12;
			dateObject.year--;
		}
		
		var previousMonth = DOM.get('calendar_previous_month_link['+this.formId+']['+this.id+']');
		previousMonth.onclick = this.update.bind(this,dateObject);

		dateObject = deepObjectCopy( this.data );
		dateObject.month++;
		if( dateObject.month>12 ) {
			dateObject.month=1;
			dateObject.year++;
		}

		var nextMonth = DOM.get('calendar_next_month_link['+this.formId+']['+this.id+']');
		nextMonth.onclick = this.update.bind(this,dateObject);
		
		if( this.startHidden ) this.hide(); 
	}
	
	this.show = function()
	{
		DOM.show( this.element );
	}
	
	this.hide = function()
	{
		DOM.hide( this.element );
	}
	
}).extend('View_Calendar');
/*
Version history:
v1: 
- base model; allows you to instantiate Form_Validation, and attach to it various
   Form_Validator's, which has three key methods:
    - this.hasErrors: a method to return true/false as to whether its element contains
       errors
    - this.displayError / this.clearError: this gets called when the element is told to
	   display its error, along with a custom error message (if applicable) 
v2:
- modified to allow for versioning
- onFieldError (in the validator class) and onError (in the validation class) receive
    and array of the erring fields, rather than just an error field count
*/
OO.Class.define('Form_Validation',function(){
	this.options;
	this.form;
	this.fields = [];
	this.version = 1;
	
	this.getVersion = function() { return this.version; }
	this.setVersion = function( v )
	{
		this.version = v;
	}
	
	this.getForm = function() { return this.form; }
	this.setForm = function(x) 
	{ 
		this.form = x;
		this.form.onsubmit = this.onSubmit.bind(this); 
	}
	
	this.add = function( field )
	{
		this.fields.push( field );
	}
	
	this.onSubmit = function()
	{
		var errorFields = [];
		var firstToError;
		foreachArray( this.fields, function(i,field) {
			if( field.hasErrors() ) {
				
				if( !def(firstToError) ) firstToError=i;
				
				errorFields.push( field );
				
				this.onFieldError( field, ( this.version==1 ? errorFields.length : errorFields ) );
			}
			
		}.bind(this));
	
		if( def(firstToError) ) this.fields[ firstToError ].focus();
		
		if( errorFields.length>0 ) {
			var response = this.onError( ( this.version==1 ? errorFields.length : errorFields ) );
			if( def(response) ) {
				return response;
			} 
			return false;
		} else {
			var response = this.onSuccess(); 
			foreach( this.fields, function(i,field){
				field.submitSuccessful();
			});
			if( def(response) ) {
				return response;
			}
			return true;
		}
	}
	
	this.focus = function( which )
	{
		if( def(which) && def(this.fields[which]) && def(this.fields[which].focus) ) {
			this.fields[which].focus();
		}
	}
	
	this.onFieldError = noop;
	this.onError = noop;
	this.onSuccess = noop;
	this.initialize = noop;
	
	this.__construct = function( options )
	{
		if( def(options) ) {
			this.options = options;
			if( def(options.form) ) {
				this.setForm( options.form );
			}
		}
		
		this.initialize( options );
	}
	
});
OO.Class.define('Cfs_Form_Validation',function(){
	this.formId = '';
	
	this.getFormId = function() { return this.formId; } 
	this.setFormId = function(o) { this.formId = o; }
	
	this.getFeedback = function() 
	{
		return DOM.get( 'jsfeedback'+this.formId );
	} 
	
	this.getFeedbackText = function() 
	{
		return DOM.get( 'jsfeedback'+this.formId+'_error_fields' );
	} 
	
	this.onError = function( errorFields )
	{
		var feedbackMsg = '';
		foreachArray( errorFields, function(i,errorField){
			feedbackMsg += '<span class="error_field_name">' + errorField.getName() + '</span>';
			//if( i<errorFields.length-1 ) {
			//	feedbackMsg += ', ';
			//}
		});
		//feedbackMsg+='.';
		
		var feedback = this.getFeedback();
		var feedbackText = this.getFeedbackText();
		feedbackText.innerHTML = feedbackMsg;
		DOM.show( feedback );
	}
	
	this.onSuccess = function()
	{
		DOM.hide( 'feedback'+this.formId );
	}
	
	this.initialize = function(o)
	{
	}
	
}).extend('Form_Validation');
OO.Class.define('Form_Validator',function(){
	this.element;
	this.options;
	
	this.getElement = function(){ return this.element; }
	this.setElement = function(e){ this.element = e; }
	
	this.hasErrors = function( validator )
	{
		return false;
	}
	
	this.__construct = function( options )
	{
		if( !def(options) ) var options={};
		this.options = options;
		if( def(this.options.element) ) {
			this.element = this.options.element;
		} 
		this.initialize( options );
	}
	
	this.submitSuccessful = noop;
	this.focus = noop;
	this.initialize = noop;
});
				
OO.Class.define('Cfs_Form_Validator',function(){
	this.data = false;
	this.formId = false;
	
	this.getName = function() 
	{
		var name = this.data.title;
		var index = name.indexOf(':');
		if( index>=0 ) name=name.substr(name,index);
		return name;
	}
	
	this.clearError = function( name )
	{
		if( !def(name) ) var name = this.element.name;
		var labelId = 'label_form'+this.formId+'_'+name;
		var label = DOM.get( labelId );
		DOM.stylize(label,{className:''});
	}
	
	this.displayError = function( name )
	{
		if( !def(name) ) var name = this.element.name;
		var labelId = 'label_form'+this.formId+'_'+name;
		var label = DOM.get( labelId );
		DOM.stylize(label,{className:'error_field_name'});
	}
	
	this.focus = function( element )
	{
		try{
			if( !def(element) ) var element = this.element;
			element.select();
			element.focus();
		} catch(e) { }
	}
	
	this.initialize = function( o )
	{
		if( def(o.data) ) this.data = o.data;
		if( def(o.formId) ) this.formId = o.formId;
		this.initializeChild( o );
	}
	this.initializeChild = noop;
	
}).extend('Form_Validator');
OO.Class.define('Cfs_Form_Validator_Input',function(){
	this.hasErrors = function()
	{
		if( !this.data.required ) return false;
		if( !danb(this.element.value) ) {
			this.displayError();
			return true;
		} else {
			this.clearError();
			return false;
		} 
	}
	
}).extend('Cfs_Form_Validator');
__rootCreate('Web');
OO.extend(Web,
{
	Email:
	{
		isValid: function(email)
		{
		    var regex = /^((([a-z]|[0-9]|!|#|$|%|&|'|\*|\+|\-|\/|=|\?|\^|_|`|\{|\||\}|~)+(\.([a-z]|[0-9]|!|#|$|%|&|'|\*|\+|\-|\/|=|\?|\^|_|`|\{|\||\}|~)+)*)@((((([a-z]|[0-9])([a-z]|[0-9]|\-){0,61}([a-z]|[0-9])\.))*([a-z]|[0-9])([a-z]|[0-9]|\-){0,61}([a-z]|[0-9])\.)[\w]{2,4}|(((([0-9]){1,3}\.){3}([0-9]){1,3}))|(\[((([0-9]){1,3}\.){3}([0-9]){1,3})\])))$/i
		    return regex.test(email);
		}
	}
});
OO.Class.define('Cfs_Form_Validator_Email',function(){
	this.hasErrors = function()
	{
		if( !this.data.required ) return false;
		
		if( !danb(this.element.value) ) {
			this.displayError();
			return true;
		} else if( !Web.Email.isValid(this.element.value) ) {
			this.displayError();
			return true;
		} else {
			this.clearError();
			return false;
		} 
	}
	
}).extend('Cfs_Form_Validator');
OO.Class.define('Cfs_Form_Validator_NoDice',function(){
	this.hasErrors = function()
	{
		if( !danb(this.element.value) ) {
			this.displayError();
			return true;
		} else {
			this.clearError();
			return false;
		} 
	}
	
}).extend('Cfs_Form_Validator');
__rootCreate('Address','PhoneNumber');
Address.PhoneNumber = 
{
	isValid: function( pn1,pn2,pn3 ) 
	{
		if( def(pn1) && !def(pn2) && !def(pne3) ) {
			var pn = pn1;
			if( pn.match(/[a-zA-Z]+/) ) return false;
			pn = pn.replace(/\D+/g,'');
			if( pn.length >= 10 ) {
				return true;
			} else {
				return false;
			}
		} else {
			if( pn1.match(/^\d{3}$/) && pn2.match(/^\d{3}$/) && pn3.match(/^\d{4}$/) ) {
				return true;
			} else {
				return false;
			}
		}
	}
};
OO.Class.define('Cfs_Form_Validator_Phone',function(){
	this.element1 = false;
	this.element2 = false;
	this.element3 = false;
	
	this.hasErrors = function()
	{
		if( !this.data.required ) return false;

		if( !danb(this.element1.value) || !danb(this.element2.value) || !danb(this.element3.value) ) {
			this.displayError( this.element1.name );
			return true;
		} else if( !Address.PhoneNumber.isValid(this.element1.value, this.element2.value, this.element3.value) ) {
			this.displayError( this.element1.name );
			return true;
		} else {
			this.clearError( this.element1.name );
			return false;
		} 
	}
	
	this.focus = function( element )
	{
		try{
			this.element1.select();
			this.element1.focus();
		} catch(e) { }
	}
	
	this.initializeChild = function( o )
	{
		if( def(o) ) {
			if( def(o.element1) ) this.element1 = o.element1;
			if( def(o.element2) ) this.element2 = o.element2;
			if( def(o.element3) ) this.element3 = o.element3;
		}
	}
	
}).extend('Cfs_Form_Validator');
OO.Class.define('Html_Element_Input',function(){
	
	this.getForm = function() { return this.element.form; }
	
	this.getName = function() { return this.element.name; }
	this.setName = function(n) { this.element.name = n; }
	
	this.getValue = function() { return this.element.value; }
	this.setValue = function(n) { this.element.value = n; }
	this.getType = function() { return this.element.type; }
	
	this.disable = function() { return this.element.disabled = true; }
	this.enable = function() { return this.element.disabled = false; }
	this.isDisabled = function() { return this.element.disabled; }
	
	this.readonly = function() { this.element.setAttribute('readOnly','readonly'); }
	this.writeable = function() { this.element.setAttribute('readOnly',''); }
	this.isReadonly = function() { return ( danb(this.element.getAttribute('readOnly')) ); }
	
	this.focus = function() { if( def(this.element.select) ) this.element.select(); this.element.focus(); }
	
}).extend('Html_Element');
OO.Class.define('Html_Element_Input_Textarea',function() {
	
	this.setRows = function(r) { return this.element.setAttribute('rows',r); }
	this.getRows = function() { return this.element.getAttribute('rows'); }
	this.setMaxLength = function(m,callback) {
		if( !danb(m) || m<0 ) return false;
		this.element.setAttribute('maxlength',m);
		
		var func = function(element,max,callback){
			var st = this.element.scrollTop;
			if ( element.value.length > max ) {
				element.value = element.value.substr( 0, max );
			}
			this.element.scrollTop = st;
			if( def(callback)&&isFunction(callback) ) callback(element,max);
		}.bind(this,this.element,m,callback);
		
		addEvent( this.element, 'keyup', func ); 
		addEvent( this.element, 'change', func );
		func(); 
		
		return true;
	}
	this.getMaxLength = function() { return this.element.getAttribute('maxlength'); }
	
}).extend('Html_Element_Input');
__rootCreate('Event');
Event.Timer = 
{
	Objects: {},
	
	create: function( name, func, ms )
	{
		if( !danb(name) || !def(func) || !def(ms) ) return dbg('couldnt create timer');
		Event.Timer.cancel( name );
		Event.Timer.Objects[ name ] = setTimeout( func, ms );
	},
	
	cancel: function( name )
	{
		if( !danb(name) ) return;
		if( def(Event.Timer.Objects[ name ]) ) {
			clearTimeout( Event.Timer.Objects[ name ] );
		}
	}
}
OO.Class.define('Cfs_Form_Validator_Paragraph',function(){
	this.maxLength = -1;
	
	this.hasErrors = function()
	{
		if( this.maxLength!=-1 ) {
			this.callback( this.element, this.maxLength );
		}
		
		if( !this.data.required ) return false;
		if( !danb(this.element.value) ) {
			this.displayError();
			return true;
		} else {
			this.clearError();
			return false;
		} 
	}
	
	this.callback = function(element,max)
	{
		Event.Timer.create(element.name+'_counter',this.callbackEvent.bind(this,element,max),50);
	}
	
	this.callbackEvent = function(element,max)
	{
		var counterElement = DOM.get(element.name+'_counter');
		var size = 18;
		if( !counterElement ) {
			counterElement = DOM.create({
				t:'div',
				id:element.name+'_counter',
				className:'textarea_counter',
				style:{
					fontSize:'12px',
					color:'#666',
					height:size+'px',
					backgroundColor:''
				}
			},DOM.getBody());
		}
		var pos = DOM.findPos( element );
		var dims = DOM.getDims( element );
		DOM.stylize( counterElement, {
			position:'absolute',
			left:pos[0]+dims[0]+5+'px',
			top:(pos[1]+dims[1]-size)+'px'
		});
		
		var left = (max-element.value.length);
		if(left<0)left=0;
		
		DOM.removeAllChildren( counterElement );
		DOM.create({t:'span',text:left},counterElement);
	}
	
	this.initializeChild = function()
	{
		Html.extend( this.element );
		var maxLength = parseInt( this.data.maxLength, 10 );
		if( !isNaN(maxLength) && maxLength>=0 ) {
			this.maxLength = maxLength;
			try {
				this.element.extended.setMaxLength( maxLength, this.callback.bind(this) );
			} catch(e){}
		}
	}
	
}).extend('Cfs_Form_Validator');
OO.Class.define('Cfs_Form_Validator_NoDice',function(){
	this.hasErrors = function()
	{
		if( !danb(this.element.value) ) {
			this.displayError();
			return true;
		} else {
			this.clearError();
			return false;
		} 
	}
	
}).extend('Cfs_Form_Validator');
OO.Class.define('Cfs_Form_Validator_Dropdown',function(){
	this.hasErrors = function()
	{
		if( !danb(this.element.value) && !(def(this.element.selectedIndex) && this.element.selectedIndex>=0) ) {
			this.displayError();
			return true;
		} else {
			this.clearError();
			return false;
		} 
	}
}).extend('Cfs_Form_Validator');
OO.Class.define('Html_Element_Input_Checkable',function() {
	this.isChecked = function()
	{
		return this.element.checked;
	}
	
	this.isDefaultChecked = function()
	{
		return this.element.defaultChecked;
	}
	
	this.check = function()
	{
		this.element.checked = true;
	}
	
	this.uncheck = function()
	{
		this.element.checked = false;
	}
	
}).extend('Html_Element_Input');
OO.Class.define('Cfs_Form_Validator_CheckboxSingle',function(){
	this.hasErrors = function()
	{
		if( !this.data.required ) return false;
		
		if( !this.element.extended.isChecked() ) {
			this.displayError();
			return true;
		} else {
			this.clearError();
			return false;
		} 
	}
	
	this.initializeChild = function()
	{
		Html.extend( this.element );
	}
	
}).extend('Cfs_Form_Validator');
OO.Class.define('Cfs_Form_Validator_CheckboxMultiple',function(){
	this.elements = [];
	
	this.hasErrors = function()
	{
	
		return false;
		
		if( !this.data.required ) return false;
		if( !this.element.extended.isChecked() ) {
			this.displayError();
			return true;
		} else {
			this.clearError();
			return false;
		} 
	}
	this.initializeChild = function( o )
	{
		var element,form = DOM.get('form'+this.formId);
		
		dbg(this.data,'this.data.options');
		foreachArray( this.data.options, function(i,option){
			element = form['input['+this.data.fieldId+']['+i+']'];
			if( !def(element) ) return dbg('input['+this.data.fieldId+']['+i+']','!def');
			Html.extend( element );
			this.elements.push( element );
		}.bind(this) ); 
		
	
	}
	
}).extend('Cfs_Form_Validator');
OO.Class.define('Cfs_Form_Validator_Radio',function(){
	this.elements = [];
	
	this.focus = function( element )
	{
		if( !def(element) ) var element = this.element[0];
		if( def(element.select) ) element.select();
		if( def(element.focus) ) element.focus();
	}
	
	this.hasErrors = function()
	{
		var oneChecked = false,lastElement=false;
		foreachArray( this.element, function(i,element){
			if( element.checked ) oneChecked=element;
			lastElement = element;
		});
		
		if( !oneChecked ) {
			this.displayError( lastElement.name );
			return true;
		} else {
			this.clearError( lastElement.name );
			return false;
		} 
	}
	
}).extend('Cfs_Form_Validator');
var debug=400;
var debug_height=400;
var Test = 
{
	Chooser: {},
	Calendar: {},
	
	setDate: function( year, month, day )
	{
		Test.Chooser.setDate( year, month, day );
		Test.Calendar.hide();
	}
};

var Cfs_Form_Vars =
{
	Chooser:{},
	Calendar:{},
	setDate: function( formId, fieldId, year, month, day )
	{
		var vars = Cfs_Form_Vars;
		if( def(vars.Chooser[formId]) ) {
			if( def(vars.Chooser[formId][fieldId]) ) {
				vars.Chooser[formId][fieldId].setDate(year,month,day);
				vars.Calendar[formId][fieldId].hide();
			}
		}
	}
};

function setupFieldDataFormValidation(){
	try{
		dbg(fieldData);
	} catch(e) { return; }
	var form, validation, instanceName, m, formId, validator;
	foreachObject(fieldData,function(formName,formData){
	
		m = formName.match(/form(\d+)/);
		if( m ) {
			formId = m[1];
		}
		form = DOM.get(formName);
		
		validation = OO.Class.instance('Cfs_Form_Validation');
		validation.setForm( form );
		validation.setFormId( formId );
		validation.setVersion( 2 );
		
		foreachArray(formData,function(i,field){
			if( field.required!=undefined && field.required=='0' && field.fieldType!='date' ) return;
			
			var t ='';
			for(var x in field) {
				t+=x+': '+field[x]+'\n';
			}
			//alert(t); 
		
			instanceName = false;
			
			element = form['input['+field.fieldId+']'];
			
			if( field.fieldType=='input' ) {
				instanceName = 'Cfs_Form_Validator_Input';
			} else if( field.fieldType=='date' ) {
				
				var chooser, calendar;
				
				chooser = OO.Class.instance('View_Date_Chooser',{
					yearElement:form['input['+field.fieldId+'][year]'],
					monthElement:form['input['+field.fieldId+'][month]'],
					dayElement:form['input['+field.fieldId+'][day]']
				});
				
				var pTypeNames = {
					Main: 'ptype_calendar',
					Week: 'ptype_calendar_week', 
					DayBlank: 'ptype_calendar_day_blank', 
					Day: 'ptype_calendar_day'
				};
				foreachArray(pTypeNames,function(i,pTypeName){
					PTypes.get(pTypeName);
				});
				var image = $p('calendar_image['+formId+']['+field.fieldId+']');
				calendar = OO.Class.instance('Cfs_View_Calendar',{
					formId:formId,
					id:field.fieldId,
					leftSibling:image, //form['input['+field.fieldId+'][year]']
					weekContainerId:'calendar_innards['+formId+']['+field.fieldId+']',
					pTypeNames:pTypeNames,
					data:{
						year:chooser.getYear(),
						month:chooser.getMonth(),
						day:chooser.getDay()
					}
				});
				
				chooser.attach( calendar );
				
				image.onclick = calendar.show.bind( calendar );
				calendar.hide();

				var vars = Cfs_Form_Vars;
				if( !def(vars.Chooser[formId]) ) vars.Chooser[formId] = {};
				if( !def(vars.Calendar[formId]) ) vars.Calendar[formId] = {};
				
				vars.Calendar[formId][field.fieldId] = calendar;
				vars.Chooser[formId][field.fieldId] = chooser;
				
			} else if( field.fieldType=='phone' ) {
				OO.Class.instance('View_Advance',{
					element1:form['input['+field.fieldId+'][1]'],
					element2:form['input['+field.fieldId+'][2]'],
					validator:function(value){return value.match(/\d{3}/);}
				});
				OO.Class.instance('View_Advance',{
					element1:form['input['+field.fieldId+'][2]'],
					element2:form['input['+field.fieldId+'][3]'],
					validator:function(value){return value.match(/\d{3}/);}
				});

				instanceName = 'Cfs_Form_Validator_Phone';
				validator = OO.Class.instance(instanceName,{element1:form['input['+field.fieldId+'][1]'],element2:form['input['+field.fieldId+'][2]'],element3:form['input['+field.fieldId+'][3]'],data:field,formId:formId});
				validation.add( validator );
				return;

			} else if( field.fieldType=='email' ) {
				instanceName = 'Cfs_Form_Validator_Email';
			} else if( field.fieldType=='paragraph' ) {
				instanceName = 'Cfs_Form_Validator_Paragraph';
			} else if( field.fieldType=='checkbox_single' ) {
				instanceName = 'Cfs_Form_Validator_CheckboxSingle';
			} else if( field.fieldType=='dropdown' ) {
				instanceName = 'Cfs_Form_Validator_Dropdown';
			} else if( field.fieldType=='checkbox_multiple' ) {
			} else if( field.fieldType=='radio' ) {
				instanceName = 'Cfs_Form_Validator_Radio';
			} else {
				return dbg( field, 'couldnt find an instance name for' );
			}
			if( !instanceName ) return;
			validator = OO.Class.instance(instanceName,{element:element,data:field,formId:formId});
			if( !validator ) return;			
			
			validation.add( validator );
		});
	});
	
}
addLoadEvent( setupFieldDataFormValidation );

/* Newer functions2 */

/* Simple AJAX: function, action (url/path), asynchronous (optional) */
SimpleAjax = function(f,ac,as) {
	this.func = f;
	this.action = ac;
	this.async = as;
	
	this.method;
	this.request;
	
	this.text;
	this.xml;
	
	var me = this;
	
	this.setFunction = function( n ) {
		me.func = n;
	}
	
	this.setAction = this.setURL = this.setPath = function( n ) {
		me.action = n;
	}
	
	this.setAsync = function( n ) {
		me.async = n;
	}
	
	this.get = function() {
		me.method='get';
		me.performRequest();
	}
	
	this.post = function() {
		me.method='post';
		me.performRequest();
	}
	
	this.put = function() {
		me.method='put';
		me.performRequest();
	}
	
	this.del = function() {
		me.method='delete';
		me.performRequest();
	}
	
	this.isXML = function() {
		return me.responseIsXML;
	}
	
	this.getResponseText = function() {
		return me.text;
	}
	
	this.getResponseXML = function() {
		return me.xml;
	}
	
	this.performRequest = function() {
		if( !def(me.async) ) me.async = true;
		if( !def(me.method) || !def(me.action) ) return;

		/* if this request is already pending, then cancel it */
		if( def(me.request) ) {		// if a request has been called already
			if( def(me.request.readyState) && me.request.readyState != 0 && me.request.readyState != 4 ) {
				me.request.abort();
			}
			me.request = null;
			me.request = undefined;
		}
		
		me.request = me.getRequest();
		
		var onStateChange;
		if( def( me.func ) ) {

			onStateChange = me.request.onreadystatechange = function() {
				
				if( def(me.request) && 
					me.request.readyState==4 && 
					def(me.request.status) && 
					(me.request.status==200 || me.request.status==0) 
					) 
				{
					if( me.request.responseText.substring(0,5)=='<?xml') {
						me.responseIsXML = true;
					} else {
						me.responseIsXML = false;
					}
					me.text = me.request.responseText;
					me.xml = me.request.responseXML;
					
					me.request = null;
					me.request = undefined;
					
					me.func( me );
				} 
			} // end of onreadystatechange function
		} // end of if def func
		
		//dbg( me.method + ' and '+ me.action + ' and ' +me.async );
		me.request.open( me.method, me.action, me.async );
		me.request.send( null );
		
		// sometimes, some browsers perform the request too quickly, and the onstatechange event fires too quickly -- this calls it explicitly
		if( def(onStateChange) ) {
			onStateChange();
		}
	}
	
	this.getRequest = function() {
		var req;
		try { return new XMLHttpRequest(); }
		catch(error) {
			try{ return new ActiveXObject("Microsoft.XMLHTTP"); }
			catch(error) { return ""; }
		}
	}
}

var req = new Object()
function openreq(func,meth,path,async) {
	if(async==undefined) async=true;
	if(req[path]!=undefined&&req[path]!=null&&req[path].readyState!=0&&req[path].readyState!=4) { // if never, or already, run(ning)
		req[path].abort();
	}
	req[path]=getreq();
	var thisreq = req[path];
	if(func!=undefined) {
		var thisfunc = func;
		var a = thisreq.onreadystatechange = function() {
			var p = path;
			if(thisreq.readyState==4 && req[p]!=undefined ) {
				if((thisreq.status==200||thisreq.status==0)) {
					req[p] = undefined;
					if(thisreq.responseText.substring(0,5)=='<?xml') {
						thisfunc(thisreq.responseXML);
					} else {
						thisfunc(thisreq.responseText);
					}
				}
			}
		}
	}
	req[path].open(meth,path,async);
	thisreq.send(null);
	a();
	
	return req[path];
}

function getreq() {
	var req;
	try { return new XMLHttpRequest(); }
	catch(error) {
		try{ return new ActiveXObject("Microsoft.XMLHTTP"); }
		catch(error) { return ""; }
	}
}	

function div(id) {
   var d = document.getElementById(id);
   return ( d==undefined ? '' : d );
}

function insertAfter(newChild, refChild) { 
	refChild.parentNode.insertBefore(newChild,refChild.nextSibling); 
} 

setupPolls = function() {
	var submit = div('submit-poll');
	if( submit!="" ){
		submit.onclick = function() {
			var form = div('poll-form');
			var accountID = $j('#account_id').text();
			var pollID = form['pollID'].value;
			var answerIDs = form['answerID'];
			var answerID = 0;
			if( answerIDs!=undefined && answerIDs.length!=undefined ) {
				for(var i=0;i<answerIDs.length;i++) {
					if(answerIDs[i].checked)answerID=answerIDs[i].value;
				}
			}
			
			if( Web.Cookie.get('poll-answered') && Web.Cookie.get('poll-answered')=='1' ) {
				answerID = 0;
			}
			
			var action = "/__webservices/?method=getPollResults&arg1="+accountID+"&arg2="+pollID+"&arg3="+answerID+"&arg4=true";
			//SimpleAjax = function(f,ac,as) {
			
			div('poll').style.display='none'; 
			div('poll-loading').style.display=''; 
			
			var aj = new SimpleAjax(
				function( req ) {
					Web.Cookie.set('poll-answered','1',1);
					
					var d = div('poll');
					//d.parentNode.removeChild( d );
					d.style.display='none';
					var nav = div('nav_container');
					var newd = document.createElement('div');
					newd.innerHTML = req.getResponseText();
					div('poll-loading').style.display='none'; 
					insertAfter(newd,d);
				},
				action
			);
			aj.get();
		}
	}
}

addLoadEvent( setupPolls );

__rootCreate = crind = function(){
	var a=arguments,o=this;
	for(var i=0;i<a.length;i++) {
		if(o[a[i]]==undefined||!isObject(o[a[i]]))o[a[i]]={};
		o=o[a[i]];
	}
}

__rootCreate('Web');
Web.Cookie =
	{
		get: function(n)
		{
			var nEQ = n + "=";
			var ca = document.cookie.split(';');
			for(var i=0;i < ca.length;i++) {
				var c = ca[i];
				while (c.charAt(0)==' ') c = c.substring(1,c.length);
				if (c.indexOf(nEQ) == 0) return c.substring(nEQ.length,c.length);
			}
			return false;
		},
		
		set: function(n,v,d)
		{
			if (d) {
				var date = new Date();
				date.setTime(date.getTime()+(d*24*60*60*1000));
				var ex = "; expires="+date.toGMTString();
			}
			else var ex= "";
			document.cookie = n+"="+v+ex+"; path=/";
		},
		
		remove: function(n)
		{
			Web.Cookie.set(n,"",-1);
		},
		
		del: function(n)
		{
			Web.Cookie.remove(n);
		}
	};

function def(element) {
	return (element==undefined ? false : true);
}


/* Older Function */

var xmlHttpLoadingStatus = false;

function createDropDownBox(paraID, labelTxt, dropBoxName, dropBoxClassName, prevSibID) {

  // create new paragraph element to hold label and dropdown
  var para = document.createElement("p");
  // give the new para an id
  para.setAttribute("id",paraID);
  
  // create label element
  var labelElem = document.createElement("label");
  var labelElemTxt = document.createTextNode(labelTxt);
  // add text to label
  labelElem.appendChild(labelElemTxt);
  // add label to para
  para.appendChild(labelElem);
  
  // create the provinces drob down box
  var dropBox = document.createElement("select");
  // set province drop down attributes
  dropBox.setAttribute("className",dropBoxClassName);
  dropBox.setAttribute("class",dropBoxClassName);
  dropBox.setAttribute("name",dropBoxName);
  highlightInput(dropBox);
  
  para.appendChild(dropBox);
  
  insertAfter(para,prevSibID);
  
  return dropBox;
}

function createTextField(paraID, labelTxt, txtFieldName, txtFieldClassName, txtFieldVal, prevSibID) {
        
  // create region text box
  var para = document.createElement("p");
  para.setAttribute("id",paraID);
  
  // create label
  var labelElem = document.createElement("label");
  var labelElemTxt = document.createTextNode(labelTxt);
  labelElem.appendChild(labelElemTxt);
  
  // create text box
  var txtBox = document.createElement("input");
  txtBox.setAttribute("type","text");
  txtBox.setAttribute("name",txtFieldName);
  txtBox.setAttribute("class",txtFieldClassName);
  txtBox.setAttribute("className",txtFieldClassName);
  txtBox.setAttribute("value",txtFieldVal);
  highlightInput(txtBox);
  
  // append elements to paragraph
  para.appendChild(labelElem);
  para.appendChild(txtBox);
  
  insertAfter(para,prevSibID);
  
  return txtBox;
}

function insertAfter(newNode, siblingID) {
  
  //alert(siblingID);
  
  if(siblingID.nodeType == 1) {
    var sibling = siblingID;
  } else {
    var sibling = document.getElementById(siblingID);
  }
  
  var theNextSibling = sibling.nextSibling;
  var theSiblingsParent = sibling.parentNode;
  
  if(theNextSibling) {
    theSiblingsParent.insertBefore(newNode,theNextSibling);
  } else {
    theSiblingsParent.appendChild(newNode);
  } 
}

function createXMLHttpRequest(){
    
    var xmlHttp;
  
    if (window.ActiveXObject){
        xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
    } else if (window.XMLHttpRequest) {
        xmlHttp = new XMLHttpRequest();
    }
    
    return xmlHttp;
}

// function to show loading animation when Ajax Loading
function showLoadAnimation(divID) {
  
  if(!xmlHttpLoadingStatus) {
    
    xmlHttpLoadingStatus = true;
    
    var titleBar = document.getElementById("calendar");
    
    //var toolTip = document.getElementById(divID);
    
    var ptag = document.createElement("p");
    ptag.setAttribute("id","loading_p");
    ptag.style.margin = "0px";
    
    var loading_text = document.createTextNode("Please wait while loading events...");
    
    ptag.appendChild(loading_text);
    
    //toolTip.appendChild(ptag);
    
    titleBar.appendChild(ptag);
  }
}


// clear loading animation when Ajax call finished loading
function clearLoadAnimation() {
  
  xmlHttpLoadingStatus = false;
  
  var loading_p = document.getElementById("loading_p");
  
  if(loading_p) {
    var contain_form = loading_p.parentNode;
    contain_form.removeChild(loading_p);
  }
}

function XMLRequestParamsURL() {
  var args = arguments;

  var recom = new String();
  
  recom = recom.concat("__webservices/?request=");

  recom = recom.concat("<request>");
  
  recom = recom.concat("<key>wIDZW8Rta7Joo0mNE8GK8g==</key>");
  
  recom = recom.concat("<function>");
  recom = recom.concat("<name>" + args[0] + "</name>");
  
  if(args.length > 1) {
    
    recom = recom.concat("<params>");
    
    for(var i = 1; i < args.length; i++) {
      if (i % 2){ //if odd
        recom = recom.concat("<param><name>" + args[i] + "</name>");
      } else {
        recom = recom.concat("<value>" + args[i] + "</value></param>");
      }
    }
    
    recom = recom.concat("</params>");
  }
  
  recom = recom.concat("</function>");
  
  recom = recom.concat("</request>");
  
  recom = recom.concat("&ts=" + new Date().getTime());
  
  return recom;

}

/* MEDIA RELEASES */

/* HTTP */
HTTP = {};

HTTP.status = function(_status){
    
    var s = _status.toString().split("");
    
    switch(s[0]){
        case "1":
            return this.getInformationalStatus(_status);
            break;
        case "2":
            return this.getSuccessfulStatus(_status);
            break;
        case "3":
            return this.getRedirectStatus(_status);
            break;
        case "4":
            return this.getClientErrorStatus(_status);
            break;
        case "5":
            return this.getServerErrorStatus(_status);
            break;
        default:
            return "An unexpected error has occurred.";
    }
    
}

HTTP.getInformationalStatus = function(_status){
    
    switch(_status){
        case 100:
            return "Continue";
            break;
        case 101:
            return "Switching Protocols";
            break;
        default:
            return "An unexpected error has occured";
    }
    
}

HTTP.getSuccessfulStatus = function(_status){
    
    switch(_status){
        
        case 200:
            return "OK";
            break;
        case 201:
            return "Created";
            break;
        case 202:
            return "Accepted";
            break;
        case 203:
            return "Non-Authoritative Information";
            break;
        case 204:
            return "No Content";
            break;
        case 205:
            return "Reset Content";
            break;
        case 206:
            return "Partial Content";
            break;
        default:
            return "An unexpected error has occurred.";
    }
    
}

HTTP.getRedirectionStatus = function(_status){
    
    switch(_status){
        
        case 300:
            return "Multiple Choices";
            break;
        case 301:
            return "Moved Permanently";
            break;
        case 302:
            return "Found";
            break;
        case 303:
            return "See Other";
            break;
        case 304:
            return "Not Modified";
            break;
        case 305:
            return "Use Proxy";
            break;
        case 307:
            return "Temporary Redirect";
            break;
        default:
            return "An unexpected error has occurred.";
    }
    
}

HTTP.getClientErrorStatus = function(_status){
    
    switch(_status){
        
        case 400:
            return "Bad Request";
            break;
        case 401:
            return "Unauthorized";
            break;
        case 402:
            return "Payment Required";
            break;
        case 403:
            return "Forbidden";
            break;
        case 404:
            return "File not found";
            break;
        case 405:
            return "Method not allowed";
            break;
        case 406:
            return "Not acceptable";
            break;
        case 407:
            return "Proxy Authenticaton Required";
            break;
        case 408:
            return "Request Timeout";
            break;
        case 409:
            return "Conflict";
            break;
        case 410:
            return "Gone";
            break;
        case 411:
            return "Length Required";
            break;
        case 412:
            return "Precondition Failed";
            break;
        case 413:
            return "Request entity too large";
            break;
        case 414:
            return "Request-URI too long";
            break;
        case 415:
            return "Unsupported Media Type";
            break;
        case 416:
            return "Requested Range Not Satisfied";
            break;
        case 417:
            return "Expectation Failed";
            break;
        default:
            return "An unexpected error has occurred.";
    }
    
}

HTTP.getServerErrorStatus = function(_status){
    
    switch(_status){
        
        case 500:
            return "Internal Server Error";
            break;
        case 501:
            return "Not Implemented";
            break;
        case 502:
            return "Bad Gateway";
            break;
        case 503:
            return "Service Unavailable";
            break;
        case 504:
            return "Gateway Timeout";
            break;
        case 505:
            return "HTTP Version not supported";
            break;
        default:
            return "An unexpected error has occurred.";
    }
    
}


/* XMLRequest */
function XMLRequest() {

  this.key = "";
  
  this.func = "";
  
  this.params = new Array();
  
}

XMLRequest.prototype.setKey = function(_key) {
  this.key = _key;
}

XMLRequest.prototype.setFunction= function(_func) {
  this.func = _func;
}

XMLRequest.prototype.addParam = function(_name,_value) {
  this.params[_name] = _value;
}

XMLRequest.prototype.toString = function() {
  return this.buildXML();
}

XMLRequest.prototype.buildXML = function() {

  var str = new String();
  
  str = str.concat("<request>");
  
  str = str.concat("<key>" + this.key + "</key>");
  
  str = str.concat("<function>");
  str = str.concat("<name>" + this.func + "</name>");
    
  str = str.concat("<params>");
  
  for(var j in this.params) {
      str = str.concat("<param><name>" + j + "</name><value>" + this.params[j] + "</value></param>");
  }
  
  str = str.concat("</params>");
  
  str = str.concat("</function>");
  
  str = str.concat("</request>");
  
  return str;
  
}

/* Ajax */
Ajax = {};

Ajax.makeRequest = function (method, url, callbackMethod) {
    this.request = (window.XMLHttpRequest)? new XMLHttpRequest(): new ActiveXObject("MSXML2.XMLHTTP");
    this.request.onreadystatechange = callbackMethod;
    this.request.open(method, url, true);
    this.request.send(url);
}

Ajax.checkReadyState = function(_id) {
    
    switch(this.request.readyState){
        case 1:
            //loading
            break;
        case 2:
            //loading
            break;
        case 3:
            //loading
            break;
        case 4:
            AjaxUpdater.isUpdating = false;
            return HTTP.status(this.request.status);
        default:
            // an unexpected error has occured
    }
    
}

Ajax.getResponse = function() {
    
    if (this.request.getResponseHeader('Content-Type').indexOf('xml') != -1){
        return this.request.responseXML.documentElement;
    } else {
        return this.request.responseText;
    }
    
}


/* AjaxUpdater */
AjaxUpdater = {};

AjaxUpdater.initialize = function() {
    AjaxUpdater.isUpdating = false;
    AjaxUpdater.pool = new Array();
    AjaxUpdater.poolIndex = 0;
    AjaxUpdater.interval = null;
    AjaxUpdater.ajaxCallback;
}

AjaxUpdater.initialize();

AjaxUpdater.add = function(method, service, callback) {

    if (callback == undefined || callback == ""){
        callback = AjaxUpdater.onResponse;
    }
     
    var update = new AjaxUpdate(method, service, callback);
    AjaxUpdater.pool.push(update);
    
}

AjaxUpdater.execute = function(){
    
    if (AjaxUpdater.poolIndex >= AjaxUpdater.pool.length) {
        //clearInterval(AjaxUpdater.interval);
        return false;
    }
    
    if (!AjaxUpdater.isUpdating) {
        
        if (AjaxUpdater.pool[AjaxUpdater.poolIndex]) {
            AjaxUpdater.pool[AjaxUpdater.poolIndex].execute();
            AjaxUpdater.poolIndex++;
        }
        
    }
    
}


AjaxUpdater.update = function(method, service, callback) {
    
    if (callback == undefined || callback == ""){
        callback = AjaxUpdater.onResponse;
    }
    
    Ajax.makeRequest(method, service, callback);
    AjaxUpdater.isUpdating = true;
    
}


AjaxUpdater.onResponse = function() {
    
    if (Ajax.checkReadyState('loading') == 200){
        AjaxUpdater.isUpdating = false;
    }
    
}

AjaxUpdater.callback = function() {
  
}


/* AjaxUpdate Object */

//constructor
function AjaxUpdate(method, service, callback){
    this.method = method;
    this.service = service;
    this.callback = callback;
}

AjaxUpdate.prototype.execute = function() {
    Ajax.makeRequest(this.method, this.service, this.callback);
    AjaxUpdater.isUpdating = true;
}


/* MediaRelease */
function MediaRelease(headline, subheadline, abstract, url, date){
    this.headline = headline;
    this.subheadline = subheadline;
    this.abstract = abstract;
    this.url = url;
    this.date = new Date(date.replace(/[-]/g," "));
    this.daynames = {
			'en':
				["Sunday",
       	              "Monday",
              	       "Tuesday",
                     	"Wednesday",
	                     "Thursday",
      		              "Friday",
      	       	       "Saturday"],
			'fr-ca':
				["dimanche",
       	              "lundi",
              	       "mardi",
                     	"mercredi",
	                     "jeudi",
      		              "vendredi",
      	       	       "samedi"]
			};
                     
    this.monthnames = {
			'en':
				["January",
	                       "February",
	                       "March",
	                       "April",
	                       "May",
	                       "June",
	                       "July",
	                       "August",
	                       "September",
	                       "October",
	                       "November",
	                       "December"],
			'fr-ca':
				["janvier",
	                       "fevrier",
	                       "mars",
	                       "avril",
	                       "mai",
	                       "juin",
	                       "juillet",
	                       "aout",
	                       "septembre",
	                       "octobre",
	                       "novembre",
	                       "decembre"]
			};
}

MediaRelease.prototype.display = function(){
  
	var _container = document.createElement("div");
	_container.setAttribute("className","mediaRelease");
	_container.setAttribute("class","mediaRelease");

	if(typeof(this.headline) != "undefined" && this.headline != "") {
		var _headline = document.createElement("a");
		_container.setAttribute("className","headline");
		_container.setAttribute("class","headline");
		
		_headline.setAttribute("href",MediaReleaseManager.baseurl + MediaReleaseManager.pathurl + "?release_id=" + this.url);
		var _headline_text = document.createTextNode(this.headline);
		_headline.appendChild(_headline_text);
		
		_container.appendChild(_headline);
	}


	var _date = document.createElement("p");
	_date.setAttribute("className","date");
	_date.setAttribute("class","date");
	var _date_text = document.createTextNode(this.daynames[lang][this.date.getDay()] + " " +
		this.monthnames[lang][this.date.getMonth()] + " " +
		this.date.getDate() + ", " +
		this.date.getFullYear());

	_date.appendChild(_date_text);
	_container.appendChild(_date);
	
	if( showSubheadline ) {   
		if(typeof(this.subheadline) != "undefined" && this.subheadline != "") {
			var _subheadline = document.createElement("p");
			_subheadline.setAttribute("className","subheadline");
			_subheadline.setAttribute("class","subheadline");
			var _subheadline_text = document.createTextNode(this.subheadline);
			_subheadline.appendChild(_subheadline_text);
			
			_container.appendChild(_subheadline);
		}
	}
	
	if( showAbstract ) {   
		if(typeof(this.abstract) != "undefined" && this.abstract != "") {
			var _abstract = document.createElement("p");
			_abstract.setAttribute("className","abstract");
			_abstract.setAttribute("class","abstract");
			var _abstract_text = document.createTextNode(this.abstract);
			_abstract.appendChild(_abstract_text);
			_container.appendChild(_abstract);
		}
	}
	
	return _container;
}

/* Managers */
function Manager(){
    this.collection = new Array();
}

Manager.prototype.add = function(item){
    this.collection.push(item);
}

Manager.prototype.display = function(_id){
    
    var items = document.getElementById(_id);
    
    while(node = items.lastChild) {
      items.removeChild(items.lastChild);
    }
    
    for(var i = 0; i < this.collection.length; i++){
        var item = this.collection[i];
        items.appendChild(item.display());
    }
    
    // clear media release Manager stack
    MediaReleaseManager.clear();
    
}

Manager.prototype.parse = function(){
}

Manager.prototype.get = function(){
}

Manager.prototype.clear = function() { 
  this.collection = [];
}

MediaReleaseManager = new Manager();
MediaReleaseManager.categories = new Array();

MediaReleaseManager.parse = function() {
  
  if(Ajax.checkReadyState() == "OK") {
    
    var releases = Ajax.getResponse().getElementsByTagName("release");
    
    for(var i = 0; i < releases.length; i++) {
      
      if(Ajax.getResponse().getElementsByTagName("headline")[i].hasChildNodes()) {
        var headline = Ajax.getResponse().getElementsByTagName("headline")[i].firstChild.data;
      } else {
        var headline = "";
      }
      
      if(Ajax.getResponse().getElementsByTagName("subheadline")[i].hasChildNodes()) {
        var subheadline = Ajax.getResponse().getElementsByTagName("subheadline")[i].firstChild.data;
      } else {
        var subheadline = "";
      }
      
      if(Ajax.getResponse().getElementsByTagName("abstract")[i].hasChildNodes()) {
        var abstract = Ajax.getResponse().getElementsByTagName("abstract")[i].firstChild.data;
      } else {
        var abstract = "";
      }
      
      if(Ajax.getResponse().getElementsByTagName("release_id")[i].hasChildNodes()) {
        var headline_link = Ajax.getResponse().getElementsByTagName("release_id")[i].firstChild.data;
      } else {
        var headline_link = "";
      }
      
      if(Ajax.getResponse().getElementsByTagName("publish_date")[i].hasChildNodes()) {
        var publish_date = Ajax.getResponse().getElementsByTagName("publish_date")[i].firstChild.data;
      } else {
        var publish_date = "";
      }
      
      var release = new MediaRelease(headline, subheadline, abstract, headline_link, publish_date);
      
      MediaReleaseManager.add(release);
      
    }
    
    MediaReleaseManager.display("releases");
    
    AjaxUpdater.isUpdating = false;
    
    // continue the function chain
    //AjaxUpdater.execute();
     
  }
  
}

MediaReleaseManager.addCategory = function(_category) {
  this.categories.push(_category);
}

MediaReleaseManager.setLanguage = function(_lang) {
  this.language = _lang;
}

MediaReleaseManager.setLimit = function(_limit) {
  this.limit = _limit;
}

MediaReleaseManager.setBaseURL = function(url) {
  this.baseurl = url;
}

MediaReleaseManager.setMediaReleasePath = function(url) {
  this.pathurl = url;
}

MediaReleaseManager.buildRequest = function() {
  
  _xmlRequestObj = new XMLRequest();
  
  _xmlRequestObj.setKey("wIDZW8Rta7Joo0mNE8GK8g==");
  
  _xmlRequestObj.setFunction("GetMediaReleases");
  
  _xmlRequestObj.addParam("categories",this.categories.join(","));
  
  if(this.language) {
    _xmlRequestObj.addParam("language",this.language);
  }
  
  if(this.limit) {
    _xmlRequestObj.addParam("limit",this.limit);
  }
  
  return _xmlRequestObj.toString();
}

function setParams() {
	try {
		dbg(lang);
		if( lang=='fr' ) lang='fr-ca';
	} catch(e) { 
		__rootCreate('lang');
		lang = 'en'; 	
	}

	try { dbg(categoryId); 	} catch(e) { __rootCreate('categoryId'); categoryId=4; }
	try { dbg(limit); 		} catch(e) { __rootCreate('limit'); limit=5; }
	try { dbg(showSubheadline); 	} catch(e) { __rootCreate('showSubheadline'); showSubheadline=false; }
	try { dbg(showAbstract); 	} catch(e) { __rootCreate('showAbstract'); showAbstract=false; }

	MediaReleaseManager.addCategory( categoryId );
	MediaReleaseManager.setLimit( limit );

	// e.g., http://www.cfs-fcee.ca/html/english/media/mediapage.php?release_id=930

	MediaReleaseManager.setLanguage( lang );
	MediaReleaseManager.setBaseURL( 'http://www.cfs-fcee.ca' );	
	MediaReleaseManager.setMediaReleasePath( '/html/' + ( lang=='fr-ca' ? 'french' : 'english' ) + '/media/mediapage.php' );
}

/* exMediaRelease */
function initMR() {
	
	if( !div('releases') ) return;
	
	setParams();

	if( 0 ) {
		var req = MediaReleaseManager.buildRequest();
		for(var i=0;i<100;i++)
			req=req.replace('><',">\n<");
		alert(MediaReleaseManager.parse);
		return alert( req );
	}
	
	var request = "/__national/?request=" + MediaReleaseManager.buildRequest();
	
	AjaxUpdater.add("GET",request, MediaReleaseManager.parse);
	AjaxUpdater.execute();

	//setInterval("AjaxUpdater.update('GET','" + request + "', MediaReleaseManager.parse)",5000);
	setInterval( AjaxUpdater.update.bind(AjaxUpdater,'GET', request, MediaReleaseManager.parse) , 60000 );
}

addLoadEvent( initMR );

/** CALENDAR **/

var toolTipActive = false;

var eventsCollection = new Array();

function doCalendarEvents() {
  if(!document.getElementById) return false;
  if(!document.getElementsByTagName) return false;
  
  var calendar = document.getElementById("calendar");
  

  if(calendar) {
    calendarHighlight(calendar);
  }
  
}

addLoadEvent(doCalendarEvents);

function calendarHighlight(calendar_id) {
  
	if (!calendar_id) {
		console.log('no');
		return false;
	}
    
	var days = calendar_id.getElementsByTagName("td");
    
	var month; 
	var year;
    
	for (var i = 0; i < days.length; i++) {
    
        if (days[i].className.match("with-events")) {
        
			timestamp = getEventDate(days[i]);
        
			if (typeof(year) == "undefined" && typeof(month) == "undefined") {
				year = timestamp.substr(0,4);
				month = timestamp.substr(5,2);
			}

			days[i].onmouseover = function(e) {
          
				removeTT(e);
          
				if (!this.className.match("blank") &&
					!this.className.match("frame") &&
					!this.className.match("side_column")) {
					
					this.style.backgroundColor = "#FFFFCC";
					
				}

				// if there is one or more event on a
				// day and a toolTip isn't already made

				if (this.className.match("with-events")) {

					// only display tool tip if none exists
					if(!toolTipActive) {

						// set tool tip to active state
						toolTipActive = true;

						// Get Coords to diplay tool tip
						var xCoord = findPos(this)[0] + this.offsetWidth;
						var yCoord = findPos(this)[1];

						var timestamp = getEventDate(this);
              
						displayToolTip(xCoord,yCoord,timestamp);

					}

				}

			}
			
			days[i].onmouseout = function() {
				if(this.getAttribute("id") == "today") {
					this.style.backgroundColor = "#FFEDDF"
				} else if(this.className.match("blank")) {
					this.style.backgroundColor = "#EFEFEF";
				} else if (this.className.match("event_day")) {
					this.style.backgroundColor = "#DFEBFF";
				} else if (this.className.match("frame") ||
					this.className.match("side_column")) {
					this.style.backgroundColor = "#cfcfcf";
				} else {
					this.style.backgroundColor = "#FFFFFF";
				}
			}

        }
        
	}
	
	loadEvents(month,year);
    
}

function getEventDate(element) {

	// the time stamp of the current day
	var timestamp = element.getElementsByTagName("a")[0].getAttribute("href");
  
	timestamp = timestamp.split('/');
  
	var arrayIndex = timestamp.length - 1;
  
	var day = timestamp[arrayIndex];
	arrayIndex -= 2;
	
	var month = timestamp[arrayIndex];
	arrayIndex -= 2;
	
	var year = timestamp[arrayIndex];

	if (parseInt(month) < 10){
		month = '0' + month;
	}

	if (parseInt(day) < 10){
		day = '0' + day;
	}
  
	return year + '-' + month + '-' + day;
  
}

function displayToolTip(xCoord,yCoord,timestamp) {
  
  var toolTipWidth = 200;
  var toolTipHeight = 100;
  
  var toolTip = document.createElement("div");
  toolTip.setAttribute("id","toolTip");
  toolTip.onmouseout = removeTT;
  
  // tool tip frame styles
  toolTip.style.position = "absolute";
  toolTip.style.left = xCoord + "px";
  toolTip.style.top = yCoord - 1 + "px";
  toolTip.style.width = toolTipWidth + "px";
  toolTip.style.minHeight = toolTipHeight + "px";
  toolTip.style.background = "#FFFFCC";
  toolTip.style.border = "1px solid #EFEFEF";
  toolTip.style.padding = "5px";
  
  document.body.appendChild(toolTip);
    
  displayCachedEvents(timestamp);
}

function removeToolTip() {
      
  var currentToolTip = document.getElementById("toolTip");

  if(currentToolTip) {
    document.body.removeChild(currentToolTip);
    
    // once tool tip is removed, reset
    // tool tip status to false
    toolTipActive = false;
  }
}

function removeTT(e) {
  
  if(!e) var e = window.event;
  
  // grab event target element
  var tg = (window.event) ? e.srcElement : e.target;
  
  // fix safari bug, grabs the right target for safari
  if(tg.nodeType == 3) { tg = tg.parentNode; }
  
  var eventType = e.type;
  
  if(tg.nodeName == "A" || tg.nodeName == "P") {
    // do nothing
  } else if(tg.nodeName == "TD" && eventType == "mouseout") {
    
    // do nothing
    
  } else if(tg.nodeName == "TD" && eventType == "mouseover") {
    
    removeToolTip();
    
  } else if (tg.nodeName != "DIV") {
      
    removeToolTip();
    
  } else if(tg.nodeName == "DIV") {
    
    if(mouseInside(tg,e)) {
      removeToolTip();
    }
    
  }
}

function mouseInside(tg,e) {
  currentX = findPos(tg)[0];
  currentY = findPos(tg)[1];
  
  // the minus 12 is for firefox - must be different for IE
  currentWidth = tg.offsetWidth - 12;
  currentHeight = tg.offsetHeight  - 12;
  
  if((e.clientX < currentX) || (e.clientX > (currentX + currentWidth)) ||
     (e.clientY < currentY) || (e.clientY > (currentY + currentHeight))) {

    return true;
               
  } else {
    
    return false;
  }
}

// returns 2 element array with x and y coords of element
function findPos(obj) {
  
	var curleft = curtop = 0;
	
	if (obj.offsetParent) {
  	
		curleft = obj.offsetLeft
		curtop = obj.offsetTop
		
		while (obj = obj.offsetParent) {
  		
			curleft += obj.offsetLeft
			curtop += obj.offsetTop
			
		}
	}
	
	return [curleft,curtop];
	
}

/* ---------------- ToolTip Ajax Functions Below -------- */

var xmlHttpToolTip;

function handleToolTip(){
    if (xmlHttpToolTip.readyState == 4){
        if (xmlHttpToolTip.status == 200){
            parseToolTip();
        }
    } else if (xmlHttpToolTip.readyState == 1) {
      showLoadAnimation();
    } else if (xmlHttpToolTip.readyState == 2 ) {
      clearLoadAnimation();
    }
}

function parseToolTip(){
  
  var allResults = xmlHttpToolTip.responseXML.getElementsByTagName("event");
  
  var result = null;
  
  if(allResults.length > 0) {
  
    for(var i = 0; i < allResults.length; i++) {
        
      result = allResults[i];
      eventUrl = result.getElementsByTagName("url")[0];
      title = result.getElementsByTagName("title")[0];
      info = result.getElementsByTagName("info")[0];
      timestamp = result.getElementsByTagName("start_date")[0];
      
      eventUrl = (eventUrl.hasChildNodes()) ? eventUrl.firstChild.nodeValue : "";
      title = (title.hasChildNodes()) ? title.firstChild.nodeValue : "";
      if( lang=='fr' ) {
	      info = (info.hasChildNodes()) ? info.firstChild.nodeValue + "..." : "Suivez le lien pour en savoir plus sur cette activit\u00e9.";
	  } else {
      	info = (info.hasChildNodes()) ? info.firstChild.nodeValue + "..." : "Follow the link to read more about this event.";
      }
      timestamp = (timestamp.hasChildNodes()) ? timestamp.firstChild.nodeValue.substr(0,10) : "";
      
      eventsCollection.push([timestamp,eventUrl,title,info]);
    }
  }
}

function checkEventCache(timestamp) {
  
  eventsLoaded = false;
  
  for(var i = 0; i < eventsCollection.length; i++) {
    if(eventsCollection[i][0] == timestamp) {
      eventsLoaded = true;
    }
  }
  
  return eventsLoaded;
  
}

function displayCachedEvents(timestamp) {
  
  var toolTip = document.getElementById("toolTip");
  
  var limit = 3;
  var eventCount = 0;
  
  if(eventsCollection.length) {
  
    for(var i = 0; i < eventsCollection.length; i++) {
      
      if((eventsCollection[i][0] == timestamp) && (eventCount < limit)) {
      
        eventLink = document.createElement("a");
        eventLink.setAttribute("href",eventsCollection[i][1]);
        eventLinkText = document.createTextNode(eventsCollection[i][2]);
        eventLink.appendChild(eventLinkText);
        toolTip.appendChild(eventLink);
        
        info = document.createElement("p");
        info.appendChild(document.createTextNode(eventsCollection[i][3]));
        toolTip.appendChild(info);
        
        eventCount++;        
      }
    }
    
    if(eventCount >= limit) {
      
      var url = eventsCollection[0][1].substr(0,eventsCollection[0][1].lastIndexOf("&"));
      url = url + "&date=" + timestamp;
      
      var allEventsLink = document.createElement("a");
      allEventsLink.setAttribute("href",url);
      //allEventsLinkText = document.createTextNode("View all events...");
      
      if( lang=='fr' ) {
      	allEventsLinkText = document.createTextNode("Pour voir toutes les activit\u00e9s...");
      } else {
      	allEventsLinkText = document.createTextNode("View all events...");
      }
      allEventsLink.appendChild(allEventsLinkText);
      
      toolTip.appendChild(allEventsLink);
    }
    
  } else {
    
    message = document.createElement("p");
    if( lang=='fr' ) {
    	message.appendChild(document.createTextNode("Veuillez attendre pendant le chargement des \u00e9v\u00e9nements..."));
    } else {
    	message.appendChild(document.createTextNode("Please Wait while events are loaded...")); 
    }
    //message.appendChild(document.createTextNode("Veuillez attendre pendant le chargement des événements..."));
    
    toolTip.appendChild(message);
    
  }
}

function loadEvents(month, year) {
	if( month==undefined || year==undefined ) return;
  
  var accountID = $j('#account_id').text();

  //var url = XMLRequestParamsURL('GetEvents','account_id',accountID,'month',month,'year',year);
  var url = "/__webservices/?method=getEvents&arg1="+accountID+"&arg2="+year+"&arg3="+month+"&arg4=true";
  
  //document.body.appendChild(document.createTextNode(url));
  
  xmlHttpToolTip = createXMLHttpRequest();
  xmlHttpToolTip.onreadystatechange = handleToolTip;
  xmlHttpToolTip.open("GET", url, true);
  xmlHttpToolTip.send(null);
}

// -->
