/////////////////////////////////////////////////////////////////////
//
// Copyright © 2002-2003, Microsoft Corporation.  All rights reserved.
//
// File: Syllabus.js
//
// Description: Implements a tree view of the table of contents.
//
/////////////////////////////////////////////////////////////////////

var m_oLMSAPI = null;			// Viewer API
var m_oXSLCache = null;			// Cached stylesheet used to transform XML to HTML
var m_oCurrNavElement = null;		// Most recent node selection
var m_oLastNavElement = null;		// Prior node selection
var m_oContentFrameWin = null;		// Content IFrame
var m_oTimerInterval = null;		// Timer object used for TOC synchronization
var m_bInitialized = false;		// Flag to indicate TOC initialization status
var m_aStatusImg = null;		// Array of SCO completion status images (checkmarks, etc.)
var m_bShowCheckmarks = false;		// Flag to indicate whether to display node status checkmarks
var m_sRTL = "ltr";			// initial RTL value
var m_bIsHostOLP = false;		// Flag to indicate whether the viewer is running within the offline player
var m_bModal = false;			// Flag to indicate whether a modal dialog window is presently open
var prevElement = null;
var prevParent = null;
//this.bthumbnailsLoaded = false;  //Flag to indicate whether thumbnails are loaded.
var bthumbnailsLoaded = false; //Flag to indicate whether thumbnails are loaded.
var nodeID=null;

/////////////////////////////////////////////////////////////////////
// PUBLIC METHODS
/////////////////////////////////////////////////////////////////////

//-------------------------------------------------------------------
// Function: Init
//
// Purpose: Hooks the viewer's API and establishes a delegate
//	    for viewer event callbacks.
//
// Parameters: None
//
// Returns: None
//-------------------------------------------------------------------
function Init()
{
	try
	{
		if (!m_bInitialized)
		{
			// Setup one time direction member
			var sDirVal = window.document.dir;
			sDirVal = sDirVal.toLowerCase();
			if ( sDirVal == "rtl" )	 m_sRTL = "rtl";

			// Get a reference to the LMS API
			m_oLMSAPI = parent.API;

			// Establish a viewer event delegate
			var nEvents = EVENT_LESSONSTATUS|EVENT_EXITSTATUS|EVENT_PREVIOUS|EVENT_NEXT|EVENT_SELECT|EVENT_SYNCH_LESSON|EVENT_MODAL_CHANGE;
			m_oLMSAPI.LRNListenForEvents(HandleViewerEvents,nEvents);

			// Display status checkmarks if we have a server-side SQL database
			m_bShowCheckmarks = (m_oLMSAPI.LRNIsViewerHosted() || m_oLMSAPI.LRNUsingSQLDB());

			// Is the viewer running within the offline player?
			m_bIsHostOLP = m_oLMSAPI.LRNIsHostOfflinePlayer();

			// Cache status images
			InitStatusImages();

			// Get a reference to the content frame object to be used later 
			m_oContentFrameWin = parent.ContentFrame;

			// Initialize the XSL template cache
			InitXSLCache();

			// Write the TOC's select element, if necessary.
			RenderMultipleTOCS();

			SelectTOC();
		
			m_bInitialized = true;
			//hide the thumbnail div at load time
	        document.getElementById('thumbnailControl').style.display = "none";
		}
	}
	catch(e)
	{
		// We may need to wait until the viewer has settled
		window.setTimeout(Init,100);
	}
}

//-------------------------------------------------------------------
// Function: Unload
//
// Purpose: Handles any cleanup tasks prior to exit.
//
// Parameters: None
//
// Returns: None
//-------------------------------------------------------------------
function Unload()
{
	try {m_oLMSAPI.LRNUnListenForEvents(HandleViewerEvents)} catch(e) {};
}

//-------------------------------------------------------------------
// Function: SelectTOC
//
// Purpose:
//	
//
// Parameters: None
//
// Returns: None
//-------------------------------------------------------------------
function SelectTOC()
{
	m_oCurrNavElement = null;
		
	try
	{
		var oSelectCtrl = document.getElementById('__idselectctrl'); 		
		if (!oSelectCtrl)
			m_oLMSAPI.LRNSetCurrentTOC();
		else
			m_oLMSAPI.LRNSetCurrentTOC(oSelectCtrl.value);
	
		// Write the tree nodes.
		document.getElementById('__idtreectrl').innerHTML = GetChildrenHTML();	
	
		// Get the course & node IDs from the viewer URL.  If the querystring exists
		// then the viewer was launched via a shortcut and we'll navigate to the indicated node.
		var sLocID = parent.GetItemFromURL("NodeID");
		var sCourseID = parent.GetItemFromURL("CourseID");

		if (!sLocID)
		{
			sCourseID = m_oLMSAPI.LRNGetScopedValue("lrn.startcourse","",true);
			sLocID = m_oLMSAPI.LRNGetScopedValue("lrn.startlocation","",true);
		}

		if (sLocID)
		{
			if (sCourseID) m_oLMSAPI.LRNGetItem(sCourseID);	// Demand-load the submanifest
			m_oLMSAPI.LRNDoSelect(sLocID);			// Return to the specified node
		}
		else
			m_oLMSAPI.LRNDoSelectFirst();
	}
	catch(e)
	{
	}
}

//-------------------------------------------------------------------
// Function: ScrollToNode
//
// Purpose: Scrolls the TOC node into view.
//
// Parameters:
//	oNode [in] -
//
// Returns: None
//-------------------------------------------------------------------
function ScrollToNode(oNode)
{
	try
	{
		if (!oNode) oNode = m_oCurrNavElement;

		// Force the TOC to render correctly
		var divSepStyle = window.parent.document.all.divSep.style;
		if (divSepStyle.display != "none")
		{
	 		parent.ForceTocRedraw();
		}

		// We are not using scrollinto view because of flicker.
		if (oNode.offsetTop < this.scrollTop)
			window.scrollBy(0,oNode.offsetTop-this.scrollTop);
		else if (oNode.offsetTop + oNode.children(0).offsetHeight > this.clientHeight + this.scrollTop)
			window.scrollBy(0,oNode.offsetTop-(this.clientHeight+this.scrollTop)+oNode.children(0).offsetHeight);
	}
	catch(e)
	{
	}
}

//-------------------------------------------------------------------
// Function: getItemNodes
//
// Purpose: retrieves the information for all the course item nodes.
//
// Parameters:
//	oNode [in] -
//
// Returns: Array containing the item nodes information
//-------------------------------------------------------------------
function getItemNodes()
{
    //check if thumbnails has already been loaded.If not,set the variable to true
    //&  get the itemnodes from the manifest 
      var delimiter = "$&%#";
    if(!bthumbnailsLoaded)
    {
        bthumbnailsLoaded = true;
        var itemArr = API.getItemNodes();
        for(var itemCount = 0 ; itemCount < itemArr.length ; itemCount++)
        {
            var itemId = itemArr[itemCount].split(delimiter)[0];
            var itemStatus = GetStatus(itemId);
            itemArr[itemCount]= itemArr[itemCount] + delimiter + itemStatus;
        }
        return itemArr;
        
    }
    
}
/////////////////////////////////////////////////////////////////////
// PRIVATE METHODS
/////////////////////////////////////////////////////////////////////

//-------------------------------------------------------------------
// Function: InitStatusImages
//
// Purpose: Initializes an associative array of status images.
//
// Parameters: None
//
// Returns: None
//-------------------------------------------------------------------
function InitStatusImages()
{
	var IMG_SIZE = 16;
	m_aStatusImg = new Array();
	m_aNoteStatusImg = new Array();

	if (m_bShowCheckmarks)
	{
		m_aStatusImg["completed"] = new Image(IMG_SIZE,IMG_SIZE);
		m_aStatusImg["completed"].src = IMG_STATUS_COMPLETED;
		m_aStatusImg["incomplete"] = new Image(IMG_SIZE,IMG_SIZE);
		m_aStatusImg["incomplete"].src = IMG_STATUS_INCOMPLETE;
		m_aStatusImg["passed"] = new Image(IMG_SIZE,IMG_SIZE);
		m_aStatusImg["passed"].src = IMG_STATUS_PASSED;
		m_aStatusImg["failed"] = new Image(IMG_SIZE,IMG_SIZE);
		m_aStatusImg["failed"].src = IMG_STATUS_FAILED;
		m_aStatusImg["browsed"] = new Image(IMG_SIZE,IMG_SIZE);
		m_aStatusImg["browsed"].src = IMG_STATUS_BROWSED;
		m_aStatusImg["not attempted"] = new Image(IMG_SIZE,IMG_SIZE);
		m_aStatusImg["not attempted"].src = IMG_STATUS_NOT_ATTEMPTED;
	}
	else
	{
		m_aStatusImg["block"] = new Image(IMG_SIZE,IMG_SIZE);
		m_aStatusImg["block"].src = IMG_TRANSPARENT_BLOCK;
	}
}

//-------------------------------------------------------------------
// Function: InitXSLCache
//
// Purpose: Caches the XML stylesheet used to transform the internal
//	    XML data into HTML.
//
// Parameters: None
//
// Returns: None
//
// Note: Function can throw
//-------------------------------------------------------------------
function InitXSLCache()
{
    if(window.ActiveXObject)
    {
        var sVersion = GetXmlParserVersion();
      					
  	    // Load the stylesheet
  	    var oXSL = new ActiveXObject("Msxml2.FreeThreadedDOMDocument." + sVersion);
	    try
	    {
		    oXSL.setProperty("AllowXsltScript", true);
	    }
	    catch(err) {}
      	
	    oXSL.async = false;
	    oXSL.validateOnParse = false;
	    oXSL.resolveExternals = false;
	    try {oXSL.setProperty("NewParser",true);} catch(e) {}

	    if (!oXSL.load("xsl/syllabus.xsl"))
	    {
		    var oError = new Object();
		    oError.description = ERR_CANNOT_LOAD_XML_FILE + "syllabus.xsl" + "\n" + oXSL.parseError.reason;
		    throw(oError);
  	    }

  	    // Cache the stylesheet so we don't have to compile it with each transform.
  	    m_oXSLCache = new ActiveXObject("Msxml2.XSLTemplate." + sVersion);
	    m_oXSLCache.stylesheet = oXSL;
    }
    else
    {
        var oXSL = new XmlDom();	
        oXSL.resolveExternals = false;
        var success = oXSL.load("xsl/syllabus.xsl");
        if (!oXSL.load("xsl/syllabus.xsl"))
        {
	        var oError = new Object();
	        oError.description = ERR_CANNOT_LOAD_XML_FILE + "syllabus.xsl" + "\n" + oXSL.parseError.reason;
	        throw(oError);
        }	
        m_oXSLCache = oXSL;
  	}
    
}

//-------------------------------------------------------------------
// Function: GetChildrenHTML
//
// Purpose: Gets the HTML of the children of the specified node.
//	    If id is null, the top level is retrieved.	
//
// Parameters:
//	sID [in] - item identifier
//
// Returns: String
//-------------------------------------------------------------------
function GetChildrenHTML(sID)
{
	var sInnerHTML = "";
	
	try
	{
		var oNodes = m_oLMSAPI.LRNGetChildren(sID);
		if (oNodes)
		{
			// Fixes checkmarking persistence between sessions
			// when running on EK's platform
			if (m_oLMSAPI.LRNIsViewerHosted()) InitNodesStatus(oNodes);
		 }	
	    if(window.ActiveXObject)
	    {
	        if (oNodes)
	        {
		        var oXSLT = m_oXSLCache.createProcessor();
		        oXSLT.input = oNodes;
		        oXSLT.addParameter("bDisplayStatus",m_bShowCheckmarks);
		        oXSLT.transform();
		        sInnerHTML = oXSLT.output;
		    }
	    }
	    else
	    {
	        if (oNodes)
	        {
                var oXSLT = new XSLTProcessor();
                cleanWhitespace(m_oXSLCache);
                oXSLT.importStylesheet(m_oXSLCache);
                oXSLT.setParameter(null, "bDisplayStatus", m_bShowCheckmarks);            
                var XMLResult = oXSLT.transformToDocument(oNodes);              
                sInnerHTML = XMLResult.xml;
		    }
		}
	}
	catch(e)
	{
	}		

	return sInnerHTML;
}

//-------------------------------------------------------------------
// Function: InitNodesStatus
//
// Purpose: Determines and sets the completion status for the provided	
//	    nodelist to fix checkmarking when running on EK's platform.
//
// Parameters:
//	oNodes [in] - nodelist to update
//
// Returns: None
//-------------------------------------------------------------------
function InitNodesStatus(oNodes)
{
	try
	{
		var oChildNodes = oNodes.documentElement.childNodes;
		var oChild = null;
		var sStatus = "";
		
		for(ic=0;ic<oChildNodes.length;ic++)
		{
		    oChild = oChildNodes[ic];
			sStatus = GetStatus(oChild.getAttribute("ID"));
			oChild.setAttribute("LessonStatus", sStatus);
		}
	}
	catch(e)
	{
	}
}

//-------------------------------------------------------------------
// Function: GetStatus
//
// Purpose: Determines the completion status of the current item.	
//
// Parameters:
//	sID [in] - current item identifier
//
// Returns: String
//-------------------------------------------------------------------
function GetStatus(sID)
{
    try
    {
	    var sStatus = "not attempted";

	    // Get the node's descendants
	    var oDescendants = m_oLMSAPI.LRNGetDescendants(sID);

	    if (oDescendants)
	    {
		    // Get the current node's status
		    bIsComplete = m_oLMSAPI.LRNIsComplete(sID);
    		
		    if (document.getElementById(sID) != null)
	        {
	            //Set the Completion status for Module node
		        if ((document.getElementById(sID).getAttribute("parentid") == "") && (document.getElementById(sID).getAttribute("haschildren") == "1")) 
		        {
                    if (bIsComplete )
                    sStatus = "completed";
		        }
	        }
        }
	}
	catch (e)
    {
    }

	return sStatus;
}

//-------------------------------------------------------------------
// Function: RenderMultipleTOCS
//
// Purpose: Renders a selection listbox at the top of the TOC when
//	    the manifest contains multiple organization elements.
//	    This allows the user to select which organization to use.
//
// Parameters: None
//
// Returns: None
//
// Note: Function can throw
//-------------------------------------------------------------------
function RenderMultipleTOCS()
{
	var oNodes = m_oLMSAPI.LRNGetTOCS();
	var oTOCS = oNodes.documentElement.childNodes;

	// Display a selction listbox if multiple manifest organization elements are present
	if (oTOCS.length > 1)
	{
		var oDoc = window.document;
		var sElement = "<select id='__idselectctrl' style='width:100%;display:none' onchange='document.body.SelectTOC()'></select>";
		var oSelect = oDoc.createElement(sElement);
		var oTOC = null;
		for(ic = 0; ic < oTOCS.length; ic++)
		{
		    oTOC = oTOCS[ic];
			var oOption = oDoc.createElement("option");
			oOption.text = oTOC.attributes.getNamedItem("Title").nodeValue;
			oOption.value = oTOC.attributes.getNamedItem("ID").nodeValue;
			oSelect.add(oOption);
		}

		// Add the element to the top of the TOC
		oDoc.body.insertBefore(oSelect,__idtreectrl);
		oSelect.style.display = "block";
	}
}

//-------------------------------------------------------------------
// Function: SelectNode
//
// Purpose: Selects the specified node within the tree.  If the node's
//	    HTML does not exist, it is added to the tree.
//
// Parameters:
//	sID	    [in] - Item identifier
//	bNoCollapse [in] - Flag to indicate whether okay to collapse parent
//	nEvent	    [in] - Event type
//	bMoveHilite [in] - Flag to indicate whether to move the current node
//			   highlight
//
// Returns: None
//-------------------------------------------------------------------
function SelectNode(sID,nEvent,bNoCollapse,bMoveHilite)
{
	try
	{
		RemoveSelectUI(m_oLastNavElement,bMoveHilite);
		if(window.ActiveXObject)
		    m_oCurrNavElement = __idtreectrl.all(sID);
		else
            m_oCurrNavElement = document.getElementById("__idtreectrl").querySelector("div[id='"+sID+"']");
	
		// Check to see if not retrieved from the xmldom yet.
		if (!m_oCurrNavElement && m_oLMSAPI.LRNGetParentID(sID) != "")
		{
			var sParentID = m_oLMSAPI.LRNGetParentID(sID);
			SelectNode(sParentID,nEvent,true,bMoveHilite);
			RemoveSelectUI(m_oCurrNavElement,bMoveHilite);
			if(window.ActiveXObject)
			    m_oCurrNavElement = __idtreectrl.all(sID);
			else
			    m_oCurrNavElement = __idtreectrl.children[sID];
		}
		var oParent = null;
		if (window.ActiveXObject) {
		    //IE9 fix to resolve the expand collapse issue of TOC
            if (m_oCurrNavElement.getAttribute("ParentID") != "")
                oParent = __idtreectrl.all(m_oCurrNavElement.getAttribute("ParentID"));
		}
		else {
		    oParent = document.getElementById(m_oCurrNavElement.getAttribute("parentid"));
		}


		if (oParent)
		{
			SelectNode(oParent.id,nEvent,true,bMoveHilite);
			RemoveSelectUI(m_oCurrNavElement,bMoveHilite);
			if(window.ActiveXObject)
			    m_oCurrNavElement = __idtreectrl.all(sID);
			else
                m_oCurrNavElement = document.getElementById("__idtreectrl").querySelector("div[id='"+sID+"']");
		}

		// Get the children, if necessary.
		if (m_oCurrNavElement.getAttribute("haschildren") == "1")
		{
			if (m_oCurrNavElement.children["__idChildrenContainer"].children.length == 0)
			{
				sInnerHTML = GetChildrenHTML(sID);
				m_oCurrNavElement.children["__idChildrenContainer"].innerHTML = sInnerHTML;
			}
		}
	
		AddSelectUI(m_oCurrNavElement,bNoCollapse,nEvent,bMoveHilite);
	}
	catch(e)
	{
	}
}

//-------------------------------------------------------------------
// Function: RemoveSelectUI
//
// Purpose:
//	
//
// Parameters:
//	oNode	    [in] -
//	bMoveHilite [in] -
//
// Returns: None
//-------------------------------------------------------------------
function RemoveSelectUI(oNode,bMoveHilite)
{
	try
	{
		if (bMoveHilite)
		{
		    if (window.ActiveXObject)
		    {
		        if (oNode.children("__idParent").all("__idLinkCaption").className != "")
		            var oLinkCaption = oNode.children("__idParent").all("__idLinkCaption");
		        else if (oNode.children("__idParent").className != "")
		            var oLinkCaption = oNode.children("__idParent");
			}
			else
			{
			    if (oNode.children["__idParent"].querySelector("div[id='__idLinkCaption']").className != "")
			        var oLinkCaption = oNode.children["__idParent"].querySelector("div[id='__idLinkCaption']");
			    else if (oNode.children["__idParent"].className != "")
			        var oLinkCaption = oNode.children["__idParent"];
			}
			switch (oLinkCaption.className)
			{
				case "nodeActive":
				case "nodeHover":
					oLinkCaption.className = "node";
					break;
				case "courseActive":
				case "courseHover":
					oLinkCaption.className = "course";break;
				case "courseSelected":break;
				case "nodeParentSelected":
					oLinkCaption.oldClass="nodeParentSelected";
					oLinkCaption.className="nodeParent";break;	
			    case "topicNode":
			        oLinkCaption.parentElement.className = "topicNodeVisited";break;
			}
		}
	}
	catch(e)
	{
	}
}

//-------------------------------------------------------------------
// Function: AddSelectUI
//
// Purpose:
//	
//
// Parameters:
//	oNode	    [in] -
//	bNoCollapse [in] -
//	nEvent	    [in] -
//	bMoveHilite [in] -
//
// Returns: None
//-------------------------------------------------------------------
function AddSelectUI(oNode,bNoCollapse,nEvent,bMoveHilite)
{
	try
	{
		if (bMoveHilite)
		{
			//var oLinkCaption = document.getElementById("__idLinkCaption");
			if (window.ActiveXObject)
		    {
		        if (oNode.children("__idParent").all("__idLinkCaption").className != "")
		            var oLinkCaption = oNode.children("__idParent").all("__idLinkCaption");
		        else if (oNode.children("__idParent").className != "")
		            var oLinkCaption = oNode.children("__idParent");
			}
			else
			{
			    if (oNode.children["__idParent"].querySelector("div[id='__idLinkCaption']").className != "")
			        var oLinkCaption = oNode.children["__idParent"].querySelector("div[id='__idLinkCaption']");
			    else if (oNode.children["__idParent"].className != "")
			        var oLinkCaption = oNode.children["__idParent"];
			}
			
			switch (oLinkCaption.className)
			{
				case "node":
				case "nodeHover":
					oLinkCaption.setAttribute("oldClass","nodeActive");
					oLinkCaption.setAttribute("className","nodeActive");
					oLinkCaption.oldClass="nodeActive";
					oLinkCaption.className="nodeActive";
					break;
				case "course":
				case "courseHover":
					oLinkCaption.setAttribute("oldClass","courseActive");
					oLinkCaption.setAttribute("className","courseActive");
					oLinkCaption.oldClass="courseActive";
					oLinkCaption.className="courseActive";
				case "nodeParent":
				    oLinkCaption.oldClass="nodeActive";
				    if(parent.isLessonEnabled)
					    oLinkCaption.className="nodeParentSelected";
					    
			}

			m_oLastNavElement = oNode;
		}
	
		if (oNode.children["__idChildrenContainer"].style.display == "none")
		ExpandNode(oNode,nodeID);
		else if (!bNoCollapse && nEvent == EVENT_SELECT)
		nodeID = CollapseNode(oNode);
	}
	catch(e)
	{
	}
}

//-------------------------------------------------------------------
// Function: ExpandNode
//
// Purpose: Expands a collapsed TOC node, exposing its descendants.
//
// Parameters:
//	oNode [in] - Node to expand
//
// Returns: None
//-------------------------------------------------------------------	
function ExpandNode(oNode,nodeID)
{

	try
	{
	if(nodeID!=oNode.id)
    {
		var oChildrenContainer = oNode.children["__idChildrenContainer"];
		var oChildrenContStyle = oChildrenContainer.style;

		if (oChildrenContainer.children.length > 0)
		{
			if (oChildrenContStyle.display == "none")
				oChildrenContStyle.display = "block";
			if(window.ActiveXObject)
		        var oItemImg = oNode.children("__idParent").all("__idItem_Img");
	        else
    			var oItemImg = oNode.children["__idParent"].querySelector("IMG[id='__idItem_Img']");

			    oItemImg.src = oItemImg.getAttribute("img_expand");
		}
		else
			oChildrenContStyle.display = "none";
	}
	}
	catch(e)
	{
	}	
}

//-------------------------------------------------------------------
// Function: CollapseNode
//
// Purpose: Collapses an expanded TOC node, hiding its descendants.
//
// Parameters:
//	oNode [in] - Node to collapse
//
// Returns: None
//-------------------------------------------------------------------
function CollapseNode(oNode)
{
	try
	{		
		oNode.children["__idChildrenContainer"].style.display = "none";
		if(window.ActiveXObject)
		    var oImg = oNode.children("__idParent").all("__idItem_Img");
        else
		    var oImg = oNode.children["__idParent"].querySelector("IMG[id='__idItem_Img']");
		
			   oImg.src =oImg.getAttribute("img_collapse");
		return oNode.id;
	}
	catch(e)
	{
	}
}

//-------------------------------------------------------------------
// Function: UpdateStatus
//
// Purpose: Updates the graphic which displays the status of the TOC node.
//
// Parameters:
//	sID	[in] - Item identifier
//	sStatus [in] - Status
//
// Returns: None
//-------------------------------------------------------------------
function UpdateStatus(sID,sStatus)
{
	try
	{
	    var currentThumbnail_sID = "imgDiv_" + sID;
		if ("string" == typeof(sID) && "string" == typeof(sStatus))
		{
		    if(sStatus == "block")
		    {
		        if (m_oLastNavElement.getAttribute("haschildren") != "1") 
		            m_oLastNavElement.className="topicNode";
		        if (prevElement != null && prevElement.id != "__idItem_Img" && prevParent.getAttribute("haschildren") != "1") 
		            prevElement.parentElement.className="topicNode";
		    }
		    if (sStatus != "current node" && sStatus != "block")
		   {
		       document.getElementById("__idItemStatusImg").src = m_aStatusImg[sStatus].src;
		       if ((document.getElementById(sID).getAttribute("haschildren") == '1' && document.getElementById(sID).getAttribute("parentid") == "") && sStatus == "completed") 
		           document.getElementById("__idItemStatusImg").style.visibility = "Visible";
		       else
		           document.getElementById("__idItemStatusImg").style.visibility = "Hidden";
		    }

		}
		//unselecting the module node
		if(m_oLastNavElement.childNodes[0].className == "courseSelected" && m_oLastNavElement.getAttribute("haschildren") == '1' && m_oLastNavElement.getAttribute("parentid") == "")
		{
		    m_oLastNavElement.childNodes[0].setAttribute("className","nodeParent");
		    m_oLastNavElement.childNodes[0].className="nodeParent";
		    try{
		    m_oLastNavElement[0].className="nodeParent";
		    }catch(exp){}
		}
		//unselecting the topic nodes
		if(prevElement!=null)
		if(m_oLastNavElement.className == "topicNodeSelected" || prevElement.parentNode.className == "topicNodeSelected")
		{
		    m_oLastNavElement.setAttribute("className","topicNode");
		    prevElement.parentNode.setAttribute("className", "topicNode");
		    m_oLastNavElement.className = "topicNode";
		    prevElement.parentNode.className = "topicNode";
		}
		
		//set the status for thumbnails
		 
		if(parent.bthumbnailsLoaded)
		{
		    UpdateThumbnailStatus(sID,sStatus,"itemLoad",m_bShowCheckmarks);
		}
		//highlighting the topic node and module node
		if(sStatus == "current node")
		{
		      if(document.getElementById(sID).getAttribute("haschildren") == '0')
		      {
		         document.getElementById(sID).className="topicNodeSelected"; 
		      }
		      else if(document.getElementById(sID).getAttribute("haschildren") == '1' && document.getElementById(sID).getAttribute("parentid") == "")
		      {
		         document.getElementById(sID).childNodes[0].setAttribute("className","courseSelected");
		         document.getElementById(sID).childNodes[0].className="courseSelected";
		      }
		      if (parent.bthumbnailsLoaded)
	         {
	            document.getElementById(currentThumbnail_sID).parentNode.className="thumbnailsSelected";
	         }		  
		}			
		
	}
	catch(e)
	{
	}
}

/////////////////////////////////////////////////////////////////////
// EVENT HANDLERS
/////////////////////////////////////////////////////////////////////

//-------------------------------------------------------------------
// Function: HandleViewerEvents
//
// Purpose: Delegate for viewer-based events.
//
// Parameters:
//	oEvent [in] - Event object
//
// Returns: None
//-------------------------------------------------------------------
function HandleViewerEvents(oEvent)
{
	try
	{
		var sID = oEvent.id;
        var currentThumbnail_sID = "imgDiv_" + sID;
		switch (oEvent.type)
		{
			case EVENT_PREVIOUS:
			case EVENT_NEXT:
	 		case EVENT_SELECT:
			case EVENT_SYNCH_LESSON:
				// Replace the current node arrow, otherwise we have duplicates.
				if (m_oLastNavElement) UpdateStatus(m_oLastNavElement.id, "block");

				SelectNode(sID,oEvent.type,true,true);
				UpdateStatus(sID,"current node");	// Specify 'current node' to display an arrow
				if(oEvent.type != EVENT_SELECT && oEvent.type != EVENT_SYNCH_LESSON && TreeControltd.style.display != "none")
                {
                    if(window.ActiveXObject)
                        document.getElementById(sID).parentNode.focus();
                    else
                        m_oCurrNavElement = document.getElementById("__idtreectrl").querySelector("div[id='"+sID+"']").parentNode.focus();
                }
				if(parent.bthumbnailsLoaded && oEvent.type != EVENT_SELECT && oEvent.type != EVENT_SYNCH_LESSON)
				{
                    thumbnailControl.document.getElementById(currentThumbnail_sID).parentNode.focus();
                }
				break;
	 		case EVENT_LESSONSTATUS:
				if (m_bShowCheckmarks)
				{
					var sNewStatus = GetStatus(sID);
					UpdateStatus(sID,sNewStatus);
				}
				else
					// Display a one pixel graphic to replace the current node arrow.
					UpdateStatus(sID,"block");
				break;
			case EVENT_MODAL_CHANGE:
				m_bModal = oEvent.id;
				break;
			case EVENT_EXITSTATUS:
				var sNewStatus = m_oLMSAPI.LRNGetScopedValue("cmi.core.exit",sID);
				if (sNewStatus == "suspend")
					m_oLMSAPI.LRNDoPrevious();
				if (sNewStatus == "logout")
					//alert ("The LRN Content Viewer received a CMI logout request - close the browser window to exit");
					window.close();
				break;
		}
	}
	catch(e)
	{
	}
}

//-------------------------------------------------------------------
// Function: evt_OnClick
//
// Purpose:
//	
//
// Parameters: None
//
// Returns: None
//-------------------------------------------------------------------
function evt_OnClick(event)
{
	try
	{
	    nodeID=null;
	    var oParent;
	    var srcElement;

	    if (window.ActiveXObject) {
	        srcElement = event.srcElement;
	    }
	    else {
	        srcElement = event.target;
	    }
				
		//unselecting the previously selected node
	    if (srcElement.nodeName != "BODY" && srcElement.parentElement.id != "__idtreectrl")
		{
		    if(prevElement != null)
		    {		        
		        if(prevElement.className == "topicNodeSelected")
		        {
		            //if (prevElement.getAttribute("uniqueid") != srcElement.getAttribute("uniqueID"))
		                prevElement.className="topicNode";
		        }
		        if (prevParent.className == "topicNodeSelected") {
		            //if (prevElement.getAttribute("uniqueid") != srcElement.getAttribute("uniqueID"))
		                prevParent.className="topicNode";
		        }
		        if (prevElement.parentElement.className == "topicNodeSelected")
		        {
		            //if (prevElement.getAttribute("uniqueid") != srcElement.getAttribute("uniqueID"))
		                prevElement.parentElement.className="topicNode";
		        }
		        if (prevParent.getAttribute("haschildren") == "1" && prevParent.getAttribute("parentid") == "" && prevElement.parentNode.parentNode.className == "courseSelected")
		        {
		            //if (prevElement.getAttribute("uniqueid") != srcElement.getAttribute("uniqueID"))
		                prevElement.parentNode.parentNode.className="course";
		        }
		    }
		}
		parent.HideMenu();	// Hide any open menu

		event.cancelBubble=true;        
		if (m_bModal) return;

		var oNode = null;

		if (window.ActiveXObject) {
		    var oElement = event.srcElement;
		}
		else {
		    var oElement = event.target;
		}	
		
		if(oElement.nodeName == "TD")
		    oParent = oElement.parentElement.parentElement.parentElement.parentElement.parentElement;
		else
		    oParent = oElement.parentElement.parentElement.parentElement.parentElement.parentElement.parentElement;       
        
		switch (oElement.getAttribute("name"))
		{
			case "link":
			case "Item_Img":
				oNode = oParent;
				break;
			default:
				return;
		}	
	    
		if (oElement.getAttribute("name") == "Item_Img" ||(oNode.getAttribute("parentid")!="" && (oNode.getAttribute("haschildren")=="1") ))
		 {   
			if (oParent.getAttribute("haschildren") == "1")
			{			
	           if (!document.getElementById(oNode.id).children["__idChildrenContainer"].children[0])
	           {	            
	            	m_oLMSAPI.LRNGetItem(oNode.id);
	            }

				if(oNode.getAttribute("parentid") == "")
				{
				    SelectNode(oNode.id,EVENT_SELECT,false,true);
				}
				else
				{
				    if (parent.isLessonEnabled && oElement.getAttribute("name") != "Item_Img")
				        SelectNode(oNode.id, EVENT_SELECT, true, false);
				    else
				        SelectNode(oNode.id, EVENT_SELECT, false, false);
				}
			    prevElement = oElement;
		        prevParent = oNode;		        
		        if(!parent.isLessonEnabled)
				return;
			}
		}
		
		
		// OLP: Only load the content if the item has been downloaded.
		var oLinkCaption = document.getElementById("__idLinkCaption");

		if (m_bIsHostOLP && (oLinkCaption.getAttribute("className") == "nodeUnavailable" || oLinkCaption.getAttribute("className") == "courseUnavailable"))
			return;
		else
		{
			m_oLMSAPI.LRNDoSelect(oNode.id);
		}
		
		prevElement = oElement;
		prevParent = oNode;
	}
	catch(e)
	{
	}
}

//-------------------------------------------------------------------
// Function: evt_OnKeyPress
//
// Purpose:
//	
//
// Parameters: None
//
// Returns: None
//-------------------------------------------------------------------
function evt_OnKeyPress()
{
	try
	{
		switch (event.keyCode)
		{
			case ASCII_KEYCODE_ARROW_RIGHT:
				var oNode = event.srcElement.parentElement.parentElement.parentElement.parentElement.parentElement.parentElement;
				
				var oChildren = oNode.children;

				if (oChildren("__idChildrenContainer").style.display == "none")
				{
					if (oChildren("__idChildrenContainer").children(0))
						ExpandNode(oNode);

					else if (oNode.HasChildren == "1") {
						// Simulate a mouse click to render the children HTML
						oChildren("__idParent").all( "__idItem_Img" ).click();
						
					}						
				}
				else if (oChildren("__idChildrenContainer").style.display == "block")
				{
					var sID = m_oLMSAPI.LRNGetNextID(oNode.id);
				}
				break;
			case ASCII_KEYCODE_ARROW_LEFT:
				var oNode = event.srcElement.parentElement.parentElement.parentElement.parentElement.parentElement.parentElement;
				var oChildren = oNode.children;
				if (oChildren("__idChildrenContainer").style.display == "block"){
					CollapseNode(oNode);
				}
				else if (oNode.HasChildren == "0" || (oChildren("__idChildrenContainer").style.display == "none"))
				{
					var sID = m_oLMSAPI.LRNGetParentID(oNode.id);
				}
				break;
			default:
				parent.HandleKeys(event);
		}	
	}
	catch(e)
	{
	}
}

// SIG // Begin signature block
// SIG // MIIbCgYJKoZIhvcNAQcCoIIa+zCCGvcCAQExCzAJBgUr
// SIG // DgMCGgUAMGcGCisGAQQBgjcCAQSgWTBXMDIGCisGAQQB
// SIG // gjcCAR4wJAIBAQQQEODJBs441BGiowAQS9NQkAIBAAIB
// SIG // AAIBAAIBAAIBADAhMAkGBSsOAwIaBQAEFIwBj+Hkq8GA
// SIG // 1SFdsX787r8Zxi2goIIV5zCCBIUwggNtoAMCAQICCmEI
// SIG // d18AAAAAAEowDQYJKoZIhvcNAQEFBQAweTELMAkGA1UE
// SIG // BhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNV
// SIG // BAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBD
// SIG // b3Jwb3JhdGlvbjEjMCEGA1UEAxMaTWljcm9zb2Z0IENv
// SIG // ZGUgU2lnbmluZyBQQ0EwHhcNMTAwNzE5MjI1MzEwWhcN
// SIG // MTExMDE5MjI1MzEwWjCBgzELMAkGA1UEBhMCVVMxEzAR
// SIG // BgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1v
// SIG // bmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlv
// SIG // bjENMAsGA1UECxMETU9QUjEeMBwGA1UEAxMVTWljcm9z
// SIG // b2Z0IENvcnBvcmF0aW9uMIIBIjANBgkqhkiG9w0BAQEF
// SIG // AAOCAQ8AMIIBCgKCAQEAzH6Ae0H6i7RNmSlD3eb4Ut9b
// SIG // Qpe9Mxmc77Xa0MDc6PG3vlzhCrLCNaB+5PPUOKfyD0Jy
// SIG // p7qbzx8k3lYNhHPM02P3F82vaW9hTUyAT8h3HFFkyNME
// SIG // 8xQms7hCPzNDsNsmWViTtW2JYg8HVlvVEqCxCcwWK/mM
// SIG // 32FW6AZ4f9dziCYDZ9Gj/zSCrC1M2ALs7W+5ojHFMky7
// SIG // 9v1fYlte8fZkkceFd0cc9qcrRy0LN1RPth8EjbXsYCen
// SIG // 8362fKFMkaaLcdbGNWFHvMEVS92sMyK+BhmWS4oebgDr
// SIG // vh5p3VhZIQMrPL7mEwUXZjWnhi0a8dk0wAGAGvyaRp1u
// SIG // pOdI3DXqNwIDAQABo4IBAjCB/zATBgNVHSUEDDAKBggr
// SIG // BgEFBQcDAzAdBgNVHQ4EFgQU5G9fyon5U77wcFcGUKrC
// SIG // eQ2sVpswDgYDVR0PAQH/BAQDAgeAMB8GA1UdIwQYMBaA
// SIG // FFdFdBxdsPbIQwXgjFQtjzKn/kiWMEkGA1UdHwRCMEAw
// SIG // PqA8oDqGOGh0dHA6Ly9jcmwubWljcm9zb2Z0LmNvbS9w
// SIG // a2kvY3JsL3Byb2R1Y3RzL0NvZGVTaWdQQ0EuY3JsME0G
// SIG // CCsGAQUFBwEBBEEwPzA9BggrBgEFBQcwAoYxaHR0cDov
// SIG // L3d3dy5taWNyb3NvZnQuY29tL3BraS9jZXJ0cy9Db2Rl
// SIG // U2lnUENBLmNydDANBgkqhkiG9w0BAQUFAAOCAQEAlkFd
// SIG // PVwrpM64KkUvQgJeoZAcTHQnCc4LVH1wKEFyO6QVvNEE
// SIG // Ulevd3RtC1VXhzcQSR7W5tTCY5S0/aQuLfpf4hlZFYTZ
// SIG // t7bpUqJS3iNfIC9Z06sahH8d473qD98BiDkl2O1kYRkb
// SIG // eq+mFEpGUEjZckvVS5Ld8A+EfMvTxvJMeG79vP9mEAr3
// SIG // A10V6l6YDAnSmY8utSC9YebJbwUUEct7+0IIvQPxJldn
// SIG // TY9Zi7hEx0XTYgQMLTADWF7sSPRuqBQxBP00orgELQLd
// SIG // OqEJXq1hsY9wwHhVI2Oon1l3otu5G3EoHPwu4QSPte80
// SIG // vkqZR+NkUhY8+r3g6OAUDBAiNIKCHjCCBMowggOyoAMC
// SIG // AQICCmED3PYAAAAAAAwwDQYJKoZIhvcNAQEFBQAwdzEL
// SIG // MAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24x
// SIG // EDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jv
// SIG // c29mdCBDb3Jwb3JhdGlvbjEhMB8GA1UEAxMYTWljcm9z
// SIG // b2Z0IFRpbWUtU3RhbXAgUENBMB4XDTA4MDcyNTE5MTI1
// SIG // MFoXDTExMDcyNTE5MjI1MFowgbMxCzAJBgNVBAYTAlVT
// SIG // MRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdS
// SIG // ZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9y
// SIG // YXRpb24xDTALBgNVBAsTBE1PUFIxJzAlBgNVBAsTHm5D
// SIG // aXBoZXIgRFNFIEVTTjoxNTlDLUEzRjctMjU3MDElMCMG
// SIG // A1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2Vydmlj
// SIG // ZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
// SIG // AMDtgRShXnfAW/R2iWL6rXxoFLT3vTXYE3laF8rZbFFF
// SIG // YiZ6Lx/Y6sFuARf5w6YfZ9tRsCzeihft/yCtNOqY+6XW
// SIG // KtLxRCcHWi06k/9WU7DI9fMD8knMFtD1AExY+Jv1ByWx
// SIG // ZhfAvcjSUoWNwis4ssM2vvmH2vSOXUPXBr+ZBZ+kzv6r
// SIG // jWFj5znF8xj22PwxNmlyWqIaTD7qhyVCndE+8ZfSGDKT
// SIG // cFVTgR7jOw3ovoJ4beb6zZikb9vuZvSVyM01yZ67Ng2D
// SIG // lpQmp5DgqTQ71cCePvDUR42GDIKkWDA6HHbjrZVmtLf9
// SIG // CYoFYA+jD+KTllginJ0r26KUGJCVAr0GQJUCAwEAAaOC
// SIG // ARkwggEVMB0GA1UdDgQWBBTS7Q0eJLs3qdggak0d0hbV
// SIG // Lr6e6zAfBgNVHSMEGDAWgBQjNPjZUkZwCu1A+3b7syuw
// SIG // wzWzDzBUBgNVHR8ETTBLMEmgR6BFhkNodHRwOi8vY3Js
// SIG // Lm1pY3Jvc29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9N
// SIG // aWNyb3NvZnRUaW1lU3RhbXBQQ0EuY3JsMFgGCCsGAQUF
// SIG // BwEBBEwwSjBIBggrBgEFBQcwAoY8aHR0cDovL3d3dy5t
// SIG // aWNyb3NvZnQuY29tL3BraS9jZXJ0cy9NaWNyb3NvZnRU
// SIG // aW1lU3RhbXBQQ0EuY3J0MBMGA1UdJQQMMAoGCCsGAQUF
// SIG // BwMIMA4GA1UdDwEB/wQEAwIGwDANBgkqhkiG9w0BAQUF
// SIG // AAOCAQEAnApVyMxEEzQM2GMndn0++jgyg1Od8gj5MvXF
// SIG // bnChybFjaxmdCWfZneuKattgZunpUibzO8Zq08JSvqi5
// SIG // 62qqeIzJFn2QlaDMIbOegb3NwYspvWIl7wlX54ZOKuyA
// SIG // yrv8IRbEP05SGeYOsdjBwnmQZLRQcxA1Xl0Rwbi6qs9S
// SIG // 9oCRAObvUUNG6dDolPYsJA2KxrIxiqN+NmykBUxnByq7
// SIG // uxClpTAactAGIDskk1sV2TmT03MtGsTUbB6hCOz2Mbhr
// SIG // S+zuXDMCFDKMfBEgLyADf/kMnbjTnl/WCPyBoJm4u1Vu
// SIG // zUJLOk2MFCvKyBLTYm7qDQqdCaNm2XlPjhqi/8yYBDCC
// SIG // BgcwggPvoAMCAQICCmEWaDQAAAAAABwwDQYJKoZIhvcN
// SIG // AQEFBQAwXzETMBEGCgmSJomT8ixkARkWA2NvbTEZMBcG
// SIG // CgmSJomT8ixkARkWCW1pY3Jvc29mdDEtMCsGA1UEAxMk
// SIG // TWljcm9zb2Z0IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9y
// SIG // aXR5MB4XDTA3MDQwMzEyNTMwOVoXDTIxMDQwMzEzMDMw
// SIG // OVowdzELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hp
// SIG // bmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoT
// SIG // FU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEhMB8GA1UEAxMY
// SIG // TWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBMIIBIjANBgkq
// SIG // hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAn6Fssd/bSJIq
// SIG // fGsuGeG94uPFmVEjUK3O3RhOJA/u0afRTK10MCAR6wfV
// SIG // VJUVSZQbQpKumFwwJtoAa+h7veyJBw/3DgSY8InMH8sz
// SIG // JIed8vRnHCz8e+eIHernTqOhwSNTyo36Rc8J0F6v0LBC
// SIG // BKL5pmyTZ9co3EZTsIbQ5ShGLieshk9VUgzkAyz7apCQ
// SIG // MG6H81kwnfp+1pez6CGXfvjSE/MIt1NtUrRFkJ9IAEpH
// SIG // ZhEnKWaol+TTBoFKovmEpxFHFAmCn4TtVXj+AZodUAiF
// SIG // ABAwRu233iNGu8QtVJ+vHnhBMXfMm987g5OhYQK1HQ2x
// SIG // /PebsgHOIktU//kFw8IgCwIDAQABo4IBqzCCAacwDwYD
// SIG // VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUIzT42VJGcArt
// SIG // QPt2+7MrsMM1sw8wCwYDVR0PBAQDAgGGMBAGCSsGAQQB
// SIG // gjcVAQQDAgEAMIGYBgNVHSMEgZAwgY2AFA6sgmBAVieX
// SIG // 5SUT/CrhClOVWeSkoWOkYTBfMRMwEQYKCZImiZPyLGQB
// SIG // GRYDY29tMRkwFwYKCZImiZPyLGQBGRYJbWljcm9zb2Z0
// SIG // MS0wKwYDVQQDEyRNaWNyb3NvZnQgUm9vdCBDZXJ0aWZp
// SIG // Y2F0ZSBBdXRob3JpdHmCEHmtFqFKoKWtTHNY9AcTLmUw
// SIG // UAYDVR0fBEkwRzBFoEOgQYY/aHR0cDovL2NybC5taWNy
// SIG // b3NvZnQuY29tL3BraS9jcmwvcHJvZHVjdHMvbWljcm9z
// SIG // b2Z0cm9vdGNlcnQuY3JsMFQGCCsGAQUFBwEBBEgwRjBE
// SIG // BggrBgEFBQcwAoY4aHR0cDovL3d3dy5taWNyb3NvZnQu
// SIG // Y29tL3BraS9jZXJ0cy9NaWNyb3NvZnRSb290Q2VydC5j
// SIG // cnQwEwYDVR0lBAwwCgYIKwYBBQUHAwgwDQYJKoZIhvcN
// SIG // AQEFBQADggIBABCXisNcA0Q23em0rXfbznlRTQGxLnRx
// SIG // W20ME6vOvnuPuC7UEqKMbWK4VwLLTiATUJndekDiV7uv
// SIG // WJoc4R0Bhqy7ePKL0Ow7Ae7ivo8KBciNSOLwUxXdT6uS
// SIG // 5OeNatWAweaU8gYvhQPpkSokInD79vzkeJkuDfcH4nC8
// SIG // GE6djmsKcpW4oTmcZy3FUQ7qYlw/FpiLID/iBxoy+cwx
// SIG // SnYxPStyC8jqcD3/hQoT38IKYY7w17gX606Lf8U1K16j
// SIG // v+u8fQtCe9RTciHuMMq7eGVcWwEXChQO0toUmPU8uWZY
// SIG // sy0v5/mFhsxRVuidcJRsrDlM1PZ5v6oYemIp76KbKTQG
// SIG // dxpiyT0ebR+C8AvHLLvPQ7Pl+ex9teOkqHQ1uE7FcSMS
// SIG // JnYLPFKMcVpGQxS8s7OwTWfIn0L/gHkhgJ4VMGboQhJe
// SIG // GsieIiHQQ+kr6bv0SMws1NgygEwmKkgkX1rqVu+m3pmd
// SIG // yjpvvYEndAYR7nYhv5uCwSdUtrFqPYmhdmG0bqETpr+q
// SIG // R/ASb/2KMmyy/t9RyIwjyWa9nR2HEmQCPS2vWY+45CHl
// SIG // tbDKY7R4VAXUQS5QrJSwpXirs6CWdRrZkocTdSIvMqgI
// SIG // bqBbjCW/oO+EyiHW6x5PyZruSeD3AWVviQt9yGnI5m7q
// SIG // p5fOMSn/DsVbXNhNG6HY+i+ePy5VFmvJE6P9MIIGgTCC
// SIG // BGmgAwIBAgIKYRUIJwAAAAAADDANBgkqhkiG9w0BAQUF
// SIG // ADBfMRMwEQYKCZImiZPyLGQBGRYDY29tMRkwFwYKCZIm
// SIG // iZPyLGQBGRYJbWljcm9zb2Z0MS0wKwYDVQQDEyRNaWNy
// SIG // b3NvZnQgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkw
// SIG // HhcNMDYwMTI1MjMyMjMyWhcNMTcwMTI1MjMzMjMyWjB5
// SIG // MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3Rv
// SIG // bjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWlj
// SIG // cm9zb2Z0IENvcnBvcmF0aW9uMSMwIQYDVQQDExpNaWNy
// SIG // b3NvZnQgQ29kZSBTaWduaW5nIFBDQTCCASIwDQYJKoZI
// SIG // hvcNAQEBBQADggEPADCCAQoCggEBAJ+N34U3jLEGVmY2
// SIG // TtQK6zYjkR6vq41Y6cTPwZ86CiTExMResO4VFMX6Ppkz
// SIG // axlpcvR8BV/lmSVE1zUZipDcKI6QDO/VkGGt3twYcC2D
// SIG // yW+vhSz43bm5MP1xeByD/cipuYJnDXq4wQnCvBaXVz8c
// SIG // mNNp1zCQkJCNMB/YJtSee4jZ4gntl0lF6wRSgXV7uLUi
// SIG // uC5Wu9fPqU48CoOiqDrFrbYBDmrPIrQjH2zVJ+e3fsG0
// SIG // 1TKteSUcQobinYX0V9obWS8tJpIpxbPXhaOeYFqU5nuc
// SIG // e16CNEtt/9TuJ9Ci3NGQDM59DhV8iKw0x8BsmIRKyUR5
// SIG // aCjfIoMNuIosSGHi/hECAwEAAaOCAiMwggIfMBAGCSsG
// SIG // AQQBgjcVAQQDAgEAMB0GA1UdDgQWBBRXRXQcXbD2yEMF
// SIG // 4IxULY8yp/5IljALBgNVHQ8EBAMCAcYwDwYDVR0TAQH/
// SIG // BAUwAwEB/zCBmAYDVR0jBIGQMIGNgBQOrIJgQFYnl+Ul
// SIG // E/wq4QpTlVnkpKFjpGEwXzETMBEGCgmSJomT8ixkARkW
// SIG // A2NvbTEZMBcGCgmSJomT8ixkARkWCW1pY3Jvc29mdDEt
// SIG // MCsGA1UEAxMkTWljcm9zb2Z0IFJvb3QgQ2VydGlmaWNh
// SIG // dGUgQXV0aG9yaXR5ghB5rRahSqClrUxzWPQHEy5lMFAG
// SIG // A1UdHwRJMEcwRaBDoEGGP2h0dHA6Ly9jcmwubWljcm9z
// SIG // b2Z0LmNvbS9wa2kvY3JsL3Byb2R1Y3RzL21pY3Jvc29m
// SIG // dHJvb3RjZXJ0LmNybDBUBggrBgEFBQcBAQRIMEYwRAYI
// SIG // KwYBBQUHMAKGOGh0dHA6Ly93d3cubWljcm9zb2Z0LmNv
// SIG // bS9wa2kvY2VydHMvTWljcm9zb2Z0Um9vdENlcnQuY3J0
// SIG // MHYGA1UdIARvMG0wawYJKwYBBAGCNxUvMF4wXAYIKwYB
// SIG // BQUHAgIwUB5OAEMAbwBwAHkAcgBpAGcAaAB0ACAAqQAg
// SIG // ADIAMAAwADYAIABNAGkAYwByAG8AcwBvAGYAdAAgAEMA
// SIG // bwByAHAAbwByAGEAdABpAG8AbgAuMBMGA1UdJQQMMAoG
// SIG // CCsGAQUFBwMDMA0GCSqGSIb3DQEBBQUAA4ICAQAwvLAg
// SIG // pGKgp+85JmE93KzGmdCGxC71gzJlXiI+m9aG+Oi2n8qL
// SIG // 1jt1C6GRPkzdZHSMSfKIjBhnbP4VZka4OkZCl8iRN9Qk
// SIG // sees0+pBFIN308lPBV+jFFK/lqQvPlZbEHXOU8POBVRp
// SIG // tGXJJKUP4SW4GrlN5QK5UB5Ps5gMHZUC7iJZrSLLBXQL
// SIG // BEV7BFng2A+z60z4YN3CeJ7Rup9r9/PufkQRQNK9uptL
// SIG // FghupL5V5KY4EqNI9BxVeoog0X3+kduUjy/Ce2umZIVP
// SIG // o+UsNCldC7/1xzgvxCDEVjH2ac6F+AqR7NDWrro4BQzr
// SIG // bk9MnAMpqqL8GKApDA1cXFYjV9oclg3IJjbBRMvl4eZv
// SIG // ieeP6Zi1c9N44+2jATx05V68bPYhiWcF7JedtbH9r6bp
// SIG // cqXDNOEvn/n0ajniLQSCW/zQnK58nRH55rVTGXS6OUo5
// SIG // 631Cs0o7Nz3CSnsnmOfiTpsbSlQ4aiM3vmq3SO7qQg1J
// SIG // JJGOtwQul2/k50W7j039YNnXWcLYgNZgNHu3oZMg/oG4
// SIG // qqVcCemKDb4oTX7X6A/tZXjRMV+5ZtvfQucLzAIHjd//
// SIG // IAajRWW0szKNLpHiTbSpyfq8awQOsp/qn96kyQqW9I33
// SIG // 2Jio8IUCCFmkIKYsCxryUgbtaeVkGBvgo6veynwUYUO4
// SIG // ZfU2o1UTK2csTRswTDGCBI8wggSLAgEBMIGHMHkxCzAJ
// SIG // BgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAw
// SIG // DgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3Nv
// SIG // ZnQgQ29ycG9yYXRpb24xIzAhBgNVBAMTGk1pY3Jvc29m
// SIG // dCBDb2RlIFNpZ25pbmcgUENBAgphCHdfAAAAAABKMAkG
// SIG // BSsOAwIaBQCggbwwGQYJKoZIhvcNAQkDMQwGCisGAQQB
// SIG // gjcCAQQwHAYKKwYBBAGCNwIBCzEOMAwGCisGAQQBgjcC
// SIG // ARUwIwYJKoZIhvcNAQkEMRYEFBxnegDhHKyrI65KkrgO
// SIG // 5Fn+AKvEMFwGCisGAQQBgjcCAQwxTjBMoCaAJABNAGkA
// SIG // YwByAG8AcwBvAGYAdAAgAEwAZQBhAHIAbgBpAG4AZ6Ei
// SIG // gCBodHQ6Ly93d3cubWljcm9zb2Z0LmNvbS9sZWFybmlu
// SIG // ZzANBgkqhkiG9w0BAQEFAASCAQAtTeyBIEAUWVnrPk5h
// SIG // lgA4p7Uh22nn8ZeYUcylap269+r6mhqyV6+FtRJc0cp1
// SIG // yvuqtKNu5Gk1s4QZqDt3ZHFJDndfQYYQQ39xhZ3akp0u
// SIG // 0AdZsGSAqIwkUeY91DbEIovA1Xoe2nDtUurGpYpDPboV
// SIG // GB84QpUTCliJPdWoQ/GhJgSH8McSvVgQmo2Ma5R718DJ
// SIG // Zd9ZLLbiv989VrLek41Rb+VaCGTUw9cKImFNX2eTRYUa
// SIG // q+tgNBjTbbmh3nFgseimlLuujF5p97rbA3S3fcu3u1Uu
// SIG // usQ7I6TRi5ntbTIU9/aA5yVwSitaMXlw13wMS908g7Wi
// SIG // Ir+BqG/I8If8lOhRoYICHTCCAhkGCSqGSIb3DQEJBjGC
// SIG // AgowggIGAgEBMIGFMHcxCzAJBgNVBAYTAlVTMRMwEQYD
// SIG // VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25k
// SIG // MR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24x
// SIG // ITAfBgNVBAMTGE1pY3Jvc29mdCBUaW1lLVN0YW1wIFBD
// SIG // QQIKYQPc9gAAAAAADDAHBgUrDgMCGqBdMBgGCSqGSIb3
// SIG // DQEJAzELBgkqhkiG9w0BBwEwHAYJKoZIhvcNAQkFMQ8X
// SIG // DTEwMTExMTIzMzkxMVowIwYJKoZIhvcNAQkEMRYEFAx9
// SIG // lFwhWwLD0ZImTE4DMIAT8ygnMA0GCSqGSIb3DQEBBQUA
// SIG // BIIBAGZafOmAjcw9oThAGXIzur3Jp6xw4oP3voYCfMYo
// SIG // trHlVBRw2ibIYhyGxCvseXyjJlWGZcBgzLZtdexHsxPJ
// SIG // ig+ksehwirv+WEcKpz+u/irj7n/rJy6JV0E2UihZAshx
// SIG // 3CTVFkBAznrgvSj+fCEXp4UoIfQyiFWiaLFqQt7YPVTn
// SIG // gP1ksZdcJEUPSHjhmAqx0oS6+R7uy8RoeSB9dFQ1EsgD
// SIG // lkyHd8jB5cHTjz8cpPtb4w1KFeRt0w1udc6ptyzyE/OR
// SIG // FQceg8M45Dnchs2BQMY7YAgJ9FVdpsbI9KUL8Pj87pgU
// SIG // RqPNjPwsdjoh0AfsyPICzVURAYb2/UJeux7ZGcQ=
// SIG // End signature block
