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