// *****************************************************************************
//      Simple Calendar Widget - Cross-Browser Javascript pop-up calendar.
//
//   Copyright (C) 2005-2007  Anthony Garrett
//
//   This library is free software; you can redistribute it and/or
//   modify it under the terms of the GNU Lesser General Public
//   License as published by the Free Software Foundation; either
//   version 2.1 of the License, or (at your option) any later version.
//
//   This library is distributed in the hope that it will be useful,
//   but WITHOUT ANY WARRANTY; without even the implied warranty of
//   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//   Lesser General Public License for more details.
//
//   You should have received a copy of the GNU Lesser General Public
//   License along with this library; if not, it is available at
//   the GNU web site (http://www.gnu.org/) or by writing to the
//   Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
//   Boston, MA  02110-1301  USA
//
// *****************************************************************************
//
// Contact:   Sorry, I can't offer support for this but if you find a problem
//            (or just want to tell me how useful you find it), please send
//            me an email at scwfeedback@tarrget.info (Note the two Rs in
//            tarrget).  I will try to fix problems quickly but this is a
//            spare time thing for me.
//
// Credits:   I wrote this from scratch myself but I couldn't have done it
//            without the superb "JavaScript The Definitive Guide" by David
//            Flanagan (Pub. O'Reilly ISBN 0-596-00048-0).  I also recognise
//            a contribution from my experience with PopCalendar 4.1 by
//            Liming(Victor) Weng.
//
// Link back: Please give me credit and link back to my page.  To ensure that
//            search engines give my page a higher ranking you can add the
//            following HTML to any indexed page on your web site:
//
//            <A HREF="http://www.tarrget.info/calendar/scw.htm">
//              Simple Calendar Widget by Anthony Garrett
//            </A>
//
// Features:  Easily customised
//                  (output date format, colours, language, year range and
//                   week start day)
//            Accepts a date as input
//                  (see comments below for formats).
//            Cross-browser code tested against;
//                  Internet Explorer 6.0.28     Mozilla  1.7.1
//                  Opera             7.52+      Firefox  0.9.1+
//                  Konqueror         3.4.0      Flock    0.4.9
//
// How to add the Calendar to your page:
//            This script needs to be defined for your page so, immediately
//            after the BODY tag add the following line;
//
//                  <script type='Text/JavaScript' src='scw.js'></script>
//
//            Your root directory of the web site should also contain an empty
//            file called "scwblank.html". See
//                  http://www.tarrget.info/calendar/IEnightmare.html
//            for a full explanation.
//
// How to use the Calendar once it is defined for your page:
//
//            Simply choose an event to trigger the calendar (like an onClick
//            or an onMouseOver) and an element to work on (for the calendar
//            to take its initial date from and write its output date to) then
//            write it like this;
//
//                  <<event>>="scwShow(<<element>>,event);"
//
//            e.g. onClick="scwShow(document.getElementById('myElement'),event);"
//            or   onMouseOver="scwShow(this,event);"
//
//            NOTE: If you wish to use the calendar with an Anchor tag, do
//                  not use the syntax:   href="javascript:scwShow(...)"
//                  Instead you should use the following;
//
//                  <a href="#" onclick="scwShow(<<element>>,event);return false;">
//                      <<your text>>
//                  </a>
//
//            If you are using a text node then specify the text's parent node
//            in the function call. The date should be the only text under that
//            node;
//
//            e.g.  <p onclick="scwShow(this,event);"><<date>></p>
//
//            You can also disable days of the week by adding arguments to the
//            call to scwShow.  The values should be Sunday = 0 through to
//            Saturday = 6.  A call to scwShow with Friday and Monday disabled
//            would look something like this;
//
//                  scwShow(<<element>>,event,5,1);
//
//            Finally you can use the following technique to run a function
//            when the calendar closes:
//
//                  scwNextAction=<<function>>.runsAfterSCW(this,<<arguments>>);
//                  scwShow(<<element>>,event <<,optional arguments above>>);
//
//            Where <<function>> is a function defined on the calling page
//            and <<arguments>> is the list of arguments being passed to that
//            function.
//
//      No event? No problem!
//
//            Normally the calendar will be triggered by an event but if you wish to
//            control it in code and the event is not available to you, simply pass
//            an element as the second parameter;
//
//            E.G.  scwShow(<<target element>>,<<source element>>);
//                  as in: scwShow(this,this);
//
//            ------------------------------------------------------------------
//            Here's an extremely trivial but fully functioning example page
//            showing two of the ways to trigger the calendar;
//
//            <html>
//                <head><title>Basic Example</title></head>
//                <body>
//                    <script type='text/JavaScript' src='scw.js'></script>
//                    <p onclick='scwShow(this,event);'>06-Dec-2006</p>
//                    <input onclick='scwShow(this,event);' value='07-Dec-2006' />
//                    <br/><br/>
//                    <a href='#' onclick='scwShow(this,event);return false;'>
//                        08-Dec-2006
//                    </a>
//                </body>
//            </html>
//
// *****************************************************************************
//
// See http://www.tarrget.info/calendar/scw.htm for a complete version history
//
// Version   Date        By               Description
// =======   ====        ===============  ===========
//   3.58    2007-04-04  Anthony Garrett  Resolved an error caused when the date
//                                         range does not include the current year.
//                                         Thanks to Steve Davis for letting me know.
//
//                                        Fixed "Today" selector display which
//                                         was incorrectly visible when year range
//                                         ended last year. (Also the result of
//                                         investigations based on Steve Davis'
//                                         feedback).
//
//   3.59    2007-06-13  Anthony Garrett  Added Verdana to font list of
//                                         calendar's CSS.  Resolves rendering
//                                         bug in Safari Beta 3 for Windows.
//
//   3.60    2007-07-31  Anthony Garrett  Fixed javascript error that occurred
//                                         when the target element had no value
//                                         attribute.  The error had no impact
//                                         on the behaviour of the script.  Thanks
//                                         to John Phelps for reporting this bug.
//
//   3.70    2007-09-21  Anthony Garrett  Updated the event trapping to make it
//                                         less intrusive on the page body.
//                                         NOTE: This requires that a calendar's
//                                         second parameter should be the calling
//                                         event (not the calling object as in
//                                         previous versions).
//                                         Thanks to Steve Davis for the bug report
//                                         that led to this change.
//
//                                        Fixed a bug that caused undelimited
//                                         dates to be handled incorrectly. They
//                                         are now parsed against the full date
//                                         output format then checked for validity.
//                                         Thanks to Dan Wood for raising this bug.
//
//                                        Replaced the date input sequence user
//                                         configuration setting with parsing the
//                                         sequence from the full format. New users
//                                         are often confused by the sequence and
//                                         in practice (to allow the calendar's date
//                                         output to be used for input) the sequence
//                                         must always match the full format element
//                                         order.
//
//                                        Extended IFRAME backing to all calendar objects
//                                         in order to improve calendar display over
//                                         some embedded applets and objects.  Thanks to
//                                         Stanko Kupcevic for his feedback on this.
//                                         NOTE: It is not possible to protect any
//                                         JavaScript object displayed over an
//                                         embedded DYNAMIC (and, therefore refreshed)
//                                         object because browsers usually do not
//                                         directly control the screen handling within
//                                         the object.  The best advice therefore remains
//                                         to design pages in such a way that the calendar
//                                         does not overlap embedded objects.
//
//  3.71     2008-12-14  Anthony Garrett  Restored the ability to use an element
//                                         as the second parameter when opening a
//                                         calendar while retaining the option
//                                         of passing an event. Thanks to Thierry Blind
//                                         and Sergey Snovsky for the feedback.
//
//  3.72     2008-02-24  Anthony Garrett  Trapped calls to script with only a
//                                         NAME attribute is set for the target
//                                         element when the script really requires
//                                         an ID attribute.  This is the most
//                                         frequent mistake reported to me.
//
//  3.73     2008-04-11  Anthony Garrett  Corrected the input month name parsing
//                                         so that it set the calendar to the
//                                         right month when long month names used.
//                                         Thanks to Ben Diamand for this bug report.
// *****************************************************************************

// ************************************
// Start of Simple Calendar Widget Code
// ************************************

// This date is used throughout to determine today's date.

    var scwDateNow = new Date(Date.parse(new Date().toDateString()));

//******************************************************************************
//------------------------------------------------------------------------------
// Customisation section
//------------------------------------------------------------------------------
//******************************************************************************

    // 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()-10;

    // How many years do want to be valid and to show in the drop-down list?

    var scwDropDownYears   = 20;

    // 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.

    var scwLanguage;

    scwHolidays=Array();

    function scwTestHoliday(dt) {
        if(dt.getDay()==0) return true;
      //  debug(dt)
       // debug(dt.getFullYear(),dt.getMonth()+1,dt.getDate())
        dt=''+(((dt.getFullYear()*13)+dt.getMonth()+1)*32+dt.getDate())
     //   debug(dt)
        if(scwHolidays[dt]) return true;
        return false;
    }

    function scwSetDefaultLanguage()
        {try
            {scwSetLanguage();}
         catch (exception)
            {// English
             scwToday               = 'Today:';
             scwDrag                = 'click here to drag';
             scwArrMonthNames       = ['Jan','Feb','Mar','Apr','May','Jun',
                                       'Jul','Aug','Sep','Oct','Nov','Dec'];
             scwArrWeekInits        = ['S','M','T','W','T','F','S'];
             scwInvalidDateMsg      = 'The entered date is invalid.\n';
             scwOutOfRangeMsg       = 'The entered date is out of range.';
             scwDoesNotExistMsg     = 'The entered date does not exist.';
             scwInvalidAlert        = ['Invalid date (',') ignored.'];
             scwDateDisablingError  = ['Error ',' is not a Date object.'];
             scwRangeDisablingError = ['Error ',
                                       ' should consist of two elements.'];
            }
        };

    // Note:  Always start the scwArrWeekInits array with your string for
    //        Sunday whatever scwWeekStart (below) is set to.

    // scwWeekStart determines the start of the week in the display
    // Set it to: 0 (Zero) for Sunday, 1 (One) for Monday etc..

    var scwWeekStart       =    0;

    // 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.

    var scwShowInvalidDateMsg       = true,
        scwShowOutOfRangeMsg        = true,
        scwShowDoesNotExistMsg      = true,
        scwShowInvalidAlert         = true,
        scwShowDateDisablingError   = true,
        scwShowRangeDisablingError  = true;

    // Set the allowed input date delimiters here...
    // E.g. To set the rising slash, hyphen, full-stop (aka stop or point),
    //      comma and space as delimiters use
    //              var scwArrDelimiters   = ['/','-','.',',',' '];

    var scwArrDelimiters   = ['/','-','.',',',' '];

    // 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
    var scwDateDisplayFormat = 'MMM dd, yyyy';     // e.g. 'MMM-DD-YYYY' for the US

    // Output date format

    //var scwDateOutputFormat  = 'DD MMM, YYYY'; // e.g. 'MMM-DD-YYYY' for the US
    var scwDateOutputFormat  = 'MMM dd, yyyy'; // e.g. 'MMM-DD-YYYY' for the US

    // Note: The delimiters used should be in scwArrDelimiters.

    // 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       = true;

    // var scwDisabledDates   = new Array();

    // e.g. To disable 10-Dec-2005:
    //          scwDisabledDates[0] = new Date(2005,11,10);
    //
    //      or a range from 2004-Dec-25 to 2005-Jan-01:
    //          scwDisabledDates[1] = [new Date(2004,11,25),new Date(2005,0,1)];
    //
    // Remember that Javascript months are Zero-based.

    // 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.

    var scwFormatTodayCell = true;
    var scwTodayCellBorderColour = 'red';

    // 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 = false;

    // 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
//------------------------------------------------------------------------------
//******************************************************************************

//  Variables required by both scwShow and scwShowMonth

    var scwTargetEle,
        scwTriggerEle,
        scwMonthSum            = 0,
        scwBlnFullInputDate    = true,
        scwPassEnabledDay      = new Array(),
        scwSeedDate            = /*new Date()*/ 0,
        scwParmActiveToday     = true,
        scwWeekStart           = scwWeekStart%7,
        scwToday,
        scwDrag,
        scwArrMonthNames,
        scwArrWeekInits,
        scwInvalidDateMsg,
        scwOutOfRangeMsg,
        scwDoesNotExistMsg,
        scwInvalidAlert,
        scwDateDisablingError,
        scwChanged,   
        scwRangeDisablingError;

    // Add a method to format a date into the required pattern

    Date.prototype.scwFormat =
        function(scwFormat)
            {var charCount = 0,
                 codeChar  = '',
                 result    = '';

             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;
            };

    // Add a method to left pad zeroes

    String.prototype.scwPadLeft =
        function(padToLength)
            {var result = '';
             for (var i=0;i<(padToLength - this.length);i++) {result += '0';}
             return (result + this);
            };

    // Set up a closure so that any next function can be triggered
    // after the calendar has been closed AND that function can take
    // arguments.

    Function.prototype.runsAfterSCW =
        function()  {var func = this,
                         args = new Array(arguments.length);

                     for (var i=0;i<args.length;++i) {args[i] = arguments[i];}

                     return function()
                        {// concat/join the two argument arrays
                         for (var i=0;i<arguments.length;++i) {args[args.length] = arguments[i];}
                         return (args.shift()==scwTriggerEle)?func.apply(this, args):null;
                        };
                    };

    // Set up some shortcuts


    // 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.
//
//      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.
//
// ****************************************************************************

    function scwShow(scwEle,scwSource)
        {scwChanged=false;
        if (!scwSource) {scwSource = window.event;}

         if (scwSource.tagName) // Second parameter isn't an event it's an element
            {var scwSourceEle = scwSource; }
         else   // Second parameter is an event
            {var scwSourceEle = (scwSource.target)
                                    ?scwSource.target
                                    :scwSource.srcElement;
            }

         scwTriggerEle = scwSourceEle;

         // Take any parameters that there might be from the third onwards as
         // day numbers to be disabled 0 = Sunday through to 6 = Saturday.

         scwParmActiveToday = true;

         for (var i=0;i<7;i++)
            {scwPassEnabledDay[(i+7-scwWeekStart)%7] = true;
             for (var j=2;j<arguments.length;j++)
                {if (arguments[j]==i)
                    {scwPassEnabledDay[(i+7-scwWeekStart)%7] = false;
                     if (scwDateNow.getDay()==i) {scwParmActiveToday = false;}
                    }
                }
            }

         //   If no value is preset then the seed date is
         //      Today (when today is in range) OR
         //      The middle of the date range.

        // BC-- Actually, I seed with the last date set
        // on the page, or the current date if none present 
        if(!scwSeedDate) scwSeedDate = scwDateNow;

         // Find the date and Strip space characters from start and
         // end of date input.

         var scwDateValue = '';

         if (scwEle.value) {scwDateValue = scwEle.value.replace(/^\s+/,'').replace(/\s+$/,'');}
         else   {if (typeof scwEle.value == 'undefined')
                    {var scwChildNodes = scwEle.childNodes;
                     for (var i=0;i<scwChildNodes.length;i++)
                        {if (scwChildNodes[i].nodeType == 3)
                            {scwDateValue = scwChildNodes[i].nodeValue.replace(/^\s+/,'').replace(/\s+$/,'');
                             if (scwDateValue.length > 0)
                                {scwTriggerEle.scwTextNode = scwChildNodes[i];
                                 scwTriggerEle.scwLength   = scwChildNodes[i].nodeValue.length;
                                 break;
                                }
                            }
                        }
                    }
                }

         // Set the language-dependent elements

         scwSetDefaultLanguage();

         document.getElementById('scwDragText').innerHTML = scwDrag;

         document.getElementById('scwMonths').options.length = 0;
         for (var i=0;i<scwArrMonthNames.length;i++)
            {document.getElementById('scwMonths').options[i] = new Option(scwArrMonthNames[i],scwArrMonthNames[i]);}

         document.getElementById('scwYears').options.length = 0;
         for (var i=0;i<scwDropDownYears;i++)
            {document.getElementById('scwYears').options[i] =  new Option((scwBaseYear+i),(scwBaseYear+i));}

         for (var i=0;i<scwArrWeekInits.length;i++)
            {document.getElementById('scwWeekInit' + i).innerHTML = scwArrWeekInits[(i+scwWeekStart)%scwArrWeekInits.length];}

         if (document.getElementById('scwFoot'))
            {document.getElementById('scwFoot').innerHTML = scwToday + ' ' + scwDateNow.scwFormat(scwDateDisplayFormat);}

         if (scwDateValue.length==0)
            {// If no value is entered and today is within the range,
             // use today's date, otherwise use the middle of the valid range.

             scwBlnFullInputDate=false;

             if ((new Date(scwBaseYear+scwDropDownYears,0,0))<scwSeedDate ||
                 (new Date(scwBaseYear,0,1))                 >scwSeedDate
                )
                {scwSeedDate = new Date(scwBaseYear + Math.floor(scwDropDownYears / 2), 5, 1);}
            }
         else
            {
            scwSeedDate=scwParseDate(scwDateValue) 
            }

         // Test that we have arrived at a valid date

         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.

             if ((new Date(scwBaseYear,0,1)) > scwSeedDate)
                {if (scwBlnStrict && scwShowOutOfRangeMsg) {alert(scwOutOfRangeMsg);}
                 scwSeedDate = new Date(scwBaseYear,0,1);
                 scwBlnFullInputDate=false;
                }
             else
                {if ((new Date(scwBaseYear+scwDropDownYears,0,0))<scwSeedDate)
                    {if (scwBlnStrict && scwShowOutOfRangeMsg) {alert(scwOutOfRangeMsg);}
                     scwSeedDate = new Date(scwBaseYear + Math.floor(scwDropDownYears)-1,11,1);
                     scwBlnFullInputDate=false;
                    }
                 /*else
                    {if (scwBlnStrict && scwBlnFullInputDate &&
                          (scwSeedDate.getDate()      != scwArrSeedDate[2] ||
                           (scwSeedDate.getMonth()+1) != scwArrSeedDate[1] ||
                           scwSeedDate.getFullYear()  != scwArrSeedDate[0]
                          )
                        )
                        {if (scwShowDoesNotExistMsg) alert(scwDoesNotExistMsg);
                         scwSeedDate = new Date(scwSeedDate.getFullYear(),scwSeedDate.getMonth()-1,1);
                         scwBlnFullInputDate=false;
                        }
                    } */
                }
            }

         // Test the disabled dates for validity
         // Give error message if not valid.
/*
         for (var i=0;i<scwDisabledDates.length;i++)
            {if (!((typeof scwDisabledDates[i] == 'object') && (scwDisabledDates[i].constructor == Date)))
                {if ((typeof scwDisabledDates[i] == 'object') && (scwDisabledDates[i].constructor == Array))
                    {var scwPass = true;

                     if (scwDisabledDates[i].length !=2)
                        {if (scwShowRangeDisablingError)
                            {alert(scwRangeDisablingError[0] + scwDisabledDates[i] + scwRangeDisablingError[1]);}
                         scwPass = false;
                        }
                     else
                        {for (var j=0;j<scwDisabledDates[i].length;j++)
                            {if (!((typeof scwDisabledDates[i][j] == 'object') && (scwDisabledDates[i][j].constructor == Date)))
                                {if (scwShowRangeDisablingError)
                                    {alert(  scwDateDisablingError[0] + scwDisabledDates[i][j] + scwDateDisablingError[1]);}
                                 scwPass = false;
                                }
                            }
                        }

                     if (scwPass && (scwDisabledDates[i][0] > scwDisabledDates[i][1])) {scwDisabledDates[i].reverse();}
                    }
                 else
                    {if (scwShowRangeDisablingError) {alert(scwDateDisablingError[0] + scwDisabledDates[i] + scwDateDisablingError[1]);}}
                }
            }
        */

         // Calculate the number of months that the entered (or
         // defaulted) month is after the start of the allowed
         // date range.

         scwMonthSum =  12*(scwSeedDate.getFullYear()-scwBaseYear)+scwSeedDate.getMonth();

         document.getElementById('scwYears' ).options.selectedIndex = Math.floor(scwMonthSum/12);
         document.getElementById('scwMonths').options.selectedIndex = (scwMonthSum%12);

         // Check whether or not dragging is allowed and display drag handle if necessary

         document.getElementById('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.

         scwTargetEle=scwEle;

         var offsetTop =parseInt(scwEle.offsetTop ,10) + parseInt(scwEle.offsetHeight,10),
             offsetLeft=parseInt(scwEle.offsetLeft,10);

         if (!window.opera)
             {while (scwEle.tagName!='BODY' && scwEle.tagName!='HTML')
                 {offsetTop -=parseInt(scwEle.scrollTop, 10);
                  offsetLeft-=parseInt(scwEle.scrollLeft,10);
                  scwEle=scwEle.parentNode;
                 }
              scwEle=scwTargetEle;
             }

         do {scwEle=scwEle.offsetParent;
             offsetTop +=parseInt(scwEle.offsetTop, 10);
             offsetLeft+=parseInt(scwEle.offsetLeft,10);
            }
         while (scwEle.tagName!='BODY' && scwEle.tagName!='HTML');

         document.getElementById('scw').style.top =offsetTop +'px';
         document.getElementById('scw').style.left=offsetLeft+'px';

         // Show it on the page
         document.getElementById('scw').style.visibility='inherit';
        };

    function scwHide()
        {
        if(eventHandler.ev2&&eventHandler.ev2.scwnohide)
            return
        document.getElementById('scw').style.visibility='hidden';
         if (typeof scwNextAction!='undefined' && scwNextAction!=null)
             {scwNextActionReturn = scwNextAction();
              // Explicit null set to prevent closure causing memory leak
              scwNextAction = null;
             }
         if(scwChanged) yajax.fakeEvent({
             'target':scwTargetEle,
             'type':'change'
            });
         scwChanged=false
        };

    function scwCancel(scwEvt)
        {if (scwClickToHide) {scwHide();}
         scwStopPropagation(scwEvt);
        };

    function scwStopPropagation(scwEvt)
        {if (scwEvt.stopPropagation)
                {scwEvt.stopPropagation();}     // Capture phase
         else   {scwEvt.cancelBubble = true;}   // Bubbling phase
        };

    function scwBeginDrag(event)
        {var elementToDrag = document.getElementById('scw');

         var deltaX    = event.clientX,
             deltaY    = event.clientY,
             offsetEle = elementToDrag;

         do {deltaX   -= parseInt(offsetEle.offsetLeft,10);
             deltaY   -= parseInt(offsetEle.offsetTop ,10);
             offsetEle = offsetEle.offsetParent;
            }
         while (offsetEle.tagName!='BODY' &&
                offsetEle.tagName!='HTML');

         if (document.addEventListener)
                {document.addEventListener('mousemove',moveHandler,true);        // Capture phase
                 document.addEventListener('mouseup',  upHandler,  true);        // Capture phase
                }
         else   {elementToDrag.attachEvent('onmousemove',moveHandler); // Bubbling phase
                 elementToDrag.attachEvent('onmouseup',  upHandler);   // Bubbling phase
                 elementToDrag.setCapture();
                }

         scwStopPropagation(event);

         function moveHandler(scwEvt)
            {if (!scwEvt) scwEvt = window.event;

             elementToDrag.style.left = (scwEvt.clientX - deltaX) + 'px';
             elementToDrag.style.top  = (scwEvt.clientY - deltaY) + 'px';

             scwStopPropagation(scwEvt);
            };

         function upHandler(scwEvt)
            {if (!scwEvt) scwEvt = window.event;

             if (document.removeEventListener)
                    {document.removeEventListener('mousemove',moveHandler,true);     // Capture phase
                     document.removeEventListener('mouseup',  upHandler,  true);     // Capture phase
                    }
             else   {elementToDrag.detachEvent('onmouseup',  upHandler);   // Bubbling phase
                     elementToDrag.detachEvent('onmousemove',moveHandler); // Bubbling phase
                     elementToDrag.releaseCapture();
                    }

             scwStopPropagation(scwEvt);
            };
        };

    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
         //                  (which initiates the display).

         var scwShowDate  = new Date(Date.parse(new Date().toDateString())),
             scwStartDate = new Date();

         // 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.

         scwShowDate.setHours(12);

         scwSelYears  = document.getElementById('scwYears');
         scwSelMonths = document.getElementById('scwMonths');

         if (scwSelYears.options.selectedIndex>-1)
            {scwMonthSum=12*(scwSelYears.options.selectedIndex)+scwBias;
             if (scwSelMonths.options.selectedIndex>-1) {scwMonthSum+=scwSelMonths.options.selectedIndex;}
            }
         else
            {if (scwSelMonths.options.selectedIndex>-1) {scwMonthSum+=scwSelMonths.options.selectedIndex;}}

         scwShowDate.setFullYear(scwBaseYear + Math.floor(scwMonthSum/12),(scwMonthSum%12),1);

         // If the Week numbers are displayed, shift the week day names to the right.
         document.getElementById('scwWeek_').style.display=(scwWeekNumberDisplay)?'':'none';

         // Opera has a bug with setting the selected index.
         // It requires the following work-around to force SELECTs to display correctly.
         if (window.opera)
            {document.getElementById('scwMonths').style.display = 'inherit';
             document.getElementById('scwYears' ).style.display = 'inherit';
           }

         // Set the drop down boxes.
         scwTemp = (12*parseInt((scwShowDate.getFullYear()-scwBaseYear),10)) + parseInt(scwShowDate.getMonth(),10);

         if (scwTemp > -1 && scwTemp < (12*scwDropDownYears))
            {scwSelYears.options.selectedIndex=Math.floor(scwMonthSum/12);
             scwSelMonths.options.selectedIndex=(scwMonthSum%12);

             scwCurMonth = scwShowDate.getMonth();

             scwShowDate.setDate((((scwShowDate.
                                    getDay()-scwWeekStart)<0)?-6:1)+
                                 scwWeekStart-scwShowDate.getDay());

             // This statement moved by Michael Cerveny to make version 3.55
             var scwCompareDateValue = new Date(scwShowDate.getFullYear(),
                                                scwShowDate.getMonth(),
                                                scwShowDate.getDate()).valueOf();

             scwStartDate = new Date(scwShowDate);

             if (document.getElementById('scwFoot'))
                {var scwFoot = document.getElementById('scwFoot');

                 function scwFootOutput() {scwSetOutput(scwDateNow);};

                 scwFoot.onclick=scwFootOutput;
                 scwFoot.className   = 'scwFoot';
                }

             function scwSetOutput(scwOutputDate)
                {if (typeof scwTargetEle.value == 'undefined')
                      {scwTriggerEle.scwTextNode.replaceData(0,scwTriggerEle.scwLength,scwOutputDate.scwFormat(scwDateOutputFormat));}
                 else {
                     var old=scwTargetEle.value;
                     scwTargetEle.value = scwOutputDate.scwFormat(scwDateOutputFormat);
                     if(old!=scwTargetEle.value) scwChanged=true;
                     
                 }
                 scwSeedDate=scwOutputDate
                };

             function scwCellOutput(scwEvt)
                {var scwEle = scwEventTrigger(scwEvt),
                     scwOutputDate = new Date(scwStartDate);

                 if (scwEle.nodeType==3) scwEle=scwEle.parentNode;

                 scwOutputDate.setDate(scwStartDate.getDate() + parseInt(scwEle.id.substr(8),10));

                 scwSetOutput(scwOutputDate);
                 eventHandler.ev2.scwnohide=0
                 scwHide();
                };

             function scwEventTrigger(scwEvt)
                {if (!scwEvt) {scwEvt = event;}
                 return scwEvt.target||scwEvt.srcElement;
                };

             function scwWeekNumber(scwInDate)
                {// The base day in the week of the input date
                 var scwInDateWeekBase = new Date(scwInDate);

                 scwInDateWeekBase.setDate(scwInDateWeekBase.getDate()
                                            - scwInDateWeekBase.getDay()
                                            + scwWeekNumberBaseDay
                                            + ((scwInDate.getDay()>
                                                scwWeekNumberBaseDay)?7:0));

                 // The first Base Day in the year
                 var scwFirstBaseDay = new Date(scwInDateWeekBase.getFullYear(),0,1);

                 scwFirstBaseDay.setDate(scwFirstBaseDay.getDate()
                                            - scwFirstBaseDay.getDay()
                                            + scwWeekNumberBaseDay
                                        );

                 if (scwFirstBaseDay < new Date(scwInDateWeekBase.getFullYear(),0,1))
                    {scwFirstBaseDay.setDate(scwFirstBaseDay.getDate()+7);}

                 // Start of Week 01
                 var scwStartWeekOne = new Date(scwFirstBaseDay
                                                - scwWeekNumberBaseDay
                                                + scwInDate.getDay());

                 if (scwStartWeekOne > scwFirstBaseDay)
                    {scwStartWeekOne.setDate(scwStartWeekOne.getDate()-7);}

                 // 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.

                 var scwWeekNo = '0' + (Math.round((scwInDateWeekBase - scwFirstBaseDay)/604800000,0) + 1);

                 // Return the last two characters in the week number string

                 return scwWeekNo.substring(scwWeekNo.length-2, scwWeekNo.length);
                };

             // Treewalk to display the dates.
             // I tried to use getElementsByName but IE refused to cooperate
             // so I resorted to this method which works for all tested
             // browsers.

             var i;
             var scwCells = document.getElementById('scwCells');
             if(scwWeekNumberDisplay) {
//Calculate the week number using scwShowDate
                 for(i=0;i<7;i++) {
                     scwTmpEl.innerHTML = scwWeekNumber(scwShowDate);
                     scwTmpEl.style.borderColor =
                         (scwTmpEl.currentStyle)
                            ?scwTmpEl.currentStyle['backgroundColor']
                            :(window.getComputedStyle)
                                ?document.defaultView.getComputedStyle(scwTmpEl,null).getPropertyValue('background-color')
                                :'';
                     scwTmpEl.style.display='';
                 }
             }
             else {
                 document.getElementById('scwWeek_').style.display='none';
                 for(i=0;i<7;i++)
                     document.getElementById('scwWeek_'+i).style.display='none';
             }

             for (i=0;i<7;i++) {
                 var scwRows = document.getElementById('scwWeek_'+i).parentNode;

                 for (j=1;j<8;j++) {
                     var scwCell = document.getElementById('scwCell_'+(i*7+j-1))
                    
                     scwCell.innerHTML= scwShowDate.getDate();
                     // scwDisabled=false
                     scwCell.style.visibility =
                        (scwOutOfMonthHide &&
                            (scwShowDate <
                                (new Date(scwShowDate.getFullYear(),
                                          scwCurMonth,1,
                                          scwShowDate.getHours()))
                             ||
                             scwShowDate >
                                (new Date(scwShowDate.getFullYear(),
                                          scwCurMonth+1,0,
                                          scwShowDate.getHours()))
                            )
                        )?'hidden':'inherit';
                     if(scwCell.style.visibility=='hidden') debug('hidden')

                     if(0){}
                     else
                        {

                        scwCell.onclick=scwCellOutput;
                        if(scwShowDate.toDateString()==scwSeedDate.toDateString()) {
                            scwCell.className='scwInputDate' 
                        }
                        else if(scwTestHoliday(scwShowDate)) {
                            scwCell.className='scwCellsWeekend'
                        }
                        else if(scwShowDate.getMonth()!=scwCurMonth) {
                            scwCell.className='scwCellsExMonth'
                        }
                        else {
                            scwCell.className='scwCells'
                        }

                        /* scwCell.className=
                            (scwTestHoliday(scwShowDate))
                                ?'scwCellsWeekend':
                             (scwShowDate.getMonth()!=scwCurMonth)
                                ?'scwCellsExMonth'
                                :(scwBlnFullInputDate &&
                                  scwShowDate.toDateString()==
                                  scwSeedDate.toDateString())
                                    ?'scwInputDate' :'scwCells'; */

                         scwCell.style.borderColor =
                             (scwFormatTodayCell && scwShowDate.toDateString() == scwDateNow.toDateString())
                                ?scwTodayCellBorderColour
                                :(scwCell.currentStyle)
                                    ?scwCell.currentStyle['backgroundColor']
                                    :(window.getComputedStyle)
                                        ?document.defaultView.getComputedStyle(scwCell,null).getPropertyValue('background-color')
                                        :'';
                       }

                     scwShowDate.setDate(scwShowDate.getDate()+1);
                     scwCompareDateValue = new Date(scwShowDate.getFullYear(),scwShowDate.getMonth(),scwShowDate.getDate()).valueOf();
                    }
                }
            }

         // 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.

         if (window.opera)
            {document.getElementById('scwMonths').style.display = 'inline';
             document.getElementById('scwYears' ).style.display = 'inline';
             document.getElementById('scw').style.visibility='hidden';
             document.getElementById('scw').style.visibility='inherit';
           }
        };

// *************************
//  End of Function Library
// *************************
// ***************************
// Start of Calendar structure
// ***************************

function scwHeadLeftFunc() { scwShowMonth(-1); }
function scwMonthsFunc() { scwShowMonth(0); }
function scwHeadRightFunc() { scwShowMonth(1); }

function scwInitialize() {
    if (document.addEventListener)
            {document.getElementById('scw'         ).addEventListener('click',scwCancel,false);
             document.getElementById('scwHeadLeft' ).addEventListener('click',scwStopPropagation,false);
             document.getElementById('scwMonths'   ).addEventListener('click',scwStopPropagation,false);
             document.getElementById('scwMonths'   ).addEventListener('change',scwStopPropagation,false);
             document.getElementById('scwYears'    ).addEventListener('click',scwStopPropagation,false);
             document.getElementById('scwYears'    ).addEventListener('change',scwStopPropagation,false);
             document.getElementById('scwHeadRight').addEventListener('click',scwStopPropagation,false);
             document.getElementById('scwCells').addEventListener('click',scwStopPropagation,false);

             document.getElementById('scwDragtd').addEventListener('mousedown',scwBeginDrag,false);
             document.getElementById('scwHeadLeft').addEventListener('click',scwHeadLeftFunc,false);
             document.getElementById('scwMonths').addEventListener('click',scwMonthsFunc,false);
             document.getElementById('scwYears').addEventListener('click',scwMonthsFunc,false);
             document.getElementById('scwHeadRight').addEventListener('click',scwHeadRightFunc,false);
            }
    else    {document.getElementById('scw'         ).attachEvent('onclick',scwCancel);
             document.getElementById('scwHeadLeft' ).attachEvent('onclick',scwStopPropagation);
             document.getElementById('scwMonths'   ).attachEvent('onclick',scwStopPropagation);
             document.getElementById('scwMonths'   ).attachEvent('onchange',scwStopPropagation);
             document.getElementById('scwYears'    ).attachEvent('onclick',scwStopPropagation);
             document.getElementById('scwYears'    ).attachEvent('onchange',scwStopPropagation);
             document.getElementById('scwHeadRight').attachEvent('onclick',scwStopPropagation);
             document.getElementById('scwCells').attachEvent('onclick',scwStopPropagation);

             document.getElementById('scwDragtd').attachEvent('onmousedown',scwBeginDrag);
             document.getElementById('scwHeadLeft').attachEvent('onclick',scwHeadLeftFunc);
             document.getElementById('scwMonths').attachEvent('onclick',scwMonthsFunc);
             document.getElementById('scwYears').attachEvent('onclick',scwMonthsFunc);
             document.getElementById('scwHeadRight').attachEvent('onclick',scwHeadRightFunc);
            }
    if (document.addEventListener)
            {document.addEventListener('click',scwHide, false);}
    else    {document.attachEvent('onclick',scwHide);}

}
// ************************************
//  End of Simple Calendar Widget Code
// ************************************

date_formats_with_year = ['mdY', 'Ymd',  
                          'dbY', 'bdY',
                          'mdy', 'ymd',  
                          'dby', 'bdy']
date_formats_with_yeariso = ['mdY', 'Ymd',  
                          'dbY', 'bdY',
                          'ymd', 'mdy',  
                          'dby', 'bdy']

date_formats_without_year = [ 'db', 'bd','md']

function scwParseDate(str) {
    function parseFormat(fmt,dt) {
        var d=new Date()
        d.setTime(946713600)
        for(var i=0;i<fmt.length;i++) {
            var f=fmt.substr(i,1)
            var p=dt[i]
            switch(f) {
                case 'm':
                    d.setMonth(parseRange(p,1,12)-1)
                    break
                case 'd':
                    d.setDate(parseRange(p,1,31))
                    break
                case 'Y':
                    d.setFullYear(parseRange(p,100,9999))
                    break
                case 'y':
                    d.setFullYear(parseRange(p,0,99)+2000)
                    break
                case 'b':
                    d.setMonth(parseMonth(p))
                    break
                default:
                    alert('bad format')
                    throw true
            }
            if(isNaN(d)) throw true
        }
        return d
    }

    function parseRange(v,s,e) {
        if(!v.match(/^\d+$/)) {
            throw true
        }
        v=parseInt(v,10)
        if(v>e||v<s) throw true
        return v
    }
    function parseMonth(v) {
        v=v.toUpperCase()
        if(v.length>3) v=v.substr(0,3)
        for(var i=0;i<12;i++) {
            m=scwArrMonthNames[i]
            m=m.toUpperCase() 
            if(v==m) return i
        }
        throw true
    }
    var dfwy=date_formats_with_yeariso
    if(str.indexOf('/')!=-1||str.indexOf(',')!=-1)
        dfwy=date_formats_with_year
    str=str.replace(/([a-zA-Z])([0-9])/,'$1 $2')
    str=str.replace(/([0-9])([a-zA-Z])/,'$1 $2')
    var dt=str.split(/[\/ ,-]+/,3)
    if(dt.length==3) {
        for(var i=0;i<dfwy.length;i++) {
            fmt=date_formats_with_year[i]
            try {
                return parseFormat(fmt,dt)
            } catch(e) {}
        }
    }
    if(dt.length==2) {
        for(var i=0;i<date_formats_without_year.length;i++) {
            fmt=date_formats_without_year[i]
            try {
                var t=parseFormat(fmt,dt)
                t.setFullYear(Date().getFullYear())
                return t
            } catch(e) {}
        }
    }
    return Number.NaN
}

function calClick(yajax,ev1,ev2) {
    var id=ev2.target.id
    var param=id.split(':')
    scwStopPropagation(ev1)
    eventHandler.ev2.scwnohide=1
    /* if nothing is done, a click event can be caught by
    both scwHide and scwShow. The original way this was 
    supposed to work, scwShow was deeper in the document,
    and then cancelled propagation. But my framework ties
    everything to document, and two document level events
    are executed in arbitary order without a portable way
    to stop them. So I attach a value to the current
    event, and solve the problem that way */
    param.shift()
    var el=document.getElementById(param.join(':'))
    scwShow(el,ev1)
}




