1/* 2 dynDateTime 0.2 3 4 A jQuery date time picker. 5 6 Author: Toolman 7 Version: 0.2 8 Website: http://code.google.com/p/dyndatetime/ 9 10*/ 11 12 13(function($) { 14 var myr=0; 15 $.fn.dynDateTime = function(options) { 16 17 // plugin defaults 18 $.fn.dynDateTime.defaults = { 19 displayArea: null, 20 button: null, 21 eventName: "click", 22 ifFormat: "%Y/%m/%d", 23 daFormat: "%Y/%m/%d", 24 singleClick: true, 25 dateStatusFunc: null, 26 dateText: null, 27 firstDay: null, 28 align: "Br", 29 range: [1900, 2999], 30 weekNumbers: true, 31 flat: null, 32 flatCallback: null, 33 onSelect: null, 34 onClose: null, 35 onUpdate: null, 36 date: null, 37 showsTime: false, 38 timeFormat: "24", 39 electric: true, 40 step: 1, 41 position: null, 42 cache: false, 43 showOthers: false, 44 multiple: null, 45 debug: false, 46 isCht: false 47 }; 48 49 var opts = $.extend({}, $.fn.dynDateTime.defaults, options); 50 51 return this.each(function() { 52 53 //opts are shared per jQuery call; create per inputField closures of non-shared values for each instance 54 var this_inputField = this; 55 var this_displayArea = null; 56 var this_button = null; 57 var this_flat = null; 58 if(opts.displayArea) { 59 try { 60 this_displayArea = eval("jQuery(this)" + opts.displayArea + ".get(0);"); 61 } catch (err) { 62 opts.displayArea = null; 63 } 64 } 65 if(opts.button) { 66 try { 67 this_button = eval("jQuery(this)" + opts.button + ".get(0);"); 68 } catch (err) { 69 opts.button = null; 70 } 71 } 72 if(opts.flat) { 73 try { 74 this_flat = eval("jQuery(this)" + opts.flat + ".get(0);"); 75 } catch (err) { 76 opts.flat = null; 77 } 78 } 79 80 81 82 if (!(this_flat || opts.multiple || this_inputField || this_displayArea || this_button)) { 83 log("opts"); 84 //nothing to do 85 return; 86 } 87 88 //default onSelect 89 function onSelect(cal) { 90 var p = cal.opts; 91 var update = (cal.dateClicked || p.electric); 92 if (update && this_inputField) { 93 this_inputField.value = cal.date.print(p.ifFormat); 94 if (typeof this_inputField.onchange == "function") 95 this_inputField.onchange(); 96 } 97 if (update && this_displayArea) 98 this_displayArea.innerHTML = cal.date.print(p.daFormat); 99 if (update && typeof p.onUpdate == "function") 100 p.onUpdate(cal); 101 if (update && p.flat) { 102 if (typeof p.flatCallback == "function") 103 p.flatCallback(cal); 104 } 105 if (update && p.singleClick && cal.dateClicked) 106 cal.callCloseHandler(); 107 }; 108 109 //flat setup 110 if (this_flat != null) { 111 112 var cal = new Calendar(opts.firstDay, opts.date, opts.onSelect || onSelect); 113 cal.showsOtherMonths = opts.showOthers; 114 cal.showsTime = opts.showsTime; 115 cal.time24 = (opts.timeFormat == "24"); 116 cal.opts = opts; 117 cal.weekNumbers = opts.weekNumbers; 118 cal.setRange(opts.range[0], opts.range[1]); 119 cal.setDateStatusHandler(opts.dateStatusFunc); 120 cal.getDateText = opts.dateText; 121 if (opts.ifFormat) { 122 cal.setDateFormat(opts.ifFormat); 123 } 124 if (this_inputField && typeof this_inputField.value == "string") { 125 //cal.parseDate(this_inputField.value); 126 log("rar"); 127 } 128 cal.create(this_flat); 129 cal.show(); 130 return; 131 } 132 133 //find the element to mount show/hide event 134 var triggerEl = this_button || this_displayArea || this_inputField ; 135 136 //bolt on event 137 triggerEl["on" + opts.eventName] = function() { 138 log("clicked"); 139 var dateEl = this_inputField || this_displayArea; 140 var dateFmt = this_inputField ? opts.ifFormat : opts.daFormat; 141 var mustCreate = false; 142 var cal = window.calendar; 143 if (dateEl) 144 opts.date = Date.parseDate(dateEl.value || dateEl.innerHTML, dateFmt); 145 if (!(cal && opts.cache)) { 146 window.calendar = cal = new Calendar(opts.firstDay, 147 opts.date, 148 opts.onSelect || onSelect, 149 opts.onClose || function(cal) { cal.hide(); }); 150 cal.showsTime = opts.showsTime; 151 cal.time24 = (opts.timeFormat == "24"); 152 cal.weekNumbers = opts.weekNumbers; 153 mustCreate = true; 154 } else { 155 if (opts.date) 156 cal.setDate(opts.date); 157 cal.hide(); 158 } 159 if (opts.multiple) { 160 cal.multiple = {}; 161 for (var i = opts.multiple.length; --i >= 0;) { 162 var d = opts.multiple[i]; 163 var ds = d.print("%Y%m%d"); 164 cal.multiple[ds] = d; 165 } 166 } 167 cal.showsOtherMonths = opts.showOthers; 168 cal.yearStep = opts.step; 169 cal.setRange(opts.range[0], opts.range[1]); 170 cal.opts = opts; 171 cal.setDateStatusHandler(opts.dateStatusFunc); 172 cal.getDateText = opts.dateText; 173 cal.setDateFormat(dateFmt); 174 if (mustCreate) 175 cal.create(); 176 cal.refresh();
177 if (!opts.position) 178 cal.showAtElement(this_button || this_displayArea || this_inputField, opts.align); 179 else 180 cal.showAt(opts.position[0], opts.position[1]); 181 return false; 182 }; 183 }); 184 185 // private function for debugging 186 function log(msg) { 187 if(opts.debug) { 188 window.loadFirebugConsole(); // file:// based access seems to disable this for me! 189 if (window.console && window.console.log ) window.console.log("dynDateTime: " + msg); 190 } 191 }; 192 }; 193})(jQuery); 194 195// Begin old dynarch code 196 197/* Copyright Mihai Bazon, 2002-2005 | www.bazon.net/mishoo 198 * ----------------------------------------------------------- 199 * 200 * The DHTML Calendar, version 1.0 "It is happening again" 201 * 202 * Details and latest version at: 203 * www.dynarch.com/projects/calendar 204 * 205 * This script is developed by Dynarch.com. Visit us at www.dynarch.com. 206 * 207 * This script is distributed under the GNU Lesser General Public License. 208 * Read the entire license text here: http://www.gnu.org/licenses/lgpl.html 209 */ 210 211// $Id: calendar.js,v 1.51 2005/03/07 16:44:31 mishoo Exp $ 212 213/** The Calendar object constructor. */ 214Calendar = function (firstDayOfWeek, dateStr, onSelected, onClose) { 215 // member variables 216 this.activeDiv = null; 217 this.currentDateEl = null; 218 this.getDateStatus = null; 219 this.getDateToolTip = null; 220 this.getDateText = null; 221 this.timeout = null; 222 this.onSelected = onSelected || null; 223 this.onClose = onClose || null; 224 this.dragging = false; 225 this.hidden = false; 226 this.minYear = 1912; 227 this.maxYear = 3000; 228 this.dateFormat = Calendar._TT["DEF_DATE_FORMAT"]; 229 this.ttDateFormat = Calendar._TT["TT_DATE_FORMAT"]; 230 this.isPopup = true; 231 this.weekNumbers = true; 232 this.firstDayOfWeek = typeof firstDayOfWeek == "number" ? firstDayOfWeek : Calendar._FD; // 0 for Sunday, 1 for Monday, etc. 233 this.showsOtherMonths = false; 234 this.dateStr = dateStr; 235 236 var yearArray = this.dateStr.toString().split(" "); 237 var year = yearArray[yearArray.length - 1]; 238 if (parseInt(year, 10) < 1911) { 239 this.dateStr = ""; 240 var i = 0; 241 for (i = 0; i < yearArray.length - 1; i++) { 242 this.dateStr = this.dateStr + yearArray[i] + " "; 243 } 244 this.dateStr = this.dateStr + (parseInt(year, 10) + 1911).toString(); 245 alert(this.dateStr); 246 } 247 248 this.ar_days = null; 249 this.showsTime = false; 250 this.time24 = true; 251 this.yearStep = 2; 252 this.hiliteToday = true; 253 this.multiple = null; 254 // HTML elements 255 this.table = null; 256 this.element = null; 257 this.tbody = null; 258 this.firstdayname = null; 259 // Combo boxes 260 this.monthsCombo = null; 261 this.yearsCombo = null; 262 this.hilitedMonth = null; 263 this.activeMonth = null; 264 this.hilitedYear = null; 265 this.activeYear = null; 266 // Information 267 this.dateClicked = false; 268 269 // one-time initializations 270 if (typeof Calendar._SDN == "undefined") { 271 // table of short day names 272 if (typeof Calendar._SDN_len == "undefined") 273 Calendar._SDN_len = 3; 274 var ar = new Array(); 275 for (var i = 8; i > 0;) { 276 ar[--i] = Calendar._DN[i].substr(0, Calendar._SDN_len); 277 } 278 Calendar._SDN = ar; 279 // table of short month names 280 if (typeof Calendar._SMN_len == "undefined") 281 Calendar._SMN_len = 3; 282 ar = new Array(); 283 for (var i = 12; i > 0;) { 284 ar[--i] = Calendar._MN[i].substr(0, Calendar._SMN_len); 285 } 286 Calendar._SMN = ar; 287 } 288}; 289 290// ** constants 291 292/// "static", needed for event handlers. 293Calendar._C = null; 294 295/// detect a special case of "web browser" 296Calendar.is_ie = ( /msie/i.test(navigator.userAgent) && 297 !/opera/i.test(navigator.userAgent) ); 298 299Calendar.is_ie5 = ( Calendar.is_ie && /msie 5\.0/i.test(navigator.userAgent) ); 300 301/// detect Opera browser 302Calendar.is_opera = /opera/i.test(navigator.userAgent); 303 304/// detect KHTML-based browsers 305Calendar.is_khtml = /Konqueror|Safari|KHTML/i.test(navigator.userAgent); 306 307// BEGIN: UTILITY FUNCTIONS; beware that these might be moved into a separate 308// library, at some point. 309 310Calendar.getAbsolutePos = function(el) { 311 var SL = 0, ST = 0; 312 var is_div = /^div$/i.test(el.tagName); 313 if (is_div && el.scrollLeft) 314 315 SL = el.scrollLeft; 316 if (is_div && el.scrollTop) 317 ST = el.scrollTop; 318 var r = { x: el.offsetLeft - SL, y: el.offsetTop - ST }; 319 if (el.offsetParent) { 320 var tmp = this.getAbsolutePos(el.offsetParent); 321 r.x += tmp.x; 322 r.y += tmp.y; 323 } 324 return r; 325}; 326 327Calendar.isRelated = function (el, evt) { 328 var related = evt.relatedTarget; 329 if (!related) { 330 var type = evt.type; 331 if (type == "mouseover") { 332 related = evt.fromElement; 333 } else if (type == "mouseout") { 334 related = evt.toElement; 335 } 336 } 337 while (related) { 338 if (related == el) { 339 return true; 340 } 341 related = related.parentNode; 342 } 343 return false; 344}; 345 346Calendar.removeClass = function(el, className) { 347 if (!(el && el.className)) { 348 return; 349 } 350 var cls = el.className.split(" "); 351 var ar = new Array(); 352 for (var i = cls.length; i > 0;) { 353 if (cls[--i] != className) { 354 ar[ar.length] = cls[i];
355 } 356 } 357 el.className = ar.join(" "); 358}; 359 360Calendar.addClass = function(el, className) { 361 Calendar.removeClass(el, className); 362 el.className += " " + className; 363}; 364 365// FIXME: the following 2 functions totally suck, are useless and should be replaced immediately. 366Calendar.getElement = function(ev) { 367 var f = Calendar.is_ie ? window.event.srcElement : ev.currentTarget; 368 while (f.nodeType != 1 || /^div$/i.test(f.tagName)) 369 f = f.parentNode; 370 return f; 371}; 372 373Calendar.getTargetElement = function(ev) { 374 var f = Calendar.is_ie ? window.event.srcElement : ev.target; 375 while (f.nodeType != 1) 376 f = f.parentNode; 377 return f; 378}; 379 380Calendar.stopEvent = function(ev) { 381 ev || (ev = window.event); 382 if (Calendar.is_ie) { 383 ev.cancelBubble = true; 384 ev.returnValue = false; 385 } else { 386 ev.preventDefault(); 387 ev.stopPropagation(); 388 } 389 return false; 390}; 391 392Calendar.addEvent = function(el, evname, func) { 393 if (el.attachEvent) { // IE 394 el.attachEvent("on" + evname, func); 395 } else if (el.addEventListener) { // Gecko / W3C 396 el.addEventListener(evname, func, true); 397 } else { 398 el["on" + evname] = func; 399 } 400}; 401 402Calendar.removeEvent = function(el, evname, func) { 403 if (el.detachEvent) { // IE 404 el.detachEvent("on" + evname, func); 405 } else if (el.removeEventListener) { // Gecko / W3C 406 el.removeEventListener(evname, func, true); 407 } else { 408 el["on" + evname] = null; 409 } 410}; 411 412Calendar.createElement = function(type, parent) { 413 var el = null; 414 if (document.createElementNS) { 415 // use the XHTML namespace; IE won't normally get here unless 416 // _they_ "fix" the DOM2 implementation. 417 el = document.createElementNS("http://www.w3.org/1999/xhtml", type); 418 } else { 419 el = document.createElement(type); 420 } 421 if (typeof parent != "undefined") { 422 parent.appendChild(el); 423 } 424 return el; 425}; 426 427// END: UTILITY FUNCTIONS 428 429// BEGIN: CALENDAR STATIC FUNCTIONS 430 431/** Internal -- adds a set of events to make some element behave like a button. */ 432Calendar._add_evs = function(el) { 433 with (Calendar) { 434 addEvent(el, "mouseover", dayMouseOver); 435 addEvent(el, "mousedown", dayMouseDown); 436 addEvent(el, "mouseout", dayMouseOut); 437 if (is_ie) { 438 addEvent(el, "dblclick", dayMouseDblClick); 439 el.setAttribute("unselectable", true); 440 } 441 } 442}; 443 444Calendar.findMonth = function(el) { 445 if (typeof el.month != "undefined") { 446 return el; 447 } else if (typeof el.parentNode.month != "undefined") { 448 return el.parentNode; 449 } 450 return null; 451}; 452 453Calendar.findYear = function(el) { 454 if (typeof el.year != "undefined") { 455 return el; 456 } else if (typeof el.parentNode.year != "undefined") { 457 return el.parentNode; 458 } 459 return null; 460}; 461 462Calendar.showMonthsCombo = function () { 463 var cal = Calendar._C; 464 if (!cal) { 465 return false; 466 } 467 var cal = cal; 468 var cd = cal.activeDiv; 469 var mc = cal.monthsCombo; 470 if (cal.hilitedMonth) { 471 Calendar.removeClass(cal.hilitedMonth, "hilite"); 472 } 473 if (cal.activeMonth) { 474 Calendar.removeClass(cal.activeMonth, "active"); 475 } 476 var mon = cal.monthsCombo.getElementsByTagName("div")[cal.date.getMonth()]; 477 Calendar.addClass(mon, "active"); 478 cal.activeMonth = mon; 479 var s = mc.style; 480 s.display = "block"; 481 if (cd.navtype < 0) 482 s.left = cd.offsetLeft + "px"; 483 else { 484 var mcw = mc.offsetWidth; 485 if (typeof mcw == "undefined") 486 // Konqueror brain-dead techniques 487 mcw = 50; 488 s.left = (cd.offsetLeft + cd.offsetWidth - mcw) + "px"; 489 } 490 s.top = (cd.offsetTop + cd.offsetHeight) + "px"; 491}; 492 493Calendar.showYearsCombo = function (fwd) { 494 var cal = Calendar._C; 495 if (!cal) { 496 return false; 497 } 498 var cal = cal; 499 var cd = cal.activeDiv; 500 var yc = cal.yearsCombo; 501 if (cal.hilitedYear) { 502 Calendar.removeClass(cal.hilitedYear, "hilite"); 503 } 504 if (cal.activeYear) { 505 Calendar.removeClass(cal.activeYear, "active"); 506 } 507 cal.activeYear = null; 508 var Y = cal.date.getFullYear() + (fwd ? 1 : -1); 509 var yr = yc.firstChild; 510 var show = false; 511 for (var i = 12; i > 0; --i) { 512 if (Y >= cal.minYear && Y <= cal.maxYear) { 513 yr.innerHTML = Y-1911; //topcat 514 yr.year = Y; 515 yr.style.display = "block"; 516 show = true; 517 } else { 518 yr.style.display = "none"; 519 } 520 yr = yr.nextSibling; 521 Y += fwd ? cal.yearStep : -cal.yearStep; 522 } 523 if (show) { 524 var s = yc.style; 525 s.display = "block"; 526 if (cd.navtype < 0) 527 s.left = cd.offsetLeft + "px"; 528 else { 529 var ycw = yc.offsetWidth; 530 if (typeof ycw == "undefined") 531 // Konqueror brain-dead techniques 532 ycw = 50; 533 s.left = (cd.offsetLeft + cd.offsetWidth - ycw) + "px"; 534 } 535 s.top = (cd.offsetTop + cd.offsetHeight) + "px"; 536 } 537}; 538 539// event handlers 540 541Calendar.tableMouseUp = function(ev) { 542 var cal = Calendar._C; 543 if (!cal) { 544 return false; 545 } 546 if (cal.timeout) { 547 clearTimeout(cal.timeout); 548 } 549 var el = cal.activeDiv; 550 if (!el) { 551 return false; 552 } 553 var target = Calendar.getTargetElement(ev); 554 ev || (ev = window.event); 555 Calendar.removeClass(el, "active"); 556 if (target == el || target.parentNode == el) { 557 Calendar.cellClick(el, ev); 558 } 559 var mon = Calendar.findMonth(target); 560 var date = null; 561 if (mon) { 562 date = new Date(cal.date); 563 if (mon.month != date.getMonth()) { 564 date.setMonth(mon.month); 565 cal.setDate(date); 566 cal.dateClicked = false; 567 cal.callHandler(); 568 } 569 } else { 570 var year = Calendar.findYear(target); 571 if (year) { 572 date = new Date(cal.date); 573 if (year.year != date.getFullYear()) { 574 date.setFullYear(year.year); 575 cal.setDate(date); 576 cal.dateClicked = false; 577 cal.callHandler(); 578 } 579 } 580 } 581 with (Calendar) { 582 removeEvent(document, "mouseup", tableMouseUp); 583 removeEvent(document, "mouseover", tableMouseOver); 584 removeEvent(document, "mousemove", tableMouseOver); 585 cal._hideCombos(); 586 _C = null; 587 return stopEvent(ev); 588 } 589}; 590 591Calendar.tableMouseOver = function (ev) { 592 var cal = Calendar._C; 593 if (!cal) { 594 return; 595 } 596 var el = cal.activeDiv; 597 var target = Calendar.getTargetElement(ev); 598 if (target == el || target.parentNode == el) { 599 Calendar.addClass(el, "hilite active"); 600 Calendar.addClass(el.parentNode, "rowhilite"); 601 } else { 602 if (typeof el.navtype == "undefined" || (el.navtype != 50 && (el.navtype == 0 || Math.abs(el.navtype) > 2))) 603 Calendar.removeClass(el, "active"); 604 Calendar.removeClass(el, "hilite"); 605 Calendar.removeClass(el.parentNode, "rowhilite"); 606 } 607 ev || (ev = window.event); 608 if (el.navtype == 50 && target != el) { 609 var pos = Calendar.getAbsolutePos(el); 610 var w = el.offsetWidth; 611 var x = ev.clientX; 612 var dx; 613 var decrease = true; 614 if (x >
614 pos.x + w) { 615 dx = x - pos.x - w; 616 decrease = false; 617 } else 618 dx = pos.x - x; 619 620 if (dx < 0) dx = 0; 621 var range = el._range; 622 var current = el._current; 623 var count = Math.floor(dx / 10) % range.length; 624 for (var i = range.length; --i >= 0;) 625 if (range[i] == current) 626 break; 627 while (count-- > 0) 628 if (decrease) { 629 if (--i < 0) 630 i = range.length - 1; 631 } else if ( ++i >= range.length ) 632 i = 0; 633 var newval = range[i]; 634 el.innerHTML = newval; 635 636 cal.onUpdateTime(); 637 } 638 var mon = Calendar.findMonth(target); 639 if (mon) { 640 if (mon.month != cal.date.getMonth()) { 641 if (cal.hilitedMonth) { 642 Calendar.removeClass(cal.hilitedMonth, "hilite"); 643 } 644 Calendar.addClass(mon, "hilite"); 645 cal.hilitedMonth = mon; 646 } else if (cal.hilitedMonth) { 647 Calendar.removeClass(cal.hilitedMonth, "hilite"); 648 } 649 } else { 650 if (cal.hilitedMonth) { 651 Calendar.removeClass(cal.hilitedMonth, "hilite"); 652 } 653 var year = Calendar.findYear(target); 654 if (year) { 655 if (year.year != cal.date.getFullYear()) { 656 if (cal.hilitedYear) { 657 Calendar.removeClass(cal.hilitedYear, "hilite"); 658 } 659 Calendar.addClass(year, "hilite"); 660 cal.hilitedYear = year; 661 } else if (cal.hilitedYear) { 662 Calendar.removeClass(cal.hilitedYear, "hilite"); 663 } 664 } else if (cal.hilitedYear) { 665 Calendar.removeClass(cal.hilitedYear, "hilite"); 666 } 667 } 668 return Calendar.stopEvent(ev); 669}; 670 671Calendar.tableMouseDown = function (ev) { 672 if (Calendar.getTargetElement(ev) == Calendar.getElement(ev)) { 673 return Calendar.stopEvent(ev); 674 } 675}; 676 677Calendar.calDragIt = function (ev) { 678 var cal = Calendar._C; 679 if (!(cal && cal.dragging)) { 680 return false; 681 } 682 var posX; 683 var posY; 684 if (Calendar.is_ie) { 685 posY = window.event.clientY + document.body.scrollTop; 686 posX = window.event.clientX + document.body.scrollLeft; 687 } else { 688 posX = ev.pageX; 689 posY = ev.pageY; 690 } 691 cal.hideShowCovered(); 692 var st = cal.element.style; 693 st.left = (posX - cal.xOffs) + "px"; 694 st.top = (posY - cal.yOffs) + "px"; 695 return Calendar.stopEvent(ev); 696}; 697 698Calendar.calDragEnd = function (ev) { 699 var cal = Calendar._C; 700 if (!cal) { 701 return false; 702 } 703 cal.dragging = false; 704 with (Calendar) { 705 removeEvent(document, "mousemove", calDragIt); 706 removeEvent(document, "mouseup", calDragEnd); 707 tableMouseUp(ev); 708 } 709 cal.hideShowCovered(); 710}; 711 712Calendar.dayMouseDown = function(ev) { 713 var el = Calendar.getElement(ev); 714 if (el.disabled) { 715 return false; 716 } 717 var cal = el.calendar; 718 cal.activeDiv = el; 719 Calendar._C = cal; 720 if (el.navtype != 300) with (Calendar) { 721 if (el.navtype == 50) { 722 el._current = el.innerHTML; 723 addEvent(document, "mousemove", tableMouseOver); 724 } else 725 addEvent(document, Calendar.is_ie5 ? "mousemove" : "mouseover", tableMouseOver); 726 addClass(el, "hilite active"); 727 addEvent(document, "mouseup", tableMouseUp); 728 } else if (cal.isPopup) { 729 cal._dragStart(ev); 730 } 731 if (el.navtype == -1 || el.navtype == 1) { 732 if (cal.timeout) clearTimeout(cal.timeout); 733 cal.timeout = setTimeout("Calendar.showMonthsCombo()", 250); 734 } else if (el.navtype == -2 || el.navtype == 2) { 735 if (cal.timeout) clearTimeout(cal.timeout); 736 cal.timeout = setTimeout((el.navtype > 0) ? "Calendar.showYearsCombo(true)" : "Calendar.showYearsCombo(false)", 250); 737 } else { 738 cal.timeout = null; 739 } 740 return Calendar.stopEvent(ev); 741}; 742 743Calendar.dayMouseDblClick = function(ev) { 744 Calendar.cellClick(Calendar.getElement(ev), ev || window.event); 745 if (Calendar.is_ie) { 746 document.selection.empty(); 747 } 748}; 749 750Calendar.dayMouseOver = function(ev) { 751 var el = Calendar.getElement(ev); 752 if (Calendar.isRelated(el, ev) || Calendar._C || el.disabled) { 753 return false; 754 } 755 if (el.ttip) { 756 if (el.ttip.substr(0, 1) == "_") { 757 el.ttip = el.caldate.print(el.calendar.ttDateFormat) + el.ttip.substr(1); 758 } 759 el.calendar.tooltips.innerHTML = el.ttip; 760 } 761 if (el.navtype != 300) { 762 Calendar.addClass(el, "hilite"); 763 if (el.caldate) { 764 Calendar.addClass(el.parentNode, "rowhilite"); 765 } 766 } 767 return Calendar.stopEvent(ev); 768}; 769 770Calendar.dayMouseOut = function(ev) { 771 with (Calendar) { 772 var el = getElement(ev); 773 if (isRelated(el, ev) || _C || el.disabled) 774 return false; 775 removeClass(el, "hilite"); 776 if (el.caldate) 777 removeClass(el.parentNode, "rowhilite"); 778 if (el.calendar) 779 el.calendar.tooltips.innerHTML = _TT["SEL_DATE"]; 780 return stopEvent(ev); 781 } 782}; 783 784/** 785 * A generic "click" handler :) handles all types of buttons defined in this 786 * calendar. 787 */ 788Calendar.cellClick = function(el, ev) { 789 var cal = el.calendar; 790 var closing = false; 791 var newdate = false; 792 var date = null; 793 if (typeof el.navtype == "undefined") { 794 if (cal.currentDateEl) { 795 Calendar.removeClass(cal.currentDateEl, "selected"); 796 Calendar.addClass(el, "selected"); 797 closing = (cal.currentDateEl == el); 798 if (!closing) { 799 cal.currentDateEl = el; 800 } 801 } 802 cal.date.setDateOnly(el.caldate); 803 date = cal.date; 804 var other_month = !(cal.dateClicked = !el.otherMonth); 805 if (!other_month && !cal.currentDateEl) 806 cal._toggleMultipleDate(new Date(date)); 807 else 808 newdate = !el.disabled; 809 // a date was clicked 810 if (other_month) 811 cal._init(cal.firstDayOfWeek, date); 812 } else { 813 if (el.navtype == 200) { 814 Calendar.removeClass(el, "hilite"); 815 cal.callCloseHandler(); 816 return; 817 } 818 date = new Date(cal.date); 819 if (el.navtype == 0) 820 date.setDateOnly(new Date()); // TODAY 821 // unless "today" was clicked, we assume no date was clicked so 822 // the selected handler will know not to close the calenar when 823 // in single-click mode. 824 // cal.dateClicked = (el.navtype == 0); 825 cal.dateClicked = false; 826 var year = date.getFullYear(); 827 if (parseInt(year, 10) < 1911) { 828 year += 1911; 829 } 830 var mon = date.getMonth(); 831 function setMonth(m) { 832 var day = date.getDate(); 833 var max = date.getMonthDays(m); 834 if (day > max) { 835 date.setDate(max); 836 } 837 date.setMonth(m); 838 }; 839 switch (el.navtype) { 840 case 400: 841 Calendar.removeClass(el, "hilite"); 842 var text = Calendar._TT["ABOUT"]; 843 if (typeof text != "undefined") { 844 text += cal.showsTime ? Calendar._TT["ABOUT_TIME"] : ""; 845 } else { 846 // FIXME: this should be removed as soon as lang files get updated! 847 text = "Help and about box text is not translated into this language.\n" + 848 "If you know this language and you feel generous please update\n" + 849 "the corresponding file in \"lang\" subdir to match calendar-en.js\n" + 850 "and send it back to <[email protected]> to get it into the distribution ;-)\n\n" + 851 "Thank you!\n" +
852 "http://dynarch.com/mishoo/calendar.epl\n"; 853 } 854 alert(text); 855 return; 856 case -2: 857 if (year > cal.minYear) { 858 date.setFullYear(year - 1); 859 } 860 break; 861 case -1: 862 if (mon > 0) { 863 setMonth(mon - 1); 864 } else if (year-- > cal.minYear) { 865 date.setFullYear(year); 866 setMonth(11); 867 } 868 break; 869 case 1: 870 if (mon < 11) { 871 setMonth(mon + 1); 872 } else if (year < cal.maxYear) { 873 date.setFullYear(year + 1); 874 setMonth(0); 875 } 876 break; 877 case 2: 878 if (year < cal.maxYear) { 879 date.setFullYear(year + 1); 880 } 881 break; 882 case 100: 883 cal.setFirstDayOfWeek(el.fdow); 884 return; 885 case 50: 886 var range = el._range; 887 var current = el.innerHTML; 888 for (var i = range.length; --i >= 0;) 889 if (range[i] == current) 890 break; 891 if (ev && ev.shiftKey) { 892 if (--i < 0) 893 i = range.length - 1; 894 } else if ( ++i >= range.length ) 895 i = 0; 896 var newval = range[i]; 897 el.innerHTML = newval; 898 cal.onUpdateTime(); 899 return; 900 case 0: 901 // TODAY will bring us here 902 if ((typeof cal.getDateStatus == "function") && 903 cal.getDateStatus(date, date.getFullYear(), date.getMonth(), date.getDate())) { 904 return false; 905 } 906 break; 907 } 908 if (!date.equalsTo(cal.date)) { 909 cal.setDate(date); 910 newdate = true; 911 } else if (el.navtype == 0) 912 newdate = closing = true; 913 } 914 if (newdate) { 915 ev && cal.callHandler(); 916 } 917 if (closing) { 918 Calendar.removeClass(el, "hilite"); 919 ev && cal.callCloseHandler(); 920 } 921}; 922 923// END: CALENDAR STATIC FUNCTIONS 924 925// BEGIN: CALENDAR OBJECT FUNCTIONS 926/** 927 * This function creates the calendar inside the given parent. If _par is 928 * null than it creates a popup calendar inside the BODY element. If _par is 929 * an element, be it BODY, then it creates a non-popup calendar (still 930 * hidden). Some properties need to be set before calling this function. 931 */ 932Calendar.prototype.create = function (_par) { 933 var parent = null; 934 if (!_par) { 935 // default parent is the document body, in which case we create 936 // a popup calendar. 937 parent = document.getElementsByTagName("body")[0]; 938 this.isPopup = true; 939 } else { 940 parent = _par; 941 this.isPopup = false; 942 } 943 944 var yearArray = this.dateStr.toString().split(" "); 945 var year = yearArray[yearArray.length - 1]; 946 if (parseInt(year, 10) < 1911) { 947 this.dateStr = ""; 948 var i = 0; 949 for (i = 0; i < yearArray.length - 1; i++) { 950 this.dateStr = this.dateStr + yearArray[i] + " "; 951 } 952 this.dateStr = this.dateStr + (parseInt(year, 10) + 1911).toString(); 953 //alert(this.dateStr); 954 } 955 956 this.date = this.dateStr ? new Date(this.dateStr) : new Date(); 957 958 var table = Calendar.createElement("table"); 959 this.table = table; 960 table.cellSpacing = 0; 961 table.cellPadding = 0; 962 table.calendar = this; 963 Calendar.addEvent(table, "mousedown", Calendar.tableMouseDown); 964 965 var div = Calendar.createElement("div"); 966 this.element = div; 967 div.className = "calendar"; 968 if (this.isPopup) { 969 div.style.position = "absolute"; 970 div.style.display = "none"; 971 } 972 div.appendChild(table); 973 974 var thead = Calendar.createElement("thead", table); 975 var cell = null; 976 var row = null; 977 978 var cal = this; 979 var hh = function (text, cs, navtype) { 980 cell = Calendar.createElement("td", row); 981 cell.colSpan = cs; 982 cell.className = "button"; 983 if (navtype != 0 && Math.abs(navtype) <= 2) 984 cell.className += " nav"; 985 Calendar._add_evs(cell); 986 cell.calendar = cal; 987 cell.navtype = navtype; 988 cell.innerHTML = "<div unselectable='on'>
988" + text + "</div>"; 989 return cell; 990 }; 991 992 row = Calendar.createElement("tr", thead); 993 var title_length = 6; 994 (this.isPopup) && --title_length; 995 (this.weekNumbers) && ++title_length; 996 997 hh("?", 1, 400).ttip = Calendar._TT["INFO"]; 998 this.title = hh("", title_length, 300); 999 this.title.className = "title"; 1000 if (this.isPopup) { 1001 this.title.ttip = Calendar._TT["DRAG_TO_MOVE"]; 1002 this.title.style.cursor = "move"; 1003 hh("×", 1, 200).ttip = Calendar._TT["CLOSE"]; 1004 } 1005 1006 row = Calendar.createElement("tr", thead); 1007 row.className = "headrow"; 1008 1009 this._nav_py = hh("«", 1, -2); 1010 this._nav_py.ttip = Calendar._TT["PREV_YEAR"]; 1011 1012 this._nav_pm = hh("‹", 1, -1); 1013 this._nav_pm.ttip = Calendar._TT["PREV_MONTH"]; 1014 1015 this._nav_now = hh(Calendar._TT["TODAY"], this.weekNumbers ? 4 : 3, 0); 1016 this._nav_now.ttip = Calendar._TT["GO_TODAY"]; 1017 1018 this._nav_nm = hh("›", 1, 1); 1019 this._nav_nm.ttip = Calendar._TT["NEXT_MONTH"]; 1020 1021 this._nav_ny = hh("»", 1, 2); 1022 this._nav_ny.ttip = Calendar._TT["NEXT_YEAR"]; 1023 1024 // day names 1025 row = Calendar.createElement("tr", thead); 1026 row.className = "daynames"; 1027 if (this.weekNumbers) { 1028 cell = Calendar.createElement("td", row); 1029 cell.className = "name wn"; 1030 cell.innerHTML = Calendar._TT["WK"]; 1031 } 1032 for (var i = 7; i > 0; --i) { 1033 cell = Calendar.createElement("td", row); 1034 if (!i) { 1035 cell.navtype = 100; 1036 cell.calendar = this; 1037 Calendar._add_evs(cell); 1038 } 1039 } 1040 this.firstdayname = (this.weekNumbers) ? row.firstChild.nextSibling : row.firstChild; 1041 this._displayWeekdays(); 1042 1043 var tbody = Calendar.createElement("tbody", table); 1044 this.tbody = tbody; 1045 1046 for (i = 6; i > 0; --i) { 1047 row = Calendar.createElement("tr", tbody); 1048 if (this.weekNumbers) { 1049 cell = Calendar.createElement("td", row); 1050 } 1051 for (var j = 7; j > 0; --j) { 1052 cell = Calendar.createElement("td", row); 1053 cell.calendar = this; 1054 Calendar._add_evs(cell); 1055 } 1056 } 1057 1058 if (this.showsTime) { 1059 row = Calendar.createElement("tr", tbody); 1060 row.className = "time"; 1061 1062 cell = Calendar.createElement("td", row); 1063 cell.className = "time"; 1064 cell.colSpan = 2; 1065 cell.innerHTML = Calendar._TT["TIME"] || " "; 1066 1067 cell = Calendar.createElement("td", row); 1068 cell.className = "time"; 1069 cell.colSpan = this.weekNumbers ? 4 : 3; 1070 1071 (function () { 1072 function makeTimePart(className, init, range_start, range_end) { 1073 var part = Calendar.createElement("span", cell); 1074 part.className = className; 1075 part.innerHTML = init; 1076 part.calendar = cal; 1077 part.ttip = Calendar._TT["TIME_PART"]; 1078 part.navtype = 50; 1079 part._range = []; 1080 if (typeof range_start != "number") 1081 part._range = range_start; 1082 else { 1083 for (var i = range_start; i <= range_end; ++i) { 1084 var txt; 1085 if (i < 10 && range_end >= 10) txt = '0' + i; 1086 else txt = '' + i; 1087 part._range[part._range.length] = txt; 1088 } 1089 } 1090 Calendar._add_evs(part); 1091 return part; 1092 }; 1093 var hrs = cal.date.getHours(); 1094 var mins = cal.date.getMinutes(); 1095 var t12 = !cal.time24; 1096 var pm = (hrs > 12); 1097 if (t12 && pm) hrs -= 12; 1098 var H = makeTimePart("hour", hrs, t12 ? 1 : 0, t12 ? 12 : 23); 1099 var span = Calendar.createElement("span", cell); 1100 span.innerHTML = ":"; 1101 span.className = "colon"; 1102 var M = makeTimePart("minute", mins, 0, 59); 1103 var AP = null; 1104 cell = Calendar.createElement("td", row); 1105 cell.className = "time"; 1106 cell.colSpan = 2; 1107 if (t12) 1108 AP = makeTimePart("ampm", pm ? "pm" : "am", ["am", "pm"]); 1109 else 1110 cell.innerHTML = " "; 1111 1112 cal.onSetTime = function () { 1113 var pm, hrs = this.date.getHours(), 1114 mins = this.date.getMinutes(); 1115 if (t12) { 1116 pm = (hrs >= 12); 1117 if (pm) hrs -= 12; 1118 if (hrs == 0) hrs = 12; 1119 AP.innerHTML = pm ? "pm" : "am"; 1120 } 1121 H.innerHTML = (hrs < 10) ? ("0" + hrs) : hrs; 1122 M.innerHTML = (mins < 10) ? ("0" + mins) : mins; 1123 }; 1124 1125 cal.onUpdateTime = function () { 1126 var date = this.date; 1127 var h = parseInt(H.innerHTML, 10); 1128 if (t12) { 1129 if (/pm/i.test(AP.innerHTML) && h < 12) 1130 h += 12; 1131 else if (/am/i.test(AP.innerHTML) && h == 12) 1132 h = 0; 1133 } 1134 var d = date.getDate(); 1135 var m = date.getMonth(); 1136 var y = date.getFullYear(); 1137 date.setHours(h); 1138 date.setMinutes(parseInt(M.innerHTML, 10)); 1139 date.setFullYear(y); 1140 date.setMonth(m); 1141 date.setDate(d); 1142 this.dateClicked = false; 1143 this.callHandler(); 1144 }; 1145 })(); 1146 } else { 1147 this.onSetTime = this.onUpdateTime = function () { }; 1148 } 1149 1150 var tfoot = Calendar.createElement("tfoot", table); 1151
1152 row = Calendar.createElement("tr", tfoot); 1153 row.className = "footrow"; 1154 1155 cell = hh(Calendar._TT["SEL_DATE"], this.weekNumbers ? 8 : 7, 300); 1156 cell.className = "ttip"; 1157 if (this.isPopup) { 1158 cell.ttip = Calendar._TT["DRAG_TO_MOVE"]; 1159 cell.style.cursor = "move"; 1160 } 1161 this.tooltips = cell; 1162 1163 div = Calendar.createElement("div", this.element); 1164 this.monthsCombo = div; 1165 div.className = "combo"; 1166 for (i = 0; i < Calendar._MN.length; ++i) { 1167 var mn = Calendar.createElement("div"); 1168 mn.className = Calendar.is_ie ? "label-IEfix" : "label"; 1169 mn.month = i; 1170 mn.innerHTML = Calendar._SMN[i]; 1171 div.appendChild(mn); 1172 } 1173 1174 div = Calendar.createElement("div", this.element); 1175 this.yearsCombo = div; 1176 div.className = "combo"; 1177 for (i = 12; i > 0; --i) { 1178 var yr = Calendar.createElement("div"); 1179 yr.className = Calendar.is_ie ? "label-IEfix" : "label"; 1180 div.appendChild(yr); 1181 } 1182 1183 this._init(this.firstDayOfWeek, this.date); 1184 parent.appendChild(this.element); 1185}; 1186 1187/** keyboard navigation, only for popup calendars */ 1188Calendar._keyEvent = function(ev) { 1189 var cal = window._dynarch_popupCalendar; 1190 if (!cal || cal.multiple) 1191 return false; 1192 (Calendar.is_ie) && (ev = window.event); 1193 var act = (Calendar.is_ie || ev.type == "keypress"), 1194 K = ev.keyCode; 1195 if (ev.ctrlKey) { 1196 switch (K) { 1197 case 37: // KEY left 1198 act && Calendar.cellClick(cal._nav_pm); 1199 break; 1200 case 38: // KEY up 1201 act && Calendar.cellClick(cal._nav_py); 1202 break; 1203 case 39: // KEY right 1204 act && Calendar.cellClick(cal._nav_nm); 1205 break; 1206 case 40: // KEY down 1207 act && Calendar.cellClick(cal._nav_ny); 1208 break; 1209 default: 1210 return false; 1211 } 1212 } else switch (K) { 1213 case 32: // KEY space (now) 1214 Calendar.cellClick(cal._nav_now); 1215 break; 1216 case 27: // KEY esc 1217 act && cal.callCloseHandler(); 1218 break; 1219 case 37: // KEY left 1220 case 38: // KEY up 1221 case 39: // KEY right 1222 case 40: // KEY down 1223 if (act) { 1224 var prev, x, y, ne, el, step; 1225 prev = K == 37 || K == 38; 1226 step = (K == 37 || K == 39) ? 1 : 7; 1227 function setVars() { 1228 el = cal.currentDateEl; 1229 var p = el.pos; 1230 x = p & 15; 1231 y = p >> 4; 1232 ne = cal.ar_days[y][x]; 1233 };setVars(); 1234 function prevMonth() { 1235 var date = new Date(cal.date); 1236 date.setDate(date.getDate() - step); 1237 cal.setDate(date); 1238 }; 1239 function nextMonth() { 1240 var date = new Date(cal.date); 1241 date.setDate(date.getDate() + step); 1242 cal.setDate(date); 1243 }; 1244 while (1) { 1245 switch (K) { 1246 case 37: // KEY left 1247 if (--x >= 0) 1248 ne = cal.ar_days[y][x]; 1249 else { 1250 x = 6; 1251 K = 38; 1252 continue; 1253 } 1254 break; 1255 case 38: // KEY up 1256 if (--y >= 0) 1257 ne = cal.ar_days[y][x]; 1258 else { 1259 prevMonth(); 1260 setVars(); 1261 } 1262 break; 1263 case 39: // KEY right 1264 if (++x < 7) 1265 ne = cal.ar_days[y][x]; 1266 else { 1267 x = 0; 1268 K = 40; 1269 continue; 1270 } 1271 break; 1272 case 40: // KEY down 1273 if (++y < cal.ar_days.length) 1274 ne = cal.ar_days[y][x]; 1275 else { 1276 nextMonth(); 1277 setVars(); 1278 } 1279 break; 1280 } 1281 break; 1282 } 1283 if (ne) { 1284 if (!ne.disabled) 1285 Calendar.cellClick(ne); 1286 else if (prev) 1287 prevMonth(); 1288 else 1289 nextMonth(); 1290 } 1291 } 1292 break; 1293 case 13: // KEY enter 1294 if (act) 1295 Calendar.cellClick(cal.currentDateEl, ev); 1296 break; 1297 default: 1298 return false; 1299 } 1300 return Calendar.stopEvent(ev); 1301}; 1302 1303/** 1304 * (RE)Initializes the calendar to the given date and firstDayOfWeek 1305 */ 1306Calendar.prototype._init = function (firstDayOfWeek, date) { 1307 var today = new Date(), 1308 TY = today.getFullYear(), 1309 TM = today.getMonth(), 1310 TD = today.getDate(); 1311 this.table.style.visibility = "hidden"; 1312 var year = date.getFullYear(); 1313 if (parseInt(year, 10) < 1911) { 1314 year += 1911; 1315 } 1316 if (year < this.minYear) { 1317 year = this.minYear; 1318 date.setFullYear(year); 1319 } else if (year > this.maxYear) { 1320 year = this.maxYear; 1321 date.setFullYear(year); 1322 } 1323 this.firstDayOfWeek = firstDayOfWeek; 1324 this.date = new Date(date);
1325 var month = date.getMonth(); 1326 var mday = date.getDate(); 1327 var no_days = date.getMonthDays(); 1328 1329 // calendar voodoo for computing the first day that would actually be 1330 // displayed in the calendar, even if it's from the previous month. 1331 // WARNING: this is magic. ;-) 1332 date.setDate(1); 1333 var day1 = (date.getDay() - this.firstDayOfWeek) % 7; 1334 if (day1 < 0) 1335 day1 += 7; 1336 date.setDate(-day1); 1337 date.setDate(date.getDate() + 1); 1338 1339 var row = this.tbody.firstChild; 1340 var MN = Calendar._SMN[month]; 1341 var ar_days = this.ar_days = new Array(); 1342 var weekend = Calendar._TT["WEEKEND"]; 1343 var dates = this.multiple ? (this.datesCells = {}) : null; 1344 for (var i = 0; i < 6; ++i, row = row.nextSibling) { 1345 var cell = row.firstChild; 1346 if (this.weekNumbers) { 1347 cell.className = "day wn"; 1348 cell.innerHTML = date.getWeekNumber(); 1349 cell = cell.nextSibling; 1350 } 1351 row.className = "daysrow"; 1352 var hasdays = false, iday, dpos = ar_days[i] = []; 1353 for (var j = 0; j < 7; ++j, cell = cell.nextSibling, date.setDate(iday + 1)) { 1354 iday = date.getDate(); 1355 var wday = date.getDay(); 1356 cell.className = "day"; 1357 cell.pos = i << 4 | j; 1358 dpos[j] = cell; 1359 var current_month = (date.getMonth() == month); 1360 if (!current_month) { 1361 if (this.showsOtherMonths) { 1362 cell.className += " othermonth"; 1363 cell.otherMonth = true; 1364 } else { 1365 cell.className = "emptycell"; 1366 cell.innerHTML = " "; 1367 cell.disabled = true; 1368 continue; 1369 } 1370 } else { 1371 cell.otherMonth = false; 1372 hasdays = true; 1373 } 1374 cell.disabled = false; 1375 cell.innerHTML = this.getDateText ? this.getDateText(date, iday) : iday; 1376 if (dates) 1377 dates[date.print("%Y%m%d")] = cell; 1378 if (this.getDateStatus) { 1379 var status = this.getDateStatus(date, year, month, iday); 1380 if (this.getDateToolTip) { 1381 var toolTip = this.getDateToolTip(date, year, month, iday); 1382 if (toolTip) 1383 cell.title = toolTip; 1384 } 1385 if (status === true) { 1386 cell.className += " disabled"; 1387 cell.disabled = true; 1388 } else { 1389 if (/disabled/i.test(status)) 1390 cell.disabled = true; 1391 cell.className += " " + status; 1392 } 1393 } 1394 if (!cell.disabled) { 1395 cell.caldate = new Date(date); 1396 cell.ttip = "_"; 1397 if (!this.multiple && current_month 1398 && iday == mday && this.hiliteToday) { 1399 cell.className += " selected"; 1400 this.currentDateEl = cell; 1401 } 1402 if (date.getFullYear() == TY && 1403 date.getMonth() == TM && 1404 iday == TD) { 1405 cell.className += " today"; 1406 cell.ttip += Calendar._TT["PART_TODAY"]; 1407 } 1408 if (weekend.indexOf(wday.toString()) != -1) 1409 cell.className += cell.otherMonth ? " oweekend" : " weekend"; 1410 } 1411 } 1412 if (!(hasdays || this.showsOtherMonths)) 1413 row.className = "emptyrow"; 1414 } 1415 //topcat 1416 //this.title.innerHTML = Calendar._MN[month] + ", " + year; 1417 //alert("Show:" + year); 1418 if (parseInt(year, 10) > 1911) 1419 this.title.innerHTML = "æ°å" + (parseInt(year, 10) - 1911).toString() + "å¹´ ," + Calendar._MN[month]; //topcat 1420 else 1421 this.title.innerHTML = "æ°å" + (parseInt(year, 10)).toString() + "å¹´ ," + Calendar._MN[month]; //topcat 1422 this.onSetTime(); 1423 this.table.style.visibility = "visible"; 1424 this._initMultipleDates();
1425 // PROFILE 1426 // this.tooltips.innerHTML = "Generated in " + ((new Date()) - today) + " ms"; 1427}; 1428 1429Calendar.prototype._initMultipleDates = function() { 1430 if (this.multiple) { 1431 for (var i in this.multiple) { 1432 var cell = this.datesCells[i]; 1433 var d = this.multiple[i]; 1434 if (!d) 1435 continue; 1436 if (cell) 1437 cell.className += " selected"; 1438 } 1439 } 1440}; 1441 1442Calendar.prototype._toggleMultipleDate = function(date) { 1443 if (this.multiple) { 1444 var ds = date.print("%Y%m%d"); 1445 var cell = this.datesCells[ds]; 1446 if (cell) { 1447 var d = this.multiple[ds]; 1448 if (!d) { 1449 Calendar.addClass(cell, "selected"); 1450 this.multiple[ds] = date; 1451 } else { 1452 Calendar.removeClass(cell, "selected"); 1453 delete this.multiple[ds]; 1454 } 1455 } 1456 } 1457}; 1458 1459Calendar.prototype.setDateToolTipHandler = function (unaryFunction) { 1460 this.getDateToolTip = unaryFunction; 1461}; 1462 1463/** 1464 * Calls _init function above for going to a certain date (but only if the 1465 * date is different than the currently selected one). 1466 */ 1467Calendar.prototype.setDate = function (date) { 1468 if (!date.equalsTo(this.date)) { 1469 this._init(this.firstDayOfWeek, date); 1470 } 1471}; 1472 1473/** 1474 * Refreshes the calendar. Useful if the "disabledHandler" function is 1475 * dynamic, meaning that the list of disabled date can change at runtime. 1476 * Just * call this function if you think that the list of disabled dates 1477 * should * change. 1478 */ 1479Calendar.prototype.refresh = function () { 1480 this._init(this.firstDayOfWeek, this.date); 1481}; 1482 1483/** Modifies the "firstDayOfWeek" parameter (pass 0 for Synday, 1 for Monday, etc.). */ 1484Calendar.prototype.setFirstDayOfWeek = function (firstDayOfWeek) { 1485 this._init(firstDayOfWeek, this.date); 1486 this._displayWeekdays(); 1487}; 1488 1489/** 1490 * Allows customization of what dates are enabled. The "unaryFunction" 1491 * parameter must be a function object that receives the date (as a JS Date 1492 * object) and returns a boolean value. If the returned value is true then 1493 * the passed date will be marked as disabled. 1494 */ 1495Calendar.prototype.setDateStatusHandler = Calendar.prototype.setDisabledHandler = function (unaryFunction) { 1496 this.getDateStatus = unaryFunction; 1497}; 1498 1499/** Customization of allowed year range for the calendar. */ 1500Calendar.prototype.setRange = function (a, z) { 1501 this.minYear = a; 1502 this.maxYear = z; 1503}; 1504 1505/** Calls the first user handler (selectedHandler). */ 1506Calendar.prototype.callHandler = function () { 1507 if (this.onSelected) { 1508 this.onSelected(this, this.date.print(this.dateFormat)); 1509 } 1510}; 1511 1512/** Calls the second user handler (closeHandler). */ 1513Calendar.prototype.callCloseHandler = function () { 1514 if (this.onClose) { 1515 this.onClose(this); 1516 } 1517 this.hideShowCovered(); 1518}; 1519 1520/** Removes the calendar object from the DOM tree and destroys it. */ 1521Calendar.prototype.destroy = function () { 1522 var el = this.element.parentNode; 1523 el.removeChild(this.element); 1524 Calendar._C = null; 1525 window._dynarch_popupCalendar = null; 1526}; 1527 1528/** 1529 * Moves the calendar element to a different section in the DOM tree (changes 1530 * its parent). 1531 */ 1532Calendar.prototype.reparent = function (new_parent) { 1533 var el = this.element; 1534 el.parentNode.removeChild(el); 1535 new_parent.appendChild(el); 1536}; 1537 1538// This gets called when the user presses a mouse button anywhere in the 1539// document, if the calendar is shown. If the click was outside the open 1540// calendar this function closes it. 1541Calendar._checkCalendar = function(ev) { 1542 var calendar = window._dynarch_popupCalendar; 1543 if (!calendar) { 1544 return false; 1545 } 1546 var el = Calendar.is_ie ? Calendar.getElement(ev) : Calendar.getTargetElement(ev); 1547 for (; el != null && el != calendar.element; el = el.parentNode); 1548 if (el == null) { 1549 // calls closeHandler which should hide the calendar. 1550 window._dynarch_popupCalendar.callCloseHandler(); 1551 return Calendar.stopEvent(ev); 1552 } 1553}; 1554 1555/** Shows the calendar. */ 1556Calendar.prototype.show = function () { 1557 var rows = this.table.getElementsByTagName("tr"); 1558 for (var i = rows.length; i > 0;) { 1559 var row = rows[--i]; 1560 Calendar.removeClass(row, "rowhilite"); 1561 var cells = row.getElementsByTagName("td"); 1562 for (var j = cells.length; j > 0;) { 1563 var cell = cells[--j]; 1564 Calendar.removeClass(cell, "hilite"); 1565 Calendar.removeClass(cell, "active"); 1566 } 1567 } 1568 this.element.style.display = "block"; 1569 this.hidden = false; 1570 if (this.isPopup) { 1571 window._dynarch_popupCalendar = this; 1572 Calendar.addEvent(document, "keydown", Calendar._keyEvent); 1573 Calendar.addEvent(document, "keypress", Calendar._keyEvent); 1574 Calendar.addEvent(document, "mousedown", Calendar._checkCalendar); 1575 } 1576 this.hideShowCovered(); 1577}; 1578 1579/** 1580 * Hides the calendar. Also removes any "hilite" from the class of any TD 1581 * element. 1582 */ 1583Calendar.prototype.hide = function () { 1584 if (this.isPopup) { 1585 Calendar.removeEvent(document, "keydown", Calendar._keyEvent); 1586 Calendar.removeEvent(document, "keypress", Calendar._keyEvent); 1587 Calendar.removeEvent(document, "mousedown", Calendar._checkCalendar); 1588 } 1589 this.element.style.display = "none"; 1590 this.hidden = true; 1591 this.hideShowCovered(); 1592}; 1593 1594/** 1595 * Shows the calendar at a given absolute position (beware that, depending on 1596 * the calendar element style -- position property -- this might be relative 1597 * to the parent's containing rectangle). 1598 */ 1599Calendar.prototype.showAt = function (x, y) { 1600 var s = this.element.style; 1601 s.left = x + "px"; 1602 s.top = y + "px"; 1603 this.show(); 1604}; 1605 1606/** Shows the calendar near a given element. */ 1607Calendar.prototype.showAtElement = function (el, opts) { 1608 var self = this; 1609 var p = Calendar.getAbsolutePos(el); 1610 if (!opts || typeof opts != "string") { 1611 this.showAt(p.x, p.y + el.offsetHeight); 1612 return true; 1613 } 1614 function fixPosition(box) { 1615 if (box.x < 0) 1616 box.x = 0; 1617 if (box.y < 0) 1618 box.y = 0; 1619 var cp = document.createElement("div"); 1620 var s = cp.style; 1621 s.position = "absolute"; 1622 s.right = s.bottom = s.width = s.height = "0px"; 1623 document.body.appendChild(cp); 1624 var br = Calendar.getAbsolutePos(cp); 1625 document.body.removeChild(cp); 1626 if (Calendar.is_ie) { 1627 br.y += document.body.scrollTop; 1628 br.x += document.body.scrollLeft; 1629 } else { 1630 br.y += window.scrollY; 1631 br.x += window.scrollX; 1632 } 1633 var tmp = box.x + box.width - br.x; 1634 if (tmp > 0) box.x -= tmp; 1635 tmp = box.y + box.height - br.y; 1636 if (tmp > 0) box.y -= tmp; 1637 }; 1638 this.element.style.display = "block"; 1639 Calendar.continuation_for_the_fucking_khtml_browser = function() { 1640 var w = self.element.offsetWidth;
1641 var h = self.element.offsetHeight; 1642 self.element.style.display = "none"; 1643 var valign = opts.substr(0, 1); 1644 var halign = "l"; 1645 if (opts.length > 1) { 1646 halign = opts.substr(1, 1); 1647 } 1648 // vertical alignment 1649 switch (valign) { 1650 case "T": p.y -= h; break; 1651 case "B": p.y += el.offsetHeight; break; 1652 case "C": p.y += (el.offsetHeight - h) / 2; break; 1653 case "t": p.y += el.offsetHeight - h; break; 1654 case "b": break; // already there 1655 } 1656 // horizontal alignment 1657 switch (halign) { 1658 case "L": p.x -= w; break; 1659 case "R": p.x += el.offsetWidth; break; 1660 case "C": p.x += (el.offsetWidth - w) / 2; break; 1661 case "l": p.x += el.offsetWidth - w; break; 1662 case "r": break; // already there 1663 } 1664 p.width = w; 1665 p.height = h + 40; 1666 self.monthsCombo.style.display = "none"; 1667 fixPosition(p); 1668 self.showAt(p.x, p.y); 1669 }; 1670 if (Calendar.is_khtml) 1671 setTimeout("Calendar.continuation_for_the_fucking_khtml_browser()", 10); 1672 else 1673 Calendar.continuation_for_the_fucking_khtml_browser(); 1674}; 1675 1676/** Customizes the date format. */ 1677Calendar.prototype.setDateFormat = function (str) { 1678 this.dateFormat = str; 1679}; 1680 1681/** Customizes the tooltip date format. */ 1682Calendar.prototype.setTtDateFormat = function (str) { 1683 this.ttDateFormat = str; 1684}; 1685 1686/** 1687 * Tries to identify the date represented in a string. If successful it also 1688 * calls this.setDate which moves the calendar to the given date. 1689 */ 1690Calendar.prototype.parseDate = function(str, fmt) { 1691 if (!fmt) 1692 fmt = this.dateFormat; 1693 this.setDate(Date.parseDate(str, fmt)); 1694}; 1695 1696Calendar.prototype.hideShowCovered = function () { 1697 if (!Calendar.is_ie && !Calendar.is_opera) 1698 return; 1699 function getVisib(obj){ 1700 var value = obj.style.visibility; 1701 if (!value) { 1702 if (document.defaultView && typeof (document.defaultView.getComputedStyle) == "function") { // Gecko, W3C 1703 if (!Calendar.is_khtml) 1704 value = document.defaultView. 1705 getComputedStyle(obj, "").getPropertyValue("visibility"); 1706 else 1707 value = ''; 1708 } else if (obj.currentStyle) { // IE 1709 value = obj.currentStyle.visibility; 1710 } else 1711 value = ''; 1712 } 1713 return value; 1714 }; 1715 1716 var tags = new Array("applet", "iframe", "select"); 1717 var el = this.element; 1718 1719 var p = Calendar.getAbsolutePos(el); 1720 var EX1 = p.x; 1721 var EX2 = el.offsetWidth + EX1; 1722 var EY1 = p.y; 1723 var EY2 = el.offsetHeight + EY1; 1724 1725 for (var k = tags.length; k > 0; ) { 1726 var ar = document.getElementsByTagName(tags[--k]); 1727 var cc = null; 1728 1729 for (var i = ar.length; i > 0;) { 1730 cc = ar[--i]; 1731 1732 p = Calendar.getAbsolutePos(cc); 1733 var CX1 = p.x; 1734 var CX2 = cc.offsetWidth + CX1; 1735 var CY1 = p.y; 1736 var CY2 = cc.offsetHeight + CY1; 1737 1738 if (this.hidden || (CX1 > EX2) || (CX2 < EX1) || (CY1 > EY2) || (CY2 < EY1)) { 1739 if (!cc.__msh_save_visibility) { 1740 cc.__msh_save_visibility = getVisib(cc); 1741 } 1742 cc.style.visibility = cc.__msh_save_visibility; 1743 } else { 1744 if (!cc.__msh_save_visibility) { 1745 cc.__msh_save_visibility = getVisib(cc); 1746 } 1747 cc.style.visibility = "hidden"; 1748 } 1749 } 1750 } 1751}; 1752 1753/** Internal function; it displays the bar with the names of the weekday. */ 1754Calendar.prototype._displayWeekdays = function () { 1755 var fdow = this.firstDayOfWeek; 1756 var cell = this.firstdayname; 1757 var weekend = Calendar._TT["WEEKEND"]; 1758 for (var i = 0; i < 7; ++i) { 1759 cell.className = "day name"; 1760 var realday = (i + fdow) % 7; 1761 if (i) { 1762 cell.ttip = Calendar._TT["DAY_FIRST"].replace("%s", Calendar._DN[realday]); 1763 cell.navtype = 100; 1764 cell.calendar = this; 1765 cell.fdow = realday; 1766 Calendar._add_evs(cell); 1767 } 1768 if (weekend.indexOf(realday.toString()) != -1) { 1769 Calendar.addClass(cell, "weekend"); 1770 } 1771 cell.innerHTML = Calendar._SDN[(i + fdow) % 7]; 1772 cell = cell.nextSibling; 1773 } 1774}; 1775 1776/** Internal function. Hides all combo boxes that might be displayed. */ 1777Calendar.prototype._hideCombos = function () { 1778 this.monthsCombo.style.display = "none"; 1779 this.yearsCombo.style.display = "none"; 1780}; 1781 1782/** Internal function. Starts dragging the element. */ 1783Calendar.prototype._dragStart = function (ev) { 1784 if (this.dragging) { 1785 return; 1786 } 1787 this.dragging = true; 1788 var posX; 1789 var posY; 1790 if (Calendar.is_ie) { 1791 posY = window.event.clientY + document.body.scrollTop; 1792 posX = window.event.clientX + document.body.scrollLeft; 1793 } else { 1794 posY = ev.clientY + window.scrollY; 1795 posX = ev.clientX + window.scrollX; 1796 } 1797 var st = this.element.style; 1798 this.xOffs = posX - parseInt(st.left); 1799 this.yOffs = posY - parseInt(st.top); 1800 with (Calendar) { 1801 addEvent(document, "mousemove", calDragIt); 1802 addEvent(document, "mouseup", calDragEnd); 1803 } 1804}; 1805 1806// BEGIN: DATE OBJECT PATCHES 1807 1808/** Adds the number of days array to the Date object. */ 1809Date._MD = new Array(31,28,31,30,31,30,31,31,30,31,30,31); 1810 1811/** Constants used for time computations */ 1812Date.SECOND = 1000 /* milliseconds */; 1813Date.MINUTE = 60 * Date.SECOND; 1814Date.HOUR = 60 * Date.MINUTE; 1815Date.DAY = 24 * Date.HOUR; 1816Date.WEEK = 7 * Date.DAY; 1817 1818Date.parseDate = function (str, fmt) { 1819 var today = new Date(); 1820 var y = 0; 1821 var m = -1; 1822 var d = 0; 1823 var a = str.split(/\W+/); 1824 var b = fmt.match(/%./g); 1825 var i = 0, j = 0; 1826 var hr = 0; 1827 var min = 0; 1828 for (i = 0; i < a.length; ++i) { 1829 if (!a[i]) 1830 continue; 1831 switch (b[i]) { 1832 case "%d": 1833 case "%e": 1834 d = parseInt(a[i], 10); 1835 break; 1836 1837 case "%m": 1838 m = parseInt(a[i], 10) - 1; 1839 break; 1840 1841 case "%Y": 1842 1843 case "%y": 1844 y = parseInt(a[i], 10); 1845 (y < 100) && (y += (y > 29) ? 1900 : 2000); 1846 break; 1847 1848 case "%b": 1849 case "%B": 1850 for (j = 0; j < 12; ++j) { 1851 if (Calendar._MN[j].substr(0, a[i].length).toLowerCase() == a[i].toLowerCase()) { m = j; break; } 1852 } 1853 break; 1854 1855 case "%H": 1856 case "%I": 1857 case "%k": 1858 case "%l": 1859 hr = parseInt(a[i], 10); 1860 break; 1861 1862 case "%P": 1863 case "%p": 1864 if (/pm/i.test(a[i]) && hr < 12) 1865 hr += 12; 1866 else if (/am/i.test(a[i]) && hr >= 12) 1867 hr -= 12; 1868 break; 1869
1870 case "%M": 1871 min = parseInt(a[i], 10); 1872 break; 1873 } 1874 } 1875 if (isNaN(y)) y = today.getFullYear(); 1876 if (isNaN(m)) m = today.getMonth(); 1877 if (isNaN(d)) d = today.getDate(); 1878 if (isNaN(hr)) hr = today.getHours(); 1879 if (isNaN(min)) min = today.getMinutes(); 1880 if (y != 0 && m != -1 && d != 0) 1881 return new Date(y, m, d, hr, min, 0); 1882 y = 0; m = -1; d = 0; 1883 for (i = 0; i < a.length; ++i) { 1884 if (a[i].search(/[a-zA-Z]+/) != -1) { 1885 var t = -1; 1886 for (j = 0; j < 12; ++j) { 1887 if (Calendar._MN[j].substr(0, a[i].length).toLowerCase() == a[i].toLowerCase()) { t = j; break; } 1888 } 1889 if (t != -1) { 1890 if (m != -1) { 1891 d = m + 1; 1892 } 1893 m = t; 1894 } 1895 } else if (parseInt(a[i], 10) <= 12 && m == -1) { 1896 m = a[i] - 1; 1897 } else if (parseInt(a[i], 10) > 31 && y == 0) { 1898 y = parseInt(a[i], 10); 1899 if (y < 1911) 1900 y += 1911; 1901 //alert("test:" + y); 1902 //(y < 100) && (y += (y > 29) ? 1900 : 2000); 1903 } else if (d == 0) { 1904 d = a[i]; 1905 } 1906 } 1907 if (y == 0) 1908 y = today.getFullYear(); 1909 if (m != -1 && d != 0) 1910 return new Date(y, m, d, hr, min, 0); 1911 return today; 1912}; 1913 1914/** Returns the number of days in the current month */ 1915Date.prototype.getMonthDays = function(month) { 1916 var year = this.getFullYear(); 1917 if (typeof month == "undefined") { 1918 month = this.getMonth(); 1919 } 1920 if (((0 == (year%4)) && ( (0 != (year%100)) || (0 == (year%400)))) && month == 1) { 1921 return 29; 1922 } else { 1923 return Date._MD[month]; 1924 } 1925}; 1926 1927/** Returns the number of day in the year. */ 1928Date.prototype.getDayOfYear = function() { 1929 var now = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0, 0); 1930 var then = new Date(this.getFullYear(), 0, 0, 0, 0, 0); 1931 var time = now - then; 1932 return Math.floor(time / Date.DAY); 1933}; 1934 1935/** Returns the number of the week in year, as defined in ISO 8601. */ 1936Date.prototype.getWeekNumber = function() { 1937 var d = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0, 0); 1938 var DoW = d.getDay(); 1939 d.setDate(d.getDate() - (DoW + 6) % 7 + 3); // Nearest Thu 1940 var ms = d.valueOf(); // GMT 1941 d.setMonth(0); 1942 d.setDate(4); // Thu in Week 1 1943 return Math.round((ms - d.valueOf()) / (7 * 864e5)) + 1; 1944}; 1945 1946/** Checks date and time equality */ 1947Date.prototype.equalsTo = function(date) { 1948 return ((this.getFullYear() == date.getFullYear()) && 1949 (this.getMonth() == date.getMonth()) && 1950 (this.getDate() == date.getDate()) && 1951 (this.getHours() == date.getHours()) && 1952 (this.getMinutes() == date.getMinutes())); 1953}; 1954 1955/** Set only the year, month, date parts (keep existing time) */ 1956Date.prototype.setDateOnly = function(date) { 1957 var tmp = new Date(date); 1958 this.setDate(1); 1959 this.setFullYear(tmp.getFullYear()); 1960 this.setMonth(tmp.getMonth()); 1961 this.setDate(tmp.getDate()); 1962}; 1963 1964/** Prints the date in a string according to the given format. */ 1965Date.prototype.print = function (str) { 1966 var m = this.getMonth(); 1967 var d = this.getDate(); 1968 var y = this.getFullYear(); 1969 var wn = this.getWeekNumber(); 1970 var w = this.getDay(); 1971 var s = {}; 1972 var hr = this.getHours(); 1973 var pm = (hr >= 12); 1974 var ir = (pm) ? (hr - 12) : hr; 1975 var dy = this.getDayOfYear(); 1976 if (ir == 0) 1977 ir = 12; 1978 var min = this.getMinutes(); 1979 var sec = this.getSeconds(); 1980 s["%a"] = Calendar._SDN[w]; // abbreviated weekday name [FIXME: I18N] 1981 s["%A"] = Calendar._DN[w]; // full weekday name 1982 s["%b"] = Calendar._SMN[m]; // abbreviated month name [FIXME: I18N] 1983 s["%B"] = Calendar._MN[m]; // full month name 1984 // FIXME: %c : preferred date and time representation for the current locale 1985 s["%C"] = 1 + Math.floor(y / 100); // the century number 1986 s["%d"] = (d < 10) ? ("0" + d) : d; // the day of the month (range 01 to 31) 1987 s["%e"] = d; // the day of the month (range 1 to 31) 1988 // FIXME: %D : american date style: %m/%d/%y
1989 // FIXME: %E, %F, %G, %g, %h (man strftime) 1990 s["%H"] = (hr < 10) ? ("0" + hr) : hr; // hour, range 00 to 23 (24h format) 1991 s["%I"] = (ir < 10) ? ("0" + ir) : ir; // hour, range 01 to 12 (12h format) 1992 s["%j"] = (dy < 100) ? ((dy < 10) ? ("00" + dy) : ("0" + dy)) : dy; // day of the year (range 001 to 366) 1993 s["%k"] = hr; // hour, range 0 to 23 (24h format) 1994 s["%l"] = ir; // hour, range 1 to 12 (12h format) 1995 s["%m"] = (m < 9) ? ("0" + (1 + m)) : (1 + m); // month, range 01 to 12 1996 s["%M"] = (min < 10) ? ("0" + min) : min; // minute, range 00 to 59 1997 s["%n"] = "\n"; // a newline character 1998 s["%p"] = pm ? "PM" : "AM"; 1999 s["%P"] = pm ? "pm" : "am"; 2000 // FIXME: %r : the time in am/pm notation %I:%M:%S %p 2001 // FIXME: %R : the time in 24-hour notation %H:%M 2002 s["%s"] = Math.floor(this.getTime() / 1000); 2003 s["%S"] = (sec < 10) ? ("0" + sec) : sec; // seconds, range 00 to 59 2004 s["%t"] = "\t"; // a tab character 2005 // FIXME: %T : the time in 24-hour notation (%H:%M:%S) 2006 s["%U"] = s["%W"] = s["%V"] = (wn < 10) ? ("0" + wn) : wn; 2007 s["%u"] = w + 1; // the day of the week (range 1 to 7, 1 = MON) 2008 s["%w"] = w; // the day of the week (range 0 to 6, 0 = SUN) 2009 // FIXME: %x : preferred date representation for the current locale without the time 2010 // FIXME: %X : preferred time representation for the current locale without the date 2011 s["%y"] = ('' + y).substr(2, 2); // year without the century (range 00 to 99) 2012 s["%Y"] = y; // year with the century 2013 //topcat 2014 s["%Z"] = (y-1911).toString(); //.substr(0,3); // year with the century 2015 2016 s["%%"] = "%"; // a literal '%' character 2017 2018 2019 var re = /%./g; 2020 if (!Calendar.is_ie5 && !Calendar.is_khtml) 2021 return str.replace(re, function (par) { return s[par] || par; }); 2022 2023 var a = str.match(re); 2024 for (var i = 0; i < a.length; i++) { 2025 var tmp = s[a[i]]; 2026 if (tmp) { 2027 re = new RegExp(a[i], 'g'); 2028 str = str.replace(re, tmp); 2029 } 2030 } 2031 2032 return str; 2033}; 2034 2035Date.prototype.__msh_oldSetFullYear = Date.prototype.setFullYear; 2036Date.prototype.setFullYear = function(y) { 2037 var d = new Date(this); 2038 d.__msh_oldSetFullYear(y); 2039 if (d.getMonth() != this.getMonth()) 2040 this.setDate(28); 2041 this.__msh_oldSetFullYear(y); 2042}; 2043 2044// END: DATE OBJECT PATCHES 2045 2046 2047// global object that remembers the calendar 2048window._dynarch_popupCalendar = null; 2049
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.