//Page framework written by Tyler Beck

// ----------------------------------------

function $(value)
{
	return document.getElementById(value);
}

// ----------------------------------------

function _(value)
{
	return document.getElementsByName(value);
}

// ----------------------------------------
// define frame name
frameName = '';
if (this.parent != null && this.name!= '')
{
	frameName = this.name;
}

// ----------------------------------------
// Define Page Framework
// ----------------------------------------
if (Page == null)
{
	//alert('INIT: PAGE');
	var Page = {
	
	version: 1,
	query: null,
	initialized: false,
	initializers: [],
	
	// ------------------------
	// abstract event target
	targetOf: function(event)
	{
		if (document.all)
		{
			return event.srcElement;
		}
		else
		{
			return event.target;
		}
	},

	// ------------------------
	// abstract add listener
	addEvent: function(o, e, f, s)
	{
   	var r = o[r = "_" + (e = "on" + e)] = o[r] || (o[e] ? [[o[e], o]] : []), a, c, d;
    	r[r.length] = [f, s || o], o[e] = function(e)
    	{
        try{
            (e = e || event).preventDefault || (e.preventDefault = function(){e.returnValue = false;});
            e.stopPropagation || (e.stopPropagation = function(){e.cancelBubble = true;});
            e.target || (e.target = e.srcElement || null);
            e.key = (e.which + 1 || e.keyCode + 1) - 1 || 0;
        }catch(f){}
        for(d = 1, f = r.length; f; r[--f] && (a = r[f][0], o = r[f][1], a.call ? c = a.call(o, e) : (o._ = a, c = o._(e), o._ = null), d &= c !== false));
        return e = null, !!d;
      }
	},
	
	// ------------------------
	// abstract remove listener
	removeEvent: function(o, e, f, s)
	{
		 for(var i = (e = o["_on" + e] || []).length; i;)
			  if(e[--i] && e[i][0] == f && (s || o) == e[i][1])
					return delete e[i];
		 return false;
	},
	
	// ------------------------
	// abstract eval
	evaluate: function(exp)
	{
			try
			{
				if (window.execScript)
				{
					window.execScript(exp);
				}
				else
				{
					eval(exp);
				}
			}
			catch(e)
			{
				if (Page.query['debugjs'] != null)
					alert ('Error: '+exp);
			}
	},


	// ------------------------
	// url encode
	encode: function(str)
	{
		str = str.replace(/%/g,'%25');
		str = str.replace(/ /g,'%20');
		str = str.replace(/</g,'%3C');
		str = str.replace(/>/g,'%3E');
		str = str.replace(/#/g,'%23');
		str = str.replace(/\{/g,'%7B');
		str = str.replace(/\}/g,'%7D');
		str = str.replace(/\|/g,'%7C');
		str = str.replace(/\\/g,'%5C');
		str = str.replace(/\^/g,'%5E');
		str = str.replace(/~/g,'%7E');
		str = str.replace(/\[/g,'%5B');
		str = str.replace(/\]/g,'%5D');
		str = str.replace(/`/g,'%60');
		str = str.replace(/;/g,'%3B');
		str = str.replace(/\//g,'%2F');
		str = str.replace(/\?/g,'%3F');
		str = str.replace(/\:/g,'%3A');
		str = str.replace(/@/g,'%40');
		str = str.replace(/=/g,'%3D');
		str = str.replace(/\&/g,'%26');
		str = str.replace(/\$/g,'%24');
		
		return str;
	},
	
	// ------------------------
	// looks for item in array
	inArray: function(item,arr)
	{
		for (var i in arr)
		{
			if (arr[i] == item)
				return true;
		}
		return false;
	},
	
	// ------------------------
	// determines if obj is string
	isString: function (obj)
	{
		return (typeof obj == "string");
	},

	// ------------------------
	// outputs str as html 
	//  contents of element
	output: function (element, str)
	{
		if (Page.isString(element))
			element = $(element);
		element.innerHTML = str;
	},
	
	// ------------------------
	// loads script into  
	//  contents of element
	loadScript: function (element, src)
	{
		if (Page.isString(element))
			element = $(element);
		
		var scr = document.createElement('script');
		scr.type = 'text/javascript';
		scr.src = src;
		element.appendChild(src);
	},
	
	// ------------------------
	// registers expression for
	// evaluation upon framework
	// initialization
	registerInitializer: function (exp)
	{
		if (!this.initialized)
			this.initializers.push(exp);
		else
			this.evaluate(exp);
	},
		
	// ------------------------
	// initialize framework
	initialize: function ()
	{
		if (!this.initialized)
		{
			//get query string
			var str;
			if (frameName == '')
				str = window.location.search;
			else
				str = frameName;
			var qindex = str.search(/\?/);
			var q = str.substring(qindex+1);
			this.query = new Object();
			if (q)
			{
				var fields = q.split('&');
				for (var n = 0; n < fields.length; n++) 
				{
					var field = fields[n].split('=');
					this.query[unescape(field[0])] = unescape(field[1]);
				}
			}
			//execute initialization expressions
			for (var i=0; i<this.initializers.length; i++)
			{
				this.evaluate(this.initializers[i]);
			}
			
			Page.images.preloadQueue.preload();
		}
		this.initialized = true;
	},
	
	// ------------------------
	// extends framework
	extend: function( properties ) 
	{
		for (var prop in properties)
		{
			this[prop] = properties[prop];
		}
		return true;
	},



// ----------------------------------------
// Define Style Sub-Framework
// ----------------------------------------
style: 
{	
	// ------------------------
	// sets element style
	setStyle: function(element, style, value)
	{
		if (Page.isString(element))
			element = $(element);
		
		if (element != null)
		{
			try
			{
				element.style[style] = value;
			}
			catch (e)
			{
				if (Page.query['debugjs'] != null)
					alert ('Error: '+exp);
			}
		}
	},
	
	// ------------------------
	// display styles
	displayNone: function(element)
	{
		this.setStyle(element,'display','none')
	},
	displayBlock: function(element)
	{
		this.setStyle(element,'display','block')
	},
	displayInline: function(element)
	{
		this.setStyle(element,'display','inline')
	},
	
	// ------------------------
	// visibility styles
	show: function(element)
	{
		this.setStyle(element,'visibility','visible')
	},
	hide: function(element)
	{
		this.setStyle(element,'visibility','hidden')
	}
},

// ----------------------------------------
// Define Image Sub-Framework
// ----------------------------------------

images: 
{
	// ------------------------
	// manages image preloading
	preloadQueue: 
	{
		queue: [],
		
		// ------------------------
		// add image to preload
		add: function(source, id)
		{
			this.queue.push( {source:source, id:id}) ;
		},
				
		// ------------------------
		// load next in queue
		preload: function()
		{	
			for (var i=0; i<this.queue.length; i++)
			{
				
				var obj = this.queue[i];
				var img = new Image();
				img.onload=function()
				{
					if (obj.id != null)
					{
						try
						{	
							$(obj.id).src = Page.images.preloadQueue.queue[i].src;
						}
						catch(e)
						{
							if (Page.query['debugjs'] != null)
								alert ('Error: '+exp)
						}
					}
				}
				img.src = obj.source;
				
			}
		}


	}
	
},

// ----------------------------------------
// Define Effect Sub-Framework
// ----------------------------------------
effects:
{	
	// ------------------------
	// tweens property
	tween: function(element,prop,from,to,step,total,rate,easing,isStyleProp,units)
	{		
		if (easing == null)
			easing = 'none';
		if (rate == null)
			rate = 30;
		isStyleProp = (isStyleProp == true || isStyleProp == 'true');
		if (units == null)
			units = '';
			
		if (Page.isString(element))
			element = $(element);
			
		if (step<=total)
		{
			var inc = this.ease(step,total,easing) * (to - from);
			var value = from + inc;
			if (units != '')
				value += units;

			if (isStyleProp)
				Page.style.setStyle(element,prop,value);
			else
				element[prop] = value;
		    setTimeout("Page.effects.tween('"+element.id+"','"+prop+"',"+from+","+to+","+(step+1)+","+total+","+rate+",'"+easing+"','"+isStyleProp+"','"+units+"')",rate);
		}
	},
	
	ease: function(step,total,type)
	{
		if (type == 'out')
		{
			var rate = 2;
			var start = (Math.pow(rate,total) - 1)/ (rate - 1);
			start = Math.pow(rate,total-1) / start;
			var s = 0;
			var inc = 0;
			if (step == total)
				return 1;
			while (s < step)
			{
				inc += start/Math.pow(rate,s);
				s++;
			}
			return inc;
		}
				
		return ( step/total );
	}
},

// ----------------------------------------
// Define Validation Sub-Framework
// ----------------------------------------
validate:
{	
	// ------------------------
	// email validation
	email: function(value,req)
	{
		if (req == null)
			req = false;
		
		if (value.length == 0 && req)
			return 'VE001';
			
		if (!value.match(/[a-z0-9!#$%&'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+\/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?/))
			return 'VE002';
			
		return '';
	},
	
	// ------------------------
	// us phone validation
	usphone: function(value,req)
	{
		if (req == null)
			req = false;
	
		if (value.length == 0)
			if(req)
				return 'VE001';
			else
				return '';
				
		//get rid of extraneous characters	
		value = value.replace( /[^0-9]+/g,'');
		if (value[0] == '1' || value[0] == '0')
			return 'VE003';
		if (value.length < 10)
			return 'VE003';
		if (value.length > 10)
			return 'VE003';
		return '';
	},
	
	// ------------------------
	// string validation
	string: function(value, min, max, req)
	{
		if (min == null)
			min = 0;
		if (max == null)
			max = 4000;
		if (value.length == 0 && req)
			return 'VE001';
		if (value.length < min)
			return 'VE004';
		if (value.length > max)
			return 'VE005';
		
		return '';
	},
	
	// ------------------------
	// number validation
	number: function(value, min, max, domain)
	{
		if (min == null)
			min = -0xFFFFFF;
		if (max == null)
			max = 0xFFFFFF;
		if (domain == null)
			domain = 'real';
		
			
		if (value.match(/[^0-9\.]+/g))
			return 'VE009';

		if (value.match(/[0-9]*\.[0-9]*\./g))
			return 'VE0010';
			
		value = Number(value);

		if (domain == 'int' && (value%1)!=0 )
			return 'VE006';
		
		if (value < min)
			return 'VE007';
			
		if (value > max)
			return 'VE008';
		
		return '';
	},
	
	// ------------------------
	// validation error lookup
	errors:
	{
		VE001: "The \"$1\" field is required",
		VE002: "The value entered for \"$1\" is not a valid email address",
		VE003: "The value entered for \"$1\" is not a valid 10-digit US phone number",
		VE004: "The value entered for \"$1\" is too short ",
		VE005: "The value entered for \"$1\" is too long ",
		VE006: "The value entered for \"$1\" must be a whole number",
		VE007: "The value entered for \"$1\" is too small",
		VE008: "The value entered for \"$1\" is too big",
		VE009: "The value entered for \"$1\" has invalid characters",
		VE010: "The value entered for \"$1\" has too many decimal points"
	},
	
	// ------------------------
	// validation error formatting
	getError: function(code,field)
	{
		var str = this.errors[code];
		if (str != null)
			str = str.replace(/\$1/g,field);
		
		return str;
	}
},

// ----------------------------------------
// Define AJAX Sub-Framework
// ----------------------------------------
ajax: 
{	
	// ------------------------
	// async requests
	requests: {},
	
	// ------------------------
	// loads dom document
	loadXMLData: function(path,params,requestId,process)
	{
		this.requests[requestId] = false;
		
		if(window.XMLHttpRequest && !(window.ActiveXObject)) 
		{
			// branch for native XMLHttpRequest object
			try 
			{
				this.requests[requestId] = new XMLHttpRequest();
			} 
			catch(e) 
			{
				this.requests[requestId] = false;
			}
		} 
		else if(window.ActiveXObject) 
		{
			// branch for IE/Windows ActiveX version
			try 
			{
				this.requests[requestId] = new ActiveXObject("Msxml2.XMLHTTP");
			} 
			catch(e) 
			{
				try 
				{
					this.requests[requestId] = new ActiveXObject("Microsoft.XMLHTTP");
				} 
				catch(e) 
				{
					this.requests[requestId] = false;
				}
			}
		}
		
		if(this.requests[requestId]) 
		{
			Page.evaluate("Page.ajax.requests['"+requestId+"'].onreadystatechange = "+process);
			this.requests[requestId].open("POST", path, true);
			this.requests[requestId].setRequestHeader("Content-type", "application/x-www-form-urlencoded");
			if (params != null)
			{
				if (!Page.isString(params))
				{
					var str = "";
					for (var i in params)
					{
						str+=i+"="+Page.encode(params[i])+"&";
					}
					params = str;
				}

				if (params.length > 0)
				{
					//alert('path: '+ path+'\nparams: '+params);
					this.requests[requestId].setRequestHeader("Content-type", "application/x-www-form-urlencoded");
					this.requests[requestId].setRequestHeader("Content-Length", params.length);
					this.requests[requestId].setRequestHeader("Connection", "close");

				}
			}
			
			this.requests[requestId].send( params );
		}
		
	},
	
	// ------------------------
	// loads text (synchronously)
	loadText: function (url,params)
	{
		var request = false;
		var str = '';
		
		if(window.XMLHttpRequest && !(window.ActiveXObject)) 
		{
			// branch for native XMLHttpRequest object
			try 
			{
				request = new XMLHttpRequest();
			} 
			catch(e) 
			{
				request = false;
			}
		} 
		else if(window.ActiveXObject) 
		{
			// branch for IE/Windows ActiveX version
			try 
			{
				request = new ActiveXObject("Msxml2.XMLHTTP");
			} 
			catch(e) 
			{
				try 
				{
					request = new ActiveXObject("Microsoft.XMLHTTP");
				} 
				catch(e) 
				{
					request = false;
				}
			}
		}
		
		if (request) 
		{
			request.open("POST", url, false);
			request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
			if (params != null)
			{
				if (!Page.isString(params))
				{
					var str = "";
					for (var i in params)
					{
						str+=i+"="+Page.encode(params[i])+"&";
					}
					params = str;
				}
				
				if (params.length > 0)
				{
					request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
					request.setRequestHeader("Content-Length", params.length);
					request.setRequestHeader("Connection", "close");
				}
			}
			
			str = request.send( params );
		}
		
		return str;
	},
	
	
	// ------------------------
	// loads xml and xsl to
	// apply to element
	transform: function (xml,xsl,element,callback,params)
	{
		if (callback == null)
			callback = '';
		
		var rid1 = ""+Math.round(Math.random()*1000000000000);
		var rid2 = ""+Math.round(Math.random()*1000000000000);
				
		var pr = "function(){ Page.ajax.transformationReadyStateChange('"+element+"','"+rid1+"','"+rid2+"','"+callback+"'); }";
		this.loadXMLData(xml,params,rid1,pr);
		this.loadXMLData(xsl,null,rid2,pr);

	},

	// ------------------------
	// xmlLoad state change handler
	transformationReadyStateChange: function(element,rid1,rid2,callback)
	{
		/*alert('transformationReadyStateChange: rs=['+
				Page.ajax.requests[rid1].readyState+','+
				Page.ajax.requests[rid2].readyState+'] status=['+
				Page.ajax.requests[rid1].status+','+
				Page.ajax.requests[rid2].status+'] ');*/
		
		if (Page.ajax.requests[rid1].readyState == 4 && Page.ajax.requests[rid2].readyState == 4) 
		{
			if (Page.ajax.requests[rid1].status == 200 && Page.ajax.requests[rid2].status == 200) 
			{
				//try
				//{
					//alert(Page.ajax.requests[rid1].responseText);
				//	alert(Page.ajax.requests[rid2].responseText);
					Page.ajax.applyTransformation(element,rid1,rid2,callback);
				//}
				//{
					//if (Page.query['debugjs'] != null)
				//		alert ('Error: XSL/XML transformation error - '+element);
				//}
			}
		}
	},

	// ------------------------
	// do transformation
	applyTransformation: function(element,rid1,rid2,callback)
	{				
		var str;
		var newdiv = document.createElement('div');
				
		if (window.ActiveXObject)
		{
			str = Page.ajax.requests[rid1].responseXML.transformNode(Page.ajax.requests[rid2].responseXML);
			newdiv.innerHTML = str;
			this.applyNodes(newdiv.childNodes, element);
		}
		else if (document.implementation && document.implementation.createDocument)
		{
			//alert(Page.ajax.requests[rid1].responseText);
			var xsltProcessor = new XSLTProcessor();
			xsltProcessor.importStylesheet(Page.ajax.requests[rid2].responseXML);
			var resultDocument = xsltProcessor.transformToFragment(Page.ajax.requests[rid1].responseXML, document);
			this.applyNodes(resultDocument.childNodes,element);
		}
		else
		{
			if (this.query['debugjs'] != null)
				alert ('Error: XSL/XML transformation browser support error - '+element);
		}
		
		if (callback != '')
		{
			try
			{
				Page.evaluate(callback);
			}
			catch(e)
			{
				if (Page.query['debugjs'] != null)
					alert ('Error: XSL/XML transformation callback error - '+element);
			}
		}
		
	},
	
	// ------------------------
	// load nodes into DOM so that
	// they're available to rest of
	// page
	applyNodes: function(nodes,element)
	{
		var frag = document.createDocumentFragment();
		var scripts = document.createDocumentFragment();

		while (nodes.length > 0)
		{
			var c = nodes[0];
			//only scripts that are children of root will execute!!!
			if (c.nodeName.toLowerCase() == 'script' &&
				 c.getAttribute('type') == 'text/javascript')
			{
				scripts.appendChild(c);
			}
			else
			{
				frag.appendChild(c);
			}
		}
		$(element).innerHTML = '';		
		$(element).appendChild(frag);
		//run scripts - mozilla executes scripts properly... no need for workaround

		if (Page.browser != null && Page.browser.browser != 'Firefox' && Page.browser.browser != 'Mozilla')
		{
			for (var i=0; i<scripts.childNodes.length; i++)
			{
				Page.evaluate(scripts.childNodes[i].innerHTML);
			}
		}
		else
		{
			$(element).appendChild(scripts);
		}
		
	}
	
}

}
}

