
/** helper functions **/

function getAll( el ) { 
	if( el.all ) { 
		return el.all; 
	} else { 
		return el.getElementsByTagName("*"); 
	} 
}

function addClass( el, className )
{
	var regex = new RegExp("\\b"+className+"\\b");
	var s = el.className;
	if( regex.exec( s ) )
	{
		return;
	}
	if( s!='' )
	{
		s = s + ' ';
	}
	s = s + className;
	return el.className = s;
}
function delClass( el, className )
{
	var regex = new RegExp("\\b"+className+"\\b");
	var s = el.className;
	s = s.replace( regex, '' );
	return el.className = s;
}

function hasClass( el, className )
{
	var regex = new RegExp("\\b"+className+"\\b");
	return regex.exec( el.className );
}

function addStyles(obj,styles) {
	if(typeof obj.style.cssText != 'undefined') {
		obj.style.cssText=styles;
	} else if(typeof obj.style.cssText == 'undefined' && typeof obj.style != 'undefined') {
		obj.style=styles;
	} else {
		obj.setAttribute("style",styles);
	}
}
	
function appendQuery( url, qs )
{
	return url + (url.match(/\?/) ? '&' : '?') + qs;
}

function labelFor( id )
{
	var els = document.getElementsByTagName('label');
	for( var i=0; i<els.length; i++ )
	{
		if( els[i].htmlFor == id || els[i].getAttribute('for') == id )
		{
			return els[i];
		}
	}
	return null;
}

function roundElementHeight( o )
{
	/* Stop Mozilla from creating a body scrollbar when siblings
	have computed heights with decimal parts.
	offsetHeight is the style.height + borders + paddings; we
	work out the border and padding dimensions by first
	setting the style.height to our target and checking offsetHeight
	again:
		style.height = offsetHeight - border+padding
		-> border+padding = offsetHeight - style.height
	*/
	var tmp;
	var diff;
	o.style.height = '';
	tmp = Math.ceil( o.offsetHeight );
	if( tmp == o.offsetHeight )
	{
		return;
	}
	o.style.height = tmp + 'px';
	diff = o.offsetHeight - tmp;
	tmp -= diff;
	o.style.height = tmp + 'px';
}


var scrollbar_removed = false;

var window_width;
var window_height;
function calc_window_dimensions()
{
	if (self.innerWidth)
	{
		window_width = self.innerWidth;
		window_height = self.innerHeight;
	}
	else if (document.documentElement && document.documentElement.clientWidth)
	{
		window_width = document.documentElement.clientWidth;
		window_height = document.documentElement.clientHeight;
	}
	else if (document.body)
	{
		window_width = document.body.clientWidth;
		window_height = document.body.clientHeight;
	}
}

function findPosX(obj)
{
	var curleft = 0;
	if (obj.offsetParent)
	{
		while (obj.offsetParent)
		{
			curleft += obj.offsetLeft;
			obj = obj.offsetParent;
		}
	}
	else if (obj.x)
		curleft += obj.x;

		var container = document.getElementById( 'container' );
// 	curleft -= container.offsetLeft;
	return curleft;
}

function findScrollPosX(obj)
{
	var pos=0;
	while( obj.parentNode ) {
		pos -= obj.scrollLeft;
		obj = obj.parentNode;
	}
	return pos;
}

function findScreenPosX(obj)
{
	return findPosX(obj) + findScrollPosX(obj);
	return curleft;
}

function camelcase(str)
{
	str=str.split(/\b/);
	var outstr = str[0];
	for(i=1;i<str.length;i++){
		outstr=outstr+str[i].charAt(0).toUpperCase()+str[i].substring(1)
	}
	return outstr.replace(/[^\w]/g,'');
}

function hyphenate(s)
{
	sa=s.replace(/[^\w\s]/g,'').split(/\b/);
	t=Array();
	for(i=0;i<sa.length;i++){
		ss=sa[i].replace(/[^\w]/g,'');
		if( ss == '' )
			continue;
		t[t.length] = ss;
	}
	return t.join('-');
}

function AJAX() {
	var o = false;
	/*@cc_on @*/
	/*@if (@_jscript_version >= 5)
 		try {
  			o = new ActiveXObject("Msxml2.XMLHTTP");
 		} catch (e) {
  			try {
   				o = new ActiveXObject("Microsoft.XMLHTTP");
  			} catch (E) {
   				o = false;
  			}
 		}
	@end @*/
	if (!o && typeof XMLHttpRequest!='undefined') {
		o = new XMLHttpRequest();
	}
	
	return o;
}

function ajax_callback(url, obj, fn)
{
	ajax = new AJAX();
	ajax.open("GET", url, true);
	ajax.onreadystatechange = function() { 
		if( ajax.readyState==4 ) {
			eval( 'obj.' + fn + '(ajax.responseText)' );
		}
	 };
	ajax.send(null);
}


/** src: http://www.netspade.com/articles/javascript/cookies.xml **/
/**
 * Sets a Cookie with the given name and value.
 *
 * name       Name of the cookie
 * value      Value of the cookie
 * [expires]  Expiration date of the cookie (default: end of current session)
 * [path]     Path where the cookie is valid (default: path of calling document)
 * [domain]   Domain where the cookie is valid
 *              (default: domain of calling document)
 * [secure]   Boolean value indicating if the cookie transmission requires a
 *              secure transmission
 */
function setCookie(name, value, expires, path, domain, secure)
{
    document.cookie= name + "=" + escape(value) +
        ((expires) ? "; expires=" + expires.toGMTString() : "") +
        ((path) ? "; path=" + path : "") +
        ((domain) ? "; domain=" + domain : "") +
        ((secure) ? "; secure" : "");
}

/**
 * Gets the value of the specified cookie.
 *
 * name  Name of the desired cookie.
 *
 * Returns a string containing value of specified cookie,
 *   or null if cookie does not exist.
 */
function getCookie(name)
{
    var dc = document.cookie;
    var prefix = name + "=";
    var begin = dc.indexOf("; " + prefix);
    if (begin == -1)
    {
        begin = dc.indexOf(prefix);
        if (begin != 0) return null;
    }
    else
    {
        begin += 2;
    }
    var end = document.cookie.indexOf(";", begin);
    if (end == -1)
    {
        end = dc.length;
    }
    return unescape(dc.substring(begin + prefix.length, end));
}

/**
 * Deletes the specified cookie.
 *
 * name      name of the cookie
 * [path]    path of the cookie (must be same as path used to create cookie)
 * [domain]  domain of the cookie (must be same as domain used to create cookie)
 */
function deleteCookie(name, path, domain)
{
    if (getCookie(name))
    {
        document.cookie = name + "=" + 
            ((path) ? "; path=" + path : "") +
            ((domain) ? "; domain=" + domain : "") +
            "; expires=Thu, 01-Jan-70 00:00:01 GMT";
    }
}

/** search document for elements with triggers and initialise them **/
addLoadEvent( function() { triggers( document ) } );

var g_triggers=null;
var g_trigger_direct = Array();
function trigger(fn,id,args)
{
	g_trigger_direct[g_trigger_direct.length] = Array(fn,id,args);
}

function triggers(el)
{
	var els = getAll(el);
	var regex = new RegExp(/\s(\w+)((\s(arg-[\w-]+\b))+|\b)/);
	var res;
	var parts;
	var k;
	var args;
	g_triggers = Array();
	
	for( var i=0; i<els.length; i++ )
	{
		// hack around IE's weird split
		x_class = ' ' + els[i].className;
		parts = x_class.split( /\bjs\b/ );
		for( var j=1; j<parts.length; j++ )
		{
			if( res = regex.exec(parts[j]) ) 
			{
				k = g_triggers.length;
				if( typeof eval( "window." + res[1] ) == 'function' ) {
					eval( "g_triggers[" + k + "] = new " + res[1] + "(" + k + ");" );
					g_triggers[k].init( els[i], res[2].replace( / arg-/g, ',' ).replace( /^,/, '' ) );
				}
			}
		}
	}
	
	var target_el;
	els = el.getElementsByTagName('script');
	regex = new RegExp("(\\w+)\\.(\\w+)\\(([^\\)]*)\\)");
	for( var i=0; i<els.length; i++ )
	{
		if( els[i].getAttribute('type') == 'text/x-trigger' )
		{
			if( res = regex.exec(els[i].innerHTML) )
			{
				switch( res[1] )
				{
				case 'next' :
					target_el = els[i].nextSibling;
					while( target_el.nodeName == '#text' )
						target_el = target_el.nextSibling;
					break;
				case 'previous' :
					target_el = els[i].previousSibling;
					while( target_el.nodeName == '#text' )
						target_el = target_el.previousSibling;
					break;
				case 'parent' :
					target_el = els[i].parentNode;
					break;
				default:
					target_el = document.getElementById( res[1] );
					break;
				}
				k = g_triggers.length;
				eval( "g_triggers[" + k + "] = new " + res[2] + "(" + k + ");" );
				g_triggers[k].init( target_el, res[3] );
			}
		}
	}
	
	for( i=0; i<g_trigger_direct.length; i++ )
	{
		target_el = document.getElementById( g_trigger_direct[i][1] );
		k = g_triggers.length;
		eval( "g_triggers[" + k + "] = new " + g_trigger_direct[i][0] + "(" + k + ");" );
		g_triggers[k].init( target_el, g_trigger_direct[i][2] );
	}
}

function minheight( trigger_id )
{
	this.trigger_id = trigger_id;
	
	this.init = function(el, args) {
		this.args = args;
		this.el = el;
		this.el.trigger = this;
		this.redraw();
	};
	
	this.redraw = function() {
		var res = this.args.split( /,/ );
		var min_h = this.el.offsetHeight;

		if( min_h < document.getElementById( res[0] ).offsetHeight ) {
			if( document.all ) {			
			    var agt=navigator.userAgent.toLowerCase();
				// ie 5.x has box model issues
				if( (parseInt(navigator.appVersion) == 4 && agt.indexOf("msie 5.0")!=-1) ||
					(parseInt(navigator.appVersion) == 4 && agt.indexOf("msie 5.5") !=-1) ) {
					res[1] = 0;
				}
				this.el.style.height = '' + (document.getElementById( res[0] ).offsetHeight - res[1]) + 'px';
			} else {
				this.el.style.minHeight = '' + (document.getElementById( res[0] ).offsetHeight - res[1]) + 'px';
			}
		}
		
		if( !scrollbar_removed ) {
			scrollbar_removed = true;
			removescrollbar();
		}
	};

}

function reltarget( trigger_id )
{
	this.trigger_id = trigger_id;
	this.target_id = null;
	this.state = 'init';
	this.xmlhttprequest = null;
	
	this.init = function( el, args )
	{
		this.el = el;
		this.args = args;
		this.el.trigger = this;
		this.el.onclick = function(e) { return this.trigger.onclick(e) };
		this.target_id = el.getAttribute('rel');
	}
	
	this.onclick = function(e) {
		
		if( this.state == 'loading' )
		{
			if( !this.abortrequest() )
			{
				return false;
			}
		}
		this.xmlhttprequest = new AJAX();
		el = document.getElementById( this.target_id );
		if( el == null )
		{
			return true;
		}
		this.state = 'loading';
		this.xmlhttprequest.open("GET", appendQuery(this.el.href,'js='+this.target_id), true);
		eval( 'this.xmlhttprequest.onreadystatechange = function() { g_triggers[' + this.trigger_id + '].onreadystatechange() }' );
		this.xmlhttprequest.send(null);
		setTimeout( "g_triggers[" + this.trigger_id + "].showloadmessage()", 400 );
		return false;
	};

	this.onreadystatechange = function(obj) {
		if( this.xmlhttprequest.readyState == 4 ) 
		{
			this.state = '';
			try
			{
				x_ajax = this.xmlhttprequest.getResponseHeader( 'x-ajax' );
			}
			catch(e)
			{
				window.location = this.el.href;
				return;
			}
			if( this.xmlhttprequest.responseText == '' )
			{
				return;
			}
			el = document.getElementById( this.target_id );
 			el.innerHTML = this.xmlhttprequest.responseText;
			triggers( document );
		}
	};
	
	this.showloadmessage = function() {
		if( 'loading' == this.state )
		{
			el = document.getElementById( this.target_id );
			el.innerHTML = '<p>Loading ...</p>';
		}
	};
	
	this.showabortmessage = function() {
		if( 'aborting' == this.state )
		{
			el = document.getElementById( this.target_id );
			el.innerHTML = '<p>Cancelled</p>';
		}
	};
	
	this.abortrequest = function() {
		this.state = 'aborting';
		this.showabortmessage();
		this.xmlhttprequest.abort();
		var abort_countdown = 5000;
		while( this.state != '' && abort_countdown-->0 );
		if( abort_countdown<0 )
		{
			return false;
		}
		return true;
	};
}

trigger_popup_window = false;
function popup(trigger_id)
{
	this.trigger_id = trigger_id;
	this.size = { small: [460,340], medium: [650,450], large: [800,720] };
	
	this.init = function( el, args )
	{
		el.trigger = this;
		if( this.size[args] )
		{
			this.width = this.size[args][0];
			this.height = this.size[args][1];
		}
		else
		{
			this.width = this.size['small'][0];
			this.height = this.size['small'][1];
		}
		el.onclick = function(e) { return this.trigger.onclick(this) }
	}
	
	this.onclick = function(a)
	{
		trigger_popup_window = window.open( a.href, 'trigger_popup_window', 'width='+ this.width + ',height='+this.height+',toolbar=no,directories=no,location=no,scrollbars=yes' );
		trigger_popup_window.focus();
		return false;
	}
}
function closepopup()
{
	if( trigger_popup_window )
	{
		trigger_popup_window.close();
	}
}

function a_targetgroup(trigger_id)
{
	this.trigger_id = trigger_id;
	
	this.init = function( el, args )
	{
		this.anchors = el.getElementsByTagName( 'A' );
		this.args = args.split( /,/ );
		for( var i=0; i<this.anchors.length; i++ )
		{
			this.anchors[i].trigger = this;
			this.anchors[i].onclick = function(e) { return this.trigger.onclick(this) };
		}
		var regex = new RegExp(/\b([\w-]+)\b/);
		var res;
		if( res = regex.exec( this.args[0] ) )
		{
			this.target_id = res[1];
		}
		this.set_title = (this.args[1]=='title');
	}

	this.onclick = function(srcel) {
		if( this.state == 'loading' )
		{
			if( !this.abortrequest() )
			{
				return false;
			}
		}
		this.xmlhttprequest = new AJAX();
		el = document.getElementById( this.target_id );
		if( el == null )
		{
			return true;
		}
		this.state = 'loading';
		this.href = srcel.href;
		this.xmlhttprequest.open("GET", appendQuery(srcel.href,'js=' + this.target_id), true);
		eval( 'this.xmlhttprequest.onreadystatechange = function() { g_triggers[' + this.trigger_id + '].onreadystatechange() }' );
		this.xmlhttprequest.send(null);
		if( this.set_title && '' != srcel.title )
		{
			document.title = srcel.title;
		}
		setTimeout( "g_triggers[" + this.trigger_id + "].showloadmessage()", 400 );
		return false;
	};

	this.onreadystatechange = function(obj) {
		if( this.xmlhttprequest.readyState == 4 ) 
		{
			this.state = '';
			if( this.xmlhttprequest.responseText == '' )
			{
				return;
			}
			try
			{
				x_ajax = this.xmlhttprequest.getResponseHeader( 'x-ajax' );
			}
			catch(e)
			{
				window.location = this.href;
				return;
			}
			el = document.getElementById( this.target_id );
 			el.innerHTML = this.xmlhttprequest.responseText;
			triggers( document );
			
			el = document.getElementById( 'content' );
			/* TODO: works in Moz, but not IE */
			el.scrollTop = 0; // Moz
			//el.style.top = '0';
		}
	};
	
	this.showloadmessage = function() {
		if( 'loading' == this.state )
		{
			el = document.getElementById( this.target_id );
			el.innerHTML = '<p><img src="/_img/loading.gif" /></p>';
		}
	};
	
	this.showabortmessage = function() {
		if( 'aborting' == this.state )
		{
			el = document.getElementById( this.target_id );
			el.innerHTML = '<p>Cancelled</p>';
		}
	};
	
	this.abortrequest = function() {
		this.state = 'aborting';
		this.showabortmessage();
		this.xmlhttprequest.abort();
		var abort_countdown = 5000;
		while( this.state != '' && abort_countdown-->0 );
		if( abort_countdown<0 )
		{
			return false;
		}
		return true;
	};
}

function maxheight( trigger_id )
{
	this.trigger_id = trigger_id;
	
	this.init = function(el, args) {
		this.el = el;
		this.others = args;
		this.el.trigger = this;
		this.myheight = 0;
		this.redraw(1);
		eval( "addEvent( window, 'resize', function() { g_triggers["+ this.trigger_id +"].redraw(); }, false )" );
	};
	
	this.redraw = function(init) {
		calc_window_dimensions();
		if( this.myheight == window_height )
		{
			return;
		}
		this.myheight = window_height;
		var el_height = window_height;
		var res = this.others.split( /,/ );
		var i=0, screen=(res[0]=='screen');
		if (screen )
		{
			i++;
		}
		for( ; i<res.length; i++ )
		{
			if( init )
			{
				roundElementHeight(document.getElementById( res[i] ));
			}
			el_height -= document.getElementById( res[i] ).offsetHeight;
		}
		if( screen && init )
		{
			this.min_el_height = this.el.offsetHeight;
		}
		if( screen && this.min_el_height < el_height )
		{
			this.el.style.height = '' + el_height + 'px';
			
		}
		if( !screen )
		{
			this.el.style.height = '' + el_height + 'px';
			this.el.style.overflow = 'auto';
		}
	};

}

function scrollpos( trigger_id )
{
	this.trigger_id = trigger_id;
	
	this.init = function(el, args) {
		if( undefined == el.id )
			return;
		this.el = el;
		this.el.trigger = this;
		this.cookie = 'scrollpos_' + this.el.id;
		eval( 'addUnLoadEvent( function() { g_triggers['+this.trigger_id+'].unload() } )' );
		this.move();
		if( this.el.scrollTop != getCookie( this.cookie ) )
		{
			eval( 'setTimeout( function() { g_triggers['+this.trigger_id+'].move() }, 100 )' );
		}
	}
	
	this.unload = function() {
		setCookie( this.cookie, this.el.scrollTop );
	}
	
	this.move = function() {
		this.el.scrollTop = getCookie( this.cookie );
	}
}

function removescrollbar() {
	if( document.all ) {
		document.documentElement.style.overflow = 'hidden';
		document.documentElement.childNodes[1].style.overflow = 'hidden';
	}
}

/** FORM element validation **/
triggers_validate = new Array();
triggers_validate['notnull'] = /.+/;
triggers_validate['email'] = /.+@.+/;
triggers_validate['url'] = /^\/.+/;
triggers_validate['date'] = /^\d{1,2}\/\d{1,2}\/\d{4}$/;
triggers_validate['color'] = /^#[a-f0-9A-F]{6}$/;
triggers_validate['number'] = /^[\d\.]*$/;
triggers_validate['number_notnull'] = /^[\d\.]+$/;

function validate( trigger_id )
{
	this.trigger_id = trigger_id;
	this.intimer = 0;

	this.init = function( el, args )
	{
		var regex = new RegExp("\\b([\\w-]+)\\b");
		if( res = regex.exec( args ) )
		{
			this.regex = new RegExp(triggers_validate[res[1]]);
			this.el = el;
			this.el.trigger = this;
			addEvent( this.el, 'keypress', function(e) { this.trigger.onkeypress(e); } );
			this.el.onchange = function(e) { return this.trigger.onchange(e) };
			this.el.onfocus = function(e) { return this.trigger.onfocus(e) };
			this.el.onblur = function(e) { return this.trigger.onblur(e) };
			this.el.insertstring = function(s) { return this.trigger.insertstring(this,s) };
			this.validate();
			if( this.el.form.onsubmit == undefined )
			{
				eval( 'this.el.form.onsubmit = function() { return g_triggers[' + this.trigger_id + '].onsubmit() }' );
			}
		}
	}
	
	this.validate = function()
	{
		if( this.regex.exec( this.el.value ) )
		{
			addClass( this.el, 'valid' );
			delClass( this.el, 'invalid' );
			
			var id = this.el.getAttribute('id')
			var msgel = document.getElementById( id + '_msg' )
			if( msgel )
			{
				addClass( msgel, 'validation' );
			}
			
			return true;
		}
		else
		{
			addClass( this.el, 'invalid' );
			delClass( this.el, 'valid' );
			return false;
		}
	}
	
	this.onchange = function(e)
	{
		this.validate();
	}
	this.onblur = function(e)
	{
		delClass( this.el, 'checking' );
		this.validate();
	}
	this.onfocus = function(e)
	{
		addClass( this.el, 'checking' );
		this.validate();
	}
	
	this.onkeypress = function(e)
	{
		if( !this.intimer )
		{
			this.intimer = 1;
			setTimeout( "g_triggers[" + this.trigger_id + "].keypresstimer()", 400 );
		}
	}
	this.keypresstimer = function()
	{
		this.intimer = 0;
		this.validate();
	}
	
	this.onsubmit = function()
	{
		var frm = this.el.form;
		var msg = '';
		var focussed = -1;
		var id;
		var msgel;
		mytypes = '';
		if( !hasClass(frm.clicked, 'validates') )
		{
			return true;
		}
		for( var i=0; i<frm.elements.length; i++ )
		{
			if( frm.elements[i].trigger != undefined )
			{
				id = frm.elements[i].getAttribute('id')
				msgel = document.getElementById( id + '_msg' )
				if( msgel )
				{
					if( frm.elements[i].trigger.validate() )
					{
						addClass( msgel, 'validation' );
					}
					else
					{
						delClass( msgel, 'validation' );
						if( focussed<0 )
						{
							focussed = i;
						}
					}
				}
				else
				{
					if( !frm.elements[i].trigger.validate() )
					{
						msg += '\n' + labelFor(frm.elements[i].getAttribute('id')).innerHTML + ' not entered correctly';
						if( focussed<0 )
						{
							focussed = i;
						}
					}
				}
			}
		}
		if( msg != '' )
		{
			alert( 'Please fix the following before submitting:' + msg );
		}
		frm.elements[focussed].focus();
		return false;
	}
	
	this.insertstring = function(el,s) {
		/* ref: http://www.howtocreate.co.uk/emails/Armand.html */
		el.focus();
		if( el.createTextRange ) 
		{
		   document.selection.createRange().text += s;
 		} else if( el.setSelectionRange ) 
		{
			var len = el.selectionEnd;
			el.value = el.value.substr( 0, len ) + s + el.value.substr( len );
			el.setSelectionRange(len+s.length,len+s.length);
		} else 
		{ 
			el.value += insText; 
		}
	}
}

function resizebar( trigger_id )
{
	this.trigger_id = trigger_id;
	
	this.init = function( el, args ) {
		if( typeof(el.resizebar_trigger) == 'object' )
		{
			/* don't add resizebars twice */
			return;
		}
		el.resizebar_trigger = this;
		this.el = el;
		el.style.width = parseInt(el.offsetWidth) + 'px';
		this.bar = document.createElement('div');
		this.bar.objParent = el;
		this.bar.className = 'resizebar_handle';
		addStyles( this.bar, 'left:0;top:0;height:0;' );
		eval( "addEvent( this.bar, 'mousedown', function(e) {g_triggers[" + this.trigger_id + "].set_position(e)})" );
		this.el.parentNode.insertBefore(this.bar, this.el.nextSibling);
	
		eval( "addEvent( window, 'resize', function(e) {g_triggers[" + this.trigger_id + "].window_resize(e)})" );
		eval( "addEvent( document, 'mousemove', function(e) {g_triggers[" + this.trigger_id + "].get_position(e)})" );
		eval( "addEvent( document, 'mouseup', function(e) {g_triggers[" + this.trigger_id + "].resize_element=null})" );
		this.window_resize();
	}
	
	this.get_position = function(e) {
		if( this.resize_element != null ) {
			var curEvent = ((typeof event == "undefined")? e: event);
			var newX = curEvent.clientX;
			var pixelMovement = parseInt(newX - this.cur_x);
			var newWidth = parseInt(this.width + pixelMovement);
			var newPos = parseInt(this.pos_x + pixelMovement);
			this.resize_element.style.width = newWidth + "px";
			this.resize_target_element.style.left = newPos + "px";
		}
	}
	
	this.set_position = function(e) {
		curEvent = ((typeof event == "undefined")? e: event);
		this.resize_element = (curEvent["target"] ? curEvent["target"] : curEvent["srcElement"]).objParent;
		this.resize_target_element = curEvent["target"] ? curEvent["target"] : curEvent["srcElement"];
		this.cur_x = curEvent.clientX;
		var tempWidth = this.resize_element.style.width;
		var widthArray = tempWidth.split("p");
		this.width = parseInt(widthArray[0]);
		var tempPos = this.resize_target_element.style.left;
		var posArray = tempPos.split("p");
		var oldPos = parseInt(posArray[0]);
		this.pos_x = parseInt(posArray[0]);
	}

	this.resize_bar = function() {
		if( null == this.bar ) return;
		this.bar.style.height = this.el.offsetHeight + 'px';
		this.bar.style.top = this.el.offsetTop + 'px';
		this.bar.style.left = this.el.offsetLeft + this.el.offsetWidth + 'px';
// 		addStyles( this.bar, 'left:' + p_left + ';top:' + p_top + ';height:' + p_height + ';' );
	}

	this.window_resize = function(e) {
		this.resize_bar();
	}

}

var qsParam = new Object();
function QueryString()
{
	var qs = window.location.search.substring(1);
	var params = qs.split("&");
	
	for ( var i = 0; i < params.length; i++ ) {
		var pairs = params[i].split("=");
		if ( pairs.length == 2 ) {
			qsParam[ pairs[0] ] = pairs[1];
		}
	}
	
}

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

function tagsuggest_popup( trigger_id )
{
	this.trigger_id = trigger_id;
	this.init = function(el,args) {
		this.el = el;
		this.args = args.split(",");
		var _self = this;
		
		QueryString();
		
		this.type = "";
		if ( "red" == qsParam["type"] ) {
			this.type = "tag[red]";
		} else if ( qsParam["field"] != "" ) {
			this.type = qsParam["field"];
		} else {
			this.type = "tag[white]";
		}
		
		for ( var i = 0; i < el.getElementsByTagName("div").length; i++ ) {
			el.getElementsByTagName("div")[i].onclick = function() {
				var value = opener.window.document.forms[_self.args].elements[ _self.type ].value;
				if ( "" == value ) {
					opener.window.document.forms[_self.args].elements[ _self.type ].value = this.innerHTML.trim();
				} else {
					opener.window.document.forms[_self.args].elements[ _self.type ].value += ", " + this.innerHTML.trim();
				}
			};
		}
	};
}

function tagsuggest( trigger_id )
{
	this.trigger_id = trigger_id;
	this.init = function(el,args) {
		this.el = el;
		this.args = args.split(",");
		var _self = this;
		
		for ( var i = 0; i < this.el.getElementsByTagName("span").length; i++ ) {
			this.el.getElementsByTagName("span")[i].onclick = function() {
				var value = document.forms[_self.args[1]].elements[_self.args[0]].value;
				if ( "" == value ) {
					document.forms[_self.args[1]].elements[_self.args[0]].value = this.innerHTML.trim();
				} else {
					document.forms[_self.args[1]].elements[_self.args[0]].value += ", " + this.innerHTML.trim();
				}
			}
		}
	};
}

function checkusername( trigger_id )
{
	this.trigger_id = trigger_id;
	var _self = this;

	this.init = function(el,args) {
		this.el = el;
		this.args = args.split(",");
		
		_self.xmlhttprequest = new AJAX();
		el.onclick = this.onclick;
	};
	
	this.onclick = function() {
		var username = _self.el.parentNode.firstChild.value;
		if ( "" == username ) {
			document.getElementById( _self.args[0] ).innerHTML = "";
			document.getElementById( _self.args[0] ).style.display = "none";
			return;
		}
		
		_self.xmlhttprequest.open("GET", appendQuery(window.location.href,'js=check-username&username=' + username), true);
		eval( '_self.xmlhttprequest.onreadystatechange = function() { g_triggers[' + _self.trigger_id + '].onreadystatechange() }' );
		_self.xmlhttprequest.send(null);
	};

	this.onreadystatechange = function(obj) {
		if( this.xmlhttprequest.readyState == 4 ) 
		{
			if( this.xmlhttprequest.responseText == '' )
			{
				document.getElementById( this.args[0] ).innerHTML = "";
				document.getElementById( this.args[0] ).style.display = "none";
				return;
			}
			if ( this.xmlhttprequest.responseText == 0 ) {
				document.getElementById( this.args[0] ).innerHTML = "Username Available";
				document.getElementById( this.args[0] ).style.color = "#2CA015";
				document.getElementById( this.args[0] ).style.display = "inline";
			} else {
				document.getElementById( this.args[0] ).innerHTML = "Username in use";
				document.getElementById( this.args[0] ).style.color = "#FF0000";
				document.getElementById( this.args[0] ).style.display = "inline";
			}
		}
	};

}

function get_winery_options( trigger_id )
{
	this.trigger_id = trigger_id;
	var _self = this;
	
	this.init = function(el,args) {
		this.el = el;
		this.args = args.split(",");
		
		_self.xmlhttprequest = new AJAX();
		
		this.el.onchange = function() {
			var value = this.options[this.selectedIndex].value;
			_self.xmlhttprequest.open("GET", appendQuery('/_js/winery_options.php','region=' + value), true);
			eval( '_self.xmlhttprequest.onreadystatechange = function() { g_triggers[' + _self.trigger_id + '].onreadystatechange() }' );
			_self.xmlhttprequest.send(null);
		};
		
	};
	
	this.onreadystatechange = function() {
		if( this.xmlhttprequest.readyState == 4 ) {
			if ( typeof this.xmlhttprequest.responseXML != 'undefined' ) {
				var winery = document.forms[ this.args[1] ].elements[ this.args[0] ];
				var options = this.xmlhttprequest.responseXML.getElementsByTagName( "option" );
				var option;
				
				winery.innerHTML = "";
				for ( var i = 0; i < options.length; i++ ) {
					option = document.createElement("option");
					option.value = options[i].getAttribute("value");
					option.appendChild( document.createTextNode(options[i].firstChild.nodeValue) );
					winery.appendChild( option );
				}
			}
		}
	};
	
};

function switch_search( trigger_id )
{
	this.trigger_id = trigger_id;
	
	this.init = function( el, args ) {
		this.el = el;
		this.args = args.split(",");
		
		this.el.onclick = function() {
			document.forms["search"].elements["keyword"].value = document.forms["search"].elements["s_keyword"].value;
			var Srdo = document.forms["search"].elements["s_filter"];
			var Ardo = document.forms["search"].elements["filter"];
			for ( var i = 0; i < Srdo.length;i++ ) {
				if ( Srdo[i].checked ) {
					Ardo[i].checked = "checked";
				}
			}
			
			document.getElementById( "advanced").style.display = "block";
			document.getElementById( "simple").style.display = "none";
		};
	};
};

function getElementsByClassName( el, classname ) {
	var node = el;
	var nodes = node.getElementsByTagName( "*" );
	
	var els = new Array(), j = 0;
	for ( var i = 0; i < nodes.length; i++ ) {
		if ( hasClass( nodes[i], classname ) ) {
			els[j] = nodes[i];
			j++;
		}
	}
	
	return els;
};

function locationchange( trigger_id )
{
	
	this.trigger_id = trigger_id;
	
	this.init = function( el, args )
	{
		this.el = el;
		this.args = args;
		var _self = this;
		
		this.country = getElementsByClassName( this.el, "country" );
		this.city = getElementsByClassName( this.el, "city" );
		
		this.on_val = !document.all ? "table-row" : "block";
		for ( var i = 0; i < el.elements["location"].length; i++ ) {
			el.elements["location"][i].onclick = function(e) {
				on_val = e ? "table-row" : "block";
				if ( this.checked ) {
					_self.country[0].style.display = this.value == "row" ? _self.on_val : "none";
					_self.city[0].style.display = this.value == "row" ? "none" : self.on_val;
				}
			};
			
			if ( el.elements["location"][i].checked ) {
				_self.country[0].style.display = el.elements["location"][i].value == "row" ? _self.on_val : "none";
				_self.city[0].style.display = el.elements["location"][i].value == "row" ? "none" : _self.on_val;
			}
		}
	};
	
}

function star_rating( trigger_id )
{
	this.trigger_id = trigger_id;
	this.rate_enabled = true;
	
	this.init = function( el, args )
	{
		this.el = el;
		this.args = args;
		
		this.form = document.forms["wine-vintage"];
		var current = this.form.elements[ this.args ].value;
		
		
		this.divs = el.getElementsByTagName( "div" );
		for ( var i = 0; i < this.divs.length; i++ ) {
			eval( "this.divs[i].onmouseover = function(e) { g_triggers[" + this.trigger_id + "].onmouseover(e); return false;}" );
			eval( "this.divs[i].onmouseout = function(e) { g_triggers[" + this.trigger_id + "].onmouseout(e); return false;}" );
			eval( "this.divs[i].onclick = function(e) { g_triggers[" + this.trigger_id + "].onclick(e); return false;}" );
		}
	};
	
	this.onmouseover = function(e) {
		if ( !this.rate_enabled ) {
			return;
		}
		
		var src = e ? e.target : window.event.srcElement;
		var classnames = src.className.split(" ");
		
		var num = 0, score = 0, text = "";
		switch ( classnames[1] )
		{
		case "one":
			num = classnames[0] =="leftstar" ? 1 : 2;
			score = classnames[0] =="leftstar" ? .5 : 1;
			text = classnames[0] == "leftstar" ? "not good (&lt;80/100)" : "not bad (80-84/100)";
			break;
		case "two":
			num = classnames[0] == "leftstar" ? 3 : 4;
			score = classnames[0] == "leftstar" ? 1.5 : 2;
			text = classnames[0] == "leftstar" ? "not bad (80-84/100)" : "decent (85-87/100)";
			break;
		case "three":
			num = classnames[0] =="leftstar" ? 5 : 6;
			score = classnames[0] =="leftstar" ? 2.5 : 3;
			text = classnames[0] =="leftstar" ? "decent (85-87/100)" : "good (88-90/100)";
			break;
		case "four":
			num = classnames[0] =="leftstar" ? 7 : 8;
			score = classnames[0] =="leftstar" ? 3.5 : 4;
			text = classnames[0] =="leftstar" ? "good (88-90/100)" : "really good (91-94/100)";
			break;
		case "five":
			num = classnames[0] =="leftstar" ? 9 : 10;
			score = classnames[0] =="leftstar" ? 4.5 : 5;
			text = classnames[0] =="leftstar" ? "really good (91-94/100)" : "out of this world (&gt;95/100)";
			break;
		}
		
		this.form.elements[ this.args ].value = score;
		
		for ( var i = 0; i < this.divs.length; i++ ) {
			this.divs[i].style.backgroundPosition = "0px 0px";
		}
		
		if ( num > 0 ) {
			for ( var i = 0; i < num; i++ ) {
				this.divs[i].style.backgroundPosition = "0px 36px";
			}
		}
		
		getElementsByClassName( this.el.parentNode.parentNode, this.args )[1].innerHTML = text;
	};
	
	this.onmouseout = function(e) {
		if ( !this.rate_enabled ) {
			return;
		}
		
		var event = e ? e : window.event;
		var src = e ? e.target : window.event.srcElement;
		var classnames = src.className.split(" ");
		
		var el_pos = findScreenPosX( src );
		var mouse_pos = event.pageX ? event.pageX : event.clientX - 2;
		
		if ( this.rate_enabled )
		{
			if ( classnames[1] == "one" ) {
				if ( el_pos > mouse_pos ) {
					this.divs[0].style.backgroundPosition = "0px 0px";
					this.form.elements[ this.args ].value = 0;
					getElementsByClassName( this.el.parentNode.parentNode, this.args )[1].innerHTML = "not good (&lt;80/100)";
				}
			}
		}
	};
	
	this.onclick = function(e) {
		this.rate_enabled = this.rate_enabled ? false : true;
	};
	
}

function introtext( trigger_id )
{
	this.trigger_id = trigger_id;
	
	this.init = function(el, args)
	{
		this.el = el;
		this.args = args;
		this.text = el.innerHTML;
		var _self = this;
		
		while (this.el.hasChildNodes()) this.el.removeChild(this.el.firstChild);
		
		this.a = document.createElement( "a" );
		this.a.className = "intro";
		this.a.appendChild( document.createTextNode( "Click here for introduction" ) );
		this.a.onclick = function() { 
			_self.a.innerHTML = "none" == _self.div.style.display ? "Hide Introduction" : "Click here for introduction";
			_self.div.style.display = "none" == _self.div.style.display ? "block" : "none";
		};
		
		this.div = document.createElement( "div" );
		this.div.innerHTML = this.text;
		this.div.style.display = "none";
		
		this.el.appendChild( this.a );
		this.el.appendChild( this.div );
	};

}

g_open_folder = 0;
function open_folder( trigger_id )
{
	this.trigger_id = trigger_id;
	this.init = function(el,args){
		if( g_open_folder != 0 )
		{
			img = document.getElementById( 'folder_' + g_open_folder );
			delClass( img, "open" )
		}
		g_open_folder = args;
		img = document.getElementById( 'folder_' + g_open_folder );
		addClass( img, "open" )
	}
}

function suggest_winery( trigger_id )
{
	this.trigger_id = trigger_id;
	this.init = function(el,args)
	{
		this.args = args.split(/,/);
		this.el = el;
		this.ajax = new Array();
		this.ajax_count = 0;
		
		this.winerylist = document.getElementById( this.args[0] );
		this.winelist = document.getElementById( this.args[1] );
		this.vintagelist = document.getElementById( this.args[2] );
		this.winelabel = document.getElementById( this.args[3] );
		this.step_4 = document.getElementById(this.args[4]);
		eval( "addEvent( el, 'keyup', function(e) { g_triggers["+ this.trigger_id +"].onchange(e); }, false )" );
	}

	this.onchange = function(e)
	{
		this.ajax_count++;		
		if (this.el.value == "")
		{
			this.populate();
			return;
		}
		var url = "/_js/suggest-winery.js?q=" + encodeURIComponent(this.el.value) + "&jseq=" + this.ajax_count;
		var i = "i" + this.ajax_count;	
		

		this.ajax[i] = new AJAX();
		eval( "this.ajax[i].onreadystatechange = function() { g_triggers["+ this.trigger_id +"].ajaxcallback('" + i + "'); } " );
		this.ajax[i].open("GET", url, true);		
		this.ajax[i].send(null);
	}

	this.ajaxcallback = function(i)
	{ 
		if( this.ajax[i].readyState==4 )
		{
			x_ajax = this.ajax[i].getResponseHeader( 'X-AJAX' );
			if ( parseInt(x_ajax) != this.ajax_count )
			{
				return;
			}
			var options = new Array();
			var labels = this.ajax[i].responseXML.getElementsByTagName("i");

			for (var l=0; l < labels.length; l++)
			{	
				options[labels.item(l).attributes[0].value] = labels.item(l).childNodes[0].nodeValue;
			}
			this.populate(options);	

			delete this.ajax[i];	
		}	
	}

	this.populate = function(options)
	{	
		this.winerylist.options.length = 0;
		for (var i in options)
		{
			this.winerylist.options[this.winerylist.options.length] = new Option(options[i], i);
		}
		this.winelist.options.length = 0;
		this.winelist.options[this.winelist.options.length] = new Option("no winery selected in 'Step 1' yet", "");
		this.vintagelist.options.length = 0;
		this.vintagelist.options[this.vintagelist.options.length] = new Option("no wine selected in 'Step 2' yet", "");
		this.winelabel.innerHTML = "no year (vintage) selected in 'Step 3' yet";
		this.step_4.style.display = "none";
	}
}

function suggest_wine( trigger_id )
{
	this.trigger_id = trigger_id;
	this.init = function(el,args)
	{
		this.args = args.split(/,/);
		this.el = el;
		this.ajax = new Array();
		this.ajax_count = 0;
		
		this.winelist = document.getElementById( this.args[0] );
		this.vintagelist = document.getElementById( this.args[1] );
		this.winelabel = document.getElementById( this.args[2] );
		this.step_4 = document.getElementById(this.args[3]);
		eval( "addEvent( el, 'change', function(e) { g_triggers["+ this.trigger_id +"].change(e); }, false )" );		
	}

	this.change = function(e)
	{
		var url = "/_js/suggest-wine.js?winery=" + encodeURIComponent(this.el.value) + "&jseq=" + this.ajax_count;
		var i = "i" + this.ajax_count++;
		this.ajax[i] = new AJAX();
		eval( "this.ajax[i].onreadystatechange = function() { g_triggers["+ this.trigger_id +"].ajaxcallback('" + i + "'); } " );
		this.ajax[i].open("GET", url, true);		
		this.ajax[i].send(null);
	}

	this.ajaxcallback = function(i)
	{ 
		if( this.ajax[i].readyState==4 ) {
			var options = new Array();
			var labels = this.ajax[i].responseXML.getElementsByTagName("i");

			for (var l=0; l < labels.length; l++)
			{	
				options[labels.item(l).attributes[0].value] = labels.item(l).childNodes[0].nodeValue;
			}
			this.populate(options);
			
			delete this.ajax[i];	
		}	
	}

	this.populate = function(options)
	{
		this.winelist.options.length = 0;
		for (var i in options)
		{
			this.winelist.options[this.winelist.options.length] = new Option(options[i], i);
		}
		if (this.winelist.options.length == 0)
		{
			this.winelist.options[this.winelist.options.length] = new Option("there are no wines listed for this winery yet,", "");
			this.winelist.options[this.winelist.options.length] = new Option("add one by clicking the link below this box", "");
		}
		this.vintagelist.options.length = 0;
		this.vintagelist.options[this.vintagelist.options.length] = new Option("no wine selected in 'Step 2' yet", "");
		this.winelabel.innerHTML = "no year (vintage) selected in 'Step 3' yet";
		this.step_4.style.display = "none";
	}
}

function suggest_vintage( trigger_id )
{
	this.trigger_id = trigger_id;
	this.init = function(el,args)
	{
		this.args = args.split(/,/);
		this.el = el;
		this.ajax = new Array();
		this.ajax_count = 0;
		
		this.vintagelist = document.getElementById( this.args[0] );
		this.winelabel = document.getElementById( this.args[1] );
		this.step_4 = document.getElementById(this.args[2]);
		eval( "addEvent( el, 'change', function(e) { g_triggers["+ this.trigger_id +"].change(e); }, false )" );
	}

	this.change = function(e)
	{
		var url = "/_js/suggest-vintage.js?wine=" + encodeURIComponent(this.el.value) + "&jseq=" + this.ajax_count;
		var i = "i" + this.ajax_count++;
		this.ajax[i] = new AJAX();
		eval( "this.ajax[i].onreadystatechange = function() { g_triggers["+ this.trigger_id +"].ajaxcallback('" + i + "'); } " );
		this.ajax[i].open("GET", url, true);
		this.ajax[i].send(null);
	}

	this.ajaxcallback = function(i)
	{ 
		if( this.ajax[i].readyState==4 ) {
			var options = new Array();
			var labels = this.ajax[i].responseXML.getElementsByTagName("i");

			for (var l=0; l < labels.length; l++)
			{	
				options[labels.item(l).attributes[0].value] = labels.item(l).childNodes[0].nodeValue;
			}
			this.populate(options);

			delete this.ajax[i];	
		}	
	}

	this.populate = function(options)
	{
		this.vintagelist.options.length = 0;
		for (var i in options)
		{
			this.vintagelist.options[this.vintagelist.options.length] = new Option(options[i], i);
		}
		if (this.vintagelist.options.length == 0)
		{
			this.vintagelist.options[this.vintagelist.options.length] = new Option("there are no vintages listed for this wine yet,", "");
			this.vintagelist.options[this.vintagelist.options.length] = new Option("add one by clicking the link below this box", "");
		}
		this.winelabel.innerHTML = "no year (vintage) selected in 'Step 3' yet";
		this.step_4.style.display = "none";
	}
}

function select_wine( trigger_id )
{
	this.trigger_id = trigger_id;
	this.init = function(el,args)
	{
		this.args = args.split(/,/);
		this.el = el;
		this.ajax = new Array();
		this.ajax_count = 0;

		this.winelabel = document.getElementById( this.args[0] );
		this.detailed_review = document.getElementById(this.args[1] );
		this.step_4 = document.getElementById(this.args[2] );
		this.step_4_form = document.getElementById(this.args[3] );
		this.mode = this.args[4];

		eval( "addEvent( el, 'change', function(e) { g_triggers["+ this.trigger_id +"].change(e); }, false )" );		
	}

	this.change = function(e)
	{
		var url = "/_js/select-vintage.js?vintage=" + encodeURIComponent(this.el.value) + "&jseq=" + this.ajax_count;
		var i = "i" + this.ajax_count++;
		this.ajax[i] = new AJAX();
		eval( "this.ajax[i].onreadystatechange = function() { g_triggers["+ this.trigger_id +"].ajaxcallback('" + i + "'); } " );
		this.ajax[i].open("GET", url, true);		
		this.ajax[i].send(null);
	}

	this.ajaxcallback = function(i)
	{ 
		if( this.ajax[i].readyState==4 ) {
			var options = new Array();
			var labels = this.ajax[i].responseText;
			this.populate(this.decode(labels));	
			delete this.ajax[i];
		}			
	}

	this.decode = function(s)
	{
		var r = new Array();
		var parts = s.split(/&/);
		for( var i in parts ) {
			var nv = parts[i].split('=');
			var n = decodeURIComponent(nv[0]);
			var v = decodeURIComponent(nv[1]);
			r[n] = v;
		}
		return r;
	}

	this.populate = function(result)
	{
		this.winelabel.innerHTML = result["label"];
		this.step_4.style.display = "";

		if (this.mode == "cellar")
		{
			this.step_4_form.action = result["url"] + "/" + this.mode;
		}
		else
		{
			this.step_4_form.action = result["url"];
			this.detailed_review.href = result["url"] + "/" + this.mode;
		}
	}
}



function cellar_quantity( trigger_id )
{
	this.trigger_id = trigger_id;
	this.init = function(el,args)
	{
		this.args = args.split(/,/);
		this.el = el;

		this.step_4_form = document.getElementById(this.args[0] );

		eval( "addEvent( el, 'change', function(e) { g_triggers["+ this.trigger_id +"].change(e); }, false )" );		
	}

	this.change = function(e)
	{
		var url = this.step_4_form.action.split('?');
		this.step_4_form.action = url[0];

		if (this.el.value > 0)
		{
			this.step_4_form.action = this.step_4_form.action + "?qty=" + encodeURIComponent(this.el.value);
		}
	}
}