function ConvertNSPSToSpace(inText)
{
	return inText.replace(/&nbsp;/g,' ');
}

// parses the string and removes any list index from the beginning
// list indexes: * -
function StripListIndex(inText)
{
	inText = Trim(inText);
	inText = inText.replace(/^[*|-]/, '');
	inText = Trim(inText);					// after removing bullets, trim again
	
	return inText;
}

function Trim(inText)
{
	return inText.replace(/^\s+|\s+$/, '');
}

function GetIndentationOfText(inText)
{
	inText = inText.replace(/\s\s\s\s/g, '\t');
	reg_exp ="/[^\t]/";		// get first non-tab character
	reg_exp=eval(reg_exp);
	
	depth = inText.search(reg_exp);
	if (depth > 0)
		return depth;
	else return 0;
}

function getCheckedValue(radioObj)
{
	if(!radioObj)
		return "";
	var radioLength = radioObj.length;
	if(radioLength == undefined)
		if(radioObj.checked)
			return radioObj.value;
		else return "";
		
	for (var i = 0; i < radioLength; i++)
	{
		if(radioObj[i].checked)
			return radioObj[i].value;
	}
	return "";
}

function ValidateDate(day, month, year)
{
var dteDate;

	dteDate=new Date(year,month,day);				// javascript months start at 0 (0-11 instead of 1-12)
	
	return ((day==dteDate.getDate()) && (month==dteDate.getMonth()) && (year==dteDate.getFullYear()));
}

// date_str is in format: 21/09/2008
// format uses the same syntax as the PHP date function
function GetFormattedDate(format, date_str)
{
	var date_obj = parseDate(date_str, "d/M/y");
	var date_format = "";

	if (!date_obj)
		return "";
	
	switch (format)
	{
	case "M d":		date_format = "NNN d";				// Aug 20
					break;
			
	case "M d, Y":	date_format = "NNN d, y";			// Aug 20, 2004
					break;
			
	case "D d":		date_format = "E d";				// Fri 20
					break;
	}
	return formatDate(date_obj, date_format);
}

function GetFriendlyDate(in_date)
{
	var format = "";
	var date_obj = parseDate(in_date, "d/M/y");
	var today = new Date();
	
	var difference = Math.round((date_obj - today)/(1000*60*60*24));
	
	if (difference == 0)		// today
		return "Today";
	else if (difference == 1)
		return "Tomorrow";
	else if (difference == -1)
		return "Yesterday";
	else if (Math.abs(difference) < 7)
		format = "D d";
	else format = "M d";
	
	formatted_date = GetFormattedDate(format, in_date);
	
	return formatted_date;
}

function IsDatePassed(in_date)
{
	if (in_date == "")
		return false;
		
	var date_obj = parseDate(in_date, "d/M/y");
	var today = new Date();
	
	var difference = Math.round((date_obj - today)/(1000*60*60*24));
	
	if (difference < 0)
		return true;
	else return false;
}

function FormatNumberWithCommas(nStr)
{
	nStr += '';
	x = nStr.split('.');
	x1 = x[0];
	x2 = x.length > 1 ? '.' + x[1] : '';
	var rgx = /(\d+)(\d{3})/;
	while (rgx.test(x1)) {
		x1 = x1.replace(rgx, '$1' + ',' + '$2');
	}
	return x1 + x2;
}

function GetScreenHeight()
{
	var screenH = 480;
	if (parseInt(navigator.appVersion) > 3)
		return screen.height;
	else if (navigator.appName == "Netscape" && parseInt(navigator.appVersion) == 3 && navigator.javaEnabled()) 
	{
		var jToolkit = java.awt.Toolkit.getDefaultToolkit();
		var jScreenSize = jToolkit.getScreenSize();
		return jScreenSize.height;
	}
}

function GetScreenWidth()
{
	var screenW = 600;
	if (parseInt(navigator.appVersion) > 3)
		return screen.width;
	else if (navigator.appName == "Netscape" && parseInt(navigator.appVersion) == 3 && navigator.javaEnabled()) 
	{
		var jToolkit = java.awt.Toolkit.getDefaultToolkit();
		var jScreenSize = jToolkit.getScreenSize();
		return jScreenSize.width;
	}
}

function ShowTour()
{
	var h = GetScreenHeight();
	var w = GetScreenWidth();
	var left = (w - 1000) / 2;
	
	window.open('/tour.html', 'popup', 'left='+left+',height='+h+',width=1000,scrollbars');
	
	return false;
}

function isLeapYear(year) 
{
	if (year % 4 != 0) 
		return false;
	else
	{ 
		if (year % 100 != 0) 
			return true;
		else
		{
			if (year % 400 != 0) 
				return false;
			else return true;
		}
	}
}

function addslashes(str) {
	str=str.replace(/\\/g,'\\\\');
	str=str.replace(/\'/g,'\\\'');
	str=str.replace(/\"/g,'\\"');
	str=str.replace(/\0/g,'\\0');
	return str;
}

function stripslashes(str) {
	str=str.replace(/\\'/g,'\'');
	str=str.replace(/\\"/g,'"');
	str=str.replace(/\\0/g,'\0');
	str=str.replace(/\\\\/g,'\\');
	return str;
}

function findPosX(obj)
{
var curleft = 0;
	if(obj.offsetParent)
	{
		while(1) 
		{
			curleft += obj.offsetLeft;
			if(!obj.offsetParent)
				break;
			obj = obj.offsetParent;
		}
	}
	else if(obj.x)
		curleft += obj.x;
	return curleft;
}

function findPosY(obj)
{
var curtop = 0;
	if(obj.offsetParent)
	{
		while(1)
		{
			curtop += obj.offsetTop;
			if(!obj.offsetParent)
				break;
			obj = obj.offsetParent;
		}
	}
	else if(obj.y)
    	curtop += obj.y;
	return curtop;
}

function StripHTMLTags(str, allowed_tags)
{
//alert(str);
	var key = '', allowed = false;
	var matches = [];
	var allowed_array = [];
	var allowed_tag = '';
	var i = 0;
	var k = '';
	var html = '';

	var replacer = function(search, replace, str) {
			return str.split(search).join(replace);
		};

	// Build allowed tags associative array
	if (allowed_tags)
		allowed_array = allowed_tags.match(/([a-zA-Z]+)/gi);
	
	str += '';

	matches = str.match(/(<\/?[\S][^>]*>)/gi);			// Match tags

	for (key in matches)								// Go through all HTML tags
	{
		if (isNaN(key))									// IE7 Hack
			continue;

		html = matches[key].toString();					// Save HTML tag

		allowed = false;								// Is tag not in allowed list? Remove from str!

		for (k in allowed_array)						// Go through all allowed tags
		{
			allowed_tag = allowed_array[k];				// Init
			i = -1;

			if (i != 0) { i = html.toLowerCase().indexOf('<'+allowed_tag+'>');}
			if (i != 0) { i = html.toLowerCase().indexOf('<'+allowed_tag+' ');}
			if (i != 0) { i = html.toLowerCase().indexOf('</'+allowed_tag)   ;}

			if (i == 0)									// Determine
			{
				allowed = true;
				break;
			}
		}

		if (!allowed)
			str = replacer(html, "", str); 				// Custom replace. No regexing
	}
	
//alert(str);
	return str;
}

// REQUIRES browserdetect.js to be included
// property can take the following values: 'browser', 'version', 'OS'.
// if the param isn't passed, we default it to 'browser'
function DetectBrowser(property)
{
	if (property == null)				// in case property parameter isn't passed, we default it to 'browser'
	   property = 'browser';
	
	BrowserDetect.init();
	ret_value = '';
	switch (property)
	{
	case 'browser': ret_value = BrowserDetect.browser;
					break;
	
	case 'version': ret_value = BrowserDetect.version;
					break;
	
	case 'OS': 		ret_value = BrowserDetect.OS;
					break;
					
	default:		ret_value = '';
					break;
	}
	
	return ret_value;
}

/*
 * NormalizeMarkup()
 * Normalizes the content based on the browser
 *
 * @params
 * content:		content that needs to be normalized
 * browser:		which browser are we getting the content from?
 * lf_tag:		line-feed tag to use in case content conains multiple lines (usually it will be '\n' or <br />)
 *
 * @return
 * Normalized content. In case we don't support the browser, we return the content as is.
 */
function NormalizeMarkup(content, browser, lf_tag)
{
	var std_content = content;
	var allowed_tags = "<br><br />";
	
	if (typeof lf_tag === "undefined")
		lf_tag = "<br />";
	
	switch (browser)
	{
	case 'Chrome':
	case 'Safari':	allowed_tags += '<p></p>';
					var first_line;
					var firstline = new RegExp("(.*?)<div>.*?<\/div>");
					var nextline = new RegExp("<div>(.*?)<\/div>","g");

					first_line = firstline.exec(content);
					
					if (first_line != null)											// content contains multiple lines
						std_content = StripHTMLTags(first_line[1], allowed_tags);
					else std_content = StripHTMLTags(content, allowed_tags);		// content is in single line
					
					while(result = nextline.exec(content))
						std_content += "<br />" + StripHTMLTags(result[1], allowed_tags);
					
					break;
					
	case 'Firefox':	allowed_tags += '<p></p>';
					std_content = content;
					std_content = std_content.replace(/<br>/gi, "<br />");
					std_content = std_content.replace(/<br \/>/gi, "<br />");
					std_content = std_content.replace(/\n/gi, "");					// for FF on Windows
					std_content = StripHTMLTags(std_content, allowed_tags);
					
					break;
					
	case 'Opera':	
	case 'Explorer':var nextline = new RegExp("<P[^>]*>(.*?)<\/P>","ig");
					var stdr_content = "";
					// in IE 7, its not getting into his loop
					while(result = nextline.exec(content)) {
						if(stdr_content == "")
							stdr_content = StripHTMLTags(result[1], allowed_tags);
						else stdr_content += "<br />"+StripHTMLTags(result[1], allowed_tags);
					}
					
					std_content += stdr_content;
					break;
					
	default:		// handle all other browsers here (we will see this later)
					alert("Sorry, we don't support your browser ("+browser+").");
					break;
	}
	
	// some times, there is a trailing line feed at the end of the text. knock it off!
	if (std_content.match(/<br \/>$/gi))
		std_content = std_content.replace(/<br \/>$/gi, '');
		
	if (std_content.match(/<br>$/gi))
		std_content = std_content.replace(/<br>$/gi, '');
	
	std_content = std_content.replace(/<br>/gi, lf_tag);
	std_content = std_content.replace(/<br \/>/gi, lf_tag);
	
	if (std_content == lf_tag)			// if the content contains only a line break, we empty it.
		std_content = '';
	
	return std_content;
}

function getScrollTop()
{
	if(typeof pageYOffset!= 'undefined')
		return pageYOffset;				// most browsers
	else
	{
	var B= document.body; 				// IE 'quirks'
	var D= document.documentElement;	// IE with doctype
		D= (D.clientHeight)? D: B;
		return D.scrollTop;
	}
}

var currentPage = null;
var currentDialog = null;
var currentWidth = 0;
var currentHash = location.hash;
var hashPrefix = "#_";
var pageHistory = [];
var newPageCount = 0;
var checkTimer;

function CountChildren(row)
{
	if (row.hasChildNodes())
	{
	var child = row.firstChild;
	var num_children = 0;
		while (child)
		{
			if (child.nodeType == 1)
				num_children++;

			child = child.nextSibling;
		}
		return num_children;
	}
	else return 0;
}

// text is always loaded into attributes array FIRST
// this function therefore always converts either to or from this array to whatever else we require
// direction specifies where the text is going
function NormaliseText(txt, direction)
{
//	alert(txt+' dir: '+direction);
	if (typeof txt === "undefined")
		return "";

	switch (direction)
	{
	case 'html': 	text = txt.replace(/&#10;/gi, "<br />");
					text = text.replace(/\"/gi, "&quot;");
				//	text = autoHTML(text, 'target="_blank" onclick="gHandleClicked=true;"');
					break;

	case 'opml':	text = txt.replace(/&/g, "&amp;");					// dumping text from edit box to attributes obj
					text = text.replace(/\"/g, "&quot;");
					text = text.replace(/\n/g, "&#10;");
					text = text.replace(/</g, "&lt;");
					text = text.replace(/>/g, "&gt;");
					break;

	case 'opml2attr':
//					text = txt.replace(/&/g, "&amp;");					// dumping text from opml to attributes obj
					text = txt.replace(/&#38;/g, "&amp;");				// these would have got expanded by the XML parser,
					text = text.replace(/\"/g, "&quot;");				// so re-encode them
					text = text.replace(/\n/g, "&#10;");				
					text = text.replace(/</g, "&lt;");
					text = text.replace(/>/g, "&gt;");
					break;

	case 'edit':	text = txt.replace(/&#10;/g, "\n");					// loading text from atributes to edit box
					text = text.replace(/&quot;/g, "\"");
					text = text.unescapeHTML();
				//	text = text.replace(/&/g, "&amp;");
					break;
	default:		text = txt;
	}

	return text;
}

function nl2br(txt)
{
	txt = txt.replace(/\r\n/g, "&#10;");
	txt = txt.replace(/\r/g, "&#10;");
	txt = txt.replace(/\n/g, "&#10;");

	return txt;
}

function autoHTML(strSrc, optAtt)
{
	strSrc = strSrc.replace(/&quot;/gi, '#z#zz#s#a###v#');			// replace " with 8 hashes, definitely not allowed in email addresses and urls :)

	strSrc = strSrc.replace(/(https:\/\/|http:\/\/|ftp:\/\/|www.)([a-zA-Z0-9_?.#-\/&%+=;]*)/gi, '<a href="$1//$2" ' + optAtt + '>$1$2</a>');
	strSrc = strSrc.replace(/www.\/\//gi, 'http://www.');
	
	strSrc = strSrc.replace(/[\s]*([^\s]*@[^\s]*)/gi,' <a href="mailto:$1">$1</a>');

	strSrc = strSrc.replace(/#z#zz#s#a###v#/gi, '&quot;');
	return strSrc;
}

function Set_Cookie( name, value, expires, path, domain, secure ) 
{
// set time, it's in milliseconds
var today = new Date();
today.setTime( today.getTime() );

/*
if the expires variable is set, make the correct 
expires time, the current script below will set 
it for x number of days, to make it for hours, 
delete * 24, for minutes, delete * 60 * 24
*/
if ( expires )
{
expires = expires * 1000 * 60 * 60 * 24;
}
var expires_date = new Date( today.getTime() + (expires) );

document.cookie = name + "=" +escape( value ) +
( ( expires ) ? ";expires=" + expires_date.toGMTString() : "" ) + 
( ( path ) ? ";path=" + path : "" ) + 
( ( domain ) ? ";domain=" + domain : "" ) +
( ( secure ) ? ";secure" : "" );
}

// this function gets the cookie, if it exists
function Get_Cookie( name ) {
	
var start = document.cookie.indexOf( name + "=" );
var len = start + name.length + 1;
if ( ( !start ) &&
( name != document.cookie.substring( 0, name.length ) ) )
{
return null;
}
if ( start == -1 ) return null;
var end = document.cookie.indexOf( ";", len );
if ( end == -1 ) end = document.cookie.length;
return unescape( document.cookie.substring( len, end ) );
}

// this deletes the cookie when called
function Delete_Cookie( name, path, domain ) {
if ( Get_Cookie( name ) ) document.cookie = name + "=" +
( ( path ) ? ";path=" + path : "") +
( ( domain ) ? ";domain=" + domain : "" ) +
";expires=Thu, 01-Jan-1970 00:00:01 GMT";
}

function ScrollToAndFlash(div)
{
	new Effect.ScrollTo(div); Effect.Pulsate(div,{from:0.3, pulses:3});
}

function HasClass(p_element, p_class)
{
	if (p_element.className)
	{
		l_classes = new Array();
		l_classes = p_element.className.split(' ');
		for (var i = 0; i < l_classes.length; i++)
			if (l_classes[i] == p_class)
				return true;
	}
	return false;
}

function AddClass(p_element, p_class)
{
	if (!p_element)
		return;
		
	if (!p_element.className)
		p_element.className = p_class;
	else
	{
		l_classes = new Array();
		l_classes = p_element.className.split(' ');
		for (var i = 0; i < l_classes.length; i++)
			if (l_classes[i] == p_class)
				return;
		p_element.className += ' ' + p_class;
	}
}

function RemoveClass(p_element, p_class)
{
	if (!p_element)
		return;

	if (p_element.className)
	{
		l_classes = new Array();
		l_classes = p_element.className.split(' ');
		for (var i = 0; i < l_classes.length; i++)
			if (l_classes[i] == p_class)
				l_classes.splice(i, 1);
		p_element.className = l_classes.join(' ');
	}
}

function getElementsByClassName(className, tag, elm)
{
	var testClass = new RegExp("(^|\\s)" + className + "(\\s|$)");
	var tag = tag || "*";
	var elm = elm || document;
	var elements = (tag == "*" && elm.all)? elm.all : elm.getElementsByTagName(tag);
	var returnElements = [];
	var current;
	var length = elements.length;
	for(var i=0; i<length; i++)
	{
		current = elements[i];
		if(testClass.test(current.className)){
			returnElements.push(current);
		}
	}
	return returnElements;
}

function isElementVisible(e)		    //returns true is should be visible to user.
{
	if (typeof e == "string")
		e = xGetElementById(e);

	while (e.nodeName.toLowerCase() != 'body' && e.style.display.toLowerCase() != 'none' && e.style.visibility.toLowerCase() != 'hidden')
	    e = e.parentNode;
	
	if (e.nodeName.toLowerCase() == 'body')
	    return true;
	else return false;
}

function CheckOrientAndLocation()
{
    if (window.innerWidth != gCurrentWidth)
    {
        gCurrentWidth = window.innerWidth;

        var orient = gCurrentWidth == 320 ? "profile" : "landscape";
        document.body.setAttribute("orient", orient);
    }
}

// this positions the insertion point at the end of the text
// it doesn't happen automatically in Safari
// we call this function when we place focus on the textarea
// position:	can take 2 values, 'start', 'end'
function SetCaretPosition(txtarea_id, position)
{
	txtarea = document.getElementById(txtarea_id);
	if (position == 'start')
		pos = 0;
	else pos = txtarea.innerHTML.length;

	if (txtarea.setSelectionRange)
	{
		txtarea.focus();
		txtarea.setSelectionRange(pos,pos);
	}
	else if (txtarea.createTextRange)
	{
		var range = txtarea.createTextRange();
		range.collapse(true);
		range.moveEnd('character', pos);
		range.moveStart('character', pos);
		range.select();
	}
}


var gElementInFocus = null;
TrackElementFocus=function(e)
{ 
	gElementInFocus = e;
    alert(gElementInFocus+" gets focus");
}

TrackElementBlur=function(e)
{
	if (gElementInFocus == e)
	{
		gElementInFocus = null;
		alert(e + " lost focus");
	}
	else alert('no element in focus');
}

function ScrollToRow(row_id)
{
//	$jq.scrollTo($jq(row_id), 800);
}

// PRINTING OPTIONS
function ShowPrintOptions()
{
	document.getElementById('print-options').style.display = 'block';
}

function HidePrintOptions()
{
	document.getElementById('print-options').style.display = 'none';
}

function ShowImportBox()
{
	document.getElementById('import-options').style.display = 'block';
};

function HideImportOptions()
{
	document.getElementById('import-options').style.display = 'none';
}

var gBackground = true;
var gBorders = true;
var gHeaders = true;
function ToggleBackgrounds()
{

	if (gBackground)
	{
		document.getElementById('backgrounds').style.display = 'none';
		document.getElementById('blank').style.display = 'block';
	}
	else
	{
		document.getElementById('backgrounds').style.display = 'block';
		document.getElementById('blank').style.display = 'none';
	}
	gBackground = !gBackground;
}

function ToggleBorders()
{
	if (gBorders)
		document.getElementById('borders').style.display = 'none';
	else document.getElementById('borders').style.display = 'block';

	gBorders = !gBorders;
}

function ToggleHeaders()
{
	if (gHeaders)
		document.getElementById('headers').style.display = 'none';
	else document.getElementById('headers').style.display = 'block';

	gHeaders = !gHeaders;
}

function ToggleBullets(style)
{
	if (style == 'bullet')
	{
		document.getElementById('numbers').style.display = 'none';
		document.getElementById('bullets').style.display = 'block';
	}
	else
	{
		document.getElementById('numbers').style.display = 'block';
		document.getElementById('bullets').style.display = 'none';
	}
}

// --------------------------------
// inline editing related functions
// --------------------------------
function GetCursorPosition()
{
	var cursorPos;
	if (window.getSelection)
	{
		var selObj = window.getSelection();
		var selRange = selObj.getRangeAt(0);
		cursorPos =  findNode(selObj.anchorNode.parentNode.childNodes, selObj.anchorNode) + selObj.anchorOffset;
		/* FIXME the following works wrong in Opera when the document is longer than 32767 chars */
	}
	else if (document.selection)
	{
		var range = document.selection.createRange();
		var bookmark = range.getBookmark();
		/* FIXME the following works wrong when the document is longer than 65535 chars */
		cursorPos = bookmark.charCodeAt(2) - 11; /* Undocumented function [3] */
	}
	return cursorPos;
}

function findNode(list, node)
{
	for (var i = 0; i < list.length; i++)
	{
		if (list[i] == node)
			return i;
	}
	return -1;
}

function SetCursorPosition(browser, obj_id, position)
{
	obj = document.getElementById(obj_id);
	
	if (browser == 'Firefox')
	{
		obj.focus();
//		return;						// this has been added. still to be tested fully
	}

	if (obj.setSelectionRange)
	{
		obj.focus();  
		obj.setSelectionRange(position, position);
	}
	else if (obj.createTextRange)
	{
		var range = obj.createTextRange();
		range.move("character", position);  
		range.select(); 
	}
	else if (window.getSelection)					// Firefox and Safari
	{
		s = window.getSelection();
		var r1 = document.createRange();

		var walker=document.createTreeWalker(obj, NodeFilter.SHOW_ELEMENT, null, false);
		var p = position;
		var n = obj;

		while(walker.nextNode())
		{
			n = walker.currentNode; alert(n);
			if (p > n.value.length)
				p -= n.value.length;
			else break;
		}

		n = n.firstChild;

		if (obj.innerHTML == '')
			obj.focus();
		else
		{
			r1.setStart(n, p);
			r1.setEnd(n, p);
	
			s.removeAllRanges();
			s.addRange(r1);
		}
	}
	else if (document.selection)					// Internet Explorer
	{
		var r1 = document.body.createTextRange();
		r1.moveToElementText(obj);
		r1.setEndPoint("EndToEnd", r1);
		r1.moveStart('character', position);
		r1.moveEnd('character', position-obj.innerText.length);
		r1.select();
	}
	
	return false;
}

// --------------------------------
// end of inline editing functions
// --------------------------------

function CanShowElementBelow(element_to_display, ref_element)
{
	element_bottom = $jq(ref_element).offset().top + $jq(ref_element).height();

	win_scrollTop = $(window).scrollTop;
	if (win_scrollTop)
		element_bottom -= win_scrollTop;
	
	hud_height = $jq(element_to_display).height();
	window_height = $jq(window).height();
	
	if (element_bottom + hud_height < window_height)
		return true;
	else return false;
}

function DuplicateObject(obj)
{
	return jQuery.extend(true, {}, obj);
}

function UnsetAttribute(myArray, myKey)
{
	for (key in myArray)
	{
	    if (key == myKey)
	        myArray.splice(key, 1);
	}
}

function print_r(arr,level)
{
	var dumped_text = "";
	if(!level) level = 0;
	
	//The padding given at the beginning of the line.
	var level_padding = "";
	for(var j=0;j<level+1;j++) level_padding += "    ";
	
	if(typeof(arr) == 'object') { //Array/Hashes/Objects 
		for(var item in arr) {
			var value = arr[item];
			
			if(typeof(value) == 'object') { //If it is an array,
				dumped_text += level_padding + "'" + item + "' ...\n";
				dumped_text += dump(value,level+1);
			} else {
				dumped_text += level_padding + "'" + item + "' => \"" + value + "\"\n";
			}
		}
	} else { //Stings/Chars/Numbers etc.
		dumped_text = "===>"+arr+"<===("+typeof(arr)+")";
	}
	alert(dumped_text);
}
