/******************************************
* WI_Newsfeed script for viewing Moreover newsfeeds- By Lawrence Carvalho (lawrence@nodetraveller.com)
* http://www.nodetraveller.com
******************************************/
function WI_Newsfeeds(objName, numMenuRows) {
	this.objName = objName;

	
	//numMenuRows is the number of rows to show in the pageset Menu (choose newsfeed menu)
	this.newsFeedContainer = document.getElementById("textHolder");
	this.newsFeedDivObj = document.getElementById("text");
	this.titleDivObj = document.getElementById("titleText");
	this.scriptObj = document.getElementById("scriptSrc");
	this.newsFeedMenuButton = document.getElementById("newsFeedMenuButton");
	this.newsFeedMenu = document.getElementById("newsFeedMenu");
	this.managementDivObj = document.getElementById("newsFeedManagement");
	this.actionMenu = document.getElementById("newsFeedActionMenu");
	this.favFeedsMenu = document.getElementById("favFeedsMenu");
	
	this.errTimeout = 0;
	this.ERR_TIMEOUT = 60;
	this.SCRIPT_OBJ_ID = "scriptSrc";
	this.article = new Array();
	this.printTimer = null;
	this.currentCategory = -1;
	this.channelTitle;
	this.defaultNewsFeed = readCookie("NewsFeedDefault");
	this.isMenuVisible = false;
	this.sortFavFeeds = false;
	this.menuRefs = new Array();	
	
	this.menu = new pageSet(this.objName+".menu",this.objName,"newsFeedMenu",".pageSet", numMenuRows);
	this.selectBox = new selectBox(this.objName+".selectBox","selectText",true);
	this.populateSelectBox();
	
}

WI_Newsfeeds.prototype.loadContent = loadContent
WI_Newsfeeds.prototype.printArticles = printArticles
WI_Newsfeeds.prototype.setTitle = setTitle
WI_Newsfeeds.prototype.refresh = refresh
WI_Newsfeeds.prototype.setDefaultNewsFeed = setDefaultNewsFeed
WI_Newsfeeds.prototype.stopScrolling = stopScrolling
WI_Newsfeeds.prototype.scrollUp = scrollUp
WI_Newsfeeds.prototype.scrollDown = scrollDown
WI_Newsfeeds.prototype.scrollTo = scrollTo
WI_Newsfeeds.prototype.grabBar = grabBar
WI_Newsfeeds.prototype.manageNewsfeeds = manageNewsfeeds
WI_Newsfeeds.prototype.cancelNewsfeedMenu = function() {
	this.hideNewsfeedMenu();
	this.showFeeds();
}
/*******************************************************************************
Function: 	showMenu
Action	:	Calls the openMenu method which opens the action menu
*******************************************************************************/
WI_Newsfeeds.prototype.showMenu = function(event) {
	this.openMenu(event,this.actionMenu)
}


/*******************************************************************************
Function: 	showFeeds
Action	:	Shows the newsfeeds and also updates the scroll-
			bar and title
*******************************************************************************/
WI_Newsfeeds.prototype.showFeeds = function() {
	this.newsFeedDivObj.style.visibility = "visible";
	if (this.yScrollBar)
		this.yScrollBar.show();
	this.setTitle(this.channelTitle);
}


/*******************************************************************************
Function: 	hideFeeds
Action	:	Hides the newsfeeds
*******************************************************************************/
WI_Newsfeeds.prototype.hideFeeds = function() {
	this.newsFeedDivObj.style.visibility = "hidden";
}


/*******************************************************************************
Function: 	showNewfeedMenu
Action	:	Shows the newsfeedmenus
*******************************************************************************/
WI_Newsfeeds.prototype.showNewsfeedMenu = function() {
	this.hideFeeds();
	this.hideManagementSection();
	this.newsFeedMenu.style.visibility = "visible";
	this.yScrollBar.hide();
	this.setTitle("Category Menu");
	this.isMenuVisible = true;
	this.hideMenus();
}


/*******************************************************************************
Function: 	hideNewsFeedMenu
Action	:	Hides the newsFeeds menu
*******************************************************************************/
WI_Newsfeeds.prototype.hideNewsfeedMenu = function() {
	this.newsFeedMenu.style.visibility = "hidden";
	if(this.yScrollBar)
		this.yScrollBar.show();
	this.isMenuVisible = false;	
}

/*******************************************************************************
Function: 	showManagementSection
Action	:	Shows the management section
*******************************************************************************/
WI_Newsfeeds.prototype.showManagementSection = function() {
	this.managementDivObj.style.display="block";
	this.setTitle("NewsFeed Management");
	this.hideMenus();
	this.selectBox.updateBox();
}


/*******************************************************************************
Function: 	hideManagementSection
Action	:	Shows the management section
*******************************************************************************/
WI_Newsfeeds.prototype.hideManagementSection = function() {
	this.managementDivObj.style.display="none";
}


/*******************************************************************************
Function: 	getRandomFeed
Action	:	loads a random newsfeed
*******************************************************************************/
WI_Newsfeeds.prototype.getRandomFeed = function() {
	this.loadContent(parseInt(Math.random()*category_array.length));
	this.hideMenus();
}


/*******************************************************************************
Function: 	setDefaultNewsFeed
Action	:	Sets the current newsfeed as the default newfeed
*******************************************************************************/
function setDefaultNewsFeed(feedNum) {
	this.defaultNewsFeed = feedNum;
	saveCookie("NewsFeedDefault", this.defaultNewsFeed ,365*10)
}


/*******************************************************************************
Function: 	loadContent
Action	:	Loads the newsfeed using the specified feed num
*******************************************************************************/
function loadContent(feedNum) {
	this.hideNewsfeedMenu();
	this.hideManagementSection();
	this.showFeeds();
	if (isNaN(parseInt(feedNum))){
		feedNum = readCookie("currentNewsFeed");
		if(isNaN(parseInt(feedNum)))
			feedNum = this.defaultNewsFeed;
	}
	article = new Array();
	if (this.scriptObj) 
		this.newsFeedDivObj.removeChild(this.scriptObj);
	
	while(this.newsFeedDivObj.hasChildNodes()){
		this.newsFeedDivObj.removeChild(this.newsFeedDivObj.lastChild);
	}
	script = document.createElement('script');
	script.src = "http://p.moreover.com/cgi-local/page?"+category_array[feedNum].feed_name+"&o=js";
	script.type = 'text/javascript';
	script.defer = true;
	script.id = this.SCRIPT_OBJ_ID;
	
	this.newsFeedDivObj.appendChild(script);
	this.scriptObj = script;
	this.setTitle("Loading Articles...");
	
	this.printTimer = setTimeout(this.objName+".printArticles("+feedNum+")",1000);
}


/*******************************************************************************
Function: 	setTitle
Action	:	Sets the title to the specified new title
*******************************************************************************/
function setTitle(newTitle) {
	this.titleDivObj.innerHTML = newTitle;
}

var article = new Array;


/*******************************************************************************
Function: 	printArticles
Action	:	Generates the actual list of newsfeeds
*******************************************************************************/
function printArticles(feedNum) {
	clearTimeout(this.printTimer);
	if (article.length!=0) {

		var numOfArticles = article.length;
		for(i=0;i<numOfArticles;i++) {
			newLink = document.createElement("a");
			newLink.href = article[i].url;
			newLink.target = "_blank";
			newLink.innerHTML = article[i].headline_text;
			newLink.className = "morehl";
			this.newsFeedDivObj.appendChild(newLink);
			this.newsFeedDivObj.appendChild(document.createElement("br"));
			newLink = document.createElement("a");
			newLink.href = article[i].document_url
			newLink.target = "_blank";
			newLink.innerHTML = article[i].source;
			newLink.className = "moresrc";
			this.newsFeedDivObj.appendChild(newLink);
			this.newsFeedDivObj.appendChild(document.createTextNode('\u00A0'));
			this.newsFeedDivObj.appendChild(document.createTextNode('\u00A0'));
			newSpan = document.createElement("span");
			newSpan.className = "moreti";
			newSpan.appendChild(document.createTextNode(article[i].harvest_time));
			this.newsFeedDivObj.appendChild(newSpan);
			this.newsFeedDivObj.appendChild(document.createElement("hr"));
		}

	this.setTitle(category_array[feedNum].full_name);
	this.currentCategory = feedNum;
	this.channelTitle = category_array[feedNum].full_name;
	this.errTimeout = 0;
	
	this.yScrollBar = new scrollBar(this.objName+".yScrollBar", "Y", "textHolder", "text", "yTrack", "yBar","titleText", "upArrow", "downArrow", null, null, false);
	this.hideNewsfeedMenu();
	saveCookie("currentNewsFeed",feedNum)
	
	}
	else {
		if (this.errTimeout <this.ERR_TIMEOUT) {
			this.printTimer = setTimeout(this.objName+".printArticles("+feedNum+")",1000);
			this.errTimeout++;
		}
		else { 
			this.setTitle("Error loading newsfeed.");
		}
	}	
}


/*******************************************************************************
Function: 	manageNewsfeeds
Action	:	Shows the manage Newsfeed screen
*******************************************************************************/
function manageNewsfeeds() {
	this.showManagementSection();
	this.hideNewsfeedMenu();
	this.hideFeeds();
	if (this.yScrollBar)
		this.yScrollBar.hide();

}


/*******************************************************************************
Function: 	refresh
Action	:	Refreshs the current newsfeed list 
*******************************************************************************/
function refresh() { 
	this.loadContent(this.currentCategory);
	//this.actionMenu.style.visibility="hidden";
	this.hideMenus();
}


/*******************************************************************************
Function: 	stopScrolling
Action	:	stops the scrollbar from scrolling - Really an interface method to 
			the scrollbar object corresponding method
*******************************************************************************/
function stopScrolling() {
	this.yScrollBar.stopScroll();
}


/*******************************************************************************
Function: 	scrollUp
Action	:	Scrolls the scrollbar upwards - Really an interface method to 
			the scrollbar objects corresponding method
*******************************************************************************/
function scrollUp(){
	this.yScrollBar.incScroll(-2);
}


/*******************************************************************************
Function: 	scrollDown
Action	:	Scrolls the scrollbar downwards - Really an interface method to 
			the scrollbar objects corresponding method
*******************************************************************************/
function scrollDown(){ 
	this.yScrollBar.incScroll(2);
}


/*******************************************************************************
Function: 	scrollTo
Action	:	Scrolls the scrollbar to a particular position - Really an interface 
			method to the scrollbar objects corresponding method
*******************************************************************************/
function scrollTo(event) {
	this.yScrollBar.clickScroll2(event);
}


/*******************************************************************************
Function: 	grabBar
Action	:	grabs the scrollbar (for drag purposes)- Really an interface method 
			to the scrollbar objects corresponding method
*******************************************************************************/
function grabBar(event) {
	this.yScrollBar.grabBar(event);
}


/*******************************************************************************
Function: 	hideMenus
Action	:	Hides all the menus
*******************************************************************************/
WI_Newsfeeds.prototype.hideMenus = function(){
	for(var i=0;i<this.menuRefs.length;i++) {
		var menuObj = this.menuRefs.pop();
		menuObj.style.visibility="hidden";
	}

}


/*******************************************************************************
Function: 	setCurrentFeedAsDefault
Action	:	Sets the current feed as the default
*******************************************************************************/
WI_Newsfeeds.prototype.setCurrentFeedAsDefault = function() {
	this.setDefaultNewsFeed(this.currentCategory);
	this.hideMenus();
}


/*******************************************************************************
Function: 	populateSelectBox
Action	:	Populates the select box
*******************************************************************************/
WI_Newsfeeds.prototype.populateSelectBox = function() {
	//get favs from cookie
	var favsNumbers = "";
	try {
		favsNumbers = readCookie("FavsNewsFeed").split(",");
	} catch(err) {
		favsNumbers="";
	}
	
	if (favsNumbers!="") {
		for(var i=0;i<favsNumbers.length;i++) {
			var feedNumber = favsNumbers[i];
			var isDefault = (this.defaultNewsFeed==feedNumber);
			this.selectBox.addOption(new tDOMOption("<strong>"+category_array[feedNumber].channel_name+":</strong><br />" + category_array[feedNumber].full_name,feedNumber,isDefault),false,null);
		}
	}
	this.populateFavFeedsMenu();
}



/*******************************************************************************
Function: 	populateFavFeedsMenu
Action	:	Populate the Favourite newsfeeds menu
*******************************************************************************/
WI_Newsfeeds.prototype.populateFavFeedsMenu = function() {
	//clear favFeedsMenu
	while(this.favFeedsMenu.hasChildNodes()){
		this.favFeedsMenu.removeChild(this.favFeedsMenu.lastChild);
	}
	var favs = this.selectBox.containerDiv.getElementsByTagName("span");
	var numFavs = favs.length;

	if (numFavs==0){
		var span = document.createElement("span");
		span.className="selectOff"
		span.appendChild(document.createTextNode("<empty>"));
		this.favFeedsMenu.appendChild(span);
	}
	else {
		for(i=0;i<numFavs;i++){
			var option = this.selectBox.options[i];
			var span = document.createElement("span");
			span.className = "selectOff";
			span.innerHTML=option.getText();
			var thisObj = this;
			var optValue = option.getValue();
			span.optValue = optValue;
			addEvent(span,"mouseover",function(event) {if (event.target) {
						var srcElem= event.target.parentNode ;
						if (srcElem.nodeName=="DIV")
							return;
						while (srcElem.nodeName!="SPAN") {
							srcElem = srcElem.parentNode
						}
						
					}
					else  {
						var srcElem = event.srcElement;
						while (srcElem.tagName!="SPAN") {
							srcElem = srcElem.parentNode
						}
	
					}
					
					srcElem.className="selectOn"; },false);
			addEvent(span,"mouseout",function(event) {if (event.target) {
						var srcElem= event.target.parentNode ;
						if (srcElem.nodeName=="DIV")
							return;
						while (srcElem.nodeName!="SPAN") {
							srcElem = srcElem.parentNode
						}
						
					}
					else  {
						var srcElem = event.srcElement;
						while (srcElem.tagName!="SPAN") {
							srcElem = srcElem.parentNode
						}
	
					}
					
					srcElem.className="selectOff"; },false);
			addEvent(span,"mousedown", function(event){ 
					if (event.target) {
						var srcElem= event.target.parentNode ;
						if (srcElem.nodeName=="DIV")
							return;
						if (srcElem.tagName=="STRONG")
							srcElem = srcElem.parentNode;
					}
					else  {
						var srcElem = event.srcElement;
						if (srcElem.tagName=="STRONG")
							srcElem = srcElem.parentElement;
					}
					var optionValue = srcElem.optValue;	
					thisObj.loadContent(optionValue); 
					thisObj.hideMenus();
			}, false);
			this.favFeedsMenu.appendChild(span);
		}
	}
}


/*******************************************************************************
Function: 	addFavNewsFeed
Action	:	Adds a new newsfeed to the list of favourite newsfeeds
*******************************************************************************/
WI_Newsfeeds.prototype.addFavNewsfeed = function () {
	var feedNum = this.currentCategory;
	this.selectBox.addOption(new tDOMOption("<strong>"+category_array[feedNum].channel_name+":</strong><br />" + category_array[feedNum].full_name,feedNum,false), true, function(feedNumber) {

	var cookieStatus = readCookie("FavsNewsFeed");
	
		if (cookieStatus!=null) {
			if (cookieStatus.indexOf(feedNumber)==-1) {

				var oldFavs = cookieStatus;
				var newFavs = oldFavs + "," + feedNumber;
			saveCookie("FavsNewsFeed", newFavs ,365*2)
			}
		}
		else {

			var newFavs = feedNumber;
		saveCookie("FavsNewsFeed", newFavs ,365*2)
		}
});
	if (this.sortFavFeeds)
		this.sortFeeds();
	this.hideMenus();	
	this.populateSelectBox();
}


/*******************************************************************************
Function	: 	removeFavNewsfeed
Action		:	Removes newsfeed from the favourites list
Arguments	:	removeAll - a boolean which denotes whether to remove all 
				newsfeeds from the favourites menu or just the currently 
				selected one.
*******************************************************************************/
WI_Newsfeeds.prototype.removeFavNewsfeed = function (removeAll) {
	var thisObj = this;
	this.selectBox.removeOption(removeAll,true, function(removeAll) {
		if(removeAll) {
			eraseCookie("FavsNewsFeed");
		}
		else {
			if(thisObj.selectBox.getLength()>1) {
				var index = thisObj.selectBox.selectedIndex;
				var feedNum = thisObj.selectBox.options[index].getValue();
				var oldFavs = readCookie("FavsNewsFeed").split(",");
				var newFavs = oldFavs.slice(0,index);
				newFavs = newFavs.concat(oldFavs.slice(index+1,oldFavs.length));
				newFavs = newFavs.join()
				saveCookie("FavsNewsFeed", newFavs ,365*2);
			}
			else saveCookie("FavsNewsFeed", "" ,365*2);
		}
	});
	this.populateSelectBox();
}


/*******************************************************************************
Function: 	sortFeeds
Action	:	Sorts the newsfeeds by Text
*******************************************************************************/
WI_Newsfeeds.prototype.sortFeeds = function() {
	this.selectBox.sortByText(false)
}


/*******************************************************************************
Function	: 	toggleSort
Action		:	Toggles whether to sort the fav newsfeeds when they are added.
Arguments	:	event	- 	mouse event object
*******************************************************************************/
WI_Newsfeeds.prototype.toggleSort = function(event) {
	this.sortFavFeeds=!this.sortFavFeeds;
	var srcObj = (event.target) ? event.target : event.srcElement;
	(this.sortFavFeeds) ? srcObj.style.backgroundColor="#999999" : srcObj.style.backgroundColor="#FFFFFF"
	if (this.sortFavFeeds)
		this.sortFeeds();
}


/*******************************************************************************
Function	: 	openFavsMenu
Action		:	Opens the Favourite newsfeeds Menu
Arguments	:	event	- 	mouse event object
*******************************************************************************/
WI_Newsfeeds.prototype.openFavsMenu = function(event) {
	var thisObj = this;
	this.openMenu(event,this.favFeedsMenu,true);
}


/*******************************************************************************
Function	: 	openMenu
Action		:	Shows the specifed menu
Arguments	:	event 	- 	mouse event object
				el 		- 	reference to a div element
				isSub	-	a boolean denoting whether the menu is a submenu as
							opposed to a root menu
*******************************************************************************/
WI_Newsfeeds.prototype.openMenu = function (event,el,isSub) {
  var x, y;
  if (isSub) {
	//get root menu;
	var obj = (event.target)? event.target.parentNode.parentNode: event.srcElement.parentElement;
	if(obj.nodeName=="BODY") return;
	
	obj.onmouseout = null;
	this.menuRefs.push(obj);
  }

 this.menuRefs.push(el);
 var thisObj = this;
 closeMenuActionfn = function() {
	for(i=0;i<thisObj.menuRefs.length;i++) {
			var menuObj = thisObj.menuRefs.pop();
			menuObj.style.visibility="hidden";
	}
 }
 el.onmouseout = closeMenu
  if (window.event) {
    x = window.event.clientX + document.documentElement.scrollLeft
                             + document.body.scrollLeft;
    y = window.event.clientY + document.documentElement.scrollTop +
                             + document.body.scrollTop;
  }
  else {
    x = event.clientX + window.scrollX;
    y = event.clientY + window.scrollY;
  }
	var srcObj = (event.target) ? event.target : event.srcElement;
	if (isSub)
		srcObj = (event.target) ? event.target.parentNode : srcObj;
	
	srcTop = srcObj.offsetTop - el.offsetHeight ;

  x += 5; y += (srcTop) /*+ ((event.target) ? 0 : event.srcElement.offsetHeight)*/;
 
  el.style.left = x + "px";
  el.style.top  = y + "px";
  el.style.visibility = "visible";

}


/*******************************************************************************
Function	: 	closeMenu
Action		:	Closes the menu when the mouse is moved away from it
Arguments	:	event	-	mouse event object
*******************************************************************************/
function closeMenu(event) {
  var current, related;

  if (window.event) {
    current = this;
	related = window.event.toElement;
  }
  else {
    current = event.currentTarget;
    related = event.relatedTarget;
  }
  
  if (current != related && !contains(current, related))  {
		closeMenuActionfn();
	}
}


/*******************************************************************************
Function	: 	contains
Action		:	Checks to see if one element contains another
Arguments	:	a	-	an element
				b	-	another element
Note		:	Very slightly modified version. Original version found at
				www.brainjar.com
*******************************************************************************/
function contains(a, b) {
try {
  // Return true if node a contains node b.
	  while (b.parentNode)
	    if ((b = b.parentNode) == a)
	      return true;
	  return false;
 }	catch(err) {
 	;
 }
}


/*******************************************************************************
Function	:   _sortByProperty
Action		:   Sorts an array using the specified property
Arguments	:	property	-	specified property by which to sort by
				ref			-	a boolean denoting whether to reverse the array
Notes		:	This method was found at www.scottandrew.com and so was not 
				written by me
*******************************************************************************/
function _sortByProperty(property,rev)
{
	var fn = function(a,b)
	{
		if (a[property] < b[property])
		{
			return (rev)? 1:-1;
		} else if (a[property] > b[property])
		{
			return (rev)? -1:1;
		} else
		{
			return 0;
		}
	}
	this.sort(fn);
	return this;
}
Array.prototype.sortByProperty = _sortByProperty;
