You are here: irt.org | Articles | JavaScript | Date and Time | Date Spinner [ previous next ]
Published on: Monday 21st July 1997 By: Martin Webb
A recent posting to the comp.lang.javascript newsgroup requested a date spinner which would increment forward or backwards one day at a time. This article describes the JavaScript example I posted in reply.
First the date spinner, which at first glance looks like a new form object, but is in fact a text field following by an image:
and the example code:
<HTML> <HEAD> <SCRIPT LANGUAGE = 'JavaScript'><!-- function y2k(number) { return (number < 1000) ? number + 1900 : number; } var date = new Date(); var milliseconds = Date.UTC(y2k(date.getYear()),date.getMonth(),date.getDate()); function prevDay() { milliseconds -= 86400000; formatDate(); } function nextDay() { milliseconds += 86400000; formatDate(); } function formatDate() { date = new Date(milliseconds); var year = date.getYear(); var month = date.getMonth() + 1; var day = date.getDate(); document.date.spinner.value = ((year < 1000) ? year + 1900 : year) + '-' + ((month < 10) ? '0' + month : month) + '-' + ((day < 10) ? '0' + day : day); } //--></SCRIPT> </HEAD> <BODY onLoad="formatDate()"> <MAP NAME="spinner-map"> <AREA SHAPE="RECT" COORDS="0,0,18,10" HREF="javascript:prevDay()" onMouseOver="self.status='';return true" > <AREA SHAPE="RECT" COORDS="0,12,18,23" HREF="javascript:nextDay()" onMouseOver="self.status='';return true" > </MAP> <P> <FORM NAME="date"> <INPUT NAME="spinner" TYPE="TEXT" SIZE="10" VALUE="9999-99-99" ><A HREF="JavaScript:" onMouseOver="self.status='';return true" ><IMG SRC="date.gif" BORDER=0 WIDTH=19 HEIGHT=24 ALIGN=TOP USEMAP="#spinner-map" ALT="Click" ></A> </FORM> </BODY> </HTML>
First we define all our JavaScript variables and functions within the <HEAD> and </HEAD> HTML tags:
- which is used to get the current date.
- which holds the number of milliseconds from January 1, 1970, 00:00:00 to the date held in date, using the UTC() method.
- which subtracts one day, i.e. 24 * 60 * 60 * 1000 milliseconds, from milliseconds and then invokes formatDate() to update the text box.
- which adds one day, i.e. 24 * 60 * 60 * 1000 milliseconds, from milliseconds and then invokes formatDate() to update the text box.
- which formats the value milliseconds into the required date string, and updates the value of the text box using the object hiearchy document.formName.elementName.value. It strings the year, month and day together, using the conditional expression to pad the month and day with an extra leading zero if necessary.
The onLoad event within the <BODY> tag is used to ensure the whole page is loaded before any JavaScript is invoked. This ensures that the form is fully defined before trying to change the values of the text box. When the onLoad event is triggered it invokes the formatDate() function to update the text box.
A client-side image map is used, spinner-map, which defines two rectangle areas within the date.gif image, which either invoke the prevDay() or the nextDay() JavaScript functions, and set the document status to blank to hide the ugly "Javascript:prevDay()" and "Javascript:nextDay()" status messages.
Finally the date form is defined.
The spinner text field has a size of 10 specified and an initial value of '9999-99-99'.
The date.gif image is wrapped in a anchor to allow the client-side image map to work. It does not actually require a proper HREF url.
The image has the border set to zero to stop it from being shown.
To avoid spaces appearing between the form elements the end and start of the HTML tags have been deliberately coded as ><.
The image refers to the client-side image map using USEMAP="#spinner-map".
Obviously this is only one example of what can be achieved using this spinner. The spinner can be used where you need to control how many items are visible within the same text box, and where it is necessary to step through the items one at a time.
Another example where this can be used is too restrict the range of dates entered. The following will only allow a date that is equal or greater than todays date. It also disallows the user from entering the text directly in the textbox, because as soon as the field is changed, i.e. the user clicks elsewhere after changing the text value, it checks the field contents with its last known value.
This example does not use image maps, and therefore would be supported by far more browsers.
and the example code:
<SCRIPT LANGUAGE = 'JavaScript'><!-- function y2k(number) { return (number < 1000) ? number + 1900 : number; } var date2 = new Date(); var milliseconds2 = Date.UTC(y2k(date2.getYear()),date2.getMonth(),date2.getDate()); var baseTime = milliseconds; var currentDate = ""; function prevDay2() { if (milliseconds2 > baseTime) milliseconds2 -= 86400000; formatDate2(); } function nextDay2() { milliseconds2 += 86400000; formatDate2(); } function formatDate2() { date2 = new Date(milliseconds2); var year2 = date2.getYear(); var month2 = date2.getMonth() + 1; var day2 = date2.getDate(); document.date2.spinner.value = ((year2 < 1000) ? year2 + 1900 : year2) + '-' + ((month2 < 10) ? '0' + month2 : month2) + '-' + ((day2 < 10) ? '0' + day2 : day2); currentDate = document.date2.spinner.value; } function checkDate() { if (document.date2.spinner.value != currentDate) document.date2.spinner.value = currentDate } //--></SCRIPT> <P> <FORM NAME="date2"> <A HREF="JavaScript:prevDay2()" onMouseOver="self.status='';return true" ><IMG SRC="prev.gif" BORDER=0 WIDTH=17 HEIGHT=23 ALIGN=TOP ALT="Click" ></A><INPUT NAME="spinner" TYPE="TEXT" SIZE="10" VALUE="9999-99-99" onChange="checkDate()" ><A HREF="JavaScript:nextDay2()" onMouseOver="self.status='';return true" ><IMG SRC="next.gif" BORDER=0 WIDTH=17 HEIGHT=23 ALIGN=TOP ALT="Click" ></A> </FORM> <SCRIPT LANGUAGE = 'JavaScript'><!-- formatDate2() //--></SCRIPT>
Monday's child is full of grace