﻿//Global variables
var winCal;
var aaa;
var dtToday = new Date(); //Today Date & Time
var Cal; // Calander Variable
var docCal;
var MonthName = ["","فروردين","ارديبهشت","خرداد","تير","مرداد","شهریور","مهر","آبان","آذر","دی","بهمن","اسفند"];
var WeekDayName = ["شنبه","يکشنبه","دوشنبه","سه‌شنبه","چهارشنبه","پنجشنبه","جمعه"];//PERSIAN_WEEKDAYS

//Configurable parameters
var cnTop="200";//top coordinate of calendar window.
var cnLeft="500";//left coordinate of calendar window
var WindowTitle ="DateTime Picker";//Date Time Picker title.
var WeekChar=10;//number of character for week day. if 2 then Mo,Tu,We. if 3 then Mon,Tue,Wed.
var CellWidth=20;//Width of day cell.
var DateSeparator="/";//Date Separator, you can change it to "/" if you want.

var ShowLongMonth=true;//Show long month name in Calendar header. example: "January".
var ShowMonthYear=true;//Show Month and Year in Calendar header.
var MonthYearColor="#C6A83E";//Font Color of Month and Year in Calendar header.
var WeekHeadColor="#B2BFE2";//Background Color in Week header.
var FridayColor="#FADDA6";//Background color of Sunday.
var WeekDayColor="white";//Background color of weekdays.
var FontColor="blue";//color of font in Calendar day cell.
var TodayColor="#D9ECFF";//Background color of today.
var SelDateColor="#FFFF99";//Backgrond color of selected date in textbox.
var YrSelColor="#1D5F81";//color of font of Year selector.
var YrSelColor1="#ff0000";//color of font of Year selector.
var ThemeBg="";//Background image of Calendar window.
//end Configurable parameters

var GREGORIAN_EPOCH = 1721425.5;
var PERSIAN_EPOCH = 1948320.5;
//end Global variable

//Base Functions
/*  MOD  --  Modulus function which works for non-integers.  */
function mod(a, b)
{
    return a - (b * Math.floor(a / b));
}

//  AMOD  --  Modulus function which returns numerator if modulus is zero
function amod(a, b)
{
    return mod(a - 1, b) + 1;
}

function getFirstDayMonth(pYear,pMonth)
{
	return jd_to_gregorian(persian_to_jd(pYear,pMonth,1));
}
//End of Base Functions

//  GREGORIAN_TO_JD  --  Determine Julian day number from Gregorian calendar date
function gregorian_to_jd(year, month, day)
{
    return (GREGORIAN_EPOCH - 1) +
           (365 * (year - 1)) +
           Math.floor((year - 1) / 4) +
           (-Math.floor((year - 1) / 100)) +
           Math.floor((year - 1) / 400) +
           Math.floor((((367 * month) - 362) / 12) +
           ((month <= 2) ? 0 :(leap_gregorian(year) ? -1 : -2)) + day);
}

//  JD_TO_GREGORIAN  --  Calculate Gregorian calendar date from Julian day
function jd_to_gregorian(jd) {
    var wjd, depoch, quadricent, dqc, cent, dcent, quad, dquad,
        yindex, dyindex, year, yearday, leapadj;

    wjd = Math.floor(jd - 0.5) + 0.5;
    depoch = wjd - GREGORIAN_EPOCH;
    quadricent = Math.floor(depoch / 146097);
    dqc = mod(depoch, 146097);
    cent = Math.floor(dqc / 36524);
    dcent = mod(dqc, 36524);
    quad = Math.floor(dcent / 1461);
    dquad = mod(dcent, 1461);
    yindex = Math.floor(dquad / 365);
    year = (quadricent * 400) + (cent * 100) + (quad * 4) + yindex;
    if (!((cent == 4) || (yindex == 4))) {
        year++;
    }
    yearday = wjd - gregorian_to_jd(year, 1, 1);
    leapadj = ((wjd < gregorian_to_jd(year, 3, 1)) ? 0 : (leap_gregorian(year) ? 1 : 2)
              );
    month = Math.floor((((yearday + leapadj) * 12) + 373) / 367);
    day = (wjd - gregorian_to_jd(year, month, 1)) + 1;

    return new Array(year, month, day);
}

//  LEAP_GREGORIAN  --  Is a given year in the Gregorian calendar a leap year ?
function leap_gregorian(year)
{
    return ((year % 4) == 0) &&
            (!(((year % 100) == 0) && ((year % 400) != 0)));
}

//  LEAP_PERSIAN  --  Is a given year a leap year in the Persian calendar ?
function leap_persian(year)
{
    return ((((((year - ((year > 0) ? 474 : 473)) % 2820) + 474) + 38) * 682) % 2816) < 682;
}

//  PERSIAN_TO_JD  --  Determine Julian day from Persian date

function persian_to_jd(year, month, day)
{
    var epbase, epyear;

    epbase = year - ((year >= 0) ? 474 : 473);
    epyear = 474 + mod(epbase, 2820);

    return day +
            ((month <= 7) ?
                ((month - 1) * 31) :
                (((month - 1) * 30) + 6)
            ) +
            Math.floor(((epyear * 682) - 110) / 2816) +
            (epyear - 1) * 365 +
            Math.floor(epbase / 2820) * 1029983 +
            (PERSIAN_EPOCH - 1);
}

//  JD_TO_PERSIAN  --  Calculate Persian date from Julian day
function jd_to_persian(jd)
{
    var year, month, day, depoch, cycle, cyear, ycycle,
        aux1, aux2, yday;


    jd = Math.floor(jd) + 0.5;

    depoch = jd - persian_to_jd(475, 1, 1);
    cycle = Math.floor(depoch / 1029983);
    cyear = mod(depoch, 1029983);
    if (cyear == 1029982) {
        ycycle = 2820;
    } else {
        aux1 = Math.floor(cyear / 366);
        aux2 = mod(cyear, 366);
        ycycle = Math.floor(((2134 * aux1) + (2816 * aux2) + 2815) / 1028522) +
                    aux1 + 1;
    }
    year = ycycle + (2820 * cycle) + 474;
    if (year <= 0) {
        year--;
    }
    yday = (jd - persian_to_jd(year, 1, 1)) + 1;
    month = (yday <= 186) ? Math.ceil(yday / 31) : Math.ceil((yday - 6) / 30);
    day = (jd - persian_to_jd(year, month, 1)) + 1;
    return new Array(year, month, day);
}

//pCtrl is the name of the object that persian date time must be set/get on it
//gCtrl is the name of the object that gregorian date time must be set/get on it
function newCalendar(pCtrl,gCtrl)
{
    ////////////////////////////////////////////////TOP//////////////////////////////////////    
    var cnTop = 100;
    var cnLeft = 100;

    if(window.event)
    {
    cnTop=window.event.clientY+100;
    if((window.screen.height-window.event.clientY)<300)
        cnTop=window.event.clientY-140;
    ////////////////////////////////////////////////LEFT//////////////////////////////////////   
    cnLeft=window.event.clientX-300;
    if(window.event.clientX<300)
    {
        cnLeft=window.event.clientX;
        cnTop+=20;
    }
    }
    //////////////////////////////////////////////////////////////////////////////////////////

	Cal = new Calendar(dtToday);
	
	if (pCtrl!=null)
	{
		Cal.Ctrl=pCtrl;
	}

	if (gCtrl!=null)
	{
		Cal.gCtrl=gCtrl;
	}

	expDateTime = document.getElementById(pCtrl).value;
	exgDateTime = document.getElementById(gCtrl).value;

	if(expDateTime != "")
	{
		parseDate(expDateTime,'p');
	}else
	if(exgDateTime != "")
	{
		parseDate(exgDateTime,'g');
	}
//	document.getElementById('divID').style.top=cnTop;
//	document.getElementById('divID').style.left=cnLeft;
//	winCal=window.open("","DateTimePicker","height=200,width=300,status=yes,toolbar=no,menubar=no,location=no,top="+cnTop+",left="+cnLeft);
//    docCal = winCal.document;
	RenderCal();
}

function showPersianDate(gCtrl,pCtrl)
{
	exgDateTime = document.getElementById(gCtrl).value;

	if(exgDateTime != "")
	{
		Cal = new Calendar(dtToday);	
		parseDate(exgDateTime,'g');
		document.getElementById(pCtrl).value=Cal.FormatDate(Cal.Date);
	}
}

function parseDate(exDateTime,calType)
{
	if (exDateTime!="")//Parse Date String
	{
		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;

		Sp1 = exDateTime.indexOf(DateSeparator,0);
		Sp2 = exDateTime.indexOf(DateSeparator,(parseInt(Sp1)+1));
		
		strYear=exDateTime.substring(Sp2+1,Sp2+5);
		strMonth = exDateTime.substring(Sp1+1,Sp2);
		strDate = exDateTime.substring(0,Sp1);
		
		intMonth = parseInt(strMonth,10);

		switch(calType)
		{
			case 'p' :
				if ((parseInt(intMonth,10)>=0) && (parseInt(intMonth,10)<12))
					Cal.Month=intMonth;

				//parse year
				strYear=exDateTime.substring(Sp2+1,Sp2+5);
				YearPattern = /^\d{4}$/;
				if (YearPattern.test(strYear))
					Cal.Year=parseInt(strYear,10);

				//parse Date
				if ((parseInt(strDate,10)<=Cal.GetMonDays()) && (parseInt(strDate,10)>=1))
					Cal.Date=strDate;
				
				Cal.RefreshCal(parseInt(Cal.Year),parseInt(Cal.Month),parseInt(Cal.Date),'g');
				break;
			case 'g' :
				if ((parseInt(intMonth,10)>=0) && (parseInt(intMonth,10)<12))
					Cal.gMonth=intMonth;

				//parse year
				strYear=exDateTime.substring(Sp2+1,Sp2+5);
				YearPattern = /^\d{4}$/;
				if (YearPattern.test(strYear))
					Cal.gYear=parseInt(strYear,10);

				//parse Date
				if ((parseInt(strDate,10)<=Cal.GetMonDays()) && (parseInt(strDate,10)>=1))
					Cal.gDate=strDate;
			
				Cal.RefreshCal(parseInt(Cal.gYear),parseInt(Cal.gMonth),parseInt(Cal.gDate),'p');
				break;			
		}
	}
}

function RenderCal()
{
	var vCalHeader;
	var vCalData;
	var i;
	var j;
	var SelectStr;
	var vDayCount=0;
	var vFirstDay;
//	docCal.open();
//	docCal.writeln("<html dir='rtl'><head><title>"+WindowTitle+"</title>");
//	aaa.innerHTML="<script>var winMain=window.opener;</script>";
	aaa.innerHTML="<form name='Calendar'>";

	vCalHeader="<table style=\"background-color:#EBEBEB\" border=1 cellpadding=0 cellspacing=0 width='100%' align=\"center\" valign=\"top\">\n";
	//Month Selector
	vCalHeader+="<tr>\n<td colspan='7'><table border=0 width='100%' cellpadding=0 cellspacing=0><tr><td align='right'>\n";
	vCalHeader+="<select name=\"MonthSelector\" onChange=\"javascript:Cal.SwitchMth(this.selectedIndex+1);RenderCal();\" class='cfont'>\n";
	for (i=1;i<=12;i++)
	{
		if (i==Cal.Month)
			SelectStr="Selected";
		else
			SelectStr="";	
		vCalHeader+="<option "+SelectStr+" value >"+MonthName[i]+"\n";
	}
	vCalHeader+="</select></td>";
	//Year selector
	vCalHeader+="\n<td align='left'><a href=\"javascript:Cal.DecYear();RenderCal()\" class=\"cfont\"><font color=\""+YrSelColor+"\"><قبلي</font></a>"+
				"<font face=\"Tahoma\" color=\""+YrSelColor1+"\" size=3 class=\"cfont\"><b> "+Cal.Year+" </b></font><a href=\"javascript:Cal.IncYear();RenderCal()\" class=\"cfont\">"+
				"<font color=\""+YrSelColor+"\">بعدي></font></a></td></tr></table></td>\n";
	vCalHeader+="</tr>";
	//Calendar header shows Month and Year
	if (ShowMonthYear)
		vCalHeader+="<tr><td colspan='7'><font face='Tahoma' size='2' align='center' color='"+MonthYearColor+"'><b>"+Cal.GetMonthName(ShowLongMonth)+" "+Cal.Year+"</b></font></td></tr>\n";
	//Week day header
	vCalHeader+="<tr bgcolor="+WeekHeadColor+">";
	for (i=0;i<7;i++)
	{
		vCalHeader+="<td align='center'><font face='Tahoma' size='1'>"+WeekDayName[i].substr(0,WeekChar)+"</font></td>";
	}
	vCalHeader+="</tr>";	
//	aaa.innerHTML+=vCalHeader;
	
	//Calendar detail
	pCalDate = getFirstDayMonth(Cal.Year,Cal.Month);
	vFisrtDayMonth = new Date(pCalDate[0],(pCalDate[1]-1),pCalDate[2]);
	vFirstDay = vFisrtDayMonth.getDay()+1;
	vFirstDay = (vFirstDay == 7) ? 0 : vFirstDay;
	vCalData="<tr>";
	for (i=0;i<vFirstDay;i++)
	{
		vCalData=vCalData+GenCell();
		vDayCount=vDayCount+1;
	}

	for (j=1;j<=Cal.GetMonDays();j++)
	{
		var strCell;
		vDayCount=vDayCount+1;
		if ((j==pCalDate[0])&&(Cal.Month==pCalDate[1]-1)&&(Cal.Year==pCalDate[2]))
		{
			strCell=GenCell(j,true,TodayColor);//Highlight today's date
		}
		else
		{
			if (j==Cal.Date)
			{
				strCell=GenCell(j,true,SelDateColor);
			}
			else
			{
				if ((vDayCount)%7==0)
				{
					strCell=GenCell(j,false,FridayColor);
				}
				else
					strCell=GenCell(j,null,WeekDayColor);
			}		
		}						
		vCalData=vCalData+strCell;

		if((vDayCount%7==0)&&(j<Cal.GetMonDays()))
		{
			vCalData=vCalData+"</tr>\n<tr>";
		}
	}
	vCalData=vCalHeader+vCalData;
	
	vCalHeader+="\n</table>";
	vCalHeader+="</form>";
	aaa.innerHTML+=vCalData;
	aaa.style.display="";
//	docCal.close();
}

function GenCell(pValue,pHighLight,pColor)//Generate table cell with value
{
	var PValue;
	var PCellStr;
	var vColor;
	var vHLstr1;//HighLight string
	var vHlstr2;
	var vGValue;
	
	if (pValue==null)
		PValue="";
	else
		PValue=pValue;
	
	if (pColor!=null)
		vColor="bgcolor=\""+pColor+"\"";
	else
		vColor="";
		
	if ((pHighLight!=null)&&(pHighLight))
		{vHLstr1="color='red'><b>";vHLstr2="</b>";}
	else
		{vHLstr1=">";vHLstr2="";}	
	
	vGValue="document.getElementById('"+Cal.gCtrl+"').value='"+Cal.GFormatDate(PValue)+"'";
	PCellStr="<td "+vColor+" width="+CellWidth+" align='center'><font face='Tahoma' size='2'"+
				vHLstr1+"<a href=\"javascript:void(0)\" onclick=\"document.getElementById('"+Cal.Ctrl+"').value='"+
				Cal.FormatDate(PValue)+"';"+vGValue+";aaa.style.display=\'none\';\">"+PValue+"</a>"+vHLstr2+"</font></td>";
	return PCellStr;
}

function Calendar(pDate,pCtrl,gCtrl)
{
	//Properties
	this.gDate = pDate.getDate();//selected date
	this.gMonth = pDate.getMonth();//selected month number
	this.gYear = pDate.getFullYear();//selected year in 4 digits

	this.Date;
	this.Month;
	this.Year;

	this.RefreshCal(this.gYear,this.gMonth+1,this.gDate,'p');
	
	this.MyWindow = winCal;
	this.Ctrl = pCtrl;
	this.gCtrl = gCtrl;
	this.Format = "ddMMyyyy";
	this.Separator = DateSeparator;
	this.ShowTime = false;
}

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 GetMonthName(IsLong)
{
	var Month=MonthName[this.Month];
	if (IsLong)
		return Month;
	else
		return Month.substr(0,3);
}
Calendar.prototype.GetMonthName=GetMonthName;

function GetMonDays()//Get number of days in a month
{
	var DaysInMonth=[0,31, 31, 31, 31, 31, 31, 30, 30, 30, 30, 30, 29];
	if (this.IsLeapYear())
	{
		DaysInMonth[12]=30;
	}	
	return DaysInMonth[this.Month];	
}
Calendar.prototype.GetMonDays=GetMonDays;

function IsLeapYear()
{
	return leap_persian(this.Year);
}
Calendar.prototype.IsLeapYear=IsLeapYear;

function FormatDate(pDate)
{	
    // new whith 0
    var day,month,year;  
    day=pDate.toString();  
    month=this.Month.toString();
    year=this.Year.toString();
    
    if(day.length==1) day="0"+day;
    if(month.length==1) month="0"+month;
    
	if (this.Format.toUpperCase()=="DDMMYYYY")
		return (day + DateSeparator + month + DateSeparator + year);
		
	//old without 0
	//if (this.Format.toUpperCase()=="DDMMYYYY") 
	//	return (pDate+DateSeparator+(this.Month)+DateSeparator+this.Year);
}
Calendar.prototype.FormatDate=FormatDate;

function GFormatDate(pDate)
{
    // new whith 0
    this.RefreshCal(this.Year,this.Month,pDate,'g');
        
    var day,month,year;  
    day=this.gDate.toString();  
    month=this.gMonth.toString();
    year=this.gYear.toString();
    
    if(day.length==1) day="0"+day;
    if(month.length==1) month="0"+month;
    if(year.length==3) year="2"+year;
    
	if (this.Format.toUpperCase()=="DDMMYYYY")
		return (day + DateSeparator + month + DateSeparator + year);

    //old without 0
	//this.RefreshCal(this.Year,this.Month,pDate,'g');
	//if (this.Format.toUpperCase()=="DDMMYYYY")
	//	return (this.gDate+DateSeparator+(this.gMonth)+DateSeparator+this.gYear);
}
Calendar.prototype.GFormatDate=GFormatDate;

function RefreshCal(Year,Month,Day,UpType)
{
	var tDate;
	switch(UpType){
		case 'p' :
			tDate = this.GregorianToPersian(Year,(Month),Day);
			this.Year = tDate[0];
			this.Month = tDate[1];
			this.Date = tDate[2];
			break;
		case 'g' :
			tDate = this.PersianToGregorian(Year,Month,Day);
			this.gYear = tDate[0];
			this.gMonth = tDate[1];
			this.gDate = tDate[2];
			break;
	}
}
Calendar.prototype.RefreshCal=RefreshCal;

function GregorianToPersian(Year,Month,Day)
{
	return jd_to_persian(gregorian_to_jd(Year,Month,Day));
}
Calendar.prototype.GregorianToPersian=GregorianToPersian;

function PersianToGregorian(Year,Month,Day)
{
	return jd_to_gregorian(persian_to_jd(Year,Month,Day));
}
Calendar.prototype.PersianToGregorian=PersianToGregorian;
