source: ether_2012/web/cathy/js/anytime.js @ 319

Last change on this file since 319 was 319, checked in by vmipsl, 12 years ago

Import du projet Ether pour le nouveau look 2012

File size: 176.6 KB
Line 
1/*****************************************************************************
2 *  FILE:  anytime.js - The Any+Time(TM) JavaScript Library (source)
3 *
4 *  VERSION: 4.1112H
5 *
6 *  Copyright 2008-2010 Andrew M. Andrews III (www.AMA3.com). Some Rights
7 *  Reserved. This work licensed under the Creative Commons Attribution-
8 *  Noncommercial-Share Alike 3.0 Unported License except in jurisdicitons
9 *  for which the license has been ported by Creative Commons International,
10 *  where the work is licensed under the applicable ported license instead.
11 *  For a copy of the unported license, visit
12 *  http://creativecommons.org/licenses/by-nc-sa/3.0/
13 *  or send a letter to Creative Commons, 171 Second Street, Suite 300,
14 *  San Francisco, California, 94105, USA.  For ported versions of the
15 *  license, visit http://creativecommons.org/international/
16 *
17 *  Alternative licensing arrangements may be made by contacting the
18 *  author at http://www.AMA3.com/contact/
19 *
20 *  The Any+Time(TM) JavaScript Library provides the following ECMAScript
21 *  functionality:
22 *
23 *    AnyTime.Converter
24 *      Converts Dates to/from Strings, allowing a wide range of formats
25 *      closely matching those provided by the MySQL DATE_FORMAT() function,
26 *      with some noteworthy enhancements.
27 *
28 *    AnyTime.pad()
29 *      Pads a value with a specific number of leading zeroes.
30 *
31 *    AnyTime.noPicker()
32 *      Destroys a calendar widget previously added by AnyTime.picker().
33 *      Can also be invoked via jQuery using $(selector).AnyTime_noPicker()
34 *
35 *    AnyTime.picker()
36 *      Attaches a calendar widget to a text field for selecting date/time
37 *      values with fewer mouse movements than most similar pickers.  Any
38 *      format supported by AnyTime.Converter can be used for the text field.
39 *      If JavaScript is disabled, the text field remains editable without
40 *      any of the picker features.
41 *      Can also be invoked via jQuery using $(selector).AnyTime_picker()
42 *
43 *  IMPORTANT NOTICE:  This code depends upon the jQuery JavaScript Library
44 *  (www.jquery.com), currently version 1.4.
45 *
46 *  The Any+Time(TM) code and styles in anytime.css have been tested (but not
47 *  extensively) on Windows Vista in Internet Explorer 8.0, Firefox 3.0, Opera
48 *  10.10 and Safari 4.0.  Minor variations in IE6+7 are to be expected, due
49 *  to their broken box model. Please report any other problems to the author
50 *  (URL above).
51 *
52 *  Any+Time is a trademark of Andrew M. Andrews III.
53 *  Thanks to Chu for help with a setMonth() issue!
54 ****************************************************************************/
55
56// http://www.ama3.com/anytime
57
58var AnyTime =
59{
60    //=============================================================================
61    //  AnyTime.pad() pads a value with a specified number of zeroes and returns
62    //  a string containing the padded value.
63    //=============================================================================
64
65    pad: function( val, len )
66    {
67        var str = String( Math.abs( val ) );
68        while( str.length < len )
69            str = '0' + str;
70        if( val < 0 )
71            str = '-' + str;
72        return str;
73    }
74};
75
76(function( $ )
77{
78    // private members
79
80    var __oneDay = (24 * 60 * 60 * 1000);
81    var __daysIn = [ 31,28,31,30,31,30,31,31,30,31,30,31 ];
82    var __iframe = null;
83    var __initialized = false;
84    var __msie6 = ( navigator.userAgent.indexOf( 'MSIE 6' ) > 0 );
85    var __msie7 = ( navigator.userAgent.indexOf( 'MSIE 7' ) > 0 );
86    var __pickers = [];
87
88    //  Add methods to jQuery to create and destroy pickers using
89    //  the typical jQuery approach.
90
91    jQuery.prototype.AnyTime_picker = function( options )
92    {
93        return this.each( function( i )
94        {
95            AnyTime.picker( this.id, options );
96        } );
97    }
98
99    jQuery.prototype.AnyTime_noPicker = function()
100    {
101        return this.each( function( i )
102        {
103            AnyTime.noPicker( this.id );
104        } );
105    }
106
107    //  Add special methods to jQuery to compute the height and width
108    //  of picker components differently for Internet Explorer 6.x
109    //  This prevents the pickers from being too tall and wide.
110
111    jQuery.prototype.AnyTime_height = function( inclusive )
112    {
113        return ( __msie6 ?
114                Number( this.css( 'height' ).replace( /[^0-9]/g, '' ) ) :
115                this.outerHeight( inclusive ) );
116    };
117
118    jQuery.prototype.AnyTime_width = function( inclusive )
119    {
120        return ( __msie6 ?
121                (1 + Number( this.css( 'width' ).replace( /[^0-9]/g, '' ) )) :
122                this.outerWidth( inclusive ) );
123    };
124
125
126    //  Add a method to jQuery to change the classes of an element to
127    //  indicate whether it's value is current (used by AnyTime.picker),
128    //  and another to trigger the click handler for the currently-
129    //  selected button under an element.
130
131    jQuery.prototype.AnyTime_current = function( isCurrent, isLegal )
132    {
133        if( isCurrent )
134        {
135            this.removeClass( 'AnyTime-out-btn ui-state-default ui-state-disabled ui-state-highlight' );
136            this.addClass( 'AnyTime-cur-btn ui-state-default ui-state-highlight' );
137        }
138        else
139        {
140            this.removeClass( 'AnyTime-cur-btn ui-state-highlight' );
141            if( ! isLegal )
142                this.addClass( 'AnyTime-out-btn ui-state-disabled' );
143            else
144                this.removeClass( 'AnyTime-out-btn ui-state-disabled' );
145        }
146    };
147
148    jQuery.prototype.AnyTime_clickCurrent = function()
149    {
150        this.find( '.AnyTime-cur-btn' ).triggerHandler( 'click' );
151    }
152
153    $( document ).ready(
154            function()
155            {
156                //  IE6 doesn't float popups over <select> elements unless an
157                //      <iframe> is inserted between them!  The <iframe> is added to
158                //      the page *before* the popups are moved, so they will appear
159                //  after the <iframe>.
160
161                if( __msie6 )
162                {
163                    __iframe = $( '<iframe frameborder="0" scrolling="no"></iframe>' );
164                    __iframe.src = "javascript:'<html></html>';";
165                    $( __iframe ).css( {
166                        display: 'block',
167                        height: '1px',
168                        left: '0',
169                        top: '0',
170                        width: '1px',
171                        zIndex: 0
172                    } );
173                    $( document.body ).append( __iframe );
174                }
175
176                //  Move popup windows to the end of the page.  This allows them to
177                //  overcome XHTML restrictions on <table> placement enforced by MSIE.
178
179                for( var id in __pickers )
180                    if( ! Array.prototype[id] ) // prototype.js compatibility issue
181                        __pickers[id].onReady();
182
183                __initialized = true;
184
185            } ); // document.ready
186
187//=============================================================================
188//  AnyTime.Converter
189//
190//  This object converts between Date objects and Strings.
191//
192//  To use AnyTime.Converter, simply create an instance for a format string,
193//  and then (repeatedly) invoke the format() and/or parse() methods to
194//  perform the conversions.  For example:
195//
196//    var converter = new AnyTime.Converter({format:'%Y-%m-%d'})
197//    var datetime = converter.parse('1967-07-30') // July 30, 1967 @ 00:00
198//    alert( converter.format(datetime) ); // outputs: 1967-07-30
199//
200//  Constructor parameter:
201//
202//  options - an object of optional parameters that override default behaviors.
203//    The supported options are:
204//
205//    baseYear - the number to add to two-digit years if the %y format
206//      specifier is used.  By default, AnyTime.Converter follows the
207//      MySQL assumption that two-digit years are in the range 1970 to 2069
208//      (see http://dev.mysql.com/doc/refman/5.1/en/y2k-issues.html).
209//      The most common alternatives for baseYear are 1900 and 2000.
210//
211//    dayAbbreviations - an array of seven strings, indexed 0-6, to be used
212//      as ABBREVIATED day names.  If not specified, the following are used:
213//      ['Sun','Mon','Tue','Wed','Thu','Fri','Sat']
214//      Note that if the firstDOW option is passed to AnyTime.picker() (see
215//      AnyTime.picker()), this array should nonetheless begin with the
216//      desired abbreviation for Sunday.
217//
218//    dayNames - an array of seven strings, indexed 0-6, to be used as
219//      day names.  If not specified, the following are used: ['Sunday',
220//        'Monday','Tuesday','Wednesday','Thursday','Friday','Saturday']
221//      Note that if the firstDOW option is passed to AnyTime.picker() (see
222//      AnyTime.picker()), this array should nonetheless begin with the
223//      desired name for Sunday.
224//
225//    eraAbbreviations - an array of two strings, indexed 0-1, to be used
226//      as ABBREVIATED era names.  Item #0 is the abbreviation for "Before
227//      Common Era" (years before 0001, sometimes represented as negative
228//      years or "B.C"), while item #1 is the abbreviation for "Common Era"
229//      (years from 0001 to present, usually represented as unsigned years
230//      or years "A.D.").  If not specified, the following are used:
231//      ['BCE','CE']
232//
233//    format - a string specifying the pattern of strings involved in the
234//      conversion.  The parse() method can take a string in this format and
235//      convert it to a Date, and the format() method can take a Date object
236//      and convert it to a string matching the format.
237//
238//      Fields in the format string must match those for the DATE_FORMAT()
239//      function in MySQL, as defined here:
240//      http://tinyurl.com/bwd45#function_date-format
241//
242//      IMPORTANT:  Some MySQL specifiers are not supported (especially
243//      those involving day-of-the-year, week-of-the-year) or approximated.
244//      See the code for exact behavior.
245//
246//      In addition to the MySQL format specifiers, the following custom
247//      specifiers are also supported:
248//
249//        %B - If the year is before 0001, then the "Before Common Era"
250//          abbreviation (usually BCE or the obsolete BC) will go here.
251//
252//        %C - If the year is 0001 or later, then the "Common Era"
253//          abbreviation (usually CE or the obsolete AD) will go here.
254//
255//        %E - If the year is before 0001, then the "Before Common Era"
256//          abbreviation (usually BCE or the obsolete BC) will go here.
257//          Otherwise, the "Common Era" abbreviation (usually CE or the
258//          obsolete AD) will go here.
259//
260//        %Z - The current four-digit year, without any sign.  This is
261//          commonly used with years that might be before (or after) 0001,
262//          when the %E (or %B and %C) specifier is used instead of a sign.
263//          For example, 45 BCE is represented "0045".  By comparison, in
264//          the "%Y" format, 45 BCE is represented "-0045".
265//
266//        %z - The current year, without any sign, using only the necessary
267//          number of digits.  This if the year is commonly used with years
268//          that might be before (or after) 0001, when the %E (or %B and %C)
269//          specifier is used instead of a sign.  For example, the year
270//          45 BCE is represented as "45", and the year 312 CE as "312".
271//
272//        %# - the timezone offset, with a sign, in minutes.
273//
274//        %+ - the timezone offset, with a sign, in hours and minutes, in
275//          four-digit, 24-hour format with no delimiter (for example, +0530).
276//          To remember the difference between %+ and %-, it might be helpful
277//          to remember that %+ might have more characters than %-.
278//
279//        %: - the timezone offset, with a sign, in hours and minutes, in
280//          four-digit, 24-hour format with a colon delimiter (for example,
281//          +05:30).  This is similar to the %z format used by Java. 
282//          To remember the difference between %: and %;, it might be helpful
283//          to remember that a colon (:) has a period (.) on the bottom and
284//          a semicolon (;) has a comma (,), and in English sentence structure,
285//          a period represents a more significant stop than a comma, and
286//          %: might be a longer string than %; (I know it's a stretch, but
287//          it's easier than looking it up every time)!
288//     
289//        %- - the timezone offset, with a sign, in hours and minutes, in
290//          three-or-four-digit, 24-hour format with no delimiter (for
291//          example, +530).
292//
293//        %; - the timezone offset, with a sign, in hours and minutes, in
294//          three-or-four-digit, 24-hour format with a colon delimiter
295//          (for example, +5:30).
296//
297//        %@ - the timezone offset label.  By default, this will be the
298//          string "UTC" followed by the offset, with a sign, in hours and 
299//          minutes, in four-digit, 24-hour format with a colon delimiter
300//          (for example, UTC+05:30).  However, if Any+Time(TM) has been
301//          extended with a member named utcLabel (for example, by the
302//          anytimetz.js file), then it is assumed to be an array of arrays,
303//          where the primary array is indexed by time zone offsets, and
304//          each sub-array contains a potential label for that offset.
305//          When parsing with %@, the array is scanned for matches to the
306//          input string, and if a match is found, the corresponding UTC
307//          offset is used.  When formatting, the array is scanned for a
308//          matching offset, and if one is found, the first member of the
309//          sub-array is used for output (unless overridden with
310//          utcFormatOffsetSubIndex or setUtcFormatOffsetSubIndex()).
311//          If the array does not exist, or does not contain a sub-array
312//          for the offset, then the default format is used.
313//
314//    monthAbbreviations - an array of twelve strings, indexed 0-6, to be
315//      used as ABBREVIATED month names.  If not specified, the following
316//      are used: ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep',
317//        'Oct','Nov','Dec']
318//
319//    monthNames - an array of twelve strings, indexed 0-6, to be used as
320//      month names.  If not specified, the following are used:
321//      ['January','February','March','April','May','June','July',
322//        'August','September','October','November','December']
323//
324//    utcFormatOffsetAlleged - the offset from UTC, in minutes, to claim that
325//      a Date object represents during formatting, even though it is formatted
326//      using local time. Unlike utcFormatOffsetImposed, which actually
327//      converts the Date object to the specified different time zone, this
328//      option merely reports the alleged offset when a timezone specifier
329//      (%#, %+, %-, %:, %; %@) is encountered in the format string.
330//      This primarily exists so AnyTime.picker can edit the time as specified
331//      (without conversion to local time) and then convert the edited time to
332//      a different time zone (as selected using the picker).  Any initial
333//      value specified here can be changed by setUtcFormatOffsetAlleged().
334//      If a format offset is alleged, one cannot also be imposed (the imposed
335//      offset is ignored).
336//
337//    utcFormatOffsetImposed - the offset from UTC, in minutes, to specify when
338//      formatting a Date object.  By default, a Date is always formatted
339//      using the local time zone.
340//
341//    utcFormatOffsetSubIndex - when extending AnyTime with a utcLabel array
342//      (for example, by the anytimetz.js file), the specified sub-index is
343//      used to choose the Time Zone label for the UTC offset when formatting
344//      a Date object.  This primarily exists so AnyTime.picker can specify
345//      the label selected using the picker.  Any initial value specified here
346//      can be changed by setUtcFormatOffsetSubIndex().
347//
348//    utcParseOffsetAssumed - the offset from UTC, in minutes, to assume when
349//      parsing a String object.  By default, a Date is always parsed using the
350//      local time zone, unless the format string includes a timezone
351//      specifier (%#, %+, %-, %:, %; or %@), in which case the timezone
352//      specified in the string is used. The Date object created by parsing
353//      always represents local time regardless of the input time zone.
354//
355//    utcParseOffsetCapture - if true, any parsed string is always treated as
356//      though it represents local time, and any offset specified by the string
357//      (or utcParseOffsetAssume) is captured for return by the
358//      getUtcParseOffsetCaptured() method.  If the %@ format specifier is
359//      used, the sub-index of any matched label is also captured for return
360//      by the getUtcParseOffsetSubIndex() method.  This primarily exists so
361//      AnyTime.picker can edit the time as specified (without conversion to
362//      local time) and then convert the edited time to a different time zone
363//      (as selected using the picker).
364//=============================================================================
365
366    AnyTime.Converter = function( options )
367    {
368        // private members
369
370        var _flen = 0;
371        var _longDay = 9;
372        var _longMon = 9;
373        var _shortDay = 6;
374        var _shortMon = 3;
375        var _offAl = Number.MIN_VALUE; // format time zone offset alleged
376        var _offCap = Number.MIN_VALUE; // parsed time zone offset captured
377        var _offF = Number.MIN_VALUE; // format time zone offset imposed
378        var _offFSI = (-1); // format time zone label subindex
379        var _offP = Number.MIN_VALUE; // parsed time zone offset assumed
380        var _offPSI = (-1);        // parsed time zone label subindex captured
381        var _captureOffset = false;
382
383        // public members
384
385        this.fmt = '%Y-%m-%d %T';
386        this.dAbbr = ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'];
387        this.dNames = ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'];
388        this.eAbbr = ['BCE','CE'];
389        this.mAbbr = [ 'Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec' ];
390        this.mNames = [ 'January','February','March','April','May','June','July','August','September','October','November','December' ];
391        this.baseYear = null;
392
393        //-------------------------------------------------------------------------
394        //  AnyTime.Converter.dAt() returns true if the character in str at pos
395        //  is a digit.
396        //-------------------------------------------------------------------------
397
398        this.dAt = function( str, pos )
399        {
400            return ( (str.charCodeAt( pos ) >= '0'.charCodeAt( 0 )) &&
401                    (str.charCodeAt( pos ) <= '9'.charCodeAt( 0 )) );
402        };
403
404        //-------------------------------------------------------------------------
405        //  AnyTime.Converter.format() returns a String containing the value
406        //  of a specified Date object, using the format string passed to
407        //  AnyTime.Converter().
408        //
409        //  Method parameter:
410        //
411        //    date - the Date object to be converted
412        //-------------------------------------------------------------------------
413
414        this.format = function( date )
415        {
416            var d = new Date( date.getTime() );
417            if( ( _offAl == Number.MIN_VALUE ) && ( _offF != Number.MIN_VALUE ) )
418                d.setTime( ( d.getTime() + (d.getTimezoneOffset() * 60000) ) + (_offF * 60000) );
419
420            var t;
421            var str = '';
422            for( var f = 0; f < _flen; f++ )
423            {
424                if( this.fmt.charAt( f ) != '%' )
425                    str += this.fmt.charAt( f );
426                else
427                {
428                    var ch = this.fmt.charAt( f + 1 )
429                    switch( ch )
430                    {
431                        case 'a': // Abbreviated weekday name (Sun..Sat)
432                            str += this.dAbbr[ d.getDay() ];
433                            break;
434                        case 'B': // BCE string (eAbbr[0], usually BCE or BC, only if appropriate) (NON-MYSQL)
435                            if( d.getFullYear() < 0 )
436                                str += this.eAbbr[0];
437                            break;
438                        case 'b': // Abbreviated month name (Jan..Dec)
439                            str += this.mAbbr[ d.getMonth() ];
440                            break;
441                        case 'C': // CE string (eAbbr[1], usually CE or AD, only if appropriate) (NON-MYSQL)
442                            if( d.getFullYear() > 0 )
443                                str += this.eAbbr[1];
444                            break;
445                        case 'c': // Month, numeric (0..12)
446                            str += d.getMonth() + 1;
447                            break;
448                        case 'd': // Day of the month, numeric (00..31)
449                            t = d.getDate();
450                            if( t < 10 ) str += '0';
451                            str += String( t );
452                            break;
453                        case 'D': // Day of the month with English suffix (0th, 1st,...)
454                            t = String( d.getDate() );
455                            str += t;
456                            if( ( t.length == 2 ) && ( t.charAt( 0 ) == '1' ) )
457                                str += 'th';
458                            else
459                            {
460                                switch( t.charAt( t.length - 1 ) )
461                                {
462                                    case '1':
463                                        str += 'st';
464                                        break;
465                                    case '2':
466                                        str += 'nd';
467                                        break;
468                                    case '3':
469                                        str += 'rd';
470                                        break;
471                                    default:
472                                        str += 'th';
473                                        break;
474                                }
475                            }
476                            break;
477                        case 'E': // era string (from eAbbr[], BCE, CE, BC or AD) (NON-MYSQL)
478                            str += this.eAbbr[ (d.getFullYear() < 0) ? 0 : 1 ];
479                            break;
480                        case 'e': // Day of the month, numeric (0..31)
481                            str += d.getDate();
482                            break;
483                        case 'H': // Hour (00..23)
484                            t = d.getHours();
485                            if( t < 10 ) str += '0';
486                            str += String( t );
487                            break;
488                        case 'h': // Hour (01..12)
489                        case 'I': // Hour (01..12)
490                            t = d.getHours() % 12;
491                            if( t == 0 )
492                                str += '12';
493                            else
494                            {
495                                if( t < 10 ) str += '0';
496                                str += String( t );
497                            }
498                            break;
499                        case 'i': // Minutes, numeric (00..59)
500                            t = d.getMinutes();
501                            if( t < 10 ) str += '0';
502                            str += String( t );
503                            break;
504                        case 'k': // Hour (0..23)
505                            str += d.getHours();
506                            break;
507                        case 'l': // Hour (1..12)
508                            t = d.getHours() % 12;
509                            if( t == 0 )
510                                str += '12';
511                            else
512                                str += String( t );
513                            break;
514                        case 'M': // Month name (January..December)
515                            str += this.mNames[ d.getMonth() ];
516                            break;
517                        case 'm': // Month, numeric (00..12)
518                            t = d.getMonth() + 1;
519                            if( t < 10 ) str += '0';
520                            str += String( t );
521                            break;
522                        case 'p': // AM or PM
523                            str += ( ( d.getHours() < 12 ) ? 'AM' : 'PM' );
524                            break;
525                        case 'r': // Time, 12-hour (hh:mm:ss followed by AM or PM)
526                            t = d.getHours() % 12;
527                            if( t == 0 )
528                                str += '12:';
529                            else
530                            {
531                                if( t < 10 ) str += '0';
532                                str += String( t ) + ':';
533                            }
534                            t = d.getMinutes();
535                            if( t < 10 ) str += '0';
536                            str += String( t ) + ':';
537                            t = d.getSeconds();
538                            if( t < 10 ) str += '0';
539                            str += String( t );
540                            str += ( ( d.getHours() < 12 ) ? 'AM' : 'PM' );
541                            break;
542                        case 'S': // Seconds (00..59)
543                        case 's': // Seconds (00..59)
544                            t = d.getSeconds();
545                            if( t < 10 ) str += '0';
546                            str += String( t );
547                            break;
548                        case 'T': // Time, 24-hour (hh:mm:ss)
549                            t = d.getHours();
550                            if( t < 10 ) str += '0';
551                            str += String( t ) + ':';
552                            t = d.getMinutes();
553                            if( t < 10 ) str += '0';
554                            str += String( t ) + ':';
555                            t = d.getSeconds();
556                            if( t < 10 ) str += '0';
557                            str += String( t );
558                            break;
559                        case 'W': // Weekday name (Sunday..Saturday)
560                            str += this.dNames[ d.getDay() ];
561                            break;
562                        case 'w': // Day of the week (0=Sunday..6=Saturday)
563                            str += d.getDay();
564                            break;
565                        case 'Y': // Year, numeric, four digits (negative if before 0001)
566                            str += AnyTime.pad( d.getFullYear(), 4 );
567                            break;
568                        case 'y': // Year, numeric (two digits, negative if before 0001)
569                            t = d.getFullYear() % 100;
570                            str += AnyTime.pad( t, 2 );
571                            break;
572                        case 'Z': // Year, numeric, four digits, unsigned (NON-MYSQL)
573                            str += AnyTime.pad( Math.abs( d.getFullYear() ), 4 );
574                            break;
575                        case 'z': // Year, numeric, variable length, unsigned (NON-MYSQL)
576                            str += Math.abs( d.getFullYear() );
577                            break;
578                        case '%': // A literal '%' character
579                            str += '%';
580                            break;
581                        case '#': // signed timezone offset in minutes
582                            t = ( _offAl != Number.MIN_VALUE ) ? _offAl :
583                                    ( _offF == Number.MIN_VALUE ) ? (0 - d.getTimezoneOffset()) : _offF;
584                            if( t >= 0 )
585                                str += '+';
586                            str += t;
587                            break;
588                        case '@': // timezone offset label
589                            t = ( _offAl != Number.MIN_VALUE ) ? _offAl :
590                                    ( _offF == Number.MIN_VALUE ) ? (0 - d.getTimezoneOffset()) : _offF;
591                            if( AnyTime.utcLabel && AnyTime.utcLabel[t] )
592                            {
593                                if( ( _offFSI > 0 ) && ( _offFSI < AnyTime.utcLabel[t].length ) )
594                                    str += AnyTime.utcLabel[t][_offFSI];
595                                else
596                                    str += AnyTime.utcLabel[t][0];
597                                break;
598                            }
599                            str += 'UTC';
600                            ch = ':'; // drop through for offset formatting
601                        case '+': // signed, 4-digit timezone offset in hours and minutes
602                        case '-': // signed, 3-or-4-digit timezone offset in hours and minutes
603                        case ':': // signed 4-digit timezone offset with colon delimiter
604                        case ';': // signed 3-or-4-digit timezone offset with colon delimiter
605                            t = ( _offAl != Number.MIN_VALUE ) ? _offAl :
606                                    ( _offF == Number.MIN_VALUE ) ? (0 - d.getTimezoneOffset()) : _offF;
607                            if( t < 0 )
608                                str += '-';
609                            else
610                                str += '+';
611                            t = Math.abs( t );
612                            str += ((ch == '+') || (ch == ':')) ? AnyTime.pad( Math.floor( t / 60 ), 2 ) : Math.floor( t / 60 );
613                            if( (ch == ':') || (ch == ';') )
614                                str += ':';
615                            str += AnyTime.pad( t % 60, 2 );
616                            break;
617                        case 'f': // Microseconds (000000..999999)
618                        case 'j': // Day of year (001..366)
619                        case 'U': // Week (00..53), where Sunday is the first day of the week
620                        case 'u': // Week (00..53), where Monday is the first day of the week
621                        case 'V': // Week (01..53), where Sunday is the first day of the week; used with %X
622                        case 'v': // Week (01..53), where Monday is the first day of the week; used with %x
623                        case 'X': // Year for the week where Sunday is the first day of the week, numeric, four digits; used with %V
624                        case 'x': // Year for the week, where Monday is the first day of the week, numeric, four digits; used with %v
625                            throw '%' + ch + ' not implemented by AnyTime.Converter';
626                        default: // for any character not listed above
627                            str += this.fmt.substr( f, 2 );
628                    } // switch ( this.fmt.charAt(f+1) )
629                    f++;
630                } // else
631            } // for ( var f = 0 ; f < _flen ; f++ )
632            return str;
633
634        }; // AnyTime.Converter.format()
635
636        //-------------------------------------------------------------------------
637        //  AnyTime.Converter.getUtcParseOffsetCaptured() returns the UTC offset
638        //  last captured by a parsed string (or assumed by utcParseOffsetAssumed).
639        //  It returns Number.MIN_VALUE if this object was not constructed with
640        //  the utcParseOffsetCapture option set to true, or if an offset was not
641        //  specified by the last parsed string or utcParseOffsetAssumed.
642        //-------------------------------------------------------------------------
643
644        this.getUtcParseOffsetCaptured = function()
645        {
646            return _offCap;
647        };
648
649        //-------------------------------------------------------------------------
650        //  AnyTime.Converter.getUtcParseOffsetCaptured() returns the UTC offset
651        //  last captured by a parsed string (or assumed by utcParseOffsetAssumed).
652        //  It returns Number.MIN_VALUE if this object was not constructed with
653        //  the utcParseOffsetCapture option set to true, or if an offset was not
654        //  specified by the last parsed string or utcParseOffsetAssumed.
655        //-------------------------------------------------------------------------
656
657        this.getUtcParseOffsetSubIndex = function()
658        {
659            return _offPSI;
660        };
661
662        //-------------------------------------------------------------------------
663        //  AnyTime.Converter.parse() returns a Date initialized from a specified
664        //  string, using the format passed to AnyTime.Converter().
665        //
666        //  Method parameter:
667        //
668        //    str - the String object to be converted
669        //-------------------------------------------------------------------------
670
671        this.parse = function( str )
672        {
673            _offCap = _offP;
674            _offPSI = (-1);
675            var era = 1;
676            var time = new Date( 4, 0, 1, 0, 0, 0, 0 );//4=leap year bug
677            var slen = str.length;
678            var s = 0;
679            var tzSign = 1, tzOff = _offP;
680            var i, matched, sub, sublen, temp;
681            for( var f = 0; f < _flen; f++ )
682            {
683                if( this.fmt.charAt( f ) == '%' )
684                {
685                    var ch = this.fmt.charAt( f + 1 );
686                    switch( ch )
687                    {
688                        case 'a': // Abbreviated weekday name (Sun..Sat)
689                            matched = false;
690                            for( sublen = 0; s + sublen < slen; sublen++ )
691                            {
692                                sub = str.substr( s, sublen );
693                                for( i = 0; i < 12; i++ )
694                                    if( this.dAbbr[i] == sub )
695                                    {
696                                        matched = true;
697                                        s += sublen;
698                                        break;
699                                    }
700                                if( matched )
701                                    break;
702                            } // for ( sublen ... )
703                            if( ! matched )
704                                throw 'unknown weekday: ' + str.substr( s );
705                            break;
706                        case 'B': // BCE string (eAbbr[0]), only if needed. (NON-MYSQL)
707                            sublen = this.eAbbr[0].length;
708                            if( ( s + sublen <= slen ) && ( str.substr( s, sublen ) == this.eAbbr[0] ) )
709                            {
710                                era = (-1);
711                                s += sublen;
712                            }
713                            break;
714                        case 'b': // Abbreviated month name (Jan..Dec)
715                            matched = false;
716                            for( sublen = 0; s + sublen < slen; sublen++ )
717                            {
718                                sub = str.substr( s, sublen );
719                                for( i = 0; i < 12; i++ )
720                                    if( this.mAbbr[i] == sub )
721                                    {
722                                        time.setMonth( i );
723                                        matched = true;
724                                        s += sublen;
725                                        break;
726                                    }
727                                if( matched )
728                                    break;
729                            } // for ( sublen ... )
730                            if( ! matched )
731                                throw 'unknown month: ' + str.substr( s );
732                            break;
733                        case 'C': // CE string (eAbbr[1]), only if needed. (NON-MYSQL)
734                            sublen = this.eAbbr[1].length;
735                            if( ( s + sublen <= slen ) && ( str.substr( s, sublen ) == this.eAbbr[1] ) )
736                                s += sublen; // note: CE is the default era
737                            break;
738                        case 'c': // Month, numeric (0..12)
739                            if( ( s + 1 < slen ) && this.dAt( str, s + 1 ) )
740                            {
741                                time.setMonth( (Number( str.substr( s, 2 ) ) - 1) % 12 );
742                                s += 2;
743                            }
744                            else
745                            {
746                                time.setMonth( (Number( str.substr( s, 1 ) ) - 1) % 12 );
747                                s++;
748                            }
749                            break;
750                        case 'D': // Day of the month with English suffix (0th,1st,...)
751                            if( ( s + 1 < slen ) && this.dAt( str, s + 1 ) )
752                            {
753                                time.setDate( Number( str.substr( s, 2 ) ) );
754                                s += 4;
755                            }
756                            else
757                            {
758                                time.setDate( Number( str.substr( s, 1 ) ) );
759                                s += 3;
760                            }
761                            break;
762                        case 'd': // Day of the month, numeric (00..31)
763                            time.setDate( Number( str.substr( s, 2 ) ) );
764                            s += 2;
765                            break;
766                        case 'E': // era string (from eAbbr[]) (NON-MYSQL)
767                            sublen = this.eAbbr[0].length;
768                            if( ( s + sublen <= slen ) && ( str.substr( s, sublen ) == this.eAbbr[0] ) )
769                            {
770                                era = (-1);
771                                s += sublen;
772                            }
773                            else if( ( s + ( sublen = this.eAbbr[1].length ) <= slen ) && ( str.substr( s, sublen ) == this.eAbbr[1] ) )
774                                s += sublen; // note: CE is the default era
775                            else
776                                throw 'unknown era: ' + str.substr( s );
777                            break;
778                        case 'e': // Day of the month, numeric (0..31)
779                            if( ( s + 1 < slen ) && this.dAt( str, s + 1 ) )
780                            {
781                                time.setDate( Number( str.substr( s, 2 ) ) );
782                                s += 2;
783                            }
784                            else
785                            {
786                                time.setDate( Number( str.substr( s, 1 ) ) );
787                                s++;
788                            }
789                            break;
790                        case 'f': // Microseconds (000000..999999)
791                            s += 6; // SKIPPED!
792                            break;
793                        case 'H': // Hour (00..23)
794                            time.setHours( Number( str.substr( s, 2 ) ) );
795                            s += 2;
796                            break;
797                        case 'h': // Hour (01..12)
798                        case 'I': // Hour (01..12)
799                            time.setHours( Number( str.substr( s, 2 ) ) );
800                            s += 2;
801                            break;
802                        case 'i': // Minutes, numeric (00..59)
803                            time.setMinutes( Number( str.substr( s, 2 ) ) );
804                            s += 2;
805                            break;
806                        case 'k': // Hour (0..23)
807                            if( ( s + 1 < slen ) && this.dAt( str, s + 1 ) )
808                            {
809                                time.setHours( Number( str.substr( s, 2 ) ) );
810                                s += 2;
811                            }
812                            else
813                            {
814                                time.setHours( Number( str.substr( s, 1 ) ) );
815                                s++;
816                            }
817                            break;
818                        case 'l': // Hour (1..12)
819                            if( ( s + 1 < slen ) && this.dAt( str, s + 1 ) )
820                            {
821                                time.setHours( Number( str.substr( s, 2 ) ) );
822                                s += 2;
823                            }
824                            else
825                            {
826                                time.setHours( Number( str.substr( s, 1 ) ) );
827                                s++;
828                            }
829                            break;
830                        case 'M': // Month name (January..December)
831                            matched = false;
832                            for( sublen = _shortMon; s + sublen <= slen; sublen++ )
833                            {
834                                if( sublen > _longMon )
835                                    break;
836                                sub = str.substr( s, sublen );
837                                for( i = 0; i < 12; i++ )
838                                {
839                                    if( this.mNames[i] == sub )
840                                    {
841                                        time.setMonth( i );
842                                        matched = true;
843                                        s += sublen;
844                                        break;
845                                    }
846                                }
847                                if( matched )
848                                    break;
849                            }
850                            break;
851                        case 'm': // Month, numeric (00..12)
852                            time.setMonth( (Number( str.substr( s, 2 ) ) - 1) % 12 );
853                            s += 2;
854                            break;
855                        case 'p': // AM or PM
856                            if( time.getHours() == 12 )
857                            {
858                                if( str.charAt( s ) == 'A' )
859                                    time.setHours( 0 );
860                            }
861                            else if( str.charAt( s ) == 'P' )
862                                time.setHours( time.getHours() + 12 );
863                            s += 2;
864                            break;
865                        case 'r': // Time, 12-hour (hh:mm:ss followed by AM or PM)
866                            time.setHours( Number( str.substr( s, 2 ) ) );
867                            time.setMinutes( Number( str.substr( s + 3, 2 ) ) );
868                            time.setSeconds( Number( str.substr( s + 6, 2 ) ) );
869                            if( time.getHours() == 12 )
870                            {
871                                if( str.charAt( s ) == 'A' )
872                                    time.setHours( 0 );
873                            }
874                            else if( str.charAt( s ) == 'P' )
875                                time.setHours( time.getHours() + 12 );
876                            s += 10;
877                            break;
878                        case 'S': // Seconds (00..59)
879                        case 's': // Seconds (00..59)
880                            time.setSeconds( Number( str.substr( s, 2 ) ) );
881                            s += 2;
882                            break;
883                        case 'T': // Time, 24-hour (hh:mm:ss)
884                            time.setHours( Number( str.substr( s, 2 ) ) );
885                            time.setMinutes( Number( str.substr( s + 3, 2 ) ) );
886                            time.setSeconds( Number( str.substr( s + 6, 2 ) ) );
887                            s += 8;
888                            break;
889                        case 'W': // Weekday name (Sunday..Saturday)
890                            matched = false;
891                            for( sublen = _shortDay; s + sublen <= slen; sublen++ )
892                            {
893                                if( sublen > _longDay )
894                                    break;
895                                sub = str.substr( s, sublen );
896                                for( i = 0; i < 7; i++ )
897                                {
898                                    if( this.dNames[i] == sub )
899                                    {
900                                        matched = true;
901                                        s += sublen;
902                                        break;
903                                    }
904                                }
905                                if( matched )
906                                    break;
907                            }
908                            break;
909                        case 'w': // Day of the week (0=Sunday..6=Saturday) (ignored)
910                            s += 1;
911                            break;
912                        case 'Y': // Year, numeric, four digits, negative if before 0001
913                            i = 4;
914                            if( str.substr( s, 1 ) == '-' )
915                                i++;
916                            time.setFullYear( Number( str.substr( s, i ) ) );
917                            s += i;
918                            break;
919                        case 'y': // Year, numeric (two digits), negative before baseYear
920                            i = 2;
921                            if( str.substr( s, 1 ) == '-' )
922                                i++;
923                            temp = Number( str.substr( s, i ) );
924                            if( typeof(this.baseYear) == 'number' )
925                                temp += this.baseYear;
926                            else if( temp < 70 )
927                                temp += 2000;
928                            else
929                                temp += 1900;
930                            time.setFullYear( temp );
931                            s += i;
932                            break;
933                        case 'Z': // Year, numeric, four digits, unsigned (NON-MYSQL)
934                            time.setFullYear( Number( str.substr( s, 4 ) ) );
935                            s += 4;
936                            break;
937                        case 'z': // Year, numeric, variable length, unsigned (NON-MYSQL)
938                            i = 0;
939                            while( ( s < slen ) && this.dAt( str, s ) )
940                                i = ( i * 10 ) + Number( str.charAt( s++ ) );
941                            time.setFullYear( i );
942                            break;
943                        case '#': // signed timezone offset in minutes.
944                            if( str.charAt( s++ ) == '-' )
945                                tzSign = (-1);
946                            for( tzOff = 0; ( s < slen ) && (String( i = Number( str.charAt( s ) ) ) == str.charAt( s )); s++ )
947                                tzOff = ( tzOff * 10 ) + i;
948                            tzOff *= tzSign;
949                            break;
950                        case '@': // timezone label
951                            _offPSI = (-1);
952                            if( AnyTime.utcLabel )
953                            {
954                                matched = false;
955                                for( tzOff in AnyTime.utcLabel )
956                                    if( ! Array.prototype[tzOff] ) // prototype.js compatibility issue
957                                    {
958                                        for( i = 0; i < AnyTime.utcLabel[tzOff].length; i++ )
959                                        {
960                                            sub = AnyTime.utcLabel[tzOff][i];
961                                            sublen = sub.length;
962                                            if( ( s + sublen <= slen ) && ( str.substr( s, sublen ) == sub ) )
963                                            {
964                                                s += sublen;
965                                                matched = true;
966                                                break;
967                                            }
968                                        }
969                                        if( matched )
970                                            break;
971                                    }
972                                if( matched )
973                                {
974                                    _offPSI = i;
975                                    tzOff = Number( tzOff );
976                                    break; // case
977                                }
978                            }
979                            if( ( s + 9 < slen ) || ( str.substr( s, 3 ) != "UTC" ) )
980                                throw 'unknown time zone: ' + str.substr( s );
981                            s += 3;
982                            ch = ':'; // drop through for offset parsing
983                        case '-': // signed, 3-or-4-digit timezone offset in hours and minutes
984                        case '+': // signed, 4-digit timezone offset in hours and minutes
985                        case ':': // signed 4-digit timezone offset with colon delimiter
986                        case ';': // signed 3-or-4-digit timezone offset with colon delimiter
987                            if( str.charAt( s++ ) == '-' )
988                                tzSign = (-1);
989                            tzOff = Number( str.charAt( s ) );
990                            if( (ch == '+') || (ch == ':') || ((s + 3 < slen) && (String( Number( str.charAt( s + 3 ) ) ) !== str.charAt( s + 3 ))) )
991                                tzOff = (tzOff * 10) + Number( str.charAt( ++s ) );
992                            tzOff *= 60;
993                            if( (ch == ':') || (ch == ';') )
994                                s++; // skip ":" (assumed)
995                            tzOff = ( tzOff + Number( str.substr( ++s, 2 ) ) ) * tzSign;
996                            s += 2;
997                            break;
998                        case 'j': // Day of year (001..366)
999                        case 'U': // Week (00..53), where Sunday is the first day of the week
1000                        case 'u': // Week (00..53), where Monday is the first day of the week
1001                        case 'V': // Week (01..53), where Sunday is the first day of the week; used with %X
1002                        case 'v': // Week (01..53), where Monday is the first day of the week; used with %x
1003                        case 'X': // Year for the week where Sunday is the first day of the week, numeric, four digits; used with %V
1004                        case 'x': // Year for the week, where Monday is the first day of the week, numeric, four digits; used with %v
1005                            throw '%' + this.fmt.charAt( f + 1 ) + ' not implemented by AnyTime.Converter';
1006                        case '%': // A literal '%' character
1007                        default: // for any character not listed above
1008                            throw '%' + this.fmt.charAt( f + 1 ) + ' reserved for future use';
1009                            break;
1010                    }
1011                    f++;
1012                } // if ( this.fmt.charAt(f) == '%' )
1013                else if( this.fmt.charAt( f ) != str.charAt( s ) )
1014                    throw str + ' is not in "' + this.fmt + '" format';
1015                else
1016                    s++;
1017            } // for ( var f ... )
1018            if( era < 0 )
1019                time.setFullYear( 0 - time.getFullYear() );
1020            if( tzOff != Number.MIN_VALUE )
1021            {
1022                if( _captureOffset )
1023                    _offCap = tzOff;
1024                else
1025                    time.setTime( ( time.getTime() - (tzOff * 60000) ) - (time.getTimezoneOffset() * 60000) );
1026            }
1027
1028            return time;
1029
1030        }; // AnyTime.Converter.parse()
1031
1032        //-------------------------------------------------------------------------
1033        //  AnyTime.Converter.setUtcFormatOffsetAlleged()  sets the offset from
1034        //  UTC, in minutes, to claim that a Date object represents during
1035        //  formatting, even though it is formatted using local time.  This merely
1036        //  reports the alleged offset when a timezone specifier (%#, %+, %-, %:,
1037        //  %; or %@) is encountered in the format string--it does not otherwise
1038        //  affect the date/time value.  This primarily exists so AnyTime.picker
1039        //  can edit the time as specified (without conversion to local time) and
1040        //  then convert the edited time to a different time zone (as selected
1041        //  using the picker).  This method returns the previous value, if any,
1042        //  set by the utcFormatOffsetAlleged option, or a previous call to
1043        //  setUtcFormatOffsetAlleged(), or Number.MIN_VALUE if no offset was
1044        //  previously-alleged.  Call this method with Number.MIN_VALUE to cancel
1045        //  any prior value.  Note that if a format offset is alleged, any offset
1046        //  specified by option utcFormatOffsetImposed is ignored.
1047        //-------------------------------------------------------------------------
1048
1049        this.setUtcFormatOffsetAlleged = function( offset )
1050        {
1051            var prev = _offAl;
1052            _offAl = offset;
1053            return prev;
1054        };
1055
1056        //-------------------------------------------------------------------------
1057        //  AnyTime.Converter.setUtcFormatOffsetSubIndex() sets the sub-index
1058        //  to choose from the AnyTime.utcLabel array of arrays when formatting
1059        //  a Date using the %@ specifier.  For more information, see option
1060        //  AnyTime.Converter.utcFormatOffsetSubIndex.  This primarily exists so
1061        //  AnyTime.picker can specify the Time Zone label selected using the
1062        //  picker).  This method returns the previous value, if any, set by the
1063        //  utcFormatOffsetSubIndex option, or a previous call to
1064        //  setUtcFormatOffsetAlleged(), or (-1) if no sub-index was previously-
1065        //  chosen.  Call this method with (-1) to cancel any prior value.
1066        //-------------------------------------------------------------------------
1067
1068        this.setUtcFormatOffsetSubIndex = function( subIndex )
1069        {
1070            var prev = _offFSI;
1071            _offFSI = subIndex;
1072            return prev;
1073        };
1074
1075        //-------------------------------------------------------------------------
1076        //      AnyTime.Converter construction code:
1077        //-------------------------------------------------------------------------
1078
1079        (function( _this )
1080        {
1081            var i, len;
1082
1083            options = jQuery.extend( true, {}, options || {} );
1084
1085            if( options.baseYear )
1086                _this.baseYear = Number( options.baseYear );
1087
1088            if( options.format )
1089                _this.fmt = options.format;
1090
1091            _flen = _this.fmt.length;
1092
1093            if( options.dayAbbreviations )
1094                _this.dAbbr = $.makeArray( options.dayAbbreviations );
1095
1096            if( options.dayNames )
1097            {
1098                _this.dNames = $.makeArray( options.dayNames );
1099                _longDay = 1;
1100                _shortDay = 1000;
1101                for( i = 0; i < 7; i++ )
1102                {
1103                    len = _this.dNames[i].length;
1104                    if( len > _longDay )
1105                        _longDay = len;
1106                    if( len < _shortDay )
1107                        _shortDay = len;
1108                }
1109            }
1110
1111            if( options.eraAbbreviations )
1112                _this.eAbbr = $.makeArray( options.eraAbbreviations );
1113
1114            if( options.monthAbbreviations )
1115                _this.mAbbr = $.makeArray( options.monthAbbreviations );
1116
1117            if( options.monthNames )
1118            {
1119                _this.mNames = $.makeArray( options.monthNames );
1120                _longMon = 1;
1121                _shortMon = 1000;
1122                for( i = 0; i < 12; i++ )
1123                {
1124                    len = _this.mNames[i].length;
1125                    if( len > _longMon )
1126                        _longMon = len;
1127                    if( len < _shortMon )
1128                        _shortMon = len;
1129                }
1130            }
1131
1132            if( typeof options.utcFormatOffsetImposed != "undefined" )
1133                _offF = options.utcFormatOffsetImposed;
1134
1135            if( typeof options.utcParseOffsetAssumed != "undefined" )
1136                _offP = options.utcParseOffsetAssumed;
1137
1138            if( options.utcParseOffsetCapture )
1139                _captureOffset = true;
1140
1141        })( this ); // AnyTime.Converter construction
1142
1143    }; // AnyTime.Converter =
1144
1145//=============================================================================
1146//  AnyTime.noPicker()
1147//
1148//  Removes the date/time entry picker attached to a specified text field.
1149//=============================================================================
1150
1151    AnyTime.noPicker = function( id )
1152    {
1153        if( __pickers[id] )
1154        {
1155            __pickers[id].cleanup();
1156            delete __pickers[id];
1157        }
1158    };
1159
1160//=============================================================================
1161//  AnyTime.picker()
1162//
1163//  Creates a date/time entry picker attached to a specified text field.
1164//  Instead of entering a date and/or time into the text field, the user
1165//  selects legal combinations using the picker, and the field is auto-
1166//  matically populated.  The picker can be incorporated into the page
1167//      "inline", or used as a "popup" that appears when the text field is
1168//  clicked and disappears when the picker is dismissed. Ajax can be used
1169//  to send the selected value to a server to approve or veto it.
1170//
1171//  To create a picker, simply include the necessary files in an HTML page
1172//  and call the function for each date/time input field.  The following
1173//  example creates a popup picker for field "foo" using the default
1174//  format, and a second date-only (no time) inline (always-visible)
1175//  Ajax-enabled picker for field "bar":
1176//
1177//    <link rel="stylesheet" type="text/css" href="anytime.css" />
1178//    <script type="text/javascript" src="jquery.js"></script>
1179//    <script type="text/javascript" src="anytime.js"></script>
1180//    <input type="text" id="foo" tabindex="1" value="1967-07-30 23:45" />
1181//    <input type="text" id="bar" tabindex="2" value="01/06/90" />
1182//    <script type="text/javascript">
1183//      AnyTime.picker( "foo" );
1184//      AnyTime.picker( "bar", { placement:"inline", format: "%m/%d/%y",
1185//                                                              ajaxOptions { url: "/some/server/page/" } } );
1186//    </script>
1187//
1188//  The appearance of the picker can be extensively modified using CSS styles.
1189//  A default appearance can be achieved by the "anytime.css" stylesheet that
1190//  accompanies this script.  The default style looks better in browsers other
1191//  than Internet Explorer (before IE8) because older versions of IE do not
1192//  properly implement the CSS box model standard; however, it is passable in
1193//  Internet Explorer as well.
1194//
1195//  Method parameters:
1196//
1197//  id - the "id" attribute of the textfield to associate with the
1198//    AnyTime.picker object.  The AnyTime.picker will attach itself
1199//    to the textfield and manage its value.
1200//
1201//  options - an object (associative array) of optional parameters that
1202//    override default behaviors.  The supported options are:
1203//
1204//    ajaxOptions - options passed to jQuery's $.ajax() method whenever
1205//      the user dismisses a popup picker or selects a value in an inline
1206//      picker.  The input's name (or ID) and value are passed to the
1207//      server (appended to ajaxOptions.data, if present), and the
1208//      "success" handler sets the input's value to the responseText.
1209//      Therefore, the text returned by the server must be valid for the
1210//      input'sdate/time format, and the server can approve or veto the
1211//      value chosen by the user. For more information, see:
1212//      http://docs.jquery.com/Ajax.
1213//      If ajaxOptions.success is specified, it is used instead of the
1214//      default "success" behavior.
1215//
1216//    askEra - if true, buttons to select the era are shown on the year
1217//        selector popup, even if format specifier does not include the
1218//        era.  If false, buttons to select the era are NOT shown, even
1219//        if the format specifier includes ther era.  Normally, era buttons
1220//        are only shown if the format string specifies the era.
1221//
1222//    askSecond - if false, buttons for number-of-seconds are not shown
1223//        even if the format includes seconds.  Normally, the buttons
1224//        are shown if the format string includes seconds.
1225//
1226//    earliest - String or Date object representing the earliest date/time
1227//        that a user can select.  For best results if the field is only
1228//        used to specify a date, be sure to set the time to 00:00:00.
1229//        If a String is used, it will be parsed according to the picker's
1230//        format (see AnyTime.Converter.format()).
1231//
1232//    firstDOW - a value from 0 (Sunday) to 6 (Saturday) stating which
1233//      day should appear at the beginning of the week.  The default is 0
1234//      (Sunday).  The most common substitution is 1 (Monday).  Note that
1235//      if custom arrays are specified for AnyTime.Converter's dayAbbreviations
1236//      and/or dayNames options, they should nonetheless begin with the
1237//      value for Sunday.
1238//
1239//    hideInput - if true, the <input> is "hidden" (the picker appears in
1240//      its place). This actually sets the border, height, margin, padding
1241//      and width of the field as small as possivle, so it can still get focus.
1242//      If you try to hide the field using traditional techniques (such as
1243//      setting "display:none"), the picker will not behave correctly.
1244//
1245//    labelDayOfMonth - the label for the day-of-month "buttons".
1246//      Can be any HTML!  If not specified, "Day of Month" is assumed.
1247//
1248//    labelDismiss - the label for the dismiss "button" (if placement is
1249//      "popup"). Can be any HTML!  If not specified, "X" is assumed.
1250//
1251//    labelHour - the label for the hour "buttons".
1252//      Can be any HTML!  If not specified, "Hour" is assumed.
1253//
1254//    labelMinute - the label for the minute "buttons".
1255//      Can be any HTML!  If not specified, "Minute" is assumed.
1256//
1257//    labelMonth - the label for the month "buttons".
1258//      Can be any HTML!  If not specified, "Month" is assumed.
1259//
1260//    labelTimeZone - the label for the UTC offset (timezone) "buttons".
1261//      Can be any HTML!  If not specified, "Time Zone" is assumed.
1262//
1263//    labelSecond - the label for the second "buttons".
1264//      Can be any HTML!  If not specified, "Second" is assumed.
1265//      This option is ignored if askSecond is false!
1266//
1267//    labelTitle - the label for the "title bar".  Can be any HTML!
1268//      If not specified, then whichever of the following is most
1269//      appropriate is used:  "Select a Date and Time", "Select a Date"
1270//      or "Select a Time", or no label if only one field is present.
1271//
1272//    labelYear - the label for the year "buttons".
1273//      Can be any HTML!  If not specified, "Year" is assumed.
1274//
1275//    latest - String or Date object representing the latest date/time
1276//        that a user can select.  For best results if the field is only
1277//        used to specify a date, be sure to set the time to 23:59:59.
1278//        If a String is used, it will be parsed according to the picker's
1279//        format (see AnyTime.Converter.format()).
1280//
1281//    placement - One of the following strings:
1282//
1283//      "popup" = the picker appears above its <input> when the input
1284//        receives focus, and disappears when it is dismissed.  This is
1285//        the default behavior.
1286//
1287//      "inline" = the picker is placed immediately after the <input>
1288//        and remains visible at all times.  When choosing this placement,
1289//        it is best to make the <input> invisible and use only the
1290//        picker to select dates.  The <input> value can still be used
1291//        during form submission as it will always reflect the current
1292//        picker state.
1293//
1294//        WARNING: when using "inline" and XHTML and including a day-of-
1295//        the-month format field, the input may only appear where a <table>
1296//        element is permitted (for example, NOT within a <p> element).
1297//        This is because the picker uses a <table> element to arrange
1298//        the day-of-the-month (calendar) buttons.  Failure to follow this
1299//        advice may result in an "unknown error" in Internet Explorer.
1300//
1301//    The following additional options may be specified; see documentation
1302//    for AnyTime.Converter (above) for information about these options:
1303//
1304//      baseYear
1305//      dayAbbreviations
1306//      dayNames
1307//      eraAbbreviations
1308//      format
1309//      monthAbbreviations
1310//      monthNames
1311//
1312//  Other behavior, such as how to format the values on the display
1313//  and which "buttons" to include, is inferred from the format string.
1314//=============================================================================
1315
1316    AnyTime.picker = function( id, options )
1317    {
1318        //  Create a new private object instance to manage the picker,
1319        //  if one does not already exist.
1320
1321        if( __pickers[id] )
1322            throw 'Cannot create another AnyTime picker for "' + id + '"';
1323
1324        var _this = null;
1325
1326        __pickers[id] =
1327        {
1328            //  private members
1329
1330            twelveHr: false,
1331            ajaxOpts: null,        // options for AJAX requests
1332            denyTab: true,      // set to true to stop Opera from tabbing away
1333            askEra: false,        // prompt the user for the era in yDiv?
1334            cloak: null,        // cloak div
1335            conv: null,            // AnyTime.Converter
1336            bMinW: 0,            // min width of body div
1337            bMinH: 0,            // min height of body div
1338            dMinW: 0,            // min width of date div
1339            dMinH: 0,            // min height of date div
1340            div: null,            // picker div
1341            dB: null,            // body div
1342            dD: null,            // date div
1343            dY: null,            // years div
1344            dMo: null,            // months div
1345            dDoM: null,            // date-of-month table
1346            hDoM: null,            // date-of-month heading
1347            hMo: null,            // month heading
1348            hTitle: null,        // title heading
1349            hY: null,            // year heading
1350            dT: null,            // time div
1351            dH: null,            // hours div
1352            dM: null,            // minutes div
1353            dS: null,            // seconds div
1354            dO: null,           // offset (time zone) div
1355            earliest: null,        // earliest selectable date/time
1356            fBtn: null,            // button with current focus
1357            fDOW: 0,            // index to use as first day-of-week
1358            hBlur: null,        // input handler
1359            hClick: null,       // input handler
1360            hFocus: null,       // input handler
1361            hKeydown: null,     // input handler
1362            hKeypress: null,    // input handler
1363            id: null,            // picker ID
1364            inp: null,            // input text field
1365            latest: null,        // latest selectable date/time
1366            lastAjax: null,        // last value submitted using AJAX
1367            lostFocus: false,    // when focus is lost, must redraw
1368            lX: 'X',            // label for dismiss button
1369            lY: 'Year',            // label for year
1370            lO: 'Time Zone',    // label for UTC offset (time zone)
1371            oBody: null,        // UTC offset selector popup
1372            oConv: null,        // AnyTime.Converter for offset display
1373            oCur: null,         // current-UTC-offset button
1374            oDiv: null,            // UTC offset selector popup
1375            oLab: null,            // UTC offset label
1376            oListMinW: 0,       // min width of offset list element
1377            oMinW: 0,           // min width of UTC offset element
1378            oSel: null,         // select (plus/minus) UTC-offset button
1379            offMin: Number.MIN_VALUE, // current UTC offset in minutes
1380            offSI: -1,          // current UTC label sub-index (if any)
1381            offStr: "",         // current UTC offset (time zone) string
1382            pop: true,            // picker is a popup?
1383            time: null,            // current date/time
1384            tMinW: 0,            // min width of time div
1385            tMinH: 0,            // min height of time div
1386            url: null,            // URL to submit value using AJAX
1387            wMinW: 0,            // min width of picker
1388            wMinH: 0,            // min height of picker
1389            yAhead: null,        // years-ahead button
1390            y0XXX: null,        // millenium-digit-zero button (for focus)
1391            yCur: null,            // current-year button
1392            yDiv: null,            // year selector popup
1393            yLab: null,            // year label
1394            yNext: null,        // next-year button
1395            yPast: null,        // years-past button
1396            yPrior: null,        // prior-year button
1397
1398            //---------------------------------------------------------------------
1399            //  .initialize() initializes the picker instance.
1400            //---------------------------------------------------------------------
1401
1402            initialize: function( id )
1403            {
1404                _this = this;
1405
1406                this.id = 'AnyTime--' + id.replace( /[^-_.A-Za-z0-9]/g, '--AnyTime--' );
1407
1408                options = jQuery.extend( true, {}, options || {} );
1409                options.utcParseOffsetCapture = true;
1410                this.conv = new AnyTime.Converter( options );
1411
1412                if( options.placement )
1413                {
1414                    if( options.placement == 'inline' )
1415                        this.pop = false;
1416                    else if( options.placement != 'popup' )
1417                        throw 'unknown placement: ' + options.placement;
1418                }
1419
1420                if( options.ajaxOptions )
1421                {
1422                    this.ajaxOpts = jQuery.extend( {}, options.ajaxOptions );
1423                    if( ! this.ajaxOpts.success )
1424                        this.ajaxOpts.success = function( data, status )
1425                        {
1426                            _this.inp.val( data );
1427                        };
1428                }
1429
1430                if( options.earliest )
1431                {
1432                    if( typeof options.earliest.getTime == 'function' )
1433                        this.earliest = options.earliest.getTime();
1434                    else
1435                        this.earliest = this.conv.parse( options.earliest.toString() );
1436                }
1437
1438                if( options.firstDOW )
1439                {
1440                    if( ( options.firstDOW < 0 ) || ( options.firstDOW > 6 ) )
1441                        throw new Exception( 'illegal firstDOW: ' + options.firstDOW );
1442                    this.fDOW = options.firstDOW;
1443                }
1444
1445                if( options.latest )
1446                {
1447                    if( typeof options.latest.getTime == 'function' )
1448                        this.latest = options.latest.getTime();
1449                    else
1450                        this.latest = this.conv.parse( options.latest.toString() );
1451                }
1452
1453                this.lX = options.labelDismiss || 'X';
1454                this.lY = options.labelYear || 'Year';
1455                this.lO = options.labelTimeZone || 'Time Zone';
1456
1457                //  Infer what we can about what to display from the format.
1458
1459                var i;
1460                var t;
1461                var lab;
1462                var shownFields = 0;
1463                var format = this.conv.fmt;
1464
1465                if( typeof options.askEra != 'undefined' )
1466                    this.askEra = options.askEra;
1467                else
1468                    this.askEra = (format.indexOf( '%B' ) >= 0) || (format.indexOf( '%C' ) >= 0) || (format.indexOf( '%E' ) >= 0);
1469                var askYear = (format.indexOf( '%Y' ) >= 0) || (format.indexOf( '%y' ) >= 0) || (format.indexOf( '%Z' ) >= 0) || (format.indexOf( '%z' ) >= 0);
1470                var askMonth = (format.indexOf( '%b' ) >= 0) || (format.indexOf( '%c' ) >= 0) || (format.indexOf( '%M' ) >= 0) || (format.indexOf( '%m' ) >= 0);
1471                var askDoM = (format.indexOf( '%D' ) >= 0) || (format.indexOf( '%d' ) >= 0) || (format.indexOf( '%e' ) >= 0);
1472                var askDate = askYear || askMonth || askDoM;
1473                this.twelveHr = (format.indexOf( '%h' ) >= 0) || (format.indexOf( '%I' ) >= 0) || (format.indexOf( '%l' ) >= 0) || (format.indexOf( '%r' ) >= 0);
1474                var askHour = this.twelveHr || (format.indexOf( '%H' ) >= 0) || (format.indexOf( '%k' ) >= 0) || (format.indexOf( '%T' ) >= 0);
1475                var askMinute = (format.indexOf( '%i' ) >= 0) || (format.indexOf( '%r' ) >= 0) || (format.indexOf( '%T' ) >= 0);
1476                var askSec = ( (format.indexOf( '%r' ) >= 0) || (format.indexOf( '%S' ) >= 0) || (format.indexOf( '%s' ) >= 0) || (format.indexOf( '%T' ) >= 0) );
1477                if( askSec && ( typeof options.askSecond != 'undefined' ) )
1478                    askSec = options.askSecond;
1479                var askOff = ( (format.indexOf( '%#' ) >= 0) || (format.indexOf( '%+' ) >= 0) || (format.indexOf( '%-' ) >= 0) || (format.indexOf( '%:' ) >= 0) || (format.indexOf( '%;' ) >= 0) || (format.indexOf( '%<' ) >= 0) || (format.indexOf( '%>' ) >= 0) || (format.indexOf( '%@' ) >= 0) );
1480                var askTime = askHour || askMinute || askSec || askOff;
1481
1482                if( askOff )
1483                    this.oConv = new AnyTime.Converter( { format: options.formatUtcOffset ||
1484                            format.match( /\S*%[-+:;<>#@]\S*/g ).join( ' ' ) } );
1485
1486                //  Create the picker HTML and add it to the page.
1487                //  Popup pickers will be moved to the end of the body
1488                //  once the entire page has loaded.
1489
1490                this.inp = $( document.getElementById( id ) ); // avoids ID-vs-pseudo-selector probs like id="foo:bar"
1491                this.div = $( '<div class="AnyTime-win AnyTime-pkr ui-widget ui-widget-content ui-corner-all" style="width:0;height:0" id="' + this.id + '" aria-live="off"/>' );
1492                this.inp.after( this.div );
1493                this.wMinW = this.div.outerWidth( !$.browser.safari );
1494                this.wMinH = this.div.AnyTime_height( true );
1495                this.hTitle = $( '<h5 class="AnyTime-hdr ui-widget-header ui-corner-top"/>' );
1496                this.div.append( this.hTitle );
1497                this.dB = $( '<div class="AnyTime-body" style="width:0;height:0"/>' );
1498                this.div.append( this.dB );
1499                this.bMinW = this.dB.outerWidth( true );
1500                this.bMinH = this.dB.AnyTime_height( true );
1501
1502                if( options.hideInput )
1503                    this.inp.css( {border:0,height:'1px',margin:0,padding:0,width:'1px'} );
1504
1505                //  Add dismiss box to title (if popup)
1506
1507                t = null;
1508                var xDiv = null;
1509                if( this.pop )
1510                {
1511                    xDiv = $( '<div class="AnyTime-x-btn ui-state-default">' + this.lX + '</div>' );
1512                    this.hTitle.append( xDiv );
1513                    xDiv.click( function( e )
1514                    {
1515                        _this.dismiss( e );
1516                    } );
1517                }
1518
1519                //  date (calendar) portion
1520
1521                lab = '';
1522                if( askDate )
1523                {
1524                    this.dD = $( '<div class="AnyTime-date" style="width:0;height:0"/>' );
1525                    this.dB.append( this.dD );
1526                    this.dMinW = this.dD.outerWidth( true );
1527                    this.dMinH = this.dD.AnyTime_height( true );
1528
1529                    if( askYear )
1530                    {
1531                        this.yLab = $( '<h6 class="AnyTime-lbl AnyTime-lbl-yr">' + this.lY + '</h6>' );
1532                        this.dD.append( this.yLab );
1533
1534                        this.dY = $( '<ul class="AnyTime-yrs ui-helper-reset" />' );
1535                        this.dD.append( this.dY );
1536
1537                        this.yPast = this.btn( this.dY, '&lt;', this.newYear, ['yrs-past'], '- ' + this.lY );
1538                        this.yPrior = this.btn( this.dY, '1', this.newYear, ['yr-prior'], '-1 ' + this.lY );
1539                        this.yCur = this.btn( this.dY, '2', this.newYear, ['yr-cur'], this.lY );
1540                        this.yCur.removeClass( 'ui-state-default' );
1541                        this.yCur.addClass( 'AnyTime-cur-btn ui-state-default ui-state-highlight' );
1542
1543                        this.yNext = this.btn( this.dY, '3', this.newYear, ['yr-next'], '+1 ' + this.lY );
1544                        this.yAhead = this.btn( this.dY, '&gt;', this.newYear, ['yrs-ahead'], '+ ' + this.lY );
1545
1546                        shownFields++;
1547
1548                    } // if ( askYear )
1549
1550                    if( askMonth )
1551                    {
1552                        lab = options.labelMonth || 'Month';
1553                        this.hMo = $( '<h6 class="AnyTime-lbl AnyTime-lbl-month">' + lab + '</h6>' );
1554                        this.dD.append( this.hMo );
1555                        this.dMo = $( '<ul class="AnyTime-mons" />' );
1556                        this.dD.append( this.dMo );
1557                        for( i = 0; i < 12; i++ )
1558                        {
1559                            var mBtn = this.btn( this.dMo, this.conv.mAbbr[i],
1560                                    function( event )
1561                                    {
1562                                        var elem = $( event.target );
1563                                        if( elem.hasClass( "AnyTime-out-btn" ) )
1564                                            return;
1565                                        var mo = event.target.AnyTime_month;
1566                                        var t = new Date( this.time.getTime() );
1567                                        if( t.getDate() > __daysIn[mo] )
1568                                            t.setDate( __daysIn[mo] )
1569                                        t.setMonth( mo );
1570                                        this.set( t );
1571                                        this.upd( elem );
1572                                    },
1573                                    ['mon','mon' + String( i + 1 )], lab + ' ' + this.conv.mNames[i] );
1574                            mBtn[0].AnyTime_month = i;
1575                        }
1576                        shownFields++;
1577                    }
1578
1579                    if( askDoM )
1580                    {
1581                        lab = options.labelDayOfMonth || 'Day of Month';
1582                        this.hDoM = $( '<h6 class="AnyTime-lbl AnyTime-lbl-dom">' + lab + '</h6>' );
1583                        this.dD.append( this.hDoM );
1584                        this.dDoM = $( '<table border="0" cellpadding="0" cellspacing="0" class="AnyTime-dom-table"/>' );
1585                        this.dD.append( this.dDoM );
1586                        t = $( '<thead class="AnyTime-dom-head"/>' );
1587                        this.dDoM.append( t );
1588                        var tr = $( '<tr class="AnyTime-dow"/>' );
1589                        t.append( tr );
1590                        for( i = 0; i < 7; i++ )
1591                            tr.append( '<th class="AnyTime-dow AnyTime-dow' + String( i + 1 ) + '">' + this.conv.dAbbr[(this.fDOW + i) % 7] + '</th>' );
1592
1593                        var tbody = $( '<tbody class="AnyTime-dom-body" />' );
1594                        this.dDoM.append( tbody );
1595                        for( var r = 0; r < 6; r++ )
1596                        {
1597                            tr = $( '<tr class="AnyTime-wk AnyTime-wk' + String( r + 1 ) + '"/>' );
1598                            tbody.append( tr );
1599                            for( i = 0; i < 7; i++ )
1600                                this.btn( tr, 'x',
1601                                        function( event )
1602                                        {
1603                                            var elem = $( event.target );
1604                                            if( elem.hasClass( "AnyTime-out-btn" ) )
1605                                                return;
1606                                            var dom = Number( elem.html() );
1607                                            if( dom )
1608                                            {
1609                                                var t = new Date( this.time.getTime() );
1610                                                t.setDate( dom );
1611                                                this.set( t );
1612                                                this.upd( elem );
1613                                            }
1614                                        },
1615                                        ['dom'], lab );
1616                        }
1617                        shownFields++;
1618
1619                    } // if ( askDoM )
1620
1621                } // if ( askDate )
1622
1623                //  time portion
1624
1625                if( askTime )
1626                {
1627                    var tensDiv, onesDiv;
1628
1629                    this.dT = $( '<div class="AnyTime-time" style="width:0;height:0" />' );
1630                    this.dB.append( this.dT );
1631                    this.tMinW = this.dT.outerWidth( true );
1632                    this.tMinH = this.dT.AnyTime_height( true );
1633
1634                    if( askHour )
1635                    {
1636                        this.dH = $( '<div class="AnyTime-hrs"/>' );
1637                        this.dT.append( this.dH );
1638
1639                        lab = options.labelHour || 'Hour';
1640                        this.dH.append( $( '<h6 class="AnyTime-lbl AnyTime-lbl-hr">' + lab + '</h6>' ) );
1641                        var amDiv = $( '<ul class="AnyTime-hrs-am"/>' );
1642                        this.dH.append( amDiv );
1643                        var pmDiv = $( '<ul class="AnyTime-hrs-pm"/>' );
1644                        this.dH.append( pmDiv );
1645
1646                        for( i = 0; i < 12; i++ )
1647                        {
1648                            if( this.twelveHr )
1649                            {
1650                                if( i == 0 )
1651                                    t = '12am';
1652                                else
1653                                    t = String( i ) + 'am';
1654                            }
1655                            else
1656                                t = AnyTime.pad( i, 2 );
1657
1658                            this.btn( amDiv, t, this.newHour, ['hr','hr' + String( i )], lab + ' ' + t );
1659
1660                            if( this.twelveHr )
1661                            {
1662                                if( i == 0 )
1663                                    t = '12pm';
1664                                else
1665                                    t = String( i ) + 'pm';
1666                            }
1667                            else
1668                                t = i + 12;
1669
1670                            this.btn( pmDiv, t, this.newHour, ['hr','hr' + String( i + 12 )], lab + ' ' + t );
1671                        }
1672
1673                        shownFields++;
1674
1675                    } // if ( askHour )
1676
1677                    if( askMinute )
1678                    {
1679                        this.dM = $( '<div class="AnyTime-mins"/>' );
1680                        this.dT.append( this.dM );
1681
1682                        lab = options.labelMinute || 'Minute';
1683                        this.dM.append( $( '<h6 class="AnyTime-lbl AnyTime-lbl-min">' + lab + '</h6>' ) );
1684                        tensDiv = $( '<ul class="AnyTime-mins-tens"/>' );
1685                        this.dM.append( tensDiv );
1686
1687                        for( i = 0; i < 6; i++ )
1688                            this.btn( tensDiv, i,
1689                                    function( event )
1690                                    {
1691                                        var elem = $( event.target );
1692                                        if( elem.hasClass( "AnyTime-out-btn" ) )
1693                                            return;
1694                                        var t = new Date( this.time.getTime() );
1695                                        t.setMinutes( (Number( elem.text() ) * 10) + (this.time.getMinutes() % 10) );
1696                                        this.set( t );
1697                                        this.upd( elem );
1698                                    },
1699                                    ['min-ten','min' + i + '0'], lab + ' ' + i + '0' );
1700                        for( ; i < 12; i++ )
1701                            this.btn( tensDiv, '&#160;', $.noop, ['min-ten','min' + i + '0'], lab + ' ' + i + '0' ).addClass( 'AnyTime-min-ten-btn-empty ui-state-default ui-state-disabled' );
1702
1703                        onesDiv = $( '<ul class="AnyTime-mins-ones"/>' );
1704                        this.dM.append( onesDiv );
1705                        for( i = 0; i < 10; i++ )
1706                            this.btn( onesDiv, i,
1707                                    function( event )
1708                                    {
1709                                        var elem = $( event.target );
1710                                        if( elem.hasClass( "AnyTime-out-btn" ) )
1711                                            return;
1712                                        var t = new Date( this.time.getTime() );
1713                                        t.setMinutes( (Math.floor( this.time.getMinutes() / 10 ) * 10) + Number( elem.text() ) );
1714                                        this.set( t );
1715                                        this.upd( elem );
1716                                    },
1717                                    ['min-one','min' + i], lab + ' ' + i );
1718                        for( ; i < 12; i++ )
1719                            this.btn( onesDiv, '&#160;', $.noop, ['min-one','min' + i + '0'], lab + ' ' + i ).addClass( 'AnyTime-min-one-btn-empty ui-state-default ui-state-disabled' );
1720
1721                        shownFields++;
1722
1723                    } // if ( askMinute )
1724
1725                    if( askSec )
1726                    {
1727                        this.dS = $( '<div class="AnyTime-secs"/>' );
1728                        this.dT.append( this.dS );
1729                        lab = options.labelSecond || 'Second';
1730                        this.dS.append( $( '<h6 class="AnyTime-lbl AnyTime-lbl-sec">' + lab + '</h6>' ) );
1731                        tensDiv = $( '<ul class="AnyTime-secs-tens"/>' );
1732                        this.dS.append( tensDiv );
1733
1734                        for( i = 0; i < 6; i++ )
1735                            this.btn( tensDiv, i,
1736                                    function( event )
1737                                    {
1738                                        var elem = $( event.target );
1739                                        if( elem.hasClass( "AnyTime-out-btn" ) )
1740                                            return;
1741                                        var t = new Date( this.time.getTime() );
1742                                        t.setSeconds( (Number( elem.text() ) * 10) + (this.time.getSeconds() % 10) );
1743                                        this.set( t );
1744                                        this.upd( elem );
1745                                    },
1746                                    ['sec-ten','sec' + i + '0'], lab + ' ' + i + '0' );
1747                        for( ; i < 12; i++ )
1748                            this.btn( tensDiv, '&#160;', $.noop, ['sec-ten','sec' + i + '0'], lab + ' ' + i + '0' ).addClass( 'AnyTime-sec-ten-btn-empty ui-state-default ui-state-disabled' );
1749
1750                        onesDiv = $( '<ul class="AnyTime-secs-ones"/>' );
1751                        this.dS.append( onesDiv );
1752                        for( i = 0; i < 10; i++ )
1753                            this.btn( onesDiv, i,
1754                                    function( event )
1755                                    {
1756                                        var elem = $( event.target );
1757                                        if( elem.hasClass( "AnyTime-out-btn" ) )
1758                                            return;
1759                                        var t = new Date( this.time.getTime() );
1760                                        t.setSeconds( (Math.floor( this.time.getSeconds() / 10 ) * 10) + Number( elem.text() ) );
1761                                        this.set( t );
1762                                        this.upd( elem );
1763                                    },
1764                                    ['sec-one','sec' + i], lab + ' ' + i );
1765                        for( ; i < 12; i++ )
1766                            this.btn( onesDiv, '&#160;', $.noop, ['sec-one','sec' + i + '0'], lab + ' ' + i ).addClass( 'AnyTime-sec-one-btn-empty ui-state-default ui-state-disabled' );
1767
1768                        shownFields++;
1769
1770                    } // if ( askSec )
1771
1772                    if( askOff )
1773                    {
1774                        this.dO = $( '<div class="AnyTime-offs" />' );
1775                        this.dT.append( this.dO );
1776                        this.oMinW = this.dO.outerWidth( true );
1777
1778                        this.oLab = $( '<h6 class="AnyTime-lbl AnyTime-lbl-off">' + this.lO + '</h6>' );
1779                        this.dO.append( this.oLab );
1780
1781                        var offDiv = $( '<ul class="AnyTime-off-list ui-helper-reset" />' );
1782                        this.dO.append( offDiv );
1783
1784                        this.oCur = this.btn( offDiv, '', this.newOffset, ['off','off-cur'], lab );
1785                        this.oCur.removeClass( 'ui-state-default' );
1786                        this.oCur.addClass( 'AnyTime-cur-btn ui-state-default ui-state-highlight' );
1787                        this.oCur.css( {overflow:"hidden"} );
1788
1789                        this.oSel = this.btn( offDiv, '&#177;', this.newOffset, ['off','off-select'], '+/- ' + this.lO );
1790                        this.oListMinW = this.oCur.outerWidth( true ) + this.oSel.outerWidth( true );
1791
1792                        shownFields++;
1793                    }
1794
1795                } // if ( askTime )
1796
1797                //  Set the title.  If a title option has been specified, use it.
1798                //  Otherwise, determine a worthy title based on which (and how many)
1799                //  format fields have been specified.
1800
1801                if( options.labelTitle )
1802                    this.hTitle.append( options.labelTitle );
1803                else if( shownFields > 1 )
1804                    this.hTitle.append( 'Select a ' + (askDate ? (askTime ? 'Date and Time' : 'Date') : 'Time') );
1805                else
1806                    this.hTitle.append( 'Select' );
1807
1808
1809                /** VMIPSL **/
1810                if( options.methodToCall )
1811                    this.methodToCall = options.methodToCall;
1812
1813                /** VMIPSL **/
1814                if( options.idToUpdateEarliest )
1815                    this.idToUpdateEarliest = options.idToUpdateEarliest;
1816
1817                //  Initialize the picker's date/time value.
1818
1819                try
1820                {
1821                    this.time = this.conv.parse( this.inp.val() );
1822                    this.offMin = this.conv.getUtcParseOffsetCaptured();
1823                    this.offSI = this.conv.getUtcParseOffsetSubIndex();
1824                }
1825                catch ( e )
1826                {
1827                    this.time = new Date();
1828                }
1829                this.lastAjax = this.time;
1830
1831
1832                //  If this is a popup picker, hide it until needed.
1833
1834                if( this.pop )
1835                {
1836                    this.div.hide();
1837                    if( __iframe )
1838                        __iframe.hide();
1839                    this.div.css( 'position', 'absolute' );
1840                }
1841
1842                //  Setup event listeners for the input and resize listeners for
1843                //  the picker.  Add the picker to the instances list (which is used
1844                //  to hide pickers if the user clicks off of them).
1845
1846                this.inp.blur( this.hBlur =
1847                        function( e )
1848                        {
1849                            _this.inpBlur( e );
1850                        } );
1851
1852                this.inp.click( this.hClick =
1853                        function( e )
1854                        {
1855                            _this.showPkr( e );
1856                        } );
1857
1858                this.inp.focus( this.hFocus =
1859                        function( e )
1860                        {
1861                            if( _this.lostFocus )
1862                                _this.showPkr( e );
1863                            _this.lostFocus = false;
1864                        } );
1865
1866                this.inp.keydown( this.hKeydown =
1867                        function( e )
1868                        {
1869                            _this.key( e );
1870                        } );
1871
1872                this.inp.keypress( this.hKeypress =
1873                        function( e )
1874                        {
1875                            if( $.browser.opera && _this.denyTab )
1876                                e.preventDefault();
1877                        } );
1878
1879                this.div.click(
1880                        function( e )
1881                        {
1882                            _this.lostFocus = false;
1883                            _this.inp.focus();
1884                        } );
1885
1886                $( window ).resize(
1887                        function( e )
1888                        {
1889                            _this.pos( e );
1890                        } );
1891
1892                if( __initialized )
1893                    this.onReady();
1894
1895            }, // initialize()
1896
1897
1898            //---------------------------------------------------------------------
1899            //  .ajax() notifies the server of a value change using Ajax.
1900            //---------------------------------------------------------------------
1901
1902            ajax: function()
1903            {
1904                if( this.ajaxOpts && ( this.time.getTime() != this.lastAjax.getTime() ) )
1905                {
1906                    try
1907                    {
1908                        var opts = jQuery.extend( {}, this.ajaxOpts );
1909                        if( typeof opts.data == 'object' )
1910                            opts.data[this.inp[0].name || this.inp[0].id] = this.inp.val();
1911                        else
1912                        {
1913                            var opt = (this.inp[0].name || this.inp[0].id) + '=' + encodeURI( this.inp.val() );
1914                            if( opts.data )
1915                                opts.data += '&' + opt;
1916                            else
1917                                opts.data = opt;
1918                        }
1919                        $.ajax( opts );
1920                        this.lastAjax = this.time;
1921                    }
1922                    catch( e )
1923                    {
1924                    }
1925                }
1926                return;
1927
1928            }, // .ajax()
1929
1930            //---------------------------------------------------------------------
1931            //  .askOffset() is called by this.newOffset() when the UTC offset or
1932            //  +- selection button is clicked.
1933            //---------------------------------------------------------------------
1934
1935            askOffset: function( event )
1936            {
1937                if( ! this.oDiv )
1938                {
1939                    this.makeCloak();
1940
1941                    this.oDiv = $( '<div class="AnyTime-win AnyTime-off-selector ui-widget ui-widget-content ui-corner-all" style="position:absolute" />' );
1942                    this.div.append( this.oDiv );
1943
1944                    // the order here (HDR,BODY,XDIV,TITLE) is important for width calcluation:
1945                    var title = $( '<h5 class="AnyTime-hdr AnyTime-hdr-off-selector ui-widget-header ui-corner-top" />' );
1946                    this.oDiv.append( title );
1947                    this.oBody = $( '<div class="AnyTime-body AnyTime-body-off-selector" style="overflow:auto;white-space:nowrap" />' );
1948                    this.oDiv.append( this.oBody );
1949                    var oBHS = this.oBody.AnyTime_height( true ); // body spacing
1950                    var oBWS = this.oBody.AnyTime_width( true );
1951                    var oTWS = title.AnyTime_width( true );
1952
1953                    var xDiv = $( '<div class="AnyTime-x-btn ui-state-default">' + this.lX + '</div>' );
1954                    title.append( xDiv );
1955                    xDiv.click( function( e )
1956                    {
1957                        _this.dismissODiv( e );
1958                    } );
1959                    title.append( this.lO );
1960                    if( __msie6 || __msie7 ) // IE bugs!
1961                        title.width( String( this.lO.length * 0.8 ) + "em" );
1962                    var oBW = title.AnyTime_width( true ) - oBWS; // initial body width
1963
1964                    var cont = $( '<ul class="AnyTime-off-off" />' );
1965                    var last = null;
1966                    this.oBody.append( cont );
1967                    var useSubIndex = (this.oConv.fmt.indexOf( '%@' ) >= 0);
1968                    var btnW = 0; // determine uniform button width
1969                    if( AnyTime.utcLabel )
1970                        for( var o = -720; o < 720; o++ )
1971                            if( AnyTime.utcLabel[o] )
1972                            {
1973                                this.oConv.setUtcFormatOffsetAlleged( o );
1974                                for( var i = 0; i < AnyTime.utcLabel[o].length; i++ )
1975                                {
1976                                    this.oConv.setUtcFormatOffsetSubIndex( i );
1977                                    last = this.btn( cont, this.oConv.format( this.time ), this.newOPos, ['off-off'], o );
1978                                    last[0].AnyTime_offMin = o;
1979                                    last[0].AnyTime_offSI = i;
1980                                    var w = last.width();
1981                                    if( w > btnW )
1982                                        btnW = w;
1983                                    if( ! useSubIndex )
1984                                        break; // for
1985                                }
1986                            }
1987
1988                    if( last )
1989                        last.addClass( 'AnyTime-off-off-last-btn' );
1990
1991                    // compute optimal width
1992
1993                    this.oBody.find( '.AnyTime-off-off-btn' ).width( btnW ); // set uniform button width
1994                    if( last )
1995                    {
1996                        var lW = last.AnyTime_width( true );
1997                        if( lW > oBW )
1998                            oBW = lW + 1; // expand body to hold buttons
1999                    }
2000                    this.oBody.width( oBW );
2001                    oBW = this.oBody.AnyTime_width( true );
2002                    this.oDiv.width( oBW );
2003                    if( __msie6 || __msie7 ) // IE bugs!
2004                        title.width( oBW - oTWS );
2005
2006                    // compute optimal height
2007
2008                    var oH = this.oDiv.AnyTime_height( true );
2009                    var oHmax = this.div.height() * 0.75;
2010                    if( oH > oHmax )
2011                    {
2012                        oH = oHmax;
2013                        this.oBody.height( oH - (title.AnyTime_height( true ) + oBHS) );
2014                        this.oBody.width( this.oBody.width() + 20 ); // add nominal px for scrollbar
2015                        this.oDiv.width( this.oDiv.width() + 20 );
2016                        if( __msie6 || __msie7 ) // IE bugs!
2017                            title.width( this.oBody.AnyTime_width( true ) - oTWS );
2018                    }
2019                    if( ! __msie7 ) // IE7 bug!
2020                        this.oDiv.height( String( oH ) + 'px' );
2021
2022                } // if ( ! this.oDiv )
2023                else
2024                {
2025                    this.cloak.show();
2026                    this.oDiv.show();
2027                }
2028                this.pos( event );
2029                this.updODiv( null );
2030
2031                var f = this.oDiv.find( '.AnyTime-off-off-btn.AnyTime-cur-btn:first' );
2032                if( ! f.length )
2033                    f = this.oDiv.find( '.AnyTime-off-off-btn:first' );
2034                this.setFocus( f );
2035
2036            }, // .askOffset()
2037
2038            //---------------------------------------------------------------------
2039            //  .askYear() is called by this.newYear() when the yPast or yAhead
2040            //  button is clicked.
2041            //---------------------------------------------------------------------
2042
2043            askYear: function( event )
2044            {
2045                if( ! this.yDiv )
2046                {
2047                    this.makeCloak();
2048
2049                    this.yDiv = $( '<div class="AnyTime-win AnyTime-yr-selector ui-widget ui-widget-content ui-corner-all" style="position:absolute" />' );
2050                    this.div.append( this.yDiv );
2051
2052                    var title = $( '<h5 class="AnyTime-hdr AnyTime-hdr-yr-selector ui-widget-header ui-corner-top" />' );
2053                    this.yDiv.append( title );
2054
2055                    var xDiv = $( '<div class="AnyTime-x-btn ui-state-default">' + this.lX + '</div>' );
2056                    title.append( xDiv );
2057                    xDiv.click( function( e )
2058                    {
2059                        _this.dismissYDiv( e );
2060                    } );
2061
2062                    title.append( this.lY );
2063
2064                    var yBody = $( '<div class="AnyTime-body AnyTime-body-yr-selector" />' );
2065                    var yW = yBody.AnyTime_width( true );
2066                    var yH = 0;
2067                    this.yDiv.append( yBody );
2068
2069                    cont = $( '<ul class="AnyTime-yr-mil" />' );
2070                    yBody.append( cont );
2071                    this.y0XXX = this.btn( cont, 0, this.newYPos, ['mil','mil0'], this.lY + ' ' + 0 + '000' );
2072                    for( i = 1; i < 10; i++ )
2073                        this.btn( cont, i, this.newYPos, ['mil','mil' + i], this.lY + ' ' + i + '000' );
2074                    yW += cont.AnyTime_width( true );
2075                    if( yH < cont.AnyTime_height( true ) )
2076                        yH = cont.AnyTime_height( true );
2077
2078                    cont = $( '<ul class="AnyTime-yr-cent" />' );
2079                    yBody.append( cont );
2080                    for( i = 0; i < 10; i++ )
2081                        this.btn( cont, i, this.newYPos, ['cent','cent' + i], this.lY + ' ' + i + '00' );
2082                    yW += cont.AnyTime_width( true );
2083                    if( yH < cont.AnyTime_height( true ) )
2084                        yH = cont.AnyTime_height( true );
2085
2086                    cont = $( '<ul class="AnyTime-yr-dec" />' );
2087                    yBody.append( cont );
2088                    for( i = 0; i < 10; i++ )
2089                        this.btn( cont, i, this.newYPos, ['dec','dec' + i], this.lY + ' ' + i + '0' );
2090                    yW += cont.AnyTime_width( true );
2091                    if( yH < cont.AnyTime_height( true ) )
2092                        yH = cont.AnyTime_height( true );
2093
2094                    cont = $( '<ul class="AnyTime-yr-yr" />' );
2095                    yBody.append( cont );
2096                    for( i = 0; i < 10; i++ )
2097                        this.btn( cont, i, this.newYPos, ['yr','yr' + i], this.lY + ' ' + i );
2098                    yW += cont.AnyTime_width( true );
2099                    if( yH < cont.AnyTime_height( true ) )
2100                        yH = cont.AnyTime_height( true );
2101
2102                    if( this.askEra )
2103                    {
2104                        cont = $( '<ul class="AnyTime-yr-era" />' );
2105                        yBody.append( cont );
2106
2107                        this.btn( cont, this.conv.eAbbr[0],
2108                                function( event )
2109                                {
2110                                    var t = new Date( this.time.getTime() );
2111                                    var year = t.getFullYear();
2112                                    if( year > 0 )
2113                                        t.setFullYear( 0 - year );
2114                                    this.set( t );
2115                                    this.updYDiv( $( event.target ) );
2116                                },
2117                                ['era','bce'], this.conv.eAbbr[0] );
2118
2119                        this.btn( cont, this.conv.eAbbr[1],
2120                                function( event )
2121                                {
2122                                    var t = new Date( this.time.getTime() );
2123                                    var year = t.getFullYear();
2124                                    if( year < 0 )
2125                                        t.setFullYear( 0 - year );
2126                                    this.set( t );
2127                                    this.updYDiv( $( event.target ) );
2128                                },
2129                                ['era','ce'], this.conv.eAbbr[1] );
2130
2131                        yW += cont.AnyTime_width( true );
2132                        if( yH < cont.AnyTime_height( true ) )
2133                            yH = cont.AnyTime_height( true );
2134
2135                    } // if ( this.askEra )
2136
2137                    if( $.browser.msie ) // IE8+ThemeUI bug!
2138                        yW += 1;
2139                    else if( $.browser.safari ) // Safari small-text bug!
2140                        yW += 2;
2141                    yH += yBody.AnyTime_height( true );
2142                    yBody.css( 'width', String( yW ) + 'px' );
2143                    if( ! __msie7 ) // IE7 bug!
2144                        yBody.css( 'height', String( yH ) + 'px' );
2145                    if( __msie6 || __msie7 ) // IE bugs!
2146                        title.width( yBody.outerWidth( true ) );
2147                    yH += title.AnyTime_height( true );
2148                    if( title.AnyTime_width( true ) > yW )
2149                        yW = title.AnyTime_width( true );
2150                    this.yDiv.css( 'width', String( yW ) + 'px' );
2151                    if( ! __msie7 ) // IE7 bug!
2152                        this.yDiv.css( 'height', String( yH ) + 'px' );
2153
2154                } // if ( ! this.yDiv )
2155                else
2156                {
2157                    this.cloak.show();
2158                    this.yDiv.show();
2159                }
2160                this.pos( event );
2161                this.updYDiv( null );
2162                this.setFocus( this.yDiv.find( '.AnyTime-yr-btn.AnyTime-cur-btn:first' ) );
2163
2164            }, // .askYear()
2165
2166            //---------------------------------------------------------------------
2167            //  .inpBlur() is called when a picker's input loses focus to dismiss
2168            //  the popup.  A 1/3 second delay is necessary to restore focus if
2169            //  the div is clicked (shorter delays don't always work!)  To prevent
2170            //  problems cause by scrollbar focus (except in FF), focus is
2171            //  force-restored if the offset div is visible.
2172            //---------------------------------------------------------------------
2173
2174            inpBlur: function( event )
2175            {
2176                if( this.oDiv && this.oDiv.is( ":visible" ) )
2177                {
2178                    _this.inp.focus();
2179                    return;
2180                }
2181                this.lostFocus = true;
2182                setTimeout(
2183                        function()
2184                        {
2185                            if( _this.lostFocus )
2186                            {
2187                                _this.div.find( '.AnyTime-focus-btn' ).removeClass( 'AnyTime-focus-btn ui-state-focus' );
2188                                if( _this.pop )
2189                                    _this.dismiss( event );
2190                                else
2191                                    _this.ajax();
2192                            }
2193                        }, 334 );
2194            },
2195
2196            //---------------------------------------------------------------------
2197            //  .btn() is called by AnyTime.picker() to create a <div> element
2198            //  containing an <a> element.  The elements are given appropriate
2199            //  classes based on the specified "classes" (an array of strings).
2200            //  The specified "text" and "title" are used for the <a> element.
2201            //  The "handler" is bound to click events for the <div>, which will
2202            //  catch bubbling clicks from the <a> as well.  The button is
2203            //  appended to the specified parent (jQuery), and the <div> jQuery
2204            //  is returned.
2205            //---------------------------------------------------------------------
2206
2207            btn: function( parent, text, handler, classes, title )
2208            {
2209                var tagName = ( (parent[0].nodeName.toLowerCase() == 'ul') ? 'li' : 'td');
2210                var div$ = '<' + tagName +
2211                        ' class="AnyTime-btn';
2212                for( var i = 0; i < classes.length; i++ )
2213                    div$ += ' AnyTime-' + classes[i] + '-btn';
2214                var div = $( div$ + ' ui-state-default">' + text + '</' + tagName + '>' );
2215                parent.append( div );
2216                div.AnyTime_title = title;
2217
2218                div.click(
2219                        function( e )
2220                        {
2221                            // bind the handler to the picker so "this" is correct
2222                            _this.tempFunc = handler;
2223                            _this.tempFunc( e );
2224                        } );
2225                div.dblclick(
2226                        function( e )
2227                        {
2228                            var elem = $( this );
2229                            if( elem.is( '.AnyTime-off-off-btn' ) )
2230                                _this.dismissODiv( e );
2231                            else if( elem.is( '.AnyTime-mil-btn' ) || elem.is( '.AnyTime-cent-btn' ) || elem.is( '.AnyTime-dec-btn' ) || elem.is( '.AnyTime-yr-btn' ) || elem.is( '.AnyTime-era-btn' ) )
2232                                _this.dismissYDiv( e );
2233                            else if( _this.pop )
2234                                _this.dismiss( e );
2235                        } );
2236                return div;
2237
2238            }, // .btn()
2239
2240            //---------------------------------------------------------------------
2241            //  .cleanup() destroys the DOM events and elements associated with
2242            //  the picker so it can be deleted.
2243            //---------------------------------------------------------------------
2244
2245            cleanup: function( event )
2246            {
2247                this.inp.unbind( 'blur', this.hBlur );
2248                this.inp.unbind( 'click', this.hClick );
2249                this.inp.unbind( 'focus', this.hFocus );
2250                this.inp.unbind( 'keydown', this.hKeydown );
2251                this.inp.unbind( 'keypress', this.hKeypress );
2252                this.div.remove();
2253            },
2254
2255            //---------------------------------------------------------------------
2256            //  .dismiss() dismisses a popup picker.
2257            //---------------------------------------------------------------------
2258
2259            dismiss: function( event )
2260            {
2261                this.ajax();
2262                this.div.hide();
2263                if( __iframe )
2264                    __iframe.hide();
2265                if( this.yDiv )
2266                    this.dismissYDiv();
2267                if( this.oDiv )
2268                    this.dismissODiv();
2269                this.lostFocus = true;
2270            },
2271
2272            //---------------------------------------------------------------------
2273            //  .dismissODiv() dismisses the UTC offset selector popover.
2274            //---------------------------------------------------------------------
2275
2276            dismissODiv: function( event )
2277            {
2278                this.oDiv.hide();
2279                this.cloak.hide();
2280                this.setFocus( this.oCur );
2281            },
2282
2283            //---------------------------------------------------------------------
2284            //  .dismissYDiv() dismisses the date selector popover.
2285            //---------------------------------------------------------------------
2286
2287            dismissYDiv: function( event )
2288            {
2289                this.yDiv.hide();
2290                this.cloak.hide();
2291                this.setFocus( this.yCur );
2292            },
2293
2294            //---------------------------------------------------------------------
2295            //  .setFocus() makes a specified psuedo-button appear to get focus.
2296            //---------------------------------------------------------------------
2297
2298            setFocus: function( btn )
2299            {
2300                if( ! btn.hasClass( 'AnyTime-focus-btn' ) )
2301                {
2302                    this.div.find( '.AnyTime-focus-btn' ).removeClass( 'AnyTime-focus-btn ui-state-focus' );
2303                    this.fBtn = btn;
2304                    btn.removeClass( 'ui-state-default ui-state-highlight' );
2305                    btn.addClass( 'AnyTime-focus-btn ui-state-default ui-state-highlight ui-state-focus' );
2306                }
2307                if( btn.hasClass( 'AnyTime-off-off-btn' ) )
2308                {
2309                    var oBT = this.oBody.offset().top;
2310                    var btnT = btn.offset().top;
2311                    var btnH = btn.AnyTime_height( true );
2312                    if( btnT - btnH < oBT ) // move a page up
2313                        this.oBody.scrollTop( btnT + this.oBody.scrollTop() - ( this.oBody.innerHeight() + oBT ) + ( btnH * 2 ) );
2314                    else if( btnT + btnH > oBT + this.oBody.innerHeight() ) // move a page down
2315                        this.oBody.scrollTop( ( btnT + this.oBody.scrollTop() ) - ( oBT + btnH ) );
2316                }
2317            },
2318
2319            //---------------------------------------------------------------------
2320            //  .key() is invoked when a user presses a key while the picker's
2321            //  input has focus.  A psuedo-button is considered "in focus" and an
2322            //  appropriate action is performed according to the WAI-ARIA Authoring
2323            //  Practices 1.0 for datepicker from
2324            //  www.w3.org/TR/2009/WD-wai-aria-practices-20091215/#datepicker:
2325            //
2326            //  * LeftArrow moves focus left, continued to previous week.
2327            //  * RightArrow moves focus right, continued to next week.
2328            //  * UpArrow moves focus to the same weekday in the previous week.
2329            //  * DownArrow moves focus to same weekday in the next week.
2330            //  * PageUp moves focus to same day in the previous month.
2331            //  * PageDown moves focus to same day in the next month.
2332            //  * Shift+Page Up moves focus to same day in the previous year.
2333            //  * Shift+Page Down moves focus to same day in the next year.
2334            //  * Home moves focus to the first day of the month.
2335            //  * End moves focus to the last day of the month.
2336            //  * Ctrl+Home moves focus to the first day of the year.
2337            //  * Ctrl+End moves focus to the last day of the year.
2338            //  * Esc closes a DatePicker that is opened as a Popup. 
2339            //
2340            //  The following actions (for multiple-date selection) are NOT
2341            //  supported:
2342            //  * Shift+Arrow performs continous selection. 
2343            //  * Ctrl+Space multiple selection of certain days.
2344            //
2345            //  The authoring practices do not specify behavior for a time picker,
2346            //  or for month-and-year pickers that do not have a day-of-the-month,
2347            //  but AnyTime.picker uses the following behavior to be as consistent
2348            //  as possible with the defined datepicker functionality:
2349            //  * LeftArrow moves focus left or up to previous value or field.
2350            //  * RightArrow moves focus right or down to next value or field.
2351            //  * UpArrow moves focus up or left to previous value or field.
2352            //  * DownArrow moves focus down or right to next value or field
2353            //  * PageUp moves focus to the current value in the previous units
2354            //    (for example, from ten-minutes to hours or one-minutes to
2355            //    ten-minutes or months to years).
2356            //  * PageDown moves focus to the current value in the next units
2357            //    (for example, from hours to ten-minutes or ten-minutes to
2358            //    one-minutes or years to months).
2359            //  * Home moves the focus to the first unit button.
2360            //  * End moves the focus to the last unit button.
2361            //
2362            //  In addition, Tab and Shift+Tab move between units (including to/
2363            //  from the Day-of-Month table) and also in/out of the picker.
2364            //
2365            //  Because AnyTime.picker sets a value as soon as the button receives
2366            //  focus, SPACE and ENTER are not needed (the WAI-ARIA guidelines use
2367            //  them to select a value.
2368            //---------------------------------------------------------------------
2369
2370            key: function( event )
2371            {
2372                var mo;
2373                var t = null;
2374                var elem = this.div.find( '.AnyTime-focus-btn' );
2375                var key = event.keyCode || event.which;
2376                this.denyTab = true;
2377
2378                if( key == 16 ) // Shift
2379                {
2380                }
2381                else if( ( key == 10 ) || ( key == 13 ) || ( key == 27 ) ) // Enter & Esc
2382                {
2383                    if( this.oDiv && this.oDiv.is( ':visible' ) )
2384                        this.dismissODiv( event );
2385                    else if( this.yDiv && this.yDiv.is( ':visible' ) )
2386                        this.dismissYDiv( event );
2387                    else if( this.pop )
2388                        this.dismiss( event );
2389                }
2390                else if( ( key == 33 ) || ( ( key == 9 ) && event.shiftKey ) ) // PageUp & Shift+Tab
2391                {
2392                    if( this.fBtn.hasClass( 'AnyTime-off-off-btn' ) )
2393                    {
2394                        if( key == 9 )
2395                            this.dismissODiv( event );
2396                    }
2397                    else if( this.fBtn.hasClass( 'AnyTime-mil-btn' ) )
2398                    {
2399                        if( key == 9 )
2400                            this.dismissYDiv( event );
2401                    }
2402                    else if( this.fBtn.hasClass( 'AnyTime-cent-btn' ) )
2403                        this.yDiv.find( '.AnyTime-mil-btn.AnyTime-cur-btn' ).triggerHandler( 'click' );
2404                    else if( this.fBtn.hasClass( 'AnyTime-dec-btn' ) )
2405                        this.yDiv.find( '.AnyTime-cent-btn.AnyTime-cur-btn' ).triggerHandler( 'click' );
2406                    else if( this.fBtn.hasClass( 'AnyTime-yr-btn' ) )
2407                        this.yDiv.find( '.AnyTime-dec-btn.AnyTime-cur-btn' ).triggerHandler( 'click' );
2408                    else if( this.fBtn.hasClass( 'AnyTime-era-btn' ) )
2409                        this.yDiv.find( '.AnyTime-yr-btn.AnyTime-cur-btn' ).triggerHandler( 'click' );
2410                    else if( this.fBtn.parents( '.AnyTime-yrs' ).length )
2411                    {
2412                        if( key == 9 )
2413                        {
2414                            this.denyTab = false;
2415                            return;
2416                        }
2417                    }
2418                    else if( this.fBtn.hasClass( 'AnyTime-mon-btn' ) )
2419                    {
2420                        if( this.dY )
2421                            this.yCur.triggerHandler( 'click' );
2422                        else if( key == 9 )
2423                        {
2424                            this.denyTab = false;
2425                            return;
2426                        }
2427                    }
2428                    else if( this.fBtn.hasClass( 'AnyTime-dom-btn' ) )
2429                    {
2430                        if( ( key == 9 ) && event.shiftKey ) // Shift+Tab
2431                        {
2432                            this.denyTab = false;
2433                            return;
2434                        }
2435                        else // PageUp
2436                        {
2437                            t = new Date( this.time.getTime() );
2438                            if( event.shiftKey )
2439                                t.setFullYear( t.getFullYear() - 1 );
2440                            else
2441                            {
2442                                mo = t.getMonth() - 1;
2443                                if( t.getDate() > __daysIn[mo] )
2444                                    t.setDate( __daysIn[mo] )
2445                                t.setMonth( mo );
2446                            }
2447                            this.keyDateChange( t );
2448                        }
2449                    }
2450                    else if( this.fBtn.hasClass( 'AnyTime-hr-btn' ) )
2451                    {
2452                        t = this.dDoM || this.dMo;
2453                        if( t )
2454                            t.AnyTime_clickCurrent();
2455                        else if( this.dY )
2456                            this.yCur.triggerHandler( 'click' );
2457                        else if( key == 9 )
2458                        {
2459                            this.denyTab = false;
2460                            return;
2461                        }
2462                    }
2463                    else if( this.fBtn.hasClass( 'AnyTime-min-ten-btn' ) )
2464                    {
2465                        t = this.dH || this.dDoM || this.dMo;
2466                        if( t )
2467                            t.AnyTime_clickCurrent();
2468                        else if( this.dY )
2469                            this.yCur.triggerHandler( 'click' );
2470                        else if( key == 9 )
2471                        {
2472                            this.denyTab = false;
2473                            return;
2474                        }
2475                    }
2476                    else if( this.fBtn.hasClass( 'AnyTime-min-one-btn' ) )
2477                        this.dM.AnyTime_clickCurrent();
2478                    else if( this.fBtn.hasClass( 'AnyTime-sec-ten-btn' ) )
2479                    {
2480                        if( this.dM )
2481                            t = this.dM.find( '.AnyTime-mins-ones' );
2482                        else
2483                            t = this.dH || this.dDoM || this.dMo;
2484                        if( t )
2485                            t.AnyTime_clickCurrent();
2486                        else if( this.dY )
2487                            this.yCur.triggerHandler( 'click' );
2488                        else if( key == 9 )
2489                        {
2490                            this.denyTab = false;
2491                            return;
2492                        }
2493                    }
2494                    else if( this.fBtn.hasClass( 'AnyTime-sec-one-btn' ) )
2495                        this.dS.AnyTime_clickCurrent();
2496                    else if( this.fBtn.hasClass( 'AnyTime-off-btn' ) )
2497                    {
2498                        if( this.dS )
2499                            t = this.dS.find( '.AnyTime-secs-ones' );
2500                        else if( this.dM )
2501                            t = this.dM.find( '.AnyTime-mins-ones' );
2502                        else
2503                            t = this.dH || this.dDoM || this.dMo;
2504                        if( t )
2505                            t.AnyTime_clickCurrent();
2506                        else if( this.dY )
2507                            this.yCur.triggerHandler( 'click' );
2508                        else if( key == 9 )
2509                        {
2510                            this.denyTab = false;
2511                            return;
2512                        }
2513                    }
2514                }
2515                else if( ( key == 34 ) || ( key == 9 ) ) // PageDown or Tab
2516                {
2517                    if( this.fBtn.hasClass( 'AnyTime-mil-btn' ) )
2518                        this.yDiv.find( '.AnyTime-cent-btn.AnyTime-cur-btn' ).triggerHandler( 'click' );
2519                    else if( this.fBtn.hasClass( 'AnyTime-cent-btn' ) )
2520                        this.yDiv.find( '.AnyTime-dec-btn.AnyTime-cur-btn' ).triggerHandler( 'click' );
2521                    else if( this.fBtn.hasClass( 'AnyTime-dec-btn' ) )
2522                        this.yDiv.find( '.AnyTime-yr-btn.AnyTime-cur-btn' ).triggerHandler( 'click' );
2523                    else if( this.fBtn.hasClass( 'AnyTime-yr-btn' ) )
2524                    {
2525                        t = this.yDiv.find( '.AnyTime-era-btn.AnyTime-cur-btn' );
2526                        if( t.length )
2527                            t.triggerHandler( 'click' );
2528                        else if( key == 9 )
2529                            this.dismissYDiv( event );
2530                    }
2531                    else if( this.fBtn.hasClass( 'AnyTime-era-btn' ) )
2532                    {
2533                        if( key == 9 )
2534                            this.dismissYDiv( event );
2535                    }
2536                    else if( this.fBtn.hasClass( 'AnyTime-off-off-btn' ) )
2537                    {
2538                        if( key == 9 )
2539                            this.dismissODiv( event );
2540                    }
2541                    else if( this.fBtn.parents( '.AnyTime-yrs' ).length )
2542                    {
2543                        t = this.dDoM || this.dMo || this.dH || this.dM || this.dS || this.dO;
2544                        if( t )
2545                            t.AnyTime_clickCurrent();
2546                        else if( key == 9 )
2547                        {
2548                            this.denyTab = false;
2549                            return;
2550                        }
2551                    }
2552                    else if( this.fBtn.hasClass( 'AnyTime-mon-btn' ) )
2553                    {
2554                        t = this.dDoM || this.dH || this.dM || this.dS || this.dO;
2555                        if( t )
2556                            t.AnyTime_clickCurrent();
2557                        else if( key == 9 )
2558                        {
2559                            this.denyTab = false;
2560                            return;
2561                        }
2562                    }
2563                    else if( this.fBtn.hasClass( 'AnyTime-dom-btn' ) )
2564                    {
2565                        if( key == 9 ) // Tab
2566                        {
2567                            t = this.dH || this.dM || this.dS || this.dO;
2568                            if( t )
2569                                t.AnyTime_clickCurrent();
2570                            else
2571                            {
2572                                this.denyTab = false;
2573                                return;
2574                            }
2575                        }
2576                        else // PageDown
2577                        {
2578                            t = new Date( this.time.getTime() );
2579                            if( event.shiftKey )
2580                                t.setFullYear( t.getFullYear() + 1 );
2581                            else
2582                            {
2583                                mo = t.getMonth() + 1;
2584                                if( t.getDate() > __daysIn[mo] )
2585                                    t.setDate( __daysIn[mo] )
2586                                t.setMonth( mo );
2587                            }
2588                            this.keyDateChange( t );
2589                        }
2590                    }
2591                    else if( this.fBtn.hasClass( 'AnyTime-hr-btn' ) )
2592                    {
2593                        t = this.dM || this.dS || this.dO;
2594                        if( t )
2595                            t.AnyTime_clickCurrent();
2596                        else if( key == 9 )
2597                        {
2598                            this.denyTab = false;
2599                            return;
2600                        }
2601                    }
2602                    else if( this.fBtn.hasClass( 'AnyTime-min-ten-btn' ) )
2603                        this.dM.find( '.AnyTime-mins-ones .AnyTime-cur-btn' ).triggerHandler( 'click' );
2604                    else if( this.fBtn.hasClass( 'AnyTime-min-one-btn' ) )
2605                    {
2606                        t = this.dS || this.dO;
2607                        if( t )
2608                            t.AnyTime_clickCurrent();
2609                        else if( key == 9 )
2610                        {
2611                            this.denyTab = false;
2612                            return;
2613                        }
2614                    }
2615                    else if( this.fBtn.hasClass( 'AnyTime-sec-ten-btn' ) )
2616                        this.dS.find( '.AnyTime-secs-ones .AnyTime-cur-btn' ).triggerHandler( 'click' );
2617                    else if( this.fBtn.hasClass( 'AnyTime-sec-one-btn' ) )
2618                    {
2619                        if( this.dO )
2620                            this.dO.AnyTime_clickCurrent();
2621                        else if( key == 9 )
2622                        {
2623                            this.denyTab = false;
2624                            return;
2625                        }
2626                    }
2627                    else if( this.fBtn.hasClass( 'AnyTime-off-btn' ) )
2628                    {
2629                        if( key == 9 )
2630                        {
2631                            this.denyTab = false;
2632                            return;
2633                        }
2634                    }
2635                }
2636                else if( key == 35 ) // END
2637                {
2638                    if( this.fBtn.hasClass( 'AnyTime-mil-btn' ) || this.fBtn.hasClass( 'AnyTime-cent-btn' ) ||
2639                            this.fBtn.hasClass( 'AnyTime-dec-btn' ) || this.fBtn.hasClass( 'AnyTime-yr-btn' ) ||
2640                            this.fBtn.hasClass( 'AnyTime-era-btn' ) )
2641                    {
2642                        t = this.yDiv.find( '.AnyTime-ce-btn' );
2643                        if( ! t.length )
2644                            t = this.yDiv.find( '.AnyTime-yr9-btn' );
2645                        t.triggerHandler( 'click' );
2646                    }
2647                    else if( this.fBtn.hasClass( 'AnyTime-dom-btn' ) )
2648                    {
2649                        t = new Date( this.time.getTime() );
2650                        t.setDate( 1 );
2651                        t.setMonth( t.getMonth() + 1 );
2652                        t.setDate( t.getDate() - 1 );
2653                        if( event.ctrlKey )
2654                            t.setMonth( 11 );
2655                        this.keyDateChange( t );
2656                    }
2657                    else if( this.dS )
2658                        this.dS.find( '.AnyTime-sec9-btn' ).triggerHandler( 'click' );
2659                    else if( this.dM )
2660                        this.dM.find( '.AnyTime-min9-btn' ).triggerHandler( 'click' );
2661                    else if( this.dH )
2662                        this.dH.find( '.AnyTime-hr23-btn' ).triggerHandler( 'click' );
2663                    else if( this.dDoM )
2664                        this.dDoM.find( '.AnyTime-dom-btn-filled:last' ).triggerHandler( 'click' );
2665                    else if( this.dMo )
2666                        this.dMo.find( '.AnyTime-mon12-btn' ).triggerHandler( 'click' );
2667                    else if( this.dY )
2668                        this.yAhead.triggerHandler( 'click' );
2669                }
2670                else if( key == 36 ) // HOME
2671                {
2672                    if( this.fBtn.hasClass( 'AnyTime-mil-btn' ) || this.fBtn.hasClass( 'AnyTime-cent-btn' ) ||
2673                            this.fBtn.hasClass( 'AnyTime-dec-btn' ) || this.fBtn.hasClass( 'AnyTime-yr-btn' ) ||
2674                            this.fBtn.hasClass( 'AnyTime-era-btn' ) )
2675                    {
2676                        this.yDiv.find( '.AnyTime-mil0-btn' ).triggerHandler( 'click' );
2677                    }
2678                    else if( this.fBtn.hasClass( 'AnyTime-dom-btn' ) )
2679                    {
2680                        t = new Date( this.time.getTime() );
2681                        t.setDate( 1 );
2682                        if( event.ctrlKey )
2683                            t.setMonth( 0 );
2684                        this.keyDateChange( t );
2685                    }
2686                    else if( this.dY )
2687                        this.yCur.triggerHandler( 'click' );
2688                    else if( this.dMo )
2689                        this.dMo.find( '.AnyTime-mon1-btn' ).triggerHandler( 'click' );
2690                    else if( this.dDoM )
2691                        this.dDoM.find( '.AnyTime-dom-btn-filled:first' ).triggerHandler( 'click' );
2692                    else if( this.dH )
2693                        this.dH.find( '.AnyTime-hr0-btn' ).triggerHandler( 'click' );
2694                    else if( this.dM )
2695                        this.dM.find( '.AnyTime-min00-btn' ).triggerHandler( 'click' );
2696                    else if( this.dS )
2697                        this.dS.find( '.AnyTime-sec00-btn' ).triggerHandler( 'click' );
2698                }
2699                else if( key == 37 ) // left arrow
2700                {
2701                    if( this.fBtn.hasClass( 'AnyTime-dom-btn' ) )
2702                        this.keyDateChange( new Date( this.time.getTime() - __oneDay ) );
2703                    else
2704                        this.keyBack();
2705                }
2706                else if( key == 38 ) // up arrow
2707                {
2708                    if( this.fBtn.hasClass( 'AnyTime-dom-btn' ) )
2709                        this.keyDateChange( new Date( this.time.getTime() - (7 * __oneDay) ) );
2710                    else
2711                        this.keyBack();
2712                }
2713                else if( key == 39 ) // right arrow
2714                {
2715                    if( this.fBtn.hasClass( 'AnyTime-dom-btn' ) )
2716                        this.keyDateChange( new Date( this.time.getTime() + __oneDay ) );
2717                    else
2718                        this.keyAhead();
2719                }
2720                else if( key == 40 ) // down arrow
2721                {
2722                    if( this.fBtn.hasClass( 'AnyTime-dom-btn' ) )
2723                        this.keyDateChange( new Date( this.time.getTime() + (7 * __oneDay) ) );
2724                    else
2725                        this.keyAhead();
2726                }
2727                else if( ( ( key == 86 ) || ( key == 118 ) ) && event.ctrlKey )
2728                {
2729                    this.inp.val( "" ).change();
2730                    var _this = this;
2731                    setTimeout( function()
2732                    {
2733                        _this.showPkr( null );
2734                    }, 100 );
2735                    return;
2736                }
2737                else
2738                    this.showPkr( null );
2739
2740                event.preventDefault();
2741
2742            }, // .key()
2743
2744            //---------------------------------------------------------------------
2745            //  .keyAhead() is called by #key when a user presses the right or
2746            //  down arrow.  It moves to the next appropriate button.
2747            //---------------------------------------------------------------------
2748
2749            keyAhead: function()
2750            {
2751                if( this.fBtn.hasClass( 'AnyTime-mil9-btn' ) )
2752                    this.yDiv.find( '.AnyTime-cent0-btn' ).triggerHandler( 'click' );
2753                else if( this.fBtn.hasClass( 'AnyTime-cent9-btn' ) )
2754                    this.yDiv.find( '.AnyTime-dec0-btn' ).triggerHandler( 'click' );
2755                else if( this.fBtn.hasClass( 'AnyTime-dec9-btn' ) )
2756                    this.yDiv.find( '.AnyTime-yr0-btn' ).triggerHandler( 'click' );
2757                else if( this.fBtn.hasClass( 'AnyTime-yr9-btn' ) )
2758                    this.yDiv.find( '.AnyTime-bce-btn' ).triggerHandler( 'click' );
2759                else if( this.fBtn.hasClass( 'AnyTime-sec9-btn' ) )
2760                {
2761                }
2762                else if( this.fBtn.hasClass( 'AnyTime-sec50-btn' ) )
2763                    this.dS.find( '.AnyTime-sec0-btn' ).triggerHandler( 'click' );
2764                else if( this.fBtn.hasClass( 'AnyTime-min9-btn' ) )
2765                {
2766                    if( this.dS )
2767                        this.dS.find( '.AnyTime-sec00-btn' ).triggerHandler( 'click' );
2768                }
2769                else if( this.fBtn.hasClass( 'AnyTime-min50-btn' ) )
2770                    this.dM.find( '.AnyTime-min0-btn' ).triggerHandler( 'click' );
2771                else if( this.fBtn.hasClass( 'AnyTime-hr23-btn' ) )
2772                {
2773                    if( this.dM )
2774                        this.dM.find( '.AnyTime-min00-btn' ).triggerHandler( 'click' );
2775                    else if( this.dS )
2776                        this.dS.find( '.AnyTime-sec00-btn' ).triggerHandler( 'click' );
2777                }
2778                else if( this.fBtn.hasClass( 'AnyTime-hr11-btn' ) )
2779                    this.dH.find( '.AnyTime-hr12-btn' ).triggerHandler( 'click' );
2780                else if( this.fBtn.hasClass( 'AnyTime-mon12-btn' ) )
2781                {
2782                    if( this.dDoM )
2783                        this.dDoM.AnyTime_clickCurrent();
2784                    else if( this.dH )
2785                        this.dH.find( '.AnyTime-hr0-btn' ).triggerHandler( 'click' );
2786                    else if( this.dM )
2787                        this.dM.find( '.AnyTime-min00-btn' ).triggerHandler( 'click' );
2788                    else if( this.dS )
2789                        this.dS.find( '.AnyTime-sec00-btn' ).triggerHandler( 'click' );
2790                }
2791                else if( this.fBtn.hasClass( 'AnyTime-yrs-ahead-btn' ) )
2792                {
2793                    if( this.dMo )
2794                        this.dMo.find( '.AnyTime-mon1-btn' ).triggerHandler( 'click' );
2795                    else if( this.dH )
2796                        this.dH.find( '.AnyTime-hr0-btn' ).triggerHandler( 'click' );
2797                    else if( this.dM )
2798                        this.dM.find( '.AnyTime-min00-btn' ).triggerHandler( 'click' );
2799                    else if( this.dS )
2800                        this.dS.find( '.AnyTime-sec00-btn' ).triggerHandler( 'click' );
2801                }
2802                else if( this.fBtn.hasClass( 'AnyTime-yr-cur-btn' ) )
2803                    this.yNext.triggerHandler( 'click' );
2804                else
2805                    this.fBtn.next().triggerHandler( 'click' );
2806
2807            }, // .keyAhead()
2808
2809
2810            //---------------------------------------------------------------------
2811            //  .keyBack() is called by #key when a user presses the left or
2812            //  up arrow. It moves to the previous appropriate button.
2813            //---------------------------------------------------------------------
2814
2815            keyBack: function()
2816            {
2817                if( this.fBtn.hasClass( 'AnyTime-cent0-btn' ) )
2818                    this.yDiv.find( '.AnyTime-mil9-btn' ).triggerHandler( 'click' );
2819                else if( this.fBtn.hasClass( 'AnyTime-dec0-btn' ) )
2820                    this.yDiv.find( '.AnyTime-cent9-btn' ).triggerHandler( 'click' );
2821                else if( this.fBtn.hasClass( 'AnyTime-yr0-btn' ) )
2822                    this.yDiv.find( '.AnyTime-dec9-btn' ).triggerHandler( 'click' );
2823                else if( this.fBtn.hasClass( 'AnyTime-bce-btn' ) )
2824                    this.yDiv.find( '.AnyTime-yr9-btn' ).triggerHandler( 'click' );
2825                else if( this.fBtn.hasClass( 'AnyTime-yr-cur-btn' ) )
2826                    this.yPrior.triggerHandler( 'click' );
2827                else if( this.fBtn.hasClass( 'AnyTime-mon1-btn' ) )
2828                {
2829                    if( this.dY )
2830                        this.yCur.triggerHandler( 'click' );
2831                }
2832                else if( this.fBtn.hasClass( 'AnyTime-hr0-btn' ) )
2833                {
2834                    if( this.dDoM )
2835                        this.dDoM.AnyTime_clickCurrent();
2836                    else if( this.dMo )
2837                        this.dMo.find( '.AnyTime-mon12-btn' ).triggerHandler( 'click' );
2838                    else if( this.dY )
2839                        this.yNext.triggerHandler( 'click' );
2840                }
2841                else if( this.fBtn.hasClass( 'AnyTime-hr12-btn' ) )
2842                    this.dH.find( '.AnyTime-hr11-btn' ).triggerHandler( 'click' );
2843                else if( this.fBtn.hasClass( 'AnyTime-min00-btn' ) )
2844                {
2845                    if( this.dH )
2846                        this.dH.find( '.AnyTime-hr23-btn' ).triggerHandler( 'click' );
2847                    else if( this.dDoM )
2848                        this.dDoM.AnyTime_clickCurrent();
2849                    else if( this.dMo )
2850                        this.dMo.find( '.AnyTime-mon12-btn' ).triggerHandler( 'click' );
2851                    else if( this.dY )
2852                        this.yNext.triggerHandler( 'click' );
2853                }
2854                else if( this.fBtn.hasClass( 'AnyTime-min0-btn' ) )
2855                    this.dM.find( '.AnyTime-min50-btn' ).triggerHandler( 'click' );
2856                else if( this.fBtn.hasClass( 'AnyTime-sec00-btn' ) )
2857                {
2858                    if( this.dM )
2859                        this.dM.find( '.AnyTime-min9-btn' ).triggerHandler( 'click' );
2860                    else if( this.dH )
2861                        this.dH.find( '.AnyTime-hr23-btn' ).triggerHandler( 'click' );
2862                    else if( this.dDoM )
2863                        this.dDoM.AnyTime_clickCurrent();
2864                    else if( this.dMo )
2865                        this.dMo.find( '.AnyTime-mon12-btn' ).triggerHandler( 'click' );
2866                    else if( this.dY )
2867                        this.yNext.triggerHandler( 'click' );
2868                }
2869                else if( this.fBtn.hasClass( 'AnyTime-sec0-btn' ) )
2870                    this.dS.find( '.AnyTime-sec50-btn' ).triggerHandler( 'click' );
2871                else
2872                    this.fBtn.prev().triggerHandler( 'click' );
2873
2874            }, // .keyBack()
2875
2876            //---------------------------------------------------------------------
2877            //  .keyDateChange() is called by #key when an direction key
2878            //  (arrows/page/etc) is pressed while the Day-of-Month calendar has
2879            //  focus. The current day is adjusted accordingly.
2880            //---------------------------------------------------------------------
2881
2882            keyDateChange: function( newDate )
2883            {
2884                if( this.fBtn.hasClass( 'AnyTime-dom-btn' ) )
2885                {
2886                    this.set( newDate );
2887                    this.upd( null );
2888                    this.setFocus( this.dDoM.find( '.AnyTime-cur-btn' ) );
2889                }
2890            },
2891
2892            //---------------------------------------------------------------------
2893            //  .makeCloak() is called by .askOffset() and .askYear() to create
2894            //  a cloak div.
2895            //---------------------------------------------------------------------
2896
2897            makeCloak: function()
2898            {
2899                if( ! this.cloak )
2900                {
2901                    this.cloak = $( '<div class="AnyTime-cloak" style="position:absolute" />' );
2902                    this.div.append( this.cloak );
2903                    this.cloak.click(
2904                            function( e )
2905                            {
2906                                if( _this.oDiv && _this.oDiv.is( ":visible" ) )
2907                                    _this.dismissODiv( e );
2908                                else
2909                                    _this.dismissYDiv( e );
2910                            } );
2911                }
2912                else
2913                    this.cloak.show();
2914            },
2915
2916            //---------------------------------------------------------------------
2917            //  .newHour() is called when a user clicks an hour value.
2918            //  It changes the date and updates the text field.
2919            //---------------------------------------------------------------------
2920
2921            newHour: function( event )
2922            {
2923                var h;
2924                var t;
2925                var elem = $( event.target );
2926                if( elem.hasClass( "AnyTime-out-btn" ) )
2927                    return;
2928                if( ! this.twelveHr )
2929                    h = Number( elem.text() );
2930                else
2931                {
2932                    var str = elem.text();
2933                    t = str.indexOf( 'a' );
2934                    if( t < 0 )
2935                    {
2936                        t = Number( str.substr( 0, str.indexOf( 'p' ) ) );
2937                        h = ( (t == 12) ? 12 : (t + 12) );
2938                    }
2939                    else
2940                    {
2941                        t = Number( str.substr( 0, t ) );
2942                        h = ( (t == 12) ? 0 : t );
2943                    }
2944                }
2945                t = new Date( this.time.getTime() );
2946                t.setHours( h );
2947                this.set( t );
2948                this.upd( elem );
2949
2950            }, // .newHour()
2951
2952            //---------------------------------------------------------------------
2953            //  .newOffset() is called when a user clicks the UTC offset (timezone)
2954            //  (or +/- button) to shift the year.  It changes the date and updates
2955            //  the text field.
2956            //---------------------------------------------------------------------
2957
2958            newOffset: function( event )
2959            {
2960                if( event.target == this.oSel[0] )
2961                    this.askOffset( event );
2962                else
2963                {
2964                    this.upd( this.oCur );
2965                }
2966            },
2967
2968            //---------------------------------------------------------------------
2969            //  .newOPos() is called internally whenever a user clicks an offset
2970            //  selection value.  It changes the date and updates the text field.
2971            //---------------------------------------------------------------------
2972
2973            newOPos: function( event )
2974            {
2975                var elem = $( event.target );
2976                this.offMin = elem[0].AnyTime_offMin;
2977                this.offSI = elem[0].AnyTime_offSI;
2978                var t = new Date( this.time.getTime() );
2979                this.set( t );
2980                this.updODiv( elem );
2981
2982            }, // .newOPos()
2983
2984            //---------------------------------------------------------------------
2985            //  .newYear() is called when a user clicks a year (or one of the
2986            //  "arrows") to shift the year.  It changes the date and updates the
2987            //  text field.
2988            //---------------------------------------------------------------------
2989
2990            newYear: function( event )
2991            {
2992                var elem = $( event.target );
2993                if( elem.hasClass( "AnyTime-out-btn" ) )
2994                    return;
2995                var txt = elem.text();
2996                if( ( txt == '<' ) || ( txt == '&lt;' ) )
2997                    this.askYear( event );
2998                else if( ( txt == '>' ) || ( txt == '&gt;' ) )
2999                    this.askYear( event );
3000                else
3001                {
3002                    var t = new Date( this.time.getTime() );
3003                    t.setFullYear( Number( txt ) );
3004                    this.set( t );
3005                    this.upd( this.yCur );
3006                }
3007            },
3008
3009            //---------------------------------------------------------------------
3010            //  .newYPos() is called internally whenever a user clicks a year
3011            //  selection value.  It changes the date and updates the text field.
3012            //---------------------------------------------------------------------
3013
3014            newYPos: function( event )
3015            {
3016                var elem = $( event.target );
3017                if( elem.hasClass( "AnyTime-out-btn" ) )
3018                    return;
3019
3020                var era = 1;
3021                var year = this.time.getFullYear();
3022                if( year < 0 )
3023                {
3024                    era = (-1);
3025                    year = 0 - year;
3026                }
3027                year = AnyTime.pad( year, 4 );
3028                if( elem.hasClass( 'AnyTime-mil-btn' ) )
3029                    year = elem.html() + year.substring( 1, 4 );
3030                else if( elem.hasClass( 'AnyTime-cent-btn' ) )
3031                    year = year.substring( 0, 1 ) + elem.html() + year.substring( 2, 4 );
3032                else if( elem.hasClass( 'AnyTime-dec-btn' ) )
3033                    year = year.substring( 0, 2 ) + elem.html() + year.substring( 3, 4 );
3034                else
3035                    year = year.substring( 0, 3 ) + elem.html();
3036                if( year == '0000' )
3037                    year = 1;
3038                var t = new Date( this.time.getTime() );
3039                t.setFullYear( era * year );
3040                this.set( t );
3041                this.updYDiv( elem );
3042
3043            }, // .newYPos()
3044
3045            //---------------------------------------------------------------------
3046            //  .onReady() initializes the picker after the page has loaded and,
3047            //  if IE6, after the iframe has been created.
3048            //---------------------------------------------------------------------
3049
3050            onReady: function()
3051            {
3052                this.lostFocus = true;
3053                if( ! this.pop )
3054                    this.upd( null );
3055                else
3056                {
3057                    if( this.div.parent() != document.body )
3058                        this.div.appendTo( document.body );
3059                }
3060            },
3061
3062            //---------------------------------------------------------------------
3063            //  .pos() positions the picker, such as when it is displayed or
3064            //  when the window is resized.
3065            //---------------------------------------------------------------------
3066
3067            pos: function( event ) // note: event is ignored but this is a handler
3068            {
3069                if( this.pop )
3070                {
3071                    var off = this.inp.offset();
3072                    var bodyWidth = $( document.body ).outerWidth( true );
3073                    var pickerWidth = this.div.outerWidth( true );
3074                    var left = off.left;
3075                    if( left + pickerWidth > bodyWidth - 20 )
3076                        left = bodyWidth - ( pickerWidth + 20 );
3077                    var top = off.top - this.div.outerHeight( true );
3078                    if( top < 0 )
3079                        top = off.top + this.inp.outerHeight( true );
3080                    this.div.css( { top: String( top ) + 'px', left: String( left < 0 ? 0 : left ) + 'px' } );
3081                }
3082
3083                var wOff = this.div.offset();
3084
3085                if( this.oDiv && this.oDiv.is( ":visible" ) )
3086                {
3087                    var oOff = this.oLab.offset();
3088                    if( this.div.css( 'position' ) == 'absolute' )
3089                    {
3090                        oOff.top -= wOff.top;
3091                        oOff.left = oOff.left - wOff.left;
3092                        wOff = { top: 0, left: 0 };
3093                    }
3094                    var oW = this.oDiv.AnyTime_width( true );
3095                    var wW = this.div.AnyTime_width( true );
3096                    if( oOff.left + oW > wOff.left + wW )
3097                    {
3098                        oOff.left = (wOff.left + wW) - oW;
3099                        if( oOff.left < 2 )
3100                            oOff.left = 2;
3101                    }
3102
3103                    var oH = this.oDiv.AnyTime_height( true );
3104                    var wH = this.div.AnyTime_height( true );
3105                    oOff.top += this.oLab.AnyTime_height( true );
3106                    if( oOff.top + oH > wOff.top + wH )
3107                        oOff.top = oOff.top - oH;
3108                    if( oOff.top < wOff.top )
3109                        oOff.top = wOff.top;
3110
3111                    this.oDiv.css( { top: oOff.top + 'px', left: oOff.left + 'px' } );
3112                }
3113
3114                else if( this.yDiv && this.yDiv.is( ":visible" ) )
3115                {
3116                    var yOff = this.yLab.offset();
3117                    if( this.div.css( 'position' ) == 'absolute' )
3118                    {
3119                        yOff.top -= wOff.top;
3120                        yOff.left = yOff.left - wOff.left;
3121                        wOff = { top: 0, left: 0 };
3122                    }
3123                    yOff.left += ( (this.yLab.outerWidth( true ) - this.yDiv.outerWidth( true )) / 2 );
3124                    this.yDiv.css( { top: yOff.top + 'px', left: yOff.left + 'px' } );
3125                }
3126
3127                if( this.cloak )
3128                    this.cloak.css( {
3129                        top: wOff.top + 'px',
3130                        left: wOff.left + 'px',
3131                        height: String( this.div.outerHeight( true ) - 2 ) + 'px',
3132                        width: String( this.div.outerWidth( !$.browser.safari ) - 2 ) + 'px'
3133                    } );
3134
3135            }, // .pos()
3136
3137            //---------------------------------------------------------------------
3138            //  .set() changes the current time.  It returns true if the new
3139            //  time is within the allowed range (if any).
3140            //---------------------------------------------------------------------
3141
3142            set: function( newTime )
3143            {
3144                var t = newTime.getTime();
3145                if( this.earliest && ( t < this.earliest ) )
3146                    this.time = new Date( this.earliest );
3147                else if( this.latest && ( t > this.latest ) )
3148                    this.time = new Date( this.latest );
3149                else
3150                    this.time = newTime;
3151            },
3152
3153            //---------------------------------------------------------------------
3154            //  .showPkr() displays the picker and sets the focus psuedo-
3155            //  element. The current value in the input field is used to initialize
3156            //  the picker.
3157            //---------------------------------------------------------------------
3158
3159            showPkr: function( event )
3160            {
3161                try
3162                {
3163                    this.time = this.conv.parse( this.inp.val() );
3164                    this.offMin = this.conv.getUtcParseOffsetCaptured();
3165                    this.offSI = this.conv.getUtcParseOffsetSubIndex();
3166                }
3167                catch ( e )
3168                {
3169                    this.time = new Date();
3170                }
3171                this.set( this.time );
3172                this.upd( null );
3173
3174                fBtn = null;
3175                var cb = '.AnyTime-cur-btn:first';
3176                if( this.dDoM )
3177                    fBtn = this.dDoM.find( cb );
3178                else if( this.yCur )
3179                    fBtn = this.yCur;
3180                else if( this.dMo )
3181                    fBtn = this.dMo.find( cb );
3182                else if( this.dH )
3183                    fBtn = this.dH.find( cb );
3184                else if( this.dM )
3185                    fBtn = this.dM.find( cb );
3186                else if( this.dS )
3187                    fBtn = this.dS.find( cb );
3188
3189                this.setFocus( fBtn );
3190                this.pos( event );
3191
3192                //  IE6 doesn't float popups over <select> elements unless an
3193                //      <iframe> is inserted between them!  So after the picker is
3194                //      made visible, move the <iframe> behind it.
3195
3196                if( this.pop && __iframe )
3197                    setTimeout(
3198                            function()
3199                            {
3200                                var pos = _this.div.offset();
3201                                __iframe.css( {
3202                                    height: String( _this.div.outerHeight( true ) ) + 'px',
3203                                    left: String( pos.left ) + 'px',
3204                                    position: 'absolute',
3205                                    top: String( pos.top ) + 'px',
3206                                    width: String( _this.div.outerWidth( true ) ) + 'px'
3207                                } );
3208                                __iframe.show();
3209                            }, 300 );
3210
3211            }, // .showPkr()
3212
3213            /** VMIPSL **/
3214            updateEarliest: function()
3215            {
3216                if( !this.idToUpdateEarliest || !$( document.getElementById( this.idToUpdateEarliest ) )[0] || !$( document.getElementById( this.idToUpdateEarliest ) )[0].value )
3217                    return;
3218
3219                this.earliest = this.conv.parse( $( document.getElementById( this.idToUpdateEarliest ) )[0].value ).getTime();
3220            },
3221
3222            //---------------------------------------------------------------------
3223            //  .upd() updates the picker's appearance.  It is called after
3224            //  most events to make the picker reflect the currently-selected
3225            //  values. fBtn is the psuedo-button to be given focus.
3226            //---------------------------------------------------------------------
3227
3228            upd: function( fBtn )
3229            {
3230                /** VMIPSL **/
3231                this.updateEarliest();
3232
3233                var cmpLo = new Date( this.time.getTime() );
3234                cmpLo.setMonth( 0, 1 );
3235                cmpLo.setHours( 0, 0, 0, 0 );
3236                var cmpHi = new Date( this.time.getTime() );
3237                cmpHi.setMonth( 11, 31 );
3238                cmpHi.setHours( 23, 59, 59, 999 );
3239
3240                //  Update year.
3241
3242                var current = this.time.getFullYear();
3243                if( this.earliest && this.yPast )
3244                {
3245                    cmpHi.setYear( current - 2 );
3246                    if( cmpHi.getTime() < this.earliest )
3247                        this.yPast.addClass( 'AnyTime-out-btn ui-state-disabled' );
3248                    else
3249                        this.yPast.removeClass( 'AnyTime-out-btn ui-state-disabled' );
3250                }
3251                if( this.yPrior )
3252                {
3253                    this.yPrior.text( AnyTime.pad( (current == 1) ? (-1) : (current - 1), 4 ) );
3254                    if( this.earliest )
3255                    {
3256                        cmpHi.setYear( current - 1 );
3257                        if( cmpHi.getTime() < this.earliest )
3258                            this.yPrior.addClass( 'AnyTime-out-btn ui-state-disabled' );
3259                        else
3260                            this.yPrior.removeClass( 'AnyTime-out-btn ui-state-disabled' );
3261                    }
3262                }
3263                if( this.yCur )
3264                    this.yCur.text( AnyTime.pad( current, 4 ) );
3265                if( this.yNext )
3266                {
3267                    this.yNext.text( AnyTime.pad( (current == -1) ? 1 : (current + 1), 4 ) );
3268                    if( this.latest )
3269                    {
3270                        cmpLo.setYear( current + 1 );
3271                        if( cmpLo.getTime() > this.latest )
3272                            this.yNext.addClass( 'AnyTime-out-btn ui-state-disabled' );
3273                        else
3274                            this.yNext.removeClass( 'AnyTime-out-btn ui-state-disabled' );
3275                    }
3276                }
3277                if( this.latest && this.yAhead )
3278                {
3279                    cmpLo.setYear( current + 2 );
3280                    if( cmpLo.getTime() > this.latest )
3281                        this.yAhead.addClass( 'AnyTime-out-btn ui-state-disabled' );
3282                    else
3283                        this.yAhead.removeClass( 'AnyTime-out-btn ui-state-disabled' );
3284                }
3285
3286                //  Update month.
3287
3288                cmpLo.setFullYear( this.time.getFullYear() );
3289                cmpHi.setFullYear( this.time.getFullYear() );
3290                var i = 0;
3291                current = this.time.getMonth();
3292                $( '#' + this.id + ' .AnyTime-mon-btn' ).each(
3293                        function()
3294                        {
3295                            cmpLo.setMonth( i );
3296                            cmpHi.setDate( 1 );
3297                            cmpHi.setMonth( i + 1 );
3298                            cmpHi.setDate( 0 );
3299                            $( this ).AnyTime_current( i == current,
3300                                    ((!_this.earliest) || (cmpHi.getTime() >= _this.earliest)) &&
3301                                            ((!_this.latest) || (cmpLo.getTime() <= _this.latest)) );
3302                            i++;
3303                        } );
3304
3305                //  Update days.
3306
3307                cmpLo.setFullYear( this.time.getFullYear() );
3308                cmpHi.setFullYear( this.time.getFullYear() );
3309                cmpLo.setMonth( this.time.getMonth() );
3310                cmpHi.setMonth( this.time.getMonth(), 1 );
3311                current = this.time.getDate();
3312                var currentMonth = this.time.getMonth();
3313                var dow1 = cmpLo.getDay();
3314                if( this.fDOW > dow1 )
3315                    dow1 += 7;
3316                var wom = 0, dow = 0;
3317                $( '#' + this.id + ' .AnyTime-wk' ).each(
3318                        function()
3319                        {
3320                            dow = _this.fDOW;
3321                            $( this ).children().each(
3322                                    function()
3323                                    {
3324                                        if( dow - _this.fDOW < 7 )
3325                                        {
3326                                            var td = $( this );
3327                                            if( ((wom == 0) && (dow < dow1)) || (cmpLo.getMonth() != currentMonth) )
3328                                            {
3329                                                td.html( '&#160;' );
3330                                                td.removeClass( 'AnyTime-dom-btn-filled AnyTime-cur-btn ui-state-default ui-state-highlight' );
3331                                                td.addClass( 'AnyTime-dom-btn-empty' );
3332                                                if( wom ) // not first week
3333                                                {
3334                                                    if( ( cmpLo.getDate() == 1 ) && ( dow != 0 ) )
3335                                                        td.addClass( 'AnyTime-dom-btn-empty-after-filled' );
3336                                                    else
3337                                                        td.removeClass( 'AnyTime-dom-btn-empty-after-filled' );
3338                                                    if( cmpLo.getDate() <= 7 )
3339                                                        td.addClass( 'AnyTime-dom-btn-empty-below-filled' );
3340                                                    else
3341                                                        td.removeClass( 'AnyTime-dom-btn-empty-below-filled' );
3342                                                    cmpLo.setDate( cmpLo.getDate() + 1 );
3343                                                    cmpHi.setDate( cmpHi.getDate() + 1 );
3344                                                }
3345                                                else // first week
3346                                                {
3347                                                    td.addClass( 'AnyTime-dom-btn-empty-above-filled' );
3348                                                    if( dow == dow1 - 1 )
3349                                                        td.addClass( 'AnyTime-dom-btn-empty-before-filled' );
3350                                                    else
3351                                                        td.removeClass( 'AnyTime-dom-btn-empty-before-filled' );
3352                                                }
3353                                                td.addClass( 'ui-state-default ui-state-disabled' );
3354                                            }
3355                                            else
3356                                            {
3357                                                i = cmpLo.getDate();
3358                                                td.text( i );
3359                                                td.removeClass( 'AnyTime-dom-btn-empty AnyTime-dom-btn-empty-above-filled AnyTime-dom-btn-empty-before-filled ' +
3360                                                        'AnyTime-dom-btn-empty-after-filled AnyTime-dom-btn-empty-below-filled ' +
3361                                                        'ui-state-default ui-state-disabled' );
3362                                                td.addClass( 'AnyTime-dom-btn-filled ui-state-default' );
3363                                                td.AnyTime_current( i == current,
3364                                                        ((!_this.earliest) || (cmpHi.getTime() >= _this.earliest)) &&
3365                                                                ((!_this.latest) || (cmpLo.getTime() <= _this.latest)) );
3366                                                cmpLo.setDate( i + 1 );
3367                                                cmpHi.setDate( i + 1 );
3368                                            }
3369                                        }
3370                                        dow++;
3371                                    } );
3372                            wom++;
3373                        } );
3374
3375                //  Update hour.
3376
3377                cmpLo.setFullYear( this.time.getFullYear() );
3378                cmpHi.setFullYear( this.time.getFullYear() );
3379                cmpLo.setMonth( this.time.getMonth(), this.time.getDate() );
3380                cmpHi.setMonth( this.time.getMonth(), this.time.getDate() );
3381                var not12 = ! this.twelveHr;
3382                var hr = this.time.getHours();
3383                $( '#' + this.id + ' .AnyTime-hr-btn' ).each(
3384                        function()
3385                        {
3386                            var html = this.innerHTML;
3387                            var i;
3388                            if( not12 )
3389                                i = Number( html );
3390                            else
3391                            {
3392                                i = Number( html.substring( 0, html.length - 2 ) );
3393                                if( html.charAt( html.length - 2 ) == 'a' )
3394                                {
3395                                    if( i == 12 )
3396                                        i = 0;
3397                                }
3398                                else if( i < 12 )
3399                                    i += 12;
3400                            }
3401                            cmpLo.setHours( i );
3402                            cmpHi.setHours( i );
3403                            $( this ).AnyTime_current( hr == i,
3404                                    ((!_this.earliest) || (cmpHi.getTime() >= _this.earliest)) &&
3405                                            ((!_this.latest) || (cmpLo.getTime() <= _this.latest)) );
3406                            if( i < 23 )
3407                                cmpLo.setHours( cmpLo.getHours() + 1 );
3408                        } );
3409
3410                //  Update minute.
3411
3412                cmpLo.setHours( this.time.getHours() );
3413                cmpHi.setHours( this.time.getHours() );
3414                var units = this.time.getMinutes();
3415                var tens = String( Math.floor( units / 10 ) );
3416                var ones = String( units % 10 );
3417                $( '#' + this.id + ' .AnyTime-min-ten-btn:not(.AnyTime-min-ten-btn-empty)' ).each(
3418                        function()
3419                        {
3420                            $( this ).AnyTime_current( this.innerHTML == tens,
3421                                    ((!_this.earliest) || (cmpHi.getTime() >= _this.earliest)) &&
3422                                            ((!_this.latest) || (cmpLo.getTime() <= _this.latest)) );
3423                            if( cmpLo.getMinutes() < 50 )
3424                            {
3425                                cmpLo.setMinutes( cmpLo.getMinutes() + 10 );
3426                                cmpHi.setMinutes( cmpHi.getMinutes() + 10 );
3427                            }
3428                        } );
3429                cmpLo.setMinutes( Math.floor( this.time.getMinutes() / 10 ) * 10 );
3430                cmpHi.setMinutes( Math.floor( this.time.getMinutes() / 10 ) * 10 );
3431                $( '#' + this.id + ' .AnyTime-min-one-btn:not(.AnyTime-min-one-btn-empty)' ).each(
3432                        function()
3433                        {
3434                            $( this ).AnyTime_current( this.innerHTML == ones,
3435                                    ((!_this.earliest) || (cmpHi.getTime() >= _this.earliest)) &&
3436                                            ((!_this.latest) || (cmpLo.getTime() <= _this.latest)) );
3437                            cmpLo.setMinutes( cmpLo.getMinutes() + 1 );
3438                            cmpHi.setMinutes( cmpHi.getMinutes() + 1 );
3439                        } );
3440
3441                //  Update second.
3442
3443                cmpLo.setMinutes( this.time.getMinutes() );
3444                cmpHi.setMinutes( this.time.getMinutes() );
3445                units = this.time.getSeconds();
3446                tens = String( Math.floor( units / 10 ) );
3447                ones = String( units % 10 );
3448                $( '#' + this.id + ' .AnyTime-sec-ten-btn:not(.AnyTime-sec-ten-btn-empty)' ).each(
3449                        function()
3450                        {
3451                            $( this ).AnyTime_current( this.innerHTML == tens,
3452                                    ((!_this.earliest) || (cmpHi.getTime() >= _this.earliest)) &&
3453                                            ((!_this.latest) || (cmpLo.getTime() <= _this.latest)) );
3454                            if( cmpLo.getSeconds() < 50 )
3455                            {
3456                                cmpLo.setSeconds( cmpLo.getSeconds() + 10 );
3457                                cmpHi.setSeconds( cmpHi.getSeconds() + 10 );
3458                            }
3459                        } );
3460                cmpLo.setSeconds( Math.floor( this.time.getSeconds() / 10 ) * 10 );
3461                cmpHi.setSeconds( Math.floor( this.time.getSeconds() / 10 ) * 10 );
3462                $( '#' + this.id + ' .AnyTime-sec-one-btn:not(.AnyTime-sec-one-btn-empty)' ).each(
3463                        function()
3464                        {
3465                            $( this ).AnyTime_current( this.innerHTML == ones,
3466                                    ((!_this.earliest) || (cmpHi.getTime() >= _this.earliest)) &&
3467                                            ((!_this.latest) || (cmpLo.getTime() <= _this.latest)) );
3468                            cmpLo.setSeconds( cmpLo.getSeconds() + 1 );
3469                            cmpHi.setSeconds( cmpHi.getSeconds() + 1 );
3470                        } );
3471
3472                //  Update offset (time zone).
3473
3474                if( this.oConv )
3475                {
3476                    this.oConv.setUtcFormatOffsetAlleged( this.offMin );
3477                    this.oConv.setUtcFormatOffsetSubIndex( this.offSI );
3478                    var tzs = this.oConv.format( this.time );
3479                    this.oCur.html( tzs );
3480                }
3481
3482                //      Set the focus element, then size the picker according to its
3483                //      components, show the changes, and invoke Ajax if desired.
3484
3485                if( fBtn )
3486                    this.setFocus( fBtn );
3487
3488                this.conv.setUtcFormatOffsetAlleged( this.offMin );
3489                this.conv.setUtcFormatOffsetSubIndex( this.offSI );
3490                this.inp.val( this.conv.format( this.time ) ).change();
3491                this.div.show();
3492
3493                var d, totH = 0, totW = 0, dYW = 0, dMoW = 0, dDoMW = 0;
3494                if( this.dY )
3495                {
3496                    totW = dYW = this.dY.outerWidth( true );
3497                    totH = this.yLab.AnyTime_height( true ) + this.dY.AnyTime_height( true );
3498                }
3499                if( this.dMo )
3500                {
3501                    dMoW = this.dMo.outerWidth( true );
3502                    if( dMoW > totW )
3503                        totW = dMoW;
3504                    totH += this.hMo.AnyTime_height( true ) + this.dMo.AnyTime_height( true );
3505                }
3506                if( this.dDoM )
3507                {
3508                    dDoMW = this.dDoM.outerWidth( true );
3509                    if( dDoMW > totW )
3510                        totW = dDoMW;
3511                    if( __msie6 || __msie7 )
3512                    {
3513                        if( dMoW > dDoMW )
3514                            this.dDoM.css( 'width', String( dMoW ) + 'px' );
3515                        else if( dYW > dDoMW )
3516                            this.dDoM.css( 'width', String( dYW ) + 'px' );
3517                    }
3518                    totH += this.hDoM.AnyTime_height( true ) + this.dDoM.AnyTime_height( true );
3519                }
3520                if( this.dD )
3521                {
3522                    this.dD.css( { width:String( totW ) + 'px', height:String( totH ) + 'px' } );
3523                    totW += this.dMinW;
3524                    totH += this.dMinH;
3525                }
3526
3527                var w = 0, h = 0, timeH = 0, timeW = 0;
3528                if( this.dH )
3529                {
3530                    w = this.dH.outerWidth( true );
3531                    timeW += w + 1;
3532                    h = this.dH.AnyTime_height( true );
3533                    if( h > timeH )
3534                        timeH = h;
3535                }
3536                if( this.dM )
3537                {
3538                    w = this.dM.outerWidth( true );
3539                    timeW += w + 1;
3540                    h = this.dM.AnyTime_height( true );
3541                    if( h > timeH )
3542                        timeH = h;
3543                }
3544                if( this.dS )
3545                {
3546                    w = this.dS.outerWidth( true );
3547                    timeW += w + 1;
3548                    h = this.dS.AnyTime_height( true );
3549                    if( h > timeH )
3550                        timeH = h;
3551                }
3552                if( this.dO )
3553                {
3554                    w = this.oMinW;
3555                    if( timeW < w + 1 )
3556                        timeW = w + 1;
3557                    timeH += this.dO.AnyTime_height( true );
3558                }
3559                if( this.dT )
3560                {
3561                    this.dT.css( { width:String( timeW ) + 'px', height:String( timeH ) + 'px' } );
3562                    timeW += this.tMinW + 1;
3563                    timeH += this.tMinH;
3564                    totW += timeW;
3565                    if( timeH > totH )
3566                        totH = timeH;
3567                    if( this.dO ) // stretch offset button if possible
3568                    {
3569                        var dOW = this.dT.width() - (this.oMinW + 1);
3570                        this.dO.css( {width:String( dOW ) + "px"} );
3571                        this.oCur.css( {width:String( dOW - (this.oListMinW + 4) ) + "px"} );
3572                    }
3573                }
3574
3575                this.dB.css( {height:String( totH ) + 'px',width:String( totW ) + 'px'} );
3576
3577                totH += this.bMinH;
3578                totW += this.bMinW;
3579                totH += this.hTitle.AnyTime_height( true ) + this.wMinH;
3580                totW += this.wMinW;
3581                if( this.hTitle.outerWidth( true ) > totW )
3582                    totW = this.hTitle.outerWidth( true ); // IE quirk
3583                this.div.css( {height:String( totH ) + 'px',width:String( totW ) + 'px'} );
3584
3585                if( ! this.pop )
3586                    this.ajax();
3587
3588                /** VMIPSL **/
3589                if( this.methodToCall )
3590                    this.methodToCall();
3591            }, // .upd()
3592
3593            //---------------------------------------------------------------------
3594            //  .updODiv() updates the UTC offset selector's appearance.  It is
3595            //  called after most events to make the picker reflect the currently-
3596            //  selected values. fBtn is the psuedo-button to be given focus.
3597            //---------------------------------------------------------------------
3598
3599            updODiv: function( fBtn )
3600            {
3601                var cur, matched = false, def = null;
3602                this.oDiv.find( '.AnyTime-off-off-btn' ).each(
3603                        function()
3604                        {
3605                            if( this.AnyTime_offMin == _this.offMin )
3606                            {
3607                                if( this.AnyTime_offSI == _this.offSI )
3608                                    $( this ).AnyTime_current( matched = true, true );
3609                                else
3610                                {
3611                                    $( this ).AnyTime_current( false, true );
3612                                    if( def == null )
3613                                        def = $( this );
3614                                }
3615                            }
3616                            else
3617                                $( this ).AnyTime_current( false, true );
3618                        } );
3619                if( ( ! matched ) && ( def != null ) )
3620                    def.AnyTime_current( true, true );
3621
3622                //  Show change
3623
3624                this.conv.setUtcFormatOffsetAlleged( this.offMin );
3625                this.conv.setUtcFormatOffsetSubIndex( this.offSI );
3626                this.inp.val( this.conv.format( this.time ) ).change();
3627                this.upd( fBtn );
3628
3629            }, // .updODiv()
3630
3631            //---------------------------------------------------------------------
3632            //  .updYDiv() updates the year selector's appearance.  It is
3633            //  called after most events to make the picker reflect the currently-
3634            //  selected values. fBtn is the psuedo-button to be given focus.
3635            //---------------------------------------------------------------------
3636
3637            updYDiv: function( fBtn )
3638            {
3639                var i, legal;
3640                var era = 1;
3641                var yearValue = this.time.getFullYear();
3642                if( yearValue < 0 )
3643                {
3644                    era = (-1);
3645                    yearValue = 0 - yearValue;
3646                }
3647                yearValue = AnyTime.pad( yearValue, 4 );
3648                var eY = _this.earliest && new Date( _this.earliest ).getFullYear();
3649                var lY = _this.latest && new Date( _this.latest ).getFullYear();
3650
3651                i = 0;
3652                this.yDiv.find( '.AnyTime-mil-btn' ).each(
3653                        function()
3654                        {
3655                            legal = ( ((!_this.earliest) || (era * (i + (era < 0 ? 0 : 999)) >= eY)) && ((!_this.latest) || (era * (i + (era > 0 ? 0 : 999)) <= lY)) );
3656                            $( this ).AnyTime_current( this.innerHTML == yearValue.substring( 0, 1 ), legal );
3657                            i += 1000;
3658                        } );
3659
3660                i = (Math.floor( yearValue / 1000 ) * 1000);
3661                this.yDiv.find( '.AnyTime-cent-btn' ).each(
3662                        function()
3663                        {
3664                            legal = ( ((!_this.earliest) || (era * (i + (era < 0 ? 0 : 99)) >= eY)) && ((!_this.latest) || (era * (i + (era > 0 ? 0 : 99)) <= lY)) );
3665                            $( this ).AnyTime_current( this.innerHTML == yearValue.substring( 1, 2 ), legal );
3666                            i += 100;
3667                        } );
3668
3669                i = (Math.floor( yearValue / 100 ) * 100);
3670                this.yDiv.find( '.AnyTime-dec-btn' ).each(
3671                        function()
3672                        {
3673                            legal = ( ((!_this.earliest) || (era * (i + (era < 0 ? 0 : 9)) >= eY)) && ((!_this.latest) || (era * (i + (era > 0 ? 0 : 9)) <= lY)) );
3674                            $( this ).AnyTime_current( this.innerHTML == yearValue.substring( 2, 3 ), legal );
3675                            i += 10;
3676                        } );
3677
3678                i = (Math.floor( yearValue / 10 ) * 10);
3679                this.yDiv.find( '.AnyTime-yr-btn' ).each(
3680                        function()
3681                        {
3682                            legal = ( ((!_this.earliest) || (era * i >= eY)) && ((!_this.latest) || (era * i <= lY)) );
3683                            $( this ).AnyTime_current( this.innerHTML == yearValue.substring( 3 ), legal );
3684                            i += 1;
3685                        } );
3686
3687                this.yDiv.find( '.AnyTime-bce-btn' ).each(
3688                        function()
3689                        {
3690                            $( this ).AnyTime_current( era < 0, (!_this.earliest) || ( _this.earliest < 0 ) );
3691                        } );
3692                this.yDiv.find( '.AnyTime-ce-btn' ).each(
3693                        function()
3694                        {
3695                            $( this ).AnyTime_current( era > 0, (!_this.latest) || ( _this.latest > 0 ) );
3696                        } );
3697
3698                //  Show change
3699
3700                this.conv.setUtcFormatOffsetAlleged( this.offMin );
3701                this.conv.setUtcFormatOffsetSubIndex( this.offSI );
3702                this.inp.val( this.conv.format( this.time ) ).change();
3703                this.upd( fBtn );
3704
3705            } // .updYDiv()
3706
3707        }; // __pickers[id] = ...
3708        __pickers[id].initialize( id );
3709
3710    } // AnyTime.picker =
3711
3712})( jQuery ); // function($)...
3713
3714
3715//
3716//  END OF FILE
3717//
3718//if(window.location.hostname.length&&(window.location.hostname!='www.ama3.com')&&(window.location.hostname!='dev2.ama3.com'))alert('REMOVE THE LAST LINE FROM anytime.js!');
Note: See TracBrowser for help on using the repository browser.