/*
 *+------------------------------------------------------------------------+
 *| IBM Confidential
 *| OCO Source Materials
 *| BI and PM: viewer
 *| (C) Copyright IBM Corp. 2001, 2009
 *|
 *| US Government Users Restricted Rights - Use, duplication or
 *| disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
 *|
 *+------------------------------------------------------------------------+
 */

//
// This class represents the basic representation of a selection object.
//

/*
  Constructor.

  Parameters:

  Returns:
*/
function CSelectionObject()
{
	this.initialize();
}

CSelectionObject.prototype.initialize = function()
{
	this.m_oCellRef = {};
	this.m_sColumnRef = "";
	this.m_sColumnName = "";
	this.m_aDataItems = [];
	this.m_aUseValues = [];
	this.m_aDisplayValues = [];
	this.m_sCellTypeId = "";
	this.m_sLayoutType = "";
	this.m_sTag = "";
	this.m_aMuns = [];
	this.m_aRefQueries = [];
	this.m_aMetadataItems = [];
	this.m_aDrillOptions = [];
	this.m_selectionController = {};
	this.m_contextIds = [];
	this.m_fetchedContextIds = false;
	this.m_selectedClass =  [];
	this.m_cutClass=[];
};

/*
  Parameters: none

  Returns: object reference to html <td> element
*/
CSelectionObject.prototype.getCellRef = function()
{
	return this.m_oCellRef;
};

/*
  Parameters: none

  Returns: string
*/
CSelectionObject.prototype.getColumnRef = function()
{
	return this.m_sColumnRef;
};

/*
  Parameters: none

  Returns: string
*/
CSelectionObject.prototype.getColumnName = function()
{
	if (this.m_sColumnName == "")
	{
		if (this.m_selectionController.hasContextData() && this.m_contextIds.length)
		{
			this.m_sColumnName = this.m_selectionController.getRefDataItem(this.m_contextIds[0][0]);
		}
	}
	return this.m_sColumnName;
};

/*
  Parameters: none

  Returns: array of strings
*/
CSelectionObject.prototype.getDataItems = function()
{
	if (!this.m_aDataItems.length) {
		this.fetchContextIds();
		for (var i = 0; i < this.m_contextIds.length; ++i) {
			this.m_aDataItems[this.m_aDataItems.length] = [];
			for (var j = 0; j < this.m_contextIds[i].length; ++j) {
				var contextId = this.m_contextIds[i][j];
				this.m_aDataItems[this.m_aDataItems.length-1].push(this.m_selectionController.isContextId(contextId)? this.m_selectionController.getRefDataItem(contextId) : "");
			}
		}
	}
	return this.m_aDataItems;
};

/*
  Parameters: none

  Returns: array of strings
*/
CSelectionObject.prototype.getUseValues = function()
{
	if (!this.m_aUseValues.length) {
		this.fetchContextIds();
		for (var i = 0; i < this.m_contextIds.length; ++i) {
			this.m_aUseValues[this.m_aUseValues.length] = [];
			for (var j = 0; j < this.m_contextIds[i].length; ++j) {
				var contextId = this.m_contextIds[i][j];
				this.m_aUseValues[this.m_aUseValues.length-1].push(this.m_selectionController.isContextId(contextId) ? this.m_selectionController.getUseValue(contextId) : "");
			}
		}
	}
	return this.m_aUseValues;
};

/*
  Parameters: none

  Returns: string
*/
CSelectionObject.prototype.getCellTypeId = function()
{
	return this.m_sCellTypeId;
};

/*
  Parameters: none

  Returns: array of strings
*/
CSelectionObject.prototype.getDisplayValues = function()
{
	return this.m_aDisplayValues;
};

/*
  Parameters: none

  Returns: string
*/
CSelectionObject.prototype.getLayoutType = function()
{
	return this.m_sLayoutType;
};

/*
  Parameters: none

  Returns: string
*/
CSelectionObject.prototype.getTag = function()
{
	return this.m_sTag;
};

/*
  Parameters: none

  Returns: Array
*/
CSelectionObject.prototype.getMuns = function()
{
	if (!this.m_aMuns.length) {
		this.fetchContextIds();
		for (var i = 0; i < this.m_contextIds.length; ++i) {
			this.m_aMuns[this.m_aMuns.length] = [];
			for (var j = 0; j < this.m_contextIds[i].length; ++j) {
				var contextId = this.m_contextIds[i][j];
				this.m_aMuns[this.m_aMuns.length-1].push(this.m_selectionController.isContextId(contextId) ? this.m_selectionController.getMun(contextId) : "");
			}
		}
	}
	return this.m_aMuns;
};

/*
  Parameters: none

  Returns: Array
*/
CSelectionObject.prototype.getRefQueries = function()
{
	if (!this.m_aRefQueries.length) {
		this.fetchContextIds();
		for (var i = 0; i < this.m_contextIds.length; ++i) {
			this.m_aRefQueries[this.m_aRefQueries.length] = [];
			for (var j = 0; j < this.m_contextIds[i].length; ++j) {
				var contextId = this.m_contextIds[i][j];
				this.m_aRefQueries[this.m_aRefQueries.length-1].push(this.m_selectionController.isContextId(contextId) ? this.m_selectionController.getRefQuery(contextId) : "");
			}
		}
	}
	return this.m_aRefQueries;
};

CSelectionObject.prototype.getDimensionalItems = function(sType)
{
	var aItems = new Array();
	this.fetchContextIds();
	for (var i = 0; i < this.m_contextIds.length; ++i) {
		aItems[aItems.length] = [];
		for (var j = 0; j < this.m_contextIds[i].length; ++j) {
			var contextId = this.m_contextIds[i][j];

			if(this.m_selectionController.isContextId(contextId))
			{
				var sItem = "";

				switch(sType)
				{
					case "hun":
					{
						sItem = this.m_selectionController.getHun(contextId);
						break;
					}
					case "lun":
					{
						sItem = this.m_selectionController.getLun(contextId);
						break;
					}
					case "dun":
					{
						sItem = this.m_selectionController.getDun(contextId);
						break;
					}
				}
			}

			aItems[aItems.length-1].push(sItem);
		}
	}

	return aItems;
};

/*
  Parameters: none

  Returns: Array
*/
CSelectionObject.prototype.getMetadataItems = function()
{
	if (!this.m_aMetadataItems.length) {
		this.fetchContextIds();
		for (var i = 0; i < this.m_contextIds.length; ++i) {
			this.m_aMetadataItems[this.m_aMetadataItems.length] = [];
			for (var j = 0; j < this.m_contextIds[i].length; ++j) {
				var contextId = this.m_contextIds[i][j];
				var sMetaDataItem="";
				if(this.m_selectionController.isContextId(contextId))
				{
					var sLun = this.m_selectionController.getLun(contextId);
					var sHun = this.m_selectionController.getHun(contextId);

					if(sLun && sLun != "")
					{
						sMetaDataItem  = sLun;
					}
					else if(sHun && sHun != "")
					{
						sMetaDataItem  = sHun;
					}
					else
					{
					 	sMetaDataItem = this.m_selectionController.getQueryModelId(contextId);
					}

				}

				this.m_aMetadataItems[this.m_aMetadataItems.length-1].push(sMetaDataItem);
			}
		}
	}
	return this.m_aMetadataItems;
};

/*
  Parameters: none

  Returns: Array
*/
CSelectionObject.prototype.getDrillOptions = function()
{
	if (!this.m_aDrillOptions.length) {
		this.fetchContextIds();
		for (var i = 0; i < this.m_contextIds.length; ++i) {
			this.m_aDrillOptions[this.m_aDrillOptions.length] = [];
			for (var j = 0; j < this.m_contextIds[i].length; ++j) {
				var contextId = this.m_contextIds[i][j];
				this.m_aDrillOptions[this.m_aDrillOptions.length-1].push(this.m_selectionController.isContextId(contextId) ? this.m_selectionController.getDrillFlag(contextId) : 0);
			}
		}
	}
	return this.m_aDrillOptions;
};

/*
  Parameters: none

  Returns: array
*/
CSelectionObject.prototype.getSelectedContextIds = function()
{
	return this.m_contextIds;
};


CSelectionObject.prototype.fetchContextIds = function()
{
	if (!this.m_fetchedContextIds && this.m_contextIds.length && this.m_selectionController.hasContextData())
	{
		var fetchContextIds = [];
		for (var i = 0; i < this.m_contextIds.length; i++) {
			for (var j = 0; j < this.m_contextIds[i].length; j++) {
				fetchContextIds.push(this.m_contextIds[i][j]);
			}
		}
		this.m_selectionController.fetchContextData(fetchContextIds);
		this.m_fetchedContextIds = true;
	}
};

CSelectionObject.prototype.setSelectionController = function(sc) {
	if (sc) {
		this.m_selectionController = sc;
	}
};

CSelectionObject.prototype.getLayoutElementId = function() {
	return this.m_layoutElementId;
};

CSelectionObject.prototype.hasContextInformation = function() {
	for (var i=0; i < this.m_contextIds.length; i++)
	{
		for (var j=0; j < this.m_contextIds[i].length; j++)
		{
			if (this.m_contextIds[i][j].length > 0)
			{
				return true;
			}
		}
	}

	return false;
};


//
// This class represents the basic representation of a chart selection object.
//

/*
  Constructor.

  Parameters:

  Returns:
*/


// set up the base class
CSelectionChartObject.prototype = new CSelectionObject();
CSelectionChartObject.prototype.constructor = CSelectionChartObject;
CSelectionChartObject.baseclass = CSelectionObject.prototype;

function CSelectionChartObject()
{
	// initialize the base class
	CSelectionChartObject.baseclass.initialize.call(this);
};


//
// This class creates a factory for selection objects.
//

/*
  Constructor.

  Parameters:

  Returns: selection object factory
*/
function CSelectionObjectFactory(selectionController)
{
	this.m_selectionController = selectionController;
}

CSelectionObjectFactory.prototype.getSelectionController = function()
{
	return this.m_selectionController;
};

/*
  Parameters:
  cellRef - an HTML reference to a <td> element

  Returns: selection object
*/
CSelectionObjectFactory.prototype.getSelectionObject = function(cellRef, matchOnCTX)
{
	var newSelObj = new CSelectionObject();

	newSelObj.setSelectionController(this.getSelectionController());
	newSelObj.m_oCellRef = cellRef;
	newSelObj.m_sColumnRef = cellRef.getAttribute("cid");
	newSelObj.m_sCellTypeId = cellRef.getAttribute("uid");
	newSelObj.m_sLayoutType = cellRef.getAttribute("type");
	newSelObj.m_sTag = cellRef.getAttribute("tag");
	newSelObj.m_layoutElementId = this.getLayoutElementId(cellRef);

	//Query Studio specific code
	if (typeof cf != "undefined")
	{
		var miniQueryObj = cf.cfgGet("MiniQueryObj");
		if(miniQueryObj)
		{
			var tagElement = miniQueryObj.findChildWithAttribute("tag", newSelObj.m_sTag);
			if(tagElement && tagElement.getAttribute("id") != null)
			{
				newSelObj.m_sColumnName = tagElement.getAttribute("id");
			}
		}
	}

	//get all of the child textItem nodes
	var allChildren = cellRef.getElementsByTagName("span");
	if (allChildren.length > 0)
	{
		for (var i = 0; i < allChildren.length; i++)
		{
			var oChild = allChildren[i];
			if (oChild.nodeType == 1 && oChild.nodeName.toLowerCase() == "span" && oChild.style.visibility != "hidden")
			{
				var contextNode = null;
				if (cellRef.getAttribute("ctx") != null && cellRef.getAttribute("ctx") != "") {
					contextNode = cellRef;
				}
				else if(oChild.getAttribute("ctx") != null && oChild.getAttribute("ctx") != "") {
					contextNode = oChild;
				}
				else if(oChild.getAttribute("dtTargets") && oChild.childNodes && oChild.childNodes.length) {
					for (var idxCN = 0; idxCN < oChild.childNodes.length; idxCN++)
					{
						if (oChild.childNodes[idxCN].nodeType == 1) {
							contextNode = oChild.childNodes[idxCN];
						}
					}
				}

				newSelObj.m_aDisplayValues[newSelObj.m_aDisplayValues.length] = oChild.innerHTML;

				var context = "";
				if(contextNode && contextNode.getAttribute("ctx"))
				{
					 context = contextNode.getAttribute("ctx");
				}

				// Check to see if we're explicity matching on a ctx id. If we are and we don't match, move on to the next node
				if(typeof matchOnCTX != "undefined" && matchOnCTX != context) {
					continue;
				}

				newSelObj = this.processCTX(newSelObj, context);
			}
		}
	}
	else if(cellRef.getAttribute("ctx") != null && cellRef.getAttribute("ctx") != "" && newSelObj.m_sLayoutType == "datavalue")
	{
		newSelObj = this.processCTX(newSelObj, cellRef.getAttribute("ctx"));
	}

	return newSelObj;
};

/*
  Parameters:
  selObj - a CSelectionObject object
  context - the ctx attribute from the span or td

  Returns: selection object
*/
CSelectionObjectFactory.prototype.processCTX = function(selObj, context)
{
	if (typeof context != "string" || context.length == 0)
	{
		return selObj;
	}

	// A:B::C:D::E   becomes   [[A,B],[C,D],[E]]
	if (typeof selObj.m_contextIds == "object" && selObj.m_contextIds !== null && selObj.m_contextIds.length > 0)
	{
		var tempContextIds = context.split("::");
		for(var ctx = 0; ctx < selObj.m_contextIds.length; ++ctx)
		{
			try
			{
				if (tempContextIds[ctx])
				{
					selObj.m_contextIds[ctx] = selObj.m_contextIds[ctx].concat(tempContextIds[ctx].split(":"));
				}
			}
			catch (e)
			{
			}
		}
	}
	else
	{
		selObj.m_contextIds = context.split("::");
		for(var ctx = 0; ctx < selObj.m_contextIds.length; ++ctx)
		{
			selObj.m_contextIds[ctx] = selObj.m_contextIds[ctx].split(":");
		}
	}

	return selObj;
}

/*
  Parameters:
  tag - a reference to the column

  Returns: selection object
*/
CSelectionObjectFactory.prototype.getSecondarySelectionObject = function(tag, layoutType, theDocument)
{
	if (!theDocument) {
		theDocument = document;
	}
	var newSelObj = new CSelectionObject();
	newSelObj.setSelectionController(this.getSelectionController());

	// Non-default initialization
	newSelObj.m_oCellRef = null;
	newSelObj.m_sColumnRef = null;
	newSelObj.m_sCellTypeId = null;
	newSelObj.refQuery = "";

	var allTds = theDocument.getElementsByTagName("td");

	// Figure out from the secondary selection what needs to be selected
	for (var i = 0; i < allTds.length; i++)
	{
		var colTag = allTds[i].getAttribute("tag");
		if (colTag != null && colTag != "")
		{
			if (tag == colTag)
			{
				var colClass = allTds[i].className;
				if (colClass != null && colTag != "")
				{
					if ((layoutType == "columnTitle" && colClass == "lt") || (layoutType == "datavalue" && colClass == "lc"))
					{
						newSelObj.m_sColumnRef = allTds[i].getAttribute("cid");
						newSelObj.m_sCellTypeId  = allTds[i].getAttribute("uid");
						break;
					}
				}
			}
		}
	}

	if (newSelObj.m_sCellTypeId == null) {
		return null;
	}
	return newSelObj;
};

CSelectionObjectFactory.prototype.getSelectionChartObject = function(chartNode)
{
	var contextIds = chartNode.getAttribute("ctx");

	if(contextIds == null) {
		return null;
	}

	var newSelObj = new CSelectionChartObject();
	newSelObj.setSelectionController(this.getSelectionController());

	newSelObj.m_contextIds = contextIds.split("::");
	for(var ctx = 0; ctx < newSelObj.m_contextIds.length; ++ctx)
	{
		newSelObj.m_contextIds[ctx] = newSelObj.m_contextIds[ctx].split(":");
	}

	newSelObj.m_layoutElementId = this.getLayoutElementId(chartNode);
	return newSelObj;
};


//get the unique ID for the layout object.
CSelectionObjectFactory.prototype.getLayoutElementId = function(el) {
	var id = "";
	if (el) {
		id = el.LID || "";
		if (!id) {
			var parentNode = el.parentNode;
			if (parentNode) {
				id = this.getLayoutElementId(parentNode);
			}
		}
	}
	return  id;
};




//
// This class creates a controller for all of the selection objects.
//

/*
  Constructor.

  Parameters:

  Returns: selection controller
*/
function CSelectionController(sNamespace, oCognosViewer)
{
	this.m_bSelectionBasedFeaturesEnabled = false;
	this.m_bDrillUpDownEnabled = false;
	this.m_bModelDrillThroughEnabled = false;
	this.m_oCognosViewer = null;
	if (oCognosViewer) {
		this.m_oCognosViewer = oCognosViewer;
	}

	this.initialize(sNamespace);
}

CSelectionController.prototype.initialize = function(sNamespace)
{
	this.m_sNamespace = sNamespace;
	this.m_aCutColumns = new Array();
	this.m_aSelectedObjects = new Array();
	this.m_selectedClass = new Array();
	this.m_cutClass = new Array();
	this.m_oObserver = new CObserver(this);

	this.m_bSelectionArraysSetup = false;
	this.m_aSelectionHoverNodes = [];

	//deprecated
	this.m_bUsingCCDManager = false;	//This bool can go when we switch to JSON format exclusively
	this.m_aReportMetadataArray = [];
	this.m_aReportContextDataArray = [];

	//JSON
	this.m_oCDManager = new CCDManager();

	this.m_oSelectionObjectFactory = new CSelectionObjectFactory(this);

	this.m_selectedChartArea = null;

	if(this.m_oCognosViewer != null)
	{
		this.m_oCDManager.SetCognosViewer(this.m_oCognosViewer);
	}

	this.m_disableSecondarySelection = false;
	this.m_maxSecondarySelection = -1;
};

CSelectionController.prototype.getCCDManager = function()
{
	return this.m_oCDManager;
};

CSelectionController.prototype.getCtxIdFromDisplayValue = function(sDisplayValue)
{
	if (!this.m_bUsingCCDManager) {
		var contextDataArray = this.getReportContextDataArray();
		var CD_DISPLAY_VALUE_IDX = 1;
		for (var sCtxId in contextDataArray)
		{
			var contextItem = contextDataArray[sCtxId];
			if(contextItem[CD_DISPLAY_VALUE_IDX] == sDisplayValue)
				return sCtxId;
		}

		return "";
	} else {
		var sCtxId = this.m_oCDManager.GetContextIdForDisplayValue(sDisplayValue);
		return (sCtxId == null) ? "" : sCtxId;
	}
};

CSelectionController.prototype.getCtxIdFromMetaData = function(sLun, sHun)
{
	return this.m_oCDManager.getContextIdForMetaData(sLun, sHun);
};

CSelectionController.prototype.getCtxIdFromMun = function(sMun)
{
	if (!this.m_bUsingCCDManager) {
		var metaDataArray = this.getReportMetadataArray();
		var MD_USE_VALUE_IDX = 0;
		for(var sKey in metaDataArray)
		{
			var metaDataItem = metaDataArray[sKey];
			if(metaDataItem[MD_USE_VALUE_IDX] == sMun)
			{
				var CD_METADATA_KEY_IDX = 2;
				var contextDataArray = this.getReportContextDataArray();
				for(var sCtxId in contextDataArray)
				{
					var contextItem = contextDataArray[sCtxId];
					if(contextItem[CD_METADATA_KEY_IDX] == sKey)
						return sCtxId;
				}
			}
		}

		return "";
	} else {
		var sCtxId = this.m_oCDManager.GetContextIdForMUN(sMun);
		return (sCtxId == null) ? "" : sCtxId;
	}
};

CSelectionController.prototype.canDrillDown = function(sCtxId)
{
	var drillFlag = this.getDrillFlagForMember(sCtxId);
	return (drillFlag == 3 || drillFlag == 2);
};

CSelectionController.prototype.canDrillUp = function(sCtxId)
{
	var drillFlag = this.getDrillFlagForMember(sCtxId);
	return (drillFlag == 3 || drillFlag == 1);
};


CSelectionController.prototype.getQueryModelId = function(sCtxId)
{
	var qmid = "";
	if (!this.m_bUsingCCDManager) {
		var contextObj = this.m_aReportContextDataArray[sCtxId];
		if(contextObj && typeof contextObj[3] != "undefined"){
			var queryModelItemRefId = contextObj[3];
			var contextQueryModelItem = this.m_aReportMetadataArray[queryModelItemRefId];
			if(typeof contextQueryModelItem != "undefined" && typeof contextQueryModelItem[1] != "undefined" && contextQueryModelItem[1] == "I")
			{
				qmid = contextQueryModelItem[0];
			}
		}

	} else {
		qmid = this.m_oCDManager.GetQMID(sCtxId);
	}
	return qmid;
};

CSelectionController.prototype.getRefQuery = function(sCtxId)
{
	if (!this.m_bUsingCCDManager) {
		return this.getMetaDataItemUseValue(4/*ref query item reference*/, sCtxId);
	} else {
		var sRefQuery = this.m_oCDManager.GetQuery(sCtxId);
		return (sRefQuery == null) ? "" : sRefQuery;
	}
};

CSelectionController.prototype.getRefDataItem = function(sCtxId)
{
	if (!this.m_bUsingCCDManager) {
		return this.getMetaDataItemUseValue(0/*ref data item reference key*/, sCtxId);
	} else {
		var sRefDataItem = this.m_oCDManager.GetRDIValue(sCtxId);
		return (sRefDataItem == null) ? "" : sRefDataItem
	}
};

CSelectionController.prototype.getMun = function(sCtxId)
{
	if (!this.m_bUsingCCDManager) {
		return this.getMetaDataItemUseValue(2/*Mun reference key*/, sCtxId);
	} else {
		var sMun = this.m_oCDManager.GetMUN(sCtxId);
		return (sMun == null) ? "" : sMun;
	}
};

CSelectionController.prototype.getHun = function(sCtxId)
{
	if (!this.m_bUsingCCDManager) {
		var sHun = null;
		var aData = this.getRDI(sCtxId);

		if (aData && aData.length > 4 && aData[1] == "R") {
			var sRefDataItem = aData[4];
			var aReportMetadataArray = this.getReportMetadataArray();
			aData = aReportMetadataArray[sRefDataItem];
		}

		if (aData && aData.length > 1 && aData[1] == "H")
		{
			sHun = aData[0];
		}

		return sHun;
	} else {
		return this.m_oCDManager.GetHUN(sCtxId);
	}
};

CSelectionController.prototype.fetchContextData = function(fetchContextIds)
{
	if (this.m_bUsingCCDManager) {
		this.m_oCDManager.FetchContextData(fetchContextIds);
	}

};

//////////////////
// These can go once we have moved to JSON objects
CSelectionController.prototype.getMetaDataItem = function(sKey)
{
	var metaDataArray = this.getReportMetadataArray();
	if(typeof metaDataArray[sKey] != "undefined")
	{
		return metaDataArray[sKey];
	}

	return null;
};

CSelectionController.prototype.getContextDataItem = function(sCtxId)
{
	var contextDataArray = this.getReportContextDataArray();
	if(typeof contextDataArray[sCtxId] != "undefined")
	{
		return contextDataArray[sCtxId];
	}

	return null;
};

CSelectionController.prototype.getMetaDataItemUseValue = function(iKeyIndex, sCtxId)
{
	/**
	 * 0 == ref data item
	 * 2 == mun
	 * 3 == level or qmid
	 * 4 == query
	 */
	var contextItem = this.getContextDataItem(sCtxId);
	if(contextItem != null)
	{
		var metaDataQueryKey = contextItem[iKeyIndex];
		if(metaDataQueryKey != "")
		{
			var metaDataItem = this.getMetaDataItem(metaDataQueryKey);
			if(metaDataItem != null)
			{
				return metaDataItem[0/*use value index*/];
			}
		}
	}

	return "";
};

CSelectionController.prototype.getRDI = function(sCtxId) {
	var contextItem = this.getContextDataItem(sCtxId);
	if(contextItem != null)
	{
		var metaDataQueryKey = contextItem[0];
		if(metaDataQueryKey != "")
		{
			var metaDataItem = this.getMetaDataItem(metaDataQueryKey);
			if(metaDataItem != null)
			{
				return metaDataItem;
			}
		}
	}
};




/////////////////////

CSelectionController.prototype.getNamespace = function()
{
	return this.m_sNamespace;
};

CSelectionController.prototype.setSelectionBasedFeaturesEnabled = function(bValue)
{
	this.m_bSelectionBasedFeaturesEnabled = bValue;
};

CSelectionController.prototype.getSelectionBasedFeaturesEnabled = function()
{
	return this.m_bSelectionBasedFeaturesEnabled;
};

CSelectionController.prototype.setDrillUpDownEnabled = function(bValue)
{
	this.m_bDrillUpDownEnabled = bValue;
};

CSelectionController.prototype.getDrillUpDownEnabled = function()
{
	return this.m_bDrillUpDownEnabled;
};

CSelectionController.prototype.setModelDrillThroughEnabled = function(bValue)
{
	this.m_bModelDrillThroughEnabled = bValue;
};

CSelectionController.prototype.getModelDrillThroughEnabled = function()
{
	return this.m_bModelDrillThroughEnabled;
};

/*
  Parameters:

  Returns: boolean
*/
CSelectionController.prototype.clearSelectedObjects = function(theDocument)
{
	try
	{
		if (!theDocument) {
			theDocument = document;
		}
		this.updateUI(theDocument, this.getSelections(), true, false);
		this.m_aSelectedObjects = new Array();
		if (typeof this.onSelectionChange == "function")
		{
			this.onSelectionChange();
		}
		return true;
	}
	catch (e)
	{
		return false;
	}
};

/*
  Parameters:

  Returns: boolean
*/
CSelectionController.prototype.resetSelections = function(theDocument)
{
	try
	{
		if (!theDocument) {
			theDocument = document;
		}
		this.updateUI(theDocument, this.getSelections(), true, false);
		this.updateUI(theDocument, this.getCutColumns(), true, false);
		this.m_aCutColumns = new Array();
		this.m_aSelectedObjects = new Array();
		this.m_selectedClass = new Array();
		this.m_cutClass = new Array();

		if (typeof this.onSelectionChange == "function")
		{
			this.onSelectionChange();
		}
		return true;
	}
	catch (e)
	{
		return false;
	}
};

/*
  Parameters:

  Returns: boolean
*/
CSelectionController.prototype.addSelectionObject = function(CSelectionObject, theDocument)
{
	try
	{
		if (!theDocument) {
			theDocument = document;
		}
		//test to see if this object is already selected
		var theCell = CSelectionObject.getCellRef();
		if (this.isCellSelected(theCell) !== true || (typeof theCell != "object" || theCell === null))
		{
			//test to see if this object is currently cut
/* TODO: Put this back in once Report Server starts to produce context data
			if (this.isColumnCut(CSelectionObject.getColumnName()) !== true)
			{
				this.m_aSelectedObjects[this.m_aSelectedObjects.length] = CSelectionObject;
				if (typeof this.onSelectionChange == "function")
					this.onSelectionChange();
				this.updateUI(theDocument, this.getSelections(), false, false);
			}
   /TODO */


/* TODO: Take this out once Report Server starts to produce context data */
			if (this.isColumnCut(CSelectionObject.getTag()) !== true)
			{
				this.m_aSelectedObjects[this.m_aSelectedObjects.length] = CSelectionObject;
				if (typeof this.onSelectionChange == "function")
				{
					this.onSelectionChange();
				}
				this.updateUI(theDocument, this.getSelections(), false, false);
			}
/* /TODO */
		}
		return true;
	}
	catch (e)
	{
		return false;
	}
};

/*
  Parameters:

  Returns: boolean
*/
CSelectionController.prototype.removeSelectionObject = function(CSelectionObject, theDocument)
{
	try
	{

		if (!theDocument) {
			theDocument = document;
		}
		var removed = new Array();
		var idxSelObjects;
		for (idxSelObjects = 0; idxSelObjects < this.m_aSelectedObjects.length; idxSelObjects++)
		{
			var selObjCellRef = this.m_aSelectedObjects[idxSelObjects].getCellRef();
			var cselObjCellRef = CSelectionObject.getCellRef();
			if (typeof selObjCellRef == "object" && typeof cselObjCellRef == "object" && selObjCellRef !== null && cselObjCellRef !== null)
			{
				if (selObjCellRef == cselObjCellRef)
				{
					removed[removed.length] = idxSelObjects;
				}
			}
		}


		if (removed.length > 0)
		{
			this.updateUI(theDocument, this.getSelections(), true, false);
			var newArr = new Array();
			for (idxSelObjects = 0; idxSelObjects < this.m_aSelectedObjects.length; idxSelObjects++)
			{
				var addToNewArr = true;
				for (var j = 0; j < removed.length; j++)
				{
					if (idxSelObjects == removed[j])
					{
						addToNewArr = false;
					}
				}
				if (addToNewArr)
				{
					newArr[newArr.length] = this.m_aSelectedObjects[idxSelObjects];
				}
			}
			this.m_aSelectedObjects = newArr;
			this.updateUI(theDocument, this.getSelections(), false, false);
		}
		if (typeof this.onSelectionChange == "function")
		{
			this.onSelectionChange();
		}
		return true;
	}
	catch (e)
	{
		return false;
	}
};

/*
  Parameters:

  Returns: boolean
*/


CSelectionController.prototype.isCellSelected = function(cellNode)
{
	try
	{
		for (var i = 0; i < this.m_aSelectedObjects.length; i++)
		{
			var selObjCellRef = this.m_aSelectedObjects[i].getCellRef();
			if (typeof selObjCellRef == "object" && selObjCellRef !== null)
			{
				if (selObjCellRef == cellNode)
				{
					return true;
				}
			}
		}
	}
	catch (e)
	{
	}
	return false;
};

/*
  Parameters:

  Returns: boolean
*/
CSelectionController.prototype.isColumnSelected = function(columnName)
{
	try
	{
		for (var i = 0; i < this.m_aSelectedObjects.length; i++)
		{
/* TODO: Put this back in once Report Server starts to produce context data
			if (this.m_aSelectedObjects[i].getColumnName() == columnName)
			{
				return true;
			}
   /TODO */


/* TODO: Take this out once Report Server starts to produce context data */
			if (this.m_aSelectedObjects[i].getTag() == columnName)
			{
				return true;
			}
/* /TODO */
		}
	}
	catch (e)
	{
	}
	return false;
};

/*
  Parameters:

  Returns: boolean
*/
CSelectionController.prototype.isColumnCut = function(columnName)
{
	try
	{
		for (var i = 0; i < this.m_aCutColumns.length; i++)
		{
/* TODO: Put this back in once Report Server starts to produce context data
			if (this.m_aCutColumns[i].getColumnName() == columnName)
			{
				return true;
			}
   /TODO */


/* TODO: Take this out once Report Server starts to produce context data */
			if (this.m_aCutColumns[i].getTag() == columnName)
			{
				return true;
			}
/* /TODO */
		}
	}
	catch (e)
	{
	}
	return false;
};

/*
  Parameters:

  Returns: array of selected objects
*/
CSelectionController.prototype.getSelections = function()
{
	return this.m_aSelectedObjects;
};

/*
  Parameters:

  Returns: array of selected objects
*/
CSelectionController.prototype.hasCutColumns = function()
{
	if (this.m_aCutColumns.length === 0)
	{
		return false;
	}
	else
	{
		return true;
	}
};

/*
  Parameters:

  Returns: boolean
*/
CSelectionController.prototype.setCutColumns = function(cutValue, theDocument)
{
	try
	{

		if (!theDocument) {
			theDocument = document;
		}
		this.updateUI(theDocument, this.getSelections(), true, false);
		this.updateUI(theDocument, this.getCutColumns(), true, 1);
		this.m_aCutColumns = new Array();
		//sets all currently selected columns to cutValue
		if (cutValue === true)
		{
			for (var i = 0; i < this.m_aSelectedObjects.length; i++)
			{
				this.m_aCutColumns[i] = this.m_aSelectedObjects[i];
			}
			this.m_aSelectedObjects = new Array();
		}
		this.updateUI(theDocument, this.getCutColumns(), false, 2);
		/* I don't know yet if we want to observe the cutting of columns, leave it out for now.
		if (typeof this.onSelectionChange == "function")
		{
			this.onSelectionChange();
		}
		*/

		return true;
	}
	catch (e)
	{
		return false;
	}
};

/*
  Parameters:

  Returns: array of cut columns
*/
CSelectionController.prototype.getCutColumns = function()
{
	return this.m_aCutColumns;
};

/*
  Parameters:

  Returns: reference to observer function
*/
CSelectionController.prototype.getObservers = function()
{
	return this.m_oObserver;
};

/*
  Parameters:

  Returns: void
*/
CSelectionController.prototype.attachObserver = function(observer)
{
	this.m_oObserver.attach(observer);
};

/*
  This is called when a selection changes

  Parameters:

  Returns: void
*/
CSelectionController.prototype.onSelectionChange = function()
{
	this.getObservers().notify();
};

/*
  Parameters:

  Returns: array of columns to draw
*/
CSelectionController.prototype.getSelectedColumns = function(allSelections)
{
	var columnsToDraw = new Array();
	if (typeof allSelections == "undefined")
	{
		allSelections = this.getSelections();
	}
	var allSelectionsLength = allSelections.length;
	for (var i = 0; i < allSelectionsLength; i++)
	{
		var currentSelection = allSelections[i];
		var addNewEntry = true;
		for (var j = 0; j < columnsToDraw.length; j++)
		{
			if (columnsToDraw[j][0] == currentSelection.getColumnRef() && columnsToDraw[j][1] == currentSelection.getCellTypeId())
			{
				addNewEntry = false;
				break;
			}
		}
		if (addNewEntry)
		{
			columnsToDraw[columnsToDraw.length] = new Array(currentSelection.getColumnRef(), currentSelection.getCellTypeId(), currentSelection.getLayoutType(), currentSelection.getTag(), currentSelection.getColumnName());
		}
	}
	return columnsToDraw;
};

CSelectionController.prototype.getAllSelectedObjects = function()
{
	var selectedItems = [];
	var chartArea = this.getSelectedChartArea();
	if(chartArea != null) {
		var selectedChartNode = this.getSelectionObjectFactory().getSelectionChartObject(chartArea);
		if (selectedChartNode != null)
		{
			selectedItems.push(selectedChartNode);
		}
	} else {
		selectedItems = this.getSelections();
	}

	return selectedItems;
};
/*
  Parameters:

  Returns: array of column ids
*/
CSelectionController.prototype.getSelectedColumnIds = function(aAllSelections)
{
	var aColumnIds = new Array();
	if (typeof aAllSelections == "undefined")
	{
		aAllSelections = this.getSelections();
	}
	var aSelectedColumns = this.getSelectedColumns(aAllSelections);
	for (var idxSelCols = 0; idxSelCols < aSelectedColumns.length; idxSelCols++)
	{
		var addNewEntry = true;
		for (var idxColIds = 0; idxColIds < aColumnIds.length; idxColIds++)
		{
			if (aColumnIds[idxColIds] == aSelectedColumns[idxSelCols][4])
			{
				addNewEntry = false;
				break;
			}
		}
		if (addNewEntry)
		{
			aColumnIds[aColumnIds.length] = aSelectedColumns[idxSelCols][4];
		}
	}
	return aColumnIds;
};


var STYLE_SELECTION = {};

CSelectionController.prototype.selecting = function(c,style)
{

	var sText = "." + c + style;
	var doc = document;
	var oIFrame = document.getElementById('CVIFrame' + this.m_sNamespace)
	if (oIFrame)
	{
		doc = oIFrame.contentWindow.document;
	}

	var nStyle = doc.createElement('style');
	nStyle.setAttribute("type", "text/css");
	if (nStyle.styleSheet)
	{
		// IE
		nStyle.styleSheet.cssText = sText;
	}
	else
	{
		// Mozilla & Firefox
		nStyle.appendChild( doc.createTextNode(sText) );
	}

	doc.getElementsByTagName("head").item(0).appendChild(nStyle);

	STYLE_SELECTION[ c ] = nStyle;
};

CSelectionController.prototype.deselecting = function(anArray)
{
	for(var i = 0; i < anArray.length; ++i)
	{
		if ( STYLE_SELECTION[ anArray[i] ])
		{
			var node = STYLE_SELECTION[ anArray[i] ];
			node.parentNode.removeChild( node );
			STYLE_SELECTION[ anArray[i] ] = null;
		}
	}

	if (document.all && typeof this.m_oCognosViewer.m_viewerFragment != "undefined")
	{
		// force IE to repaint the div
		var reportDiv = document.getElementById("CVReport" + this.m_oCognosViewer.getId());
		if(reportDiv != null)
		{
			var display = reportDiv.style.display;
			reportDiv.style.display = "none";
			reportDiv.style.display = display;
		}
	}
};

CSelectionController.prototype.showViewerContextMenu = function()
{
	if (this.getSelectedChartArea() != null)
	{
		return true;
	}

	if (this.m_aSelectedObjects && this.m_aSelectedObjects.length > 0)
	{
		return true;
	}

	return false;
}


function getStyleFromClass(c)
{
	for (var i = 0; i < document.styleSheets.length; i++)
	{
		var ss = document.styleSheets[i];
		var _rules = (ss.cssRules ? ss.cssRules : ss.rules);

		for (var j = 0; j < _rules.length; j++)
		{
			var cr = _rules[j];
			var reClass = new RegExp('\\b' + c + '\\b', 'g');

			if (cr.selectorText && cr.selectorText.match(reClass))
			{
				return cr;
			}
		}
	}

	return 0;
}

/*
  Parameters:

  Returns: boolean
*/

CSelectionController.prototype.updateUI = function(theDocument, allSelections, deselectAll, isCut)
{
	if (!theDocument) {
		theDocument = document;
	}
	try
	{
		if (allSelections.length > 0)
		{
			if (isCut == 1 || isCut == 2)
			{
				if (deselectAll)
				{
					this.deselecting(this.m_cutClass);
				}
				else
				{
					var cS_color = getStyleFromClass("cutSelection").style.color;
					var cS_backgroundColor = getStyleFromClass("cutSelection").style.backgroundColor;
					var allSelectionsLength = allSelections.length;
					for (var idxAllSelections = 0; idxAllSelections < allSelectionsLength; idxAllSelections++)
					{
						var selectedTD = allSelections[idxAllSelections].getCellRef();
					}
					var selectedClass = "cutQS" + selectedTD.getAttribute("cid");
					this.selecting(selectedClass,"\n{ background-color: "+cS_backgroundColor+"; color: "+cS_color+";}\n");
					this.m_cutClass.push(selectedClass);
				}
			}
			else
			{
				if(this.m_oCognosViewer)
				{
					if (deselectAll)
					{
						var allSelectionsLength = allSelections.length;

						for (var idxAllSelections = 0; idxAllSelections < allSelectionsLength; idxAllSelections++)
						{
							var selectedTD = allSelections[idxAllSelections].getCellRef();
							this.restoreOldBackgroundImage(selectedTD);
						}
						this.deselecting(this.m_selectedClass);
					}
					else
					{
						var sS_backgroundImageURL = this.getBackgroundImage(getStyleFromClass("secondarySelection"))
						var pS_backgroundImageURL = this.getBackgroundImage(getStyleFromClass("primarySelection"))
						var selectedTD="";
						var allSelectionsLength = allSelections.length;
						for (var idxAllSelections = 0; idxAllSelections < allSelectionsLength; idxAllSelections++)
						{
							selectedTD = allSelections[idxAllSelections].getCellRef();
						}

						// if we have an oldClassName it means we were showing our hover class, reset it to the original
						// class before doing the select
						if (selectedTD.getAttribute("oldClassName") != null)
						{
							selectedTD.className = selectedTD.getAttribute("oldClassName");
							selectedTD.removeAttribute("oldClassName");
						}

						this.saveOldBackgroundImage(selectedTD);
						selectedTD.style.backgroundImage = pS_backgroundImageURL;

						var secondarySelectionThresholdExceeded = false;
						if (this.m_disableSecondarySelection === false)
						{
							if(this.m_maxSecondarySelection != -1)
							{
								var secondarySelectedItems = theDocument.getElementsByName(selectedTD.getAttribute("name"));
								if(secondarySelectedItems.length > this.m_maxSecondarySelection)
								{
									secondarySelectionThresholdExceeded = true;
								}
							}
						}

						if(this.m_disableSecondarySelection === false && secondarySelectionThresholdExceeded === false)
						{
							var selectedClass = selectedTD.getAttribute("name");

							var selectedClassLength = this.m_selectedClass.length;
							if(selectedClassLength !=0)
							{
								for(var i = 0 ; i < selectedClassLength ; i++)
								{
									if(this.m_selectedClass[i]==selectedClass)
									{
										break;
									}
									if(i==(this.m_selectedClass.length -1))
									{
										this.selecting(selectedClass,"{ background-image: " + sS_backgroundImageURL + ";}");
										this.m_selectedClass.push(selectedClass);
									}
								}
							}
							else
							{
								this.selecting(selectedClass,"{ background-image: " + sS_backgroundImageURL + ";}");
								this.m_selectedClass.push(selectedClass);
							}
						}
					}
				}
			}
		}

		return true;
	}
	catch (e)
	{
		//alert("error selecting column -- please contact your administrator!");
		return false;
	}
};

CSelectionController.prototype.setSelectedChartArea = function(chartArea)
{
	this.m_selectedChartArea = chartArea;
	if (chartArea !== null)
	{
		// make sure the item we are selecting is a rsvp chart image
		if (chartArea.tagName == "IMG")
		{
			var isRSVPChart = chartArea.getAttribute("rsvpChart");
			if (isRSVPChart != "true")
			{
				this.m_selectedChartArea = null;
				return;
			}
		}
		this.getObservers().notify();
	}
};

CSelectionController.prototype.getSelectedChartArea = function()
{
	return this.m_selectedChartArea;
};

CSelectionController.prototype.getSelectedChartImage = function()
{
	var selectedChartArea = this.getSelectedChartArea();
	if (selectedChartArea === null)
	{
		return null;
	}

	if (selectedChartArea.tagName == "IMG")
	{
		return selectedChartArea;
	}

	var imageMap = selectedChartArea.parentNode;
	var imageMapName = "#" + imageMap.getAttribute("name");
	var imageMapSiblings = imageMap.parentNode.firstChild;
	while (imageMapSiblings !== null)
	{
		if (imageMapSiblings.tagName == "IMG" && imageMapSiblings.getAttribute("usemap") == imageMapName)
		{
			return imageMapSiblings;
		}
		imageMapSiblings = imageMapSiblings.nextSibling;
	}

	return null;
};

CSelectionController.prototype.downloadSelectedChartImage = function(sCVID)
{
	var chartImage = this.getSelectedChartImage();
	if (chartImage !== null)
	{
		var theDocument = this.getDocumentFromImage(chartImage);
		var theURL = 'b_action=xts.run&m=portal/download.xts&m_obj=';

		var imageURL = chartImage.name.replace(".", "_");
		var imageName = imageURL.substr(5);
		if (document.all) {
			imageURL = theDocument.parentWindow.eval("graphicSrc" + imageName);
		}
		else {
			imageURL = theDocument.defaultView.eval("graphicSrc" + imageName);
		}

		if (typeof imageURL != 'undefined' && imageURL !== null)
		{
			var urlArray = imageURL.split('&');
			if (urlArray.length === 0)
			{
				return;
			}

			for (var i = 0; i < urlArray.length; ++i)
			{
				var urlParam = urlArray[i];
				var equalPos = urlParam.indexOf('=');
				if (equalPos != -1) {
					var urlParamName = urlParam.substr(0,equalPos);
					var urlParamValue = urlParam.slice(equalPos+1);

					if (urlParamName == 'search')
					{
						theURL += urlParamValue;
						break;
					}
				}
			}

			theURL += '&m_name=';
			theURL += imageName;
			theURL += '&format=png';

			if (typeof getConfigFrame == "function")
			{
				theURL = '?' + getConfigFrame().constructGETRequestParamsString(theURL);
				window.open(theURL, "_blank", "width=0,height=0");
			}
			else
			{
				theURL = constructGETRequestParamsString(theURL);
				var formWarpRequest = document.forms["formWarpRequest" + sCVID];
				theURL = formWarpRequest.action + '?' + theURL;
				location.href = theURL;
			}
		}
	}
};

CSelectionController.prototype.getDocumentFromImage = function(image) {
	var imageDocument = null;
	if (document.all) {
		imageDocument = image.document;
	}
	else {
		imageDocument = image.ownerDocument;
	}
	return imageDocument;
};

CSelectionController.prototype.pageClicked = function(e)
{
	this.setSelectedChartArea(null);
	if ((e.keyCode != null) && (e.keyCode != 13) && (e.keyCode != 27) && (e.keyCode != 0))
	{
		return false;
	}

	var node = getNodeFromEvent(e);
	var nodeDocument = getDocumentFromEvent(e);

	if (!this.hasContextData() || !this.hasMetadata())
	{
		// Update anyway- necessary for updating context menu for authored drill
		// when there is no selection when context data is absent

		if(node.nodeName == 'AREA' || node.nodeName == 'IMG')
		{
			this.setSelectedChartArea(node);
		}
		this.getObservers().notify();
		return false;
	}


	if(typeof node.selectedCell != "undefined")
	{
		var divRegion = node;
		node = node.selectedCell;
		divRegion.removeAttribute("selectedCell");
	}

	if (typeof cf != "undefined" && typeof cf.hidePickers == "function")
	{
		cf.hidePickers();
	}

	if (e.keyCode == 27)
	{
		if (typeof g_reportSelectionController != "undefined")
		{
			g_reportSelectionController.clearSelections();
		}

		this.resetSelections(nodeDocument);
	}
	else if(node.nodeName == 'AREA' || node.nodeName == 'IMG')
	{
		this.setSelectedChartArea(node);
	}
	//Do not select a blank crosstab corner cell
	else if (!(node.firstChild == null && node.cellIndex == 0 && node.parentNode.rowIndex == 0 && node.getAttribute("cid") == null))
	{
		this.selectNode(node, e);
	}


	if (typeof g_firefoxPluginHelper != "undefined" && g_firefoxPluginHelper != null)
	{
		g_firefoxPluginHelper.addContextInfo(this);
	}
};

CSelectionController.prototype.getSelectionObjectFactory = function()
{
	return this.m_oSelectionObjectFactory;
};

CSelectionController.prototype.isDrillLinkOnCrosstabCell = function(node)
{
	return (node.getAttribute("ctx") == null && node.parentNode.getAttribute("dtTargets") != null);
};

CSelectionController.prototype.selectNode = function(node, e)
{
	while (node.nodeType == 3) { // test to see if this is a text node
		node = node.parentNode;
	}

	// crosstab cell check on a drill link. RSVP does not output ctx values on a crosstab cell, so we need to have special handling for drill link on a xtab cell.
	if(this.isDrillLinkOnCrosstabCell(node))
	{
		node = node.parentNode;
	}

	var nodeDocument = null;
	if (document.all) {
		nodeDocument = node.document;
	}
	else {
		nodeDocument = node.ownerDocument;
	}

	var ctx = node.getAttribute("ctx");
	var uid = node.getAttribute("uid");

	var callRefresh = false;
	if (typeof e == "undefined") {
		e = {};
	}
	var reportElementNode = false;
	if (typeof g_reportSelectionController != "undefined")
	{
		reportElementNode = this.checkForReportElementNode(node);
	}
	if ((ctx == null && uid == null && node.parentNode.nodeType == 1 && node.parentNode.getAttribute("uid") == null && reportElementNode == false) || (e.ctrlKey == false && e.shiftKey == false)) //if didn't use ctrl or shift click, deselect the other selections
	{
		if (this.getSelections().length > 0) {
			callRefresh = true;
		}
		if (this.hasCutColumns() == true) {
			this.clearSelectedObjects(nodeDocument);
		}
		else
		{
			this.resetSelections(nodeDocument);

			//TODO this needs to be removed
			//This will remove all selection objects from the list of selected columns in Query Studio
			if (typeof cf != "undefined" && typeof cf.removeAllSelectionsFromCfgVariables == "function") {
				cf.removeAllSelectionsFromCfgVariables();
			}
		}
		if (e.ctrlKey == true || e.shiftKey == true) {
			clearTextSelection(nodeDocument);
		}
		if (typeof g_reportSelectionController != "undefined" && reportElementNode == false)
		{
			if (g_reportSelectionController.getSelections().length > 0) {
				callRefresh = true;
			}
			g_reportSelectionController.clearSelections();
		}
	}

	if ((uid == null) && ((ctx != null) || (node.parentNode && node.parentNode.nodeType == 1 && typeof node.parentNode.getAttribute != "undefined" && node.parentNode.getAttribute("uid") != null)))  // this is a textitem or chart img
	{
		//Test to see if we're clicking on a chart in a sectioned report
		if (node.nodeName == "IMG" && (node.src.indexOf("SM=") > -1 || (navigator.appVersion.indexOf("MSIE") > -1 && node.src.indexOf("space.gif") > -1))) {
			return false;
		}
		node = node.parentNode;

		// special case for Bug#498910. Analysis Studio is adding a members attributes within the same td, broken up by divs.
		// If the parent node is a DIV and the class is "BLOCK", move up one level higher in the DOM
		if((node.className.toUpperCase() == "BLOCK" && node.nodeName.toUpperCase() == "DIV") || (node.getAttribute("dtTargets") != null))
		{
			node = node.parentNode;
		}

		uid = node.getAttribute("uid");
	}

	if (uid != null)  // this is a valid column element
	{
		var nodeChildren = node.childNodes;
		for (var i = 0; i < nodeChildren.length; i++)
		{
			if (nodeChildren[i].nodeName.toUpperCase() == "TABLE" && (nodeChildren[i].className == "ls" || nodeChildren[i].className=="xt"))
			{
				//Note that we can't purely match on the "ls" or "xt" classes for a table because they could be user assigned in RS, we must dig further
				var trs = nodeChildren[i].rows;
				for (var j = 0; j < trs.length; j++)
				{
					var tds = trs[j].cells;
					for (var k = 0; k < tds.length; k++)
					{
						if (tds[k].getAttribute("uid") != null)
						{
							//We've found a nested list or crosstab, therefore we don't want to select the outer list cell
							return false;
						}
					}
				}
			}
		}
		var SelObj;
		if(node.className.toUpperCase() == "REPEATERTABLECELL" && ctx != null)
		{
			SelObj = this.getSelectionObjectFactory().getSelectionObject(node, ctx);
		}
		else
		{
			SelObj = this.getSelectionObjectFactory().getSelectionObject(node);
		}

		// Determine if this column is already selected (if so, unselect it if CTRL or SHIFT clicked)
		if (this.isCellSelected(node) == false)
		{ // If the cell is not selected, select it
			if (e.shiftKey == true)
			{
				var allSelections = this.getSelections();
				if (allSelections.length > 0)
				{
					var lastSelection = allSelections[allSelections.length - 1];

					//Make sure both selections have the same layout and they are in the same table
					if (lastSelection.getLayoutType() == SelObj.getLayoutType() && (lastSelection.getCellRef().parentNode.parentNode == SelObj.getCellRef().parentNode.parentNode))
					{
						//Check if we want to multi-select rows or columns
						if(this.cellsAreInSameColumn(lastSelection.getCellRef(), SelObj.getCellRef()))
						{
							this.selectVertical(lastSelection, SelObj, nodeDocument);
						}

						//Shift-selection on the same row
						else if(lastSelection.getCellRef().parentNode.rowIndex == SelObj.getCellRef().parentNode.rowIndex)
						{
							this.selectHorizontal(lastSelection, SelObj, nodeDocument);
						}
					}
				}
				clearTextSelection(nodeDocument);
			}
			else if (e.ctrlKey == true) {
				clearTextSelection(nodeDocument);
			}

			this.addSelectionObject(SelObj, nodeDocument);

			// This will add the selection object to the list of selected columns in Query Studio
			if (typeof cf != "undefined" && typeof cf.addSelectionToCfgVariables == "function") {
				cf.addSelectionToCfgVariables(SelObj.getColumnName());
			}
		}
		else
		{
			if (e.ctrlKey == true)
			{ // Otherwise the cell is selected, and this is a CTRL click, so unselect it
				this.removeSelectionObject(SelObj, nodeDocument);

				// This will remove the selection of the specified column if it's the only selection in that column in Query Studio
				if (typeof cf != "undefined" && typeof cf.removeSelectionFromCfgVariables == "function")
				{
/* TODO: Put this back in once Report Server starts to produce context data
					if (!this.isColumnSelected(SelObj.getColumnName()))
						cf.removeSelectionFromCfgVariables(SelObj.getTag());
   /TODO */


/* TODO: Take this out once Report Server starts to produce context data */
					if (!this.isColumnSelected(SelObj.getTag())) {
						cf.removeSelectionFromCfgVariables(SelObj.getTag());
					}
/* /TODO */
				}
				clearTextSelection(nodeDocument);
			}
			else if (e.shiftKey == true) {
				clearTextSelection(nodeDocument);
			}
		}
		callRefresh = true;
	}
	else if (reportElementNode)
	{
		var style = null;
		while ((typeof node.id == "undefined" || node.id == null || node.id == "") && node.parentNode != null) {
			node = node.parentNode;
		}

		if (node.id == "reportTitle") {
			style = 'TitleStyle';
		}
		else if (node.id == "reportSubtitle") {
			style = 'SubtitleStyle';
		}
		else if (node.id.indexOf("reportFilter") == 0) {
			style = 'FilterStyle';
		}

		if (style != null)
		{
			selectReportElement(e,node.id,style);
			callRefresh = true;
		}
	}
	//This will refresh the dialogs with a new list of selected columns in Query Studio
	if (callRefresh == true && (typeof cf != "undefined" && typeof cf.refreshDialog == "function")) {
		cf.refreshDialog();
	}

};

//Deprecated way
CSelectionController.prototype.getReportContextDataArray = function()
{
	return this.m_aReportContextDataArray;
};

CSelectionController.prototype.getReportMetadataArray = function()
{
	return this.m_aReportMetadataArray;
};

CSelectionController.prototype.setupContextDataArray = function(contextDataArray)
{
	this.m_aReportContextDataArray = contextDataArray;
};

CSelectionController.prototype.setupMetaDataArray = function(metaDataArray)
{
	this.m_aReportMetadataArray = metaDataArray;
};


//JSON Way
CSelectionController.prototype.addContextData = function(contextDataJSONSpec) {
	this.m_aSelectedObjects = new Array();


	this.m_oCDManager.SetContextData(contextDataJSONSpec);
	if (!this.m_bUsingCCDManager) {
		this.m_bUsingCCDManager = true;
	}
	for(var i = 0; i < this.m_selectedClass.length; ++i)
	{

		this.deselecting(this.m_selectedClass);

	}
};

CSelectionController.prototype.addMetaData = function(metaDataJSONSpec) {
	this.m_aSelectedObjects = new Array();
	this.m_oCDManager.SetMetadata(metaDataJSONSpec);
	if (!this.m_bUsingCCDManager) {
		this.m_bUsingCCDManager = true;
	}
};

// Y Valve Deprecated and Old ways
CSelectionController.prototype.getDrillFlag = function(contextId) {
	var drill = "";
	if (!this.m_bUsingCCDManager) {
		var contextObj = this.m_aReportContextDataArray[contextId];
		var dataItemRefId = contextObj[0];
		var contextDataItem = this.m_aReportMetadataArray[dataItemRefId];
		if(typeof contextDataItem != "undefined" && typeof contextDataItem[3] != "undefined")
		{
			drill = contextDataItem[3];
		}

	} else {
		drill = this.m_oCDManager.GetDrillFlag(contextId);
	}
	return drill;
};


CSelectionController.prototype.getDrillFlagForMember = function(sCtxId)
{
	var drillFlag = "0";
	if (!this.m_bUsingCCDManager) {
		var contextItem = this.getContextDataItem(sCtxId);
		if(contextItem != null)
		{
			// check to see that this is a "member"
			var metaDataRefMunKey = contextItem[2]; //Mun reference key
			if(metaDataRefMunKey != "")
			{
				var metaDataRefDataItemKey = contextItem[0]; //data item reference key
				var metaDataItem = this.getMetaDataItem(metaDataRefDataItemKey);
				if(metaDataItem != null)
				{
					drillFlag = metaDataItem[3];	//drill flag index
				}
			}
		}
	} else {
		drillFlag = this.m_oCDManager.GetDrillFlagForMember(sCtxId);
	}

	return (drillFlag == null) ? 0 : drillFlag;
};

CSelectionController.prototype.getDataType = function(contextId) {
	var dtype = null;
	if (!this.m_bUsingCCDManager) {
		var iType= null;
		var aData = this.getRDI(contextId);
		if (aData && aData.length > 2)
		{
			dtype = parseInt(aData[2],10);
		}
	} else {
		dtype = parseInt(this.m_oCDManager.GetDataType(contextId),10);
	}
	return dtype;
};

CSelectionController.prototype.getUsageInfo = function(contextId) {
	if (this.m_bUsingCCDManager) {
		return this.m_oCDManager.GetUsage(contextId);
	}
};

CSelectionController.prototype.getDepth = function(contextId) {
	var sLevel = null;
	if (!this.m_bUsingCCDManager) {
		var aData = this.getRDI(contextId);
		if (aData && aData.length > 5 && aData[1] == "R") {
			sLevel = aData[5];
		}
	} else {
		sLevel = this.m_oCDManager.GetDepth(contextId);
	}
	return sLevel;
};

CSelectionController.prototype.getUseValue = function(contextId)
{
	var value = "";
	if (!this.m_bUsingCCDManager) {
		var contextObj = this.m_aReportContextDataArray[contextId];
		if(typeof contextObj[1] != "undefined")
		{
			value = contextObj[1];
		}
	} else {
		value = this.m_oCDManager.GetDisplayValue(contextId);
	}
	return value;
};

CSelectionController.prototype.getDisplayValue = function(contextId) {
	var value = "";

	var aSpans;
	var oIFrame = document.getElementById('CVIFrame' + this.m_sNamespace);
	if (typeof oIFrame == 'undefined' || oIFrame == null)
	{
		aSpans = document.getElementsByTagName("span");
	}
	else
	{
		aSpans = oIFrame.contentWindow.document.getElementsByTagName("span");
	}


	// need to find the span that has a ctx attribute equal or starts with
	// the contextId passed in
	for (var iIndex=0; iIndex < aSpans.length; iIndex++)
	{
		var ctx = aSpans[iIndex].getAttribute("ctx");
		if (ctx != null && ctx != "")
		{
			if (ctx == contextId || ctx.indexOf(contextId + ':') == 0)
			{
				if(document.all)
				{
					value = aSpans[iIndex].innerText;
				}
				else
				{
					value = aSpans[iIndex].textContent;
				}

				// need to check if there are any other spans with the same ctx. RSVP sometimes
				// uses multiple spans when generting one label
				var sibling = aSpans[iIndex].nextSibling;
				while (sibling != null)
				{
					var siblingctx = sibling.getAttribute("ctx");
					if (siblingctx != null && siblingctx != "")
					{
						if (siblingctx == contextId || siblingctx.indexOf(contextId + ':') == 0)
						{
							if(document.all)
							{
								value += sibling.innerText;
							}
							else
							{
								value += sibling.textContent;
							}
						}
					}

					sibling = sibling.nextSibling;
				}

				break;
			}
		}
	}

	if (value == "")
	{
		value = this.getUseValue(contextId);
	}

	return value;
};

CSelectionController.prototype.getDun = function(contextId)
{
	if (this.m_bUsingCCDManager)
	{
		return this.m_oCDManager.GetDUN(contextId);
	}
	else
	{
		var contextObj = this.m_aReportContextDataArray[contextId];
		if(contextObj && typeof contextObj[5] != "undefined"){
			var dimensionRefId = contextObj[5];
			var contextDimension = this.m_aReportMetadataArray[dimensionRefId];
			if(typeof contextDimension != "undefined" && typeof contextDimension[1] != "undefined" && contextDimension[1] == "D")
			{
				return contextDimension[0];
			}
		}
	}
};

CSelectionController.prototype.getPun = function(contextId) {
	if (this.m_bUsingCCDManager) {
		return this.m_oCDManager.GetPUN(contextId);
	}
};

CSelectionController.prototype.getLun = function(contextId) {
	var lun = "";
	if (!this.m_bUsingCCDManager) {
		var contextObj = this.m_aReportContextDataArray[contextId];
		if(contextObj && typeof contextObj[3] != "undefined"){
			var queryModelItemRefId = contextObj[3];
			var contextQueryModelItem = this.m_aReportMetadataArray[queryModelItemRefId];
			if(typeof contextQueryModelItem != "undefined" && typeof contextQueryModelItem[1] != "undefined" && contextQueryModelItem[1] == "L")
			{
				lun = contextQueryModelItem[0];
			}
		}

	} else {
		lun = this.m_oCDManager.GetLUN(contextId);
	}
	return lun;
};

CSelectionController.prototype.isContextId = function(contextId) {
	var isContext = false;
	if (!this.m_bUsingCCDManager) {
		var contextObj = this.m_aReportContextDataArray[contextId];
		isContext = (typeof contextObj == "object");
	} else {
		this.m_oCDManager.FetchContextData(new Array(contextId));
		isContext = this.m_oCDManager.ContextIdExists(contextId);
	}
	return isContext;
};


CSelectionController.prototype.hasContextData = function() {
	var hasContextData =  false;
	if (!this.m_bUsingCCDManager) {
		for (var i in this.m_aReportContextDataArray) {
			return true;
		}
	} else {
		hasContextData = this.m_oCDManager.HasContextData();
	}
	return hasContextData;
};

CSelectionController.prototype.hasMetadata = function() {
	var hasMetadata =  false;
	if (!this.m_bUsingCCDManager) {
		for (var i in this.m_aReportMetadataArray) {
			return true;
		}
	} else {
		hasMetadata = this.m_oCDManager.HasMetadata();
	}
	return hasMetadata;
};


/***	Gets a new index value of a cell after all the groups/non-datavalues are added or removed (depends on indexType)	***/
CSelectionController.prototype.getDifferentCellIndex = function(cellRow, cellIndex, indexType)
{
	//Go through each cell in the current row
	for(var i = 0; i < cellRow.cells.length; i++)
	{
		//If we see a cell of type "datavalue", stop and return the new cellindex value
		if (this.getSelectionObjectFactory().getSelectionObject(cellRow.cells[i]).getLayoutType() == "datavalue")
		{
			break;
		}
	}
	if (indexType == "relative")
	{
		return (cellIndex - i);
	}
	else if(indexType == "actual")
	{
		return (cellIndex + i);
	}
};

/***	Checks if two given cells are in the same column	***/
CSelectionController.prototype.cellsAreInSameColumn = function(cellOneRef, cellTwoRef)
{
	//If both selections are on the same row, they are obviously not in the same column
	if (cellOneRef.parentNode.rowIndex == cellTwoRef.parentNode.rowIndex)
	{
		return false;
	}

	//If it's a crosstab...
	if (cellOneRef.getAttribute("cid") === null)
	{
		//Compare the UIDs
		if (cellOneRef.getAttribute("uid") === cellTwoRef.getAttribute("uid"))
		{
			//If the UIDs match and the selections are column titles, they are in the same column
			if (cellOneRef.getAttribute("type") != "datavalue") {
				return true;
			}
			//if they are datavalues, see if both belong to the same column
			else if(this.getDifferentCellIndex(cellOneRef.parentNode,cellOneRef.cellIndex, "relative") == this.getDifferentCellIndex(cellTwoRef.parentNode,cellTwoRef.cellIndex, "relative")) {
				return true;
			}
		}
		else
		{
			return false;
		}
	}

	//If it's a list and the headers of both selections are same, then they are in the same column
	else if (cellOneRef.getAttribute("cid") === cellTwoRef.getAttribute("cid"))
	{
		return true;
	}
	else
	{
		return false;
	}
};

/***	Selects all the required cells between two selections in a certain column	***/
CSelectionController.prototype.selectVertical = function(sourceObj, targetObj, theDocument)
{
	if (!theDocument) {
		theDocument = document;
	}
	var currentRow = sourceObj.getCellRef().parentNode;
	var tempSelObj, i;

	var bGoDown = (sourceObj.getCellRef().parentNode.rowIndex < targetObj.getCellRef().parentNode.rowIndex);
	var lengthOfNonDataValueCells = (sourceObj.getCellRef().parentNode.cells.length - sourceObj.getCellRef().cellIndex);

	//Loop through all the rows (starting from the source cell's row)
	 //Do until we reach the target object
	while (currentRow.rowIndex != targetObj.getCellRef().parentNode.rowIndex)
	{
		if(bGoDown) {
			//source objects's row comes before the target object's row in the table, so go forward from the source
			currentRow = currentRow.nextSibling;
		}
		else {
			//source objects's row comes after the target object's row in the table, so go backward from the source
			currentRow = currentRow.previousSibling;
		}

		if (currentRow == null)
		{
			break; //There are no more rows (start or end of table)
		}

		//If the current row has the same number of cells or more than the row which had source object, go through individual cells
		if (currentRow.cells.length >= lengthOfNonDataValueCells)
		{
			for(i = 0; i < currentRow.cells.length; i++)
			{
				//Make sure both are in the same column and have the same layout
				if ((currentRow.cells[i].getAttribute("type") == sourceObj.getLayoutType()) && this.cellsAreInSameColumn(sourceObj.getCellRef(), currentRow.cells[i]))
				{
					//Get the cell that's anywhere below the source object's cell but only if they are in the same column
					tempSelObj = this.getSelectionObjectFactory().getSelectionObject(currentRow.cells[i]);
					//Add the selection if it's not already selected
					if(this.addSelectionObject(tempSelObj, theDocument))
					{
						// This will add the selection object to the list of selected columns in Query Studio
						if (typeof cf != "undefined" && typeof cf.addSelectionToCfgVariables == "function")
						{
							cf.addSelectionToCfgVariables(tempSelObj.getColumnName());
						}
					}
					break;
				}
			}
		}

	}

};

/****	Selects all the required cells between two selections on a certain row	***/
CSelectionController.prototype.selectHorizontal = function(sourceObj, targetObj, theDocument)
{
	var compareUID = "";

	//If it's a crosstab, and the UIDs of the selections don't match, exit this function
	if (sourceObj.getColumnRef() == null)
	{
		if (sourceObj.getCellRef().getAttribute("uid") == targetObj.getCellRef().getAttribute("uid")) {
			//crosstab, and same UIDs
			compareUID = sourceObj.getCellRef().getAttribute("uid");
		}
		else {
			return;
		}
	}

	//Set up start and end points of our loop
	var minNodeCellIndex, maxNodeCellIndex;
	var nodeParent = targetObj.getCellRef().parentNode; // A <tr> element
	var tempSelObj;

	if (targetObj.getCellRef().cellIndex < sourceObj.getCellRef().cellIndex)
	{
		minNodeCellIndex = targetObj.getCellRef().cellIndex;
		maxNodeCellIndex = sourceObj.getCellRef().cellIndex;
	}
	else
	{
		maxNodeCellIndex = targetObj.getCellRef().cellIndex;
		minNodeCellIndex = sourceObj.getCellRef().cellIndex;
	}

	//Go through each cell
	for (var i = minNodeCellIndex + 1; i < maxNodeCellIndex; i++)
	{
		//Select the cell if the layouts match and it's not a datavalue <----------if it's a list
		if (((sourceObj.getColumnRef() != null) && (sourceObj.getLayoutType() == targetObj.getLayoutType()) && (sourceObj.getLayoutType() != "datavalue")) ||
		//Select the cell if the UIDs match <----- if it's a crosstab
			((sourceObj.getColumnRef() == null) && (nodeParent.cells[i].getAttribute("uid") == compareUID)))
		{
			tempSelObj = this.getSelectionObjectFactory().getSelectionObject(nodeParent.cells[i]);
			//Add the selection if it's not already selected
			if(this.addSelectionObject(tempSelObj, theDocument))
			{
				// This will add the selection object to the list of selected columns in Query Studio
				if (typeof cf != "undefined" && typeof cf.addSelectionToCfgVariables == "function") {
					cf.addSelectionToCfgVariables(tempSelObj.getColumnName());
				}
			}
		}
	}
};

CSelectionController.prototype.pageDoubleClicked = function(e)
{
	var node = getNodeFromEvent(e);;

	if(typeof node.selectedCell != "undefined")
	{
		var divRegion = node;
		node = node.selectedCell;
		divRegion.removeAttribute("selectedCell");
	}

	while (node.nodeType == 3)
	{ // test to see if this is a text node
		node = node.parentNode;
	}

	var ctx = node.getAttribute("ctx");
	var uid = node.getAttribute("uid");

	if ((ctx != null) || (node.parentNode.nodeType == 1 && node.parentNode.getAttribute("uid") != null))  // this is a textitem
	{
		node = node.parentNode;

		// special case for Bug#498910. Analysis Studio is adding a members attributes within the same td, broken up by divs.
		// If the parent node is a DIV and the class is "BLOCK", move up one level higher in the DOM
		if(node.className.toUpperCase() == "BLOCK" && node.nodeName.toUpperCase() == "DIV") {
			node = node.parentNode;
		}

		uid = node.getAttribute("uid");
	}

	if (uid != null && node.firstChild != null && (node.getAttribute("type") == "columnTitle" || node.getAttribute("type") == "section"))  // this is a valid column title element
	{
		if (typeof goWindowManager != "undefined" && goWindowManager && typeof goWindowManager.getApplicationFrame == "function")
		{
			goWindowManager.getFeatureManager().launchFeature('Rename');
		}
	}
	if (typeof g_reportSelectionController != "undefined") {
		g_reportSelectionController.clearSelections();
	}
};

CSelectionController.prototype.getSelectionHoverNodes = function()
{
	return this.m_aSelectionHoverNodes;
};

CSelectionController.prototype.setSelectionHoverNodes = function(selectionHoverNodes)
{
	this.m_aSelectionHoverNodes = selectionHoverNodes;
};

CSelectionController.prototype.addSelectionHoverNode = function(node)
{
	this.m_aSelectionHoverNodes[this.m_aSelectionHoverNodes.length] = node;
};

CSelectionController.prototype.pageHover = function(e)
{
	var node = getNodeFromEvent(e);

	while (node.nodeType == 3) { // test to see if this is a text node
		node = node.parentNode;
	}

	if ((node.getAttribute("ctx") != null) || (node.parentNode.nodeType == 1 && node.parentNode.getAttribute("uid") != null))  // this is a textitem
	{
		node = node.parentNode;
	}

	var aSelectionHoverNodes = this.getSelectionHoverNodes();

	if (!(aSelectionHoverNodes.length == 1 && aSelectionHoverNodes[0] == node))
	{
		for (var i = 0; i < aSelectionHoverNodes.length; i++)
		{
			this.pageChangeHover(aSelectionHoverNodes[i], true);
		}

		this.setSelectionHoverNodes([]);

		if (this.pageChangeHover(node, false))
		{
			this.addSelectionHoverNode(node);
		}
	}
};

CSelectionController.prototype.pageChangeHover = function(node, hoverOff)
{
	var uid = node.getAttribute("uid");

	if ((node.getAttribute("ctx") != null) || (node.parentNode && node.parentNode.nodeType == 1 && node.parentNode.getAttribute("uid") != null))  // this is a textitem
	{
		node = node.parentNode;
		uid = node.getAttribute("uid");
	}

	if (uid != null && (!(node.firstChild == null && node.cellIndex == 0 && node.parentNode.rowIndex == 0 && node.getAttribute("cid") == null))  && (node.getAttribute("type") == "columnTitle" || node.getAttribute("type") == "section"))  // this is a valid column title element
	{
/* TODO: Put this back in once Report Server starts to produce context data
		var columnSelected = this.isColumnSelected(aReportMetadataArray[cid]);
   /TODO */


/* TODO: Take this out once Report Server starts to produce context data */
		var columnSelected = this.isColumnSelected(node.getAttribute("tag"));
/* /TODO */
		if (!columnSelected)
		{
/* TODO: Put this back in once Report Server starts to produce context data
			columnSelected = this.isColumnCut(aReportMetadataArray[cid]);
   /TODO */


/* TODO: Take this out once Report Server starts to produce context data */
			columnSelected = this.isColumnCut(node.getAttribute("tag"));
/* /TODO */
		}
		if (!columnSelected)
		{
			if (hoverOff)
			{
				if (node.getAttribute("oldClassName") != null)
				{
					node.className = node.getAttribute("oldClassName");
					node.removeAttribute("oldClassName");
				}

				this.restoreOldBackgroundImage(node);
			}
			else
			{
				if (node.getAttribute("oldClassName") != null) {
					node.className = node.getAttribute("oldClassName");
				}
				else {
					node.setAttribute("oldClassName", node.className);
				}

				if (node.getAttribute("oldBackgroundImageStyle") != null) {
					node.style.backgroundImage = node.getAttribute("oldBackgroundImageStyle");
				}
				else {
					this.saveOldBackgroundImage(node);
				}

				node.className += " hoverSelection";

				return true;
			}
		}
	}
	return false;
};

CSelectionController.prototype.saveOldBackgroundImage = function(node)
{
	if (node && node.getAttribute("oldBackgroundImageStyle") == null)
	{
		node.setAttribute("oldBackgroundImageStyle", this.getBackgroundImage(node));
		node.style.backgroundImage = "";
	}
}

CSelectionController.prototype.restoreOldBackgroundImage = function(node)
{
	if (node && node.style && node.getAttribute("oldBackgroundImageStyle") != null)
	{
		node.style.backgroundImage = node.getAttribute("oldBackgroundImageStyle");
		node.removeAttribute("oldBackgroundImageStyle");
	}
}

CSelectionController.prototype.getBackgroundImage = function(node)
{
	if(node && node.style)
	{
		return node.style.backgroundImage;
	}
	return "";
};

CSelectionController.prototype.pageContextClicked = function(e)
{
	var node = getNodeFromEvent(e);

	if(typeof node.selectedCell != "undefined")
	{
		var divRegion = node;
		node = node.selectedCell;
		divRegion.removeAttribute("selectedCell");
	}

	while (node != null && node.tagName != "TD")
	{
		node = node.parentNode;
	}

	if (node != null)
	{
		var nodeBackgroundImage = this.getBackgroundImage(node);
		var pS_backgroundImageURL = this.getBackgroundImage(getStyleFromClass("primarySelection"));
		if (this.getSelections().length == 0 ||  nodeBackgroundImage != pS_backgroundImageURL )
		{
			this.pageClicked(e);
		}
	}
	if (typeof populateContextMenu != "undefined")
	{
		populateContextMenu();
		moveContextMenu(e);
	}

	var bReturn = false;

	if (this.showViewerContextMenu())
	{
		//NS6 specific
		if (typeof e.preventDefault == "function")
		{
			e.preventDefault();
		}
		bReturn = true;
	}

	return bReturn;
};

CSelectionController.prototype.chartContextMenu = function(e)
{
	if(this.getSelectedChartArea() == null)
	{
		return;
	}

	if (typeof populateContextMenu != "undefined")
	{
		populateContextMenu();
		moveContextMenu(e);
	}

	//NS6 specific
	if (typeof e.preventDefault == "function")
	{
		e.preventDefault();
	}
	return false;
};

CSelectionController.prototype.titleAreaContextMenu = function(e, sType, sId)
{
	if (typeof populateContextMenu != "undefined")
	{
		goWindowManager.getApplicationFrame().cfgSet("contextMenuType", sType);
		goWindowManager.getApplicationFrame().cfgSet("contextMenuId", sId);
		populateContextMenu(sType.toUpperCase());
		moveContextMenu(e, sType.toUpperCase());
	}

	//NS6 specific
	if (typeof e.preventDefault == "function")
	{
		e.preventDefault();
	}
	return false;
};

CSelectionController.prototype.selectionsAreAllSameType = function()
{
	var allSelections = this.getSelections();
	if (allSelections.length > 0)
	{
		var layoutType = allSelections[0].getLayoutType();
		for (var i = 1; i < allSelections.length; i++)
		{
			if (layoutType != allSelections[i].getLayoutType()) {
				return 0;  // They aren't all the same type
			}
		}
		return 1;  // They are all the same type
	}
	return -1;  // There are no selections
};

CSelectionController.prototype.selectionsAreAllOnSameColumn = function()
{
	var allSelections = this.getSelections();
	var i = 0;
	if (allSelections.length > 0)
	{
		var colRef = allSelections[0].getColumnRef();
		if (colRef != null && colRef != "")
		{
			for (i = 1; i < allSelections.length; i++)
			{
				if (colRef != allSelections[i].getColumnRef()) {
					return false;  // They aren't all on the same column
				}
			}
		}
		else
		{
			var cellTypeId = allSelections[0].getCellTypeId();
			for (i = 1; i < allSelections.length; i++)
			{
				if (cellTypeId != allSelections[i].getCellTypeId()) {
					return false;  // They aren't all on the same column
				}
			}
		}
		return true;  // They are all on the same column
	}
	return false;  // There are no selections
};

CSelectionController.prototype.checkForReportElementNode = function(node)
{
	if (typeof node != "undefined" && node != null && typeof node.className != "undefined" && node.className != null)
	{
		if (node.className == "tt")
		{
			// Check to see if this is the report title or subtitle
			if (typeof node.parentNode != "undefined" && node.parentNode != null && typeof node.parentNode.parentNode != "undefined" && node.parentNode.parentNode != null && (node.parentNode.className == "reportSubtitleStyle" || node.parentNode.id == "reportTitleLink")) {
				node = node.parentNode.parentNode;
			}
			else {
				return false;
			}
		}
/*
		else if (node.className == "textItem")
		{
			// Handle page footer here
			if (typeof node.parentNode != "undefined" && node.parentNode != null && node.parentNode.className == "tableCell"
				&& typeof node.parentNode.parentNode != "undefined" && node.parentNode.parentNode != null && node.parentNode.parentNode.className == "tableRow"
				&& typeof node.parentNode.parentNode.parentNode != "undefined" && node.parentNode.parentNode.parentNode != null && node.parentNode.parentNode.className == "tb"
				&& typeof node.parentNode.parentNode.parentNode.parentNode != "undefined" && node.parentNode.parentNode.parentNode.parentNode != null && node.parentNode.parentNode.parentNode.className == "pf"
				)
				node = node.parentNode;
			else
				return false;
		}
*/
		else if (typeof node.parentNode != "undefined" && node.parentNode != null)
		{
			// Check to see if this is the report filter area
			var parentNode = node.parentNode;
			while (typeof parentNode != "undefined" && parentNode != null)
			{
				if (typeof parentNode.className != "undefined" && parentNode.className != null && parentNode.className.substr(0, 2) == "ft")
				{
					node = parentNode;
					break;
				}
				else {
					parentNode = parentNode.parentNode;
				}
			}
		}
		else {
			return false;
		}
		var nodeCN = node.className.substr(0, 2);
		if (nodeCN == "ta" || nodeCN == "ts" || nodeCN == "ft") {
			return true;
		}
	}
	return false;
};

CSelectionController.prototype.chartClicked = function(htmlElement)
{
	this.setSelectedChartArea(htmlElement);
};

function clearTextSelection(theDocument)
{
	if (!theDocument) {
		theDocument = document;
	}
	try
	{
		if (typeof theDocument.selection == "object" && theDocument.selection !== null)
		{
			theDocument.selection.empty();
		}
		else if (typeof window.getSelection == "function" && typeof window.getSelection() == "object" && window.getSelection() !== null)
		{
			//NS6 specific
			window.getSelection().removeAllRanges();
		}
	}
	catch(e)
	{
	}
}




