//This variable holds the input element that is the selected time element that the spinner will operate on
// (i.e. the hours input)
var ts_selectedInput = null;

//The variable will hold the TimeOut object that will be used for the automatic scrolling while holding the mouse button down
var ts_timeout = null;

//This variable is a counter so that the automatic scrolling starts out slow, then gets faster with iterations
var ts_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 ts_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 ts_lowerHourConstraint = 1;
var ts_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 ts_validHours = true;
var ts_validMinutes = true;
var ts_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 ts_timeIdArray = new Array();

// i18n variables
var i18n_ts_time_format;
var i18n_ts_calendar_format_with_time;
var i18n_ts_click_to_spin;
var i18n_ts_invalid_hours;
var i18n_ts_invalid_minutes;
var i18n_ts_invalid_seconds;
var i18n_ts_am;
var i18n_ts_pm;

var ts_resourceRootPath;


/* 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, ts_resourceRootPath, p_format)
{
    this.ts_resourceRootPath = ts_resourceRootPath;
    //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;
    if ( time == null )
    {
        time = "";
    }

    //Now we add the control id to our global array
    ts_timeIdArray[ts_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
    ts_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)
    {
       if ( p_format != null && p_format.length>0 )
       {
           dateFormat = timePortionOfFormat2(p_format);
       }
       else
       {
           dateFormat = i18n_ts_time_format;
       }
       // replace with 12:00:00 AM
       time = dateFormat;
       time = time.replace("hh", "12");
       time = time.replace("HH", "00");
       time = time.replace("mm", "00");
       time = time.replace("ss", "00");
       time = time.replace("K", "00");
       time = time.replace("k", "01");
       time = time.replace("a", i18n_ts_am);
    }
    else if (p_format!=null && p_format.length>0 )
    {
        dateFormat = p_format;
    }
    else if(fromCalendar)
    {
        dateFormat=i18n_ts_calendar_format_with_time;
    }
    else
    {
        dateFormat=i18n_ts_time_format;
    }
    //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]=="Z")
        {
            // ignore
        }
        else if(aFormat[i].length < 3)
        {
            ts_formatTimeElements[ts_formatTimeElements.length] = new Array();
            ts_formatTimeElements[ts_formatTimeElements.length-1][0] = aformatChar;
            ts_formatTimeElements[ts_formatTimeElements.length-1][1] = aFormat[i];
            ts_formatTimeElements[ts_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)
                {
                    ts_formatTimeElements[ts_formatTimeElements.length] = new Array();
                    ts_formatTimeElements[ts_formatTimeElements.length-1][0] = bformatChar;
                    ts_formatTimeElements[ts_formatTimeElements.length-1][1] = bFormat[j];
                    ts_formatTimeElements[ts_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)
                        {
                            ts_formatTimeElements[ts_formatTimeElements.length] = new Array();
                            ts_formatTimeElements[ts_formatTimeElements.length-1][0] = cformatChar;
                            ts_formatTimeElements[ts_formatTimeElements.length-1][1] = cFormat[k];
                            ts_formatTimeElements[ts_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 nowrap>";
    //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<ts_formatTimeElements.length;i++)
    {
        if ((ts_formatTimeElements[i][1]=="h") || (ts_formatTimeElements[i][1]=="hh"))
        {
            if(i == ts_formatTimeElements.length - 1)
            {
                newInnerHTML += "&nbsp;"+ts_formatTimeElements[i][0]+"&nbsp;";
                timeOnly += ts_formatTimeElements[i][0];
            }
            newInnerHTML += "<INPUT TYPE='text' size='4' ID=\""+ctl1.id+"hours\" onBlur=\"stopSpinner('"+ctl1.id+"')\" onFocus=\"selectInput('"+ctl1.id+"hours')\" onBlur=\"validateHours()\" value='"+ts_formatTimeElements[i][2]+"' maxlength='2' class='timeSpinnerInputUnselected'>";
            timeOnly += ts_formatTimeElements[i][2];
            if(i != ts_formatTimeElements.length - 1 && i != ts_formatTimeElements.length - 2)
            {
                newInnerHTML += "&nbsp;"+ts_formatTimeElements[i][0]+"&nbsp;";
                timeOnly += ts_formatTimeElements[i][0];
            }
            ts_lowerHourConstraint = 1;
            ts_upperHourConstraint = 12;
        }
        else if	((ts_formatTimeElements[i][1]=="H") || (ts_formatTimeElements[i][1]=="HH"))
        {
            if(i == ts_formatTimeElements.length - 1)
            {
                newInnerHTML += "&nbsp;"+ts_formatTimeElements[i][0]+"&nbsp;";
                timeOnly += ts_formatTimeElements[i][0];
            }
            newInnerHTML += "<INPUT TYPE='text' size='4' ID=\""+ctl1.id+"hours\" onBlur=\"stopSpinner('"+ctl1.id+"')\" onFocus=\"selectInput('"+ctl1.id+"hours')\" onBlur=\"validateHours()\" value='"+ts_formatTimeElements[i][2]+"' maxlength='2' class='timeSpinnerInputSelected'>";
            ts_selectedInput = ctl1.id + "hours";
            timeOnly += ts_formatTimeElements[i][2];
            if(i != ts_formatTimeElements.length - 1 && i != ts_formatTimeElements.length - 2)
            {
                newInnerHTML += "&nbsp;"+ts_formatTimeElements[i][0]+"&nbsp;";
                timeOnly += ts_formatTimeElements[i][0];
            }
            ts_lowerHourConstraint = 0;
            ts_upperHourConstraint = 23;
        }
        else if	((ts_formatTimeElements[i][1]=="k"))
        {
            if(i == ts_formatTimeElements.length - 1)
            {
                newInnerHTML += "&nbsp;"+ts_formatTimeElements[i][0]+"&nbsp;";
                timeOnly += ts_formatTimeElements[i][0];
            }
            newInnerHTML += "<INPUT TYPE='text' size='4' ID=\""+ctl1.id+"hours\" onBlur=\"stopSpinner('"+ctl1.id+"')\" onFocus=\"selectInput('"+ctl1.id+"hours')\" onBlur=\"validateHours()\" value='"+ts_formatTimeElements[i][2]+"' maxlength='2' class='timeSpinnerInputUnselected'>";
            timeOnly += ts_formatTimeElements[i][2];
            if(i != ts_formatTimeElements.length - 1 && i != ts_formatTimeElements.length - 2)
            {
                newInnerHTML += "&nbsp;"+ts_formatTimeElements[i][0]+"&nbsp;";
                timeOnly += ts_formatTimeElements[i][0];
            }
            ts_lowerHourConstraint = 1;
            ts_upperHourConstraint = 24;
        }
        else if	((ts_formatTimeElements[i][1]=="K"))
        {
            if(i == ts_formatTimeElements.length - 1)
            {
                newInnerHTML += "&nbsp;"+ts_formatTimeElements[i][0]+"&nbsp;";
                timeOnly += ts_formatTimeElements[i][0];
            }
            newInnerHTML += "<INPUT TYPE='text' size='4' ID=\""+ctl1.id+"hours\" onBlur=\"stopSpinner('"+ctl1.id+"')\" onFocus=\"selectInput('"+ctl1.id+"hours')\" onBlur=\"validateHours()\" value='"+ts_formatTimeElements[i][2]+"' maxlength='2' class='timeSpinnerInputUnselected'>";
            timeOnly += ts_formatTimeElements[i][2];
            if(i != ts_formatTimeElements.length - 1 && i != ts_formatTimeElements.length - 2)
            {
                newInnerHTML += "&nbsp;"+ts_formatTimeElements[i][0]+"&nbsp;";
                timeOnly += ts_formatTimeElements[i][0];
            }
            ts_lowerHourConstraint = 0;
            ts_upperHourConstraint = 11;
        }
        else if	((ts_formatTimeElements[i][1]=="m") || (ts_formatTimeElements[i][1]=="mm"))
        {
            if(i == ts_formatTimeElements.length - 1)
            {
                newInnerHTML += "&nbsp;"+ts_formatTimeElements[i][0]+"&nbsp;";
                timeOnly += ts_formatTimeElements[i][0];
            }
            newInnerHTML += "<INPUT TYPE='text' size='4' ID=\""+ctl1.id+"minutes\" onBlur=\"stopSpinner('"+ctl1.id+"')\" onFocus=\"selectInput('"+ctl1.id+"minutes')\" onBlur=\"validateMinutes('"+ctl1.id+"minutes')\" value='"+ts_formatTimeElements[i][2]+"' maxlength='2' class='timeSpinnerInputUnselected'>";
            timeOnly += ts_formatTimeElements[i][2];
            if(i != ts_formatTimeElements.length - 1 && i != ts_formatTimeElements.length - 2)
            {
                newInnerHTML += "&nbsp;"+ts_formatTimeElements[i][0]+"&nbsp;";
                timeOnly += ts_formatTimeElements[i][0];
            }
        }
        else if	((ts_formatTimeElements[i][1]=="s") || (ts_formatTimeElements[i][1]=="ss") )
        {
            if(i == ts_formatTimeElements.length - 1)
            {
                newInnerHTML += "&nbsp;"+ts_formatTimeElements[i][0]+"&nbsp;";
                timeOnly += ts_formatTimeElements[i][0];
            }
            newInnerHTML += "<INPUT TYPE='text' size='4' ID=\""+ctl1.id+"seconds\" onBlur=\"stopSpinner('"+ctl1.id+"')\" onFocus=\"selectInput('"+ctl1.id+"seconds')\" onBlur=\"validateSeconds('"+ctl1.id+"seconds')\" value='"+ts_formatTimeElements[i][2]+"' maxlength='2' class='timeSpinnerInputUnselected'>";
            timeOnly += ts_formatTimeElements[i][2];
            if(i != ts_formatTimeElements.length - 1 && i != ts_formatTimeElements.length - 2)
            {
                newInnerHTML += "&nbsp;"+ts_formatTimeElements[i][0]+"&nbsp;";
                timeOnly += ts_formatTimeElements[i][0];
            }
        }
        else if	(ts_formatTimeElements[i][1]=="a")
        {
            if(i == ts_formatTimeElements.length - 1)
            {
                newInnerHTML += "&nbsp;"+ts_formatTimeElements[i][0]+"&nbsp;";
                timeOnly += ts_formatTimeElements[i][0];
            }
            newInnerHTML += "<INPUT TYPE='text' size='4' ID=\""+ctl1.id+"ampmMarker\" onFocus=\"selectInput('"+ctl1.id+"ampmMarker')\" value='"+ts_formatTimeElements[i][2]+"' readonly class='timeSpinnerInputUnselected'>";
            timeOnly += ts_formatTimeElements[i][2];
            if(i != ts_formatTimeElements.length - 1 && i != ts_formatTimeElements.length - 2)
            {
                newInnerHTML += "&nbsp;"+ts_formatTimeElements[i][0]+"&nbsp;";
                timeOnly += ts_formatTimeElements[i][0];
            }
        }
        else if (ts_formatTimeElements[i][1]=="Z")
        {
            // ignore
        }
    }

    newInnerHTML += "</TD>";
    newInnerHTML += "<TD>";
    newInnerHTML += "<A href='javascript:timeSpinner()' ONMOUSEDOWN=\"startSpinner('"+ctl1.id+"', 'up')\" ONMOUSEUP=\"stopSpinner('"+ctl1.id+"')\" ONMOUSEOUT=\"stopSpinner('"+ctl1.id+"')\">"
    newInnerHTML += "<IMG NAME='timeSpinnerArrowUp' SRC='" + ts_resourceRootPath + "wlp/calendar/images/icon_arrow_up.gif' WIDTH='13' HEIGHT='8' ALT='" + i18n_ts_click_to_spin + "' BORDER='0' HSPACE='4' VSPACE='4'>";
    newInnerHTML += "</A>";
    newInnerHTML += "<BR/>";
    newInnerHTML += "<A HREF='javascript:timeSpinner()'  ONMOUSEDOWN=\"startSpinner('"+ctl1.id+"', 'down')\" ONMOUSEUP=\"stopSpinner('"+ctl1.id+"')\" ONMOUSEOUT=\"stopSpinner('"+ctl1.id+"')\">";
    newInnerHTML += "<IMG ID='timeSpinnerArrowDown' SRC='" + ts_resourceRootPath + "wlp/calendar/images/icon_arrow_down.gif' WIDTH='13' HEIGHT='8' ALT='"+ i18n_ts_click_to_spin +"' BORDER='0' HSPACE='4' VSPACE='4'>";
    newInnerHTML += "</A>";
    newInnerHTML += "</TD>";
    newInnerHTML += "</TR>";
    newInnerHTML += "</TABLE>";
    newInnerHTML += "<INPUT TYPE='HIDDEN' NAME='"+ctl1.id+"Time' ID='"+ctl1.id+"Time' VALUE='"+timeOnly+"'>";
    ctl1.innerHTML = newInnerHTML;
}

/* 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 escCtl = ctl1Id.replace("\{", "\\{");
    escCtl = escCtl.replace("\}", "\\}");
    escCtl = escCtl.replace("\[", "\\[");
    escCtl = escCtl.replace("\]", "\\]");

    var regExp = new RegExp("^"+escCtl+"hours$|^"+escCtl+"hours24$|^"+escCtl+"minutes$|^"+escCtl+"seconds$|^"+escCtl+"ampmMarker$");

    if(ts_selectedInput == null)
    {
        ts_selectedInput = ctl1Id + "hours";
    }

    if(ts_selectedInput.match(regExp) == null)
    {
        if(document.getElementById(ts_selectedInput) != null)
        {
            document.getElementById(ts_selectedInput).className = "timeSpinnerInputUnselected";
        }

        ts_selectedInput = ctl1Id + "hours";
        //We're going to go ahead and select it to take focus away from the last selected input
        document.getElementById(ts_selectedInput).select();
    }

    //Now, we want to see which time element is selected, and call the correct spinner
    if(ts_selectedInput.match("hours") != null)
    {
        //Make sure ts_selectedInput is hilighted
        document.getElementById(ts_selectedInput).className = "timeSpinnerInputSelected";
        spinHours(direction);
    }
    else if(ts_selectedInput.match("minutes") != null)
    {
        //Make sure ts_selectedInput is hilighted
        document.getElementById(ts_selectedInput).className = "timeSpinnerInputSelected";
        spinMinutes(direction);
    }
    else if(ts_selectedInput.match("seconds") != null)
    {
        //Make sure ts_selectedInput is hilighted
        document.getElementById(ts_selectedInput).className = "timeSpinnerInputSelected";
        spinSeconds(direction);
    }
    else if(ts_selectedInput.match("ampmMarker") != null)
    {
        //Make sure ts_selectedInput is hilighted
        document.getElementById(ts_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(ts_stallCounter < 3)
    {
        ts_timeout = window.setTimeout("startSpinner(\""+ctl1Id+"\", \""+direction+"\")", 500);
    }
    else if(ts_stallCounter < 13)
    {
        ts_timeout = window.setTimeout("startSpinner(\""+ctl1Id+"\", \""+direction+"\")", 100);
    }
    else if(ts_stallCounter < 60)
    {
        ts_timeout = window.setTimeout("startSpinner(\""+ctl1Id+"\", \""+direction+"\")", 50);
    }
    else
    {
        ts_timeout = window.setTimeout("startSpinner(\""+ctl1Id+"\", \""+direction+"\")", 1);
    }
    ts_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(ts_timeout);
  ts_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;
    }
    //This is just formatting to make sure all our digits are 2 places
    if(hours < 10 && hours.length == 1)
    {
        hours = "0" + hours;
    }
    if(minutes < 10 && minutes.length == 1)
    {
        minutes = "0" + minutes;
    }
    if(seconds < 10 && seconds.length == 1)
    {
        seconds = "0" + seconds;
    }

    var newTime = "";
    //Now we're going to make sure we write out the time in the correct format
    for	(i=0;i<ts_formatTimeElements.length;i++)
    {
    		if ((ts_formatTimeElements[i][1]=="h") || (ts_formatTimeElements[i][1]=="hh") || (ts_formatTimeElements[i][1]=="H") || (ts_formatTimeElements[i][1]=="HH") || (ts_formatTimeElements[i][1]=="k") || (ts_formatTimeElements[i][1]=="K"))
        {
            if(i == ts_formatTimeElements.length - 1)
            {
                newTime += ts_formatTimeElements[i][0];
            }
            newTime += hours;
            if(i != ts_formatTimeElements.length - 1 && i != ts_formatTimeElements.length - 2)
            {
                newTime += ts_formatTimeElements[i][0];
            }
        }
        else if	((ts_formatTimeElements[i][1]=="m") || (ts_formatTimeElements[i][1]=="mm"))
        {
            if(i == ts_formatTimeElements.length - 1)
            {
                newTime += ts_formatTimeElements[i][0];
            }
            newTime += minutes;
            if(i != ts_formatTimeElements.length - 1 && i != ts_formatTimeElements.length - 2)
            {
                newTime += ts_formatTimeElements[i][0];
            }
        }
        else if	((ts_formatTimeElements[i][1]=="s") || (ts_formatTimeElements[i][1]=="ss") )
        {
            if(i == ts_formatTimeElements.length - 1)
            {
                newTime += ts_formatTimeElements[i][0];
            }
            newTime += seconds;
            if(i != ts_formatTimeElements.length - 1 && i != ts_formatTimeElements.length - 2)
            {
                newTime += ts_formatTimeElements[i][0];
            }
        }
        else if	(ts_formatTimeElements[i][1]=="a")
        {
            if(i == ts_formatTimeElements.length - 1)
            {
                newTime += ts_formatTimeElements[i][0];
            }
            newTime += ampmMarker;
            if(i != ts_formatTimeElements.length - 1 && i != ts_formatTimeElements.length - 2)
            {
                newTime += ts_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 = ts_selectedInput;
    var regExp = new RegExp("hours$");
    if(ts_selectedInput.match(regExp) == null)
    {
        regExp = new RegExp("minutes$|seconds$|ampmMarker$");
        var timeElement = ts_selectedInput.match(regExp);
        var spanId = ts_selectedInput.substring(0, ts_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";
        ts_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 > ts_upperHourConstraint)
    {
        hours = ts_lowerHourConstraint;
    }
    else if(hours < ts_lowerHourConstraint)
    {
        hours = ts_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 = ts_selectedInput;
    var regExp = new RegExp("minutes$");
    if(ts_selectedInput.match(regExp) == null)
    {
        regExp = new RegExp("hours$|seconds$|ampmMarker$");
        var timeElement = ts_selectedInput.match(regExp);
        var spanId = ts_selectedInput.substring(0, ts_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";
        ts_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 = ts_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";
        ts_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 = ts_selectedInput;
    var regExp = new RegExp("ampmMarker$");
    if(ts_selectedInput.match(regExp) == null)
    {
        regExp = new RegExp("hours$|minutes$|seconds$");
        var timeElement = ts_selectedInput.match(regExp);
        var spanId = ts_selectedInput.substring(0, ts_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 == i18n_ts_am)
    {
        marker = i18n_ts_pm;
    }
    else
    {
        marker = i18n_ts_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(ts_selectedInput) == null)
    {
        ts_selectedInput = inputName;
    }
    document.getElementById(ts_selectedInput).className = "timeSpinnerInputUnselected";
    document.getElementById(inputName).className = "timeSpinnerInputSelected";
    var regExp = new RegExp("ampmMarker$");
    if(inputName.match(regExp) == null)
    {
        document.getElementById(inputName).select();
    }
    ts_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<ts_timeIdArray.length;i++)
    {
        var ctl1Id = ts_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 > ts_upperHourConstraint)
                {
                    validHoursTemp = false;
                }
                else if(hours < ts_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 && ts_validHours))
            {
                ts_validHours = validHoursTemp;

                if(!ts_validHours)
                {
                    alert(i18n_ts_invalid_hours);
                }
            }
        }
    }
}

/*
 * 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<ts_timeIdArray.length;i++)
    {
        var ctl1Id = ts_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 && ts_validMinutes))
            {
                ts_validMinutes = validMinutesTemp;
                if(!ts_validMinutes)
                {
                    alert(i18n_ts_invalid_minutes);
                }
            }
        }
    }
}

/*
 * 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<ts_timeIdArray.length;i++)
    {
        var ctl1Id = ts_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 && ts_validSeconds))
            {
                ts_validSeconds = validSecondsTemp;
                if(!ts_validSeconds)
                {
                    alert(i18n_ts_invalid_seconds);
                }
            }
        }
    }
}

/*
 * This function should be called from the outside to make sure that the time entered is a valid time
 */
function validTime()
{
    if(ts_validHours && ts_validMinutes && ts_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()
{
}

function init_i18n_timespinner(i18n_ts_time_format, i18n_ts_calendar_format_with_time, i18n_ts_click_to_spin,
                                i18n_ts_invalid_hours, i18n_ts_invalid_minutes, i18n_ts_invalid_seconds, i18n_ts_am, i18n_ts_pm)
{
    this.i18n_ts_time_format = i18n_ts_time_format;
    this.i18n_ts_calendar_format_with_time = i18n_ts_calendar_format_with_time;
    this.i18n_ts_click_to_spin = i18n_ts_click_to_spin;
    this.i18n_ts_invalid_hours = i18n_ts_invalid_hours;
    this.i18n_ts_invalid_minutes = i18n_ts_invalid_minutes;
    this.i18n_ts_invalid_seconds = i18n_ts_invalid_seconds;
    this.i18n_ts_am = i18n_ts_am;
    this.i18n_ts_pm = i18n_ts_pm;
}

function timePortionOfFormat2(timeDateFormat)
{
    lastYearPos = timeDateFormat.lastIndexOf("y");
    lastMonthPos = timeDateFormat.lastIndexOf("M");
    maxValue = Math.max(lastYearPos, lastMonthPos);
    lastDatePos = timeDateFormat.lastIndexOf("d");
    maxValue = Math.max(maxValue, lastDatePos);
    if ( maxValue != -1 )
    {
        maxValue = maxValue+2;
        if ( (maxValue) < (timeDateFormat.length-1) )
        {
            timeDateFormat = (timeDateFormat.substr(maxValue));
        }
    }
    return timeDateFormat;
}
