Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chris Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Date control script 4

Status
Not open for further replies.

jet042

MIS
Dec 23, 2002
258
US
I wrote this script to automatically set the maximum date available in a select element based on the selected month. While the script works fine, I wonder if it could be made more efficient and if I even came close to good design with it. My programming background is primarily with PHP and VBScript, so I know the concepts but not the subtleties of JavaScript. Please take a look and give me any C&C that you think will help.

JavaScript:
function setDays(frm)
{
 var d = new Date();
 var cur_year = d.getFullYear();
 var cur_month = d.getMonth();
 cur_month = cur_month + 1;

 //Set the max number of days for the selected month
 if (frm.month.value == cur_month)
 {
  max_days = d.getDate();
 }
 else if (frm.month.value == "01" || frm.month.value == "03" || frm.month.value == "05" || frm.month.value == "07" || frm.month.value == "08" || frm.month.value == "10" || frm.month.value == "12")
 {
  max_days = 31;
 }
 else if (frm.month.value == "02")
 {
  //Determine if this is a leap year
  if (cur_year%400 == 0)
  {
   is_leapyear = true;       
  }
  else if (cur_year%100 != 0)
  {
   is_leapyear = false;
  }
  else if (cur_year%4 == 0)
  {
   is_leapyear = true;
  }
  else
  {
   is_leapyear = false;
  }

  if (is_leapyear)
  {
   max_days = 29;
  }
  else
  {
   max_days = 28;
  }
 }
 else
 {
  max_days = 30;
 }
      
 //Write the options to the days select field
 var i = 1;
 var options = "<select name=\"days\">\n";
 for (i=1; i<=max_days; i++)
 {
  if (i < 10)
  {
   val = "0" + i.toString();
  }
  else
  {
   val = i.toString();
  }

  options = options + "<option value=\"" + val + "\"";

  if (i == 1)
  {
   options = options + " selected";
  }

  options = options + ">" + i + "<\/option>\n"; 
 }

 options = options + "<\/select>\n";
		
 //Write the new options to the correct select element      
 document.getElementById('day').innerHTML = options;
}
 
I've not tested this, but based on my understanding it should work. It relies on a nice "quirk" of the JS Date object where setting an invalid day of the month clocks the date object forward to the next month by the number of days you were out.

So, you could set the number of days to "31", check the month, and if different from the original, wind the day back by 1 - then repeat until they are the same. Something like this:

Code:
function setDays(frm) {
	var now = new Date();
	var currentMonth = now.getMonth();
	var currentYear = now.getFullYear();
	var lastDayInMonth = 31;		// Assume 31 days in month

	now.setDate(lastDayInMonth);
	while (now.getMonth() != currentMonth && now.getFullYear() != currentYear) {
		lastDayInMonth--;
		now.setDate(lastDayInMonth);
	}

	// Rest of your code here based on "now" date object...
}

Hope this helps,
Dan

Coedit Limited - Delivering standards compliant, accessible web solutions

[tt]Dan's Page [blue]@[/blue] Code Couch
[/tt]
 
You're using a few common functions that would likely be useful in other applications you'd write in the future (finding max days of the month, adding leading 0s to numbers, etc.), so you should make good use of prototypes and stick them in a js library that you can easily import for future applications, instead of having to rewrite the same functions you use on a regular basis. Here's how I'd rewrite your function using 2 useful prototypes:
Code:
Date.prototype.[!]getMaxDayOfMonth[/!] = function () {
   var thisMonth = this.getMonth(); 
   return ((thisMonth == 1 || thisMonth == 3 || thisMonth == 5 || thisMonth == 7 || thisMonth == 8 || thisMonth == 10 || thisMonth == 12) ? 31 : (thisMonth == 4 || thisMonth == 6 || thisMonth == 9 || thisMonth == 11) ? 30 : (this.getFullYear() % 4) ? 28 : 29);
};

Object.prototype.[!]padString[/!] = function (padChar, padLength, padEnd) {
   var padString = this.toString();
   var padCharString = "";
   for (var padIterator = 0; padIterator < padLength - padString.length; padIterator++) {
      padCharString += padChar;
   }
   return (padEnd) ? padString + padCharString : padCharString + padString;
}

function setDays(frm) {
   var cur_year = new Date().getFullYear();
   var tempDate = new Date(cur_year + "/" + frm.elements["month"].value + "/01");

   //Set the max number of days for the selected month
   max_days = tempDate.[!]getMaxDayOfMonth()[/!];

   //clear the current list
   var dayBox = frm.elements["days"];
   dayBox.options.length = 0;
   
   for (i = 1; i <= max_days; i++) {
      dayBox[i - 1] = new Option(i.[!]padString("0", 2)[/!], i.[!]padString("0", 2)[/!]);
   }
}

-kaht

Lisa, if you don't like your job you don't strike. You just go in every day and do it really half-assed. That's the American way. - Homer Simpson
 
Okay, here's my attempt:
Code:
Date.prototype.getMaxDays = function(){
  return (new Date(this.getFullYear(),this.getMonth(),0)).getDate();
}

function setDays(frm) {
   var max_days = (new Date()).getMaxDays();
   var dayBox = frm.elements["days"];

   dayBox.options.length = 0; // Clear the list
   
   for (var i = 1; i <= max_days; i++) {
      var day = [blue]("0"+i).substring(("0"+i).length-2)[/blue];
      dayBox[i - 1] = new Option(day, day, [green]i==1[/green]);
   }
}
I leave the calculating of leap years up to the operating system because, technically, leap years are not always every four years. The zero padding is in blue and the part that selects the first day is in green.

Adam
 
I like your date prototype adam, that's pretty slick setting the date to 0 for the constructor.

-kaht

Lisa, if you don't like your job you don't strike. You just go in every day and do it really half-assed. That's the American way. - Homer Simpson
 
Thanks guys. I'll give those a shot.

Also, thanks for showing me prototyping. I'd heard of it but I haven't done any OO coding before, so I had no idea how to actually do it.
 
Dan, sorry that I didn't give you feedback too. I tried it, with a little modification, but I keep getting an error when I try it. For some reason, when I change the month I get the error "Object expected" on the line where I call the function. Here is the modified JavaScript

JavaScript:
function setDays(frm) {
  var now = new Date();
  var currentMonth = frm.month.value;
  var currentYear = now.getFullYear();
  var lastDayInMonth = 31;        // Assume 31 days in month

  now.setDate(lastDayInMonth);
  while (now.getMonth() != currentMonth && now.getFullYear() != currentYear) {
    lastDayInMonth--;
    now.setDate(lastDayInMonth);
  }
    
    
  //Write the options to the days select field
  var i = 1;
  var options = "<select name=\"date\">\n";
  for (i=1; i<=lastDayInMonth; i++)
  {
    if (i < 10)
    {
      val = "0" + i.toString();
    }
    else
    {
      val = i.toString();
    }
    options = options + "<option value=\"" + val + "\"";
    if (i == 1)
    {
      options = options + " selected";
    }
    options = options + ">" + i + "<\/option>\n"; 
  }
  options = options + "<\/select>\n";
			
  //Write the new options to the correct select element      
  document.getElementById('day').innerHTML = options;
}

The line that throws the error is in the HTML below, highlighted in red:

HTML:
<form method="post" name="CVR" action="blah.php">
  <p>
  <font style="">For: </font>
  [red]<select name="month" onChange="setDays(this.form)">[/red]
 
Aah - a few logic bugs - but the principal seemed to work OK:

Code:
<html>
<head>
	<script type="text/javascript">

	function setDays(frm) {
		var now = new Date();
		var currentMonth = frm.month.value;
		var currentYear = now.getFullYear();
		var lastDayInMonth = 31;        // Assume 31 days in month

		now.setMonth(currentMonth);
		now.setDate(lastDayInMonth);
		while (now.getMonth() != currentMonth || now.getFullYear() != currentYear) {
			lastDayInMonth--;
			now.setDate(1);
			now.setMonth(currentMonth);
			now.setDate(lastDayInMonth);
		}


		//Write the options to the days select field
		var i = 1;
		var options = "<select name=\"date\">\n";
		for (i=1; i<=lastDayInMonth; i++) {
			if (i < 10) {
				val = "0" + i.toString();
			} else {
				val = i.toString();
			}
			options = options + "<option value=\"" + val + "\"";
			if (i == 1) {
				options = options + " selected";
			}
			options = options + ">" + i + "<\/option>\n";
		}
		options = options + "<\/select>\n";

		//Write the new options to the correct select element
		document.getElementById('day').innerHTML = options;
	}
</script>

</head>


<body
	<form method="post" name="CVR" action="blah.php">
		<select name="month" onChange="setDays(this.form)">
			<option value="00">January</option>
			<option value="01">February</option>
			<option value="02">March</option>
			<option value="03">April</option>
			<option value="04">May</option>
			<option value="05">June</option>
			<option value="06">July</option>
			<option value="07">August</option>
			<option value="08">September</option>
			<option value="09">October</option>
			<option value="10">November</option>
			<option value="11">December</option>
		</select>

		<div id="day">
		</div>
	</form>
</body>
</html>

Hope this helps,
Dan



Coedit Limited - Delivering standards compliant, accessible web solutions

[tt]Dan's Page [blue]@[/blue] Code Couch
[/tt]
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top