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