/** -----------------------------------------------------------------------------

	FILE:		Popup.js
	PURPOSE:	Javascript Popup Window for allowing the user to select a filter

	Copyright 2007,2008,2009 (c) FlowTech Solutions, Inc.		(www.FlowTech-Solutions.com)

	Permission is hereby granted, free of charge, to any person obtaining
	a copy of this software and associated documentation files (the
	"Software"), to deal in the Software without restriction, including
	without limitation the rights to use, copy, modify, merge, publish,
	distribute, sublicense, and/or sell copies of the Software, and to
	permit persons to whom the Software is furnished to do so, subject to
	the following conditions:

	The above copyright notice and this permission notice shall be
	included in all copies or substantial portions of the Software.

	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
	MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
	NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
	LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
	OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
	WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


	PUBLIC METHODS		DESCRIPTION
	--------------				---------------------------------------------------
	initialize()					Initializes the control by dynamically loading the style file
	show(options)			Display the control using the configuration options (see below)
	hide()						Hides teh control and disconnects the listeners for its behaviors

	DEPENDENCIES
	------------
	prototype 1.6.0.3

----------------------------------------------------------------------------- */

var Popup = function()
{	// Singleton class
	if (window.Popup) return window.Popup;

	/* -- Public Methods ----------------------------------------------------- */
	var _public =
	{
		// Initializes and configures the control control
		initialize: function()
		{
			_private._loadStyleFile('script/css/'+_private._defaultOptions.className+'.css');
			_private.classNameLoaded = _private._defaultOptions.className;
			_private._zIndex = _private._getMaxZIndex();
		},

		size : function(optns)
		{
			_private._options = Object.extend( _private._options, optns||{} );
			_private._options.left = (_private._options.left+'').toLowerCase();
			_private._options.top = (_private._options.top+'').toLowerCase();
			_private._options.width = (_private._options.width+'').toLowerCase();
			_private._options.height = (_private._options.height+'').toLowerCase();

			if (_private._options.width == 'auto')
			{
				_private._PopupElement.style.width = 'auto';
			}
			else if ( !isNaN( parseFloat(_private._options.width) ) )
			{
				_private._PopupElement.style.width = parseFloat(_private._options.width) + 'px';
			}
			var cntnt = $('_PopupContent');
			if (_private._options.height == 'auto')
			{
				cntnt.style.height = 'auto';
			}
			else if ( !isNaN( parseFloat(_private._options.height) ) )
			{
				cntnt.style.height = parseFloat(_private._options.height) + 'px';
			}

			if (_private._options.scrollable)
				cntnt.addClassName('Popup_VerticalScrolling');
			else
				cntnt.addClassName('Popup_NoScrolling');

			// Establish the controls initial position on the page
			var popupSize = _private._PopupElement.getDimensions();
			var pageSize = _private._getPageSize();
			var pageCenter  = {y:Math.floor(pageSize.pageHeight/2), x:Math.floor(pageSize.pageWidth/2)};
			var top,left;
			switch (_private._options.left)
			{
				case 'left':
					left = 0;
					break;
				case 'right':
					left = Math.floor(pageSize.pageWidth - popupSize.width) ;
					break;
				case 'center':
					left = Math.ceil(pageCenter.x - popupSize.width / 2) ;
					break;
				default:
					left = Math.floor(parseFloat(_private._options.left)) ;
					break;
			}
			switch (_private._options.top)
			{
				case 'top':
					top = 0;
					break;
				case 'bottom':
					top = Math.floor(pageSize.pageHeight - popupSize.height);
					break;
				case 'center':
					top = Math.ceil(pageCenter.y - popupSize.height / 2) ;
					break;
				default:
					top = Math.floor(parseFloat(_private._options.top));
					break;
			}
			//_private._options.left = left +'px';
			//_private._options.top = top +'px';
			_private._PopupElement.style.left = parseFloat(left) + 'px';
			_private._PopupElement.style.top = parseFloat(top) + 'px';
		},


		// Configures and displays the control control, closes existing displayed control
		show : function(optns)
		{
			// Apply the user options to the control's configuration
			_private._options = _private._clone(_private._defaultOptions);
			_private._options = Object.extend( _private._options, optns||{} );
			_private._options.type = _private._options.type.toUpperCase();
			_private._options.left = (_private._options.left+'').toLowerCase();
			_private._options.top = (_private._options.top+'').toLowerCase();

			// If Style is NOT loaded, load new style sheet
			if (_private._options.className != _private.classNameLoaded)
			{
				_private._loadStyleFile('script/css/'+_private._options.className+'.css');
				_private.classNameLoaded = _private._options.className;
			}

			// Hide the drop downs if in IE browser (browser bug)
			if (Prototype.Browser.IE) _private._hideDropDowns();

			// Establish working z-Index level to ensure control shows on top
			var current_zindex = _private._getMaxZIndex();
			if (current_zindex > _private.zIndex) _private.zIndex = current_zindex;

			// If modal then create underlay to capture mouse clicks
			if (_private._options.modal)	_private._makeModal();

			// Establish base control container
			_private._PopupElement = $(_private._PopupID);
			if (!_private._PopupElement)
			{
				_private._PopupElement = document.createElement("div");
				_private._PopupElement = Object.extend( _private._PopupElement, {id:_private._PopupID, className:_private._options.className});
				$(_private._PopupElement).setStyle({display:'', zIndex:_private.zIndex+9, width:'auto', position:'absolute', left:'0px', top:'0px'});
				//document.body.insertBefore(_private._PopupElement,document.body.firstChild);
				document.body.appendChild(_private._PopupElement);
				_private._PopupElement = $(_private._PopupID);
			}
			_private._PopupElement.setStyle({display:'none', zIndex:_private.zIndex+9});

			// Assemble the chrome and contents
			_private._PopupElement.innerHTML =
				//'<div id="Popup"  style="width: 350px; height:100px; position:absolute; left: 100px; top:100px;">'+
					'<div class="Popup_Shell" id="Popup_Shell">'+
						'<div class="Popup_Wrapper">'+
							'<div class="Popup_n Popup_Draggable">'+
								'<div class="Popup_nw Popup_Draggable"><!-- dnc --></div>'+
								'<div class="Popup_ne Popup_Draggable"><!-- dnc --></div>'+
							'</div>'+
						'</div>'+
						'<div class="Popup_Wrapper">'+
							'<div class="Popup_w">'+
								'<div class="Popup_e">'+
									'<div class="Popup_ContentHolder">'+
										'<div class="Popup_Title Popup_Draggable">'+_private._renderTitle()+'</div>'+
										'<div class="Popup_Content" id="_PopupContent">'+
											((_private._options.type == 'FILTER') ? _private._renderFilter() :
											 (_private._options.type == 'SORT') ? _private._renderSort() :
											 (_private._options.type == 'DROPDOWN') ? _private._renderDropdown() :
											 (_private._options.type == 'MESSAGE') ? _private._renderMessage() : '' ) 	+
										'</div>'+
										'<div class="Popup_Footer">'+_private._renderFooter()+'</div>'+
									'</div>'+
								'</div>'+
							'</div>'+
						'</div>'+
						'<div class="Popup_Wrapper" style="">'+
							'<div class="Popup_s">'+
								'<div class="Popup_sw"><!-- dnc --></div>'+
								'<div class="Popup_se"><!-- dnc --></div>'+
							'</div>'+
						'</div>'+
					'</div>';
				//'</div>';

			// If  FILTER content populate field values and drop downs
			if (_private._options.type == 'FILTER')
			{// Populate the filter fields
				//	 Filter = PrefixOperation^DBAttribute^Operation^FilterValue|PrefixOperation^DBAttribute^Operation^FilterValue
				//		where Operation is: CONTAINS, STARTSWITH, EQ, NE, GT, LT, GE, or LE    	FilterValue is: value to test against		PrefixOperation is: AND, OR
				var lovLoad = _private._options.lovLoad||'';
				var lovValue = _private._options.lovValue;
				var lovDesc = _private._options.lovDesc;
				var lovSelected = _private._options.lovSelected||'';
				var lovDisable = _private._options.lovDisable||'';
				if (!lovLoad || !lovValue || lovValue=='' || !lovDesc || lovDesc=='') return false;
				var filters = _private._options.filter.split('|');
				for (var f=0; f< _private._options.nbrFilterLevels; f++)
				{
					if (f<filters.length)
					{
						filter = filters[f].split('^');
						if (filter.length < 3) break;
						if (f>0)		_private._selectOption('fltrPrefix_'+f,filter[0])
						_private._loadLov('fltrField_'+f,lovLoad,lovValue,lovDesc,filter[1],lovDisable);
						_private._selectOption('fltrOper_'+f,filter[2])
						$('fltrValue_'+f).setValue(filter[3]||'');
					}
					else
						_private._loadLov('fltrField_'+f,lovLoad,lovValue,lovDesc,'',lovDisable);
				}
			}
			else
			// If  FILTER content populate field values and drop downs
			if (_private._options.type == 'SORT')
			{// Populate the sort fields
				//	 Sort = DBAttribute Asc_Desc [,DBAttribute Asc_Desc ...]
				var lovLoad = _private._options.lovLoad||'';
				var lovValue = _private._options.lovValue;
				var lovDesc = _private._options.lovDesc;
				var lovSelected = _private._options.lovSelected||'';
				var lovDisable = _private._options.lovDisable||'';
				if (!lovLoad || !lovValue || lovValue=='' || !lovDesc || lovDesc=='') return false;
				var sorts = _private._options.sort.split(',');
				for (var s=0; s<_private._options.nbrSortLevels; s++)
				{
					if (s<sorts.length)
					{
						sort = sorts[s].removeWhiteSpace().split(' ');
						sortField = sort[0];
						sortOrder = ((sort.length < 2) ? 'ASC' : sort[1]).toUpperCase();
						_private._loadLov('sortField_'+s, lovLoad, lovValue, lovDesc, sortField, lovDisable);
						_private._selectOption('sortOrder_'+s, sortOrder)
					}
					else
					{
						_private._loadLov('sortField_'+s, lovLoad, lovValue, lovDesc, '', lovDisable);
						//_private._selectOption('sortOrder_'+s, 'ASC')
					}
				}
			}
			else
			// If  FILTER content populate field values and drop downs
			if (_private._options.type == 'DROPDOWN')
			{// Populate the sort fields
				//	 Sort = DBAttribute Asc_Desc [,DBAttribute Asc_Desc ...]
				var lovLoad = _private._options.lovLoad||'';
				var lovValue = _private._options.lovValue;
				var lovDesc = _private._options.lovDesc;
				var lovSelected = _private._options.lovSelected||'';
				var lovDisable = _private._options.lovDisable||'';
				if (!lovLoad || !lovValue || lovValue=='' || !lovDesc || lovDesc=='') return false;
				_private._loadLov('dropdownField', lovLoad, lovValue, lovDesc, lovSelected, lovDisable);
			}

			Popup.size();

			// Establish the close  control behavior
			$('_PopupClose').observe('click',_private._closeButton);

			if ( _private._options.draggable )
			{// Enable the draggable feature by adding listeners to the draggable areas
				var dragElms = _private._PopupElement.getElementsByClassName('Popup_Draggable');
				for (var i=0; i<dragElms.length; i++)
					$(dragElms[i]).observe( 'mousedown', _private._dragOBJ );
			}

			// Establish behavior for the optional buttons
			var buttons = _private._options.showButtons.split(",");
			var buttonID, button;
			for (var b=0; b<buttons.length; b++)
			{
				buttonID = buttons[b].split("|")[0];
				button = $('Popup_'+buttonID);
				button.observe('click',_private._buttonListener);
			}

			// Establish a listener for closing the control if the user clicks outside of the control
			if ( _private._options.autoClose )
				$(document.body).observe('click',_private._autoClose);


			// Display the popup control
			window.setTimeout(function(){_private._PopupElement.style.display = '';},50);

			// Fire an event to indicate the popup has been displayed
			_private.zIndex = _private._getMaxZIndex();
			window.setTimeout(function(){$(document).fire("Popup:Show",{options:_private._options});},150);
		},

		// Hides the popup control
		hide : function()
		{
			// Disconnect the listener for the click outside the control
			if ( _private._options.autoClose )
				$(document.body).stopObserving('click',_private._autoClose);

			// Disconnect the listener for the control close event
			$('_PopupClose').stopObserving('click',_private._closeButton);

			// Disconnect the drag related event listeners for the control
			if ( _private._options.draggable )
			{// Enable the draggable feature by adding listeners to the draggable areas
				var dragElms = _private._PopupElement.getElementsByClassName('Popup_Draggable');
				for (var i=0; i<dragElms.length; i++)
				{
					$(dragElms[i]).stopObserving('mousedown', _private._dragOBJ);
				}
			}

			// Disconnect the custom buttons events associated with the control
			var buttons = _private._options.showButtons.split(",");
			var buttonID;
			for (var b=0; b<buttons.length; b++)
			{
				buttonID = buttons[b].split("|")[0];
				$('Popup_'+buttonID).stopObserving('click', _private._buttonListener);
				$(document).stopObserving("Popup:"+buttonID);
			}

			// If modal then destroy underlay
			if (_private._options.modal) _private._destroyModal();

			// Remove any remaining listeners
			$(document).stopObserving("Popup:Show");
			$(document).stopObserving("Popup:OK");
			$(document).stopObserving("Popup:YES");
			$(document).stopObserving("Popup:NO");
			$(document).stopObserving("Popup:CANCEL");

			// Make the control dissapear
			_private._PopupElement = $(_private._PopupID);
			_private._PopupElement.style.display = 'none';

			// Restore the drop downs if in IE browser (browser bug)
			if (Prototype.Browser.IE) _private._unhideDropDowns();

			$(document).fire("Popup:Hide",{options:_private._options});
		},

		loadLov: function(elm,lovLoad,lovValue,lovDesc,lovSelected,lovDisable)
		{
			_private._loadLov(elm,lovLoad,lovValue,lovDesc,lovSelected,lovDisable);
		}
	};


	/* -- Private Properties and Methods ------------------------------------- */
	var _private =
	{
		_PopupID :		'Popup',
		_PopupElement :	null,
		_zIndex :		0,
		_defaultOptions :		{
						className:		"PopupInfo",			// Style skin to use
						type:				"FILTER",			// FILTER, SORT, DROPDOWN, or MESSAGE
						title:					"SELECT FILTER(s)",
						showButtons:	"OK|Ok,CLOSE|Close,CANCEL|Cancel,YES,NO",
						hide:				true,
						top:					"center",			// absolute position of the top edge of the control
						left:					"center",			// absolute position of the left edge of the control
						width:				null,
						height:				null,
						draggable:		true,					// Determines if control is draggable
						scrollable:			false,				// true (vertical scrolling only) or false
						modal:				false,				// makes the popup modal (do not use with autoClose)
						autoClose:		false,				// enables the automatic closing of the control if user clicks outside of it
						filter:				"",						//	Filter = PrefixOperation^DBAttribute^Operation^FilterValue|PrefixOperation^DBAttribute^Operation^FilterValue
																		//	where Operation is: CONTAINS, STARTSWITH, EQ, NE, GT, LT, GE, or LE    FilterValue is: value to test against	PrefixOperation is: AND, OR
						nbrFilterLevels:	 2,
						sort:					",",
						nbrSortLevels:	3,
						dropdown:			"",
						lovLoad:			"{Code:'0', Desc:'Description 0'}{Code:'1', Desc:'Description 1'}{Code:'2', Desc:'Description 2'}{Code:'3', Desc:'Description 3'}",
						lovValue:			"Code",
						lovDesc	:			"Desc",
						message:			""							// Required if type=MESSAGE
						},



		// Renders the HTML title area of the control
		_renderTitle: function ()
		{
			var html ='<img id="_PopupClose" class="Popup_Close" src="script/css/Popup/close.gif" width="13" height="13" title="Close" border="0"/>'+
							'<span class="Popup_HeaderTitle Popup_Draggable"  id="_PopupTitle">'+(_private._options.title || '')+'</span>';
			return (html);
		},


		// Renders HTML for selecting Filters
		_renderFilter: function()
		{
			var html = '<form id="filterForm"><table class="Popup_Filter" id="Popup_Filter" cellpadding="2" cellspacing="2" align="center"><tbody>';
			var blankLine = '<TR><TD colspan=3 style="Font-Size: 1pt; Height: 4pt;">&nbsp;</TD></TR>';
			for (var i=0; i<_private._options.nbrFilterLevels; i++)
			{
				if (i>0)
				{
					html += blankLine +
						'<TR><TD width="1px"></TD>' +
								'<TD align="center"><SELECT id="fltrPrefix_'+i+'" class="Popup_FilterSelect"><OPTION VALUE="">&nbsp;</OPTION><OPTION VALUE="AND">AND</OPTION><OPTION VALUE="OR">OR</OPTION></SELECT></TD>' +
								'<TD width="1px"></TD>' +
						'</TR>';
				}
				html += blankLine +
						'<TR><TD width="1px"></TD>' +
							'<TD align="center" >' +
								'<SELECT id="fltrField_'+i+'"  class="Popup_FilterSelect"><OPTION VALUE="">&nbsp;</OPTION></SELECT>&nbsp;' +
								'<SELECT id="fltrOper_'+i+'"  class="Popup_FilterSelect"><OPTION VALUE="">&nbsp;</OPTION><OPTION VALUE="CONTAINS">CONTAINS</OPTION><OPTION VALUE="STARTSWITH">STARTS WITH</OPTION><OPTION VALUE="EQ">EQUALS</OPTION><OPTION VALUE="NE">NOT EQUAL</OPTION><OPTION VALUE="GT">GREATER THAN</OPTION><OPTION VALUE="LT">LESS THAN</OPTION><OPTION VALUE="GE">GTR THN EQUAL</OPTION><OPTION VALUE="LE">LESS THN EQUAL</OPTION></SELECT>&nbsp;&nbsp;' +
								'<INPUT type="text" ID="fltrValue_'+i+'" maxlength=250 size=15 class="Popup_FilterInput" title="Enter a value" value="" />' + '</TD>' +
							'<TD width="1px"></TD>' +
						'</TR>';
			}
			html += blankLine +
					'<TR><TD width="1px"></TD>' +
						'<TD ID="Popup_Message" class="Popup_Message" width="99%">'+(_private._options.message||'')+'</TD>' +
						'<TD width="1px"></TD>' +
					'</TR>' +
					blankLine;

			html += "</tbody></table></form>";		// Completes the HTML for the control
			return html;
		},


		// Renders HTML for selecting Sorts
		_renderSort: function()
		{
			var html = '<form id="sortForm"><table class="Popup_Sort" id="Popup_Sort" cellpadding="2" cellspacing="2" align="center"><tbody>';
			var blankLine = '<TR><TD colspan=3 style="Font-Size: 1pt; Height: 4pt;">&nbsp;</TD></TR>';
			for (var i=0; i<_private._options.nbrSortLevels; i++)
			{
				html += blankLine +
					'<TR><TD width="1px"></TD>' +
							'<TD align="center" >' +
							  '<SELECT id="sortField_'+i+'" class="Popup_SortSelect"><OPTION VALUE="">&nbsp;</OPTION></SELECT>&nbsp;' +
							  '<SELECT id="sortOrder_'+i+'" class="Popup_SortSelect"><OPTION VALUE="">&nbsp;</OPTION><OPTION VALUE="ASC">Ascending</OPTION><OPTION VALUE="DESC">Descending</OPTION></SELECT>' +
							'<TD width="1px"></TD>' +
						'</TR>';
				}
			html += blankLine;

			html += "</tbody></table></form>";		// Completes the HTML for the control
			return html;
		},


		// Renders HTML for selecting Sorts
		_renderDropdown: function()
		{
			var html = '<form id="dropdownForm"><table class="Popup_Dropdown" id="Popup_Dropdown" cellpadding="2" cellspacing="2" align="center"><tbody>';
			var blankLine = '<TR><TD colspan=3 style="Font-Size: 1pt; Height: 4pt;">&nbsp;</TD></TR>';
			html += blankLine +
					'<TR><TD width="1px"></TD>' +
							'<TD align="center"><SELECT id="dropdownField" class="Popup_DropdownSelect"><OPTION VALUE="">&nbsp;</OPTION></SELECT></TD>' +
							'<TD width="1px"></TD>' +
					'</TR>';
			html += blankLine +
					'<TR><TD width="1px"></TD>' +
							'<TD ID="Popup_Message" class="Popup_Message" width="99%">'+(_private._options.message||'')+'</TD>' +
							'<TD width="1px"></TD>' +
					'</TR>' +
					blankLine;
			html += "</tbody></table></form>";		// Completes the HTML for the control
			return html;
		},


		// Simply stuff the message (HTML) provided in the options.message into the content area
		_renderMessage: function()
		{
			var html = '<span id="InformationMessage">'+(_private._options.message||'')+'</span>';
			return(html);
		},


		// Assemble footer button toolbar
		_renderFooter: function()
		{
			var html='';
			var buttons = _private._options.showButtons.split(",");
			var buttonID, buttonText;
			for (var b=0; b<buttons.length; b++)
			{
				buttonID = buttons[b].split("|")[0];
				buttonText = buttons[b].indexOf("|") >= 0 ? buttons[b].split("|")[1] : buttons[b].split("|")[0];
				html += "<a href='#' class='Popup_Button' id='Popup_"+buttonID+"'>"+buttonText+"</a> ";
			}
			return(html);
		},


		// Populate and establish selected value for the drop down element
		_loadLov: function(elm,lovLoad,lovValue,lovDesc,lovSelected,lovDisable)
		{
			elm = $(elm);
			if (elm.tagName.toLowerCase() != 'select' || !lovLoad || !lovValue || !lovDesc) return false;
			lovDisable = lovDisable || '';
			lovSelected = ',' + lovSelected + ',';
			try
			{
				var lovArray = eval('['+lovLoad.replace(/\+/g,' ').replace(/\|/g,',').replace(/\}\{/g,'},{').replace(/\}\s\{/g,'},{')+']');
				// Constructor: var newOpt = new Option("text", "value", isDefaultSelectedFlag, isSelectedFlag);
				for (var k=0, idx=0; k<lovArray.length; k++)
				{
					idx = elm.options.length;
					//optionValue = Url.decode(LovArray[k][LovValue]);
					//elm.options[idx] = new Option(Url.decode(LovArray[k][LovDesc]), Url.decode(LovArray[k][LovValue]), false, false);
					optionValue = lovArray[k][lovValue];
					elm.options[idx] = new Option(lovArray[k][lovDesc], lovArray[k][lovValue], false, false);
					elm.options[idx].extendedProperties = lovArray[k];
					elm.options[idx].disabled = (lovDisable !='' ? lovArray[k][lovDisable] : false);
					elm.options[idx].selected = (lovSelected !='' ? lovSelected.indexOf(','+optionValue+',')>=0 : false);
				}
			}
			catch (err)
			{
				_private._logError({ name:'_lovLoad()', description:'Popup._lovLoad() assembling LOV array failed', error:err });
			}
			return true;
		},


		// Establish Current Selection For Dropdown Control
		_selectOption: function(elm, value)
		{
			elm=$(elm);
			for (var k=0; k<elm.options.length; k++)
			{
				if (elm.options[k].value.toUpperCase() == value.toUpperCase())
				{
					elm.selectedIndex = k;
					return;
				}
			}
		},


		// Makes the popup modal.  User must click a button in the control.
		_makeModal: function()
		{
			_private._modalUnderlay = $(_private._PopupID+'Underlay');
			if (_private._modalUnderlay) return;
			_private._modalUnderlay =document.createElement("div");
			_private._modalUnderlay = Object.extend( _private._modalUnderlay,
				{id:_private._PopupID+'Underlay', className:'Popup_Underlay'});
			window.document.body.insertBefore(_private._modalUnderlay,window.document.body.firstChild);
			_private._modalUnderlay = $(_private._PopupID+'Underlay');
			_private._modalUnderlay.setStyle(
				{zIndex:_private.zIndex+8, display:'',position:'absolute',top:'0',left:'0',
				 height:_private._getPageSize().pageHeight+'px',width:'100%'});
			Event.observe( _private._modalUnderlay, 'click', _private._emptyFunction );

			// Special Case: create a div element to disable the top navigation bar on the top most parent page
			if ( typeof(utils) == "object" && utils.enableNavigation ) utils.enableNavigation(false);
		},

		// Makes the popup modal.  User must click a button in the control.
		_destroyModal: function()
		{
			if (!_private._modalUnderlay) return;
			Event.stopObserving( _private._modalUnderlay, 'click', _private._emptyFunction );
			_private._modalUnderlay.setStyle({zIndex:0, display:'none'});
			_private._modalUnderlay.parentNode.removeChild(_private._modalUnderlay);
			_private._modalUnderlay = null;
		},

		// Empty function to capture clicks on the underlay (modal)
		_emptyFunction : function(evnt)
		{
			Event.stop(evnt);
			return(false);
		},


		// Button Listener
		_buttonListener: function(evnt)
		{
			var eventElement = Event.element(evnt);
			//  We verify explicitly the event element is the actual triggering element
			var buttons = _private._options.showButtons.split(",");
			var buttonID, button=null, b=99999;
			for (b=0; b<buttons.length && button!=eventElement; b++)
			{
				buttonID = buttons[b].split("|")[0];
				button = $('Popup_'+buttonID);
			}

			// Hide the popup
			//_public.hide();

			// Dont recoignize the button just return
			if (button!=eventElement)	 return(true);

			var newFilter = '';
			if (_private._options.type == 'FILTER')
			{
				for (var f=0; f<_private._options.nbrFilterLevels; f++)
				{

					fltrPrefix = (f>0) ?  $('fltrPrefix_'+f).getValue() : '';
					fltrField = $('fltrField_'+f).getValue();
					fltrOper = $('fltrOper_'+f).getValue();
					flterValue = $('fltrValue_'+f).getValue().trim();
					if ( (f==0 || (f>0 && fltrPrefix != '' && fltrField)) && fltrField != '' && fltrOper != '' && flterValue != '' )
					{
						newFilter += (f>0 ? '|':'') + fltrPrefix + '^' + fltrField + '^' + fltrOper + '^' + flterValue;
					}
				}

			}

			var newSort = '';
			if (_private._options.type == 'SORT')
			{
				for (var s=0; s<_private._options.nbrSortLevels; s++)
				{
					sortField = $('sortField_'+s).getValue();
					sortOrder = $('sortOrder_'+s).getValue()||'';
					if (sortField && sortField != '')
					{
						newSort += (newSort != '' ? ',':'') + sortField + ' ' + (sortOrder == '' ? 'ASC':sortOrder);
					}
				}
			}

			var newDropdown = '';
			if (_private._options.type == 'DROPDOWN')
			{
				dropdownField = $('dropdownField').getValue();
			}

			$(document).fire("Popup:"+buttonID,{
				options:_private._options,
				eventName:"Popup:"+buttonID,
				newFilter:newFilter,
				newSort:newSort,
				newDropdown:newDropdown
				});

			//if (evnt)	Event.stop(evnt);

			// Hide the popup
			if ( _private._options.hide )
				_public.hide();

			return(true);
		},

		_closeButton: function(evnt)
		{
			//if (evnt)	Event.stop(evnt);
			$(document).fire("Popup:Close",{options:_private._options});
			_public.hide();
		},

		// User click somewhere on the page
		_autoClose: function(evnt)
		{
			// if click event happened outside of the control control, close the control control
			var elt = $(Event.element(evnt));
			if (elt && !elt.descendantOf(_private._PopupElement))
				{
					//if (evnt)	Event.stop(evnt);
					_private._closeButton(evnt);
				}
			return true;
		},

		// Initiates the drag function of the copntrol
		_dragOBJ : function (evnt)
		{// Context is the calling page's DOM
			var dragElement = _private._PopupElement;
			//if ( !dragElement.hasClassName('Popup_Draggable') )	return true;
			if (evnt) evnt.stop();	// stop the event from bubbling any further
			var dragMode = true;

			function drag(evnt)
			{
				if( dragMode )
				{
					var pos = {x:evnt.screenX, y:evnt.screenY};
					//dragElement.innerHTML = "(" + pos.x + ", " + pos.y + ")"
					var dX = pos.x - anchor.x;
					var dY = pos.y - anchor.y;
					dragElement.style.left = (oX + dX) + 'px';
					dragElement.style.top = (oY + dY) + 'px';
					if (evnt) evnt.stop();	// stop the event from bubbling any further
				}
			}
			function stopdrag()
			{
				_private._options.left = dragElement.style.left;
				_private._options.top = dragElement.style.top;
				dragMode = false;
				dragElement = null;
				if (evnt) evnt.stop();	// stop the event from bubbling any further
				Event.stopObserving( document.body, 'mousemove', drag );
				Event.stopObserving( document.body, 'mouseup', stopdrag );
				_private._PopupElement = $(_private._PopupID);
			}

			var oX=parseInt(dragElement.style.left);
			var oY=parseInt(dragElement.style.top);
			_private._options.left = oX;
			_private._options.top = oY;
			var anchor = {x:evnt.screenX, y:evnt.screenY};
			// Capture mouse movements in parent(current) DOM space
			Event.observe(document.body, 'mousemove', drag );
			Event.observe(document.body, 'mouseup', stopdrag );
		},

		// Retrieves the maximum ZIndex value across the whole page
		_getMaxZIndex: function()
		{
			var allElems = window.top.document.getElementsByTagName ? window.top.document.getElementsByTagName("*") : window.top.document.all;
			var maxZIndex = 0;
			for (var i = 0; i < allElems.length; i++)
			{
				var zIndex = allElems[i].zIndex ? allElems[i].zIndex : allElems[i].style.zIndex;
				maxZIndex = (parseInt(zIndex) > maxZIndex) ? parseInt(zIndex) : maxZIndex;
			}
			return maxZIndex;
		},

		// Encodes the special character for HTML rendering
		_encodeToHtml: function(strng)
		{
			if (!strng || strng == '')
				return strng;
			var encodedHtml = strng.toString();
			return encodedHtml.split("\x3C").join("&lt;").split("\x26").join("&amp;").split("\x3E").join("&gt;").split("\x22").join("&quot;");
		},

		//	Enable the inclusion of dependent library components
		_loadJSFile: function(libraryName, scriptLoadedCallback)
		{
			var headID = document.getElementsByTagName("head")[0];
			var newScript = document.createElement('script');
			newScript.type = 'text/javascript';
			newScript.src = libraryName;
			if (typeof(scriptLoadedCallback) == "function")
			{
				newScript.onload = scriptLoadedCallback;
			}
			headID.appendChild(newScript);
			//inserting via DOM fails in Safari 2.0, so brute force approach
			//document.write('<script type="text/javascript" src="'+libraryName+'"></script>');
		},

		//	Enable the inclusion of dependent library components
		_loadStyleFile: function(StyleSheetName)
		{
			var headID = document.getElementsByTagName("head")[0];
			var cssNode = document.createElement('link');
			cssNode.type = 'text/css';
			cssNode.rel = 'stylesheet';
			cssNode.href = StyleSheetName;
			cssNode.media = 'screen';
			headID.appendChild(cssNode);
		},


		// Hides a list of SELECT elements (use for IE browser only)
		_hideDropDowns: function()
		{
			if (!Prototype.Browser.IE) return;
			var	elements = document.getElementsByTagName("select"),
					e, element, description, dLength;
			for (e = elements.length-1; e>=0; e--)
			{
				element = elements[e];
				if (element.style.display != 'none')
				{
					description = (element.selectedIndex >= 0) ? element.options[element.selectedIndex].text : '';
					dLength = Math.ceil(1.1*description.length);
					dLength = (dLength <= 0) ? 1: dLength;
					var newInputelement = document.createElement('input');
					newInputelement = Object.extend(newInputelement,
						{id:"xpop_"+element.id, readOnly:true, className:'ReadOnly', type:'text', value:description, size:dLength});
					element.parentNode.insertBefore(newInputelement,element.nextSibling);
					newInputelement.style.width = parseInt(element.style.width)+'px';
					newInputelement.style.height = parseInt(element.style.height)+'px';
					element.style.display = 'none';
				}
			}
		},

		// Unhides all the elements that were hidden  (use for IE browser only)
		_unhideDropDowns: function()
		{
			if (!Prototype.Browser.IE) return;
			var element, tmpElement, e, elements = document.getElementsByTagName("select");
			for (e = elements.length-1; e>=0; e--)
			{
				element = elements[e];
				tmpElement = $("xpop_"+element.id);
				if (tmpElement)
				{// Existence of element prefixed by xcal_ indicates the calendar hid the select element
					element.parentNode.removeChild(tmpElement);
					element.style.display = '';
				}
			}
		},


		// Determine the page dimensions
		_getPageSize: function(parent)
		{
			parent = parent || document.body;
			var windowWidth, windowHeight, pageHeight, pageWidth;
			if ( parent  != document.body )
			{
				windowWidth = parent.getWidth();
				windowHeight = parent.getHeight();
				pageWidth = parent.scrollWidth;
				pageHeight = parent.scrollHeight;
			}
			else
			{
				var xScroll, yScroll;
				if (window.innerHeight && window.scrollMaxY)
				{
				xScroll = document.body.scrollWidth;
				yScroll = window.innerHeight + window.scrollMaxY;
				}
				else if (document.body.scrollHeight > document.body.offsetHeight)
				{ // all but Explorer Mac
					xScroll = document.body.scrollWidth;
					yScroll = document.body.scrollHeight;
				}
				else
				{ // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari
					xScroll = document.body.offsetWidth;
					yScroll = document.body.offsetHeight;
				}

				if (self.innerHeight)
				{  // all except Explorer
					windowWidth = self.innerWidth;
					windowHeight = self.innerHeight;
				}
				else if (document.documentElement && document.documentElement.clientHeight)
				{ // Explorer 6 Strict Mode
					windowWidth = document.documentElement.clientWidth;
					windowHeight = document.documentElement.clientHeight;
				}
				else if (document.body)
				{ // other Explorers
					windowWidth = document.body.clientWidth;
					windowHeight = document.body.clientHeight;
				}

				// for small pages with total height less then height of the viewport
				if( yScroll < windowHeight )
				{
					pageHeight = windowHeight;
				}
				else
				{
					pageHeight = yScroll;
				}

				// for small pages with total width less then width of the viewport
				if(xScroll < windowWidth)
				{
					pageWidth = windowWidth;
				}
				else
				{
					pageWidth = xScroll;
				}
			}

			var scrOfX = 0, scrOfY = 0;
			if (typeof( window.pageYOffset ) == 'number')
			{
				//Netscape compliant
				scrOfY = window.pageYOffset;
				scrOfX = window.pageXOffset;
			}
			else if (document.body && (document.body.scrollLeft || document.body.scrollTop))
			{
				//DOM compliant
				scrOfY = document.body.scrollTop;
				scrOfX = document.body.scrollLeft;
			}
			else if (document.documentElement && (document.documentElement.scrollLeft || document.documentElement.scrollTop))
			{
				//IE6 standards compliant mode
				scrOfY = document.documentElement.scrollTop;
				scrOfX = document.documentElement.scrollLeft;
			}
			return( {pageWidth: pageWidth ,pageHeight: pageHeight , windowWidth: windowWidth, windowHeight: windowHeight, scrollLeft: scrOfX, scrollTop: scrOfY} );
		},

		// Clone (deep level copy)
		_clone : function(obj)
		{
			if (typeof obj !== 'object' || obj == null) return obj;
			var c = obj instanceof Array ? [] : {};

			for (var i in obj)
			{
				var prop = obj[i];

				 if (typeof prop == 'object')
				{
					if (prop instanceof Array)
					{
						c[i] = [];

						for (var j = 0; j < prop.length; j++)
						{
							if (typeof prop[j] != 'object')
								{
									c[i].push(prop[j]);
								}
								else
								{
									c[i].push(clone(prop[j]));
								}
						}
					}
					else
					{
						c[i] = clone(prop);
					}
				}
				else
				{
					c[i] = prop;
				}
			}

			return c;
		},


		// -----	DEBUG TOOLS
		_logError : function(err)
		{
			err.browser = navigator.userAgent;
			_private._dumpObject( err );
			return err;
		},
		_encodeToHtml : function (strng)
		{
			if ( !strng || strng=='' ) return strng;
			if (!strng.toString) return '!ERROR-Unable to inspect!';
			var encodedHtml = strng.toString();
			return encodedHtml.split("\x3C").join("&lt;").split("\x26").join("&amp;").split("\x3E").join("&gt;").split("\x22").join("&quot;");
		},
		_dumpObject : function(obj)
		{
			/*  doesn't work consistantly - certain style proprties are not inspectable
			var win=window.open('about:blank','_blank','top=100,left=50,width=500,height=500,directories=no,location=no,scrollbars=yes,resizable=yes');
			win.document.write( Object.inspect(decodeURIComponent(Object.toQueryString(obj).split('&').join('<br/>'))) );
			*/
			var str = '';
			for(k in obj)
			{
				if (typeof(obj[k]) != 'function')
					str += k +' = '+ _private._encodeToHtml(obj[k]) + '<br/>';
			}
			var win=window.open('about:blank','_blank','top=100,left=50,width=500,height=500,directories=no,location=no,scrollbars=yes,resizable=yes');
			win.document.write( str );
			return str;
		}
	};


	/* -- Constructor -------------------------------------------------------- */
	return(_public);
}();


// When the DOM is constructed, make sure the formMgr initialization is executed.
Event.observe(document, "dom:loaded", Popup.initialize);

