// Set the bounds for the calendar here... // If you want the year to roll forward you can use something like this... // var scwBaseYear = scwDateNow.getFullYear()-5; // alternatively, hard code a date like this... // var scwBaseYear = 1990;

var scwBaseYear = scwDateNow.getFullYear()-50;

// How many years do want to be valid and to show in the drop-down list?

var scwDropDownYears = 51;

// All language-dependent changes can be made here...

// If you wish to work in a single language (other than English) then // just replace the English (in the function scwSetLanguage below) with // your own text.

// Using multiple languages: // In order to keep this script to a resonable size I have not included // languages here. You can set language fields in a function that you // should call scwSetLanguage the script will use your languages. // I have included all the translations that have been sent to me in // such a function on the demonstration page.

// scwWeekStart determines the start of the week in the display // Set it to: 0 (Zero) for Sunday, 1 (One) for Monday etc..

var scwWeekStart = 1;

// The week start day for the display is taken as the week start // for week numbering. This ensures that only one week number // applies to one line of the calendar table. // [ISO 8601 begins the week with Day 1 = Monday.]

// If you want to see week numbering on the calendar, set // this to true. If not, false.

var scwWeekNumberDisplay = false;

// Week numbering rules are generally based on a day in the week // that determines the first week of the year. ISO 8601 uses // Thursday (day four when Sunday is day zero). You can alter // the base day here.

// See http://www.cl.cam.ac.uk/~mgk25/iso-time.html for more information

var scwWeekNumberBaseDay = 4;

// Each of the calendar's alert message types can be disabled // independently here.

// Set the format for the displayed 'Today' date and for the output // date here. // // The format is described using delimiters of your choice (as set // in scwArrDelimiters above) and case insensitive letters D, M and Y. // // NOTE: If no delimiters are input then the date output format is used // to parse the value. This allows less flexiblility in the input // value than using delimiters but an accurately entered date // remains parsable. // // Definition Returns // ---------- ------- // D date in the month without zero filling // DD date in the month left zero filled // M month number without zero filling // MM month number left zero filled // MMM month string from scwArrMonthNames // YY year number in two digits // YYYY year number in four digits

// Displayed "Today" date format

var scwDateDisplayFormat = 'dd-mm-yy'; // e.g. 'MMM-DD-YYYY' for the US

// Output date format

var scwDateOutputFormat = 'DD/MM/YYYY'; // e.g. 'MMM-DD-YYYY' for the US

// Note: The delimiters used should be in scwArrDelimiters.

// scwZindex controls how the pop-up calendar interacts with the rest // of the page. It is usually adequate to leave it as 1 (One) but I // have made it available here to help anyone who needs to alter the // level in order to ensure that the calendar displays correctly in // relation to all other elements on the page.

var scwZindex = 1;

// Personally I like the fact that entering 31-Sep-2005 displays // 1-Oct-2005, however you may want that to be an error. If so, // set scwBlnStrict = true. That will cause an error message to // display and the selected month is displayed without a selected // day. Thanks to Brad Allan for his feedback prompting this feature.

var scwBlnStrict = false;

// If you are using ReadOnly or Disabled fields to return the date // value into, it can be useful to show a button on the calendar // that allows the value to be cleared. If you want to do that, // set scwClearButton = true;

var scwClearButton = true;

// The calendar will position itself aligned with the bottom left // corner of the target element. If automatic positioning is turned // on with scwAutoPosition = true then if that would cause the // calendar to display off the visible screen, it is shifted to // a position that is visible.

var scwAutoPosition = true;

// If you wish to disable any displayed day, e.g. Every Monday, // you can do it by setting the following array. The array elements // match the displayed cells. // // You could put something like the following in your calling page // to disable all weekend days; // // for (var i=0;i<scwEnabledDay.length;i++) // {if (i%7%6==0) scwEnabledDay[i] = false;} // // The above approach will allow you to disable days of the week // for the whole of your page easily. If you need to set different // disabled days for a number of date input fields on your page // there is an easier way: You can pass additional arguments to // scwShow. The syntax is described at the top of this script in // the section: // "How to use the Calendar once it is defined for your page:" // // It is possible to use these two approaches in combination.

// You can disable any specific date (e.g. 24-Jan-2006 or Today) by // creating an element of the array scwDisabledDates as a date object // with the value you want to disable. Date ranges can be disabled // by placing an array of two values (Start and End) into an element // of this array.

// The disabling by date and date range does prevent the current day // from being selected. Disabling days of the week does not so you can set // the scwActiveToday value to false to prevent selection.

var scwActiveToday = true;

// Dates that are out of the displayed month are shown at the start // (unless the month starts on the first day of the week) and end of each // month. // // Set scwOutOfMonthDisable to true to disable these dates (or false // to allow their selection). // // Set scwOutOfMonthHide to true to hide these dates (or false // to make them visible).

var scwOutOfMonthDisable = false; var scwOutOfMonthHide = false;

// Dates that are out of the specified range can be displayed at the start // of the very first month and end of the very last. Set // scwOutOfRangeDisable to true to disable these dates (or false to // allow their selection).

var scwOutOfRangeDisable = true;

// If you want a special format for the cell that contains the current day // set this to true. This sets a thin border around the cell in the colour // set by scwTodayCellBorderColour.

// You can allow the calendar to be dragged around the screen by // using the setting scwAllowDrag to true. // I can't say I recommend it because of the danger of the user // forgetting which date field the calendar will update when there // are multiple date fields on a page.

var scwAllowDrag = false;

// Closing the calendar by clicking on it (rather than elsewhere on the // main page) can be inconvenient. The scwClickToHide boolean value // controls this feature.

var scwClickToHide = true;

// I have made every effort to isolate the pop-up script from any // CSS defined on the main page but if you have anything set that // affects the pop-up (or you may want to change the way it looks) // then you can address it in the following style sheets.

// This style sheet can be extracted from the script and edited into regular // CSS (by removing all occurrences of + and '). That can be used as the // basis for themes. Classes are described in comments within the style // sheet.

//******************************************************************************//------------------------------------------------------------------------------// End of customisation section//------------------------------------------------------------------------------//******************************************************************************

for (var i=0;i<=scwFormat.length;i++) {if (i<scwFormat.length && scwFormat.charAt(i)==codeChar) {// If we haven't hit the end of the string and // the format string character is the same as // the previous one, just clock up one to the // length of the current element definition charCount++; } else {switch (codeChar) {case 'y': case 'Y': result += (this.getFullYear()%Math. pow(10,charCount)).toString(). scwPadLeft(charCount); break; case 'm': case 'M': // If we find an M, check the number of them to // determine whether to get the month number or // the month name. result += (charCount<3) ?(this.getMonth()+1). toString().scwPadLeft(charCount) :scwArrMonthNames[this.getMonth()]; break; case 'd': case 'D': // If we find a D, get the date and format it result += this.getDate().toString(). scwPadLeft(charCount); break; default: // Copy any unrecognised characters across while (charCount-- > 0) {result += codeChar;} }

if (i<scwFormat.length) {// Store the character we have just worked on codeChar = scwFormat.charAt(i); charCount = 1; } } } return result; };

function scwID(id) {if (document.getElementById(id) || (!document.getElementById(id) && document.getElementsByName(id).length==0)) // IF An ID attribute is assigned // OR No ID attribute is assigned but using IE and Opera // (which will find the NAME attribute value using getElementById) // OR No element has this ID or NAME attribute value // (used internally by the script) // THEN Return the required element. {return document.getElementById(id);} else {if (document.getElementsByName(id).length==1) // IF No ID attribute is assigned // AND Using a standards-based browser // AND Only one element has the NAME attribute set to the value // THEN Return the required element (using the NAME attribute value). {return document.getElementsByName(id)[0];} else {if (document.getElementsByName(id).length>1) { // IF No ID attribute is assigned // AND using a standards-based browser // AND more than one element has the NAME attribute set to the value // THEN alert developer to fix the fault. alert( 'SCW' + ' \nCannot uniquely identify element named: ' + id + '.\nMore than one identical NAME attribute defined' + '.\nSolution: Assign the required element a unique ID attribute value.'); } } } };

// Use a global variable for the return value from the next action // IE fails to pass the function through if the target element is in // a form and scwNextAction is not defined.

var scwNextActionReturn, scwNextAction;

// ****************************************************************************// Start of Function Library//// Exposed functions://// scwShow Entry point for display of calendar,// called in main page.// showCal Legacy name of scwShow:// Passes only legacy arguments,// not the optional day disabling arguments.//// scwShowMonth Displays a month on the calendar,// Called when a month is set or changed.//// scwBeginDrag Controls calendar dragging.//// scwCancel Called when the calendar background is clicked:// Calls scwStopPropagation and may call scwHide.// scwHide Hides the calendar, called on various events.// scwStopPropagation Stops the propagation of an event.//// ****************************************************************************

// These regular expressions validate the input date format // to the following rules; // Day 1-31 (optional zero on single digits) // Month 1-12 (optional zero on single digits) // or case insensitive name // Year One, Two or four digits

// Months names are as set in the language-dependent // definitions and delimiters are set just below there

if (isNaN(scwSeedDate)) {if (scwShowInvalidDateMsg) {alert(scwInvalidDateMsg + scwInvalidAlert[0] + scwDateValue + scwInvalidAlert[1]);} scwSeedDate = new Date(scwBaseYear + Math.floor(scwDropDownYears/2),5,1); scwBlnFullInputDate=false; } else {// Test that the date is within range, // if not then set date to a sensible date in range.

// Check whether or not dragging is allowed and display drag handle if necessary

scwID('scwDrag').style.display=(scwAllowDrag)?'':'none';

// Display the month

scwShowMonth(0);

// Position the calendar box

// The object sniffing for Opera allows for the fact that Opera // is the only major browser that correctly reports the position // of an element in a scrollable DIV. This is because IE and // Firefox omit the DIV from the offsetParent tree.

function scwShowMonth(scwBias) {// Set the selectable Month and Year // May be called: from the left and right arrows // (shift month -1 and +1 respectively) // from the month selection list // from the year selection list // from the showCal routine // (which initiates the display).

// Set the time to the middle of the day so that the handful of // regions that have daylight saving shifts that change the day // of the month (i.e. turn the clock back at midnight or forward // at 23:00) do not mess up the date display in the calendar.

// Subtract the date of the current week from the date of the // first week of the year to get the number of weeks in // milliseconds. Divide by the number of milliseconds // in a week then round to no decimals in order to remove // the effect of daylight saving. Add one to make the first // week, week 1. Place a string zero on the front so that // week numbers are zero filled.

// Opera has a bug with setting the selected index. // It requires the following work-around to force SELECTs to display correctly. // Also Opera's poor dynamic rendering prior to 9.5 requires // the visibility to be reset to prevent garbage in the calendar // when the displayed month is changed.