| 1 |
/* http://keith-wood.name/datepick.html |
| 2 |
Datepicker for jQuery 3.7.1. |
| 3 |
Written by Marc Grabanski (m@marcgrabanski.com) and |
| 4 |
Keith Wood (kbwood{at}iinet.com.au). |
| 5 |
Dual licensed under the GPL (http://dev.jQuery.com/browser/trunk/jQuery/GPL-LICENSE.txt) and |
| 6 |
MIT (http://dev.jQuery.com/browser/trunk/jQuery/MIT-LICENSE.txt) licenses. |
| 7 |
Please attribute the authors if you use it. */ |
| 8 |
|
| 9 |
/** |
| 10 |
* TODO: for fixing conflicts with any other datepickers, we will be need to make fix like this here, and then in all other places in plugin. |
| 11 |
* Replaced items (2023-07-01 ) |
| 12 |
* |
| 13 |
* .datepick > .wpbc_calendar |
| 14 |
$.datepick > $.wpbc_calendar |
| 15 |
jQuery.datepick > jQuery.wpbc_calendar |
| 16 |
Datepick > WPBC_Calendar |
| 17 |
|
| 18 |
browser_is_supported_datepick > browser_is_supported_wpbc_calendar |
| 19 |
isArray > wpbc_is_array |
| 20 |
extendRemove > wpbc_extend_remove |
| 21 |
|
| 22 |
var PROP_NAME = 'datepick'; > var PROP_NAME = 'wpbc_calendar'; |
| 23 |
_tableClass: ['datepick', > _tableClass: ['datepick wpbc_calendar', |
| 24 |
*/ |
| 25 |
|
| 26 |
(function($) { // Hide the namespace |
| 27 |
|
| 28 |
var PROP_NAME = 'datepick'; |
| 29 |
|
| 30 |
|
| 31 |
// https://github.com/jquery/jquery-migrate/blob/master/src/core.js#L50 |
| 32 |
// FixIn: 8.7.10.1. |
| 33 |
if (!$.browser_is_supported_datepick) { |
| 34 |
var uaMatch = function(ua) { |
| 35 |
ua = ua.toLowerCase(); |
| 36 |
|
| 37 |
var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || /(webkit)[ \/]([\w.]+)/.exec(ua) || /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || /(msie) ([\w.]+)/.exec(ua) || ua.indexOf('compatible') < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || []; |
| 38 |
|
| 39 |
return match[2] || '0'; |
| 40 |
}; |
| 41 |
|
| 42 |
$.browser_is_supported_datepick = { |
| 43 |
mozilla: /mozilla/.test(navigator.userAgent.toLowerCase()) && !/webkit/.test(navigator.userAgent.toLowerCase()), |
| 44 |
webkit: /webkit/.test(navigator.userAgent.toLowerCase()), |
| 45 |
opera: /opera/.test(navigator.userAgent.toLowerCase()), |
| 46 |
msie: /msie/.test(navigator.userAgent.toLowerCase()), |
| 47 |
android: (navigator.userAgent.toLowerCase().indexOf('mozilla/5.0') > -1 && navigator.userAgent.toLowerCase().indexOf('android ') > -1 && navigator.userAgent.toLowerCase().indexOf('applewebkit') > -1), |
| 48 |
version: uaMatch(navigator.userAgent) |
| 49 |
}; |
| 50 |
} |
| 51 |
|
| 52 |
/* Date picker manager. |
| 53 |
Use the singleton instance of this class, $.datepick, to interact with the date picker. |
| 54 |
Settings for (groups of) date pickers are maintained in an instance object, |
| 55 |
allowing multiple different settings on the same page. */ |
| 56 |
|
| 57 |
function Datepick() { |
| 58 |
this._uuid = new Date().getTime(); // Unique identifier seed |
| 59 |
this._curInst = null; // The current instance in use |
| 60 |
this._keyEvent = false; // If the last event was a key event |
| 61 |
this._disabledInputs = []; // List of date picker inputs that have been disabled |
| 62 |
this._datepickerShowing = false; // True if the popup picker is showing , false if not |
| 63 |
this._inDialog = false; // True if showing within a "dialog", false if not |
| 64 |
this.regional = []; // Available regional settings, indexed by language code |
| 65 |
this.regional[''] = { // Default regional settings |
| 66 |
clearText: 'Clear', // Display text for clear link |
| 67 |
clearStatus: 'Erase the current date', // Status text for clear link |
| 68 |
closeText: 'Close', // Display text for close link |
| 69 |
closeStatus: 'Close without change', // Status text for close link |
| 70 |
prevText: '<Prev', // Display text for previous month link |
| 71 |
prevStatus: 'Show the previous month', // Status text for previous month link |
| 72 |
prevBigText: '<<', // Display text for previous year link |
| 73 |
prevBigStatus: 'Show the previous year', // Status text for previous year link |
| 74 |
nextText: 'Next>', // Display text for next month link |
| 75 |
nextStatus: 'Show the next month', // Status text for next month link |
| 76 |
nextBigText: '>>', // Display text for next year link |
| 77 |
nextBigStatus: 'Show the next year', // Status text for next year link |
| 78 |
currentText: 'Today', // Display text for current month link |
| 79 |
currentStatus: 'Show the current month', // Status text for current month link |
| 80 |
monthNames: ['January','February','March','April','May','June', |
| 81 |
'July','August','September','October','November','December'], // Names of months for drop-down and formatting |
| 82 |
monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], // For formatting |
| 83 |
monthStatus: 'Show a different month', // Status text for selecting a month |
| 84 |
yearStatus: 'Show a different year', // Status text for selecting a year |
| 85 |
weekHeader: 'Wk', // Header for the week of the year column |
| 86 |
weekStatus: 'Week of the year', // Status text for the week of the year column |
| 87 |
dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], // For formatting |
| 88 |
dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], // For formatting |
| 89 |
dayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'], // Column headings for days starting at Sunday |
| 90 |
dayStatus: 'Set DD as first week day', // Status text for the day of the week selection |
| 91 |
dateStatus: 'Select DD, M d', // Status text for the date selection |
| 92 |
dateFormat: 'mm/dd/yy', // See format options on parseDate |
| 93 |
firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ... |
| 94 |
initStatus: 'Select a date', // Initial Status text on opening |
| 95 |
isRTL: false, // True if right-to-left language, false if left-to-right |
| 96 |
showMonthAfterYear: false, // True if the year select precedes month, false for month then year |
| 97 |
yearSuffix: '' // Additional text to append to the year in the month headers |
| 98 |
}; |
| 99 |
this._defaults = { // Global defaults for all the date picker instances |
| 100 |
wpbc_resource_id: 0, // ID of booking resource - customization // FixIn: 9.4.4.13. |
| 101 |
useThemeRoller: false, // True to apply ThemeRoller styling, false for default styling |
| 102 |
showOn: 'focus', // 'focus' for popup on focus, |
| 103 |
// 'button' for trigger button, or 'both' for either |
| 104 |
showAnim: 'show', // Name of jQuery animation for popup |
| 105 |
showOptions: {}, // Options for enhanced animations |
| 106 |
duration: 'normal', // Duration of display/closure |
| 107 |
buttonText: '...', // Text for trigger button |
| 108 |
buttonImage: '', // URL for trigger button image |
| 109 |
buttonImageOnly: false, // True if the image appears alone, false if it appears on a button |
| 110 |
alignment: 'bottom', // Alignment of popup - with nominated corner of input: |
| 111 |
// 'top' or 'bottom' aligns depending on language direction, |
| 112 |
// 'topLeft', 'topRight', 'bottomLeft', 'bottomRight' |
| 113 |
autoSize: false, // True to size the input for the date format, false to leave as is |
| 114 |
defaultDate: null, // Used when field is blank: actual date, |
| 115 |
// +/-number for offset from today, null for today |
| 116 |
showDefault: false, // True to populate field with the default date |
| 117 |
appendText: '', // Display text following the input box, e.g. showing the format |
| 118 |
closeAtTop: true, // True to have the clear/close at the top, |
| 119 |
// false to have them at the bottom |
| 120 |
mandatory: false, // True to hide the Clear link, false to include it |
| 121 |
hideIfNoPrevNext: false, // True to hide next/previous month links |
| 122 |
// if not applicable, false to just disable them |
| 123 |
navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links |
| 124 |
showBigPrevNext: false, // True to show big prev/next links |
| 125 |
stepMonths: 1, // Number of months to step back/forward |
| 126 |
stepBigMonths: 12, // Number of months to step back/forward for the big links |
| 127 |
gotoCurrent: false, // True if today link goes back to current selection instead |
| 128 |
changeMonth: true, // True if month can be selected directly, false if only prev/next |
| 129 |
changeYear: true, // True if year can be selected directly, false if only prev/next |
| 130 |
yearRange: '-10:+10', // Range of years to display in drop-down, |
| 131 |
// either relative to current year (-nn:+nn) or absolute (nnnn:nnnn) |
| 132 |
changeFirstDay: false, // True to click on day name to change, false to remain as set |
| 133 |
showOtherMonths: false, // True to show dates in other months, false to leave blank |
| 134 |
selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable |
| 135 |
highlightWeek: false, // True to highlight the selected week |
| 136 |
showWeeks: false, // True to show week of the year, false to omit |
| 137 |
calculateWeek: this.iso8601Week, // How to calculate the week of the year, |
| 138 |
// takes a Date and returns the number of the week for it |
| 139 |
shortYearCutoff: '+10', // Short year values < this are in the current century, |
| 140 |
// > this are in the previous century, string value starting with '+' |
| 141 |
// for current year + value, -1 for no change |
| 142 |
showStatus: false, // True to show status bar at bottom, false to not show it |
| 143 |
statusForDate: this.dateStatus, // Function to provide status text for a date - |
| 144 |
// takes date and instance as parameters, returns display text |
| 145 |
minDate: null, // The earliest selectable date, or null for no limit |
| 146 |
maxDate: null, // The latest selectable date, or null for no limit |
| 147 |
numberOfMonths: 1, // Number of months to show at a time |
| 148 |
showCurrentAtPos: 0, // The position in multiple months at which to show the current month (starting at 0) |
| 149 |
rangeSelect: false, // Allows for selecting a date range on one date picker |
| 150 |
rangeSeparator: ' - ', // Text between two dates in a range |
| 151 |
multiSelect: 0, // Maximum number of selectable dates |
| 152 |
multiSeparator: ',', // Text between multiple dates |
| 153 |
beforeShow: null, // Function that takes an input field and |
| 154 |
// returns a set of custom settings for the date picker |
| 155 |
beforeShowDay: null, // Function that takes a date and returns an array with |
| 156 |
// [0] = true if selectable, false if not, [1] = custom CSS class name(s) or '', |
| 157 |
// [2] = cell title (optional), e.g. $.datepick.noWeekends |
| 158 |
onChangeMonthYear: null, // Define a callback function when the month or year is changed |
| 159 |
onHover: null, // Define a callback function when hovering over a day |
| 160 |
onSelect: null, // Define a callback function when a date is selected |
| 161 |
onClose: null, // Define a callback function when the datepicker is closed |
| 162 |
altField: '', // Selector for an alternate field to store selected dates into |
| 163 |
altFormat: '', // The date format to use for the alternate field |
| 164 |
constrainInput: true // The input is constrained by the current date format |
| 165 |
}; |
| 166 |
$.extend(this._defaults, this.regional['']); |
| 167 |
this.dpDiv = $('<div style="display: none;"></div>'); |
| 168 |
} |
| 169 |
|
| 170 |
$.extend(Datepick.prototype, { |
| 171 |
version: '3.7.0', // Current version |
| 172 |
|
| 173 |
/* Class name added to elements to indicate already configured with a date picker. */ |
| 174 |
markerClassName: 'hasDatepick', // Responsive Skin |
| 175 |
|
| 176 |
// Class/id names for default and ThemeRoller stylings |
| 177 |
_mainDivId: ['datepick-div', 'ui-datepicker-div'], // The main datepicker division |
| 178 |
_mainDivClass: ['', 'ui-datepicker ' + |
| 179 |
'ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'], // Popup class |
| 180 |
_inlineClass: ['datepick-inline', 'ui-datepicker-inline ui-datepicker ' + |
| 181 |
'ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'], // Inline class |
| 182 |
_multiClass: ['datepick-multi', 'ui-datepicker-multi'], // Multi-month class |
| 183 |
_rtlClass: ['datepick-rtl', 'ui-datepicker-rtl'], // Right-to-left class |
| 184 |
_appendClass: ['datepick-append', 'ui-datepicker-append'], // Append text class |
| 185 |
_triggerClass: ['datepick-trigger', 'ui-datepicker-trigger'], // Trigger class |
| 186 |
_dialogClass: ['datepick-dialog', 'ui-datepicker-dialog'], // Dialog class |
| 187 |
_promptClass: ['datepick-prompt', 'ui-datepicker-prompt'], // Dialog prompt class |
| 188 |
_disableClass: ['datepick-disabled', 'ui-datepicker-disabled'], // Disabled covering class |
| 189 |
_controlClass: ['datepick-control', 'ui-datepicker-header ' + |
| 190 |
'ui-widget-header ui-helper-clearfix ui-corner-all'], // Control bar class |
| 191 |
_clearClass: ['datepick-clear', 'ui-datepicker-clear'], // Clear class |
| 192 |
_closeClass: ['datepick-close', 'ui-datepicker-close'], // Close class |
| 193 |
_linksClass: ['datepick-links', 'ui-datepicker-header ' + |
| 194 |
'ui-widget-header ui-helper-clearfix ui-corner-all'], // Links bar class |
| 195 |
_prevClass: ['datepick-prev', 'ui-datepicker-prev'], // Previous class |
| 196 |
_nextClass: ['datepick-next', 'ui-datepicker-next'], // Next class |
| 197 |
_currentClass: ['datepick-current', 'ui-datepicker-current'], // Current class |
| 198 |
_oneMonthClass: ['datepick-one-month', 'ui-datepicker-group'], // Single month class |
| 199 |
_newRowClass: ['datepick-new-row', 'ui-datepicker-row-break'], // New month row class |
| 200 |
_monthYearClass: ['datepick-header', 'ui-datepicker-header ' + |
| 201 |
'ui-widget-header ui-helper-clearfix ui-corner-all'], // Month/year header class |
| 202 |
_monthSelectClass: ['datepick-new-month', 'ui-datepicker-month'], // Month select class |
| 203 |
_monthClass: ['', 'ui-datepicker-month'], // Month text class |
| 204 |
_yearSelectClass: ['datepick-new-year', 'ui-datepicker-year'], // Year select class |
| 205 |
_yearClass: ['', 'ui-datepicker-year'], // Year text class |
| 206 |
_tableClass: ['datepick wpbc_calendar', 'ui-datepicker-calendar'], // Month table class // FixIn: 9.7.3.7 |
| 207 |
_tableHeaderClass: ['datepick-title-row', ''], // Week header class |
| 208 |
_weekColClass: ['datepick-week-col', 'ui-datepicker-week-col'], // Week number column class |
| 209 |
_weekRowClass: ['datepick-days-row', ''], // Week row class |
| 210 |
_weekendClass: ['datepick-week-end-cell', 'ui-datepicker-week-end'], // Weekend class |
| 211 |
_dayClass: ['datepick-days-cell', ''], // Single day class |
| 212 |
_otherMonthClass: ['datepick-other-month', 'ui-datepicker-other-month'], // Other month class |
| 213 |
_todayClass: ['datepick-today', 'ui-state-highlight'], // Today class |
| 214 |
_selectableClass: ['', 'ui-state-default'], // Selectable cell class |
| 215 |
_unselectableClass: ['datepick-unselectable', |
| 216 |
'ui-datepicker-unselectable ui-state-disabled'], // Unselectable cell class |
| 217 |
_selectedClass: ['datepick-current-day', 'ui-state-active'], // Selected day class |
| 218 |
_dayOverClass: ['datepick-days-cell-over', 'ui-state-hover'], // Day hover class |
| 219 |
_weekOverClass: ['datepick-week-over', 'ui-state-hover'], // Week hover class |
| 220 |
_statusClass: ['datepick-status', 'ui-datepicker-status'], // Status bar class |
| 221 |
_statusId: ['datepick-status-', 'ui-datepicker-status-'], // Status bar ID prefix |
| 222 |
_coverClass: ['datepick-cover', 'ui-datepicker-cover'], // IE6- iframe class |
| 223 |
|
| 224 |
/* Override the default settings for all instances of the date picker. |
| 225 |
@param settings (object) the new settings to use as defaults (anonymous object) |
| 226 |
@return (Datepick) the manager object */ |
| 227 |
setDefaults: function(settings) { |
| 228 |
extendRemove(this._defaults, settings || {}); |
| 229 |
return this; |
| 230 |
}, |
| 231 |
|
| 232 |
/* Attach the date picker to a jQuery selection. |
| 233 |
@param target (element) the target input field or division or span |
| 234 |
@param settings (object) the new settings to use for this date picker instance */ |
| 235 |
_attachDatepick: function(target, settings) { |
| 236 |
if (!target.id) |
| 237 |
target.id = 'dp' + (++this._uuid); |
| 238 |
var nodeName = target.nodeName.toLowerCase(); |
| 239 |
var inst = this._newInst($(target), (nodeName == 'div' || nodeName == 'span')); |
| 240 |
// Check for settings on the control itself |
| 241 |
var inlineSettings = ($.fn.metadata ? $(target).metadata() : {}); |
| 242 |
inst.settings = $.extend({}, settings || {}, inlineSettings || {}); |
| 243 |
this._adjustInstDate(inst); // FixIn: Adjust cursor date (currently rendering Month, if we define the minDate in the future !!! // FixIn: 10.13.1.4. |
| 244 |
if (inst.inline) { |
| 245 |
inst.dpDiv.addClass(this._inlineClass[ |
| 246 |
this._get(inst, 'useThemeRoller') ? 1 : 0]); |
| 247 |
this._inlineDatepick(target, inst); |
| 248 |
} |
| 249 |
else |
| 250 |
this._connectDatepick(target, inst); |
| 251 |
}, |
| 252 |
|
| 253 |
/* Create a new instance object. |
| 254 |
@param target (jQuery) the target input field or division or span |
| 255 |
@param inline (boolean) true if this datepicker appears inline */ |
| 256 |
_newInst: function(target, inline) { |
| 257 |
var id = target[0].id.replace(/([:\[\]\.\$])/g, '\\\\$1'); // Escape jQuery meta chars |
| 258 |
return {id: id, input: target, // Associated target |
| 259 |
cursorDate: this._daylightSavingAdjust(new Date()), // Current position |
| 260 |
drawMonth: 0, drawYear: 0, // Month being drawn |
| 261 |
dates: [], // Selected dates |
| 262 |
inline: inline, // Is datepicker inline or not |
| 263 |
dpDiv: (!inline ? this.dpDiv : $('<div></div>')), // presentation div |
| 264 |
siblings: $([])}; // Created siblings (trigger/append) |
| 265 |
}, |
| 266 |
|
| 267 |
/* Attach the date picker to an input field. |
| 268 |
@param target (element) the target input field or division or span |
| 269 |
@param inst (object) the instance settings for this datepicker */ |
| 270 |
_connectDatepick: function(target, inst) { |
| 271 |
var input = $(target); |
| 272 |
if (input.hasClass(this.markerClassName)) |
| 273 |
return; |
| 274 |
var appendText = this._get(inst, 'appendText'); |
| 275 |
var isRTL = this._get(inst, 'isRTL'); |
| 276 |
var useTR = this._get(inst, 'useThemeRoller') ? 1 : 0; |
| 277 |
if (appendText) { |
| 278 |
var append = $('<span class="' + this._appendClass[useTR] + '">' + appendText + '</span>'); |
| 279 |
input[isRTL ? 'before' : 'after'](append); |
| 280 |
inst.siblings = inst.siblings.add(append); |
| 281 |
} |
| 282 |
var showOn = this._get(inst, 'showOn'); |
| 283 |
if (showOn == 'focus' || showOn == 'both') // Pop-up date picker when in the marked field |
| 284 |
input.on('focus.wpbc_datepick', this._showDatepick); // FixIn: 10.0.0.45. |
| 285 |
if (showOn == 'button' || showOn == 'both') { // Pop-up date picker when button clicked |
| 286 |
var buttonText = this._get(inst, 'buttonText'); |
| 287 |
var buttonImage = this._get(inst, 'buttonImage'); |
| 288 |
var trigger = $(this._get(inst, 'buttonImageOnly') ? |
| 289 |
$('<img/>').addClass(this._triggerClass[useTR]). |
| 290 |
attr({src: buttonImage, alt: buttonText, title: buttonText}) : |
| 291 |
$('<button type="button"></button>').addClass(this._triggerClass[useTR]). |
| 292 |
html(buttonImage == '' ? buttonText : $('<img/>').attr( |
| 293 |
{src: buttonImage, alt: buttonText, title: buttonText}))); |
| 294 |
input[isRTL ? 'before' : 'after'](trigger); |
| 295 |
inst.siblings = inst.siblings.add(trigger); |
| 296 |
// FixIn: 8.7.11.12. |
| 297 |
trigger.on( 'click', function (){ |
| 298 |
if ($.datepick._datepickerShowing && $.datepick._lastInput == target) |
| 299 |
$.datepick._hideDatepick(); |
| 300 |
else |
| 301 |
$.datepick._showDatepick(target); |
| 302 |
return false; |
| 303 |
}); |
| 304 |
} |
| 305 |
input.addClass( this.markerClassName ).on( 'keydown.wpbc_datepick', this._doKeyDown ).on( 'keypress.wpbc_datepick', this._doKeyPress ).on( 'keyup.wpbc_datepick', this._doKeyUp ); //FixIn: 10.0.0.45 // FixIn: 8.7.11.12. |
| 306 |
if (this._get(inst, 'showDefault') && !inst.input.val()) { |
| 307 |
inst.dates = [this._getDefaultDate(inst)]; |
| 308 |
this._showDate(inst); |
| 309 |
} |
| 310 |
this._autoSize(inst); |
| 311 |
$.data(target, PROP_NAME, inst); |
| 312 |
}, |
| 313 |
|
| 314 |
/* Apply the maximum length for the date format. |
| 315 |
@param inst (object) the instance settings for this datepicker */ |
| 316 |
_autoSize: function(inst) { |
| 317 |
if (this._get(inst, 'autoSize') && !inst.inline) { |
| 318 |
var date = new Date(2009, 12 - 1, 20); // Ensure double digits |
| 319 |
var dateFormat = this._get(inst, 'dateFormat'); |
| 320 |
if (dateFormat.match(/[DM]/)) { |
| 321 |
var findMax = function(names) { |
| 322 |
var max = 0; |
| 323 |
var maxI = 0; |
| 324 |
for (var i = 0; i < names.length; i++) { |
| 325 |
if (names[i].length > max) { |
| 326 |
max = names[i].length; |
| 327 |
maxI = i; |
| 328 |
} |
| 329 |
} |
| 330 |
return maxI; |
| 331 |
}; |
| 332 |
date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ? |
| 333 |
'monthNames' : 'monthNamesShort')))); |
| 334 |
date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ? |
| 335 |
'dayNames' : 'dayNamesShort'))) + 20 - date.getDay()); |
| 336 |
} |
| 337 |
inst.input.attr('size', this._formatDate(inst, date).length); |
| 338 |
} |
| 339 |
}, |
| 340 |
|
| 341 |
/* Attach an inline date picker to a div. |
| 342 |
@param target (element) the target input field or division or span |
| 343 |
@param inst (object) the instance settings for this datepicker */ |
| 344 |
_inlineDatepick: function(target, inst) { |
| 345 |
var divSpan = $(target); |
| 346 |
if (divSpan.hasClass(this.markerClassName)) |
| 347 |
return; |
| 348 |
divSpan.addClass(this.markerClassName); |
| 349 |
$.data(target, PROP_NAME, inst); |
| 350 |
inst.drawMonth = inst.cursorDate.getMonth(); |
| 351 |
inst.drawYear = inst.cursorDate.getFullYear(); |
| 352 |
$('body').append(inst.dpDiv); |
| 353 |
this._updateDatepick(inst); |
| 354 |
// Fix width for dynamic number of date pickers |
| 355 |
/* // FixIn: 9.7.3.4 |
| 356 |
// Commented below 3 lines to not include width into <div class="datepick-inline datepick-multi" style="width: 4428px;"> |
| 357 |
inst.dpDiv.width(this._getNumberOfMonths(inst)[1] * |
| 358 |
$('.' + this._oneMonthClass[this._get(inst, 'useThemeRoller') ? 1 : 0], |
| 359 |
inst.dpDiv)[0].offsetWidth); |
| 360 |
*/ |
| 361 |
divSpan.append(inst.dpDiv); |
| 362 |
this._updateAlternate(inst); |
| 363 |
|
| 364 |
// FixIn: 9.4.4.13. |
| 365 |
var resource_id = parseInt( divSpan.get( 0 ).getAttribute( 'id' ).replace( 'calendar_booking', '' ) ); |
| 366 |
inst.settings.wpbc_resource_id = resource_id; // To get this property use: this._get(inst, 'wpbc_resource_id') |
| 367 |
|
| 368 |
// FixIn: 9.4.4.12. |
| 369 |
$( 'body' ).trigger( |
| 370 |
'wpbc_datepick_inline_calendar_loaded' // event name |
| 371 |
, [ |
| 372 |
divSpan.get( 0 ).getAttribute( 'id' ).replace( 'calendar_booking', '' ) // Resource ID - '1' |
| 373 |
, divSpan // jQuery( '#calendar_booking1' ) |
| 374 |
, inst // datepick Obj |
| 375 |
] |
| 376 |
); |
| 377 |
// To catch this event: jQuery( 'body' ).on('wpbc_datepick_inline_calendar_loaded', function( event, resource_id, jCalContainer, inst ) { ... } ); |
| 378 |
//FixIn End: 9.4.4.12 |
| 379 |
}, |
| 380 |
|
| 381 |
/* Pop-up the date picker in a "dialog" box. |
| 382 |
@param input (element) ignored |
| 383 |
@param date (string or Date) the initial date to display |
| 384 |
@param onSelect (function) the function to call when a date is selected |
| 385 |
@param settings (object) update the dialog date picker instance's settings |
| 386 |
@param pos (int[2]) coordinates for the dialog's position within the screen or |
| 387 |
(event) with x/y coordinates or |
| 388 |
leave empty for default (screen centre) */ |
| 389 |
_dialogDatepick: function(input, date, onSelect, settings, pos) { |
| 390 |
var inst = this._dialogInst; // Internal instance |
| 391 |
if (!inst) { |
| 392 |
var id = 'dp' + (++this._uuid); |
| 393 |
this._dialogInput = $('<input type="text" id="' + id + |
| 394 |
'" style="position: absolute; width: 1px; z-index: -1"/>'); |
| 395 |
this._dialogInput.on( 'keydown.wpbc_datepick', this._doKeyDown); // FixIn: 10.0.0.45. |
| 396 |
$('body').append(this._dialogInput); |
| 397 |
inst = this._dialogInst = this._newInst(this._dialogInput, false); |
| 398 |
inst.settings = {}; |
| 399 |
$.data(this._dialogInput[0], PROP_NAME, inst); |
| 400 |
} |
| 401 |
extendRemove(inst.settings, settings || {}); |
| 402 |
date = (date && date.constructor == Date ? this._formatDate(inst, date) : date); |
| 403 |
this._dialogInput.val(date); |
| 404 |
this._pos = (pos ? (isArray(pos) ? pos : [pos.pageX, pos.pageY]) : null); |
| 405 |
if (!this._pos) { |
| 406 |
var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft; |
| 407 |
var scrollY = document.documentElement.scrollTop || document.body.scrollTop; |
| 408 |
this._pos = // Should use actual width/height below |
| 409 |
[(document.documentElement.clientWidth / 2) - 100 + scrollX, |
| 410 |
(document.documentElement.clientHeight / 2) - 150 + scrollY]; |
| 411 |
} |
| 412 |
|
| 413 |
// Move input on screen for focus, but hidden behind dialog |
| 414 |
this._dialogInput.css('left', (this._pos[0] + 20) + 'px').css('top', this._pos[1] + 'px'); |
| 415 |
inst.settings.onSelect = onSelect; |
| 416 |
this._inDialog = true; |
| 417 |
this.dpDiv.addClass(this._dialogClass[this._get(inst, 'useThemeRoller') ? 1 : 0]); |
| 418 |
this._showDatepick(this._dialogInput[0]); |
| 419 |
if ($.blockUI) |
| 420 |
$.blockUI(this.dpDiv); |
| 421 |
$.data(this._dialogInput[0], PROP_NAME, inst); |
| 422 |
}, |
| 423 |
|
| 424 |
/* Detach a datepicker from its control. |
| 425 |
@param target (element) the target input field or division or span */ |
| 426 |
_destroyDatepick: function(target) { |
| 427 |
var $target = $(target); |
| 428 |
if (!$target.hasClass(this.markerClassName)) { |
| 429 |
return; |
| 430 |
} |
| 431 |
var inst = $.data(target, PROP_NAME); |
| 432 |
$.removeData(target, PROP_NAME); |
| 433 |
if (inst.inline) |
| 434 |
$target.removeClass(this.markerClassName).empty(); |
| 435 |
else { |
| 436 |
$(inst.siblings).remove(); |
| 437 |
//$target.removeClass(this.markerClassName).unbind('focus', this._showDatepick).unbind('keydown', this._doKeyDown).unbind('keypress', this._doKeyPress).unbind('keyup', this._doKeyUp); // FixIn: 10.0.0.45. |
| 438 |
//$target.removeClass(this.markerClassName).off('focus', this._showDatepick).off('keydown', this._doKeyDown).off('keypress', this._doKeyPress).off('keyup', this._doKeyUp); // FixIn: 10.0.0.45. |
| 439 |
$target.removeClass( this.markerClassName ).off( 'focus.wpbc_datepick' ).off( 'keydown.wpbc_datepick' ).off( 'keypress.wpbc_datepick' ).off( 'keyup.wpbc_datepick' ); // FixIn: 10.0.0.45. |
| 440 |
} |
| 441 |
}, |
| 442 |
|
| 443 |
/* Enable the date picker to a jQuery selection. |
| 444 |
@param target (element) the target input field or division or span */ |
| 445 |
_enableDatepick: function(target) { |
| 446 |
var $target = $(target); |
| 447 |
if (!$target.hasClass(this.markerClassName)) |
| 448 |
return; |
| 449 |
var inst = $.data(target, PROP_NAME); |
| 450 |
var useTR = this._get(inst, 'useThemeRoller') ? 1 : 0; |
| 451 |
if (inst.inline) |
| 452 |
$target.children('.' + this._disableClass[useTR]).remove().end(). |
| 453 |
find('select').attr('disabled', ''); |
| 454 |
else { |
| 455 |
target.disabled = false; |
| 456 |
inst.siblings.filter('button.' + this._triggerClass[useTR]). |
| 457 |
each(function() { this.disabled = false; }).end(). |
| 458 |
filter('img.' + this._triggerClass[useTR]). |
| 459 |
css({opacity: '1.0', cursor: ''}); |
| 460 |
} |
| 461 |
this._disabledInputs = $.map(this._disabledInputs, |
| 462 |
function(value) { return (value == target ? null : value); }); // Delete entry |
| 463 |
}, |
| 464 |
|
| 465 |
/* Disable the date picker to a jQuery selection. |
| 466 |
@param target (element) the target input field or division or span */ |
| 467 |
_disableDatepick: function(target) { |
| 468 |
var $target = $(target); |
| 469 |
if (!$target.hasClass(this.markerClassName)) |
| 470 |
return; |
| 471 |
var inst = $.data(target, PROP_NAME); |
| 472 |
var useTR = this._get(inst, 'useThemeRoller') ? 1 : 0; |
| 473 |
if (inst.inline) { |
| 474 |
var inline = $target.children('.' + this._inlineClass[useTR]); |
| 475 |
var offset = inline.offset(); |
| 476 |
var relOffset = {left: 0, top: 0}; |
| 477 |
inline.parents().each(function() { |
| 478 |
if ($(this).css('position') == 'relative') { |
| 479 |
relOffset = $(this).offset(); |
| 480 |
return false; |
| 481 |
} |
| 482 |
}); |
| 483 |
$target.prepend('<div class="' + this._disableClass[useTR] + '" style="' + |
| 484 |
'width: ' + inline.width() + 'px; height: ' + inline.height() + |
| 485 |
'px; left: ' + (offset.left - relOffset.left) + |
| 486 |
'px; top: ' + (offset.top - relOffset.top) + 'px;"></div>'). |
| 487 |
find('select').attr('disabled', 'disabled'); |
| 488 |
} |
| 489 |
else { |
| 490 |
target.disabled = true; |
| 491 |
inst.siblings.filter('button.' + this._triggerClass[useTR]). |
| 492 |
each(function() { this.disabled = true; }).end(). |
| 493 |
filter('img.' + this._triggerClass[useTR]). |
| 494 |
css({opacity: '0.5', cursor: 'default'}); |
| 495 |
} |
| 496 |
this._disabledInputs = $.map(this._disabledInputs, |
| 497 |
function(value) { return (value == target ? null : value); }); // Delete entry |
| 498 |
this._disabledInputs.push(target); |
| 499 |
}, |
| 500 |
|
| 501 |
/* Is the first field in a jQuery collection disabled as a datepicker? |
| 502 |
@param target (element) the target input field or division or span |
| 503 |
@return (boolean) true if disabled, false if enabled */ |
| 504 |
_isDisabledDatepick: function(target) { |
| 505 |
return (!target ? false : $.inArray(target, this._disabledInputs) > -1); |
| 506 |
}, |
| 507 |
|
| 508 |
/* Retrieve the instance data for the target control. |
| 509 |
@param target (element) the target input field or division or span |
| 510 |
@return (object) the associated instance data |
| 511 |
@throws error if a jQuery problem getting data */ |
| 512 |
_getInst: function(target) {//alert(target.id); |
| 513 |
try { |
| 514 |
return $.data(target, PROP_NAME); |
| 515 |
} |
| 516 |
catch (err) { |
| 517 |
throw 'Missing instance data for this datepicker'; |
| 518 |
} |
| 519 |
}, |
| 520 |
|
| 521 |
/* Update or retrieve the settings for a date picker attached to an input field or division. |
| 522 |
@param target (element) the target input field or division or span |
| 523 |
@param name (object) the new settings to update or |
| 524 |
(string) the name of the setting to change or retrieve, |
| 525 |
when retrieving also 'all' for all instance settings or |
| 526 |
'defaults' for all global defaults |
| 527 |
@param value (any) the new value for the setting |
| 528 |
(omit if above is an object or to retrieve value) */ |
| 529 |
_optionDatepick: function(target, name, value) { |
| 530 |
var inst = this._getInst(target); |
| 531 |
if (arguments.length == 2 && typeof name == 'string') { |
| 532 |
return (name == 'defaults' ? $.extend({}, $.datepick._defaults) : |
| 533 |
(inst ? (name == 'all' ? $.extend({}, inst.settings) : |
| 534 |
this._get(inst, name)) : null)); |
| 535 |
} |
| 536 |
var settings = name || {}; |
| 537 |
if (typeof name == 'string') { |
| 538 |
settings = {}; |
| 539 |
settings[name] = value; |
| 540 |
} |
| 541 |
if (inst) { |
| 542 |
if (this._curInst == inst) { |
| 543 |
this._hideDatepick(null); |
| 544 |
} |
| 545 |
var dates = this._getDateDatepick(target); |
| 546 |
extendRemove(inst.settings, settings); |
| 547 |
this._autoSize(inst); |
| 548 |
extendRemove(inst, {dates: []}); |
| 549 |
var blank = (!dates || isArray(dates)); |
| 550 |
if (isArray(dates)) |
| 551 |
for (var i = 0; i < dates.length; i++) |
| 552 |
if (dates[i]) { |
| 553 |
blank = false; |
| 554 |
break; |
| 555 |
} |
| 556 |
if (!blank) |
| 557 |
this._setDateDatepick(target, dates); |
| 558 |
if (inst.inline) |
| 559 |
$(target).children('div').removeClass(this._inlineClass.join(' ')). |
| 560 |
addClass(this._inlineClass[this._get(inst, 'useThemeRoller') ? 1 : 0]); |
| 561 |
this._updateDatepick(inst); |
| 562 |
} |
| 563 |
}, |
| 564 |
|
| 565 |
// Change method deprecated |
| 566 |
_changeDatepick: function(target, name, value) { |
| 567 |
this._optionDatepick(target, name, value); |
| 568 |
}, |
| 569 |
|
| 570 |
/* Redraw the date picker attached to an input field or division. |
| 571 |
@param target (element) the target input field or division or span */ |
| 572 |
_refreshDatepick: function(target) { |
| 573 |
var inst = this._getInst(target); |
| 574 |
if (inst) { |
| 575 |
this._updateDatepick(inst); |
| 576 |
} |
| 577 |
}, |
| 578 |
|
| 579 |
/* Set the dates for a jQuery selection. |
| 580 |
@param target (element) the target input field or division or span |
| 581 |
@param date (Date) the new date |
| 582 |
@param endDate (Date) the new end date for a range (optional) */ |
| 583 |
_setDateDatepick: function(target, date, endDate) { |
| 584 |
var inst = this._getInst(target); |
| 585 |
if (inst) { |
| 586 |
this._setDate(inst, date, endDate); |
| 587 |
this._updateDatepick(inst); |
| 588 |
this._updateAlternate(inst); |
| 589 |
} |
| 590 |
}, |
| 591 |
|
| 592 |
/* Get the date(s) for the first entry in a jQuery selection. |
| 593 |
@param target (element) the target input field or division or span |
| 594 |
@return (Date) the current date or |
| 595 |
(Date[2]) the current dates for a range */ |
| 596 |
_getDateDatepick: function(target) { |
| 597 |
var inst = this._getInst(target); |
| 598 |
if (inst && !inst.inline) |
| 599 |
this._setDateFromField(inst); |
| 600 |
return (inst ? this._getDate(inst) : null); |
| 601 |
}, |
| 602 |
|
| 603 |
/* Handle keystrokes. |
| 604 |
@param event (KeyEvent) the keystroke details |
| 605 |
@return (boolean) true to continue, false to discard */ |
| 606 |
_doKeyDown: function(event) { |
| 607 |
var inst = $.datepick._getInst(event.target); |
| 608 |
inst.keyEvent = true; |
| 609 |
var handled = true; |
| 610 |
var isRTL = $.datepick._get(inst, 'isRTL'); |
| 611 |
var useTR = $.datepick._get(inst, 'useThemeRoller') ? 1 : 0; |
| 612 |
if ($.datepick._datepickerShowing) |
| 613 |
switch (event.keyCode) { |
| 614 |
case 9: $.datepick._hideDatepick(null, ''); |
| 615 |
break; // Hide on tab out |
| 616 |
case 13: var sel = $('td.' + $.datepick._dayOverClass[useTR], inst.dpDiv); |
| 617 |
if (sel.length == 0) |
| 618 |
sel = $('td.' + $.datepick._selectedClass[useTR] + ':first', inst.dpDiv); |
| 619 |
if (sel[0]) |
| 620 |
$.datepick._selectDay(sel[0], event.target, inst.cursorDate.getTime()); |
| 621 |
else |
| 622 |
$.datepick._hideDatepick(null, $.datepick._get(inst, 'duration')); |
| 623 |
break; // Select the value on enter |
| 624 |
case 27: $.datepick._hideDatepick(null, $.datepick._get(inst, 'duration')); |
| 625 |
break; // Hide on escape |
| 626 |
case 33: $.datepick._adjustDate(event.target, (event.ctrlKey ? |
| 627 |
-$.datepick._get(inst, 'stepBigMonths') : |
| 628 |
-$.datepick._get(inst, 'stepMonths')), 'M'); |
| 629 |
break; // Previous month/year on page up/+ ctrl |
| 630 |
case 34: $.datepick._adjustDate(event.target, (event.ctrlKey ? |
| 631 |
+$.datepick._get(inst, 'stepBigMonths') : |
| 632 |
+$.datepick._get(inst, 'stepMonths')), 'M'); |
| 633 |
break; // Next month/year on page down/+ ctrl |
| 634 |
case 35: if (event.ctrlKey || event.metaKey) |
| 635 |
$.datepick._clearDate(event.target); |
| 636 |
handled = event.ctrlKey || event.metaKey; |
| 637 |
break; // Clear on ctrl or command + end |
| 638 |
case 36: if (event.ctrlKey || event.metaKey) |
| 639 |
$.datepick._gotoToday(event.target); |
| 640 |
handled = event.ctrlKey || event.metaKey; |
| 641 |
break; // Current on ctrl or command + home |
| 642 |
case 37: if (event.ctrlKey || event.metaKey) |
| 643 |
$.datepick._adjustDate(event.target, (isRTL ? +1 : -1), 'D'); |
| 644 |
handled = event.ctrlKey || event.metaKey; |
| 645 |
// -1 day on ctrl or command + left |
| 646 |
if (event.originalEvent.altKey) |
| 647 |
$.datepick._adjustDate(event.target, |
| 648 |
(event.ctrlKey ? -$.datepick._get(inst, 'stepBigMonths') : |
| 649 |
-$.datepick._get(inst, 'stepMonths')), 'M'); |
| 650 |
// Next month/year on alt + left/+ ctrl |
| 651 |
break; |
| 652 |
case 38: if (event.ctrlKey || event.metaKey) |
| 653 |
$.datepick._adjustDate(event.target, -7, 'D'); |
| 654 |
handled = event.ctrlKey || event.metaKey; |
| 655 |
break; // -1 week on ctrl or command + up |
| 656 |
case 39: if (event.ctrlKey || event.metaKey) |
| 657 |
$.datepick._adjustDate(event.target, (isRTL ? -1 : +1), 'D'); |
| 658 |
handled = event.ctrlKey || event.metaKey; |
| 659 |
// +1 day on ctrl or command + right |
| 660 |
if (event.originalEvent.altKey) |
| 661 |
$.datepick._adjustDate(event.target, |
| 662 |
(event.ctrlKey ? +$.datepick._get(inst, 'stepBigMonths') : |
| 663 |
+$.datepick._get(inst, 'stepMonths')), 'M'); |
| 664 |
// Next month/year on alt + right/+ ctrl |
| 665 |
break; |
| 666 |
case 40: if (event.ctrlKey || event.metaKey) |
| 667 |
$.datepick._adjustDate(event.target, +7, 'D'); |
| 668 |
handled = event.ctrlKey || event.metaKey; |
| 669 |
break; // +1 week on ctrl or command + down |
| 670 |
default: handled = false; |
| 671 |
} |
| 672 |
else if (event.keyCode == 36 && event.ctrlKey) // Display the date picker on ctrl+home |
| 673 |
$.datepick._showDatepick(this); |
| 674 |
else |
| 675 |
handled = false; |
| 676 |
if (handled) { |
| 677 |
event.preventDefault(); |
| 678 |
event.stopPropagation(); |
| 679 |
} |
| 680 |
inst.ctrlKey = (event.keyCode < 48); |
| 681 |
return !handled; |
| 682 |
}, |
| 683 |
|
| 684 |
/* Filter entered characters - based on date format. |
| 685 |
@param event (KeyEvent) the keystroke details |
| 686 |
@return (boolean) true to continue, false to discard */ |
| 687 |
_doKeyPress: function(event) { |
| 688 |
var inst = $.datepick._getInst(event.target); |
| 689 |
if ($.datepick._get(inst, 'constrainInput')) { |
| 690 |
var chars = $.datepick._possibleChars(inst); |
| 691 |
var chr = String.fromCharCode(event.keyCode || event.charCode); |
| 692 |
return inst.ctrlKey || (chr < ' ' || !chars || chars.indexOf(chr) > -1); |
| 693 |
} |
| 694 |
}, |
| 695 |
|
| 696 |
/* Synchronise manual entry and field/alternate field. |
| 697 |
@param event (KeyEvent) the keystroke details |
| 698 |
@return (boolean) true to continue */ |
| 699 |
_doKeyUp: function(event) { |
| 700 |
var inst = $.datepick._getInst(event.target); |
| 701 |
if (inst.input.val() != inst.lastVal) { |
| 702 |
try { |
| 703 |
var separator = ($.datepick._get(inst, 'rangeSelect') ? |
| 704 |
$.datepick._get(inst, 'rangeSeparator') : |
| 705 |
($.datepick._get(inst, 'multiSelect') ? |
| 706 |
$.datepick._get(inst, 'multiSeparator') : '')); |
| 707 |
var dates = (inst.input ? inst.input.val() : ''); |
| 708 |
dates = (separator ? dates.split(separator) : [dates]); |
| 709 |
var ok = true; |
| 710 |
for (var i = 0; i < dates.length; i++) { |
| 711 |
if (!$.datepick.parseDate($.datepick._get(inst, 'dateFormat'), |
| 712 |
dates[i], $.datepick._getFormatConfig(inst))) { |
| 713 |
ok = false; |
| 714 |
break; |
| 715 |
} |
| 716 |
} |
| 717 |
if (ok) { // Only if valid |
| 718 |
$.datepick._setDateFromField(inst); |
| 719 |
$.datepick._updateAlternate(inst); |
| 720 |
$.datepick._updateDatepick(inst); |
| 721 |
} |
| 722 |
} |
| 723 |
catch (event) { |
| 724 |
// Ignore |
| 725 |
} |
| 726 |
} |
| 727 |
return true; |
| 728 |
}, |
| 729 |
|
| 730 |
/* Extract all possible characters from the date format. |
| 731 |
@param inst (object) the instance settings for this datepicker |
| 732 |
@return (string) the set of characters allowed by this format */ |
| 733 |
_possibleChars: function (inst) { |
| 734 |
var dateFormat = $.datepick._get(inst, 'dateFormat'); |
| 735 |
var chars = ($.datepick._get(inst, 'rangeSelect') ? |
| 736 |
$.datepick._get(inst, 'rangeSeparator') : |
| 737 |
($.datepick._get(inst, 'multiSelect') ? |
| 738 |
$.datepick._get(inst, 'multiSeparator') : '')); |
| 739 |
var literal = false; |
| 740 |
for (var iFormat = 0; iFormat < dateFormat.length; iFormat++) |
| 741 |
if (literal) |
| 742 |
if (dateFormat.charAt(iFormat) == "'" && !lookAhead("'")) |
| 743 |
literal = false; |
| 744 |
else |
| 745 |
chars += dateFormat.charAt(iFormat); |
| 746 |
else |
| 747 |
switch (dateFormat.charAt(iFormat)) { |
| 748 |
case 'd': case 'm': case 'y': case '@': |
| 749 |
chars += '0123456789'; |
| 750 |
break; |
| 751 |
case 'D': case 'M': |
| 752 |
return null; // Accept anything |
| 753 |
case "'": |
| 754 |
if (lookAhead("'")) |
| 755 |
chars += "'"; |
| 756 |
else |
| 757 |
literal = true; |
| 758 |
break; |
| 759 |
default: |
| 760 |
chars += dateFormat.charAt(iFormat); |
| 761 |
} |
| 762 |
return chars; |
| 763 |
}, |
| 764 |
|
| 765 |
/* Update the datepicker when hovering over a date. |
| 766 |
@param td (element) the current cell |
| 767 |
@param id (string) the ID of the datepicker instance |
| 768 |
@param timestamp (number) the timestamp for this date */ |
| 769 |
_doMouseOver: function(td, id, timestamp) { |
| 770 |
var inst = $.datepick._getInst($('#' + id)[0]); |
| 771 |
var useTR = $.datepick._get(inst, 'useThemeRoller') ? 1 : 0; |
| 772 |
if ( $( td ).find( 'a' ).length ) //FixIn: 2023-08-06 |
| 773 |
$(td).parents('tbody').find('td'). |
| 774 |
removeClass($.datepick._dayOverClass[useTR]).end().end(). |
| 775 |
addClass($.datepick._dayOverClass[useTR]); |
| 776 |
if ($.datepick._get(inst, 'highlightWeek')) |
| 777 |
$(td).parent().parent().find('tr'). |
| 778 |
removeClass($.datepick._weekOverClass[useTR]).end().end(). |
| 779 |
addClass($.datepick._weekOverClass[useTR]); |
| 780 |
if ($(td).text()) { |
| 781 |
var date = new Date(timestamp); |
| 782 |
if ($.datepick._get(inst, 'showStatus')) { |
| 783 |
var status = ($.datepick._get(inst, 'statusForDate').apply( |
| 784 |
(inst.input ? inst.input[0] : null), [date, inst]) || |
| 785 |
$.datepick._get(inst, 'initStatus')); |
| 786 |
$('#' + $.datepick._statusId[useTR] + id).html(status); |
| 787 |
} |
| 788 |
if ($.datepick._get(inst, 'onHover')) |
| 789 |
$.datepick._doHover(td, '#' + id, date.getFullYear(), date.getMonth()); |
| 790 |
} |
| 791 |
}, |
| 792 |
|
| 793 |
/* Update the datepicker when no longer hovering over a date. |
| 794 |
@param td (element) the current cell |
| 795 |
@param id (string) the ID of the datepicker instance */ |
| 796 |
_doMouseOut: function(td, id) { |
| 797 |
var inst = $.datepick._getInst($('#' + id)[0]); |
| 798 |
var useTR = $.datepick._get(inst, 'useThemeRoller') ? 1 : 0; |
| 799 |
$(td).removeClass($.datepick._dayOverClass[useTR]). |
| 800 |
removeClass($.datepick._weekOverClass[useTR]); |
| 801 |
if ($.datepick._get(inst, 'showStatus')) |
| 802 |
$('#' + $.datepick._statusId[useTR] + id).html($.datepick._get(inst, 'initStatus')); |
| 803 |
if ($.datepick._get(inst, 'onHover')) |
| 804 |
$.datepick._doHover(td, '#' + id); |
| 805 |
}, |
| 806 |
|
| 807 |
/* Hover over a particular day. |
| 808 |
@param td (element) the table cell containing the selection |
| 809 |
@param id (string) the ID of the target field |
| 810 |
@param year (number) the year for this day |
| 811 |
@param month (number) the month for this day */ |
| 812 |
_doHover: function(td, id, year, month) { |
| 813 |
var inst = this._getInst($(id)[0]); |
| 814 |
var useTR = $.datepick._get(inst, 'useThemeRoller') ? 1 : 0; |
| 815 |
//if ($(td).hasClass(this._unselectableClass[useTR])) |
| 816 |
// return; |
| 817 |
var onHover = this._get(inst, 'onHover'); |
| 818 |
//FixIn: 2023-08-06 |
| 819 |
var temp_daylight_day = ( $( td ).find( 'a' ).length) ? new Date( year, month, $( td ).find( 'a' ).text() ) : null; |
| 820 |
temp_daylight_day = ( ( null === temp_daylight_day ) && ( $( td ).find( 'span' ).length ) ) ? new Date( year, month, $( td ).find( 'span' ).text() ) : temp_daylight_day; |
| 821 |
|
| 822 |
var date = (year ? |
| 823 |
// this._daylightSavingAdjust(new Date(year, month, $(td).find('a').text())) : null); //FixIn: 2023-08-06 |
| 824 |
this._daylightSavingAdjust( temp_daylight_day ) : null); //FixIn: 2023-08-06 |
| 825 |
onHover.apply((inst.input ? inst.input[0] : null), |
| 826 |
[(date ? this._formatDate(inst, date) : ''), date, inst]); |
| 827 |
}, |
| 828 |
|
| 829 |
/* Pop-up the date picker for a given input field. |
| 830 |
@param input (element) the input field attached to the date picker or |
| 831 |
(event) if triggered by focus */ |
| 832 |
_showDatepick: function(input) { |
| 833 |
input = input.target || input; |
| 834 |
if ($.datepick._isDisabledDatepick(input) || $.datepick._lastInput == input) // Already here |
| 835 |
return; |
| 836 |
var inst = $.datepick._getInst(input); |
| 837 |
var beforeShow = $.datepick._get(inst, 'beforeShow'); |
| 838 |
var useTR = $.datepick._get(inst, 'useThemeRoller') ? 1 : 0; |
| 839 |
extendRemove(inst.settings, (beforeShow ? beforeShow.apply(input, [input, inst]) : {})); |
| 840 |
$.datepick._hideDatepick(null, ''); |
| 841 |
$.datepick._lastInput = input; |
| 842 |
$.datepick._setDateFromField(inst); |
| 843 |
if ($.datepick._inDialog) // Hide cursor |
| 844 |
input.value = ''; |
| 845 |
if (!$.datepick._pos) { // Position below input |
| 846 |
$.datepick._pos = $.datepick._findPos(input); |
| 847 |
$.datepick._pos[1] += input.offsetHeight; // Add the height |
| 848 |
} |
| 849 |
var isFixed = false; |
| 850 |
$(input).parents().each(function() { |
| 851 |
isFixed |= $(this).css('position') == 'fixed'; |
| 852 |
return !isFixed; |
| 853 |
}); |
| 854 |
if (isFixed && $.browser_is_supported_datepick.opera) { // Correction for Opera when fixed and scrolled |
| 855 |
$.datepick._pos[0] -= document.documentElement.scrollLeft; |
| 856 |
$.datepick._pos[1] -= document.documentElement.scrollTop; |
| 857 |
} |
| 858 |
var offset = {left: $.datepick._pos[0], top: $.datepick._pos[1]}; |
| 859 |
$.datepick._pos = null; |
| 860 |
// Determine sizing offscreen |
| 861 |
inst.dpDiv.css({position: 'absolute', display: 'block', top: '-1000px'}); |
| 862 |
$.datepick._updateDatepick(inst); |
| 863 |
// Fix width for dynamic number of date pickers |
| 864 |
inst.dpDiv.width($.datepick._getNumberOfMonths(inst)[1] * |
| 865 |
$('.' + $.datepick._oneMonthClass[useTR], inst.dpDiv).width()); |
| 866 |
// And adjust position before showing |
| 867 |
offset = $.datepick._checkOffset(inst, offset, isFixed); |
| 868 |
inst.dpDiv.css({position: ($.datepick._inDialog && $.blockUI ? |
| 869 |
'static' : (isFixed ? 'fixed' : 'absolute')), display: 'none', |
| 870 |
left: offset.left + 'px', top: offset.top + 'px'}); |
| 871 |
if (!inst.inline) { |
| 872 |
var showAnim = $.datepick._get(inst, 'showAnim') || 'show'; |
| 873 |
var duration = $.datepick._get(inst, 'duration'); |
| 874 |
var postProcess = function() { |
| 875 |
$.datepick._datepickerShowing = true; |
| 876 |
var borders = $.datepick._getBorders(inst.dpDiv); |
| 877 |
inst.dpDiv.find('iframe.' + $.datepick._coverClass[useTR]). // IE6- only |
| 878 |
css({left: -borders[0], top: -borders[1], |
| 879 |
width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()}); |
| 880 |
}; |
| 881 |
if ($.effects && $.effects[showAnim]) |
| 882 |
inst.dpDiv.show(showAnim, $.datepick._get(inst, 'showOptions'), duration, postProcess); |
| 883 |
else |
| 884 |
inst.dpDiv[showAnim](duration, postProcess); |
| 885 |
if (duration == '') |
| 886 |
postProcess(); |
| 887 |
if (inst.input[0].type != 'hidden') |
| 888 |
$( inst.input ).trigger( 'focus' ); // FixIn: 8.7.11.12. |
| 889 |
$.datepick._curInst = inst; |
| 890 |
} |
| 891 |
}, |
| 892 |
|
| 893 |
/* Generate the date picker content. |
| 894 |
@param inst (object) the instance settings for this datepicker */ |
| 895 |
_updateDatepick: function(inst) { |
| 896 |
if ( null === inst ) { |
| 897 |
return; |
| 898 |
} |
| 899 |
var borders = this._getBorders(inst.dpDiv); |
| 900 |
var useTR = this._get(inst, 'useThemeRoller') ? 1 : 0; |
| 901 |
inst.dpDiv.empty().append(this._generateHTML(inst)). |
| 902 |
find('iframe.' + this._coverClass[useTR]). // IE6- only |
| 903 |
css({left: -borders[0], top: -borders[1], |
| 904 |
width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()}); |
| 905 |
var numMonths = this._getNumberOfMonths(inst); |
| 906 |
if (!inst.inline) |
| 907 |
inst.dpDiv.attr('id', this._mainDivId[useTR]); |
| 908 |
if (!inst.inline) inst.dpDiv.attr('class', 'datepick-inline'); // Added by wpdevelop for the correct showing of calendar in the search form. |
| 909 |
inst.dpDiv.removeClass(this._mainDivClass[1 - useTR]). |
| 910 |
addClass(this._mainDivClass[useTR]). |
| 911 |
removeClass(this._multiClass.join(' ')). |
| 912 |
addClass(numMonths[0] != 1 || numMonths[1] != 1 ? this._multiClass[useTR] : ''). |
| 913 |
removeClass(this._rtlClass.join(' ')). |
| 914 |
addClass(this._get(inst, 'isRTL') ? this._rtlClass[useTR] : ''); |
| 915 |
if (inst.input && inst.input[0].type != 'hidden' && inst == $.datepick._curInst) |
| 916 |
$( inst.input ).trigger( 'focus' ); // FixIn: 8.7.11.12. |
| 917 |
|
| 918 |
// FixIn: 9.4.4.13. |
| 919 |
var resource_id = this._get(inst, 'wpbc_resource_id'); |
| 920 |
if ( resource_id > 0 ){ |
| 921 |
$( 'body' ).trigger( |
| 922 |
'wpbc_datepick_inline_calendar_refresh' // event name |
| 923 |
, [ |
| 924 |
resource_id // Resource ID - 1 |
| 925 |
, inst // datepick Obj |
| 926 |
] |
| 927 |
); |
| 928 |
} |
| 929 |
// To catch this event: jQuery( 'body' ).on('wpbc_datepick_inline_calendar_refresh', function( event, resource_id, inst ) { ... } ); |
| 930 |
//FixIn End: 9.4.4.13 |
| 931 |
}, |
| 932 |
|
| 933 |
/* Retrieve the size of left and top borders for an element. |
| 934 |
@param elem (jQuery object) the element of interest |
| 935 |
@return (number[2]) the left and top borders */ |
| 936 |
_getBorders: function(elem) { |
| 937 |
var convert = function(value) { |
| 938 |
var extra = ($.browser_is_supported_datepick.msie ? 1 : 0); |
| 939 |
return {thin: 1 + extra, medium: 3 + extra, thick: 5 + extra}[value] || value; |
| 940 |
}; |
| 941 |
return [parseFloat(convert(elem.css('border-left-width'))), |
| 942 |
parseFloat(convert(elem.css('border-top-width')))]; |
| 943 |
}, |
| 944 |
|
| 945 |
/* Check positioning to remain on the screen. |
| 946 |
@param inst (object) the instance settings for this datepicker |
| 947 |
@param offset (object) the offset of the attached field |
| 948 |
@param isFixed (boolean) true if control or a parent is 'fixed' in position |
| 949 |
@return (object) the updated offset for the datepicker */ |
| 950 |
_checkOffset: function(inst, offset, isFixed) { |
| 951 |
var alignment = this._get(inst, 'alignment'); |
| 952 |
var isRTL = this._get(inst, 'isRTL'); |
| 953 |
var pos = inst.input ? this._findPos(inst.input[0]) : null; |
| 954 |
var browserWidth = document.documentElement.clientWidth; |
| 955 |
var browserHeight = document.documentElement.clientHeight; |
| 956 |
if (browserWidth == 0) |
| 957 |
return offset; |
| 958 |
var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft; |
| 959 |
var scrollY = document.documentElement.scrollTop || document.body.scrollTop; |
| 960 |
var above = pos[1] - (this._inDialog ? 0 : inst.dpDiv.outerHeight()) - |
| 961 |
(isFixed && $.browser_is_supported_datepick.opera ? document.documentElement.scrollTop : 0); |
| 962 |
var below = offset.top; |
| 963 |
var alignL = offset.left; |
| 964 |
var alignR = pos[0] + (inst.input ? inst.input.outerWidth() : 0) - inst.dpDiv.outerWidth() - |
| 965 |
(isFixed && $.browser_is_supported_datepick.opera ? document.documentElement.scrollLeft : 0); |
| 966 |
var tooWide = (offset.left + inst.dpDiv.outerWidth() - scrollX) > browserWidth; |
| 967 |
var tooHigh = (offset.top + inst.dpDiv.outerHeight() - scrollY) > browserHeight; |
| 968 |
if (alignment == 'topLeft') { |
| 969 |
offset = {left: alignL, top: above}; |
| 970 |
} |
| 971 |
else if (alignment == 'topRight') { |
| 972 |
offset = {left: alignR, top: above}; |
| 973 |
} |
| 974 |
else if (alignment == 'bottomLeft') { |
| 975 |
offset = {left: alignL, top: below}; |
| 976 |
} |
| 977 |
else if (alignment == 'bottomRight') { |
| 978 |
offset = {left: alignR, top: below}; |
| 979 |
} |
| 980 |
else if (alignment == 'top') { |
| 981 |
offset = {left: (isRTL || tooWide ? alignR : alignL), top: above}; |
| 982 |
} |
| 983 |
else { // bottom |
| 984 |
offset = {left: (isRTL || tooWide ? alignR : alignL), |
| 985 |
top: (tooHigh ? above : below)}; |
| 986 |
} |
| 987 |
offset.left = Math.max((isFixed ? 0 : scrollX), offset.left - (isFixed ? scrollX : 0)); |
| 988 |
offset.top = Math.max((isFixed ? 0 : scrollY), offset.top - (isFixed ? scrollY : 0)); |
| 989 |
return offset; |
| 990 |
}, |
| 991 |
|
| 992 |
/* Find an element's position on the screen. |
| 993 |
@param elem (element) the element to check |
| 994 |
@return (number[2]) the x- and y-coordinates for the object */ |
| 995 |
_findPos: function(elem) { |
| 996 |
while (elem && (elem.type == 'hidden' || elem.nodeType != 1)) { |
| 997 |
elem = elem.nextSibling; |
| 998 |
} |
| 999 |
var position = $(elem).offset(); |
| 1000 |
return [position.left, position.top]; |
| 1001 |
}, |
| 1002 |
|
| 1003 |
/* Hide the date picker from view. |
| 1004 |
@param input (element) the input field attached to the date picker |
| 1005 |
@param duration (string) the duration over which to close the date picker */ |
| 1006 |
_hideDatepick: function(input, duration) { |
| 1007 |
var inst = this._curInst; |
| 1008 |
if (!inst || (input && inst != $.data(input, PROP_NAME))) |
| 1009 |
return false; |
| 1010 |
var rangeSelect = this._get(inst, 'rangeSelect'); |
| 1011 |
if (rangeSelect && inst.stayOpen) |
| 1012 |
this._updateInput('#' + inst.id); |
| 1013 |
inst.stayOpen = false; |
| 1014 |
if (this._datepickerShowing) { |
| 1015 |
duration = (duration != null ? duration : this._get(inst, 'duration')); |
| 1016 |
var showAnim = this._get(inst, 'showAnim'); |
| 1017 |
var postProcess = function() { |
| 1018 |
$.datepick._tidyDialog(inst); |
| 1019 |
}; |
| 1020 |
if (duration != '' && $.effects && $.effects[showAnim]) |
| 1021 |
inst.dpDiv.hide(showAnim, $.datepick._get(inst, 'showOptions'), |
| 1022 |
duration, postProcess); |
| 1023 |
else |
| 1024 |
inst.dpDiv[(duration == '' ? 'hide' : (showAnim == 'slideDown' ? 'slideUp' : |
| 1025 |
(showAnim == 'fadeIn' ? 'fadeOut' : 'hide')))](duration, postProcess); |
| 1026 |
if (duration == '') |
| 1027 |
this._tidyDialog(inst); |
| 1028 |
var onClose = this._get(inst, 'onClose'); |
| 1029 |
if (onClose) // Trigger custom callback |
| 1030 |
onClose.apply((inst.input ? inst.input[0] : null), |
| 1031 |
[(inst.input ? inst.input.val() : ''), this._getDate(inst), inst]); |
| 1032 |
this._datepickerShowing = false; |
| 1033 |
this._lastInput = null; |
| 1034 |
inst.settings.prompt = null; |
| 1035 |
if (this._inDialog) { |
| 1036 |
this._dialogInput.css({ position: 'absolute', left: '0', top: '-100px' }); |
| 1037 |
this.dpDiv.removeClass(this._dialogClass[this._get(inst, 'useThemeRoller') ? 1 : 0]); |
| 1038 |
if ($.blockUI) { |
| 1039 |
$.unblockUI(); |
| 1040 |
$('body').append(this.dpDiv); |
| 1041 |
} |
| 1042 |
} |
| 1043 |
this._inDialog = false; |
| 1044 |
} |
| 1045 |
this._curInst = null; |
| 1046 |
return false; |
| 1047 |
}, |
| 1048 |
|
| 1049 |
/* Tidy up after a dialog display. |
| 1050 |
@param inst (object) the instance settings for this datepicker */ |
| 1051 |
_tidyDialog: function(inst) { |
| 1052 |
var useTR = this._get(inst, 'useThemeRoller') ? 1 : 0; |
| 1053 |
//inst.dpDiv.removeClass(this._dialogClass[useTR]).unbind('.datepick'); // FixIn: 10.0.0.45. |
| 1054 |
inst.dpDiv.removeClass(this._dialogClass[useTR]).off('.datepick'); // FixIn: 10.0.0.45. |
| 1055 |
$('.' + this._promptClass[useTR], inst.dpDiv).remove(); |
| 1056 |
}, |
| 1057 |
|
| 1058 |
/* Close date picker if clicked elsewhere. |
| 1059 |
@param event (MouseEvent) the mouse click to check */ |
| 1060 |
_checkExternalClick: function(event) { |
| 1061 |
if (!$.datepick._curInst) |
| 1062 |
return; |
| 1063 |
var $target = $(event.target); |
| 1064 |
var useTR = $.datepick._get($.datepick._curInst, 'useThemeRoller') ? 1 : 0; |
| 1065 |
// replaced .andSelf to .addBack // FixIn: 10.0.0.45. |
| 1066 |
if (!$target.parents().addBack().is('#' + $.datepick._mainDivId[useTR]) && |
| 1067 |
!$target.hasClass($.datepick.markerClassName) && |
| 1068 |
!$target.parents().addBack().hasClass($.datepick._triggerClass[useTR]) && |
| 1069 |
$.datepick._datepickerShowing && !($.datepick._inDialog && $.blockUI)) |
| 1070 |
$.datepick._hideDatepick(null, ''); |
| 1071 |
}, |
| 1072 |
|
| 1073 |
/* Adjust one of the date sub-fields. |
| 1074 |
@param id (string) the ID of the target field |
| 1075 |
@param offset (number) the amount to change by |
| 1076 |
@param period (string) 'D' for days, 'M' for months, 'Y' for years */ |
| 1077 |
_adjustDate: function(id, offset, period) { |
| 1078 |
var inst = this._getInst($(id)[0]); |
| 1079 |
this._adjustInstDate(inst, offset + |
| 1080 |
(period == 'M' ? this._get(inst, 'showCurrentAtPos') : 0), // Undo positioning |
| 1081 |
period); |
| 1082 |
this._updateDatepick(inst); |
| 1083 |
return false; |
| 1084 |
}, |
| 1085 |
|
| 1086 |
/* Show the month for today or the current selection. |
| 1087 |
@param id (string) the ID of the target field */ |
| 1088 |
_gotoToday: function(id) { |
| 1089 |
var target = $(id); |
| 1090 |
var inst = this._getInst(target[0]); |
| 1091 |
if (this._get(inst, 'gotoCurrent') && inst.dates[0]) |
| 1092 |
inst.cursorDate = new Date(inst.dates[0].getTime()); |
| 1093 |
else |
| 1094 |
inst.cursorDate = this._daylightSavingAdjust(new Date()); |
| 1095 |
inst.drawMonth = inst.cursorDate.getMonth(); |
| 1096 |
inst.drawYear = inst.cursorDate.getFullYear(); |
| 1097 |
this._notifyChange(inst); |
| 1098 |
this._adjustDate(target); |
| 1099 |
return false; |
| 1100 |
}, |
| 1101 |
|
| 1102 |
/* Selecting a new month/year. |
| 1103 |
@param id (string) the ID of the target field |
| 1104 |
@param select (element) the select being chosen from |
| 1105 |
@param period (string) 'M' for month, 'Y' for year */ |
| 1106 |
_selectMonthYear: function(id, select, period) { |
| 1107 |
var target = $(id); |
| 1108 |
var inst = this._getInst(target[0]); |
| 1109 |
inst.selectingMonthYear = false; |
| 1110 |
var value = parseInt(select.options[select.selectedIndex].value, 10); |
| 1111 |
inst['selected' + (period == 'M' ? 'Month' : 'Year')] = |
| 1112 |
inst['draw' + (period == 'M' ? 'Month' : 'Year')] = value; |
| 1113 |
inst.cursorDate.setDate(Math.min(inst.cursorDate.getDate(), |
| 1114 |
$.datepick._getDaysInMonth(inst.drawYear, inst.drawMonth))); |
| 1115 |
inst.cursorDate['set' + (period == 'M' ? 'Month' : 'FullYear')](value); |
| 1116 |
this._notifyChange(inst); |
| 1117 |
this._adjustDate(target); |
| 1118 |
}, |
| 1119 |
|
| 1120 |
/* Restore input focus after not changing month/year. |
| 1121 |
@param id (string) the ID of the target field */ |
| 1122 |
_clickMonthYear: function(id) { |
| 1123 |
var inst = this._getInst($(id)[0]); |
| 1124 |
if (inst.input && inst.selectingMonthYear && !$.browser_is_supported_datepick.msie) |
| 1125 |
$( inst.input ).trigger( 'focus' ); // FixIn: 8.7.11.12. |
| 1126 |
inst.selectingMonthYear = !inst.selectingMonthYear; |
| 1127 |
}, |
| 1128 |
|
| 1129 |
/* Action for changing the first week day. |
| 1130 |
@param id (string) the ID of the target field |
| 1131 |
@param day (number) the number of the first day, 0 = Sun, 1 = Mon, ... */ |
| 1132 |
_changeFirstDay: function(id, day) { |
| 1133 |
var inst = this._getInst($(id)[0]); |
| 1134 |
inst.settings.firstDay = day; |
| 1135 |
this._updateDatepick(inst); |
| 1136 |
return false; |
| 1137 |
}, |
| 1138 |
|
| 1139 |
/* Select a particular day. |
| 1140 |
@param td (element) the table cell containing the selection |
| 1141 |
@param id (string) the ID of the target field |
| 1142 |
@param timestamp (number) the timestamp for this day */ |
| 1143 |
_selectDay: function(td, id, timestamp) { |
| 1144 |
var inst = this._getInst($(id)[0]); |
| 1145 |
var useTR = this._get(inst, 'useThemeRoller') ? 1 : 0; |
| 1146 |
if ($(td).hasClass(this._unselectableClass[useTR])) |
| 1147 |
return false; |
| 1148 |
var rangeSelect = this._get(inst, 'rangeSelect'); |
| 1149 |
var multiSelect = this._get(inst, 'multiSelect'); |
| 1150 |
if (rangeSelect) |
| 1151 |
inst.stayOpen = !inst.stayOpen; |
| 1152 |
else if (multiSelect) |
| 1153 |
inst.stayOpen = true; |
| 1154 |
if (inst.stayOpen) { |
| 1155 |
$('.datepick td', inst.dpDiv).removeClass(this._selectedClass[useTR]); |
| 1156 |
$(td).addClass(this._selectedClass[useTR]); |
| 1157 |
} |
| 1158 |
inst.cursorDate = this._daylightSavingAdjust(new Date(timestamp)); |
| 1159 |
var date = new Date(inst.cursorDate.getTime()); |
| 1160 |
if (rangeSelect && !inst.stayOpen) |
| 1161 |
inst.dates[1] = date; |
| 1162 |
else if (multiSelect) { |
| 1163 |
var pos = -1; |
| 1164 |
for (var i = 0; i < inst.dates.length; i++) |
| 1165 |
if (inst.dates[i] && date.getTime() == inst.dates[i].getTime()) { |
| 1166 |
pos = i; |
| 1167 |
break; |
| 1168 |
} |
| 1169 |
if (pos > -1) |
| 1170 |
inst.dates.splice(pos, 1); |
| 1171 |
else if (inst.dates.length < multiSelect) { |
| 1172 |
if (inst.dates[0]) |
| 1173 |
inst.dates.push(date); |
| 1174 |
else |
| 1175 |
inst.dates = [date]; |
| 1176 |
inst.stayOpen = (inst.dates.length != multiSelect); |
| 1177 |
} |
| 1178 |
} |
| 1179 |
else |
| 1180 |
inst.dates = [date]; |
| 1181 |
this._updateInput(id); |
| 1182 |
if (inst.stayOpen) |
| 1183 |
this._updateDatepick(inst); |
| 1184 |
else if ((rangeSelect || multiSelect) && inst.inline) |
| 1185 |
this._updateDatepick(inst); |
| 1186 |
return false; |
| 1187 |
}, |
| 1188 |
|
| 1189 |
/* Erase the input field and hide the date picker. |
| 1190 |
@param id (string) the ID of the target field */ |
| 1191 |
_clearDate: function(id) { |
| 1192 |
var target = $(id); |
| 1193 |
var inst = this._getInst(target[0]); |
| 1194 |
if (this._get(inst, 'mandatory')) |
| 1195 |
return false; |
| 1196 |
inst.stayOpen = false; |
| 1197 |
inst.dates = (this._get(inst, 'showDefault') ? |
| 1198 |
[this._getDefaultDate(inst)] : []); |
| 1199 |
this._updateInput(target); |
| 1200 |
return false; |
| 1201 |
}, |
| 1202 |
|
| 1203 |
/* Update the input field with the selected date. |
| 1204 |
@param id (string) the ID of the target field or |
| 1205 |
(element) the target object */ |
| 1206 |
_updateInput: function(id) { |
| 1207 |
var inst = this._getInst($(id)[0]); |
| 1208 |
var dateStr = this._showDate(inst); |
| 1209 |
this._updateAlternate(inst); |
| 1210 |
var onSelect = this._get(inst, 'onSelect'); |
| 1211 |
if (onSelect) |
| 1212 |
onSelect.apply((inst.input ? inst.input[0] : null), |
| 1213 |
[dateStr, this._getDate(inst), inst]); // Trigger custom callback |
| 1214 |
else if (inst.input) |
| 1215 |
inst.input.trigger('change'); // Fire the change event |
| 1216 |
if (inst.inline) |
| 1217 |
this._updateDatepick(inst); |
| 1218 |
else if (!inst.stayOpen) { |
| 1219 |
this._hideDatepick(null, this._get(inst, 'duration')); |
| 1220 |
this._lastInput = inst.input[0]; |
| 1221 |
if (typeof(inst.input[0]) != 'object') |
| 1222 |
$( inst.input ).trigger( 'focus' ); //FixIn: 8.7.11.12 // Restore focus |
| 1223 |
this._lastInput = null; |
| 1224 |
} |
| 1225 |
return false; |
| 1226 |
}, |
| 1227 |
|
| 1228 |
/* Update the input field with the current date(s). |
| 1229 |
@param inst (object) the instance settings for this datepicker |
| 1230 |
@return (string) the formatted date(s) */ |
| 1231 |
_showDate: function(inst) { |
| 1232 |
var dateStr = ''; |
| 1233 |
if (inst.input) { |
| 1234 |
dateStr = (inst.dates.length == 0 ? '' : this._formatDate(inst, inst.dates[0])); |
| 1235 |
if (dateStr) { |
| 1236 |
if (this._get(inst, 'rangeSelect')) |
| 1237 |
dateStr += this._get(inst, 'rangeSeparator') + |
| 1238 |
this._formatDate(inst, inst.dates[1] || inst.dates[0]); |
| 1239 |
else if (this._get(inst, 'multiSelect')) |
| 1240 |
for (var i = 1; i < inst.dates.length; i++) |
| 1241 |
dateStr += this._get(inst, 'multiSeparator') + |
| 1242 |
this._formatDate(inst, inst.dates[i]); |
| 1243 |
} |
| 1244 |
inst.input.val(dateStr); |
| 1245 |
} |
| 1246 |
return dateStr; |
| 1247 |
}, |
| 1248 |
|
| 1249 |
/* Update any alternate field to synchronise with the main field. |
| 1250 |
@param inst (object) the instance settings for this datepicker */ |
| 1251 |
_updateAlternate: function(inst) { |
| 1252 |
var altField = this._get(inst, 'altField'); |
| 1253 |
if (altField) { // Update alternate field too |
| 1254 |
var altFormat = this._get(inst, 'altFormat') || this._get(inst, 'dateFormat'); |
| 1255 |
var settings = this._getFormatConfig(inst); |
| 1256 |
var dateStr = this.formatDate(altFormat, inst.dates[0], settings); |
| 1257 |
if (dateStr && this._get(inst, 'rangeSelect')) |
| 1258 |
dateStr += this._get(inst, 'rangeSeparator') + this.formatDate( |
| 1259 |
altFormat, inst.dates[1] || inst.dates[0], settings); |
| 1260 |
else if (this._get(inst, 'multiSelect')) |
| 1261 |
for (var i = 1; i < inst.dates.length; i++) |
| 1262 |
dateStr += this._get(inst, 'multiSeparator') + |
| 1263 |
this.formatDate(altFormat, inst.dates[i], settings); |
| 1264 |
$(altField).val(dateStr); |
| 1265 |
} |
| 1266 |
}, |
| 1267 |
|
| 1268 |
/* Set as beforeShowDay function to prevent selection of weekends. |
| 1269 |
@param date (Date) the date to customise |
| 1270 |
@return ([boolean, string]) is this date selectable?, what is its CSS class? */ |
| 1271 |
noWeekends: function(date) { |
| 1272 |
return [(date.getDay() || 7) < 6, '']; |
| 1273 |
}, |
| 1274 |
|
| 1275 |
/* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition. |
| 1276 |
@param date (Date) the date to get the week for |
| 1277 |
@return (number) the number of the week within the year that contains this date */ |
| 1278 |
iso8601Week: function(date) { |
| 1279 |
var checkDate = new Date(date.getTime()); |
| 1280 |
// Find Thursday of this week starting on Monday |
| 1281 |
checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7)); |
| 1282 |
var time = checkDate.getTime(); |
| 1283 |
checkDate.setMonth(0); // Compare with Jan 1 |
| 1284 |
checkDate.setDate(1); |
| 1285 |
return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1; |
| 1286 |
}, |
| 1287 |
|
| 1288 |
/* Provide status text for a particular date. |
| 1289 |
@param date (Date) the date to get the status for |
| 1290 |
@param inst (object) the current datepicker instance |
| 1291 |
@return (string) the status display text for this date */ |
| 1292 |
dateStatus: function(date, inst) { |
| 1293 |
return $.datepick.formatDate($.datepick._get(inst, 'dateStatus'), |
| 1294 |
date, $.datepick._getFormatConfig(inst)); |
| 1295 |
}, |
| 1296 |
|
| 1297 |
/* Parse a string value into a date object. |
| 1298 |
See formatDate below for the possible formats. |
| 1299 |
@param format (string) the expected format of the date |
| 1300 |
@param value (string) the date in the above format |
| 1301 |
@param settings (object) attributes include: |
| 1302 |
shortYearCutoff (number) the cutoff year for determining the century (optional) |
| 1303 |
dayNamesShort (string[7]) abbreviated names of the days from Sunday (optional) |
| 1304 |
dayNames (string[7]) names of the days from Sunday (optional) |
| 1305 |
monthNamesShort (string[12]) abbreviated names of the months (optional) |
| 1306 |
monthNames (string[12]) names of the months (optional) |
| 1307 |
@return (Date) the extracted date value or null if value is blank */ |
| 1308 |
parseDate: function (format, value, settings) { |
| 1309 |
if (format == null || value == null) |
| 1310 |
throw 'Invalid arguments'; |
| 1311 |
value = (typeof value == 'object' ? value.toString() : value + ''); |
| 1312 |
if (value == '') |
| 1313 |
return null; |
| 1314 |
settings = settings || {}; |
| 1315 |
var shortYearCutoff = settings.shortYearCutoff || this._defaults.shortYearCutoff; |
| 1316 |
shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff : |
| 1317 |
new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10)); |
| 1318 |
var dayNamesShort = settings.dayNamesShort || this._defaults.dayNamesShort; |
| 1319 |
var dayNames = settings.dayNames || this._defaults.dayNames; |
| 1320 |
var monthNamesShort = settings.monthNamesShort || this._defaults.monthNamesShort; |
| 1321 |
var monthNames = settings.monthNames || this._defaults.monthNames; |
| 1322 |
var year = -1; |
| 1323 |
var month = -1; |
| 1324 |
var day = -1; |
| 1325 |
var doy = -1; |
| 1326 |
var literal = false; |
| 1327 |
// Check whether a format character is doubled |
| 1328 |
var lookAhead = function(match) { |
| 1329 |
var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match); |
| 1330 |
if (matches) |
| 1331 |
iFormat++; |
| 1332 |
return matches; |
| 1333 |
}; |
| 1334 |
// Extract a number from the string value |
| 1335 |
var getNumber = function(match) { |
| 1336 |
lookAhead(match); |
| 1337 |
var size = (match == '@' ? 14 : (match == '!' ? 20 : |
| 1338 |
(match == 'y' ? 4 : (match == 'o' ? 3 : 2)))); |
| 1339 |
var digits = new RegExp('^\\d{1,' + size + '}'); |
| 1340 |
var num = value.substring(iValue).match(digits); |
| 1341 |
if (!num) |
| 1342 |
throw 'Missing number at position ' + iValue; |
| 1343 |
iValue += num[0].length; |
| 1344 |
return parseInt(num[0], 10); |
| 1345 |
}; |
| 1346 |
// Extract a name from the string value and convert to an index |
| 1347 |
var getName = function(match, shortNames, longNames) { |
| 1348 |
var names = (lookAhead(match) ? longNames : shortNames); |
| 1349 |
for (var i = 0; i < names.length; i++) { |
| 1350 |
if (value.substr(iValue, names[i].length) == names[i]) { |
| 1351 |
iValue += names[i].length; |
| 1352 |
return i + 1; |
| 1353 |
} |
| 1354 |
} |
| 1355 |
throw 'Unknown name at position ' + iValue; |
| 1356 |
}; |
| 1357 |
// Confirm that a literal character matches the string value |
| 1358 |
var checkLiteral = function() { |
| 1359 |
if (value.charAt(iValue) != format.charAt(iFormat)) |
| 1360 |
throw 'Unexpected literal at position ' + iValue; |
| 1361 |
iValue++; |
| 1362 |
}; |
| 1363 |
var iValue = 0; |
| 1364 |
for (var iFormat = 0; iFormat < format.length; iFormat++) { |
| 1365 |
if (literal) |
| 1366 |
if (format.charAt(iFormat) == "'" && !lookAhead("'")) |
| 1367 |
literal = false; |
| 1368 |
else |
| 1369 |
checkLiteral(); |
| 1370 |
else |
| 1371 |
switch (format.charAt(iFormat)) { |
| 1372 |
case 'd': |
| 1373 |
day = getNumber('d'); |
| 1374 |
break; |
| 1375 |
case 'D': |
| 1376 |
getName('D', dayNamesShort, dayNames); |
| 1377 |
break; |
| 1378 |
case 'o': |
| 1379 |
doy = getNumber('o'); |
| 1380 |
break; |
| 1381 |
case 'w': |
| 1382 |
getNumber('w'); |
| 1383 |
break; |
| 1384 |
case 'm': |
| 1385 |
month = getNumber('m'); |
| 1386 |
break; |
| 1387 |
case 'M': |
| 1388 |
month = getName('M', monthNamesShort, monthNames); |
| 1389 |
break; |
| 1390 |
case 'y': |
| 1391 |
year = getNumber('y'); |
| 1392 |
break; |
| 1393 |
case '@': |
| 1394 |
var date = new Date(getNumber('@')); |
| 1395 |
year = date.getFullYear(); |
| 1396 |
month = date.getMonth() + 1; |
| 1397 |
day = date.getDate(); |
| 1398 |
break; |
| 1399 |
case '!': |
| 1400 |
var date = new Date((getNumber('!') - this._ticksTo1970) / 10000); |
| 1401 |
year = date.getFullYear(); |
| 1402 |
month = date.getMonth() + 1; |
| 1403 |
day = date.getDate(); |
| 1404 |
break; |
| 1405 |
case "'": |
| 1406 |
if (lookAhead("'")) |
| 1407 |
checkLiteral(); |
| 1408 |
else |
| 1409 |
literal = true; |
| 1410 |
break; |
| 1411 |
default: |
| 1412 |
checkLiteral(); |
| 1413 |
} |
| 1414 |
} |
| 1415 |
if (iValue < value.length) |
| 1416 |
throw 'Additional text found at end'; |
| 1417 |
if (year == -1) |
| 1418 |
year = new Date().getFullYear(); |
| 1419 |
else if (year < 100) |
| 1420 |
year += (shortYearCutoff == -1 ? 1900 : new Date().getFullYear() - |
| 1421 |
new Date().getFullYear() % 100 - (year <= shortYearCutoff ? 0 : 100)); |
| 1422 |
if (doy > -1) { |
| 1423 |
month = 1; |
| 1424 |
day = doy; |
| 1425 |
do { |
| 1426 |
var dim = this._getDaysInMonth(year, month - 1); |
| 1427 |
if (day <= dim) |
| 1428 |
break; |
| 1429 |
month++; |
| 1430 |
day -= dim; |
| 1431 |
} while (true); |
| 1432 |
} |
| 1433 |
var date = this._daylightSavingAdjust(new Date(year, month - 1, day)); |
| 1434 |
if (date.getFullYear() != year || date.getMonth() + 1 != month || date.getDate() != day) |
| 1435 |
throw 'Invalid date'; // E.g. 31/02/* |
| 1436 |
return date; |
| 1437 |
}, |
| 1438 |
|
| 1439 |
/* Standard date formats. */ |
| 1440 |
ATOM: 'yy-mm-dd', // RFC 3339 (ISO 8601) |
| 1441 |
COOKIE: 'D, dd M yy', |
| 1442 |
ISO_8601: 'yy-mm-dd', |
| 1443 |
RFC_822: 'D, d M y', |
| 1444 |
RFC_850: 'DD, dd-M-y', |
| 1445 |
RFC_1036: 'D, d M y', |
| 1446 |
RFC_1123: 'D, d M yy', |
| 1447 |
RFC_2822: 'D, d M yy', |
| 1448 |
RSS: 'D, d M y', // RFC 822 |
| 1449 |
TICKS: '!', |
| 1450 |
TIMESTAMP: '@', |
| 1451 |
W3C: 'yy-mm-dd', // ISO 8601 |
| 1452 |
|
| 1453 |
_ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) + |
| 1454 |
Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000), |
| 1455 |
|
| 1456 |
/* Format a date object into a string value. |
| 1457 |
The format can be combinations of the following: |
| 1458 |
d - day of month (no leading zero) |
| 1459 |
dd - day of month (two digit) |
| 1460 |
o - day of year (no leading zeros) |
| 1461 |
oo - day of year (three digit) |
| 1462 |
D - day name short |
| 1463 |
DD - day name long |
| 1464 |
w - week of year (no leading zero) |
| 1465 |
ww - week of year (two digit) |
| 1466 |
m - month of year (no leading zero) |
| 1467 |
mm - month of year (two digit) |
| 1468 |
M - month name short |
| 1469 |
MM - month name long |
| 1470 |
y - year (two digit) |
| 1471 |
yy - year (four digit) |
| 1472 |
@ - Unix timestamp (ms since 01/01/1970) |
| 1473 |
! - Windows ticks (100ns since 01/01/0001) |
| 1474 |
'...' - literal text |
| 1475 |
'' - single quote |
| 1476 |
@param format (string) the desired format of the date |
| 1477 |
@param date (Date) the date value to format |
| 1478 |
@param settings (object) attributes include: |
| 1479 |
dayNamesShort (string[7]) abbreviated names of the days from Sunday (optional) |
| 1480 |
dayNames (string[7]) names of the days from Sunday (optional) |
| 1481 |
monthNamesShort (string[12]) abbreviated names of the months (optional) |
| 1482 |
monthNames (string[12]) names of the months (optional) |
| 1483 |
calculateWeek (function) function that determines week of the year (optional) |
| 1484 |
@return (string) the date in the above format */ |
| 1485 |
formatDate: function (format, date, settings) { |
| 1486 |
if (!date) |
| 1487 |
return ''; |
| 1488 |
settings = settings || {}; |
| 1489 |
var dayNamesShort = settings.dayNamesShort || this._defaults.dayNamesShort; |
| 1490 |
var dayNames = settings.dayNames || this._defaults.dayNames; |
| 1491 |
var monthNamesShort = settings.monthNamesShort || this._defaults.monthNamesShort; |
| 1492 |
var monthNames = settings.monthNames || this._defaults.monthNames; |
| 1493 |
var calculateWeek = settings.calculateWeek || this._defaults.calculateWeek; |
| 1494 |
// Check whether a format character is doubled |
| 1495 |
var lookAhead = function(match) { |
| 1496 |
var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match); |
| 1497 |
if (matches) |
| 1498 |
iFormat++; |
| 1499 |
return matches; |
| 1500 |
}; |
| 1501 |
// Format a number, with leading zero if necessary |
| 1502 |
var formatNumber = function(match, value, len) { |
| 1503 |
var num = '' + value; |
| 1504 |
if (lookAhead(match)) |
| 1505 |
while (num.length < len) |
| 1506 |
num = '0' + num; |
| 1507 |
return num; |
| 1508 |
}; |
| 1509 |
// Format a name, short or long as requested |
| 1510 |
var formatName = function(match, value, shortNames, longNames) { |
| 1511 |
return (lookAhead(match) ? longNames[value] : shortNames[value]); |
| 1512 |
}; |
| 1513 |
var output = ''; |
| 1514 |
var literal = false; |
| 1515 |
if (date) |
| 1516 |
for (var iFormat = 0; iFormat < format.length; iFormat++) { |
| 1517 |
if (literal) |
| 1518 |
if (format.charAt(iFormat) == "'" && !lookAhead("'")) |
| 1519 |
literal = false; |
| 1520 |
else |
| 1521 |
output += format.charAt(iFormat); |
| 1522 |
else |
| 1523 |
switch (format.charAt(iFormat)) { |
| 1524 |
case 'd': |
| 1525 |
output += formatNumber('d', date.getDate(), 2); |
| 1526 |
break; |
| 1527 |
case 'D': |
| 1528 |
output += formatName('D', date.getDay(), dayNamesShort, dayNames); |
| 1529 |
break; |
| 1530 |
case 'o': |
| 1531 |
output += formatNumber('o', |
| 1532 |
(date.getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000, 3); |
| 1533 |
break; |
| 1534 |
case 'w': |
| 1535 |
output += formatNumber('w', calculateWeek(date), 2); |
| 1536 |
break; |
| 1537 |
case 'm': |
| 1538 |
output += formatNumber('m', date.getMonth() + 1, 2); |
| 1539 |
break; |
| 1540 |
case 'M': |
| 1541 |
output += formatName('M', date.getMonth(), monthNamesShort, monthNames); |
| 1542 |
break; |
| 1543 |
case 'y': |
| 1544 |
output += (lookAhead('y') ? date.getFullYear() : |
| 1545 |
(date.getFullYear() % 100 < 10 ? '0' : '') + date.getFullYear() % 100); |
| 1546 |
break; |
| 1547 |
case '@': |
| 1548 |
output += date.getTime(); |
| 1549 |
break; |
| 1550 |
case '!': |
| 1551 |
output += date.getTime() * 10000 + this._ticksTo1970; |
| 1552 |
break; |
| 1553 |
case "'": |
| 1554 |
if (lookAhead("'")) |
| 1555 |
output += "'"; |
| 1556 |
else |
| 1557 |
literal = true; |
| 1558 |
break; |
| 1559 |
default: |
| 1560 |
output += format.charAt(iFormat); |
| 1561 |
} |
| 1562 |
} |
| 1563 |
return output; |
| 1564 |
}, |
| 1565 |
|
| 1566 |
/* Get a setting value, defaulting if necessary. |
| 1567 |
@param inst (object) the instance settings for this datepicker |
| 1568 |
@param name (string) the name of the property |
| 1569 |
@return (any) the property's value */ |
| 1570 |
_get: function(inst, name) { |
| 1571 |
return inst.settings[name] !== undefined ? |
| 1572 |
inst.settings[name] : this._defaults[name]; |
| 1573 |
}, |
| 1574 |
|
| 1575 |
/* Parse existing date and initialise date picker. |
| 1576 |
@param inst (object) the instance settings for this datepicker */ |
| 1577 |
_setDateFromField: function(inst) { |
| 1578 |
var dateFormat = this._get(inst, 'dateFormat'); |
| 1579 |
var rangeSelect = this._get(inst, 'rangeSelect'); |
| 1580 |
var multiSelect = this._get(inst, 'multiSelect'); |
| 1581 |
inst.lastVal = (inst.input ? inst.input.val() : ''); |
| 1582 |
var dates = inst.lastVal; |
| 1583 |
dates = (rangeSelect ? dates.split(this._get(inst, 'rangeSeparator')) : |
| 1584 |
(multiSelect ? dates.split(this._get(inst, 'multiSeparator')) : [dates])); |
| 1585 |
inst.dates = []; |
| 1586 |
var settings = this._getFormatConfig(inst); |
| 1587 |
for (var i = 0; i < dates.length; i++) |
| 1588 |
try { |
| 1589 |
inst.dates[i] = this.parseDate(dateFormat, dates[i], settings); |
| 1590 |
} |
| 1591 |
catch (event) { |
| 1592 |
inst.dates[i] = null; |
| 1593 |
} |
| 1594 |
for (var i = inst.dates.length - 1; i >= 0; i--) |
| 1595 |
if (!inst.dates[i]) |
| 1596 |
inst.dates.splice(i, 1); |
| 1597 |
if (rangeSelect && inst.dates.length < 2) |
| 1598 |
inst.dates[1] = inst.dates[0]; |
| 1599 |
if (multiSelect && inst.dates.length > multiSelect) |
| 1600 |
inst.dates.splice(multiSelect, inst.dates.length); |
| 1601 |
inst.cursorDate = new Date((inst.dates[0] || this._getDefaultDate(inst)).getTime()); |
| 1602 |
inst.drawMonth = inst.cursorDate.getMonth(); |
| 1603 |
inst.drawYear = inst.cursorDate.getFullYear(); |
| 1604 |
this._adjustInstDate(inst); |
| 1605 |
}, |
| 1606 |
|
| 1607 |
/* Retrieve the default date shown on opening. |
| 1608 |
@param inst (object) the instance settings for this datepicker |
| 1609 |
@return (Date) the default date */ |
| 1610 |
_getDefaultDate: function(inst) { |
| 1611 |
return this._restrictMinMax(inst, |
| 1612 |
this._determineDate(inst, this._get(inst, 'defaultDate'), new Date())); |
| 1613 |
}, |
| 1614 |
|
| 1615 |
/* A date may be specified as an exact value or a relative one. |
| 1616 |
@param inst (object) the instance settings for this datepicker |
| 1617 |
@param date (Date or number or string) the date or offset |
| 1618 |
@param defaultDate (Date) the date to use if no other supplied |
| 1619 |
@return (Date) the decoded date */ |
| 1620 |
_determineDate: function(inst, date, defaultDate) { |
| 1621 |
var offsetNumeric = function(offset) { |
| 1622 |
var date = new Date(); |
| 1623 |
date.setDate(date.getDate() + offset); |
| 1624 |
return date; |
| 1625 |
}; |
| 1626 |
var offsetString = function(offset) { |
| 1627 |
try { |
| 1628 |
return $.datepick.parseDate($.datepick._get(inst, 'dateFormat'), |
| 1629 |
offset, $.datepick._getFormatConfig(inst)); |
| 1630 |
} |
| 1631 |
catch (e) { |
| 1632 |
// Ignore |
| 1633 |
} |
| 1634 |
var date = (offset.toLowerCase().match(/^c/) ? |
| 1635 |
$.datepick._getDate(inst) : null) || new Date(); |
| 1636 |
var year = date.getFullYear(); |
| 1637 |
var month = date.getMonth(); |
| 1638 |
var day = date.getDate(); |
| 1639 |
var pattern = /([+-]?[0-9]+)\s*(d|w|m|y)?/g; |
| 1640 |
var matches = pattern.exec(offset.toLowerCase()); |
| 1641 |
while (matches) { |
| 1642 |
switch (matches[2] || 'd') { |
| 1643 |
case 'd': |
| 1644 |
day += parseInt(matches[1], 10); break; |
| 1645 |
case 'w': |
| 1646 |
day += parseInt(matches[1], 10) * 7; break; |
| 1647 |
case 'm': |
| 1648 |
month += parseInt(matches[1], 10); |
| 1649 |
day = Math.min(day, $.datepick._getDaysInMonth(year, month)); |
| 1650 |
break; |
| 1651 |
case 'y': |
| 1652 |
year += parseInt(matches[1], 10); |
| 1653 |
day = Math.min(day, $.datepick._getDaysInMonth(year, month)); |
| 1654 |
break; |
| 1655 |
} |
| 1656 |
matches = pattern.exec(offset.toLowerCase()); |
| 1657 |
} |
| 1658 |
return new Date(year, month, day); |
| 1659 |
}; |
| 1660 |
date = (date == null ? defaultDate : (typeof date == 'string' ? offsetString(date) : |
| 1661 |
(typeof date == 'number' ? (isNaN(date) || date == Infinity || date == -Infinity ? |
| 1662 |
defaultDate : offsetNumeric(date)) : date))); |
| 1663 |
date = (date && (date.toString() == 'Invalid Date' || |
| 1664 |
date.toString() == 'NaN') ? defaultDate : date); |
| 1665 |
if (date) { |
| 1666 |
date.setHours(0); |
| 1667 |
date.setMinutes(0); |
| 1668 |
date.setSeconds(0); |
| 1669 |
date.setMilliseconds(0); |
| 1670 |
} |
| 1671 |
return this._daylightSavingAdjust(date); |
| 1672 |
}, |
| 1673 |
|
| 1674 |
/* Handle switch to/from daylight saving. |
| 1675 |
Hours may be non-zero on daylight saving cut-over: |
| 1676 |
> 12 when midnight changeover, but then cannot generate |
| 1677 |
midnight datetime, so jump to 1AM, otherwise reset. |
| 1678 |
@param date (Date) the date to check |
| 1679 |
@return (Date) the corrected date */ |
| 1680 |
_daylightSavingAdjust: function(date) { |
| 1681 |
if (!date) return null; |
| 1682 |
date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0); |
| 1683 |
return date; |
| 1684 |
}, |
| 1685 |
|
| 1686 |
/* Set the date(s) directly. |
| 1687 |
@param inst (object) the instance settings for this datepicker |
| 1688 |
@param date (Date or Date[] or number or string) the new date or start of a range |
| 1689 |
@param endDate (Date or number or string) the end of a range */ |
| 1690 |
_setDate: function(inst, date, endDate) { |
| 1691 |
date = (!date ? [] : (isArray(date) ? date : [date])); |
| 1692 |
if (endDate) |
| 1693 |
date.push(endDate); |
| 1694 |
var clear = (date.length == 0); |
| 1695 |
var origMonth = inst.cursorDate.getMonth(); |
| 1696 |
var origYear = inst.cursorDate.getFullYear(); |
| 1697 |
inst.dates = [this._restrictMinMax(inst, this._determineDate(inst, date[0], new Date()))]; |
| 1698 |
inst.cursorDate = new Date(inst.dates[0].getTime()); |
| 1699 |
inst.drawMonth = inst.cursorDate.getMonth(); |
| 1700 |
inst.drawYear = inst.cursorDate.getFullYear(); |
| 1701 |
if (this._get(inst, 'rangeSelect')) |
| 1702 |
inst.dates[1] = (date.length < 1 ? inst.dates[0] : |
| 1703 |
this._restrictMinMax(inst, this._determineDate(inst, date[1], null))); |
| 1704 |
else if (this._get(inst, 'multiSelect')) |
| 1705 |
for (var i = 1; i < date.length; i++) |
| 1706 |
inst.dates[i] = this._restrictMinMax(inst, this._determineDate(inst, date[i], null)); |
| 1707 |
if (origMonth != inst.cursorDate.getMonth() || origYear != inst.cursorDate.getFullYear()) |
| 1708 |
this._notifyChange(inst); |
| 1709 |
this._adjustInstDate(inst); |
| 1710 |
this._showDate(inst); |
| 1711 |
}, |
| 1712 |
|
| 1713 |
/* Retrieve the date(s) directly. |
| 1714 |
@param inst (object) the instance settings for this datepicker |
| 1715 |
@return (Date or Date[2] or Date[]) the current date or dates |
| 1716 |
(for a range or multiples) */ |
| 1717 |
_getDate: function(inst) { |
| 1718 |
var startDate = (inst.input && inst.input.val() == '' ? null : inst.dates[0]); |
| 1719 |
if (this._get(inst, 'rangeSelect')) |
| 1720 |
return (startDate ? [inst.dates[0], inst.dates[1] || inst.dates[0]] : [null, null]); |
| 1721 |
else if (this._get(inst, 'multiSelect')) |
| 1722 |
return inst.dates.slice(0, inst.dates.length); |
| 1723 |
else |
| 1724 |
return startDate; |
| 1725 |
}, |
| 1726 |
|
| 1727 |
|
| 1728 |
/* Generate the HTML for the current state of the date picker. |
| 1729 |
@param inst (object) the instance settings for this datepicker |
| 1730 |
@return (string) the new HTML for the datepicker */ |
| 1731 |
_generateHTML: function(inst) { |
| 1732 |
var today = new Date(); |
| 1733 |
today = this._daylightSavingAdjust( |
| 1734 |
new Date(today.getFullYear(), today.getMonth(), today.getDate())); // Clear time |
| 1735 |
|
| 1736 |
|
| 1737 |
var showStatus = this._get(inst, 'showStatus'); |
| 1738 |
var initStatus = this._get(inst, 'initStatus') || ' '; |
| 1739 |
var isRTL = this._get(inst, 'isRTL'); |
| 1740 |
var useTR = this._get(inst, 'useThemeRoller') ? 1 : 0; |
| 1741 |
// Build the date picker HTML |
| 1742 |
var clear = (this._get(inst, 'mandatory') ? '' : |
| 1743 |
'<div class="' + this._clearClass[useTR] + '"><a href="javascript:void(0)" ' + |
| 1744 |
'onclick="jQuery.datepick._clearDate(\'#' + inst.id + '\');"' + |
| 1745 |
this._addStatus(useTR, showStatus, inst.id, this._get(inst, 'clearStatus'), initStatus) + |
| 1746 |
'>' + this._get(inst, 'clearText') + '</a></div>'); |
| 1747 |
var controls = '<div class="' + this._controlClass[useTR] + '">' + (isRTL ? '' : clear) + |
| 1748 |
'<div class="' + this._closeClass[useTR] + '"><a href="javascript:void(0)" ' + |
| 1749 |
'onclick="jQuery.datepick._hideDatepick();"' + |
| 1750 |
this._addStatus(useTR, showStatus, inst.id, this._get(inst, 'closeStatus'), initStatus) + |
| 1751 |
'>' + this._get(inst, 'closeText') + '</a></div>' + (isRTL ? clear : '') + '</div>'; |
| 1752 |
var prompt = this._get(inst, 'prompt'); |
| 1753 |
var closeAtTop = this._get(inst, 'closeAtTop'); |
| 1754 |
var hideIfNoPrevNext = this._get(inst, 'hideIfNoPrevNext'); |
| 1755 |
var navigationAsDateFormat = this._get(inst, 'navigationAsDateFormat'); |
| 1756 |
var showBigPrevNext = this._get(inst, 'showBigPrevNext'); |
| 1757 |
var numMonths = this._getNumberOfMonths(inst); |
| 1758 |
var showCurrentAtPos = this._get(inst, 'showCurrentAtPos'); |
| 1759 |
var stepMonths = this._get(inst, 'stepMonths'); |
| 1760 |
var stepBigMonths = this._get(inst, 'stepBigMonths'); |
| 1761 |
var isMultiMonth = (numMonths[0] != 1 || numMonths[1] != 1); |
| 1762 |
var minDate = this._getMinMaxDate(inst, 'min', true); |
| 1763 |
var maxDate = this._getMinMaxDate(inst, 'max'); |
| 1764 |
var drawMonth = inst.drawMonth - showCurrentAtPos; |
| 1765 |
var drawYear = inst.drawYear; |
| 1766 |
if (drawMonth < 0) { |
| 1767 |
drawMonth += 12; |
| 1768 |
drawYear--; |
| 1769 |
} |
| 1770 |
if (maxDate) { // Don't show past maximum unless also restricted by minimum |
| 1771 |
var maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(), |
| 1772 |
maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate())); |
| 1773 |
maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw); |
| 1774 |
while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) { |
| 1775 |
drawMonth--; |
| 1776 |
if (drawMonth < 0) { |
| 1777 |
drawMonth = 11; |
| 1778 |
drawYear--; |
| 1779 |
} |
| 1780 |
} |
| 1781 |
} |
| 1782 |
inst.drawMonth = drawMonth; |
| 1783 |
inst.drawYear = drawYear; |
| 1784 |
// Controls and links |
| 1785 |
var prevText = this._get(inst, 'prevText'); |
| 1786 |
prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText, |
| 1787 |
this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)), |
| 1788 |
this._getFormatConfig(inst))); |
| 1789 |
var prevBigText = (showBigPrevNext ? this._get(inst, 'prevBigText') : ''); |
| 1790 |
prevBigText = (!navigationAsDateFormat ? prevBigText : this.formatDate(prevBigText, |
| 1791 |
this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepBigMonths, 1)), |
| 1792 |
this._getFormatConfig(inst))); |
| 1793 |
var prev = '<div class="' + this._prevClass[useTR] + '">' + |
| 1794 |
(this._canAdjustMonth(inst, -1, drawYear, drawMonth) ? |
| 1795 |
(showBigPrevNext ? '<a href="javascript:void(0)" onclick="jQuery.datepick._adjustDate(\'#' + |
| 1796 |
inst.id + '\', -' + stepBigMonths + ', \'M\');"' + |
| 1797 |
this._addStatus(useTR, showStatus, inst.id, this._get(inst, 'prevBigStatus'), initStatus) + |
| 1798 |
'>' + prevBigText + '</a>' : '') + |
| 1799 |
'<a href="javascript:void(0)" onclick="jQuery.datepick._adjustDate(\'#' + |
| 1800 |
inst.id + '\', -' + stepMonths + ', \'M\');"' + |
| 1801 |
this._addStatus(useTR, showStatus, inst.id, this._get(inst, 'prevStatus'), initStatus) + |
| 1802 |
'>' + prevText + '</a>' : |
| 1803 |
(hideIfNoPrevNext ? ' ' : (showBigPrevNext ? '<label>' + prevBigText + '</label>' : '') + |
| 1804 |
'<label>' + prevText + '</label>')) + '</div>'; |
| 1805 |
var nextText = this._get(inst, 'nextText'); |
| 1806 |
nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText, |
| 1807 |
this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)), |
| 1808 |
this._getFormatConfig(inst))); |
| 1809 |
var nextBigText = (showBigPrevNext ? this._get(inst, 'nextBigText') : ''); |
| 1810 |
nextBigText = (!navigationAsDateFormat ? nextBigText : this.formatDate(nextBigText, |
| 1811 |
this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepBigMonths, 1)), |
| 1812 |
this._getFormatConfig(inst))); |
| 1813 |
var next = '<div class="' + this._nextClass[useTR] + '">' + |
| 1814 |
(this._canAdjustMonth(inst, +1, drawYear, drawMonth) ? |
| 1815 |
'<a href="javascript:void(0)" onclick="jQuery.datepick._adjustDate(\'#' + |
| 1816 |
inst.id + '\', +' + stepMonths + ', \'M\');"' + |
| 1817 |
this._addStatus(useTR, showStatus, inst.id, this._get(inst, 'nextStatus'), initStatus) + |
| 1818 |
'>' + nextText + '</a>' + |
| 1819 |
(showBigPrevNext ? '<a href="javascript:void(0)" onclick="jQuery.datepick._adjustDate(\'#' + |
| 1820 |
inst.id + '\', +' + stepBigMonths + ', \'M\');"' + |
| 1821 |
this._addStatus(useTR, showStatus, inst.id, this._get(inst, 'nextBigStatus'), initStatus) + |
| 1822 |
'>' + nextBigText + '</a>' : '') : |
| 1823 |
(hideIfNoPrevNext ? ' ' : '<label>' + nextText + '</label>' + |
| 1824 |
(showBigPrevNext ? '<label>' + nextBigText + '</label>' : ''))) + '</div>'; |
| 1825 |
var currentText = this._get(inst, 'currentText'); |
| 1826 |
var gotoDate = (this._get(inst, 'gotoCurrent') && inst.dates[0] ? inst.dates[0] : today); |
| 1827 |
currentText = (!navigationAsDateFormat ? currentText : |
| 1828 |
this.formatDate(currentText, gotoDate, this._getFormatConfig(inst))); |
| 1829 |
var html = (closeAtTop && !inst.inline ? controls : '');/* + |
| 1830 |
'<div class="' + this._linksClass[useTR] + '">' + (isRTL ? next : prev) + |
| 1831 |
'<div class="' + this._currentClass[useTR] + '">' + (this._isInRange(inst, gotoDate) ? |
| 1832 |
'<a href="javascript:void(0)" onclick="jQuery.datepick._gotoToday(\'#' + inst.id + '\');"' + |
| 1833 |
this._addStatus(useTR, showStatus, inst.id, this._get(inst, 'currentStatus'), initStatus) + '>' + |
| 1834 |
currentText + '</a>' : (hideIfNoPrevNext ? ' ' : '<label>' + currentText + '</label>')) + |
| 1835 |
'</div>' + (isRTL ? prev : next) + '</div>' + |
| 1836 |
(prompt ? '<div class="' + this._promptClass[useTR] + '"><span>' + |
| 1837 |
prompt + '</span></div>' : '');/**/ |
| 1838 |
html += '<div class="calendar-links">' + (isRTL ? next : prev) ; |
| 1839 |
html += (isRTL ? prev : next) + '</div>' ; |
| 1840 |
var firstDay = parseInt(this._get(inst, 'firstDay'), 10); |
| 1841 |
firstDay = (isNaN(firstDay) ? 0 : firstDay); |
| 1842 |
var changeFirstDay = this._get(inst, 'changeFirstDay'); |
| 1843 |
var dayNames = this._get(inst, 'dayNames'); |
| 1844 |
var dayNamesShort = this._get(inst, 'dayNamesShort'); |
| 1845 |
var dayNamesMin = this._get(inst, 'dayNamesMin'); |
| 1846 |
var monthNames = this._get(inst, 'monthNames'); |
| 1847 |
var beforeShowDay = this._get(inst, 'beforeShowDay'); |
| 1848 |
var showOtherMonths = this._get(inst, 'showOtherMonths'); |
| 1849 |
var selectOtherMonths = this._get(inst, 'selectOtherMonths'); |
| 1850 |
var showWeeks = this._get(inst, 'showWeeks'); |
| 1851 |
var calculateWeek = this._get(inst, 'calculateWeek') || this.iso8601Week; |
| 1852 |
var weekStatus = this._get(inst, 'weekStatus'); |
| 1853 |
var status = (showStatus ? this._get(inst, 'dayStatus') || initStatus : ''); |
| 1854 |
var dateStatus = this._get(inst, 'statusForDate') || this.dateStatus; |
| 1855 |
var defaultDate = this._getDefaultDate(inst); |
| 1856 |
for (var row = 0; row < numMonths[0]; row++) { |
| 1857 |
for (var col = 0; col < numMonths[1]; col++) { |
| 1858 |
var cursorDate = this._daylightSavingAdjust( |
| 1859 |
new Date(drawYear, drawMonth, inst.cursorDate.getDate())); |
| 1860 |
html += '<div class="' + this._oneMonthClass[useTR] + // Responsive skin |
| 1861 |
(col == 0 && !useTR ? ' ' + this._newRowClass[useTR] : '') + '">' + |
| 1862 |
this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate, |
| 1863 |
cursorDate, row > 0 || col > 0, useTR, showStatus, initStatus, monthNames) + // Draw month headers |
| 1864 |
'<table class="' + this._tableClass[useTR] + '" cellpadding="0" cellspacing="0"><thead>' + |
| 1865 |
'<tr class="' + this._tableHeaderClass[useTR] + '">' + (showWeeks ? '<th' + |
| 1866 |
this._addStatus(useTR, showStatus, inst.id, weekStatus, initStatus) + '>' + |
| 1867 |
this._get(inst, 'weekHeader') + '</th>' : ''); |
| 1868 |
for (var dow = 0; dow < 7; dow++) { // Days of the week |
| 1869 |
var day = (dow + firstDay) % 7; |
| 1870 |
var dayStatus = (!showStatus || !changeFirstDay ? '' : |
| 1871 |
status.replace(/DD/, dayNames[day]).replace(/D/, dayNamesShort[day])); |
| 1872 |
html += '<th' + ((dow + firstDay + 6) % 7 < 5 ? '' : |
| 1873 |
' class="' + this._weekendClass[useTR] + '"') + '>' + |
| 1874 |
(!changeFirstDay ? '<span' + |
| 1875 |
this._addStatus(useTR, showStatus, inst.id, dayNames[day], initStatus) : |
| 1876 |
'<a href="javascript:void(0)" onclick="jQuery.datepick._changeFirstDay(\'#' + |
| 1877 |
inst.id + '\', ' + day + ');"' + |
| 1878 |
this._addStatus(useTR, showStatus, inst.id, dayStatus, initStatus)) + |
| 1879 |
' title="' + dayNames[day] + '">' + |
| 1880 |
dayNamesMin[day] + (changeFirstDay ? '</a>' : '</span>') + '</th>'; |
| 1881 |
} |
| 1882 |
html += '</tr></thead><tbody>'; |
| 1883 |
var daysInMonth = this._getDaysInMonth(drawYear, drawMonth); |
| 1884 |
if (drawYear == inst.cursorDate.getFullYear() && drawMonth == inst.cursorDate.getMonth()) |
| 1885 |
inst.cursorDate.setDate(Math.min(inst.cursorDate.getDate(), daysInMonth)); |
| 1886 |
var leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7; |
| 1887 |
var numRows = (isMultiMonth ? 6 : Math.ceil((leadDays + daysInMonth) / 7)); |
| 1888 |
var printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays)); |
| 1889 |
for (var dRow = 0; dRow < numRows; dRow++) { // Create datepicker rows |
| 1890 |
html += '<tr class="' + this._weekRowClass[useTR] + '">' + |
| 1891 |
(showWeeks ? '<td class="' + this._weekColClass[useTR] + '"' + |
| 1892 |
this._addStatus(useTR, showStatus, inst.id, weekStatus, initStatus) + '>' + |
| 1893 |
calculateWeek(printDate) + '</td>' : ''); |
| 1894 |
for (var dow = 0; dow < 7; dow++) { // Create datepicker days |
| 1895 |
var daySettings = (beforeShowDay ? |
| 1896 |
beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, '']); |
| 1897 |
var otherMonth = (printDate.getMonth() != drawMonth); |
| 1898 |
var unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] || |
| 1899 |
(minDate && printDate < minDate) || (maxDate && printDate > maxDate); |
| 1900 |
var selected = (this._get(inst, 'rangeSelect') && inst.dates[0] && |
| 1901 |
printDate.getTime() >= inst.dates[0].getTime() && |
| 1902 |
printDate.getTime() <= (inst.dates[1] || inst.dates[0]).getTime()); |
| 1903 |
for (var i = 0; i < inst.dates.length; i++) |
| 1904 |
selected = selected || (inst.dates[i] && |
| 1905 |
printDate.getTime() == inst.dates[i].getTime()); |
| 1906 |
var empty = otherMonth && !showOtherMonths; |
| 1907 |
html += '<td data-content="" class="' + this._dayClass[useTR] + |
| 1908 |
((dow + firstDay + 6) % 7 >= 5 ? ' ' + this._weekendClass[useTR] : '') + // Highlight weekends |
| 1909 |
(otherMonth ? ' ' + this._otherMonthClass[useTR] : '') + // Highlight days from other months |
| 1910 |
((printDate.getTime() == cursorDate.getTime() && |
| 1911 |
drawMonth == inst.cursorDate.getMonth() && inst.keyEvent) || // User pressed key |
| 1912 |
(defaultDate.getTime() == printDate.getTime() && |
| 1913 |
defaultDate.getTime() == cursorDate.getTime()) ? |
| 1914 |
// Or defaultDate is selected printedDate and defaultDate is cursorDate |
| 1915 |
' ' /*+ $.datepick._dayOverClass[useTR]*/ : '') + // Highlight selected day // FixIn: 9.2.1.7. |
| 1916 |
(unselectable ? ' ' + this._unselectableClass[useTR] : |
| 1917 |
' ' + this._selectableClass[useTR]) + // Highlight unselectable days |
| 1918 |
(empty ? '' : ' ' + daySettings[1] + // Highlight custom dates |
| 1919 |
(selected ? ' ' + this._selectedClass[useTR] : '') + // Currently selected |
| 1920 |
// Highlight today (if different) |
| 1921 |
(printDate.getTime() == today.getTime() ? ' ' + this._todayClass[useTR] : '')) + '"' + |
| 1922 |
(!empty && daySettings[2] ? ' title="' + daySettings[2] + '"' : '') + // Cell title |
| 1923 |
// (unselectable ? '' : ' onmouseover="' + 'jQuery.datepick._doMouseOver(this,\'' + |
| 1924 |
(false ? '' : ' onmouseover="' + 'jQuery.datepick._doMouseOver(this,\'' + //FixIn: 2023-08-06 |
| 1925 |
inst.id + '\',' + printDate.getTime() + ')"' + |
| 1926 |
' onmouseout="jQuery.datepick._doMouseOut(this,\'' + inst.id + '\')"' + |
| 1927 |
' onclick="jQuery.datepick._selectDay(this,\'#' + // Select |
| 1928 |
inst.id + '\',' + printDate.getTime() + ')"') + '>'; |
| 1929 |
|
| 1930 |
/** Start content of Day cell *************************************************************/ |
| 1931 |
html += '<div class="wpbc-cell-box">' + // FixIn: 8.9.4.13. |
| 1932 |
'<div class="wpbc-diagonal-el">' + |
| 1933 |
'<div class="wpbc-co-out">' + |
| 1934 |
'<svg height="100%" width="100%" viewBox="0 0 100 100" preserveAspectRatio="none">' + |
| 1935 |
'<polygon points="0,0 0,99 99,0"></polygon>' + |
| 1936 |
'<polygon points="0,0 0,100 49,100 49,0"></polygon>' + |
| 1937 |
'</svg>' + |
| 1938 |
'</div>' + |
| 1939 |
'<div class="wpbc-co-in">' + |
| 1940 |
'<svg height="100%" width="100%" viewBox="0 0 98 98" preserveAspectRatio="none">' + |
| 1941 |
'<polygon points="0,99 99,99 99,0"></polygon>' + |
| 1942 |
'<polygon points="50,98 98,98 98,0 50,0"></polygon>' + |
| 1943 |
'</svg>' + |
| 1944 |
'</div>' + |
| 1945 |
'</div>' + |
| 1946 |
//'<div class="check-in-div"><div></div></div>' + // Deprecated! remove this line |
| 1947 |
//'<div class="check-out-div"><div></div></div>' + // Deprecated! remove this line |
| 1948 |
'<div class="date-cell-content">' + // FixIn: 8.9.4.13. |
| 1949 |
'<div class="date-content-top">' + |
| 1950 |
(unselectable ? '' : ((typeof (wpbc_show_date_info_top) == 'function') ? wpbc_show_date_info_top( inst.id, printDate.getTime() ) : '')) + |
| 1951 |
'</div>' + |
| 1952 |
(empty ? ' ' : // Not showing other months // FixIn: 6.0.1.2. |
| 1953 |
(unselectable ? '<span>' + printDate.getDate()+ '</span>' : '<a href="javascript:void(0)" >' + printDate.getDate() + '</a>')) + // FixIn: 10.0.0.19. |
| 1954 |
'<div class="date-content-bottom">'+ |
| 1955 |
(unselectable ? '' : ((typeof (wpbc_show_date_info_bottom) == 'function') ? wpbc_show_date_info_bottom( inst.id, printDate.getTime() ) : '')) + |
| 1956 |
'</div>' + |
| 1957 |
'</div>' + |
| 1958 |
'</div>'; |
| 1959 |
/** End content of Day cell *******************************************************************/ |
| 1960 |
html += '</td>'; |
| 1961 |
printDate.setDate(printDate.getDate() + 1); |
| 1962 |
printDate = this._daylightSavingAdjust(printDate); |
| 1963 |
} |
| 1964 |
html += '</tr>'; |
| 1965 |
} |
| 1966 |
drawMonth++; |
| 1967 |
if (drawMonth > 11) { |
| 1968 |
drawMonth = 0; |
| 1969 |
drawYear++; |
| 1970 |
} |
| 1971 |
html += '</tbody></table></div>'; |
| 1972 |
} |
| 1973 |
if (useTR) |
| 1974 |
html += '<div class="' + this._newRowClass[useTR] + '"></div>'; |
| 1975 |
} |
| 1976 |
html += (showStatus ? '<div style="clear: both;"></div><div id="' + this._statusId[useTR] + |
| 1977 |
inst.id +'" class="' + this._statusClass[useTR] + '">' + initStatus + '</div>' : '') + |
| 1978 |
(!closeAtTop && !inst.inline ? controls : '') + |
| 1979 |
'<div style="clear: both;"></div>' + |
| 1980 |
($.browser_is_supported_datepick.msie && parseInt($.browser_is_supported_datepick.version, 10) < 7 && !inst.inline ? |
| 1981 |
'<iframe src="javascript:false;" class="' + this._coverClass[useTR] + '"></iframe>' : ''); |
| 1982 |
inst.keyEvent = false; |
| 1983 |
return html; |
| 1984 |
}, |
| 1985 |
|
| 1986 |
/* Generate the month and year header. |
| 1987 |
@param inst (object) the instance settings for this datepicker |
| 1988 |
@param drawMonth (number) the current month |
| 1989 |
@param drawYear (number) the current year |
| 1990 |
@param minDate (Date) the minimum allowed date or null if none |
| 1991 |
@param maxDate (Date) the maximum allowed date or null if none |
| 1992 |
@param cursorDate (Date) the current date position |
| 1993 |
@param secondary (boolean) true if not the first month/year header |
| 1994 |
@param useTR (number) 1 if applying ThemeRoller styling, 0 if not |
| 1995 |
@param showStatus (boolean) true if status bar is visible |
| 1996 |
@param initStatus (string) the default status message |
| 1997 |
@param monthNames (string[12]) the names of the months |
| 1998 |
@return (string) the HTML for the month and year */ |
| 1999 |
_generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate, |
| 2000 |
cursorDate, secondary, useTR, showStatus, initStatus, monthNames) { |
| 2001 |
var minDraw = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)); |
| 2002 |
minDate = (minDate && minDraw < minDate ? minDraw : minDate); |
| 2003 |
var changeMonth = this._get(inst, 'changeMonth'); |
| 2004 |
var changeYear = this._get(inst, 'changeYear'); |
| 2005 |
var showMonthAfterYear = this._get(inst, 'showMonthAfterYear'); |
| 2006 |
var html = '<div class="' + this._monthYearClass[useTR] + '">'; |
| 2007 |
var monthHtml = ''; |
| 2008 |
// Month selection |
| 2009 |
if (secondary || !changeMonth) |
| 2010 |
monthHtml += '<span class="' + this._monthClass[useTR] + '">' + |
| 2011 |
monthNames[drawMonth] + '</span>'; |
| 2012 |
else { |
| 2013 |
var inMinYear = (minDate && minDate.getFullYear() == drawYear); |
| 2014 |
var inMaxYear = (maxDate && maxDate.getFullYear() == drawYear); |
| 2015 |
monthHtml += '<select class="' + this._monthSelectClass[useTR] + '" ' + |
| 2016 |
'onchange="jQuery.datepick._selectMonthYear(\'#' + inst.id + '\', this, \'M\');" ' + |
| 2017 |
'onclick="jQuery.datepick._clickMonthYear(\'#' + inst.id + '\');"' + |
| 2018 |
this._addStatus(useTR, showStatus, inst.id, this._get(inst, 'monthStatus'), |
| 2019 |
initStatus) + '>'; |
| 2020 |
for (var month = 0; month < 12; month++) { |
| 2021 |
if ((!inMinYear || month >= minDate.getMonth()) && |
| 2022 |
(!inMaxYear || month <= maxDate.getMonth())) |
| 2023 |
monthHtml += '<option value="' + month + '"' + |
| 2024 |
(month == drawMonth ? ' selected="selected"' : '') + |
| 2025 |
'>' + monthNames[month] + '</option>'; |
| 2026 |
} |
| 2027 |
monthHtml += '</select>'; |
| 2028 |
} |
| 2029 |
if (!showMonthAfterYear) |
| 2030 |
html += monthHtml + (secondary || !changeMonth || !changeYear ? ' ' : ''); |
| 2031 |
// Year selection |
| 2032 |
if (secondary || !changeYear) |
| 2033 |
html += '<span class="' + this._yearClass[useTR] + '">' + drawYear + '</span>'; |
| 2034 |
else { |
| 2035 |
// Determine range of years to display |
| 2036 |
var years = this._get(inst, 'yearRange').split(':'); |
| 2037 |
var year = 0; |
| 2038 |
var endYear = 0; |
| 2039 |
if (years.length != 2) { |
| 2040 |
year = drawYear - 10; |
| 2041 |
endYear = drawYear + 10; |
| 2042 |
} else if (years[0].charAt(0) == '+' || years[0].charAt(0) == '-') { |
| 2043 |
year = drawYear + parseInt(years[0], 10); |
| 2044 |
endYear = drawYear + parseInt(years[1], 10); |
| 2045 |
} else { |
| 2046 |
year = parseInt(years[0], 10); |
| 2047 |
endYear = parseInt(years[1], 10); |
| 2048 |
} |
| 2049 |
year = (minDate ? Math.max(year, minDate.getFullYear()) : year); |
| 2050 |
endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear); |
| 2051 |
html += '<select class="' + this._yearSelectClass[useTR] + '" ' + |
| 2052 |
'onchange="jQuery.datepick._selectMonthYear(\'#' + inst.id + '\', this, \'Y\');" ' + |
| 2053 |
'onclick="jQuery.datepick._clickMonthYear(\'#' + inst.id + '\');"' + |
| 2054 |
this._addStatus(useTR, showStatus, inst.id, this._get(inst, 'yearStatus'), |
| 2055 |
initStatus) + '>'; |
| 2056 |
for (; year <= endYear; year++) { |
| 2057 |
html += '<option value="' + year + '"' + |
| 2058 |
(year == drawYear ? ' selected="selected"' : '') + |
| 2059 |
'>' + year + '</option>'; |
| 2060 |
} |
| 2061 |
html += '</select>'; |
| 2062 |
} |
| 2063 |
html += this._get(inst, 'yearSuffix'); |
| 2064 |
if (showMonthAfterYear) |
| 2065 |
html += (secondary || !changeMonth || !changeYear ? ' ' : '') + monthHtml; |
| 2066 |
html += '</div>'; // Close datepicker_header |
| 2067 |
return html; |
| 2068 |
}, |
| 2069 |
|
| 2070 |
/* Provide code to set and clear the status panel. |
| 2071 |
@param useTR (number) 1 if applying ThemeRoller styling, 0 if not |
| 2072 |
@param showStatus (boolean) true if the status bar is shown |
| 2073 |
@param id (string) the ID of the datepicker instance |
| 2074 |
@param text (string) the status text to display |
| 2075 |
@param initStatus (string) the default status message |
| 2076 |
@return (string) hover actions for the status messages */ |
| 2077 |
_addStatus: function(useTR, showStatus, id, text, initStatus) { |
| 2078 |
return (showStatus ? ' onmouseover="jQuery(\'#' + this._statusId[useTR] + id + |
| 2079 |
'\').html(\'' + (text || initStatus) + '\');" ' + |
| 2080 |
'onmouseout="jQuery(\'#' + this._statusId[useTR] + id + |
| 2081 |
'\').html(\'' + initStatus + '\');"' : ''); |
| 2082 |
}, |
| 2083 |
|
| 2084 |
/* Adjust one of the date sub-fields. |
| 2085 |
@param inst (object) the instance settings for this datepicker |
| 2086 |
@param offset (number) the change to apply |
| 2087 |
@param period (string) 'D' for days, 'M' for months, 'Y' for years */ |
| 2088 |
_adjustInstDate: function(inst, offset, period) { |
| 2089 |
var yearMonth = inst.drawYear + '/' + inst.drawMonth; |
| 2090 |
var year = inst.drawYear + (period == 'Y' ? offset : 0); |
| 2091 |
var month = inst.drawMonth + (period == 'M' ? offset : 0); |
| 2092 |
var day = Math.min(inst.cursorDate.getDate(), this._getDaysInMonth(year, month)) + |
| 2093 |
(period == 'D' ? offset : 0); |
| 2094 |
inst.cursorDate = this._restrictMinMax(inst, |
| 2095 |
this._daylightSavingAdjust(new Date(year, month, day))); |
| 2096 |
inst.drawMonth = inst.cursorDate.getMonth(); |
| 2097 |
inst.drawYear = inst.cursorDate.getFullYear(); |
| 2098 |
if (yearMonth != inst.drawYear + '/' + inst.drawMonth) |
| 2099 |
this._notifyChange(inst); |
| 2100 |
}, |
| 2101 |
|
| 2102 |
/* Ensure a date is within any min/max bounds. |
| 2103 |
@param inst (object) the instance settings for this datepicker |
| 2104 |
@param date (Date) the date to check |
| 2105 |
@return (Date) the restricted date */ |
| 2106 |
_restrictMinMax: function(inst, date) { |
| 2107 |
var minDate = this._getMinMaxDate(inst, 'min', true); |
| 2108 |
var maxDate = this._getMinMaxDate(inst, 'max'); |
| 2109 |
date = (minDate && date < minDate ? new Date(minDate.getTime()) : date); |
| 2110 |
date = (maxDate && date > maxDate ? new Date(maxDate.getTime()) : date); |
| 2111 |
return date; |
| 2112 |
}, |
| 2113 |
|
| 2114 |
/* Notify change of month/year. |
| 2115 |
@param inst (object) the instance settings for this datepicker */ |
| 2116 |
_notifyChange: function(inst) { |
| 2117 |
var onChange = this._get(inst, 'onChangeMonthYear'); |
| 2118 |
if (onChange) |
| 2119 |
onChange.apply((inst.input ? inst.input[0] : null), |
| 2120 |
[inst.cursorDate.getFullYear(), inst.cursorDate.getMonth() + 1, |
| 2121 |
this._daylightSavingAdjust(new Date( |
| 2122 |
inst.cursorDate.getFullYear(), inst.cursorDate.getMonth(), 1)), inst]); |
| 2123 |
}, |
| 2124 |
|
| 2125 |
/* Determine the number of months to show. |
| 2126 |
@param inst (object) the instance settings for this datepicker |
| 2127 |
@return (number[2]) the number of rows and columns to display */ |
| 2128 |
_getNumberOfMonths: function(inst) { |
| 2129 |
var numMonths = this._get(inst, 'numberOfMonths'); |
| 2130 |
return (numMonths == null ? [1, 1] : |
| 2131 |
(typeof numMonths == 'number' ? [1, numMonths] : numMonths)); |
| 2132 |
}, |
| 2133 |
|
| 2134 |
/* Determine the current minimum/maximum date. |
| 2135 |
Ensure no time components are set. May be overridden for a range. |
| 2136 |
@param inst (object) the instance settings for this datepicker |
| 2137 |
@param minMax (string) 'min' or 'max' for required date |
| 2138 |
@param checkRange (boolean) true to allow override for a range minimum |
| 2139 |
@return (Date) the minimum/maximum date or null if none */ |
| 2140 |
_getMinMaxDate: function(inst, minMax, checkRange) { |
| 2141 |
var date = this._determineDate(inst, this._get(inst, minMax + 'Date'), null); |
| 2142 |
var rangeMin = this._getRangeMin(inst); |
| 2143 |
return (checkRange && rangeMin && (!date || rangeMin > date) ? rangeMin : date); |
| 2144 |
}, |
| 2145 |
|
| 2146 |
/* Retrieve the temporary range minimum when in the process of selecting. |
| 2147 |
@param inst (object) the instance settings for this datepicker |
| 2148 |
@return (Date) the temporary minimum or null */ |
| 2149 |
_getRangeMin: function(inst) { |
| 2150 |
return (this._get(inst, 'rangeSelect') && inst.dates[0] && |
| 2151 |
!inst.dates[1] ? inst.dates[0] : null); |
| 2152 |
}, |
| 2153 |
|
| 2154 |
/* Find the number of days in a given month. |
| 2155 |
@param year (number) the full year |
| 2156 |
@param month (number) the month (0 to 11) |
| 2157 |
@return (number) the number of days in this month */ |
| 2158 |
_getDaysInMonth: function(year, month) { |
| 2159 |
return 32 - new Date(year, month, 32).getDate(); |
| 2160 |
}, |
| 2161 |
|
| 2162 |
/* Find the day of the week of the first of a month. |
| 2163 |
@param year (number) the full year |
| 2164 |
@param month (number) the month (0 to 11) |
| 2165 |
@return (number) 0 = Sunday, 1 = Monday, ... */ |
| 2166 |
_getFirstDayOfMonth: function(year, month) { |
| 2167 |
return new Date(year, month, 1).getDay(); |
| 2168 |
}, |
| 2169 |
|
| 2170 |
/* Determines if we should allow a "prev/next" month display change. |
| 2171 |
@param inst (object) the instance settings for this datepicker |
| 2172 |
@param offset (number) the number of months to change by |
| 2173 |
@param curYear (number) the full current year |
| 2174 |
@param curMonth (number) the current month (0 to 11) |
| 2175 |
@return (boolean) true if prev/next allowed, false if not */ |
| 2176 |
_canAdjustMonth: function(inst, offset, curYear, curMonth) { |
| 2177 |
var numMonths = this._getNumberOfMonths(inst); |
| 2178 |
var date = this._daylightSavingAdjust(new Date(curYear, |
| 2179 |
curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1)); |
| 2180 |
if (offset < 0) |
| 2181 |
date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth())); |
| 2182 |
return this._isInRange(inst, date); |
| 2183 |
}, |
| 2184 |
|
| 2185 |
/* Is the given date in the accepted range? |
| 2186 |
@param inst (object) the instance settings for this datepicker |
| 2187 |
@param date (Date) the date to check |
| 2188 |
@return (boolean) true if the date is in the allowed minimum/maximum, false if not */ |
| 2189 |
_isInRange: function(inst, date) { |
| 2190 |
// During range selection, use minimum of selected date and range start |
| 2191 |
var minDate = this._getRangeMin(inst) || this._getMinMaxDate(inst, 'min'); |
| 2192 |
var maxDate = this._getMinMaxDate(inst, 'max'); |
| 2193 |
return ((!minDate || date >= minDate) && (!maxDate || date <= maxDate)); |
| 2194 |
}, |
| 2195 |
|
| 2196 |
/* Provide the configuration settings for formatting/parsing. |
| 2197 |
@param inst (object) the instance settings for this datepicker |
| 2198 |
@return (object) the settings subset */ |
| 2199 |
_getFormatConfig: function(inst) { |
| 2200 |
return {shortYearCutoff: this._get(inst, 'shortYearCutoff'), |
| 2201 |
dayNamesShort: this._get(inst, 'dayNamesShort'), dayNames: this._get(inst, 'dayNames'), |
| 2202 |
monthNamesShort: this._get(inst, 'monthNamesShort'), monthNames: this._get(inst, 'monthNames')}; |
| 2203 |
}, |
| 2204 |
|
| 2205 |
/* Format the given date for display. |
| 2206 |
@param inst (object) the instance settings for this datepicker |
| 2207 |
@param year (number, optional) the full year |
| 2208 |
@param month (number, optional) the month of the year (0 to 11) |
| 2209 |
@param day (number, optional) the day of the month |
| 2210 |
@return (string) formatted date */ |
| 2211 |
_formatDate: function(inst, year, month, day) { |
| 2212 |
if (!year) |
| 2213 |
inst.dates[0] = new Date(inst.cursorDate.getTime()); |
| 2214 |
var date = (year ? (typeof year == 'object' ? year : |
| 2215 |
this._daylightSavingAdjust(new Date(year, month, day))) : inst.dates[0]); |
| 2216 |
return this.formatDate(this._get(inst, 'dateFormat'), date, this._getFormatConfig(inst)); |
| 2217 |
} |
| 2218 |
}); |
| 2219 |
|
| 2220 |
/* jQuery extend now ignores nulls! |
| 2221 |
@param target (object) the object to extend |
| 2222 |
@param props (object) the new settings |
| 2223 |
@return (object) the updated object */ |
| 2224 |
function extendRemove(target, props) { |
| 2225 |
$.extend(target, props); |
| 2226 |
for (var name in props) |
| 2227 |
if (props[name] == null || props[name] == undefined) |
| 2228 |
target[name] = props[name]; |
| 2229 |
return target; |
| 2230 |
}; |
| 2231 |
|
| 2232 |
/* Determine whether an object is an array. |
| 2233 |
@param a (object) the object to test |
| 2234 |
@return (boolean) true if an array, false if not */ |
| 2235 |
function isArray(a) { |
| 2236 |
return (a && a.constructor == Array); |
| 2237 |
}; |
| 2238 |
|
| 2239 |
/* Invoke the datepicker functionality. |
| 2240 |
@param options (string) a command, optionally followed by additional parameters or |
| 2241 |
(object) settings for attaching new datepicker functionality |
| 2242 |
@return (jQuery) jQuery object */ |
| 2243 |
$.fn.datepick = function(options){ |
| 2244 |
var otherArgs = Array.prototype.slice.call(arguments, 1); |
| 2245 |
if (typeof options == 'string' && (options == 'isDisabled' || |
| 2246 |
options == 'getDate' || options == 'settings')) |
| 2247 |
return $.datepick['_' + options + 'Datepick']. |
| 2248 |
apply($.datepick, [this[0]].concat(otherArgs)); |
| 2249 |
if (options == 'option' && arguments.length == 2 && typeof arguments[1] == 'string') |
| 2250 |
return $.datepick['_' + options + 'Datepick']. |
| 2251 |
apply($.datepick, [this[0]].concat(otherArgs)); |
| 2252 |
return this.each(function() { |
| 2253 |
typeof options == 'string' ? |
| 2254 |
$.datepick['_' + options + 'Datepick']. |
| 2255 |
apply($.datepick, [this].concat(otherArgs)) : |
| 2256 |
$.datepick._attachDatepick(this, options); |
| 2257 |
}); |
| 2258 |
}; |
| 2259 |
|
| 2260 |
$.datepick = new Datepick(); // Singleton instance |
| 2261 |
|
| 2262 |
$(function() { |
| 2263 |
|
| 2264 |
$( document ).on( 'mousedown', $.datepick._checkExternalClick ).find( 'body' ).append( $.datepick.dpDiv ); // FixIn: 8.7.11.12. |
| 2265 |
}); |
| 2266 |
|
| 2267 |
})(jQuery); |
| 2268 |
|