/*
Javascript functions and object constructors for active-content message board
Version 0.931
9/25/2006 9:03 AM
*/

// CONSTANTS
var PT_AMP = String.fromCharCode(38); // get an ampersand reference cuz we're in XML and it's a bitch to deal with
var PT_LF = String.fromCharCode(13); // get newline char
var PT_CR = String.fromCharCode(10); // get carriage return char
var PT_CRLF = PT_LF + PT_CR; // construct a windows CRLF
var PT_SPACE = String.fromCharCode(32); // get space character
var PT_NBSP = String.fromCharCode(160); // get non-breaking space character
var PT_AHAT = String.fromCharCode(194); // Uppercase A with circumflex (for stripping rogue xml entities)
var PT_SLASH = String.fromCharCode(47);; // literal slash
var PT_SLASHES = PT_SLASH + PT_SLASH; // double slash (won't get removed by code optimizers, etc.)
var PT_MONTHS = "January,February,March,April,May,June,July,August,September,October,November,December".split(",");
var PT_WEEKDAYS = "Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday".split(",");
var PT_CatListStr = location.search.match(/(catList=)([^&]+)/gim);
//Simple advanced search HTML
var advSearchHTML = "<table class=\"ptAdvSearch\"><tr><td><table><tr><td><input type=\"text\" id=\"ptSearchBox\" name=\"ptSearchBox\" onkeypress=\"if (event.keyCode == 13 || event.keyCode == 10){ptSearchButton.onclick(); return false;}\"></input><button type=\"button\" id=\"ptSearchButton\" name=\"ptSearchButton\" onclick=\"PT_goSearch(\'pt_acsearch.htm\');return false;\">Search</button><button id=\"ptAdvancedSearchButton\" onclick=\"PT_advancedSearch();return false;\">Advanced</button></td></tr></table></td></tr><tr><td><div id=\"ptAdvancedSearch\" style=\"display:none\"><table style=\"width:100%\"><tr><td>Search Type</td><td>Start Date</td><td>End Date</td><td>Sort By</td><td>Forums to Search</td></tr><tr><td class=\"ptSearchHeadLeft\"><select name=\"s_how\" id=\"s_how\"><option value=\"all\">Containing all of the words</option><option value=\"any\">Containing any of the words</option><option value=\"phrase\">Containing the exact phrase</option><option value=\"nat\">Answering the question</option><option value=\"bool\">Using the boolean expression</option></select></td><td class=\"ptSearchHeadRt\"><select name=\"s_after\" id=\"s_after\"><option value=\"0\">Today</option><option value=\"1\">Yesterday</option><option value=\"2\">Day Before Yesterday</option><option value=\"7\">1 Week Ago</option><option value=\"14\">2 Weeks Ago</option><option value=\"21\">3 Weeks Ago</option><option value=\"31\">1 Month Ago</option><option value=\"62\">2 Months Ago</option><option value=\"93\">3 Months Ago</option><option value=\"183\">6 Months Ago</option><option value=\"366\">1 Year Ago</option><option value=\"10000\">Beginning of Time</option></select></td><td class=\"ptSearchHeadRt\"><select name=\"s_before\" id=\"s_before\"><option value=\"0\">Today</option><option value=\"1\">Yesterday</option><option value=\"2\">Day Before Yesterday</option><option value=\"7\">1 Week Ago</option><option value=\"14\">2 Weeks Ago</option><option value=\"21\">3 Weeks Ago</option><option value=\"31\">1 Month Ago</option><option value=\"62\">2 Months Ago</option><option value=\"93\">3 Months Ago</option><option value=\"183\">6 Months Ago</option><option value=\"366\">1 Year Ago</option><option value=\"10000\">Beginning of Time</option></select></td><td class=\"ptSearchHeadRt\"><select name=\"s_order\" id=\"s_order\"><option value=\"Relevance\">Relevance</option><option selected=\"selected\" value=\"Newest\">Newest First</option><option value=\"Oldest\">Oldest First</option></select></td><td><label for=\"s_breadth_1\"><input type=\"radio\" name=\"s_breadth\" id=\"s_breadth_1\" value=\"0\">All</label><label for=\"s_breadth_2\"><input type=\"radio\" name=\"s_breadth\" id=\"s_breadth_2\" value=\"1\" checked=\"checked\">This</label></td></tr></table></div></td></tr></table>";

// global to keep track of whether or not advanced search is being used
// hack for demo purposes only
var PT_useAdvancedSearch = false; 

// Strips &nbsp; entities gratuitously supplied
// by the WYSIWYG editor.
function PT_nbspStripper(txt)
{
	var newText = txt.toString();
	var rex = new RegExp(PT_AHAT,"gim");
	newText = newText.replace(rex,PT_NBSP);

	return newText;
}


// diagnostic function for debugging
// adapt or change for production
function PT_showError(err)
{
	var div = document.createElement("DIV");
	var h3 = document.createElement("H3");
	var txt = document.createTextNode("ERROR: " + err.name);
	h3.appendChild(txt);
	var ul = document.createElement("UL");
	for (var prop in err)
	{
		var li = document.createElement("LI");		
		var txt = document.createTextNode(prop + " : " + err[prop]);
		li.appendChild(txt);
	}
	div.appendChild(h3);
	div.appendChild(ul);
	return div;	
}

function PT_loc(loc)
{
	for (var prop in loc)
	{
		this[prop] = loc[prop];
	}	
}

function PT_convertPtDate(dateStr,returnType)
{
	// parse dateStr
	var dateItems = dateStr.split("T")[0].split("-");
	var year = parseInt(dateItems[0],10);
	var month = parseInt(dateItems[1],10)-1;
	var day = parseInt(dateItems[2],10);
	var timeItems = dateStr.split("T")[1].split(":");
	var hours = parseInt(timeItems[0]);
	var minutes = parseInt(timeItems[1]);
	var seconds = parseInt(timeItems[2]);
	var d = new Date(year, month, day, hours, minutes, seconds);
	// adjust for timezone
	d = new Date(d.valueOf() - (d.getTimezoneOffset()*60000));
	switch (returnType)
	{
		case "short":
			var dd = d.toDateString().split(" ");
			dd.shift();
			var tt = d.toLocaleTimeString();
			return dd.join(" ") + "<br>" + tt;
			break;
			
		case "long":
			return d.toString();
			break;
			
		case "prospero":
			var today = new Date();
			var timeSinceMidnight = today.getHours() * 60 * 60;
			timeSinceMidnight += today.getMinutes() * 60;
			timeSinceMidnight += today.getSeconds();
			timeSinceMidnight *= 1000;
			var delta = today.valueOf() - d.valueOf();
			
			// parse date string
			var dd = d.toDateString().split(" ");
			dd.shift(); // get rid of day name
			if (today.getYear() == d.getYear()) dd.pop(); // get rid of year if same
			
			// get rid of seconds and lowercase the am/pm
			var tt = d.toLocaleTimeString();
			var aryTime = tt.split(" ");
			var aryTimePrefix = aryTime[0].split(":")
			aryTimePrefix.pop();
			if (aryTime.length>1)
			{
				tt = aryTimePrefix.join(":") + " " + aryTime[1].toLowerCase();
			}
			// if more than a day old, give long date, else just give time
			if (delta > timeSinceMidnight)
			{
				return dd.join(" ") + ", " + tt ;
			}
			else
			{
				return tt;
			}
			break;
			
		default:
			return d;
	}
}

// takes a semicolon delimited string, parses query string 
// and passes specific items to the SRC attribute of a script
// which will be written to the head element of a page
function PT_passQS(items)
{
	var aryItems = items.split(";");
	var aryPassItems = new Array();
	var locSearch = location.search;
	var imax = aryItems.length;
	for (var i=0;i<imax;i++)
	{
		var prop = aryItems[i];
		var rex = new RegExp(prop+"=[^&]+","gi");
		var propMatch = locSearch.match(rex);
		if (propMatch)
		{
			aryPassItems.push(propMatch);
		}
	}
	var uString = aryPassItems.join("&");
	uString = uString.replace(/\s+|(%20)/gi,"+");
	return uString;
}

// Returns a page navigator when a list of items is longer than its specified
// page length. Navigator has arrows for first, previous, next, and end, as well
// as a link to each individual page. Current page shows up as an unlinked number.
// Can be styled through CSS classnames.
//  Requires four params:
//    intItemsTotal             total number of items in all pages of list
//    intItemsCurIndex          which item are we currently on (db cursor)
//    intItemsPerPage           number of items per page
//    strQsName                 query string arg that specifies intItemsCurIndex value
function PT_navTable(intItemsTotal,intItemsCurIndex,intItemsPerPage,strQsName)
{
	try
	{
		// get integers for math calculations
		var fullPages = parseInt(intItemsTotal/intItemsPerPage); // how many complete pages do we have?
		var totalPages = Math.ceil(intItemsTotal/intItemsPerPage); // how many pages total (i.e., with remainder)
		var intLastItemsPerPage = intItemsTotal%intItemsPerPage; // how many items on last page
		var firstPageIndex = 1; 
		var curPage = Math.floor(intItemsCurIndex/intItemsPerPage); // integer of the current page number
		var prevPageIndex = (intItemsCurIndex > intItemsPerPage) ? intItemsCurIndex - intItemsPerPage : 1; // int val for prev page
		var lastPageIndex = intItemsTotal - intLastItemsPerPage + 1; // int val for last page;
		var nextPageTsn = (intItemsCurIndex < lastPageIndex) ? intItemsCurIndex + intItemsPerPage : lastPageIndex; // int val for next page
		// strings representing the various nav links (may be changed, replaced with images, etc.)
		var first = document.createTextNode("|< "); 
		var last = document.createTextNode(" >|"); 
		var prev = document.createTextNode(" < "); 
		var next = document.createTextNode("> "); 
		
		var href = location.href;
		var rex = new RegExp(strQsName+"=[^&]*","gi"); // search query string for current list index
			
		// create table to return
		var table = document.createElement("TABLE");
		table.className = "msgNavTable";
		var tr = document.createElement("TR");
		// First Page Link
		var td = document.createElement("TD");
		td.className = "msgArrow";
		if (curPage == 0)
		{
			td.style.color = "#CCC";
			td.appendChild(first);
		}
		else
		{
			var a = document.createElement("A");
			a.href = (href.match(rex)) ? href.replace(rex,strQsName + "="+firstPageIndex) : href + "&" + strQsName + "="+firstPageIndex;
			a.appendChild(first);
			td.appendChild(a);	
		}
		tr.appendChild(td);
		// Prev Page Link
		var td = document.createElement("TD");
		td.className = "msgArrow";
		if (curPage == 0)
		{
			td.style.color = "#CCC";
			td.appendChild(prev);
		}
		else
		{
			var a = document.createElement("A");
			a.href = (href.match(rex)) ? href.replace(rex,strQsName + "="+prevPageIndex) : href + "&" + strQsName + "="+prevPageIndex;
			a.appendChild(prev);
			td.appendChild(a);
		}
		tr.appendChild(td);
		
		// Individual Page Links	
		for (var i=0;i<totalPages;i++)
		{
			var pageTsn = (i * intItemsPerPage) + 1;
			var td = document.createElement("TD");
			td.style.textAlign = "center";
			txt = document.createTextNode((i+1).toString());
			if (i == curPage)
			{
				td.style.backgroundColor = "#BBB";
				td.style.color = "#FFF";
				td.style.fontWeight = "bold";
				td.appendChild(txt);
			}
			else
			{
			var a = document.createElement("A");
			a.href = (href.match(rex)) ? href.replace(rex,strQsName + "="+pageTsn) : href + "&" + strQsName + "="+pageTsn;
			a.appendChild(txt);
			td.appendChild(a);		
			}
			tr.appendChild(td);
		}
		
		// Next Page Link
		var td = document.createElement("TD");
		td.style.textAlign = "right";
		td.className = "msgArrow";
		if (curPage == totalPages-1)
		{
			td.style.color = "#CCC";
			td.appendChild(next);
		}
		else
		{
			var a = document.createElement("A");
			a.href = (href.match(rex)) ? href.replace(rex,strQsName + "="+nextPageTsn) : href + "&" + strQsName + "="+nextPageTsn;
			a.appendChild(next);
			td.appendChild(a);
		}
		tr.appendChild(td);
		// Last Page Link
		var td = document.createElement("TD");
		td.style.textAlign = "right";
		td.className = "msgArrow";
		if (curPage == totalPages-1)
		{
			td.style.color = "#CCC";
			td.appendChild(last);
		}
		else
		{
			var a = document.createElement("A");
			a.href = (href.match(rex)) ? href.replace(rex,strQsName + "="+lastPageIndex) : href + "&" + strQsName + "="+lastPageIndex;
			a.appendChild(last);
			td.appendChild(a);
		}
		tr.appendChild(td);
		table.appendChild(tr);
		// all done, send back to calling function
		return table;
	}
	catch (e)
	{
		return PT_showError(e);
	}
}

// Common code to add/remove query string search args
// and navigate to search page where they can be parsed
// and return a results set
function PT_goSearch(page)
{
	try
	{
		var searchBox = document.getElementById("ptSearchBox");
		var val = searchBox.value;
		if (val == "" && !PT_useAdvancedSearch)
		{
			alert("Please enter a value");
			return;
		} 
		var advTerms = new Array();
		var advString = new String();
		if (PT_useAdvancedSearch)
		{
			var elm = document.getElementById("s_how");
			if (elm) advTerms.push("how=" + elm.value);	
			var elm = document.getElementById("s_after");
			if (elm) advTerms.push("sda=" + elm.value);	
			var elm = document.getElementById("s_before");
			if (elm) advTerms.push("eda=" + elm.value);	
			var elm = document.getElementById("s_order");
			if (elm) advTerms.push("order=" + elm.value);
			if (document.forms["SearchForm"].s_breadth_1.checked)
			{
				advTerms.push("catList=all");
			} 	
			advString = (advTerms.length > 0) ? "&" + advTerms.join("&") : "";
		}
		else
		{
			if (document.forms["SearchForm"].s_breadth_1.checked)
			{
				advString = "&catList=all";
			} 	
		}
		val = val.replace(/\s+/gi,"+");
		var loc = window.location;
		var webtag = loc.search.match(/webtag=[^&]+/gi);
		var qs = "?" + webtag + "&q=" + val + "&startIndex=1" + advString;
		var wPath = loc.pathname.split("/");
		wPath.pop();
		wPath.push(page);
		var urlString = loc.protocol + PT_SLASHES + loc.host + wPath.join("/") + qs;
		loc.href = urlString;
	}
	catch (e)
	{
		return PT_showError(e);
	}
}

// simple DHTML mechanism for displaying/hiding advanced search controls
// and changing button name, etc.
function PT_advancedSearch()
{
	var advTable = document.getElementById("ptAdvancedSearch");
	var advBtn = document.getElementById("ptAdvancedSearchButton");
	if (PT_useAdvancedSearch)
	{
		advTable.style.display = "none";
		PT_useAdvancedSearch = false;
		advBtn.innerHTML = "Advanced";
	}
	else
	{
		advTable.style.display = "block";
		PT_useAdvancedSearch = true;
		advBtn.innerHTML = "Basic";
	}
}

// we have to set the advanced search form values on page load
function PT_setAdvancedSearchControls()
{
	var locSearch = location.search.replace("?","");
	var locSearchTerms = locSearch.split("&");
	var searchFields = new Array();
	var imax = locSearchTerms.length;
	var isAdvanced = false;
	for (var i=0;i<imax;i++)
	{
		var prop = locSearchTerms[i].split("=")[0];
		var val = locSearchTerms[i].split("=")[1];
		switch (prop)
		{
			case "how":
				var elm = document.getElementById("s_how");
				if (elm) elm.value = val;
				isAdvanced = true;
				break;	
			case "eda":
				var elm = document.getElementById("s_before");
				if (elm) elm.value = val;
				isAdvanced = true;
				break;	
			case "sda":
				var elm = document.getElementById("s_after");
				if (elm) elm.value = val;
				isAdvanced = true;
				break;	
			case "order":
				var elm = document.getElementById("s_order");
				if (elm) elm.value = val;
				isAdvanced = true;
				break;	
		}
	}
	if (isAdvanced)
	{
		// set advanced search flag to true, change button name, show advanced controls
		PT_useAdvancedSearch = true;
		document.getElementById("ptAdvancedSearchButton").innerHTML = "Basic";
		document.getElementById("ptAdvancedSearch").style.display = "block";
	}
	else 
	{
		// set default values
		var elm = document.getElementById("s_how");
		if (elm) elm.value = "all";
		var elm = document.getElementById("s_before");
		if (elm) elm.value = "0";
		var elm = document.getElementById("s_after");
		if (elm) elm.value = "366";
		var elm = document.getElementById("s_order");
		if (elm) elm.value = "Newest";

	}
}

// diagnostic function, delete for production if desired
function PT_objectShow(obj)
{
	var s = new String();
	for (var prop in obj)
	{
		s += prop + ": " + obj[prop] + PT_CRLF;	
	}
	alert(s);
}
// extended to return a string instead of just making an alert
function PT_objectShow(obj,isString)
{
	var s = new String();
	for (var prop in obj)
	{
		s += prop + ": " + obj[prop] + PT_CRLF;	
	}
	if (isString)
	{
		return (s);
	}
	else
	{
		alert(s);
	}
}

// returns a query string from a semicolon-delimited list of name-value pairs
// or navigates to new query string if navBool = true
// NOTE: this is a work in progress. It needs to have cases for deleting
// qs args successfully, etc. Should also be extended to handle raw
// query strings (&-delimited) as well as semicolon-delimited, and
// return a value in the same format as the input
function PT_updateQuery(args,navBool)
{
	var qsAry = args.split(";");
	var qs = location.search;
	var imax = qsAry.length;
	for (var i=0;i<imax;i++)
	{
		var ary = qsAry[i].split(":");
		var prop = ary[0];
		var val = ary[1];
		var rex = new RegExp(prop + "=[^&]*","gi");
		if (qs.match(rex))
		{
			if (val)
			{
				qs = qs.replace(rex,prop + "=" + val);	
			}
			else
			{
				qs = qs.replace(rex,"");	
			}
		}
		else
		{
			qs += PT_AMP + prop + "=" + val;	
		}
	}
	if (navBool)
	{
		location.search = qs;
	}
	else
	{
		qs = qs.replace(/&+/gi,"&");
		qs = qs.replace(/&$/gi,"");
	 	return qs;
	}
}

function PT_showCatList()
{
	if (PT_Cat_Object && PT_catList && PT_catList.categories)
	{
		var cats = PT_catList.categories;
		var imax = cats.length;
		var div = document.createElement("DIV");
		var h3 = document.createElement("H3");
		h3.innerHTML = "Categories Reference";
		div.appendChild(h3);
		for (var i=0;i<imax;i++)
		{
			var h4 = document.createElement("H4");
			h4.innerHTML = cats[i].catPhrase;
			var ul = document.createElement("UL");
			for (var prop in cats[i])
			{
				if (typeof cats[i][prop] == "string")
				{
					var li = document.createElement("LI");
					var txt = document.createTextNode(prop + ": " + cats[i][prop]);
					li.appendChild(txt);
					ul.appendChild(li);
				}
			}
			div.appendChild(h4);
			div.appendChild(ul);
		}
		document.body.appendChild(div);
	}
}


/* OBJECT CONSTRUCTORS */

// empty object constructor, superclass of all these objects
function PT_mbItem()
{
		
}
PT_mbItem.prototype.init = PT_objectPropertyInit;
// object constructor with common props 
function PT_objectPropertyInit(args)
{
	this._name = new String;
	this._parent = new Object();
	var aryArgs = args.split(";");
	var imax = aryArgs.length;
	for (var i=0;i<imax;i++)
	{
		var ary = aryArgs[i].split(":");
		var prop = ary[0];
		var val = ary[1];
		this[prop] = val;
	}
}

// this constructs the object based on the root node for
// discussion list or message list pages. Also hosts certain
// common methods for navigation, etc.
function PT_forum (args)
{
	this.init(args);

	this.folders = new Array();
    this.catList = new String();
    if (PT_CatListStr) this.catList = PT_CatListStr;
	var searchString = window.location.search.substr(1);
	var pairs = searchString.split(PT_AMP);
	var imax = pairs.length;
	
	// methods
	// mechanism for keeping track of and closing open windows
	this.openWins = new Array();
	this.windStem = "PT_popWin_";
	this.windex = 0;
	this.popWin = function (url) {
		this.windex++;
		var winName = this.windStem + this.windex.toString();
		this.openWins.push(window.open(url,winName,"width=800,height=600,scrollbars=yes,resizable=yes"));
	};
	this.closeWindow = function(win) {
		if (win) // close the child window
		{
			var idx = parseInt(win.name.split("_")[2]);
			win.close();
			this.openWins[idx] = null;
		}
		else // close all
		{
			while (this.openWins.length > 0)
			{
				var win = this.openWins.pop();
				if (win) win.close(); 
			}
		}
	};
	// open a window or navigate to a new location in this window
	this.getURL = function (args,pop) {
		var loc = window.location;
		var urlString = "http:/" + "/mb.espn.go.com/n/pfx/forum.aspx";
		var argList = args.split(";");
		var qs = argList.join(PT_AMP);
		qs = qs.replace(/:/gim,"=");
		urlString += "?" + qs;
		if (pop)
		{
			this.popWin(urlString + "&ptpw=true");
		}
		else
		{
			window.location = urlString;
		}
	};
	// get all the discussions and sort them, even if there are multiple folders
	this.getEarliestDiscussionDate = function(bolEarliestDate) {
		this.dscDates = new Array();
		var imax = this.folders.length;
		for (var i=0;i<imax;i++)
		{
			var jmax = this.folders[i].discussions.length;
			for (var j=0;j<jmax;j++)
			{
				this.dscDates.push(this.folders[i].discussions[j].discussionMaxDate);	
			}
			this.dscDates.sort();
		}
		return (bolEarliestDate) ? this.dscDates[0] : this.dscDates[this.dscDates.length-1];	
	};
	this.navToDate = function(bolEarliestDate) {
		var newUrl = new String();
		var rex = /(lastDate=)([^&]+)/gim;
		var qs = location.search;
		var newDate = this.getEarliestDiscussionDate(bolEarliestDate);
		if (qs) // if there's a query string, we want to keep the other pieces
		{
			if (qs.match(rex)) // if there is a lastDate already
			{
				qs = qs.replace(rex,"lastDate="+newDate);
			}
			else // just append a lastDate to the query string
			{
				qs += "&lastDate=" + newDate;
			}
			location.search = qs;
		}
		else // just create a query string
		{
			location.search = "lastDate=" + newDate;
		}
	};
	this.intItemsTotal = 0;
	this.curTsn = 0;

}
PT_forum.prototype = new PT_mbItem();
PT_forum.prototype.constructor = PT_forum;

// First child of PT_Forum_Obj. May be multiple
function PT_folder (args)
{
	this.init(args);
	this.discussions = new Array();
    this.postNew = function() {
    var catList = (PT_CatListStr != "") ? "&" + PT_CatListStr : "";
    PT_Forum_Obj.getURL("webtag:" + PT_Forum_Obj.webtag + ";folderId:" + this.folderId + ";nav:post;" + catList,true);
  };
 }
PT_folder.prototype = new PT_mbItem();
PT_folder.prototype.constructor = PT_folder;

// Array object shared by both discussion list and message list
// member of PT_Forum_Obj.folders[n].discussions
 function PT_discussion(args)
 {
	this.init(args);
	this.messages = new Array();	 
 }
PT_discussion.prototype = new PT_mbItem();
PT_discussion.prototype.constructor = PT_discussion;
PT_discussion.prototype.show = PT_objectShow;

// Array object, member of PT_Forum_Obj.folders[n].discussions[n].messages
function PT_message (args)
{
	this.init(args);
	this.user = new Object();
	this.attachments = new Array();
	this.edits = new Array();
	// method to call a popup reply window 
	this.reply = function() {
		PT_Forum_Obj.getURL("webtag:" + PT_Forum_Obj.webtag + ";toUserId:" + this.fromUserId + ";replyToTid:" + this.dscTid + ";replyToTsn:" + this.tsn + ";nav:post",true);
	};
	this.replyQuoted = function() {
		PT_Forum_Obj.getURL("webtag:" + PT_Forum_Obj.webtag + ";toUserId:" + this.fromUserId + ";replyToTid:" + this.dscTid + ";replyToTsn:" + this.tsn + ";nav:post;quoted:true",true);
	};
	// method to popup a report violation window
	this.reportViolation = function() {
		PT_Forum_Obj.getURL("webtag:" + PT_Forum_Obj.webtag + ";tsn:" + this.tsn + ";tid:" + this.dscTid + ";nav:TosReportMaster",true);
	};
}
PT_message.prototype = new PT_mbItem();
PT_message.prototype.constructor = PT_message;

// object, member of PT_Forum_Obj.folders[n].discussions[n].messages[n]
function PT_user (args)
{
	this.init(args);
}
PT_user.prototype = new PT_mbItem();
PT_user.prototype.constructor = PT_user;

// object, member of PT_Forum_Obj.folders[n].discussions[n].messages[n].attachments
function PT_attachment (args)
{
	this.init(args);
}
PT_attachment.prototype = new PT_mbItem();
PT_attachment.prototype.constructor = PT_attachment;

// object, member of PT_Forum_Obj.folders[n].discussions[n].messages[n].edits
function PT_edit (args)
{
	this.init(args);
}
PT_edit.prototype = new PT_mbItem();
PT_edit.prototype.constructor = PT_edit;

// root object of search results page. Referenced as PT_Search_Obj;
function PT_searchObj (args)
{
	this.init(args);
	this.results = new Array();	 
}
PT_searchObj.prototype = new PT_mbItem();
PT_searchObj.prototype.constructor = PT_searchObj;

// object, member of PT_Search_Obj.results
function PT_searchResult (args)
{
	this.init(args);
}
PT_searchResult.prototype = new PT_mbItem();
PT_searchResult.prototype.constructor = PT_searchResult;

// root object of category list
function PT_Cat_Object (args)
{
	this.init(args);
}
PT_Cat_Object.prototype = new PT_mbItem();
PT_Cat_Object.prototype.constructor = PT_Cat_Object;



function PT_ActiveContentRequestorLoad(){
    //initilize the requestor by getting reference to the head of the current html page
    this._Head = document.getElementsByTagName("head").item(0);
    if(this._Head != null){
        this._wellformed= true;
        //if the page contains a head then the page is wellformed and request for scripts will be inserted into the head
    }
    // set flag so the control does not reinitialize of subsequent requests
    this._initialized=true;
}


function PT_ActiveContentRequestorGetData(script_key,dataurl,params,callback){
    //script_key- a value used to identify different activecontanet request
    // every difference active content request should have a unique script key to avoid collisions
    // making a request using a script_key of a previous request overides the previous request
    
    // daturl - the active content url containing booths its webtag and type
    // of the form 	"http://betawww.prospero.com/dir-app/acx/activeContent.aspx?webtag=espnmb&type=discussions"
    
    //params - additional parameters needed by the content element for processing 
    // of the form 	"activityHours=24&count=40&catList=NHL&encoding=iso-8859-1"
    // note the iso-8859-1 is needed if the script is executed from a page that uses iso-8859-1 encoding
    // the ommission of encoding results in utf encoding by default
    
    //call back- the name of a javascript function that expects the Jsonoized content element as its sole parameter
    // of the form "callback" where there is expected a function name callbak of the form
    
    // function callback(JSON_OBJ)
    //{
    //  //do stuff with the object when its loaded
    //}
        
    if(! this._initialized){
        //load if its not initialized
        this.Load();
    }
    if(!this._wellformed) return;
    // make sure its its is wellformed(has a head element)
    if(!dataurl)return;
    //if not dataurl then exit
    // use the params to set up the url
    if(callback)
    {
        callback ="&callback="+callback;
    }
    else
    {
        callback="";
    }
    if(!params){
        params="";
    }else{
        params="&" +params+"&";
    }


    var url = dataurl + params+"fmt=json&scriptkey=" +script_key + callback
    // now that the url is formed
    // first check to see if a script with the supplied key has been called already
    if(this._Scripts[script_key])
    {
      //    if so
      //    remove it
     this._Head.removeChild(this._Scripts[script_key]);
    }
    // now create a new script element and and refrence it in the this._Scripts collection    
    // by its script_key
    this._Scripts[script_key] = document.createElement("script");
    //set its url
    this._Scripts[script_key].setAttribute("src", url);
    //set an id (not needed but could be useful)
	this._Scripts[script_key].setAttribute("id",script_key);
	//append it to the head
	this._Head.appendChild(this._Scripts[script_key]);
	//this will cause the script to be loaded
}

function PT_ActiveContentRequestor(){
    //insure one and only one Activecontent requestor is created to avaoid collisions
    if(window.PT_ACTIVECONTENTREQUESTOR!=null){
        //if it already exists then exit
        return null;
    }
    window.PT_ACTIVECONTENTREQUESTOR=this;
    this._wellformed = false;
    this._Scripts = new Object();
    this._initialized = false;
}

PT_ActiveContentRequestor.prototype.Load=PT_ActiveContentRequestorLoad;
PT_ActiveContentRequestor.prototype.GetData=PT_ActiveContentRequestorGetData;

//make sure the window.PT_ACTIVECONTENTREQUESTOR exists by calling the its 'tor

new PT_ActiveContentRequestor();


function PT_RenderJsonTree(JsonObject,element){
    if(typeof element=='string'){
        element= document.getElementById('element');
    }
    if(element){
        element.innerHTML = "";
        for(s in JsonObject){
            PT_RenderJSONElement(JsonObject[s],s,element);
        }    
    }
}



//utility function used show/hide tree nodes

function PT_TreeToggleBody(itemIndex){
    var opened = false;
    var Elm = document.getElementById("PT_TREELEAF_"+itemIndex);
    if(Elm){
        if(Elm.style.display=="none")
        {
            Elm.style.display="block";
            opened= true;
        }
        else
        {
            Elm.style.display="none";
        }
        
        var btn = document.getElementById("PT_Toggle_"+itemIndex);
        if(btn)
        {
            if(opened)
            {
                btn.className="ptcToggle_Opened"
            }
            else
            {
                btn.className="ptcToggle_Closed"              
            }
        }
    }
}

//walk the json tree and create a tree control that can inspect its properties


function PT_RenderJSONElement(JsonObject,Name,container)
{
    var currentElemCount =PT_RenderJSONElement.count++; 
	var elementDiv = document.createElement("div");
	elementDiv.className="ptcElement"
    container.appendChild(elementDiv);
    var headerDiv = document.createElement("div");
    elementDiv.appendChild(headerDiv);
    headerDiv.className="ptcElementHeader";
    
    var toggleButton = document.createElement("button");
    //var btnText = document.createTextNode("+");
    //toggleButton.appendChild(btnText);
    toggleButton.className="ptcToggle_Closed";
    toggleButton.setAttribute("id","PT_Toggle_"+ + currentElemCount)
    toggleButton.onclick=new Function("PT_TreeToggleBody(" + currentElemCount + ")")
    headerDiv.appendChild(toggleButton);
    var title = document.createElement("span");
    title.className="ptcTitle";
    var text = document.createTextNode(Name + " : " );
    title.appendChild(text);
    headerDiv.appendChild(title);
    if(JsonObject["$text"]){
        var textEl = document.createElement("span")
        textEl.className="ptcText";
        text = document.createTextNode(JsonObject["$text"]);
        textEl.appendChild(text);
        headerDiv.appendChild(textEl);
    }
    var elementBody = document.createElement("div");
    elementBody.setAttribute("id","PT_TREELEAF_" + currentElemCount);
    elementBody.style.display="none";
    elementBody.className="ptcElementBody";
    elementDiv.appendChild(elementBody);
    for(var s in JsonObject)
    {
        if(s!="$text"){
            if(s.substr(0,1)=="@"){
                PT_RenderAttribute(JsonObject,s,elementBody)            ;
            }
            else if(JsonObject[s] instanceof Array )
            {
                var len= JsonObject[s].length;
                for(var i =0; i < len; i++){
                  PT_RenderJSONElement(JsonObject[s][i],s+"["+ i+"]" ,elementBody)                          
                }
			}
			else if(JsonObject[s] instanceof Object )
			{
                PT_RenderJSONElement(JsonObject[s],s,elementBody)
			}              
        }
    }
}

PT_RenderJSONElement.count=0;

function PT_RenderAttribute(JsonObject,Name,container){
    var attrDiv = document.createElement("div");
    attrDiv.className="ptcAttribute";
    container.appendChild(attrDiv);
    var attrTable= document.createElement("table");
    attrDiv.appendChild(attrTable);
    var tbody = document.createElement("tbody");
    attrTable.appendChild(tbody);
    var attrRow = document.createElement("tr");
    tbody.appendChild(attrRow);
    var titleEl = document.createElement("td");
    titleEl.className="ptcTitle"
    attrRow.appendChild(titleEl)
    var text =document.createTextNode(Name+ " : ");
    titleEl.appendChild(text);
    var valueEl = document.createElement("td");
    valueEl.className="ptcValue";
    attrRow.appendChild(valueEl)
    text =document.createTextNode(JsonObject[Name]);
    valueEl.appendChild(text);
}

