// News Scroller and CopyRight Software Add-ons

// API
// These are the functions you will call to use the NewsScroller from your web page

window.NewsScrollerInstance = new Array();//instance array

// NewsScroller_Initialize
//	Parameters:
//		elmDivForNews: object reference to a DIV element that will be used to display the news
//	Return:
//		returns a NewsScroller object, with supporting properties and methods
function NewsScroller ()
{

	/*if (window.NewsScrollerInstance != null)
		{
		window.alert("Only one NewsScroller control is allowed on a page.");
		return;
		}*/
		
		//allows multiple instances
	this.InstanceCount=window.NewsScrollerInstance.length;
	window.NewsScrollerInstance[this.InstanceCount]=this;
	
	this.LoadXML = NewsScroller_LoadXML;
	this.AddNewsItem = NewsScroller_AddNewsItem;
	this.Clear = NewsScroller_Clear;
	this.StartScrolling = NewsScroller_StartScrolling;
	this.StopScrolling = NewsScroller_StopScrolling;
	this.Render = NewsScroller_Render;
	
	// public properties
	this.className = "Scroller";
	this.itemNormalClassName = "";

	this.scrollRate = 35;
	this.scrollStep = 1;
	this.scrollPause = 4000;
	this.ElementGap= 15; // gap between elements
	
	// internal use
	this.RenderChildren = NewsScroller_RenderChildren;
	this.NewsScrollerScrollNews = NewsScroller_ScrollNews;//not actually used

	this.renderedControl = "";
	this.itemsText = new Array(); //heading
	this.itemsLink = new Array(); //heading link
	this.itemsLinkText = new Array(); //text
	this.itemCount = 0;
	
	this.scrollEnabled = false;
}

function NewsScroller_LoadXML (sXmlID)
{
	this.Clear();
	if(window.ActiveXObject)
	{
	//	var elmXml = document.getElementById(sXmlID);
	//	var xDoc = elmXml.XMLDocument;
		xDoc= new ActiveXObject("Microsoft.XMLDOM");
		xDoc.async=false;
		xDoc.load(sXmlID);
		
		var xItems = xDoc.selectNodes("xml/Items/Item");
		for (var iNode = 0; iNode < xItems.length; iNode++)
		{
			var xItem = xItems[iNode];
			var xText = xItem.selectSingleNode("Text").firstChild;
			var xLink = xItem.selectSingleNode("Link");
			var xLinkText = xItem.selectSingleNode("LinkText").firstChild; //this should be a CDATA block if you want HTML, seems to work fine with plain text
			this.AddNewsItem(xText.data, xLink.text, xLinkText.data);
		}
	}//else if activex doesnt work we need to call the addnewsitems another way
	else if(XMLHttpRequest)
	{//assume its firefox
		var XMLHttp = new XMLHttpRequest();
		XMLHttp.open("GET", sXmlID, false);
		XMLHttp.send(null);
		xDoc=XMLHttp.responseXML;
		var xItems = xDoc.selectNodes("Items/Item", xDoc.documentElement);
		for (var iNode = 0; iNode < xItems.length; iNode++)
		{
			var xItem = xItems[iNode];
			//alert(xItem.selectSingleNode("Text", xItem).childNodes[1].nodeValue)
  			var xText = xItem.selectSingleNode("Text", xItem).childNodes[1];
			var xLink = "";// xItem.selectSingleNode("Link", xItem).childNodes[1]; //blanked to make it work
			var xLinkText = xItem.selectSingleNode("LinkText", xItem).childNodes[1]; //this should be a CDATA block if you want HTML, seems to work fine with plain text
			this.AddNewsItem(xText.nodeValue, xLink.nodeValue, xLinkText.nodeValue);
		}
		
		
	}
	var elmControl = document.getElementById(this.renderedControl);
	this.RenderChildren(this.renderedControl);
	
}


function NewsScroller_AddNewsItem (strText, strLink, strLinkText)
{
	this.itemsText[this.itemCount] = strText;
	this.itemsLink[this.itemCount] = strLink;
	this.itemsLinkText[this.itemCount] = strLinkText;
	this.itemCount++;
}

function NewsScroller_Clear ()
{
	this.StopScrolling ();
	var elmControl = document.getElementById(this.renderedControl);
	while (elmControl.childNodes.length > 0)
		elmControl.removeChild(elmControl.childNodes[0]);
	this.itemsText = new Array();
	this.itemsLink = new Array();
	this.itemsLinkText = new Array();
	this.itemCount = 0;
}

function NewsScroller_StartScrolling ()
{
	if (this.itemCount > 0)
		{
		var sControlName = this.renderedControl;
		if (sControlName == null)
			{
			window.alert ("You must render a control before you can start scrolling it.");
			return;
			}
		var elmControl = document.getElementById(sControlName);
		var elmItem0 = document.getElementById(sControlName+"0");
		if (this.itemCount > 1)
			{
			var elmItem1 = document.getElementById(sControlName + "1");
			this.cySeparator = (elmItem1.offsetTop - elmItem0.offsetTop) - elmItem0.offsetHeight;
			}
		else
			{
			this.cySeparator = 0;
			}
		
			if (this.ScrollTimerID == null)
			{
				if(window.setInterval)
					this.ScrollTimerID = window.setInterval("NewsScroller_ScrollNews("+this.InstanceCount+")", this.scrollRate); //passes the instance count so there can be more than one
						
			}
		}
}

function NewsScroller_StopScrolling ()
{
	window.clearInterval(this.ScrollTimerID);
	this.ScrollTimerID = null;
}

function NewsScroller_Render(sControlID)
{
	if (sControlID.length == 0)
		{
		window.alert("You must provide a unique ID for the rendered control.");
		return;
		}
	var elmControl = document.getElementById(sControlID);
	if (elmControl != null)
		{
		window.alert("A NewsScroller with this ID has already been rendered. Please use a unique ID.");
		return;
		}
	this.renderedControl = sControlID;
	
	// <DIV>
	document.write("<div");
	document.write(" id=\"" + sControlID + "\"");
	document.write(" class=\"" + this.className + "\"");
	document.write(" style=\"position: relative; width: 100%; height: 100%; \"");
	document.write(">");
	
	// </DIV>
	document.write("</div>");

	this.RenderChildren(sControlID);
 
	var dtNow = new Date();
	var dtResume = new Date(dtNow.getFullYear(), dtNow.getMonth(), dtNow.getDate(), dtNow.getHours(), dtNow.getMinutes(), dtNow.getSeconds(), this.scrollPause);
	elmControl = document.getElementById(sControlID);
	elmControl.ResumeDateTime = dtResume;
}

// Supporting functions
function NewsScroller_RenderChildren()
{
	var sControlID = this.renderedControl;
	elmControl = document.getElementById(sControlID);
	
	// <DIV>
	elmDiv = document.createElement("div");
	elmDiv.style.position = "absolute";
	elmDiv.style.left = "0px";
	elmDiv.style.width = "100%";
	elmDiv.style.height = "100%";
	elmDiv.style.overflow = "hidden";
	elmControl.appendChild(elmDiv);
	
	for (var nItem = 0; nItem < this.itemCount; nItem++)
		{
		var sItemName = sControlID + nItem.toString();
		
		var elmP = document.createElement("p");
		elmP.id = sItemName;
		elmP.style.position = "relative";
		elmP.style.top = "0px";
		elmP.style.width = "100%";
		elmP.className = this.itemNormalClassName;
		elmDiv.appendChild(elmP);
		
		if(this.itemsLink[nItem])
		{
			var elmA = document.createElement("a");
			elmA.className = this.itemNormalClassName;
			elmA.href = this.itemsLink[nItem];
			elmP.appendChild(elmA);
			
			var tn = document.createTextNode(this.itemsText[nItem]);
			elmA.appendChild(tn);
			
			var elmBr=document.createElement("br"); //new line after the link
			elmP.appendChild(elmBr);
		}else
		{
			elmP.innerHTML+=this.itemsText[nItem];
			
			var elmBr=document.createElement("br"); //new line after the link
			elmP.appendChild(elmBr);
		}
		
		//var textnode=document.createHTMLNode(this.itemsLinkText[nItem]);
		elmP.innerHTML+=this.itemsLinkText[nItem]; // adds the html
		
		var elmBr=document.createElement("br"); //adds a new line just in case, this could be any separator really
		elmP.appendChild(elmBr);
		
		
		}
}

function NewsScroller_ScrollNews(nsCount)
{
	var ns = window.NewsScrollerInstance[nsCount]; //gets the right instance of the news scroller
	var sControlName = ns.renderedControl;
	if (sControlName.length == 0)
		{
		window.alert ("Do not call ScrollNews directly. Use the Start method of the NewsScroller object.");
		return;
		}
	var elmControl = document.getElementById(sControlName);
	if (new Date() >= elmControl.ResumeDateTime)
		{
		// see whether any item is about to reach the top,
		var cyOffset = 0;
		for (var nItem = 0; nItem < ns.itemCount; nItem++)
			{
			var sItemName = sControlName + nItem.toString();
			var elmItem = document.getElementById(sItemName);
			if ((elmItem.offsetTop > 0) && ((elmItem.offsetTop - ns.scrollStep) <= 0))
				{
				// the top of this item has reached the top of the control,
				// so pause scrolling for the whole control
				var dtNow = new Date();
				var dtResume = new Date(dtNow.getFullYear(), dtNow.getMonth(), dtNow.getDate(), dtNow.getHours(), dtNow.getMinutes(), dtNow.getSeconds(), ns.scrollPause);
				elmControl.ResumeDateTime = dtResume;
				cyOffset = elmItem.offsetTop;
				}
			}
		if (cyOffset > 0)
			{
			// control is just now paused, so scroll all items up 
			// in order to put the top item flush with the top of the control
			for (var nItem = 0; nItem < ns.itemCount; nItem++)
				{
				var sItemName = sControlName + nItem.toString();
				var elmItem = document.getElementById(sItemName);
				//elmItem.style.pixelTop = elmItem.style.pixelTop - cyOffset; 
				elmItem.style.top = parseInt(elmItem.style.top) - cyOffset;
				}
			}
		else
			{
			// the control is not paused, so scroll every item up by one step
			for (var nItem = 0; nItem < ns.itemCount; nItem++)
				{
				var sItemName = sControlName + nItem.toString();
				var elmItem = document.getElementById(sItemName);
				//elmItem.style.pixelTop = parseInt(elmItem.style.pixelTop) - ns.scrollStep;
				elmItem.style.top = parseInt(elmItem.style.top) - ns.scrollStep;
				
				
				}
			}
		// see whether any items have scrolled off the top
		for (var nItem = 0; nItem < ns.itemCount; nItem++)
			{
			var sItemName = sControlName + nItem.toString();
			var elmItem = document.getElementById(sItemName);
			if ((elmItem.offsetTop + elmItem.offsetHeight) <= 0)
				{
				// the bottom of this item has scrolled beyond the top of the control,
				// so move it to the bottom of the control
				if (ns.itemCount > 1)
					{
					var sBottomItemName;
					if (nItem == 0)
						sBottomItemName = sControlName + (ns.itemCount - 1).toString();
					else
						sBottomItemName = sControlName + (nItem - 1).toString();
					var elmBottomItem = document.getElementById(sBottomItemName);
					//elmItem.style.pixelTop = (elmBottomItem.offsetTop + elmBottomItem.offsetHeight + ns.cySeparator + ns.ElementGap) - (elmItem.offsetTop - elmItem.style.pixelTop);
					elmItem.style.top = parseInt((elmBottomItem.offsetTop + elmBottomItem.offsetHeight + ns.cySeparator + ns.ElementGap) - (elmItem.offsetTop - parseInt(elmItem.style.top)));
					}
				else
					{
					//elmItem.style.pixelTop = elmItem.parentElement.offsetHeight;
					//alert(elmItem.parentElement.offsetHeight);
					elmItem.style.top = parseInt(elmItem.parentNode.offsetHeight);
				}
				}
			}
		}
}

// mozXPath [http://km0ti0n.blunted.co.uk/mozxpath/] km0ti0n@gmail.com
// Code licensed under Creative Commons Attribution-ShareAlike License 
// http://creativecommons.org/licenses/by-sa/2.5/
if( document.implementation.hasFeature("XPath", "3.0") )
{
	XMLDocument.prototype.selectNodes = function(cXPathString, xNode)
	{
		if( !xNode ) { xNode = this; } 

		var oNSResolver = this.createNSResolver(this.documentElement)
		var aItems = this.evaluate(cXPathString, xNode, oNSResolver, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null)
		var aResult = [];
		for( var i = 0; i < aItems.snapshotLength; i++)
		{
			aResult[i] =  aItems.snapshotItem(i);
		}
		
		return aResult;
	}
	XMLDocument.prototype.selectSingleNode = function(cXPathString, xNode)
	{
		if( !xNode ) { xNode = this; } 

		var xItems = this.selectNodes(cXPathString, xNode);
		if( xItems.length > 0 )
		{
			return xItems[0];
		}
		else
		{
			return null;
		}
	}

	Element.prototype.selectNodes = function(cXPathString)
	{
		if(this.ownerDocument.selectNodes)
		{
			return this.ownerDocument.selectNodes(cXPathString, this);
		}
		else{throw "For XML Elements Only";}
	}

	Element.prototype.selectSingleNode = function(cXPathString)
	{	
		if(this.ownerDocument.selectSingleNode)
		{
			return this.ownerDocument.selectSingleNode(cXPathString, this);
		}
		else{throw "For XML Elements Only";}
	}

}
