[ Index ] |
|
Code source de XOOPS 2.0.17.1 |
1 /* Copyright Mihai Bazon, 2002 | http://students.infoiasi.ro/~mishoo 2 * --------------------------------------------------------------------- 3 * 4 * The DHTML Calendar, version 0.9.2 "The art of date selection" 5 * 6 * Details and latest version at: 7 * http://students.infoiasi.ro/~mishoo/site/calendar.epl 8 * 9 * Feel free to use this script under the terms of the GNU Lesser General 10 * Public License, as long as you do not remove or alter this notice. 11 */ 12 13 // $Id: calendar.js,v 1.1 2003/03/04 10:35:31 okazu Exp $ 14 15 /** The Calendar object constructor. */ 16 Calendar = function (mondayFirst, dateStr, onSelected, onClose) { 17 // member variables 18 this.activeDiv = null; 19 this.currentDateEl = null; 20 this.checkDisabled = 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.mondayFirst = mondayFirst; 33 this.dateStr = dateStr; 34 this.ar_days = null; 35 // HTML elements 36 this.table = null; 37 this.element = null; 38 this.tbody = null; 39 this.firstdayname = null; 40 // Combo boxes 41 this.monthsCombo = null; 42 this.yearsCombo = null; 43 this.hilitedMonth = null; 44 this.activeMonth = null; 45 this.hilitedYear = null; 46 this.activeYear = null; 47 48 // one-time initializations 49 if (!Calendar._DN3) { 50 // table of short day names 51 var ar = new Array(); 52 for (var i = 8; i > 0;) { 53 ar[--i] = Calendar._DN[i].substr(0, 3); 54 } 55 Calendar._DN3 = ar; 56 // table of short month names 57 ar = new Array(); 58 for (var i = 12; i > 0;) { 59 ar[--i] = Calendar._MN[i].substr(0, 3); 60 } 61 Calendar._MN3 = ar; 62 } 63 }; 64 65 // ** constants 66 67 /// "static", needed for event handlers. 68 Calendar._C = null; 69 70 /// detect a special case of "web browser" 71 Calendar.is_ie = ( (navigator.userAgent.toLowerCase().indexOf("msie") != -1) && 72 (navigator.userAgent.toLowerCase().indexOf("opera") == -1) ); 73 74 // short day names array (initialized at first constructor call) 75 Calendar._DN3 = null; 76 77 // short month names array (initialized at first constructor call) 78 Calendar._MN3 = null; 79 80 // BEGIN: UTILITY FUNCTIONS; beware that these might be moved into a separate 81 // library, at some point. 82 83 Calendar.getAbsolutePos = function(el) { 84 var r = { x: el.offsetLeft, y: el.offsetTop }; 85 if (el.offsetParent) { 86 var tmp = Calendar.getAbsolutePos(el.offsetParent); 87 r.x += tmp.x; 88 r.y += tmp.y; 89 } 90 return r; 91 }; 92 93 Calendar.isRelated = function (el, evt) { 94 var related = evt.relatedTarget; 95 if (!related) { 96 var type = evt.type; 97 if (type == "mouseover") { 98 related = evt.fromElement; 99 } else if (type == "mouseout") { 100 related = evt.toElement; 101 } 102 } 103 while (related) { 104 if (related == el) { 105 return true; 106 } 107 related = related.parentNode; 108 } 109 return false; 110 }; 111 112 Calendar.removeClass = function(el, className) { 113 if (!(el && el.className)) { 114 return; 115 } 116 var cls = el.className.split(" "); 117 var ar = new Array(); 118 for (var i = cls.length; i > 0;) { 119 if (cls[--i] != className) { 120 ar[ar.length] = cls[i]; 121 } 122 } 123 el.className = ar.join(" "); 124 }; 125 126 Calendar.addClass = function(el, className) { 127 Calendar.removeClass(el, className); 128 el.className += " " + className; 129 }; 130 131 Calendar.getElement = function(ev) { 132 if (Calendar.is_ie) { 133 return window.event.srcElement; 134 } else { 135 return ev.currentTarget; 136 } 137 }; 138 139 Calendar.getTargetElement = function(ev) { 140 if (Calendar.is_ie) { 141 return window.event.srcElement; 142 } else { 143 return ev.target; 144 } 145 }; 146 147 Calendar.stopEvent = function(ev) { 148 if (Calendar.is_ie) { 149 window.event.cancelBubble = true; 150 window.event.returnValue = false; 151 } else { 152 ev.preventDefault(); 153 ev.stopPropagation(); 154 } 155 }; 156 157 Calendar.addEvent = function(el, evname, func) { 158 if (Calendar.is_ie) { 159 el.attachEvent("on" + evname, func); 160 } else { 161 el.addEventListener(evname, func, true); 162 } 163 }; 164 165 Calendar.removeEvent = function(el, evname, func) { 166 if (Calendar.is_ie) { 167 el.detachEvent("on" + evname, func); 168 } else { 169 el.removeEventListener(evname, func, true); 170 } 171 }; 172 173 Calendar.createElement = function(type, parent) { 174 var el = null; 175 if (document.createElementNS) { 176 // use the XHTML namespace; IE won't normally get here unless 177 // _they_ "fix" the DOM2 implementation. 178 el = document.createElementNS("http://www.w3.org/1999/xhtml", type); 179 } else { 180 el = document.createElement(type); 181 } 182 if (typeof parent != "undefined") { 183 parent.appendChild(el); 184 } 185 return el; 186 }; 187 188 // END: UTILITY FUNCTIONS 189 190 // BEGIN: CALENDAR STATIC FUNCTIONS 191 192 /** Internal -- adds a set of events to make some element behave like a button. */ 193 Calendar._add_evs = function(el) { 194 with (Calendar) { 195 addEvent(el, "mouseover", dayMouseOver); 196 addEvent(el, "mousedown", dayMouseDown); 197 addEvent(el, "mouseout", dayMouseOut); 198 if (is_ie) { 199 addEvent(el, "dblclick", dayMouseDblClick); 200 el.setAttribute("unselectable", true); 201 } 202 } 203 }; 204 205 Calendar.findMonth = function(el) { 206 if (typeof el.month != "undefined") { 207 return el; 208 } else if (typeof el.parentNode.month != "undefined") { 209 return el.parentNode; 210 } 211 return null; 212 }; 213 214 Calendar.findYear = function(el) { 215 if (typeof el.year != "undefined") { 216 return el; 217 } else if (typeof el.parentNode.year != "undefined") { 218 return el.parentNode; 219 } 220 return null; 221 }; 222 223 Calendar.showMonthsCombo = function () { 224 var cal = Calendar._C; 225 if (!cal) { 226 return false; 227 } 228 var cal = cal; 229 var cd = cal.activeDiv; 230 var mc = cal.monthsCombo; 231 if (cal.hilitedMonth) { 232 Calendar.removeClass(cal.hilitedMonth, "hilite"); 233 } 234 if (cal.activeMonth) { 235 Calendar.removeClass(cal.activeMonth, "active"); 236 } 237 var mon = cal.monthsCombo.getElementsByTagName("div")[cal.date.getMonth()]; 238 Calendar.addClass(mon, "active"); 239 cal.activeMonth = mon; 240 mc.style.left = cd.offsetLeft + "px"; 241 mc.style.top = (cd.offsetTop + cd.offsetHeight) + "px"; 242 mc.style.display = "block"; 243 }; 244 245 Calendar.showYearsCombo = function (fwd) { 246 var cal = Calendar._C; 247 if (!cal) { 248 return false; 249 } 250 var cal = cal; 251 var cd = cal.activeDiv; 252 var yc = cal.yearsCombo; 253 if (cal.hilitedYear) { 254 Calendar.removeClass(cal.hilitedYear, "hilite"); 255 } 256 if (cal.activeYear) { 257 Calendar.removeClass(cal.activeYear, "active"); 258 } 259 cal.activeYear = null; 260 var Y = cal.date.getFullYear() + (fwd ? 1 : -1); 261 var yr = yc.firstChild; 262 var show = false; 263 for (var i = 12; i > 0; --i) { 264 if (Y >= cal.minYear && Y <= cal.maxYear) { 265 yr.firstChild.data = Y; 266 yr.year = Y; 267 yr.style.display = "block"; 268 show = true; 269 } else { 270 yr.style.display = "none"; 271 } 272 yr = yr.nextSibling; 273 Y += fwd ? 2 : -2; 274 } 275 if (show) { 276 yc.style.left = cd.offsetLeft + "px"; 277 yc.style.top = (cd.offsetTop + cd.offsetHeight) + "px"; 278 yc.style.display = "block"; 279 } 280 }; 281 282 // event handlers 283 284 Calendar.tableMouseUp = function(ev) { 285 var cal = Calendar._C; 286 if (!cal) { 287 return false; 288 } 289 if (cal.timeout) { 290 clearTimeout(cal.timeout); 291 } 292 var el = cal.activeDiv; 293 if (!el) { 294 return false; 295 } 296 var target = Calendar.getTargetElement(ev); 297 Calendar.removeClass(el, "active"); 298 if (target == el || target.parentNode == el) { 299 Calendar.cellClick(el); 300 } 301 var mon = Calendar.findMonth(target); 302 var date = null; 303 if (mon) { 304 date = new Date(cal.date); 305 if (mon.month != date.getMonth()) { 306 date.setMonth(mon.month); 307 cal.setDate(date); 308 } 309 } else { 310 var year = Calendar.findYear(target); 311 if (year) { 312 date = new Date(cal.date); 313 if (year.year != date.getFullYear()) { 314 date.setFullYear(year.year); 315 cal.setDate(date); 316 } 317 } 318 } 319 with (Calendar) { 320 removeEvent(document, "mouseup", tableMouseUp); 321 removeEvent(document, "mouseover", tableMouseOver); 322 removeEvent(document, "mousemove", tableMouseOver); 323 cal._hideCombos(); 324 stopEvent(ev); 325 _C = null; 326 } 327 }; 328 329 Calendar.tableMouseOver = function (ev) { 330 var cal = Calendar._C; 331 if (!cal) { 332 return; 333 } 334 var el = cal.activeDiv; 335 var target = Calendar.getTargetElement(ev); 336 if (target == el || target.parentNode == el) { 337 Calendar.addClass(el, "hilite active"); 338 Calendar.addClass(el.parentNode, "rowhilite"); 339 } else { 340 Calendar.removeClass(el, "active"); 341 Calendar.removeClass(el, "hilite"); 342 Calendar.removeClass(el.parentNode, "rowhilite"); 343 } 344 var mon = Calendar.findMonth(target); 345 if (mon) { 346 if (mon.month != cal.date.getMonth()) { 347 if (cal.hilitedMonth) { 348 Calendar.removeClass(cal.hilitedMonth, "hilite"); 349 } 350 Calendar.addClass(mon, "hilite"); 351 cal.hilitedMonth = mon; 352 } else if (cal.hilitedMonth) { 353 Calendar.removeClass(cal.hilitedMonth, "hilite"); 354 } 355 } else { 356 var year = Calendar.findYear(target); 357 if (year) { 358 if (year.year != cal.date.getFullYear()) { 359 if (cal.hilitedYear) { 360 Calendar.removeClass(cal.hilitedYear, "hilite"); 361 } 362 Calendar.addClass(year, "hilite"); 363 cal.hilitedYear = year; 364 } else if (cal.hilitedYear) { 365 Calendar.removeClass(cal.hilitedYear, "hilite"); 366 } 367 } 368 } 369 Calendar.stopEvent(ev); 370 }; 371 372 Calendar.tableMouseDown = function (ev) { 373 if (Calendar.getTargetElement(ev) == Calendar.getElement(ev)) { 374 Calendar.stopEvent(ev); 375 } 376 }; 377 378 Calendar.calDragIt = function (ev) { 379 var cal = Calendar._C; 380 if (!(cal && cal.dragging)) { 381 return false; 382 } 383 var posX; 384 var posY; 385 if (Calendar.is_ie) { 386 posY = window.event.clientY + document.body.scrollTop; 387 posX = window.event.clientX + document.body.scrollLeft; 388 } else { 389 posX = ev.pageX; 390 posY = ev.pageY; 391 } 392 cal.hideShowCovered(); 393 var st = cal.element.style; 394 st.left = (posX - cal.xOffs) + "px"; 395 st.top = (posY - cal.yOffs) + "px"; 396 Calendar.stopEvent(ev); 397 }; 398 399 Calendar.calDragEnd = function (ev) { 400 var cal = Calendar._C; 401 if (!cal) { 402 return false; 403 } 404 cal.dragging = false; 405 with (Calendar) { 406 removeEvent(document, "mousemove", calDragIt); 407 removeEvent(document, "mouseover", stopEvent); 408 removeEvent(document, "mouseup", calDragEnd); 409 tableMouseUp(ev); 410 } 411 cal.hideShowCovered(); 412 }; 413 414 Calendar.dayMouseDown = function(ev) { 415 var el = Calendar.getElement(ev); 416 if (el.disabled) { 417 return false; 418 } 419 var cal = el.calendar; 420 cal.activeDiv = el; 421 Calendar._C = cal; 422 if (el.navtype != 300) with (Calendar) { 423 addClass(el, "hilite active"); 424 addEvent(document, "mouseover", tableMouseOver); 425 addEvent(document, "mousemove", tableMouseOver); 426 addEvent(document, "mouseup", tableMouseUp); 427 } else if (cal.isPopup) { 428 cal._dragStart(ev); 429 } 430 Calendar.stopEvent(ev); 431 if (el.navtype == -1 || el.navtype == 1) { 432 cal.timeout = setTimeout("Calendar.showMonthsCombo()", 250); 433 } else if (el.navtype == -2 || el.navtype == 2) { 434 cal.timeout = setTimeout((el.navtype > 0) ? "Calendar.showYearsCombo(true)" : "Calendar.showYearsCombo(false)", 250); 435 } else { 436 cal.timeout = null; 437 } 438 }; 439 440 Calendar.dayMouseDblClick = function(ev) { 441 Calendar.cellClick(Calendar.getElement(ev)); 442 if (Calendar.is_ie) { 443 document.selection.empty(); 444 } 445 }; 446 447 Calendar.dayMouseOver = function(ev) { 448 var el = Calendar.getElement(ev); 449 if (Calendar.isRelated(el, ev) || Calendar._C || el.disabled) { 450 return false; 451 } 452 if (el.ttip) { 453 if (el.ttip.substr(0, 1) == "_") { 454 var date = null; 455 with (el.calendar.date) { 456 date = new Date(getFullYear(), getMonth(), el.caldate); 457 } 458 el.ttip = date.print(el.calendar.ttDateFormat) + el.ttip.substr(1); 459 } 460 el.calendar.tooltips.firstChild.data = el.ttip; 461 } 462 if (el.navtype != 300) { 463 Calendar.addClass(el, "hilite"); 464 if (el.caldate) { 465 Calendar.addClass(el.parentNode, "rowhilite"); 466 } 467 } 468 Calendar.stopEvent(ev); 469 }; 470 471 Calendar.dayMouseOut = function(ev) { 472 with (Calendar) { 473 var el = getElement(ev); 474 if (isRelated(el, ev) || _C || el.disabled) { 475 return false; 476 } 477 removeClass(el, "hilite"); 478 if (el.caldate) { 479 removeClass(el.parentNode, "rowhilite"); 480 } 481 el.calendar.tooltips.firstChild.data = _TT["SEL_DATE"]; 482 stopEvent(ev); 483 } 484 }; 485 486 /** 487 * A generic "click" handler :) handles all types of buttons defined in this 488 * calendar. 489 */ 490 Calendar.cellClick = function(el) { 491 var cal = el.calendar; 492 var closing = false; 493 var newdate = false; 494 var date = null; 495 if (typeof el.navtype == "undefined") { 496 Calendar.removeClass(cal.currentDateEl, "selected"); 497 Calendar.addClass(el, "selected"); 498 closing = (cal.currentDateEl == el); 499 if (!closing) { 500 cal.currentDateEl = el; 501 } 502 cal.date.setDate(el.caldate); 503 date = cal.date; 504 newdate = true; 505 } else { 506 if (el.navtype == 200) { 507 Calendar.removeClass(el, "hilite"); 508 cal.callCloseHandler(); 509 return; 510 } 511 date = (el.navtype == 0) ? new Date() : new Date(cal.date); 512 var year = date.getFullYear(); 513 var mon = date.getMonth(); 514 function setMonth(m) { 515 var day = date.getDate(); 516 var max = date.getMonthDays(m); 517 if (day > max) { 518 date.setDate(max); 519 } 520 date.setMonth(m); 521 }; 522 switch (el.navtype) { 523 case -2: 524 if (year > cal.minYear) { 525 date.setFullYear(year - 1); 526 } 527 break; 528 case -1: 529 if (mon > 0) { 530 setMonth(mon - 1); 531 } else if (year-- > cal.minYear) { 532 date.setFullYear(year); 533 setMonth(11); 534 } 535 break; 536 case 1: 537 if (mon < 11) { 538 setMonth(mon + 1); 539 } else if (year < cal.maxYear) { 540 date.setFullYear(year + 1); 541 setMonth(0); 542 } 543 break; 544 case 2: 545 if (year < cal.maxYear) { 546 date.setFullYear(year + 1); 547 } 548 break; 549 case 100: 550 cal.setMondayFirst(!cal.mondayFirst); 551 return; 552 } 553 if (!date.equalsTo(cal.date)) { 554 cal.setDate(date); 555 newdate = el.navtype == 0; 556 } 557 } 558 if (newdate) { 559 cal.callHandler(); 560 } 561 if (closing) { 562 Calendar.removeClass(el, "hilite"); 563 cal.callCloseHandler(); 564 } 565 }; 566 567 // END: CALENDAR STATIC FUNCTIONS 568 569 // BEGIN: CALENDAR OBJECT FUNCTIONS 570 571 /** 572 * This function creates the calendar inside the given parent. If _par is 573 * null than it creates a popup calendar inside the BODY element. If _par is 574 * an element, be it BODY, then it creates a non-popup calendar (still 575 * hidden). Some properties need to be set before calling this function. 576 */ 577 Calendar.prototype.create = function (_par) { 578 var parent = null; 579 if (! _par) { 580 // default parent is the document body, in which case we create 581 // a popup calendar. 582 parent = document.getElementsByTagName("body")[0]; 583 this.isPopup = true; 584 } else { 585 parent = _par; 586 this.isPopup = false; 587 } 588 this.date = this.dateStr ? new Date(this.dateStr) : new Date(); 589 590 var table = Calendar.createElement("table"); 591 this.table = table; 592 table.cellSpacing = 0; 593 table.cellPadding = 0; 594 table.calendar = this; 595 Calendar.addEvent(table, "mousedown", Calendar.tableMouseDown); 596 597 var div = Calendar.createElement("div"); 598 this.element = div; 599 div.className = "calendar"; 600 if (this.isPopup) { 601 div.style.position = "absolute"; 602 div.style.display = "none"; 603 div.style.width = "150px"; 604 } 605 div.appendChild(table); 606 607 var thead = Calendar.createElement("thead", table); 608 var cell = null; 609 var row = null; 610 611 var cal = this; 612 var hh = function (text, cs, navtype) { 613 cell = Calendar.createElement("td", row); 614 cell.colSpan = cs; 615 cell.className = "button"; 616 Calendar._add_evs(cell); 617 cell.calendar = cal; 618 cell.navtype = navtype; 619 if (text.substr(0, 1) != "&") { 620 cell.appendChild(document.createTextNode(text)); 621 } 622 else { 623 // FIXME: dirty hack for entities 624 cell.innerHTML = text; 625 } 626 return cell; 627 }; 628 629 row = Calendar.createElement("tr", thead); 630 var title_length = 6; 631 (this.isPopup) && --title_length; 632 (this.weekNumbers) && ++title_length; 633 634 hh("-", 1, 100).ttip = Calendar._TT["TOGGLE"]; 635 this.title = hh("", title_length, 300); 636 this.title.className = "title"; 637 if (this.isPopup) { 638 this.title.ttip = Calendar._TT["DRAG_TO_MOVE"]; 639 this.title.style.cursor = "move"; 640 hh("×", 1, 200).ttip = Calendar._TT["CLOSE"]; 641 } 642 643 row = Calendar.createElement("tr", thead); 644 row.className = "headrow"; 645 646 this._nav_py = hh("«", 1, -2); 647 this._nav_py.ttip = Calendar._TT["PREV_YEAR"]; 648 649 this._nav_pm = hh("‹", 1, -1); 650 this._nav_pm.ttip = Calendar._TT["PREV_MONTH"]; 651 652 this._nav_now = hh(Calendar._TT["TODAY"], this.weekNumbers ? 4 : 3, 0); 653 this._nav_now.ttip = Calendar._TT["GO_TODAY"]; 654 655 this._nav_nm = hh("›", 1, 1); 656 this._nav_nm.ttip = Calendar._TT["NEXT_MONTH"]; 657 658 this._nav_ny = hh("»", 1, 2); 659 this._nav_ny.ttip = Calendar._TT["NEXT_YEAR"] 660 661 // day names 662 row = Calendar.createElement("tr", thead); 663 row.className = "daynames"; 664 if (this.weekNumbers) { 665 cell = Calendar.createElement("td", row); 666 cell.className = "name wn"; 667 cell.appendChild(document.createTextNode(Calendar._TT["WK"])); 668 } 669 for (var i = 7; i > 0; --i) { 670 cell = Calendar.createElement("td", row); 671 cell.appendChild(document.createTextNode("")); 672 if (!i) { 673 cell.navtype = 100; 674 cell.calendar = this; 675 Calendar._add_evs(cell); 676 } 677 } 678 this.firstdayname = (this.weekNumbers) ? row.firstChild.nextSibling : row.firstChild; 679 this._displayWeekdays(); 680 681 var tbody = Calendar.createElement("tbody", table); 682 this.tbody = tbody; 683 684 for (i = 6; i > 0; --i) { 685 row = Calendar.createElement("tr", tbody); 686 if (this.weekNumbers) { 687 cell = Calendar.createElement("td", row); 688 cell.appendChild(document.createTextNode("")); 689 } 690 for (var j = 7; j > 0; --j) { 691 cell = Calendar.createElement("td", row); 692 cell.appendChild(document.createTextNode("")); 693 cell.calendar = this; 694 Calendar._add_evs(cell); 695 } 696 } 697 698 var tfoot = Calendar.createElement("tfoot", table); 699 700 row = Calendar.createElement("tr", tfoot); 701 row.className = "footrow"; 702 703 cell = hh(Calendar._TT["SEL_DATE"], this.weekNumbers ? 8 : 7, 300); 704 cell.className = "ttip"; 705 if (this.isPopup) { 706 cell.ttip = Calendar._TT["DRAG_TO_MOVE"]; 707 cell.style.cursor = "move"; 708 } 709 this.tooltips = cell; 710 711 div = Calendar.createElement("div", this.element); 712 this.monthsCombo = div; 713 div.className = "combo"; 714 for (i = 0; i < Calendar._MN.length; ++i) { 715 var mn = Calendar.createElement("div"); 716 mn.className = "label"; 717 mn.month = i; 718 mn.appendChild(document.createTextNode(Calendar._MN3[i])); 719 div.appendChild(mn); 720 } 721 722 div = Calendar.createElement("div", this.element); 723 this.yearsCombo = div; 724 div.className = "combo"; 725 for (i = 12; i > 0; --i) { 726 var yr = Calendar.createElement("div"); 727 yr.className = "label"; 728 yr.appendChild(document.createTextNode("")); 729 div.appendChild(yr); 730 } 731 732 this._init(this.mondayFirst, this.date); 733 parent.appendChild(this.element); 734 }; 735 736 /** keyboard navigation, only for popup calendars */ 737 Calendar._keyEvent = function(ev) { 738 if (!window.calendar) { 739 return false; 740 } 741 (Calendar.is_ie) && (ev = window.event); 742 var cal = window.calendar; 743 var act = (Calendar.is_ie || ev.type == "keypress"); 744 if (ev.ctrlKey) { 745 switch (ev.keyCode) { 746 case 37: // KEY left 747 act && Calendar.cellClick(cal._nav_pm); 748 break; 749 case 38: // KEY up 750 act && Calendar.cellClick(cal._nav_py); 751 break; 752 case 39: // KEY right 753 act && Calendar.cellClick(cal._nav_nm); 754 break; 755 case 40: // KEY down 756 act && Calendar.cellClick(cal._nav_ny); 757 break; 758 default: 759 return false; 760 } 761 } else switch (ev.keyCode) { 762 case 32: // KEY space (now) 763 Calendar.cellClick(cal._nav_now); 764 break; 765 case 27: // KEY esc 766 act && cal.hide(); 767 break; 768 case 37: // KEY left 769 case 38: // KEY up 770 case 39: // KEY right 771 case 40: // KEY down 772 if (act) { 773 var date = cal.date.getDate() - 1; 774 var el = cal.currentDateEl; 775 var ne = null; 776 var prev = (ev.keyCode == 37) || (ev.keyCode == 38); 777 switch (ev.keyCode) { 778 case 37: // KEY left 779 (--date >= 0) && (ne = cal.ar_days[date]); 780 break; 781 case 38: // KEY up 782 date -= 7; 783 (date >= 0) && (ne = cal.ar_days[date]); 784 break; 785 case 39: // KEY right 786 (++date < cal.ar_days.length) && (ne = cal.ar_days[date]); 787 break; 788 case 40: // KEY down 789 date += 7; 790 (date < cal.ar_days.length) && (ne = cal.ar_days[date]); 791 break; 792 } 793 if (!ne) { 794 if (prev) { 795 Calendar.cellClick(cal._nav_pm); 796 } else { 797 Calendar.cellClick(cal._nav_nm); 798 } 799 date = (prev) ? cal.date.getMonthDays() : 1; 800 el = cal.currentDateEl; 801 ne = cal.ar_days[date - 1]; 802 } 803 Calendar.removeClass(el, "selected"); 804 Calendar.addClass(ne, "selected"); 805 cal.date.setDate(ne.caldate); 806 cal.currentDateEl = ne; 807 } 808 break; 809 case 13: // KEY enter 810 if (act) { 811 cal.callHandler(); 812 cal.hide(); 813 } 814 break; 815 default: 816 return false; 817 } 818 Calendar.stopEvent(ev); 819 }; 820 821 /** 822 * (RE)Initializes the calendar to the given date and style (if mondayFirst is 823 * true it makes Monday the first day of week, otherwise the weeks start on 824 * Sunday. 825 */ 826 Calendar.prototype._init = function (mondayFirst, date) { 827 var today = new Date(); 828 var year = date.getFullYear(); 829 if (year < this.minYear) { 830 year = this.minYear; 831 date.setFullYear(year); 832 } else if (year > this.maxYear) { 833 year = this.maxYear; 834 date.setFullYear(year); 835 } 836 this.mondayFirst = mondayFirst; 837 this.date = new Date(date); 838 var month = date.getMonth(); 839 var mday = date.getDate(); 840 var no_days = date.getMonthDays(); 841 date.setDate(1); 842 var wday = date.getDay(); 843 var MON = mondayFirst ? 1 : 0; 844 var SAT = mondayFirst ? 5 : 6; 845 var SUN = mondayFirst ? 6 : 0; 846 if (mondayFirst) { 847 wday = (wday > 0) ? (wday - 1) : 6; 848 } 849 var iday = 1; 850 var row = this.tbody.firstChild; 851 var MN = Calendar._MN3[month]; 852 var hasToday = ((today.getFullYear() == year) && (today.getMonth() == month)); 853 var todayDate = today.getDate(); 854 var week_number = date.getWeekNumber(); 855 var ar_days = new Array(); 856 for (var i = 0; i < 6; ++i) { 857 if (iday > no_days) { 858 row.className = "emptyrow"; 859 row = row.nextSibling; 860 continue; 861 } 862 var cell = row.firstChild; 863 if (this.weekNumbers) { 864 cell.className = "day wn"; 865 cell.firstChild.data = week_number; 866 cell = cell.nextSibling; 867 } 868 ++week_number; 869 row.className = "daysrow"; 870 for (var j = 0; j < 7; ++j) { 871 cell.className = "day"; 872 if ((!i && j < wday) || iday > no_days) { 873 // cell.className = "emptycell"; 874 cell.innerHTML = " "; 875 cell.disabled = true; 876 cell = cell.nextSibling; 877 continue; 878 } 879 cell.disabled = false; 880 cell.firstChild.data = iday; 881 if (typeof this.checkDisabled == "function") { 882 date.setDate(iday); 883 if (this.checkDisabled(date)) { 884 cell.className += " disabled"; 885 cell.disabled = true; 886 } 887 } 888 if (!cell.disabled) { 889 ar_days[ar_days.length] = cell; 890 cell.caldate = iday; 891 cell.ttip = "_"; 892 if (iday == mday) { 893 cell.className += " selected"; 894 this.currentDateEl = cell; 895 } 896 if (hasToday && (iday == todayDate)) { 897 cell.className += " today"; 898 cell.ttip += Calendar._TT["PART_TODAY"]; 899 } 900 if (wday == SAT || wday == SUN) { 901 cell.className += " weekend"; 902 } 903 } 904 ++iday; 905 ((++wday) ^ 7) || (wday = 0); 906 cell = cell.nextSibling; 907 } 908 row = row.nextSibling; 909 } 910 this.ar_days = ar_days; 911 this.title.firstChild.data = Calendar._MN[month] + ", " + year; 912 // PROFILE 913 // this.tooltips.firstChild.data = "Generated in " + ((new Date()) - today) + " ms"; 914 }; 915 916 /** 917 * Calls _init function above for going to a certain date (but only if the 918 * date is different than the currently selected one). 919 */ 920 Calendar.prototype.setDate = function (date) { 921 if (!date.equalsTo(this.date)) { 922 this._init(this.mondayFirst, date); 923 } 924 }; 925 926 /** Modifies the "mondayFirst" parameter (EU/US style). */ 927 Calendar.prototype.setMondayFirst = function (mondayFirst) { 928 this._init(mondayFirst, this.date); 929 this._displayWeekdays(); 930 }; 931 932 /** 933 * Allows customization of what dates are enabled. The "unaryFunction" 934 * parameter must be a function object that receives the date (as a JS Date 935 * object) and returns a boolean value. If the returned value is true then 936 * the passed date will be marked as disabled. 937 */ 938 Calendar.prototype.setDisabledHandler = function (unaryFunction) { 939 this.checkDisabled = unaryFunction; 940 }; 941 942 /** Customization of allowed year range for the calendar. */ 943 Calendar.prototype.setRange = function (a, z) { 944 this.minYear = a; 945 this.maxYear = z; 946 }; 947 948 /** Calls the first user handler (selectedHandler). */ 949 Calendar.prototype.callHandler = function () { 950 if (this.onSelected) { 951 this.onSelected(this, this.date.print(this.dateFormat)); 952 } 953 }; 954 955 /** Calls the second user handler (closeHandler). */ 956 Calendar.prototype.callCloseHandler = function () { 957 if (this.onClose) { 958 this.onClose(this); 959 } 960 this.hideShowCovered(); 961 }; 962 963 /** Removes the calendar object from the DOM tree and destroys it. */ 964 Calendar.prototype.destroy = function () { 965 var el = this.element.parentNode; 966 el.removeChild(this.element); 967 Calendar._C = null; 968 delete el; 969 }; 970 971 /** 972 * Moves the calendar element to a different section in the DOM tree (changes 973 * its parent). 974 */ 975 Calendar.prototype.reparent = function (new_parent) { 976 var el = this.element; 977 el.parentNode.removeChild(el); 978 new_parent.appendChild(el); 979 }; 980 981 // This gets called when the user presses a mouse button anywhere in the 982 // document, if the calendar is shown. If the click was outside the open 983 // calendar this function closes it. 984 Calendar._checkCalendar = function(ev) { 985 if (!window.calendar) { 986 return false; 987 } 988 var el = Calendar.is_ie ? Calendar.getElement(ev) : Calendar.getTargetElement(ev); 989 for (; el != null && el != calendar.element; el = el.parentNode); 990 if (el == null) { 991 // calls closeHandler which should hide the calendar. 992 window.calendar.callCloseHandler(); 993 Calendar.stopEvent(ev); 994 } 995 }; 996 997 /** Shows the calendar. */ 998 Calendar.prototype.show = function () { 999 var rows = this.table.getElementsByTagName("tr"); 1000 for (var i = rows.length; i > 0;) { 1001 var row = rows[--i]; 1002 Calendar.removeClass(row, "rowhilite"); 1003 var cells = row.getElementsByTagName("td"); 1004 for (var j = cells.length; j > 0;) { 1005 var cell = cells[--j]; 1006 Calendar.removeClass(cell, "hilite"); 1007 Calendar.removeClass(cell, "active"); 1008 } 1009 } 1010 this.element.style.display = "block"; 1011 this.hidden = false; 1012 if (this.isPopup) { 1013 window.calendar = this; 1014 Calendar.addEvent(document, "keydown", Calendar._keyEvent); 1015 Calendar.addEvent(document, "keypress", Calendar._keyEvent); 1016 Calendar.addEvent(document, "mousedown", Calendar._checkCalendar); 1017 } 1018 this.hideShowCovered(); 1019 }; 1020 1021 /** 1022 * Hides the calendar. Also removes any "hilite" from the class of any TD 1023 * element. 1024 */ 1025 Calendar.prototype.hide = function () { 1026 if (this.isPopup) { 1027 Calendar.removeEvent(document, "keydown", Calendar._keyEvent); 1028 Calendar.removeEvent(document, "keypress", Calendar._keyEvent); 1029 Calendar.removeEvent(document, "mousedown", Calendar._checkCalendar); 1030 } 1031 this.element.style.display = "none"; 1032 this.hidden = true; 1033 this.hideShowCovered(); 1034 }; 1035 1036 /** 1037 * Shows the calendar at a given absolute position (beware that, depending on 1038 * the calendar element style -- position property -- this might be relative 1039 * to the parent's containing rectangle). 1040 */ 1041 Calendar.prototype.showAt = function (x, y) { 1042 var s = this.element.style; 1043 s.left = x + "px"; 1044 s.top = y + "px"; 1045 this.show(); 1046 }; 1047 1048 /** Shows the calendar near a given element. */ 1049 Calendar.prototype.showAtElement = function (el) { 1050 var p = Calendar.getAbsolutePos(el); 1051 this.showAt(p.x, p.y + el.offsetHeight); 1052 }; 1053 1054 /** Customizes the date format. */ 1055 Calendar.prototype.setDateFormat = function (str) { 1056 this.dateFormat = str; 1057 }; 1058 1059 /** Customizes the tooltip date format. */ 1060 Calendar.prototype.setTtDateFormat = function (str) { 1061 this.ttDateFormat = str; 1062 }; 1063 1064 /** 1065 * Tries to identify the date represented in a string. If successful it also 1066 * calls this.setDate which moves the calendar to the given date. 1067 */ 1068 Calendar.prototype.parseDate = function (str, fmt) { 1069 var y = 0; 1070 var m = -1; 1071 var d = 0; 1072 var a = str.split(/\W+/); 1073 if (!fmt) { 1074 fmt = this.dateFormat; 1075 } 1076 var b = fmt.split(/\W+/); 1077 var i = 0, j = 0; 1078 for (i = 0; i < a.length; ++i) { 1079 if (b[i] == "D" || b[i] == "DD") { 1080 continue; 1081 } 1082 if (b[i] == "d" || b[i] == "dd") { 1083 d = parseInt(a[i]); 1084 } 1085 if (b[i] == "m" || b[i] == "mm") { 1086 m = parseInt(a[i]) - 1; 1087 } 1088 if (b[i] == "y") { 1089 y = parseInt(a[i]); 1090 } 1091 if (b[i] == "yy") { 1092 y = parseInt(a[i]) + 1900; 1093 } 1094 if (b[i] == "M" || b[i] == "MM") { 1095 for (j = 0; j < 12; ++j) { 1096 if (Calendar._MN[j].substr(0, a[i].length).toLowerCase() == a[i].toLowerCase()) { m = j; break; } 1097 } 1098 } 1099 } 1100 if (y != 0 && m != -1 && d != 0) { 1101 this.setDate(new Date(y, m, d)); 1102 return; 1103 } 1104 y = 0; m = -1; d = 0; 1105 for (i = 0; i < a.length; ++i) { 1106 if (a[i].search(/[a-zA-Z]+/) != -1) { 1107 var t = -1; 1108 for (j = 0; j < 12; ++j) { 1109 if (Calendar._MN[j].substr(0, a[i].length).toLowerCase() == a[i].toLowerCase()) { t = j; break; } 1110 } 1111 if (t != -1) { 1112 if (m != -1) { 1113 d = m+1; 1114 } 1115 m = t; 1116 } 1117 } else if (parseInt(a[i]) <= 12 && m == -1) { 1118 m = a[i]-1; 1119 } else if (parseInt(a[i]) > 31 && y == 0) { 1120 y = a[i]; 1121 } else if (d == 0) { 1122 d = a[i]; 1123 } 1124 } 1125 if (y == 0) { 1126 var today = new Date(); 1127 y = today.getFullYear(); 1128 } 1129 if (m != -1 && d != 0) { 1130 this.setDate(new Date(y, m, d)); 1131 } 1132 }; 1133 1134 Calendar.prototype.hideShowCovered = function () { 1135 var tags = new Array("applet", "iframe", "select"); 1136 var el = this.element; 1137 1138 var p = Calendar.getAbsolutePos(el); 1139 var EX1 = p.x; 1140 var EX2 = el.offsetWidth + EX1; 1141 var EY1 = p.y; 1142 var EY2 = el.offsetHeight + EY1; 1143 1144 for (var k = tags.length; k > 0; ) { 1145 var ar = document.getElementsByTagName(tags[--k]); 1146 var cc = null; 1147 1148 for (var i = ar.length; i > 0;) { 1149 cc = ar[--i]; 1150 1151 p = Calendar.getAbsolutePos(cc); 1152 var CX1 = p.x; 1153 var CX2 = cc.offsetWidth + CX1; 1154 var CY1 = p.y; 1155 var CY2 = cc.offsetHeight + CY1; 1156 1157 if (this.hidden || (CX1 > EX2) || (CX2 < EX1) || (CY1 > EY2) || (CY2 < EY1)) { 1158 cc.style.visibility = "visible"; 1159 } else { 1160 cc.style.visibility = "hidden"; 1161 } 1162 } 1163 } 1164 }; 1165 1166 /** Internal function; it displays the bar with the names of the weekday. */ 1167 Calendar.prototype._displayWeekdays = function () { 1168 var MON = this.mondayFirst ? 0 : 1; 1169 var SUN = this.mondayFirst ? 6 : 0; 1170 var SAT = this.mondayFirst ? 5 : 6; 1171 var cell = this.firstdayname; 1172 for (var i = 0; i < 7; ++i) { 1173 cell.className = "day name"; 1174 if (!i) { 1175 cell.ttip = this.mondayFirst ? Calendar._TT["SUN_FIRST"] : Calendar._TT["MON_FIRST"]; 1176 cell.navtype = 100; 1177 cell.calendar = this; 1178 Calendar._add_evs(cell); 1179 } 1180 if (i == SUN || i == SAT) { 1181 Calendar.addClass(cell, "weekend"); 1182 } 1183 cell.firstChild.data = Calendar._DN3[i + 1 - MON]; 1184 cell = cell.nextSibling; 1185 } 1186 }; 1187 1188 /** Internal function. Hides all combo boxes that might be displayed. */ 1189 Calendar.prototype._hideCombos = function () { 1190 this.monthsCombo.style.display = "none"; 1191 this.yearsCombo.style.display = "none"; 1192 }; 1193 1194 /** Internal function. Starts dragging the element. */ 1195 Calendar.prototype._dragStart = function (ev) { 1196 if (this.dragging) { 1197 return; 1198 } 1199 this.dragging = true; 1200 var posX; 1201 var posY; 1202 if (Calendar.is_ie) { 1203 posY = window.event.clientY + document.body.scrollTop; 1204 posX = window.event.clientX + document.body.scrollLeft; 1205 } else { 1206 posY = ev.clientY + window.scrollY; 1207 posX = ev.clientX + window.scrollX; 1208 } 1209 var st = this.element.style; 1210 this.xOffs = posX - parseInt(st.left); 1211 this.yOffs = posY - parseInt(st.top); 1212 with (Calendar) { 1213 addEvent(document, "mousemove", calDragIt); 1214 addEvent(document, "mouseover", stopEvent); 1215 addEvent(document, "mouseup", calDragEnd); 1216 } 1217 }; 1218 1219 // BEGIN: DATE OBJECT PATCHES 1220 1221 /** Adds the number of days array to the Date object. */ 1222 Date._MD = new Array(31,28,31,30,31,30,31,31,30,31,30,31); 1223 1224 /** Constants used for time computations */ 1225 Date.SECOND = 1000 /* milliseconds */; 1226 Date.MINUTE = 60 * Date.SECOND; 1227 Date.HOUR = 60 * Date.MINUTE; 1228 Date.DAY = 24 * Date.HOUR; 1229 Date.WEEK = 7 * Date.DAY; 1230 1231 /** Returns the number of days in the current month */ 1232 Date.prototype.getMonthDays = function(month) { 1233 var year = this.getFullYear(); 1234 if (typeof month == "undefined") { 1235 month = this.getMonth(); 1236 } 1237 if (((0 == (year%4)) && ( (0 != (year%100)) || (0 == (year%400)))) && month == 1) { 1238 return 29; 1239 } else { 1240 return Date._MD[month]; 1241 } 1242 }; 1243 1244 /** Returns the number of the week. The algorithm was "stolen" from PPK's 1245 * website, hope it's correct :) http://www.xs4all.nl/~ppk/js/week.html */ 1246 Date.prototype.getWeekNumber = function() { 1247 var now = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0, 0); 1248 var then = new Date(this.getFullYear(), 0, 1, 0, 0, 0); 1249 var time = now - then; 1250 var day = then.getDay(); 1251 (day > 3) && (day -= 4) || (day += 3); 1252 return Math.round(((time / Date.DAY) + day) / 7); 1253 }; 1254 1255 /** Checks dates equality (ignores time) */ 1256 Date.prototype.equalsTo = function(date) { 1257 return ((this.getFullYear() == date.getFullYear()) && 1258 (this.getMonth() == date.getMonth()) && 1259 (this.getDate() == date.getDate())); 1260 }; 1261 1262 /** Prints the date in a string according to the given format. */ 1263 Date.prototype.print = function (frm) { 1264 var str = new String(frm); 1265 var m = this.getMonth(); 1266 var d = this.getDate(); 1267 var y = this.getFullYear(); 1268 var wn = this.getWeekNumber(); 1269 var w = this.getDay(); 1270 var s = new Array(); 1271 s["d"] = d; 1272 s["dd"] = (d < 10) ? ("0" + d) : d; 1273 s["m"] = 1+m; 1274 s["mm"] = (m < 9) ? ("0" + (1+m)) : (1+m); 1275 s["y"] = y; 1276 s["yy"] = new String(y).substr(2, 2); 1277 s["w"] = wn; 1278 s["ww"] = (wn < 10) ? ("0" + wn) : wn; 1279 with (Calendar) { 1280 s["D"] = _DN3[w]; 1281 s["DD"] = _DN[w]; 1282 s["M"] = _MN3[m]; 1283 s["MM"] = _MN[m]; 1284 } 1285 var re = /(.*)(\W|^)(d|dd|m|mm|y|yy|MM|M|DD|D|w|ww)(\W|$)(.*)/; 1286 while (re.exec(str) != null) { 1287 str = RegExp.$1 + RegExp.$2 + s[RegExp.$3] + RegExp.$4 + RegExp.$5; 1288 } 1289 return str; 1290 }; 1291 1292 // END: DATE OBJECT PATCHES 1293 1294 // global object that remembers the calendar 1295 window.calendar = null;
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Sun Nov 25 11:44:32 2007 | par Balluche grâce à PHPXref 0.7 |
![]() |