var datePickerDivID = 'datepicker'; var iFrameDivID = 'datepickeriframe'; var dayNameListShort = new Array( 'Zo', 'Ma', 'Di', 'Wo', 'Do', 'Vr', 'Za' ); var dayNameListLong = new Array( 'Zondag', 'Maandag', 'Dinsdag', 'Woensdag', 'Donderdag', 'Vrijdag', 'Zaterdag' ); var monthNameListShort = new Array( 'Jan', 'Feb', 'Mrt', 'Apr', 'Mei', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dec' ); var monthNameListLong = new Array( 'Januari', 'Februari', 'Maart', 'April', 'Mei', 'Juni', 'Juli', 'Augustus', 'September', 'Oktober', 'November', 'December' ); var currentlySelectedDate; var minimumDate; var maximumDate; /* these variables define the date formatting we're expecting and outputting. */ /* If you want to use a different format by default, change the */ /* defaultDateSeparator and defaultDateFormat variables either here or on */ /* your HTML page. */ var defaultDateSeparator = '/'; /* common values would be '/' or '-' */ var defaultDateFormat = 'dmy' /* valid values are 'mdy', 'dmy', and 'ymd' */ var dateSeparator = defaultDateSeparator; var dateFormat = defaultDateFormat; function displayDatePicker(dateFieldName, displayBelowThisObject, dtFormat, dtSep) { var targetDateField = document.getElementsByName(dateFieldName).item(0); /* fetch the current date */ currentlySelectedDate = getFieldDate(targetDateField.value); currentlySelectedDate = dateClearTime(currentlySelectedDate); /* set the range of valid dates */ minimumDate = new Date(); minimumDate = dateClearTime(minimumDate); minimumDate.setDate(minimumDate.getDate() + 7); maximumDate = new Date(); maximumDate = dateClearTime(maximumDate); maximumDate.setDate(maximumDate.getDate() - 1); maximumDate.setMonth(maximumDate.getMonth() + 6); /* if we weren't told what node to display the datepicker beneath, just */ /* display it beneath the date field we're updating */ if (! displayBelowThisObject) { displayBelowThisObject = targetDateField; } /* if a date separator character was given, update the dateSeparator variable */ if (dtSep) { dateSeparator = dtSep; } else { dateSeparator = defaultDateSeparator; } /* if a date format was given, update the dateFormat variable */ if (dtFormat) { dateFormat = dtFormat; } else { dateFormat = defaultDateFormat; } var x = displayBelowThisObject.offsetLeft; var y = displayBelowThisObject.offsetTop + displayBelowThisObject.offsetHeight ; /* deal with elements inside tables and such */ var parent = displayBelowThisObject; while (parent.offsetParent) { parent = parent.offsetParent; x += parent.offsetLeft; y += parent.offsetTop ; } drawDatePicker(targetDateField, x, y); } /* Draw the datepicker object (which is just a table with calendar elements) */ /* at the specified x and y coordinates, using the targetDateField object as */ /* the input tag that will ultimately be populated with a date. */ /* This function will normally be called by the displayDatePicker function. */ function drawDatePicker(targetDateField, x, y) { /* the datepicker table will be drawn inside of a
with an ID defined by */ /* the global datePickerDivID variable. If such a div doesn't yet exist on */ /* the HTML document we're working with, add one. */ if (! document.getElementById(datePickerDivID)) { var newNode = document.createElement('div'); newNode.setAttribute('id', datePickerDivID); newNode.setAttribute('class', 'dpDiv'); newNode.setAttribute('style', 'visibility: hidden;'); document.body.appendChild(newNode); } /* move the datepicker div to the proper x,y coordinate and toggle the */ /* visiblity */ var pickerDiv = document.getElementById(datePickerDivID); pickerDiv.style.position = 'absolute'; pickerDiv.style.left = x + 'px'; pickerDiv.style.top = y + 'px'; pickerDiv.style.visibility = (pickerDiv.style.visibility == 'visible' ? 'hidden' : 'visible'); pickerDiv.style.display = (pickerDiv.style.display == 'block' ? 'none' : 'block'); pickerDiv.style.zIndex = 10000; /* draw the datepicker table */ refreshDatePicker(targetDateField.name); } /* This is the function that actually draws the datepicker calendar. */ function refreshDatePicker(dateFieldName, year, month) { /* if no arguments are passed, use today's date; otherwise, month and year */ /* are required */ var thisDay = new Date(); if (month >= 0 && year > 0) { thisDay = new Date(year, month, 1); } thisDay = dateClearTime(thisDay); thisDay.setDate(1); /* the calendar will be drawn as a table; you can customize the table */ /* elements with a global CSS style sheet or by hardcoding style and */ /* formatting elements below */ var CRLF = '\r\n'; var HTML_ELEMENT_TABLE = '' + CRLF; var HTML_ELEMENT_END_TABLE = '
' + CRLF; var HTML_ELEMENT_TR = ''; var HTML_ELEMENT_TR_TITLE = ''; var HTML_ELEMENT_TR_DAYS = ''; var HTML_ELEMENT_TR_TODAYBUTTON = ''; var HTML_ELEMENT_END_TR = '' + CRLF; var HTML_ELEMENT_TD = ''; } else if (thisDay.getTime() >= maximumDate.getTime()) { onClickEventHtml = ' onclick="alert(\'You have to select a date prior to 6 months in the future.\');return false;">'; } else { onClickEventHtml = ' onclick="updateDateField(\'' + dateFieldName + '\', \'' + getDateString(thisDay) + '\');">'; } if (thisDay.getTime() < minimumDate.getTime() || thisDay.getTime() >= maximumDate.getTime()) { calendarHtml += HTML_ELEMENT_TD_OUT_OF_RANGE + onClickEventHtml + thisDay.getDate() + HTML_ELEMENT_END_TD; } else if (thisDay.getTime() == currentlySelectedDate.getTime()) { calendarHtml += HTML_ELEMENT_TD_SELECTED + onClickEventHtml + HTML_ELEMENT_DIV_SELECTED + thisDay.getDate() + HTML_ELEMENT_END_DIV + HTML_ELEMENT_END_TD; } else { calendarHtml += HTML_ELEMENT_TD + onClickEventHtml + thisDay.getDate() + HTML_ELEMENT_END_TD; } /* if this is a Saturday, start a new row */ if (thisDay.getDay() == 6) { calendarHtml += HTML_ELEMENT_END_TR; calendarHtml += HTML_ELEMENT_TR; } /* increment the day */ thisDay.setDate(thisDay.getDate() + 1); } while (thisDay.getDate() > 1) /* fill in any trailing blanks */ if (thisDay.getDay() > 0) { for (i = 6; i > thisDay.getDay(); i--) calendarHtml += HTML_ELEMENT_TD + ' ' + HTML_ELEMENT_END_TD; } calendarHtml += HTML_ELEMENT_END_TR; /* add a button to allow the user to easily return to today, or close the */ /* calendar */ var today = new Date(); var todayString = 'Today is ' + dayNameListShort[today.getDay()] + ', ' + monthNameListShort[today.getMonth()] + ' ' + today.getDate(); calendarHtml += HTML_ELEMENT_TR_TODAYBUTTON + HTML_ELEMENT_TD_TODAYBUTTON; calendarHtml += ' '; calendarHtml += ''; calendarHtml += HTML_ELEMENT_END_TD + HTML_ELEMENT_END_TR; /* and finally, close the table */ calendarHtml += HTML_ELEMENT_END_TABLE; document.getElementById(datePickerDivID).innerHTML = calendarHtml; /* add an "iFrame shim" to allow the datepicker to display above selection */ /* lists */ adjustiFrame(); } /* Convenience function for writing the code for the buttons that bring us */ /* back or forward a month. */ function getButtonCode(dateFieldName, dateVal, adjust, label) { var newMonth = (dateVal.getMonth () + adjust) % 12; var newYear = dateVal.getFullYear() + parseInt((dateVal.getMonth() + adjust) / 12); if (newMonth < 0) { newMonth += 12; newYear += -1; } return ''; } /* Convert a JavaScript Date object to a string, based on the dateFormat and */ /* dateSeparator variables at the beginning of this script library. */ function getDateString(dateVal) { var dayString = '00' + dateVal.getDate(); var monthString = '00' + (dateVal.getMonth()+1); dayString = dayString.substring(dayString.length - 2); monthString = monthString.substring(monthString.length - 2); switch (dateFormat) { case 'dmy': return dayString + dateSeparator + monthString + dateSeparator + dateVal.getFullYear(); case 'ymd': return dateVal.getFullYear() + dateSeparator + monthString + dateSeparator + dayString; case 'mdy': default: return monthString + dateSeparator + dayString + dateSeparator + dateVal.getFullYear(); } } /* Convert a string to a JavaScript Date object. */ function getFieldDate(dateString) { var dateVal; var dArray; var d, m, y; try { dArray = splitDateString(dateString); if (dArray) { switch (dateFormat) { case 'dmy': d = parseInt(dArray[0], 10); m = parseInt(dArray[1], 10) - 1; y = parseInt(dArray[2], 10); break; case 'ymd': d = parseInt(dArray[2], 10); m = parseInt(dArray[1], 10) - 1; y = parseInt(dArray[0], 10); break; case 'mdy': default : d = parseInt(dArray[1], 10); m = parseInt(dArray[0], 10) - 1; y = parseInt(dArray[2], 10); break; } dateVal = new Date(y, m, d); } else if (dateString) { dateVal = new Date(dateString); } else { dateVal = new Date(); } } catch(e) { dateVal = new Date(); } return dateVal; } /* Try to split a date string into an array of elements, using common date */ /* separators. If the date is split, an array is returned; otherwise, we just */ /* return false. */ function splitDateString(dateString) { var dArray; if (dateString.indexOf('/') >= 0) dArray = dateString.split('/'); else if (dateString.indexOf('.') >= 0) dArray = dateString.split('.'); else if (dateString.indexOf('-') >= 0) dArray = dateString.split('-'); else if (dateString.indexOf('\\') >= 0) dArray = dateString.split('\\'); else dArray = false; return dArray; } /* Update the field with the given dateFieldName with the dateString that has */ /* been passed, and hide the datepicker. If no dateString is passed, just */ /* close the datepicker without changing the field value. */ /* Also, if the page developer has defined a function called datePickerClosed */ /* anywhere on the page or in an imported library, we will attempt to run */ /* that function with the updated field as a parameter. This can be used for */ /* such things as date validation, setting default values for related fields, */ /* etc. For example, you might have a function like this to validate a start */ /* date field: */ /* function datePickerClosed(dateField) { var dateObj = getFieldDate(dateField.value); var today = new Date(); today = new Date(today.getFullYear(), today.getMonth(), today.getDate()); if (dateField.name == 'StartDate') { if (dateObj < today) { // if the date is before today, alert the user and display the datepicker // // again // alert('Please enter a date that is today or later'); dateField.value = ''; document.getElementById(datePickerDivID).style.visibility = 'visible'; adjustiFrame(); } else { // if the date is okay, set the EndDate field to 7 days after the StartDate // dateObj.setTime(dateObj.getTime() + (7 * 24 * 60 * 60 * 1000)); var endDateField = document.getElementsByName('EndDate').item(0); endDateField.value = getDateString(dateObj); } } } */ function updateDateField(dateFieldName, dateString) { var targetDateField = document.getElementsByName(dateFieldName).item(0); if (dateString) { targetDateField.value = dateString; document.getElementById('cancelDateContainer').innerHTML = dateString; } var pickerDiv = document.getElementById(datePickerDivID); pickerDiv.style.visibility = 'hidden'; pickerDiv.style.display = 'none'; adjustiFrame(); /* after the datepicker has closed, optionally run a user-defined function */ /* called datePickerClosed, passing the field that was just updated as a */ /* parameter (note that this will only run if the user actually selected a */ /* date from the datepicker) */ if ((dateString) && (typeof(datePickerClosed) == 'function')) { datePickerClosed(targetDateField); } } /* Use an "iFrame shim" to deal with problems where the datepicker shows up */ /* behind selection list elements, if they're below the datepicker. The */ /* problem and solution are described at: */ /* http://dotnetjunkies.com/WebLog/jking/archive/2003/07/21/488.aspx */ function adjustiFrame(pickerDiv, iFrameDiv) { /* we know that Opera doesn't like something about this, so if we think we're */ /* using Opera, don't even try */ if (navigator.userAgent.toLowerCase().indexOf('opera') == -1) { /* put a try/catch block around the whole thing, just in case */ try { if (! document.getElementById(iFrameDivID)) { var newNode = document.createElement('iFrame'); newNode.setAttribute('id', iFrameDivID); newNode.setAttribute('src', 'javascript:false;'); newNode.setAttribute('scrolling', 'no'); newNode.setAttribute('frameborder', '0'); document.body.appendChild(newNode); } if (! pickerDiv) { pickerDiv = document.getElementById(datePickerDivID); } if (! iFrameDiv) { iFrameDiv = document.getElementById(iFrameDivID); } try { iFrameDiv.style.position = 'absolute'; iFrameDiv.style.width = pickerDiv.offsetWidth; iFrameDiv.style.height = pickerDiv.offsetHeight ; iFrameDiv.style.top = pickerDiv.style.top; iFrameDiv.style.left = pickerDiv.style.left; iFrameDiv.style.zIndex = pickerDiv.style.zIndex - 1; iFrameDiv.style.visibility = pickerDiv.style.visibility ; iFrameDiv.style.display = pickerDiv.style.display; } catch(exceptionObject) { } } catch (exceptionObject) { } } } function dateClearTime(aDate) { aDate.setHours(12); aDate.setMinutes(0); aDate.setSeconds(0); aDate.setMilliseconds(0); return aDate; }