1/*! 2ARIA Calendar Module R2.0 3Copyright 2010-2018 Bryan Garaventa (WhatSock.com) 4Refactoring Contributions Copyright 2018 Danny Allen (dannya.com) / Wonderscore Ltd (wonderscore.co.uk) 5Part of AccDC, a Cross-Browser JavaScript accessibility API, distributed under the terms of the Open Source Initiative OSI - MIT License 6*/ 7 8(function(){ 9 10 $A.setCalendar = function(pId, trigger, targ, commentsEnabled, callback, config){ 11 12 var config = config || {}, 13 helpText = 14 config.helpText 15 ? config.helpText 16 : 'Press the arrow keys to navigate by day, PageUp and PageDown to navigate by month, Alt+PageUp and Alt+PageDown to navigate by year, or Escape to cancel.', 17 18 // Control the behavior of date selection clicks 19 handleClick = (callback && typeof callback === 'function') ? callback : function(ev, dc){ 20 // format selected calendar value and set into input field 21 targ.value = dc.formatDate( 22 dc, 23 { 24 'YYYY': dc.range.current.year, 25 'MMMM': dc.range[dc.range.current.month].name, 26 'dddd': dc.range.wDays[dc.range.current.wDay].lng, 27 'MM': ('00' + (dc.range.current.month + 1)).slice(-2), 28 'DD': ('00' + dc.range.current.mDay).slice(-2), 29 'Do': dc.getDateOrdinalSuffix(dc.range.current.mDay), 30 'M': (dc.range.current.month + 1), 31 'D': dc.range.current.mDay 32 } 33 ); 34 35 dc.close(); 36 }, 37 38 pressed = {}, 39 changePressed = function(ev){ 40 pressed.alt = ev.altKey; 41 pressed.ctrl = ev.ctrlKey; 42 pressed.shift = ev.shiftKey; 43 }; 44 45 // Calendar object declaration start 46 $A( 47 [ 48 { 49 id: pId, 50 role: config.role || 'Calendar', 51 trigger: trigger, 52 bind: 'opendatepicker', 53 allowReopen: true, 54 showHiddenClose: false, 55 controlType: 'DatePicker', 56 tooltipTxt: config.tooltipTxt || 'Press Escape to cancel', 57 markedTxt: config.markedTxt || 'Selected', 58 disabledTxt: config.disabledTxt || 'Disabled', 59 commentedTxt: config.commentedTxt || 'Has Comment', 60 prevTxt: config.prevTxt || 'Previous', 61 nextTxt: config.nextTxt || 'Next', 62 monthTxt: config.monthTxt || 'Month', 63 yearTxt: config.yearTxt || 'Year', 64 leftButtonYearText: config.leftButtonYearText || '⇐', 65 rightButtonYearText: config.rightButtonYearText || '⇒', 66 leftButtonMonthText: config.leftButtonMonthText || '←', 67 rightButtonMonthText: config.rightButtonMonthText || '→', 68 drawFullCalendar: (config.drawFullCalendar === true), 69 highlightToday: (config.highlightToday === true), 70 pageUpDownNatural: (config.pageUpDownNatural === true), 71 autoPosition: isNaN(config.autoPosition) ? 9 : config.autoPosition, 72 offsetTop: isNaN(config.offsetTop) ? 0 : config.offsetTop, 73 offsetLeft: isNaN(config.offsetLeft) ? 0 : config.offsetLeft, 74 posAnchor: config.posAnchor, 75 targetObj: config.targetObj, 76 inputDateFormat: config.inputDateFormat || 'dddd MMMM D, YYYY', 77 audibleDateFormat: config.audibleDateFormat || 'D, MMMM YYYY (dddd)', 78 initialDate: ((config.initialDate instanceof Date) ? config.initialDate : new Date()), 79 minDate: ((config.minDate !== undefined) ? (config.minDate instanceof Date ? config.minDate : new Date((new Date()).setDate((new Date()).getDate() + config.minDate))) : undefined), 80 maxDate: ((config.maxDate !== undefined) ? (config.maxDate instanceof Date ? config.maxDate : new Date((new Date()).setDate((new Date()).getDate() + config.maxDate))) : undefined), 81 disableWeekdays: (config.disableWeekdays !== undefined) ? config.disableWeekdays : false, 82 disableWeekends: (config.disableWeekends !== undefined) ? config.disableWeekends : false, 83 cssObj: config.cssObj || 84 { 85 position: 'absolute', 86 zIndex: 1 87 }, 88 className: config.className || 'calendar', 89 range: 90 { 91 disabledWDays: [], 92 0: 93 { 94 name: config.months && config.months[0] ? config.months[0] : 'January', 95 max: 31, 96 marked: {}, 97 disabled: {}, 98 disabledWDays: [], 99 comments: {}, 100 message: {} 101 }, 102 1: 103 { 104 name: config.months && config.months[1] ? config.months[1] : 'February', 105 max: 28, 106 marked: {}, 107 disabled: {}, 108 disabledWDays: [], 109 comments: {}, 110 message: {} 111 }, 112 2: 113 { 114 name: config.months && config.months[2] ? config.months[2] : 'March', 115 max: 31, 116 marked: {}, 117 disabled: {}, 118 disabledWDays: [], 119 comments: {}, 120 message: {} 121 }, 122 3: 123 { 124 name: config.months && config.months[3] ? config.months[3] : 'April', 125 max: 30, 126 marked: {}, 127 disabled: {}, 128 disabledWDays: [], 129 comments: {}, 130 message: {} 131 }, 132 4: 133 { 134 name: config.months && config.months[4] ? config.months[4] : 'May', 135 max: 31, 136 marked: {}, 137 disabled: {}, 138 disabledWDays: [], 139 comments: {}, 140 message: {} 141 }, 142 5: 143 { 144 name: config.months && config.months[5] ? config.months[5] : 'June', 145 max: 30, 146 marked: {}, 147 disabled: {}, 148 disabledWDays: [], 149 comments: {}, 150 message: {} 151 }, 152 6: 153 { 154 name: config.months && config.months[6] ? config.months[6] : 'July', 155 max: 31, 156 marked: {}, 157 disabled: {}, 158 disabledWDays: [], 159 comments: {}, 160 message: {} 161 }, 162 7: 163 { 164 name: config.months && config.months[7] ? config.months[7] : 'August', 165 max: 31, 166 marked: {}, 167 disabled: {}, 168 disabledWDays: [], 169 comments: {}, 170 message: {} 171 }, 172 8: 173 { 174 name: config.months && config.months[8] ? config.months[8] : 'September', 175 max: 30, 176 marked: {}, 177 disabled: {}, 178 disabledWDays: [], 179 comments: {}, 180 message: {} 181 }, 182 9: 183 { 184 name: config.months && config.months[9] ? config.months[9] : 'October', 185 max: 31, 186 marked: {}, 187 disabled: {}, 188 disabledWDays: [], 189 comments: {}, 190 message: {} 191 }, 192 10: 193 { 194 name: config.months && config.months[10] ? config.months[10] : 'November', 195 max: 30, 196 marked: {}, 197 disabled: {}, 198 disabledWDays: [], 199 comments: {}, 200 message: {} 201 }, 202 11: 203 { 204 name: config.months && config.months[11] ? config.months[11] : 'December', 205 max: 31, 206 marked: {}, 207 disabled: {}, 208 disabledWDays: [], 209 comments: {}, 210 message: {} 211 }, 212 wDays: 213 [ 214 { 215 shrt: config.days && config.days[0] ? config.days[0].s : 'S', 216 lng: config.days && config.days[0] ? config.days[0].l : 'Sunday' 217 }, 218 { 219 shrt: config.days && config.days[1] ? config.days[1].s : 'M', 220 lng: config.days && config.days[1] ? config.days[1].l : 'Monday' 221 }, 222 { 223 shrt: config.days && config.days[2] ? config.days[2].s : 'T', 224 lng: config.days && config.days[2] ? config.days[2].l : 'Tuesday' 225 }, 226 { 227 shrt: config.days && config.days[3] ? config.days[3].s : 'W', 228 lng: config.days && config.days[3] ? config.days[3].l : 'Wednesday' 229 }, 230 { 231 shrt: config.days && config.days[4] ? config.days[4].s : 'T', 232 lng: config.days && config.days[4] ? config.days[4].l : 'Thursday' 233 }, 234 { 235 shrt: config.days && config.days[5] ? config.days[5].s : 'F', 236 lng: config.days && config.days[5] ? config.days[5].l : 'Friday' 237 }, 238 { 239 shrt: config.days && config.days[6] ? config.days[6].s : 'S', 240 lng: config.days && config.days[6] ? config.days[6].l : 'Saturday' 241 } 242 ], 243 // Change the week day offset for the calendar display 244 wdOffset: isNaN(config.wdOffset) ? 0 : config.wdOffset 245 }, 246 getWDay: function(dc, d, r){ 247 var d = typeof d === 'number' ? d : dc.range.current.wDay, o = dc.range.wdOffset; 248 249 if (o < 0) 250 d = (d + o) < 0 ? 7 + o : d + o; 251 252 else if (o > 0) 253 d = (d + o) > 6 ? -1 + ((d + o) - 6) : d + o; 254 255 if (r) 256 d = 6 - d; 257 return d; 258 }, 259 getDateOrdinalSuffix: function (i) { 260 var j = i % 10, 261 k = i % 100; 262 263 if (j == 1 && k != 11) { 264 return i + 'st'; 265 } 266 if (j == 2 && k != 12) { 267 return i + 'nd'; 268 } 269 if (j == 3 && k != 13) { 270 return i + 'rd'; 271 } 272 273 return i + 'th'; 274 }, 275 formatDate: function (dc, dateFormatTokens, dateFormat) { 276 // if dateFormat is not specified, use component default 277 if (typeof dateFormat !== 'string') { 278 dateFormat = dc.inputDateFormat; 279 } 280 281 var re = new RegExp(Object.keys(dateFormatTokens).join('|'), 'gi'); 282 283 return dateFormat.replace(re, function (matched){ 284 return dateFormatTokens[matched]; 285 }); 286 }, 287 modifyDateValues: function (values, modifications) { 288 // Note: Months are zero based 289 for (var key in modifications) { 290 var modification = modifications[key]; 291 292 if (key === 'month') { 293 values.month += modification; 294 295 if (modification < 0) { 296 // Subtraction 297 if (values.month < 0) {
298 values.month = 11; 299 300 if (values.year) { 301 values.year -= 1; 302 } 303 } 304 305 } else { 306 // Addition 307 if (values.month > 11) { 308 values.month = 0; 309 310 if (values.year) { 311 values.year += 1; 312 } 313 } 314 } 315 } 316 } 317 318 return values; 319 }, 320 setFocus: function(o, p, s){ 321 var dc = this; 322 323 if (!o) 324 return false; 325 326 this.current = o; 327 $A.query('td.dayInMonth.selected', this.containerDiv, function(i, p){ 328 $A.setAttr(p, 329 { 330 tabindex: '-1' 331 }); 332 333 $A.remClass(p, 'selected'); 334 }); 335 $A.addClass(o, 'selected'); 336 $A.setAttr(o, 337 { 338 tabindex: '0' 339 }); 340 341 if (!s){ 342 if (dc.navBtn == 'PM'){ 343 dc.buttons.pM.focus(); 344 $A.announce(dc.range[dc.range.current.month].name); 345 dc.navBtnS = true; 346 } 347 348 else if (dc.navBtn == 'NM'){ 349 dc.buttons.nM.focus(); 350 $A.announce(dc.range[dc.range.current.month].name); 351 dc.navBtnS = true; 352 } 353 354 else if (dc.navBtn == 'PY'){ 355 dc.buttons.pY.focus(); 356 $A.announce(dc.range.current.year.toString()); 357 dc.navBtnS = true; 358 } 359 360 else if (dc.navBtn == 'NY'){ 361 dc.buttons.nY.focus(); 362 $A.announce(dc.range.current.year.toString()); 363 dc.navBtnS = true; 364 } 365 366 else 367 o.focus(); 368 } 369 370 if (dc.fn.navBtn) 371 dc.fn.navBtn = ''; 372 373 else 374 dc.navBtn = ''; 375 376 return true; 377 }, 378 setCurrent: function(dc){ 379 dc.range.current = 380 { 381 mDay: dc.date.getDate(), 382 month: dc.date.getMonth(), 383 year: dc.date.getFullYear(), 384 wDay: dc.date.getDay() 385 }; 386 }, 387 setDayMarked: function (dc, dateObj, isMarked) { 388 var year = dateObj.getFullYear(), 389 month = dateObj.getMonth(), 390 day = dateObj.getDate(); 391 392 if (isMarked) { 393 // initialise marked array for month if it doesn't exist 394 if (typeof dc.range[month].marked[year] !== 'object') { 395 dc.range[month].marked[year] = []; 396 } 397 398 // set day as marked 399 dc.range[month].marked[year].push(day); 400 401 } else { 402 // unset day as marked 403 if (typeof dc.range[month].marked[year] === 'object') { 404 var arrIndex = dc.range[month].marked[year].indexOf(day); 405 406 if (arrIndex !== -1) { 407 delete dc.range[month].marked[year][arrIndex]; 408 } 409 } 410 } 411 }, 412 clearAllMarked: function (dc) { 413 for (var month in dc.range) { 414 dc.range[month].marked = {}; 415 } 416 }, 417 setDayDisabled: function (dc, dateObj, isDisabled) { 418 var year = dateObj.getFullYear(), 419 month = dateObj.getMonth(), 420 day = dateObj.getDate(); 421 422 if (isDisabled) { 423 // initialise disabled array for month if it doesn't exist 424 if (typeof dc.range[month].disabled[year] !== 'object') { 425 dc.range[month].disabled[year] = []; 426 } 427 428 // set day as disabled 429 dc.range[month].disabled[year].push(day); 430 431 } else { 432 // unset day as disabled 433 if (typeof dc.range[month].disabled[year] === 'object') { 434 var arrIndex = dc.range[month].disabled[year].indexOf(day); 435 436 if (arrIndex !== -1) { 437 delete dc.range[month].disabled[year][arrIndex]; 438 } 439 } 440 } 441 }, 442 setMonthDisabled: function (dc, dateObj, isDisabled) { 443 var year = dateObj.getFullYear(), 444 month = dateObj.getMonth(); 445 446 if (isDisabled) { 447 // reset month disabled array 448 dc.range[month].disabled[year] = []; 449 450 // set each day in month as disabled 451 for (var day = 1; day <= dc.range[month].max; day++){ 452 dc.range[month].disabled[year].push(day); 453 } 454 455 } else { 456 // unset month as disabled 457 dc.range[month].disabled[year] = []; 458 } 459 }, 460 setDayOfWeekDisabled: function (dc, dateObj, daysOfWeek, isDisabled) { 461 var year = dateObj.getFullYear(),
462 month = dateObj.getMonth(); 463 464 // initialise disabled array for month if it doesn't exist 465 if (typeof dc.range[month].disabled[year] !== 'object') { 466 dc.range[month].disabled[year] = []; 467 } 468 469 // initialise local modifiable date that we will use to call the native getDay() method on 470 var date = new Date(year, month, 1); 471 472 for (var day = 1; day <= dc.range[month].max; day++){ 473 date.setDate(day); 474 475 if (daysOfWeek.indexOf(date.getDay()) !== -1) { 476 if (isDisabled) { 477 dc.range[month].disabled[year].push(day); 478 479 } else { 480 // unset day as disabled 481 var arrIndex = dc.range[month].marked[year].indexOf(day); 482 483 if (arrIndex !== -1) { 484 delete dc.range[month].marked[year][arrIndex]; 485 } 486 } 487 } 488 } 489 }, 490 setWeekdaysDisabled: function (dc, dateObj, isDisabled) { 491 // 0 = Sunday, 6 = Saturday 492 dc.setDayOfWeekDisabled(dc, dateObj, [1, 2, 3, 4, 5], isDisabled); 493 }, 494 setWeekendsDisabled: function (dc, dateObj, isDisabled) { 495 // 0 = Sunday, 6 = Saturday, which are the days we are not setting 496 dc.setDayOfWeekDisabled(dc, dateObj, [0, 6], isDisabled); 497 }, 498 clearAllDisabled: function (dc) { 499 for (var month in dc.range) { 500 dc.range[month].disabled = {}; 501 } 502 }, 503 setMonthMessage: function (dc, dateObj, message) { 504 var year = dateObj.getFullYear(), 505 month = dateObj.getMonth(); 506 507 if ((typeof message === 'string') && (message.length > 0)) { 508 // set month message 509 dc.range[month].message[year] = message; 510 511 } else { 512 // unset month message 513 delete dc.range[month].message[year]; 514 } 515 }, 516 clearAllMessage: function (dc) { 517 for (var month in dc.range) { 518 dc.range[month].message = {}; 519 } 520 }, 521 isDisabledDate: function(dc, counter, dateObj, cmpObj){ 522 if (!cmpObj) { 523 cmpObj = dc.range.current; 524 } 525 526 var disabled = dc.range[cmpObj.month].disabled[cmpObj.year], 527 disabledAll = dc.range[cmpObj.month].disabled['*'], 528 disabledWDays = dc.range[cmpObj.month].disabledWDays, 529 disabledAllWDays = dc.range.disabledWDays; 530 531 var wkd = dateObj.getDay(); 532 533 return !!((disabled && $A.inArray(counter, disabled) !== -1) || (disabledAll && $A.inArray(counter, disabledAll) !== -1) 534 || (disabledWDays.length && $A.inArray(wkd, disabledWDays) !== -1) 535 || (disabledAllWDays.length && $A.inArray(wkd, disabledAllWDays) !== -1) 536 || dc.isOutsideDateRange(dateObj)); 537 538 }, 539 isOutsideDateRange: function(dateObj){ 540 var dateCmp = this.createDateComparisonValue(dateObj); 541 542 return ( 543 (this.minDateComparisonValue && (dateCmp < this.minDateComparisonValue)) || 544 (this.maxDateComparisonValue && (dateCmp > this.maxDateComparisonValue)) 545 ); 546 }, 547 createDayCell: function(i, cellDateObj, cssClasses, isDisabled, isSelected){ 548 var dc = this; 549 550 var cell = '<td '; 551 552 // set correct ARIA attributes 553 if (isSelected){ 554 cell += 'aria-current="date" '; 555 } 556 557 if (isDisabled){ 558 cell += 'aria-disabled="true" '; 559 } 560 561 cell += 'aria-label="'; 562 563 // draw comment? 564 var comments = dc.range[dc.range.current.month].comments[dc.range.current.year], 565 commentsAll = dc.range[dc.range.current.month].comments['*']; 566 567 var comm = ''; 568 if (comments && comments[i]) 569 comm = comments[i]; 570 else if (commentsAll && commentsAll[i]) 571 comm = commentsAll[i]; 572 573 if (comm){ 574 cell += dc.commentedTxt.replace(/<|>|\"/g, '') + ' '; 575 } 576 577 var month = cellDateObj.getMonth(); 578 var dateFormatTokens = { 579 'YYYY': cellDateObj.getFullYear(), 580 'MMMM': dc.range[month].name, 581 'dddd': dc.range.wDays[cellDateObj.getDay()].lng, 582 'MM': ('00' + (month + 1)).slice(-2), 583 'DD': ('00' + i).slice(-2), 584 'Do': dc.getDateOrdinalSuffix(i), 585 'M': (month + 1), 586 'D': i 587 }; 588 589 // set audible date value 590 var re = new RegExp(Object.keys(dateFormatTokens).join('|'), 'gi'); 591 592 cell += dc.audibleDateFormat.replace(re, function (matched){ 593 return dateFormatTokens[matched]; 594 }); 595 596 if (comm){ 597 cell += comm.replace(/<|>|\n/g, ' ').replace(/\"/g, '\"'); 598 } 599 cell += '" role="link" tabindex="-1" '; 600 601 // CSS classes
602 cell += 'class="day ' + (cssClasses ? cssClasses : ''); 603 604 if (dc.highlightToday === true){ 605 if (dc.createDateComparisonValue(cellDateObj) === dc.currentDateComparisonValue) { 606 cell += ' dayToday'; 607 } 608 } 609 610 // set date as visually marked? 611 var isMarked = ( 612 dc.range[dc.range.current.month].marked[dc.range.current.year] && 613 (dc.range[dc.range.current.month].marked[dc.range.current.year].indexOf(i) !== -1) 614 ); 615 616 if ((isSelected && !isDisabled) || isMarked){ 617 cell += ' dayMarked'; 618 } 619 620 if (isDisabled){ 621 cell += ' disabled'; 622 } 623 624 if (comm){ 625 cell += ' comment'; 626 } 627 cell += '" '; 628 629 // Title attribute 630 cell += 'title="'; 631 632 if (isMarked){ 633 cell += dc.markedTxt.replace(/<|>|\"/g, ''); 634 635 } else if (isDisabled){ 636 cell += dc.disabledTxt.replace(/<|>|\"/g, ''); 637 } 638 639 if (comm){ 640 cell += ' ' + dc.commentedTxt.replace(/<|>|\"/g, ''); 641 } 642 cell += '" id="' + dc.baseId + i + '"><span aria-hidden="true">' + i + '</span></td>'; 643 644 return cell; 645 }, 646 createDateComparisonValue: function (dateObj){ 647 return parseInt( 648 ( 649 dateObj.getFullYear() + 650 ('00' + dateObj.getMonth()).slice(-2) + 651 ('00' + dateObj.getDate()).slice(-2) 652 ), 653 10 654 ); 655 }, 656 setDate: function(dc, dateObj){ 657 // if dateObj is not specified, set to an initial value... 658 if (dateObj === undefined){ 659 // ensure initialDate value is within any set date range 660 if ((dc.minDate || dc.maxDate) && dc.isOutsideDateRange(dc.initialDate)) { 661 // initialDate config value is outside of the valid date range, determine an optimal initial date value 662 if (dc.initialDate < dc.minDate) { 663 dateObj = dc.minDate; 664 } else if (dc.initialDate > dc.maxDate) { 665 dateObj = dc.maxDate; 666 } 667 668 } else { 669 // set to initialDate config value 670 dateObj = dc.initialDate; 671 } 672 } 673 674 dc.date = dateObj; 675 dc.setCurrent(dc); 676 dc.fn.current = {}; 677 $A.internal.extend(true, dc.fn.current, dc.range.current); 678 }, 679 runOnceBefore: function(dc){ 680 // If we have minDate / maxDate set, ensure they don't have time precision, and create comparison value 681 if (dc.minDate) { 682 dc.minDate.setHours(0, 0, 0, 0); 683 dc.minDateComparisonValue = dc.createDateComparisonValue(dc.minDate); 684 } 685 if (dc.maxDate) { 686 dc.maxDate.setHours(0, 0, 0, 0); 687 dc.maxDateComparisonValue = dc.createDateComparisonValue(dc.maxDate); 688 } 689 690 // set date to initialDate 691 this.setDate(dc); 692 693 // Cache current date for comparison 694 dc.currentDate = new Date(); 695 dc.currentDateComparisonValue = dc.createDateComparisonValue(dc.currentDate); 696 }, 697 runBefore: function(dc){ 698 // Run custom specified function? 699 if (typeof config.runBefore === 'function'){ 700 config.runBefore(dc); 701 } 702 703 // based on config option, disable weekdays? 704 if (dc.disableWeekdays) { 705 dc.setWeekdaysDisabled(dc, dc.date, true); 706 } 707 708 // based on config option, disable weekends? 709 if (dc.disableWeekends) { 710 dc.setWeekendsDisabled(dc, dc.date, true); 711 } 712 713 if (config.ajax && typeof config.ajax === 'function' && !dc.stopAjax && !dc.ajaxLoading){ 714 dc.ajaxLoading = dc.cancel = true; 715 dc.fn.navBtn = dc.navBtn; 716 config.ajax.apply(dc, [dc, false]); 717 } 718 719 if (dc.range.current.month === 1) 720 dc.range[1].max = (new Date(dc.range.current.year, 1, 29).getMonth() == 1) ? 29 : 28; 721 dc.baseId = 'b' + $A.genId(); 722 dc.prevBtnId = dc.baseId + 'p'; 723 dc.nextBtnId = dc.baseId + 'n'; 724 725 // Calculate prev/next month date values, and whether they are within the allowed date range 726 var prevDateValues = dc.modifyDateValues( 727 { 728 month: dc.range.current.month, 729 year: dc.range.current.year 730 }, 731 { 732 month: -1 733 } 734 ); 735 736 var prevMonth = new Date(); 737 prevMonth.setMonth(prevDateValues.month); 738 prevMonth.setFullYear(prevDateValues.year); 739 740 var nextDateValues = dc.modifyDateValues( 741 { 742 month: dc.range.current.month, 743 year: dc.range.current.year 744 }, 745 { 746 month: 1 747 } 748 ); 749 750 var nextMonth = new Date(); 751 nextMonth.setMonth(nextDateValues.month); 752 nextMonth.setFullYear(nextDateValues.year); 753 754 // Draw the year display and prev/next year buttons? 755 var yearSelector = ''; 756 757 if (!config.condenseYear){ 758 var hasPrevYear = !dc.isOutsideDateRange(new Date((dc.range.current.year - 1), 0, 1)), 759 hasNextYear = !dc.isOutsideDateRange(new Date((dc.range.current.year + 1), 0, 1)); 760 761 yearSelector = '<tr class="yearSelector" role="presentation">' + 762 '<td class="nav prev btn year' + (!hasPrevYear ? ' disabled' : '') + '" accesskey="1" title="' 763 + dc.prevTxt.replace(/<|>|\"/g, '') + ' ' 764 + dc.yearTxt.replace(/<|>|\"/g, '') + '" aria-label="' + dc.prevTxt.replace(/<|>|\"/g, '') + ' ' 765 + dc.yearTxt.replace(/<|>|\"/g, '') + '"' 766 + (!hasPrevYear ? ' aria-disabled="true" tabindex="-1"' : ' tabindex="0"') 767 + ' role="button" id="' + dc.prevBtnId + 'Y"><span aria-hidden="true">' + dc.leftButtonYearText + '</span></td>' + 768 '<td title="' 769 + dc.tooltipTxt.replace(/<|>|\"/g, '') + '" colspan="5" class="year" role="presentation"><span>' 770 + dc.range.current.year + '</span></td>' + 771 '<td class="nav next nav prev btn' + (!hasNextYear ? ' disabled' : '') + '" accesskey="2" title="' 772 + dc.nextTxt.replace(/<|>|\"/g, '') + ' ' 773 + dc.yearTxt.replace(/<|>|\"/g, '') + '" aria-label="' + dc.nextTxt.replace(/<|>|\"/g, '') + ' ' 774 + dc.yearTxt.replace(/<|>|\"/g, '') + '"' 775 + (!hasNextYear ? ' aria-disabled="true" tabindex="-1"' : ' tabindex="0"') 776 + ' role="button" id="' + dc.nextBtnId + 'Y"><span aria-hidden="true">' + dc.rightButtonYearText + '</span></td></tr>'; 777 } 778 779 // Draw the month display and prev/next month buttons 780 var hasPrevMonth = !dc.isOutsideDateRange(new Date(prevDateValues.year, prevDateValues.month, dc.range[prevDateValues.month].max)), 781 hasNextMonth = !dc.isOutsideDateRange(new Date(nextDateValues.year, nextDateValues.month, 1)); 782 783 var monthSelector = '<tr class="monthSelector" role="presentation">' + 784 '<td class="nav prev btn month' + (!hasPrevMonth ? ' disabled' : '') + '" accesskey="3" title="' 785 + dc.prevTxt.replace(/<|>|\"/g, '') + ' ' + dc.monthTxt.replace(/<|>|\"/g, '') + '" aria-label="' 786 + dc.prevTxt.replace(/<|>|\"/g, '') + ' ' + dc.monthTxt.replace(/<|>|\"/g, '') + '"' 787 + (!hasPrevMonth ? ' aria-disabled="true" tabindex="-1"' : ' tabindex="0"') 788 + ' role="button" id="' + dc.prevBtnId + '"><span aria-hidden="true">' + dc.leftButtonMonthText + '</span></td>' + 789 '<td colspan="5" class="month" role="presentation"><span>' 790 + dc.range[dc.range.current.month].name + (!config.condenseYear ? '' : ' ' + dc.range.current.year) + '</span></td>' + 791 '<td class="nav next btn month' + (!hasNextMonth ? ' disabled' : '') + '" accesskey="4" title="' 792 + dc.nextTxt.replace(/<|>|\"/g, '') + ' ' + dc.monthTxt.replace(/<|>|\"/g, '') + '" aria-label="' 793 + dc.nextTxt.replace(/<|>|\"/g, '') + ' ' + dc.monthTxt.replace(/<|>|\"/g, '') + '"' 794 + (!hasNextMonth ? ' aria-disabled="true" tabindex="-1"' : ' tabindex="0"') 795 + ' role="button" id="' + dc.nextBtnId + '"><span aria-hidden="true">' + dc.rightButtonMonthText + '</span></td></tr>'; 796 797 // Start constructing the Datepicker table element 798 dc.source = '<table role="application" class="calendar" aria-label="' + dc.role 799 + '">' + yearSelector + monthSelector + '<tr role="presentation">'; 800 dc.iter = 0; 801 802 // Draw day headers 803 for (var i = 0; i < 7; i++){ 804 var di = dc.getWDay(dc, i), d = dc.range.wDays[di]; 805 806 if (!i){ 807 dc.iter = dc.iterE = (di + 6) > 6 ? -1 + di : di + 6; 808 dc.iterS = di; 809 } 810 dc.source += '<th scope="col" class="week" title="' + d.lng + '" role="presentation"><span>' + d.shrt 811 + '</span></th>'; 812 } 813 dc.source += '</tr><tr role="presentation">'; 814 815 // Start drawing day cells 816 var m = new Date(); 817 m.setDate(1); 818 m.setMonth(dc.range.current.month); 819 m.setFullYear(dc.range.current.year); 820 821 var f = m.getDay(); 822 m.setDate(dc.range[dc.range.current.month].max); 823 var e = m.getDay(), 824 w = dc.iterS; 825 826 // Draw the full calendar? (a full grid containing previous / next month cells) 827 if (dc.drawFullCalendar === true){ 828 var daysInMonth = (new Date(prevDateValues.year, (prevDateValues.month + 1), 0)).getDate(), 829 counter = (daysInMonth - (new Date(dc.range.current.year, dc.range.current.month, 0)).getDay() + dc.range.wdOffset); 830 } 831 832 while (w != f){ 833 w = (w + 1) > 6 ? 0 : w + 1; 834 835 if (dc.drawFullCalendar === true){ 836 prevMonth.setDate(counter); 837 dc.source += dc.createDayCell(counter, prevMonth, 'dayInPrevMonth', dc.isDisabledDate(dc, counter, prevMonth)); 838 ++counter; 839 840 } else{ 841 dc.source += '<td class="empty" role="presentation"><span> </span></td>'; 842 } 843 } 844 845 dc.range.track = {}; 846 847 for (var i = 1; i <= 31; i++){ 848 dc.range.track[dc.baseId + i] = i; 849 } 850 851 for (var i = 1; i <= dc.range[dc.range.current.month].max; i++){ 852 m.setDate(i); 853 854 var isSelected = ((i == dc.fn.current.mDay) && (dc.range.current.month == dc.fn.current.month) && 855 (dc.range.current.year == dc.fn.current.year)); 856 857 // Draw calendar day cell 858 dc.source += dc.createDayCell(i, m, 'dayInMonth', dc.isDisabledDate(dc, i, m), isSelected); 859 860 var w = m.getDay(); 861 862 if (w == dc.iter && i < dc.range[dc.range.current.month].max) 863 dc.source += '</tr><tr role="presentation">'; 864 } 865 866 if (dc.drawFullCalendar === true){ 867 var counter = 1; 868 } 869 870 while (e != dc.iter){ 871 e = (e + 1) > 6 ? 0 : e + 1; 872 873 if (dc.drawFullCalendar === true){ 874 nextMonth.setDate(counter); 875 dc.source += dc.createDayCell(counter, nextMonth, 'dayInNextMonth', dc.isDisabledDate(dc, counter, nextMonth)); 876 ++counter; 877 878 } else{ 879 dc.source += '<td class="empty" role="presentation"><span> </span></td>'; 880 } 881 } 882 dc.source += '</tr></table>'; 883 884 // if a message is set for the month, draw it 885 if (dc.range[dc.range.current.month].message[dc.range.current.year]){ 886 dc.source += 887 '<div class="monthMessage">' + 888 ' <p>' + dc.range[dc.range.current.month].message[dc.range.current.year] + '</p>' + 889 '</div>'; 890 } 891 892 // Close other calendar pickers that are currently open 893 $A.find('*', function(dc){ 894 if (dc.controlType && dc.controlType == 'DatePicker' && dc.loaded) 895 dc.close(); 896 }); 897 }, 898 click: function(ev, dc){ 899 ev.stopPropagation(); 900 }, 901 runDuring: function(dc){ 902 dc.datepickerLoaded = false;
903 $A.bind('body', 'click.datepicker', function(ev){ 904 if (dc.datepickerLoaded) 905 dc.close(); 906 }); 907 908 $A.setAttr(dc.accDCObj, 909 { 910 role: 'dialog', 911 'data-helptext': dc.helpText, 912 'aria-label': dc.role 913 }); 914 915 dc.fn.sraStart.innerHTML = dc.fn.sraEnd.innerHTML = ''; 916 $A.setAttr(dc.fn.sraStart, 917 { 918 'aria-hidden': 'true' 919 }); 920 921 $A.setAttr(dc.fn.sraEnd, 922 { 923 'aria-hidden': 'true' 924 }); 925 }, 926 runAfter: function(dc){ 927 dc.buttons = 928 { 929 pY: config.condenseYear ? null : $A.getEl(dc.prevBtnId + 'Y'), 930 nY: config.condenseYear ? null : $A.getEl(dc.nextBtnId + 'Y'), 931 pM: $A.getEl(dc.prevBtnId), 932 nM: $A.getEl(dc.nextBtnId) 933 }; 934 935 if (!config.condenseYear && dc.disableNavPrevYearBtn) 936 $A.setAttr(dc.buttons.pY, 'aria-disabled', 'true'); 937 938 if (!config.condenseYear && dc.disableNavNextYearBtn) 939 $A.setAttr(dc.buttons.nY, 'aria-disabled', 'true'); 940 941 if (dc.disableNavPrevMonthBtn) 942 $A.setAttr(dc.buttons.pM, 'aria-disabled', 'true'); 943 944 if (dc.disableNavNextMonthBtn) 945 $A.setAttr(dc.buttons.nM, 'aria-disabled', 'true'); 946 947 if (!dc.prevCurrent) 948 dc.prevCurrent = {}; 949 $A.internal.extend(true, dc.prevCurrent, dc.range.current); 950 951 var nMonth = function(){ 952 if (dc.disableNavNextMonthBtn && ($A.getAttr(dc.buttons.nM, 'aria-disabled') == 'true')) 953 return; 954 955 $A.internal.extend(true, dc.prevCurrent, dc.range.current); 956 957 var dateValues = dc.modifyDateValues( 958 { 959 month: dc.range.current.month, 960 year: dc.range.current.year 961 }, 962 { 963 month: 1 964 } 965 ); 966 967 // Only change to next month if its first day is inside the valid date range 968 if(!dc.isOutsideDateRange(new Date(dateValues.year, dateValues.month, 1))){ 969 var day = dc.range.current.mDay > dc.range[dateValues.month].max ? dc.range[dateValues.month].max : dc.range.current.mDay, 970 intendedDate = new Date(dateValues.year, dateValues.month, day); 971 972 // If intended selected date one month ahead is outside of date range, set 973 // selected date to the next available date 974 if (dc.isOutsideDateRange(intendedDate)) 975 dc.date = dc.maxDate; 976 else 977 dc.date = intendedDate; 978 } 979 980 else { 981 dc.date = dc.maxDate; 982 } 983 984 dc.setCurrent(dc); 985 dc.reopen = true; 986 dc.open(); 987 988 }, pMonth = function(){ 989 if (dc.disableNavPrevMonthBtn && ($A.getAttr(dc.buttons.pM, 'aria-disabled') == 'true')) 990 return; 991 992 $A.internal.extend(true, dc.prevCurrent, dc.range.current); 993 994 var dateValues = dc.modifyDateValues( 995 { 996 month: dc.range.current.month, 997 year: dc.range.current.year 998 }, 999 { 1000 month: -1 1001 } 1002 ); 1003 1004 // Only change to previous month if its last day is inside the valid date range 1005 if(!dc.isOutsideDateRange(new Date(dateValues.year, dateValues.month, dc.range[dateValues.month].max))){ 1006 var day = dc.range.current.mDay > dc.range[dateValues.month].max ? dc.range[dateValues.month].max : dc.range.current.mDay, 1007 intendedDate = new Date(dateValues.year, dateValues.month, day); 1008 1009 // If intended selected date one month previously is outside of date range, set 1010 // selected date to the next available date 1011 if(dc.isOutsideDateRange(intendedDate)) 1012 dc.date = dc.minDate; 1013 else 1014 dc.date = intendedDate; 1015 } 1016 1017 else{ 1018 dc.date = dc.minDate; 1019 } 1020 1021 dc.setCurrent(dc); 1022 dc.reopen = true; 1023 dc.open(); 1024 1025 }, gYear = function(forward){ 1026 if ((!forward && ((!config.condenseYear && $A.getAttr(dc.buttons.pY, 'aria-disabled') == 'true') 1027 || (config.condenseYear && dc.disableNavPrevYearBtn)))) { 1028 1029 return; 1030 1031 } else if ((forward && ((!config.condenseYear && $A.getAttr(dc.buttons.nY, 'aria-disabled') == 'true') 1032 || (config.condenseYear && dc.disableNavNextYearBtn)))) { 1033 1034 return; 1035 } 1036 1037 $A.internal.extend(true, dc.prevCurrent, dc.range.current); 1038
1039 var month = dc.range.current.month, 1040 year = forward ? dc.range.current.year + 1 : dc.range.current.year - 1; 1041 1042 if (month === 1) 1043 dc.range[1].max = 28; 1044 var day = dc.range.current.mDay > dc.range[month].max ? dc.range[month].max : dc.range.current.mDay; 1045 1046 // Only change year if the intended date is inside of any set date range 1047 var intendedDate = new Date(year, month, day); 1048 1049 if (dc.isOutsideDateRange(intendedDate)){ 1050 return; 1051 } 1052 1053 dc.date = intendedDate; 1054 dc.setCurrent(dc); 1055 dc.reopen = true; 1056 dc.open(); 1057 }; 1058 var isKP = false; 1059 $A.bind('#' + dc.containerDivId + ' td.day', 1060 { 1061 focus: function(ev){ 1062 if ($A.hasClass(this, 'comment')){ 1063 var tooltipDC = dc.children[0], year = dc.range[dc.range.current.month].comments[dc.range.current.year], 1064 all = dc.range[dc.range.current.month].comments['*'], comm = ''; 1065 1066 if (year && year[dc.range.current.mDay]) 1067 comm = year[dc.range.current.mDay]; 1068 1069 else if (all && all[dc.range.current.mDay]) 1070 comm = all[dc.range.current.mDay]; 1071 comm = trim(comm.replace(/<|>/g, '')); 1072 1073 if (comm){ 1074 tooltipDC.source = comm; 1075 tooltipDC.open(); 1076 } 1077 } 1078 1079 else if (dc.children[0].loaded) 1080 dc.children[0].close(); 1081 1082 if (dc.children[1].openEditor){ 1083 dc.children[1].openEditor = false; 1084 dc.children[1].reset(); 1085 } 1086 }, 1087 click: function(ev){ 1088 // If items from a previous / next month are selected, modify the date accordingly 1089 if ($A.hasClass(this, 'dayInPrevMonth')){ 1090 var prevDateValues = dc.modifyDateValues( 1091 { 1092 month: dc.range.current.month, 1093 year: dc.range.current.year 1094 }, 1095 { 1096 month: -1 1097 } 1098 ); 1099 1100 dc.date = new Date(prevDateValues.year, prevDateValues.month, dc.range.track[this.id]); 1101 1102 } else if ($A.hasClass(this, 'dayInNextMonth')){ 1103 var nextDateValues = dc.modifyDateValues( 1104 { 1105 month: dc.range.current.month, 1106 year: dc.range.current.year 1107 }, 1108 { 1109 month: 1 1110 } 1111 ); 1112 1113 dc.date = new Date(nextDateValues.year, nextDateValues.month, dc.range.track[this.id]); 1114 1115 } else { 1116 // Selection in current month, just adjust the date 1117 dc.date.setDate(dc.range.track[this.id]); 1118 } 1119 1120 dc.setCurrent(dc); 1121 1122 if ($A.hasClass(this, 'selected') || (!commentsEnabled && !$A.hasClass(this, 'comment'))){ 1123 if ($A.getAttr(this, 'aria-disabled') != 'true'){ 1124 $A.internal.extend(true, dc.fn.current, dc.range.current); 1125 handleClick.apply(this, [ev, dc, targ]); 1126 } 1127 1128 else{ 1129 ev.stopPropagation(); 1130 ev.preventDefault(); 1131 } 1132 } 1133 1134 else 1135 dc.setFocus(this); 1136 ev.preventDefault(); 1137 }, 1138 keydown: function(ev){ 1139 changePressed(ev); 1140 var k = ev.which || ev.keyCode; 1141 1142 if (k == 13){ 1143 isKP = true; 1144 1145 if ($A.getAttr(this, 'aria-disabled') != 'true'){ 1146 $A.internal.extend(true, dc.fn.current, dc.range.current); 1147 handleClick.apply(this, [ev, dc, targ]); 1148 } 1149 1150 ev.preventDefault(); 1151 } 1152 1153 else if (k == 32 && commentsEnabled && config.editor && config.editor.show && !dc.children[1].openEditor){ 1154 dc.children[1].openEditor = true; 1155 dc.children[1].reset(); 1156 ev.preventDefault(); 1157 } 1158 1159 else if ((k >= 37 && k <= 40) || k == 27 || (k >= 33 && k <= 36)){ 1160 var wd = dc.range.current.wDay; 1161 1162 if (k == 37){ 1163 // Left arrow key 1164 $A.internal.extend(true, dc.prevCurrent, dc.range.current); 1165 1166 if (dc.range.current.mDay > 1){ 1167 dc.range.current.mDay--; 1168 dc.range.current.wDay = !wd ? 6 : wd - 1; 1169 1170 dc.setFocus(dc.range.index[dc.range.current.mDay - 1], this); 1171 } 1172 1173 else if (dc.range.current.mDay == 1 1174 && $A.getAttr(dc.buttons.pM, 'aria-disabled') != 'true'){ 1175 1176 var dateValues = dc.modifyDateValues( 1177 { 1178 month: dc.range.current.month, 1179 year: dc.range.current.year 1180 }, 1181 { 1182 month: -1 1183 } 1184 ); 1185 var day = dc.range[dateValues.month].max; 1186
1187 if (dateValues.month === 1) 1188 day = (new Date(dateValues.year, 1, 29).getMonth() == 1) ? 29 : 28; 1189 1190 dc.date = new Date(dateValues.year, dateValues.month, day); 1191 dc.setCurrent(dc); 1192 dc.reopen = true; 1193 dc.open(); 1194 } 1195 } 1196 1197 else if (k == 39){ 1198 // Right arrow key 1199 $A.internal.extend(true, dc.prevCurrent, dc.range.current); 1200 1201 if (dc.range.current.mDay < dc.range[dc.range.current.month].max){ 1202 dc.range.current.mDay++; 1203 dc.range.current.wDay = wd == 6 ? 0 : wd + 1; 1204 1205 dc.setFocus(dc.range.index[dc.range.current.mDay - 1], this); 1206 } 1207 1208 else if (dc.range.current.mDay == dc.range[dc.range.current.month].max 1209 && $A.getAttr(dc.buttons.nM, 'aria-disabled') != 'true'){ 1210 1211 var dateValues = dc.modifyDateValues( 1212 { 1213 month: dc.range.current.month, 1214 year: dc.range.current.year 1215 }, 1216 { 1217 month: 1 1218 } 1219 ); 1220 1221 dc.date = new Date(dateValues.year, dateValues.month, 1); 1222 dc.setCurrent(dc); 1223 dc.reopen = true; 1224 dc.open(); 1225 } 1226 } 1227 1228 else if (k == 38){ 1229 // Up arrow key 1230 $A.internal.extend(true, dc.prevCurrent, dc.range.current); 1231 1232 if ((dc.range.current.mDay - 7) > 0){ 1233 dc.range.current.mDay -= 7; 1234 1235 dc.setFocus(dc.range.index[dc.range.current.mDay - 1], this); 1236 } 1237 1238 else if ($A.getAttr(dc.buttons.pM, 'aria-disabled') != 'true'){ 1239 // Go to previous month 1240 var dateValues = dc.modifyDateValues( 1241 { 1242 month: dc.range.current.month, 1243 year: dc.range.current.year 1244 }, 1245 { 1246 month: -1 1247 } 1248 ); 1249 1250 if (dateValues.month === 1 && (new Date(dateValues.year, 1, 29).getMonth() == 1)) 1251 dc.range[dateValues.month].max = 29; 1252 1253 else if (dateValues.month === 1) 1254 dc.range[dateValues.month].max = 28; 1255 1256 var day = dc.range[dateValues.month].max + (dc.range.current.mDay - 7), 1257 intendedDate = new Date(dateValues.year, dateValues.month, day); 1258 1259 // If intended selected date one month previous is outside of date range, do not attempt 1260 // to select the date cell 1261 if (!dc.isOutsideDateRange(intendedDate)){ 1262 dc.date = intendedDate; 1263 dc.setCurrent(dc); 1264 dc.reopen = true; 1265 dc.open(); 1266 } 1267 } 1268 } 1269 1270 else if (k == 40){ 1271 // Down arrow key 1272 $A.internal.extend(true, dc.prevCurrent, dc.range.current); 1273 1274 if ((dc.range.current.mDay + 7) <= dc.range[dc.range.current.month].max){ 1275 dc.range.current.mDay += 7; 1276 1277 dc.setFocus(dc.range.index[dc.range.current.mDay - 1], this); 1278 } 1279 1280 else if ($A.getAttr(dc.buttons.nM, 'aria-disabled') != 'true'){ 1281 // Go to next month 1282 var dateValues = dc.modifyDateValues( 1283 { 1284 month: dc.range.current.month, 1285 year: dc.range.current.year 1286 }, 1287 { 1288 month: 1 1289 } 1290 ); 1291 1292 var day = dc.range.current.mDay + 7 - dc.range[dc.range.current.month].max, 1293 intendedDate = new Date(dateValues.year, dateValues.month, day); 1294 1295 // If intended selected date one month ahead is outside of date range, do not attempt 1296 // to select the date cell 1297 if (!dc.isOutsideDateRange(intendedDate)){ 1298 dc.date = intendedDate; 1299 dc.setCurrent(dc); 1300 dc.reopen = true; 1301 dc.open(); 1302 } 1303 } 1304 } 1305 1306 else if (k == 27){ 1307 // Esc key 1308 dc.close(); 1309 } 1310 1311 else if (k == 33){ 1312 // PageUp key 1313 $A.internal.extend(true, dc.prevCurrent, dc.range.current); 1314 1315 if (dc.pageUpDownNatural === true){ 1316 if (pressed.alt){ 1317 gYear(false); 1318 } else{ 1319 pMonth(); 1320 } 1321 1322 } else{ 1323 if (pressed.alt){ 1324 gYear(true); 1325 } else{ 1326 nMonth(); 1327 } 1328 } 1329 } 1330 1331 else if (k == 34){ 1332 // PageDown key 1333 $A.internal.extend(true, dc.prevCurrent, dc.range.current); 1334 1335 if (dc.pageUpDownNatural === true){ 1336 if (pressed.alt){ 1337 gYear(true); 1338 } else{ 1339 nMonth(); 1340 } 1341 1342 } else{ 1343 if (pressed.alt){ 1344 gYear(false); 1345 } else{ 1346 pMonth(); 1347 } 1348 } 1349 } 1350 1351 else if (k == 36){ 1352 // Home key (goes to the first day of the row) 1353 $A.internal.extend(true, dc.prevCurrent, dc.range.current); 1354 1355 if (wd != dc.iterS && dc.range.current.mDay > 1){ 1356 while (dc.range.current.wDay != dc.iterS && $A.getEl(dc.baseId + (dc.range.current.mDay - 1))){ 1357 dc.range.current.wDay = (dc.range.current.wDay - 1) < 0 ? 6 : dc.range.current.wDay - 1; 1358 dc.range.current.mDay--; 1359 } 1360 dc.setFocus(dc.range.index[dc.range.current.mDay - 1], this); 1361 } 1362 } 1363 1364 else if (k == 35){ 1365 // End key (goes to the last day of the row) 1366 $A.internal.extend(true, dc.prevCurrent, dc.range.current); 1367 1368 if (wd != dc.iterE && dc.range.current.mDay < dc.range[dc.range.current.month].max){ 1369 while (dc.range.current.wDay != dc.iterE && $A.getEl(dc.baseId + (dc.range.current.mDay + 1))){ 1370 dc.range.current.wDay = (dc.range.current.wDay + 1) > 6 ? 0 : dc.range.current.wDay + 1; 1371 dc.range.current.mDay++; 1372 } 1373 dc.setFocus(dc.range.index[dc.range.current.mDay - 1], this); 1374 } 1375 } 1376 ev.preventDefault(); 1377 } 1378 1379 else if (k == 9 && !pressed.alt && !pressed.ctrl && !pressed.shift){ 1380 // Tab key (without any simultaneous modifiers Alt / Ctrl / Shift) 1381 $A.internal.extend(true, dc.prevCurrent, dc.range.current); 1382 1383 if (!config.condenseYear && $A.getAttr(dc.buttons.pY, 'aria-disabled') != 'true') 1384 dc.buttons.pY.focus(); 1385 1386 else if (!config.condenseYear && $A.getAttr(dc.buttons.nY, 'aria-disabled') != 'true') 1387 dc.buttons.nY.focus(); 1388 1389 else if ($A.getAttr(dc.buttons.pM, 'aria-disabled') != 'true') 1390 dc.buttons.pM.focus(); 1391 1392 else if ($A.getAttr(dc.buttons.nM, 'aria-disabled') != 'true') 1393 dc.buttons.nM.focus(); 1394 1395 ev.preventDefault(); 1396 } 1397 1398 else if (k == 9 && !pressed.alt && !pressed.ctrl && pressed.shift){ 1399 // Tab key (with simultaneous Shift modifier) 1400 $A.internal.extend(true, dc.prevCurrent, dc.range.current); 1401 1402 if ($A.getAttr(dc.buttons.nM, 'aria-disabled') != 'true') 1403 dc.buttons.nM.focus(); 1404 1405 else if ($A.getAttr(dc.buttons.pM, 'aria-disabled') != 'true') 1406 dc.buttons.pM.focus(); 1407 1408 else if (!config.condenseYear && $A.getAttr(dc.buttons.nY, 'aria-disabled') != 'true') 1409 dc.buttons.nY.focus(); 1410 1411 else if (!config.condenseYear && $A.getAttr(dc.buttons.pY, 'aria-disabled') != 'true') 1412 dc.buttons.pY.focus(); 1413 1414 ev.preventDefault(); 1415 } 1416 }, 1417 keyup: function(ev){ 1418 changePressed(ev); 1419 var k = ev.which || ev.keyCode; 1420 1421 if (k == 13 && !isKP && !dc.isAdd){ 1422 if ($A.getAttr(this, 'aria-disabled') != 'true'){ 1423 $A.internal.extend(true, dc.fn.current, dc.range.current); 1424 1425 if (!dc.setFocus.firstOpen) 1426 handleClick.apply(this, [ev, dc, targ]); 1427 } 1428 1429 ev.preventDefault(); 1430 } 1431 1432 isKP = dc.setFocus.firstOpen = dc.isAdd = false;
1433 } 1434 }); 1435 1436 $A.bind(dc.buttons.pM, 1437 { 1438 click: function(ev){ 1439 dc.navBtn = 'PM'; 1440 pMonth(); 1441 ev.preventDefault(); 1442 }, 1443 keydown: function(ev){ 1444 changePressed(ev); 1445 var k = ev.which || ev.keyCode; 1446 1447 if (k == 13 || k == 32){ 1448 dc.navBtn = 'PM'; 1449 pMonth(); 1450 ev.preventDefault(); 1451 } 1452 1453 else if (k == 27){ 1454 dc.close(); 1455 ev.preventDefault(); 1456 } 1457 1458 else if (!config.condenseYear && k == 38){ 1459 dc.buttons.pY.focus(); 1460 ev.preventDefault(); 1461 } 1462 1463 else if (k == 39){ 1464 dc.buttons.nM.focus(); 1465 ev.preventDefault(); 1466 } 1467 1468 else if (k == 37 || k == 40){ 1469 ev.preventDefault(); 1470 } 1471 1472 else if (k == 9 && !pressed.alt && !pressed.ctrl && !pressed.shift){ 1473 if ($A.getAttr(dc.buttons.nM, 'aria-disabled') != 'true') 1474 dc.buttons.nM.focus(); 1475 1476 else 1477 $A.query('td.day[tabindex="0"]', dc.containerDiv)[0].focus(); 1478 1479 ev.preventDefault(); 1480 } 1481 1482 else if (k == 9 && !pressed.alt && !pressed.ctrl && pressed.shift){ 1483 if (!config.condenseYear && $A.getAttr(dc.buttons.nY, 'aria-disabled') != 'true') 1484 dc.buttons.nY.focus(); 1485 1486 else if (!config.condenseYear && $A.getAttr(dc.buttons.pY, 'aria-disabled') != 'true') 1487 dc.buttons.pY.focus(); 1488 1489 else 1490 $A.query('td.day[tabindex="0"]', dc.containerDiv)[0].focus(); 1491 1492 ev.preventDefault(); 1493 } 1494 }, 1495 keyup: function(ev){ 1496 changePressed(ev); 1497 } 1498 }); 1499 $A.bind(dc.buttons.nM, 1500 { 1501 click: function(ev){ 1502 dc.navBtn = 'NM'; 1503 nMonth(); 1504 ev.preventDefault(); 1505 }, 1506 keydown: function(ev){ 1507 changePressed(ev); 1508 var k = ev.which || ev.keyCode; 1509 1510 if (k == 13 || k == 32){ 1511 dc.navBtn = 'NM'; 1512 nMonth(); 1513 ev.preventDefault(); 1514 } 1515 1516 else if (k == 27){ 1517 dc.close(); 1518 ev.preventDefault(); 1519 } 1520 1521 else if (!config.condenseYear && k == 38){ 1522 dc.buttons.nY.focus(); 1523 ev.preventDefault(); 1524 } 1525 1526 else if (k == 37){ 1527 dc.buttons.pM.focus(); 1528 ev.preventDefault(); 1529 } 1530 1531 else if (k == 39 || k == 40){ 1532 ev.preventDefault(); 1533 } 1534 1535 else if (k == 9 && !pressed.alt && !pressed.ctrl && !pressed.shift){ 1536 $A.query('td.day[tabindex="0"]', dc.containerDiv)[0].focus(); 1537 ev.preventDefault(); 1538 } 1539 1540 else if (k == 9 && !pressed.alt && !pressed.ctrl && pressed.shift){ 1541 if ($A.getAttr(dc.buttons.pM, 'aria-disabled') != 'true') 1542 dc.buttons.pM.focus(); 1543 1544 else if (!config.condenseYear && $A.getAttr(dc.buttons.nY, 'aria-disabled') != 'true') 1545 dc.buttons.nY.focus(); 1546 1547 else if (!config.condenseYear && $A.getAttr(dc.buttons.pY, 'aria-disabled') != 'true') 1548 dc.buttons.pY.focus(); 1549 1550 else 1551 $A.query('td.day[tabindex="0"]', dc.containerDiv)[0].focus(); 1552 1553 ev.preventDefault(); 1554 } 1555 }, 1556 keyup: function(ev){ 1557 changePressed(ev); 1558 } 1559 }); 1560 1561 if (!config.condenseYear) 1562 $A.bind(dc.buttons.pY, 1563 { 1564 click: function(ev){ 1565 dc.navBtn = 'PY'; 1566 gYear(); 1567 ev.preventDefault(); 1568 }, 1569 keydown: function(ev){ 1570 changePressed(ev); 1571 var k = ev.which || ev.keyCode; 1572 1573 if (k == 13 || k == 32){ 1574 dc.navBtn = 'PY'; 1575 gYear(); 1576 ev.preventDefault(); 1577 } 1578 1579 else if (k == 27){ 1580 dc.close(); 1581 ev.preventDefault(); 1582 } 1583 1584 else if (k == 39){ 1585 dc.buttons.nY.focus(); 1586 ev.preventDefault(); 1587 } 1588 1589 else if (k == 40){ 1590 dc.buttons.pM.focus(); 1591 ev.preventDefault(); 1592 } 1593 1594 else if (k == 37 || k == 38){ 1595 ev.preventDefault(); 1596 } 1597 1598 else if (k == 9 && !pressed.alt && !pressed.ctrl && !pressed.shift){ 1599 if ($A.getAttr(dc.buttons.nY, 'aria-disabled') != 'true') 1600 dc.buttons.nY.focus(); 1601 1602 else if ($A.getAttr(dc.buttons.pM, 'aria-disabled') != 'true') 1603 dc.buttons.pM.focus(); 1604 1605 else if ($A.getAttr(dc.buttons.nM, 'aria-disabled') != 'true') 1606 dc.buttons.nM.focus(); 1607 1608 else 1609 $A.query('td.day[tabindex="0"]', dc.containerDiv)[0].focus(); 1610 1611 ev.preventDefault(); 1612 } 1613 1614 else if (k == 9 && !pressed.alt && !pressed.ctrl && pressed.shift){ 1615 $A.query('td.day[tabindex="0"]', dc.containerDiv)[0].focus(); 1616 ev.preventDefault(); 1617 } 1618 }, 1619 keyup: function(ev){ 1620 changePressed(ev); 1621 } 1622 }); 1623 1624 if (!config.condenseYear) 1625 $A.bind(dc.buttons.nY, 1626 { 1627 click: function(ev){ 1628 dc.navBtn = 'NY'; 1629 gYear(true); 1630 ev.preventDefault(); 1631 }, 1632 keydown: function(ev){ 1633 changePressed(ev); 1634 var k = ev.which || ev.keyCode; 1635 1636 if (k == 13 || k == 32){ 1637 dc.navBtn = 'NY'; 1638 gYear(true); 1639 ev.preventDefault(); 1640 } 1641 1642 else if (k == 27){ 1643 dc.close(); 1644 ev.preventDefault(); 1645 } 1646 1647 else if (k == 37){ 1648 dc.buttons.pY.focus(); 1649 ev.preventDefault(); 1650 } 1651 1652 else if (k == 40){ 1653 dc.buttons.nM.focus(); 1654 ev.preventDefault(); 1655 } 1656 1657 else if (k == 38 || k == 39){ 1658 ev.preventDefault(); 1659 } 1660 1661 else if (k == 9 && !pressed.alt && !pressed.ctrl && !pressed.shift){ 1662 if ($A.getAttr(dc.buttons.pM, 'aria-disabled') != 'true') 1663 dc.buttons.pM.focus(); 1664 1665 else if ($A.getAttr(dc.buttons.nM, 'aria-disabled') != 'true') 1666 dc.buttons.nM.focus(); 1667 1668 else 1669 $A.query('td.day[tabindex="0"]', dc.containerDiv)[0].focus(); 1670 1671 ev.preventDefault(); 1672 } 1673 1674 else if (k == 9 && !pressed.alt && !pressed.ctrl && pressed.shift){ 1675 if ($A.getAttr(dc.buttons.pY, 'aria-disabled') != 'true') 1676 dc.buttons.pY.focus(); 1677 1678 else 1679 $A.query('td.day[tabindex="0"]', dc.containerDiv)[0].focus(); 1680 1681 ev.preventDefault(); 1682 } 1683 }, 1684 keyup: function(ev){ 1685 changePressed(ev); 1686 } 1687 }); 1688 1689 dc.range.index = $A.query('td.dayInMonth', dc.containerDiv); 1690 dc.setFocus.firstOpen = true; 1691 1692 dc.setFocus(dc.range.index[dc.range.current.mDay - 1]); 1693 1694 if (commentsEnabled && config.editor && config.editor.show) 1695 dc.children[1].open(); 1696 1697 $A.bind(window, 'resize.datepicker', function(ev){ 1698 dc.setPosition(); 1699 }); 1700 1701 $A.setAttr(dc.triggerObj, 'aria-expanded', 'true'); 1702 setTimeout(function(){ 1703 dc.datepickerLoaded = true; 1704 }, 750); 1705 1706 if (!dc.navBtnS){ 1707 if (!('ontouchstart' in window || navigator.maxTouchPoints > 0 || navigator.msMaxTouchPoints > 0)) 1708 $A.announce(dc.helpText); 1709 } 1710 dc.navBtnS = false;
1711 }, 1712 helpText: helpText, 1713 runAfterClose: function(dc){ 1714 if (!dc.reopen){ 1715 if (config.resetCurrent){ 1716 dc.date = new Date(); 1717 dc.setCurrent(dc); 1718 $A.internal.extend(true, dc.fn.current, dc.range.current); 1719 } 1720 1721 if (commentsEnabled) 1722 dc.children[0].close(); 1723 1724 if (commentsEnabled && config.editor && config.editor.show){ 1725 dc.children[1].lock = false; 1726 dc.children[1].close(); 1727 } 1728 } 1729 1730 else 1731 dc.reopen = false; 1732 1733 if (config.ajax && typeof config.ajax === 'function') 1734 dc.lock = dc.ajaxLoading = false; 1735 1736 $A.unbind(window, '.datepicker'); 1737 $A.unbind('body', '.datepicker'); 1738 1739 $A.setAttr(dc.triggerObj, 'aria-expanded', 'false'); 1740 1741 // Run custom specified function? 1742 if (typeof config.runAfterClose === 'function'){ 1743 config.runAfterClose(dc); 1744 } 1745 } 1746 } 1747 ]); 1748 // Calendar object declaration end 1749 1750 $A.setAttr(trigger, 'aria-expanded', 'false'); 1751 1752 var odc = $A.reg[pId], odcDel = false, odcDelFn = function(){ 1753 odcDel = false; 1754 }; 1755 $A.bind(trigger, 'click', function(ev){ 1756 if (!odcDel && !odc.loaded){ 1757 odcDel = true; 1758 $A.trigger(this, 'opendatepicker'); 1759 setTimeout(odcDelFn, 1000); 1760 } 1761 1762 else if (!odcDel && odc.loaded){ 1763 odcDel = true; 1764 odc.close(); 1765 setTimeout(odcDelFn, 1000); 1766 } 1767 ev.preventDefault(); 1768 }); 1769 1770 // Comment object declaration start 1771 $A($A.reg[pId], 1772 [ 1773 { 1774 id: pId + 'commentTooltip', 1775 role: config.comments && config.comments.role || 'Comment', 1776 returnFocus: false, 1777 showHiddenClose: false, 1778 allowReopen: true, 1779 autoPosition: isNaN(config.comments && config.comments.autoPosition) ? 1 : config.comments.autoPosition, 1780 offsetTop: isNaN(config.comments && config.comments.offsetTop) ? 0 : config.comments.offsetTop, 1781 offsetLeft: isNaN(config.comments && config.comments.offsetLeft) ? 0 : config.comments.offsetLeft, 1782 cssObj: 1783 { 1784 position: 'absolute', 1785 zIndex: $A.reg[pId].cssObj.zIndex 1786 }, 1787 className: config.comments && config.comments.className || 'commentTooltip', 1788 runBefore: function(dc){ 1789 dc.triggerObj = dc.parent.accDCObj; 1790 } 1791 } 1792 ]); 1793 // Comment object declaration end 1794 1795 // Form object declaration start 1796 $A($A.reg[pId], 1797 [ 1798 { 1799 id: pId + 'commentAdd', 1800 role: config.editor && config.editor.role || 'Edit', 1801 returnFocus: false, 1802 allowReopen: true, 1803 autoPosition: isNaN(config.editor && config.editor.autoPosition) ? 6 : config.editor.autoPosition, 1804 offsetTop: isNaN(config.editor && config.editor.offsetTop) ? 0 : config.editor.offsetTop, 1805 offsetLeft: isNaN(config.editor && config.editor.offsetLeft) ? 0 : config.editor.offsetLeft, 1806 cssObj: 1807 { 1808 position: 'absolute', 1809 zIndex: $A.reg[pId].cssObj.zIndex 1810 }, 1811 className: config.editor && config.editor.className || 'commentAdd', 1812 openEditor: false, 1813 source: '<textarea style="visibility: hidden; display: none;" class="commentTa" title="' 1814 + $A.reg[pId + 'commentTooltip'].role + '"></textarea><button title="' 1815 + (config.editor && config.editor.role || 'Edit') + ' ' + $A.reg[pId + 'commentTooltip'].role 1816 + '" class="commentBtn">' + (config.editor && config.editor.role || 'Edit') + '</button>', 1817 runBefore: function(dc){ 1818 dc.triggerObj = dc.parent.accDCObj; 1819 }, 1820 click: function(ev, dc){ 1821 ev.stopPropagation(); 1822 }, 1823 runDuring: function(dc){ 1824 $A.setAttr(dc.accDCObj, 1825 { 1826 role: 'dialog', 1827 'aria-label': dc.role 1828 }); 1829 1830 $A.setAttr(dc.containerDiv, 'role', 'application'); 1831 1832 dc.fn.sraStart.innerHTML = dc.fn.sraEnd.innerHTML = ''; 1833 $A.setAttr(dc.fn.sraStart, 1834 { 1835 'aria-hidden': 'true' 1836 }); 1837 1838 $A.setAttr(dc.fn.sraEnd, 1839 { 1840 'aria-hidden': 'true' 1841 }); 1842 }, 1843 add: function(dc){ 1844 var comm = trim(dc.textarea.value.replace(/<|>|\n/g, ' ')); 1845 1846 if (!dc.comments[dc.parent.range.current.year]) 1847 dc.comments[dc.parent.range.current.year] = {}; 1848 dc.comments[dc.parent.range.current.year][dc.parent.range.current.mDay] = comm; 1849 var lbl = dc.parent.range.current.mDay + ', ' + dc.parent.range.wDays[dc.parent.range.current.wDay].lng + ' ' 1850 + dc.parent.range[dc.parent.range.current.month].name + ' ' + dc.parent.range.current.year, pre = ''; 1851 1852 if ((dc.parent.range[dc.parent.range.current.month].disabled[dc.parent.range.current.year] 1853 && $A.inArray(dc.parent.range.current.mDay, 1854 dc.parent.range[dc.parent.range.current.month].disabled[dc.parent.range.current.year]) !== -1) 1855 || (dc.parent.range[dc.parent.range.current.month].disabled['*'] && $A.inArray(dc.parent.range.current.mDay, 1856 dc.parent.range[dc.parent.range.current.month].disabled['*']) !== -1)) 1857 pre += dc.parent.disabledTxt.replace(/<|>|\"/g, '') + ' '; 1858 1859 if (!comm) 1860 $A.remClass(dc.parent.current, 'comment'); 1861 1862 else{ 1863 $A.addClass(dc.parent.current, 'comment'); 1864 pre += dc.parent.commentedTxt.replace(/<|>|\"/g, '') + ' '; 1865 } 1866 lbl = pre + lbl; 1867 $A.setAttr(dc.parent.current, 1868 { 1869 title: trim(pre), 1870 'aria-label': lbl + ' ' + comm.replace(/\"/g, '\"') 1871 }); 1872 }, 1873 reset: function(){ 1874 var dc = this; 1875 1876 if (dc.openEditor){ 1877 dc.comments = dc.parent.range[dc.parent.range.current.month].comments; 1878 1879 if (!dc.textarea) 1880 dc.textarea = $A.query('textarea', dc.containerDiv, function(){ 1881 $A.css(this, 1882 { 1883 visibility: '', 1884 display: '' 1885 }); 1886 1887 dc.css('left', dc.parent.accDCObj.offsetLeft); 1888 $A.bind(this, 1889 { 1890 focus: function(ev){ 1891 if (dc.parent.children[0].loaded) 1892 dc.parent.children[0].close(); 1893 }, 1894 keydown: function(ev){ 1895 var k = ev.which || ev.keyCode; 1896 1897 if (this.value.length > 800) 1898 this.value = this.value.substring(0, 799); 1899 1900 if (k == 13){ 1901 dc.parent.isAdd = true; 1902 dc.add.apply(this, [dc]); 1903 dc.parent.current.focus(); 1904 dc.openEditor = false;
1905 dc.reset(); 1906 ev.preventDefault(); 1907 } 1908 1909 else if (k == 27){ 1910 dc.parent.current.focus(); 1911 dc.openEditor = false; 1912 dc.reset(); 1913 ev.preventDefault(); 1914 } 1915 } 1916 }); 1917 })[0]; 1918 1919 else{ 1920 $A.css(dc.textarea, 1921 { 1922 visibility: '', 1923 display: '' 1924 }); 1925 1926 dc.css('left', dc.parent.accDCObj.offsetLeft); 1927 } 1928 $A.setAttr(dc.textarea, 1929 { 1930 title: dc.parent.range.current.mDay + ', ' 1931 + dc.parent.range.wDays[dc.parent.range.current.wDay].lng + ' ' 1932 + dc.parent.range[dc.parent.range.current.month].name + ' ' + dc.parent.range.current.year 1933 }).focus(); 1934 1935 if (dc.comments[dc.parent.range.current.year] 1936 && dc.comments[dc.parent.range.current.year][dc.parent.range.current.mDay]) 1937 dc.textarea.value = dc.comments[dc.parent.range.current.year][dc.parent.range.current.mDay]; 1938 $A.setAttr(dc.commentBtn, 1939 { 1940 title: (config.editor && config.editor.action1 || 'Save') + ' ' + $A.reg[pId + 'commentTooltip'].role 1941 }).innerHTML = config.editor && config.editor.action1 || 'Save'; 1942 } 1943 1944 else{ 1945 if (dc.textarea){ 1946 dc.textarea.value = ''; 1947 $A.css(dc.textarea, 1948 { 1949 visibility: 'hidden', 1950 display: 'none' 1951 }); 1952 } 1953 1954 dc.css('left', dc.parent.accDCObj.offsetLeft + dc.parent.accDCObj.offsetWidth - dc.accDCObj.offsetWidth); 1955 $A.setAttr(dc.commentBtn, 1956 { 1957 title: (config.editor && config.editor.role || 'Edit') + ' ' + $A.reg[pId + 'commentTooltip'].role 1958 }).innerHTML = config.editor && config.editor.role || 'Edit'; 1959 } 1960 }, 1961 runAfter: function(dc){ 1962 $A.query('button', dc.containerDiv, function(){ 1963 dc.commentBtn = this; 1964 $A.bind(this, 1965 { 1966 focus: function(ev){ 1967 if (dc.parent.children[0].loaded) 1968 dc.parent.children[0].close(); 1969 }, 1970 click: function(ev){ 1971 if (dc.openEditor){ 1972 dc.parent.isAdd = true; 1973 dc.add.apply(this, [dc]); 1974 dc.parent.current.focus(); 1975 dc.openEditor = false; 1976 dc.reset(); 1977 } 1978 1979 else{ 1980 dc.openEditor = true; 1981 dc.reset(); 1982 } 1983 ev.preventDefault(); 1984 }, 1985 keydown: function(ev){ 1986 var k = ev.which || ev.keyCode; 1987 1988 if (k == 27){ 1989 if (dc.openEditor){ 1990 dc.parent.current.focus(); 1991 dc.openEditor = false; 1992 dc.reset(); 1993 } 1994 1995 ev.preventDefault(); 1996 } 1997 } 1998 }); 1999 }); 2000 dc.reset(); 2001 dc.lock = true; 2002 2003 $A.bind(window, 'resize.dateeditor', function(ev){ 2004 dc.setPosition(); 2005 dc.reset(); 2006 }); 2007 2008 $A.bind($A.query('textarea', dc.containerDiv)[0], 'keydown', function(ev){ 2009 var k = ev.which || ev.keyCode; 2010 2011 if (k == 9 && !ev.altKey && !ev.ctrlKey && ev.shiftKey){ 2012 $A.query('button', dc.containerDiv)[0].focus(); 2013 ev.preventDefault(); 2014 } 2015 }); 2016 }, 2017 tabOut: function(ev, dc){ 2018 $A.query('textarea', dc.containerDiv)[0].focus(); 2019 }, 2020 runBeforeClose: function(dc){ 2021 dc.openEditor = false; 2022 dc.textarea = null; 2023 2024 $A.unbind(window, 'resize.dateeditor'); 2025 2026 if (config.ajax && typeof config.ajax === 'function') 2027 config.ajax.apply(dc.parent, [dc.parent, true]); 2028 2029 dc.parent.setFocus.firstOpen = true; 2030 }, 2031 lock: commentsEnabled && config.editor && config.editor.show ? false : true 2032 } 2033 ]); 2034 // Form object declaration end 2035 2036 }; 2037 2038 var trim = function(str){ 2039 return str.replace(/^\s+|\s+$/g, ''); 2040 }; 2041})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.