[ Index ] |
|
Code source de Joomla 1.0.13 |
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 49 2005-09-15 02:55:27Z rhuk $ 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 } 604 div.appendChild(table); 605 606 var thead = Calendar.createElement("thead", table); 607 var cell = null; 608 var row = null; 609 610 var cal = this; 611 var hh = function (text, cs, navtype) { 612 cell = Calendar.createElement("td", row); 613 cell.colSpan = cs; 614 cell.className = "button"; 615 Calendar._add_evs(cell); 616 cell.calendar = cal; 617 cell.navtype = navtype; 618 if (text.substr(0, 1) != "&") { 619 cell.appendChild(document.createTextNode(text)); 620 } 621 else { 622 // FIXME: dirty hack for entities 623 cell.innerHTML = text; 624 } 625 return cell; 626 }; 627 628 row = Calendar.createElement("tr", thead); 629 var title_length = 6; 630 (this.isPopup) && --title_length; 631 (this.weekNumbers) && ++title_length; 632 633 hh("-", 1, 100).ttip = Calendar._TT["TOGGLE"]; 634 this.title = hh("", title_length, 300); 635 this.title.className = "title"; 636 if (this.isPopup) { 637 this.title.ttip = Calendar._TT["DRAG_TO_MOVE"]; 638 this.title.style.cursor = "move"; 639 hh("×", 1, 200).ttip = Calendar._TT["CLOSE"]; 640 } 641 642 row = Calendar.createElement("tr", thead); 643 row.className = "headrow"; 644 645 this._nav_py = hh("«", 1, -2); 646 this._nav_py.ttip = Calendar._TT["PREV_YEAR"]; 647 648 this._nav_pm = hh("‹", 1, -1); 649 this._nav_pm.ttip = Calendar._TT["PREV_MONTH"]; 650 651 this._nav_now = hh(Calendar._TT["TODAY"], this.weekNumbers ? 4 : 3, 0); 652 this._nav_now.ttip = Calendar._TT["GO_TODAY"]; 653 654 this._nav_nm = hh("›", 1, 1); 655 this._nav_nm.ttip = Calendar._TT["NEXT_MONTH"]; 656 657 this._nav_ny = hh("»", 1, 2); 658 this._nav_ny.ttip = Calendar._TT["NEXT_YEAR"] 659 660 // day names 661 row = Calendar.createElement("tr", thead); 662 row.className = "daynames"; 663 if (this.weekNumbers) { 664 cell = Calendar.createElement("td", row); 665 cell.className = "name wn"; 666 cell.appendChild(document.createTextNode(Calendar._TT["WK"])); 667 } 668 for (var i = 7; i > 0; --i) { 669 cell = Calendar.createElement("td", row); 670 cell.appendChild(document.createTextNode("")); 671 if (!i) { 672 cell.navtype = 100; 673 cell.calendar = this; 674 Calendar._add_evs(cell); 675 } 676 } 677 this.firstdayname = (this.weekNumbers) ? row.firstChild.nextSibling : row.firstChild; 678 this._displayWeekdays(); 679 680 var tbody = Calendar.createElement("tbody", table); 681 this.tbody = tbody; 682 683 for (i = 6; i > 0; --i) { 684 row = Calendar.createElement("tr", tbody); 685 if (this.weekNumbers) { 686 cell = Calendar.createElement("td", row); 687 cell.appendChild(document.createTextNode("")); 688 } 689 for (var j = 7; j > 0; --j) { 690 cell = Calendar.createElement("td", row); 691 cell.appendChild(document.createTextNode("")); 692 cell.calendar = this; 693 Calendar._add_evs(cell); 694 } 695 } 696 697 var tfoot = Calendar.createElement("tfoot", table); 698 699 row = Calendar.createElement("tr", tfoot); 700 row.className = "footrow"; 701 702 cell = hh(Calendar._TT["SEL_DATE"], this.weekNumbers ? 8 : 7, 300); 703 cell.className = "ttip"; 704 if (this.isPopup) { 705 cell.ttip = Calendar._TT["DRAG_TO_MOVE"]; 706 cell.style.cursor = "move"; 707 } 708 this.tooltips = cell; 709 710 div = Calendar.createElement("div", this.element); 711 this.monthsCombo = div; 712 div.className = "combo"; 713 for (i = 0; i < Calendar._MN.length; ++i) { 714 var mn = Calendar.createElement("div"); 715 mn.className = "label"; 716 mn.month = i; 717 mn.appendChild(document.createTextNode(Calendar._MN3[i])); 718 div.appendChild(mn); 719 } 720 721 div = Calendar.createElement("div", this.element); 722 this.yearsCombo = div; 723 div.className = "combo"; 724 for (i = 12; i > 0; --i) { 725 var yr = Calendar.createElement("div"); 726 yr.className = "label"; 727 yr.appendChild(document.createTextNode("")); 728 div.appendChild(yr); 729 } 730 731 this._init(this.mondayFirst, this.date); 732 parent.appendChild(this.element); 733 }; 734 735 /** keyboard navigation, only for popup calendars */ 736 Calendar._keyEvent = function(ev) { 737 if (!window.calendar) { 738 return false; 739 } 740 (Calendar.is_ie) && (ev = window.event); 741 var cal = window.calendar; 742 var act = (Calendar.is_ie || ev.type == "keypress"); 743 if (ev.ctrlKey) { 744 switch (ev.keyCode) { 745 case 37: // KEY left 746 act && Calendar.cellClick(cal._nav_pm); 747 break; 748 case 38: // KEY up 749 act && Calendar.cellClick(cal._nav_py); 750 break; 751 case 39: // KEY right 752 act && Calendar.cellClick(cal._nav_nm); 753 break; 754 case 40: // KEY down 755 act && Calendar.cellClick(cal._nav_ny); 756 break; 757 default: 758 return false; 759 } 760 } else switch (ev.keyCode) { 761 case 32: // KEY space (now) 762 Calendar.cellClick(cal._nav_now); 763 break; 764 case 27: // KEY esc 765 act && cal.hide(); 766 break; 767 case 37: // KEY left 768 case 38: // KEY up 769 case 39: // KEY right 770 case 40: // KEY down 771 if (act) { 772 var date = cal.date.getDate() - 1; 773 var el = cal.currentDateEl; 774 var ne = null; 775 var prev = (ev.keyCode == 37) || (ev.keyCode == 38); 776 switch (ev.keyCode) { 777 case 37: // KEY left 778 (--date >= 0) && (ne = cal.ar_days[date]); 779 break; 780 case 38: // KEY up 781 date -= 7; 782 (date >= 0) && (ne = cal.ar_days[date]); 783 break; 784 case 39: // KEY right 785 (++date < cal.ar_days.length) && (ne = cal.ar_days[date]); 786 break; 787 case 40: // KEY down 788 date += 7; 789 (date < cal.ar_days.length) && (ne = cal.ar_days[date]); 790 break; 791 } 792 if (!ne) { 793 if (prev) { 794 Calendar.cellClick(cal._nav_pm); 795 } else { 796 Calendar.cellClick(cal._nav_nm); 797 } 798 date = (prev) ? cal.date.getMonthDays() : 1; 799 el = cal.currentDateEl; 800 ne = cal.ar_days[date - 1]; 801 } 802 Calendar.removeClass(el, "selected"); 803 Calendar.addClass(ne, "selected"); 804 cal.date.setDate(ne.caldate); 805 cal.currentDateEl = ne; 806 } 807 break; 808 case 13: // KEY enter 809 if (act) { 810 cal.callHandler(); 811 cal.hide(); 812 } 813 break; 814 default: 815 return false; 816 } 817 Calendar.stopEvent(ev); 818 }; 819 820 /** 821 * (RE)Initializes the calendar to the given date and style (if mondayFirst is 822 * true it makes Monday the first day of week, otherwise the weeks start on 823 * Sunday. 824 */ 825 Calendar.prototype._init = function (mondayFirst, date) { 826 var today = new Date(); 827 var year = date.getFullYear(); 828 if (year < this.minYear) { 829 year = this.minYear; 830 date.setFullYear(year); 831 } else if (year > this.maxYear) { 832 year = this.maxYear; 833 date.setFullYear(year); 834 } 835 this.mondayFirst = mondayFirst; 836 this.date = new Date(date); 837 var month = date.getMonth(); 838 var mday = date.getDate(); 839 var no_days = date.getMonthDays(); 840 date.setDate(1); 841 var wday = date.getDay(); 842 var MON = mondayFirst ? 1 : 0; 843 var SAT = mondayFirst ? 5 : 6; 844 var SUN = mondayFirst ? 6 : 0; 845 if (mondayFirst) { 846 wday = (wday > 0) ? (wday - 1) : 6; 847 } 848 var iday = 1; 849 var row = this.tbody.firstChild; 850 var MN = Calendar._MN3[month]; 851 var hasToday = ((today.getFullYear() == year) && (today.getMonth() == month)); 852 var todayDate = today.getDate(); 853 var week_number = date.getWeekNumber(); 854 var ar_days = new Array(); 855 for (var i = 0; i < 6; ++i) { 856 if (iday > no_days) { 857 row.className = "emptyrow"; 858 row = row.nextSibling; 859 continue; 860 } 861 var cell = row.firstChild; 862 if (this.weekNumbers) { 863 cell.className = "day wn"; 864 cell.firstChild.data = week_number; 865 cell = cell.nextSibling; 866 } 867 ++week_number; 868 row.className = "daysrow"; 869 for (var j = 0; j < 7; ++j) { 870 cell.className = "day"; 871 if ((!i && j < wday) || iday > no_days) { 872 // cell.className = "emptycell"; 873 cell.innerHTML = " "; 874 cell.disabled = true; 875 cell = cell.nextSibling; 876 continue; 877 } 878 cell.disabled = false; 879 cell.firstChild.data = iday; 880 if (typeof this.checkDisabled == "function") { 881 date.setDate(iday); 882 if (this.checkDisabled(date)) { 883 cell.className += " disabled"; 884 cell.disabled = true; 885 } 886 } 887 if (!cell.disabled) { 888 ar_days[ar_days.length] = cell; 889 cell.caldate = iday; 890 cell.ttip = "_"; 891 if (iday == mday) { 892 cell.className += " selected"; 893 this.currentDateEl = cell; 894 } 895 if (hasToday && (iday == todayDate)) { 896 cell.className += " today"; 897 cell.ttip += Calendar._TT["PART_TODAY"]; 898 } 899 if (wday == SAT || wday == SUN) { 900 cell.className += " weekend"; 901 } 902 } 903 ++iday; 904 ((++wday) ^ 7) || (wday = 0); 905 cell = cell.nextSibling; 906 } 907 row = row.nextSibling; 908 } 909 this.ar_days = ar_days; 910 this.title.firstChild.data = Calendar._MN[month] + ", " + year; 911 // PROFILE 912 // this.tooltips.firstChild.data = "Generated in " + ((new Date()) - today) + " ms"; 913 }; 914 915 /** 916 * Calls _init function above for going to a certain date (but only if the 917 * date is different than the currently selected one). 918 */ 919 Calendar.prototype.setDate = function (date) { 920 if (!date.equalsTo(this.date)) { 921 this._init(this.mondayFirst, date); 922 } 923 }; 924 925 /** Modifies the "mondayFirst" parameter (EU/US style). */ 926 Calendar.prototype.setMondayFirst = function (mondayFirst) { 927 this._init(mondayFirst, this.date); 928 this._displayWeekdays(); 929 }; 930 931 /** 932 * Allows customization of what dates are enabled. The "unaryFunction" 933 * parameter must be a function object that receives the date (as a JS Date 934 * object) and returns a boolean value. If the returned value is true then 935 * the passed date will be marked as disabled. 936 */ 937 Calendar.prototype.setDisabledHandler = function (unaryFunction) { 938 this.checkDisabled = unaryFunction; 939 }; 940 941 /** Customization of allowed year range for the calendar. */ 942 Calendar.prototype.setRange = function (a, z) { 943 this.minYear = a; 944 this.maxYear = z; 945 }; 946 947 /** Calls the first user handler (selectedHandler). */ 948 Calendar.prototype.callHandler = function () { 949 if (this.onSelected) { 950 this.onSelected(this, this.date.print(this.dateFormat)); 951 } 952 }; 953 954 /** Calls the second user handler (closeHandler). */ 955 Calendar.prototype.callCloseHandler = function () { 956 if (this.onClose) { 957 this.onClose(this); 958 } 959 this.hideShowCovered(); 960 }; 961 962 /** Removes the calendar object from the DOM tree and destroys it. */ 963 Calendar.prototype.destroy = function () { 964 var el = this.element.parentNode; 965 el.removeChild(this.element); 966 Calendar._C = null; 967 delete el; 968 }; 969 970 /** 971 * Moves the calendar element to a different section in the DOM tree (changes 972 * its parent). 973 */ 974 Calendar.prototype.reparent = function (new_parent) { 975 var el = this.element; 976 el.parentNode.removeChild(el); 977 new_parent.appendChild(el); 978 }; 979 980 // This gets called when the user presses a mouse button anywhere in the 981 // document, if the calendar is shown. If the click was outside the open 982 // calendar this function closes it. 983 Calendar._checkCalendar = function(ev) { 984 if (!window.calendar) { 985 return false; 986 } 987 var el = Calendar.is_ie ? Calendar.getElement(ev) : Calendar.getTargetElement(ev); 988 for (; el != null && el != calendar.element; el = el.parentNode); 989 if (el == null) { 990 // calls closeHandler which should hide the calendar. 991 window.calendar.callCloseHandler(); 992 Calendar.stopEvent(ev); 993 } 994 }; 995 996 /** Shows the calendar. */ 997 Calendar.prototype.show = function () { 998 var rows = this.table.getElementsByTagName("tr"); 999 for (var i = rows.length; i > 0;) { 1000 var row = rows[--i]; 1001 Calendar.removeClass(row, "rowhilite"); 1002 var cells = row.getElementsByTagName("td"); 1003 for (var j = cells.length; j > 0;) { 1004 var cell = cells[--j]; 1005 Calendar.removeClass(cell, "hilite"); 1006 Calendar.removeClass(cell, "active"); 1007 } 1008 } 1009 this.element.style.display = "block"; 1010 this.hidden = false; 1011 if (this.isPopup) { 1012 window.calendar = this; 1013 Calendar.addEvent(document, "keydown", Calendar._keyEvent); 1014 Calendar.addEvent(document, "keypress", Calendar._keyEvent); 1015 Calendar.addEvent(document, "mousedown", Calendar._checkCalendar); 1016 } 1017 this.hideShowCovered(); 1018 }; 1019 1020 /** 1021 * Hides the calendar. Also removes any "hilite" from the class of any TD 1022 * element. 1023 */ 1024 Calendar.prototype.hide = function () { 1025 if (this.isPopup) { 1026 Calendar.removeEvent(document, "keydown", Calendar._keyEvent); 1027 Calendar.removeEvent(document, "keypress", Calendar._keyEvent); 1028 Calendar.removeEvent(document, "mousedown", Calendar._checkCalendar); 1029 } 1030 this.element.style.display = "none"; 1031 this.hidden = true; 1032 this.hideShowCovered(); 1033 }; 1034 1035 /** 1036 * Shows the calendar at a given absolute position (beware that, depending on 1037 * the calendar element style -- position property -- this might be relative 1038 * to the parent's containing rectangle). 1039 */ 1040 Calendar.prototype.showAt = function (x, y) { 1041 var s = this.element.style; 1042 s.left = x + "px"; 1043 s.top = y + "px"; 1044 this.show(); 1045 }; 1046 1047 /** Shows the calendar near a given element. */ 1048 Calendar.prototype.showAtElement = function (el) { 1049 var p = Calendar.getAbsolutePos(el); 1050 this.showAt(p.x, p.y + el.offsetHeight); 1051 }; 1052 1053 /** Customizes the date format. */ 1054 Calendar.prototype.setDateFormat = function (str) { 1055 this.dateFormat = str; 1056 }; 1057 1058 /** Customizes the tooltip date format. */ 1059 Calendar.prototype.setTtDateFormat = function (str) { 1060 this.ttDateFormat = str; 1061 }; 1062 1063 /** 1064 * Tries to identify the date represented in a string. If successful it also 1065 * calls this.setDate which moves the calendar to the given date. 1066 */ 1067 Calendar.prototype.parseDate = function (str, fmt) { 1068 var y = 0; 1069 var m = -1; 1070 var d = 0; 1071 var a = str.split(/\W+/); 1072 if (!fmt) { 1073 fmt = this.dateFormat; 1074 } 1075 var b = fmt.split(/\W+/); 1076 var i = 0, j = 0; 1077 for (i = 0; i < a.length; ++i) { 1078 if (b[i] == "D" || b[i] == "DD") { 1079 continue; 1080 } 1081 if (b[i] == "d" || b[i] == "dd") { 1082 d = parseInt(a[i], 10); 1083 } 1084 if (b[i] == "m" || b[i] == "mm") { 1085 m = parseInt(a[i], 10) - 1; 1086 } 1087 if (b[i] == "y") { 1088 y = parseInt(a[i], 10); 1089 } 1090 if (b[i] == "yy") { 1091 y = parseInt(a[i], 10) + 1900; 1092 } 1093 if (b[i] == "M" || b[i] == "MM") { 1094 for (j = 0; j < 12; ++j) { 1095 if (Calendar._MN[j].substr(0, a[i].length).toLowerCase() == a[i].toLowerCase()) { m = j; break; } 1096 } 1097 } 1098 } 1099 if (y != 0 && m != -1 && d != 0) { 1100 this.setDate(new Date(y, m, d)); 1101 return; 1102 } 1103 y = 0; m = -1; d = 0; 1104 for (i = 0; i < a.length; ++i) { 1105 if (a[i].search(/[a-zA-Z]+/) != -1) { 1106 var t = -1; 1107 for (j = 0; j < 12; ++j) { 1108 if (Calendar._MN[j].substr(0, a[i].length).toLowerCase() == a[i].toLowerCase()) { t = j; break; } 1109 } 1110 if (t != -1) { 1111 if (m != -1) { 1112 d = m+1; 1113 } 1114 m = t; 1115 } 1116 } else if (parseInt(a[i], 10) <= 12 && m == -1) { 1117 m = a[i]-1; 1118 } else if (parseInt(a[i], 10) > 31 && y == 0) { 1119 y = a[i]; 1120 } else if (d == 0) { 1121 d = a[i]; 1122 } 1123 } 1124 if (y == 0) { 1125 var today = new Date(); 1126 y = today.getFullYear(); 1127 } 1128 if (m != -1 && d != 0) { 1129 this.setDate(new Date(y, m, d)); 1130 } 1131 }; 1132 1133 Calendar.prototype.hideShowCovered = function () { 1134 var tags = new Array("applet", "iframe", "select"); 1135 var el = this.element; 1136 1137 var p = Calendar.getAbsolutePos(el); 1138 var EX1 = p.x; 1139 var EX2 = el.offsetWidth + EX1; 1140 var EY1 = p.y; 1141 var EY2 = el.offsetHeight + EY1; 1142 1143 for (var k = tags.length; k > 0; ) { 1144 var ar = document.getElementsByTagName(tags[--k]); 1145 var cc = null; 1146 1147 for (var i = ar.length; i > 0;) { 1148 cc = ar[--i]; 1149 1150 p = Calendar.getAbsolutePos(cc); 1151 var CX1 = p.x; 1152 var CX2 = cc.offsetWidth + CX1; 1153 var CY1 = p.y; 1154 var CY2 = cc.offsetHeight + CY1; 1155 1156 if (this.hidden || (CX1 > EX2) || (CX2 < EX1) || (CY1 > EY2) || (CY2 < EY1)) { 1157 cc.style.visibility = "visible"; 1158 } else { 1159 cc.style.visibility = "hidden"; 1160 } 1161 } 1162 } 1163 }; 1164 1165 /** Internal function; it displays the bar with the names of the weekday. */ 1166 Calendar.prototype._displayWeekdays = function () { 1167 var MON = this.mondayFirst ? 0 : 1; 1168 var SUN = this.mondayFirst ? 6 : 0; 1169 var SAT = this.mondayFirst ? 5 : 6; 1170 var cell = this.firstdayname; 1171 for (var i = 0; i < 7; ++i) { 1172 cell.className = "day name"; 1173 if (!i) { 1174 cell.ttip = this.mondayFirst ? Calendar._TT["SUN_FIRST"] : Calendar._TT["MON_FIRST"]; 1175 cell.navtype = 100; 1176 cell.calendar = this; 1177 Calendar._add_evs(cell); 1178 } 1179 if (i == SUN || i == SAT) { 1180 Calendar.addClass(cell, "weekend"); 1181 } 1182 cell.firstChild.data = Calendar._DN3[i + 1 - MON]; 1183 cell = cell.nextSibling; 1184 } 1185 }; 1186 1187 /** Internal function. Hides all combo boxes that might be displayed. */ 1188 Calendar.prototype._hideCombos = function () { 1189 this.monthsCombo.style.display = "none"; 1190 this.yearsCombo.style.display = "none"; 1191 }; 1192 1193 /** Internal function. Starts dragging the element. */ 1194 Calendar.prototype._dragStart = function (ev) { 1195 if (this.dragging) { 1196 return; 1197 } 1198 this.dragging = true; 1199 var posX; 1200 var posY; 1201 if (Calendar.is_ie) { 1202 posY = window.event.clientY + document.body.scrollTop; 1203 posX = window.event.clientX + document.body.scrollLeft; 1204 } else { 1205 posY = ev.clientY + window.scrollY; 1206 posX = ev.clientX + window.scrollX; 1207 } 1208 var st = this.element.style; 1209 this.xOffs = posX - parseInt(st.left); 1210 this.yOffs = posY - parseInt(st.top); 1211 with (Calendar) { 1212 addEvent(document, "mousemove", calDragIt); 1213 addEvent(document, "mouseover", stopEvent); 1214 addEvent(document, "mouseup", calDragEnd); 1215 } 1216 }; 1217 1218 // BEGIN: DATE OBJECT PATCHES 1219 1220 /** Adds the number of days array to the Date object. */ 1221 Date._MD = new Array(31,28,31,30,31,30,31,31,30,31,30,31); 1222 1223 /** Constants used for time computations */ 1224 Date.SECOND = 1000 /* milliseconds */; 1225 Date.MINUTE = 60 * Date.SECOND; 1226 Date.HOUR = 60 * Date.MINUTE; 1227 Date.DAY = 24 * Date.HOUR; 1228 Date.WEEK = 7 * Date.DAY; 1229 1230 /** Returns the number of days in the current month */ 1231 Date.prototype.getMonthDays = function(month) { 1232 var year = this.getFullYear(); 1233 if (typeof month == "undefined") { 1234 month = this.getMonth(); 1235 } 1236 if (((0 == (year%4)) && ( (0 != (year%100)) || (0 == (year%400)))) && month == 1) { 1237 return 29; 1238 } else { 1239 return Date._MD[month]; 1240 } 1241 }; 1242 1243 /** Returns the number of the week. The algorithm was "stolen" from PPK's 1244 * website, hope it's correct :) http://www.xs4all.nl/~ppk/js/week.html */ 1245 Date.prototype.getWeekNumber = function() { 1246 var now = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0, 0); 1247 var then = new Date(this.getFullYear(), 0, 1, 0, 0, 0); 1248 var time = now - then; 1249 var day = then.getDay(); 1250 (day > 3) && (day -= 4) || (day += 3); 1251 return Math.round(((time / Date.DAY) + day) / 7); 1252 }; 1253 1254 /** Checks dates equality (ignores time) */ 1255 Date.prototype.equalsTo = function(date) { 1256 return ((this.getFullYear() == date.getFullYear()) && 1257 (this.getMonth() == date.getMonth()) && 1258 (this.getDate() == date.getDate())); 1259 }; 1260 1261 /** Prints the date in a string according to the given format. */ 1262 Date.prototype.print = function (frm) { 1263 var str = new String(frm); 1264 var m = this.getMonth(); 1265 var d = this.getDate(); 1266 var y = this.getFullYear(); 1267 var wn = this.getWeekNumber(); 1268 var w = this.getDay(); 1269 var s = new Array(); 1270 s["d"] = d; 1271 s["dd"] = (d < 10) ? ("0" + d) : d; 1272 s["m"] = 1+m; 1273 s["mm"] = (m < 9) ? ("0" + (1+m)) : (1+m); 1274 s["y"] = y; 1275 s["yy"] = new String(y).substr(2, 2); 1276 s["w"] = wn; 1277 s["ww"] = (wn < 10) ? ("0" + wn) : wn; 1278 with (Calendar) { 1279 s["D"] = _DN3[w]; 1280 s["DD"] = _DN[w]; 1281 s["M"] = _MN3[m]; 1282 s["MM"] = _MN[m]; 1283 } 1284 var re = /(.*)(\W|^)(d|dd|m|mm|y|yy|MM|M|DD|D|w|ww)(\W|$)(.*)/; 1285 while (re.exec(str) != null) { 1286 str = RegExp.$1 + RegExp.$2 + s[RegExp.$3] + RegExp.$4 + RegExp.$5; 1287 } 1288 return str; 1289 }; 1290 1291 // END: DATE OBJECT PATCHES 1292 1293 // global object that remembers the calendar 1294 window.calendar = null;
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Wed Nov 21 14:43:32 2007 | par Balluche grâce à PHPXref 0.7 |
![]() |