//This variable holds the input element that is the selected time element that the spinner will operate on
// (i.e. the hours input)
var selectedInput = null;

//The variable will hold the TimeOut object that will be used for the automatic scrolling while holding the mouse button down
var timeout = null;

//This variable is a counter so that the automatic scrolling starts out slow, then gets faster with iterations
var stallCounter = 0;

//formatTimeElements is going to be a two dimensional array where the 0th element of the second level will represent the
// separator, the 1st element will represent the time formatter itself, and the 2nd element will represent the user
// input value.  This all gets set in initTimeSpinner()
var formatTimeElements = null;

//This will be set in initTimeSpinner and will define the constaints of the hours based on the time format (ie, 12hour format
// versus 24hour format)
var lowerHourConstraint = 1;
var upperHourConstraint = 12;

//This variable is kept to determine if the individual times have been set to a valid time.  It will be updated whenever a user 
// has selected a time input field, and then clicks anywhere else
var validHours = true;
var validMinutes = true;
var validSeconds = true;

//We need to create an array that will hold the id's of all the time spinners we might have on one page (since multiple may
// be present)
var timeIdArray = new Array();


/* This is the init function that will need to be called on the load of the page to include the time spinner.
 * It will need to pass in the name of the span that will hold the spinner itself.  This span should also include 
 * any initial time that should be loaded into the spinner.
 * Here's an example of what the code should look like to include the spinner;
 *
 * <SPAN ID="timeSpan">
 *   12:34:56 PM
 * </SPAN>
 * <SCRIPT>
 *  initTimeSpinner('timeSpan');
 * <\SCRIPT>
 *
 * Please also note that the order does make a difference as the SPAN must exist for the init method to run properly.
 * The user will then be able to get the final value through a hidden element by the name of userSpanName+"Time" (ie, 
 * from our example above, the hidden field name would be "timeSpanTime".  This hidden field is written out inside of the user's
 * span tag, so if the span tag is within a form, the form can be submitted and this field will contain the time value, otherwise
 * the user can get the value through the javascript call document.getElementById(userSpanName+"Time").value
 *
 * FORMATTING - The formatting of the dates is set from within the .properties file.  This can handle formatting using the following:
 *      h, hh, H, HH, k, K for the hour
 *      mm for the minutes
 *      ss for the seconds
 *      a for the am/pm marker
 *      a colon, comma, or space for the separator (or any combination of the three)
 *   there is logic put in place to not allow certain cases to work correctly (for instance, there shouldn't be a am/pm
 *   marker included for a format based on a 24hour scale, and therefore, the marker element won't spin when it would for a
 *   12 hour scale)
 */
function initTimeSpinner(spanName, fromCalendar)
{
    //We start off by getting the time from the text box that is passed in, which should just be the value of the text box
    // and nothing more
    var ctl1 = document.getElementById(spanName);
    var time = ctl1.innerHTML;

    //Now we add the control id to our global array
    timeIdArray[timeIdArray.length] = ctl1.id;
    
    //Now, we want to remove any spaces from the end of the time string.  This is because through some HTML formatting, 
    // some extranous spaces may be inserted at the end, so we just remove them so we can be consistant
    var regExp = /\s*/;
    time = time.replace(regExp, "");
    
    //We want to set this every time.  This is incase we have multiple time spinners on one page.  Because we only use
    // the formatting in other methods, it doesn't matter what the values are in it.  We do this so we only have to iterate
    // through the formatting logic once, saving us some time
    formatTimeElements = new Array()
    
    //Now we'll parse our time into the correct divisions
    var dateFormat = "";
    
    // if the time is null, we want to make sure we use a default time of 12:00:00 AM
    if(time.length == 0)
    {
       dateFormat = 'hh:mm:ss a';
       
       // replace with 12:00:00 AM
       time = dateFormat;
       time = time.replace("hh", "12");
       time = time.replace("mm", "00");
       time = time.replace("ss", "00");
       time = time.replace("a", "AM");
    
    } else if(fromCalendar)
    {
        dateFormat='dd-MM-yyyy hh:mm:ss a';
    }
    else
    {
        dateFormat='hh:mm:ss a';
    }

    //We're going to start by picking out everything that's separated by a space
    aformatChar = " "
    aFormat	= dateFormat.split(aformatChar);
    aUser	= time.split(aformatChar);
    for(i=0;i<aFormat.length;i++)
    {
        //We're only going to grab elements that are less than three chars long from the time format.  If this
        // is the case, then we want to load our time array to parallel the time format array
        if(aFormat[i].length < 3)
        {
            formatTimeElements[formatTimeElements.length] = new Array();
            formatTimeElements[formatTimeElements.length-1][0] = aformatChar;
            formatTimeElements[formatTimeElements.length-1][1] = aFormat[i];
            formatTimeElements[formatTimeElements.length-1][2] = aUser[i];
        }
        //If we didn't put it in the array, that means it needs to be parsed
        else
        {
            //Now we pick out everything that's separated by a colon
            bformatChar = ":";
            bFormat	= aFormat[i].split(bformatChar);
            bUser	= aUser[i].split(bformatChar);
            for(j=0;j<bFormat.length;j++)
            {
                //We're only going to grab elements that are less than three chars long from the time format.  If this
                // is the case, then we want to load our time array to parallel the time format array
                if(bFormat[j].length < 3)
                {
                    formatTimeElements[formatTimeElements.length] = new Array();
                    formatTimeElements[formatTimeElements.length-1][0] = bformatChar;
                    formatTimeElements[formatTimeElements.length-1][1] = bFormat[j];
                    formatTimeElements[formatTimeElements.length-1][2] = bUser[j];
                }
                //If we didn't put it in the array, that means it needs to be parsed
                else
                {
                    //Now we pick out everything that's separated by a comma.  This is our last case
                    cformatChar = ",";
                    cFormat	= bFormat[j].split(cformatChar);
                    cUser	= bUser[j].split(cformatChar);
                    for(k=0;k<cFormat.length;k++)
                    {
                        //We're only going to grab elements that are less than three chars long from the time format.  If this
                        // is the case, then we want to load our time array to parallel the time format array
                        if(cFormat[k].length < 3)
                        {
                            formatTimeElements[formatTimeElements.length] = new Array();
                            formatTimeElements[formatTimeElements.length-1][0] = cformatChar;
                            formatTimeElements[formatTimeElements.length-1][1] = cFormat[k];
                            formatTimeElements[formatTimeElements.length-1][2] = cUser[k];
                        }
                    }
                }
            }
        }
    }

    //Now we build up the HTML that will will place back into the span that the user passed in.  We will separate all of the time
    // elements into their own span (and give them an id based on the parent span's id and what time element it is).  We will
    // also add the up and down arrows to spin the time elements
    //The timeOnly variable will collect the time only after going through the format.  We need this because it's possible
    // that the calendar will pass in a time and date.
    var timeOnly = "";
    var newInnerHTML = "";
    newInnerHTML += "<TABLE CELLPADDING='0' CELLSPACING='0'>";
    newInnerHTML += "<TR>";
    newInnerHTML += "<TD>";
    //Now we're going to make sure we write out the time in the correct format.  We want to make sure we put the separator
    // in the right place, so there is some logic around it: if it's the last element, put the separator first, else put it last,
    // unless it's the last one (which it'll be putting ahead of it) and unless it's the second to last (which will have the
    // separator bafter it due to the separator going before the last element
    for	(i=0;i<formatTimeElements.length;i++)
    {
        if ((formatTimeElements[i][1]=="h") || (formatTimeElements[i][1]=="hh"))
        {
            if(i == formatTimeElements.length - 1)
            {
                newInnerHTML += "&nbsp;"+formatTimeElements[i][0]+"&nbsp;";
                timeOnly += formatTimeElements[i][0];
            }
            newInnerHTML += "<INPUT TYPE='text' ID=\""+ctl1.id+"hours\" onFocus=\"javascript:selectInput('"+ctl1.id+"hours')\" onBlur=\"javascript:validateHours()\" value='"+formatTimeElements[i][2]+"' maxlength='2' class='timeSpinnerInputUnselected'>";
            timeOnly += formatTimeElements[i][2];
            if(i != formatTimeElements.length - 1 && i != formatTimeElements.length - 2)
            {
                newInnerHTML += "&nbsp;"+formatTimeElements[i][0]+"&nbsp;";
                timeOnly += formatTimeElements[i][0];
            }
            lowerHourConstraint = 1;
            upperHourConstraint = 12;
        }
        else if	((formatTimeElements[i][1]=="H") || (formatTimeElements[i][1]=="HH"))
        {
            if(i == formatTimeElements.length - 1)
            {
                newInnerHTML += "&nbsp;"+formatTimeElements[i][0]+"&nbsp;";
                timeOnly += formatTimeElements[i][0];
            }
            newInnerHTML += "<INPUT TYPE='text' ID=\""+ctl1.id+"hours\" onFocus=\"javascript:selectInput('"+ctl1.id+"hours')\" onBlur=\"javascript:validateHours()\" value='"+formatTimeElements[i][2]+"' maxlength='2' class='timeSpinnerInputUnselected'>";
            timeOnly += formatTimeElements[i][2];
            if(i != formatTimeElements.length - 1 && i != formatTimeElements.length - 2)
            {
                newInnerHTML += "&nbsp;"+formatTimeElements[i][0]+"&nbsp;";
                timeOnly += formatTimeElements[i][0];
            }
            lowerHourConstraint = 0;
            upperHourConstraint = 23;
        }
        else if	((formatTimeElements[i][1]=="k"))
        {
            if(i == formatTimeElements.length - 1)
            {
                newInnerHTML += "&nbsp;"+formatTimeElements[i][0]+"&nbsp;";
                timeOnly += formatTimeElements[i][0];
            }
            newInnerHTML += "<INPUT TYPE='text' ID=\""+ctl1.id+"hours\" onFocus=\"javascript:selectInput('"+ctl1.id+"hours')\" onBlur=\"javascript:validateHours()\" value='"+formatTimeElements[i][2]+"' maxlength='2' class='timeSpinnerInputUnselected'>";
            timeOnly += formatTimeElements[i][2];
            if(i != formatTimeElements.length - 1 && i != formatTimeElements.length - 2)
            {
                newInnerHTML += "&nbsp;"+formatTimeElements[i][0]+"&nbsp;";
                timeOnly += formatTimeElements[i][0];
            }
            lowerHourConstraint = 1;
            upperHourConstraint = 24;
        }
        else if	((formatTimeElements[i][1]=="K"))
        {
            if(i == formatTimeElements.length - 1)
            {
                newInnerHTML += "&nbsp;"+formatTimeElements[i][0]+"&nbsp;";
                timeOnly += formatTimeElements[i][0];
            }
            newInnerHTML += "<INPUT TYPE='text' ID=\""+ctl1.id+"hours\" onFocus=\"javascript:selectInput('"+ctl1.id+"hours')\" onBlur=\"javascript:validateHours()\" value='"+formatTimeElements[i][2]+"' maxlength='2' class='timeSpinnerInputUnselected'>";
            timeOnly += formatTimeElements[i][2];
            if(i != formatTimeElements.length - 1 && i != formatTimeElements.length - 2)
            {
                newInnerHTML += "&nbsp;"+formatTimeElements[i][0]+"&nbsp;";
                timeOnly += formatTimeElements[i][0];
            }
            lowerHourConstraint = 0;
            upperHourConstraint = 11;
        }
        else if	((formatTimeElements[i][1]=="m") || (formatTimeElements[i][1]=="mm"))
        {
            if(i == formatTimeElements.length - 1)
            {
                newInnerHTML += "&nbsp;"+formatTimeElements[i][0]+"&nbsp;";
                timeOnly += formatTimeElements[i][0];
            }
            newInnerHTML += "<INPUT TYPE='text' ID=\""+ctl1.id+"minutes\" onFocus=\"javascript:selectInput('"+ctl1.id+"minutes')\" onBlur=\"javascript:validateMinutes('"+ctl1.id+"minutes')\" value='"+formatTimeElements[i][2]+"' maxlength='2' class='timeSpinnerInputUnselected'>";
            timeOnly += formatTimeElements[i][2];
            if(i != formatTimeElements.length - 1 && i != formatTimeElements.length - 2)
            {
                newInnerHTML += "&nbsp;"+formatTimeElements[i][0]+"&nbsp;";
                timeOnly += formatTimeElements[i][0];
            }
        }
        else if	((formatTimeElements[i][1]=="s") || (formatTimeElements[i][1]=="ss") )
        {
            if(i == formatTimeElements.length - 1)
            {
                newInnerHTML += "&nbsp;"+formatTimeElements[i][0]+"&nbsp;";
                timeOnly += formatTimeElements[i][0];
            }
            newInnerHTML += "<INPUT TYPE='text' ID=\""+ctl1.id+"seconds\" onFocus=\"javascript:selectInput('"+ctl1.id+"seconds')\" onBlur=\"javascript:validateSeconds('"+ctl1.id+"seconds')\" value='"+formatTimeElements[i][2]+"' maxlength='2' class='timeSpinnerInputUnselected'>";
            timeOnly += formatTimeElements[i][2];
            if(i != formatTimeElements.length - 1 && i != formatTimeElements.length - 2)
            {
                newInnerHTML += "&nbsp;"+formatTimeElements[i][0]+"&nbsp;";
                timeOnly += formatTimeElements[i][0];
            }
        }
        else if	(formatTimeElements[i][1]=="a")
        {
            if(i == formatTimeElements.length - 1)
            {
                newInnerHTML += "&nbsp;"+formatTimeElements[i][0]+"&nbsp;";
                timeOnly += formatTimeElements[i][0];
            }
            newInnerHTML += "<INPUT TYPE='text' ID=\""+ctl1.id+"ampmMarker\" onFocus=\"javascript:selectInput('"+ctl1.id+"ampmMarker')\" value='"+formatTimeElements[i][2]+"' readonly class='timeSpinnerInputUnselected'>";
            timeOnly += formatTimeElements[i][2];
            if(i != formatTimeElements.length - 1 && i != formatTimeElements.length - 2)
            {
                newInnerHTML += "&nbsp;"+formatTimeElements[i][0]+"&nbsp;";
                timeOnly += formatTimeElements[i][0];
            }
        }
    }
    newInnerHTML += "</TD>";
    newInnerHTML += "<TD>";
    newInnerHTML += "<TABLE CELLPADDING='0' CELLSPACING='0'>";
    newInnerHTML += "<TR>";
    newInnerHTML += "<TD>";
    newInnerHTML += "<A href='javascript:timeSpinner()' ONMOUSEDOWN=\"javascript:startSpinner('"+ctl1.id+"', 'up')\" ONMOUSEUP=\"javascript:stopSpinner('"+ctl1.id+"')\" ONMOUSEOUT=\"javascript:stopSpinner('"+ctl1.id+"')\">"
    newInnerHTML += "<IMG NAME='timeSpinnerArrowUp' SRC='framework/skins/beaTools/images/icon_arrow_up.gif' WIDTH='13' HEIGHT='8' ALT='"+"Click to spin selected time element.  Hold mouse down to auto-spin."+"' BORDER='0' HSPACE='4' VSPACE='4'>";
    newInnerHTML += "</A>";
    newInnerHTML += "</TD>";
    newInnerHTML += "</TR>";
    newInnerHTML += "<TR>";
    newInnerHTML += "<TD>";
    newInnerHTML += "<A HREF='javascript:timeSpinner()'  ONMOUSEDOWN=\"javascript:startSpinner('"+ctl1.id+"', 'down')\" ONMOUSEUP=\"javascript:stopSpinner('"+ctl1.id+"')\" ONMOUSEOUT=\"javascript:stopSpinner('"+ctl1.id+"')\">";
    newInnerHTML += "<IMG ID='timeSpinnerArrowDown' SRC='framework/skins/beaTools/images/icon_arrow_down.gif' WIDTH='13' HEIGHT='8' ALT='"+"Click to spin selected time element.  Hold mouse down to auto-spin."+"' BORDER='0' HSPACE='4' VSPACE='4'>";
    newInnerHTML += "</A>";
    newInnerHTML += "</TD>";
    newInnerHTML += "</TR>";
    newInnerHTML += "</TABLE>";
    newInnerHTML += "</TD>";
    newInnerHTML += "</TR>";
    newInnerHTML += "</TABLE>";
    newInnerHTML += "<INPUT TYPE='HIDDEN' NAME='"+ctl1.id+"Time' ID='"+ctl1.id+"Time' VALUE='"+timeOnly+"'>";
    ctl1.innerHTML = newInnerHTML;

    //As our last step, we will set the selected input to be the hours input in case the user hits a button without selecting
    // a time element.  We choose hours for no particular reason other than it gets updates frequently
    if(selectedInput == null)
    {
        selectedInput = ctl1.id + "hours";
        document.getElementById(selectedInput).className = "timeSpinnerInputSelected";
    }
}

/* This is the function called on the mouseDown event of the user's click.  It will detect what the selected span is, and then
 * call the appropriate spinner based on that span.  If the selected span doesn't match that of which span correlates with the
 * button pressed, the function will slect the correct span's minutes span.
 *
 */
function startSpinner(ctl1Id, direction)
{
    //The first check is to verify that the arrow pressed corresponds with the span selected.  If not, we will choose the 
    // correct span's hour element
    var regExp = new RegExp("^"+ctl1Id+"hours$|^"+ctl1Id+"hours24$|^"+ctl1Id+"minutes$|^"+ctl1Id+"seconds$|^"+ctl1Id+"ampmMarker$");
    if(selectedInput.match(regExp) == null)
    {
        if(document.getElementById(selectedInput) != null)
        {
            document.getElementById(selectedInput).className = "timeSpinnerInputUnselected";
        }
        
        selectedInput = ctl1Id + "hours";
        //We're going to go ahead and select it to take focus away from the last selected input
        document.getElementById(selectedInput).select();
    }
    
    //Now, we want to see which time element is selected, and call the correct spinner
    if(selectedInput.match("hours") != null)
    {
        //Make sure selectedInput is hilighted
        document.getElementById(selectedInput).className = "timeSpinnerInputSelected";
        spinHours(direction);
    }
    else if(selectedInput.match("minutes") != null)
    {
        //Make sure selectedInput is hilighted
        document.getElementById(selectedInput).className = "timeSpinnerInputSelected";
        spinMinutes(direction);
    }
    else if(selectedInput.match("seconds") != null)
    {
        //Make sure selectedInput is hilighted
        document.getElementById(selectedInput).className = "timeSpinnerInputSelected";
        spinSeconds(direction);
    }
    else if(selectedInput.match("ampmMarker") != null)
    {
        //Make sure selectedInput is hilighted
        document.getElementById(selectedInput).className = "timeSpinnerInputSelected";
        spinMarker();
    }
    
    //Now, we want to recursively call our function in case the user holds the mouse down.  We also want to add
    // a stall, so if the user holds the mouse down for the set amount of iterations, the recursive calls become faster
    if(stallCounter < 3)
    {
        timeout = window.setTimeout("startSpinner(\""+ctl1Id+"\", \""+direction+"\")", 500);
    }
    else if(stallCounter < 13)
    {
        timeout = window.setTimeout("startSpinner(\""+ctl1Id+"\", \""+direction+"\")", 100);
    }
    else if(stallCounter < 60)
    {
        timeout = window.setTimeout("startSpinner(\""+ctl1Id+"\", \""+direction+"\")", 50);
    }
    else
    {
        timeout = window.setTimeout("startSpinner(\""+ctl1Id+"\", \""+direction+"\")", 1);
    }
    stallCounter++;
}

/*
 * Once the mouse button is released (mouseup event), we want to stop our recursive call and reset our stall counter
 */
function stopSpinner(ctl1Id)
{
  window.clearTimeout(timeout);
  stallCounter = 0;
  updateHiddenValue(ctl1Id);
}

function updateHiddenValue(ctl1Id)
{
    var hours = "";
    var minutes = "";
    var seconds = "";
    var ampmMarker = "";
    if(document.getElementById(ctl1Id+"hours") != null)
    {
        hours = document.getElementById(ctl1Id+"hours").value;
    }
    if(document.getElementById(ctl1Id+"hours24") != null)
    {
        hours = document.getElementById(ctl1Id+"hours24").value;
    }
    if(document.getElementById(ctl1Id+"minutes") != null)
    {
        minutes = document.getElementById(ctl1Id+"minutes").value;
    }
    if(document.getElementById(ctl1Id+"seconds") != null)
    {
        seconds = document.getElementById(ctl1Id+"seconds").value;
    }
    if(document.getElementById(ctl1Id+"ampmMarker") != null)
    {
        ampmMarker = document.getElementById(ctl1Id+"ampmMarker").value;
    }

    var newTime = "";
    //Now we're going to make sure we write out the time in the correct format    
    for	(i=0;i<formatTimeElements.length;i++)
    {
        if ((formatTimeElements[i][1]=="h") || (formatTimeElements[i][1]=="hh") || (formatTimeElements[i][1]=="H") || (formatTimeElements[i][1]=="HH") || (formatTimeElements[i][1]=="k") || (formatTimeElements[i][1]=="K"))
        {
            if(i == formatTimeElements.length - 1)
            {
                newTime += formatTimeElements[i][0];
            }
            newTime += hours;
            if(i != formatTimeElements.length - 1 && i != formatTimeElements.length - 2)
            {
                newTime += formatTimeElements[i][0];
            }
        }
        else if	((formatTimeElements[i][1]=="m") || (formatTimeElements[i][1]=="mm"))
        {
            if(i == formatTimeElements.length - 1)
            {
                newTime += formatTimeElements[i][0];
            }
            newTime += minutes;
            if(i != formatTimeElements.length - 1 && i != formatTimeElements.length - 2)
            {
                newTime += formatTimeElements[i][0];
            }
        }
        else if	((formatTimeElements[i][1]=="s") || (formatTimeElements[i][1]=="ss") )
        {
            if(i == formatTimeElements.length - 1)
            {
                newTime += formatTimeElements[i][0];
            }
            newTime += seconds;
            if(i != formatTimeElements.length - 1 && i != formatTimeElements.length - 2)
            {
                newTime += formatTimeElements[i][0];
            }
        }
        else if	(formatTimeElements[i][1]=="a")
        {
            if(i == formatTimeElements.length - 1)
            {
                newTime += formatTimeElements[i][0];
            }
            newTime += ampmMarker;
            if(i != formatTimeElements.length - 1 && i != formatTimeElements.length - 2)
            {
                newTime += formatTimeElements[i][0];
            }
        }
    }

    document.getElementById(ctl1Id+"Time").value = newTime;
}

/*
 * This is were we spin the hours.  We first make sure that we grab the right span id because this function can be
 * called two different ways.  One, it could be called when the hours element is selected.  The second is if the minutes
 * roll over (ie from 59 to 0, we need to increment the hour counter).  So, if the hours element isn't selected, we
 * need to grab the correct hours element
 */
function spinHours(direction)
{
    //Grab the correct hours element
    var hoursSpanId = selectedInput;
    var regExp = new RegExp("hours$");
    if(selectedInput.match(regExp) == null)
    {
        regExp = new RegExp("minutes$|seconds$|ampmMarker$");
        var timeElement = selectedInput.match(regExp);
        var spanId = selectedInput.substring(0, selectedInput.indexOf(timeElement));
        hoursSpanId = spanId + "hours";
    }
    
    //Do a quick chech to make sure the number is valid, and if not, set it to 00
    if(!validateNumber(document.getElementById(hoursSpanId).value))
    {
        document.getElementById(hoursSpanId).value = "00";
        validHours = true;
    }
    
    //Now we're going to either add or subtract, based on our direction.  Also, if we roll over, we want to change
    // any necessary time elements.  We also want to check if this span even exists.  Because there are mulitple hour spinners
    var hours = document.getElementById(hoursSpanId).value;
    if(direction == "up")
    {
        hours = Math.abs(hours) + 1;
    }
    else
    {
        hours = Math.abs(hours) - 1;
    }

    //We want to cycle based on our upper and lower hour constraints
    if(hours > upperHourConstraint)
    {
        hours = lowerHourConstraint;
    }
    else if(hours < lowerHourConstraint)
    {
        hours = upperHourConstraint;
    }

    //This is just formatting to make sure all our digits are 2 places
    if(hours < 10)
    {
        hours = "0" + hours;
    }

    //Finally, write out our new hour
    document.getElementById(hoursSpanId).value = hours;

}

/*
 * This is were we spin the minutes.  We first make sure that we grab the right span id because this function can be
 * called two different ways.  One, it could be called when the minutes element is selected.  The second is if the seconds
 * roll over (ie from 59 to 0, we need to increment the hour counter).  So, if the minutes element isn't selected, we
 * need to grab the correct minutes element
 */
function spinMinutes(direction)
{
    //Grab the correct minutes element
    var minutesSpanId = selectedInput;
    var regExp = new RegExp("minutes$");
    if(selectedInput.match(regExp) == null)
    {
        regExp = new RegExp("hours$|seconds$|ampmMarker$");
        var timeElement = selectedInput.match(regExp);
        var spanId = selectedInput.substring(0, selectedInput.indexOf(timeElement));
        minutesSpanId = spanId + "minutes";
    }
    
    //Do a quick chech to make sure the number is valid, and if not, set it to 00
    if(!validateNumber(document.getElementById(minutesSpanId).value))
    {
        document.getElementById(minutesSpanId).value = "00";
        validMinutes = true;
    }
    
    //Now we're going to either add or subtract, based on our direction.  Also, if we roll over, we want to change
    // any necessary time elements
    var minutes = document.getElementById(minutesSpanId).value;
    if(direction == "up")
    {
        minutes = Math.abs(minutes) + 1;
    }
    else
    {
        minutes = Math.abs(minutes) - 1;
    }

    //Because we only have 60 minutes, we want to cycle if we hit 59, or -1
    if(minutes > 59)
    {
        minutes = 0;
    }
    else if(minutes < 0)
    {
        minutes = 59;
    }

    //This is just formatting to make sure all our digits are 2 places
    if(minutes < 10)
    {
        minutes = "0" + minutes;
    }
    
    //Finally, write out our new minute
    document.getElementById(minutesSpanId).value = minutes;

}

/*
 * This is were we spin the seconds.
 */
function spinSeconds(direction)
{
    var secondsSpanId = selectedInput;
    
    //Do a quick chech to make sure the number is valid, and if not, set it to 00
    if(!validateNumber(document.getElementById(secondsSpanId).value))
    {
        document.getElementById(secondsSpanId).value = "00";
        validSeconds = true;
    }
    
    //Now we're going to either add or subtract, based on our direction.  Also, if we roll over, we want to change
     // any necessary time elements
    var seconds = document.getElementById(secondsSpanId).value;
    if(direction == "up")
    {
        seconds = Math.abs(seconds) + 1;
    }
    else
    {
        seconds = Math.abs(seconds) - 1;
    }

    //Because we only have 60 seconds, we want to cycle if we hit 59, or -1
    if(seconds > 59)
    {
        seconds = 0;
    }
    else if(seconds < 0)
    {
        seconds = 59;
    }

    //This is just formatting to make sure all our digits are 2 places
    if(seconds < 10)
    {
        seconds = "0" + seconds;
    }
    
    //Finally, write out our new second
   document.getElementById(secondsSpanId).value = seconds;

}

/*
 * This is were we spin the AM PM Marker.  We first make sure that we grab the right span id because this function can be
 * called two different ways.  One, it could be called when the marker element is selected.  The second is if the hour
 * rolls over (ie from 11AM to 12PM).  So, if the marker element isn't selected, we need to grab the correct marker element
 */
function spinMarker()
{
    //Grab the correct hours element
    var ampmMarkerSpanId = selectedInput;
    var regExp = new RegExp("ampmMarker$");
    if(selectedInput.match(regExp) == null)
    {
        regExp = new RegExp("hours$|minutes$|seconds$");
        var timeElement = selectedInput.match(regExp);
        var spanId = selectedInput.substring(0, selectedInput.indexOf(timeElement));
        ampmMarkerSpanId = spanId + "ampmMarker";
    }
    
    //Now we're going to flip between AM and PM.  Basically, if the marker element is current set to AM, we set 
    // to PM, and vice versa
    var marker = document.getElementById(ampmMarkerSpanId).value;
    if(marker == "AM")
    {
        marker = "PM"
    }
    else
    {
        marker = "AM"
    }
    
    //Finally, write out our new marker
    document.getElementById(ampmMarkerSpanId).value = marker;

}

/*
 * This function is called when the individual time element is selected.  It will de-highlight the currently selected
 * element, highlight the newly selected element, and then set the global variable to represent the newly selected element
 */
function selectInput(inputName)
{
    if(document.getElementById(selectedInput) == null)
    {
        selectedInput = inputName;
    }
    
    document.getElementById(selectedInput).className = "timeSpinnerInputUnselected";
    document.getElementById(inputName).className = "timeSpinnerInputSelected";
    var regExp = new RegExp("ampmMarker$");
    if(inputName.match(regExp) == null)
    {
        document.getElementById(inputName).select();
    }

    selectedInput = inputName;
}


/*
 * This function is called when the hours entry field loses focus and will check to see that the value that was entered
 * is valid
 */
function validateHours()
{
    for(i=0;i<timeIdArray.length;i++)
    {
        var ctl1Id = timeIdArray[i];
        if(document.getElementById(ctl1Id+"hours") != null)
        {
            var hours = document.getElementById(ctl1Id+"hours").value;
            //First check is to make sure he entry field is a valid number
            var validHoursTemp = validateNumber(hours);

            if(validHoursTemp)
            {
                if(hours > upperHourConstraint)
                {
                    validHoursTemp = false;
                }
                else if(hours < lowerHourConstraint)
                {
                    validHoursTemp = false;
                }
            }

            //We need make sure that if any of the inputs are false, that our global is set to false and not later overwritten
            if((i==0) || (i > 0 && validHours))
            {
                validHours = validHoursTemp;

                if(!validHours)
                {
                    alert("You have entered an invalid value for the hours portion of the time.\nPlease fix before submitting.");    
                }
            }
        }
    }
}

/*
 * This function is called when the hours entry field loses focus and will check to see that the value that was entered
 * is valid
 */
function validateMinutes(ctl1Id)
{
    for(i=0;i<timeIdArray.length;i++)
    {
        var ctl1Id = timeIdArray[i];
        if(document.getElementById(ctl1Id+"minutes") != null)
        {
            var minutes = document.getElementById(ctl1Id+"minutes").value;
            //First check is to make sure he entry field is a valid number
            var validMinutesTemp = validateNumber(minutes);
            
            if(validMinutesTemp)
            {
                if(minutes > 59)
                {
                    validMinutesTemp = false;
                }
                else if(minutes < 0)
                {
                    validMinutesTemp = false;
                }
            }
            
            //We need make sure that if any of the inputs are false, that our global is set to false and not later overwritten
            if((i==0) || (i > 0 && validMinutes))
            {
                validMinutes = validMinutesTemp;
                if(!validMinutes)
                {
                    alert("You have entered an invalid value for the minutes portion of the time.\nPlease fix before submitting.");    
                }
            }
        }
    }
}

/*
 * This function is called when the hours entry field loses focus and will check to see that the value that was entered
 * is valid
 */
function validateSeconds(ctl1Id)
{
    for(i=0;i<timeIdArray.length;i++)
    {
        var ctl1Id = timeIdArray[i];
        if(document.getElementById(ctl1Id+"seconds") != null)
        {
            var seconds = document.getElementById(ctl1Id+"seconds").value;
            //First check is to make sure he entry field is a valid number
            var validSecondsTemp = validateNumber(seconds);
            
            if(validSecondsTemp)
            {
                if(seconds > 59)
                {
                    validSecondsTemp = false;
                }
                else if(seconds < 0)
                {
                    validSecondsTemp = false;
                }
            }
            
            //We need make sure that if any of the inputs are false, that our global is set to false and not later overwritten
            if((i==0) || (i > 0 && validSeconds))
            {
                validSeconds = validSecondsTemp;
                if(!validSeconds)
                {
                    alert("You have entered an invalid value for the seconds portion of the time.\nPlease fix before submitting.");    
                }
            }
        }
    }
}

/*
 * This function should be called from the outside to make sure that the time entered is a valid time
 */
function validTime()
{
    if(validHours && validMinutes && validSeconds)
    {
        return true;
    }
    else
    {
        return false;
    }
}
    
/*
 * This is a validation function used to check if the passed in value is a number or not
 */
function validateNumber(value)
{
    invalid = false;
    var booleanRegExp = new RegExp("^[0-9]*$");
    matchArray = value.match(booleanRegExp);
    if(matchArray == null)
    {
        invalid = true;
    }

    return !invalid;
}

/*
 * This is just a bogus function for our spinner arrows to call in their HREF.  It was added just to make it look a bit
 * cleaner (rather than calling "#" in their HREF
 */
function timeSpinner()
{
}

/*********************************************************
 * CODE FROM calendar.jsp
 *********************************************************/
 
	var fixedX = -1			// x position (-1 if to appear below control)
	var fixedY = -1			// y position (-1 if to appear below control)
	var startAt = 0			// 0 - sunday ; 1 - monday
	var showWeekNumber = 0  // 0 - don't show; 1 - show
	var showToday = 1		// 0 - don't show; 1 - show
	

	var gotoString = "Vai al mese corrente";
	var todayString = "Oggi è";
	var weekString = "Sett";
	var scrollLeftMessage  = "Click to scroll to previous month. Hold mouse button to scroll automatically.";
	var scrollRightMessage = "Click to scroll to next month. Hold mouse button to scroll automatically.";
	var selectMonthMessage = "Click to select a month.";
	var selectYearMessage  = "Click to select a year.";
	var selectDateMessage  = "[date]";            // do not replace [date], it will be replaced by date.

	var	crossobj, crossMonthObj, crossYearObj, monthSelected, yearSelected, dateSelected, omonthSelected, oyearSelected, odateSelected, monthConstructed, yearConstructed, intervalID1, intervalID2, timeoutID1, timeoutID2, ctlToPlaceValue, ctlNow, dateFormat, nStartingYear

	var	ie=document.all
	var	dom=document.getElementById

	var	ns4=document.layers
	var	today =	new	Date()
	var	dateNow	 = today.getDate()
	var	monthNow = today.getMonth()
	var	yearNow	 = today.getYear()
	var	imgsrc = new Array("drop1.gif","drop2.gif","left1.gif","left2.gif","right1.gif","right2.gif")
	var	img	= new Array()

	var bShow = false;

    /* hides <select> and <applet> objects (for IE only) */
    function hideElement( elmID, overDiv )
    {
      if( ie )
      {
        for( i = 0; i < document.all.tags( elmID ).length; i++ )
        {
          obj = document.all.tags( elmID )[i];
          if( !obj || !obj.offsetParent )
          {
            continue;
          }
      
          // Find the element's offsetTop and offsetLeft relative to the BODY tag.
          objLeft   = obj.offsetLeft;
          objTop    = obj.offsetTop;
          objParent = obj.offsetParent;
          
          while( objParent.tagName.toUpperCase() != "BODY" )
          {
            objLeft  += objParent.offsetLeft;
            objTop   += objParent.offsetTop;
            objParent = objParent.offsetParent;
          }
      
          objHeight = obj.offsetHeight;
          objWidth = obj.offsetWidth;
      
          if(( overDiv.offsetLeft + overDiv.offsetWidth ) <= objLeft );
          else if(( overDiv.offsetTop + overDiv.offsetHeight ) <= objTop );
          else if( overDiv.offsetTop >= ( objTop + objHeight ));
          else if( overDiv.offsetLeft >= ( objLeft + objWidth ));
          else
          {
            obj.style.visibility = "hidden";
          }
        }
      }
    }
     
    /*
    * unhides <select> and <applet> objects (for IE only)
    */
    function showElement( elmID )
    {
      if( ie )
      {
        for( i = 0; i < document.all.tags( elmID ).length; i++ )
        {
          obj = document.all.tags( elmID )[i];
          
          if( !obj || !obj.offsetParent )
          {
            continue;
          }
        
          obj.style.visibility = "";
        }
      }
    }

	function HolidayRec (d, m, y, desc)
	{
		this.d = d
		this.m = m
		this.y = y
		this.desc = desc
	}

	var HolidaysCounter = 0
	var Holidays = new Array()

	function addHoliday (d, m, y, desc)
	{
		Holidays[HolidaysCounter++] = new HolidayRec ( d, m, y, desc )
	}

	if (dom)
	{
		for	(i=0;i<imgsrc.length;i++)
		{
			img[i] = new Image
			img[i].src = imgDir + imgsrc[i]
		}
		//We set the zIndex over 5001 because of the 'popup' dialog framework which is at a zIndex of 5001 (and we need the 
        // calendar to sit over it)
        document.write ("<div onclick='bShow=true' id='__calendar__' style='z-index:+5999;position:absolute;visibility:hidden;'><table	width="+((showWeekNumber==1)?250:220)+" style='font-family:arial;font-size:11px;border-width:1;border-style:solid;border-color:#a0a0a0;font-family:arial; font-size:11px}' bgcolor='#ffffff'><tr bgcolor='#0000aa'><td><table width='"+((showWeekNumber==1)?248:218)+"'><tr><td style='padding:2px;font-family:arial; font-size:11px;'><font color='#ffffff'><B><span id='caption'></span></B></font></td><td align=right><a href='javascript:hideCalendar()'><IMG SRC='"+imgDir+"close.gif' WIDTH='15' HEIGHT='13' BORDER='0' ALT='Close the Calendar'></a></td></tr></table></td></tr><tr><td style='padding:5px' bgcolor=#ffffff><span id='content'></span></td></tr>")
			
		if (showToday==1)
		{
			document.write ("<tr bgcolor=#f0f0f0><td style='padding:5px' align=center><span id='lblToday'></span></td></tr>")
		}
			
		document.write ("</table></div><div id='selectMonth' style='z-index:+5999;position:absolute;visibility:hidden;'></div><div id='selectYear' style='z-index:+5999;position:absolute;visibility:hidden;'></div>");
	}

	var	monthName =	new	Array("Gennaio","Febbraio","Marzo","Aprile","Maggio","Giugno","Luglio","Agosto","Settembre","Ottobre","Novembre","Dicembre")
	if (startAt==0)
	{
		dayName = new Array	("Dom","Lun","Mar","Mer","Gio","Ven","Sab")
	}
	else
	{
		dayName = new Array	("Lun","Mar","Mer","Gio","Ven","Sab","Dom")
	}
	var	styleAnchor="text-decoration:none;color:black;"
	var	styleLightBorder="border-style:solid;border-width:1px;border-color:#a0a0a0;"

	function swapImage(srcImg, destImg){
		if (ie)	{ document.getElementById(srcImg).setAttribute("src",imgDir + destImg) }
	}

	function init()	{
		if (!ns4)
		{
			if (!ie) { yearNow += 1900	}

			crossobj=(dom)?document.getElementById("__calendar__").style : ie? document.all.calendar : document.calendar
			hideCalendar()

			crossMonthObj=(dom)?document.getElementById("selectMonth").style : ie? document.all.selectMonth	: document.selectMonth

			crossYearObj=(dom)?document.getElementById("selectYear").style : ie? document.all.selectYear : document.selectYear

			monthConstructed=false;
			yearConstructed=false;

			if (showToday==1)
			{
				document.getElementById("lblToday").innerHTML =	todayString + " <a onmousemove='window.status=\""+gotoString+"\"' onmouseout='window.status=\"\"' title='"+gotoString+"' style='"+styleAnchor+"' href='javascript:monthSelected=monthNow;yearSelected=yearNow;constructCalendar();'>"+dayName[(today.getDay()-startAt==-1)?6:(today.getDay()-startAt)]+", " + dateNow + " " + monthName[monthNow].substring(0,3)	+ "	" +	yearNow	+ "</a>"
			}

			sHTML1="<span id='spanLeft'	style='border-style:solid;border-width:1;border-color:#3366FF;cursor:pointer' onmouseover='swapImage(\"changeLeft\",\"left2.gif\");this.style.borderColor=\"#88AAFF\";window.status=\""+scrollLeftMessage+"\"' onclick='javascript:decMonth()' onmouseout='clearInterval(intervalID1);swapImage(\"changeLeft\",\"left1.gif\");this.style.borderColor=\"#3366FF\";window.status=\"\"' onmousedown='clearTimeout(timeoutID1);timeoutID1=setTimeout(\"StartDecMonth()\",500)'	onmouseup='clearTimeout(timeoutID1);clearInterval(intervalID1)'>&nbsp<IMG id='changeLeft' SRC='"+imgDir+"left1.gif' width=10 height=11 BORDER=0>&nbsp</span>&nbsp;"
			sHTML1+="<span id='spanRight' style='border-style:solid;border-width:1;border-color:#3366FF;cursor:pointer'	onmouseover='swapImage(\"changeRight\",\"right2.gif\");this.style.borderColor=\"#88AAFF\";window.status=\""+scrollRightMessage+"\"' onmouseout='clearInterval(intervalID1);swapImage(\"changeRight\",\"right1.gif\");this.style.borderColor=\"#3366FF\";window.status=\"\"' onclick='incMonth()' onmousedown='clearTimeout(timeoutID1);timeoutID1=setTimeout(\"StartIncMonth()\",500)'	onmouseup='clearTimeout(timeoutID1);clearInterval(intervalID1)'>&nbsp<IMG id='changeRight' SRC='"+imgDir+"right1.gif'	width=10 height=11 BORDER=0>&nbsp</span>&nbsp"
			sHTML1+="<span id='spanMonth' style='border-style:solid;border-width:1;border-color:#3366FF;cursor:pointer'	onmouseover='swapImage(\"changeMonth\",\"drop2.gif\");this.style.borderColor=\"#88AAFF\";window.status=\""+selectMonthMessage+"\"' onmouseout='swapImage(\"changeMonth\",\"drop1.gif\");this.style.borderColor=\"#3366FF\";window.status=\"\"' onclick='popUpMonth()'></span>&nbsp;"
			sHTML1+="<span id='spanYear' style='border-style:solid;border-width:1;border-color:#3366FF;cursor:pointer' onmouseover='swapImage(\"changeYear\",\"drop2.gif\");this.style.borderColor=\"#88AAFF\";window.status=\""+selectYearMessage+"\"'	onmouseout='swapImage(\"changeYear\",\"drop1.gif\");this.style.borderColor=\"#3366FF\";window.status=\"\"'	onclick='popUpYear()'></span>&nbsp;"
			
			document.getElementById("caption").innerHTML  =	sHTML1

		}
	}

	function hideCalendar()	
	{
		crossobj.visibility="hidden"
		if (crossMonthObj != null){crossMonthObj.visibility="hidden"}
		if (crossYearObj !=	null){crossYearObj.visibility="hidden"}

	    showElement( 'SELECT' );
		showElement( 'APPLET' );

        var timeoutText = "toScroll(" + document.body.scrollTop + "," + document.body.scrollLeft + ");";
        setTimeout(timeoutText, 20);
	}

	function padZero(num) {
		return (num	< 10)? '0' + num : num ;
	}

	function constructDate(d,m,y)
	{
		sTmp = dateFormat
        sTmp = sTmp.replace	("dd","<e>")
		sTmp = sTmp.replace	("d","<d>")
		sTmp = sTmp.replace	("<e>",padZero(d))
		sTmp = sTmp.replace	("<d>",d)
		sTmp = sTmp.replace	("yyyy","<z>")             
		sTmp = sTmp.replace	("yy","<y>")             
		sTmp = sTmp.replace	("MMMM","<o>")             // January
		sTmp = sTmp.replace	("MMM","<k>")              // Jan
		sTmp = sTmp.replace	("MM","<n>")               // 01
		sTmp = sTmp.replace	("M","<m>")                // 1
		sTmp = sTmp.replace	("<m>",m+1)
		sTmp = sTmp.replace	("<n>",padZero(m+1))
		sTmp = sTmp.replace	("<o>",monthName[m])
		sTmp = sTmp.replace ("<k>",monthName[m].substring(0, 3));
		sTmp.replace ("<y>",y.toString().substring(2));
		return sTmp.replace ("<z>",y);
	}

	function closeCalendar() {
		var	sTmp

        var isTimeValid = true;
        if(document.getElementById(ctlToPlaceValue.id+"TimeSpinner") != null)
        {
            isTimeValid = validTime();
        }
		
        if(isTimeValid)
        {
            hideCalendar();

            if(ctlToPlaceValue.type == "text")
            {
                if(document.getElementById(ctlToPlaceValue.id+"TimeSpinner") != null)
                {
                    ctlToPlaceValue.value =	constructDateTime(constructDate(dateSelected,monthSelected,yearSelected));
                    //20071219 funzione richiamo controllo data form anagrafica
                    try
                    {
                        validateFormDate();
                    }
                    catch(e){}
                }
                else
                {
                    ctlToPlaceValue.value =	constructDate(dateSelected,monthSelected,yearSelected);
                    try
                    {
                        validateFormDate();
                    }
                    catch(e){}
                }
            }
            else
            {
                if(document.getElementById(ctlToPlaceValue.id+"TimeSpinner") != null)
                {
                    ctlToPlaceValue.innerHTML =	constructDateTime(constructDate(dateSelected,monthSelected,yearSelected));
                }
                else
                {
                    ctlToPlaceValue.innerHTML =	constructDate(dateSelected,monthSelected,yearSelected);
                }
            }
        }
        else
        {
            alert("You have entered an invalid time.  Please fix and re-submit.");
        }
	}

    function constructDateTime(date)
    {
        var dateTimeFormat = "dd-MM-yyyy hh:mm:ss a";
        var timeFormat = "hh:mm:ss a";
        dateTimeFormat = dateTimeFormat.replace(dateFormat, date);
        dateTimeFormat = dateTimeFormat.replace(timeFormat, document.getElementById(ctlToPlaceValue.id+"TimeSpinnerTime").value);
        return dateTimeFormat;
    }

	/*** Month Pulldown	***/

	function StartDecMonth()
	{
		intervalID1=setInterval("decMonth()",80)
	}

	function StartIncMonth()
	{
		intervalID1=setInterval("incMonth()",80)
	}

	function incMonth () {
		monthSelected++
		if (monthSelected>11) {
			monthSelected=0
			yearSelected++
		}
		constructCalendar()
	}

	function decMonth () {
		monthSelected--
		if (monthSelected<0) {
			monthSelected=11
			yearSelected--
		}
		constructCalendar()
	}

	function constructMonth() {
		popDownYear()
		if (!monthConstructed) {
			sHTML =	""
			for	(i=0; i<12;	i++) {
				sName =	monthName[i];
				if (i==monthSelected){
					sName =	"<B>" +	sName +	"</B>"
				}
				sHTML += "<tr><td id='m" + i + "' onmouseover='this.style.backgroundColor=\"#FFCC99\"' onmouseout='this.style.backgroundColor=\"\"' style='cursor:pointer' onclick='monthConstructed=false;monthSelected=" + i + ";constructCalendar();popDownMonth();event.cancelBubble=true'>&nbsp;" + sName + "&nbsp;</td></tr>"
			}

			document.getElementById("selectMonth").innerHTML = "<table width=70	style='font-family:arial; font-size:11px; border-width:1; border-style:solid; border-color:#a0a0a0;' bgcolor='#FFFFDD' cellspacing=0 onmouseover='clearTimeout(timeoutID1)'	onmouseout='clearTimeout(timeoutID1);timeoutID1=setTimeout(\"popDownMonth()\",100);event.cancelBubble=true'>" +	sHTML +	"</table>"

			monthConstructed=true
		}
	}

	function popUpMonth() {
		constructMonth()
		crossMonthObj.visibility = (dom||ie)? "visible"	: "show"
		crossMonthObj.left = parseInt(crossobj.left) + 50
		crossMonthObj.top =	parseInt(crossobj.top) + 26

		hideElement( 'SELECT', document.getElementById("selectMonth") );
		hideElement( 'APPLET', document.getElementById("selectMonth") );			
	}

	function popDownMonth()	{
		crossMonthObj.visibility= "hidden"
	}

	/*** Year Pulldown ***/

	function incYear() {
		for	(i=0; i<7; i++){
			newYear	= (i+nStartingYear)+1
			if (newYear==yearSelected)
			{ txtYear =	"&nbsp;<B>"	+ newYear +	"</B>&nbsp;" }
			else
			{ txtYear =	"&nbsp;" + newYear + "&nbsp;" }
			document.getElementById("y"+i).innerHTML = txtYear
		}
		nStartingYear ++;
		bShow=true
	}

	function decYear() {
		//We only want the calendar to go down to the year 1000 AD.  This is for two resons;One being that we wanted to follow the 
        // model that exists within the IDE, the second being that when Phil parses expressions based on date, he can assume the dates 
        // are AD (and there should be no reason would want to enter in a BC date)
        if(nStartingYear > 1000)
        {
            for	(i=0; i<7; i++){
                newYear	= (i+nStartingYear)-1
                if (newYear==yearSelected)
                { txtYear =	"&nbsp;<B>"	+ newYear +	"</B>&nbsp;" }
                else
                { txtYear =	"&nbsp;" + newYear + "&nbsp;" }
                document.getElementById("y"+i).innerHTML = txtYear
            }
            nStartingYear --;
        }
        bShow=true
	}

	function selectYear(nYear) {
		yearSelected=parseInt(nYear+nStartingYear);
		yearConstructed=false;
		constructCalendar();
		popDownYear();
	}

	function constructYear() {
		popDownMonth()
		sHTML =	""
		if (!yearConstructed) {

            sHTML =	"<tr><td align='center'	onmouseover='this.style.backgroundColor=\"#FFCC99\"' onmouseout='clearInterval(intervalID1);this.style.backgroundColor=\"\"' style='cursor:pointer'	onmousedown='clearInterval(intervalID1);intervalID1=setInterval(\"decYear()\",30)' onmouseup='clearInterval(intervalID1)'>-</td></tr>"

			j =	0
			nStartingYear =	yearSelected-3
			for	(i=(yearSelected-3); i<=(yearSelected+3); i++) {
				sName =	i;
				if (i==yearSelected){
					sName =	"<B>" +	sName +	"</B>"
				}

				sHTML += "<tr><td id='y" + j + "' onmouseover='this.style.backgroundColor=\"#FFCC99\"' onmouseout='this.style.backgroundColor=\"\"' style='cursor:pointer' onclick='selectYear("+j+");event.cancelBubble=true'>&nbsp;" + sName + "&nbsp;</td></tr>"
				j ++;
			}

			sHTML += "<tr><td align='center' onmouseover='this.style.backgroundColor=\"#FFCC99\"' onmouseout='clearInterval(intervalID2);this.style.backgroundColor=\"\"' style='cursor:pointer' onmousedown='clearInterval(intervalID2);intervalID2=setInterval(\"incYear()\",30)'	onmouseup='clearInterval(intervalID2)'>+</td></tr>"

			document.getElementById("selectYear").innerHTML	= "<table width=44 style='font-family:arial; font-size:11px; border-width:1; border-style:solid; border-color:#a0a0a0;'	bgcolor='#FFFFDD' onmouseover='clearTimeout(timeoutID2)' onmouseout='clearTimeout(timeoutID2);timeoutID2=setTimeout(\"popDownYear()\",100)' cellspacing=0>"	+ sHTML	+ "</table>"

			yearConstructed	= true
		}
	}

	function popDownYear() {
		clearInterval(intervalID1)
		clearTimeout(timeoutID1)
		clearInterval(intervalID2)
		clearTimeout(timeoutID2)
		crossYearObj.visibility= "hidden"
	}

	function popUpYear() {
		var	leftOffset

		constructYear()
		crossYearObj.visibility	= (dom||ie)? "visible" : "show"
		leftOffset = parseInt(crossobj.left) + document.getElementById("spanYear").offsetLeft
		if (ie)
		{
			leftOffset += 6
		}
		crossYearObj.left =	leftOffset
		crossYearObj.top = parseInt(crossobj.top) +	26
	}

	/*** calendar ***/
   function WeekNbr(n) {
      // Algorithm used:
      // From Klaus Tondering's Calendar document (The Authority/Guru)
      // hhtp://www.tondering.dk/claus/calendar.html
      // a = (14-month) / 12
      // y = year + 4800 - a
      // m = month + 12a - 3
      // J = day + (153m + 2) / 5 + 365y + y / 4 - y / 100 + y / 400 - 32045
      // d4 = (J + 31741 - (J mod 7)) mod 146097 mod 36524 mod 1461
      // L = d4 / 1460
      // d1 = ((d4 - L) mod 365) + L
      // WeekNumber = d1 / 7 + 1
 
      year = n.getFullYear();
      month = n.getMonth() + 1;
      if (startAt == 0) {
         day = n.getDate() + 1;
      }
      else {
         day = n.getDate();
      }
 
      a = Math.floor((14-month) / 12);
      y = year + 4800 - a;
      m = month + 12 * a - 3;
      b = Math.floor(y/4) - Math.floor(y/100) + Math.floor(y/400);
      J = day + Math.floor((153 * m + 2) / 5) + 365 * y + b - 32045;
      d4 = (((J + 31741 - (J % 7)) % 146097) % 36524) % 1461;
      L = Math.floor(d4 / 1460);
      d1 = ((d4 - L) % 365) + L;
      week = Math.floor(d1/7) + 1;
 
      return week;
   }

	function constructCalendar () {
		var aNumDays = Array (31,0,31,30,31,30,31,31,30,31,30,31)

		var dateMessage
		var	startDate =	new	Date (yearSelected,monthSelected,1)
		var endDate

		if (monthSelected==1)
		{
			endDate	= new Date (yearSelected,monthSelected+1,1);
			endDate	= new Date (endDate	- (24*60*60*1000));
			numDaysInMonth = endDate.getDate()
		}
		else
		{
			numDaysInMonth = aNumDays[monthSelected];
		}

		datePointer	= 0
		dayPointer = startDate.getDay() - startAt
		
		if (dayPointer<0)
		{
			dayPointer = 6
		}

		sHTML =	"<table	 border=0 style='font-family:verdana;font-size:10px;'><tr>"

		if (showWeekNumber==1)
		{
			sHTML += "<td width=27><b>" + weekString + "</b></td><td width=1 rowspan=7 bgcolor='#d0d0d0' style='padding:0px'><img src='"+imgDir+"divider.gif' width=1></td>"
		}

		for	(i=0; i<7; i++)	{
			sHTML += "<td width='27' align='right'><B>"+ dayName[i]+"</B></td>"
		}
		sHTML +="</tr><tr>"
		
		if (showWeekNumber==1)
		{
			sHTML += "<td align=right>" + WeekNbr(startDate) + "&nbsp;</td>"
		}

		for	( var i=1; i<=dayPointer;i++ )
		{
			sHTML += "<td>&nbsp;</td>"
		}
	
		for	( datePointer=1; datePointer<=numDaysInMonth; datePointer++ )
		{
			dayPointer++;
			sHTML += "<td align=right>"
			sStyle=styleAnchor
			if ((datePointer==odateSelected) &&	(monthSelected==omonthSelected)	&& (yearSelected==oyearSelected))
			{ sStyle+=styleLightBorder }

			sHint = ""
			for (k=0;k<HolidaysCounter;k++)
			{
				if ((parseInt(Holidays[k].d)==datePointer)&&(parseInt(Holidays[k].m)==(monthSelected+1)))
				{
					if ((parseInt(Holidays[k].y)==0)||((parseInt(Holidays[k].y)==yearSelected)&&(parseInt(Holidays[k].y)!=0)))
					{
						sStyle+="background-color:#FFDDDD;"
						sHint+=sHint==""?Holidays[k].desc:"\n"+Holidays[k].desc
					}
				}
			}

			var regexp= /\"/g
			sHint=sHint.replace(regexp,"&quot;")

			dateMessage = "onmousemove='window.status=\""+selectDateMessage.replace("[date]",constructDate(datePointer,monthSelected,yearSelected))+"\"' onmouseout='window.status=\"\"' "

			if ((datePointer==dateNow)&&(monthSelected==monthNow)&&(yearSelected==yearNow))
			{ sHTML += "<b><a "+dateMessage+" title=\"" + sHint + "\" style='"+sStyle+"' href='javascript:dateSelected="+datePointer+";closeCalendar();'><font color=#ff0000>&nbsp;" + datePointer + "</font>&nbsp;</a></b>"}
			else if	(dayPointer % 7 == (startAt * -1)+1)
			{ sHTML += "<a "+dateMessage+" title=\"" + sHint + "\" style='"+sStyle+"' href='javascript:dateSelected="+datePointer + ";closeCalendar();'>&nbsp;<font color=#909090>" + datePointer + "</font>&nbsp;</a>" }
			else
			{ sHTML += "<a "+dateMessage+" title=\"" + sHint + "\" style='"+sStyle+"' href='javascript:dateSelected="+datePointer + ";closeCalendar();'>&nbsp;" + datePointer + "&nbsp;</a>" }

			sHTML += ""
			if ((dayPointer+startAt) % 7 == startAt) { 
				sHTML += "</tr><tr>" 
				if ((showWeekNumber==1)&&(datePointer<numDaysInMonth))
				{
					sHTML += "<td align=right>" + (WeekNbr(new Date(yearSelected,monthSelected,datePointer+1))) + "&nbsp;</td>"
				}
			}
		}

		document.getElementById("content").innerHTML   = sHTML
		document.getElementById("spanMonth").innerHTML = "&nbsp;" +	monthName[monthSelected] + "&nbsp;<IMG id='changeMonth' SRC='"+imgDir+"drop1.gif' WIDTH='12' HEIGHT='10' BORDER=0>"
		document.getElementById("spanYear").innerHTML =	"&nbsp;" + yearSelected	+ "&nbsp;<IMG id='changeYear' SRC='"+imgDir+"drop1.gif' WIDTH='12' HEIGHT='10' BORDER=0>"
	}

	function popUpCalendar(ctl,	ctl2, showTimeSpinner) 
	{
		var	leftpos=0;
		var	toppos=0;
		
		var sTop = document.body.scrollTop;
		var sLeft = document.body.scrollLeft;

		if ( crossobj.visibility ==	"hidden" ) 
        {
			ctlToPlaceValue	= ctl2
			dateFormat='dd/MM/yyyy';

			formatChar = " "
			aFormat	= dateFormat.split(formatChar)
			if (aFormat.length<3)
			{
				formatChar = "/"
				aFormat	= dateFormat.split(formatChar)
				if (aFormat.length<3)
				{
					formatChar = "."
					aFormat	= dateFormat.split(formatChar)
					if (aFormat.length<3)
					{
						formatChar = "-"
						aFormat	= dateFormat.split(formatChar)
						if (aFormat.length<3)
						{
							// invalid date	format
							formatChar=""
						}
					}
				}
			}

            var userTime = "";
            // use user's date
            if(ctl2.type == "text")
            {
                userTime =	ctl2.value;
            }
            else
            {
                userTime =	ctl2.innerHTML;
            }
            tokensChanged =	0
			if ( formatChar	!= "" )
			{

                aData = userTime.split(formatChar);

				for	(i=0;i<3;i++)
				{
					if ((aFormat[i]=="d") || (aFormat[i]=="dd"))
					{
						dateSelected = parseInt(aData[i], 10)
						tokensChanged ++
					}
					else if	((aFormat[i]=="MM") || (aFormat[i]=="MMM"))
					{
						monthSelected =	parseInt(aData[i], 10) - 1
						tokensChanged ++
					}
					else if	(aFormat[i]=="yyyy")
					{
						yearSelected = parseInt(aData[i], 10)
						tokensChanged ++
					}
					else if	(aFormat[i]=="MMMM")
					{
						for	(j=0; j<12;	j++)
						{
							if (aData[i]==monthName[j])
							{
								monthSelected=j
								tokensChanged ++
							}
						}
					}
				}
			}

			if ((tokensChanged!=3)||isNaN(dateSelected)||isNaN(monthSelected)||isNaN(yearSelected))
			{
				dateSelected = dateNow
				monthSelected =	monthNow
				yearSelected = yearNow
			}

			odateSelected=dateSelected
			omonthSelected=monthSelected
			oyearSelected=yearSelected

			aTag = ctl
			do {
				aTag = aTag.offsetParent;
				leftpos	+= aTag.offsetLeft;
				toppos += aTag.offsetTop;
			} while(aTag.tagName!="BODY");

			crossobj.left =	fixedX==-1 ? ctl.offsetLeft	+ leftpos :	fixedX
			crossobj.top = fixedY==-1 ?	ctl.offsetTop +	toppos + ctl.offsetHeight +	2 :	fixedY
			constructCalendar (1, monthSelected, yearSelected);
			crossobj.visibility=(dom||ie)? "visible" : "show"

			hideElement( 'SELECT', document.getElementById("__calendar__") );
			hideElement( 'APPLET', document.getElementById("__calendar__") );			

			bShow = true;

            if (showToday==1)
            {
                if(showTimeSpinner == true)
                {
                    newInnerHTML = "";
                    newInnerHTML    += "<TABLE>";
                    newInnerHTML    += "<TR>";
                    newInnerHTML    += "<TD>";
                    newInnerHTML    += "<SPAN ID='"+ctl2.id+"TimeSpinner'>";
                    newInnerHTML    += userTime;
                    newInnerHTML    += "</SPAN>";
                    newInnerHTML    += "</TD>";
                    newInnerHTML    += "<TD>";
                    newInnerHTML    += "<A HREF='javascript:closeCalendar()'>";
                    newInnerHTML    += "<IMG NAME='calendarDone' SRC='framework/skins/beaTools/images/button_done.gif' WIDTH='38' HEIGHT='18' ALT='"+"Click to select updated date and time."+"' BORDER='0' HSPACE='4' VSPACE='4'>";
                    newInnerHTML    += "</A>";
                    newInnerHTML    += "</TD>";
                    newInnerHTML    += "</TR>";
                    newInnerHTML    += "</TABLE>";
                    
                    document.getElementById("lblToday").innerHTML = newInnerHTML;
                    initTimeSpinner(ctl2.id+"TimeSpinner", true);
                }
                else
                {
                    document.getElementById("lblToday").innerHTML =	todayString + " <a onmousemove='window.status=\""+gotoString+"\"' onmouseout='window.status=\"\"' title='"+gotoString+"' style='"+styleAnchor+"' href='javascript:monthSelected=monthNow;yearSelected=yearNow;constructCalendar();'>"+dayName[(today.getDay()-startAt==-1)?6:(today.getDay()-startAt)]+", " + dateNow + " " + monthName[monthNow].substring(0,3)	+ "	" +	yearNow	+ "</a>"
                }
            }
            
            var timeoutText = "toScroll(" + sTop + "," + sLeft + ");";
            setTimeout(timeoutText, 1);

        }
	}

	document.onclick = function hidecal2 (event) { 		
		if (!bShow)
		{
			hideCalendar()
		}
		bShow = false
	}
	
	function toScroll(top, left)
	{
	   //window.scrollTo(left, top);
	}

    init();
