//
// Copyright (c) 2005, Android Technologies, Inc.
//
// FILE: emorate-misc.js
//
// Miscellaneous project specific Javascript code.

// Prefix used to label sub-pages notebook tabs table cells,
//  so they can be retrieved by ID attribute + column number.
// NOTE: Must match the value in common.php.
var NOTEBOOK_TABS_SUB_PAGES_PREFIX	= "notebookTabs_subPage_";

// URL Arguments common between the server code and here (MUST MATCH).
var USER_ID 		= "user_id";
var USER_NAME 		= "user_name";
var QUERY_CODE		= "query_code";

// PATHS
var GRAPHICS_DIRECTORY	= "./graphics/";

// Button bar image names with full path.
var AGREE_BUTTON_IMAGE				= 'check-green-1.gif';
var AGREE_BUTTON_IMAGE_CHECKED		= 'check-green-1-checked.gif';
var AGREE_BUTTON_IMAGE_UNCHECKED	= 'check-green-1-unchecked.gif';
var DISAGREE_BUTTON_IMAGE			= 'red-x-1.gif';
var DISAGREE_BUTTON_IMAGE_CHECKED	= 'red-x-1-checked.gif';
var DISAGREE_BUTTON_IMAGE_UNCHECKED	= 'red-x-1-unchecked.gif';
var NONE_BUTTON_IMAGE				= 'erase-1.gif';
var SHOW_BUTTON_IMAGE				= 'show-ball.jpg';
var HIDE_BUTTON_IMAGE				= 'hide-ball.jpg';

var AGREE_CODE 		= 1;
var DISAGREE_CODE 	= 2;
var NONE_CODE 		= 3;

// We need to identify certain sub-pages, hence this variable.
var RATINGS_FIELDS_SUB_PAGE_TITLE	= "Search - Ratings Fields";
var GENERAL_FIELDS_SUB_PAGE_TITLE	= "Search - Text Fields";

var QUICK_DOCUMENT_HEADER = '<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=ISO-8859-1">' +
'\n' +
'<META NAME="Copyright" CONTENT="(c) 2005, Android Technologies, Inc.">' +
'\n' +
'<META NAME="Description" CONTENT="A fun rating & comments service for Flickr photos, based on the Flickr API.">' +
'\n' +
'<META NAME="Keywords" CONTENT="flickr, flickr picker, flickr rating, flickr comments, flickr audio, flickr sounds">' +
'\n' +
'<META NAME="Robots" CONTENT="ALL">';

// This variable is set to true by delayedAlert() so that it
//  knows not to pump out anymore alerts.  This prevents 
//  the bombarding of the the user with alert boxes.
var g_delayedAlertPosted = false;

// ----------------------------------------------------------

// Decode a string containg html entities back to it's unencoded
//  value.
function htmlentitiesDecode(theString)
{
	return theString.replace(/&#(\d+);/g, 
		function(wholematch, parenmatch1) { return String.fromCharCode(+parenmatch1); } ); 
}

// ----------------------------------------------------------
// This function is used to submit critiques.
function submitCritique(reviewID, opinionCode)
{
	// Find the IMG control used for submitting critiques.
	var imgCtrl = document.getElementById("submitCritique");
	
	if (!imgCtrl)
	{
		alert("(submitCritique) The necessary submission component was not found.");
		return;
	}
	
	if (!reviewID)
	{
		alert("(submitCritique) Invalid review ID.");
		return;
	}
	
	if (!opinionCode)
	{
		alert("(submitCritique) Invalid opinion code.");
		return;
	}
	
	var submissionUrl = "./submit-critique.php";
	var theDate = new Date();
	
	submissionUrl += "?";
	submissionUrl += "review_primary_key=" + reviewID;
	submissionUrl += "&";
	submissionUrl += "agree_disagree_none_code=" + opinionCode
	// Add the current time to defeat browser caching.  Otherwise
	//  duplicate clicks of the same critique button will not
	//  trigger a GET.
	submissionUrl += "&";
	submissionUrl += "timestamp=" + theDate.getTime();
	
	imgCtrl.src = submissionUrl;
	
	/*
	var greetingDiv = document.getElementById('greeting');
	if (!greetingDiv)
	{
		alert("(submitCritique) The 'greeting' DIV element is missing.");
		return;
	}
	
	greetingDiv.innerHTML = "submissionUrl = " + submissionUrl;
	*/
} // function submitCritique(reviewID, opinionCode)
	
function critiqueClick(srcDocument, reviewID, opinionCode)
{
	// Get references to all the opinion "buttons".
	var agreeButton 	= srcDocument.getElementById('imgAgree_' + reviewID);
	
	if (!agreeButton)
	{
		alert("(critiqueClick) The agree button could not be found!");
		return;
	}
	
	var disagreeButton 	= srcDocument.getElementById('imgDisagree_' + reviewID);
	
	if (!disagreeButton)
	{
		alert("(critiqueClick) The disagree button could not be found!");
		return;
	}
	
	var noneButton 		= srcDocument.getElementById('imgNone_' + reviewID);
	
	if (!noneButton)
	{
		alert("(critiqueClick) The none button could not be found!");
		return;
	}
	

	// PHP include needs to provide the button image file names.	
	if (opinionCode == 'agree')
	{
		agreeButton.src 	= GRAPHICS_DIRECTORY + AGREE_BUTTON_IMAGE_CHECKED;
		disagreeButton.src 	= GRAPHICS_DIRECTORY + DISAGREE_BUTTON_IMAGE_UNCHECKED;
		// Submit the new/changed critique.
		submitCritique(reviewID, AGREE_CODE);		
	}
		
	if (opinionCode == 'disagree')
	{
		// "unchecked" really means "greyed out".
		agreeButton.src 	= GRAPHICS_DIRECTORY + AGREE_BUTTON_IMAGE_UNCHECKED;
		disagreeButton.src 	= GRAPHICS_DIRECTORY + DISAGREE_BUTTON_IMAGE_CHECKED;
		submitCritique(reviewID, DISAGREE_CODE);		
	}
		
	if (opinionCode == 'none')
	{
		agreeButton.src 	= GRAPHICS_DIRECTORY + AGREE_BUTTON_IMAGE;
		disagreeButton.src 	= GRAPHICS_DIRECTORY + DISAGREE_BUTTON_IMAGE;
		submitCritique(reviewID, NONE_CODE);		
	}
} // function critiqueClick(opinionCode, opinionID)

// Extract a filename from a URL.  If removeExtension
//  is TRUE, drop the file extension too.
function extractFileName(url, removeExtension)
{
	if (!removeExtension)
		removeExtension = false;  // Default is "no".
	
	var filename = url.substring(url.lastIndexOf('\/')+1); 
	
	if (removeExtension)
		filename = filename.substring(0, filename.lastIndexOf('.'));
	
	return filename;
} // function extractFileName()

// A simple routine that pushes an error message to be displayed
//  with "alert()", off to a timer.  Useful for displaying errors
//  that occur on "timer()" functions (so the user does not get
//  bombarded with "alert()" boxes).
function showDelayedAlert(message)
{
	if (message)
		alert(message);
} // function showdelayedAlert()

// The setInterval() call variant that supports arguments is not
//  universally supported.  Embed them in the function call
//  parameter instead.
function delayedAlert(message, delayTimeMS)
{
	// Check repetitive alert prevention flag.
	if (g_delayedAlertPosted)
		return;
		
	if (!delayTimeMS)
		delayTimeMS = 500;  // Default delay.
		
	if (message)
		setTimeout("showDelayedAlert(" + "'" + message + "'" + ", " + delayTimeMS + ")");
	
	// Set flag to avoid repetitive alerts.
	g_delayedAlertPosted = true;
} // function delayedAlert()

	
// Debug helper function.
function callDebugger(callingWindow)
{
	var i = 0;
} // function callDebugger(callingWindow)

/*	
function hideHelpWindow()
{
	// Find the help area iframe.
	if (!window.frames.helparea)
	{
		alert('(hideHelpWindow) Unable to find the help document iframe.');
		return;
	} // if (!helpAreaElem)
	
	// Find the show/hide button.
	var showHideImage = document.getElementById("imgShowHideHelp")
	
	if (!showHideImage)
	{
		alert('(hideHelpWindow) Unable to find the show/hide help button..');
		return;
	} // if (!helpAreaElem)

	var hideIt = (showHideImage.src.indexOf(HIDE_BUTTON_IMAGE) >= 0);
	
	if (hideIt)
	{
		// Hide the help iframe.
		// window.frames.helparea.visible = false; // "display: none;"
		// window.frames.helparea.frameElement.style.height = 2;
		window.frames.helparea.frameElement.style.display = 'none';
		
		// Modify the show/hide button appropriately.
		showHideImage.src = GRAPHICS_DIRECTORY + SHOW_BUTTON_IMAGE;
		showHideImage.alt = "Show the Help Window.";
	}
	else
	{
		// Show the help iframe.	
		// window.frames.helparea.visible = true;
		// window.frames.helparea.frameElement.style.height = 70;
		window.frames.helparea.frameElement.style.display = '';
		
		// Modify the show/hide button appropriately.
		showHideImage.src = GRAPHICS_DIRECTORY + HIDE_BUTTON_IMAGE;
		showHideImage.alt = "Hide the Help Window.";
	} // else - if (hideit)

	showHideImage.height = 17;
	showHideImage.width = 17;	
	showHideImage.title = showHideImage.alt;
	
} // hideHelpWindow()	
*/

// Get a DIV element with utmost browser compatibility.
function getDiv(pageDoc, divID)
{
	var theDiv		= null;
	
	if (pageDoc.getElementById)
		theDiv = pageDoc.getElementById(divID);
	else if (pageDoc.all)
		// For old versions of IE.
		theDiv = pageDoc.all[divID];
	else if (pageDoc.layers)
		// For netscape 4
		theDiv = pageDoc.layers[divID];
		
	return theDiv;
} // getDiv(DivID)

// This function shows a DIV.
function showDiv(pageDoc, divID)
{
	var theDiv = getDiv(pageDoc, divID);

	if (!theDiv)	
	{
		alert("(showDiv) Unable to find a DIV element with the ID: " + divID + ".");
		return null;
	}
	
	theDiv.style.display = "block";
} // showDiv(divID)

// This function hides a DIV.
function hideDiv(pageDoc, divID)
{
	var theDiv	= getDiv(pageDoc, divID);

	if (!theDiv)	
	{
		alert("(hideDiv) Unable to find a DIV element with the ID: " + divID + ".");
		return null;
	}
	
	theDiv.style.display = "none";
} // showDiv(divID)

// This function reports whether or not a DIV is currently visible.
function isDivVisible(pageDoc, divID)
{
	var theDiv	= getDiv(pageDoc, divID);

	if (!theDiv)	
	{
		alert("(hideDiv) Unable to find a DIV element with the ID: " + divID + ".");
		return null;
	}
	
	return (theDiv.style.display != "none");
} // showDiv(divID)

// This function gets the event target for a triggered event,
//  accounting for differences betwee IE and DOM Level 2 browser
//  event models..
function getEventTarget(e)
{
	if (document.addEventListener)
	{
		// DOM Level 2 Event model.
		return e.target;
	}
	else if (document.attachEvent)
	{
		// Internet Explorer 5.x or greater Event model.
		return e.srcElement;
	}		
	
	return null;
} // getEventTarget()
 

/*
// Write HTML into the helparea IFRAME.
function writeHelp(helpHtml, bodyTagAttributes)
{
	if (!bodyTagAttributes)
		bodyTagAttributes = "";
		
	var docHtml =
		'<HTML>\n' +
		'<HEAD>\n' +
		'<TITLE>' +
		'Help Document' +
		'</TITLE>\n' +
		QUICK_DOCUMENT_HEADER +
		'</HEAD>\n' +
		'<BODY' + bodyTagAttributes + '>\n' +
		'<TABLE name="helpareaTable" id="helpareaTable" WIDTH="100%" HEIGHT="100%" >\n' +
		'<TR VALIGN="top">\n' +
		'<TD CELLPADDING="5" >\n' +
		helpHtml +
		'</TD>\n' +
		'</TR>\n' +
		'</TABLE>\n' +
		'</BODY>\n' +
		'</HTML>\n';
		
	if (!window.frames.helparea)
	{
		alert('(writeHelp) Unable to find the help document iframe.');
		return;
	} // if (!helpAreaElem)
	
	if (!window.frames.helparea.frameElement.contentDocument)
	{
		alert('(writeHelp) Unable to find the help iframe content document.');
		return;
	} // if (!helpArea.contentDocument)
		
	var helpAreaDoc =
		window.frames.helparea.frameElement.contentDocument;
	
	helpAreaDoc.open();
	helpAreaDoc.write(docHtml);
	helpAreaDoc.close();
} // writeHelp()	
*/

// (c) 2003 - Android Technologies, Inc. All rights reserved.

// Global vars.
var gMargin = 5;  // Margin used for iframes.

// This function returns TRUE if the target string
//  begins with the desired "starts-with" string.
function startsWith(startsWithString, targetString)
{
	if (targetString.indexOf(startsWithString) == 0)
		return true;
		
	return false;
}

// ---------------------------------------------------------------

function ReportError(callerId, errMsg, bShowAlert)
{
    var sErrMsg  = '';
    var sErrMsg2 = '';

    sErrMsg = 'Error reported: ' + errMsg; // e.Name + ' -> ' + e.message;
    sErrMsg2 = '(' + callerId + ')' + sErrMsg + '\n' + 'Document: ' + document.title;

    if (typeof bShowAlert == 'undefined')
        bShowAlert = true;

    // Only show alert if caller desires it.
    if (bShowAlert)
    {
        if (!gErrorsReported)
        {
            // Don't let user be bombarded by error messages.
            gErrorsReported = true;
            alert(sErrMsg2);
        }
    }

    // Always show errors in debug window if gDebug is true.
    if (gDebug)
    {
        gDebugWin.document.write(
            '<b>ERROR(' +
            callerId +
            '): </b>' +
            sErrMsg +
            '<hr/>' +
            '\n' +
            'Document: ' +
            document.title +
            '<hr/>');
    }
}

	
// object type so that strings can be passed as a property of
//  an object in order to have their values changed
function ErrorObject()
{
	this.msg = "";
}

function getFormField(id)
{
	var fe = document.getElementById(id);
	
	if (fe)
		return AllTrim(fe.value);
	else
	{
		alert("(getFormField) Unable to find an object with the ID=" + id);
		return "";
	}
}

function setFormField(id, newVal)
{
	var fe = document.getElementById(id);
	
	if (fe)
		fe.value = newVal;
	else
	{
		alert("(getFormField) Unable to find an object with the ID=" + id);
		return "";
	}
}

// Validate the data fields.
function isEmailAddressValid(email_address)
{
    if (
        (email_address.length < 1) ||
        (email_address.indexOf("@") < 0) ||
        (email_address.indexOf(".") < 0)
       )
		return false;
	return true;
}

// -------------------------------------------------
function isPasswordValid(password, confirm_password, err_obj)
{
	err_obj.msg = "";
	var bValidPassword = true;
	
    if (password.length < 1)
    {
        err_obj.msg = "Password field is empty.";
        bValidPassword = false;
    }
    else
    {
	    if (password.length < 6)
	    {
	        err_obj.msg = "Password field must be at least 6 characters long.";
	        bValidPassword = false;
	    }
	    else
	    {
		    if (confirm_password.length < 1)
		    {
		        err_obj.msg = "Password confirmation field is empty.";
		        bValidPassword = false;
		    }
		    else
		    {
			    // Make sure they match.
			    if (password != confirm_password)
			    {
			        err_obj.msg = "Password and Confirmation Password don't match.";
			        bValidPassword = false;
			    }
			} // else / if (confirm_password.length < 1)
		}
	} // if (password.length < 1)
	
	return bValidPassword;
}

// ---------------------------------------------------------------

function getSearchArguments(srcDoc)
{
    var SearchArguments = new Object();

    var hrefStr = "";
    
    if (srcDoc)
    	hrefStr = srcDoc.location.search;
    else
    	// If a URL was not passed, assume it's the current document's search string.
    	hrefStr = location.search;
    
    // alert("(getSearchArguments) search arguments = " + location.search.substring(1));

    var NameListItemPairs = hrefStr.substring(1).split("&");
    for (var i = 0; i < NameListItemPairs.length; i++)
    {
        var DelimPos = NameListItemPairs[i].indexOf('=');
        if (DelimPos != -1)
        {
            var ArgName  = NameListItemPairs[i].substring(0, DelimPos);
            var ArgListItem = NameListItemPairs[i].substring(DelimPos + 1);
            SearchArguments[ArgName] = ArgListItem;

            // alert("SearchArguments[" + ArgName + "] =" + ArgListItem);
        }
    }

    return SearchArguments;
}

// ---------------------------------------------------------------

function getSearchArgumentsAsArray(srcDoc)
{
    var SearchArguments = new Array();

    var hrefStr = "";
    if (srcDoc)
    	hrefStr = srcDoc.location.search;
    else
    	// If a URL was not passed, assume it's the current document's search string.
    	hrefStr = location.search;
    
    // alert("(getSearchArguments) search arguments = " + location.search.substring(1));

    var NameListItemPairs = hrefStr.substring(1).split("&");
    for (var i = 0; i < NameListItemPairs.length; i++)
    {
        var DelimPos = NameListItemPairs[i].indexOf('=');
        if (DelimPos != -1)
        {
            var ArgName  = NameListItemPairs[i].substring(0, DelimPos);
            var ArgListItem = NameListItemPairs[i].substring(DelimPos + 1);
            SearchArguments[ArgName] = ArgListItem;

            // alert("SearchArguments[" + ArgName + "] =" + ArgListItem);
        }
    }

    return SearchArguments;
}

// ---------------------------------------------------------------

function setWindowTitleFromSearchArg()
{
    	
	if (getSearchArguments)
	{
	    var searchArguments = getSearchArguments();
	   
	    if (searchArguments.mentor_id)
		    if (searchArguments.mentor_id.length > 0)
	   			 window.title = "PowerSell!(tm) - Mentor ID: " + searchArguments.mentor_id;
	}
}

// ---------------------------------------------------------------

function adjustIFrameSize(iframeWindow, bottomMarginIN) 
{
	var bottomMargin = 10;

	if (bottomMarginIN)
		bottomMargin = bottomMarginIN;
		
	if (iframeWindow.document.height) 
	{
		var iframeElement = document.getElementById(iframeWindow.name);
		
		iframeElement.style.height = 
			(iframeWindow.document.height + bottomMargin) + 'px';
		iframeElement.style.width = 
			iframeWindow.document.width + 'px';
	}
	else 
	{
		if (document.all) 
		{
			var iframeElement = document.all[iframeWindow.name];
			
			if (iframeWindow.document.compatMode &&
					iframeWindow.document.compatMode != 'BackCompat')
			{
				iframeElement.style.height =
					(iframeWindow.document.documentElement.scrollHeight  + bottomMargin) + 'px';
				iframeElement.style.width =
					iframeWindow.document.documentElement.scrollWidth + 'px';
			}
			else 
			{
				iframeElement.style.height =
					(iframeWindow.document.body.scrollHeight +  + bottomMargin) + 'px';
				iframeElement.style.width =
					iframeWindow.document.body.scrollWidth + 'px';
			}
		} // if (document.all) 
	} // else - if (iframeWindow.document.height) 
}

// ---------------------------------------------------------------

function resizeIFrame(id, x, y, callerId)
{
    var SX = "";
    var SY = "";

    if (true)
    {
        SX = x + '';
        SY = y + '';

        if (SX.indexOf('px') == -1)
            SX = SX + 'px';

        if (SY.indexOf('px') == -1)
            SY = SY + 'px';

        // alert("(resizeIFrame), called by '" + callerId + "'> id = " + id + ", x = " + x + ", y = " + y);

        var iframeElement = null;

        // alert("(resizeIFrame) set iframeElement to null.");
        if (top.document.all)
        {
            // Internet Explorer.
            // alert('(resizeIframe) IE browser.');
            iframeElement = top.document.all[id];

        } // if (document.all)
        else if (top.document.height)
        {
            // Other browsers.
            // alert('(resizeIframe) Non-IE browser.');
            iframeElement =
                top.document.getElementById(id);
        } // else if (top.document.height)

        if (iframeElement)
        {
            iframeElement.style.width  = x;
            iframeElement.style.height = y;
            // alert("(resizeIFrame) iframeElement.style (width, height) = " + iframeElement.style.width + ", " + iframeElement.style.height);
        }
        else
            alert('(resizeIFrame) iframeElement is null for id = ' + id);
    } // if (true)
}

// ---------------------------------------------------------------

function getScrollWidth(doc, callerId)
{
	// debugger;
	
    if (true)
    {
	    // If no document reference was passed, assume it is the
	    //  current document.
	    if (!doc)
	    	doc = document;

        var ret;

        if (doc.all)
        {
            // Internet Explorer.
            if (doc.compatMode &&
                doc.compatMode != 'BackCompat')
                ret = doc.documentElement.scrollWidth  + gMargin + 'px';
            else
                ret = doc.body.scrollWidth  + gMargin + 'px';
        } // if (doc.all)
        else if (doc.width)
            // Other browsers.
            ret = doc.width + gMargin + 'px';

        // alert('(getScrollWidth) Returning scroll width(' + ret + ') to caller Id: ' + callerId);

        return ret;
    } // if (true)
}

// ---------------------------------------------------------------

function getScrollHeight(doc, callerId)
{
    if (true)
    {
	    // If no document reference was passed, assume it is the
	    //  current document.
	    if (!doc)
	    	doc = document;

        var ret;

        if (doc.all)
        {
            // Internet Explorer.
            if (doc.compatMode &&
                doc.compatMode != 'BackCompat')
                ret = doc.documentElement.scrollHeight + gMargin + 'px';
            else
                ret = doc.body.scrollHeight + gMargin + 'px';
        } // if (doc.all)
        else if (doc.height)
            // Other browsers.
            ret = doc.height + gMargin+ 'px';

        // alert('(getScrollHeight) Returning scroll height(' + ret + ') to caller Id: ' + callerId);

        return ret;
    } // if (true)
}


// ---------------------------------------------------------------

function email_verify()
{
    // Email Address
    var S = getFormField("email_address");
    
    if (!isEmailAddressValid(S))
    {
        alert("Email Address is invalid.");
        return false;
    }

    return true;
}

// ---------------------------------------------------------------

// This function checks to see if an htmlElement is a hyperlink
//  element or not.  It also checks the parent in case the
//  htmlElement is hyperlinked element like an IMG control.
function isHyperLink(htmlElement)
{
	if (htmlElement)
	{
		// Check element itself.
		if (
			(htmlElement.tagName == "A") ||
			(htmlElement.tagName == "a")
		   )
			return htmlElement;
				
		// Check parent of element.		
		if (htmlElement.parentElement)
		{
			if (
				(htmlElement.parentElement.tagName == "A") ||
				(htmlElement.parentElement.tagName == "a")
			   )	
				return htmlElement.parentElement;
		}
	}
	
	return null;
} // function isHyperLink(htmlElement)

// ---------------------------------------------------------------

// ***************************** COOKIE CLASS ********************'

// The constructor function: creates a cookie object for the specified
// document, with a specified name and optional attributes.
// Arguments:
//   document: The Document object that the cookie is stored for. Required.
//   name:     A string that specifies a name for the cookie. Required.
//   hours:    An optional number that specifies the number of hours from now
//             that the cookie should expire.
//   path:     An optional string that specifies the cookie path attribute.
//   domain:   An optional string that specifies the cookie domain attribute.
//   secure:   An optional Boolean value that, if true, requests a secure cookie.
//
function Cookie(document, name, hours, path, domain, secure)
{
    // All the predefined properties of this object begin with '$'
    // to distinguish them from other properties which are the values to
    // be stored in the cookie.
    this.$document = document;
    this.$name = name;
    if (hours)
        this.$expiration = new Date((new Date()).getTime() + hours*3600000);
    else this.$expiration = null;
    if (path) this.$path = path; else this.$path = null;
    if (domain) this.$domain = domain; else this.$domain = null;
    if (secure) this.$secure = true; else this.$secure = false;
}

// This function is the store() method of the Cookie object.
Cookie.prototype.store = function () {
    // First, loop through the properties of the Cookie object and
    // put together the value of the cookie. Since cookies use the
    // equals sign and semicolons as separators, we'll use colons
    // and ampersands for the individual state variables we store 
    // within a single cookie value. Note that we escape the value
    // of each state variable, in case it contains punctuation or other
    // illegal characters.
    var cookieval = "";
    for(var prop in this) {
        // Ignore properties with names that begin with '$' and also methods.
        if ((prop.charAt(0) == '$') || ((typeof this[prop]) == 'function')) 
            continue;
        if (cookieval != "") cookieval += '&';
        cookieval += prop + ':' + escape(this[prop]);
    }

    // Now that we have the value of the cookie, put together the 
    // complete cookie string, which includes the name and the various
    // attributes specified when the Cookie object was created.
    var cookie = this.$name + '=' + cookieval;
    if (this.$expiration)
        cookie += '; expires=' + this.$expiration.toGMTString();
    if (this.$path) cookie += '; path=' + this.$path;
    if (this.$domain) cookie += '; domain=' + this.$domain;
    if (this.$secure) cookie += '; secure';

    // Now store the cookie by setting the magic Document.cookie property.
    this.$document.cookie = cookie;
}

// This function is the load() method of the Cookie object.
Cookie.prototype.load = function() { 
    // First, get a list of all cookies that pertain to this document.
    // We do this by reading the magic Document.cookie property.
    var allcookies = this.$document.cookie;
    if (allcookies == "") return false;

    // Now extract just the named cookie from that list.
    var start = allcookies.indexOf(this.$name + '=');
    if (start == -1) return false;   // Cookie not defined for this page.
    start += this.$name.length + 1;  // Skip name and equals sign.
    var end = allcookies.indexOf(';', start);
    if (end == -1) end = allcookies.length;
    var cookieval = allcookies.substring(start, end);

    // Now that we've extracted the value of the named cookie, we've
    // got to break that value down into individual state variable 
    // names and values. The name/value pairs are separated from each
    // other by ampersands, and the individual names and values are
    // separated from each other by colons. We use the split method
    // to parse everything.
    var a = cookieval.split('&');    // Break it into array of name/value pairs.
    for(var i=0; i < a.length; i++)  // Break each pair into an array.
        a[i] = a[i].split(':');

    // Now that we've parsed the cookie value, set all the names and values
    // of the state variables in this Cookie object. Note that we unescape()
    // the property value, because we called escape() when we stored it.
    for(var i = 0; i < a.length; i++) {
        this[a[i][0]] = unescape(a[i][1]);
    }

    // We're done, so return the success code.
    return true;
}

// This function is the remove() method of the Cookie object.
Cookie.prototype.remove = function() {
    var cookie;
    cookie = this.$name + '=';
    if (this.$path) cookie += '; path=' + this.$path;
    if (this.$domain) cookie += '; domain=' + this.$domain;
    cookie += '; expires=Fri, 02-Jan-1970 00:00:00 GMT';

    this.$document.cookie = cookie;
}


//===================================================================
//  The previous code is the definition of the Cookie class.
//  The following code is a sample use of that class.
//===================================================================

// Create the cookie we'll use to save state for this web page.
// Since we're using the default path, this cookie will be accessible
// to all web pages in the same directory as this file or "below" it.
// Therefore, it should have a name that is unique among those pages.
// Note that we set the expiration to 10 days in the future.

//? var visitordata = new Cookie(document, "name_color_count_state", 240);

// First, try to read data stored in the cookie. If the cookie is not
// defined, or if it doesn't contain the data we need, then query the
// user for that data.

//? if (!visitordata.load() || !visitordata.name || !visitordata.color) {
//?     visitordata.name = prompt("What is your name:", "");
//?     visitordata.color = prompt("What is your favorite color:", "");
//? }

// Keep track of how many times this user has visited the page:

//? if (visitordata.visits == null) visitordata.visits = 0;
//? 	visitordata.visits++;

// Store the cookie values, even if they were already stored, so that the 
// expiration date will be reset to 10 days from this most recent visit.
// Also, store them again to save the updated visits state variable.

//? visitordata.store();

// Now we can use the state variables we read:
//? document.write('<font size="7" color="' + visitordata.color + '">' +
//?                'Welcome, ' + visitordata.name + '!' +
//?                '</font>' +
//?                '<p>You have visited ' + visitordata.visits + ' times.');

// ---------------------------------------------------------------

// Given a document containing a sub-pages notebook tabs bar,
//  Highlight the given column number and un-highlight all
//  the others.
// PARAMETERS:
//	subPageDoc	: Document that contains the sub-page notebook tabs bar.
//	columnNumber: The column number to "highlight".
//	numTabs		: The number of tabs in the notebook tabs bar.
// NOTE		: Tabs are numbered starting at base 1, NOT 0.
// TIMER BASED FUNCTION!
function highlightSubPageNotebookTab(subPageDoc, columnNumber, numTabs)
{
	if (!subPageDoc)
	{
		delayedAlert("(highlightSubPageNotebookTab) Document is undefined.");
		return;
	} // if (!subPageDoc)
	
	if (!columnNumber)
	{
		delayedAlert("(highlightSubPageNotebookTab) Column number is undefined.");
		return;
	} // if (!columnNumber)
	
	if (!numTabs)
	{
		delayedAlert("(highlightSubPageNotebookTab) Tab count is undefined.");
		return;
	} // if (!numTabs)

	var fullNameOfUnhighlightImage =
		GRAPHICS_DIRECTORY + "one-sub-page-notebook-tab-purple.jpg";
	var fullNameOfHighlightImage =
		GRAPHICS_DIRECTORY + "one-sub-page-notebook-tab-yellow.jpg";
	
	for (var i = 1; i <= numTabs; i++)
	{
		// Find the table data element for the given column number.
		var tdName =
			NOTEBOOK_TABS_SUB_PAGES_PREFIX + i;	
		var tdElem =
			subPageDoc.getElementById(tdName);
			
		if (!tdElem)
		{ 
			delayedAlert("(highlightSubPageNotebookTab) Unable to find the element named: " + tdName + ".");
			return;
		} // if (!tdElem)
		
		if (i == columnNumber)
		{
			if (tdElem.attributes.background.value != fullNameOfHighlightImage)
				tdElem.attributes.background.value = fullNameOfHighlightImage;
		}
		else
		{
			if (tdElem.attributes.background.value != fullNameOfUnhighlightImage)
				tdElem.attributes.background.value = fullNameOfUnhighlightImage;
		} // else - if (i == columnNumber)
	} // for()
} // function highlightSubPageNotebookTab() 		
