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