Project

General

Profile

1
// *****************************************************************************
2
//      Simple Calendar Widget - Cross-Browser Javascript pop-up calendar.
3
//
4
//   Copyright (C) 2005-2007  Anthony Garrett
5
//
6
//   This library is free software; you can redistribute it and/or
7
//   modify it under the terms of the GNU Lesser General Public
8
//   License as published by the Free Software Foundation; either
9
//   version 2.1 of the License, or (at your option) any later version.
10
//
11
//   This library is distributed in the hope that it will be useful,
12
//   but WITHOUT ANY WARRANTY; without even the implied warranty of
13
//   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
//   Lesser General Public License for more details.
15
//
16
//   You should have received a copy of the GNU Lesser General Public
17
//   License along with this library; if not, it is available at
18
//   the GNU web site (http://www.gnu.org/) or by writing to the
19
//   Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20
//   Boston, MA  02110-1301  USA
21
//
22
// *****************************************************************************
23
//
24
// Contact:   Sorry, I can't offer support for this but if you find a problem
25
//            (or just want to tell me how useful you find it), please send
26
//            me an email at scwfeedback@tarrget.info (Note the two Rs in
27
//            tarrget).  I will try to fix problems quickly but this is a
28
//            spare time thing for me.
29
//
30
// Credits:   I wrote this from scratch myself but I couldn't have done it
31
//            without the superb "JavaScript The Definitive Guide" by David
32
//            Flanagan (Pub. O'Reilly ISBN 0-596-00048-0).  I also recognise
33
//            a contribution from my experience with PopCalendar 4.1 by
34
//            Liming(Victor) Weng.
35
//
36
// Link back: Please give me credit and link back to my page.  To ensure that
37
//            search engines give my page a higher ranking you can add the
38
//            following HTML to any indexed page on your web site:
39
//
40
//            <A HREF="http://www.tarrget.info/calendar/scw.htm">
41
//              Simple Calendar Widget by Anthony Garrett
42
//            </A>
43
//
44
// Features:  Easily customised
45
//                  (output date format, colours, language, year range and
46
//                   week start day)
47
//            Accepts a date as input
48
//                  (see comments below for formats).
49
//            Cross-browser code tested against;
50
//                  Internet Explorer 6.0.28     Mozilla  1.7.1
51
//                  Opera             7.52+      Firefox  0.9.1+
52
//                  Konqueror         3.4.0      Flock    0.4.9
53
//
54
// How to add the Calendar to your page:
55
//            This script needs to be defined for your page so, immediately
56
//            after the BODY tag add the following line;
57
//
58
//                  <script type='Text/JavaScript' src='scw.js'></script>
59
//
60
//            Your root directory of the web site should also contain an empty
61
//            file called "scwblank.html". See
62
//                  http://www.tarrget.info/calendar/IEnightmare.html
63
//            for a full explanation.
64
//
65
// How to use the Calendar once it is defined for your page:
66
//
67
//            Simply choose an event to trigger the calendar (like an onClick
68
//            or an onMouseOver) and an element to work on (for the calendar
69
//            to take its initial date from and write its output date to) then
70
//            write it like this;
71
//
72
//                  <<event>>="scwShow(<<element>>,event);"
73
//
74
//            e.g. onClick="scwShow(scwID('myElement'),event);"
75
//            or   onMouseOver="scwShow(this,event);"
76
//
77
//            NOTE: If you wish to use the calendar with an Anchor tag, do
78
//                  not use the syntax:   href="javascript:scwShow(...)"
79
//                  Instead you should use the following;
80
//
81
//                  <a href="#" onclick="scwShow(<<element>>,event);return false;">
82
//                      <<your text>>
83
//                  </a>
84
//
85
//            If you are using a text node then specify the text's parent node
86
//            in the function call. The date should be the only text under that
87
//            node;
88
//
89
//            e.g.  <p onclick="scwShow(this,event);"><<date>></p>
90
//
91
//            You can also disable days of the week by adding arguments to the
92
//            call to scwShow.  The values should be Sunday = 0 through to
93
//            Saturday = 6.  A call to scwShow with Friday and Monday disabled
94
//            would look something like this;
95
//
96
//                  scwShow(<<element>>,event,5,1);
97
//
98
//            Finally you can use the following technique to run a function
99
//            when the calendar closes:
100
//
101
//                  scwNextAction=<<function>>.runsAfterSCW(this,<<arguments>>);
102
//                  scwShow(<<element>>,event <<,optional arguments above>>);
103
//
104
//            Where <<function>> is a function defined on the calling page
105
//            and <<arguments>> is the list of arguments being passed to that
106
//            function.
107
//
108
//      No event? No problem!
109
//
110
//            Normally the calendar will be triggered by an event but if you wish to
111
//            control it in code and the event is not available to you, simply pass
112
//            an element as the second parameter;
113
//
114
//            E.G.  scwShow(<<target element>>,<<source element>>);
115
//                  as in: scwShow(this,this);
116
//
117
//            ------------------------------------------------------------------
118
//            Here's an extremely trivial but fully functioning example page
119
//            showing two of the ways to trigger the calendar;
120
//
121
//            <html>
122
//                <head><title>Basic Example</title></head>
123
//                <body>
124
//                    <script type='text/JavaScript' src='scw.js'></script>
125
//                    <p onclick='scwShow(this,event);'>06-Dec-2006</p>
126
//                    <input onclick='scwShow(this,event);' value='07-Dec-2006' />
127
//                    <br/><br/>
128
//                    <a href='#' onclick='scwShow(this,event);return false;'>
129
//                        08-Dec-2006
130
//                    </a>
131
//                </body>
132
//            </html>
133
//
134
// *****************************************************************************
135
//
136
// See http://www.tarrget.info/calendar/scw.htm for a complete version history
137
//
138
// Version   Date        By               Description
139
// =======   ====        ===============  ===========
140
//   3.58    2007-04-04  Anthony Garrett  Resolved an error caused when the date
141
//                                         range does not include the current year.
142
//                                         Thanks to Steve Davis for letting me know.
143
//
144
//                                        Fixed "Today" selector display which
145
//                                         was incorrectly visible when year range
146
//                                         ended last year. (Also the result of
147
//                                         investigations based on Steve Davis'
148
//                                         feedback).
149
//
150
//   3.59    2007-06-13  Anthony Garrett  Added Verdana to font list of
151
//                                         calendar's CSS.  Resolves rendering
152
//                                         bug in Safari Beta 3 for Windows.
153
//
154
//   3.60    2007-07-31  Anthony Garrett  Fixed javascript error that occurred
155
//                                         when the target element had no value
156
//                                         attribute.  The error had no impact
157
//                                         on the behaviour of the script.  Thanks
158
//                                         to John Phelps for reporting this bug.
159
//
160
//   3.70    2007-09-21  Anthony Garrett  Updated the event trapping to make it
161
//                                         less intrusive on the page body.
162
//                                         NOTE: This requires that a calendar's
163
//                                         second parameter should be the calling
164
//                                         event (not the calling object as in
165
//                                         previous versions).
166
//                                         Thanks to Steve Davis for the bug report
167
//                                         that led to this change.
168
//
169
//                                        Fixed a bug that caused undelimited
170
//                                         dates to be handled incorrectly. They
171
//                                         are now parsed against the full date
172
//                                         output format then checked for validity.
173
//                                         Thanks to Dan Wood for raising this bug.
174
//
175
//                                        Replaced the date input sequence user
176
//                                         configuration setting with parsing the
177
//                                         sequence from the full format. New users
178
//                                         are often confused by the sequence and
179
//                                         in practice (to allow the calendar's date
180
//                                         output to be used for input) the sequence
181
//                                         must always match the full format element
182
//                                         order.
183
//
184
//                                        Extended IFRAME backing to all calendar objects
185
//                                         in order to improve calendar display over
186
//                                         some embedded applets and objects.  Thanks to
187
//                                         Stanko Kupcevic for his feedback on this.
188
//                                         NOTE: It is not possible to protect any
189
//                                         JavaScript object displayed over an
190
//                                         embedded DYNAMIC (and, therefore refreshed)
191
//                                         object because browsers usually do not
192
//                                         directly control the screen handling within
193
//                                         the object.  The best advice therefore remains
194
//                                         to design pages in such a way that the calendar
195
//                                         does not overlap embedded objects.
196
//
197
//  3.71     2008-12-14  Anthony Garrett  Restored the ability to use an element
198
//                                         as the second parameter when opening a
199
//                                         calendar while retaining the option
200
//                                         of passing an event. Thanks to Thierry Blind
201
//                                         and Sergey Snovsky for the feedback.
202
//
203
//  3.72     2008-02-24  Anthony Garrett  Trapped calls to script with only a
204
//                                         NAME attribute is set for the target
205
//                                         element when the script really requires
206
//                                         an ID attribute.  This is the most
207
//                                         frequent mistake reported to me.
208
//
209
//  3.73     2008-04-11  Anthony Garrett  Corrected the input month name parsing
210
//                                         so that it set the calendar to the
211
//                                         right month when long month names used.
212
//                                         Thanks to Ben Diamand for this bug report.
213
//
214
//  3.80     2008-04-29  Anthony Garrett  Added optional auto-positioning of the
215
//                                         calendar when its normal position would
216
//                                         go off the visible area.
217
//                                         Thanks to Chandramouli Iyer for this
218
//                                         suggestion.
219
//
220
//  3.90     2008-05-05  Anthony Garrett  Added an optional "Clear" button for
221
//                                         use when handling a read-only text
222
//                                         input element. Thanks to Sanjay Gangwal
223
//                                         for his suggestion.
224
// *****************************************************************************
225

    
226
// ************************************
227
// Start of Simple Calendar Widget Code
228
// ************************************
229

    
230
// This date is used throughout to determine today's date.
231

    
232
    var scwDateNow = new Date(Date.parse(new Date().toDateString()));
233

    
234
//******************************************************************************
235
//------------------------------------------------------------------------------
236
// Customisation section
237
//------------------------------------------------------------------------------
238
//******************************************************************************
239

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

    
246
    var scwBaseYear        = scwDateNow.getFullYear()-10;
247

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

    
250
    var scwDropDownYears   = 20;
251

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

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

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

    
265
    var scwLanguage;
266

    
267
    function scwSetDefaultLanguage()
268
        {try
269
            {scwSetLanguage();}
270
         catch (exception)
271
            {// English
272
             scwToday               = 'Today:';
273
             scwClear               = 'Clear';
274
             scwDrag                = 'click here to drag';
275
             scwArrMonthNames       = ['Jan','Feb','Mar','Apr','May','Jun',
276
                                       'Jul','Aug','Sep','Oct','Nov','Dec'];
277
             scwArrWeekInits        = ['S','M','T','W','T','F','S'];
278
             scwInvalidDateMsg      = 'The entered date is invalid.\n';
279
             scwOutOfRangeMsg       = 'The entered date is out of range.';
280
             scwDoesNotExistMsg     = 'The entered date does not exist.';
281
             scwInvalidAlert        = ['Invalid date (',') ignored.'];
282
             scwDateDisablingError  = ['Error ',' is not a Date object.'];
283
             scwRangeDisablingError = ['Error ',
284
                                       ' should consist of two elements.'];
285
            }
286
        };
287

    
288
    // Note:  Always start the scwArrWeekInits array with your string for
289
    //        Sunday whatever scwWeekStart (below) is set to.
290

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

    
294
    var scwWeekStart       =    1;
295

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

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

    
304
    var scwWeekNumberDisplay    = false;
305

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

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

    
313
    var scwWeekNumberBaseDay    = 4;
314

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

    
318
    var scwShowInvalidDateMsg       = true,
319
        scwShowOutOfRangeMsg        = true,
320
        scwShowDoesNotExistMsg      = true,
321
        scwShowInvalidAlert         = true,
322
        scwShowDateDisablingError   = true,
323
        scwShowRangeDisablingError  = true;
324

    
325
    // Set the allowed input date delimiters here...
326
    // E.g. To set the rising slash, hyphen, full-stop (aka stop or point),
327
    //      comma and space as delimiters use
328
    //              var scwArrDelimiters   = ['/','-','.',',',' '];
329

    
330
    var scwArrDelimiters   = ['/','-','.',',',' '];
331

    
332
    // Set the format for the displayed 'Today' date and for the output
333
    // date here.
334
    //
335
    // The format is described using delimiters of your choice (as set
336
    // in scwArrDelimiters above) and case insensitive letters D, M and Y.
337
    //
338
    // NOTE: If no delimiters are input then the date output format is used
339
    //       to parse the value.  This allows less flexiblility in the input
340
    //       value than using delimiters but an accurately entered date
341
    //       remains parsable.
342
    //
343
    // Definition               Returns
344
    // ----------               -------
345
    // D            date in the month without zero filling
346
    // DD           date in the month left zero filled
347
    // M            month number without zero filling
348
    // MM           month number left zero filled
349
    // MMM          month string from scwArrMonthNames
350
    // YY           year number in two digits
351
    // YYYY         year number in four digits
352

    
353
    // Displayed "Today" date format
354

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

    
357
    // Output date format
358

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

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

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

    
369
    var scwZindex          = 1;
370

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

    
377
    var scwBlnStrict       = false;
378

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

    
384
    var scwClearButton     = true;
385

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

    
392
    var scwAutoPosition    = true;
393

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

    
414
    var scwEnabledDay      = [true, true, true, true, true, true, true,
415
                              true, true, true, true, true, true, true,
416
                              true, true, true, true, true, true, true,
417
                              true, true, true, true, true, true, true,
418
                              true, true, true, true, true, true, true,
419
                              true, true, true, true, true, true, true];
420

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

    
427
    var scwDisabledDates   = new Array();
428

    
429
    // e.g. To disable 10-Dec-2005:
430
    //          scwDisabledDates[0] = new Date(2005,11,10);
431
    //
432
    //      or a range from 2004-Dec-25 to 2005-Jan-01:
433
    //          scwDisabledDates[1] = [new Date(2004,11,25),new Date(2005,0,1)];
434
    //
435
    // Remember that Javascript months are Zero-based.
436

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

    
441
    var scwActiveToday = true;
442

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

    
453
    var scwOutOfMonthDisable = false;
454
    var scwOutOfMonthHide    = false;
455

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

    
461
    var scwOutOfRangeDisable = true;
462

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

    
467
    var scwFormatTodayCell = false;
468
    var scwTodayCellBorderColour = 'red';
469

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

    
476
    var scwAllowDrag = false;
477

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

    
482
    var scwClickToHide = false;
483

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

    
489
    document.writeln(
490
        '<style type="text/css">'                                       +
491
            '.scw           {padding:1px;vertical-align:middle;}'       +
492
            'iframe.scw     {position:absolute;z-index:' + scwZindex    +
493
                            ';top:0px;left:0px;visibility:hidden;'      +
494
                            'width:1px;height:1px;}'                    +
495
            'table.scw      {padding:0px;visibility:hidden;'            +
496
                            'position:absolute;cursor:default;'         +
497
                            'width:200px;top:0px;left:0px;'             +
498
                            'z-index:' + (scwZindex+1)                  +
499
                            ';text-align:center;}'                      +
500
        '</style>'  );
501

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

    
507
    document.writeln(
508
        '<style type="text/css">'                                       +
509
            '/* IMPORTANT:  The SCW calendar script requires all '      +
510
            '               the classes defined here.'                  +
511
            '*/'                                                        +
512
            'table.scw      {padding:       1px;'                       +
513
                            'vertical-align:middle;'                    +
514
                            'border:        ridge 2px;'                 +
515
                            'font-size:     10pt;'                      +
516
                            'font-family:   ' +
517
                                   'Verdana,Arial,Helvetica,Sans-Serif;'+
518
                            'font-weight:   bold;}'                     +
519
            'td.scwDrag,'                                               +
520
            'td.scwHead                 {padding:       0px 0px;'       +
521
                                        'text-align:    center;}'       +
522
            'td.scwDrag                 {font-size:     8pt;}'          +
523
            'select.scwHead             {margin:        3px 1px;'       +
524
                                        'text-align:    center;}'       +
525
            'input.scwHead              {height:        22px;'          +
526
                                        'width:         22px;'          +
527
                                        'vertical-align:middle;'        +
528
                                        'text-align:    center;'        +
529
                                        'margin:        2px 1px;'       +
530
                                        'font-weight:   bold;'          +
531
                                        'font-size:     10pt;'          +
532
                                        'font-family:   fixedSys;}'     +
533
            'td.scwWeekNumberHead,'                                     +
534
            'td.scwWeek                 {padding:       0px;'           +
535
                                        'text-align:    center;'        +
536
                                        'font-weight:   bold;}'         +
537
            'td.scwNow,'                                                +
538
            'td.scwNowHover,'                                           +
539
            'td.scwNow:hover,'                                          +
540
            'td.scwNowDisabled          {padding:       0px;'           +
541
                                        'text-align:    center;'        +
542
                                        'vertical-align:middle;'        +
543
                                        'font-weight:   normal;}'       +
544
            'table.scwCells             {text-align:    right;'         +
545
                                        'font-size:     8pt;'           +
546
                                        'width:         96%;}'          +
547
            'td.scwCells,'                  +
548
            'td.scwCellsHover,'             +
549
            'td.scwCells:hover,'            +
550
            'td.scwCellsDisabled,'          +
551
            'td.scwCellsExMonth,'           +
552
            'td.scwCellsExMonthHover,'      +
553
            'td.scwCellsExMonth:hover,'     +
554
            'td.scwCellsExMonthDisabled,'   +
555
            'td.scwCellsWeekend,'           +
556
            'td.scwCellsWeekendHover,'      +
557
            'td.scwCellsWeekend:hover,'     +
558
            'td.scwCellsWeekendDisabled,'   +
559
            'td.scwInputDate,'              +
560
            'td.scwInputDateHover,'         +
561
            'td.scwInputDate:hover,'        +
562
            'td.scwInputDateDisabled,'      +
563
            'td.scwWeekNo,'                 +
564
            'td.scwWeeks                {padding:           3px;'       +
565
                                        'width:             16px;'      +
566
                                        'height:            16px;'      +
567
                                        'border-width:      1px;'       +
568
                                        'border-style:      solid;'     +
569
                                        'font-weight:       bold;'      +
570
                                        'vertical-align:    middle;}'   +
571
            '/* Blend the colours into your page here...    */'         +
572
            '/* Calendar background */'                                 +
573
            'table.scw                  {background-color:  #6666CC;}'  +
574
            '/* Drag Handle */'                                         +
575
            'td.scwDrag                 {background-color:  #9999CC;'   +
576
                                        'color:             #CCCCFF;}'  +
577
            '/* Week number heading */'                                 +
578
            'td.scwWeekNumberHead       {color:             #6666CC;}'  +
579
            '/* Week day headings */'                                   +
580
            'td.scwWeek                 {color:             #CCCCCC;}'  +
581
            '/* Week numbers */'                                        +
582
            'td.scwWeekNo               {background-color:  #776677;'   +
583
                                        'color:             #CCCCCC;}'  +
584
            '/* Enabled Days */'                                        +
585
            '/* Week Day */'                                            +
586
            'td.scwCells                {background-color:  #CCCCCC;'   +
587
                                        'color:             #000000;}'  +
588
            '/* Day matching the input date */'                         +
589
            'td.scwInputDate            {background-color:  #CC9999;'   +
590
                                        'color:             #FF0000;}'  +
591
            '/* Weekend Day */'                                         +
592
            'td.scwCellsWeekend         {background-color:  #CCCCCC;'   +
593
                                        'color:             #CC6666;}'  +
594
            '/* Day outside the current month */'                       +
595
            'td.scwCellsExMonth         {background-color:  #CCCCCC;'   +
596
                                        'color:             #666666;}'  +
597
            '/* Today selector */'                                      +
598
            'td.scwNow                  {background-color:  #6666CC;'   +
599
                                        'color:             #FFFFFF;}'  +
600
            '/* Clear Button */'                                        +
601
            'td.scwClear                {padding:           0px;}'      +
602
            'input.scwClear             {padding:           0px;'       +
603
                                        'text-align:        center;'    +
604
                                        'font-size:         8pt;}'      +
605
            '/* MouseOver/Hover formatting '                            +
606
            '       If you want to "turn off" any of the formatting '   +
607
            '       then just set to the same as the standard format'   +
608
            '       above.'                                             +
609
            ' '                                                         +
610
            '       Note: The reason that the following are'            +
611
            '       implemented using both a class and a :hover'        +
612
            '       pseudoclass is because Opera handles the rendering' +
613
            '       involved in the class swap very poorly and IE6 '    +
614
            '       (and below) only implements pseudoclasses on the'   +
615
            '       anchor tag.'                                        +
616
            '*/'                                                        +
617
            '/* Active cells */'                                        +
618
            'td.scwCells:hover,'                                        +
619
            'td.scwCellsHover           {background-color:  #FFFF00;'   +
620
                                        'cursor:            pointer;'   +
621
                                        'color:             #000000;}'  +
622
            '/* Day matching the input date */'                         +
623
            'td.scwInputDate:hover,'                                    +
624
            'td.scwInputDateHover       {background-color:  #FFFF00;'   +
625
                                        'cursor:            pointer;'   +
626
                                        'color:             #000000;}'  +
627
            '/* Weekend cells */'                                       +
628
            'td.scwCellsWeekend:hover,'                                 +
629
            'td.scwCellsWeekendHover    {background-color:  #FFFF00;'   +
630
                                        'cursor:            pointer;'   +
631
                                        'color:             #000000;}'  +
632
            '/* Day outside the current month */'                       +
633
            'td.scwCellsExMonth:hover,'                                 +
634
            'td.scwCellsExMonthHover    {background-color:  #FFFF00;'   +
635
                                        'cursor:            pointer;'   +
636
                                        'color:             #000000;}'  +
637
            '/* Today selector */'                                      +
638
            'td.scwNow:hover,'                                          +
639
            'td.scwNowHover             {color:             #FFFF00;'   +
640
                                        'cursor:            pointer;'   +
641
                                        'font-weight:       bold;}'     +
642
            '/* Disabled cells */'                                      +
643
            '/* Week Day */'                                            +
644
            '/* Day matching the input date */'                         +
645
            'td.scwInputDateDisabled    {background-color:  #999999;'   +
646
                                        'color:             #000000;}'  +
647
            'td.scwCellsDisabled        {background-color:  #999999;'   +
648
                                        'color:             #000000;}'  +
649
            '/* Weekend Day */'                                         +
650
            'td.scwCellsWeekendDisabled {background-color:  #999999;'   +
651
                                        'color:             #CC6666;}'  +
652
            '/* Day outside the current month */'                       +
653
            'td.scwCellsExMonthDisabled {background-color:  #999999;'   +
654
                                        'color:             #666666;}'  +
655
            'td.scwNowDisabled          {background-color:  #6666CC;'   +
656
                                        'color:             #FFFFFF;}'  +
657
        '</style>'
658
                    );
659

    
660
//******************************************************************************
661
//------------------------------------------------------------------------------
662
// End of customisation section
663
//------------------------------------------------------------------------------
664
//******************************************************************************
665

    
666
//  Variables required by both scwShow and scwShowMonth
667

    
668
    var scwTargetEle,
669
        scwTriggerEle,
670
        scwMonthSum            = 0,
671
        scwBlnFullInputDate    = false,
672
        scwPassEnabledDay      = new Array(),
673
        scwSeedDate            = new Date(),
674
        scwParmActiveToday     = true,
675
        scwWeekStart           = scwWeekStart%7,
676
        scwToday,
677
        scwClear,
678
        scwDrag,
679
        scwArrMonthNames,
680
        scwArrWeekInits,
681
        scwInvalidDateMsg,
682
        scwOutOfRangeMsg,
683
        scwDoesNotExistMsg,
684
        scwInvalidAlert,
685
        scwDateDisablingError,
686
        scwRangeDisablingError;
687

    
688
    // Add a method to format a date into the required pattern
689

    
690
    Date.prototype.scwFormat =
691
        function(scwFormat)
692
            {var charCount = 0,
693
                 codeChar  = '',
694
                 result    = '';
695

    
696
             for (var i=0;i<=scwFormat.length;i++)
697
                {if (i<scwFormat.length && scwFormat.charAt(i)==codeChar)
698
                        {// If we haven't hit the end of the string and
699
                         // the format string character is the same as
700
                         // the previous one, just clock up one to the
701
                         // length of the current element definition
702
                         charCount++;
703
                        }
704
                 else   {switch (codeChar)
705
                            {case 'y': case 'Y':
706
                                result += (this.getFullYear()%Math.
707
                                            pow(10,charCount)).toString().
708
                                            scwPadLeft(charCount);
709
                                break;
710
                             case 'm': case 'M':
711
                                // If we find an M, check the number of them to
712
                                // determine whether to get the month number or
713
                                // the month name.
714
                                result += (charCount<3)
715
                                            ?(this.getMonth()+1).
716
                                                toString().scwPadLeft(charCount)
717
                                            :scwArrMonthNames[this.getMonth()];
718
                                break;
719
                             case 'd': case 'D':
720
                                // If we find a D, get the date and format it
721
                                result += this.getDate().toString().
722
                                            scwPadLeft(charCount);
723
                                break;
724
                             default:
725
                                // Copy any unrecognised characters across
726
                                while (charCount-- > 0) {result += codeChar;}
727
                            }
728

    
729
                         if (i<scwFormat.length)
730
                            {// Store the character we have just worked on
731
                             codeChar  = scwFormat.charAt(i);
732
                             charCount = 1;
733
                            }
734
                        }
735
                }
736
             return result;
737
            };
738

    
739
    // Add a method to left pad zeroes
740

    
741
    String.prototype.scwPadLeft =
742
        function(padToLength)
743
            {var result = '';
744
             for (var i=0;i<(padToLength - this.length);i++) {result += '0';}
745
             return (result + this);
746
            };
747

    
748
    // Set up a closure so that any next function can be triggered
749
    // after the calendar has been closed AND that function can take
750
    // arguments.
751

    
752
    Function.prototype.runsAfterSCW =
753
        function()  {var func = this,
754
                         args = new Array(arguments.length);
755

    
756
                     for (var i=0;i<args.length;++i) {args[i] = arguments[i];}
757

    
758
                     return function()
759
                        {// concat/join the two argument arrays
760
                         for (var i=0;i<arguments.length;++i) {args[args.length] = arguments[i];}
761
                         return (args.shift()==scwTriggerEle)?func.apply(this, args):null;
762
                        };
763
                    };
764

    
765
    // Set up some shortcuts
766

    
767
    function scwID(id)
768
        {if (document.getElementById(id) || (!document.getElementById(id) && document.getElementsByName(id).length==0))
769
                                    // IF   An ID attribute is assigned
770
                                    // OR   No ID attribute is assigned but using IE and Opera
771
                                    //          (which will find the NAME attribute value using getElementById)
772
                                    // OR   No element has this ID or NAME attribute value
773
                                    //          (used internally by the script)
774
                                    // THEN Return the required element.
775
                {return document.getElementById(id);}
776
         else   {if (document.getElementsByName(id).length==1)
777
                                // IF   No ID attribute is assigned
778
                                // AND  Using a standards-based browser
779
                                // AND  Only one element has the NAME attribute set to the value
780
                                // THEN Return the required element (using the NAME attribute value).
781
                        {return document.getElementsByName(id)[0];}
782
                 else   {if (document.getElementsByName(id).length>1)
783
                            {   // IF   No ID attribute is assigned
784
                                // AND  using a standards-based browser
785
                                // AND  more than one element has the NAME attribute set to the value
786
                                // THEN alert developer to fix the fault.
787
                             alert( 'SCW' +
788
                                    ' \nCannot uniquely identify element named: ' + id +
789
                                    '.\nMore than one identical NAME attribute defined' +
790
                                    '.\nSolution: Assign the required element a unique ID attribute value.');
791
                            }
792
                        }
793
                }
794
        };
795

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

    
800
    var scwNextActionReturn, scwNextAction;
801

    
802
// ****************************************************************************
803
// Start of Function Library
804
//
805
//  Exposed functions:
806
//
807
//      scwShow             Entry point for display of calendar,
808
//                              called in main page.
809
//      showCal             Legacy name of scwShow:
810
//                              Passes only legacy arguments,
811
//                              not the optional day disabling arguments.
812
//
813
//      scwShowMonth        Displays a month on the calendar,
814
//                              Called when a month is set or changed.
815
//
816
//      scwBeginDrag        Controls calendar dragging.
817
//
818
//      scwCancel           Called when the calendar background is clicked:
819
//                              Calls scwStopPropagation and may call scwHide.
820
//      scwHide             Hides the calendar, called on various events.
821
//      scwStopPropagation  Stops the propagation of an event.
822
//
823
// ****************************************************************************
824

    
825
    function showCal(scwEle,scwSource) {scwShow(scwEle,scwSource);};
826
    function scwShow(scwEle,scwSource)
827
        {if (!scwSource) {scwSource = window.event;}
828

    
829
         if (scwSource.tagName) // Second parameter isn't an event it's an element
830
            {var scwSourceEle = scwSource;
831

    
832
             if (scwID('scwIE'))  {window.event.cancelBubble = true;}
833
             else {scwSourceEle.parentNode.addEventListener('click',scwStopPropagation,false);}
834
            }
835
         else   // Second parameter is an event
836
            {var scwSourceEle = (scwSource.target)
837
                                    ?scwSource.target
838
                                    :scwSource.srcElement;
839

    
840
             // Stop the click event that opens the calendar from bubbling up to
841
             // the document-level event handler that hides it!
842
             if (scwSource.stopPropagation) {scwSource.stopPropagation();}
843
             else                           {scwSource.cancelBubble = true;}
844
            }
845

    
846
         scwTriggerEle = scwSourceEle;
847

    
848
         // Take any parameters that there might be from the third onwards as
849
         // day numbers to be disabled 0 = Sunday through to 6 = Saturday.
850

    
851
         scwParmActiveToday = true;
852

    
853
         for (var i=0;i<7;i++)
854
            {scwPassEnabledDay[(i+7-scwWeekStart)%7] = true;
855
             for (var j=2;j<arguments.length;j++)
856
                {if (arguments[j]==i)
857
                    {scwPassEnabledDay[(i+7-scwWeekStart)%7] = false;
858
                     if (scwDateNow.getDay()==i) {scwParmActiveToday = false;}
859
                    }
860
                }
861
            }
862

    
863
         //   If no value is preset then the seed date is
864
         //      Today (when today is in range) OR
865
         //      The middle of the date range.
866

    
867
         scwSeedDate = scwDateNow;
868

    
869
         // Find the date and Strip space characters from start and
870
         // end of date input.
871

    
872
         var scwDateValue = '';
873

    
874
         if (scwEle.value) {scwDateValue = scwEle.value.replace(/^\s+/,'').replace(/\s+$/,'');}
875
         else   {if (typeof scwEle.value == 'undefined')
876
                    {var scwChildNodes = scwEle.childNodes;
877
                     for (var i=0;i<scwChildNodes.length;i++)
878
                        {if (scwChildNodes[i].nodeType == 3)
879
                            {scwDateValue = scwChildNodes[i].nodeValue.replace(/^\s+/,'').replace(/\s+$/,'');
880
                             if (scwDateValue.length > 0)
881
                                {scwTriggerEle.scwTextNode = scwChildNodes[i];
882
                                 scwTriggerEle.scwLength   = scwChildNodes[i].nodeValue.length;
883
                                 break;
884
                                }
885
                            }
886
                        }
887
                    }
888
                }
889

    
890
         // Set the language-dependent elements
891

    
892
         scwSetDefaultLanguage();
893

    
894
         scwID('scwDragText').innerHTML = scwDrag;
895

    
896
         scwID('scwMonths').options.length = 0;
897
         for (var i=0;i<scwArrMonthNames.length;i++)
898
            {scwID('scwMonths').options[i] = new Option(scwArrMonthNames[i],scwArrMonthNames[i]);}
899

    
900
         scwID('scwYears').options.length = 0;
901
         for (var i=0;i<scwDropDownYears;i++)
902
            {scwID('scwYears').options[i] =  new Option((scwBaseYear+i),(scwBaseYear+i));}
903

    
904
         for (var i=0;i<scwArrWeekInits.length;i++)
905
            {scwID('scwWeekInit' + i).innerHTML = scwArrWeekInits[(i+scwWeekStart)%scwArrWeekInits.length];}
906

    
907
         if (((new Date(scwBaseYear + scwDropDownYears, 0, 0)) > scwDateNow &&
908
              (new Date(scwBaseYear, 0, 0))                    < scwDateNow) ||
909
             (scwClearButton && (scwEle.readOnly || scwEle.disabled))
910
            )   {scwID('scwFoot').style.display = '';
911
                 scwID('scwNow').innerHTML = scwToday + ' ' + scwDateNow.scwFormat(scwDateDisplayFormat);
912
                 scwID('scwClearButton').value = scwClear;
913
                 if ((new Date(scwBaseYear + scwDropDownYears, 0, 0)) > scwDateNow &&
914
                     (new Date(scwBaseYear, 0, 0))                    < scwDateNow
915
                    )   {scwID('scwNow').style.display = '';
916
                         if (scwClearButton && (scwEle.readOnly || scwEle.disabled))
917
                                {scwID('scwClear').style.display   = '';
918
                                 scwID('scwClear').style.textAlign = 'left';
919
                                 scwID('scwNow').style.textAlign   = 'right';
920
                                }
921
                         else   {scwID('scwClear').style.display = 'none';
922
                                 scwID('scwNow').style.textAlign = 'center';
923
                                }
924
                        }
925
                 else   {scwID('scwClear').style.textAlign = 'center';
926
                         scwID('scwClear').style.display = '';
927
                         scwID('scwNow').style.display = 'none';
928
                        }
929
                }
930
         else   {scwID('scwFoot').style.display = 'none';}
931

    
932
         if (scwDateValue.length==0)
933
            {// If no value is entered and today is within the range,
934
             // use today's date, otherwise use the middle of the valid range.
935

    
936
             scwBlnFullInputDate=false;
937

    
938
             if ((new Date(scwBaseYear+scwDropDownYears,0,0))<scwSeedDate ||
939
                 (new Date(scwBaseYear,0,1))                 >scwSeedDate
940
                )
941
                {scwSeedDate = new Date(scwBaseYear + Math.floor(scwDropDownYears / 2), 5, 1);}
942
            }
943
         else
944
            {function scwInputFormat()
945
                {var scwArrSeed = new Array(),
946
                     scwArrInput = scwDateValue.split(new RegExp('[\\'+scwArrDelimiters.join('\\')+']+','g'));
947

    
948
                 // "Escape" all the user defined date delimiters above -
949
                 // several delimiters will need it and it does no harm for
950
                 // the others.
951

    
952
                 // Strip any empty array elements (caused by delimiters)
953
                 // from the beginning or end of the array. They will
954
                 // still appear in the output string if in the output
955
                 // format.
956

    
957
                 if (scwArrInput[0]!=null)
958
                    {if (scwArrInput[0].length==0)                      {scwArrInput.splice(0,1);}
959
                     if (scwArrInput[scwArrInput.length-1].length==0)   {scwArrInput.splice(scwArrInput.length-1,1);}
960
                    }
961

    
962
                 scwBlnFullInputDate = false;
963

    
964
                 scwDateOutputFormat = scwDateOutputFormat.toUpperCase();
965

    
966
                 // List all the allowed letters in the date format
967
                 var template = ['D','M','Y'];
968

    
969
                 // Prepare the sequence of date input elements
970
                 var result = new Array();
971

    
972
                 for (var i=0;i<template.length;i++)
973
                    {if (scwDateOutputFormat.search(template[i])>-1)
974
                        {result[scwDateOutputFormat.search(template[i])] = template[i];}
975
                    }
976

    
977
                 var scwDateSequence = result.join('');
978

    
979
                 // Separate the elements of the date input
980
                 switch (scwArrInput.length)
981
                    {case 1:
982
                        {if (scwDateOutputFormat.indexOf('Y')>-1 &&
983
                             scwArrInput[0].length>scwDateOutputFormat.lastIndexOf('Y'))
984
                            {scwArrSeed[0] = parseInt(scwArrInput[0].substring(scwDateOutputFormat.indexOf('Y'),
985
                                                                               scwDateOutputFormat.lastIndexOf('Y')+1),10);
986
                            }
987
                         else   {scwArrSeed[0] = 0;}
988

    
989
                         if (scwDateOutputFormat.indexOf('M')>-1 &&
990
                             scwArrInput[0].length>scwDateOutputFormat.lastIndexOf('M'))
991
                            {scwArrSeed[1] = scwArrInput[0].substring(scwDateOutputFormat.indexOf('M'),
992
                                                                      scwDateOutputFormat.lastIndexOf('M')+1);
993
                            }
994
                         else   {scwArrSeed[1] = '6';}
995

    
996
                         if (scwDateOutputFormat.indexOf('D')>-1 &&
997
                             scwArrInput[0].length>scwDateOutputFormat.lastIndexOf('D'))
998
                            {scwArrSeed[2] = parseInt(scwArrInput[0].substring(scwDateOutputFormat.indexOf('D'),
999
                                                                               scwDateOutputFormat.lastIndexOf('D')+1),10);
1000
                            }
1001
                         else   {scwArrSeed[2] = 1;}
1002

    
1003
                         if (scwArrInput[0].length==scwDateOutputFormat.length) {scwBlnFullInputDate = true;}
1004
                         break;
1005
                        }
1006
                     case 2:
1007
                        {// Year and Month entry
1008
                         scwArrSeed[0] =
1009
                             parseInt(scwArrInput[scwDateSequence.
1010
                                                    replace(/D/i,'').
1011
                                                    search(/Y/i)],10);  // Year
1012
                         scwArrSeed[1] = scwArrInput[scwDateSequence.
1013
                                                    replace(/D/i,'').
1014
                                                    search(/M/i)];      // Month
1015
                         scwArrSeed[2] = 1;                             // Day
1016
                         break;
1017
                        }
1018
                     case 3:
1019
                        {// Day Month and Year entry
1020

    
1021
                         scwArrSeed[0] =
1022
                             parseInt(scwArrInput[scwDateSequence.
1023
                                                    search(/Y/i)],10);  // Year
1024
                         scwArrSeed[1] = scwArrInput[scwDateSequence.
1025
                                                    search(/M/i)];      // Month
1026
                         scwArrSeed[2] =
1027
                             parseInt(scwArrInput[scwDateSequence.
1028
                                                    search(/D/i)],10);  // Day
1029

    
1030
                         scwBlnFullInputDate = true;
1031
                         break;
1032
                        }
1033
                     default:
1034
                        {// A stuff-up has led to more than three elements in
1035
                         // the date.
1036
                         scwArrSeed[0] = 0;     // Year
1037
                         scwArrSeed[1] = 0;     // Month
1038
                         scwArrSeed[2] = 0;     // Day
1039
                        }
1040
                    }
1041

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

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

    
1052
                 var scwExpValDay    = new RegExp('^(0?[1-9]|[1-2][0-9]|3[0-1])$'),
1053
                     scwExpValMonth  = new RegExp('^(0?[1-9]|1[0-2]|'        +
1054
                                                  scwArrMonthNames.join('|') +
1055
                                                  ')$','i'),
1056
                     scwExpValYear   = new RegExp('^([0-9]{1,2}|[0-9]{4})$');
1057

    
1058
                 // Apply validation and report failures
1059

    
1060
                 if (scwExpValYear.exec(scwArrSeed[0])  == null ||
1061
                     scwExpValMonth.exec(scwArrSeed[1]) == null ||
1062
                     scwExpValDay.exec(scwArrSeed[2])   == null
1063
                    )
1064
                    {if (scwShowInvalidDateMsg)
1065
                        {alert(scwInvalidDateMsg  +
1066
                               scwInvalidAlert[0] + scwDateValue +
1067
                               scwInvalidAlert[1]);}
1068
                     scwBlnFullInputDate = false;
1069
                     scwArrSeed[0] = scwBaseYear +
1070
                                     Math.floor(scwDropDownYears/2); // Year
1071
                     scwArrSeed[1] = '6';                            // Month
1072
                     scwArrSeed[2] = 1;                              // Day
1073
                    }
1074

    
1075
                 // Return the  Year    in scwArrSeed[0]
1076
                 //             Month   in scwArrSeed[1]
1077
                 //             Day     in scwArrSeed[2]
1078

    
1079
                 return scwArrSeed;
1080
                };
1081

    
1082
             // Parse the string into an array using the allowed delimiters
1083

    
1084
             scwArrSeedDate = scwInputFormat();
1085

    
1086
             // So now we have the Year, Month and Day in an array.
1087

    
1088
             //   If the year is one or two digits then the routine assumes a
1089
             //   year belongs in the 21st Century unless it is less than 50
1090
             //   in which case it assumes the 20th Century is intended.
1091

    
1092
             if (scwArrSeedDate[0]<100) {scwArrSeedDate[0] += (scwArrSeedDate[0]>50)?1900:2000;}
1093

    
1094
             // Check whether the month is in digits or an abbreviation
1095

    
1096
             if (scwArrSeedDate[1].search(/\d+/)<0)
1097
                {for (i=0;i<scwArrMonthNames.length;i++)
1098
                    {if (scwArrSeedDate[1].toUpperCase()==scwArrMonthNames[i].toUpperCase())
1099
                        {scwArrSeedDate[1]=i+1;
1100
                         break;
1101
                        }
1102
                    }
1103
                }
1104

    
1105
             scwSeedDate = new Date(scwArrSeedDate[0],scwArrSeedDate[1]-1,scwArrSeedDate[2]);
1106
            }
1107

    
1108
         // Test that we have arrived at a valid date
1109

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

    
1119
             if ((new Date(scwBaseYear,0,1)) > scwSeedDate)
1120
                {if (scwBlnStrict && scwShowOutOfRangeMsg) {alert(scwOutOfRangeMsg);}
1121
                 scwSeedDate = new Date(scwBaseYear,0,1);
1122
                 scwBlnFullInputDate=false;
1123
                }
1124
             else
1125
                {if ((new Date(scwBaseYear+scwDropDownYears,0,0))<scwSeedDate)
1126
                    {if (scwBlnStrict && scwShowOutOfRangeMsg) {alert(scwOutOfRangeMsg);}
1127
                     scwSeedDate = new Date(scwBaseYear + Math.floor(scwDropDownYears)-1,11,1);
1128
                     scwBlnFullInputDate=false;
1129
                    }
1130
                 else
1131
                    {if (scwBlnStrict && scwBlnFullInputDate &&
1132
                          (scwSeedDate.getDate()      != scwArrSeedDate[2] ||
1133
                           (scwSeedDate.getMonth()+1) != scwArrSeedDate[1] ||
1134
                           scwSeedDate.getFullYear()  != scwArrSeedDate[0]
1135
                          )
1136
                        )
1137
                        {if (scwShowDoesNotExistMsg) alert(scwDoesNotExistMsg);
1138
                         scwSeedDate = new Date(scwSeedDate.getFullYear(),scwSeedDate.getMonth()-1,1);
1139
                         scwBlnFullInputDate=false;
1140
                        }
1141
                    }
1142
                }
1143
            }
1144

    
1145
         // Test the disabled dates for validity
1146
         // Give error message if not valid.
1147

    
1148
         for (var i=0;i<scwDisabledDates.length;i++)
1149
            {if (!((typeof scwDisabledDates[i] == 'object') && (scwDisabledDates[i].constructor == Date)))
1150
                {if ((typeof scwDisabledDates[i] == 'object') && (scwDisabledDates[i].constructor == Array))
1151
                    {var scwPass = true;
1152

    
1153
                     if (scwDisabledDates[i].length !=2)
1154
                        {if (scwShowRangeDisablingError)
1155
                            {alert(scwRangeDisablingError[0] + scwDisabledDates[i] + scwRangeDisablingError[1]);}
1156
                         scwPass = false;
1157
                        }
1158
                     else
1159
                        {for (var j=0;j<scwDisabledDates[i].length;j++)
1160
                            {if (!((typeof scwDisabledDates[i][j] == 'object') && (scwDisabledDates[i][j].constructor == Date)))
1161
                                {if (scwShowRangeDisablingError)
1162
                                    {alert(  scwDateDisablingError[0] + scwDisabledDates[i][j] + scwDateDisablingError[1]);}
1163
                                 scwPass = false;
1164
                                }
1165
                            }
1166
                        }
1167

    
1168
                     if (scwPass && (scwDisabledDates[i][0] > scwDisabledDates[i][1])) {scwDisabledDates[i].reverse();}
1169
                    }
1170
                 else
1171
                    {if (scwShowRangeDisablingError) {alert(scwDateDisablingError[0] + scwDisabledDates[i] + scwDateDisablingError[1]);}}
1172
                }
1173
            }
1174

    
1175
         // Calculate the number of months that the entered (or
1176
         // defaulted) month is after the start of the allowed
1177
         // date range.
1178

    
1179
         scwMonthSum =  12*(scwSeedDate.getFullYear()-scwBaseYear)+scwSeedDate.getMonth();
1180

    
1181
         scwID('scwYears' ).options.selectedIndex = Math.floor(scwMonthSum/12);
1182
         scwID('scwMonths').options.selectedIndex = (scwMonthSum%12);
1183

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

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

    
1188
         // Display the month
1189

    
1190
         scwShowMonth(0);
1191

    
1192
         // Position the calendar box
1193

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

    
1199
         scwTargetEle=scwEle;
1200

    
1201
         var offsetTop =parseInt(scwEle.offsetTop ,10) + parseInt(scwEle.offsetHeight,10),
1202
             offsetLeft=parseInt(scwEle.offsetLeft,10);
1203

    
1204
         if (!window.opera)
1205
             {while (scwEle.tagName!='BODY' && scwEle.tagName!='HTML')
1206
                 {offsetTop -=parseInt(scwEle.scrollTop, 10);
1207
                  offsetLeft-=parseInt(scwEle.scrollLeft,10);
1208
                  scwEle=scwEle.parentNode;
1209
                 }
1210
              scwEle=scwTargetEle;
1211
             }
1212

    
1213
         do {scwEle=scwEle.offsetParent;
1214
             offsetTop +=parseInt(scwEle.offsetTop, 10);
1215
             offsetLeft+=parseInt(scwEle.offsetLeft,10);
1216
            }
1217
         while (scwEle.tagName!='BODY' && scwEle.tagName!='HTML');
1218

    
1219
         if (scwAutoPosition)
1220
             {var scwWidth      = parseInt(scwID('scw').offsetWidth, 10),
1221
                  scwHeight     = parseInt(scwID('scw').offsetHeight,10),
1222
                  scwWindowLeft =
1223
                     (document.body && document.body.scrollLeft)
1224
                          ?document.body.scrollLeft                  //DOM compliant
1225
                          :(document.documentElement && document.documentElement.scrollLeft)
1226
                              ?document.documentElement.scrollLeft   //IE6+ standards compliant
1227
                              :0,                                    //Failed
1228
                  scwWindowWidth =
1229
                      (typeof(innerWidth) == 'number')
1230
                          ?innerWidth                                //DOM compliant
1231
                          :(document.documentElement && document.documentElement.clientWidth)
1232
                              ?document.documentElement.clientWidth  //IE6+ standards compliant
1233
                              :(document.body && document.body.clientWidth)
1234
                                  ?document.body.clientWidth         //IE non-compliant
1235
                                  :0,                                //Failed
1236
                  scwWindowTop =
1237
                      (document.body && document.body.scrollTop)
1238
                          ?document.body.scrollTop                   //DOM compliant
1239
                          :(document.documentElement && document.documentElement.scrollTop)
1240
                              ?document.documentElement.scrollTop    //IE6+ standards compliant
1241
                              :0,                                    //Failed
1242
                  scwWindowHeight =
1243
                      (typeof(innerHeight) == 'number')
1244
                          ?innerHeight                               //DOM compliant
1245
                          :(document.documentElement && document.documentElement.clientHeight)
1246
                              ?document.documentElement.clientHeight //IE6+ standards compliant
1247
                              :(document.body && document.body.clientHeight)
1248
                                  ?document.body.clientHeight        //IE non-compliant
1249
                                  :0;                                //Failed
1250

    
1251
              offsetLeft -= (offsetLeft - scwWidth + parseInt(scwTargetEle.offsetWidth,10) >= scwWindowLeft &&
1252
                             offsetLeft + scwWidth > scwWindowLeft + scwWindowWidth
1253
                            )?(scwWidth - parseInt(scwTargetEle.offsetWidth,10)):0;
1254

    
1255
              offsetTop -= (offsetTop - scwHeight - parseInt(scwTargetEle.offsetHeight,10) >= scwWindowTop &&
1256
                            offsetTop + scwHeight > scwWindowTop + scwWindowHeight
1257
                           )?(scwHeight + parseInt(scwTargetEle.offsetHeight,10)):0;
1258
             }
1259

    
1260
         scwID('scw').style.top         = offsetTop+'px';
1261
         scwID('scw').style.left        = offsetLeft+'px';
1262
         scwID('scwIframe').style.top   = offsetTop+'px';
1263
         scwID('scwIframe').style.left  = offsetLeft+'px';
1264

    
1265
         scwID('scwIframe').style.width =(scwID('scw').offsetWidth-(scwID('scwIE')?2:4))+'px';
1266
         scwID('scwIframe').style.height=(scwID('scw').offsetHeight-(scwID('scwIE')?2:4))+'px';
1267
         scwID('scwIframe').style.visibility='inherit';
1268

    
1269
         // Show it on the page
1270
         scwID('scw').style.visibility='inherit';
1271
        };
1272

    
1273
    function scwHide()
1274
        {scwID('scw').style.visibility='hidden';
1275
         scwID('scwIframe').style.visibility='hidden';
1276
         if (typeof scwNextAction!='undefined' && scwNextAction!=null)
1277
             {scwNextActionReturn = scwNextAction();
1278
              // Explicit null set to prevent closure causing memory leak
1279
              scwNextAction = null;
1280
             }
1281
        };
1282

    
1283
    function scwCancel(scwEvt)
1284
        {if (scwClickToHide) {scwHide();}
1285
         scwStopPropagation(scwEvt);
1286
        };
1287

    
1288
    function scwStopPropagation(scwEvt)
1289
        {if (scwEvt.stopPropagation)
1290
                {scwEvt.stopPropagation();}     // Capture phase
1291
         else   {scwEvt.cancelBubble = true;}   // Bubbling phase
1292
        };
1293

    
1294
    function scwBeginDrag(event)
1295
        {var elementToDrag = scwID('scw');
1296

    
1297
         var deltaX    = event.clientX,
1298
             deltaY    = event.clientY,
1299
             offsetEle = elementToDrag;
1300

    
1301
         do {deltaX   -= parseInt(offsetEle.offsetLeft,10);
1302
             deltaY   -= parseInt(offsetEle.offsetTop ,10);
1303
             offsetEle = offsetEle.offsetParent;
1304
            }
1305
         while (offsetEle.tagName!='BODY' &&
1306
                offsetEle.tagName!='HTML');
1307

    
1308
         if (document.addEventListener)
1309
                {document.addEventListener('mousemove',moveHandler,true);        // Capture phase
1310
                 document.addEventListener('mouseup',  upHandler,  true);        // Capture phase
1311
                }
1312
         else   {elementToDrag.attachEvent('onmousemove',moveHandler); // Bubbling phase
1313
                 elementToDrag.attachEvent('onmouseup',  upHandler);   // Bubbling phase
1314
                 elementToDrag.setCapture();
1315
                }
1316

    
1317
         scwStopPropagation(event);
1318

    
1319
         function moveHandler(scwEvt)
1320
            {if (!scwEvt) scwEvt = window.event;
1321

    
1322
             elementToDrag.style.left = (scwEvt.clientX - deltaX) + 'px';
1323
             elementToDrag.style.top  = (scwEvt.clientY - deltaY) + 'px';
1324

    
1325
             scwID('scwIframe').style.left = (scwEvt.clientX - deltaX) + 'px';
1326
             scwID('scwIframe').style.top  = (scwEvt.clientY - deltaY) + 'px';
1327

    
1328
             scwStopPropagation(scwEvt);
1329
            };
1330

    
1331
         function upHandler(scwEvt)
1332
            {if (!scwEvt) scwEvt = window.event;
1333

    
1334
             if (document.removeEventListener)
1335
                    {document.removeEventListener('mousemove',moveHandler,true);     // Capture phase
1336
                     document.removeEventListener('mouseup',  upHandler,  true);     // Capture phase
1337
                    }
1338
             else   {elementToDrag.detachEvent('onmouseup',  upHandler);   // Bubbling phase
1339
                     elementToDrag.detachEvent('onmousemove',moveHandler); // Bubbling phase
1340
                     elementToDrag.releaseCapture();
1341
                    }
1342

    
1343
             scwStopPropagation(scwEvt);
1344
            };
1345
        };
1346

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

    
1356
         var scwShowDate  = new Date(Date.parse(new Date().toDateString())),
1357
             scwStartDate = new Date();
1358

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

    
1364
         scwShowDate.setHours(12);
1365

    
1366
         scwSelYears  = scwID('scwYears');
1367
         scwSelMonths = scwID('scwMonths');
1368

    
1369
         if (scwSelYears.options.selectedIndex>-1)
1370
            {scwMonthSum=12*(scwSelYears.options.selectedIndex)+scwBias;
1371
             if (scwSelMonths.options.selectedIndex>-1) {scwMonthSum+=scwSelMonths.options.selectedIndex;}
1372
            }
1373
         else
1374
            {if (scwSelMonths.options.selectedIndex>-1) {scwMonthSum+=scwSelMonths.options.selectedIndex;}}
1375

    
1376
         scwShowDate.setFullYear(scwBaseYear + Math.floor(scwMonthSum/12),(scwMonthSum%12),1);
1377

    
1378
         // If the Week numbers are displayed, shift the week day names to the right.
1379
         scwID('scwWeek_').style.display=(scwWeekNumberDisplay)?'':'none';
1380

    
1381
         // Opera has a bug with setting the selected index.
1382
         // It requires the following work-around to force SELECTs to display correctly.
1383
         if (window.opera)
1384
            {scwID('scwMonths').style.display = 'inherit';
1385
             scwID('scwYears' ).style.display = 'inherit';
1386
           }
1387

    
1388
         // Set the drop down boxes.
1389
         scwTemp = (12*parseInt((scwShowDate.getFullYear()-scwBaseYear),10)) + parseInt(scwShowDate.getMonth(),10);
1390

    
1391
         if (scwTemp > -1 && scwTemp < (12*scwDropDownYears))
1392
            {scwSelYears.options.selectedIndex=Math.floor(scwMonthSum/12);
1393
             scwSelMonths.options.selectedIndex=(scwMonthSum%12);
1394

    
1395
             scwCurMonth = scwShowDate.getMonth();
1396

    
1397
             scwShowDate.setDate((((scwShowDate.
1398
                                    getDay()-scwWeekStart)<0)?-6:1)+
1399
                                 scwWeekStart-scwShowDate.getDay());
1400

    
1401
             // This statement moved by Michael Cerveny to make version 3.55
1402
             var scwCompareDateValue = new Date(scwShowDate.getFullYear(),
1403
                                                scwShowDate.getMonth(),
1404
                                                scwShowDate.getDate()).valueOf();
1405

    
1406
             scwStartDate = new Date(scwShowDate);
1407

    
1408
             if ((new Date(scwBaseYear + scwDropDownYears, 0, 0)) > scwDateNow &&
1409
                 (new Date(scwBaseYear, 0, 0))                    < scwDateNow)
1410
                {var scwNow = scwID('scwNow');
1411

    
1412
                 function scwNowOutput() {scwSetOutput(scwDateNow);};
1413

    
1414
                 if (scwDisabledDates.length==0)
1415
                    {if (scwActiveToday && scwParmActiveToday)
1416
                        {scwNow.onclick     = scwNowOutput;
1417
                         scwNow.className   = 'scwNow';
1418

    
1419
                         if (scwID('scwIE'))
1420
                            {scwNow.onmouseover  = scwChangeClass;
1421
                             scwNow.onmouseout   = scwChangeClass;
1422
                            }
1423

    
1424
                        }
1425
                     else
1426
                        {scwNow.onclick     = null;
1427
                         scwNow.className   = 'scwNowDisabled';
1428

    
1429
                         if (scwID('scwIE'))
1430
                            {scwNow.onmouseover  = null;
1431
                             scwNow.onmouseout   = null;
1432
                            }
1433

    
1434
                         if (document.addEventListener)
1435
                                {scwNow.addEventListener('click',scwStopPropagation,false);}
1436
                         else   {scwNow.attachEvent('onclick',scwStopPropagation);}
1437
                        }
1438
                    }
1439
                 else
1440
                    {for (var k=0;k<scwDisabledDates.length;k++)
1441
                        {if (!scwActiveToday || !scwParmActiveToday ||
1442
                             ((typeof scwDisabledDates[k] == 'object')                   &&
1443
                                 (((scwDisabledDates[k].constructor == Date)             &&
1444
                                   scwDateNow.valueOf() == scwDisabledDates[k].valueOf()
1445
                                  ) ||
1446
                                  ((scwDisabledDates[k].constructor == Array)               &&
1447
                                   scwDateNow.valueOf() >= scwDisabledDates[k][0].valueOf() &&
1448
                                   scwDateNow.valueOf() <= scwDisabledDates[k][1].valueOf()
1449
                                  )
1450
                                 )
1451
                             )
1452
                            )
1453
                            {scwNow.onclick     = null;
1454
                             scwNow.className   = 'scwNowDisabled';
1455

    
1456
                             if (scwID('scwIE'))
1457
                                {scwNow.onmouseover  = null;
1458
                                 scwNow.onmouseout   = null;
1459
                                }
1460

    
1461
                             if (document.addEventListener)
1462
                                    {scwNow.addEventListener('click',scwStopPropagation,false);}
1463
                             else   {scwNow.attachEvent('onclick',scwStopPropagation);}
1464
                             break;
1465
                            }
1466
                         else
1467
                            {scwNow.onclick=scwNowOutput;
1468
                             scwNow.className='scwNow';
1469

    
1470
                             if (scwID('scwIE'))
1471
                                {scwNow.onmouseover  = scwChangeClass;
1472
                                 scwNow.onmouseout   = scwChangeClass;
1473
                                }
1474
                            }
1475
                        }
1476
                    }
1477
                }
1478

    
1479
             function scwSetOutput(scwOutputDate)
1480
                {if (typeof scwTargetEle.value == 'undefined')
1481
                      {scwTriggerEle.scwTextNode.replaceData(0,scwTriggerEle.scwLength,scwOutputDate.scwFormat(scwDateOutputFormat));}
1482
                 else {scwTargetEle.value = scwOutputDate.scwFormat(scwDateOutputFormat);}
1483
                 scwHide();
1484
                };
1485

    
1486
             function scwCellOutput(scwEvt)
1487
                {var scwEle = scwEventTrigger(scwEvt),
1488
                     scwOutputDate = new Date(scwStartDate);
1489

    
1490
                 if (scwEle.nodeType==3) scwEle=scwEle.parentNode;
1491

    
1492
                 scwOutputDate.setDate(scwStartDate.getDate() + parseInt(scwEle.id.substr(8),10));
1493

    
1494
                 scwSetOutput(scwOutputDate);
1495
                };
1496

    
1497
             function scwChangeClass(scwEvt)
1498
                {var scwEle = scwEventTrigger(scwEvt);
1499

    
1500
                 if (scwEle.nodeType==3) {scwEle=scwEle.parentNode;}
1501

    
1502
                 switch (scwEle.className)
1503
                    {case 'scwCells':
1504
                        scwEle.className = 'scwCellsHover';
1505
                        break;
1506
                     case 'scwCellsHover':
1507
                        scwEle.className = 'scwCells';
1508
                        break;
1509
                     case 'scwCellsExMonth':
1510
                        scwEle.className = 'scwCellsExMonthHover';
1511
                        break;
1512
                     case 'scwCellsExMonthHover':
1513
                        scwEle.className = 'scwCellsExMonth';
1514
                        break;
1515
                     case 'scwCellsWeekend':
1516
                        scwEle.className = 'scwCellsWeekendHover';
1517
                        break;
1518
                     case 'scwCellsWeekendHover':
1519
                        scwEle.className = 'scwCellsWeekend';
1520
                        break;
1521
                     case 'scwNow':
1522
                        scwEle.className = 'scwNowHover';
1523
                        break;
1524
                     case 'scwNowHover':
1525
                        scwEle.className = 'scwNow';
1526
                        break;
1527
                     case 'scwInputDate':
1528
                        scwEle.className = 'scwInputDateHover';
1529
                        break;
1530
                     case 'scwInputDateHover':
1531
                        scwEle.className = 'scwInputDate';
1532
                    }
1533

    
1534
                 return true;
1535
                }
1536

    
1537
             function scwEventTrigger(scwEvt)
1538
                {if (!scwEvt) {scwEvt = event;}
1539
                 return scwEvt.target||scwEvt.srcElement;
1540
                };
1541

    
1542
             function scwWeekNumber(scwInDate)
1543
                {// The base day in the week of the input date
1544
                 var scwInDateWeekBase = new Date(scwInDate);
1545

    
1546
                 scwInDateWeekBase.setDate(scwInDateWeekBase.getDate()
1547
                                            - scwInDateWeekBase.getDay()
1548
                                            + scwWeekNumberBaseDay
1549
                                            + ((scwInDate.getDay()>
1550
                                                scwWeekNumberBaseDay)?7:0));
1551

    
1552
                 // The first Base Day in the year
1553
                 var scwFirstBaseDay = new Date(scwInDateWeekBase.getFullYear(),0,1);
1554

    
1555
                 scwFirstBaseDay.setDate(scwFirstBaseDay.getDate()
1556
                                            - scwFirstBaseDay.getDay()
1557
                                            + scwWeekNumberBaseDay
1558
                                        );
1559

    
1560
                 if (scwFirstBaseDay < new Date(scwInDateWeekBase.getFullYear(),0,1))
1561
                    {scwFirstBaseDay.setDate(scwFirstBaseDay.getDate()+7);}
1562

    
1563
                 // Start of Week 01
1564
                 var scwStartWeekOne = new Date(scwFirstBaseDay
1565
                                                - scwWeekNumberBaseDay
1566
                                                + scwInDate.getDay());
1567

    
1568
                 if (scwStartWeekOne > scwFirstBaseDay)
1569
                    {scwStartWeekOne.setDate(scwStartWeekOne.getDate()-7);}
1570

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

    
1579
                 var scwWeekNo = '0' + (Math.round((scwInDateWeekBase - scwFirstBaseDay)/604800000,0) + 1);
1580

    
1581
                 // Return the last two characters in the week number string
1582

    
1583
                 return scwWeekNo.substring(scwWeekNo.length-2, scwWeekNo.length);
1584
                };
1585

    
1586
             // Treewalk to display the dates.
1587
             // I tried to use getElementsByName but IE refused to cooperate
1588
             // so I resorted to this method which works for all tested
1589
             // browsers.
1590

    
1591
             var scwCells = scwID('scwCells');
1592

    
1593
             for (i=0;i<scwCells.childNodes.length;i++)
1594
                {var scwRows = scwCells.childNodes[i];
1595
                 if (scwRows.nodeType==1 && scwRows.tagName=='TR')
1596
                    {if (scwWeekNumberDisplay)
1597
                        {//Calculate the week number using scwShowDate
1598
                         scwTmpEl = scwRows.childNodes[0];
1599
                         scwTmpEl.innerHTML = scwWeekNumber(scwShowDate);
1600
                         scwTmpEl.style.borderColor =
1601
                             (scwTmpEl.currentStyle)
1602
                                ?scwTmpEl.currentStyle['backgroundColor']
1603
                                :(window.getComputedStyle)
1604
                                    ?document.defaultView.getComputedStyle(scwTmpEl,null).getPropertyValue('background-color')
1605
                                    :'';
1606
                         scwTmpEl.style.display='';
1607
                        }
1608
                     else
1609
                        {scwRows.childNodes[0].style.display='none';}
1610

    
1611
                     for (j=1;j<scwRows.childNodes.length;j++)
1612
                        {var scwCols = scwRows.childNodes[j];
1613
                         if (scwCols.nodeType==1 && scwCols.tagName=='TD')
1614
                            {scwRows.childNodes[j].innerHTML=
1615
                                scwShowDate.getDate();
1616
                             var scwCell=scwRows.childNodes[j],
1617
                                 scwDisabled =
1618
                                    ((scwOutOfRangeDisable &&
1619
                                        (scwShowDate <
1620
                                            (new Date(scwBaseYear,0,1,
1621
                                                      scwShowDate.getHours()))
1622
                                         ||
1623
                                         scwShowDate >
1624
                                            (new Date(scwBaseYear+
1625
                                                      scwDropDownYears,0,0,
1626
                                                      scwShowDate.getHours()))
1627
                                        )
1628
                                     ) ||
1629
                                     (scwOutOfMonthDisable &&
1630
                                        (scwShowDate <
1631
                                            (new Date(scwShowDate.getFullYear(),
1632
                                                      scwCurMonth,1,
1633
                                                      scwShowDate.getHours()))
1634
                                         ||
1635
                                         scwShowDate >
1636
                                            (new Date(scwShowDate.getFullYear(),
1637
                                                      scwCurMonth+1,0,
1638
                                                      scwShowDate.getHours()))
1639
                                        )
1640
                                     )
1641
                                    )?true:false;
1642

    
1643
                             scwCell.style.visibility =
1644
                                (scwOutOfMonthHide &&
1645
                                    (scwShowDate <
1646
                                        (new Date(scwShowDate.getFullYear(),
1647
                                                  scwCurMonth,1,
1648
                                                  scwShowDate.getHours()))
1649
                                     ||
1650
                                     scwShowDate >
1651
                                        (new Date(scwShowDate.getFullYear(),
1652
                                                  scwCurMonth+1,0,
1653
                                                  scwShowDate.getHours()))
1654
                                    )
1655
                                )?'hidden':'inherit';
1656

    
1657
                             for (var k=0;k<scwDisabledDates.length;k++)
1658
                                {if ((typeof scwDisabledDates[k]=='object') &&
1659
                                     (scwDisabledDates[k].constructor == Date) &&
1660
                                     scwCompareDateValue == scwDisabledDates[k].valueOf()
1661
                                    )
1662
                                    {scwDisabled = true;}
1663
                                 else
1664
                                    {if ((typeof scwDisabledDates[k]=='object') &&
1665
                                         (scwDisabledDates[k].constructor == Array) &&
1666
                                         scwCompareDateValue >= scwDisabledDates[k][0].valueOf() &&
1667
                                         scwCompareDateValue <= scwDisabledDates[k][1].valueOf()
1668
                                        )
1669
                                        {scwDisabled = true;}
1670
                                    }
1671
                                }
1672

    
1673
                             if (scwDisabled ||
1674
                                 !scwEnabledDay[j-1+(7*((i*scwCells.childNodes.length)/6))] ||
1675
                                 !scwPassEnabledDay[(j-1+(7*(i*scwCells.childNodes.length/6)))%7]
1676
                                )
1677
                                {scwRows.childNodes[j].onclick = null;
1678

    
1679
                                 if (scwID('scwIE'))
1680
                                    {scwRows.childNodes[j].onmouseover  = null;
1681
                                     scwRows.childNodes[j].onmouseout   = null;
1682
                                    }
1683

    
1684
                                 scwCell.className=
1685
                                    (scwShowDate.getMonth()!=scwCurMonth)
1686
                                        ?'scwCellsExMonthDisabled'
1687
                                        :(scwBlnFullInputDate &&
1688
                                          scwShowDate.toDateString()==
1689
                                          scwSeedDate.toDateString())
1690
                                            ?'scwInputDateDisabled'
1691
                                            :(scwShowDate.getDay()%6==0)
1692
                                                ?'scwCellsWeekendDisabled'
1693
                                                :'scwCellsDisabled';
1694

    
1695
                                 scwCell.style.borderColor =
1696
                                     (scwFormatTodayCell && scwShowDate.toDateString()==scwDateNow.toDateString())
1697
                                        ?scwTodayCellBorderColour
1698
                                        :(scwCell.currentStyle)
1699
                                            ?scwCell.currentStyle['backgroundColor']
1700
                                            :(window.getComputedStyle)
1701
                                                ?document.defaultView.getComputedStyle(scwCell,null).getPropertyValue('background-color')
1702
                                                :'';
1703
                                }
1704
                             else
1705
                                {scwRows.childNodes[j].onclick=scwCellOutput;
1706

    
1707
                                 if (scwID('scwIE'))
1708
                                    {scwRows.childNodes[j].onmouseover  = scwChangeClass;
1709
                                     scwRows.childNodes[j].onmouseout   = scwChangeClass;
1710
                                    }
1711

    
1712
                                 scwCell.className=
1713
                                     (scwShowDate.getMonth()!=scwCurMonth)
1714
                                        ?'scwCellsExMonth'
1715
                                        :(scwBlnFullInputDate &&
1716
                                          scwShowDate.toDateString()==
1717
                                          scwSeedDate.toDateString())
1718
                                            ?'scwInputDate'
1719
                                            :(scwShowDate.getDay()%6==0)
1720
                                                ?'scwCellsWeekend'
1721
                                                :'scwCells';
1722

    
1723
                                 scwCell.style.borderColor =
1724
                                     (scwFormatTodayCell && scwShowDate.toDateString() == scwDateNow.toDateString())
1725
                                        ?scwTodayCellBorderColour
1726
                                        :(scwCell.currentStyle)
1727
                                            ?scwCell.currentStyle['backgroundColor']
1728
                                            :(window.getComputedStyle)
1729
                                                ?document.defaultView.getComputedStyle(scwCell,null).getPropertyValue('background-color')
1730
                                                :'';
1731
                               }
1732

    
1733
                             scwShowDate.setDate(scwShowDate.getDate()+1);
1734
                             scwCompareDateValue = new Date(scwShowDate.getFullYear(),scwShowDate.getMonth(),scwShowDate.getDate()).valueOf();
1735
                            }
1736
                        }
1737
                    }
1738
                }
1739
            }
1740

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

    
1747
         if (window.opera)
1748
            {scwID('scwMonths').style.display = 'inline';
1749
             scwID('scwYears' ).style.display = 'inline';
1750
             scwID('scw').style.visibility='hidden';
1751
             scwID('scw').style.visibility='inherit';
1752
           }
1753
        };
1754

    
1755
// *************************
1756
//  End of Function Library
1757
// *************************
1758
// ***************************
1759
// Start of Calendar structure
1760
// ***************************
1761

    
1762
    document.writeln("<!--[if IE]><div id='scwIE'></div><![endif]-->");
1763
    document.writeln("<!--[if lt IE 7]><div id='scwIElt7'></div><![endif]-->");
1764
    document.write(
1765
     "<iframe class='scw' " + (scwID('scwIElt7')?"src='/scwblank.html '":'') +
1766
             "id='scwIframe' name='scwIframe' frameborder='0'>" +
1767
     "</iframe>" +
1768
     "<table id='scw' class='scw'>" +
1769
       "<tr class='scw'>" +
1770
         "<td class='scw'>" +
1771
           "<table class='scwHead' id='scwHead' width='100%' " +
1772
                    "cellspacing='0' cellpadding='0'>" +
1773
            "<tr id='scwDrag' style='display:none;'>" +
1774
                "<td colspan='4' class='scwDrag' " +
1775
                    "onmousedown='scwBeginDrag(event);'>" +
1776
                    "<span id='scwDragText'></span>" +
1777
                "</td>" +
1778
            "</tr>" +
1779
            "<tr class='scwHead' >" +
1780
                 "<td class='scwHead'>" +
1781
                    "<input class='scwHead' id='scwHeadLeft' type='button' value='<' " +
1782
                            "onclick='scwShowMonth(-1);'  /></td>" +
1783
                 "<td class='scwHead'>" +
1784
                    "<select id='scwMonths' class='scwHead' " +
1785
                            "onchange='scwShowMonth(0);'>" +
1786
                    "</select>" +
1787
                 "</td>" +
1788
                 "<td class='scwHead'>" +
1789
                    "<select id='scwYears' class='scwHead' " +
1790
                            "onchange='scwShowMonth(0);'>" +
1791
                    "</select>" +
1792
                 "</td>" +
1793
                 "<td class='scwHead'>" +
1794
                    "<input class='scwHead' id='scwHeadRight' type='button' value='>' " +
1795
                            "onclick='scwShowMonth(1);' /></td>" +
1796
                "</tr>" +
1797
              "</table>" +
1798
            "</td>" +
1799
          "</tr>" +
1800
          "<tr class='scw'>" +
1801
            "<td class='scw'>" +
1802
              "<table class='scwCells' align='center'>" +
1803
                "<thead>" +
1804
                  "<tr><td class='scwWeekNumberHead' id='scwWeek_' ></td>");
1805

    
1806
    for (i=0;i<7;i++)
1807
        {document.write(
1808
                      "<td class='scwWeek' id='scwWeekInit" + i + "'></td>");
1809
        }
1810

    
1811
    document.write("</tr>" +
1812
                "</thead>" +
1813
                "<tbody id='scwCells' onClick='scwStopPropagation(event);'>");
1814

    
1815
    for (i=0;i<6;i++)
1816
        {document.write(
1817
                    "<tr>" +
1818
                      "<td class='scwWeekNo' id='scwWeek_" + i + "'></td>");
1819
         for (j=0;j<7;j++)
1820
            {document.write(
1821
                        "<td class='scwCells' id='scwCell_" + (j+(i*7)) +
1822
                        "'></td>");
1823
            }
1824

    
1825
         document.write(
1826
                    "</tr>");
1827
        }
1828

    
1829
    document.write(
1830
                "</tbody>" +
1831
                "<tfoot>" +
1832
                  "<tr id='scwFoot'>" +
1833
                    "<td colspan='8' style='padding:0px;'>" +
1834
                      "<table width='100%'>" +
1835
                        "<tr>" +
1836
                          "<td id='scwClear' class='scwClear'>" +
1837
                            "<input type='button' id='scwClearButton' class='scwClear' " +
1838
                                   "onclick='scwTargetEle.value = \"\";scwHide();' />" +
1839
                          "</td>" +
1840
                          "<td class='scwNow' id='scwNow'></td>" +
1841
                        "</tr>" +
1842
                      "</table>" +
1843
                    "</td>" +
1844
                  "</tr>" +
1845
                "</tfoot>" +
1846
              "</table>" +
1847
            "</td>" +
1848
          "</tr>" +
1849
        "</table>");
1850

    
1851
    if (document.addEventListener)
1852
            {scwID('scw'         ).addEventListener('click',scwCancel,false);
1853
             scwID('scwHeadLeft' ).addEventListener('click',scwStopPropagation,false);
1854
             scwID('scwMonths'   ).addEventListener('click',scwStopPropagation,false);
1855
             scwID('scwMonths'   ).addEventListener('change',scwStopPropagation,false);
1856
             scwID('scwYears'    ).addEventListener('click',scwStopPropagation,false);
1857
             scwID('scwYears'    ).addEventListener('change',scwStopPropagation,false);
1858
             scwID('scwHeadRight').addEventListener('click',scwStopPropagation,false);
1859
            }
1860
    else    {scwID('scw'         ).attachEvent('onclick',scwCancel);
1861
             scwID('scwHeadLeft' ).attachEvent('onclick',scwStopPropagation);
1862
             scwID('scwMonths'   ).attachEvent('onclick',scwStopPropagation);
1863
             scwID('scwMonths'   ).attachEvent('onchange',scwStopPropagation);
1864
             scwID('scwYears'    ).attachEvent('onclick',scwStopPropagation);
1865
             scwID('scwYears'    ).attachEvent('onchange',scwStopPropagation);
1866
             scwID('scwHeadRight').attachEvent('onclick',scwStopPropagation);
1867
            }
1868

    
1869
// ***************************
1870
//  End of Calendar structure
1871
// ***************************
1872
// ****************************************
1873
// Start of document level event definition
1874
// ****************************************
1875

    
1876
    if (document.addEventListener)
1877
            {document.addEventListener('click',scwHide, false);}
1878
    else    {document.attachEvent('onclick',scwHide);}
1879

    
1880
// ****************************************
1881
//  End of document level event definition
1882
// ****************************************
1883
// ************************************
1884
//  End of Simple Calendar Widget Code
1885
// ************************************
(3-3/4)