';
}
*/
}
gPersist = aPersist;
var popupNode = document.getElementById("detailPopup");
popupNode.innerHTML = lInnerHTML;
popupNode.style.top = (gEventClientY) + "px";
popupNode.style.left = (gEventClientX) + "px";
}
/**************************************************************************************
* Function : detailRolloverPopupClose() *
* Description : Closes (previously invoked by onmouseover/onclick event) popup. *
* Parameters : None. *
* ISD Feature : "Detail Rollover Popup" *
* Authors : Samson Wong *
**************************************************************************************/
function detailRolloverPopupClose() {
// clear any previous pending popup invocation
if (gPopupTimer != null)
{
clearTimeout(gPopupTimer);
gPopupTimer = null;
}
if (gPersist != true) {
// document.getElementById("detailPopup").innerHTML = "";
gPopupTimer = setTimeout('document.getElementById("detailPopup").innerHTML = "";', 250);
}
}
/**************************************************************************************
* Function : SaveMousePosition() *
* Description : Saves the mouse position for use by detailRolloverPopup *
* Parameters : event, reference to mouseover/onclick event *
**************************************************************************************/
var gEventClientX = 0;
var gEventClientY = 0;
// save latest coordinates (based on last mouse movement) instead of using those saved
// an AJAX-popup-delay (default 500ms) earlier
var IE = document.all?true:false;
if (!IE) document.captureEvents(Event.MOUSEMOVE)
document.onmousemove = SaveMousePosition;
function SaveMousePosition(evt)
{
gEventClientX = mouseX(evt);
gEventClientY = mouseY(evt);
}
function mouseX(evt) {
evt = evt || window.event;
if (evt.pageX) return evt.pageX;
else if (evt.clientX)
return evt.clientX + (document.documentElement.scrollLeft ?
document.documentElement.scrollLeft :
document.body.scrollLeft);
else return null;
}
function mouseY(evt) {
evt = evt || window.event;
if (evt.pageY) return evt.pageY;
else if (evt.clientY)
return evt.clientY + (document.documentElement.scrollTop ?
document.documentElement.scrollTop :
document.body.scrollTop);
else return null;
}
/**************************************************************************************
* Description : Global variables used by "Date Formatter" feature. *
* ISD Feature : "Date Formatter" *
* Author : Samson Wong *
**************************************************************************************/
var gDateSeparator1 = "/"; // single character separator of first two components of date string ("m"s, "d"s, and "y"s)
var gDateSeparator2 = "/"; // single character separator of last two components of date string ("m"s, "d"s, and "y"s)
var gPreviousDatePattern = ""; // last recorded date pattern
var gDatePatternArray= null; // split portions of date pattern
var gDateMonthPosition = 1; // position of month portion within date pattern
var gDateDayPosition = 2; // position of day portion within date pattern
var gDateYearPosition = 3; // position of year portion within date pattern
var gDateFormatterState = "0" // current date formatter state machine state
var gDateStringEntered = ""; // last value in date textbox
var gCurrentValidDateArray = new Array(3);
// Check browser version
var isNav4 = false, isNav5 = false, isIE4 = false
if(navigator.appName == "Netscape")
{
if (navigator.appVersion < "5")
{
isNav4 = true;
isNav5 = false;
}
else
if (navigator.appVersion > "4")
{
isNav4 = false;
isNav5 = true;
}
}
else
{
isIE4 = true;
}
/**************************************************************************************
* Function : initializeDateFormatter() *
* Author : Samson Wong *
**************************************************************************************/
function initializeDateFormatter(aInputTextbox) {
gDateSeparator1 = "/";
gDateSeparator2 = "/";
gPreviousDatePattern = "";
gDatePatternArray = null;
gDateMonthPosition = 1;
gDateDayPosition = 2;
gDateYearPosition = 3;
gDateFormatterState = "0";
gCurrentValidDateString = new Array(3);
gDateStringEntered = "";
}
function myAlert(aAlertString) {
var debug = false;
if (debug) {
alert(aAlertString);
}
}
/**************************************************************************************
* Function : toggleEnableDisableDateFormatter() *
* Description : Enables/disables Date Formatter. On onfocus change (tabbing or *
* onclick), pasting, backspacing/deleting, or left/right *
* arrowing, date formatter is enabled if the date textbox is *
* empty; disabled, otherwise (in which case the user is allowed *
* to enter whatever he/she wishes, and date validation is only *
* performed upon onblur). *
* Parameters : aInputTextbox, reference to the html textbox into which the user *
* enters the date string *
* aDatePattern, date pattern (containing some combination of "m"s, *
* "s"s, "y"s, and "separators" to which the user-inputted date *
* string is to be formated *
* ISD Feature : "Date Formatter" *
* Author : Samson Wong *
**************************************************************************************/
function toggleEnableDisableDateFormatter(aInputTextbox, aDatePattern) {
aInputTextbox.style.background = "#ffffff";
initializeDateFormatter(aInputTextbox);
// myAlert("onfocus:gPreviousDatePattern(" + gPreviousDatePattern + "), aDatePattern(" + aDatePattern + ")");
// re-parse date pattern only if different from that in previous call
if (gPreviousDatePattern != aDatePattern) {
// parse date pattern
if (!parseDatePattern(aInputTextbox, aDatePattern)) {
goToNextState("DisableDateFormatter");
return false;
}
}
if (aInputTextbox.value != "") {
// myAlert("toggleEnableDisableDateFormatter(disabling:" + aInputTextbox.value + ")");
goToNextState("DisableDateFormatter");
}
// else {
// myAlert("toggleEnableDisableDateFormatter(enabling:" + aInputTextbox.value + ")");
// }
}
/**************************************************************************************
* Function : DateFormat() *
* Description : This event handler accepts user-inputted date string, and *
* auto-formats it according to the required date pattern. *
* Parameters : aInputTextbox, reference to the html textbox into which the user *
* enters the date string *
* aDateStringEntered, current contents (value) in the input textbox *
* aEvent, reference to event (onkeyup) causing this event handler to *
* be called *
* aDatePattern, date pattern (containing some combination of "m"s, *
* "s"s, "y"s, and "separators" to which the user-inputted date *
* string is to be formated *
* Returns: : false, if an invalid date digit is entered (it is automatically *
* cleared for the user) *
* true, if valid date digit is entered *
* ISD Feature : "Date Formatter" *
* Author : Samson Wong *
**************************************************************************************/
function DateFormat(aInputTextbox, aDateStringEntered, aEvent, aDatePattern) {
// if (justDoIt == true) {
var whichCode;
if (typeof(aEvent) == "number") {
whichCode = aEvent;
}
else {
whichCode = (window.Event) ? aEvent.which : aEvent.keyCode;
}
// if backspace, delete, left arrow, or right arrow...
/*
if ( (whichCode == 8) || (whichCode == 46) || (whichCode == 37) || (whichCode == 39) ) {
if (!toggleEnableDisableDateFormatter(aInputTextbox, aDatePattern)) {
return false;
}
}
*/
// if Ctrl-v...
/*
else if (whichCode == 86) {
// allow "pasting" of "copied" text into date field, but disable date formatter because
// user could have pasted anything (date validation will still be performed onblur)
goToNextState("DisableDateFormatter");
}
*/
// if "up arrow" or "plus"
if ((whichCode == 38) || (whichCode == 107)) {
if ((gDatePatternArray == null) || (gPreviousDatePattern == "") || (gPreviousDatePattern != aDatePattern))
{
toggleEnableDisableDateFormatter(aInputTextbox, aDatePattern);
}
while ((whichCode == 107) && (aInputTextbox.value.charAt(aInputTextbox.value.length-1) == "+"))
{
aInputTextbox.value = (aInputTextbox.value).substring(0,aInputTextbox.value.length-1);
}
// if date field not initialized...
if (aInputTextbox.value == "") {
// display today's date
var lCurrentDate = new Date();
displayDate(aInputTextbox, lCurrentDate);
}
else {
if (presubmitDateValidation(aInputTextbox, aDatePattern)) {
// create new date object based on current contents of date field
var lCurrentDate = createNewDate(aInputTextbox);
// if not a credit card expiration date (which lacks a day field)...
if (gDateDayPosition != 0)
{
// increment to next day (1000ms/s * 60s/min + 60min/hr + 24hr/day = 86400000ms/day)
lCurrentDate.setTime(lCurrentDate.getTime() + 86400000);
}
else
{
if (lCurrentDate.getMonth() != 11)
{
lCurrentDate.setMonth(lCurrentDate.getMonth()+1);
}
else
{
if (new Number(lCurrentDate.getYear()) < 9999)
{
lCurrentDate.setMonth(0);
lCurrentDate.setYear(lCurrentDate.getYear()+1);
}
}
}
// display new date
displayDate(aInputTextbox, lCurrentDate);
}
}
}
// if "down arrow" or "minus"
else if ((whichCode == 40) || (whichCode == 109)) {
if ((gDatePatternArray == null) || (gPreviousDatePattern == "") || (gPreviousDatePattern != aDatePattern))
{
toggleEnableDisableDateFormatter(aInputTextbox, aDatePattern);
}
while ((whichCode == 109) && (aInputTextbox.value.charAt(aInputTextbox.value.length-1) == "-"))
{
aInputTextbox.value = (aInputTextbox.value).substring(0,aInputTextbox.value.length-1);
}
// if date field not initialized...
if (aInputTextbox.value == "") {
// display today's date
var lCurrentDate = new Date();
displayDate(aInputTextbox, lCurrentDate);
}
else {
if (presubmitDateValidation(aInputTextbox, aDatePattern)) {
// create new date object based on current contents of date field
var lCurrentDate = createNewDate(aInputTextbox);
// if not a credit card expiration date (which lacks a day field)...
if (gDateDayPosition != 0)
{
// decrement to previous day (1000ms/s * 60s/min + 60min/hr + 24hr/day = 86400000ms/day)
lCurrentDate.setTime(lCurrentDate.getTime() - 86400000);
}
else
{
if (lCurrentDate.getMonth() != 0)
{
lCurrentDate.setMonth(lCurrentDate.getMonth()-1);
}
else
{
if (new Number(lCurrentDate.getYear()) > 1000)
{
lCurrentDate.setMonth(11);
lCurrentDate.setYear(lCurrentDate.getYear()-1);
}
}
}
// display new date
displayDate(aInputTextbox, lCurrentDate);
}
}
}
/*
else
{
// if date formatter not disabled...
if ((gDateFormatterState != "4") || (aInputTextbox.value.length == 1)) {
// re-parse date pattern only if different from that in previous call
if (gPreviousDatePattern != aDatePattern) {
// parse date pattern
if (!parseDatePattern(aInputTextbox, aDatePattern)) {
goToNextState("DisableDateFormatter");
return false;
}
}
// convert numpad digit entries into regular (top of) keyboard digits
if ((whichCode >=96) && (whichCode <=105)) {
whichCode -= 48;
}
else if ((whichCode == 111) || (whichCode == 191)) {
// date separator "/" returns whichCode 111 (from numpad) and 191 (from keyboard), but should be 47
whichCode = 47;
}
aInputTextbox.value = gDateStringEntered + String.fromCharCode(whichCode);
var lLastCharEntered = (aInputTextbox.value).charAt((aInputTextbox.value).length-1);
// myAlert("DateFormat(lLastCharEntered=" + lLastCharEntered + ",whichCode=" + whichCode + ")");
var lValidDigits = "1234567890";
// if last character entered is not a numerical digit nor the date separator...
if ((lValidDigits.indexOf(lLastCharEntered) == -1) && (lLastCharEntered != gDateSeparator1) && (lLastCharEntered != gDateSeparator2)) {
// sam (original) - not needed
// sam - fixed bug in original code where once one invalid character is accepted (because of "quick typing" race condition)
// all further alphabetic checking fails (i.e., all subsequent invalid characters are accepted)
//if (alphaCheck.indexOf(gDateStringEntered.charAt(gDateStringEntered.length-1)) >= 1)
//{
clearLastCharEntered(aInputTextbox);
return false;
}
if (gPreviousDatePattern != "") {
// enter state machine
switch(gDateFormatterState) {
case "0": // empty date string
if (gDateMonthPosition == 1) {
processFirstMonthDigit(aInputTextbox, gDateStringEntered);
}
else if (gDateDayPosition == 1) {
processFirstDayDigit(aInputTextbox, gDateStringEntered);
}
// year portion of date pattern is in first position
else {
processFirstYearDigit(aInputTextbox, gDateStringEntered);
}
break;
case "0.1": // validating first portion of date string, and at least one digit has already been entered for it
if (gDateMonthPosition == 1) {
processSecondMonthDigit(aInputTextbox, gDateStringEntered);
}
else if (gDateDayPosition == 1) {
processSecondDayDigit(aInputTextbox, gDateStringEntered);
}
// year portion of date pattern is in first position
else {
processSucceedingYearDigit(aInputTextbox, gDateStringEntered);
}
break;
case "1": // first portion of date string validated, awaiting first digit of second portion
if (gDateMonthPosition == 2) {
processFirstMonthDigit(aInputTextbox, gDateStringEntered);
}
else if (gDateDayPosition == 2) {
processFirstDayDigit(aInputTextbox, gDateStringEntered);
}
// year portion of date pattern is in second position
else {
processFirstYearDigit(aInputTextbox, gDateStringEntered);
}
break;
case "1.1": // validating second portion of date sring, and at least one digit has already been entered for it
if (gDateMonthPosition == 2) {
processSecondMonthDigit(aInputTextbox, gDateStringEntered);
}
else if (gDateDayPosition == 2) {
processSecondDayDigit(aInputTextbox, gDateStringEntered);
}
// year portion of date pattern is in second position
else {
processSucceedingYearDigit(aInputTextbox, gDateStringEntered);
}
break;
case "2":
if (gDateMonthPosition == 3) {
processFirstMonthDigit(aInputTextbox, gDateStringEntered);
}
else if (gDateDayPosition == 3) {
processFirstDayDigit(aInputTextbox, gDateStringEntered);
}
// year portion of date pattern is in third position
else if (gDateYearPosition == 3) {
processFirstYearDigit(aInputTextbox, gDateStringEntered);
}
// no third date portion (e.g., credit card expiration date mm/yyyy)
else {
// clear last digit entered; disallow all addition digit entry (await onblur date validation)
aInputTextbox.value = aInputTextbox.value.substring(0, gDateStringEntered.length-1);
gDateFormatterState = "3";
}
break;
case "2.1":
if (gDateMonthPosition == 3) {
processSecondMonthDigit(aInputTextbox, gDateStringEntered);
}
else if (gDateDayPosition == 3) {
processSecondDayDigit(aInputTextbox, gDateStringEntered);
}
// year portion of date pattern is in third position
else {
processSucceedingYearDigit(aInputTextbox, gDateStringEntered);
}
break;
case "3":
// disallow all addition digit entry (await onblur date validation)
aInputTextbox.value = aInputTextbox.value.substring(0, gDateStringEntered.length);
break;
}
}
}
}
*/
// save current valid string entered
gDateStringEntered = aInputTextbox.value;
return true;
// }
}
/**************************************************************************************
* Function : goToNextState() *
* Description : Updates the state machine to the next state following *
* "portionUpdated". *
* Parameters : portionUpdated, last state of parser *
* Returns: : None. *
* ISD Feature : "Date Formatter" *
* Author : Samson Wong *
**************************************************************************************/
function goToNextState(portionUpdated) {
switch(portionUpdated) {
case "FirstMonthDigit":
switch(gDateMonthPosition) {
case 1:
gDateFormatterState = "0.1";
break;
case 2:
gDateFormatterState = "1.1";
break;
case 3:
gDateFormatterState = "2.1";
break;
}
break;
case "SecondMonthDigit":
switch(gDateMonthPosition) {
case 1:
gDateFormatterState = "1";
break;
case 2:
gDateFormatterState = "2";
break;
case 3:
gDateFormatterState = "3";
break;
}
break;
case "FirstDayDigit":
switch(gDateDayPosition) {
case 1:
gDateFormatterState = "0.1";
break;
case 2:
gDateFormatterState = "1.1";
break;
case 3:
gDateFormatterState = "2.1";
break;
}
break;
case "SecondDayDigit":
switch(gDateDayPosition) {
case 1:
gDateFormatterState = "1";
break;
case 2:
gDateFormatterState = "2";
break;
case 3:
gDateFormatterState = "3";
break;
}
break;
case "FirstYearDigit":
switch(gDateYearPosition) {
case 1:
gDateFormatterState = "0.1";
break;
case 2:
gDateFormatterState = "1.1";
break;
case 3:
gDateFormatterState = "2.1";
break;
}
break;
case "SucceedingYearDigit":
switch(gDateYearPosition) {
case 1:
gDateFormatterState = "1";
break;
case 2:
if (gDateDayPosition != 0) {
gDateFormatterState = "2";
}
// else if special case of "credit card expiration date field" (i.e., without "day" value), early terminate date formatter
else {
gDateFormatterState = "3";
}
break;
case 3:
gDateFormatterState = "3";
break;
}
break;
case "DisableDateFormatter":
gDateFormatterState = "4";
break;
}
}
/**************************************************************************************
* Function : processFirstMonthDigit() *
* Description : Parses the first month digit entered. *
* Parameters : aInputTextbox, reference to the html textbox into which the user *
* enters the date string *
* gDateStringEntered, current contents (value) in the input textbox *
* Returns: : None. *
* ISD Feature : "Date Formatter" *
* Author : Samson Wong *
**************************************************************************************/
function processFirstMonthDigit(aInputTextbox, gDateStringEntered) {
// myAlert("processFirstMonthDigit(aInputTextbox.value=" + aInputTextbox.value + ",gDateStringEntered=" + gDateStringEntered + ")");
var lLastCharEntered = (aInputTextbox.value).charAt((aInputTextbox.value).length-1);
var lValidDigits = "01";
// if user entered premature date separator...
if ((lLastCharEntered == gDateSeparator1) || (lLastCharEntered == gDateSeparator2)) {
clearLastCharEntered(aInputTextbox);
}
// if "2", "3",..., or "9" entered...
else if (lValidDigits.indexOf(lLastCharEntered) == -1) {
// pre-pend month's leading "0" for user
// aInputTextbox.value = aInputTextbox.value.substring(0, aInputTextbox.value.length-1) + "0" + lLastCharEntered;
aInputTextbox.value = gDateStringEntered + "0" + lLastCharEntered;
if (gDateMonthPosition == 1) {
aInputTextbox.value += gDateSeparator1;
}
else if (gDateMonthPosition == 2) {
aInputTextbox.value += gDateSeparator2;
}
// record current valid month entry
gCurrentValidDateArray[gDateMonthPosition-1] = "0" + lLastCharEntered;
goToNextState("SecondMonthDigit");
}
// if "0" or "1" entered...
else {
// aInputTextbox.value = aInputTextbox.value.substring(0, aInputTextbox.value.length-1) + lLastCharEntered;
aInputTextbox.value = gDateStringEntered + lLastCharEntered;
// record current valid month entry
gCurrentValidDateArray[gDateMonthPosition-1] = lLastCharEntered + "m";
goToNextState("FirstMonthDigit");
}
}
/**************************************************************************************
* Function : processSecondMonthDigit() *
* Description : Parses the second month digit entered. *
* Assumption : First month digit entered was "0" or "1". *
* Parameters : aInputTextbox, reference to the html textbox into which the user *
* enters the date string *
* gDateStringEntered, current contents (value) in the input textbox *
* Returns: : None. *
* ISD Feature : "Date Formatter" *
* Author : Samson Wong *
**************************************************************************************/
function processSecondMonthDigit(aInputTextbox, gDateStringEntered) {
var lLastCharEntered = (aInputTextbox.value).charAt((aInputTextbox.value).length-1);
var lFirstCharEntered = (aInputTextbox.value).charAt((aInputTextbox.value).length-2);
// myAlert("processSecondMonthDigit(aInputTextbox.value=" + aInputTextbox.value + ",gDateStringEntered=" + gDateStringEntered + ")");
// if user entered premature date separator...
if (((gDateMonthPosition == 1) && (lLastCharEntered == gDateSeparator1)) || ((gDateMonthPosition == 2) && (lLastCharEntered == gDateSeparator2))) {
// if valid user-entered premature date separator...
if (lFirstCharEntered != "0") {
// pre-pend month's leading "0" for user
// aInputTextbox.value = aInputTextbox.value.substring(0, aInputTextbox.value.length-2) + "0" + lFirstCharEntered;
aInputTextbox.value = gDateStringEntered.substring(0,(gDateStringEntered.length)-1) + "0" + lFirstCharEntered;
if (gDateMonthPosition == 1) {
aInputTextbox.value += gDateSeparator1;
}
else if (gDateMonthPosition == 2) {
aInputTextbox.value += gDateSeparator2;
}
// record current valid month entry
gCurrentValidDateArray[gDateMonthPosition-1] = "0" + lFirstCharEntered;
goToNextState("SecondMonthDigit");
}
else {
clearLastCharEntered(aInputTextbox);
// remain in current state
}
}
// if user entered incorrect premature date separator...
else if (((gDateMonthPosition == 1) && (lLastCharEntered == gDateSeparator2)) || ((gDateMonthPosition == 2) && (lLastCharEntered == gDateSeparator1)))
{
clearLastCharEntered(aInputTextbox);
// remain in current state
}
else if (lFirstCharEntered == "0") {
// if valid month portion entered...
if (lLastCharEntered != "0") {
if (gDateMonthPosition == 1) {
aInputTextbox.value += gDateSeparator1;
}
else if (gDateMonthPosition == 2) {
aInputTextbox.value += gDateSeparator2;
}
// record current valid month entry
gCurrentValidDateArray[gDateMonthPosition-1] = gCurrentValidDateArray[gDateMonthPosition-1].replace(/m/,lLastCharEntered);
goToNextState("SecondMonthDigit");
}
// invalid month digit entered...
else {
clearLastCharEntered(aInputTextbox);
// remain in current state
}
}
else if (lFirstCharEntered == "1") {
var lValidDigits = "012";
// if valid month portion entered...
if (lValidDigits.indexOf(lLastCharEntered) != -1) {
if (gDateMonthPosition == 1) {
aInputTextbox.value += gDateSeparator1;
}
else if (gDateMonthPosition == 2) {
aInputTextbox.value += gDateSeparator2;
}
// record current valid month entry
gCurrentValidDateArray[gDateMonthPosition-1] = gCurrentValidDateArray[gDateMonthPosition-1].replace(/m/,lLastCharEntered);
goToNextState("SecondMonthDigit");
}
// invalid month digit entered...
else {
clearLastCharEntered(aInputTextbox);
// remain in current state
}
}
}
/**************************************************************************************
* Function : processFirstDayDigit() *
* Description : Parses the first day digit entered. *
* Parameters : aInputTextbox, reference to the html textbox into which the user *
* enters the date string *
* gDateStringEntered, current contents (value) in the input textbox *
* Returns: : None. *
* ISD Feature : "Date Formatter" *
* Author : Samson Wong *
**************************************************************************************/
function processFirstDayDigit(aInputTextbox, gDateStringEntered) {
var lLastCharEntered = (aInputTextbox.value).charAt((aInputTextbox.value).length-1);
// myAlert("processFirstDayDigit(aInputTextbox.value=" + aInputTextbox.value + ",gDateStringEntered=" + gDateStringEntered + ")");
var lValidDigits = "0123";
if ((lLastCharEntered == gDateSeparator1) || (lLastCharEntered == gDateSeparator2)) {
clearLastCharEntered(aInputTextbox);
}
// if "4", "5",..., or "9" entered...
else if (lValidDigits.indexOf(lLastCharEntered) == -1) {
// pre-pend month's leading "0" for user
// aInputTextbox.value = aInputTextbox.value.substring(0, aInputTextbox.value.length-1) + "0" + lLastCharEntered;
aInputTextbox.value = gDateStringEntered + "0" + lLastCharEntered;
if (gDateDayPosition == 1) {
aInputTextbox.value += gDateSeparator1;
}
else if (gDateDayPosition == 2) {
aInputTextbox.value += gDateSeparator2;
}
// record current valid day entry
gCurrentValidDateArray[gDateDayPosition-1] = "0" + lLastCharEntered;
goToNextState("SecondDayDigit");
}
// if "0", "1", "2", or "3" entered...
else {
// record current valid day entry
gCurrentValidDateArray[gDateDayPosition-1] = lLastCharEntered + "d";
goToNextState("FirstDayDigit");
}
}
/**************************************************************************************
* Function : processSecondDayDigit() *
* Description : Parses the second day digit entered. *
* Assumption : First month digit entered was "0",..., or "3. *
* Parameters : aInputTextbox, reference to the html textbox into which the user *
* enters the date string *
* gDateStringEntered, current contents (value) in the input textbox *
* Returns: : None. *
* ISD Feature : "Date Formatter" *
* Author : Samson Wong *
**************************************************************************************/
function processSecondDayDigit(aInputTextbox, gDateStringEntered) {
var lLastCharEntered = (aInputTextbox.value).charAt((aInputTextbox.value).length-1);
var lFirstCharEntered = (aInputTextbox.value).charAt((aInputTextbox.value).length-2);
// myAlert("processSecondDayDigit(aInputTextbox.value=" + aInputTextbox.value + ",gDateStringEntered=" + gDateStringEntered + ")");
// if user entered premature date separator...
if (((gDateDayPosition == 1) && (lLastCharEntered == gDateSeparator1)) || ((gDateDayPosition == 2) && (lLastCharEntered == gDateSeparator2))) {
// if valid user-entered premature date separator...
if (lFirstCharEntered != "0") {
// pre-pend day's leading "0" for user
// aInputTextbox.value = aInputTextbox.value.substring(0, aInputTextbox.value.length-2) + "0" + lFirstCharEntered;
aInputTextbox.value = gDateStringEntered.substring(0,(gDateStringEntered.length)-1) + "0" + lFirstCharEntered;
if (gDateDayPosition == 1) {
aInputTextbox.value += gDateSeparator1;
}
else if (gDateDayPosition == 2) {
aInputTextbox.value += gDateSeparator2;
}
// record current valid day entry
gCurrentValidDateArray[gDateDayPosition-1] = "0" + lFirstCharEntered;
goToNextState("SecondDayDigit");
}
else {
clearLastCharEntered(aInputTextbox);
// remain in current state
}
}
// if user entered incorrect premature date separator...
else if (((gDateDayPosition == 1) && (lLastCharEntered == gDateSeparator2)) || ((gDateDayPosition == 2) && (lLastCharEntered == gDateSeparator1)))
{
clearLastCharEntered(aInputTextbox);
// remain in current state
}
else if (lFirstCharEntered == "0") {
// if valid day portion entered...
if (lLastCharEntered != "0") {
if (gDateDayPosition == 1) {
aInputTextbox.value += gDateSeparator1;
}
else if (gDateDayPosition == 2) {
aInputTextbox.value += gDateSeparator2;
}
// record current valid day entry
gCurrentValidDateArray[gDateDayPosition-1] = gCurrentValidDateArray[gDateDayPosition-1].replace(/d/,lLastCharEntered);
goToNextState("SecondDayDigit");
}
// invalid day digit entered...
else {
clearLastCharEntered(aInputTextbox);
// remain in current state
}
}
else if ( (lFirstCharEntered == "1") ||
(lFirstCharEntered == "2") ) {
// all second day digits are valid
if (gDateDayPosition == 1) {
aInputTextbox.value += gDateSeparator1;
}
else if (gDateDayPosition == 2) {
aInputTextbox.value += gDateSeparator2;
}
// record current valid day entry
gCurrentValidDateArray[gDateDayPosition-1] = gCurrentValidDateArray[gDateDayPosition-1].replace(/d/,lLastCharEntered);
goToNextState("SecondDayDigit");
}
// first day digit is "3"...
else {
var lValidDigits = "01";
// if valid second day portion entered...
if (lValidDigits.indexOf(lLastCharEntered) != -1) {
if (gDateDayPosition == 1) {
aInputTextbox.value += gDateSeparator1;
}
else if (gDateDayPosition == 2) {
aInputTextbox.value += gDateSeparator2;
}
// record current valid day entry
gCurrentValidDateArray[gDateDayPosition-1] = gCurrentValidDateArray[gDateDayPosition-1].replace(/d/,lLastCharEntered);
goToNextState("SecondDayDigit");
}
// invalid second day digit entered...
else {
clearLastCharEntered(aInputTextbox);
// remain in current state
}
}
}
/**************************************************************************************
* Function : processFirstYearDigit() *
* Description : Parses the first year digit entered. *
* Parameters : aInputTextbox, reference to the html textbox into which the user *
* enters the date string *
* gDateStringEntered, current contents (value) in the input textbox *
* Returns: : None. *
* ISD Feature : "Date Formatter" *
* Author : Samson Wong *
**************************************************************************************/
function processFirstYearDigit(aInputTextbox, gDateStringEntered) {
var lLastCharEntered = (aInputTextbox.value).charAt((aInputTextbox.value).length-1);
// if four-digit year...
if (gDatePatternArray[gDateYearPosition-1].length == 4) {
if ((lLastCharEntered == gDateSeparator1) || (lLastCharEntered == gDateSeparator2)) {
clearLastCharEntered(aInputTextbox);
}
// if invalid year digit entered...
else if ( (lLastCharEntered != "1") &&
(lLastCharEntered != "2") ) {
// pre-pend year's leading "20" for user (assume 21st century)
// aInputTextbox.value = aInputTextbox.value.substring(0, aInputTextbox.value.length-1) + "20" + lLastCharEntered;
aInputTextbox.value = gDateStringEntered + "20" + lLastCharEntered;
// record current valid year entry
gCurrentValidDateArray[gDateYearPosition-1] = "20" + lLastCharEntered + "y";
}
else {
// aInputTextbox.value = aInputTextbox.value.substring(0, aInputTextbox.value.length-1) + lLastCharEntered;
aInputTextbox.value = gDateStringEntered + lLastCharEntered;
// record current valid year entry
gCurrentValidDateArray[gDateYearPosition-1] = lLastCharEntered + "yyy";
}
}
// if two-digit year...
else {
if ((lLastCharEntered == gDateSeparator1) || (lLastCharEntered == gDateSeparator2)) {
clearLastCharEntered(aInputTextbox);
}
else {
// any initial year digit is valid
// record current valid year entry
gCurrentValidDateArray[gDateYearPosition-1] = lLastCharEntered + "y";
}
}
goToNextState("FirstYearDigit");
}
/**************************************************************************************
* Function : processSucceedingYearDigit() *
* Description : Parses subsequent year digits entered. *
* Parameters : aInputTextbox, reference to the html textbox into which the user *
* enters the date string *
* gDateStringEntered, current contents (value) in the input textbox *
* Returns: : None. *
* ISD Feature : "Date Formatter" *
* Author : Samson Wong *
**************************************************************************************/
function processSucceedingYearDigit(aInputTextbox, gDateStringEntered) {
var lLastCharEntered = (aInputTextbox.value).charAt((aInputTextbox.value).length-1);
var lDateStringArray;
var lYearStringEnteredSoFar;
if (gDateSeparator1 == gDateSeparator2)
{
lDateStringArray = (aInputTextbox.value).split(gDateSeparator1);
lYearStringEnteredSoFar = lDateStringArray[gDateYearPosition-1];
}
else
{
if (gDateYearPosition == 3)
{
lDateStringArray = (aInputTextbox.value).split(gDateSeparator2);
lYearStringEnteredSoFar = lDateStringArray[1];
}
else if (gDateYearPosition == 2)
{
lDateStringArray = (aInputTextbox.value).split(gDateSeparator2);
lDateStringArray = lDateStringArray[0].split(gDateSeparator1);
lYearStringEnteredSoFar = lDateStringArray[1];
}
else // (gDateYearPosition == 1)
{
lDateStringArray = (aInputTextbox.value).split(gDateSeparator1);
lYearStringEnteredSoFar = lDateStringArray[0];
}
}
if ((lLastCharEntered == gDateSeparator1) || (lLastCharEntered == gDateSeparator2)) {
clearLastCharEntered(aInputTextbox);
}
else {
// any subsequent year digit is valid
// record current valid year entry
gCurrentValidDateArray[gDateYearPosition-1] = gCurrentValidDateArray[gDateYearPosition-1].replace(/y/,lLastCharEntered);
}
if (gCurrentValidDateArray[gDateYearPosition-1].indexOf("y") == -1) {
if ((gDateYearPosition == 1) && (gDateDayPosition != 0)) {
aInputTextbox.value += gDateSeparator1;
}
else if ((gDateYearPosition == 2) && (gDateDayPosition != 0)) {
aInputTextbox.value += gDateSeparator2;
}
goToNextState("SucceedingYearDigit");
}
// else, remain in current state
}
/**************************************************************************************
* Function : clearPreviousCharEntered() *
* Description : Clears the previous date digit entered, and adjusts the state *
* machine accordingly. *
* Parameters : aInputTextbox, reference to the html textbox into which the user *
* enters the date string *
* gDateStringEntered, current contents (value) in the input textbox *
* Returns: : None. *
* ISD Feature : "Date Formatter" *
* Author : Samson Wong *
**************************************************************************************/
function clearPreviousCharEntered(aInputTextbox) {
/*
switch(gDateFormatterState) {
case "0.0":
break;
case "0.1":
if (gDateYearPosition ==1) {
// clear previous date digit
aInputTextbox.value = aInputTextbox.value.substring(0, aInputTextbox.value.length-1);
// reset current valid date string
gCurrentValidDateArray[0].charAt(gDatePatterArray.length-1) = gDatePatternArray[0].charAt(gDatePatterArray.length-1);
if (gCurrentValidDateArray[0].indexOf() {
// remain in current state machine state
gDateFormatterState = "0.1"
}
else {
// reset state machine state
gDateFormatterState = "0.0"
}
}
else {
// clear only date digit
aInputTextbox.value = "";
// reset current valid date string
gCurrentValidDateArray[0] = gDatePatternArray[0];
// reset state machine state
gDateFormatterState = "0.0";
}
break;
case "1.0":
// clear date separator and last date digit
aInputTextbox.value = aInputTextbox.value.substring(0, aInputTextbox.value.length-2);
// reset current valid date string
gCurrentValidDateArray[0].charAt(gDatePatterArray.length-1) = gDatePatternArray[0].charAt(gDatePatterArray.length-1);
// reset state machine state
gDateFormatterState = "0.1";
break;
case "1.1":
break;
case "2.0":
break;
case "2.1":
break;
case "3.0":
break;
}
*/
}
/**************************************************************************************
* Function : parseDatePattern() *
* Description : Parses, validates, and records the input date pattern to which the *
* user-inputted date string will be formatted. *
* Parameters : aDatePattern, date pattern (should be composed of a combination of *
* "m"s, "d"s, "y"s, and "separators"). *
* Returns: : true, if date pattern is valid. *
* false, if date pattern is invalid. *
* ISD Feature : "Date Formatter" *
* Author : Samson Wong *
**************************************************************************************/
function parseDatePattern(aInputTextbox, aDatePattern) {
var lDatePattern = aDatePattern;
//lDatePattern = "yyyy/mm/dd";
// initialize global variables
initializeDateFormatter(aInputTextbox);
// strip all occurrences of "m"s, "d"s, and "y"s
lDatePattern = stripChar(lDatePattern, "m");
if (lDatePattern != "invalid date pattern") {
lDatePattern = stripChar(lDatePattern, "d");
}
else {
return false;
}
if (lDatePattern != "invalid date pattern") {
lDatePattern = stripChar(lDatePattern, "y");
}
else {
return false;
}
if (lDatePattern == "invalid date pattern") {
return false;
}
// strip extraneous spaces in Hungarian and Slovak date patterns
// while (lDatePattern.indexOf(" ") != -1)
// {
// lDatePattern = lDatePattern.replace(" ", "");
// aDatePattern = aDatePattern.replace(" ", "");
// }
// strip extraneous trailing separator in Slovak date pattern
// if ((lDatePattern.length == 3) && (lDatePattern.charAt(2) == ".")) {
// lDatePattern = lDatePattern.substring(0,lDatePattern.length-1);
// aDatePattern = aDatePattern.substring(0,aDatePattern.length-1);
// }
// myAlert("parseDatePattern(lDatePattern=" + lDatePattern + ",aDatePattern=" + aDatePattern + ")");
// determine date separator
// alert("lDatePattern.length(" + lDatePattern.length + ")");
if ((lDatePattern.length == 2) || (lDatePattern.length == 1)) {
if (lDatePattern.length == 2)
{
gDateSeparator1 = lDatePattern.charAt(0);
gDateSeparator2 = lDatePattern.charAt(1);
}
else // (lDatePattern.length == 1)
{
gDateSeparator1 = lDatePattern.charAt(0);
gDateSeparator2 = lDatePattern.charAt(0);
}
if (gDateSeparator1 == gDateSeparator2)
{
// split date pattern into date component portions
gDatePatternArray = aDatePattern.split(gDateSeparator1);
}
else // (gDateSeparator1 != gDateSeparator2)
{
var lTempArray1 = aDatePattern.split(gDateSeparator1);
var lDatePortion1 = lTempArray1[0];
var lTempArray2 = lTempArray1[1].split(gDateSeparator2);
var lDatePortion2 = lTempArray2[0];
if (lTempArray2.length == 1)
{
gDatePatternArray = new Array(lDatePortion1, lDatePortion2);
}
else if (lTempArray2.length > 1)
{
gDatePatternArray = new Array(lDatePortion1, lDatePortion2, lTempArray2[1]);
}
}
// alert("gDatePatternArray.length(" + gDatePatternArray.length + ")");
if ((gDatePatternArray.length == 3) || (gDatePatternArray.length == 2)) {
// now that an actual date pattern is being passed in via the event handlers, initialize date portion positions
gDateMonthPosition = 0;
gDateDayPosition = 0;
gDateYearPosition = 0;
for (var i=0; i<(gDatePatternArray.length); i++) {
// alert("gDatePatternArray[" + i + "](" + gDatePatternArray[i] + ")");
switch(gDatePatternArray[i].charAt(0)) {
case "m":
gDateMonthPosition = i+1;
break;
case "d":
gDateDayPosition = i+1;
break;
case "y":
gDateYearPosition = i+1;
break;
}
gCurrentValidDateArray[i] = gDatePatternArray[i];
}
// alert("parseDatePattern.mdyPositions(" + gDateMonthPosition + "," + gDateDayPosition + "," + gDateYearPosition + ")");
// alert("parseDatePattern(gCurrentValidDateArray[0]=" + gCurrentValidDateArray[0] + ",gCurrentValidDateArray[1]=" + gCurrentValidDateArray[1] + ",gCurrentValidDateArray[2]=" + gCurrentValidDateArray[2] + ")");
// record date pattern
gPreviousDatePattern = aDatePattern;
return true;
}
}
// clear recorded date pattern
gPreviousDatePattern = "";
return false;
}
/**************************************************************************************
* Function : stripChar() *
* Description : Helper function to removes all occurrences of an alphabetic *
* character from an input string. *
* Parameters : pString, date pattern composed of a combination of "m"s, "d"s, and *
* "y"s. *
* pCharToStrip, alphabetic character to be removed from pString. *
* Returns: : Original input string with alphabetic character removed. *
* ISD Feature : "Date Formatter" *
* Author : Samson Wong *
**************************************************************************************/
function stripChar(pString, pCharToStrip) {
var indexOfCharToEliminate = -1;
var indexOfPreviousCharEliminated = -1;
var lDone = false;
while (!lDone) {
if (pString.length == 0) {
lDone = true;
}
else {
indexOfCharToEliminate = pString.indexOf(pCharToStrip);
// myAlert("stripChar(pString=" + pString + ",pCharToStrip=" + pCharToStrip + ",indexOfCharToEliminate=" + indexOfCharToEliminate + ")");
if (indexOfCharToEliminate == -1) {
lDone = true;
}
else {
if ( (indexOfPreviousCharEliminated == -1) ||
((indexOfPreviousCharEliminated != -1) && (indexOfPreviousCharEliminated == indexOfCharToEliminate)) ) {
// remove single character from input string
pString = pString.substring(0, indexOfCharToEliminate) + pString.substring(indexOfCharToEliminate+1, (pString.length));
// record index of last character eliminated (the next, if any, character to be eliminated must be in the same location
// as this character removed, i.e., the individual "m"s, "d"s, and "y"s, respectively, must be adjacent to each other,
// otherwise the date pattern is invalid)
indexOfPreviousCharEliminated = indexOfCharToEliminate;
}
else {
// myAlert("stripCharInvalid(pString=" + pString + ",pCharToStrip=" + pCharToStrip + ")");
return("invalid date pattern");
}
}
}
}
return(pString);
}
/**************************************************************************************
* Function : clearLastCharEntered() *
* Description : Helper function to remove the last character entered in the input *
* textbox. *
* Parameters : aInputTextbox, reference to the html textbox into which the user *
* enters the date string *
* Returns: : true, if last character successfully removed. *
* false, if reference to input textbox invalid. *
* ISD Feature : "Date Formatter" *
* Authors : Richard Gorremans (xbase@volcano.net), www.spiritwolfx.com, and *
* Samson Wong *
**************************************************************************************/
function clearLastCharEntered(aInputTextbox) {
// myAlert("clearLastCharEntered(lastChar=" + aInputTextbox.value.charAt(aInputTextbox.value.length-1) + ")");
if (aInputTextbox) {
if (isNav4)
{
aInputTextbox.value = "";
aInputTextbox.focus();
aInputTextbox.select();
}
else
{
if (aInputTextbox.value.length > 1) {
// clear last character, but retain the rest of (previously-entered) date string
aInputTextbox.value = aInputTextbox.value.substring(0, ((aInputTextbox.value.length)-1));
}
else {
aInputTextbox.value = "";
}
}
return true;
}
return false;
}
/**************************************************************************************
* Function : presubmitDateValidation() *
* Description : onblur event handler to determine if date string entered is valid. *
* Changes the date textbox's background color to pink if invalid. *
* Parameters : aInputTextbox, reference to the html textbox into which the user *
* enters the date string *
* aDatePattern, date pattern (containing some combination of "m"s, *
* "s"s, "y"s, and "separators" to which the user-inputted date *
* string is to be formated *
* ISD Feature : "Date Formatter" *
* Authors : Samson Wong *
**************************************************************************************/
function presubmitDateValidation(aInputTextbox, aDatePattern) {
var lInputTextboxArray;
var lDatePatternArray;
var lDateMonthString;
var lDateDayString;
var lDateYearString;
var lValidDigits;
var lDateValid = true; // assume valid date string unless discovered otherwise
// myAlert("presubmitDateValidation(aInputTextbox.value=" + aInputTextbox.value + ",aDatePattern=" + aDatePattern + ")");
// myAlert("presubmitDateValidation(gPreviousDatePattern=" + gPreviousDatePattern + ",aDatePattern=" + aDatePattern + ")");
// re-parse date pattern only if different from that in previous call
if (gPreviousDatePattern != aDatePattern) {
// parse date pattern
if (!parseDatePattern(aInputTextbox, aDatePattern)) {
goToNextState("DisableDateFormatter");
return false;
}
}
if (aInputTextbox.value.length > 0) {
if (gDateSeparator1 == gDateSeparator2)
{
// split date pattern into date component portions
lDatePatternArray = aDatePattern.split(gDateSeparator1);
lInputTextboxArray = aInputTextbox.value.split(gDateSeparator1);
}
else // (gDateSeparator1 != gDateSeparator2)
{
lDatePatternArray = new Array(3);
var lTempArray1 = aDatePattern.split(gDateSeparator1);
lDatePatternArray[0] = lTempArray1[0];
var lTempArray2 = lTempArray1[1].split(gDateSeparator2);
lDatePatternArray[1] = lTempArray2[0];
lDatePatternArray[2] = lTempArray2[1];
lInputTextboxArray = new Array(3);
var lTempArray1 = aInputTextbox.value.split(gDateSeparator1);
lInputTextboxArray[0] = lTempArray1[0];
var lTempArray2 = lTempArray1[1].split(gDateSeparator2);
lInputTextboxArray[1] = lTempArray2[0];
lInputTextboxArray[2] = lTempArray2[1];
}
if (lDatePatternArray.length != lInputTextboxArray.length) {
lDateValid = false;
}
if (lDatePatternArray.length == 3) {
// extract individual month, day, and year strings
switch(gDateMonthPosition) {
case 1:
lDateMonthString = lInputTextboxArray[0];
break;
case 2:
lDateMonthString = lInputTextboxArray[1];
break;
case 3:
lDateMonthString = lInputTextboxArray[2];
break;
}
switch(gDateDayPosition) {
case 1:
lDateDayString = lInputTextboxArray[0];
break;
case 2:
lDateDayString = lInputTextboxArray[1];
break;
case 3:
lDateDayString = lInputTextboxArray[2];
break;
}
switch(gDateYearPosition) {
case 1:
lDateYearString = lInputTextboxArray[0];
break;
case 2:
lDateYearString = lInputTextboxArray[1];
break;
case 3:
lDateYearString = lInputTextboxArray[2];
break;
}
// myAlert("lDateMonthString(" + lDateMonthString + ")");
// myAlert("lDateDayString(" + lDateDayString + ")");
// myAlert("lDateYearString(" + lDateYearString + ")");
// validate month string
if ((lDateMonthString != null) && (lDateMonthString.length <= 2)) {
// if two digit month string...
if (lDateMonthString.length == 2) {
// if first digit is "0"...
if (lDateMonthString.charAt(0) == "0") {
lValidDigits = "123456789";
// if second digit is not "1"-"9"...
if (lValidDigits.indexOf(lDateMonthString.charAt(1)) == -1) {
lDateValid = false;
}
}
// if first digit is "1"...
else if (lDateMonthString.charAt(0) == "1") {
lValidDigits = "012";
// if second digit is not "0"-"2"...
if (lValidDigits.indexOf(lDateMonthString.charAt(1)) == -1) {
lDateValid = false;
}
}
// invalid first month digit
else {
lDateValid = false;
}
}
// if single digit month string...
else if (lDateMonthString.length == 1) {
lValidDigits = "123456789";
// if single digit is not "1"-"9"...
if (lValidDigits.indexOf(lDateMonthString.charAt(0)) == -1) {
lDateValid = false;
}
}
// zero-lengthed month string (i.e., consecutive date separators in date textbox)
else {
lDateValid = false;
}
}
// too many characters in month string
else {
lDateValid = false;
}
// validate day string
if ((lDateDayString != null) && (lDateDayString.length <= 2)) {
// if two digit day string...
if (lDateDayString.length == 2) {
// if first digit is "0"...
if (lDateDayString.charAt(0) == "0") {
lValidDigits = "123456789";
// if second digit is not "1"-"9"...
if (lValidDigits.indexOf(lDateDayString.charAt(1)) == -1) {
lDateValid = false;
}
}
// if first digit is "1" or "2"...
else if ((lDateDayString.charAt(0) == "1") || (lDateDayString.charAt(0) == "2")) {
lValidDigits = "0123456789";
// if second digit is not "0"-"9"...
if (lValidDigits.indexOf(lDateDayString.charAt(1)) == -1) {
lDateValid = false;
}
}
// if first digit is "3"...
else if (lDateDayString.charAt(0) == "3") {
lValidDigits = "01";
// if second digit is not "0" or "1"...
if (lValidDigits.indexOf(lDateDayString.charAt(1)) == -1) {
lDateValid = false;
}
}
// invalid first day digit
else {
lDateValid = false;
}
}
// if single digit day string...
else if (lDateDayString.length == 1) {
lValidDigits = "123456789";
// if single digit is not "1"-"9"...
if (lValidDigits.indexOf(lDateDayString.charAt(0)) == -1) {
lDateValid = false;
}
}
// zero-lengthed day string (i.e., consecutive date separators in date textbox)
else {
lDateValid = false;
}
}
// too many digits in day string
else {
lDateValid = false;
}
// validate year string
if ((lDateYearString != null) && (lDateYearString.length != 2) && (lDateYearString.length != 4)) {
lDateValid = false;
}
}
// special case of "credit card expiration date"...
else if (lDatePatternArray.length == 2) {
lInputTextboxArray = aInputTextbox.value.split(gDateSeparator1);
// extract individual month and year strings
lDateMonthString = lInputTextboxArray[0];
lDateYearString = lInputTextboxArray[1];
// myAlert("lDateMonthString(" + lDateMonthString + ")");
// myAlert("lDateYearString(" + lDateYearString + ")");
// validate month string
if ((lDateMonthString != null) && (lDateMonthString.length <= 2)) {
// if two digit month string...
if (lDateMonthString.length == 2) {
// if first digit is "0"...
if (lDateMonthString.charAt(0) == "0") {
lValidDigits = "123456789";
// if second digit is not "1"-"9"...
if (lValidDigits.indexOf(lDateMonthString.charAt(1)) == -1) {
lDateValid = false;
}
}
// if first digit is "1"...
else if (lDateMonthString.charAt(0) == "1") {
lValidDigits = "012";
// if second digit is not "0"-"2"...
if (lValidDigits.indexOf(lDateMonthString.charAt(1)) == -1) {
lDateValid = false;
}
}
// invalid first month digit
else {
lDateValid = false;
}
}
// if single digit month string...
else if (lDateMonthString.length == 1) {
lValidDigits = "123456789";
// if single digit is not "1"-"9"...
if (lValidDigits.indexOf(lDateMonthString.charAt(0)) == -1) {
lDateValid = false;
}
}
// zero-lengthed month string (i.e., consecutive date separators in date textbox)
else {
lDateValid = false;
}
}
// too many characters in month string
else {
lDateValid = false;
}
// validate year string
if ((lDateYearString != null) && (lDateYearString.length != 2) && (lDateYearString.length != 4)) {
lDateValid = false;
}
}
else {
lDateValid = false;
}
/*
if (lDateValid == false) {
// change date text field background color to pink
aInputTextbox.style.background = "pink";
}
*/
}
if (lDateValid == false) {
// clear recorded date pattern
gPreviousDatePattern = "";
}
return(lDateValid);
}
function updateTarget(targetName, selectedValue, selectedDisplayValue)
{
if (window.opener && !window.opener.closed) {
var target = window.opener.document.getElementById(targetName);
// sam - always replace last dropdown list entry before selecting entry via Fev_SetFormControlValue()
// because Firefox/Netscape does not support adding additional entries
// var bSuccess = Fev_SetFormControlValue(target, selectedValue);
var bSuccess = false;
if (!bSuccess)
{
// sam - replace last dropdown list entry (instead inserting a new list item) because Firefox/Netscape
// does not support adding additional entries
if ( insertListControlValue(window.opener.document, target, selectedValue, selectedDisplayValue) ||
Fev_ReplaceLastListControlOption(target, selectedValue, selectedDisplayValue) )
{
//try setting the selection again
bSuccess = Fev_SetFormControlValue(target, selectedValue);
}
}
if (bSuccess) {
if (target != null) {
if (navigator.appName == "Netscape") {
var myevent = document.createEvent("HTMLEvents")
myevent.initEvent("change", true, true)
target.dispatchEvent(myevent);
}
else { // IE
target.fireEvent('onchange');
}
}
}
window.close();
}
}
/******************************************************************************************************/
/* sam - this function should only be used for IE (Firefox/Netscape does not support "options.add()") *
/******************************************************************************************************/
//Inserts the value into a list element, independent of the element's type.
function insertListControlValue(objDocument, objListElement, strValue, strText)
{
var strTagName = Fev_GetElementTagName(objListElement);
switch (strTagName.toLowerCase())
{
case "select":
var objOption = objDocument.createElement("OPTION");
objOption.value = strValue;
objOption.text = strText;
objListElement.options.add(objOption);
return true;
break;
default:
break;
}
return false;
}
/**************************************************************************************
* Description : Global variables used by "JavaScript Date Selector" feature. *
* ISD Feature : "JavaScript Date Selector" *
* Authors : Julian Robichaux, http://www.nsftools.com, and Samson Wong *
**************************************************************************************/
var dateSelectorDivID = "dateSelector";
var iFrameDivID = "dateSelectoriframe";
var dayArrayShort = new Array('Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa');
var dayArrayMed = new Array('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat');
var dayArrayLong = new Array('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday');
var monthArrayShort = new Array('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec');
var monthArrayMed = new Array('Jan', 'Feb', 'Mar', 'Apr', 'May', 'June', 'July', 'Aug', 'Sept', 'Oct', 'Nov', 'Dec');
var monthArrayLong = new Array('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December');
// these variables define the date formatting we're expecting and outputting.
// If you want to use a different format by default, change the defaultDateSeparator
// and defaultDateFormat variables either here or on your HTML page.
var defaultDateSeparator = "/"; // common values would be "/" or "."
var defaultDateFormat = "mdy" // valid values are "mdy", "dmy", and "ymd"
var dateSeparator = defaultDateSeparator;
var dateFormat = defaultDateFormat;
/**************************************************************************************
* Function : displayDateSelector() *
* Description : Displays the date selector beneath the "date input field" when the *
* "date selector icon" is clicked. *
* Parameters : dateFieldName, html element name of the "date input field" that *
* will be filled in if the user picks a date *
* displayBelowThisObject, html element name of the object below which *
* the date selector is displayed (optional) *
* Returns: : None. *
* ISD Feature : "JavaScript Date Selector" *
* Authors : Julian Robichaux, http://www.nsftools.com, and Samson Wong *
**************************************************************************************/
function displayDateSelector(dateFieldName, displayBelowThisObject, dtFormat, dtSep)
{
var targetDateField = document.getElementsByName (dateFieldName).item(0);
// if we weren't told what node to display the dateSelector beneath, just display it
// beneath the date field we're updating
if (!displayBelowThisObject)
displayBelowThisObject = targetDateField;
// if a date separator character was given, update the dateSeparator variable
if (dtSep)
dateSeparator = dtSep;
else
dateSeparator = defaultDateSeparator;
// if a date format was given, update the dateFormat variable
if (dtFormat)
dateFormat = dtFormat;
else
dateFormat = defaultDateFormat;
var x = displayBelowThisObject.offsetLeft;
var y = displayBelowThisObject.offsetTop + displayBelowThisObject.offsetHeight ;
// deal with elements inside tables and such
var parent = displayBelowThisObject;
while (parent.offsetParent) {
parent = parent.offsetParent;
x += parent.offsetLeft;
y += parent.offsetTop ;
}
drawDateSelector(targetDateField, x, y);
}
/**************************************************************************************
* Function : drawDateSelector() *
* Description : Called by displayDateSelector() to draw the dateSelector object *
* (which is just a table with calendar elements) at the specified x *
* and y coordinates. *
* Parameters : targetDateField, html element name of the "date input field" that *
* will be filled in if the user picks a date *
* x, x-coordinate of the displayed date selector *
* y, y-coordinate of the displayed date selector *
* Returns: : None. *
* ISD Feature : "JavaScript Date Selector" *
* Authors : Julian Robichaux, http://www.nsftools.com, and Samson Wong *
**************************************************************************************/
function drawDateSelector(targetDateField, x, y)
{
var dt = getFieldDate(targetDateField.value );
// the dateSelector table will be drawn inside of a
with an ID defined by the
// global dateSelectorDivID variable. If such a div doesn't yet exist on the HTML
// document we're working with, add one.
if (!document.getElementById(dateSelectorDivID)) {
// don't use innerHTML to update the body, because it can cause global variables
// that are currently pointing to objects on the page to have bad references
//document.body.innerHTML += "";
var newNode = document.createElement("div");
newNode.setAttribute("id", dateSelectorDivID);
newNode.setAttribute("class", "dpDiv");
newNode.setAttribute("style", "visibility: hidden;");
document.body.appendChild(newNode);
}
// move the dateSelector div to the proper x,y coordinate and toggle the visiblity
var selectorDiv = document.getElementById(dateSelectorDivID);
selectorDiv.style.position = "absolute";
selectorDiv.style.left = x + "px";
selectorDiv.style.top = y + "px";
selectorDiv.style.visibility = (selectorDiv.style.visibility == "visible" ? "hidden" : "visible");
selectorDiv.style.display = (selectorDiv.style.display == "" ? "none" : "");
selectorDiv.style.zIndex = 10000;
// draw the dateSelector table
refreshDateSelector(targetDateField.name, dt.getFullYear(), dt.getMonth(), dt.getDate());
}
/**************************************************************************************
* Function : refreshDateSelector() *
* Description : Function which actually does the drawing of the date selector *
* html table. *
* Parameters : dateFieldName, html element name of the "date input field" that *
* will be filled in if the user picks a date *
* year, year to highlight (optional) (default is today's year) *
* month, month to highlight (optional) (default is today's month) *
* day, day to highlight (optional) (default is today's day) *
* Returns: : None. *
* ISD Feature : "JavaScript Date Selector" *
* Authors : Julian Robichaux, http://www.nsftools.com, and Samson Wong *
**************************************************************************************/
function refreshDateSelector(dateFieldName, year, month, day)
{
// if no arguments are passed, use today's date; otherwise, month and year
// are required (if a day is passed, it will be highlighted later)
var thisDay = new Date();
if ((month >= 0) && (year > 0)) {
thisDay = new Date(year, month, 1);
} else {
day = thisDay.getDate();
thisDay.setDate(1);
}
// the calendar will be drawn as a table
// you can customize the table elements with a global CSS style sheet,
// or by hardcoding style and formatting elements below
var crlf = "\r\n";
var TABLE = "
" + crlf;
var xTABLE = "
" + crlf;
var TR = "
";
var TR_title = "
";
var TR_days = "
";
var TR_todaybutton = "
";
var xTR = "
" + crlf;
var TD = "
";
if (dayNum == day)
html += TD_selected + TD_onclick + DIV_selected + dayNum + xDIV + xTD;
else
html += TD + TD_onclick + dayNum + xTD;
// if this is a Saturday, start a new row
if (thisDay.getDay() == 6)
html += xTR + TR;
// increment the day
thisDay.setDate(thisDay.getDate() + 1);
} while (thisDay.getDate() > 1)
// fill in any trailing blanks
if (thisDay.getDay() > 0) {
for (i = 6; i > thisDay.getDay(); i--)
html += TD_noDay + " " + xTD;
}
html += xTR;
// add a button to allow the user to easily return to today, or close the calendar
var today = new Date();
var todayString = "Today is " + dayArrayMed[today.getDay()] + ", " + monthArrayMed[ today.getMonth()] + " " + today.getDate();
html += TR_todaybutton + TD_todaybutton;
// sam
// html += " ";
html += "
";
// html += "";
html += xTD + xTR;
// and finally, close the table
html += xTABLE;
document.getElementById(dateSelectorDivID).innerHTML = html;
// add an "iFrame shim" to allow the dateSelector to display above selection lists
adjustiFrame();
}
var mobileCurrentCalendarSender = null;
function mobileCalendarShownIntercept(e,h) {
if ( e == "years" || e == "months" ) {
return;
}
mobileCurrentCalendarSender(e, h);
}
function mobileCalendarShown(sender, e) {
mobileCurrentCalendarSender = sender;
sender._switchMode = mobileCalendarShownIntercept;
}
/**************************************************************************************
* Function : getButtonCode() *
* Description : Helper function to construct the html for the previous/next *
* month/year buttons. *
* Parameters : dateFieldName, html element name of the "date input field" that *
* will be filled in if the user picks a date *
* dateVal, current date highlighted *
* adjust, number of months to move back/forward *
* label, previous/next month/year button image to use for this button *
* Returns: : The html for previous/next month/year button. *
* ISD Feature : "JavaScript Date Selector" *
* Authors : Julian Robichaux, http://www.nsftools.com, and Samson Wong *
**************************************************************************************/
function getButtonCode(dateFieldName, dateVal, adjust, label)
{
var newMonth = (dateVal.getMonth () + adjust) % 12;
var newYear = dateVal.getFullYear() + parseInt((dateVal.getMonth() + adjust) / 12);
if (newMonth < 0) {
newMonth += 12;
newYear += -1;
}
// sam
// return "";
return ""
}
/**************************************************************************************
* Function : getDateString() *
* Description : Convert a JavaScript Date object to a string, based on the *
* dateFormat and dateSeparator variables at the beginning of this *
* script library. *
* Parameters : dateVal, current date highlighted *
* Returns: : The highlighted date as a string. *
* ISD Feature : "JavaScript Date Selector" *
* Authors : Julian Robichaux, http://www.nsftools.com, and Samson Wong *
**************************************************************************************/
function getDateString(dateVal)
{
var dayString = "00" + dateVal.getDate();
var monthString = "00" + (dateVal.getMonth()+1);
dayString = dayString.substring(dayString.length - 2);
monthString = monthString.substring(monthString.length - 2);
switch (dateFormat) {
case "dmy" :
return dayString + dateSeparator + monthString + dateSeparator + dateVal.getFullYear();
case "ymd" :
return dateVal.getFullYear() + dateSeparator + monthString + dateSeparator + dayString;
case "mdy" :
default :
return monthString + dateSeparator + dayString + dateSeparator + dateVal.getFullYear();
}
}
/**************************************************************************************
* Function : getFieldDate() *
* Description : Converts a string to a JavaScript Date objec *
* Parameters : dateString, date string to be converted into a JavaScript Date *
* object. *
* Returns: : The date string as a JavaScript Date object. *
* ISD Feature : "JavaScript Date Selector" *
* Authors : Julian Robichaux, http://www.nsftools.com, and Samson Wong *
**************************************************************************************/
function getFieldDate(dateString)
{
var dateVal;
var dArray;
var d, m, y;
try {
dArray = splitDateString(dateString);
if (dArray) {
switch (dateFormat) {
case "dmy" :
d = parseInt(dArray[0], 10);
m = parseInt(dArray[1], 10) - 1;
y = parseInt(dArray[2], 10);
break;
case "ymd" :
d = parseInt(dArray[2], 10);
m = parseInt(dArray[1], 10) - 1;
y = parseInt(dArray[0], 10);
break;
case "mdy" :
default :
d = parseInt(dArray[1], 10);
m = parseInt(dArray[0], 10) - 1;
y = parseInt(dArray[2], 10);
break;
}
dateVal = new Date(y, m, d);
} else if (dateString) {
dateVal = new Date(dateString);
} else {
dateVal = new Date();
}
} catch(e) {
dateVal = new Date();
}
return dateVal;
}
/**************************************************************************************
* Function : splitDateString() *
* Description : Splits a date string into an array of elements, using common date *
* separators. *
* Parameters : dateString, date string to be converted into a JavaScript Date *
* object. *
* Returns: : The split date array, if operation successful; false, otherwise. *
* ISD Feature : "JavaScript Date Selector" *
* Authors : Julian Robichaux, http://www.nsftools.com, and Samson Wong *
**************************************************************************************/
function splitDateString(dateString)
{
var dArray;
if (dateString.indexOf("/") >= 0)
dArray = dateString.split("/");
else if (dateString.indexOf(".") >= 0)
dArray = dateString.split(".");
else if (dateString.indexOf("-") >= 0)
dArray = dateString.split("-");
else if (dateString.indexOf("\\") >= 0)
dArray = dateString.split("\\");
else
dArray = false;
return dArray;
}
/**************************************************************************************
* Function : dateSelectorClosed() *
* Description : Update the "date input field" with the date string, and hide the *
* date selector. If no date string is passed, just close the *
* date selector without changing the field value. *
* Parameters : dateFieldName, html element name of the "date input field" that *
* will be filled in if the user picks a date *
* dateString, date string with which the "date input field" is to be *
* updated. *
* Returns: : None. *
* ISD Feature : "JavaScript Date Selector" *
* Authors : Julian Robichaux, http://www.nsftools.com, and Samson Wong *
**************************************************************************************/
/**
If the page developer has defined a function called dateSelectorClosed anywhere on
the page or in an imported library, we will attempt to run that function with the updated
field as a parameter. This can be used for such things as date validation, setting default
values for related fields, etc. For example, you might have a function like this to validate
a start date field:
function dateSelectorClosed(dateField)
{
var dateObj = getFieldDate(dateField.value);
var today = new Date();
today = new Date(today.getFullYear(), today.getMonth(), today.getDate());
if (dateField.name == "StartDate") {
if (dateObj < today) {
// if the date is before today, alert the user and display the dateSelector again
alert("Please enter a date that is today or later");
dateField.value = "";
document.getElementById(dateSelectorDivID).style.visibility = "visible";
adjustiFrame();
} else {
// if the date is okay, set the EndDate field to 7 days after the StartDate
dateObj.setTime(dateObj.getTime() + (7 * 24 * 60 * 60 * 1000));
var endDateField = document.getElementsByName ("EndDate").item(0);
endDateField.value = getDateString(dateObj);
}
}
}
*/
function updateDateField(dateFieldName, dateString)
{
var targetDateField = document.getElementsByName (dateFieldName).item(0);
if (dateString)
targetDateField.value = dateString;
var selectorDiv = document.getElementById(dateSelectorDivID);
selectorDiv.style.visibility = "hidden";
selectorDiv.style.display = "none";
adjustiFrame();
targetDateField.focus();
// after the dateSelector has closed, optionally run a user-defined function called
// dateSelectorClosed, passing the field that was just updated as a parameter
// (note that this will only run if the user actually selected a date from the dateSelector)
if ((dateString) && (typeof(dateSelectorClosed) == "function"))
dateSelectorClosed(targetDateField);
}
/**************************************************************************************
* Function : adjustiFrame() *
* Description : Uses an "iFrame shim" to deal with problems where the dateSelector *
* shows up behind selection list elements, if they're below the *
* date selector. *
* The problem and solution are described at: *
* http://dotnetjunkies.com/WebLog/jking/archive/2003/07/21/488.aspx *
* http://dotnetjunkies.com/WebLog/jking/archive/2003/10/30/2975.aspx *
* Parameters : selectorDiv, html div containing date selector *
* iFrameDiv, html div containing iframe shim. *
* Returns: : None. *
* ISD Feature : "JavaScript Date Selector" *
* Authors : Julian Robichaux, http://www.nsftools.com, and Samson Wong *
**************************************************************************************/
function adjustiFrame(selectorDiv, iFrameDiv)
{
// we know that Opera doesn't like something about this, so if we
// think we're using Opera, don't even try
var is_opera = (navigator.userAgent.toLowerCase().indexOf("opera") != -1);
if (is_opera)
return;
// put a try/catch block around the whole thing, just in case
try {
if (!document.getElementById(iFrameDivID)) {
// don't use innerHTML to update the body, because it can cause global variables
// that are currently pointing to objects on the page to have bad references
//document.body.innerHTML += "