	
	function $(elName, tags)
	{
		var el;
		el = document.getElementById ( elName );
		
		if ( el && tags )
			return el.getElementsByTagName ( tags );
		
		return el;
	}
		
	function getEventEl ( e )
	{
		if ( ! e )
			var e = window.event;
	
		var targ;
		
		if ( e.target )
			targ = e.target;
		else if ( e.srcElement )
			targ = e.srcElement;
		
		// defeat Safari bug
		if ( targ.nodeType == 3 )
			targ = targ.parentNode;
	
		return targ;
	}

	function cancelEvent ( e )
	{
		if ( ! e )
			return;
		
		e.cancelBubble = true;
		
		if ( e.stopPropagation )
			e.stopPropagation();
	}
	
	function thumb()
	{
		var el;
		var cl = '';
		
		if ( el = $('f_large') )
			if ( el.checked )
				cl += 'la';
		
		if ( el = $('f_crop') )
			if ( el.checked )
				cl += 'cr';
		
		if ( el = $('thswap') )
			el.className = cl;
	}
		
	function purge( e )
	{
		var targ = getEventEl ( e );
		
		if ( window.confirm ( targ.innerHTML ) )
		{
			// remove cookies
			var date = new Date( 0 );
			
			document.cookie = 'lastImages= ; expires=' + date.toGMTString() + '; path=/';
			
			var histEl = $('history');
			
			if ( histEl )
				histEl.parentNode.removeChild(histEl);
		}

		cancelEvent( e );
		return false;
	}
	
	function withimg()
	{
		var codEl = $('codes');
		var chkEl = $('imgchk');
		
		if ( codEl && chkEl )
			codEl.className = ( chkEl.checked ? 'img' : 'noimg' );
	}
	
	function tab ( e )
	{
		var me = getEventEl ( e );
		
		if ( ! me )
			return;
		
		me = me.parentNode;
		
		while ( me && ( me.nodeName != 'DT' ) )
			me = me.parentNode;
		
		var dt = $('codes', 'DT');
		
		for ( var i=0; i < dt.length; i++ )
		{
			dt[i].className = (dt[i] == me) ? 'sel' : '';
			
			var dd = dt[i].nextSibling;
			
			while ( dd && dd.nodeName != 'DD' )
				dd = dd.nextSibling;
			
			dd.className = (dt[i] == me) ? 'sel' : '';
		}
	}
	
	/**
	 * debug helper
	 * @todo remove from release version
	 * @param e
	 * @return
	 */
	function dumpo ( e )
	{
		var t = '';
		for ( var y in e )
			t += y + '=' + e[y] + "\n";
	
		alert(t);
	}
	
	function seltext ( e )
	{
		// FF, Safari, Chrome, Opera
		if ( window.getSelection ) 
		{ 
			var sel		= window.getSelection();
			var range	= document.createRange();
			
			range.selectNodeContents(this);
			sel.removeAllRanges();
			sel.addRange(range);
			
			return true;
	  	}
		
		if ( document.selection ) 
		{
			document.selection.empty();
			var range = document.body.createTextRange();
			
			range.moveToElementText ( getEventEl ( e ) );
			range.select();
			
			return true;
	  	}
		
		return false;
	}
	
	function mailie ( e )
	{
		var el = getEventEl ( e );
		
		el.className = ( el.className == 'hover' )
			? ''
			: 'hover';
	}
	
	function hookSetTextOnChange ( textareaID, buttonID, updatedClassName )
	{
		var textarea	= document.getElementById ( textareaID );
		var button		= document.getElementById ( buttonID );
		
		if ( ! textarea || ! button )
			return;
		
		var origValue		= textarea.value;
		var origClassName	= button.className;
		
		textarea.onkeyup = function() { button.className = ( textarea.value == origValue ) ? origClassName : origClassName + ' ' + updatedClassName; };
	}
	
	/******************************* progress meter ***********************************/
	
	var uploadInterval;
	var uploadReq = null;
	
	function initProgressMeter( progressBarURL, progressBarUUID )
	{
		var progressBar = document.getElementById ( 'progressBar' );
		if ( ! progressBar )
			return false;
		
		uploadInterval = window.setInterval ( function() { updateProgressMeter( progressBar, progressBarURL, progressBarUUID ); }, 100 );
		return true;
	}
	
	function updateProgressMeter ( progressBar, progressBarURL, progressBarUUID )
	{
		// do not overwrite, let finish at least one of them :)
		if ( uploadReq != null )
			return;
		
		uploadReq = ( window.XMLHttpRequest
			? new XMLHttpRequest
			: ( window.ActiveXObject
				? new ActiveXObject ( "Microsoft.XMLHTTP" )
				: false
				)
			);
		
		if ( ! uploadReq )
			return null;

		uploadReq.open ( "GET", progressBarURL + '?X-Progress-ID=' + encodeURIComponent ( progressBarUUID ), 1 );

		uploadReq.onreadystatechange = function()
		{
			if ( uploadReq.readyState == 4 )
			{
				if ( uploadReq.status == 200 )
					updateProgressMeterValue ( progressBar, eval(uploadReq.responseText) ); // poor-man JSON parser
				
				uploadReq = null;
			}
		};
		
		uploadReq.send(null);
	}
	
	function updateProgressMeterValue ( progressBar, upload )
	{
		var progressBarWrapper = document.getElementById ( 'progressBarWrapper' );
		if ( ! progressBarWrapper )
			return false;
		
		progressBarWrapper.style.display = 'block';
		
		if ( upload.state == 'done' || upload.state == 'uploading' )
			progressBar.style.width = Math.round( 100 * upload.received / upload.size ) + '%';
		
		if ( upload.state == 'done' )
		{
			window.clearTimeout ( uploadInterval );
			progressBar.className = 'done';
		}
	}
