calDateFormat    = "MM/DD/yyyy";


// CALENDAR COLORS
topBackground = tableBGColor  =  headingCellColor = "#25408f";
bottomBackground = "ffffff";         // BG COLOR OF THE BOTTOM FRAME
cellColor = focusColor = hoverColor = "#FEF6B9"; 
wkendcellColor   = "e5e5e5";
headingTextColor = "ffffff";         // TEXT COLOR OF THE WEEKDAY ABBREVIATIONS
dateColor        = "0000ff";          // TEXT COLOR OF THE LISTED DATES (1-28+)
fontStyle        = "10pt verdana, arial, helvetica";           // TEXT STYLE FOR DATES
hoverfontStyle        = "bold 10pt verdana, arial, helvetica";           // TEXT STYLE FOR DATES
headingFontStyle = "bold 11pt verdana, arial, helvetica";      // TEXT STYLE FOR WEEKDAY ABBREVIATIONS

// FORMATTING PREFERENCES
bottomBorder  = false;        // TRUE/FALSE (WHETHER TO DISPLAY BOTTOM CALENDAR BORDER)
tableBorder   = 0;            // SIZE OF CALENDAR TABLE BORDER (BOTTOM FRAME) 0=none

// DETERMINE BROWSER BRAND
var isNav = false;
var isIE  = false;

// ASSUME IT'S EITHER NETSCAPE OR MSIE
if (navigator.appName == "Netscape") {
    isNav = true;
}
else {
    isIE = true;
}


//These are the STATIC date variables for logic statements
var now = new Date();
var theYear = now.getFullYear();          
var theMonth = now.getMonth();
var theDay = now.getDate();


function dateObject(monthnum, month, year){
	this.month = month;
	this.year = year;
	this.monthnum = monthnum
}

monthNameArray = new Array('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December');

var monthYear = new Array(12);

function getDateParam(){
	month = theMonth;
	year = theYear
	
	for(i=0; i < 13; i++){
		monthYear[i] = new dateObject(month, monthNameArray[month], year);
		month++;
		if(month == 12){
			month = 0;
			year++;
		}
	}
}

getDateParam();



// PRE-BUILD PORTIONS OF THE CALENDAR WHEN THIS JS LIBRARY LOADS INTO THE BROWSER
buildCalParts();

// CALENDAR FUNCTIONS BEGIN HERE ---------------------------------------------------

// SET THE INITIAL VALUE OF THE GLOBAL DATE FIELD
function setDateField(dateField) {

    // ASSIGN THE INCOMING FIELD OBJECT TO A GLOBAL VARIABLE
    calDateField = dateField;

    // GET THE VALUE OF THE INCOMING FIELD
    inDate = dateField.value;

    // SET calDate TO THE DATE IN THE INCOMING FIELD OR DEFAULT TO TODAY'S DATE
    setInitialDate();

    // THE CALENDAR FRAMESET DOCUMENTS ARE CREATED BY JAVASCRIPT FUNCTIONS
    calDocTop    = buildTopCalFrame();
    calDocBottom = buildBottomCalFrame();
}


// SET THE INITIAL CALENDAR DATE TO TODAY OR TO THE EXISTING VALUE IN dateField
function setInitialDate() {
   
    // CREATE A NEW DATE OBJECT (WILL GENERALLY PARSE CORRECT DATE EXCEPT WHEN "." IS USED AS A DELIMITER)
    // (THIS ROUTINE DOES *NOT* CATCH ALL DATE FORMATS, IF YOU NEED TO PARSE A CUSTOM DATE FORMAT, DO IT HERE)
    calDate = new Date(inDate);

    // IF THE INCOMING DATE IS INVALID, USE THE CURRENT DATE
    if (isNaN(calDate)) {

        // ADD CUSTOM DATE PARSING HERE
        // IF IT FAILS, SIMPLY CREATE A NEW DATE OBJECT WHICH DEFAULTS TO THE CURRENT DATE
        calDate = new Date();
    }

    // KEEP TRACK OF THE CURRENT DAY VALUE
	calDay  = calDate.getDate();
	calMonth = calDate.getMonth();
	calYear = calDate.getFullYear();
	



    // SET DAY VALUE TO 1... TO AVOID JAVASCRIPT DATE CALCULATION ANOMALIES
    // (IF THE MONTH CHANGES TO FEB AND THE DAY IS 30, THE MONTH WOULD CHANGE TO MARCH
    //  AND THE DAY WOULD CHANGE TO 2.  SETTING THE DAY TO 1 WILL PREVENT THAT)
    calDate.setDate(1);
}


// POPUP A WINDOW WITH THE CALENDAR IN IT
function showCalendar(dateField) {

    // SET INITIAL VALUE OF THE DATE FIELD AND CREATE TOP AND BOTTOM FRAMES
    setDateField(dateField);

    // USE THE JAVASCRIPT-GENERATED DOCUMENTS (calDocTop, calDocBottom) IN THE FRAMESET
    calDocFrameset = 
        "<HTML><HEAD><TITLE>JavaScript Calendar</TITLE></HEAD>\n" +
        "<FRAMESET ROWS='70,*' FRAMEBORDER='0'>\n" +
        "  <FRAME NAME='topCalFrame' SRC='javascript:parent.opener.calDocTop' SCROLLING='no'>\n" +
        "  <FRAME NAME='bottomCalFrame' SRC='javascript:parent.opener.calDocBottom' SCROLLING='no'>\n" +
        "</FRAMESET>\n";

    // DISPLAY THE CALENDAR IN A NEW POPUP WINDOW
    top.cal = window.open("javascript:parent.opener.calDocFrameset", "calWin", winPrefs);
    top.cal.focus();
}


// CREATE THE TOP CALENDAR FRAME
function buildTopCalFrame() {

    // CREATE THE TOP FRAME OF THE CALENDAR
    var calDoc =
        "<HTML>" +
        "<HEAD>" +
        "</HEAD>" +
        "<BODY BGCOLOR='" + topBackground + "'>" +
        "<FORM NAME='calControl' onSubmit='return false;'>" +
        "<CENTER>" +
        "<TABLE CELLPADDING=0 CELLSPACING=1 BORDER=0>" +
        "<TR><TD COLSPAN=7>" +
        "<CENTER>" +
        getMonthSelect() +
        "</CENTER>" +
        "</TD>" +
        "</TR>" +
        "<TR>" +
        "<TD COLSPAN=7 align=center>" +
        "<INPUT TYPE=BUTTON NAME='previousMonth' VALUE=' < '   onClick='parent.opener.setPreviousMonth()'><INPUT TYPE=BUTTON NAME='today' VALUE='Today' onClick='parent.opener.setToday()'><INPUT TYPE=BUTTON NAME='nextMonth' VALUE=' > '   onClick='parent.opener.setNextMonth()'></TD>" +
        "</TR>" +
        "</TABLE>" +
        "</CENTER>" +
        "</FORM>" +
        "</BODY>" +
        "</HTML>";

    return calDoc;
}


// CREATE THE BOTTOM CALENDAR FRAME 
// (THE MONTHLY CALENDAR)
function buildBottomCalFrame() {       
	var calDoc = calendarBegin;
	
	var columnCount = 0;
	var day = calDay;
    var i = 0;

    // DETERMINE THE NUMBER OF DAYS IN THE CURRENT MONTH
    var days = getDaysInMonth(calMonth, calYear);
	
	// IF GLOBAL DAY VALUE IS > THAN DAYS IN MONTH, HIGHLIGHT LAST DAY IN MONTH
    if (day > days) {
        day = days;
    }
	
	// DETERMINE WHAT DAY OF THE WEEK THE CALENDAR STARTS ON
    var firstOfMonth = new Date (calYear, calMonth, 1);
	
	// GET THE DAY OF THE WEEK THE FIRST DAY OF THE MONTH FALLS ON
    var startingPos  = firstOfMonth.getDay();
    days += startingPos;
	
	
	for (i = 0; i < startingPos; i++) {
   
		calDoc += "<TD align=center bgcolor='" + cellColor + "'>&nbsp;&nbsp;&nbsp;</TD>";
		columnCount++;

    }
// SET VALUES FOR DAYS OF THE MONTH
    var currentDay = 0;
    var dayType    = "weekday";

    // DATE CELLS CONTAIN A NUMBER
	//all cells up to current day are greyed down
		
    for (i = startingPos+1; i <= days; i++) {

	var paddingChar = "&nbsp;";

        // ADJUST SPACING SO THAT ALL LINKS HAVE RELATIVELY EQUAL WIDTHS
        if (i-startingPos+1 < 10) {
            padding = paddingChar + paddingChar;
        }  else {
            padding = paddingChar;
        }

        // GET THE DAY CURRENTLY BEING WRITTEN
        currentDay = i-startingPos;

        // SET THE TYPE OF DAY, THE focusDay GENERALLY APPEARS AS A DIFFERENT COLOR
        if (currentDay == day) {
            dayType = "focusDay";
        } else {
            dayType = "weekDay";
        }

        // ADD THE DAY TO THE CALENDAR STRING
  
  columnCount++;

if((theYear == calYear) && (theMonth == calMonth) && (currentDay < theDay) || isHoliday(currentDay)){
					calDoc += "<TD align=center bgcolor='" + wkendcellColor + "'><font face=verdana, arial, helvetica size=2 color=000000 style='text-decoration: line-through'>" + padding + currentDay + paddingChar + "</font></TD>";
				}else{
					calDoc += "<TD align=center bgcolor='" + cellColor + "'>" + "<a class='" + dayType + "' href='javascript:parent.opener.returnDate(" + currentDay + ")'>" + padding + currentDay + paddingChar + "</a></TD>";

				}
if(columnCount == 7 || columnCount == 14 || columnCount == 21 || columnCount == 28 || columnCount == 35 || columnCount == 42){
	calDoc += "</TR><TR>";

}
}
// MAKE REMAINING NON-DATE CELLS BLANK
    for (i=days; i<42; i++)  {

        calDoc += "<TD align=center bgcolor='" + cellColor + "'>&nbsp;&nbsp;&nbsp;</TD>";
	columnCount++;

        // START A NEW ROW WHEN NECESSARY
        if (columnCount % 7 == 0) {
            calDoc += "</TR>";
            if (i<41) {
                calDoc += "<TR>";
            }
        }
    }
	
	calDoc += calendarEnd;
	return calDoc;

}


function isHoliday(currentDay){
var holiday = new Date (calYear, calMonth, currentDay);
var isHoliday = holiday.getDay();
	 if(calMonth == 0){
	 	if(currentDay == 1)
			return (true);
		}
	else if(calMonth == 4){
	 	if(isHoliday == 1 && 25 <= currentDay && currentDay <= 31)
			return (true);
			}
	 else if(calMonth == 6){
	 	if(currentDay == 4)
			return (true);
			}
	else if(calMonth == 8){
	 	if(isHoliday == 1 && 1 <= currentDay && currentDay <= 7)
			return (true);
			}
	 else if(calMonth == 10){
	 	if((isHoliday == 4 &&  22 <= currentDay && currentDay <= 28))
			return (true);
			}
	 else if(calMonth == 11){
	 	if(currentDay == 24 || currentDay == 25)
			return (true);
			}
	//hardcoded for Easter
	else if (calYear == 2006 && calMonth == 3 && currentDay == 16) return true;
	else if (calYear == 2007 && calMonth == 3 && currentDay == 8) return true;
	else if (calYear == 2008 && calMonth == 2 && currentDay == 23) return true;
	else if (calYear == 2009 && calMonth == 3 && currentDay == 12) return true;
	else if (calYear == 2010 && calMonth == 3 && currentDay == 4) return true;
	else if (calYear == 2011 && calMonth == 3 && currentDay == 24) return true;
	else if (calYear == 2012 && calMonth == 3 && currentDay == 8) return true;
	else if (calYear == 2013 && calMonth == 2 && currentDay == 31) return true;
	else if (calYear == 2014 && calMonth == 3 && currentDay == 20) return true;
	else if (calYear == 2015 && calMonth == 3 && currentDay == 5) return true;
		else{
			return (false);
			}
}

// WRITE THE MONTHLY CALENDAR TO THE BOTTOM CALENDAR FRAME
function writeCalendar() {

    // CREATE THE NEW CALENDAR FOR THE SELECTED MONTH & YEAR
    calDocBottom = buildBottomCalFrame();

    // WRITE THE NEW CALENDAR TO THE BOTTOM FRAME
    top.cal.frames['bottomCalFrame'].document.open();
    top.cal.frames['bottomCalFrame'].document.write(calDocBottom);
    top.cal.frames['bottomCalFrame'].document.close();
}


// SET THE CALENDAR TO TODAY'S DATE AND DISPLAY THE NEW CALENDAR
function setToday() {
    // SET MONTH IN DROP-DOWN LIST
    top.cal.frames['topCalFrame'].document.calControl.monthYearSelect.selectedIndex = 0;
	calMonth = monthYear[0].monthnum;
	calYear = monthYear[0].year;
	calDay = now.getDate();
    writeCalendar();
}


// SET THE GLOBAL DATE TO THE SELECTED MONTH AND REDRAW THE CALENDAR
function setMonthSelect() {
    // GET THE NEWLY SELECTED MONTH AND CHANGE THE CALENDAR ACCORDINGLY
	var i =	top.cal.frames['topCalFrame'].document.calControl.monthYearSelect.selectedIndex
	calMonth = monthYear[i].monthnum;
	calYear = monthYear[i].year;
    writeCalendar();
}


// SET THE GLOBAL DATE TO THE PREVIOUS MONTH AND REDRAW THE CALENDAR
function setPreviousMonth() {
	var i =	top.cal.frames['topCalFrame'].document.calControl.monthYearSelect.selectedIndex
	if (i == 0){
	}else{
	i--;
	top.cal.frames['topCalFrame'].document.calControl.monthYearSelect.selectedIndex = i;
	calMonth = monthYear[i].monthnum;
	calYear = monthYear[i].year;
    writeCalendar();
	}
}


// SET THE GLOBAL DATE TO THE NEXT MONTH AND REDRAW THE CALENDAR
function setNextMonth() {
    var i =	top.cal.frames['topCalFrame'].document.calControl.monthYearSelect.selectedIndex
	if (i == 12){
	}else{
	i++;
	top.cal.frames['topCalFrame'].document.calControl.monthYearSelect.selectedIndex = i;
	calMonth = monthYear[i].monthnum;
	calYear = monthYear[i].year;
    writeCalendar();
	}
}


// GET NUMBER OF DAYS IN MONTH
function getDaysInMonth(month, year)  {
	var days 
	
    // RETURN 31 DAYS
    if (month==0 || month==2 || month==4 || month==6 || month==7 ||
        month==9 || month==11)  {
        days=31;
    }
    // RETURN 30 DAYS
    else if (month==3 || month==5 || month==8 || month==10) {
        days=30;
    }
    // RETURN 29 DAYS
    else if (month==1)  {
        if (isLeapYear(year)) {
            days=29;
        }
        // RETURN 28 DAYS
        else {
            days=28;
        }
    }
    return (days);
}


// CHECK TO SEE IF YEAR IS A LEAP YEAR
function isLeapYear (Year) {

    if (((Year % 4)==0) && ((Year % 100)!=0) || ((Year % 400)==0)) {
        return (true);
    }
    else {
        return (false);
    }
}


// BUILD THE MONTH SELECT LIST
function getMonthSelect() {
		
    // START HTML SELECT LIST ELEMENT
    monthSelect = "<SELECT NAME='monthYearSelect' onChange='parent.opener.setMonthSelect()'>";

    // SHOW THE CORRECT MONTH IN THE SELECT LIST
    for (i in monthYear){
		if ((monthYear[i].monthnum == (calMonth)) && (monthYear[i].year == calYear)){
		monthSelect += "<OPTION SELECTED value=" + i + ">" + monthYear[i].month + " - " + monthYear[i].year +  "</option>";
	}else{
		monthSelect += "<OPTION value=" + i + ">" + monthYear[i].month + " - " + monthYear[i].year +  "</option>";
}
    }
	 monthSelect += "</SELECT>";

    // RETURN A STRING VALUE WHICH CONTAINS A SELECT LIST OF ALL 13 MONTHS
    return monthSelect;
}


// SET DAYS OF THE WEEK 
function createWeekdayList() {
    weekdayArray = new Array('Su','Mo','Tu','We','Th','Fr','Sa');
  

    // START HTML TO HOLD WEEKDAY NAMES IN TABLE FORMAT
    var weekdays = "<TR BGCOLOR='" + headingCellColor + "'>";

    // LOOP THROUGH WEEKDAY ARRAY
    for (i in weekdayArray) {

        weekdays += "<TD class='heading' align=center>" + weekdayArray[i] + "</TD>";
    }
    	weekdays += "</TR>";

    // RETURN TABLE ROW OF WEEKDAY ABBREVIATIONS TO DISPLAY ABOVE THE CALENDAR
    return weekdays;
}


// PRE-BUILD PORTIONS OF THE CALENDAR (FOR PERFORMANCE REASONS)
function buildCalParts() {

    // GENERATE WEEKDAY HEADERS FOR THE CALENDAR
    weekdays = createWeekdayList();

    // BUILD THE TOP PORTION OF THE CALENDAR PAGE USING CSS TO CONTROL SOME DISPLAY ELEMENTS
    calendarBegin =
        "<HTML>" +
        "<HEAD>" +
        // STYLESHEET DEFINES APPEARANCE OF CALENDAR
        "<STYLE type='text/css'>" +
        "<!--" +
        "TD.heading { text-decoration: none; color:" + headingTextColor + "; font: " + headingFontStyle + "; }" +
        "A.focusDay:link, A.focusDay:active, A.focusDay:visited { background-color: #25408f; color: " + focusColor + "; text-decoration: none; font: " + hoverfontStyle + "; }" +
"A.focusDay:hover { text-decoration: underline; background-color: #ab673f; color: " + hoverColor + "; font: " + hoverfontStyle + "; }" +
        "A.weekday:link, A.weekday:active, A.weekday:visited  {text-decoration: none; color: " + dateColor + "; text-decoration: none; font: " + fontStyle + "; }" +
        "A.weekday:hover { background-color: #25408f; color: " + hoverColor + "; font: " + hoverfontStyle + "; }" +
        "-->" +
        "</STYLE>" +
        "</HEAD>" +
        "<BODY BGCOLOR='" + bottomBackground + "'" +
        "<CENTER>";

        // NAVIGATOR NEEDS A TABLE CONTAINER TO DISPLAY THE TABLE OUTLINES PROPERLY
        if (isNav) {
            calendarBegin += 
                "<TABLE CELLPADDING=0 CELLSPACING=1 BORDER=" + tableBorder + " ALIGN=CENTER BGCOLOR='" + tableBGColor + "'><TR><TD>";
        }

        // BUILD WEEKDAY HEADINGS
        calendarBegin +=
            "<TABLE CELLPADDING=0 CELLSPACING=1 BORDER=" + tableBorder + " ALIGN=CENTER BGCOLOR='" + tableBGColor + "'>" +
            weekdays +
            "<TR>";


    // BUILD THE BOTTOM PORTION OF THE CALENDAR PAGE
    calendarEnd = "";

        // WHETHER OR NOT TO DISPLAY A THICK LINE BELOW THE CALENDAR
        if (bottomBorder) {
            calendarEnd += "<TR></TR>";
        }

        // NAVIGATOR NEEDS A TABLE CONTAINER TO DISPLAY THE BORDERS PROPERLY
        if (isNav) {
            calendarEnd += "</TD></TR></TABLE>";
        }

        // END THE TABLE AND HTML DOCUMENT
        calendarEnd +=
            "</TABLE>" +
            "</CENTER>" +
            "</BODY>" +
            "</HTML>";
}


// REPLACE ALL INSTANCES OF find WITH replace
// inString: the string you want to convert
// find:     the value to search for
// replace:  the value to substitute
//
// usage:    jsReplace(inString, find, replace);
// example:  jsReplace("To be or not to be", "be", "ski");
//           result: "To ski or not to ski"
//
function jsReplace(inString, find, replace) {

    var outString = "";

    if (!inString) {
        return "";
    }

    // REPLACE ALL INSTANCES OF find WITH replace
    if (inString.indexOf(find) != -1) {
        // SEPARATE THE STRING INTO AN ARRAY OF STRINGS USING THE VALUE IN find
        t = inString.split(find);

        // JOIN ALL ELEMENTS OF THE ARRAY, SEPARATED BY THE VALUE IN replace
        return (t.join(replace));
    }
    else {
        return inString;
    }
}


// JAVASCRIPT FUNCTION -- DOES NOTHING (USED FOR THE HREF IN THE CALENDAR CALL)
function doNothing() {
}


// ENSURE THAT VALUE IS TWO DIGITS IN LENGTH
function makeTwoDigit(inValue) {

    var numVal = parseInt(inValue, 10);

    // VALUE IS LESS THAN TWO DIGITS IN LENGTH
    if (numVal < 10) {

        // ADD A LEADING ZERO TO THE VALUE AND RETURN IT
        return("0" + numVal);
    }
    else {
        return numVal;
    }
}


// SET FIELD VALUE TO THE DATE SELECTED AND CLOSE THE CALENDAR WINDOW
function returnDate(inDay){

    // SET THE DATE RETURNED TO THE USER
	var index = top.cal.frames['topCalFrame'].document.calControl.monthYearSelect.selectedIndex;
    var day           = inDay
    var month         = monthYear[index].monthnum+1
    var year          = monthYear[index].year

    outDate = calDateFormat;

    // RETURN TWO DIGIT DAY
    if (calDateFormat.indexOf("DD") != -1) {
        day = makeTwoDigit(day);
        outDate = jsReplace(outDate, "DD", day);
    }

    // RETURN TWO DIGIT MONTH
    if (calDateFormat.indexOf("MM") != -1) {
        month = makeTwoDigit(month);
        outDate = jsReplace(outDate, "MM", month);
    }

    // RETURN FOUR-DIGIT YEAR
    if (calDateFormat.indexOf("yyyy") != -1) {
        outDate = jsReplace(outDate, "yyyy", year);
    }

    // SET THE VALUE OF THE FIELD THAT WAS PASSED TO THE CALENDAR
    calDateField.value = outDate;

    // GIVE FOCUS BACK TO THE DATE FIELD
    calDateField.focus();

    // CLOSE THE CALENDAR WINDOW
    top.cal.close()
}
