/*********************************************************************/
/*                                                                   */
/* IBM Confidential                                                  */
/*                                                                   */
/* OCO Source Materials                                              */
/*                                                                   */
/* Copyright IBM Corp. 2005, 2007                                    */
/*                                                                   */
/* The source code for this program is not published or otherwise    */
/* divested of its trade secrets, irrespective of what has been      */
/* deposited with the U.S. Copyright Office.                         */
/*                                                                   */
/*********************************************************************/

//-------------------------------------------------------------
//  Quickplace Context Menu library
//-------------------------------------------------------------

// TO DO...................................
// - "register" or "attach" menus to elements not listed here (?)
// - handle non-members (don't show icon, or show different icon w/o action)
// - handle folder context menus differently than for docs
// - Other: see various "FIX ME" comments below.............
//

var g_pageX = 0;
var g_pageY = 0;

//---------------------------------------------------------------------

function QP_ContextMenu_Item(type, label, action, target, title, title_disabled, icon, submenu)
{
	this.type = type; 
	this.label = label || "";
	this.action = action || "";
	this.target = target || "_self";
	this.title = title || this.label;
	this.title_disabled = title_disabled || this.title;
	this.icon = icon;
	this.submenu = submenu;

}

function QP_ContextMenu(name, extraClass)
{ 
	if (document.getElementById(name + "_Menu") != null) {
		 // This menu already exists in the DOM - set flag & return
		 this.exists = true;
		 return;
	} 
	else {
		 // No such menu exists - go ahead...
		 this.exists			= false;

		 this.name				= name;
		 this.extraClass		= extraClass;
		 this.items				= new Array();
		 
		 this.write				= QP_ContextMenu_write;
		 this.sfHover			= QP_ContextMenu_sfHover;
		 this.show				= QP_ContextMenu_show;
		 this.addItem			= QP_ContextMenu_addItem;
		 this.addSubmenu		= QP_ContextMenu_addSubmenu;
		 this.addHTML			= QP_ContextMenu_addHTML;
		 this.addSeparator	= QP_ContextMenu_addSeparator;
		 this.addImage			= QP_ContextMenu_addImage;
		 this.fixName			= QP_ContextMenu_fixName;
		 this.makeItem			= QP_ContextMenu_makeItem;
		 this.makeSeparator	= QP_ContextMenu_makeSeparator;

		 this.HTML				= 0;
		 this.LINK				= 1;
		 this.LINK_SUBMENU	= 2;
		 this.IMAGE				= 3;
		 this.SEPARATOR		= 4;
	}
}

function QP_PersonMenu(szDN, szCN, szDisplayName, szEmail, szPhone, szPhoto, szDescription, szProfileUnid)
{ 
	var fixedName = QP_ContextMenu_fixName(szDN);
	if (QP_ContextMenu_exists(fixedName)) {
		 // This menu already exists in the DOM - set flag & return
		 this.exists = true;
		 return;
	} 
	else {
		 // No such menu exists - go ahead...
		 this.exists			= false;

		 // Inherit from QP_ContextMenu
		 this.base				= QP_ContextMenu;
		 this.base(fixedName);

		 this.CN					= szCN;
		 this.DN					= szDN;
		 this.displayName		= szDisplayName || szCN;
		 // FIX ME: remove 'test' strings
		 this.email				= szEmail || "";
		 this.phone				= szPhone || "";
		 this.photo				= szPhoto || "";
		 this.description		= szDescription || "";
		 this.profileUnid		= szProfileUnid || "";
		 
		 this.makeBizCard		= QP_PersonMenu_makeBizCard;
		 this.write				= QP_PersonMenu_write;
	}
}
QP_PersonMenu.prototype = new QP_ContextMenu;


// ---------------------------------------------------------

function QP_ContextMenu_get(name)
{ 
	return document.getElementById(name + "_Menu");
}

function QP_ContextMenu_exists(name)
{ 
	return (document.getElementById(name + "_Menu") != null);
}

// Convert menu name (which may be a Notes canonical name) to a valid HTML Id that we can use
// as a basis for menu-related HTML elements.
// Must begin with a letter ([A-Za-z]) and may be followed by any number of letters, digits ([0-9]),
// hyphens ("-"), underscores ("_"), colons (":"), and periods (".").
function QP_ContextMenu_fixName(name) {
	if (typeof(name) == "undefined")
		return "";
	else
		return name.replace(/[.=\/ ]/g, "-");
//	return encodeForUrl(encodeURIComponent(name));
}

function QP_ContextMenu_mouseTracker(e) {
	 // No logging here because would cause infinite loop
    e = e || window.Event || window.event;
    g_pageX = e.pageX || e.clientX;
    g_pageY = e.pageY || e.clientY;
}


// ---------------------------------------------------------

function QP_ContextMenu_addItem(label, action, target, title, icon, title_disabled)
{ 
	this.items[this.items.length] = new QP_ContextMenu_Item(this.LINK, label, action, target, title, title_disabled, icon);
}

function QP_ContextMenu_addSubmenu(label, action, target, title, icon, title_disabled, submenu)
{ 
	this.items[this.items.length] = new QP_ContextMenu_Item(this.LINK_SUBMENU, label, action, target, title, title_disabled, icon, submenu);
}

function QP_ContextMenu_addImage(label, action, target)
{ 
	this.items[this.items.length] = new QP_ContextMenu_Item(this.IMAGE, label, action, target);
}

function QP_ContextMenu_addHTML(label, action, target)
{ 
	this.items[this.items.length] = new QP_ContextMenu_Item(this.HTML, label, action, target);
}

function QP_ContextMenu_addSeparator(label, action, target)
{ 
	this.items[this.items.length] = new QP_ContextMenu_Item(this.SEPARATOR, "", "", "");
}

// ----------------------------------------------------------
// Generate HTML for one menu item
//
function QP_ContextMenu_makeItem(szLabel, szAction, szTitle)
{
	var title = szTitle || szLabel;
	var action = szAction || "#";
	var html = "";

	html += '<li><a id="' + this.name + '_' + QP_ContextMenu_fixName(szLabel) + '"';
	if (szAction == "") {
		 // Item is inactive - show as greyed out
		 html += ' href="javascript:void(0);" class="h-contextMenu-disabled"';
	}
	else {
		 if (title != "")
			  html += ' title="' + title + '"';
		 html += ' href="' + action + '"';
	}
	html += '>' + szLabel + '</a></li>';
	return html;
}

// ----------------------------------------------------------

function QP_ContextMenu_populateItem(menu, szLabel, szAction, szNewLabel)
{

	var xLabel = ((szNewLabel) ? szNewLabel: szLabel);
	
	var elem = document.getElementById(menu + '_' + QP_ContextMenu_fixName(szLabel));

	if (elem) {

		if (szAction == "") {
			elem.href = "javascript:void(0);"
			elem.parentNode.parentNode.className = "wcfMenuItemDisabled";
		} else {
			elem.href = szAction;
			elem.parentNode.parentNode.className = "wcfMenuItem";
		}

		//update the label of the link if it is passed in.
		if (szNewLabel) {
			elem.innerHTML = szNewLabel;
		}
		
		elem.title = xLabel;
	}
	 
}

// ----------------------------------------------------------

function QP_PersonMenu_populateItem(menu, szLabel, szAction)
{
	if (szAction && szAction != "") {
		var elem = document.getElementById(menu + '_' + QP_ContextMenu_fixName(szLabel));
		if (elem) {
			elem.href = szAction;
			elem.className = "h-context-menu";
			elem.title = szLabel;
		}
	}
}

// ----------------------------------------------------------
// Generate HTML separator for context menu items
//
function QP_ContextMenu_makeSeparator()
{
	return '<li class="h-context-separator"><hr/></li>';
}


// ----------------------------------------------------------
// Generate HTML separator for context menu items
//
function QP_PersonMenu_makeBizCard()
{
	var html = "";
	html += '<div class="photoCard">';
	html += '<img id="' + this.name + '_photo" src="' 
		+ getMemberPhotoLink(this.CN, this.DN, this.DisplayName, this.email, this.photo, this.profileUnid)
		+ '" alt="">';
	html += '</div>';

	html += '<div class="businessCard">';
	html += '<ul>';
	html += '<li id="' + this.name + '_name" class="cardName">' + this.displayName +'</li>';
	html += '<li id="' + this.name + '_email">' + this.email + '</li>';
	html += '<li id="' + this.name + '_desc">' + this.description + '</li>';
	html += '<li id="' + this.name + '_phone">' + this.phone + '</li>';
	html += '</ul>';
	html += '</div>';
	return html;
}

// ----------------------------------------------------------

function QP_PersonMenu_populateBizCard(szCN, szDN, szDisplayName, szEmail, szPhone, szPhoto, szDescription, szUNID)
{ 
	var menuName = QP_ContextMenu_fixName(szDN);
	var elem;

	elem = document.getElementById(menuName + "_photo");
	if (elem)
		 elem.src = getMemberPhotoLink(szCN, szDN, szDisplayName, szEmail, szPhoto, szUNID);
	elem = document.getElementById(menuName + "_email");
	if (elem)
		 elem.innerHTML = szEmail;
	elem = document.getElementById(menuName + "_desc");
	if (elem)
		 elem.innerHTML = szDescription;
	elem = document.getElementById(menuName + "_phone");
	if (elem)
		 elem.innerHTML = szPhone;
}

// ----------------------------------------------------------

function QP_PersonMenu_write()
{ 
	var html = "";

	// Create the span that surrounds the entire menu
	var menu = document.createElement("span");
	menu.id = (this.name + "_Menu");
	menu.style.visibility="hidden";
	menu.style.position="absolute";

	// Create unordered list
	html += '<div class="personMenu">';

	html += this.makeBizCard();

	html += '<div class="personMenuActions">';

	html += '<ul id="' + this.name + '_Top"';
	for (var i = 0; i < this.items.length; i++)
	{
		if (this.items[i].type == this.LINK) {
			html += this.makeItem(this.items[i].label, this.items[i].action);
		}
		else if (this.items[i].type == this.SEPARATOR) {
			 html += this.makeSeparator();
		}
	}
	html += '</ul>';
	html += '</div>';
	html += '</div>';

	menu.innerHTML = html;
	document.body.appendChild(menu);

	if (document.all) {
		// Do for IE only:
		this.sfHover();
	}
}




// ----------------------------------------------------------

function QP_ContextMenu_write()
{ 
	var html = "";

	// Create the span that surrounds the entire menu
	var menu = document.createElement("div");
	menu.id = (this.name + "_Menu");
 	menu.className = "h-wcfMenuContainer";
	if (this.extraClass)
		 menu.className += (" " + this.extraClass);
	menu.style.visibility="hidden";
	menu.style.position="absolute";

	html += ''
 		+ '<table cellpadding="0" cellspacing="0">'
 		+ '<tbody>'
 		+ '<tr>'
 		+ '<td class="wcfMenuBorder" rowspan="2" colspan="2">'
 		+ '<table class="wcfMenu" cellpadding="0" cellspacing="0">'
		+ '<tbody>';

	for (var i = 0; i < this.items.length; i++)
	{
		if (this.items[i].type == this.LINK) {
			var action = this.items[i].action;

			if (action == "") {
				// Item is inactive - show as greyed out
				html += '<tr class="wcfMenuItemDisabled">';
				action = 'javascript:void(0);';
			}
			else {
				html += '<tr class="wcfMenuItem"';
				html += ' onmouseover="javascript:QP_ContextMenu_hideSubmenus(this, \'' + this.name + '\');"';
				html += '>';
			}

			html += '<td class="first" title="' + this.items[i].title + '">';
			if (this.items[i].icon) {				
				html += '<img src="' + this.items[i].icon + '" alt="' + this.items[i].title + '">';
			}
			else {
				html += '<img src="/qphtml/html/common/clear_pixel.gif">';
			}
			html += '</td>';
			  
			html += '<td>';
			html += '<a id="' + this.name + '_' + QP_ContextMenu_fixName(this.items[i].label) + '" ';
			html += 'title="' + this.items[i].title_disabled + '" tabindex="0" href="' + action + '">';
			html += this.items[i].label + '</a>';
			html += '</td>';
			  
			html += '<td class="last">&nbsp;</td></tr>';
		}
		else if (this.items[i].type == this.LINK_SUBMENU) {
			// Menu item pointing to a submenu
			var action = this.items[i].action;

			if (action == "") {
				// Item is inactive - show as greyed out
				html += '<tr class="wcfMenuItemDisabled h-context-submenu">';
				action = 'javascript:void(0);';
			}
			else {
				html += '<tr class="wcfMenuItem h-context-submenu"';
				html += ' onmouseover="javascript:QP_ContextMenu_hideSubmenus(this, \'' + this.name + '\');';
				html += 'QP_ContextMenu_showSubmenu(this, \'' + this.items[i].submenu + '\');"';
				html += '>';
			}

			html += '<td class="first" title="' + this.items[i].title + '">';
			if (this.items[i].icon) {
				html += '<img src="' + this.items[i].icon + '" alt="' + this.items[i].title + '">';
			}
			else {
				html += '<img src="/qphtml/html/common/clear_pixel.gif">';
			}
			html += '</td>';
			  
			html += '<td>';
			html += '<a id="' + this.name + '_' + QP_ContextMenu_fixName(this.items[i].label) + '" ';
			html += 'title="' + this.items[i].title_disabled + '" tabindex="0" href="' + action + '">';
			html += this.items[i].label + '</a>';
			html += '</td>';
			  
			html += '<td class="last">&nbsp;</td></tr>';
		}
		else if (this.items[i].type == this.SEPARATOR) {
			html += '<tr class="wcfMenuItemSeparator">';
			html += '<td class="first">';
			html += '<img src="/qphtml/html/common/clear_pixel.gif">';
			html += '</td>';
			html += '<td colspan="2" class="last">';
			html += '<hr class="portlet-separator">';
			html += '</td></tr><tr class="wcfMenuItem">';
		}
	}

	html += ''
 		+ '</tbody>'
 		+ '</table>'
 		+ '</td><td class="b-tr"></td>'
 		+ '</tr>'
 		+ '<tr><td class="b-r"><img src="/qphtml/html/common/clear_pixel.gif"></td></tr>'
 		+ '<tr><td class="b-bl"></td><td class="b-b"><img src="/qphtml/html/common/clear_pixel.gif"></td><td class="b-br"></td></tr>'
 		+ '</tbody>'
		+ '</table>';

	menu.innerHTML = html;
	document.body.appendChild(menu);

	if (document.all) {
		// Do for IE only:
		this.sfHover();
	}
}


function QP_ContextMenu_sfHover()
{
	QP_ContextMenu_fixIEhover(this.name);
}

function QP_ContextMenu_fixIEhover(name)
{
	var sfEls = document.getElementById(name + "_Menu").getElementsByTagName("li");
	for (var i=0; i<sfEls.length; i++) {
		sfEls[i].onmouseover=function() {
			this.className+=" sfhover";
		}
		sfEls[i].onmouseout=function() {
			this.className=this.className.replace(new RegExp(" sfhover\\b"), "");
		}
	}
}


// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// DISPLAY FUNCTIONS
//
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

// Active menu and item w/in menu
var g_activeMenu = null;
var g_activeItem = null;

// Active menu "stack"
var g_activeIdx = -1;
var g_visibleMenu = new Array();

// Offsets for precise positioning of submenus.
// May need adjusting if changes made in CSS
var hOffsetAdjust = 4;
var vOffsetAdjust = 6;

// Return absolute position of an elem as [x,y]
function findPos(elem)
{
	var x = y = 0;
	if (elem.offsetParent) {
		x = elem.offsetLeft
		y = elem.offsetTop
		while (elem = elem.offsetParent) {
			x += elem.offsetLeft
			y += elem.offsetTop
		}
	}
	return [x,y];
}

// Show a submenu beside the current active menu item
function QP_ContextMenu_showSubmenu(item, menu)
{
	var pos = findPos(item);
	g_activeItem = item;
	g_pageX = pos[0] + item.offsetWidth - hOffsetAdjust;
	g_pageY = (pos[1] - vOffsetAdjust);
	QP_ContextMenu_show(menu, false);
}

// Show a menu (any type)
function QP_ContextMenu_show(menu, bHidePrev)
{
	var bHide = (bHidePrev==undefined ? true : bHidePrev);
	if (bHide)
		 QP_ContextMenu_hide();

	g_activeMenu = document.getElementById(menu + "_Menu");
	if (g_activeMenu) {
		// Store the menu id on the "stack"
		g_visibleMenu[++g_activeIdx] = g_activeMenu;

		// adjust the X/Y position so that the entire Menu will show
		var mWidth = g_activeMenu.offsetWidth;
		var mHeight = g_activeMenu.offsetHeight;
		if (document.all) {
			// IE
			if (document.body.clientHeight < (5 + g_pageY + document.body.scrollTop + mHeight))
				 g_activeMenu.style.pixelTop = (document.body.clientHeight - mHeight - 2);
			else
				 g_activeMenu.style.pixelTop =  (5 + g_pageY + document.body.scrollTop);
		}
		else {
			if (document.body.clientHeight < (5 + g_pageY + document.body.scrollTop + mHeight))
				g_activeMenu.style.top = (document.body.clientHeight - mHeight - 2) + "px";
			else
				g_activeMenu.style.top =  (5 + g_pageY + document.body.scrollTop) + "px";
		}
		if (document.body.clientWidth < (5 + g_pageX + document.body.scrollLeft + mWidth))
			g_activeMenu.style.left = (document.body.clientWidth - mWidth - 2) + "px";
		else
			g_activeMenu.style.left = (5 + g_pageX + document.body.scrollLeft) + "px";
			 
		g_activeMenu.style.zIndex = 1000 + g_activeIdx;
		g_activeMenu.style.visibility="visible";
	}

	// Cause the current menu to disappear when click outside of it
	dojo.event.connect(document.body, "onmouseup", "onBodyClick");
}

function onBodyClick(e)
{
	var elem = (e.target) ? e.target : e.srcElement;
	if (elem.className.indexOf("-context") < 0)
		 QP_ContextMenu_hide();
}

// Hide the active menu
function QP_ContextMenu_hide()
{
	while (g_activeIdx >= 0) {
		g_visibleMenu[g_activeIdx--].style.visibility="hidden";
	}
}

// Hide all submenus below the active menu
function QP_ContextMenu_hideSubmenus(item,menu)
{
	thisMenu = document.getElementById(menu + "_Menu");
	while (g_activeIdx >= 0 && g_visibleMenu[g_activeIdx] != thisMenu) {
		g_visibleMenu[g_activeIdx--].style.visibility="hidden";
	}
}


// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// MAIN "ONLOAD" FUNCTION TO ATTACH EVENT HANDLERS TO ELEMENTS ON PAGE THAT CAN HAVE A CONTEXT MENU.
// CALL THIS ONLY AFTER PAGE IS LOADED.
//
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

function QP_ContextMenu_attachMenus()
{
	if (UIContextMenusAreEnabled())
	{
		var bDocuments = UIContextMenuIsEnabled("documents");
		var bFolders = UIContextMenuIsEnabled("folders");
		var bMyPlaces = UIContextMenuIsEnabled("my_places");
		var bUserNames = UIContextMenuIsEnabled("user_names");

		try {
			// Attach handlers to all elements on page that require one
			var sl = document.getElementsByTagName("span");

			for (var i=0; i < sl.length; i++)
			{
				var span = sl[i];
				if ((bDocuments && span.className == "h-doc-anchor")
					|| (bFolders && span.className == "h-folder-anchor")) 
				{
					var aTags = span.getElementsByTagName("a");
					if (aTags[0]) {
						makeDocContextMenu(span.className, aTags[0].id, aTags[0].href);
						dojo.event.connect(span, "onmouseover", "onDocMouseOver");
						dojo.event.connect(span, "onmouseout", "onDocMouseOut");
					}
				}
				else if (bUserNames && span.className == "h-user-anchor") 
				{
					var aTags = span.getElementsByTagName("a");
					if (aTags[0]) {
						// span's title attribute is DN
						makeUserContextMenu(aTags[0].innerHTML, span.title, aTags[0].href);
 						dojo.event.connect(span, "onmouseover", "onPersonMouseOver");
 						dojo.event.connect(span, "onmouseout", "onPersonMouseOut");
					}
				}
				else if (bMyPlaces && span.className == "h-my-places-anchor") 
				{
					var aTags = span.getElementsByTagName("a");
					if (aTags[0]) {
						makeMyPlacesContextMenu(aTags[0].innerHTML, aTags[0].href, span);
						dojo.event.connect(span, "onmouseover", "onMyPlacesMouseOver");
						dojo.event.connect(span, "onmouseout", "onMyPlacesMouseOut");
					}
				}
			}
		}
		catch(e) {
			// Dojo not installed? Degrade to no menus
		}
	}
} // QP_ContextMenu_attachMenus()


// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// EVENT HANDLERS FOR ACTION BUTTONS
//
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

var newQPObjMenu;

function onNewQPObjMouseOver(e)
{
	QP_ContextMenu_mouseTracker(e);

	var elem = (e.target) ? e.target : e.srcElement;
	var img = (elem.nodeName.toUpperCase() == "A") ? elem.nextSibling : elem;

	if (img) {
		// this is the context menu icon
		img.setAttribute("src", "/qphtml/html/common/menu_s.gif");

		// Create (if necessary) and show the New... menu
		newQPObjMenu = new QP_ContextMenu("NewQPObj", "h-newQPObj-menu");
		if (!newQPObjMenu.exists) {
			 createNewQPObjMenu(createQPObjMenuItem);
			 newQPObjMenu.write();
		}
		QP_ContextMenu_show("NewQPObj");
	}
//	e.preventDefault();
}

function onNewQPObjMouseOut(e)
{
	var elem = (e.target) ? e.target : e.srcElement;
	var img = (elem.nodeName.toUpperCase() == "A") ? elem.nextSibling : elem;

	if (img) {
		img.setAttribute("src", "/qphtml/html/common/menu_u.gif");
	}
	 return;
//	e.preventDefault();
}

function createQPObjMenuItem(formUnid, title, description, docType, importField, publishedFormId)
{
	var imgSrc = "/qphtml/html/common/clear_pixel.gif";
	var imgTag = GetDocTypeIconImgTag(docType, formUnid, ((docType == '1'/*D_QPTypeFolder*/)? '1'/*D_FolderStyleStandardList*/ : ''));
	var x = imgTag.indexOf('src="');
	var y = imgTag.indexOf('"', x+6);
	if (x>0 && y>0)
		 imgSrc = imgTag.substring(x+5,y);

	newQPObjMenu.addItem(title, "javascript:editNewQPObject('" + formUnid + "');", "_self", description, imgSrc);
}


// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// EVENT HANDLERS FOR DOCUMENT & FOLDER CONTEXT MENUS
//
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

function onDocMouseOver(e)
{
	var elem = (e.target) ? e.target : e.srcElement;
	var img = (elem.nodeName.toUpperCase() == "A") ? elem.nextSibling : elem;

	if (img) {
		// this is the context menu icon
		img.setAttribute("src", "/qphtml/html/common/menu_s.gif");
		dojo.event.connect(img, "onmouseup", "onDocContextMenu");
	}
	e.preventDefault();
//	e.stopPropagation();
}

function onDocMouseOut(e)
{
	var elem = (e.target) ? e.target : e.srcElement;
	var img = (elem.nodeName.toUpperCase() == "A") ? elem.nextSibling : elem;

	if (img) {
		// this is the context menu icon
		img.setAttribute("src", "/qphtml/html/common/menu_u.gif");
	}
	e.preventDefault();
//	e.stopPropagation();
}

function onDocContextMenu(e)
{
	QP_ContextMenu_mouseTracker(e);

	var img = (e.target) ? e.target : e.srcElement;
	var a = img.previousSibling;

	if (a) {
		// this is the doc name anchor
		showDocContextMenu(a, a.id);
	}
	e.preventDefault();
//	e.stopPropagation();
}

//---------------------------------------------------------------------------------------------------------
// FIX ME:
// - Don't make the AJAX request if menu already populated!
//
function showDocContextMenu(elem, unid)
{ 
 	ajax = new QPAjax();
 	ajax.RequestXML((elem.href + "&Form=h_DocXml&nowebcaching"),
						 (elem.parentNode.className=="h-folder-anchor"?populateFolderContextMenu:populateDocContextMenu));
	
	// Show the (minimal) menu while waiting for data
	QP_ContextMenu_show(unid);
}


// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// EVENT HANDLERS FOR USER NAME CONTEXT MENUS
//
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

function onPersonMouseOver(e)
{
	var elem = (e.target) ? e.target : e.srcElement;
	var img = (elem.nodeName.toUpperCase() == "A") ? elem.nextSibling : elem;

	if (img) {
		// this is the context menu icon
		img.setAttribute("src", "/qphtml/html/common/menu_dropdown.gif");
		dojo.event.connect(img, "onclick"/*"onmouseup"*/, "onPersonContextMenu");
	}
	e.preventDefault();
//	e.stopPropagation();
}

function onPersonMouseOut(e)
{
	var elem = (e.target) ? e.target : e.srcElement;
	var img = (elem.nodeName.toUpperCase() == "A") ? elem.nextSibling : elem;

	if (img) {
		// this is the context menu icon
		img.setAttribute("src", "/qphtml/html/common/clear_pixel.gif");
	}
	e.preventDefault();
//	e.stopPropagation();
}

function onPersonContextMenu(e)
{
	QP_ContextMenu_mouseTracker(e);

	var img = (e.target) ? e.target : e.srcElement;
	var a = img.previousSibling;

	if (a) {
		// this is the user name anchor
		QP_PersonMenu_show(a.href, a.parentNode.title);
	}
	e.preventDefault();
//	e.stopPropagation();
}

//---------------------------------------------------------------------------------------------------------
// FIX ME:
// - Don't make the AJAX request if menu already populated!
//
function QP_PersonMenu_show(href, name)
{
 	ajax = new QPAjax();
	ajax.RequestXML((href + "&Form=h_MemberXml&nowebcaching"), populateUserContextMenu);
	
	// Show the (minimal) menu while waiting for data
	QP_ContextMenu_show(QP_ContextMenu_fixName(name));
}


// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// EVENT HANDLERS FOR MY PLACES CONTEXT MENUS
//
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

function onMyPlacesContextMenu(e)
{
	QP_ContextMenu_mouseTracker(e);

	var img = (e.target) ? e.target : e.srcElement;
	var a = img.previousSibling;

	if (a) {
		QP_ContextMenu_show(a.innerHTML + "_MyPlaces");
	}
	e.preventDefault();
//	e.stopPropagation();
}

function onMyPlacesMouseOver(e)
{
	var elem = (e.target) ? e.target : e.srcElement;
	var img = (elem.nodeName.toUpperCase() == "A") ? elem.nextSibling : elem;

	if (img) {
		// this is the context menu icon
		img.setAttribute("src", "/qphtml/html/common/menu_s.gif");
		dojo.event.connect(img, "onmouseup", "onMyPlacesContextMenu");
	}
	e.preventDefault();
//	e.stopPropagation();
}

function onMyPlacesMouseOut(e)
{
	var elem = (e.target) ? e.target : e.srcElement;
	var img = (elem.nodeName.toUpperCase() == "A") ? elem.nextSibling : elem;

	if (img) {
		// this is the context menu icon
		img.setAttribute("src", "/qphtml/html/common/menu_u.gif");
	}
	e.preventDefault();
//	e.stopPropagation();
}


// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// USER NAME CONTEXT MENU ANCHORS
//
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

// Generate the <span> containing a user name anchor (<a> tag) and whatever else is needed
// to associate a context menu with that element.
//
// FIX ME:
// - handle names without a profile (e.g., doc authors with -Default- access) - don't show icon?
//
function makeUserNameAnchor(szDN, szCN, szCNPostfixHTML)
{ 
	var memPostfix = szCNPostfixHTML || ''; // Default: no text - e.g., "(Group)" - after name

	return '<span class="h-user-anchor" title="' + szDN + '">'
		+ '<a href="' + getMemberInfoLink(szDN) + '">'
		+ szCN + memPostfix
		+ '</a>'
		+ '<img class="h-contextMenu-icon" src="/qphtml/html/common/clear_pixel.gif" align="absmiddle"/>'
		+ '</span>';
}


// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// DOCUMENT & FOLDER CONTEXT MENU ANCHORS
//
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

// Duplication of preprocessor #defines, so we can have this code here and not in template
// for now - should probably move back to template (h_ContextMenus.h) eventually.
var D_QPTypeFolder = "1";
var LABEL_YES = "Yes";

// Generate the anchor (<a>) tag for a document, folder, etc.
function GenerateQPObjURLAnchorTag(folderName, qpObjUnid, urlPointer, urlNewWindow, szDocType)
{ 
	var objUrl = GenerateQPObjURLString (folderName, qpObjUnid, urlPointer);

	var aTag = '<a';
	aTag += ' id="' + qpObjUnid + '"'; // NB! Assumes this will never appear twice on the same page!
	aTag += ' href="' + objUrl + '"';

	if (urlNewWindow == LABEL_YES) {
		aTag += ' target="_blank"';
	}
	aTag += '>';

	return (aTag);
}

// Generate the <span> containing a document or folder anchor and whatever else is needed
// to associate a context menu with that element.
function GenerateQPObjURLAnchor(type, aTag, aInner)
{ 
	var span = '<span class=' + (type==D_QPTypeFolder?"h-folder-anchor":"h-doc-anchor") + '>';

	// Add the <a> tag and its inner HTML
	span += (aTag + aInner + '</a>');
	span += '<img class="h-contextMenu-icon" title="Click for options." alt="Click for options." src="/qphtml/html/common/menu_u.gif" align="absmiddle" />';
	span += '</span>';

	return (span);
}


// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// XML PARSING FOR DATA USED TO POPULATE MENUS
//
// FIX ME: 
// - This stuff belongs in a generic XML Parser class!
// - Assumes a "flat" XML structure.
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

// Parse XML containing document-related data.
function getTagValue(xmlDoc, docTag, tag)
{
	try
	{
		//Open the XML Document
		var root = xmlDoc;
		var docs = root.getElementsByTagName(docTag);
		var docTags = docs[0].getElementsByTagName(tag);

		if (docTags.length >= 1) {
			 var val = getNodeValue(docTags[0]);
			 return val;
		}
		else {
			 return "";
		}
	}
	catch (e)
	{
		return "";
	}
}

function getNodeValue (node) {
	if (typeof node.textContent != 'undefined')
	{
		return node.textContent;
	}
	else if (typeof node.innerText != 'undefined')
	{
		return node.innerText;
	}
	else if (typeof node.text != 'undefined')
	{
		return node.text;
	}
	else
	{
		switch (node.nodeType)
		{
			case 3:
			case 4:
				return node.nodeValue;
				break;
			case 1:
			case 11:
				var innerText = '';
				for (var i = 0; i < node.childNodes.length; i++)
				{
					innerText += getNodeValue(node.childNodes[i]);
				}
				return innerText;
				break;
			default:
				return '';
		}
	}
}
