/*
	so.js: the official script of seven orbs
	http://sevenorbs.com/so_script
*/

so_ispresent = 1;

osoUnique = 1; // for use in appending unique client-side prefixes (ex. 'e77_') to page elements
so_routineEditorCode = 1;
dent = 0;
osoRandom = Math.floor(Math.random()*100001);
so_jaxrand = Math.floor(Math.random()*100001);
nGroupCounter = 1;

// Handy extensions of Javascript:
		// Trim
		String.prototype.trim = function () { return this.replace(/^[\n]*/, "").replace(/[\n]*$/, "").replace(/^[\s]*/, "").replace(/[\s]*$/, ""); }
		// make up for crappy difference in ie/ff's versions of dereferencing xml node text
		function soGetNodeText(node) {
			var ret = '';
			if (node) {
				if (node.text) {
					var ret = node.text;
				}
				else if (node.textContent) {
					var ret = node.textContent;
				}
			}
			if (typeof ret.trim == 'function' || typeof ret.trim == 'object') {
				var ret = ret.trim();
			}
			return ret;
		}
	// DOM functions
		// get childDivs!
		function getChildDivs(el) {
			var c = 0;
			var r = 0;
			var ret = new Array();
			if (el && el.childNodes && el.childNodes.length) {
				while (c < el.childNodes.length) {
					var thisNode = el.childNodes[c];
					if (thisNode.nodeName == 'DIV') {
						ret[r] = thisNode;
						r = r + 1;
					}
					c = c + 1;
				}
			}
			return(ret);
		}
		function getChildAs(el) {
			var c = 0;
			var r = 0;
			var ret = new Array();
			if (el && el.childNodes && el.childNodes.length) {
				while (c < el.childNodes.length) {
					var thisNode = el.childNodes[c];
					if (thisNode.nodeName == 'A') {
						ret[r] = thisNode;
						r = r + 1;
					}
					c = c + 1;
				}
			}
			return(ret);
		}
		// get child elements which are 'real' elements (not text nodes)
		function getChildEls(el) {
			var c = 0;
			var r = 0;
			var ret = new Array();
			if (el && el.childNodes && el.childNodes.length) {
				while (c < el.childNodes.length) {
					var thisNode = el.childNodes[c];
					if (thisNode.nodeType == 1) {
						ret[r] = thisNode;
						r = r + 1;
					}
					c = c + 1;
				}
			}
			return(ret);
		}
		// 'prepend' child
		function SO_prependChild(pEl,newEl) {
			var c = pEl.childNodes[0];
			if (typeof c !== 'undefined') { pEl.insertBefore(newEl,c) }
			else { pEl.appendChild(newEl) }
		}


// MARKUP FORMATTING FUNCTIONS
	function markupEscape(str) {
		if (str && str !== '') {
			var newStr = str.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;').replace(/\n/g,'<br>').replace(/  /g,'&nbsp;').replace(/\t/g,'&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;');
			return(newStr);
		}
		else {
			return('');
		}
	}
	function markupEscapeIgnoreWS(str) {
		if (str) {
			var newStr = str.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;');
			return(newStr);
		}
		else {
			return('');
		}
	}
	function markupEscapePseudo(str) {
		if (str && str !== '') {
			var newStr = str.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\n/g,'<br>').replace(/  /g,'&nbsp;&nbsp;').replace(/\t/g,'&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;');
			var newStr = newStr.replace(/&lt;([ ]*(\/[ ]*)?(a|p|br|b|img|hr|h1|h2|h3|h4|h5|h6|ul|li|iframe|span|marquee)([ ]+(href|style|src|frameborder|height|width|scrolling|marginheight|marginwidth)[ ]*=[ ]*(")[^"]*")*[ ]*\/?[ ]*)&gt;/gi,'<$1>');
			var newStr = newStr.replace(/&amp;amp;/gi,'&');
			var newStr = newStr.replace(/&amp;nbsp;/gi,'&nbsp;');
			var newStr = newStr.replace(/&amp;gt;/gi,'&gt;');
			var newStr = newStr.replace(/&amp;lt;/gi,'&lt;');
			return(newStr);
		}
		else {
			return('');
		}
	}


// IDENTITY STRING FUNCTIONS
	function makeStringUnique(elId) {
		if (elId && isOsoUnique(elId) == 0) {
			elId = 'e' + osoUnique + ':' + elId;
			osoUnique = osoUnique + 1;
		}
		return(elId);
	}
	function makeKidsUnique(el) {
		if (el && el.childNodes) {
			var i = 0;
			while (i < el.childNodes.length) {
				var thisChild = el.childNodes[i];
				if (thisChild.nodeType == 1 && thisChild.id && isOsoUnique(thisChild.id) == 0) {
					thisChild.id = 'e' + osoUnique + ':' + thisChild.id;
					osoUnique = osoUnique + 1;
				}
				i = i + 1;
			}
		}
	}
	// handy functions for reading identity strings (e9:genre-orb_type.99);
	function getUniqueNum(str) {
		if (isOsoUnique(str) && str.indexOf('-') > -1) {
			return(str.split(':')[0].split('e')[1]);
		}
		else {
			return(0);
		}
	}
	function getGenre(str) {
		if (isOsoUnique(str) && str.indexOf('-') > -1) {
			return(str.split('-')[0].split(':')[1]);
		}
		else {
			return(0);
		}
	}
	function getTypeName(str) {
		if (isOsoUnique(str) && str.indexOf('-') > -1) {
			return(str.split('-')[1].split('.')[0]);
		}
		else {
			return(0);
		}
	}
	function getIdNum(str) {
		if (isOsoUnique(str) && str.indexOf('-') > -1) {
			return(str.split('-')[1].split('.')[1]);
		}
		else {
			return(0);
		}
	}
	function isChildOf(Astr,Bstr) { // expects Astr and Bstr to be orbs
		if (Astr == Bstr) {
			return(0);
		}
		else if (Bstr == Astr + Bstr.replace(Astr,"") && Bstr.indexOf(Astr) == 0) {
			return(1);
		}
		else {
			return(0);
		}
	}


// Handy query string functions
	function qstringToFormFields(str) {
		str = str.replace(/&amp;/ig,'soTemporaryAmpersandEscape');
		var qArray = str.split('&');
		var fieldString = '';
		var q = 0;
		while (q < qArray.length) {
			thisQ = qArray[q];
			thisField = thisQ.split('=')[0];
			thisValue = thisQ.replace(thisField + '=','');
			if (thisField && thisValue) {
				thisField = thisField.replace(/soTemporaryAmpersandEscape/g,'&amp;');
				thisValue = thisValue.replace(/soTemporaryAmpersandEscape/g,'&amp;');
				fieldString = fieldString + '<input type="hidden" name="' + thisField + '" value="' + thisValue + '">';
			}
			q = q + 1;
		}
		return(fieldString);
	}


// 7o ELEMENT ID DECISION/LOCATION FUNCTIONS
	function isOsoUnique(string) {
		var reg = /e[0-9]+:/;
		if (reg.test(string) == true) {
			return(1);
		}
		else {
			return(0);
		}
	}
	function isIn(pElId,el,stopAt) {
		var thisEl = el;
		while (thisEl.parentNode) {
			thisEl = thisEl.parentNode;
			if (stopAt && stopAt.id && stopAt.id == thisEl.id) {
				return(0);
				break;
			}
			if (thisEl.id && thisEl.id.indexOf(pElId) > -1) {
				return(1);
				break;
			}
		}
		return(0);
	}


// 7o-FRIENDLY AJAX FUNCTIONS
	function oGet(qstring,onComplete,onIncomplete,siteformat) {
		if (!onComplete) { var onComplete = ''; }
		if (!onIncomplete) { var onIncomplete = ''; }
		if (!siteformat) {
			if (qstring.indexOf('http://') == 0) {
				var siteformat = 'external';
			}
			else {
				var siteformat = 'xml';
			}
		}
		var httpRequest;
		if (window.XMLHttpRequest) { // Mozilla, Safari, ...
			httpRequest = new XMLHttpRequest();
			if (httpRequest.overrideMimeType) {
				httpRequest.overrideMimeType('text/xml');
				// See note below about this line
			}
		} 
		else if (window.ActiveXObject) { // IE
			try {
				httpRequest = new ActiveXObject("Msxml2.XMLHTTP");
				} 
				catch (e) {
						   try {
								httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
							   } 
							 catch (e) {}
						  }
									   }
	
		if (!httpRequest) {
			alert('Giving up :( Cannot create an XMLHTTP instance');
			return false;
		}
		httpRequest.onreadystatechange = function() { returnGetBounce(httpRequest,onComplete,onIncomplete); };
		if (siteformat == 'external') {
			var strr = qstring.replace(/&amp;/g, "&");
		}
		else {
			var strr = 'http://' + document.domain + '/index.cfm?' + qstring.replace(/&amp;/g, "&") + '&jaxrand=' + so_jaxrand;
		}
		 if (siteformat !== 'none' && siteformat !== 'external') {
			var strr = strr + '&siteformat=' + siteformat;
		 }
		httpRequest.open('GET', strr, true);
		httpRequest.send('');
	}
	function returnGetBounce(httpRequest,onComplete,onIncomplete) {
		if (httpRequest.readyState == 4) {
			if (httpRequest.status == 200) {
				var responseText = httpRequest.responseText;
				var responseXML = httpRequest.responseXML;
				if (onComplete) {
					eval(onComplete);
				}
			} else {
				if (typeof onIncomplete == 'string' && onIncomplete !== '') {
					eval(onIncomplete);
				}
				else {
					alert('There was a problem with the request.');
				}
			}
		}
	}
		function oGet2(responseXML,targetDivId,forEachRow,clearTargetDiv,emptySetMessage) {
			var targetDiv = document.getElementById(targetDivId);
			if (!responseXML) {
				alert('oGet2: could not find response xml');
				targetDiv.innerHTML = '<div style="margin:2em">- error -</div>';
			}
			else {
				if (clearTargetDiv && clearTargetDiv == 1) {
					targetDiv.innerHTML = '';
				}
				if (responseXML.getElementsByTagName('row').length == 0) {
					if (!emptySetMessage) {
						var emptySetMessage = '- no records found -';
					}
					targetDiv.innerHTML = '<div style="margin:2em">' + emptySetMessage + '</div>';
				}
				else {
					var s = 0;
					while (s < responseXML.getElementsByTagName('row').length) {
						var thisRow = responseXML.getElementsByTagName('row')[s];
						eval(forEachRow);
						s = s + 1;
					}
				}
			}
		}

	function oPost(qstring,onComplete,onIncomplete,siteformat,geto) {
		if (!onComplete) { var onComplete = ''; }
		if (!onIncomplete) { var onIncomplete = ''; }
		if (!siteformat) { var siteformat = 'xml'; }
		if (!geto) { var geto = 0; }

		var httpRequest;
	
		if (window.XMLHttpRequest) { // Mozilla, Safari, ...
			httpRequest = new XMLHttpRequest();
			if (httpRequest.overrideMimeType) {
				httpRequest.overrideMimeType('text/xml');
				// See note below about this line
			}
		} 
		else if (window.ActiveXObject) { // IE
			try {
				httpRequest = new ActiveXObject("Msxml2.XMLHTTP");
				} 
				catch (e) {
						   try {
								httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
							   } 
							 catch (e) {}
						  }
									   }
	
		if (!httpRequest) {
			alert('Giving up :( Cannot create an XMLHTTP instance');
			return false;
		}
		httpRequest.onreadystatechange = function() { returnPostBounce(httpRequest,onComplete,onIncomplete); };
		var strr = 'http://' + document.domain + '/?&jaxrand=' + so_jaxrand;
		 if (siteformat !== 'none') {
			var strr = strr + '&siteformat=' + siteformat;
		 }
		 if (geto !== 0) {
			var strr = strr + '&o=' + geto;
		 }
		httpRequest.open('POST', strr, true);
		httpRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
		httpRequest.send(qstring);
	
	}
	function returnPostBounce(httpRequest,onComplete,onIncomplete) {
	
		if (httpRequest.readyState == 4) {
			if (httpRequest.status == 200) {
				var responseText = httpRequest.responseText;
				var responseXML = httpRequest.responseXML;
				if (onComplete) {
					eval(onComplete);
				}
			} else {
				if (typeof onIncomplete == 'string' && onIncomplete !== '') {
					eval(onIncomplete);
				}
				else {
					alert('There was a problem with the request.');
				}
			}
		}
	
	}
		function didPostWork(xmldoc) {
			if (!xmldoc) {
				return(0);
			}
			else {
				var root_node = xmldoc.getElementsByTagName('posterror')[0];
				if (root_node && root_node.getElementsByTagName('ok') && root_node.getElementsByTagName('ok')[0]) {
					if (root_node.getElementsByTagName('ok')[0].textContent) { // Moz
						if (root_node.getElementsByTagName('ok')[0].textContent == '1') {
							return(1);
						}
						else {
							return(0);
						}
					}
					else if (root_node.getElementsByTagName('ok')[0].text) { // IE
						if (root_node.getElementsByTagName('ok')[0].text == '1') {
							return(1);
						}
						else {
							return(0);
						}
					}
					else {
						alert('so.js could not dereference node text.  Try another browser.');
					}
				}
				else {
					return(0);
				}
			}
		}


// Drag/drop helpers
	// Inserts (el) in (drop) according to (ev).
	function pasteHere(el,drop,ev,altEl) {
		didInsert = 0;
		var n = 0;
		if (altEl == 'a') { var dropKids = getChildAs(drop); }
		else { var dropKids = getChildDivs(drop); }
		while (n < dropKids.length) {
			thisChild = dropKids[n];
			if (thisChild.id && thisChild.nodeType !== 3) {
				if (thisChild.parentNode.id && thisChild.parentNode.id == el.id) {
					break;
				}
				if (thisChild.parentNode.childNodes.length == 0) {
					break;
				}
				var thisScreenX = findPos(thisChild)[0];
				var thisScreenY = findPos(thisChild)[1];
				// alert('event: ' + mouseX(ev) + ',' + mouseY(ev) + ' | ' + thisChild.id + ': ' + thisScreenX + ',' + thisScreenY);
				if (thisScreenY >= mouseY(ev)) {
					// alert('inserting ' + el.id + ' before ' + thisChild.id + ' in ' + thisChild.parentNode.id);
					thisChild.parentNode.insertBefore(el,thisChild);
					didInsert = 1;
					break;
				}
			}
			n = n + 1;
		}
		if (didInsert == 0) {
			drop.appendChild(el);
		}
	}

	function findPos(obj) { // from http://www.quirksmode.org/js/findpos.html
		var curleft = curtop = 0;
		if (obj.offsetParent) {
			do {
				curleft += obj.offsetLeft;
				curtop += obj.offsetTop;
			} while (obj = obj.offsetParent);
			return [curleft,curtop];
		}
		else {
			return[0,0];
		}
	}

	function mouseX(evt) {
		if (evt.pageX) return evt.pageX; 
		else if (evt.clientX)return evt.clientX + (document.documentElement.scrollLeft ?  document.documentElement.scrollLeft : document.body.scrollLeft); 
		else return null;
	}
	function mouseY(evt) {
		if (evt.pageY) return evt.pageY; 
		else if (evt.clientY)return evt.clientY + (document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop); 
		else return null;
	}


// For simple text fields named like 'orb-id-fieldname'
	function fieldToTextinput() {
		this.onclick = '';
		this.innerHTML = '<input class="ofont" value="' + this.innerHTML + '"> <span style="cursor:pointer">ok</span>';
		this.getElementsByTagName('span')[0].onclick = textinputToField;
	}
	function textinputToField() {
		var thisOrb = this.parentNode.id.split('-')[0];
		var thisIdNum = this.parentNode.id.split('-')[1];
		var thisFieldName = this.parentNode.id.split('-')[2];
		var thisFieldValue = this.parentNode.getElementsByTagName('input')[0].value.trim();
		qstring = 'returnxml=1&1_posttype=update&1_orb=' + thisOrb + '&1_where=and-id-=-integer-' + thisIdNum + '&1_' + thisFieldName + '=' + escape(thisFieldValue);
		oPost(qstring);
		this.parentNode.onclick = fieldToTextinput;
		if (thisFieldValue == '') {
			thisFieldValue = '&nbsp;';
		}
		this.parentNode.innerHTML = thisFieldValue;
	}
// For text areas named like 'orb-id-fieldname'
	function fieldToTextarea() {
		this.onclick = '';
		this.innerHTML = '<textarea class="tiny ofont" style="width:80%">' + this.innerHTML + '</textarea> <span style="cursor:pointer">ok</span>';
		this.getElementsByTagName('span')[0].onclick = textareaToField;
	}
	function textareaToField() {
		var thisOrb = this.parentNode.id.split('-')[0];
		var thisIdNum = this.parentNode.id.split('-')[1];
		var thisFieldName = this.parentNode.id.split('-')[2];
		var thisFieldValue = this.parentNode.getElementsByTagName('textarea')[0].value.trim();
		qstring = 'returnxml=1&1_posttype=update&1_orb=' + thisOrb + '&1_where=and-id-=-integer-' + thisIdNum + '&1_' + thisFieldName + '=' + escape(thisFieldValue);
		oPost(qstring);
		this.parentNode.onclick = fieldToTextarea;
		if (thisFieldValue == '') {
			thisFieldValue = '&nbsp;';
		}
		this.parentNode.innerHTML = thisFieldValue;
	}

// Handy objects
	function Field(orb,idNum,name,value,bgcolor) {
		if (!bgcolor) {
			var bgcolor = '#FFFFFF';
		}
		rootIdString = orb + '-' + idNum + '-' + name;
		cDiv = document.createElement('div');
		cDiv.id = rootIdString + ':container';
		cDiv.className = 'fieldContainer';
		cDiv.style.background = bgcolor;
		lDiv = document.createElement('div');
		lDiv.id = rootIdString + ':label';
		lDiv.className = 'fieldLabel';
		lDiv.innerHTML = name + ':';
		cDiv.appendChild(lDiv);
		dDiv = document.createElement('div');
		dDiv.id = rootIdString;
		dDiv.className = 'fieldContent';
		if (value == null) {
			value = '&nbsp;';
		}
		dDiv.innerHTML = value;
		dDiv.onclick = fieldToTextarea;
		cDiv.appendChild(dDiv);
		return(cDiv);
	}


// ::::::: smooth operators - functions that help prevent bugs ::::::: //
rprefix_modifier = '';
rrandocount = 1;
function rPrefix(elId,replaceWithNew) { // used to prefix ids with a unique 'random' number; so, 'myid' becomes 'r99-myid'; '99' will increment so next el uses '100'.
	var ret = elId;
	  if (!ret) { var ret = ''; }
	rrandocount = rrandocount + 1;
	if (ret.indexOf('~') > -1) {
		// id already has prefix, so give it a new one
		if (replaceWithNew !== 0) {
			var ret = 'r' + rprefix_modifier + rrandocount + '~' + ret.split('~')[ret.split('~').length-1];
		}
	}
	else {
		// id has no prefix, so just prepend
		var ret = 'r' + rprefix_modifier + rrandocount + '~' + ret;
	}
	return ret;
}
	function withoutPrefix(str) {
		// returns a string, aside from its random prefix
		if (str.indexOf('~') > -1) {
			var str = str.split('~')[str.split('~').length-1];
		}
		return str;
	}
	function deep_rePrefix(el) { // for all childNodes (deep), changes rPrefix.
		var p = 0;
		while (p < el.childNodes.length) {
			var pete = el.childNodes[p];
			if (typeof pete.id == 'string' && pete.id.indexOf('~') > -1) {
				pete.id = rPrefix(pete.id,1);
				deep_rePrefix(pete);
			}
			var p = p + 1;
		}
	}


function printErr(str) {
	if (document.getElementById('err') == null) { var errdiv = document.createElement('div'); document.body.appendChild(errdiv); errdiv.id = 'err'; }
	document.getElementById('err').innerHTML = document.getElementById('err').innerHTML + ' | ' + str;
}



// New!  Turn ts from db (eg. "2009-03-27 19:48:42") into js date.
/*
	Note: 7o server is on pacific time, 7 hours behind GMT (whoa!)
*/
function soDatetime(str,islocal) {
	var str = str.trim();
	var d = new Date();
		d.setFullYear(str.split('-')[0]);
		d.setMonth(str.split('-')[1]-1);
		d.setDate(str.split('-')[2].split(' ')[0]);
		d.setHours(str.split(' ')[1].split(':')[0]);
		d.setMinutes(str.split(':')[1]);
		d.setSeconds(str.split(':')[2]);
	if (islocal == 1) {
		// convert to local time using getTimezoneOffset;
		var minutes = 1000*60; var hours = minutes*60; var days = hours*24; var years = days*365;
		d.setTime((d.getTime()) + (d.getTimezoneOffset()*60*1000) - (60*60*1000)); // + (7*60*60*1000)
	}
	return d;
}