/////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Constants
//

var ENABLE_DEBUG		= 1;		// Flag to enable debugging. Post messages to JavaScrip consoles in FireFox and Opera.

//
//
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////


/*	
 * Open the Keyword Search window.
 *
 */
 
function OpenKeywordWindow()
{
	var keywordUrl = "/fotoweb/Keywords.fwx";
	var windowFeatures = "dependent=0,width=450,height=550,menubar=0,scrollbars=0,status=0,titlebar=0,toolbar=0,resizable=1";
	
	window.open(keywordUrl, "FWKeywordWindow", windowFeatures);
}

/*
 * Open Google maps window
 *
 */
function OpenGoogleMaps(event, latitude, longitude)
{
	fwStopEventPropagation(event);

	var url = 'http://maps.google.com/?ie=UTF8&z=14&t=h&q=' + latitude + ',' + longitude;

	OpenInNewWindow(url, 'gmaps', true );
}


/*
 * Open albums in new window and set focus
 *
 */
 
 function OpenInNewWindow(url, windowName, openNew )
 {
 	var windowFeatures = "dependent=0,menubar=1,scrollbars=1,location=1,status=1,titlebar=1,toolbar=1,resizable=1";
	
	var wnd;
	
	if( openNew )
	{
		wnd = window.open(url, windowName, windowFeatures);
		wnd.focus();
	}
	else
	{
		//navigate(url)
		window.location = url;
	}
 }


/*	
 * Open the a window with a comping image
 *
 */
 
 function OpenCompingImageWindow(queryString, width, height)
 {
 	var compingImageUrl = "/fotoweb/Zoom.fwx?" + queryString;
	var windowFeatures = "dependent=0,width=" + width + ",height=" + height + ",menubar=0,scrollbars=0,status=0,titlebar=0,toolbar=0,resizable=1";
	
	
	var wnd;
	var wndName = "";
	
	// To open all comps in the same window, uncomment the line below
	//wndName = "FWCompingImage";
	
	wnd = window.open(compingImageUrl, wndName, windowFeatures);
	wnd.focus();
 }
 
 
 
 /*	
 * Open a window that plays a file using a browser plug-in (quicktime)
 *
 */
 
 function OpenPlayerWindow(queryString)
 {
 	var compingImageUrl = "/fotoweb/Player.fwx?" + queryString;
	var windowFeatures = "dependent=0,width=700,height=500,menubar=0,scrollbars=1,status=0,titlebar=0,toolbar=0,resizable=1";
	

	window.open(compingImageUrl, "FWPlayer", windowFeatures);
 }



 /*	
 * Open a window that shows image detail
 *
 */
 
 function OpenDetailWindow(queryString)
 {
 	var compingImageUrl = "/fotoweb/Detail.fwx?" + queryString;
	var windowFeatures = "dependent=yes,width=800,height=700,menubar=0,scrollbars=1,status=0,titlebar=0,toolbar=0,resizable=1";
	

	window.open(compingImageUrl, "Detail", windowFeatures);
 }



/*
 * Open the Image Note edit box 
 *
 */
 
function OpenImageNoteDialog(foxtoken)
{
	var ImageNoteURL = "/fotoweb/ImageNote.fwx";
	var varWindowFeatures = "dependent=yes,width=450,height=280,menubar=0,scrollbars=0,status=0,titlebar=0,toolbar=0";
	
	ImageNoteURL += '?f=' + foxtoken;
	
	window.open(ImageNoteURL, "ImageNote", varWindowFeatures);
}



////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Various helper methods
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


//
// Description:	Toggles detailed error description on server error page.
// Arguments:	None..
// Returns:	None.
//
function fwServerErrorPageToggler()
{
	var errDetails = document.getElementById('errorDetails');
	var iconDetails = document.getElementById('detailIcon');
	
	if(!errDetails)
	{
		return;
	}
	
	var visibility, iconSource;
	
	if ( errDetails.style.visibility == 'hidden' )
	{
		visibility = 'visible';
		iconSource = '/fotoweb/rsrc/CollapseIcon.gif';
	}
	else
	{
		visibility = 'hidden';
		iconSource = '/fotoweb/rsrc/ExpandIcon.gif';
	}
	
	errDetails.style.visibility = visibility;
			
	if(iconDetails)
	{
		iconDetails.src = iconSource;
	}
}


//
// Description:	Displays a message box.
// Arguments:	enableDebug - Flag to indicate whether debuggin is enabled.
//              title - Message box title.
//				msg - Message to be displayed.
// Returns:		Always true.
//
function fwDisplayMessage(enableDebug, title, msg)
{
	if (enableDebug)
	{
		alert(title + '\n\n' + msg);
	}

	return(true);
}


//
// Description:	Displays a confirmation box.
// Arguments:	enableDebug - Flag to indicate whether debuggin is enabled.
//              title - Message box title.
//				msg - Message to be displayed.
// Returns:		True or false, as returned by the confirm dialog box.
//
function fwGetConfirmation(enableDebug, title, msg)
{
	if (enableDebug)
	{
		return(confirm(title + '\n\n' + msg));
	}

	return(false);
}


//
// Description: Collects all browser related data into one variable and returns it.
// Arguments:   None.
// Returns:     Browser data collection.
//
function fwGetBrowserData()
{
	var strUserAgent = navigator.userAgent.toLowerCase();
	var strVersion = navigator.appVersion.toLowerCase();

	// DOM compatibility
	this.isDOM = (document.getElementById) ? 1 : 0;

	// Mozilla (Netscape)
	this.isMozilla = (strUserAgent.indexOf('mozilla') != -1 && strUserAgent.indexOf('compatible') == -1) ? 1 : 0;

	// Mainly Netscape 4
	this.isMozilla4 = (this.isMozilla && !this.isDOM && document.layers) ? 1 : 0;

	// Mainly Netscape 5
	//this.isMozilla5 = (this.isDOM && parseInt(strVersion) >= 5) ? 1 : 0;			// Double check!!!

	// Firefox
	this.isFirefox = (strUserAgent.indexOf('firefox') != -1 ) ? 1 : 0;

	// Mozilla DOM compatible (Netscape 6+, FireFox, Mozilla...)
	this.isMozillaDOM = (this.isDOM && this.isMozilla) ? 1 : 0;

	// Explorer
	this.isExplorer = (strUserAgent.indexOf('msie') != -1) ? 1 : 0;

	// Explorer 4
	this.isExplorer4 = (this.isExplorer && !this.isDOM && document.all) ? 1 : 0;

	// Explorer 5
	this.isExplorer5 = (strVersion.indexOf("msie 5") > -1 && this.isDOM) ? 1 : 0;
	
	// Explorer 7
	this.isExplorer7 = (strVersion.indexOf("msie 7" ) > -1 && this.isDOM) ? 1 : 0;

	// Explorer DOM compatible (Explorer 5+)
	this.isExplorerDOM = (this.isDOM && this.isExplorer) ? 1 : 0;

	// Opera
	this.isOpera = (strUserAgent.indexOf('opera') != -1) ? 1 : 0;

	// Opera 5 (special case)
	this.isOpera5 = (strUserAgent.indexOf('opera 5') != -1 || strUserAgent.indexOf('opera/5') != -1) ? 1 : 0;

	// Konqueror
	this.isKonqueror = (strUserAgent.indexOf('konqueror') != -1) ? 1 : 0; // OS = Linux

	// Safari
	this.isSafari = (strUserAgent.indexOf('safari') != -1) ? 1 : 0;

	// OmniWeb
	this.isOmniWeb = (strUserAgent.indexOf('omniweb') != -1) ? 1 : 0;

	// WebTV
	this.isWebTV = (strUserAgent.indexOf('webtv') != -1) ? 1 : 0;

	// ICab
	this.isICab = (strUserAgent.indexOf('icab') != -1) ? 1 : 0;

	return(this);
}


//
// Global variable containing browser information.
//
var g_browser = new fwGetBrowserData();


//
// Description: Prepare for debug prints.
//
var g_FireFoxConsoleService = null;


if (g_browser.isMozillaDOM && g_browser.isForefox)
{
	try
	{
		//throw "myError";
		g_FireFoxConsoleService = Components.classes['@mozilla.org/consoleservice;1'].getService(Components.interfaces.nsIConsoleService);
	}
	catch(e)
	{
		g_FireFoxConsoleService = null;
	}
}


//
// Description: Prints a debug string to JavaScript console of the browser.
// Arguments:   Message to print.
// Returns:     Nothing.
//
function fwDebugPrint(msg)
{
	// Do nothing if debugging is disabled.
	if (!ENABLE_DEBUG)
	{
		return;
	}
	
	// Write to FireFox JavaScript console or FireFox output console.
	if (g_browser.isMozillaDOM && g_browser.isFirefox)
	{
		if (g_FireFoxConsoleService)
		{
			g_FireFoxConsoleService.logStringMessage('FW JS Menu: ' + msg);
		}
		else
		{
			dump(msg + '\r\n');
		}

		return;
	}
	
	// Write to Opera JavaScript console.
    //if (g_browser.isMozilla && g_browser.isOpera)
	if (g_browser.isOpera)
    {
		opera.postError(msg);
    }

	//alert('not printing: ' + msg);
}



//
// Description: Adds an event by using the proper/available add method.
// Arguments:   myElement - The element event will be assigned to.
//              myEvent -  Name of the event.
//              myFunction - Name of the function.
//              useCapture - True / false value for bubble event.
// Returns:     True / false according to success / failure.
//
function fwAddEvent(myElement, myEvent, myFunction, useCapture)
{
	/*if (myElement.addEventListener)
	{
		myElement.addEventListener(myEvent, myFunction, false);
		return(true);
	}
	else if (myElement.attachEvent)
	{
		var r = myElement.attachEvent('on' + myEvent, myFunction);
		return(r);
	}
	else
	{
		return(false);
	}*/



	if ( typeof myElement.addEventListener != 'undefined' ) // W3C DOM approach (Mozilla, Netscape, Firefox)
	{
		myElement.addEventListener(myEvent, myFunction, useCapture);
	}
	else
	{
		var eventName = "on" + myEvent;

		//myElement.attachEvent(eventName, myFunction); // IE. If you are using this, then skip the rest.

		var oldFunction = myElement;

		if( (typeof myElement[eventName]) != 'function' )
		{
			myElement[eventName] = myFunction;
		}
		else
		{
			myElement[eventName] = function()
			{
				//oldFunction();
				myFunction();
			}
		}
	}

	return(true);
}


//
// Description: Retrieves id from the event object.
// Arguments:   Event.
// Returns:     Nothing.
//
function fwGetObjectIdFromEvent(evt)
{
	/*
	var objId = '';
	
	if (evt['target']) // Mozilla, Netscape, Firefox
	{
		objId = evt['target']['id'];
	}
	else if (evt['srcElement']) // IE
	{
		objId = evt['srcElement']['id'];
	}
	
	return(objId);
	*/


	evt = (evt) ? evt : ((window.event) ? window.event : '')
	if (evt)
	{
		var element;
		if (evt.target)
		{
			if (evt.currentTarget && (evt.currentTarget != evt.target))
			{
				element = evt.currentTarget
			}
			else
			{
				element = evt.target
			}
		}
		else
		{
			element = evt.srcElement
		}

		return(element.id);
	}

	return('');
}


//
// Description: Stop forward and backward propagations of an event object.
// Arguments:   evt - Event object.
// Returns:     Nothing.
//
function fwStopEventPropagation(evt)
{
	if (!evt)
	{
		evt = window.event;
	}

	if (evt)
	{
		evt.cancelBubble = true;

		if (evt.stopPropagation)
		{
			evt.stopPropagation();
		}
	}
}


//
// Description: Checks whether the object has the specified class name.
// Arguments:   obj - The element to search in (e.g. document).
//              className - The class name to match.
// Returns:     True/false.
//
function fwHasElementClassName(obj, className)
{
	if (!obj || !obj.className || !obj.className.length || !className || !className.length )
	{
		return(false);
	}
	
	var currentClassName = ' ' + obj.className + ' ';
	
	return (currentClassName.indexOf(' ' + className + ' ') != -1);
}


//
// Description: Retrieves an array of elements that match the specified class name.
// Arguments:   obj - The element to search in (e.g. document).
//              className - The class name to match.
// Returns:     Nothing.
//
function fwGetElementsByClassName(obj, className)
{
	var subElements = obj.getElementsByTagName('*');
	if (!subElements)
	{
		return(null);
	}
	
	var matchList = new Array();
	var elementIx = 0;
	var matchtIx = 0;
	
	for (elementIx = 0; elementIx < subElements.length; elementIx++)
	{
		var currentClassName = ' ' + subElements[elementIx].className + ' ';
		if (currentClassName.indexOf(' ' + className + ' ') != -1)
		{
			matchList[matchtIx++] = subElements[elementIx];
		}
	}
	
	if (matchList.length)
	{
		return(matchList);
	}

	return(null);
}


//
// Description: Retrieves the first element that matches the specified class name.
// Arguments:   obj - The element to search in (e.g. document).
//              className - The class name to match.
// Returns:     Nothing.
//
function fwGetElementByClassName(obj, className)
{
	var subElements = obj.getElementsByTagName('*');
	if (!subElements)
	{
		return(null);
	}

	var elementIx = 0;

	for (elementIx = 0; elementIx < subElements.length; elementIx++)
	{
		var currentClassName = ' ' + subElements[elementIx].className + ' ';
		if (currentClassName.indexOf(' ' + className + ' ') != -1)
		{
			return(subElements[elementIx]);
		}
	}

	return(null);
}



//
// Description: Returns the operating window's parent.
// Arguments:   None.
// Returns:     Parent object.
//
function fwGetTopParent()
{
	if (parent.frames[0])
	{
		return(parent);
	}
	
	return(window);
}

//
// Gets the window where the menu will operate
//
function fwGetOperatingWindow()
{
	var operatingWindow = null;

	if (parent.frames[0] && g_settings.menuMainFrameName)
	{
		if (g_browser.isExplorer)
		{
			operatingWindow = parent.frames[g_settings.menuMainFrameName].document.body;
		}
		else
		{
			operatingWindow = parent.frames[g_settings.menuMainFrameName];
		}
	}
	else
	{
		if (g_browser.isExplorer)
		{
			operatingWindow = fwGetTopParent().document.body;
		}
		else
		{
			operatingWindow = fwGetTopParent();
		}
	}
	
	return(operatingWindow);
}

//
// Description: Returns an object's top position from the upper left viewport corner.
// Arguments:   elementId - Id of the element to retrieve top for.
// Returns:     Top value in pixels.
//
function fwGetAbsoluteTop(elementId)
{
	var theElement = document.getElementById(elementId);

	// Get top position from the parent object
	var absoluteTop = theElement.offsetTop;
	
	while(theElement.offsetParent != null)
	{
		// Parse the parent hierarchy up to the document element
		var theParent = theElement.offsetParent;	// Get parent object reference
		absoluteTop += theParent.offsetTop;			// Add parent top position		
		theElement = theParent;
	}	
	
	// Safari does not expose it's 12 pixel document top in any way, 
	// so this needs to be hard-coded for a well-positioned menu
	if ( g_browser.isSafari )
	{
		absoluteTop = absoluteTop - 12;
	}
	return(absoluteTop);
	
}

function fwGetAbsoluteTopWithScrollOffset(elementId)
{
	if ( g_browser.isExplorer || g_browser.isFireFox )
	{
		return parseInt( document.body.scrollTop ) + parseInt( fwGetAbsoluteTop( elementId ) ) ;
	}
	else
	{
		return parseInt ( window.pageYOffset ) + parseInt( fwGetAbsoluteTop( elementId ) );
	}
}


//
// Description: Returns an object's left position from the upper left viewport corner.
// Arguments:   elementId - Id of the element to retrieve left for.
// Returns:     Left value in pixels.
//
function fwGetAbsoluteLeft(elementId)
{
	var theElement = document.getElementById(elementId);

	// Get left position from the parent object
	var absoluteLeft = theElement.offsetLeft;
	
	while(theElement.offsetParent != null)
	{
		// Parse the parent hierarchy up to the document element
		var theParent = theElement.offsetParent;	// Get parent object reference
		absoluteLeft += theParent.offsetLeft;		// Add parent left position		
		theElement = theParent;
	}
	if( g_browser.isExplorer )
	{
		return ( absoluteLeft - document.body.scrollLeft );
	}
	return( absoluteLeft );
}


function fwGetAbsoluteLeftWithScrollOffset(elementId)
{	
	if ( g_browser.isExplorer || g_browser.isFireFox )
	{
		return parseInt( document.body.scrollLeft ) + parseInt( fwGetAbsoluteLeft( elementId ) ) ;
	}
	else
	{		
		return parseInt( window.pageXOffset ) + parseInt ( fwGetAbsoluteLeft( elementId ) );
	}
}



//
// Description: Switches the pages on a tab strip control.
// Arguments:   tabCtrlId - Id of the tab strip control.
//              tabIndex - Index of the tab to make visible.
//              currTabPrmId - Id of the hidden field that stores index of active tab.
// Returns:     None.
//
function fwTabStrip(tabCtrlId, tabIndex, currTabPrmId)
{
	fwDebugPrint('fwTabStrip(' + tabCtrlId + ', ' + tabIndex + ', ' + currTabPrmId + ')');

	var index = 0;
	var tab = document.getElementById(tabCtrlId + '_tb' + index);
	
	while(tab)
	{
		var pane = document.getElementById(tabCtrlId + '_pn' + index);
		if (!pane)
		{
			return;
		}
		
		// Switch Css classes and the visibility.
		if ( index == tabIndex && pane.style.display == 'none' )
		{
			tab.className = tab.getAttribute('scss');
			pane.style.visibility = 'visible';
			pane.style.display = 'block';
			
			// Now set the hidden field to store the value of the current strip.
			var field = document.getElementById( currTabPrmId );
			if(field)
			{
				fwDebugPrint('Storing index of current strip: ' + index);
				field.value = index;
			}
			else
			{
				fwDebugPrint('Cannot store index of current strip.');
			}
		}		
		if ( index != tabIndex && pane.style.display != 'none' )
		{
			tab.className = tab.getAttribute('uscss');
			pane.style.visibility = 'hidden';
			pane.style.display = 'none';
		}
		
		index++;
		tab = document.getElementById(tabCtrlId + '_tb' + index);
	}
}


//
// Description: Performs a string replace.
// Arguments:   key - The key to replace.
//              value - The value to replace with.
//              str - The string to perform string replace on.
// Returns:     The final string.
//
function fwStringReplaceAll(key, value, str)
{
	var ix = str.indexOf(key);

	while (ix != -1)
	{
		str = str.replace(key, value);
		ix = str.indexOf(key);
	}

	return(str);
}


//
// Description: Performs a navigation.
// Arguments:   navUrl - Url to navigate to. Can be a JavaScript function.
// Returns:     None.
//
function fwNavigate(navUrl)
{
	//fwDebugPrint('fwNavigate(' + navUrl + ')');
	
	if (!navUrl || navUrl == '')
	{
		return;
	}
	
	navUrl = fwStringReplaceAll('&amp;', '&', navUrl);

	// If navigation Url is a javascript function, then execute it.
	if (navUrl.indexOf('javascript:') != -1)
	{
		eval(navUrl);
		return;
	}
	
	// Do the navigation
	window.location.href = navUrl;
}

//
// Description: Handles click event on the tool bar buttons.
// Arguments:   navUrl - Url to navigate to. Can be a JavaScript function.
//              target - Target window/frame.
// Returns:     None.
//
function fwNavigateWithTarget(navUrl, target)
{
	//fwDebugPrint('fwNavigateWithTarget(' + navUrl + ', ' + target + ')');
	
	if (!navUrl || navUrl == '')
	{
		return;
	}
	
	navUrl = fwStringReplaceAll('&amp;', '&', navUrl);

	// If navigation Url is a javascript function, then execute it.
	if (navUrl.indexOf('javascript:') != -1)
	{
		eval(navUrl);
		return;
	}

	// If there is no target specified, then perform a simple navigation.
	if (!target || target == '')
	{
		fwNavigate(navUrl);
		return;
	}
	
	// Open url in new window.
	if (target == '_blank')
	{
		var windowFeatures = "dependent = 0, menubar = 1 , scrollbars = 1, location = 1, status = 1, titlebar = 1, toolbar = 1, resizable = 1";
		wnd = window.open(navUrl, target, windowFeatures);
		wnd.focus();
		return;
	}
	
	// Navigate to url with proper target.
	var targetWindow;
	if (parent.frames[0])
	{
		if (parent.frames[target])
		{
			targetWindow = parent.frames[target];
		}
		else
		{
			targetWindow = parent.frames[0];
		}
	}
	else
	{
		targetWindow = window;
	}

	// Do the navigation
	targetWindow.location.href = navUrl;
}


//
// Description: Posts data to main form in the admin pages.
// Arguments:   postData - Array of "name" and "value" pairs to set before posting.
//              Note! One of name/value pairs should be "ViewMode" to tell WebAdminBaseHandler
//              which page to show next.
//              formId - Id of the form to post.
// Returns:     Nothing.
//
function fwPostAction(postData, formId)
{
	fwDebugPrint('fwPostAction(' + postData.toString() + ', ' + formId + ')');
	
	// Make sure we have an object.
	if (!postData || !postData.length)
	{
		fwDebugPrint('Incorrect object "postData": ' + postData);
		return;
	}
	
	// Make sure the postData array has an even size.
	if (postData.length == 0 || postData.length % 2 != 0)
	{
		fwDebugPrint('Incorrect size of name/value pairs (' + postData.length + ').');
		return;
	}
	
	// Find the form.
	var frm = document.getElementById(formId);
	if (!frm)
	{
		fwDebugPrint('Form not found: ' + formId);
		return;
	}
	
	// Set values.
	var counter = 0;
	for (counter = 0; counter < postData.length; counter += 2)
	{
		if (!fwAdminSetNameValue(postData[counter], postData[counter + 1]))
		{
			// No field with specified name found. Create new one.
			var newElement = fwCreateNewHiddenInput(postData[counter], postData[counter + 1]);
			if (!newElement)
			{
				return;
			}
			
			frm.appendChild(newElement);
		}
	}
	
	// Submit.
	frm.submit();
}



//
// Description: Simply submits the specified form.
// Arguments:   formId - Id of the form to submit.
// Returns:     Nothing.
//
function fwSubmit(formId)
{
	fwDebugPrint('fwSubmit(' + formId + ')');
	
	// Find the form.
	var frm = document.getElementById(formId);
	if (!frm)
	{
		fwDebugPrint('Form not found: ' + formId);
		return;
	}
	
	// Submit.
	frm.submit();
}


//
// Description: Sets the hidden field value. If the field is not found, it is created.
// Arguments:   name - Name/id of the element to set value of.
//              value - Value to be set.
// Returns:     True upon success, false otherwise.
//
function fwAdminSetNameValue(name, value)
{
	fwDebugPrint('fwAdminSetNameValue(name: ' + name + ', value: ' + value + ')');
	
	var element = document.getElementById(name);
	if (!element)
	{
		fwDebugPrint('Element not found: ' + name + '.');
		return(false);
	}
	
	element.value = value;
	
	return(true);
}


//
// Description: Creates new hidden element.
// Arguments:   name - Name/id of the element to set value of.
//              value - Value to be set.
// Returns:     The created object.
//
function fwCreateNewHiddenInput(name, value)
{
	fwDebugPrint('fwCreateHiddenInput(name: ' + name + ', value: ' + value + ')');

	var element = document.createElement('input');
	if (!element)
	{
		fwDebugPrint('Cannot create element: ' + name);
		return(null);
	}

	element.type = 'hidden';
	element.id = name;
	element.name = name;
	element.value = value;
	
	return(element);
}


//
// Description: Returns an array of query string parameters.
// Arguments:   None.
// Returns:     Array or query string parameters.
//
function fwGetQueryStringParameters()
{
	var qsParams = new Array();
	var query = window.location.search.substring(1); // We do substring(1) to exclude the "?".
	var parms = query.split('&');
	
	var ix = 0;
	for (ix = 0; ix < parms.length; ix++)
	{
		var pos = parms[ix].indexOf('=');
		if (pos > 0)
		{
			var key = parms[ix].substring(0, pos);
			var val = parms[ix].substring(pos + 1);
			qsParams[key] = val;
		}
	}
	
	return(qsParams);
}


//
// Description: This function enables/disables controls according to checkbox state.
// Arguments:   chkId - Id of the checkbox.
//              enableList - Array of control ids that are to be enabled.
//              disableList - Array of the control ids that are to be disabled.
// Returns:     None.
//
function fwEnableDisableByCheckbox(chkId, enableList, disableList)
{
	fwDebugPrint('fwEnableDisableByCheckbox: ' + chkId + ', ' + enableList + ', ' + disableList);
	
	// Find the check box.
	var chkBox = document.getElementById(chkId);
	if (!chkBox)
	{
		fwDebugPrint('Checkbox not found: ' + chkId);
		return;
	}
	
	// Make sure we have some controls to enable / disable.
	if (enableList.length == 0 && disableList.length == 0)
	{
		fwDebugPrint('No controls to enable/disable.');
		return;
	}
	
	// Enable.
	var counter = 0;
	for (counter = 0; counter < enableList.length; counter++)
	{
		var element = document.getElementById(enableList[counter]);
		if (!element)
		{
			fwDebugPrint('Control not found to enable: ' + enableList[counter]);
		}
		else
		{
			element.disabled = !chkBox.checked;
		}
	}
	
	// Disable.
	counter = 0;
	for (counter = 0; counter < disableList.length; counter++)
	{
		var element = document.getElementById(disableList[counter]);
		if (!element)
		{
			fwDebugPrint('Control not found to disable: ' + disableList[counter]);
		}
		else
		{
			element.disabled = chkBox.checked;
		}
	}
}




//
// Description: This function shows/hides controls according to checkbox state.
// Arguments:   chkId - Id of the checkbox.
//              showList - Array of control ids that are to be shown.
//              hideList - Array of the control ids that are to be hidden.
// Returns:     None.
//
function fwShowHideByCheckbox(chkId, showList, hideList)
{
	fwDebugPrint('fwShowHideByCheckbox: ' + chkId + ', ' + showList + ', ' + hideList);
	
	// Find the check box.
	var chkBox = document.getElementById(chkId);
	if (!chkBox)
	{
		fwDebugPrint('Checkbox not found: ' + chkId);
		return;
	}
	
	if(!showList)	showList = new Array();
	if(!hideList)	hideList = new Array();
	
	// Make sure we have some controls to show/hide.
	if (showList.length == 0 && hideList.length == 0)
	{
		fwDebugPrint('No controls to show/hide.');
		return;
	}
	
	// Show.
	var counter = 0;
	for (counter = 0; counter < showList.length; counter++)
	{
		var element = document.getElementById(showList[counter]);
		if (!element)
		{
			fwDebugPrint('Control not found to show: ' + showList[counter]);
		}
		else
		{
			element.style.visibility = 'visible';
			element.style.display = 'block';
		}
	}
	
	// hide.
	counter = 0;
	for (counter = 0; counter < hideList.length; counter++)
	{
		var element = document.getElementById(hideList[counter]);
		if (!element)
		{
			fwDebugPrint('Control not found to hide: ' + hideList[counter]);
		}
		else
		{
			element.style.visibility = 'hidden';
			element.style.display = 'none';
		}
	}
}


//
// Description: Selects/Unselects all check boxes that match the base id.
// Arguments:   baseId - the base id to match remaining check boxes with.
// Returns:     None.
//
function fwSelectAllCheckboxes(baseId)
{
	fwDebugPrint('fwSelectAllCheckboxes(' + baseId + ')');
	
	var mainCB = document.getElementById(baseId);
	if(!mainCB)
	{
		fwDebugPrint('fwSelectAllCheckboxes: Main checkbox not found.');
		return;
	}

	var ix = 1;
	var subCB = document.getElementById(baseId + '_' + ix++);
	
	while(subCB)
	{
		subCB.checked = mainCB.checked;
		
		subCB = document.getElementById(baseId + '_' + ix++);
	}
}


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// The following set of methods are to work with list controls (SELECT).
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//
// Description: Locates a list item. Pass in either text or value to identify the item.
// Arguments:   listCtrl - Reference to the list control.
//              text - The text identify the item.
//              value - The value to identify the item.
// Returns:     The located option object, or null.
//
function fwSelect_GetItem(listCtrl, text, value)
{
	fwDebugPrint('fwSelect_GetItem(' + listCtrl.id + ', ' + text + ', ' + value + ')');
	
	if (!listCtrl)
	{
		fwDebugPrint('fwSelect_GetItem: Invalid list control.');
		return(null);
	}
	
	var _text = null;
	if (text)
	{
		_text = text.toLowerCase();
	}
	
	var _value = null;
	if (value)
	{
		_value = value.toLowerCase();
	}

	var counter = 0;
	for (counter = 0; counter < listCtrl.length && listCtrl.options[counter]; counter++)
	{
		if (_text)
		{
			var rhsStr = listCtrl.options[counter].text.toLowerCase();
			if (_text == rhsStr)
			{
				fwDebugPrint('fwSelect_GetItem: Item found by text.');
				return(listCtrl.options[counter]);
			}
		}
		
		if (_value)
		{
			var rhsStr = listCtrl.options[counter].value.toLowerCase();
			if (_value == rhsStr)
			{
				fwDebugPrint('fwSelect_GetItem: Item found by value.');
				return(listCtrl.options[counter]);
			}
		}
	}
	
	fwDebugPrint('fwSelect_GetItem: Item not found.');
	
	return(null);
}


//
// Description: Locates a list item. Pass in either text or value to identify the item.
// Arguments:   listCtrl - Reference to the list control.
//              text - The text identify the item.
//              value - The value to identify the item.
// Returns:     The index of the located option object, or -1.
//
function fwSelect_GetItemIx(listCtrl, text, value)
{
	fwDebugPrint('fwSelect_GetItemIx(' + listCtrl.id + ', ' + text + ', ' + value + ')');
	
	if (!listCtrl)
	{
		fwDebugPrint('fwSelect_GetItemIx: Invalid list control.');
		return(-1);
	}
	
	var _text = null;
	if (text)
	{
		_text = text.toLowerCase();
	}
	
	var _value = null;
	if (value)
	{
		_value = value.toLowerCase();
	}

	var counter = 0;
	for (counter = 0; counter < listCtrl.length && listCtrl.options[counter]; counter++)
	{
		if (_text)
		{
			var rhsStr = listCtrl.options[counter].text.toLowerCase();
			if (_text == rhsStr)
			{
				fwDebugPrint('fwSelect_GetItemIx: Item found by text.');
				return(counter);
			}
		}
		
		if (_value)
		{
			var rhsStr = listCtrl.options[counter].value.toLowerCase();
			if (_value == rhsStr)
			{
				fwDebugPrint('fwSelect_GetItemIx: Item found by value.');
				return(counter);
			}
		}
	}
	
	fwDebugPrint('fwSelect_GetItemIx: Item not found.');
	
	return(-1);
}


//
// Description: Checks whether an item exists. Pass in either text or value to identify the item.
// Arguments:   listControlId - Id of the list  control
//              text - The text identify the item.
//              value - The value to identify the item.
// Returns:     True/false.
//
function fwSelect_ItemExists(listControlId, text, value)
{
	fwDebugPrint('fwSelect_ItemExists(' + listControlId + ', ' + text + ', ' + value + ')');
	
	var listCtrl = document.getElementById(listControlId);
	if (!listCtrl)
	{
		fwDebugPrint('fwSelect_ItemExists: List control not found.');
		return(false);
	}

	if (fwSelect_GetItem(listCtrl, text, value))
	{
		fwDebugPrint('fwSelect_ItemExists: Item exists.');
		return(true);
	}

	fwDebugPrint('fwSelect_ItemExists: Item does not exist.');
	
	return(false);
}


//
// Description: Deletes the selected item from the list control. If deleteAll falg is false, the the last selected item is deleted.
// Arguments:   listControlId - Id of the list  control
//              deleteAll - Flag to delete all selected items.
// Returns:     True if any item is deleted.
//
function fwSelect_DeleteSelected(listControlId, deleteAll)
{
	fwDebugPrint('fwSelect_DeleteSelected(' + listControlId + ', ' + deleteAll + ')');
	
	var listCtrl = document.getElementById(listControlId);
	if (!listCtrl)
	{
		fwDebugPrint('fwSelect_DeleteSelected: List control not found.');
		return(false);
	}
	
	var anyDeleted = false;
	var counter = 0;
	for(counter = listCtrl.length - 1; counter >= 0; counter--)
	{
		if(listCtrl.options[counter].selected)
		{
			listCtrl.remove(counter);
			anyDeleted = true;
			
			if(!deleteAll)
			{
				break;
			}
		}
	}
	
	if (anyDeleted)
	{
		fwDebugPrint('fwSelect_DeleteSelected: One ore more item(s) deleted.');
	}
	else
	{
		fwDebugPrint('fwSelect_DeleteSelected: No Item(s) deleted.');
	}
	
	return(anyDeleted);
}


//
// Description: Retrieves t he last selected item.
// Arguments:   listControlId - Id of the list  control
// Returns:     The selected item.
//
function fwSelect_GetSelectedItem(listControlId)
{
	fwDebugPrint('fwSelect_GetSelectedItem(' + listControlId + ')');
	
	var listCtrl = document.getElementById(listControlId);
	if (!listCtrl)
	{
		fwDebugPrint('fwSelect_GetSelectedItem: List control not found.');
		return(null);
	}
	
	var counter = 0;
	for(counter = listCtrl.length - 1; counter >= 0; counter--)
	{
		if(listCtrl.options[counter].selected)
		{
			fwDebugPrint('fwSelect_GetSelectedItem: Returning selected item.');
			return(listCtrl.options[counter]);
		}
	}

	fwDebugPrint('fwSelect_GetSelectedItem: No Item selected.');
	
	return(null);
}


//
// Description: Deletes an item from the list control. Pass in either text or value to identify the item.
// Arguments:   listControlId - Id of the list  control
//              text - The text identify the item.
//              value - The value to identify the item.
// Returns:     True/false.
//
function fwSelect_DeleteItem(listControlId, text, value)
{
	fwDebugPrint('fwSelect_DeleteItem(' + listControlId + ', ' + text + ', ' + value + ')');
	
	var listCtrl = document.getElementById(listControlId);
	if (!listCtrl)
	{
		fwDebugPrint('fwSelect_DeleteItem: List control not found.');
		return(false);
	}
	
	var itemIx = fwSelect_GetItemIx(listCtrl, text, value);
	if(itemIx != -1)
	{
		listCtrl.remove(itemIx);
		fwDebugPrint('fwSelect_DeleteItem: Item deleted.');
		return(true);
	}

	fwDebugPrint('fwSelect_DeleteItem: Item not deleted.');
	
	return(false);
}


//
// Description: Adds an item to the list control. The caller should take care of duplicates.
// Arguments:   listControlId - Id of the list  control
//              text - The text of the new item.
//              value - The value of the new item.
// Returns:     True/false.
//
function fwSelect_AddItem(listControlId, text, value)
{
	fwDebugPrint('fwSelect_AddItem(' + listControlId + ', ' + text + ', ' + value + ')');
	
	if (text == '' || value == '')
	{
		fwDebugPrint('fwSelect_AddItem: Cannot add empty items.');
		return(false);
	}
	
	var listCtrl = document.getElementById(listControlId);
	if (!listCtrl)
	{
		fwDebugPrint('fwSelect_AddItem: List control not found.');
		return(false);
	}
	
	// Create and add new item
	var newOption = document.createElement('option');
	if (!newOption)
	{
		fwDebugPrint('fwSelect_AddItem: Cannot create new item.');
		return(false);
	}
	
	newOption.text = text;
	newOption.value = value;

	try
	{
		listCtrl.add(newOption, null); // May not work in some versions of IE.
	}
	catch(ex)
	{
		listCtrl.add(newOption); // Alternative upon failure.
	}
	
	fwDebugPrint('fwSelect_AddItem: New item added.');
	
	return(true);
}


//
// Description: Replaces an existing item in the list control. Pass in either text or value to identify the item.
// Arguments:   listControlId - Id of the list  control
//              oldText - The text identify the item.
//              oldValue - The value to identify the item.
//              newText - The new text of the item.
//              newValue - The new value of the item.
// Returns:     True/false.
//
function fwSelect_ReplaceItem(listControlId, oldText, oldValue, newText, newValue)
{
	fwDebugPrint('fwSelect_ReplaceItem(' + listControlId + ', ' + oldText + ', ' + oldValue + ', ' + newText + ', ' + newValue + ')');
	
	if (newText == '' && newValue == '')
	{
		fwDebugPrint('fwSelect_ReplaceItem: Cannot replace with empty parameters.');
		return(false);
	}
	
	var listCtrl = document.getElementById(listControlId);
	if (!listCtrl)
	{
		fwDebugPrint('fwSelect_ReplaceItem: List control not found.');
		return(false);
	}
	
	var item = fwSelect_GetItem(listCtrl, oldText, oldValue);
	if(!item)
	{
		fwDebugPrint('fwSelect_ReplaceItem: Item not replaced.');
	
		return(false);
	}
	
	if (newText)
	{
		item.text = newText;
	}
	
	if (newValue)
	{
		item.value = newValue;
	}
	
	fwDebugPrint('fwSelect_ReplaceItem: Item replaced.');
	
	return(true);
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// END SELECT METHODS
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////




////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// The following set of methods are to work with FotoWeb Preview Size List drop down control.
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////



//
// Description: Copies the selected value of  the quick list drop down control to the master control and hides all quick list drop downs.
// Arguments:   dropDownId - Id of the drop down control to get value of.
//              pslParamName - Name of the parameter to add to postback URL.
//              postbackURL - The postback URL to expand and navigat to.
// Returns:     Nothing.
//
function fwPSL_UpdatePreviewSize(dropDownId, pslParamName, postbackURL)
{
	// Get selected value.
	var selectedItem = fwSelect_GetSelectedItem(dropDownId);

	if (!selectedItem)
	{
		fwDebugPrint('fwPSL_UpdatePreviewSize: No selected item retrieved.');
		return;
	}
	
	fwDebugPrint('fwPSL_UpdatePreviewSize: New selected item is: ' + selectedItem.value);
	
	// Expand postback URL.
	postbackURL += '&amp;' + pslParamName + '=' + selectedItem.value;
	
	// Navigate.
	fwNavigate(postbackURL);
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// END PREVIEW SIZE LIST METHODS
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////




////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// The following set of methods are to work with FotoWeb Album Server Controls.
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//
// Description: Retrieves the current value of the specified drop and down
//              and add to the parameter array. Then the parameter array is
//              passed to the method that posts these parameters to the specified form.
// Arguments:   dropDownId - Id of the drop down control to get value of.
//              formId - Id of the form to post data to.
//              params - The parameter array. The value of the drop down is added to the
//                       first parameter pair in the array.
// Returns:     Nothing.
//
function fwSharedAlbumRoleChanger(dropDownId, formId, params )
{
	// Get selected value.
	var selectedItem = fwSelect_GetSelectedItem(dropDownId);
	
	if (!selectedItem)
	{
		fwDebugPrint('fwSharedAlbumRoleChanger: No selected item retrieved.');
		return;
	}
	
	fwDebugPrint('fwSharedAlbumRoleChanger: New selected item is: ' + selectedItem.value);

	// Post data to the form.
	
	if(!params)
	{
		fwDebugPrint('fwSharedAlbumRoleChanger: No parameter array passed in.');
		return;
	}
	
	params[1] = selectedItem.value;
	
	fwPostAction(params, formId)
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// END FOTOWEB ALBUM SERVER CONTROL METHODS
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////




////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// The following set of methods are to work with FotoWeb drop down control.
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////



//
// Description: Expands/collapses the FotoWeb drop down control.
// Arguments:   id - Id of the drop down control.
// Returns:     None.
//
function fwDropDown_Expand(id)
{
	fwDebugPrint('fwDropDown_Expand(' + id + ')');

	var ddCtrl = document.getElementById(id);
	if(!ddCtrl)
	{
		fwDebugPrint('fwDropDown_Expand: Drop down not found.');
		return;
	}

	var itemsBlock = fwGetElementByClassName(ddCtrl, 'fwDropDown_Items');
	if(!itemsBlock)
	{
		fwDebugPrint('fwDropDown_Expand: Items block not found.');
		return;
	}

	itemsBlock.style.position  = 'absolute';
	itemsBlock.style.left = parseInt(ddCtrl.offsetLeft) + 'px';
	itemsBlock.style.width = parseInt(ddCtrl.offsetWidth) + 'px';


	if (itemsBlock.style.visibility == 'visible')
	{
		fwDebugPrint('fwDropDown_Expand: Hiding items.');
		itemsBlock.style.visibility = 'hidden';
		itemsBlock.style.display = 'none';
	}
	else
	{
		fwDebugPrint('fwDropDown_Expand: Showing items.');
		itemsBlock.style.visibility = 'visible';
		itemsBlock.style.display = 'block';
	}
}

//
// Description: Expands/collapses the FotoWeb drop down control.
// Arguments:   item - Item calling the method.
//              id - Id of the drop down control.
//              itemValId - Id of the item value div.
// Returns:     None.
//
function fwDropDown_Select(item, id, itemValId)
{
	fwDebugPrint('fwDropDown_Select(' + item + ', ' + id + ')');

	var selection = document.getElementById(id + '_sel');
	if(!selection)
	{
		fwDebugPrint('fwDropDown_Select: Selection not found.');
		return;
	}


	// Set visible data
	selection.innerHTML = item.innerHTML;

	// Set hidden data
	var itemData = document.getElementById(itemValId);
	if(!itemData)
	{
		fwDebugPrint('fwDropDown_Select: Item data not found.');
		return;
	}


	var inputCtrl = document.getElementById(id + '_inp');
	if(!inputCtrl)
	{
		fwDebugPrint('fwDropDown_Select: Input control not found.');
		return;
	}

	inputCtrl.value = itemData.innerHTML;


	fwDropDown_Expand(id);

}


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// END DROP DOWN METHODS
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////





////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// The following set of methods are to work with FotoWeb message boxes.
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

function fwShowMessageBox()
{
	fwDebugPrint('fwShowMessageBox()');
	
	// Check if FotoWeb message box div is present.
	var fwMsgBox = document.getElementById('fwMessageBox');
	if(!fwMsgBox)
	{
		fwDebugPrint('fwShowMessageBox: No message box on this page.');
		return;
	}
	
	fwDebugPrint('fwShowMessageBox: Displaying message box.');


	// We display the box before positiong to allow positioning function to get proper offset values.
	fwMsgBox.style.display = 'block'; 
	fwMsgBox.style.visibility = 'visible';

	fwPositionMessageBox();


	// Add 'onScroll' and 'onresize' events, just in case.
	fwAddEvent(window, 'scroll', fwPositionMessageBox, false);
	fwAddEvent(window, 'resize', fwPositionMessageBox, false);
}

function fwHideMessageBox()
{
	fwDebugPrint('fwHideMessageBox()');
	
	// Check if FotoWeb message box div is present.
	var fwMsgBox = document.getElementById('fwMessageBox');
	if(!fwMsgBox)
	{
		fwDebugPrint('fwHideMessageBox: No message box on this page.');
		return;
	}
	
	fwDebugPrint('fwHideMessageBox: Hiding message box.');
	
	fwMsgBox.style.visibility = 'hidden';
	fwMsgBox.style.display = 'none';
}

function fwPositionMessageBox()
{
	fwDebugPrint('fwPositionMessageBox()');
	
	// Check if FotoWeb message box div is present.
	var fwMsgBox = document.getElementById('fwMessageBox');
	if(!fwMsgBox)
	{
		fwDebugPrint('fwPositionMessageBox: No message box on this page.');
		return;
	}
	
	fwDebugPrint('fwPositionMessageBox: Positioning message box.');
	
	if(fwMsgBox.style.visibility == 'hidden')
	{
		return;
	}

	var posX = 0;
	var posY = 0;
	
	if (g_browser.isFirefox || g_browser.isSafari)
	{
		posX = parseInt(window.innerWidth) / 2 - parseInt(fwMsgBox.offsetWidth) / 2 + parseInt(window.pageXOffset);
		posY = parseInt(window.innerHeight) / 2 - parseInt(fwMsgBox.offsetHeight) / 2 +  parseInt(window.pageYOffset);
	}
	else
	{
		posX = parseInt(document.body.clientWidth) / 2 - parseInt(fwMsgBox.offsetWidth) / 2  + parseInt(document.body.scrollLeft);
		posY = parseInt(document.body.clientHeight) / 2 - parseInt(fwMsgBox.offsetHeight) / 2 + parseInt(document.body.scrollTop);
	}
	
	fwMsgBox.style.left = posX + 'px';
	fwMsgBox.style.top = posY + 'px';

	fwDebugPrint('fwPositionMessageBox: Left = ' + posX + ', Top = ' + posY);
}




//
// Description: Displays a confirmation box before continuing with posting data.
// Arguments:   msg - Message to display.
//              postData - Array of "name" and "value" pairs to set before posting.
//              Note! One of name/value pairs should be "ViewMode" to tell WebAdminBaseHandler
//              which page to show next.
//              formId - Id of the form to post.
// Returns:     Nothing.
//
function fwConfirmBeforePost(msg, postData, formId)
{
	fwDebugPrint('fwAdminDeleteObject');
	
	if(!msg || msg == '')
	{
		fwPostAction(postData, formId);
		return;
	}
	
	if (confirm(msg))
	{ 
		fwPostAction(postData, formId);
	}
	else
	{
		fwDebugPrint('Delete canceled.');
	}
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// END FOTOWEB MESSAGEBOX METHODS.
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////






////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// FOTOWEB FORM VALIDATION METHODS.
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// Global variable for administering validation of form elements
var globalTests = new Array( );	

// Error marking colors:
var markingForeColor =   'white';
var markingBackColor = '#FD7303';

		
		
/**
 * Constant definition of the various test types that exist
 */
var testTypes  =
{
	FW_EMAIL			: 1,
	FW_POSITIVE_INTEGER : 2,
	FW_POSITIVE_DOUBLE	: 3,			
	FW_TEXT_ALL			: 4,
	FW_TEXT_NO_NUMBERS	: 5, 
	FW_REGULAREXPRESSION: 6, 
	FW_CHECK			: 7, 
	FW_FILENAME			: 8
}



/**
 * Object template for validation (this is NOT a function)
 */
function fwTestEntry( formId, element, testType, regExp, required, minChars, maxChars, minRange, maxRange, errorMessage )
{
	this.formId			= formId;			
	this.element		= element;
	this.testType		= testType;			
	this.regExp			= regExp;
	this.required		= required;
	this.minChars		= minChars;
	this.maxChars		= maxChars;
	this.minRange		= minRange;
	this.maxRange		= maxRange;
	this.errorMessage	= errorMessage;
	this.markingElement = null;
	this.errorCondition	= '';
}






/** 
 * Create a testEntry and add it to the global array of entries to test
 */
function fwSetValidator( formId, element, testType, regExp, required, minChars, maxChars, minRange, maxRange, errorMessage )
{
	var testObject = new fwTestEntry( formId, element, testType, regExp, required, minChars, maxChars, minRange, maxRange, errorMessage );
	globalTests[ globalTests.length ] = testObject;
}


/**
 * Trim both edges of a string
 */
function fwTrimEdges( element )
{
	return fwLTrim( fwRTrim( element  ) );	
}
		
		
/**
 *Trim left edge of a string
 */
function fwLTrim( element )
{
	if ( element )
	{
		element.value  = element.value.replace( /^\s+/g, "" );// strip leading
		return element;
	}
}

		
/**
 * Trim right edge of a string
 */
function fwRTrim( element )
{
	if ( element )
	{
		element.value = element.value.replace( /\s+$/g, "" );// strip trailing
		return element;				
	}
}
		

/**
 * Highlights the element in a red bagkground to emphasize error
 */
function fwMarkError( element )
{
	if ( element )
	{				
		element.style.color		 = markingForeColor;
		element.style.background = markingBackColor;
	}	
}
		
		
/**
 * Sets the default error text, and assigns it to the "public" errorMessage if this is not
 * set. If the currentTestObject was created with an error message, this will override the 
 * internal messages
 */
function fwSetErrorMessage( currentTestObject, text )
{
	// Internal message
	currentTestObject.errorCondition = text;

	// No override message = use internal message
	if (currentTestObject.errorMessage.length == 0 )
	{
		currentTestObject.errorMessage = currentTestObject.element.id + ': ' + currentTestObject.errorCondition;
	}
	fwMarkError( currentTestObject.element );				
}
		
		
/**
 * Simple empty/nothingness test
 */	
function fwIsEmpty ( currentTestObject )
{
	if ( currentTestObject.element  )
	{
		return currentTestObject.element.value.length == 0;		
	}
	return true;
}
		
		
/**
 * Checks that an element whose value is required, actually contains a value
 */		
function fwIsRequiredOk( currentTestObject )
{
	if ( currentTestObject.required == false && currentTestObject.element.value.length == 0 )
		return true;

	// Ensure value is trimmed on both sides
	fwTrimEdges( currentTestObject.element ); 

	if ( fwIsEmpty( currentTestObject ) )
	{
		if ( currentTestObject.required == true )
			fwSetErrorMessage( currentTestObject, "Required field is empty" );
		else
			fwSetErrorMessage( currentTestObject, "Optional field cannot consist of spaces only" )
			
		return false;				
	}
	return true;
}
		
		
/**
 * Test min/max length of field, as long as there's data here.
 */
function fwIsLengthCheckOk( currentTestObject )
{
	// if both min and max are set to zero, we're effectively turning off the entire feature of this function
	if ( currentTestObject.minChars == 0 && currentTestObject.maxChars == 0 )
		return true;

	// if the element to test is null, we're probably dealing with a checkbox, radio, or some other type of control that will not
	// subject itself easilly to value tests, hence, we test for nothingness on this, and return true if the element is invalid
	if ( ! currentTestObject.element )
	{
		return true;
	}

	// consistency test. Min. Characters should not be allowed to be greater than max characters:
	if ( currentTestObject.minChars > currentTestObject.maxChars )
	{
		fwSetErrorMessage( currentTestObject, "Consistency error: Minimum number of characters cannot be greater than maximum number of characters" );
	}

	// if the field is not required, and we have no data, that is OK
	if ( currentTestObject.required == false && fwIsEmpty( currentTestObject  ) )
		return true;

	// Check minimums
	if ( currentTestObject.element.value.lenght < currentTestObject.minChars )
	{
		fwSetErrorMessage( currentTestObject, "The minimum number of characters for this field is " + currentTestObject.minChars );
		return false;
	}

	// Same for max values
	if ( currentTestObject.element.value.length > currentTestObject.maxChars )
	{
		fwSetErrorMessage( currentTestObject, "The maximum number of characters for this field was exceeded" );
		return false;
	}

	return true;		
}
		
		
/**
 * Checks that an email address is valid. The regular expression used does not catch
 * an email starting with a dot, hence the extra test.
 */
function fwValidateEmail( currentTestObject )
{
	// Email field validates if it is empty, and required is set to false	
	if ( fwIsEmpty( currentTestObject ) && currentTestObject.required == false )
		return true;

	var filter  		= /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
	var address_array 	= currentTestObject.element.value.split( ";" );
	
	for( var i = 0; i < address_array.length; i++ )
	{

		if ( address_array[ i ].charAt( 0 ) == '.' )
		{
			fwSetErrorMessage( currentTestObject, "One or more illegal email addresses found" );
			return false;
		}

		if ( ! filter.test ( address_array[ i ] ) ) 
		{
			fwSetErrorMessage( currentTestObject, "One or more illegal email addresses found" );
			return false;
		}
	}
	return true;
}
		
		
/**
 * "Validation" of a checkbox can only be done in the instance of a required checkmark,
 * i.e. for the user to accept the terms and conditions of something, which is quite
 * common.
 */
 function fwValidateCheckBox( currentTestObject )
 {

	if ( ! currentTestObject.element.checked && currentTestObject.required == false )
		return true;

	if ( ! currentTestObject.element.checked && currentTestObject.required == true )
	{
		fwSetErrorMessage( currentTestObject, "Please click the checkbox" );
		return false;				
	}
	return true;
 }
		 
		 
 /**
  * TODO: define what to test here
  */
  function fwValidateRadioBox ( currentTestObject )
  {
		return true;	
  }
		  
		  
		  
  /**
   * Validate the currentTestObject with a supplied regular expression
   */
  function fwValidateRegularExpression( currentTestObject )
  {
	// Allow empty values on non-required fields
	if ( ! currentTestObject.required && currentTestObject.element.value.length == 0 )
		return true;

	// Bad design error - no regular expression given to test with
	if ( currentTestObject.regExp.value.length == 0 )
	{
		fwSetErrorMessage( currentTestObject, "Regular expression chosen, but not given" );
		return false;
	}

	// Try the regexp on our value, and return false if it fails
	if ( ! currentTestObject.regExp.test( currentTestObject.element.value ) )
	{
		fwSetErrorMessage( currentTestObject, "The data contained in the field are invalid" );
		return false;
	}
	return true;		  
  }
		  
		  
/**
 * We like to spell it out :)
 */
function fwIsNumeric( currentTestObject )
{
	// Allow empty values on non-required fields
	if ( ! currentTestObject.required && currentTestObject.element.value.length	 == 0 )
		return true;

	if ( isNaN( currentTestObject.element.value ) )
	{
		return false;
	}
	return true;
}
		   
		   
/**
 * returns true if the value in the current test object is numeric, and, if ranges are defined, 
 * that the value falls within the given range.
 */
function fwValidateAsAnyNumber( currentTestObject )
{
	// Allow empty values on non-required fields
	if ( ! currentTestObject.required && currentTestObject.element.value.length == 0 )
		return true;

	if ( ! fwIsNumeric( currentTestObject ) )	
	{
		fwSetErrorMessage( currentTestObject, "This field requires a number" );
		return false;
	}

	// if both min and max ranges are set to -1 then its turned off
	if ( currentTestObject.minRange == -1 && currentTestObject.maxRange == -1 )				
		return true;

	if ( eval ( currentTestObject.minRange > currentTestObject.maxRange ) ) 
	{
		fwSetErrorMessage( currentTestObject, "Code error: Maximum value is set to be lower than minimum value in range" );
		return false;
	}

	if ( eval ( currentTestObject.element.value < currentTestObject.minRange ) )
	{
		fwSetErrorMessage( currentTestObject, "Value given is lower than minium allowed" );
		return false;
	}

	if ( eval ( currentTestObject.element.value > currentTestObject.maxRange ) )
	{
		fwSetErrorMessage( currentTestObject, "Value given is higher than the maximum allowed" );
		return false;
	}

	return true;
}
		   
		   
/** 
 * Returns true if the current test object contains a positive number
 */
function fwValidateAsAnyPositiveNumber( currentTestObject )
{
	if( ! fwValidateAsAnyNumber( currentTestObject ) )
		return false;

	if ( eval ( currentTestObject.element.value < 0 ) )
	{
		fwSetErrorMessage( currentTestObject, "Only positive numbers allowed" );
		return false;				
	}
	return true;
}
		   
		   
/**
 * Returns true if the current test object contains an integral value
 */
function fwValidateAnyInteger( currentTestObject )
{
	if ( ! fwValidateAsAnyNumber( currentTestObject ) )
		return false;

	var floater  = parseFloat( currentTestObject.element.value );
	var integer  = parseInt  ( currentTestObject.element.value );

	if ( eval( Math.abs( floater ) - Math.abs(integer) ) != 0 || currentTestObject.element.value.indexOf('.') >= 0 )
	{
		fwSetErrorMessage( currentTestObject, "Only whole numbers are allowed here" );
		return false;
	}
	return true;
}
		   
		   
/**
 * If a number can be interpreted as a floating value, it passes this test
 */
function fwValidateAnyDouble ( currentTestObject )
{
	if ( ! fwValidateAsAnyNumber( currentTestObject ) )
		return false;

	// Missing a dot-value, add it
	if ( currentTestObject.element.value.indexOf('.') == -1  )
	{	
		currentTestObject.element.value += '.0';
	}
	return true;
}
		   
		   
/**
 * Validates to true only if the element.value contains a positive integer. Ranges are checked, if enabled 
 */
function fwValidatePositiveInt( currentTestObject )
{				
	if ( ! fwValidateAnyInteger( currentTestObject ) )
		return false;

	if( ! fwValidateAsAnyPositiveNumber( currentTestObject  ) )
		return false;

	return true;				
}
		   
		   
/**
 * if a numeric value can pass as a floating, positive value, it passes this test
 */
function fwValidatePositiveDbl( currentTestObject )
{
	if ( ! fwValidateAsAnyPositiveNumber( currentTestObject ) )
		return false;

	// Missing a dot-value, add it
	if ( currentTestObject.element.value.indexOf('.') == -1  )
	{	
		currentTestObject.element.value += '.0';
	}
	return true;
}


/**
 *
 */
function fwValidateAllText ( currentTestObject )
{
	return true;
}


/**
 *
 */
function fwValidateFileName( currentTestObject )
{
	// Allow empty values on non-required fields
	if ( ! currentTestObject.required && currentTestObject.element.value.length == 0 )
		return true;

	// Regexp to validate a filename
	//var regExpr = /^[A-Za-z0-9\-_]{1,255}\.[A-Za-z]{1,4}$/g;
        

    /*/ Test the regular expression with the filename
    if ( ! regExpr.test( currentTestObject.element.value ) )
    {
    	fwSetErrorMessage( currentTestObject, "This does not appear to be a valid file name" );
    	
    	return false;
    }*/
    return true;
}

		
		
/**
 * The mother validation function, from here, all other validations are performed.
 */
function fwValidateAll( theForm )
{
	var errorMessages = new Array(); // builds up a list of messages for the final alert
	var noError		  = true;		 // no errors found
	var firstFocus	  = false;		 // We have an item to set focus on
	var focusElement  = -1;			 // id of the focus item

	
	// Traverse all pre-defined tests:	
	for (var i = 0; i < globalTests.length; i++ )
	{		
		// Inspect current form submitted only (in case of multiple forms)		
		if ( globalTests[ i ].formId.id == theForm.id )
		{
			
			// Check if the element is required
			if ( fwIsRequiredOk( globalTests[ i ] ) )
			{					
				// Do check of minimum/maximum length of value (does not include numeric range)
				if ( fwIsLengthCheckOk( globalTests[i ] )  )
				{
					switch ( globalTests[ i ].testType )
					{
						case testTypes.FW_TEXT_ALL			: noError = fwValidateAllText		( globalTests[ i ] ) ; break;
						case testTypes.FW_EMAIL				: noError = fwValidateEmail			( globalTests[ i ] ) ; break;
						case testTypes.FW_CHECK				: noError = fwValidateCheckBox		( globalTests[ i ] ) ; break;
						case testTypes.FW_RADIO				: noError = fwValidateRadioBox		( globalTests[ i ] ) ; break;
						case testTypes.FW_REGULAREXPRESSION	: noError = fwValidateRegExp		( globalTests[ i ] ) ; break;
						case testTypes.FW_INTEGER			: noError = fwValidateAnyInteger  	( globalTests[ i ] ) ; break;
						case testTypes.FW_DOUBLE			: noError = fwValidateAnyDouble   	( globalTests[ i ] ) ; break;
						case testTypes.FW_POSITIVE_INTEGER	: noError = fwValidatePositiveInt	( globalTests[ i ] ) ; break;
						case testTypes.FW_POSITIVE_DOUBLE	: noError = fwValidatePositiveDbl	( globalTests[ i ] ) ; break;
						case testTypes.FW_FILENAME			: noError = fwValidateFileName		( globalTests[ i ] ) ; break;
						
					} // Switch

				}
				else
				{
					noError = false;
				}
			}
			else
			{
				noError = false;				
			}

			// noError = false means we have an error :)
			if ( noError == false )
			{
				errorMessages[ errorMessages.length ] = globalTests[ i ].errorMessage;
				noError = true;

				// Set focus to first error
				if ( focusElement == - 1 )
				{
					focusElement 	= i;
				}
				
				// A marking Element is used in those cases where the erratic element itself cannot be styled / marked 
				// with an error, and you wish to use a different element to highlight the error instead
				fwMarkError( globalTests[ i ].markingElement )
			}
			
		}
	} // for


	if (errorMessages.length >= 1 )
	{
		var message = 'Errors found: \n\n';
		for ( var i = 0; i < errorMessages.length; i++ )
		{
			message += eval(i + 1) + ': ' + errorMessages[ i ] + '\n';
		}
		alert ( message );
		
		if ( focusElement >= 0 ) 
		{			
			globalTests[ focusElement ].element.focus();
		}
			
		return false;
	}		
	return true;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// END FOTOWEB FORM VALIDATION METHODS.
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////




////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// FOTOWEB STRING MANIPULATION METHODS.
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

function fwIsWhiteSpace(c)
{
	// Space
	if(c == String.fromCharCode(32))	return(true);
	
	// Tab
	if(c == String.fromCharCode(9))		return(true);

	// Line feed
	if(c == String.fromCharCode(10))	return(true);
	
	// Carriage return
	if(c == String.fromCharCode(13))	return(true);

	return(false);
}

function fwTrim(text)
{
	if (!text || !text.length)	return('');
	if (text.length == 0)		return('');
	
	text = fwRightTrim(text);
	text = fwLeftTrim(text);

	return(text);
}

function fwRightTrim(text)
{
	if (!text || !text.length)	return('');
	if (text.length == 0)		return('');

	var index = text.length - 1;
	
	while(index >= 0 && fwIsWhiteSpace(text.charAt(index)))
	{
		index--;
	}
	
	if (index > 0)
	{
		return(text.substring(0,index + 1));
	}
	
	return('');
}

function fwLeftTrim(text)
{
	if (!text || !text.length)	return('');
	if (text.length == 0)		return('');

	var index = 0;
	
	while(index < text.length && fwIsWhiteSpace(text.charAt(index)))
	{
		index++;
	}
	
	if (index < text.length)
	{
		return(text.substring(index, text.length));
	}
	
	return('');
}

var li = 0;

// Class definition of a single ArchiveInfo item
function archiveInfo( listIndex, isIndexed )
{
	// Variables
	this.ListIndex		= listIndex;
	this.IsIndexed		= isIndexed;
}

var g_indexedArchives 		= new Array( );


function updateOption( listIndex )
{
	var currentArchive 	= g_indexedArchives[ listIndex ];
	var searchBox		= document.getElementById( "idFwSearch" );
	var labelSearch		= document.getElementById( "idFwLabelSearch" );
	var applyButton		= document.getElementById( "idFwSubmit" );
	var searchTitle		= document.getElementById( "idFwSearchTitle" );

	if( currentArchive && searchBox && labelSearch && applyButton && searchTitle )
	{
		if( currentArchive.IsIndexed )
		{
			searchBox.style.display		= "inline";
			labelSearch.style.display	= "inline";
			
			
			if( applyButton.getAttribute( "searchtext" ) )
			{
				applyButton.value		= applyButton.getAttribute( "searchtext" );
			}						
			else
			{
				applyButton.value		= "Search";
			}
		}
		else
		{
			searchBox.style.display		= "none";
			labelSearch.style.display	= "none";

			if( applyButton.getAttribute( "oktext" ) )
			{
				applyButton.value		= applyButton.getAttribute( "oktext" );
			}			
			else
			{
				applyButton.value		= "Ok";
			}
		}
	}
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// END FOTOWEB STRING MANIPULATION METHODS.
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// FOTOWEB RATING METHODS.
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

function fwRating_EditRating(event, navUrl)
{
  fwStopEventPropagation(event);
  
  fwNavigate(navUrl);
}

function fwRating_ShowEdit(event, id)
{
  fwStopEventPropagation(event);
  
  var displayCtrl = document.getElementById(id + '_display');
  var editCtrl = document.getElementById(id + '_edit');

  if(displayCtrl && editCtrl)
  {
    displayCtrl.style.display = 'none';
    displayCtrl.style.visibility = 'hidden';
    
    editCtrl.style.display = 'block';
    editCtrl.style.visibility = 'visible';
  }
}

function fwRating_HideEdit(event, id)
{
  fwStopEventPropagation(event);
  
  var displayCtrl = document.getElementById(id + '_display');
  var editCtrl = document.getElementById(id + '_edit');

  if(displayCtrl && editCtrl)
  {
    displayCtrl.style.display = 'block';
    displayCtrl.style.visibility = 'visible';
    
    editCtrl.style.display = 'none';
    editCtrl.style.visibility = 'hidden';
  }
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// END FOTOWEB RATING METHODS.
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// OPEN ORDER WINDOW
function OrderWindow(URL) {
 	var oppna = open(URL, "namn", "toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=yes, resizable=no, width=650, height=550, top=50, left=100") 
 	
 	oppna.focus();
}

/*
 * Called whenever a value changes in the grid list boxes or the sorting list box
 *
 */
function OnChangeLayoutOrSorting(theForm)
{
	theForm.submit();
}

function PreviewWindow(URL) {
 	var oppna = open(URL, "namn", "toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=yes, resizable=no, width=650, height=500, top=50, left=100") 
 	
 	oppna.focus();
}
