/****************************************************************************************
*	file		: clientscript/global.js
*
*	Global javascript functions and variables
*
****************************************************************************************/

/*
*	Global variables
*/
var is_opera  	= (navigator.userAgent.toLowerCase().indexOf('opera') != -1 || (typeof(window.opera) != 'undefined') ? true : false);
var is_safari 	= (navigator.userAgent.toLowerCase().indexOf('applewebkit') != -1 || (navigator.vendor == 'Apple Computer, Inc.') ? true : false);
var is_ie    	= (navigator.userAgent.toLowerCase().indexOf('msie') != -1 && (!is_opera) && (!is_safari) ? true : false);
var is_mozilla	= (navigator.product == 'Gecko' && !is_safari ? true : false);

var PDIR = 'http://www.beije.fi/'

/***************************************************************************************
* Global init function
*
*/
function core_init()
{
	//
	// Session keepalive
	//
	setInterval(
		function()
		{
			var a = new ajax_handler(false);
			a.post( PDIR+'ajax.php?do=session_keepalive' );
		}
		,120000
	);

	//
	// Initialize tooltips
	//
	if( typeof window.register_tooltip == 'function' )
	{
		var tags = fetchtags_by_classname( document, 'tooltipitem', true );
		var len = tags.length;
		
		for( var i = 0; i < len; i++ )
		{
			if( tags[i].id == '' )
			{
				tags[i].id = 'tt_'+gen_random(8);
			}
			
			register_tooltip(tags[i].id);
		}
	}
	
	//
	// Onresize and onscroll functions
	//
	window.onresize = function()
	{
		if( typeof dialogs == 'object' )
		{
			for( i in dialogs )
			{
				if( dialogs[i].visible )
				{
					dialogs[i].updateposition();
				}
			}
		}
	};


	window.onscroll = function()
	{
		if( typeof dialogs == 'object' )
		{
			for( i in dialogs )
			{
				if( dialogs[i].visible )
				{
					dialogs[i].updateposition();
				}
			}
		}
	};
}



/***************************************************************************************
* Generate a random string
*
* @param	stringlen 	Length of the string
* @param usechars		Which characters to use
*
* @return				string
*/
function gen_random( stringlen, usechars )
{
	if( !stringlen )
		stringlen = 3;
		
	if( !usechars )
		usechars = 'all';
	
	switch( usechars )
	{	
		case 'all': 		var chars = "abcdefghijklmnopqrstuvxyzABCDEFGHIJKLMNOPQRSTUVXYZ1234567890"; break;
		case 'numbers': 	var chars = "1234567890"; break;
		case 'chars': 		var chars = "abcdefghijklmnopqrstuvxyzABCDEFGHIJKLMNOPQRSTUVXYZ"; break;
	}
	
	var string = '';
	
	for( var i=0; i<stringlen; i++ )
	{
		var rnum = Math.floor( Math.random() * chars.length );
		string += chars.substring(rnum,rnum+1);
	}
	
	
	return string;
}


/***************************************************************************************
* Prevents event bubbling
*
* @param	event					Event object
* @param preventdefault		If e.preventDefault() should be runt to halt the current event
*
* @return	event
*/
function do_event( eobj, preventdefault )
{
	if( !eobj || is_ie )
	{
		window.event.cancelBubble = true;

		if( preventdefault )
		{
			window.event.returnValue = false;
		}
		
		return window.event;
	}
	else
	{
		eobj.stopPropagation();
		
		if( preventdefault )
		{
			eobj.preventDefault();
		}
		
		return eobj;
	}
}



/***************************************************************************************
*	Get an element by its id
*
*	@param idname	ID of the tag to fetch
*
*	@return object
*/
function getbyid( idname )
{
	if( typeof(idname) == 'object' )
	{
		return idname;
	}
	
	if( document.getElementById )
	{
		return document.getElementById(idname);
	}
	else if( document.all )
	{
		return document.all[idname];
	}
	else
	{
		return false;
	}
}

/***************************************************************************************
*	Fetch tags by tagname from parent-object
*
*	@param parent		Parent object in which to search for tags
*	@param tagname		Type of tags to fetch
*
*	@return array
*/
function fetchtags( parent, tagname )
{
	if( parent == null )
	{
		return false;
	}
	else if( typeof parent.getElementsByTagName != 'undefined' )
	{
		return parent.getElementsByTagName(tagname);
	}
	else if( parent.all && parent.all.tags )
	{
		return parent.all.tags(tagname);
	}
	else
	{
		return new Array();
	}
}

/***************************************************************************************
*	Fetch tags by class name from parent-object
*
*	@param parent		Parent object in which to search for tags
*	@param classname	The classname to search for
*	@param fetchall	If true fetch all tags that match the classname, if false fetch only the first
*
*	@return mixed array|object|false
*/
function fetchtags_by_classname( parent, classname, fetchall )
{
	fetchall = ( fetchall ? true : false );
	
	var tags = fetchtags(parent, '*');
	var len = tags.length;
	var matches = new Array();
	
	for( var i = 0; i < len; i++ )
	{
		if( hasclass(tags[i], classname) )
		{
			if( fetchall )
			{
				matches.push(tags[i]);
			}
			else
			{
				return tags[i];
			}
		}
	}
	
	if( fetchall )
	{
		return matches;
	}
	
	return false;
}


/***************************************************************************************
*	Create an element
*
*	@param elementtype	Type of element to create
*
*	@return object
*/
function createelement( elementtype )
{
	return document.createElement( elementtype );
}

/***************************************************************************************
*	Get an objects parent element
*
*	@param object	child object
*
*	@return object	parent object
*/
function getparent( obj )
{
	if( typeof obj != 'object' )
	{
		obj = getbyid(obj);
	}
	
	if( obj.parentNode ) 
	{
		return obj.parentNode;
	}
	
	return false;
}


/*
* ##########################################################################################################################################
* #
* #	String functions
* #
* ##########################################################################################################################################
*/
/***************************************************************************************
*	Gets a strings length
*
*	@param string	string
*
*	@return int
*/
function strlen( string )
{

	string = string.split("");
	
	return string.length;
}

/***************************************************************************************
*	Check if a string is empty or contains only whitespaces
*
*	@param str	The string to check
*
*	@return bool
*/
function is_empty( str )
{
	if( str == '' )
	{
		return true;
	}
	
	var reg = new RegExp('^[\\s]*$');
	if( str.match(reg) )
	{
		return true;
	}
	
	return false;
}

/***************************************************************************************
*	Explode a string on newline characters
*
*	@param str	The string to explode
*
*	@return array
*/
function explodenl( str )
{
	return str.split("\n");
}

/***************************************************************************************
*	Convert newline characters to <br/> tags in a string
*
*	@param str	The string to convert
*
*	@return string
*/
function nl2br( str )
{
	return str.replace("\n", "<br/>");
}

/***************************************************************************************
*	Convert <br/> tags to newline characters in a string
*
*	@param str	The string to convert
*
*	@return string
*/
function br2nl( str )
{
	return str.replace(/\<br(\s*\/|)\>(\s*)/g, "\r\n");
}

/***************************************************************************************
*	Explode a string on whitespaces
*
*	@param str	The string to explode
*
*	@return array
*/
function explodews( str )
{
	var reg = new RegExp('\\s+');
	return str.split(reg);
}


/***************************************************************************************
*	Trim whitespaces from the beginning and end of a string
*
*	@param str	The string to trim
*
*	@return string
*/
function trim( str )
{
	var sregexp = new RegExp('^[\\s]+');
	var eregexp = new RegExp('[\\s]+$');
	str = str.replace(sregexp, '');
	str = str.replace(eregexp, '');
	return str;
}

/***************************************************************************************
*	Shows an element by removing the "hidden" css-class from it
*
*	@param obj	The object to show (or id of the object)
*
*	@return true
*/
function showelement( obj )
{
	if( typeof obj != 'object' )
	{
		obj = getbyid(obj);	
	}
	
	if( !obj )
	{
		return false;
	}
	
	removeclass(obj, 'hidden');
	
	return true;
}

/***************************************************************************************
*	Hides an element by appending the "hidden" css-class to it
*
*	@param obj	The object to hide (or id of the object)
*
*	@return true
*/
function hideelement( obj )
{
	if( typeof obj != 'object' )
	{
		obj = getbyid(obj);	
	}
	
	if( !obj )
	{
		return false;
	}
	
	addclass(obj, 'hidden');
	
	return true;
}

/***************************************************************************************
*	Returns true if an object has the provided css-class
*
*	@param obj	The object (or id of the object)
*	@param classname	The classname to test for
*
*	@return bool
*/
function hasclass( obj, classname )
{
	if( typeof obj != 'object' )
	{
		obj = getbyid(obj);	
	}
	
	if( !obj )
	{
		return false;
	}

	var regexp = new RegExp('(\\s|^)'+classname+'(\\s|$)');
	return ( obj.className.match(regexp) );
}

/***************************************************************************************
*	Adds a css-class to an object
*
*	@param obj	The object (or id of the object)
*	@param classname	The classname to add
*
*	@return none
*/
function addclass( obj, classname )
{
	if( typeof obj != 'object' )
	{
		obj = getbyid(obj);	
	}
	
	if( !obj )
	{
		return false;
	}
	
	if( !hasclass(obj, classname) )
	{
		obj.className += ' ' + classname;
	}
}

/***************************************************************************************
*	Removes a css-class from an object
*
*	@param obj	The object (or id of the object)
*	@param classname	The classname to remove
*
*	@return none
*/
function removeclass( obj, classname )
{
	if( typeof obj != 'object' )
	{
		obj = getbyid(obj);	
	}
	
	if( !obj )
	{
		return false;
	}
	
	var regexp = new RegExp('(\\s|^)'+classname+'(\\s|$)');
	obj.className = obj.className.replace(regexp, ' ');
	obj.className = trim( obj.className );
}

/***************************************************************************************
*	Replaces all occurances of rsclass with aclass
*
*	@param obj	The object (or id of the object)
*	@param rclass	The classname to remove
*	@param aclass	The classname to add
*
*	@return none
*/
function replaceclass( obj, rclass, aclass )
{
	removeclass( obj, rclass );
	addclass( obj, aclass );
}

/***************************************************************************************
*	Random array sorting function
*
*	Usage example:
*	var myarray = new Array('str', 'str2', 'str3');
*	myarray.sort(array_sort_random);
*
*	The above array is now randomized
*
*	@return int
*/
function array_sort_random()
{
	return ( Math.round( Math.random() ) - 0.5 );
}

/***************************************************************************************
*	Add an event
*
*	@param obj		The object
*	@param evnt		The event
*	@param func		The function to be added
*
*	@return mixed
*/
function addevent( obj, evnt, func )
{
	if( obj.addEventListener )
	{
		return obj.addEventListener( evnt, func, false );
	}
	else if( obj.attachEvent )
	{
		return obj.attachEvent( 'on'+evnt, func );
	}

	return false;
}

/***************************************************************************************
*	Removes an event
*
*	@param obj		The object
*	@param evnt		The event
*	@param func		The function to be removed
*
*	@return mixed
*/
function removeevent( obj, evnt, func )
{
	if( obj.removeEventListener )
	{
		return obj.removeEventListener( evnt, func, false );
	}
	else if( obj.detachEvent )
	{
		return obj.detachEvent( 'on'+evnt, func );
	}

	return false;
}


/***************************************************************************************
*	Return the document width
*
*	@return int
*/
function documentwidth()
{
	var dimx = 0;
	
	if( document.documentElement && ( document.documentElement.clientWidth ) )
	{
		dimx = document.documentElement.clientWidth;
	}
	else if( document.body && ( document.body.clientWidth ) )
	{
		dimx = document.body.clientWidth;
	}
	else if( typeof( window.innerWidth ) == 'number' )
	{
		dimx = window.innerWidth;
	}
	
	dimx = parseInt(dimx);
	
	return dimx;
}

/***************************************************************************************
*	Return the document height
*
*	@return int
*/
function documentheight()
{
	var dimy = 0;
	
	if( document.documentElement && ( document.documentElement.clientHeight ) )
	{
		dimy = document.documentElement.clientHeight;
	}
	else if( document.body && ( document.body.clientHeight ) )
	{
		dimy = document.body.clientHeight;
	}
	else if( typeof( window.innerHeight ) == 'number' )
	{
		dimy = window.innerHeight;
	}
	
	dimy = parseInt(dimy);
	
	return dimy;
}

/***************************************************************************************
*	Return the document's x scroll
*
*	@return int
*/
function scrollx()
{
	var scrollx = window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft;
	scrollx = parseInt(scrollx);
	return scrollx;
}

/***************************************************************************************
*	Return the document's y scroll
*
*	@return int
*/
function scrolly()
{
	var scrolly = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
	scrolly = parseInt(scrolly);
	return scrolly;
}


/***************************************************************************************
*	Get an objects total left position from the browsers left edge
*
*	@param obj	Object or id
*
*	@return int
*/
function objectleft( obj )
{
	var curleft = 0;

	if( typeof obj != 'object' )
	{
		obj = getbyid(obj);
	}
	
	if (obj.offsetParent)
	{
		curleft = obj.offsetLeft
		while (obj = obj.offsetParent)
		{
			curleft += obj.offsetLeft;
		}
	}
	
	curleft = parseInt(curleft);
	
	return curleft;
}

/***************************************************************************************
*	Get an objects total top position from the browsers top edge
*
*	@param obj	Object or id
*
*	@return int
*/
function objecttop( obj )
{
	var curtop = 0;
	
	if( typeof obj != 'object' )
	{
		obj = getbyid(obj);
	}
	
	if (obj.offsetParent)
	{
		curtop = obj.offsetTop
		while (obj = obj.offsetParent)
		{
			curtop += obj.offsetTop;
		}
	}
	
	curtop = parseInt(curtop);
	
	return curtop;
}

/***************************************************************************************
*	Get an objects position from the top left corner of the browser
*
*	@param obj	Object or id
*
*	@return array
*/
function objectpos(obj)
{
	return [ objectleft(obj), objecttop(obj) ];
}
	

/***************************************************************************************
*	Get an objects width
*
*	@param obj	Object or id
*
*	@return int
*/
function objectwidth( obj )
{
	var objw = 0;
	
	if( typeof obj != 'object' )
	{
		obj = getbyid(obj);
	}
	
	if( obj.style.width )
	{
		objw = obj.style.width.replace(/px/,'');
	}
	else if( obj.offsetWidth )
	{
		objw = obj.offsetWidth;
	}
	
	objw = parseInt(objw);
	
	return objw;
}

/***************************************************************************************
*	Get an objects height
*
*	@param obj	Object or id
*
*	@return int
*/
function objectheight( obj )
{
	var objh = 0;
	
	if( typeof obj != 'object' )
	{
		obj = getbyid(obj);
	}
	
	if( obj.style.height )
	{
		objh = obj.style.height.replace(/px/,'');
	}
	else if( obj.offsetHeight )
	{
		objh = obj.offsetHeight;
	}
	
	objh = parseInt(objh);
	
	return objh;
}

/***************************************************************************************
*	Get an objects dimensions
*
*	@param obj	Object or id
*
*	@return array
*/
function objectdim( obj )
{
	return [ objectwidth(obj), objectheight(obj) ];
}

/***************************************************************************************
*	Get an objects boundaries
*
*	@param obj	Object or id
*
*	@return array
*/
function objectboundaries( obj )
{
	var cxmin = cxmax = cymin = cymax = 0;
	
	if( typeof obj != 'object' )
	{
		obj = getbyid(obj);
	}
	
	cxmin = objectleft(obj);
	cxmax = cxmin + objectwidth(obj);
	cymin = objecttop(obj);
	cymax = cymin + objectheight(obj);
	
	return [ cxmin, cxmax, cymin, cymax ];
}

/***************************************************************************************
*	Check if the cursor is over an object
*
*	@param obj				Object or id
*	@param e					Event object
*	@param detailedmode	If true the function returns 1 if the cursor is
*								over the top half of the object, and 2 if the cursor
*								is over the bottom half of the object
*
*	@return mixed
*/
function cursor_is_over( obj, e, detailedmode )
{	
	if( typeof obj != 'object' )
	{
		obj = getbyid(obj);
	}
	
	var mx = cursorleft(e);
	var my = cursortop(e);
	var b = objectboundaries(obj);

	if( mx >= b[0] && mx <= b[1] && my >= b[2] && my <= b[3] )
	{
		if( typeof detailedmode == 'undefined' )
		{
			return true;
		}
		else
		{
			var triggerpoint = ( b[0] + Math.floor( objectwidth(obj) / 2 ) );
			if( mx <= triggerpoint )
			{
				return 1;
			}
			else
			{
				return 2;
			}
		}
	}
	
	return false;
}
	
	
/***************************************************************************************
*	Returns the cursors left position
*
*	@param e Event object
*
*	@return int
*/
function cursorleft(e)
{
	if(!e) e = window.event;
	var xpos = 0;
	
	if ( e.pageX )
	{
		xpos = e.pageX;
	}
	else if( e.clientX )
	{
		xpos = e.clientX + ( document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft );
	}
	
	return xpos;
}

/***************************************************************************************
*	Returns the cursors top position
*
*	@param e Event object
*
*	@return int
*/
function cursortop(e)
{
	if(!e) e = window.event;
	var ypos = 0;
	
	if ( e.pageY )
	{
		ypos = e.pageY;
	}
	else if( e.clientY )
	{
		ypos = e.clientY + ( document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop );
	}
	
	return ypos;
}

/***************************************************************************************
*	Returns the cursors left and top positions
*
*	@param e Event object
*
*	@return array [left,top]
*/
function cursorpos(e)
{
	return [ cursorleft(e), cursortop(e) ];	
}

	

/***************************************************************************************
*	Validates a form, checks for empty fields
*	Fields are given as arguments, for example:
*	validateform( formname, errormessage, 'username', 'password' );
*
*	@param formname		Name of form
*	@param errormessage	Errormessage to show
*/	
function validateform( formname, errormessage )
{
	var a = arguments;

	for( i=2; i < a.length; i++ )
	{
		if( formname.elements[a[i]].value == "" )
		{
			alert( errormessage );
			formname.elements[a[i]].focus();
			return false;
		}
	}

	return true;
}

/***************************************************************************************
*	Cross-browser compatible way of setting an elements opacity
*
*	@param obj			Object
*	@param opacity		Opacity in range 0-100
*/	
function set_opacity( obj, opacity )
{
	obj.style.opacity = (opacity/100);
	obj.style.filter = 'alpha(opacity='+opacity+')';
}

/***************************************************************************************
*	Function for outputting messages to firbug console
*
*	@param message	Can be string, object, array
*	@param mode		if "console" the firebug console is used, else the
*						message is put in a div at the page bottom
*
*/	
function debug( message, mode )
{
	if( !mode )
	{
		mode = 'console';
	}
	
	if(typeof console == 'object')
	{
		console.info(message);
	}
	
	if( divobj = getbyid('debug') )
	{
	}
	else
	{
		if( document.body )
		{
			var divobj = createelement('div');
			divobj.id = 'debug';
			divobj.className = 'debug';
			document.body.appendChild(divobj);
		}
	}
	
	if( divobj )
	{
		divobj.innerHTML += message+'<br/>';
	}	
}

/***************************************************************************************
*	Function for outputting messages in an input object
*
*	@param message	Message string
*
*/	
function debug_input( message )
{
	if( inputobj = getbyid('debug_input') )
	{
	}
	else
	{
		if( document.body )
		{
			var inputobj = createelement('input');
			inputobj.id = 'debug_input';
			inputobj.style.position = 'absolute';
			inputobj.style.top = '10px';
			inputobj.style.left = '10px';
			document.body.appendChild(inputobj);
		}
	}
	
	if( inputobj )
	{
		inputobj.value = message;
	}	
}



/***************************************************************************************
*	Sets a cookie
*
*	@param name		Cookie name
*	@param value	Cookie value
*	@param expires	Expiring time
*
*	@return none
*/		
function setcookie(name, value, expires)
{
	document.cookie = name + '=' + escape(value) + '; path=/' + (typeof expires != 'undefined' ? '; expires=' + expires.toGMTString() : '');
}


/*
* ##########################################################################################################################################
* #
* #	Dropdown functions
* #
* ##########################################################################################################################################
*/
/****************************************************************************************
*	Register a dropdown
*	@param string id		Id of the dropdown
*	@param bool open		If the dropdown should be open when the page loads
*
*	@return bool
*/
function register_dropdown( id, open )
{
	open = ( open ? true : false );
	var useimage = false;
	
	var trigger = getbyid('dropdown_trigger_' + id);
	var dropdown = getbyid('dropdown_' + id);
	var image = null;
	
	// Die if the elements are not found
	if( !trigger || !dropdown )
	{
		return false;
	}
	
	// Check if there is an img-tag in the trigger
	// that we can manipulate
	var imgs = fetchtags( trigger, 'img' );
	if( imgs && imgs.length > 0 )
	{
		var img = imgs[0];
		
		// The image has a classname that we can change
		// when opening and closing the dropdown
		if( img.className.indexOf('-open') != -1 || img.className.indexOf('-closed') != -1 )
		{
			// Set the image state
			img.className = ( open ? img.className.replace('-closed', '-open') : img.className.replace('-open', '-closed') );
			
			useimage = true;
			image = img;
		}
	}
	
	// Set id and onclick event for the trigger
	trigger.dropdownid = id;
	trigger.onclick = toggle_dropdown;
	
	// Set id, open state and target height for the animation
	// on the dropdown element
	dropdown.dropdownid = id;
	dropdown.open = ( open ? 1 : 0 );
	dropdown.isanimating = false;
	dropdown.useimage = ( useimage ? 1 : 0 );
	dropdown.image = image;
	dropdown.targetheight = objectheight(dropdown);
	
	// Hide or show the object
	dropdown.style.display = ( open ? 'block' : 'none' );
	dropdown.style.overflow = 'hidden';
	
	return true;
}


/****************************************************************************************
*	Toggle a dropdown
*	@param e Event object
*
*	@return false
*/
function toggle_dropdown(e)
{
	if( this.dropdownid )
	{
		var trigger = getbyid('dropdown_trigger_' + this.dropdownid);
		var obj = getbyid('dropdown_' + this.dropdownid);
		
		if( obj && !obj.isanimating )
		{
			// Close the dropdown
			if( obj.open )
			{
				obj.open = 0;
				obj.targetheight = objectheight(obj);
				
				var anim = new Animator(obj, '{"height": {"from":"auto", "to":0}, "speed":10}');
				anim.oncomplete = function()
				{
					obj.isanimating = false;
					obj.style.display = 'none';
					
					if( obj.useimage && obj.image )
					{
						obj.image.className = obj.image.className.replace('-open', '-closed');
					}
				};
				
				obj.isanimating = true;
				anim.animate();
			}
			// Open the dropdown
			else
			{
				obj.open = 1;
				obj.style.display = 'block';
				
				var anim = new Animator(obj, '{"height": {"from":0, "to":'+obj.targetheight+'}, "speed":10}');
				anim.oncomplete = function()
				{
					obj.isanimating = false;
					obj.style.height = '';
					
					if( obj.useimage && obj.image )
					{
						obj.image.className = obj.image.className.replace('-closed', '-open');
					}
				};
				
				obj.isanimating = true;
				anim.animate();
			}
		}
	}
	
	return false;
}



/*
* ##########################################################################################################################################
* #
* #	Ajax handler
* #
* ##########################################################################################################################################
*/
/****************************************************************************************
*	Method for sending ajax post requests and handle JSON-data
*
*	@param json	Is the response JSON-encoded?
*/
function ajax_handler(json, async)
{
	this.response = '';
	this.containerobj = false;
	this.requestobject = false;
	// json (true) the data is returned in json_encode() format
	this.json = ( json ? true : false );
	// asynchronous (true) the server returns the request when it is
	// finished without stalling the script
	// synchronous (false) the script stalls and waits for the request to finish
	this.async = ( async ? true : false );
	
	
	/****************************************************************************************
	*	Initialize the request object
	*/
	this.init = function()
	{
		if( window.XMLHttpRequest )
		{
			this.requestobject = new XMLHttpRequest();
		}
		else
		{
			this.requestobject = new ActiveXObject("Microsoft.XMLHTTP");
		}
		
		this.requestobject.onreadystatechange = this.rs;
		return ( this.requestobject ? true : false );
	};
	
	/****************************************************************************************
	*	Perform a normal POST-request and return
	*	the response
	*
	*	@param url	Url of the file
	*	@param url	POST Parameters
	*
	*/
	this.post = function( url, data )
	{
		if( this.requestobject )
		{
			data = ( data ? data : '' );
			
			this.requestobject.open('post', url, this.async);
			this.requestobject.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
			this.requestobject.send(data);
			
			if( this.json )
			{
				this.response = eval('(' + this.requestobject.responseText + ')');
			}
			else
			{
				this.response = this.requestobject.responseText;
			}
		
			return this.response;
		}
		
		return false;
	};
	
	
	/****************************************************************************************
	*	Perform a normal GET-request and return
	*	the response
	*
	*	@param url	Url of the file
	*
	*/
	this.get = function( url )
	{
		if( this.requestobject )
		{
			this.requestobject.open('get', url, this.async);
			this.requestobject.send(null);
		}
		
		return false;
	};
	
	/****************************************************************************************
	*	Readystate change wrapper for asynchronous mode, this
	*	can be overwritten when creating a new instance of the class
	*
	*/
	this.rs = function()
	{
		if( this.requestobject )
		{
			if( this.requestobject.readyState == 4 )
			{
				if( this.json )
				{
					this.response = eval('(' + this.requestobject.responseText + ')');
				}
				else
				{
					this.response = this.requestobject.responseText;
				}
			}
		}
	};
	
	// Initialize
	this.init();
}





/*
* ##########################################################################################################################################
* #
* #	Checkall functions
* #
* ##########################################################################################################################################
*/
/****************************************************************************************
*	Register checkall
*
*	@param int id
*
*/
function register_checkall( id )
{
	var checkbox = getbyid('checkall_'+id);
	var container = getbyid('checkall_content_'+id);
	
	if( checkbox && container )
	{
		checkbox.checkallid = id;
		checkbox.onclick = checkall;
	}
}

/****************************************************************************************
*	Onclick wrapper for checkall
*
*	@param e event object
*
*/
function checkall(e)
{
	e = e | window.event;
	
	if( this.checkallid )
	{
		var container = getbyid('checkall_content_'+this.checkallid);
		var inputs = fetchtags( container, 'input' );
	
		for( var i = 0; i < inputs.length; i++ )
		{
			inputs[i].checked = ( this.checked ? true : false );
		}
	}
	
	return true;
}


/****************************************************************************************
* Function that shows/hides an element based on which
* value was selected in the dropdown
*
* @param obj	The select object
* @param val	If the selected value is equal to this, the element is shown
* @param elm	The element to show/hide
*
*/
function select_toggle_obj(obj, val, elm)
{
	if( typeof elm != 'object' )
	{
		elm = getbyid(elm);
	}
	
	if( !elm )
	{
		return true;
	}
	
	if( obj.options[obj.selectedIndex].value == val )
	{
		showelement(elm);
	}
	else
	{
		hideelement(elm);
	}
}


/****************************************************************************************
* Function that disables an input filed if a checkbox is checked
*
* @param obj	The checkbox
* @param elm	The input element to toggle
*
*/
function check_disable_obj(obj, elm)
{
	if( typeof elm != 'object' )
	{
		elm = getbyid(elm);
	}
	
	if( !elm )
	{
		return true;
	}
	
	elm.disabled = ( obj.checked ? false : true );
	
	return true;
}



/****************************************************************************************
* Handler for the image upload form @ mediaeditor
*
*/
function imageupload_handler()
{
	this.uploaderitems = null;
	this.addfieldsbutton = null;
	this.addfieldscount = null;
	this.itemcount = 1;
	
	/****************************************************************************************
	* Initialize
	*
	*/
	this.init = function()
	{
		this.uploaderitems = getbyid('uploader-items');
		this.addfieldsbutton = getbyid('addfields-button');
		this.addfieldscount = getbyid('addfields-fieldcount');
		
		this.addfieldsbutton.uploadhandler = this;
		
		addevent(this.addfieldsbutton, 'click', this.addfields_onclick_handler);
	};
	
	/****************************************************************************************
	* Onclick handler for the addfields button 
	*
	*/
	this.addfields_onclick_handler = function( e )
	{
		e = e || window.event;
		var targetobj = e.target || e.srcElement;
		
		var fieldcount = parseInt(targetobj.uploadhandler.addfieldscount.value);
		if( !fieldcount )
		{
			fieldcount = 0;
		}
		
		targetobj.uploadhandler.update_fieldcount();
		
		for( var i = 0; i < fieldcount; i++ )
		{
			targetobj.uploadhandler.createfield();
		}
	};
	
	/****************************************************************************************
	* Update the field count 
	*
	*/
	this.update_fieldcount = function()
	{
		var items = fetchtags_by_classname(this.uploaderitems, 'uploader-item', true);
		this.itemcount = items.length;
	};
	
	/****************************************************************************************
	* Create a new field 
	*
	*/
	this.createfield = function()
	{
		if( this.itemcount > 20 )
		{
			return true;
		}
		
		var itemdiv = createelement('div');
		itemdiv.className = 'uploader-item';
		
		var sp1 = createelement('span');
		sp1.innerHTML = phrase.image + ': ';
		var sp2 = createelement('span');
		sp2.innerHTML = ' ' + phrase.uploader_or_url + ': ';
	
		var fileinput = createelement('input');
		fileinput.type = 'file';
		fileinput.name = 'imagefile_' + (this.itemcount + 1);
		
		var urlinput = createelement('input');
		urlinput.type = 'text';
		urlinput.size = '30';
		urlinput.className = 't';
		urlinput.name = 'imageurl_' + (this.itemcount + 1);
		
		itemdiv.appendChild(sp1);
		itemdiv.appendChild(fileinput);
		itemdiv.appendChild(sp2);
		itemdiv.appendChild(urlinput);
		this.uploaderitems.appendChild(itemdiv);
		
		this.itemcount++;
	};
	
	
	this.init();
}



function uploadhandler(id, posthash)
{
	this.id = id;
	this.form = null;
	this.iframe = null;
	this.posthash = posthash;
	this.ajax = null;
	
	this.init = function()
	{
		this.form = getbyid(this.id + '_form');
		this.iframe = getbyid(this.id + '_iframe');
		
		this.ajax = new ajax_handler(true);
	};
	
	this.reload = function()
	{
		var data = this.ajax.post(
			PDIR+'ajax.php?do=uploader_reload',
			'posthash=' + this.posthash
		);
		
		debug(data);
	};
	
	this.startupload = function()
	{
	};
	
	this.init();
}



/****************************************************************************************
* Insert text into the editor
*
* @param text	The text to insert
*
*/
function editor_insert( text )
{
	var textarea = getbyid('editormessage');
	if( !textarea )
	{
		alert("not found");
		return false;
	}
	
	var scrolltop = textarea.scrollTop;
	
	if( document.selection )
	{
		textarea.focus();
		sel = document.selection.createRange();
		
		if( sel.text.length > 0 )
		{
			var selection = sel.text;
			sel.text = text + selection;
			
			if( selection.indexOf('\n') == -1 )
			{
				var selstart = -selection.length - endtag.length;
				sel.moveStart('character', selstart);
				sel.select();
			}
		}
		else
		{
			sel.text = starttag + endtag;
			sel.select();		
		}
		
		textarea.scrollTop = scrolltop;
	}
	else /* Not IE */
	{
		var spos = textarea.selectionStart;
		var epos = textarea.selectionEnd;
		var len = textarea.textLength;

		if( epos && (epos - spos > 0) )
		{
			var s1 = (textarea.value).substring(0, spos);
			var s2 = (textarea.value).substring(spos, epos)
			var s3 = (textarea.value).substring(epos, len);
			
			textarea.value = s1 + text + s2 + s3;
		}
		else
		{
			textarea.value = textarea.value.substring(0,spos) + text + textarea.value.substring(epos, len) ;
			textarea.selectionStart = spos + text.length;
			textarea.selectionEnd = epos + text.length;
		}

		textarea.focus();	
		textarea.scrollTop = scrolltop;
	}
	
	
	return false;
}



/****************************************************************************************
* Attachment upload handler
*
* @param posthash		Info hash for the post being edited or created
*
*/
function attachment_handler(posthash)
{
	this.posthash = (posthash ? posthash : '');
	this.messagediv = null;
	this.filelist = null;
	this.fileinput = null;
	this.formobj = null;
	this.submitbutton = null;
	this.ajaxobj = null;
	
	this.init = function()
	{
		this.messagediv = getbyid('attachment-message');
		this.filelist = getbyid('attachment-list');
		this.formobj = getbyid('attachment-form');
		this.fileinput = getbyid('attachment-file');
		this.submitbutton = getbyid('attachment-submitbutton');
		// Properties
		this.formobj.attachmenthandler = this;
		this.fileinput.attachmenthandler = this;

		this.ajaxobj = new ajax_handler(true, false);
		
		// Attach event to form
		addevent(this.formobj, 'submit', this.startupload);
		// Attach event to file input
		addevent(this.fileinput, 'change', this.fileinput_onchange_event);
	};
	
	this.fileinput_onchange_event = function(e)
	{
		if( !e.target ) return false;
		var input = e.target;
		input.attachmenthandler.formobj.submit();
	};
	
	this.startupload = function(e)
	{
		if( !e.target ) return false;
		var form = e.target;
		form.attachmenthandler.submitbutton.value = 'Uploading...';
		form.attachmenthandler.submitbutton.disabled = true;
	};
	
	this.refreshlist = function()
	{
		var data = this.ajaxobj.post(PDIR+'ajax.php?do=attachmentlist', 'posthash=' + this.posthash);
		if( data.success )
		{
			this.filelist.innerHTML = data.html;
			this.fileinput.value = '';
		}
		
		this.submitbutton.value = 'Upload';
		this.submitbutton.disabled = false;
	};
	
	this.deleteitem = function(attachmentid)
	{
		var data = this.ajaxobj.post(PDIR+'ajax.php?do=deleteattachment', 'posthash=' + this.posthash + '&attachmentid=' + attachmentid);
		this.refreshlist();
		return false;
	};
	
	this.inserttext = function(attachmenttype, attachmentid)
	{
		if( attachmenttype == 'image' )
		{
			editor_insert('[img='+attachmentid+'][/img]');
		}
		else if( attachmenttype == 'video' )
		{
			editor_insert('[video='+attachmentid+']');
		}
		else
		{
			editor_insert('[file='+attachmentid+']');
		}
		
		return false;
	};
	
	this.init();
}

/***************************************************************************************
*	Bind support, copied from https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind
*
*	Sets the context of an external call to the original sources this
*
*/
if (!Function.prototype.bind) 
{  
  Function.prototype.bind = function (oThis) 
  {  
	if (typeof this !== "function") // closest thing possible to the ECMAScript 5 internal IsCallable function  

	  throw new TypeError("Function.prototype.bind - what is trying to be fBound is not callable");  

	var aArgs = Array.prototype.slice.call(arguments, 1),   

		fToBind = this,   

		fNOP = function () {},  

		fBound = function () 
		{  
		  return fToBind.apply(this instanceof fNOP ? this : oThis || window, aArgs.concat(Array.prototype.slice.call(arguments)));      
		};  

	fNOP.prototype = this.prototype;  
	fBound.prototype = new fNOP();  

	return fBound;  
  };  
} 


