Bay Lakes Information Systems creates pages for vacation areas that allow people to learn more about the area and check availability of lodging in the area. They have pages for each city in an area and these pages have listings of most hotels, motels, inns, bed and breakfasts, etc. Each property has a listing of the dates that it has vacancies (along with other information about the property). The company wanted to make it possible for someone to find all properties in the area that have vacancies for a given date. They also wanted to have a page that would mail requests for information to various properties. Each of these pages would have a form with areas for specifying dates. Each also had specific requirements for which dates were possible. To see the final page for the vacancy problem click here and to see the final page for the email click here.
The email form start out to be a simple fix on a page generated by FrontPage. The email was never delivered, so something had to be done. The first step was simply to fix the action section of the page to use the mailto command in HTML. When mailto is the action associated with a form submit, the information in the form is mailed directly to the address that follows the command. So I changed the form line of this page to read as follows.
<FORM name="info" action="mailto:mielkeb@uwgb.edu" METHOD="post" ENCTYPE= "text/plain" onSubmit="return Form_Validator(this)" >
There are two problems with this somewhat simplistic approach. First, there may not be enough information entered in the form to allow the property owner to reply to a request for information, and second, there are parts of the form (the date part) that need updating on a regualar basis.
To make sure that enough information has been provided, a JavaScript function Form_Validator was called. It did simple checks like, if the person wanted to be contacted by email, did they provide a valid email address. Note valid does not mean correct. In all cases the person must provide a first and last name before submitting the form. Some samples of this code are shown here, but the complete code is in the page referenced above .
This function checks to see that the email address doesn't begin or end with a period or "at" sign. It also checks to see there is exactly one "at" sign and they are not consecutive. This avoids someone trying to type @. to get around the email address test.
function validEMail( val) {
var mailStr;
var i;
var atFound;
var dotFound;
dotFound = false;
atFound = false;
// check first character
mailStr = val.charAt(0);
if ((mailStr == '.') || (mailStr == '@'))
return false;
// check last character
mailStr = val.charAt(val.length - 1);
if ((mailStr == '.') || (mailStr == '@'))
return false;
// check characters between first and last
for (i = 1;i<val.length - 1;i++)
{
mailStr = val.charAt(i);
if (mailStr == '@')
{
if (atFound) //|| (dotFound))
return false;
atFound = true;
if (val.charAt(i+1) == '.')
return false;
} // end if mailStr == '@'
if (mailStr == '.')
{
if (val.charAt(i+1)== '@')
return false;
dotFound = true;
} // end if mailStr == '.'
} // end for loop
if ((!(atFound)) || (!(dotFound)))
return false;
return true;
}
This function and many others are used in many different pages, so are stored in a script file utilityfunctions.js. The form validator function checks to see the user has filled in enought information to allow the property owner to reply. Notice the form is passed as a parameter to this function. This allows the function to be used for more than one similar form. In this case it was not necessary, but in others it will save lots of work.
function Form_Validator(theForm)
{
if (theForm.Month.selectedIndex < 0)
{
alert("Please select one of the \"Month\" options.");
theForm.Month.focus();
return (false);
}
if (theForm.Day.selectedIndex < 0)
{
alert("Please select one of the \"Day\" options.");
theForm.Day.focus();
return (false);
}
// Lots of other tests to make sure proper fields have required information.
if(theForm.Contact.selectedIndex==2 &&
(!validZip( theForm.zip.value)||theForm.street1.value=="" || theForm.city.value==""))
{
alert("You have asked to be contacted by mail,"+"
but have not given a mail address. Please fill this in.");
if(theForm.street1.value=="")
theForm.street1.focus();
else if (theForm.city.value=="")
theForm.city.focus();
else
theForm.zip.focus();
return (false);
}
return (true);
}
You also want to avoid having the user send dates that aren't correct, so a second script is used to initialize the date in the date choosing section and to change numbers of days in the month and disallow the selection of dates that have already passed.The initialization script gets the date from the users machine and sets the date selector to that day. When the user changes any of the date components, the new result is checked against the current date and any dates that precede the current date are reset to the current date.
The functions used here are also used for many of the initialization processes so are placed in the utility package. The one interesting aspect of this script is that the init function does not set up the dates directly. Originally this was the case, but Netscape could not loat the utilities package before the functions were used so the users got a message that the page was not found. To avoid this I called the setDates function from the init function using the setTimeout function to cause a one second delay.
function setDates()
{
month = getMonth();
year = getCurYear();
day=getDay();
var opt = document.info;
opt.Year.options[0].text = year;
opt.Year.options[1].text = year+1;
opt.Year.options[2].text = year + 2;
opt.Year.selectedIndex = 0;
opt.Day.selectedIndex=day-1;
opt.Month.selectedIndex=month;
setFebruary(year);
setDayOptions(month,opt.Day);
}
function init()
{
setTimeout("setDates()",1000);
}
Each of the form selections for date calls on the setYearMany function which is used to set the date and year for forms with more than a one year range. Here is the select for Month.
<SELECT name=Month size=1 onChange="setYearMany(this,info.Day,info.Year)">
<OPTION selected value=January>January</OPTION>
<OPTION value=February>February</OPTION>
<OPTION value=March>March</OPTION>
<OPTION value=April>April</OPTION>
<OPTION value=May>May</OPTION>
<OPTION value=June>June</OPTION>
<OPTION value=July>July</OPTION>
<OPTION value=August>August</OPTION>
<OPTION value=September>September</OPTION>
<OPTION value=October>October</OPTION>
<OPTION value=November>November</OPTION>
<OPTION value=December>December</OPTION>
</SELECT>
The actual setYearMany function checks the year, month and date to make sure that date is not passed and makes sure only the correct number of days are displayed in the date combobox.
var lastDay = new Array(31,28,31,30,31,30,31,31,30,31,30,31);
//**** Set the days in the option boxes to correspond to the correct ones
//**** For the month
function setDayOptions(month,opt)
{
var i;
for(i=0;i<lastDay[month];i++)
opt.options[i].text = i+1;
for(i=lastDay[month];i<31;i++)
opt.options[i].text = "";
}
function setFebruary(year)
{
if(year%4==0 && year%100!=0)//works until 2400-Y2.4K is another problem.
lastDay[1]=29;
else
lastDay[1]=28;
}
function checkLastDay(month,day,year)
{
if(year%4==0 && year%100!=0)//works until 2400-Y2.4K is another problem.
lastDay[1]=29;
else
lastDay[1]=28;
return day<= lastDay[month];
}
// This variation on the last function is used if the page has more than two years
// listed in the year options.
function setYearMany(theMonth,theDate,theYear)
{
var localDay = eval(theDate.selectedIndex+1),
localMonth =theMonth.selectedIndex;
if(theYear.selectedIndex==0 &&(localMonth<month || (localMonth==month && localDay<day)))
theYear.selectedIndex = 1;
// If it is a leep year don't change the end of Feb since if you
//are in February, you will want to keep day 29 no matter what day the
//person selects
checkLastDay(1,1,theYear.options[theYear.selectedIndex].text);
setDayOptions(theMonth.selectedIndex,theDate);
}
You will see the asp that corresponds to other part of this project later .