// Javascript name: My Date Time Picker
// Date created: 16-Nov-2003 23:19
// Scripter: TengYong Ng
// ( Revised by Dylan Doxey on 11-Nov-2007 )
// Website: http://www.rainforestnet.com
// Copyright (c) 2003 TengYong Ng
// FileName: DateTimePicker.js
// Version: 0.8 
// Contact: contact@rainforestnet.com
//  Note: Permission given to use this script in ANY kind of applications if
//       header lines are left unchanged.

//Global variables
var winCal;
var dtToday = new Date();
var Cal;
var docCal;
var MonthName = [
    'January',   'February', 'March',    'April',
    'May',       'June',     'July',     'August',
    'September', 'October',  'November', 'December'
];
var WeekDayName = [
    'Sunday',   'Monday', 'Tuesday', 'Wednesday',
    'Thursday', 'Friday', 'Saturday'
];
var exDateTime;              // Existing Date and Time

// Configurable parameters
var cnHeight       = 175;    // calendar window height.
var cnWidth        = 175;    // calendar window width.
var WindowTitle    = 'Date'; // Date Time Picker title.
var WeekChar       = 2;      // number of character for week day. if 2 then Mo,Tu,We. if 3 then Mon,Tue,Wed.
var DateSeparator  = '-';    // Date Separator, you can change it to '/' if you want.
var TimeMode       = 24;     // default TimeMode value. 12 or 24
var ShowLongMonth  = true;   // Show long month name in Calendar header. example: 'January'.
var ShowMonthYear  = true;   // Show Month and Year in Calendar header.

var WeekHead  = '#0099CC';   // Background Color in Week header.
var Sunday    = '#6699FF';   // Background color of Sunday.
var Saturday  = '#CCCCFF';   // Background color of Saturday.
var WeekDay   = 'white';     // Background color of weekdays.
var Font      = 'blue';      // color of font in Calendar day cell.
var Today     = '#FFFF33';   // Background color of today.
var SelDate   = '#FFFF99';   // Backgrond color of selected date in textbox.
var YrSel     = '#cc0033';   // color of font of Year selector.
var TdNormal  = '#ffe';      // normal td color

function NewCal( pCtrl, pFormat, pShowTime, pTimeMode ) {

    Cal = new Calendar(dtToday);

    if ( ( pShowTime != null ) && ( pShowTime ) ) {

        Cal.ShowTime = true;

        if (
             ( pTimeMode != null )
          && (
               ( pTimeMode == '12' )
            || ( pTimeMode == '24' )
            )
        ) {
            TimeMode = pTimeMode;
        }
    }
    if ( pCtrl   != null ) Cal.Ctrl   = pCtrl;
    if ( pFormat != null ) Cal.Format = pFormat.toUpperCase();

    exDateTime = domElement( pCtrl ).value;

    // Parse Date String
    if ( exDateTime != '' ) {

        var Sp1;  // Index of Date Separator 1
        var Sp2;  // Index of Date Separator 2
        var tSp1; // Index of Time Separator 1
        var tSp1; // Index of Time Separator 2
        var strMonth;
        var strDate;
        var strYear;
        var intMonth;
        var YearPattern;
        var strHour;
        var strMinute;
        var strSecond;

        //parse month
        Sp1 = exDateTime.indexOf( DateSeparator, 0                       );
        Sp2 = exDateTime.indexOf( DateSeparator, ( parseInt( Sp1 ) + 1 ) );

        if (
             ( Cal.Format.toUpperCase() == 'DDMMYYYY'  )
          || ( Cal.Format.toUpperCase() == 'DDMMMYYYY' )
        ) {
            strMonth = exDateTime.substring( Sp1 + 1, Sp2 );
            strDate  = exDateTime.substring( 0, Sp1       );
        }
        else
            if (
                 ( Cal.Format.toUpperCase() == 'MMDDYYYY'  )
              || ( Cal.Format.toUpperCase() == 'MMMDDYYYY' )
            ) {
                strMonth = exDateTime.substring( 0, Sp1       );
                strDate  = exDateTime.substring( Sp1 + 1, Sp2 );
            }

        if ( isNaN( strMonth ) ) intMonth = Cal.GetMonthIndex( strMonth );
        else intMonth = parseInt( strMonth, 10 ) - 1;

        if ( 
             ( parseInt( intMonth, 10 ) >= 0 ) 
	  && ( parseInt( intMonth, 10 ) < 12 ) 
	) {
            Cal.Month = intMonth;
        }
        //end parse month

        //parse Date
        if ( 
             ( parseInt( strDate, 10 ) <= Cal.GetMonDays() ) 
	  && ( parseInt( strDate, 10 ) >= 1 ) 
	) {
            Cal.Date = strDate;
	}
        //end parse Date

        //parse year
        strYear = exDateTime.substring( Sp2 + 1 , Sp2 + 5 );
    	YearPattern = new RegExp(/^\d{4}$/);
        if ( YearPattern.test( strYear ) ) Cal.Year = parseInt( strYear, 10 );
        //end parse year

        //parse time
        if ( Cal.ShowTime == true ) {

            tSp1 = exDateTime.indexOf( ':', 0                        );
            tSp2 = exDateTime.indexOf( ':', ( parseInt( tSp1 ) + 1 ) );
	    
            strHour = exDateTime.substring( tSp1, (tSp1) - 2 );
            Cal.SetHour( strHour );

            strMinute = exDateTime.substring( tSp1 + 1, tSp2 );
            Cal.SetMinute( strMinute );

            strSecond = exDateTime.substring( tSp2 + 1, tSp2 + 3 );
            Cal.SetSecond( strSecond );
        }
    }

    var popupargs = 'toolbar=0,status=0,menubar=0,fullscreen=no,resizable=0,'
    	+ centeredPopupCoords( cnWidth, cnHeight );

    winCal = window.open( '', 'DateTimePicker', popupargs );

    docCal = winCal.document;

    RenderCal();
}

function RenderCal() {

    var vCalHeader;
    var vCalData;
    var vCalTime;
    var i;
    var j;
    var SelectStr;
    var vDayCount = 0;
    var vFirstDay;

    docCal.open();
    docCal.writeln(
        '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" '
    	    + '"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'
    );
    docCal.writeln('<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">');
    docCal.writeln('<head>');
    docCal.writeln('<title>'+WindowTitle+'</title>');
    docCal.writeln('<script type="text/javascript">var winMain = window.opener;</script>');
    docCal.writeln('<style type="text/css">');
    docCal.writeln('*{');
    docCal.writeln('    font-family: arial, helvetica, sans-serif;');
    docCal.writeln('    font-size: 8px;');
    docCal.writeln('}')
    docCal.writeln('td { width: 20px; background-color: ' + TdNormal + '; border: #666 1px solid; }');
    docCal.writeln('table td table td { border: #fff 0px solid; }');
    docCal.writeln('.WeekHead  { background-color: ' + WeekHead  + '; }'); 
    docCal.writeln('.Sunday    { background-color: ' + Sunday    + '; }'); 
    docCal.writeln('.Saturday  { background-color: ' + Saturday  + '; }'); 
    docCal.writeln('.WeekDay   { background-color: ' + WeekDay   + '; }'); 
    docCal.writeln('.Font      { background-color: ' + Font      + '; }'); 
    docCal.writeln('.Today     { background-color: ' + Today     + '; }'); 
    docCal.writeln('.SelDate   { background-color: ' + SelDate   + '; }'); 
    docCal.writeln('.YrSel     { background-color: ' + YrSel     + '; }'); 
    docCal.writeln('</style>');
    docCal.writeln('</head><body>');
    docCal.writeln('<form id="Calendar" action="" onsubmit="return false;">');

    vCalHeader = '<table cellpadding="1" cellspacing="1" width="100%"><tbody>';

    //Month Selector
    vCalHeader += '<tr>'
        + '<td colspan="7">'
        + '<table width="100%" cellpadding="0" cellspacing="0"><tbody>'
        + '<tr>';

    vCalHeader += '<td align="left" class="month-select">'
        + '<select'
        + ' name="MonthSelector"'
        + ' onchange="javascript:winMain.Cal.SwitchMth(this.selectedIndex);winMain.RenderCal();"'
        + '>\n';

    for ( var i = 0; i < 12 ; i++ ) {

        if (i == Cal.Month) SelectStr = ' selected="selected"';
        else SelectStr = '';

        vCalHeader += '<option' + SelectStr + '>' + MonthName[i] + '</option>\n';
    }
    vCalHeader += '</select>'
        + '</td>';

    //Year selector
    vCalHeader += '<td align="right" class="year-select">'
        + '<a href="javascript:winMain.Cal.DecYear();winMain.RenderCal()">&lt;</a>'
        + '<span>' + Cal.Year + '</span>'
        + '<a href="javascript:winMain.Cal.IncYear();winMain.RenderCal()">&gt;</a>'
        + '</td>';

    vCalHeader += '</tr></tbody></table>';
    vCalHeader += '</td></tr>';

    //Calendar header shows Month and Year
    if ( ShowMonthYear ) vCalHeader += '<tr class="month-head">'
        + '<td colspan="7">'
        + Cal.GetMonthName(ShowLongMonth) + ' ' + Cal.Year
        + '</td></tr>';

    //Week day header
    vCalHeader += '<tr class="weekday-head">';
    for ( var i=0; i < 7; i++ ) {

        vCalHeader += '<td align="center" class="WeekHead">' + WeekDayName[i].substr( 0, WeekChar ) + '</td>';
    }
    vCalHeader += '</tr>';
    docCal.write(vCalHeader);

    //Calendar detail
    CalDate = new Date( Cal.Year, Cal.Month );
    CalDate.setDate( 1 );
    vFirstDay = CalDate.getDay();
    vCalData = '\n<tr>';

    for ( var i = 0; i < vFirstDay; i++ ) {

        vCalData = vCalData  + GenCell();
        vDayCount++;
    }

    for ( var j = 1; j <= Cal.GetMonDays(); j++ ) {

        var strCell;
        vDayCount++;

        if (
             (         j == dtToday.getDate()     )
          && ( Cal.Month == dtToday.getMonth()    )
          && ( Cal.Year  == dtToday.getFullYear() )
        ) {
            // Highlight today's date
            strCell = GenCell( j, true, 'Today' );
        }
        else {

            if (j == Cal.Date) {

                strCell = GenCell( j, true, 'SelDate' );
            }
            else {

                if ( vDayCount % 7 == 0 ) strCell = GenCell( j, false, 'Saturday' );
                else
                    if ( ( vDayCount + 6 ) % 7 == 0 ) strCell = GenCell( j, false, 'Sunday' );
                    else strCell = GenCell( j, null, WeekDay );
            }
        }
        vCalData = vCalData + strCell;

        if (
             ( vDayCount % 7 == 0 )
          && ( j < Cal.GetMonDays() )
        ) {
            vCalData += '</tr>\n<tr>';
        }
    }
    vCalData = vCalData.replace( /<tr>$/, '' );
    for (; vDayCount % 7 != 0; vDayCount++ ) {
        vCalData += GenCell();
    }
    vCalData += '</tr>';

    docCal.writeln( vCalData );

    //Time picker
    if ( Cal.ShowTime ) {

        var showHour;
        showHour = Cal.getShowHour();

        vCalTime = '<tr>'
            + '<td colspan="7" align="center">';

        vCalTime += '<input type="text" name="hour" '
        + 'value="' + showHour + '" maxlength="2" size="1" style="width:22px;" '
        + 'onchange="javascript:winMain.Cal.SetHour(this.value)" />';
        vCalTime += ' : ';
        vCalTime += '<input type="text" name="minute" '
        + 'value="' + Cal.Minutes + '" maxlength="2" size="1" style="width:22px;" '
        + 'onchange="javascript:winMain.Cal.SetMinute(this.value)" />';
        vCalTime += ' : ';
        vCalTime += '<input type="text" name="second" '
        + 'value="' + Cal.Seconds + '" maxlength="2" size="1" style="width:22px;" '
        + 'onchange="javascript:winMain.Cal.SetSecond(this.value)" />';

        if ( TimeMode == 12 ) {

            var SelectAm  = ( parseInt( Cal.Hours, 10 ) < 12  ) ? ' selected="selected"' : '';
            var SelectPm  = ( parseInt( Cal.Hours, 10 ) >= 12 ) ? ' selected="selected"' : '';

            vCalTime += '<select name="ampm" '
	        + 'onchange="javascript:winMain.Cal.SetAmPm(this.options[this.selectedIndex].value);"'
		+ '>';
            vCalTime += '<option' + SelectAm + '>AM</option>';
            vCalTime += '<option' + SelectPm + '>PM</option>';
            vCalTime += '</select>';
        }
        vCalTime += '</td>'
            + '</tr>';

        docCal.write(vCalTime);
    }
    //end time picker
    docCal.writeln('</tbody></table>');
    docCal.writeln('</form></body></html>');
    docCal.close();
}

// Generate table cell with value
function GenCell( pValue, pHighLight, pColor ) {

    var PValue;
    var PCellStr;
    var color_class;
    var vHLstr1; //HighLight string
    var vHlstr2;
    var vTimeStr;

    if ( pValue == null ) PValue = '';
    else PValue = pValue;

    if ( pColor != null ) color_class = pColor;
    else color_class = '';

    if ( ( pHighLight != null ) && ( pHighLight ) ) {
        vHLstr1 = ' style="color:red;"';
    }
    else {
        vHLstr1 = '';
    }

    if ( Cal.ShowTime ) {

        vTimeStr = 'winMain.domElement(\''
            + Cal.Ctrl
            + '\').value+=\' \'+'
            + 'winMain.Cal.getShowHour()'
            + '+\':\'+'
            + 'winMain.Cal.Minutes'
            + '+\':\'+'
            + 'winMain.Cal.Seconds';

        if ( TimeMode == 12 ) vTimeStr += '+ \' \' + winMain.Cal.AMorPM';

        vTimeStr += ';';
    }
    else vTimeStr = '';

    PCellStr = '<td class="' + color_class + '" align="center"' + vHLstr1 + '>'
        + '<a href="javascript:winMain.domElement(\''
        + Cal.Ctrl
        + '\').value=\''
        + Cal.FormatDate( PValue )
        + '\';'
        + vTimeStr
        + 'window.close();">'
        + PValue
        + '</a>'
        + '</td>';

    return PCellStr;
}

function centeredPopupCoords( xsize, ysize ) {
    var centerOnHeight = ( screen.availHeight / 3 );
    var centerOnWidth  = ( screen.availWidth  / 3 );
    var positX = centerOnWidth  - ( xsize / 3 );
    var positY = centerOnHeight - ( ysize / 3 );
    var position = 'width=' + xsize + ',' + 'height=' + ysize + ',';
    if ( document.all ) position += "left=" + positX + ",top=" + positY + ",";
    else position += "screenX=" + positX + ",screenY=" + positY + ",";
    return position;
}

function Calendar( pDate, pCtrl ) {

    //Properties
    this.Date  = pDate.getDate();     //selected date
    this.Month = pDate.getMonth();    //selected month number
    this.Year  = pDate.getFullYear(); //selected year in 4 digits
    this.Hours = pDate.getHours();

    if ( pDate.getMinutes() < 10 ) this.Minutes = '0' + pDate.getMinutes();
    else this.Minutes = pDate.getMinutes();

    if ( pDate.getSeconds() < 10) this.Seconds = '0' + pDate.getSeconds();
    else this.Seconds = pDate.getSeconds();

    this.MyWindow  = winCal;
    this.Ctrl      = pCtrl;
    this.Format    = 'ddMMyyyy';
    this.Separator = DateSeparator;
    this.ShowTime  = false;

    if ( pDate.getHours() < 12 ) this.AMorPM = 'AM';
    else this.AMorPM = 'PM';
}

function GetMonthIndex( shortMonthName ) {

    for ( var i = 0; i < 12; i++ ) {
        if (
             MonthName[i].substring( 0, 3 ).toUpperCase() == shortMonthName.toUpperCase()
        ) {
            return i;
        }
    }
}
Calendar.prototype.GetMonthIndex = GetMonthIndex;

function IncYear() {
    Cal.Year++;
}
Calendar.prototype.IncYear = IncYear;

function DecYear() {
    Cal.Year--;
}
Calendar.prototype.DecYear = DecYear;

function SwitchMth( intMth ) {

    Cal.Month = intMth;
}
Calendar.prototype.SwitchMth = SwitchMth;

function SetHour( intHour ) {

    var MaxHour;
    var MinHour;

    if ( TimeMode == 24 ) {

        MaxHour = 23;
        MinHour = 0
    }
    else if ( TimeMode == 12 ) {
        MaxHour = 12;
        MinHour = 1
    }
    else alert('TimeMode can only be 12 or 24');

    var HourExp = new RegExp('^\\d\\d$');
    if (
         HourExp.test( intHour )
      && ( parseInt( intHour, 10 ) <= MaxHour )
      && ( parseInt( intHour, 10 ) >= MinHour )
    ) {
        if ( ( TimeMode == 12 ) && ( Cal.AMorPM == 'PM') ) {

            if ( parseInt( intHour, 10 ) == 12 ) Cal.Hours = 12;
            else Cal.Hours = parseInt( intHour, 10 ) + 12;
        }
        else {
            if (
                 ( TimeMode   == 12   )
              && ( Cal.AMorPM == 'AM' )
            ) {
                if ( intHour == 12 ) intHour -= 12;
                Cal.Hours = parseInt( intHour, 10 );
            }
            else if ( TimeMode == 24 ) Cal.Hours = parseInt( intHour, 10 );
        }
    }
}
Calendar.prototype.SetHour = SetHour;

function SetMinute( intMin ) {

    var MinExp = new RegExp('^\\d\\d$');

    if ( MinExp.test( intMin ) && ( intMin < 60 ) ) Cal.Minutes = intMin;

    return;
}
Calendar.prototype.SetMinute = SetMinute;

function SetSecond( intSec ) {

    var SecExp = new RegExp('^\\d\\d$');

    if ( SecExp.test(intSec) && ( intSec < 60 ) ) Cal.Seconds = intSec;

    return;
}
Calendar.prototype.SetSecond = SetSecond;

function SetAmPm( pvalue ) {

    this.AMorPM = pvalue;

    if (pvalue == 'PM') {

        this.Hours = ( parseInt( this.Hours, 10 ) ) + 12;

        if (this.Hours == 24) this.Hours = 12;
    }
    else if (pvalue == 'AM') this.Hours -= 12;

    return;
}
Calendar.prototype.SetAmPm = SetAmPm;

function getShowHour() {
    var finalHour;

    if ( TimeMode == 12 ) {

        if (parseInt(this.Hours,10) == 0) {
            this.AMorPM = 'AM';
            finalHour = parseInt(this.Hours,10)+12;
        }
        else if (parseInt(this.Hours,10) == 12) {
            this.AMorPM = 'PM';
            finalHour = 12;
        }
        else if (this.Hours>12) {
            this.AMorPM = 'PM';
            if ((this.Hours-12)<10)
                finalHour = '0'+((parseInt(this.Hours,10))-12);
            else
                finalHour = parseInt(this.Hours,10)-12;
        }
        else {

            this.AMorPM = 'AM';

            if ( this.Hours < 10 ) finalHour = '0' + parseInt( this.Hours, 10 );
            else finalHour = this.Hours;
        }
    }
    else if (TimeMode == 24) {

        if ( this.Hours < 10 ) finalHour = '0' + parseInt( this.Hours, 10 );
        else finalHour = this.Hours;
    }

    return finalHour;
}
Calendar.prototype.getShowHour = getShowHour;

function GetMonthName(IsLong) {

    var Month = MonthName[this.Month];

    if ( IsLong ) return Month;
    else return Month.substr( 0, 3 );
}
Calendar.prototype.GetMonthName = GetMonthName;

//Get number of days in a month
function GetMonDays() {

    var DaysInMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];

    if ( this.IsLeapYear() ) {

        DaysInMonth[1] = 29;
    }
    return DaysInMonth[this.Month];
}
Calendar.prototype.GetMonDays = GetMonDays;

function IsLeapYear() {

    if ( ( this.Year % 4 ) == 0 ) {
        if (
             ( this.Year % 100 == 0 )
          && ( this.Year % 400 != 0 )
        ) {
            return false;
        }
        return true;
    }
    return false;
}
Calendar.prototype.IsLeapYear = IsLeapYear;

function FormatDate( pDate ) {

    switch ( this.Format.toUpperCase() ) {
        case 'DDMMYYYY': {
            return ( pDate + DateSeparator + ( this.Month + 1 ) + DateSeparator + this.Year );
            break;
        }
        case 'DDMMMYYYY': {
            return ( pDate + DateSeparator + this.GetMonthName( false ) + DateSeparator + this.Year );
            break;
        }
        case 'MMDDYYYY': {
            return ( ( this.Month + 1 ) + DateSeparator + pDate + DateSeparator + this.Year );
            break;
        }
        case 'MMMDDYYYY': {
            return ( this.GetMonthName( false ) + DateSeparator + pDate + DateSeparator + this.Year );
            break;
        }
    }
    return;
}

Calendar.prototype.FormatDate = FormatDate;
