/*
__________________________________________________________________________________________

***** THERE IS NO REVIZE SCRIPT (I.E. JSP CODE) OR JSP INCLUDES IN THIS FILE *****

The #RevizeProperties jsp comment used by Dreamweaver and should be retained

Begining code should only be needed to view calendar and moved to calendar_app_view.js
Code for editing mostly at end of file should stay here however there are probably 
new functions and constants at the end that are needed for viewing.

These javascript files are great canidates for plugins folder.
__________________________________________________________________________________________

*/
/*-----------------------------------------------------------------------------
toggle debug; called by invisible link in heading
-----------------------------------------------------------------------------*/
function setDebug(win)
{
	if (typeof win == 'undefined') win = window;

	var debugState = !RZ.debug
	if (win.confirm('Set debug ' + debugState + '?'))
	{
		RZ.debug = debugState
		win.onunload = null;
		win.location.reload()
	}

	return void(0)
}
/*-----------------------------------------------------------------------------
If reloading frame - only can be used from inside this file
-----------------------------------------------------------------------------*/
function RZisReload()
{
	if(typeof RZ == 'undefined'
	|| typeof RZ.calendar == 'undefined'
	|| typeof RZ.calendar.date == 'undefined'
	|| typeof RZ.calendar.isDataLoaded == 'undefined')
		return true
	else
		return false
}
/*-----------------------------------------------------------------------------
Soft reload of specified url in specified frame
-----------------------------------------------------------------------------*/
function RZsoftReload(frame)
{
	if (navigator.appVersion.indexOf('MSIE') != -1)	//IE
		frame.history.go(0);

	else											//NS
		frame.location.reload(true);
}
/*-----------------------------------------------------------------------------
Load frame with specified url
Note: iframe frames should not be reloaded until parent page comletes loading
-----------------------------------------------------------------------------*/
function RZloadFrame(frame,url)
{
	url = RZ.calendar.pathname + url;
	frame.location.replace(url);
}
/*-----------------------------------------------------------------------------
Clear last scheduled timeout
-----------------------------------------------------------------------------*/
function RZclearTimeout()
{
	if (typeof RZ.calendar.timeout != 'undefined'
	&& RZ.calendar.timeout != null)
		clearTimeout(RZ.calendar.timeout);
	RZ.calendar.timeout = null
}
/*-----------------------------------------------------------------------------
Parses parameters after hash # see wiki for syntax
http://redmine.revize.com/projects/calendar/wiki/Wiki

Returns:
	RZ.calendar.name
	RZ.calendar.date
	RZ.calendar.view
	RZ.calendar.minihtml
	RZ.calendar.css
	updates cooresponding cookies (backward compatibility)

Note:
	Calendar cookies cleared if any parameters are specified.
-----------------------------------------------------------------------------*/
function RZcalendarParameters()
{
    var key, end;
    var calname = ''
    var caldate = new Date();
    var calview = 'month'	//default if not iframe
    if (parent.location.href != document.location.href)
    	calview = 'brief'	//default if called from iframe
    var calminihtml = 'calendar_mini.html';
 	var calcss = '';	

	var hash = location.hash
	if (hash.length > 0)
	{
		hash = hash.substring(1);
		if (hash.indexOf('%') != -1) hash = unescape(hash);
		hash = hash.replace(/,{2,}/g,',');
	}
	if (hash.substr(0,1) == ',')
		hash = hash.substr(1);

	//----- check for css= (or new paramater; css depreciated)
	key = 'css=';
	pos = hash.indexOf(key);
	if (pos != -1)
	{
		calcss = hash.substr(pos+key.length);
		hash = hash.substring(0,pos);
		if (RZright(hash,1) == ',')
			hash = hash.substr(0,hash.length-1);
	}

	//----- check for -mini= if found remove and save specified filename
	key = '-mini=';
	pos = hash.indexOf(key);
	if (pos != -1)
	{
		end = hash.indexOf(',',pos);
		if (end < 0) end = hash.length;		//> fixes display
       	calminihtml = hash.substring(pos+key.length,end);
		if (calminihtml == '*')	calminihtml = 'calendar_mini_base.html';
		hash = hash.substring(0,pos+key.length-1) + hash.substring(end);
	}

	//----- Check for view
	RZ.calendar.selectDay = true;
	var pos = hash.lastIndexOf('-')
	if (pos != -1)
	{
		var opt = hash.substring(pos+1).toLowerCase()
		switch (opt)
		{
			case 'month':
			case 'week':
			case 'day':
			case 'brief':
			case 'mini':
				calview = opt;
				hash = hash.substring(0,pos)
				RZ.calendar.isCurrentMonth = true;
				break;
			default:
		}
	}

	//----- Strip trailing blanks and/or commas
	while (hash.length > 0
	&& (hash.substring(hash.length-1)==' '
	||  hash.substring(hash.length-1)==','))
		hash = hash.substring(0,hash.length-1)

	//----- Check for date
	//dave, feb 2, 1999
	//10-22-1998
	//feb 28, 1999

    pos = hash.indexOf(',');
    if (pos == -1) pos = hash.lastIndexOf(' ');
    if (pos != -1)
    {
		// if 2nd comma or date is valid after 1st comma
		if ( hash.indexOf(',',pos+1) != -1
		|| !isNaN(Date.parse(replace(hash,'-','/').substring(pos))) )
		{
			calname = hash.substring(0,pos);
			caldate = hash.substring(pos+1);
		}
		//	is hash is valid date using first comma
		else if ( !isNaN(Date.parse(replace(hash,'-','/'))) )
		{
			calname = ''		//no name
			caldate = hash;		//have date
			RZ.calendar.isCurrentMonth = false;
		}
		else
		{
			calname = hash
			caldate = new Date()
		}
	}
	else if ( !isNaN(Date.parse(replace(hash,'-','/'))) )
		caldate = hash;		//have date
	else
		calname = hash;		//have name

	//----- validate date
	if (caldate)
	caldate = new Date(replace(caldate,'-','/'));
	else
		caldate = new Date();	//safari does not work with empty string
	if ( isNaN(caldate) )
		caldate = new Date();

	//----- See if only specified calendar is allowed
	if (calname.indexOf('*') == 0)
	{
		calname = calname.substring(1);
		RZ.calendar.exclusive = calname;
	}

	//----- Save specified calender name, date, view and minihtml
	RZ.calendar.name = RZrestoreName(calname);
	RZ.calendar.date = caldate;
	RZ.calendar.view = calview;
	RZ.calendar.minihtml = calminihtml;
	RZ.calendar.css = calcss;
	if (calview == 'mini' && RZwinaccess(parent) && parent.RZ)
	{
		if (!parent.RZ.calendar) parent.RZ.calendar = {};
		parent.RZ.calendar.minihtml = calminihtml;
		parent.RZ.calendar.css = calcss;
	}
	else
		RZ.calendar.isFrames = true;
}

/*-----------------------------------------------------------------------------
Checks if the given month in given year active in javaScript Database
Month ranges from 1 to 12; year is 4 digit year
-----------------------------------------------------------------------------*/
function RZis_activemonth(month, year)
{
	toRet = false;
	if ( ( typeof RZ != 'undefined' )
	&& ( typeof RZ.calendar != 'undefined' )
	&& ( typeof RZ.calendar.months != 'undefined' )
	&& ( typeof RZ.calendar.months[month] != 'undefined' )
	&& ( typeof RZ.calendar.months[month].years != 'undefined' ) )
	{
		var numElems = RZ.calendar.months[month].years.length;
		for ( var i = 0; i < numElems; i++ )
		{
			if ( ( typeof RZ.calendar.months[month].years[i] != 'undefined' )
				&& ( year == RZ.calendar.months[month].years[i].year ) )
			{
				toRet = true;
				break;
			}
		}
	}
	return toRet;
}

/*-----------------------------------------------------------------------------
Adds a new object to the calendar, month , year tree from javaScript DB
Month ranges from 1 to 12; year is 4 digit year
-----------------------------------------------------------------------------*/
function RZactivemonth_add(month,year)
{
	//----- Create months and months[month] object
	if (typeof RZ.calendar.months == 'undefined') RZ.calendar.months = new Object();
	if (typeof RZ.calendar.months[month] == 'undefined') RZ.calendar.months[month] = new Object();

	//----- Determine next year index
	//		(if necessary, create RZ.calendar.months[month].years)
	var yrIdx = 0;
	if (typeof RZ.calendar.months[month].years == 'undefined')
		RZ.calendar.months[month].years = new Array();
	else
		yrIdx = RZ.calendar.months[month].years.length;

	//----- Create new event object and set year
	RZ.calendar.months[month].years[yrIdx] = new Object();
	RZ.calendar.months[month].years[yrIdx].year = year;

	return;
}
/*-----------------------------------------------------------------------------
Used for getting the active month file name,
that is to be included depending on the calendar name
-----------------------------------------------------------------------------*/
function RZgetActiveMonthListFileName( calendarName )
{
	if ( null == calendarName || "" == calendarName )
		return null;

	var calid = RZ.calendar.ids[calendarName.toLowerCase()]
	return ("calendar_" + calid + "_activemonths.html")
}

/*-----------------------------------------------------------------------------
Used for getting the active month file name also based on the calendar name.
month ranges from 1 to 12; year is 4 digit year
-----------------------------------------------------------------------------*/
function RZgetActiveMonthDataFileName( calendarName, year, month )
{
	if (null == calendarName || "" == calendarName)
		return null;

	else if (null == year)
		return null;

	else if (null == month || month < 1 || month > 12)
		return null;

	var monthStr = (month).toString()
	if (monthStr.length == 1)
		monthStr = '0' + monthStr;

	var calid = RZ.calendar.ids[calendarName.toLowerCase()]
	var filename = "calendar_" + calid
				 + "_activemonthsdata_"
				 + year + '-' + monthStr + ".html";

	return filename;
}
/*-----------------------------------------------------------------------------
Return number of events for specified day
days (optional): either RZ.calendar.days (default) or RZ.calendar.daysNext
-----------------------------------------------------------------------------*/
function RZevent_count(day,days)
{
	if (RZ.calendar && days !== null)
	{
		if (!days) days = RZ.calendar.days
		if (days && days[day] && days[day].events)
			return days[day].events.length;
	}
	return 0;
}
/*-----------------------------------------------------------------------------
Return specified event for specified day for active months
used in javaScript Database
days (optional): either RZ.calendar.days (default) or RZ.calendar.daysNext
-----------------------------------------------------------------------------*/
function RZevent_get(day,eventIdx,days)
{
	if (RZ.calendar)
	{
		if (!days) days = RZ.calendar.days
		if (days && days[day] && days[day].events)
			return days[day].events[eventIdx];
	}
	return null;
}
/*-----------------------------------------------------------------------------
Return mixed case calendar name
-----------------------------------------------------------------------------*/
function RZcalendarName(calname)
{
	if (RZisReload()) return '';

	if (typeof calname == 'undefined')
		calname = RZ.calendar.name;

	if (calname != '')
	{
		var calid = RZ.calendar.ids[calname.toLowerCase()];
		calname = RZ.calendar.names[calid];
	}

	return calname;
}
/*-----------------------------------------------------------------------------
Restore calendar name after reading from cookie or url
-----------------------------------------------------------------------------*/
function RZrestoreName(filename)
{
	filename = replace(filename,'%20',' ')
	filename = replace(filename,'&sqout',"'")
	return filename;
}
/*-----------------------------------------------------------------------------
Restore calendar name after reading from cookie or url
-----------------------------------------------------------------------------*/
function replace( inStr, fromString, toString )
{
	var pos = 0
	if (inStr == null
	|| typeof inStr.length == 'undefined' //true or false
	|| inStr.length == 0) return '';

	var fromLen = fromString.length
	if (fromLen == 0) return inStr

	while (true)
	{
		pos = inStr.indexOf(fromString,pos)
		if (pos == -1) break
		inStr = RZsubstring( inStr, 0, pos )
		      + toString
		      + RZsubstring( inStr, pos + fromLen )
		pos += toString.length
	}
	return inStr
}
/*-----------------------------------------------------------------------------
Returns day of week
-----------------------------------------------------------------------------*/
function RZdayName(date)
{
	var days = new Array("Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday");
	return days[ date.getDay() ];
}
/*-----------------------------------------------------------------------------
Returns month of year
-----------------------------------------------------------------------------*/
function RZmonthName(date)
{
	var months = new Array('January','February','March','April','May','June',
	                       'July','August','September','October','November','December');
	return months[ date.getMonth() ];
}
/*-----------------------------------------------------------------------------
Returns day with suffix: e.g. 1st, 2nd, 3rd, 4th, etc.
-----------------------------------------------------------------------------*/
function RZdaySuffix(date)
{
    var suffix = ''
    var day = date.getDate();
    if (day == 1 || day == 21 || day == 31)
    	suffix = 'st';
    else if (day == 2 || day == 22)
    	suffix = 'nd';
    else if (day == 3 || day == 23)
    	suffix = 'rd';
    else
    	suffix = 'th';
    return day + '<span class="eventDaySuffix">' + suffix + '</span>';
}
/*-----------------------------------------------------------------------------
method to convert the military time to am and pm, put space at end if not blank
-----------------------------------------------------------------------------*/
function RZgetTimeInAmPmSpace(time)
{
	var returnValue = RZgetTimeInAmPm(time);
	if (returnValue != '')
		returnValue += ' '
	return returnValue
}
/*-----------------------------------------------------------------------------
method to convert the military time to am and pm
-----------------------------------------------------------------------------*/
function RZgetTimeInAmPm(time)
{

	if (time == '' || time == ':')
		return '';

	var inParts = time.split(":");
	var am_pm;
	if(inParts[0] =='0')
	{
		am_pm = " am";
		inParts[0] = '12'
		return (inParts[0] + ":" + inParts[1] + am_pm);
	}
	if(inParts[0] =='1' || inParts[0] =='2' || inParts[0] =='3' || inParts[0] =='4' || inParts[0] =='5'
	|| inParts[0] =='6' || inParts[0] =='7' || inParts[0] =='8' || inParts[0] =='9' || inParts[0] =='10'
	|| inParts[0] =='11'||inParts[0] =='12' )
	{
		am_pm = " am";
		if(inParts[0] =='12')
			am_pm = " pm";
		return (inParts[0] + ":" + inParts[1] + am_pm);
	}
	else
	{
		am_pm = " pm";
	}
	if(inParts[0] =='13')
		inParts[0] = '1'
	if(inParts[0] =='14')
		inParts[0] = '2'
	if(inParts[0] =='15')
		inParts[0] = '3'
	if(inParts[0] =='16')
		inParts[0] = '4'
	if(inParts[0] =='17')
		inParts[0] = '5'
	if(inParts[0] =='18')
		inParts[0] = '6'
	if(inParts[0] =='19')
		inParts[0] = '7'
	if(inParts[0] =='20')
		inParts[0] = '8'
	if(inParts[0] =='21')
		inParts[0] = '9'
	if(inParts[0] =='22')
		inParts[0] = '10'
	if(inParts[0] =='23')
		inParts[0] = '11'

	return (inParts[0] + ":" + inParts[1] + am_pm);
}
/*-----------------------------------------------------------------------------
Set target for all links
-----------------------------------------------------------------------------*/
function RZsetTarget(win,targetName)
{
	if (!win) win = window;
	if (!targetName) targetName = '_new';
	var links = win.document.getElementsByTagName('a');
	if (links)
		for (i=0;i<links.length;i++)
			if (links[i].href.toLowerCase().indexOf('javascript:') != 0)
				links[i].target = targetName;
}
/******************************************************************************
Above code is only needed to view mini? calendar - remainder needed for editing
******************************************************************************/
/**	calendar_app.js
 *  JavaScript Library used for Calendar Application
 *
 *  $Author:   mindfire  $
 */

/*-----------------------------------------------------------------------------
Define RZ object and variables usually defined in jsp headers
-----------------------------------------------------------------------------*/
if (typeof RZ == 'undefined') var RZ = new Object();
if (typeof RZ.calendar == 'undefined') RZ.calendar = new Object();
if (typeof RZ.calendar.name == 'undefined') RZ.calendar.name = "";
if (typeof RZ.calendar.group == 'undefined') RZ.calendar.group = "";
if (typeof RZ.calendar.view == 'undefined') RZ.calendar.view = "";
if (typeof RZ.calendar.viewdate == 'undefined') RZ.calendar.viewdate = null;
if (typeof RZ.calendar.debug == 'undefined') RZ.calendar.debug = false;

/*-----------------------------------------------------------------------------
Define RZ authentication variables set/used in various files across application
-----------------------------------------------------------------------------*/
// credentials for all defined calendars
if (typeof RZ.calendar.credentials == 'undefined') RZ.calendar.credentials = new Array();

// credentials for current calendar being displayed
if (typeof RZ.calendar.user == 'undefined') RZ.calendar.user = "";
if (typeof RZ.calendar.roles == 'undefined') RZ.calendar.roles = "";
if (typeof RZ.calendar.administrators == 'undefined') RZ.calendar.administrators = "";
if (typeof RZ.calendar.editors == 'undefined') RZ.calendar.editors = "";
if (typeof RZ.calendar.rolluplist == 'undefined') RZ.calendar.rolluplist = "";

/*-----------------------------------------------------------------------------
Define variables commonly used in Calendar Application
-----------------------------------------------------------------------------*/

//the day number in order of display in weekview
var RZweekDayArray = ["1","4","2","5","3","6","7"];

//set for time not defined
var RZblankTime = 100;

//set for the time delay in the calendar heading

var RZtimeOut = 1000;

//set for the time delay for the notable event display
var RZtimeOut_notable = 1500;

//set for the time delay the display of the main bodies
var RZtimeOut_main = 1000;

var RZcount = 0;

//set to default start hour
var RZdefaultStartTimeHour = 8;

//month array used in HTML for all the views
var RZmonthNameArr = ["January", "February", "March", "April", "May", "June",
						"July", "August", "September", "October", "November", "December"];

var RZmonthArray = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];

//time array to get the time in the day view
var RZtimeArr = ["12","1","2","3","4","5","6","7","8","9","10","11","12","1",
				"2","3","4","5","6","7","8","9","10","11"];

// day array to get the day name
var RZdayArr = ["", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"];

// variable which sets the summary length
var RZsummaryLength = 30;

//variable which represents a blank when entered in the url
var RZcharSpace = "%20";

//variable that specifies the minimum duration
var RZminDuration = 15;

/*-----------------------------------------------------------------------------
Function Block - Active Months
-----------------------------------------------------------------------------*/
function addRZcharSpace(file_name)
{
	var new_file="";
	for(var u=0;u<file_name.length;u++)	{
		if(file_name.charAt(u) == ' ') {
			new_file += RZcharSpace;
		} else {
			new_file += file_name.charAt(u);
		}
	}
	return new_file;
}

/*-----------------------------------------------------------------------------
Function to deselect a list on the basis of
"-Select-", "-Roles-" and "-Users-" option
-----------------------------------------------------------------------------*/
function deselectValue(formList)
{
	for (var i = 0; i < formList.length; i++)
	{
		if (formList.options[i].text == "-Select-"
		|| formList.options[i].text == "-Users-"
		|| formList.options[i].text == "-Roles-")
		{
			formList.options[i].selected = false;
		}
	}
}

/*-----------------------------------------------------------------------------
Return year,month,day,event string for use on calendar days javascript links
-----------------------------------------------------------------------------*/
function formatEventClick(date,eventIndex)
{
	var str = date.getFullYear() + ',' + (date.getMonth()+1) + ',' + date.getDate()
	if (typeof(eventIndex) != 'undefined') str += ',' + eventIndex;
	return str;
}

/*-----------------------------------------------------------------------------
Function which checks whether the date is same
-----------------------------------------------------------------------------*/
function checkForSameDate (date1, date2 )
{
	if (date1.getDate() == date2.getDate()
	&& date1.getMonth() == date2.getMonth()
	&& date1.getFullYear() == date2.getFullYear())
		return true;
	else
		return false;
}
/*-----------------------------------------------------------------------------
Function to popup the event details
-----------------------------------------------------------------------------*/
function RZpopupEventDetail(eventid, show_event)
{

	var eventurl = "../calendar_view_common/calendar_event_detail.html#"
				+ eventid + "#" + show_event;
	RZ.calendar.eventwindow = RZpopupUrl('Events',eventurl,'600','500','');
	window.focus()
}

/*-----------------------------------------------------------------------------
Function to popup the signup form

Input Arguments:
coordinator_email-		email address of event coordinator
supervisor_approval-	'yes' if supervisor approval is required
-----------------------------------------------------------------------------*/
function RZpopupSignupDetail(coordinator_email, supervisor_approval, eventid, date)
{
	//----- Calculate absolute url reference (allows call from any frame)
	var url = location.href;
	var pos = url.indexOf('#')
	if (pos != -1)
		url = url.substring(0,pos)
	url = url.substring(0,url.lastIndexOf("/"))

	if (location.pathname.indexOf('/calendar_mini') != -1)
		url = url.substring(0,url.lastIndexOf('/'));
	url += "/calendar_view_common/calendar_main_signup.html";

	RZ.calendar.coordinator_email = coordinator_email;
	RZ.calendar.supervisor_approval = supervisor_approval;
	RZ.calendar.eventId = eventid;
	RZ.calendar.date = new Date(date);
	RZ.calendar.signupwin = RZpopupUrl('RZsignup', url, '520', '500', 'no');
	return void(0);		//for href value
}
/*-----------------------------------------------------------------------------
Function to parse the path to get the webspace path
-----------------------------------------------------------------------------*/
function parse_path(pathname)
{
	var c = 0;
	var signpath = "";
	for ( i=0; i<pathname.length ;i++)
	{
		signpath += pathname.charAt(i);
		if ( pathname.charAt(i) == '/' )
			c++;

		if (c == 2 )
		{
			i++;
			while ( i != pathname.length && pathname.charAt(i) != '/' )
			{
				signpath += pathname.charAt(i);
				i++;
			}
			break;
		}
	}
	return signpath;
}

/*-----------------------------------------------------------------------------
Create & return new event object for specified day of month
used in javaScript Database
-----------------------------------------------------------------------------*/
function RZevent_addMonth(inDate)
{
	var dateObj = null;
	dateObj = new Date(inDate);

	return RZevent_add(dateObj.getDate());
}

/*-----------------------------------------------------------------------------
Create & return new event object for specified day of month
used in javaScript Database
-----------------------------------------------------------------------------*/
function RZevent_add(day)
{
	var dayObj = !RZ.calendar.isNextMonthDataLoaded ? 'days' : 'daysNext';

	//----- Create days and days[day] object
	if (typeof RZ.calendar[dayObj] == 'undefined')
		RZ.calendar[dayObj] = new Object();

	if (typeof RZ.calendar[dayObj][day] == 'undefined')
		RZ.calendar[dayObj][day] = new Object();

	//----- Determine next event index (if necessary, create RZ.calendar.days[day].events)
	var eventIdx = 0;
	if ( typeof RZ.calendar[dayObj][day].events == 'undefined')
		RZ.calendar[dayObj][day].events = new Array();
	else
		eventIdx = RZ.calendar[dayObj][day].events.length;

	//----- Create new event object
	RZ.calendar[dayObj][day].events[eventIdx] = new Object();
	return RZ.calendar[dayObj][day].events[eventIdx];
}


/*-----------------------------------------------------------------------------
Returns array of years for the calendar.
used in Calendra Header, fetched from javascript database
-----------------------------------------------------------------------------*/
function RZgetAllYears()
{
	var arr = new Array();
	var flag = false;
	var numElems, i, j, year;

	if ( typeof RZ != 'undefined'
	&& typeof RZ.calendar != 'undefined'
	&& typeof RZ.calendar.months != 'undefined')
	{
		for (var month = 0; month < 12; month++) {
			if ( ( typeof RZ.calendar.months[month] != 'undefined' )
				&& ( typeof RZ.calendar.months[month].years != 'undefined' ) )
			{
				numElems = RZ.calendar.months[month].years.length;
				for ( i = 0; i < numElems; i++ ) {
					if ( typeof RZ.calendar.months[month].years[i] != 'undefined' )	{
						year = RZ.calendar.months[month].years[i].year;
						for ( j = 0; j < arr.length; j++ ) {
							if ( arr[j] == year ) {
								flag = true;
								break;
							}
						}
						if ( false == flag ) {
						//this implies year doesn't already exist.
						//so insert in the array arr
							arr[arr.length] = year;
						} else {
							flag = false;
						}
					}
				}
			}
		}
	}
	return arr;
}

/*-----------------------------------------------------------------------------
Function Block - Active Weeks
-----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------
Function to find the weekdate and the file name
-----------------------------------------------------------------------------*/
function RZgetWeekDate(day)
{
	//RETRIEVING THE DATE
	var wdate = RZgetDateForView( RZ.calendar.date );

	//CALLING THE FUNCTION TO FIND THE DATE AND MONTH
	var RZweekDate = RZgetCurrentDate(wdate, day);
	weekDate = new Date( RZweekDate.getFullYear(), RZweekDate.getMonth(),
						RZweekDate.getDate());

	//RETRIEVING THE WEEK NUMBER
	var RZyearWeek = weekNumber_local(RZweekDate);
	return weekDate;
}

/*-----------------------------------------------------------------------------
Return specified event for specified day[1 - 7 for Mon - Sun]  for active weeks
used in javaScript Database
-----------------------------------------------------------------------------*/
function RZeventfromweek_get(day,eventIdx)
{
	if ( typeof RZ.calendar != 'undefined'
	&& typeof RZ.calendar.weekdays != 'undefined'
	&& typeof RZ.calendar.weekdays[day] != 'undefined'
	&& typeof RZ.calendar.weekdays[day].events != 'undefined'
	&& typeof RZ.calendar.weekdays[day].events[eventIdx] != 'undefined')
		return RZ.calendar.weekdays[day].events[eventIdx];
	 else
		return null;
}

/*-----------------------------------------------------------------------------
Create & return new event object for specified day[1 - 7 for Mon - Sun] of week
used in javaScript Database
-----------------------------------------------------------------------------*/
function RZevent_addWeek(inDate)
{
	var dateObj = null;
	var dayNo;

	dateObj = new Date(inDate);
	dayNo = dateObj.getDay();
	if ( 0 == dayNo ) dayNo = 7;

	return RZeventtoweek_add(dayNo);
}

/*-----------------------------------------------------------------------------
Create & return new event object for specified day[1 - 7 for Mon - Sun] of week
used in javaScript Database
-----------------------------------------------------------------------------*/
function RZeventtoweek_add(day)
{
	//----- Create weekdays and weekdays[day] object
	if (typeof RZ.calendar.weekdays == 'undefined')
		RZ.calendar.weekdays = new Object();

	if (typeof RZ.calendar.weekdays[day] == 'undefined')
		RZ.calendar.weekdays[day] = new Object();

	//----- Determine next event index (if necessary, create RZ.calendar.weekdays[day].events)
	var eventIdx = 0;
	if ( typeof RZ.calendar.weekdays[day].events == 'undefined')
		RZ.calendar.weekdays[day].events = new Array();
	else
		eventIdx = RZ.calendar.weekdays[day].events.length;

	//----- Create new event object
	RZ.calendar.weekdays[day].events[eventIdx] = new Object();
	return RZ.calendar.weekdays[day].events[eventIdx];
}

/*-----------------------------------------------------------------------------
Used for getting the active week file name,
that is to be included depending on the calendar name
-----------------------------------------------------------------------------*/
function RZgetActiveWeekListFileName( calendarName )
{
	if ( null == calendarName || "" == calendarName )
		return null;

	var calid = RZ.calendar.ids[calendarName.toLowerCase()]
	return ("calendar_" + calid + "_activeweeks.html")
}

/*-----------------------------------------------------------------------------
Used for getting the active week's data file name,
that is to be included depending on the calendar name
-----------------------------------------------------------------------------*/
function RZgetActiveWeekDataFileName( calendarName, year, yearweek )
{
	if (null == calendarName || "" == calendarName)
		return null;

	else if (null == year)
		return null;

	else if (null == yearweek || 1 > yearweek || 53 < yearweek)
		return null;

	//----- Published filenames can not contain single quote
	calendarName = replace(calendarName,"'","_");

	var yearweekStr = yearweek.toString()
	if (yearweekStr.length == 1)
		yearweekStr = '0' + yearweekStr;

	var calid = RZ.calendar.ids[calendarName.toLowerCase()]
	var filename = "calendar_" + calid
				 + "_activeweeksdata_"
				 + year + '-' + yearweek + ".html";

	return filename;
}

/*-----------------------------------------------------------------------------
Checks if the given week in given year active in javaScript Database
-----------------------------------------------------------------------------*/
function RZis_activeweek(yearweek, year)
{
	toRet = false;
	if ( ( typeof RZ.calendar != 'undefined' )
	&& ( typeof RZ.calendar.yearweeks != 'undefined' )
	&& ( typeof RZ.calendar.yearweeks[yearweek] != 'undefined' )
	&& ( typeof RZ.calendar.yearweeks[yearweek].years != 'undefined' ) )
	{
		var numElems = RZ.calendar.yearweeks[yearweek].years.length;
		for ( var i = 0; i < numElems; i++ )
		{
			if ( ( typeof RZ.calendar.yearweeks[yearweek].years[i] != 'undefined' )
			&& ( year == RZ.calendar.yearweeks[yearweek].years[i].year ) )
			{
				toRet = true;
				break;
			}
		}
	}
	return toRet;
}

/*-----------------------------------------------------------------------------
Adds a new object to the calendar, yearweek , year tree from javaScript DB
-----------------------------------------------------------------------------*/
function RZactiveweek_add(yearweek,year)
{
	//----- Create yearweeks and yearweeks[yearweek] object
	if (typeof RZ.calendar.yearweeks == 'undefined')
		RZ.calendar.yearweeks = new Object();

	if (typeof RZ.calendar.yearweeks[yearweek] == 'undefined')
		RZ.calendar.yearweeks[yearweek] = new Object();

	//----- Determine next year index
	// (if necessary, create RZ.calendar.yearweeks[yearweek].years)
	var yrIdx = 0;
	if (typeof RZ.calendar.yearweeks[yearweek].years == 'undefined')
		RZ.calendar.yearweeks[yearweek].years = new Array();
	else
		yrIdx = RZ.calendar.yearweeks[yearweek].years.length;

	//----- Create new event object
	RZ.calendar.yearweeks[yearweek].years[yrIdx] = new Object();
	RZ.calendar.yearweeks[yearweek].years[yrIdx].year = year;

	return;
}


/*-----------------------------------------------------------------------------
General Function Block
-----------------------------------------------------------------------------*/

/*-----------------------------------------------------------------------------
Returns current date if cookie is not set
-----------------------------------------------------------------------------*/
function RZgetDateForView( date )
{
	if ( "" == date )
		date = new Date();
	else
		date = new Date(date);
		if ( isNaN(date) ) date = new Date();

	return date;
}

/*-----------------------------------------------------------------------------
Function to sort Array
-----------------------------------------------------------------------------*/
function RZsortArray(inArr)
{
	if ( null == inArr ) return null;

	var temp, i, j, k;

	for ( i = 0; i <= (inArr.length - 2); i++ )
	{
		for ( j = i+1; j <= (inArr.length - 1); j++ )
		{
			if ( inArr[i] > inArr[j] )
			{
				temp = inArr[i];
				inArr[i] = inArr[j];
				inArr[j] = temp;
			}
		}
	}
	return inArr;
}

/*-----------------------------------------------------------------------------
Function to check if input string is numeric or not
-----------------------------------------------------------------------------*/
function RZisNumeric(strVal)
{
	var ch;
	for (var n = strVal.length - 1; n >= 0; n--)
	{
		ch = strVal.charAt (n);
		if ( !( ch>='0' && ch<='9' ) )
			return false;
	}
	return true;
}

/*-----------------------------------------------------------------------------
Function to check if input string is alphanumeric or not
-----------------------------------------------------------------------------*/
function RZisAlphaNumeric(strVal)
{
	var ch;
	for (var n = strVal.length - 1; n >= 0; n--)
	{
		ch = strVal.charAt (n);
		if (!( ( ch>='a' && ch<='z' )
		|| ( ch>='A' && ch<='Z' )
		|| ( ch>='0' && ch<='9' )))
		{
			return false;
		}
	}
	return true;
}

/*-----------------------------------------------------------------------------
Function to check if input character is digit or not
-----------------------------------------------------------------------------*/
function RZisDigit (ch)
{
	if ( ch>='0' && ch<='9' )
		return true;
	else
		return false;
}

/*-----------------------------------------------------------------------------
used in the weekview to view the dates and day name
gets the currentdate and month
------------------------------------------------------------------------------*/
function RZgetCurrentDate(RZdate, RZday)
{
	var RZcurrentDay = RZdate.getDay();

	// CHANGING THE CURRENT DAY TO 7 FOR SUNDAY
	if (RZcurrentDay == 0)
		RZcurrentDay = 7;

	// GETTING THE CURRENT DATE, MONTH, YEAR
	var RZcurrentDate  = RZdate.getDate();
	var RZcurrentMonth = RZdate.getMonth();
	var RZcurrentYear  = RZdate.getFullYear();

	// FIND THE TOTAL DAYS IN A MONTH
	var RZtotalDays = getDaysInMonth_local(RZcurrentMonth, RZcurrentYear);

	if (RZday < RZcurrentDay)
	{
		RZcurrentDate = RZcurrentDate - (RZcurrentDay - RZday) ;
		if (RZcurrentDate <= 0)
		{
			RZcurrentMonth = RZcurrentMonth - 1;
			// CHECKING IF MONTH IS IN PREVIOUS YEAR
			if (RZcurrentMonth < 0)
			{
				RZcurrentMonth = 11;
				RZcurrentYear = RZcurrentYear - 1;
			}
			RZtotalDays = getDaysInMonth_local(RZcurrentMonth, RZcurrentYear);
			RZcurrentDate = RZcurrentDate + RZtotalDays;
		}
	}
	else if (RZday > RZcurrentDay)
	{
		RZcurrentDate = RZcurrentDate + ( RZday - RZcurrentDay);
		if (RZcurrentDate > RZtotalDays)
		{
			RZcurrentMonth = RZcurrentMonth + 1;
			//CHECKING IF MONTH IS IN NEXT YEAR
			if (RZcurrentMonth > 11)
			{
				RZcurrentMonth = 0;
				RZcurrentYear = RZcurrentYear + 1;
			}
			RZcurrentDate = RZcurrentDate - RZtotalDays;
		}
	}
	var RZDate = new Date(RZcurrentYear, RZcurrentMonth, RZcurrentDate);
	return RZDate;
}

/*-----------------------------------------------------------------------------
Function to get the hours
-----------------------------------------------------------------------------*/
function RZgetHrs(name)
{
	var hrsList = "<select name = '"+name+"' onChange='setStartHour()'>"

	for ( i = 0; i < 24; i++ )
	{
		if ( i == RZdefaultStartTimeHour )
			hrsList += "<option selected>";
		else
			hrsList += "<option>";

		hrsList += i + "</option>";
	}
	hrsList += "</select>";
	return hrsList;
}

/*-----------------------------------------------------------------------------
Function which validates the phone number
check if phone number is in the format (XXX) XXX-XXXX
-----------------------------------------------------------------------------*/
function checkPhoneNumber(phonenumber)
{

/* +--+ Phone no. format is changed

	var i;
	var phone = phonenumber.value;
	var lenPhone = phone.length;

	//if phone not available than no check
	if ( 0 == lenPhone ) return true;


	//if phone number only has blank spaces than error
	phone = RZtrim(phone);
	lenPhone = phone.length;
	if ( 0 == lenPhone ) return false;

	//if phone is lesser then the expected length than error
	if ( 11 > lenPhone ) return false;
	//if 1st char is not "(" than error
	if ( "(" != phone.charAt(0) ) return false;

	//next 3 chars must be digits if not error
	for ( i = 1; i < 4; i++ ) {
		if ( ! RZisDigit(phone.charAt(i) ) ) return false;
	}

	//next 2 chars must be ") " if not error
	if ( ( ")" != phone.charAt(4) ) || ( " " != phone.charAt(5) ) ) return false;

	//next 3 chars must be digits if not error
	for ( i = 6; i < 9; i++ ) {
		if ( ! RZisDigit(phone.charAt(i) ) ) return false;
	}

	//next char must be "-" if not error
	if ( "-" != phone.charAt(9) ) return false;

	//rest of the chars must be digits if not error
	for ( i = 10; i < lenPhone; i++ ) {
		if ( ! RZisDigit(phone.charAt(i) ) ) return false;
	}
	for ( i = 0; i < lenPhone; i++ ) {
		if ( ! RZisDigit(phone.charAt(i) ) ) return false;
	}
*/

	return true; //every thing is fine.

}

/*-----------------------------------------------------------------------------
Function which validates the phone number
check if phone number is in the format (XXX) XXX-XXXX
-----------------------------------------------------------------------------*/
function checkPhone(phoneNo)
{

return true;
/* no validation for phone no.
	if (phoneNo.value == '') return true;

	var phoneRE = /^\(*\d{3}\)*\s*\d{3}-*\d{4}$/;
	if (phoneNo.value.match(phoneRE)) {
		return true;
	} else {
		return false;
	}
*/
}

/*-----------------------------------------------------------------------------
Function which checks the validation of email
-----------------------------------------------------------------------------*/
function checkEmail(email_value)
{
	var i =0;
	var k;
	var email = email_value;

	if (email != '') {
		// FIRST AND LAST CHARACTER SHOULD NOT BE "@"
		if(email.charAt(0) == '@' || email.charAt(email.length-1)=='@')	{
			return false;
		}
		k = email.indexOf("@",i);
		if ( k < 0)	{
			return false;
		}
		i = k+1;
		k = email.indexOf("@",i);
		if (k > 0) {
			return false;
		}

		//SHOULD CONTAIN ONLY CHARS BETWEEN a-z, A-Z , 0-9, '-', '_', '.'
		for (var n = email.length - 1; n >= 0; n--)	{
			ch = email.charAt (n);
			if (!( ( ch>='a' && ch<='z' ) || ( ch>='A' && ch<='Z' )
				|| ( ch>='0' && ch<='9' ) || ( ch == '.' )
				|| ( ch == '-' ) || (ch == '_') || ( ch == '@' ) ))
		    	{
					return false;
		      	}
		 }
	}
	return true;

}

/*-----------------------------------------------------------------------------
Function to check the uniqueness of the calendar name
-----------------------------------------------------------------------------*/
function checkUniqueValue(cArr, cvalue)
{
	if ( typeof cArr != 'undefined')
	{
		for (u2 = 0; u2 < cArr.length; u2++)
		{
			if (cvalue == cArr[u2]) return false;
		}
	}
	return true;
}

/*-----------------------------------------------------------------------------
Function to retrieve the start time in minutes (input is X:XX)
-----------------------------------------------------------------------------*/
function RZgetTimeInMinutes(mvalue)
{
	var first=0;
	var second=0;
	var totalTime = 0;
	var timeIndex;

	if (mvalue != '')
	{
		timeIndex = mvalue.indexOf(":");
		first = mvalue.substring(0,timeIndex);
		second = mvalue.substring(timeIndex+1, mvalue.length);
		totalTime = (first * 60) + (second * 1);
	}
	else
		totalTime = 0;

	return totalTime;
}

/*-----------------------------------------------------------------------------
Function to display the error messages
-----------------------------------------------------------------------------*/
function RZfieldError (theField, errorMsg, win)
{
	if (typeof win == 'undefined') win = window;

	theField.focus()
	theField.select()
	win.alert(errorMsg)
	return false
}


/*-----------------------------------------------------------------------------
Function to replace the %20 string with blank
-----------------------------------------------------------------------------*/
function replaceSpace(filename)
{
	return replace(filename,'20%',' ');
}

/*-----------------------------------------------------------------------------
Function to remove starting "--"
-----------------------------------------------------------------------------*/
function removeStartHyphen( inStr )
{
	if ( 0 == inStr.indexOf("--") )
		inStr = inStr.substring(2);

	return(inStr);
}

/*-----------------------------------------------------------------------------
Function to get values of "show_all" and "restricted_calendar_list"
of current calendar from calendar_heading page.
It is used by body files of 3 views

Returns inArr with the following values:
	1st element contains "showall"
	2nd element contains "restrictedlist"
-----------------------------------------------------------------------------*/
function RZgetParamsOfCurrentCalendar(inArr, inCalId)
{
	var i,selObj,optObj
	inArr[0] = '';
	inArr[1] = '';

	while (true)
	{
		if (RZisReload()) break;	//if top frame reloading
		if (typeof topframe.mainFrame == 'undefined') break;
		if (typeof topframe.mainFrame.headerFrame == 'undefined') break;
		var headerFrame = topframe.mainFrame.headerFrame;

		if (typeof headerFrame.document.calendar_heading == 'undefined') break;
		if (typeof headerFrame.document.calendar_heading.calendarName == 'undefined') break;
		selObj = headerFrame.document.calendar_heading.calendarName;
		if (typeof selObj.length == 'undefined') break;

		for ( i = 0; i < selObj.length; i++ )
		{
			optObj = selObj.options[i];
			if (inCalId == optObj.value)
			{
				inArr[0] = topframe.RZ.calendar.credentials[inCalId].showall;
				inArr[1] = topframe.RZ.calendar.credentials[inCalId].restrictedlist;
				break;
			}
		}
		inArr[1] = "|" + inArr[1] + "|";
		break;
	}

	return inArr;
}

/*-----------------------------------------------------------------------------
Function which finds the calendar name the event belongs to based on the
calendar id
-----------------------------------------------------------------------------*/
function RZgetCalendarNameForEvent(id)
{
	return RZ.calendar.names[id];

/*	Old method
	var optionId;
	var RZcalendar_name = "";

	if(RZwinaccess(parent)
	&& RZwinaccess (parent.parent)
	&& RZwinaccess(parent.parent.mainFrame))
	{
		if(parent.parent.mainFrame.document.calendar_heading != null
		&& parent.parent.mainFrame.document.calendar_heading.calendarName != null
		&& typeof parent.parent.mainFrame.document.calendar_heading.calendarName == 'object')
		{
			var selObj = "";
			selObj = parent.parent.mainFrame.document.calendar_heading.calendarName;

			for ( var i = 0; i < selObj.length; i++ )
			{
				optionId = selObj.options[i].value;

				if ( optionId == id )
				{
					RZcalendar_name = removeStartHyphen(selObj.options[i].text);
					return RZcalendar_name;
				}

			}
		}

	}

	return RZcalendar_name;
*/
}

/*-----------------------------------------------------------------------------------
-----------------------------------------------------------------------------------*/
function getHtmlOfDayEvents(arr)
{
	var toReturn = "";
	for(var i = 0; i < arr.length; i ++)
		toReturn += arr[i][1];

	return toReturn ;
}

/*-----------------------------------------------------------------------------------
-----------------------------------------------------------------------------------*/
function sortOnTime(arr, loB, hiB)
{
	if(loB == hiB || loB > hiB)
		return;

	var min = new Array();
	min[0] = arr[loB][0];
	min[1] = arr[loB][1];
	if (arr.length > 1)
		min[2] = arr[loB][2];
	var minIdx = loB;

	var min_temp = min[0];
	for(var i = loB; i < hiB; i++)
	{
		if(min_temp > arr[i][0])
		{
			minIdx = i;
			min_temp = arr[i][0];
		}
	}
	if(minIdx != loB)
	{
		arr[loB][0] = arr[minIdx][0];
		arr[loB][1] = arr[minIdx][1];
		if (arr.length > 1)
			arr[loB][2] = arr[minIdx][2];
		arr[minIdx][0] = min[0];
		arr[minIdx][1] = min[1];
		if (arr.length > 1)
			arr[minIdx][2] = min[2];
	}
	loB++;
	sortOnTime(arr, loB, hiB);
}
/*-----------------------------------------------------------------------------------
If date is string and of the form mm-dd-yyyy, convert - to slash for firefox
Don't convert form of: Sun Feb 08 2009 00:00:00 GMT-0500 (Eastern Standard Time)
clicking on a day in month view passes the long string above
-----------------------------------------------------------------------------------*/
function formatDateSlash(date)
{
	if (typeof(date) == 'string' && date.indexOf('-') < 'mm-dd-yyyy'.length)
		date = new Date(date.toString().replace(/-/g,'/'));
	return date;
}
/*-----------------------------------------------------------------------------------
-----------------------------------------------------------------------------------*/
function formatDateTime(date)
{
	if (date.constructor != Date) date = new Date(date);

	return formatDate(date) + ' ' + formatTime(date);
}
/*-----------------------------------------------------------------------------------
-----------------------------------------------------------------------------------*/
function formatDate(date)
{
	if (date.constructor != Date) date = new Date(date);
	
	date = RZright('00' + (date.getMonth()+1),2) + '-'
		 + RZright('00' + date.getDate(),2) + '-'
		 + date.getFullYear();
	return date;
}
/*-----------------------------------------------------------------------------------
-----------------------------------------------------------------------------------*/
function formatTime(date)
{
	if (date.constructor != Date) date = new Date(date);

	var hours = RZright('00' + date.getHours(),2);
	var minutes = RZright('00' + date.getMinutes(),2);

	var time = hours + ':' + minutes + ' am'
	if (hours == '00')		//midnight
		time = minutes == '00' ? 'midnight' : '12:' + minutes + ' am';
	else if (hours == '12')	//noon
		time = minutes = '00' ? 'noon' : '12:' + minutes + ' pm';
	else if (hours > '12')
		time = RZright('00'+(hours-12),2) + ':' + minutes + ' pm';

	return time;
}
/*-----------------------------------------------------------------------------------
return true if using frames otherwise return false.
-----------------------------------------------------------------------------------*/
function isFrames()
{
	return RZ.calendar.isFrames
		   || parent.location.pathname.indexOf('/calendar_app/calendar_frames') != -1
		   || location.pathname.indexOf('/calendar_app/calendar_frames') != -1;
}
/*-----------------------------------------------------------------------------------
//example of using the html encode object

// set the type of encoding to numerical entities e.g & instead of &
Encoder.EncodeType = "numerical";

// or to set it to encode to html entities e.g & instead of &
Encoder.EncodeType = "entity";

// HTML encode text from an input element
// This will prevent double encoding.
var encoded = Encoder.htmlEncode(document.getElementById('input'));

// To encode but to allow double encoding which means any existing entities such as
// &amp; will be converted to &amp;amp;
var dblEncoded = Encoder.htmlEncode(document.getElementById('input'),true);

// Decode the now encoded text
var decoded = Encoder.htmlDecode(encoded);

// Check whether the text still contains HTML/Numerical entities
var containsEncoded = Encoder.hasEncoded(decoded);
-----------------------------------------------------------------------------------*/
/**
 * A Javascript object to encode and/or decode html characters using HTML or Numeric 
 * entities that handles double or partial encoding
 * Author: R Reid
 * source: http://www.strictly-software.com/htmlencode
 * Licences: GPL, The MIT License (MIT)
 * Copyright: (c) 2011 Robert Reid - Strictly-Software.com
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this 
 * software and associated documentation files (the "Software"), to deal in the Software
 * without restriction, including without limitation the rights to use, copy, modify,
 * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 
 * permit persons to whom the Software is furnished to do so, subject to the following
 * conditions:
 * The above copyright notice and this permission notice shall be included in all copies
 * or substantial portions of the Software.  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT
 * WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
 * SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 * 
 * Revision:
 *  2011-07-14, Jacques-Yves Bleau: 
 *       - fixed conversion error with capitalized accentuated characters
 *       + converted arr1 and arr2 to object property to remove redundancy
 *
 * Revision:
 *  2011-11-10, Ce-Yi Hio: 
 *       - fixed conversion error with a number of capitalized entity characters
 *
 * Revision:
 *  2011-11-10, Rob Reid: 
 *		 - changed array format
 */
Encoder = {

	// When encoding do we convert characters into html or numerical entities
	EncodeType : "entity",  // entity OR numerical

	isEmpty : function(val){
		if(val){
			return ((val===null) || val.length==0 || /^\s+$/.test(val));
		}else{
			return true;
		}
	},
	
	// arrays for conversion from HTML Entities to Numerical values
	arr1: ['&nbsp;','&iexcl;','&cent;','&pound;','&curren;','&yen;','&brvbar;','&sect;','&uml;','&copy;','&ordf;','&laquo;','&not;','&shy;','&reg;','&macr;','&deg;','&plusmn;','&sup2;','&sup3;','&acute;','&micro;','&para;','&middot;','&cedil;','&sup1;','&ordm;','&raquo;','&frac14;','&frac12;','&frac34;','&iquest;','&Agrave;','&Aacute;','&Acirc;','&Atilde;','&Auml;','&Aring;','&AElig;','&Ccedil;','&Egrave;','&Eacute;','&Ecirc;','&Euml;','&Igrave;','&Iacute;','&Icirc;','&Iuml;','&ETH;','&Ntilde;','&Ograve;','&Oacute;','&Ocirc;','&Otilde;','&Ouml;','&times;','&Oslash;','&Ugrave;','&Uacute;','&Ucirc;','&Uuml;','&Yacute;','&THORN;','&szlig;','&agrave;','&aacute;','&acirc;','&atilde;','&auml;','&aring;','&aelig;','&ccedil;','&egrave;','&eacute;','&ecirc;','&euml;','&igrave;','&iacute;','&icirc;','&iuml;','&eth;','&ntilde;','&ograve;','&oacute;','&ocirc;','&otilde;','&ouml;','&divide;','&oslash;','&ugrave;','&uacute;','&ucirc;','&uuml;','&yacute;','&thorn;','&yuml;','&quot;','&amp;','&lt;','&gt;','&OElig;','&oelig;','&Scaron;','&scaron;','&Yuml;','&circ;','&tilde;','&ensp;','&emsp;','&thinsp;','&zwnj;','&zwj;','&lrm;','&rlm;','&ndash;','&mdash;','&lsquo;','&rsquo;','&sbquo;','&ldquo;','&rdquo;','&bdquo;','&dagger;','&Dagger;','&permil;','&lsaquo;','&rsaquo;','&euro;','&fnof;','&Alpha;','&Beta;','&Gamma;','&Delta;','&Epsilon;','&Zeta;','&Eta;','&Theta;','&Iota;','&Kappa;','&Lambda;','&Mu;','&Nu;','&Xi;','&Omicron;','&Pi;','&Rho;','&Sigma;','&Tau;','&Upsilon;','&Phi;','&Chi;','&Psi;','&Omega;','&alpha;','&beta;','&gamma;','&delta;','&epsilon;','&zeta;','&eta;','&theta;','&iota;','&kappa;','&lambda;','&mu;','&nu;','&xi;','&omicron;','&pi;','&rho;','&sigmaf;','&sigma;','&tau;','&upsilon;','&phi;','&chi;','&psi;','&omega;','&thetasym;','&upsih;','&piv;','&bull;','&hellip;','&prime;','&Prime;','&oline;','&frasl;','&weierp;','&image;','&real;','&trade;','&alefsym;','&larr;','&uarr;','&rarr;','&darr;','&harr;','&crarr;','&lArr;','&uArr;','&rArr;','&dArr;','&hArr;','&forall;','&part;','&exist;','&empty;','&nabla;','&isin;','&notin;','&ni;','&prod;','&sum;','&minus;','&lowast;','&radic;','&prop;','&infin;','&ang;','&and;','&or;','&cap;','&cup;','&int;','&there4;','&sim;','&cong;','&asymp;','&ne;','&equiv;','&le;','&ge;','&sub;','&sup;','&nsub;','&sube;','&supe;','&oplus;','&otimes;','&perp;','&sdot;','&lceil;','&rceil;','&lfloor;','&rfloor;','&lang;','&rang;','&loz;','&spades;','&clubs;','&hearts;','&diams;'],
	arr2: ['&#160;','&#161;','&#162;','&#163;','&#164;','&#165;','&#166;','&#167;','&#168;','&#169;','&#170;','&#171;','&#172;','&#173;','&#174;','&#175;','&#176;','&#177;','&#178;','&#179;','&#180;','&#181;','&#182;','&#183;','&#184;','&#185;','&#186;','&#187;','&#188;','&#189;','&#190;','&#191;','&#192;','&#193;','&#194;','&#195;','&#196;','&#197;','&#198;','&#199;','&#200;','&#201;','&#202;','&#203;','&#204;','&#205;','&#206;','&#207;','&#208;','&#209;','&#210;','&#211;','&#212;','&#213;','&#214;','&#215;','&#216;','&#217;','&#218;','&#219;','&#220;','&#221;','&#222;','&#223;','&#224;','&#225;','&#226;','&#227;','&#228;','&#229;','&#230;','&#231;','&#232;','&#233;','&#234;','&#235;','&#236;','&#237;','&#238;','&#239;','&#240;','&#241;','&#242;','&#243;','&#244;','&#245;','&#246;','&#247;','&#248;','&#249;','&#250;','&#251;','&#252;','&#253;','&#254;','&#255;','&#34;','&#38;','&#60;','&#62;','&#338;','&#339;','&#352;','&#353;','&#376;','&#710;','&#732;','&#8194;','&#8195;','&#8201;','&#8204;','&#8205;','&#8206;','&#8207;','&#8211;','&#8212;','&#8216;','&#8217;','&#8218;','&#8220;','&#8221;','&#8222;','&#8224;','&#8225;','&#8240;','&#8249;','&#8250;','&#8364;','&#402;','&#913;','&#914;','&#915;','&#916;','&#917;','&#918;','&#919;','&#920;','&#921;','&#922;','&#923;','&#924;','&#925;','&#926;','&#927;','&#928;','&#929;','&#931;','&#932;','&#933;','&#934;','&#935;','&#936;','&#937;','&#945;','&#946;','&#947;','&#948;','&#949;','&#950;','&#951;','&#952;','&#953;','&#954;','&#955;','&#956;','&#957;','&#958;','&#959;','&#960;','&#961;','&#962;','&#963;','&#964;','&#965;','&#966;','&#967;','&#968;','&#969;','&#977;','&#978;','&#982;','&#8226;','&#8230;','&#8242;','&#8243;','&#8254;','&#8260;','&#8472;','&#8465;','&#8476;','&#8482;','&#8501;','&#8592;','&#8593;','&#8594;','&#8595;','&#8596;','&#8629;','&#8656;','&#8657;','&#8658;','&#8659;','&#8660;','&#8704;','&#8706;','&#8707;','&#8709;','&#8711;','&#8712;','&#8713;','&#8715;','&#8719;','&#8721;','&#8722;','&#8727;','&#8730;','&#8733;','&#8734;','&#8736;','&#8743;','&#8744;','&#8745;','&#8746;','&#8747;','&#8756;','&#8764;','&#8773;','&#8776;','&#8800;','&#8801;','&#8804;','&#8805;','&#8834;','&#8835;','&#8836;','&#8838;','&#8839;','&#8853;','&#8855;','&#8869;','&#8901;','&#8968;','&#8969;','&#8970;','&#8971;','&#9001;','&#9002;','&#9674;','&#9824;','&#9827;','&#9829;','&#9830;'],
		
	// Convert HTML entities into numerical entities
	HTML2Numerical : function(s){
		return this.swapArrayVals(s,this.arr1,this.arr2);
	},	

	// Convert Numerical entities into HTML entities
	NumericalToHTML : function(s){
		return this.swapArrayVals(s,this.arr2,this.arr1);
	},


	// Numerically encodes all unicode characters
	numEncode : function(s){
		
		if(this.isEmpty(s)) return "";

		var e = "";
		for (var i = 0; i < s.length; i++)
		{
			var c = s.charAt(i);
			if (c < " " || c > "~")
			{
				c = "&#" + c.charCodeAt() + ";";
			}
			e += c;
		}
		return e;
	},
	
	// HTML Decode numerical and HTML entities back to original values
	htmlDecode : function(s){

		var c,m,d = s;
		
		if(this.isEmpty(d)) return "";

		// convert HTML entites back to numerical entites first
		d = this.HTML2Numerical(d);
		
		// look for numerical entities &#34;
		arr=d.match(/&#[0-9]{1,5};/g);
		
		// if no matches found in string then skip
		if(arr!=null){
			for(var x=0;x<arr.length;x++){
				m = arr[x];
				c = m.substring(2,m.length-1); //get numeric part which is refernce to unicode character
				// if its a valid number we can decode
				if(c >= -32768 && c <= 65535){
					// decode every single match within string
					d = d.replace(m, String.fromCharCode(c));
				}else{
					d = d.replace(m, ""); //invalid so replace with nada
				}
			}			
		}

		return d;
	},		

	// encode an input string into either numerical or HTML entities
	htmlEncode : function(s,dbl){
			
		if(this.isEmpty(s)) return "";

		// do we allow double encoding? E.g will &amp; be turned into &amp;amp;
		dbl = dbl || false; //default to prevent double encoding
		
		// if allowing double encoding we do ampersands first
		if(dbl){
			if(this.EncodeType=="numerical"){
				s = s.replace(/&/g, "&#38;");
			}else{
				s = s.replace(/&/g, "&amp;");
			}
		}

		// convert the xss chars to numerical entities ' " < >
		s = this.XSSEncode(s,false);
		
		if(this.EncodeType=="numerical" || !dbl){
			// Now call function that will convert any HTML entities to numerical codes
			s = this.HTML2Numerical(s);
		}

		// Now encode all chars above 127 e.g unicode
		s = this.numEncode(s);

		// now we know anything that needs to be encoded has been converted to numerical entities we
		// can encode any ampersands & that are not part of encoded entities
		// to handle the fact that I need to do a negative check and handle multiple ampersands &&&
		// I am going to use a placeholder

		// if we don't want double encoded entities we ignore the & in existing entities
		if(!dbl){
			s = s.replace(/&#/g,"##AMPHASH##");
		
			if(this.EncodeType=="numerical"){
				s = s.replace(/&/g, "&#38;");
			}else{
				s = s.replace(/&/g, "&amp;");
			}

			s = s.replace(/##AMPHASH##/g,"&#");
		}
		
		// replace any malformed entities
		s = s.replace(/&#\d*([^\d;]|$)/g, "$1");

		if(!dbl){
			// safety check to correct any double encoded &amp;
			s = this.correctEncoding(s);
		}

		// now do we need to convert our numerical encoded string into entities
		if(this.EncodeType=="entity"){
			s = this.NumericalToHTML(s);
		}

		return s;					
	},

	// Encodes the basic 4 characters used to malform HTML in XSS hacks
	XSSEncode : function(s,en){
		if(!this.isEmpty(s)){
			en = en || true;
			// do we convert to numerical or html entity?
			if(en){
				s = s.replace(/\'/g,"&#39;"); //no HTML equivalent as &apos is not cross browser supported
				s = s.replace(/\"/g,"&quot;");
				s = s.replace(/</g,"&lt;");
				s = s.replace(/>/g,"&gt;");
			}else{
				s = s.replace(/\'/g,"&#39;"); //no HTML equivalent as &apos is not cross browser supported
				s = s.replace(/\"/g,"&#34;");
				s = s.replace(/</g,"&#60;");
				s = s.replace(/>/g,"&#62;");
			}
			return s;
		}else{
			return "";
		}
	},

	// returns true if a string contains html or numerical encoded entities
	hasEncoded : function(s){
		if(/&#[0-9]{1,5};/g.test(s)){
			return true;
		}else if(/&[A-Z]{2,6};/gi.test(s)){
			return true;
		}else{
			return false;
		}
	},

	// will remove any unicode characters
	stripUnicode : function(s){
		return s.replace(/[^\x20-\x7E]/g,"");
		
	},

	// corrects any double encoded &amp; entities e.g &amp;amp;
	correctEncoding : function(s){
		return s.replace(/(&amp;)(amp;)+/,"$1");
	},


	// Function to loop through an array swaping each item with the value from another array e.g swap HTML entities with Numericals
	swapArrayVals : function(s,arr1,arr2){
		if(this.isEmpty(s)) return "";
		var re;
		if(arr1 && arr2){
			//ShowDebug("in swapArrayVals arr1.length = " + arr1.length + " arr2.length = " + arr2.length)
			// array lengths must match
			if(arr1.length == arr2.length){
				for(var x=0,i=arr1.length;x<i;x++){
					re = new RegExp(arr1[x], 'g');
					s = s.replace(re,arr2[x]); //swap arr1 item with matching item from arr2	
				}
			}
		}
		return s;
	},

	inArray : function( item, arr ) {
		for ( var i = 0, x = arr.length; i < x; i++ ){
			if ( arr[i] === item ){
				return i;
			}
		}
		return -1;
	}

}

