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