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

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

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

Listbox Selection Question

Status
Not open for further replies.

Johnblaze1

Programmer
Sep 17, 2002
25
US
I am new to JavaScript and could use some help. I have a listbox on a webform that contains the date of all Sunday's in a given year.
Users fill out this form on a Monday and must pick the appropriate Sunday from the listbox. Is there a way to have the listbox pre-select the most recent Sunday?
So, if a user filled out the form on Monday Sep 19th the form would pre-select 09/18/2005 from the listbox?

Thanks
John
 
Certainly. Since you provide no code, I'll just generalize.

(1) grab today's date: var today = new Date(); Use the methods of a Date object to build a number of the following format: YYYYMMDD.

(2) make sure each option/date in your drop down list is assigned a value of the same form: YYYYMMDD and that the options/dates are given in order. I'll assume ascending order for now.

(3) use a binary search of the option list to determine which value the date is closest to.

Is that enough to get you going?

--Dave
 
Dave

If I wasnt completely clueless, that would be very helpful. However, I am. I normaly do C and VB coding. This webform is just a front end that drops info to an email, which is read into a VB tool which transfers to a database. Here is the HTML for the listbox

<DIV align=left><SELECT id=select17 style="WIDTH: 115px"
size=1 name=cboWeekEnd> <OPTION
selected>9/4/2005</OPTION> <OPTION>09/11/2005</OPTION>
<OPTION>9/18/2005</OPTION> <OPTION>9/25/2005</OPTION>
<OPTION>10/2/2005</OPTION> <OPTION>10/9/2005</OPTION>
<OPTION>10/16/2005</OPTION> <OPTION>10/23/2005</OPTION>
<OPTION>10/30/2005</OPTION> <OPTION>11/6/2005</OPTION>
<OPTION>11/13/2005</OPTION> <OPTION>11/20/2005</OPTION>
<OPTION>11/27/2005</OPTION> <OPTION>12/4/2005</OPTION>
<OPTION>12/11/2005</OPTION> <OPTION>12/18/2005</OPTION>
<OPTION>12/25/2005</OPTION> <OPTION>1/1/2006</OPTION>
<OPTION>1/8/2006</OPTION> <OPTION>1/15/2006</OPTION>
<OPTION>1/22/2006</OPTION> <OPTION>1/29/2006</OPTION>
<OPTION>2/5/2006</OPTION> <OPTION>2/12/2006</OPTION>
<OPTION>2/19/2006</OPTION> <OPTION>2/26/2006</OPTION>
<OPTION>3/5/2006</OPTION> <OPTION>3/12/2006</OPTION>
<OPTION>3/19/2006</OPTION> <OPTION>3/26/2006</OPTION>
<OPTION>4/2/2006</OPTION> <OPTION>4/9/2006</OPTION></SELECT>
</DIV></TD></TR></TBODY></TABLE>

I really dont even know how to implement a binary search in JavaScript. And pseudo code would be great.

John
 
Okay, well, "for fun", I typed up the following and tested it, using your option list and select list name. I dropped the DIV and TABLE tags too:

Code:
<html>
<head>
<script>
//(1) Start by getting a numeric value representing TODAY that
// you can use for comparing dates.  Final format:  YYYYMMDD
var today = new Date();

var todayDay = today.getDate();
//NOTE:  zero-padding of single-digit days essential for making this work.
if(todayDay < 10)
 todayDay = '0' + todayDay;

var todayMonth = today.getMonth()+1; 
//Regarding above:  months are 0-based, but easier for us if 1-based.  
// Ask about this if you don't understand.
//NOTE:  zero-padding of single-digit months essential for making this work.
if(todayMonth < 10)
 todayMonth = '0' + todayMonth;

var todayYear = today.getYear();

var todayString = '' + todayYear + todayMonth + todayDay; 
//above: string concatenation

var todayVal = parseInt(todayString, 10); //YYYYMMDD version of today

//(2) Declare global variable myList.
var myList;

//(3) Called with BODY tag's onload event, starts date selection going.  
function startBallRolling()
{
 myList = document.forms[0].cboWeekEnd;

 //To begin with, lowest index is 0
 // highest index is document.forms[0].cboWeekEnd.options.length-1.
 findClosest(0, document.forms[0].cboWeekEnd.options.length-1);
}//end startBallRolling()

//(4) Function looks at middle of drop-down list, then decides if it's
// in the right place.  If not, it searches either the top or bottom
// half of the list (by calling itself with different parameters) and
// the process continues, searching smaller and smaller "halves" of the
// remaining list until it finds its mark.  i.e., does a binary search.
function findClosest(low, high)
{
 //Go to middle of list (binary search)
 var halfwayIndex = Math.floor((low+high)/2);
 var dateVal = getDateVal(myList.options[halfwayIndex].text);

 if(dateVal == todayVal)
 {
  myList.selectedIndex = halfwayIndex;  //Done.
 }
 else if(dateVal > todayVal)
 {
  if(halfwayIndex == 0) //start of list.  Can't go lower, so...
  {
   myList.selectedIndex = 0; //Done.
  }//end if
  else
  {
   var newIndex = halfwayIndex - 1;
   var newDateVal = getDateVal(myList.options[newIndex].text);
   if(newDateVal > todayVal) //too far away.  Search bottom half of list.
   {
    findClosest(low, halfwayIndex);
   }//end if
   else  //we're where we need to be.  Determine which is closer.
   {
    var choice = whichIsCloser(halfwayIndex, dateVal, newIndex, newDateVal, todayVal);
    myList.selectedIndex = choice;  //Done.
   }//end else
  }//end else
 }//end else if
 else //dateVal < todayVal
 {
  if(halfwayIndex == myList.options.length-1) //end of list.  Can't go higher, so...
  {
   myList.selectedIndex = myList.options.length-1; //Done.
  }//end if
  else
  {
   var newIndex = halfwayIndex + 1;
   var newDateVal = getDateVal(myList.options[newIndex].text);
   if(newDateVal < todayVal) //too far away.  Search top half of list.
   {
    findClosest(halfwayIndex, high);
   }//end if
   else //we're where we need to be.  Determine which is closer.
   {
    var choice = whichIsCloser(halfwayIndex, dateVal, newIndex, newDateVal, todayVal);
    myList.selectedIndex = choice; //Done.
   }//end else
  }//end else
 }//end else
}//end findClosest(var, var)

//Returns YYYYMMDD int value of date sent in MM/DD/YYYY format
function getDateVal(optDate)
{
 //optDate of form:  MM/DD/YYYY.

 var month = parseInt(optDate.substring(0, optDate.indexOf("/")), 10);
 if(month < 10) //Treating month like an int
  month = '0' + month; //Now treating month like a String.  Crazy, huh?

 optDate = optDate.substring(optDate.indexOf("/")+1);
 //Now optDate of form:  DD/YYYY

 var day = parseInt(optDate.substring(0, optDate.indexOf("/")), 10);
 if(day < 10)
  day = '0' + day;

 optDate = optDate.substring(optDate.indexOf("/")+1);
 //Finally optDate of form:  YYYY

 var year = optDate;

 return parseInt('' + year + month + day);
}//end getDateVal(var)

//Returns index1 or index2, based on whether date1 or date2 (respectively)
// is closer to the dateOfInterest
function whichIsCloser(index1, date1, index2, date2, dateOfInterest)
{
 var compare1 = Math.abs(dateOfInterest - date1);
 var compare2 = Math.abs(dateOfInterest - date2);
 if(compare1 < compare2)
  return index1;
 else
  return index2;
}//end whichIsCloser(var, var, var, var, var)
</script>
</head>
<body onload='startBallRolling();'>
<form>
<SELECT id=select17 style="WIDTH: 115px" size=1 name=cboWeekEnd> 
<OPTION selected>9/4/2005</OPTION> 
<OPTION>09/11/2005</OPTION> 
<OPTION>9/18/2005</OPTION> 
<OPTION>9/25/2005</OPTION> 
<OPTION>10/2/2005</OPTION> 
<OPTION>10/9/2005</OPTION> 
<OPTION>10/16/2005</OPTION> 
<OPTION>10/23/2005</OPTION> 
<OPTION>10/30/2005</OPTION> 
<OPTION>11/6/2005</OPTION> 
<OPTION>11/13/2005</OPTION> 
<OPTION>11/20/2005</OPTION> 
<OPTION>11/27/2005</OPTION> 
<OPTION>12/4/2005</OPTION> 
<OPTION>12/11/2005</OPTION> 
<OPTION>12/18/2005</OPTION> 
<OPTION>12/25/2005</OPTION> 
<OPTION>1/1/2006</OPTION> 
<OPTION>1/8/2006</OPTION> 
<OPTION>1/15/2006</OPTION> 
<OPTION>1/22/2006</OPTION> 
<OPTION>1/29/2006</OPTION> 
<OPTION>2/5/2006</OPTION> 
<OPTION>2/12/2006</OPTION> 
<OPTION>2/19/2006</OPTION> 
<OPTION>2/26/2006</OPTION> 
<OPTION>3/5/2006</OPTION> 
<OPTION>3/12/2006</OPTION> 
<OPTION>3/19/2006</OPTION> 
<OPTION>3/26/2006</OPTION> 
<OPTION>4/2/2006</OPTION> 
<OPTION>4/9/2006</OPTION>
</SELECT> 
</form>
</body>
</html>

Now, I probably didn't do as much testing of this as I should, but check out the comments and see if you can make sense of this.

Good luck! Post if you have any more questions.

--Dave
 
Thanks so much. I really appreciate the comments, that helps me learn this quicker.

Thanks again
 
To further test it, you can skip the part where I format today's value and just code it as:

var todayVal = 20050801; //lower than first day on list
var todayVal = 20060501; //greater than last day on list
var todayVal = 20051016; //exact date on list
//test within bottom half of list
var todayVal = 20051107; //just above a date on the list
var todayVal = 20051112; //just below a date on the list
//test within top half of list
var todayVal = 20060306; //just above a date on the list
var todayVal = 20060311; //just below a date on the list

With these tests, the functions I wrote should be thoroughly tested. There's always the chance I accidentally stuck an infinite loop in there, so you should really test the function well before rolling it out. You might consider it with one less option in the list too (an odd number of options if the list is currently even or even if it is odd).

Again, good luck!

--Dave
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top