//aryooeye.PopupDivManager;r.0.0.0;richarduie[at]yahoo[dot]com;(c)2008

/////////////////////////////////////////////////////////////////////////
//                                                                     //
//   Manage popup DIVs dynamically using JavaScript object prototype   //
//                                                                     //
/////////////////////////////////////////////////////////////////////////
//                                                                     //
//   RUI library member that enforces containment under "aryooeye"     //
//   namespace; offers pseudo-static reference options for public      //
//   members via name by dot(.)-references to members that can rely    //
//   on "instantiation" calls to default, no-argument constructor.     //
//                                                                     //
/////////////////////////////////////////////////////////////////////////
//                                                                     //
//   Filename.......PopupDivManager.js                                 //
//   Author.........Richard Harrison (richarduie[at]yahoo[dot]com)     //
//   Created On.....2008-01-19                                         //
//   Last Revised...2008-01-31                                         //
//                                                                     //
/////////////////////////////////////////////////////////////////////////

/**
 *  @Object: PopupDivManager
 *
 *
 *  @Syntax: var popDivMgr = new aryooeye.PopupDivManager()
 *           PopupDivManager.{method_name}() [static]
 *
 *  @Goals:  add popup DIVs on-the-fly
 *
 *  NOTE.....this is a very lightweight implementation to 
 *           keep the bandwidth requirements small - the 
 *           popup containers are DIV elements and, thus, 
 *           can contain any other type of HTML element - 
 *           however, there is no built-in defense against 
 *           the "bleed-through" of window-class elements, 
 *           e.g., select controls, in IE6 - if such 
 *           protection is required, try one of the heavy-
 *           weight implementations, such as the YUI 
 *           container/ovelay module.
 */


/////////////////////////////////////////////////////////////////////
//   N A M E S P A C E   C O N T A I N E R   O V E R H E A D
//
//   Enforce the condition that any RUI object can only be
//   created under the namespace aryooeye in order to further
//   ensure protection from potential name-collisions.
//
	// If namespace object does not yet exist, create it.
	if ('undefined' == typeof aryooeye) var aryooeye = new Function();
	// If object has already been attached, exit.
	if ('undefined' == typeof aryooeye.PopupDivManager)
{	// open conditional object creation
	// Now add current object to aryooeye namespace.
	aryooeye.PopupDivManager =


function PopupDivManager ()
{
	//////////////////////////////////////////////////////////////////
	//  D E P E N D E N C Y   M A N A G E M E N T  ///////////////////
	//	 ...no current dependencies...

	//////////////////////////////////////////////////////////////////
	//  P R I V A T E   M E M B E R S  ///////////////////////////////
		// Declare private methods.
			function register(puid, pud) {
			// register associative index (key) for popup (div) -
			// note - key will be id of div element in page context
				puArray[puid] = pud;
			}

			function addCloser(content, puid, name) {
			// for persistent popups that are not closed in response to some other event,
			// provide a fairly obvious "close" idiom to allow user to close the popup
			// manually - place a click-sensitive "X" on the popup to allow user to
			// close the popup manually
				var cs = closerStyle;	// convenience reference to style for closer [X]
				// convert font-size of closer [X] to integer
				var fs = parseInt(cs.substring(cs.indexOf('font-size:') + 'font-size:'.length));
				var p = parseInt(padding);					// convert padding to integer
				// reduce available width for content by font-size of closer [X] and
				// padding of container div
				var w = (width - fs - p) + 'px';			// calcuate width for content
				// left placement for closer [X] puts right margin of [X] 2px from right-
				// hand border of container (top is 2px as well - statically declared)
				var l = (width - fs + p - 2) + 'px';	// calculate left for "button"
				// add HTML for closer to the content for the popup
				var c = '' +
					'<div style="width: ' + w + ';">' + content + '</div>' 	+
					'<div style="' + cs + ' left: ' + l + ' ;" ' 					+
						'onclick="' + name + '.hidePopup(\'' + puid + '\');">X</div>'		;
				return c;
			}

			function chkParms(puid, c, w, h, l, t, x) {
			// check parameters and set internal values accordingly
			// return true, if all's well - otherwise false
				if (!puid || !c) return false;	// exit, if container id or content missing
				content = c;							// set content to that requested
				width = ((!w)?300:w) + 'px';		// set width to that requested, with default
				height = ((!h)?300:h) + 'px';		// set height to that requested, with default
				left = ((!l)?300:l) + 'px';		// set left to that requested, with default
				top = ((!t)?300:t) + 'px';			// set top to that requested, with default
				// set indicator of whether div will have a "closer" element, default to true
				hasCloser = (!x && false != x)?true:x;
				return true;	// good exit
			}

		// Declare private fields.
			// - publicly gettable and settable
			//  style attributes for popup - initialize with defaults
			var backgroundColor = '#EEE';
			var borderColor = 'black';
			var borderStyle = 'solid';
			var borderWidth = '2px';
			var color = '#48A';
			var fontFamily = 'Arial, sans-serif';
			var fontSize = '14px';
			var fontWeight = 'bold';
			var margin = 0;
			var padding = '6px';
			var position = 'absolute';
			var textAlign = 'left';
			var zIndex = 9;
			var highestZ = 9;

			var hasCloser;					// Boolean to indicate whether popup has a closer [X] control
			var puArray = new Array();	// puArray to store popups

			var name = 'pdm';				// default name for object - reset as needed to avoid name-collisions

			// set style attributes for closer control, in case requested
			var closerStyle = '' +
				'background-color: white; '			+
				'border: 2px solid red; ' 				+
				'color: red; '								+
				'cursor:pointer; '						+
				'font-family: Arial, sans-serif; '	+
				'font-size: 10px; '						+
				'font-weight: bold; '					+
				'margin: 0; '								+
				'padding: 0 0 1px 1px; '				+
				'position: absolute; '					+
				'top: 2px; '								+
				'text-align: center; '					+
				'width: 10px; '							;

			var content, width, height, left, top;	// no default values for these

			// - publicly gettable only

	//////////////////////////////////////////////////////////////////
	//  P U B L I C   M E M B E R S  /////////////////////////////////
		// Declare public methods.
			// - accessors and mutators...privileged updates of private fields
			//  use of any of the setters will override previous settings with
			//  new values that will be used for any new popups created after
			//  the change - existing, registered popups are not affected
			this.getBgColor = function() { return backgroundColor; }
			this.setBgColor = function(b) { backgroundColor = b; }

			this.getBorderColor = function() { return borderColor; }
			this.setBorderColor = function(b) { borderColor = b; }

			this.getBorderStyle = function() { return borderStyle; }
			this.setBorderStyle = function(b) { borderStyle = b; }

			this.getBorderWidth = function() { return borderWidth; }
			this.setBorderWidth = function(b) { borderWidth = b; }

			this.getCloserStyle = function() { return closerStyle; }
			this.setCloserStyle = function(s) { closerStyle = s; }

			this.getColor = function() { return color; }
			this.setColor = function(c) { color = c; }

			this.getContent = function() { return content; }
			this.setContent = function(c) { content = c; }

			this.getFontFamily = function() { return fontFamily; }
			this.setFontFamily = function(f) { fontFamily = f; }

			this.getFontSize = function() { return fontSize; }
			this.setFontSize = function(f) { fontSize = f; }

			this.getFontWeight = function() { return fontWeight; }
			this.setFontWeight = function(f) { fontWeight = f; }

			this.getHasCloser = function() { return hasCloser; }
			this.setHasCloser = function(h) { hasCloserStyle = h; }

			this.getHeight = function() { return height; }
			this.setHeight = function(h) { height = h; }

			this.getLeft = function() { return left; }
			this.setLeft = function(l) { left = l; }

			this.getName = function() { return name; }
			this.setName = function(n) { name = n; }

			this.getPadding = function() { return padding; }
			this.setPadding = function(p) { padding = p; }

			this.getTop = function() { return top; }
			this.setTop = function(l) { top = t; }

			this.getWidth = function() { return width; }
			this.setWidth = function(w) { width = w; }

			this.getZIndex = function() { return zIndex; }
			this.setZIndex = function(z) { zIndex = z; }

			// - control methods
			this.createPopup = function(puid, c, w, h, l, t, x) {
			// create the popup and assign its properties
				if (!chkParms(puid, c, w, h, l, t, x)) return false;
				if (puArray[puid]) this.destroyPopup(puid);
				var DIV = document.createElement('DIV');
				DIV.id = puid;
				DIV.innerHTML = (hasCloser)?addCloser(content, puid, this.getName()):content;
				DIV.style.backgroundColor = backgroundColor;
				DIV.style.borderColor = borderColor;
				DIV.style.borderStyle = borderStyle;
				DIV.style.borderWidth = borderWidth;
				DIV.style.color = color;
				DIV.style.display = 'none';			// intitially, don't show popup
				DIV.style.fontFamily = fontFamily;
				DIV.style.fontSize = fontSize;
				DIV.style.fontWeight = fontWeight;
				DIV.style.left = left;
				DIV.style.margin = margin;
				DIV.style.padding = padding;
				DIV.style.position = position;
				DIV.style.textAlign = textAlign;
				DIV.style.top = top;
				DIV.style.width = width;
				DIV.style.zIndex = zIndex;
				document.body.appendChild(DIV);		// add element to body of document
				register(puid, DIV);						// record id and element
				return true;
			}

			this.showPopup = function(puid) {
				try {
					document.getElementById(puid).style.display = 'block';
					return true;
				}
				catch (e) {	return false;}
			}

			this.hidePopup = function(puid) {
				try {
					document.getElementById(puid).style.display = 'none';
					return true;
				}
				catch (e) {	return false;}
			}

			this.destroyPopup = function(puid) {
				var d = document.getElementById(puid);
				try {
					document.body.removeChild(d);
				}
				catch (e) {;}
				register(puid, null);
			}

			this.doPopup = function(puid, c, w, h, l, t, x) {
			// convenience method to both create and show popup with current
			// properties, except for those specified in parameters
				if (this.createPopup(puid, c, w, h, l, t, x)) {
					this.showPopup(puid);
					return true;
				}
				else return false;
			}

			this.hideAllPopups = function() {
			// hide all popups currently under management
				for(key in puArray) {
					this.hidePopup(key);
				}
			}
			// Declare public fields.

	//////////////////////////////////////////////////////////////////
	//  C O N S T R U C T O R  ///////////////////////////////////////
		// Construction steps - only run at instantiation.
		// ...no differential construction required at present...
}

}	// close conditional object creation

/////////////////////////////////////////////////////////////////////
//   S U P P O R T    P S E U D O - S T A T I C    C L A S S -
//   S T Y L E    R E F E R E N C E S
	//	Since constructor supports default, no-argument instantiation,
	// provide a "static" reference version to the public members.
	// Note that this removes rui namespace insulation against name-
	// collisions; developer is responsible for managing name-safety
	// in implementation context. Next statement can be commented or
	// de-commented without affecting base object in any way.
//	var PopupDivManager = new aryooeye.PopupDivManager();
