//********************************
//LIST SOLD OUT DATES HERE
//********************************
var SoldOutArray = new Array();

SoldOutArray[0] = new Date("January 1, 1971 20:00");
SoldOutArray[1] = new Date("April 5, 2008 20:00");
SoldOutArray[2] = new Date("April 6, 2008 18:00");
SoldOutArray[3] = new Date("April 12, 2008 20:00");
SoldOutArray[4] = new Date("April 13, 2008 18:00");
SoldOutArray[5] = new Date("April 18, 2008 20:00");
SoldOutArray[6] = new Date("April 19, 2008 20:00");
SoldOutArray[7] = new Date("April 20, 2008 18:00");
SoldOutArray[8] = new Date("April 25, 2008 20:00");
SoldOutArray[9] = new Date("April 26, 2008 20:00");
SoldOutArray[10] = new Date("April 27, 2008 18:00");

//********************************
//CONSTANT DECLARATIONS
//********************************
var MAX_DD_ENTRIES = 24;  // <--SET THE MAXIMUM NUMBER OF DROPDOWN ENTRIES HERE
var MAX_CAL_WEEKS = 52;
var SOS = "Sold Out"	//Sold out string
var BLDate = new Date(2007, 06, 1, 00, 00, 00); //Baseline date (yyyy, mm, dd, hh, mm, ss)
var RegularTicketPrice = "Tickets $12";

//********************************
//BEGIN DATABASE OF PLAYS (include scheduled-but-non-reservalbe events & calendar annotations)
//********************************
/*SPECIFYING SHOW DATES:
There are two ways to list dates: 
1. List ea. day individually in the PDaTi array: PDaTi= new Array(new Date("July 20, 2007 20:00"), new Date("July 21, 2007 20:00"), new Date("July 27, 2007 20:00"), new Date("July 28, 2007 20:00"),new Date("August 3, 2007 20:00"), new Date("August 4, 2007 20:00"), new Date("August 5, 2007 18:00"));
2. If all performances are at times (F8, Sa8, Su6): PDaTi[0] = DaTi of Opening night; [1] = "x"; [2] = total number of shows.
3. If events are sequential days all at the same time: PDaTi[0] = DaTi of Opening night; [1] = "xx"; [2] = total number of shows.
*/

//2=ddElig, 1=timed event w/o reservations (e.g., staged reading); 0=plain annotation (e.g., "Mother's day")

//Prototyipical entry (Cut & past for additional entries:
/*
p++;
PlayArray[p] = new PlayObj;
with (PlayArray[p]) {
PTitle = "";
ddElig = 2;  //2=ddElig, 1=timed event w/o reservations (e.g., staged reading); 0=plain annotation (e.g., "Mother's day")
PBorderColor = "#000000";
PBorderWidth = "1px";
PTextColor = "#ffffff";
PBold = "bold";
PBackgroundColor = "#0000ff";
PDaTi= new Array(new Date("May 11, 2007 20:00"));
PDaTiString = null;
PSpecNote = "*Opening night reception after"
PResOpenInt=BLDate.valueOf();  //the ms value of the date that this show should start to appear in Reservationsdd
PTicketPrice = null;  //should only be used if not standard price.
}
*/

//These are the arrays that make up the databases in external scripts and functions defined here
var PlayArray = new Array();
var EventArray = new Array();
var p = -1;
var e = -1;
var iPlay = null; //play instance
var iDaTi = null; //instance of an event date & time
var lno;  //list no (drop-down number; 0 is used for "Select performance..."
var MoArray = new Array("January ", "February ", "March ", "April ", "May ", "June ", "July ", "August ", "September ", "October ", "November ", "December ")
var DayArray = new Array("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday")
var TodayDate = new Date();
var TodayInt = TodayDate.getTime();

/*
p++;
PlayArray[p] = new PlayObj;
with (PlayArray[p]) {
PTitle = "Prototypical Entry";
ddElig = 2;
PBorderColor = "#FF00FF";
PBorderWidth = "3px";
PTextColor = "#00FF00";
PBold = "bold";
PBackgroundColor = "#00FFFF";
PDaTi= new Array(new Date("July 16, 2007 23:59"), new Date("July 17, 2007 23:59"), new Date("July 18, 2007 23:59"));
PDaTi= new Array(new Date("July 16, 2007 23:59"), "x", 3);
PSpecNote= "*Pay-as-you-can";
PResOpenInt=BLDate.valueOf();  //the ms value of the date that this show should start to appear in Reservationsdd
PTicketPrice = null;  //should only be used if not standard price.
}
*/


/*
p++;
PlayArray[p] = new PlayObj;
with (PlayArray[p]) {
PTitle = "Parted Waters";
ddElig = 1;  //2=ddElig, 1=timed event w/o reservations (e.g., staged reading); 0=plain annotation (e.g., "Mother's day")
PBorderColor = "#000000";
PBorderWidth = "2px";
PTextColor = "#000000";
PBold = "bold";
PDaTi= new Array(new Date("May 25, 2008 13:00"));
PDaTiString = "1:00 PM";
PSpecNote= "(Staged Reading)";
PTicketPrice = "FREE";  //should only be used if not standard price.
}
*/

p++;
PlayArray[p] = new PlayObj;
with (PlayArray[p]) {
PTitle = "I Hate Hamlet";
ddElig = 2;  //2=ddElig, 1=timed event w/o reservations (e.g., staged reading); 0=plain annotation (e.g., "Mother's day")
PBorderColor = "#c40062";
PBorderWidth = "4px";
PTextColor = "#ffffff";
PBold = "bold";
PBackgroundColor = "#ff6820";
PDaTi= new Array(new Date("June 13, 2008 20:00"));
PDaTiString = null;
PSpecNote = "*Opening night reception after";
PResOpenInt=BLDate.valueOf();  //the ms value of the date that this show should start to appear in Reservationsdd
PTicketPrice = null;  //should only be used if not standard price.
}

p++;
PlayArray[p] = new PlayObj;
with (PlayArray[p]) {
PTitle = "I Hate Hamlet";
ddElig = 2;  //2=ddElig, 1=timed event w/o reservations (e.g., staged reading); 0=plain annotation (e.g., "Mother's day")
PBorderColor = "#c40062";
PBorderWidth = "4px";
PTextColor = "#ffffff";
PBold = "bold";
PBackgroundColor = "#ff6820";
PDaTi= new Array(new Date("June 14, 2008 20:00"), "x", 5);
PDaTiString = null;
PResOpenInt=BLDate.valueOf();  //the ms value of the date that this show should start to appear in Reservationsdd
PTicketPrice = null;  //should only be used if not standard price.
}

p++;
PlayArray[p] = new PlayObj;
with (PlayArray[p]) {
PTitle = "I Hate Hamlet";
ddElig = 2;  //2=ddElig, 1=timed event w/o reservations (e.g., staged reading); 0=plain annotation (e.g., "Mother's day")
PBorderColor = "#c40062";
PBorderWidth = "4px";
PTextColor = "#ffffff";
PBold = "bold";
PBackgroundColor = "#ff6820";
PDaTi= new Array(new Date("July 5, 2008 20:00"), "x", 2);
PDaTiString = null;
PResOpenInt=BLDate.valueOf();  //the ms value of the date that this show should start to appear in Reservationsdd
PTicketPrice = "Tickets $6";  //should only be used if not standard price.
}

p++;
PlayArray[p] = new PlayObj;
with (PlayArray[p]) {
PTitle = "I Hate Hamlet";
ddElig = 2;  //2=ddElig, 1=timed event w/o reservations (e.g., staged reading); 0=plain annotation (e.g., "Mother's day")
PBorderColor = "#c40062";
PBorderWidth = "4px";
PTextColor = "#ffffff";
PBold = "bold";
PBackgroundColor = "#ff6820";
PDaTi= new Array(new Date("July 11, 2008 20:00"), new Date("July 19, 2008 20:00"), new Date("July 25, 2008 20:00"), new Date("July 27, 2008 18:00"));
PDaTiString = null;
PResOpenInt=BLDate.valueOf();  //the ms value of the date that this show should start to appear in Reservationsdd
PTicketPrice = null;  //should only be used if not standard price.
}

p++;
PlayArray[p] = new PlayObj;
with (PlayArray[p]) {
PTitle = "Goodnight Desdemona (Good Morning Juliet)";
ddElig = 2;  //2=ddElig, 1=timed event w/o reservations (e.g., staged reading); 0=plain annotation (e.g., "Mother's day")
PBorderColor = "#ff6820";
PBorderWidth = "4px";
PTextColor = "#ffffff";
PBold = "bold";
PBackgroundColor = "#c40062";
PDaTi= new Array(new Date("July 2, 2008 20:00"));
PSpecNote = "*Preview";
PDaTiString = null;
xxr = new Date("July 6, 2008 20:00");
PResOpenInt = xxr.valueOf();  //the ms value of the date that this show should start to appear in Reservationsdd
PTicketPrice = "$3";  //should only be used if not standard price.
}

p++;
PlayArray[p] = new PlayObj;
with (PlayArray[p]) {
PTitle = "Goodnight Desdemona (Good Morning Juliet)";
ddElig = 2;  //2=ddElig, 1=timed event w/o reservations (e.g., staged reading); 0=plain annotation (e.g., "Mother's day")
PBorderColor = "#ff6820";
PBorderWidth = "4px";
PTextColor = "#ffffff";
PBold = "bold";
PBackgroundColor = "#c40062";
PDaTi= new Array(new Date("August 1, 2008 20:00"), "x", 3);
PDaTiString = null;
PResOpenInt=BLDate.valueOf();  //the ms value of the date that this show should start to appear in Reservationsdd
PTicketPrice = null;  //should only be used if not standard price.
}

p++;
PlayArray[p] = new PlayObj;
with (PlayArray[p]) {
PTitle = "Goodnight Desdemona (Good Morning Juliet)";
ddElig = 2;  //2=ddElig, 1=timed event w/o reservations (e.g., staged reading); 0=plain annotation (e.g., "Mother's day")
PBorderColor = "#ff6820";
PBorderWidth = "4px";
PTextColor = "#ffffff";
PBold = "bold";
PBackgroundColor = "#c40062";
PDaTi= new Array(new Date("July 12, 2008 20:00"), new Date("July 13, 2008 18:00"), 
new Date("July 18, 2008 20:00"), new Date("July 20, 2008 18:00"), new Date("July 26, 2008 20:00"));
PDaTiString = null;
PResOpenInt=BLDate.valueOf();  //the ms value of the date that this show should start to appear in Reservationsdd
PTicketPrice = null;  //should only be used if not standard price.
}

p++;
PlayArray[p] = new PlayObj;
with (PlayArray[p]) {
PTitle = "Goodnight Desdemona (Good Morning Juliet)";
ddElig = 2;  //2=ddElig, 1=timed event w/o reservations (e.g., staged reading); 0=plain annotation (e.g., "Mother's day")
PBorderColor = "#ff6820";
PBorderWidth = "4px";
PTextColor = "#ffffff";
PBold = "bold";
PBackgroundColor = "#c40062";
PDaTi= new Array(new Date("July 3, 2008 20:00"), new Date("July 4, 2008 20:00"));
PDaTiString = null;
PResOpenInt=BLDate.valueOf();  //the ms value of the date that this show should start to appear in Reservationsdd
PTicketPrice = "Tickets $6";  //should only be used if not standard price.
}


p++;
PlayArray[p] = new PlayObj;
with (PlayArray[p]) {
PTitle = "The Complete History of America (Abridged)";
ddElig = 2;  //2=ddElig, 1=timed event w/o reservations (e.g., staged reading); 0=plain annotation (e.g., "Mother's day")
PBorderColor = "#f6df7e";
PBorderWidth = "3px";
PTextColor = "#f6df7e";
PBold = "bold";
PBackgroundColor = "#663300";
PDaTi= new Array(new Date("September 5, 2008 20:00"), "x", 12);
PDaTiString = null;
PResOpenInt=BLDate.valueOf();  //the ms value of the date that this show should start to appear in Reservationsdd
PTicketPrice = null;  //should only be used if not standard price.
}

p++;
PlayArray[p] = new PlayObj;
with (PlayArray[p]) {
PTitle = "Electoral Dysfunctions";
ddElig = 2;  //2=ddElig, 1=timed event w/o reservations (e.g., staged reading); 0=plain annotation (e.g., "Mother's day")
PBorderColor = "#ff0000";
PBorderWidth = "4px";
PTextColor = "#ffffff";
PBold = "bold";
PBackgroundColor = "#0000ff";
PDaTi= new Array(new Date("October 10, 2008 20:00"), "x", 12);
PDaTiString = null;
PResOpenInt=BLDate.valueOf();  //the ms value of the date that this show should start to appear in Reservationsdd
PTicketPrice = null;  //should only be used if not standard price.
}



p++;
PlayArray[p] = new PlayObj;
with (PlayArray[p]) {
PTitle = "Mothers\' Day";
ddElig = 0;
PDaTi= new Array(new Date("May 11, 2008"));
}

p++;
PlayArray[p] = new PlayObj;
with (PlayArray[p]) {
PTitle = "Fathers\' Day";
ddElig = 0;
PDaTi= new Array(new Date("June 15, 2008"));
}

p++;
PlayArray[p] = new PlayObj;
with (PlayArray[p]) {
PTitle = "Independence Day";
ddElig = 0;
PDaTi= new Array(new Date("July 4, 2008"));
}

p++;
PlayArray[p] = new PlayObj;
with (PlayArray[p]) {
PTitle = "Labor Day";
ddElig = 0;
PDaTi= new Array(new Date("September 1, 2008"));
}

p++;
PlayArray[p] = new PlayObj;
with (PlayArray[p]) {
PTitle = "Halloween";
ddElig = 0;
PDaTi= new Array(new Date("October 31, 2008"));
}

p++;
PlayArray[p] = new PlayObj;
with (PlayArray[p]) {
PTitle = "Thanksgiving";
ddElig = 0;
PDaTi= new Array(new Date("November 27, 2008"));
}

p++;
PlayArray[p] = new PlayObj;
with (PlayArray[p]) {
PTitle = "Hanukkah";
ddElig = 0;
PDaTi= new Array(new Date("December 22, 2008"));
}

p++;
PlayArray[p] = new PlayObj;
with (PlayArray[p]) {
PTitle = "Christmas";
ddElig = 0;
PDaTi= new Array(new Date("December 25, 2008"));
}

p++;
PlayArray[p] = new PlayObj;
with (PlayArray[p]) {
PTitle = "New Year\'s Day";
ddElig = 0;
PDaTi= new Array(new Date("January 1, 2009"));
}

p++;
PlayArray[p] = new PlayObj;
with (PlayArray[p]) {
PTitle = "Martin Luther King Day";
ddElig = 0;
PDaTi= new Array(new Date("January 19, 2009"));
}

p++;
PlayArray[p] = new PlayObj;
with (PlayArray[p]) {
PTitle = "Valentines\' Day";
ddElig = 0;
PDaTi= new Array(new Date("February 14, 2009"));
}

p++;
PlayArray[p] = new PlayObj;
with (PlayArray[p]) {
PTitle = "Election Day";
ddElig = 0;
PDaTi= new Array(new Date("November 4, 2008"));
}

//END OF DATABASE OF PLAYS

//*******************************
//THE DATABASE IS CONVERTED INTO AN ARRAY OF DISCRETE EVENTS; THIS ARRAY IS ACCESSED BY PERFORMANCECALENDAR.HTM
//*******************************
//Scan plays and dates within plays
for (p=0; p<PlayArray.length; p++) {  //I'm re-using p which is no longer needed to build PlayArray
iPlay = PlayArray[p];

//Make one event per date
if ((iPlay.PDaTi.length) > 2 && (iPlay.PDaTi[1] == "x")) {
ExpandCodedDates(iPlay);
} else if ((iPlay.PDaTi.length) > 2 && (iPlay.PDaTi[1] == "xx")) {
ExpandContiguousRun(iPlay);
} else {
ReadDates(iPlay);
}}  //end if  //end for p

//sort the event array
EventArray.sort(SortEventArray);

//********************************
//OBJECT DEFINITIONS
//********************************
//Define Play Object
function PlayObj() {
this.PTitle=null;
this.ddElig=2; //2=ddElig, 1=timed event w/o reservations (e.g., staged reading); 0=plain annotation (e.g., "Mother's day")
this.PBorderStyle="solid";
this.PBorderColor = "#000000";
this.PBorderWidth = "1px";
this.PTextColor = "#000000";
this.PBold = "bold";  //"bold" or "normal"
this.PBackgroundColor = null;
this.PDaTi = null;
this.PDaTiString = null;
this.PSpecNote = null;
this.PResOpenInt = BLDate.valueOf();
this.PTicketPrice = null;
}

//Define Event Object
function EventObj(poo, datio) {
this.po=poo;  //Object holding the original Play Object 
this.dati=new Date(datio.getTime());
this.AmerTimeString=poo.PDaTiString ? poo.PDaTiString : GetAmerTime(datio);
this.soTF = SoldOutTF(datio);
this.lds = BuildLongDateString(datio);
}

//************************************
//FUNCTIONS ONLY USED BY THIS PAGE
//************************************
//Read un-encoded dates from Play Object and load them into the Event Array
function ReadDates(ProdnObj) {
for (var t = 0; t < ProdnObj.PDaTi.length; t++) {
iDaTi = iPlay.PDaTi[t];
//Add a new Event Object to the Event Array
if (iDaTi.getTime() >= TodayInt) {
e++;
EventArray[e] = new EventObj(ProdnObj, iDaTi);
}}}  //end for t  //end if //end fcn

//Decode encoded dates for regular shows (Fri, Sat, Sun)
function ExpandCodedDates(ProdnObj) {
//Get the opening night date and count x performances fwd
var ONDate = new Date(ProdnObj.PDaTi[0].getTime()); //Opening Night Date
for (var i = 0; i < ProdnObj.PDaTi[2]; i++) {
//reset clock to midnight (and some change)
ONDate.setHours(0);

//Set Fridays to a normal 8:00 performance
if (ONDate.getDay() == 5) {
ONDate.setHours(20);
ONDate.setMinutes(0);

//Set Saturdays to a normal 8:00 performance
} else if (ONDate.getDay() == 6) {
ONDate.setHours(20);
ONDate.setMinutes(0);

//Set Sundays to a normal 6:00 performance
} else if (ONDate.getDay() == 0) {
ONDate.setHours(18);
ONDate.setMinutes(0);

//Advance other days to the upcoming Friday (+ 1 hr for possibkle DST)
} else {
ONDate.setHours(0);
ONDate.setTime(ONDate.getTime() + ((5-ONDate.getDay())*86400000)+3600000);
ONDate.setHours(20);
ONDate.setMinutes(0);
}  //end if

//Add unexpired events to the Event Array
if (ONDate.getTime() >= TodayInt) {
e++;
EventArray[e] = new EventObj(ProdnObj, ONDate);
}

//Advance date by 1 day  (25 hrs to allow for possible DST) for the next iteration of for i loop
ONDate.setTime(ONDate.getTime() + 90000000);
}}  //end for i  //end fcn


//Decode encoded dates for a string of identical events
function ExpandContiguousRun(ProdnObj) {
//Get the initial date 
var ONDate = new Date(ProdnObj.PDaTi[0].getTime()); //Opening Night Date

//Count x days forward
for (var i = 0; i < ProdnObj.PDaTi[2]; i++) {

//set hours and minutes to the same time as the initial date
ONDate.setHours(ProdnObj.PDaTi[0].getHours());
ONDate.setMinutes(ProdnObj.PDaTi[0].getMinutes());
ONDate.setSeconds(0);

//Add unexpired events to the Event Array
if (ONDate.getTime() >= TodayInt) {
e++;
EventArray[e] = new EventObj(ProdnObj, ONDate);
}

//Advance date by 1 day  (25 hrs to allow for possible DST) for the next iteration of for i loop
ONDate.setTime(ONDate.getTime() + 90000000);
}}  //end for i  //end fcn

//Sorting function for Event Array
function SortEventArray(sea1, sea2) {
var dsea1 = sea1.dati.getTime();
var dsea2 = sea2.dati.getTime();
if (dsea1 != dsea2) {return (dsea1-dsea2);}
else {return (sea1.po.ddElig - sea2.po.ddElig);}
} 

//determine if a date is in the SoldOutArray
function SoldOutTF(dt2) {
for (var i2 = 0; i2 < SoldOutArray.length; i2++) {
if (new Date(SoldOutArray[i2]).valueOf() == dt2.valueOf()) {
return true;
break;}}	//end if //end fort
return false;
}


//***********************************************************
//COMMON FUNCTIONS (Or functions of possible broad use)
//***********************************************************
//Convert Julian date to a date object
function JulianToDate(j) {
var jms = j*dms + 3600000;  //total millisec associated with the Julian Date + 1 hr in case clocks moved fwd
var Dia = new Date(BLms + jms);
Dia.setHours(0,0,0,0);
return Dia;
}

//Convert a Date object to a Julian date integer
function DateToJulian(d) {
d.setHours(0,0,0,0);
var Diffms = d.getTime()-BLms+ 3600000; //add 1 hour in case clocks moved fwd
var jd = Math.floor(Diffms/dms)
return jd;
}

//Determine the Julian date of the Sunday starting the current week
function GetCalStartJulian() {
var td = new Date();  //today's date
var offset = td.getDay();  //DOW code e.g., Sunday = 0
var rv = DateToJulian(td);
rv -= offset;
return rv;
}

//Format a date as: DOW, Month Day, Year @ American Time
function BuildLongDateString(d) {
var lds1 = DayArray[d.getDay()];
var lds2 = MoArray[d.getMonth()];
var lds3 = d.getDate();
var lds4 = d.getYear(); 
if (lds4  < 1900) {lds4 += 1900;}
var lds = lds1.toUpperCase() + ", " + lds2 + " " + lds3 + ", " + lds4;
return lds;
}  //end fcn

//Format a date as: DOW, Month Day, Year @ American Time
function BuildShortDateString(d) {
var lds2 = MoArray[d.getMonth()];
var lds3 = d.getDate();
var lds4 = d.getYear(); 
if (lds4  < 1900) {lds4 += 1900;}
var lds = lds2 + " " + lds3 + ", " + lds4;
return lds;
}  //end fcn

//Return a string formattted to show 12-hour time without seconds
function GetAmerTime(d) {
var rvString;
var hrs = d.getHours();
var mins = d.getMinutes();
if (mins < 10) {mins = "0" + mins;}
if (hrs >= 13) {
	rvString = (hrs-12) + ":" + mins + " PM";}
else if (hrs == 12) {
	rvString = "12:" + mins + " noon";}
else {rvString = hrs + ":" + mins + " AM"}
return rvString;
}

function TodayAfter3TF (pd) {  //pd = performance date
var td = new Date();  //today object set to current date
var tdh = td.getHours();
if (tdh < 15) {
	return false; 
} else {
	return SameDayTF(pd, td); 
}}  //end if  //end fcn

function SameDayTF(day1, day2) {
if (day1.getDate() != day2.getDate()) {
	return false; 
} else if (day1.getMonth() != day2.getMonth()) {
	return false;
} else if (day1.getYear() != day2.getYear()) {
	return false;
} else {
	return true;
}}  //end if //end function


function SecondDateTomorrowTF(d1, d2) {
//IF THE same year
if (d1.getYear() == d2.getYear()) {
	//If the same month, check for sequential days
	if (d1.getMonth() == d2.getMonth()) {if (d2.getDate() == (d1.getDate() + 1)) return true; else return false;}
	//If not the same month, check for month breaks
	else if (d2.getMonth() == (d1.getMonth() + 1)) {return MonthBreakTF(d1, d2);}
	//If not a month break and not the same month, then can't be sequential days
	else return false;}
//IF SEQUENTIAL years: Can only be next day if 12/31 to 1/1
else if (d2.getFullYear() == (d1.getFullYear() + 1)) {
	if ((d2.getMonth() == 0) && (d1.getMonth() == 11)) {
		if ((d2.getDate() == 1) && (d1.getDate() == 31)) return true; else return false;}
	else return false;} 
//OTHERWISE can't be next day 
else return false;
}  //end function

function MonthBreakTF(d1, d2) {
//Determines if d1 is the last day of one month and d2 the first day of the second month
if (d2.getDate() != 1) return false;
if (d1.getMonth() == 0) {if (d1.getDate() == 31) return true; else return false;}
else if (d1.getMonth() == 1) {if (d1.getDate() == FebLastDay(d1)) return true; else return false;}
else if (d1.getMonth() == 2) {if (d1.getDate() == 31) return true; else return false;}
else if (d1.getMonth() == 3) {if (d1.getDate() == 30) return true; else return false;}
else if (d1.getMonth() == 4) {if (d1.getDate() == 31) return true; else return false;}
else if (d1.getMonth() == 5) {if (d1.getDate() == 30) return true; else return false;}
else if (d1.getMonth() == 6) {if (d1.getDate() == 31) return true; else return false;}
else if (d1.getMonth() == 7) {if (d1.getDate() == 31) return true; else return false;}
else if (d1.getMonth() == 8) {if (d1.getDate() == 30) return true; else return false;}
else if (d1.getMonth() == 9) {if (d1.getDate() == 31) return true; else return false;}
else if (d1.getMonth() == 10) {if (d1.getDate() == 30) return true; else return false;}
else return false;
}  //end fcn

function FebLastDay(d1){
//Creates a day that is 1 second from the end of 2/28
//Then advances the time by 2 hrs, and checks if the day is 2/29 or 3/1
var nd = new Date(d1.getFullYear(), 1, 28, 23, 59, 59);
var ndt = nd.getTime();
ndt += 7200000  //add 2 hrs to flip over to next day
nd = new Date(ndt);
if (nd.getDate() == 29) return 29; else return 28;
} //end fcn

function GetColorDecimal(CoHex, rgb) {
var hexchar = "0123456789ABCDEF";
var cht = CoHex.toUpperCase();
var co = 0;
if (rgb == "r") {co = 0;}
else if (rgb == "g") {co = 2;}
else if (rgb == "b") {co = 4;}
else co = 0;
//get rid of # in case it is part of CoHex string
var re = /#/g;
cht = cht.replace(re, "");
//get the first two characters of the remaining string
var r1 = cht.substr(co + 0, 1);
var r2 = cht.substr(co + 1, 1);
//convert each character to a decimal
var dec1 = hexchar.indexOf(r1);
var dec2 = hexchar.indexOf(r2);
return dec1*16 + dec2;
}  //end fcn

function ToHexStr(dec) {
hexchar = "0123456789ABCDEF";
if (dec > 255) return "FF";
var i = dec % 16;
var j = (dec - i) / 16;
var rv = hexchar.charAt(j) + hexchar.charAt(i);
return rv;
}  //end fcn 

function FadeColor(cht, tgt, frac) {
var mv = 0;
//get color hex triplets for original color
var reddec = GetColorDecimal(cht, "r");
var grndec = GetColorDecimal(cht, "g");
var bludec = GetColorDecimal(cht, "b");
//get color hex triplets for target color
var redtgt = GetColorDecimal(tgt, "r");
var grntgt = GetColorDecimal(tgt, "g");
var blutgt = GetColorDecimal(tgt, "b");
//move rgb components towards target by frac
var reddelta = (redtgt-reddec) * frac;
var grndelta = (grntgt-grndec) * frac;
var bludelta = (blutgt-bludec) * frac;
reddec += reddelta;
grndec += grndelta;
bludec += bludelta;
//build hex triplet string for return value
var redstr = ToHexStr(reddec);
var grnstr = ToHexStr(grndec);
var blustr = ToHexStr(bludec);
var rv = "#" + redstr + grnstr + blustr;
return rv;
}  //end fcn

function GetTopPendingEvent(mc) {  //mc=match criteria: 0=annotation, 1=scheduled event, 2=reservable performance, 3=any
var tp = 0;
var sot = new Date(TodayDate.valueOf());  //start of today
sot.setHours(0);
sot.setMinutes(0);
for (tp=0; tp<EventArray.length; tp++) {
dObj = EventArray[tp].dati;
if (dObj.valueOf() >= sot.valueOf()) {
var ddepo = EventArray[tp].po;
if ((EventArray[tp].po.ddElig == mc) || (mc == 3)) {
return tp;
break;
}}}//end if x 2 //end for
return tp;}  //default return value //end fcn

function FirstEventInstance(itm) {  //itm=item no. to match
var xObj = EventArray[itm];
var EvNa = xObj.po.PTitle;
var Evdd = xObj.po.ddElig;
for (i=0; i<EventArray.length; i++) {
xObj = EventArray[i];
if ((xObj.po.PTitle == EvNa) || (xObj.po.ddElig == Evdd)){
return i;
break;} //end if
} //end for
return itm;  //default return value
} //end fcn

function LastEventInstance(itm) {  //itm=item no. to match
var xObj = EventArray[itm];
var EvNa = xObj.po.PTitle;
var Evdd = xObj.po.ddElig;
for (i=(EventArray.length-1); i>=0; i--) {
xObj = EventArray[i];
if ((xObj.po.PTitle == EvNa) && (xObj.po.ddElig == Evdd)){
return i;
break;} //end if
} //end for
return itm;  //default return value
} //end fcn

