/*
 * Author: Rodney Rehm
 * Web: http://www.rodneyrehm.de
 * Get blockup at http://www.rodneyrehm.de/tools/blockup
 *
 * Date / Version: 12. July 2006
 *
 * Published under the Open Source BSD-License
 * http://www.opensource.org/licenses/bsd-license.php
 */


/**
 * generic interface to create easy non-window popups
 * @param hideOverly set to true, if overlay should not be displayed, defaults to false
 **/
function blockup( hideOverlay )
{
	/* some sort of constants */
	this.CONTROL_CLOSEBUTTON = 0;		/* display a close-button */
	this.CONTROL_CONFIRMBUTTONS = 1;	/* display an ok- and cancel-button */
	this.CONTROL_OVERLAYCLICK = 2;		/* hide blockup when clicking on overlay */
	this.CONTROL_CONTENTCLICK = 3;		/* hide blockup when clicking on content */
	this.CONTROL_CLICK = 4;				/* hide blockup when clicking anywhere */

	this.POS_CENTER = 0;				/* position: center center */
	this.POS_TOP = 1;					/* position: top center */
	this.POS_TOPRIGHT = 2;				/* position: top right */
	this.POS_RIGHT = 3;					/* position: center right */
	this.POS_BOTTOMRIGHT = 4;			/* position: bottom right */
	this.POS_BOTTOM = 5;				/* position: bottom center */
	this.POS_BOTTOMLEFT = 6;			/* position: bottom left */
	this.POS_LEFT = 7;					/* position: center left */
	this.POS_TOPLEFT = 8;				/* position: top left */
	var position = this.POS_CENTER;		/* currently chosen position */

	/* eventhandler */
	this.okHandler = function(){ return true; };		/* called when ok-button is clicked */
	this.cancelHandler = function(){ return true; };	/* called when cancel- resp. close-button is clicked */

	var pd = new pageDimensions();		/* keep track of page dimensions */
	var myThis = this;					/* self-reference */
	var objectsHideCache = new Array();	/* keep track of objects hidden on show() */

	/* just in case.. */
	if(hideOverlay != true) hideOverlay = false;

	/* dom-elements in use */
	var overlay, container, content, controls;

	/**
	 * register neccessary objects in DOM-tree
	 **/
	this.register = function()
	{
		/*
			<div class="blockupOverlay"></div>
			<div class="blockupContainer">
				<div class="blockupContent"></div>
				<div class="blockupControls"></div>
			</div>
		*/

		var body = document.getElementsByTagName('body')[0];

		// add overlay
		overlay = document.createElement( 'div' );
		overlay.className = 'blockupOverlay';
		body.appendChild( overlay );

		// add contentPanel
		container = document.createElement( 'div' );
		container.className = 'blockupContainer';
		body.appendChild( container );

		// add content
		content = document.createElement( 'div' );
		content.className = 'content';
		container.appendChild( content );

		// add controls
		controls = document.createElement( 'div' );
		controls.className = 'controls';
		container.appendChild( controls );

		// don't show blockup till it's told to
		this.hide();
	}

	/**
	 * remove neccessary objects from DOM-tree
	 **/
	this.unregister = function()
	{
		container.parentNode.removeChild( container );
		overlay.parentNode.removeChild( overlay );
	}

	/**
	 * position and display blockup, hide objects like <select>
	 * @returns always false (for simpler embed in onclick handlers)
	 **/
	this.show = function()
	{
		// pageDimensions have to be calculated once page finished loading
		pd.refresh();

		// make panels visible
		overlay.style.display = 'block';
		container.style.display = 'block';

		// enlarge overlay to fit document
		overlay.style.height = pd.getDocHeight() + 'px';

		// hide overlay if neccessary
		if(hideOverlay)
			overlay.style.visibility = 'hidden';

		// adjust container width to fit content exactly
		container.style.width =  content.offsetWidth + 'px';

		/*
		 * HORIZONTAL POSITIONING
		 */
		if( position == this.POS_TOPLEFT || position == this.POS_BOTTOMLEFT || position == this.POS_LEFT  )
		{
			// move content to the left
			container.style.left = '0px';
		}
		else if( position == this.POS_TOPRIGHT || position == this.POS_BOTTOMRIGHT || position == this.POS_RIGHT )
		{
			// move content to the right
			container.style.left = (overlay.offsetWidth - container.offsetWidth ) + 'px';
		}
		else
		{
			// horizontally center content
			container.style.left = ((pd.getViewWidth() / 2) - (content.offsetWidth / 2)) + 'px';
		}

		/*
		 * VERTICAL POSITIONING
		 */
		if( position == this.POS_TOPLEFT || position == this.POS_TOPRIGHT || position == this.POS_TOP )
		{
			// move content to the top
			container.style.top = pd.getVerticalScroll() + 'px';
		}
		else if( position == this.POS_BOTTOMLEFT || position == this.POS_BOTTOMRIGHT || position == this.POS_BOTTOM )
		{
			// move content to the bottom
			container.style.top = pd.getVerticalScroll() + (pd.getViewHeight() - container.offsetHeight) + 'px';
		}
		else
		{
			// vertically center content - adjust if container is higher than viewport
			var offset = (pd.getViewHeight() / 2) - (container.offsetHeight / 2);
			if(offset < 0) offset = 0;
			container.style.top = (pd.getVerticalScroll() + offset) + 'px';
		}

		// hide things like <select>
		var selects = document.getElementsByTagName('select');
		var ownSelects = container.getElementsByTagName('select');
		objectsHideCache = new Array();		/* clean cache */
		for(var i=0; i < selects.length; i++)
		{
			/* we don't want to hide selects within our blockup */
			var ignoreThis = false;
			for(var x=0; x < selects.length; x++)
			{
				if( selects[i] == ownSelects[x] )
					ignoreThis = true;
			}

			/*
			 * only hide not already hidden elements to not accidentaly make
			 * something visible, which we didn't hide. also don't hide objects
			 * within our blockup
			 */
			if( !ignoreThis && selects[i].style.visibility != 'hidden' )
			{
				// remember which objects were hidden, so the can be made
				// visible again on hide()
				objectsHideCache[ objectsHideCache.length ] = selects[i];
				selects[i].style.visibility = 'hidden'
			}
		}

		// return false to simplify embed in links
		return false;
	};

	/**
	 * hide blockup and make hidden objects visible again
	 * @returns always false (for simpler embed in onclick)
	 **/
	this.hide = function()
	{
		overlay.style.display = 'none';
		container.style.display = 'none';

		// make (only) previously hidden selects visible again
		for(var i=0; i < objectsHideCache.length; i++)
		{
			objectsHideCache[i].style.visibility = 'visible'
		}

		// return false to simplify embed in links
		return false;
	};

	/**
	 * remove everything inside content
	 **/
	this.emptyContent = function()
	{
		while( content.hasChildNodes() )
		{
			content.removeChild( content.firstChild );
		}
	}


	/**
	 * add an element to content, move within DOM-tree if neccessary
	 * @param elem object to append to content
	 * @returns success (bool)
	 **/
	this.addElement = function( elem )
	{
		if( !elem )
			return false;

		if(elem.parentNode)
			elem.parentNode.removeChild( elem );
		content.appendChild( elem );

		return true;
	};

	/**
	 * add an element identified by ID to content and move within DOM-tree
	 * @param elemID ID of element to append to object
	 * @return void
	 **/
	this.addElementById = function( elemID )
	{
		elem = document.getElementById( elemID );
		if( !elem )
			return false;

		if(elem.parentNode)
			elem.parentNode.removeChild( elem );
		content.appendChild( elem );

		return true;
	};


	/**
	 * add controls to blockup
	 * @param controlType prefefined controlSet (CONTROL_OVERLAYCLICK,
	 * CONTROL_CONTENTCLICK, CONTROL_CLICK, CONTROL_CLOSEBUTTON,
	 * CONTROL_CONFIRMBUTTONS) or an object to append to controls
	 **/
	this.addControls = function( controlType )
	{

		switch( controlType )
		{
			case this.CONTROL_OVERLAYCLICK:
				// add hide-handlers to overlay
				overlay.onclick =  myThis.hide;
			break;

			case this.CONTROL_CONTENTCLICK:
				// add hide-handlers to container / content
				container.onclick =  myThis.hide;
				content.onclick =  myThis.hide;
			break;

			case this.CONTROL_CLICK:
				// add hide-handlers to every layer
				overlay.onclick =  myThis.hide;
				container.onclick =  myThis.hide;
				content.onclick =  myThis.hide;
			break;

			case this.CONTROL_CLOSEBUTTON:
				var button = document.createElement('input');
					button.type = 'button';
					button.value = 'Close';
					button.onclick = function()
					{
						if(!myThis.okHandler())
							return;
						myThis.hide();
					};
				controls.appendChild( button );
			break;

			case this.CONTROL_CONFIRMBUTTONS:

				var button = document.createElement('input');
					button.type = 'button';
					button.value = 'OK';
					button.onclick = function()
					{
						if(!myThis.okHandler())
							return;
						myThis.hide();
					};
				controls.appendChild( button );

				var button = document.createElement('input');
					button.type = 'button';
					button.value = 'Cancel';
					button.onclick = function()
					{
						if(!myThis.cancelHandler())
							return;
						myThis.hide();
					};
				controls.appendChild( button );
			break;

			default:
				controls.appendChild( controlType );
			break;
		}
	};

	/**
	 * set positioning of blockup to: center center
	 **/
	this.positionCenter = function()
	{
		position = this.POS_CENTER;
	}

	/**
	 * set positioning of blockup to: top center
	 **/
	this.positionTop = function()
	{
		position = this.POS_TOP;
	}

	/**
	 * set positioning of blockup to: top right
	 **/
	this.positionTopRight = function()
	{
		position = this.POS_TOPRIGHT;
	}

	/**
	 * set positioning of blockup to: center right
	 **/
	this.positionRight = function()
	{
		position = this.POS_RIGHT;
	}

	/**
	 * set positioning of blockup to: bottom right
	 **/
	this.positionBottomRight = function()
	{
		position = this.POS_BOTTOMRIGHT;
	}

	/**
	 * set positioning of blockup to: bottom center
	 **/
	this.positionBottom = function()
	{
		position = this.POS_BOTTOM;
	}

	/**
	 * set positioning of blockup to: bottom left
	 **/
	this.positionBottomLeft = function()
	{
		position = this.POS_BOTTOMLEFT;
	}

	/**
	 * set positioning of blockup to: center left
	 **/
	this.positionLeft = function()
	{
		position = this.POS_LEFT;
	}

	/**
	 * set positioning of blockup to: top left
	 **/
	this.positionTopLeft = function()
	{
		position = this.POS_TOPLEFT;
	}

	/**
	 * set classNames of "root-elements" (overlay and container)
	 * @param overlayClass className to set for overlay, false for default-value
	 * @param containerClass className to set for container, false for default-value
	 **/
	this.setClassNames = function( overlayClass, containerClass )
	{
		if( !overlayClass )
			overlay.className = 'blockupOverlay';
		else
			overlay.className = overlayClass;

		if( !containerClass )
			container.className = 'blockupContainer';
		else
			container.className = containerClass;
	}

	/**
	 * set eventHandler for OK-Button
	 * @param func function-object to be executed when ok-button is pressed
	 **/
	this.setOkHandler = function( func )
	{
		this.okHandler = func;
	}

	/**
	 * set eventHandler for CANCEL-Button and CLOSE-Button
	 * @param func function-object to be executed when cancel- or close-button is pressed
	 **/
	this.setCancelHandler = function( func )
	{
		this.cancelHandler = func;
	}

	/* initiate that thing */
	this.register();
}


/**
 *
 * @access public
 * @return void
 **/
function blockupIMG( relName )
{
	var bu, img;

	var myThis = this;
	if(!relName) relName = 'blockupIMG';

	var imgCache = new Object();

	/**
	 *
	 * @access public
	 * @return void
	 **/
	this.init = function()
	{
		// scan all links for rel="relName"
		links = document.getElementsByTagName('a');
		for(var i=0; i < links.length; i++)
		{
			if(links[i].rel == relName)
			{
				links[i].onclick = function(){ return myThis.show( this ); }
			}
		}

		// get blockup ready
		bu = new blockup();
		bu.addControls( bu.CONTROL_CLICK );
		img = document.createElement('img');
		bu.addElement( img );
	}

	this.show = function( link )
	{
		if( !imgCache[link.href] )
		{
			imgCache[link.href] = new Image();
			imgCache[link.href].src = link.href;
			imgCache[link.href].onload = function(){ myThis.show(link); };
			return false;
		}

		img.src = imgCache[link.href].src;
		img.alt = link.getElementsByTagName('img')[0].alt

		return bu.show();
	}

	this.hide = function()
	{
		bu.hide();
	}

	this.init();
}






