UNPKG

apex4x

Version:

The Comprehensive ARIA Development Suite

1,292 lines (1,210 loc) 136 kB
/*@license ARIA Date Picker Module 5.11 for Apex 4X Author: Bryan Garaventa (https://www.linkedin.com/in/bgaraventa) Contributions by Danny Allen (dannya.com) / Wonderscore Ltd (wonderscore.co.uk) https://github.com/whatsock/apex License: MIT <https://opensource.org/licenses/MIT> */ (function () { if (!("setDatepicker" in $A)) { $A.addWidgetProfile("Datepicker", { configure: function (dc) { return { returnFocus: false, allowRerender: true, exposeBounds: true, exposeHiddenClose: false, }; }, role: function (dc) { return { role: "dialog", "aria-modal": "false", "aria-label": dc.role, }; }, innerRole: function (dc) { return { role: "application", }; }, }); $A.extend({ setDatepicker: function (config) { var config = config || {}, helpTextShort = config.helpTextShort ? config.helpTextShort : "Press F1 for help.", helpText = config.helpText ? config.helpText : "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.", monthOnly = config.monthOnly === true, monthSelect = monthOnly || config.monthSelect === true, yearSelect = monthOnly || config.yearSelect === true, forceSelect = monthOnly || config.forceSelect === true, // Toggles for openOnFocus support. openOnFocusHelpText = config.openOnFocusHelpText ? config.openOnFocusHelpText : "Press Down arrow to browse the calendar, or Escape to close.", onFocusInit = false, onFocusTraverse = false, pId = config.id || $A.genId(), trigger = $A.morph(config.toggle), targ = $A.morph(config.input), commentsEnabled = !monthOnly && config.enableComments === true, // Control the behavior of date selection clicks handleClick = $A.isFn(config.onActivate) ? config.onActivate : function (ev, dc) { // format selected calendar value and set into input field targ.value = dc.formatDate(dc); $A.trigger(targ, "input change"); dc.remove(); if (!dc.triggerClicked) $A.focus(config.returnFocusTo || targ); else $A.focus(config.returnFocusTo || trigger); dc.triggerClicked = false; }, pressed = {}, changePressed = function (ev) { pressed.alt = ev.altKey; pressed.ctrl = ev.ctrlKey; pressed.shift = ev.shiftKey; }; var baseId = $A.genId(); // Calendar object declaration start var mainDC = $A( [ { id: pId, role: config.role || "Calendar", widgetType: "Datepicker", // autoCloseWidget: true, autoCloseSameWidget: true, trigger: trigger, target: targ, on: "opendatepicker", disabled: config.disabled === true, // Toggles for openOnFocus support. returnFocus: false, openOnFocus: config.openOnFocus === true, openOnFocusHelpText: openOnFocusHelpText, showEscBtn: monthOnly || config.showEscBtn === true, escBtnName: config.escBtnName || (monthOnly ? "Save" : "Close"), escBtnIcon: config.escBtnIcon || "&times;", tooltipTxt: config.tooltipTxt || "Press Escape to cancel", markedTxt: config.markedTxt || "Selected", disabledTxt: config.disabledTxt || "Disabled", commentedTxt: config.commentedTxt || "Has Comment", prevTxt: config.prevTxt || "Previous", nextTxt: config.nextTxt || "Next", monthTxt: config.monthTxt || "Month", yearTxt: config.yearTxt || "Year", leftButtonYearText: config.leftButtonYearText || "&#8656;", rightButtonYearText: config.rightButtonYearText || "&#8658;", leftButtonMonthText: config.leftButtonMonthText || "&#8592;", rightButtonMonthText: config.rightButtonMonthText || "&#8594;", drawFullCalendar: config.drawFullCalendar === true, highlightToday: $A.isBool(config.highlightToday) ? config.highlightToday : true, pageUpDownNatural: true, // inputDateFormat: config.inputDateFormat || "dddd MMMM D, YYYY", inputDateFormat: config.inputDateFormat || "MM/DD/YYYY", audibleDateFormat: config.audibleDateFormat || "dddd D MMMM YYYY", initialDate: config.initialDate instanceof Date ? config.initialDate : new Date(), minDate: config.minDate !== undefined ? config.minDate instanceof Date ? config.minDate : new Date( new Date().setDate( new Date().getDate() + config.minDate, ), ) : undefined, maxDate: config.maxDate !== undefined ? config.maxDate instanceof Date ? config.maxDate : new Date( new Date().setDate( new Date().getDate() + config.maxDate, ), ) : undefined, disableWeekdays: config.disableWeekdays !== undefined ? config.disableWeekdays : false, disableWeekends: config.disableWeekends !== undefined ? config.disableWeekends : false, className: config.className || "calendar", range: { disabledWDays: [], 0: { name: config.months && config.months[0] ? config.months[0] : "January", max: 31, marked: {}, disabled: {}, disabledWDays: [], comments: {}, message: {}, }, 1: { name: config.months && config.months[1] ? config.months[1] : "February", max: 28, marked: {}, disabled: {}, disabledWDays: [], comments: {}, message: {}, }, 2: { name: config.months && config.months[2] ? config.months[2] : "March", max: 31, marked: {}, disabled: {}, disabledWDays: [], comments: {}, message: {}, }, 3: { name: config.months && config.months[3] ? config.months[3] : "April", max: 30, marked: {}, disabled: {}, disabledWDays: [], comments: {}, message: {}, }, 4: { name: config.months && config.months[4] ? config.months[4] : "May", max: 31, marked: {}, disabled: {}, disabledWDays: [], comments: {}, message: {}, }, 5: { name: config.months && config.months[5] ? config.months[5] : "June", max: 30, marked: {}, disabled: {}, disabledWDays: [], comments: {}, message: {}, }, 6: { name: config.months && config.months[6] ? config.months[6] : "July", max: 31, marked: {}, disabled: {}, disabledWDays: [], comments: {}, message: {}, }, 7: { name: config.months && config.months[7] ? config.months[7] : "August", max: 31, marked: {}, disabled: {}, disabledWDays: [], comments: {}, message: {}, }, 8: { name: config.months && config.months[8] ? config.months[8] : "September", max: 30, marked: {}, disabled: {}, disabledWDays: [], comments: {}, message: {}, }, 9: { name: config.months && config.months[9] ? config.months[9] : "October", max: 31, marked: {}, disabled: {}, disabledWDays: [], comments: {}, message: {}, }, 10: { name: config.months && config.months[10] ? config.months[10] : "November", max: 30, marked: {}, disabled: {}, disabledWDays: [], comments: {}, message: {}, }, 11: { name: config.months && config.months[11] ? config.months[11] : "December", max: 31, marked: {}, disabled: {}, disabledWDays: [], comments: {}, message: {}, }, wDays: [ { shrt: config.days && config.days[0] ? config.days[0].s : "S", lng: config.days && config.days[0] ? config.days[0].l : "Sunday", }, { shrt: config.days && config.days[1] ? config.days[1].s : "M", lng: config.days && config.days[1] ? config.days[1].l : "Monday", }, { shrt: config.days && config.days[2] ? config.days[2].s : "T", lng: config.days && config.days[2] ? config.days[2].l : "Tuesday", }, { shrt: config.days && config.days[3] ? config.days[3].s : "W", lng: config.days && config.days[3] ? config.days[3].l : "Wednesday", }, { shrt: config.days && config.days[4] ? config.days[4].s : "T", lng: config.days && config.days[4] ? config.days[4].l : "Thursday", }, { shrt: config.days && config.days[5] ? config.days[5].s : "F", lng: config.days && config.days[5] ? config.days[5].l : "Friday", }, { shrt: config.days && config.days[6] ? config.days[6].s : "S", lng: config.days && config.days[6] ? config.days[6].l : "Saturday", }, ], // Change the week day offset for the calendar display wdOffset: isNaN(config.wdOffset) ? 0 : config.wdOffset, }, getWDay: function (dc, d, r) { var d = $A.isNum(d) ? d : dc.range.current.wDay, o = dc.range.wdOffset; if (o < 0) d = d + o < 0 ? 7 + o : d + o; else if (o > 0) d = d + o > 6 ? -1 + (d + o - 6) : d + o; if (r) d = 6 - d; return d; }, getDateOrdinalSuffix: function (i) { var j = i % 10, k = i % 100; if (j === 1 && k !== 11) { return i + "st"; } if (j === 2 && k !== 12) { return i + "nd"; } if (j === 3 && k !== 13) { return i + "rd"; } return i + "th"; }, formatDate: function (dc, dateFormatTokens, dateFormat) { if (!dateFormatTokens) dateFormatTokens = { YYYY: dc.range.current.year, YY: dc.range.current.year.toString().slice(-2), MMMM: dc.range[dc.range.current.month].name, dddd: dc.range.wDays[dc.range.current.wDay].lng, MM: ("00" + (dc.range.current.month + 1)).slice(-2), DD: ("00" + dc.range.current.mDay).slice(-2), Do: dc.getDateOrdinalSuffix(dc.range.current.mDay), M: dc.range.current.month + 1, D: dc.range.current.mDay, }; // if dateFormat is not specified, use component default if (!$A.isStr(dateFormat)) dateFormat = dc.inputDateFormat; var re = new RegExp( Object.keys(dateFormatTokens).join("|"), "gi", ); return dateFormat.replace(re, function (matched) { return dateFormatTokens[matched]; }); }, modifyDateValues: function (values, modifications) { // Note: Months are zero based for (var key in modifications) { var modification = modifications[key]; if (key === "month") { values.month += modification; if (modification < 0) { // Subtraction if (values.month < 0) { values.month = 11; if (values.year) { values.year -= 1; } } } else { // Addition if (values.month > 11) { values.month = 0; if (values.year) { values.year += 1; } } } } } return values; }, setFocus: function (o, p, s) { var dc = this; if (!o) return false; dc.current = o; if (!monthOnly) { dc.query("td.dayInMonth.selected", function (i, p) { $A.setAttr(p, { tabindex: "-1", }); $A.remClass(p, "selected"); $A.data(p, "_Selected", 0); }); $A.addClass(o, "selected"); $A.data(o, "_Selected", true); $A.setAttr(o, { tabindex: "0", }); } if (!s) { if (dc.navBtn === "PM") { dc.buttons.pM.focus(); setTimeout(function () { $A.announce( dc.range[dc.range.current.month].name, false, true, ); }, 1); dc.navBtnS = true; } else if (dc.navBtn === "NM") { dc.buttons.nM.focus(); setTimeout(function () { $A.announce( dc.range[dc.range.current.month].name, false, true, ); }, 1); dc.navBtnS = true; } else if (dc.navBtn === "PY") { dc.buttons.pY.focus(); setTimeout(function () { $A.announce( dc.range.current.year.toString(), false, true, ); }, 1); dc.navBtnS = true; } else if (dc.navBtn === "NY") { dc.buttons.nY.focus(); setTimeout(function () { $A.announce( dc.range.current.year.toString(), false, true, ); }, 1); dc.navBtnS = true; } else if (dc.navBtn === "CY") { if (!dc.buttons.cYS.hidden) dc.buttons.cYS.focus(); else if (!dc.buttons.cY.hidden) dc.buttons.cY.focus(); } else if ( dc.navBtn === "CM" || (monthOnly && (!dc.openOnFocus || triggered)) ) { if (dc.navBtn === "CM") { if (!dc.buttons.cMS.hidden) dc.buttons.cMS.focus(); else if (!dc.buttons.cM.hidden) dc.buttons.cM.focus(); } else { if (!dc.buttons.cYS.hidden) dc.buttons.cYS.focus(); else if (!dc.buttons.cY.hidden) dc.buttons.cY.focus(); } } else { // Toggles for openOnFocus support. if ( !dc.openOnFocus || (dc.openOnFocus && !onFocusInit && onFocusTraverse) ) { o.focus(); } } } if (dc.fn.navBtn) dc.fn.navBtn = ""; else dc.navBtn = ""; return true; }, setCurrent: function (dc) { if (dc.date instanceof Date) { dc.range.current = { mDay: dc.date.getDate(), month: dc.date.getMonth(), year: dc.date.getFullYear(), wDay: dc.date.getDay(), }; } }, setDayMarked: function (dc, dateObj, isMarked) { var year = dateObj.getFullYear(), month = dateObj.getMonth(), day = dateObj.getDate(); if (isMarked) { // initialise marked array for month if it doesn't exist if (typeof dc.range[month].marked[year] !== "object") { dc.range[month].marked[year] = []; } // set day as marked dc.range[month].marked[year].push(day); } else { // unset day as marked if (typeof dc.range[month].marked[year] === "object") { var arrIndex = dc.range[month].marked[year].indexOf(day); if (arrIndex !== -1) { delete dc.range[month].marked[year][arrIndex]; } } } }, clearAllMarked: function (dc) { for (var month in dc.range) { dc.range[month].marked = {}; } }, setDayDisabled: function (dc, dateObj, isDisabled) { var year = dateObj.getFullYear(), month = dateObj.getMonth(), day = dateObj.getDate(); if (isDisabled) { // initialise disabled array for month if it doesn't exist if (typeof dc.range[month].disabled[year] !== "object") { dc.range[month].disabled[year] = []; } // set day as disabled dc.range[month].disabled[year].push(day); } else { // unset day as disabled if (typeof dc.range[month].disabled[year] === "object") { var arrIndex = dc.range[month].disabled[year].indexOf(day); if (arrIndex !== -1) { delete dc.range[month].disabled[year][arrIndex]; } } } }, setMonthDisabled: function (dc, dateObj, isDisabled) { var year = dateObj.getFullYear(), month = dateObj.getMonth(); if (isDisabled) { // reset month disabled array dc.range[month].disabled[year] = []; // set each day in month as disabled for (var day = 1; day <= dc.range[month].max; day++) { dc.range[month].disabled[year].push(day); } } else { // unset month as disabled dc.range[month].disabled[year] = []; } }, setDayOfWeekDisabled: function ( dc, dateObj, daysOfWeek, isDisabled, ) { var year = dateObj.getFullYear(), month = dateObj.getMonth(); // initialise disabled array for month if it doesn't exist if (typeof dc.range[month].disabled[year] !== "object") { dc.range[month].disabled[year] = []; } // initialise local modifiable date that we will use to call the native getDay() method on var date = new Date(year, month, 1); for (var day = 1; day <= dc.range[month].max; day++) { date.setDate(day); if (daysOfWeek.indexOf(date.getDay()) !== -1) { if (isDisabled) { dc.range[month].disabled[year].push(day); } else { // unset day as disabled var arrIndex = dc.range[month].marked[year].indexOf(day); if (arrIndex !== -1) { delete dc.range[month].marked[year][arrIndex]; } } } } }, setWeekdaysDisabled: function (dc, dateObj, isDisabled) { // 0 = Sunday, 6 = Saturday dc.setDayOfWeekDisabled( dc, dateObj, [1, 2, 3, 4, 5], isDisabled, ); }, setWeekendsDisabled: function (dc, dateObj, isDisabled) { // 0 = Sunday, 6 = Saturday, which are the days we are not setting dc.setDayOfWeekDisabled(dc, dateObj, [0, 6], isDisabled); }, clearAllDisabled: function (dc) { for (var month in dc.range) { dc.range[month].disabled = {}; } }, setMonthMessage: function (dc, dateObj, message) { var year = dateObj.getFullYear(), month = dateObj.getMonth(); if ($A.isStr(message) && message.length > 0) { // set month message dc.range[month].message[year] = message; } else { // unset month message delete dc.range[month].message[year]; } }, clearAllMessage: function (dc) { for (var month in dc.range) { dc.range[month].message = {}; } }, isDisabledYear: function (dc, year) { for (var month = 0; month <= 11; month++) { if (!dc.isDisabledMonth(dc, month, year)) return false; } return true; }, isDisabledMonth: function (dc, month, year) { for (var day = 1; day <= dc.range[month].max; day++) { if (!dc.isDisabledDate(dc, day, new Date(year, month, day))) return false; } return true; }, isDisabledDate: function (dc, counter, dateObj, cmpObj) { if (!cmpObj) { cmpObj = dc.range.current; } var disabled = dc.range[cmpObj.month].disabled[cmpObj.year], disabledAll = dc.range[cmpObj.month].disabled["*"], disabledWDays = dc.range[cmpObj.month].disabledWDays, disabledAllWDays = dc.range.disabledWDays; var wkd = dateObj.getDay(); return !!( (disabled && $A.inArray(counter, disabled) !== -1) || (disabledAll && $A.inArray(counter, disabledAll) !== -1) || (disabledWDays.length && $A.inArray(wkd, disabledWDays) !== -1) || (disabledAllWDays.length && $A.inArray(wkd, disabledAllWDays) !== -1) || dc.isOutsideDateRange(dateObj) ); }, isOutsideDateRange: function (dateObj) { var dateCmp = this.createDateComparisonValue(dateObj); return ( (this.minDateComparisonValue && dateCmp < this.minDateComparisonValue) || (this.maxDateComparisonValue && dateCmp > this.maxDateComparisonValue) ); }, createDayCell: function ( i, cellDateObj, cssClasses, isDisabled, isSelected, ) { var dc = this, cell = "<td ", dateToday = dc.createDateComparisonValue(new Date()), dateNew = dc.createDateComparisonValue(cellDateObj); // set correct ARIA attributes if (dateNew === dateToday) { cell += 'aria-current="date" '; } if (isDisabled) { cell += 'aria-disabled="true" '; } cell += 'aria-label="'; // draw comment? var comments = dc.range[dc.range.current.month].comments[ dc.range.current.year ], commentsAll = dc.range[dc.range.current.month].comments["*"]; var comm = ""; if (comments && comments[i]) comm = comments[i]; else if (commentsAll && commentsAll[i]) comm = commentsAll[i]; if (comm) { cell += dc.commentedTxt.replace(/<|>|\"/g, "") + " "; } var month = cellDateObj.getMonth(); var dateFormatTokens = { YYYY: cellDateObj.getFullYear(), MMMM: dc.range[month].name, dddd: dc.range.wDays[cellDateObj.getDay()].lng, MM: ("00" + (month + 1)).slice(-2), DD: ("00" + i).slice(-2), Do: dc.getDateOrdinalSuffix(i), M: month + 1, D: i, }; // set audible date value var re = new RegExp( Object.keys(dateFormatTokens).join("|"), "gi", ); cell += dc.audibleDateFormat.replace(re, function (matched) { return dateFormatTokens[matched]; }); if (comm) { cell += comm.replace(/<|>|\n/g, " ").replace(/\"/g, '\\"'); } cell += '" role="button" tabindex="-1" '; // CSS classes cell += 'class="day ' + (cssClasses ? cssClasses : ""); if (dc.highlightToday === true) { if (dateNew === dateToday) { cell += " dayToday"; } } // set date as visually marked? var isMarked = dc.range[dc.range.current.month].marked[ dc.range.current.year ] && dc.range[dc.range.current.month].marked[ dc.range.current.year ].indexOf(i) !== -1; if ((isSelected && !isDisabled) || isMarked) { cell += " dayMarked"; } if (isDisabled) { cell += " disabled"; } if (comm) { cell += " comment"; } cell += '" '; // Title attribute cell += 'title="'; if (isMarked) { cell += dc.markedTxt.replace(/<|>|\"/g, ""); } else if (isDisabled) { cell += dc.disabledTxt.replace(/<|>|\"/g, ""); } cell += '" id="' + dc.baseId + i + '"><span aria-hidden="true">' + i + "</span></td>"; return cell; }, createDateComparisonValue: function (dateObj) { return parseInt( dateObj.getFullYear() + ("00" + dateObj.getMonth()).slice(-2) + ("00" + dateObj.getDate()).slice(-2), 10, ); }, presetDate: function (dc, initialDate, minDate, maxDate) { dc = dc || this; dc.initialDate = initialDate || dc.initialDate || new Date(); dc.minDate = minDate || dc.minDate || null; dc.maxDate = maxDate || dc.maxDate || null; dc.setDateComparisons(dc); dc.date = !dc.isDisabledDate( dc, dc.initialDate.getDate(), dc.initialDate, ) ? dc.initialDate : new Date(); dc.setCurrent(dc); dc.fn.current = {}; $A.extend(true, dc.fn.current, dc.range.current); }, setDate: function (dc, dateObj) { // if dateObj is not specified, set to an initial value... if (dateObj === undefined) { // ensure initialDate value is within any set date range if ( (dc.minDate || dc.maxDate) && dc.isOutsideDateRange(dc.initialDate) ) { // initialDate config value is outside of the valid date range, determine an optimal initial date value if (dc.initialDate < dc.minDate) { dateObj = dc.minDate; } else if (dc.initialDate > dc.maxDate) { dateObj = dc.maxDate; } } else { // set to initialDate config value dateObj = dc.initialDate; } } dc.date = dateObj; dc.setCurrent(dc); dc.fn.current = {}; $A.extend(true, dc.fn.current, dc.range.current); }, setDateComparisons: function (dc) { // If we have minDate / maxDate set, ensure they don't have time precision, and create comparison value if (dc.minDate instanceof Date) { dc.minDate.setHours(0, 0, 0, 0); dc.minDateComparisonValue = dc.createDateComparisonValue( dc.minDate, ); } if (dc.maxDate instanceof Date) { dc.maxDate.setHours(0, 0, 0, 0); dc.maxDateComparisonValue = dc.createDateComparisonValue( dc.maxDate, ); } if (dc.initialDate instanceof Date) { dc.currentDate = dc.initialDate; } else { dc.currentDate = new Date(); } // Cache current date for comparison dc.currentDateComparisonValue = dc.createDateComparisonValue( dc.currentDate, ); }, storeCurrentDate: function (dc) { dc.date = new Date( dc.range.current.year, dc.range.current.month, dc.range.current.mDay, ); }, setDisabled: function (dc, s) { if (typeof dc === "boolean") { s = dc; dc = this; } else dc = dc || this; dc.disabled = s ? true : false; $A.setAttr([targ, trigger], "disabled", dc.disabled); if (!dc.disabled) $A.remAttr([targ, trigger], "disabled"); }, onceBeforeRender: function (dc) { if (!(dc.date instanceof Date)) { if ( dc.yearSelect && !(dc.minDate instanceof Date) && !$A.isNum(dc.minDate) && $A.isNum(dc.yearSelectMin) ) { dc.minDate = new Date(dc.yearSelectMin, 0, 1); } if ( dc.yearSelect && !(dc.maxDate instanceof Date) && !$A.isNum(dc.maxDate) && $A.isNum(dc.yearSelectMax) ) { dc.maxDate = new Date(dc.yearSelectMax, 11, 31); } dc.setDateComparisons(dc); dc.setDate(dc); } }, rerenderTable: function (dc) { dc.rerendering = true; dc.afterRemove(dc); dc.beforeRender(dc); dc.duringRender(dc); dc.afterRender(dc); dc.rerendering = false; }, beforeRender: function (dc) { function isValidDateString(dateString) { var regex_mmddyyyy = /^(0?[1-9]|1[0-2])\/(0?[1-9]|[12][0-9]|3[01])\/\d{4}$/, regex_ddmmyyyy = /^(0?[1-9]|[12][0-9]|3[01])\/(0?[1-9]|1[0-2])\/\d{4}$/; return ( regex_mmddyyyy.test(dateString) || regex_ddmmyyyy.test(dateString) ); } var dateValue = targ.value.replace(/\.|\-/g, "/"), dateParts = targ.value.split("/"); if (dateParts.length === 2) { if (dateParts[1] > 12) { if (dateParts[1].length === 2) dateParts[1] = "20" + dateParts[1]; dateValue = dateParts[0] + "/01/" + dateParts[1]; } else if (dateParts[0] > 12) { if (dateParts[0].length === 2) dateParts[0] = "20" + dateParts[0]; dateValue = dateParts[1] + "/01/" + dateParts[0]; } } else if ( config.inputDateFormat === "DD/MM/YYYY" && dateParts.length === 3 ) { if (dateParts[2].length === 2) dateParts[2] = "20" + dateParts[2]; dateValue = dateParts[1] + "/" + dateParts[0] + "/" + dateParts[2]; } else if ( config.inputDateFormat === "MM/DD/YYYY" && dateParts.length === 3 ) { if (dateParts[2].length === 2) dateParts[2] = "20" + dateParts[2]; dateValue = dateParts[0] + "/" + dateParts[1] + "/" + dateParts[2]; } var isValid = isValidDateString(dateValue); if (!isValid) { dateValue = dc.initialDate; } if ( !dc.rerendering && isValid && dateValue && !dc.isOutsideDateRange(new Date(dateValue)) ) { dc.presetDate(dc, new Date(dateValue)); } // based on config option, disable weekdays? if (dc.disableWeekdays) { dc.setWeekdaysDisabled(dc, dc.date, true); } // based on config option, disable weekends? if (dc.disableWeekends) { dc.setWeekendsDisabled(dc, dc.date, true); } if ( $A.isFn(config.configure) && !dc.stopConfigure && !dc.configureLoading ) { dc.configureLoading = dc.cancel = true; dc.fn.navBtn = dc.navBtn; if (config.configure.apply(dc, [dc]) === true) { setTimeout(function () { dc.render(); }, 1); } } if (dc.range.current.month === 1) dc.range[1].max = new Date(dc.range.current.year, 1, 29).getMonth() === 1 ? 29 : 28; dc.baseId = baseId; dc.prevBtnId = dc.baseId + "p"; dc.currentBtnId = dc.baseId + "c"; dc.nextBtnId = dc.baseId + "n"; // Calculate prev/next month date values, and whether they are within the allowed date range var prevDateValues = dc.modifyDateValues( { month: dc.range.current.month, year: dc.range.current.year, }, { month: -1, }, ); var prevMonth = new Date(); prevMonth.setMonth(prevDateValues.month); prevMonth.setFullYear(prevDateValues.year); var nextDateValues = dc.modifyDateValues( { month: dc.range.current.month, year: dc.range.current.year, }, { month: 1, }, ); var nextMonth = new Date(); nextMonth.setMonth(nextDateValues.month); nextMonth.setFullYear(nextDateValues.year); // Draw the year display and prev/next year buttons? var yearSelector = ""; if (!config.condenseYear) { var hasPrevYear = !dc.isOutsideDateRange( new Date(dc.range.current.year - 1, 0, 1), ), hasNextYear = !dc.isOutsideDateRange( new Date(dc.range.current.year + 1, 0, 1), ); yearSelector = '<tr class="yearSelector" role="presentation">' + '<td class="nav prev btn year' + (!hasPrevYear ? " disabled" : "") + '" accesskey="1" title="' + dc.prevTxt.replace(/<|>|\"/g, "") + " " + dc.yearTxt.replace(/<|>|\"/g, "") + '" aria-label="' + dc.prevTxt.replace(/<|>|\"/g, "") + " " + dc.yearTxt.replace(/<|>|\"/g, "") + '"' + (!hasPrevYear ? ' aria-disabled="true" tabindex="-1"' : ' tabindex="0"') + ' role="button" id="' + dc.prevBtnId + 'Y"><span aria-hidden="true">' + dc.leftButtonYearText + "</span></td>" + '<td colspan="5" class="year" role="presentation" title="' + dc.tooltipTxt.replace(/<|>|\"/g, "") + '">' + // Add year select field if enabled. (yearSelect ? "<select " + (forceSelect ? "" : "hidden ") + 'class="nav current select year" id="' + dc.currentBtnId + 'Y" title="' + dc.yearTxt.replace(/<|>|\"/g, "") + '" aria-label="' + dc.yearTxt.replace(/<|>|\"/g, "") + '">' + (function () { var min = config.yearSelectMin || dc.range.current.year, max = config.yearSelectMax || dc.range.current.year, s = ""; if (dc.minDate instanceof Date) min = Math.min(min, dc.minDate.getFullYear()); if (dc.maxDate instanceof Date) max = Math.max(max, dc.maxDate.getFullYear()); while (min <= max) { if (!dc.isDisabledYear(dc, min)) s += "<option" + (min === dc.range.current.year ? ' selected="selected"' : "") + " value=" + min + ">" + min + "</option>"; min++; } return s; })() + "</select>" + "<span " + (forceSelect ? "hidden " : "") + 'class="nav current btn year" tabindex="0" role="button" id="' + dc.currentBtnId + 'YB">' + dc.range.current.year + "</span>" : "<span>" + dc.range.current.year + "</span>") + "</td>" + '<td class="nav next btn year' + (!hasNextYear ? " disabled" : "") + '" accesskey="2" title="' + dc.nextTxt.replace(/<|>|\"/g, "") + " " + dc.yearTxt.replace(/<|>|\"/g, "") + '" aria-label="' + dc.nextTxt.replace(/<|>|\"/g, "") + " " + dc.yearTxt.replace(/<|>|\"/g, "") + '"' + (!hasNextYear ? ' aria-disabled="true" tabindex="-1"' : ' tabindex="0"') + ' role="button" id="' + dc.nextBtnId + 'Y"><span aria-hidden="true">' + dc.rightButtonYearText + "</span></td></tr>"; } // Draw the month display and prev/next month buttons var hasPrevMonth = !dc.isOutsideDateRange( new Date( prevDateValues.year, prevDateValues.month, dc.range[prevDateValues.month].max, ), ), hasNextMonth = !dc.isOutsideDateRange( new Date(nextDateValues.year, nextDateValues.month, 1), ); var monthSelector = '<tr class="monthSelector" role="presentation">' + '<td class="nav prev btn month' + (!hasPrevMonth ? " disabled" : "") + '" accesskey="3" title="' + dc.prevTxt.replace(/<|>|\"/g, "") + " " + dc.monthTxt.replace(/<|>|\"/g, "") + '" aria-label="' + dc.prevTxt.replace(/<|>|\"/g, "") + " " + dc.monthTxt.replace(/<|>|\"/g, "") + '"' + (!hasPrevMonth ? ' aria-disabled="true" tabindex="-1"' : ' tabindex="0"') + ' role="button" id="' + dc.prevBtnId + '"><span aria-hidden="true">' + dc.leftButtonMonthText + "</span></td>" + '<td colspan="5" class="month" role="presentation">' + // Add month select field if enabled. (monthSelect ? "<select " + (forceSelect ? "" : "hidden ") + 'class="nav current select month" id="' + dc.currentBtnId + 'M" title="' + dc.monthTxt.replace(/<|>|\"/g, "") + '" aria-label="' + dc.monthTxt.replace(/<|>|\"/g, "") + '">' + (function () { var s = ""; for (var i = 0; i <= 11; i++) { if (!dc.isDisabledMonth(dc, i, dc.range.current.year)) s += "<option value=" + i + (i === dc.range.current.month ? ' selected="selected"' : "") + ">" + dc.range[i].name + (!config.condenseYear ? "" : " " + dc.range.current.year) + "</option>"; } return s; })() + "</select>" + "<span " + (forceSelect ? "hidden " : "") + 'class="nav current btn month" tabindex="0" role="button" id="' + dc.currentBtnId + 'MB">' + dc.range[dc.range.current.month].name + (!config.condenseYear ? "" : " " + dc.range.current.year) + "</span>" : "<span>" + dc.range[dc.range.current.month].name + (!config.condenseYear ? "" : " " + dc.range.current.year) + "</span>") + "</td>" + '<td class="nav next btn month' + (!hasNextMonth ? " disabled" : "") + '" accesskey="4" title="' + dc.nextTxt.replace(/<|>|\"/g, "") + " " + dc.monthTxt.replace(/<|>|\"/g, "") + '" aria-label="' + dc.nextTxt.replace(/<|>|\"/g, "") + " " + dc.monthTxt.replace(/<|>|\"/g, "") + '"' + (!hasNextMonth ? ' aria-disabled="true" tabindex="-1"' : ' tabindex="0"') + ' role="button" id="' + dc.nextBtnId + '"><span aria-hidden="true">' + dc.rightButtonMonthText + "</span></td></tr>"; dc.content = ""; // Start constructing the Datepicker tab