reptile7's JavaScript blog
Thursday, May 07, 2015
 
Months, Inputs, Dates, and Years
Blog Entry #351

Welcome back to our ongoing analysis of the Java Goodies Today Calendar script - I think we'll be able to finish this guy off in today's post, let's give it a shot, shall we?

Month frontiers

At this writing, we are about two-thirds of the way through the FillCalendar( ) function. Picking up from where we left off last time, the FindMonthStartDay( ) action is followed by a call to a FindNumDaysInMonth( ) function

NumDaysInMonth = FindNumDaysInMonth(Year, Midx);

that determines the number of days in the Months[Month] Year month; the days number is stored in the NumDaysInMonth variable.

function FindNumDaysInMonth(Year, Month) { if (Month == 1) { if (IsLeapYear(Year)) return 29; else return 28; } else { if (Month > 6) Month++; if (Month / 2 == Math.round(Month / 2)) return 31; } return 30; }

• If Month is 1 - i.e., if it's February - then we run Year through the IsLeapYear( ) function: if Year is a leap year we send 29 back to FillCalendar( ) and if it isn't we return 28.
• Regarding the if (Month > 6) Month++; if (Month / 2 == Math.round(Month / 2)) return 31; code for flagging 31-day months, note that the getMonth( ) returns for January (0), March (2), May (4), and July (6) are even but switch to odd for August (7), October (9), and December (11).
• A concluding return 30; statement handles April, June, September, and November.

The FindNumDaysInMonth( ) function strikes me as a solution in search of a problem; I myself would more simply get the NumDaysInMonth from a pre-specified array of days numbers as follows:

var NumDaysArray = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
if ((Year % 4) || (! (Year % 100) && (Year % 400))) NumDaysArray[1] = 28; // For non-leap years
NumDaysInMonth = NumDaysArray[Midx];


Date number distribution

We are at long last ready to load the date numbers for the myDate month into all of those size="2" calform inputs, and we do that via the for loop below, which concludes the FillCalendar( ) function.

for (i = 6; i < 43; i++) { t = i - 5 - MonthStartDay; if (t >= 1 && t <= NumDaysInMonth) document.calform.elements[i].value = t; else document.calform.elements[i].value = ""; }

• We determined the MonthStartDay in the previous post, i serves as an elements[i] index for the size="2" inputs, and t holds the date numbers themselves; you wouldn't think that there would be a relationship between these values but David came up with one (t = i - 5 - MonthStartDay;) so there you have it.
• The if...else statement sets the elements[i].values to either t or an empty string, as appropriate. (For months that do not start on a Sunday, pre-MonthStartDay ts are 0 or below and therefore the else clause is operative.)

Reeling through the years

Clicking the and buttons that flank the field in the table1 table's first row

.buttonTd { background-color: black; text-align: center; }
.headingTd { background-color: #aaaaaa; text-align: center; }

<table id="table1" cellpadding="" cellspacing="">
<tr>
<td class="buttonTd"><input type="button" value="<<" onclick="IncDecYear(-1);"></td>
<td class="headingTd" colspan="5"><input type="text" size="4" value=""></td>
<td class="buttonTd"><input type="button" value=">>" onclick="IncDecYear(1);"></td>
</tr>


calls an IncDecYear( ) function and respectively passes -1 and 1 thereto.

function IncDecYear(val) { var valNum = parseInt(val); var valNum2 = parseInt(document.calform.elements[1].value); document.calform.elements[1].value = valNum2 + valNum; FillCalendar( ); }

The IncDecYear( ) argument and the elements[1].value year are parseInt( )ed, which is unnecessary for the former (val's a number) and necessary for the latter (the field value's a string), and then added to give either the previous year or the following year. The elements[1].value is set to the new year and FillCalendar( ) is re-called so as to generate a new Months[Midx] Year calendar.

Month movement

Clicking the and buttons that flank the field in the table1 table's second row

<tr>
<td class="buttonTd"><input type="button" value="<<" onclick="IncDecMonth(-1);"></td>
<td class="headingTd" colspan="5"><input type="text" size="9" value=""></td>
<td class="buttonTd"><input type="button" value=">>" onclick="IncDecMonth(1);"></td>
</tr>


calls an IncDecMonth( ) function and respectively passes -1 and 1 thereto.

function IncDecMonth(val) { var valNum = parseInt(val); var Midx = DetermineMonthIdx( ); Midx += valNum; if (Midx > 11) Midx = 0; if (Midx < 0) Midx = 11; document.calform.elements[4].value = PadSpaces(Months[Midx]); FillCalendar( ); }

The IncDecMonth( ) function gets the getMonth( ) index for the elements[4].value month via the DetermineMonthIdx( ) function, assigns the index to a Midx variable, and adds its argument to Midx so that Midx now points to either the previous month or the following month. If Midx goes above 11 or below 0, it is brought back onto the 0-11 getMonth( ) scale via an if (Midx > 11) Midx = 0; or if (Midx < 0) Midx = 11; conditional, respectively. Midx is then plugged into the Months[ ] array to get its corresponding month name, to which 0-3 spaces are prepended via the PadSpaces( ) function. The elements[4].value is set to the PadSpaces( ) return and FillCalendar( ) is re-called so as to generate a new Months[Midx] Year calendar.

• The val argument can again be used as-is and does not need to be integerized.
• The DetermineMonthIdx( ) call is unnecessary if we initially get the elements[4].value month index via the global var Month = myDate.getMonth( ); statement and replace the post-var Midx = DetermineMonthIdx( ); Midx references with Month references.
• The PadSpaces( ) call is unnecessary if we text-align:center; the elements[4].value.

function IncDecMonth(val) { Month += val; if (Month > 11) Month = 0; if (Month < 0) Month = 11; document.calform.elements[4].value = Months[Month]; FillCalendar( ); }

Demo

There's no burning reason for me to give you a demo for the Today Calendar script as Joe's demo works fine, the script's bloated code notwithstanding; however, I like to end with a demo, so I'm going to give you one that incorporates my various code changes anyway.

S M T W T F S

I'll be working at my other blog for a while.


Powered by Blogger

Actually, reptile7's JavaScript blog is powered by Café La Llave. ;-)