/******************************************************************************
 * window_manager.js - windowManager class (lightbox effect)
 * Copyright (C) 2007, by QOOP, Inc.
 * All Rights Reserved
 ******************************************************************************/

 /** Class definition: windowManager
  * represents a single popup 'window' with exclusive focus in the
  * context of a given page.
  *
  * Constructor: Builds the window using an id for the div element it will be
  * 			 housed in and HTML to be inserted.  Sets default width, height
  *				 and position.  Note that this does not actually display the window.
  *
  * 			 new windowManager(div_id, html)
  *
  * Methods:
  * 	display_window()		-- display the 'window'
  * 	resize_window(x, y)		-- change the width and height of the window
  *		place_window(top, left) -- place window top,left pixels from the upper left corner
  *		close_window()			-- close the window (if displayed)
  *		window_is_open()		-- returns true if the window is visible
  * 	change_html(html)		-- change the html of the given window
  * 	append_html(html)		-- add the html to the given window
  * 	get_html()				-- returns the html currently displayed
  * 	set_z_index(z)			-- sets the z-index of the screen to z and window to (z + 1)
  *
  * Functions:
  * 	get_opacity_style(op)	-- returns string to be used in style="" def for opacity values 0.0-1.0
  * 							   supports the main 4 styles (w3c, ie, moz/nn, and khtml)
  *
  * Note: window_manager.js now uses browserdetect.js from %front_end%/javascript/ because of
  * MSIE bugs in versions less than 7.0
  */


/* Constructor as described above
 */
function windowManager(div_id, html)
	{
	//Default width/height
	this.height = 200 + 'px';
	this.width = 300 + 'px';

	//Default window position
	this.top = 50 + 'px';
	this.left = 50 + 'px';

	this.is_open = false;

	this.id = div_id;
	this.screen_id = div_id + 'screen';
	this.html = html;

	//display the window as display: none
	this.initialize_divs();
	}

/* Sets the z-index of the screen and window to z and (z + 1), respectively
 */
windowManager.prototype.set_z_index = function(z)
	{
	document.getElementById(this.screen_id).style.zIndex = z;
	document.getElementById(this.id).style.zIndex = (z + 1);
	}

/* sets the dimensions of the window.  If displayed,
 * this will alter the width and height
 */
windowManager.prototype.resize_window = function(x,y)
	{
	//Set the width and height
	this.width = x + 'px';
	this.height = y + 'px';

	//If the window is open, resize it
	document.getElementById(this.id).style.width = this.width;
	document.getElementById(this.id).style.height = this.height;
	}

/* Sets the position of the window.  If displayed,
 * this will alter the position
 */
windowManager.prototype.place_window = function(ctop, cleft)
	{
	//Set the position
	this.top = ctop + 'px';
	this.left = cleft + 'px';

	//If the window is open, position it
	document.getElementById(this.id).style.top = this.top;
	document.getElementById(this.id).style.left = this.left;
	}

/* Change the window's innerHTML
 */
windowManager.prototype.change_html = function(html)
	{
	this.html = html;
	document.getElementById(this.id).innerHTML = this.html;
	}

/* Add to the window's innerHTML
 */
windowManager.prototype.append_html = function(html)
	{
	this.html += html;
	document.getElementById(this.id).innerHTML = this.html;
	}

/* Accessor
 */
windowManager.prototype.get_html = function()
	{
	return this.html;
	}


/* Initialize the divs for the given windowManager instance.  This is done by creating
 * and attaching objects within the DOM
 */
windowManager.prototype.initialize_divs = function()
	{
	//Create an html block to write out to the screen
	var op_string = get_opacity_style(0.95);
	var html = "";

//Create the screen div
//	if (!document.getElementById(this.screen_id))
//		html += "<div id='" + this.screen_id + "' style=\"width: 100%; height: 100%; background: #111111; " + op_string
//			 + " position: absolute; top: 0px; left: 0px; z-index: 11; display: none;\"></div>";
//	else
//		alert("Problem initializing window manager -- screen already exists.");

//Create the focus area div
//	if (!document.getElementById(this.id))
//		html += "<div id='" + this.id + "' style=\"width:" + this.width + "; height: " + this.height + "; border: 1px solid #000000;"
//			 + " background: #FFFFFF; position: absolute; top: " + this.top + "; left: " + this.left + "; z-index: 12; display: none;\">" + this.html + "</div>";
//	else
//		alert("Problem initializing window manager -- window already exists.");

	/* If the browser is internet explorer, and below v7.0, it can't
	 * handle transparency over select elements (or other 'windowed' elements)
	 * so we need to show a flat #111 *iframe* for a screen.  This now uses
	 * browserdetect.js
	 */


	//Create the screen div element within the DOM, or an iframe for MSIE
	if (BrowserDetect.browser == "Explorer" && BrowserDetect.version < 7)
		var screen = document.createElement("iframe");
	else
		var screen = document.createElement("div");

	screen.id = this.screen_id;

	//Set various styles to the screen div
	screen.style.width = '100%';
	screen.style.height = '100%';
	screen.style.backgroundColor = "#666666";
	screen.style.position = 'absolute';
	screen.style.top = '0px';
	screen.style.left = '0px';
	screen.style.zIndex = '11';
	screen.style.display = 'none';

	//Set opacity styles
	set_opacity_styles(screen, '0.95');


	//Create the focus area element within the DOM
	var focus = document.createElement("div");
	focus.id = this.id;

	//Set various styles for the focus area div
	focus.style.width = this.width;
	focus.style.height = this.height;
	focus.style.border = '1px solid #000000';
	focus.style.background = '#ffffff';
	focus.style.position = 'absolute';
	focus.style.top = this.top;
	focus.style.left = this.left;
	focus.style.zIndex = '12';
	focus.style.display = 'none';
	focus.innerHTML = this.html;

	//Get the body element so we can append children
	var o = document.getElementsByTagName('body');
//	o[0].innerHTML = o[0].innerHTML + html;

	//Append the screen and focus area to the body element
	o[0].appendChild(screen);
	o[0].appendChild(focus);
	}

/* Get the screen width and height across all major browsers
 */
windowManager.prototype.screen_fill_page = function(elemScreen)
	{
	if( window.innerHeight && window.scrollMaxY ) // Firefox
		{
		pageWidth = window.innerWidth + window.scrollMaxX;
		pageHeight = window.innerHeight + window.scrollMaxY;
		}
	else if( document.body.scrollHeight > document.body.offsetHeight ) // all but Explorer Mac
		{
		pageWidth = document.body.scrollWidth;
		pageHeight = document.body.scrollHeight;
		}
	else // works in Explorer 6 Strict, Mozilla (not FF) and Safari
		{
		pageWidth = document.body.offsetWidth + document.body.offsetLeft;
		pageHeight = document.body.offsetHeight + document.body.offsetTop;
		}

	/*Sometimes we don't cover everything so if we can get a bigger correct size we should user
	 * that. This can occur if there is no scrollable content
	 */	
	var size = getViewportSize();
	if(size[1] > pageHeight)	
		{
		pageHeight = size[1];	
		}
	if(size[0] > pageWidth)	
		{
		pageWidth = size[0];	
		}
	
	elemScreen.style.width = pageWidth + "px";
	elemScreen.style.height = pageHeight + "px";
	}

/* Accessor function to use the screen_fill_page method without previously having the screen
 * element
 */
windowManager.prototype.reset_screen = function()
	{
	var s = document.getElementById(this.screen_id);
	this.screen_fill_page(s);
	}

/* Open the given window
 * This is done without creating a new z-order and relying simply on the
 * order things are rendered by the browser - counting on a stack-like
 * behavior where the last item rendered is always at the top.
 */
windowManager.prototype.display_window = function()
	{
	/* Display both elements, we need to potentially update values on the focusArea
	 * but the screen should just be able to have the display set
	 */
	var elemScreen = top.document.getElementById(this.screen_id);

	//Fill the entire page (not just viewport) and display
	this.screen_fill_page(elemScreen);
	document.getElementById(this.screen_id).style.display = 'block';

	//Update values for focusArea
	var elemFocus = top.document.getElementById(this.id);
	elemFocus.style.width = this.width;
	elemFocus.style.height = this.height;
	elemFocus.style.top = this.top;
	elemFocus.style.left = this.left;
	//elemFocus.innerHTML = this.html;
	elemFocus.style.display = 'block';

	//Center the window in the screen
	this.center_window();

	//fade in the screen
//	fade_element(this.screen_id, 0.0, 0.9, 30, 0);
	this.set_screen_opacity(0.5);

	//set the is_open member
	this.is_open = true;
	}

/* Set the screen opacity after the fact. op is 0.0-1.0
 */
windowManager.prototype.set_screen_opacity = function(op)
	{
	var elemScreen = document.getElementById(this.screen_id);

	//change opacity to what should be current
	var ie = parseFloat(op) * 100;
	elemScreen.style.opacity = op;
	elemScreen.style.khtmlOpacity = op;
	elemScreen.style.mozOpacity = op;
	elemScreen.style.filter = "alpha(opacity=" + ie + ")";

	}

/* Center the content window in the middle of the current viewport
 */
windowManager.prototype.center_window = function()
	{
	//Get the current scrolling and the viewport size
	var arrScroll = getPageScroll();
	var arrPort = getViewportSize();

	/* Center the window within the viewport by doing the following:
	 * 	-Find the center of the viewport
	 * 	-Subtract by half the width of the focus window
	 * 	-Add the scrolling offset
	 */
	var posx = arrScroll[0] + ((arrPort[0] / 2) - (parseInt(this.width) / 2));
	var posy = arrScroll[1] + ((arrPort[1] / 2) - (parseInt(this.height) / 2));

	/* We need to check a condition where, if the focus area is bigger than the current
	 * screen, running this method will cause the top of the focus area to extend off
	 * the top of the viewport.  To correct this, if the values posx/posy are less than
	 * the scroll vars, we'll set them to the scroll vars
	 */
	if (posx < arrScroll[0])
		posx = arrScroll[0];

	if (posy < arrScroll[1])
		posy = arrScroll[1];

	//Position the focus area
	this.place_window(posy, posx);
	}

/* Close the given window by changing their display properties to 'none'
 */
windowManager.prototype.close_window = function()
	{
	document.getElementById(this.id).style.display = 'none';
	document.getElementById(this.screen_id).style.display = 'none';
	this.is_open = false;
	}

/* Accessor for the is_open property
 */
windowManager.prototype.window_is_open = function()
	{
	return this.is_open;
	}

/* Function, outside of class, to get the style element for all 4 major
 * opacity types given a value in the range 0.0-1.0
 */
function get_opacity_style(op)
	{
	var s = "";

	//w3c opacity
	s += "opacity: " + op + "; ";

	//ie alpha filter
	var ie = parseFloat(op) * 100;
	s += "filter: alpha(opacity=" + ie + "); ";

	//old mozilla opacity
	s += "-moz-opacity: " + op + "; ";

	//kHTML opacity (safari, konquerer)
	s += "-khtml-opacity: " + op + ";";

	return s;
	}

//Set the opacity styles for a given DOM element
function set_opacity_styles(elem, op)
	{
	//w3c
	elem.style.opacity = op;
	//old mozilla
	elem.style.MozOpacity = op;
	//kHTML
	elem.style.KhtmlOpacity = op;

	//IE alpha filter (if applicable)
	var ie = parseFloat(op) * 100;
	if (elem.style.filters)
		elem.style.filters.alpha.opacity = ie;
	}

//Fade the given element in steps recursions give 50ms breaks
function fade_element(elemid, sopacity, eopacity, total_steps, current_step)
	{
	if (current_step >= total_steps)
		return;

	var elem = document.getElementById('' + elemid);

	//Calculate the opacity per step
	var total_op_shift = eopacity - sopacity;
	var step_amount = total_op_shift / total_steps;

	var current_op = sopacity + (current_step * step_amount);

	//change opacity to what should be current
	var ie = parseFloat(current_op) * 100;

	//Set border limits
	if (current_op > 1.0 || current_op < 0.0)
		return;

	//Set opacity for 4 major types (w3c, ie, moz/nn & khtml)
	elem.style.opacity = current_op;
	elem.style.khtmlOpacity = current_op;
	elem.style.mozOpacity = current_op;
	elem.style.filter = "alpha(opacity=" + ie + ")";
	current_step++;



	//Recursively call the fade_element function
	setTimeout("fade_element('" + elemid + "', " + sopacity + ", "
				  + eopacity + ", " + total_steps + ", " + current_step + ")", 15);
	}



/* Code adapted from quirksmode.net
 */
function getPageScroll(){
	var xScroll;
	var yScroll;

	if (self.pageYOffset)
		{
		yScroll = self.pageYOffset;
		xScroll = self.pageXOffset;
		}
	// Explorer 6 Strict
	else if (document.documentElement && document.documentElement.scrollTop)
		{
		yScroll = document.documentElement.scrollTop;
		xScroll = document.documentElement.scrollLeft;
		}
	// all other Explorers
	else if (document.body)
		{
		yScroll = document.body.scrollTop;
		xScroll = document.body.scrollLeft;
		}

	arrayPageScroll = new Array(xScroll, yScroll)
	return arrayPageScroll;
}

/* Adapted from sitepoint.com article - get the size of the current viewport
 */
function getViewportSize()
	{
	var size;

	if (typeof window.innerWidth != 'undefined')
   		size = new Array(window.innerWidth, window.innerHeight);
   	else if (typeof document.documentElement != 'undefined' && typeof document.documentElement.clientWidth != 'undefined' && document.documentElement.clientWidth != 0)
   		size = new Array(document.documentElement.clientWidth, document.documentElement.clientHeight);
  	else
  		size = new Array(document.getElementsByTagName('body')[0].clientWidth, document.getElementsByTagName('body')[0].clientHeight);

	return size;
	}