1/*! 2 * jQuery UI Datepicker 1.10.2 3 * http://jqueryui.com 4 * 5 * Copyright 2013 jQuery Foundation and other contributors 6 * Released under the MIT license. 7 * http://jquery.org/license 8 * 9 * http://api.jqueryui.com/datepicker/ 10 * 11 * Depends: 12 * jquery.ui.core.js 13 */ 14(function( $, undefined ) { 15 16$.extend($.ui, { datepicker: { version: "1.10.2" } }); 17 18var PROP_NAME = "datepicker", 19 dpuuid = new Date().getTime()
vendor: 29,048 bytes, lines 19-756
19, 20 instActive; 21 22/* Date picker manager. 23 Use the singleton instance of this class, $.datepicker, to interact with the date picker. 24 Settings for (groups of) date pickers are maintained in an instance object, 25 allowing multiple different settings on the same page. */ 26 27function Datepicker() { 28 this._curInst = null; // The current instance in use 29 this._keyEvent = false; // If the last event was a key event 30 this._disabledInputs = []; // List of date picker inputs that have been disabled 31 this._datepickerShowing = false; // True if the popup picker is showing , false if not 32 this._inDialog = false; // True if showing within a "dialog", false if not 33 this._mainDivId = "ui-datepicker-div"; // The ID of the main datepicker division 34 this._inlineClass = "ui-datepicker-inline"; // The name of the inline marker class 35 this._appendClass = "ui-datepicker-append"; // The name of the append marker class 36 this._triggerClass = "ui-datepicker-trigger"; // The name of the trigger marker class 37 this._dialogClass = "ui-datepicker-dialog"; // The name of the dialog marker class 38 this._disableClass = "ui-datepicker-disabled"; // The name of the disabled covering marker class 39 this._unselectableClass = "ui-datepicker-unselectable"; // The name of the unselectable cell marker class 40 this._currentClass = "ui-datepicker-current-day"; // The name of the current day marker class 41 this._dayOverClass = "ui-datepicker-days-cell-over"; // The name of the day hover marker class 42 this.regional = []; // Available regional settings, indexed by language code 43 this.regional[""] = { // Default regional settings 44 closeText: "Done", // Display text for close link 45 prevText: "Prev", // Display text for previous month link 46 nextText: "Next", // Display text for next month link 47 currentText: "Today", // Display text for current month link 48 monthNames: ["January","February","March","April","May","June", 49 "July","August","September","October","November","December"], // Names of months for drop-down and formatting 50 monthNamesShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], // For formatting 51 dayNames: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], // For formatting 52 dayNamesShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], // For formatting 53 dayNamesMin: ["Su","Mo","Tu","We","Th","Fr","Sa"], // Column headings for days starting at Sunday 54 weekHeader: "Wk", // Column header for week of the year 55 dateFormat: "mm/dd/yy", // See format options on parseDate 56 firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ... 57 isRTL: false, // True if right-to-left language, false if left-to-right 58 showMonthAfterYear: false, // True if the year select precedes month, false for month then year 59 yearSuffix: "" // Additional text to append to the year in the month headers 60 }; 61 this._defaults = { // Global defaults for all the date picker instances 62 showOn: "focus", // "focus" for popup on focus, 63 // "button" for trigger button, or "both" for either 64 showAnim: "fadeIn", // Name of jQuery animation for popup 65 showOptions: {}, // Options for enhanced animations 66 defaultDate: null, // Used when field is blank: actual date, 67 // +/-number for offset from today, null for today 68 appendText: "", // Display text following the input box, e.g. showing the format 69 buttonText: "...", // Text for trigger button 70 buttonImage: "", // URL for trigger button image 71 buttonImageOnly: false, // True if the image appears alone, false if it appears on a button 72 hideIfNoPrevNext: false, // True to hide next/previous month links 73 // if not applicable, false to just disable them 74 navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links 75 gotoCurrent: false, // True if today link goes back to current selection instead 76 changeMonth: false, // True if month can be selected directly, false if only prev/next 77 changeYear: false, // True if year can be selected directly, false if only prev/next 78 yearRange: "c-10:c+10", // Range of years to display in drop-down, 79 // either relative to today's year (-nn:+nn), relative to currently displayed year 80 // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n) 81 showOtherMonths: false, // True to show dates in other months, false to leave blank 82 selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable 83 showWeek: false, // True to show week of the year, false to not show it 84 calculateWeek: this.iso8601Week, // How to calculate the week of the year, 85 // takes a Date and returns the number of the week for it 86 shortYearCutoff: "+10", // Short year values < this are in the current century, 87 // > this are in the previous century, 88 // string value starting with "+" for current year + value 89 minDate: null, // The earliest selectable date, or null for no limit 90 maxDate: null, // The latest selectable date, or null for no limit 91 duration: "fast", // Duration of display/closure 92 beforeShowDay: null, // Function that takes a date and returns an array with 93 // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or "", 94 // [2] = cell title (optional), e.g. $.datepicker.noWeekends 95 beforeShow: null, // Function that takes an input field and 96 // returns a set of custom settings for the date picker 97 onSelect: null, // Define a callback function when a date is selected 98 onChangeMonthYear: null, // Define a callback function when the month or year is changed 99 onClose: null, // Define a callback function when the datepicker is closed 100 numberOfMonths: 1, // Number of months to show at a time 101 showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0) 102 stepMonths: 1, // Number of months to step back/forward 103 stepBigMonths: 12, // Number of months to step back/forward for the big links 104 altField: "", // Selector for an alternate field to store selected dates into 105 altFormat: "", // The date format to use for the alternate field 106 constrainInput: true, // The input is constrained by the current date format 107 showButtonPanel: false, // True to show button panel, false to not show it 108 autoSize: false, // True to size the input for the date format, false to leave as is 109 disabled: false // The initial disabled state 110 }; 111 $.extend(this._defaults, this.regional[""]); 112 this.dpDiv = bindHover($("<div id='" + this._mainDivId + "' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>")); 113} 114 115$.extend(Datepicker.prototype, { 116 /* Class name added to elements to indicate already configured with a date picker. */ 117 markerClassName: "hasDatepicker", 118 119 //Keep track of the maximum number of rows displayed (see #7043) 120 maxRows: 4, 121 122 // TODO rename to "widget" when switching to widget factory 123 _widgetDatepicker: function() { 124 return this.dpDiv; 125 }, 126 127 /* Override the default settings for all instances of the date picker. 128 * @param settings object - the new settings to use as defaults (anonymous object) 129 * @return the manager object 130 */ 131 setDefaults: function(settings) { 132 extendRemove(this._defaults, settings || {}); 133 return this; 134 }, 135 136 /* Attach the date picker to a jQuery selection. 137 * @param target element - the target input field or division or span 138 * @param settings object - the new settings to use for this date picker instance (anonymous) 139 */ 140 _attachDatepicker: function(target, settings) { 141 var nodeName, inline, inst; 142 nodeName = target.nodeName.toLowerCase(); 143 inline = (nodeName === "div" || nodeName === "span"); 144 if (!target.id) { 145 this.uuid += 1; 146 target.id = "dp" + this.uuid; 147 } 148 inst = this._newInst($(target), inline); 149 inst.settings = $.extend({}, settings || {}); 150 if (nodeName === "input") { 151 this._connectDatepicker(target, inst); 152 } else if (inline) { 153 this._inlineDatepicker(target, inst); 154 } 155 }, 156 157 /* Create a new instance object. */ 158 _newInst: function(target, inline) { 159 var id = target[0].id.replace(/([^A-Za-z0-9_\-])/g, "\\\\$1"); // escape jQuery meta chars 160 return {id: id, input: target, // associated target 161 selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection 162 drawMonth: 0, drawYear: 0, // month being drawn 163 inline: inline, // is datepicker inline or not 164 dpDiv: (!inline ? this.dpDiv : // presentation div 165 bindHover($("<div class='" + this._inlineClass + " ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>")))}; 166 }, 167 168 /* Attach the date picker to an input field. */ 169 _connectDatepicker: function(target, inst) { 170 var input = $(target); 171 inst.append = $([]); 172 inst.trigger = $([]); 173 if (input.hasClass(this.markerClassName)) { 174 return; 175 } 176 this._attachments(input, inst); 177 input.addClass(this.markerClassName).keydown(this._doKeyDown). 178 keypress(this._doKeyPress).keyup(this._doKeyUp); 179 this._autoSize(inst); 180 $.data(target, PROP_NAME, inst); 181 //If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665) 182 if( inst.settings.disabled ) { 183 this._disableDatepicker( target ); 184 } 185 }, 186 187 /* Make attachments based on settings. */ 188 _attachments: function(input, inst) { 189 var showOn, buttonText, buttonImage, 190 appendText = this._get(inst, "appendText"), 191 isRTL = this._get(inst, "isRTL"); 192 193 if (inst.append) { 194 inst.append.remove(); 195 } 196 if (appendText) { 197 inst.append = $("<span class='" + this._appendClass + "'>" + appendText + "</span>"); 198 input[isRTL ? "before" : "after"](inst.append); 199 } 200 201 input.unbind("focus", this._showDatepicker); 202 203 if (inst.trigger) { 204 inst.trigger.remove(); 205 } 206 207 showOn = this._get(inst, "showOn"); 208 if (showOn === "focus" || showOn === "both") { // pop-up date picker when in the marked field 209 input.focus(this._showDatepicker); 210 } 211 if (showOn === "button" || showOn === "both") { // pop-up date picker when button clicked 212 buttonText = this._get(inst, "buttonText"); 213 buttonImage = this._get(inst, "buttonImage"); 214 inst.trigger = $(this._get(inst, "buttonImageOnly") ? 215 $("<img/>").addClass(this._triggerClass). 216 attr({ src: buttonImage, alt: buttonText, title: buttonText }) : 217 $("<button type='button'></button>").addClass(this._triggerClass). 218 html(!buttonImage ? buttonText : $("<img/>").attr( 219 { src:buttonImage, alt:buttonText, title:buttonText }))); 220 input[isRTL ? "before" : "after"](inst.trigger); 221 inst.trigger.click(function() { 222 if ($.datepicker._datepickerShowing && $.datepicker._lastInput === input[0]) { 223 $.datepicker._hideDatepicker(); 224 } else if ($.datepicker._datepickerShowing && $.datepicker._lastInput !== input[0]) { 225 $.datepicker._hideDatepicker(); 226 $.datepicker._showDatepicker(input[0]); 227 } else { 228 $.datepicker._showDatepicker(input[0]); 229 } 230 return false; 231 }); 232 } 233 }, 234 235 /* Apply the maximum length for the date format. */ 236 _autoSize: function(inst) { 237 if (this._get(inst, "autoSize") && !inst.inline) { 238 var findMax, max, maxI, i, 239 date = new Date(2009, 12 - 1, 20), // Ensure double digits 240 dateFormat = this._get(inst, "dateFormat"); 241 242 if (dateFormat.match(/[DM]/)) { 243 findMax = function(names) { 244 max = 0; 245 maxI = 0; 246 for (i = 0; i < names.length; i++) { 247 if (names[i].length > max) { 248 max = names[i].length; 249 maxI = i; 250 } 251 } 252 return maxI; 253 }; 254 date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ? 255 "monthNames" : "monthNamesShort")))); 256 date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ? 257 "dayNames" : "dayNamesShort"))) + 20 - date.getDay()); 258 } 259 inst.input.attr("size", this._formatDate(inst, date).length); 260 } 261 }, 262 263 /* Attach an inline date picker to a div. */ 264 _inlineDatepicker: function(target, inst) { 265 var divSpan = $(target); 266 if (divSpan.hasClass(this.markerClassName)) { 267 return; 268 } 269 divSpan.addClass(this.markerClassName).append(inst.dpDiv); 270 $.data(target, PROP_NAME, inst); 271 this._setDate(inst, this._getDefaultDate(inst), true); 272 this._updateDatepicker(inst); 273 this._updateAlternate(inst); 274 //If disabled option is true, disable the datepicker before showing it (see ticket #5665) 275 if( inst.settings.disabled ) { 276 this._disableDatepicker( target ); 277 } 278 // Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements 279 // http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height 280 inst.dpDiv.css( "display", "block" ); 281 }, 282 283 /* Pop-up the date picker in a "dialog" box. 284 * @param input element - ignored 285 * @param date string or Date - the initial date to display 286 * @param onSelect function - the function to call when a date is selected 287 * @param settings object - update the dialog date picker instance's settings (anonymous object) 288 * @param pos int[2] - coordinates for the dialog's position within the screen or 289 * event - with x/y coordinates or 290 * leave empty for default (screen centre) 291 * @return the manager object 292 */ 293 _dialogDatepicker: function(input, date, onSelect, settings, pos) { 294 var id, browserWidth, browserHeight, scrollX, scrollY, 295 inst = this._dialogInst; // internal instance 296 297 if (!inst) { 298 this.uuid += 1; 299 id = "dp" + this.uuid; 300 this._dialogInput = $("<input type='text' id='" + id + 301 "' style='position: absolute; top: -100px; width: 0px;'/>"); 302 this._dialogInput.keydown(this._doKeyDown); 303 $("body").append(this._dialogInput); 304 inst = this._dialogInst = this._newInst(this._dialogInput, false); 305 inst.settings = {}; 306 $.data(this._dialogInput[0], PROP_NAME, inst); 307 } 308 extendRemove(inst.settings, settings || {}); 309 date = (date && date.constructor === Date ? this._formatDate(inst, date) : date); 310 this._dialogInput.val(date); 311 312 this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null); 313 if (!this._pos) { 314 browserWidth = document.documentElement.clientWidth; 315 browserHeight = document.documentElement.clientHeight; 316 scrollX = document.documentElement.scrollLeft || document.body.scrollLeft; 317 scrollY = document.documentElement.scrollTop || document.body.scrollTop; 318 this._pos = // should use actual width/height below 319 [(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY]; 320 } 321 322 // move input on screen for focus, but hidden behind dialog 323 this._dialogInput.css("left", (this._pos[0] + 20) + "px").css("top", this._pos[1] + "px"); 324 inst.settings.onSelect = onSelect; 325 this._inDialog = true; 326 this.dpDiv.addClass(this._dialogClass); 327 this._showDatepicker(this._dialogInput[0]); 328 if ($.blockUI) { 329 $.blockUI(this.dpDiv); 330 } 331 $.data(this._dialogInput[0], PROP_NAME, inst); 332 return this; 333 }, 334 335 /* Detach a datepicker from its control. 336 * @param target element - the target input field or division or span 337 */ 338 _destroyDatepicker: function(target) { 339 var nodeName, 340 $target = $(target), 341 inst = $.data(target, PROP_NAME); 342 343 if (!$target.hasClass(this.markerClassName)) { 344 return; 345 } 346 347 nodeName = target.nodeName.toLowerCase(); 348 $.removeData(target, PROP_NAME); 349 if (nodeName === "input") { 350 inst.append.remove(); 351 inst.trigger.remove(); 352 $target.removeClass(this.markerClassName). 353 unbind("focus", this._showDatepicker). 354 unbind("keydown", this._doKeyDown). 355 unbind("keypress", this._doKeyPress). 356 unbind("keyup", this._doKeyUp); 357 } else if (nodeName === "div" || nodeName === "span") { 358 $target.removeClass(this.markerClassName).empty(); 359 } 360 }, 361 362 /* Enable the date picker to a jQuery selection. 363 * @param target element - the target input field or division or span 364 */ 365 _enableDatepicker: function(target) { 366 var nodeName, inline, 367 $target = $(target), 368 inst = $.data(target, PROP_NAME); 369 370 if (!$target.hasClass(this.markerClassName)) { 371 return; 372 } 373 374 nodeName = target.nodeName.toLowerCase(); 375 if (nodeName === "input") { 376 target.disabled = false; 377 inst.trigger.filter("button"). 378 each(function() { this.disabled = false; }).end(). 379 filter("img").css({opacity: "1.0", cursor: ""}); 380 } else if (nodeName === "div" || nodeName === "span") { 381 inline = $target.children("." + this._inlineClass); 382 inline.children().removeClass("ui-state-disabled"); 383 inline.find("select.ui-datepicker-month, select.ui-datepicker-year"). 384 prop("disabled", false); 385 } 386 this._disabledInputs = $.map(this._disabledInputs, 387 function(value) { return (value === target ? null : value); }); // delete entry 388 }, 389 390 /* Disable the date picker to a jQuery selection. 391 * @param target element - the target input field or division or span 392 */ 393 _disableDatepicker: function(target) { 394 var nodeName, inline, 395 $target = $(target), 396 inst = $.data(target, PROP_NAME); 397 398 if (!$target.hasClass(this.markerClassName)) { 399 return; 400 } 401 402 nodeName = target.nodeName.toLowerCase(); 403 if (nodeName === "input") { 404 target.disabled = true; 405 inst.trigger.filter("button"). 406 each(function() { this.disabled = true; }).end(). 407 filter("img").css({opacity: "0.5", cursor: "default"}); 408 } else if (nodeName === "div" || nodeName === "span") { 409 inline = $target.children("." + this._inlineClass); 410 inline.children().addClass("ui-state-disabled"); 411 inline.find("select.ui-datepicker-month, select.ui-datepicker-year"). 412 prop("disabled", true); 413 } 414 this._disabledInputs = $.map(this._disabledInputs, 415 function(value) { return (value === target ? null : value); }); // delete entry 416 this._disabledInputs[this._disabledInputs.length] = target; 417 }, 418 419 /* Is the first field in a jQuery collection disabled as a datepicker? 420 * @param target element - the target input field or division or span 421 * @return boolean - true if disabled, false if enabled 422 */ 423 _isDisabledDatepicker: function(target) { 424 if (!target) { 425 return false; 426 } 427 for (var i = 0; i < this._disabledInputs.length; i++) { 428 if (this._disabledInputs[i] === target) { 429 return true; 430 } 431 } 432 return false; 433 }, 434 435 /* Retrieve the instance data for the target control. 436 * @param target element - the target input field or division or span 437 * @return object - the associated instance data 438 * @throws error if a jQuery problem getting data 439 */ 440 _getInst: function(target) { 441 try { 442 return $.data(target, PROP_NAME); 443 } 444 catch (err) { 445 throw "Missing instance data for this datepicker"; 446 } 447 }, 448 449 /* Update or retrieve the settings for a date picker attached to an input field or division. 450 * @param target element - the target input field or division or span 451 * @param name object - the new settings to update or 452 * string - the name of the setting to change or retrieve, 453 * when retrieving also "all" for all instance settings or 454 * "defaults" for all global defaults 455 * @param value any - the new value for the setting 456 * (omit if above is an object or to retrieve a value) 457 */ 458 _optionDatepicker: function(target, name, value) { 459 var settings, date, minDate, maxDate, 460 inst = this._getInst(target); 461 462 if (arguments.length === 2 && typeof name === "string") { 463 return (name === "defaults" ? $.extend({}, $.datepicker._defaults) : 464 (inst ? (name === "all" ? $.extend({}, inst.settings) : 465 this._get(inst, name)) : null)); 466 } 467 468 settings = name || {}; 469 if (typeof name === "string") { 470 settings = {}; 471 settings[name] = value; 472 } 473 474 if (inst) { 475 if (this._curInst === inst) { 476 this._hideDatepicker(); 477 } 478 479 date = this._getDateDatepicker(target, true); 480 minDate = this._getMinMaxDate(inst, "min"); 481 maxDate = this._getMinMaxDate(inst, "max"); 482 extendRemove(inst.settings, settings); 483 // reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided 484 if (minDate !== null && settings.dateFormat !== undefined && settings.minDate === undefined) { 485 inst.settings.minDate = this._formatDate(inst, minDate); 486 } 487 if (maxDate !== null && settings.dateFormat !== undefined && settings.maxDate === undefined) { 488 inst.settings.maxDate = this._formatDate(inst, maxDate); 489 } 490 if ( "disabled" in settings ) { 491 if ( settings.disabled ) { 492 this._disableDatepicker(target); 493 } else { 494 this._enableDatepicker(target); 495 } 496 } 497 this._attachments($(target), inst); 498 this._autoSize(inst); 499 this._setDate(inst, date); 500 this._updateAlternate(inst); 501 this._updateDatepicker(inst); 502 } 503 }, 504 505 // change method deprecated 506 _changeDatepicker: function(target, name, value) { 507 this._optionDatepicker(target, name, value); 508 }, 509 510 /* Redraw the date picker attached to an input field or division. 511 * @param target element - the target input field or division or span 512 */ 513 _refreshDatepicker: function(target) { 514 var inst = this._getInst(target); 515 if (inst) { 516 this._updateDatepicker(inst); 517 } 518 }, 519 520 /* Set the dates for a jQuery selection. 521 * @param target element - the target input field or division or span 522 * @param date Date - the new date 523 */ 524 _setDateDatepicker: function(target, date) { 525 var inst = this._getInst(target); 526 if (inst) { 527 this._setDate(inst, date); 528 this._updateDatepicker(inst); 529 this._updateAlternate(inst); 530 } 531 }, 532 533 /* Get the date(s) for the first entry in a jQuery selection. 534 * @param target element - the target input field or division or span 535 * @param noDefault boolean - true if no default date is to be used 536 * @return Date - the current date 537 */ 538 _getDateDatepicker: function(target, noDefault) { 539 var inst = this._getInst(target); 540 if (inst && !inst.inline) { 541 this._setDateFromField(inst, noDefault); 542 } 543 return (inst ? this._getDate(inst) : null); 544 }, 545 546 /* Handle keystrokes. */ 547 _doKeyDown: function(event) { 548 var onSelect, dateStr, sel, 549 inst = $.datepicker._getInst(event.target), 550 handled = true, 551 isRTL = inst.dpDiv.is(".ui-datepicker-rtl"); 552 553 inst._keyEvent = true; 554 if ($.datepicker._datepickerShowing) { 555 switch (event.keyCode) { 556 case 9: $.datepicker._hideDatepicker(); 557 handled = false; 558 break; // hide on tab out 559 case 13: sel = $("td." + $.datepicker._dayOverClass + ":not(." + 560 $.datepicker._currentClass + ")", inst.dpDiv); 561 if (sel[0]) { 562 $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]); 563 } 564 565 onSelect = $.datepicker._get(inst, "onSelect"); 566 if (onSelect) { 567 dateStr = $.datepicker._formatDate(inst); 568 569 // trigger custom callback 570 onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); 571 } else { 572 $.datepicker._hideDatepicker(); 573 } 574 575 return false; // don't submit the form 576 case 27: $.datepicker._hideDatepicker(); 577 break; // hide on escape 578 case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ? 579 -$.datepicker._get(inst, "stepBigMonths") : 580 -$.datepicker._get(inst, "stepMonths")), "M"); 581 break; // previous month/year on page up/+ ctrl 582 case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ? 583 +$.datepicker._get(inst, "stepBigMonths") : 584 +$.datepicker._get(inst, "stepMonths")), "M"); 585 break; // next month/year on page down/+ ctrl 586 case 35: if (event.ctrlKey || event.metaKey) { 587 $.datepicker._clearDate(event.target); 588 } 589 handled = event.ctrlKey || event.metaKey; 590 break; // clear on ctrl or command +end 591 case 36: if (event.ctrlKey || event.metaKey) { 592 $.datepicker._gotoToday(event.target); 593 } 594 handled = event.ctrlKey || event.metaKey; 595 break; // current on ctrl or command +home 596 case 37: if (event.ctrlKey || event.metaKey) { 597 $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), "D"); 598 } 599 handled = event.ctrlKey || event.metaKey; 600 // -1 day on ctrl or command +left 601 if (event.originalEvent.altKey) { 602 $.datepicker._adjustDate(event.target, (event.ctrlKey ? 603 -$.datepicker._get(inst, "stepBigMonths") : 604 -$.datepicker._get(inst, "stepMonths")), "M"); 605 } 606 // next month/year on alt +left on Mac 607 break; 608 case 38: if (event.ctrlKey || event.metaKey) { 609 $.datepicker._adjustDate(event.target, -7, "D"); 610 } 611 handled = event.ctrlKey || event.metaKey; 612 break; // -1 week on ctrl or command +up 613 case 39: if (event.ctrlKey || event.metaKey) { 614 $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), "D"); 615 } 616 handled = event.ctrlKey || event.metaKey; 617 // +1 day on ctrl or command +right 618 if (event.originalEvent.altKey) { 619 $.datepicker._adjustDate(event.target, (event.ctrlKey ? 620 +$.datepicker._get(inst, "stepBigMonths") : 621 +$.datepicker._get(inst, "stepMonths")), "M"); 622 } 623 // next month/year on alt +right 624 break; 625 case 40: if (event.ctrlKey || event.metaKey) { 626 $.datepicker._adjustDate(event.target, +7, "D"); 627 } 628 handled = event.ctrlKey || event.metaKey; 629 break; // +1 week on ctrl or command +down 630 default: handled = false; 631 } 632 } else if (event.keyCode === 36 && event.ctrlKey) { // display the date picker on ctrl+home 633 $.datepicker._showDatepicker(this); 634 } else { 635 handled = false; 636 } 637 638 if (handled) { 639 event.preventDefault(); 640 event.stopPropagation(); 641 } 642 }, 643 644 /* Filter entered characters - based on date format. */ 645 _doKeyPress: function(event) { 646 var chars, chr, 647 inst = $.datepicker._getInst(event.target); 648 649 if ($.datepicker._get(inst, "constrainInput")) { 650 chars = $.datepicker._possibleChars($.datepicker._get(inst, "dateFormat")); 651 chr = String.fromCharCode(event.charCode == null ? event.keyCode : event.charCode); 652 return event.ctrlKey || event.metaKey || (chr < " " || !chars || chars.indexOf(chr) > -1); 653 } 654 }, 655 656 /* Synchronise manual entry and field/alternate field. */ 657 _doKeyUp: function(event) { 658 var date, 659 inst = $.datepicker._getInst(event.target); 660 661 if (inst.input.val() !== inst.lastVal) { 662 try { 663 date = $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"), 664 (inst.input ? inst.input.val() : null), 665 $.datepicker._getFormatConfig(inst)); 666 667 if (date) { // only if valid 668 $.datepicker._setDateFromField(inst); 669 $.datepicker._updateAlternate(inst); 670 $.datepicker._updateDatepicker(inst); 671 } 672 } 673 catch (err) { 674 } 675 } 676 return true; 677 }, 678 679 /* Pop-up the date picker for a given input field. 680 * If false returned from beforeShow event handler do not show. 681 * @param input element - the input field attached to the date picker or 682 * event - if triggered by focus 683 */ 684 _showDatepicker: function(input) { 685 input = input.target || input; 686 if (input.nodeName.toLowerCase() !== "input") { // find from button/image trigger 687 input = $("input", input.parentNode)[0]; 688 } 689 690 if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput === input) { // already here 691 return; 692 } 693 694 var inst, beforeShow, beforeShowSettings, isFixed, 695 offset, showAnim, duration; 696 697 inst = $.datepicker._getInst(input); 698 if ($.datepicker._curInst && $.datepicker._curInst !== inst) { 699 $.datepicker._curInst.dpDiv.stop(true, true); 700 if ( inst && $.datepicker._datepickerShowing ) { 701 $.datepicker._hideDatepicker( $.datepicker._curInst.input[0] ); 702 } 703 } 704 705 beforeShow = $.datepicker._get(inst, "beforeShow"); 706 beforeShowSettings = beforeShow ? beforeShow.apply(input, [input, inst]) : {}; 707 if(beforeShowSettings === false){ 708 return; 709 } 710 extendRemove(inst.settings, beforeShowSettings); 711 712 inst.lastVal = null; 713 $.datepicker._lastInput = input; 714 $.datepicker._setDateFromField(inst); 715 716 if ($.datepicker._inDialog) { // hide cursor 717 input.value = ""; 718 } 719 if (!$.datepicker._pos) { // position below input 720 $.datepicker._pos = $.datepicker._findPos(input); 721 $.datepicker._pos[1] += input.offsetHeight; // add the height 722 } 723 724 isFixed = false; 725 $(input).parents().each(function() { 726 isFixed |= $(this).css("position") === "fixed"; 727 return !isFixed; 728 }); 729 730 offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]}; 731 $.datepicker._pos = null; 732 //to avoid flashes on Firefox 733 inst.dpDiv.empty(); 734 // determine sizing offscreen 735 inst.dpDiv.css({position: "absolute", display: "block", top: "-1000px"}); 736 $.datepicker._updateDatepicker(inst); 737 // fix width for dynamic number of date pickers 738 // and adjust position before showing 739 offset = $.datepicker._checkOffset(inst, offset, isFixed); 740 inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ? 741 "static" : (isFixed ? "fixed" : "absolute")), display: "none", 742 left: offset.left + "px", top: offset.top + "px"}); 743 744 if (!inst.inline) { 745 showAnim = $.datepicker._get(inst, "showAnim"); 746 duration = $.datepicker._get(inst, "duration"); 747 inst.dpDiv.zIndex($(input).zIndex()+1); 748 $.datepicker._datepickerShowing = true; 749 750 if ( $.effects && $.effects.effect[ showAnim ] ) { 751 inst.dpDiv.show(showAnim, $.datepicker._get(inst, "showOptions"), duration); 752 } else { 753 inst.dpDiv[showAnim || "show"](showAnim ? duration : null); 754 } 755 756 if (
vendor: 1,611 bytes, lines 756-797
756inst.input.is(":visible") && !inst.input.is(":disabled")) { 757 inst.input.focus(); 758 } 759 $.datepicker._curInst = inst; 760 } 761 }, 762 763 /* Generate the date picker content. */ 764 _updateDatepicker: function(inst) { 765 this.maxRows = 4; //Reset the max number of rows being displayed (see #7043) 766 instActive = inst; // for delegate hover events 767 inst.dpDiv.empty().append(this._generateHTML(inst)); 768 this._attachHandlers(inst); 769 inst.dpDiv.find("." + this._dayOverClass + " a").mouseover(); 770 771 var origyearshtml, 772 numMonths = this._getNumberOfMonths(inst), 773 cols = numMonths[1], 774 width = 17; 775 776 inst.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width(""); 777 if (cols > 1) { 778 inst.dpDiv.addClass("ui-datepicker-multi-" + cols).css("width", (width * cols) + "em"); 779 } 780 inst.dpDiv[(numMonths[0] !== 1 || numMonths[1] !== 1 ? "add" : "remove") + 781 "Class"]("ui-datepicker-multi"); 782 inst.dpDiv[(this._get(inst, "isRTL") ? "add" : "remove") + 783 "Class"]("ui-datepicker-rtl"); 784 785 // #6694 - don't focus the input if it's already focused 786 // this breaks the change event in IE 787 if (inst === $.datepicker._curInst && $.datepicker._datepickerShowing && inst.input && 788 inst.input.is(":visible") && !inst.input.is(":disabled") && inst.input[0] !== document.activeElement) { 789 inst.input.focus(); 790 } 791 792 // deffered render of the years select (to avoid flashes on Firefox) 793 if( inst.yearshtml ){ 794 origyearshtml = inst.yearshtml; 795 setTimeout(function(){ 796 //assure that inst.yearshtml didn't change. 797 if( origyearshtml === inst.yearshtml && inst.yearshtml ){
798 inst.dpDiv.find("select.ui-datepicker-year:first").replaceWith(inst.yearshtml); 799 } 800 origyearshtml = inst.yearshtml = null; 801 }, 0); 802 } 803 }, 804 805 /* Retrieve the size of left and top borders for an element. 806 * @param elem (jQuery object) the element of interest 807 * @return (number[2]) the left and top borders 808 */ 809 _getBorders: function(elem) { 810 var convert = function(value) { 811 return {thin: 1, medium: 2, thick: 3}[value] || value; 812 }; 813 return [parseFloat(convert(elem.css("border-left-width"))), 814 parseFloat(convert(elem.css("border-top-width")))]
vendor: 23,574 bytes, lines 814-1561
814; 815 }, 816 817 /* Check positioning to remain on screen. */ 818 _checkOffset: function(inst, offset, isFixed) { 819 var dpWidth = inst.dpDiv.outerWidth(), 820 dpHeight = inst.dpDiv.outerHeight(), 821 inputWidth = inst.input ? inst.input.outerWidth() : 0, 822 inputHeight = inst.input ? inst.input.outerHeight() : 0, 823 viewWidth = document.documentElement.clientWidth + (isFixed ? 0 : $(document).scrollLeft()), 824 viewHeight = document.documentElement.clientHeight + (isFixed ? 0 : $(document).scrollTop()); 825 826 offset.left -= (this._get(inst, "isRTL") ? (dpWidth - inputWidth) : 0); 827 offset.left -= (isFixed && offset.left === inst.input.offset().left) ? $(document).scrollLeft() : 0; 828 offset.top -= (isFixed && offset.top === (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0; 829 830 // now check if datepicker is showing outside window viewport - move to a better place if so. 831 offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ? 832 Math.abs(offset.left + dpWidth - viewWidth) : 0); 833 offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ? 834 Math.abs(dpHeight + inputHeight) : 0); 835 836 return offset; 837 }, 838 839 /* Find an object's position on the screen. */ 840 _findPos: function(obj) { 841 var position, 842 inst = this._getInst(obj), 843 isRTL = this._get(inst, "isRTL"); 844 845 while (obj && (obj.type === "hidden" || obj.nodeType !== 1 || $.expr.filters.hidden(obj))) { 846 obj = obj[isRTL ? "previousSibling" : "nextSibling"]; 847 } 848 849 position = $(obj).offset(); 850 return [position.left, position.top]; 851 }, 852 853 /* Hide the date picker from view. 854 * @param input element - the input field attached to the date picker 855 */ 856 _hideDatepicker: function(input) { 857 var showAnim, duration, postProcess, onClose, 858 inst = this._curInst; 859 860 if (!inst || (input && inst !== $.data(input, PROP_NAME))) { 861 return; 862 } 863 864 if (this._datepickerShowing) { 865 showAnim = this._get(inst, "showAnim"); 866 duration = this._get(inst, "duration"); 867 postProcess = function() { 868 $.datepicker._tidyDialog(inst); 869 }; 870 871 // DEPRECATED: after BC for 1.8.x $.effects[ showAnim ] is not needed 872 if ( $.effects && ( $.effects.effect[ showAnim ] || $.effects[ showAnim ] ) ) { 873 inst.dpDiv.hide(showAnim, $.datepicker._get(inst, "showOptions"), duration, postProcess); 874 } else { 875 inst.dpDiv[(showAnim === "slideDown" ? "slideUp" : 876 (showAnim === "fadeIn" ? "fadeOut" : "hide"))]((showAnim ? duration : null), postProcess); 877 } 878 879 if (!showAnim) { 880 postProcess(); 881 } 882 this._datepickerShowing = false; 883 884 onClose = this._get(inst, "onClose"); 885 if (onClose) { 886 onClose.apply((inst.input ? inst.input[0] : null), [(inst.input ? inst.input.val() : ""), inst]); 887 } 888 889 this._lastInput = null; 890 if (this._inDialog) { 891 this._dialogInput.css({ position: "absolute", left: "0", top: "-100px" }); 892 if ($.blockUI) { 893 $.unblockUI(); 894 $("body").append(this.dpDiv); 895 } 896 } 897 this._inDialog = false; 898 } 899 }, 900 901 /* Tidy up after a dialog display. */ 902 _tidyDialog: function(inst) { 903 inst.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar"); 904 }, 905 906 /* Close date picker if clicked elsewhere. */ 907 _checkExternalClick: function(event) { 908 if (!$.datepicker._curInst) { 909 return; 910 } 911 912 var $target = $(event.target), 913 inst = $.datepicker._getInst($target[0]); 914 915 if ( ( ( $target[0].id !== $.datepicker._mainDivId && 916 $target.parents("#" + $.datepicker._mainDivId).length === 0 && 917 !$target.hasClass($.datepicker.markerClassName) && 918 !$target.closest("." + $.datepicker._triggerClass).length && 919 $.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI) ) ) || 920 ( $target.hasClass($.datepicker.markerClassName) && $.datepicker._curInst !== inst ) ) { 921 $.datepicker._hideDatepicker(); 922 } 923 }, 924 925 /* Adjust one of the date sub-fields. */ 926 _adjustDate: function(id, offset, period) { 927 var target = $(id), 928 inst = this._getInst(target[0]); 929 930 if (this._isDisabledDatepicker(target[0])) { 931 return; 932 } 933 this._adjustInstDate(inst, offset + 934 (period === "M" ? this._get(inst, "showCurrentAtPos") : 0), // undo positioning 935 period); 936 this._updateDatepicker(inst); 937 }, 938 939 /* Action for current link. */ 940 _gotoToday: function(id) { 941 var date, 942 target = $(id), 943 inst = this._getInst(target[0]); 944 945 if (this._get(inst, "gotoCurrent") && inst.currentDay) { 946 inst.selectedDay = inst.currentDay; 947 inst.drawMonth = inst.selectedMonth = inst.currentMonth; 948 inst.drawYear = inst.selectedYear = inst.currentYear; 949 } else { 950 date = new Date(); 951 inst.selectedDay = date.getDate(); 952 inst.drawMonth = inst.selectedMonth = date.getMonth(); 953 inst.drawYear = inst.selectedYear = date.getFullYear(); 954 } 955 this._notifyChange(inst); 956 this._adjustDate(target); 957 }, 958 959 /* Action for selecting a new month/year. */ 960 _selectMonthYear: function(id, select, period) { 961 var target = $(id), 962 inst = this._getInst(target[0]); 963 964 inst["selected" + (period === "M" ? "Month" : "Year")] = 965 inst["draw" + (period === "M" ? "Month" : "Year")] = 966 parseInt(select.options[select.selectedIndex].value,10); 967 968 this._notifyChange(inst); 969 this._adjustDate(target); 970 }, 971 972 /* Action for selecting a day. */ 973 _selectDay: function(id, month, year, td) { 974 var inst, 975 target = $(id); 976 977 if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) { 978 return; 979 } 980 981 inst = this._getInst(target[0]); 982 inst.selectedDay = inst.currentDay = $("a", td).html(); 983 inst.selectedMonth = inst.currentMonth = month; 984 inst.selectedYear = inst.currentYear = year; 985 this._selectDate(id, this._formatDate(inst, 986 inst.currentDay, inst.currentMonth, inst.currentYear)); 987 }, 988 989 /* Erase the input field and hide the date picker. */ 990 _clearDate: function(id) { 991 var target = $(id); 992 this._selectDate(target, ""); 993 }, 994 995 /* Update the input field with the selected date. */ 996 _selectDate: function(id, dateStr) { 997 var onSelect, 998 target = $(id), 999 inst = this._getInst(target[0]); 1000 1001 dateStr = (dateStr != null ? dateStr : this._formatDate(inst)); 1002 if (inst.input) { 1003 inst.input.val(dateStr); 1004 } 1005 this._updateAlternate(inst); 1006 1007 onSelect = this._get(inst, "onSelect"); 1008 if (onSelect) { 1009 onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); // trigger custom callback 1010 } else if (inst.input) { 1011 inst.input.trigger("change"); // fire the change event 1012 } 1013 1014 if (inst.inline){ 1015 this._updateDatepicker(inst); 1016 } else { 1017 this._hideDatepicker(); 1018 this._lastInput = inst.input[0]; 1019 if (typeof(inst.input[0]) !== "object") { 1020 inst.input.focus(); // restore focus 1021 } 1022 this._lastInput = null; 1023 } 1024 }, 1025 1026 /* Update any alternate field to synchronise with the main field. */ 1027 _updateAlternate: function(inst) { 1028 var altFormat, date, dateStr, 1029 altField = this._get(inst, "altField"); 1030 1031 if (altField) { // update alternate field too 1032 altFormat = this._get(inst, "altFormat") || this._get(inst, "dateFormat"); 1033 date = this._getDate(inst); 1034 dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst)); 1035 $(altField).each(function() { $(this).val(dateStr); }); 1036 } 1037 }, 1038 1039 /* Set as beforeShowDay function to prevent selection of weekends. 1040 * @param date Date - the date to customise 1041 * @return [boolean, string] - is this date selectable?, what is its CSS class? 1042 */ 1043 noWeekends: function(date) { 1044 var day = date.getDay(); 1045 return [(day > 0 && day < 6), ""]; 1046 }, 1047 1048 /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition. 1049 * @param date Date - the date to get the week for 1050 * @return number - the number of the week within the year that contains this date 1051 */ 1052 iso8601Week: function(date) { 1053 var time, 1054 checkDate = new Date(date.getTime()); 1055 1056 // Find Thursday of this week starting on Monday 1057 checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7)); 1058 1059 time = checkDate.getTime(); 1060 checkDate.setMonth(0); // Compare with Jan 1 1061 checkDate.setDate(1); 1062 return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1; 1063 }, 1064 1065 /* Parse a string value into a date object. 1066 * See formatDate below for the possible formats. 1067 * 1068 * @param format string - the expected format of the date 1069 * @param value string - the date in the above format 1070 * @param settings Object - attributes include: 1071 * shortYearCutoff number - the cutoff year for determining the century (optional) 1072 * dayNamesShort string[7] - abbreviated names of the days from Sunday (optional) 1073 * dayNames string[7] - names of the days from Sunday (optional) 1074 * monthNamesShort string[12] - abbreviated names of the months (optional) 1075 * monthNames string[12] - names of the months (optional) 1076 * @return Date - the extracted date value or null if value is blank 1077 */ 1078 parseDate: function (format, value, settings) { 1079 if (format == null || value == null) { 1080 throw "Invalid arguments"; 1081 } 1082 1083 value = (typeof value === "object" ? value.toString() : value + ""); 1084 if (value === "") { 1085 return null; 1086 } 1087 1088 var iFormat, dim, extra, 1089 iValue = 0, 1090 shortYearCutoffTemp = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff, 1091 shortYearCutoff = (typeof shortYearCutoffTemp !== "string" ? shortYearCutoffTemp : 1092 new Date().getFullYear() % 100 + parseInt(shortYearCutoffTemp, 10)), 1093 dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort, 1094 dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames, 1095 monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort, 1096 monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames, 1097 year = -1, 1098 month = -1, 1099 day = -1, 1100 doy = -1, 1101 literal = false, 1102 date, 1103 // Check whether a format character is doubled 1104 lookAhead = function(match) { 1105 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match); 1106 if (matches) { 1107 iFormat++; 1108 } 1109 return matches; 1110 }, 1111 // Extract a number from the string value 1112 getNumber = function(match) { 1113 var isDoubled = lookAhead(match), 1114 size = (match === "@" ? 14 : (match === "!" ? 20 : 1115 (match === "y" && isDoubled ? 4 : (match === "o" ? 3 : 2)))), 1116 digits = new RegExp("^\\d{1," + size + "}"), 1117 num = value.substring(iValue).match(digits); 1118 if (!num) { 1119 throw "Missing number at position " + iValue; 1120 } 1121 iValue += num[0].length; 1122 return parseInt(num[0], 10); 1123 }, 1124 // Extract a name from the string value and convert to an index 1125 getName = function(match, shortNames, longNames) { 1126 var index = -1, 1127 names = $.map(lookAhead(match) ? longNames : shortNames, function (v, k) { 1128 return [ [k, v] ]; 1129 }).sort(function (a, b) { 1130 return -(a[1].length - b[1].length); 1131 }); 1132 1133 $.each(names, function (i, pair) { 1134 var name = pair[1]; 1135 if (value.substr(iValue, name.length).toLowerCase() === name.toLowerCase()) { 1136 index = pair[0]; 1137 iValue += name.length; 1138 return false; 1139 } 1140 }); 1141 if (index !== -1) { 1142 return index + 1; 1143 } else { 1144 throw "Unknown name at position " + iValue; 1145 } 1146 }, 1147 // Confirm that a literal character matches the string value 1148 checkLiteral = function() { 1149 if (value.charAt(iValue) !== format.charAt(iFormat)) { 1150 throw "Unexpected literal at position " + iValue; 1151 } 1152 iValue++; 1153 }; 1154 1155 for (iFormat = 0; iFormat < format.length; iFormat++) { 1156 if (literal) { 1157 if (format.charAt(iFormat) === "'" && !lookAhead("'")) { 1158 literal = false; 1159 } else { 1160 checkLiteral(); 1161 } 1162 } else { 1163 switch (format.charAt(iFormat)) { 1164 case "d": 1165 day = getNumber("d"); 1166 break; 1167 case "D": 1168 getName("D", dayNamesShort, dayNames); 1169 break; 1170 case "o": 1171 doy = getNumber("o"); 1172 break; 1173 case "m": 1174 month = getNumber("m"); 1175 break; 1176 case "M": 1177 month = getName("M", monthNamesShort, monthNames); 1178 break; 1179 case "y": 1180 year = getNumber("y"); 1181 break; 1182 case "@": 1183 date = new Date(getNumber("@")); 1184 year = date.getFullYear(); 1185 month = date.getMonth() + 1; 1186 day = date.getDate(); 1187 break; 1188 case "!": 1189 date = new Date((getNumber("!") - this._ticksTo1970) / 10000); 1190 year = date.getFullYear(); 1191 month = date.getMonth() + 1; 1192 day = date.getDate(); 1193 break; 1194 case "'": 1195 if (lookAhead("'")){ 1196 checkLiteral(); 1197 } else { 1198 literal = true; 1199 } 1200 break; 1201 default: 1202 checkLiteral(); 1203 } 1204 } 1205 } 1206 1207 if (iValue < value.length){ 1208 extra = value.substr(iValue); 1209 if (!/^\s+/.test(extra)) { 1210 throw "Extra/unparsed characters found in date: " + extra; 1211 } 1212 } 1213 1214 if (year === -1) { 1215 year = new Date().getFullYear(); 1216 } else if (year < 100) { 1217 year += new Date().getFullYear() - new Date().getFullYear() % 100 + 1218 (year <= shortYearCutoff ? 0 : -100); 1219 } 1220 1221 if (doy > -1) { 1222 month = 1; 1223 day = doy; 1224 do { 1225 dim = this._getDaysInMonth(year, month - 1); 1226 if (day <= dim) { 1227 break; 1228 } 1229 month++; 1230 day -= dim; 1231 } while (true); 1232 } 1233 1234 date = this._daylightSavingAdjust(new Date(year, month - 1, day)); 1235 if (date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day) { 1236 throw "Invalid date"; // E.g. 31/02/00 1237 } 1238 return date; 1239 }, 1240 1241 /* Standard date formats. */ 1242 ATOM: "yy-mm-dd", // RFC 3339 (ISO 8601) 1243 COOKIE: "D, dd M yy", 1244 ISO_8601: "yy-mm-dd", 1245 RFC_822: "D, d M y", 1246 RFC_850: "DD, dd-M-y", 1247 RFC_1036: "D, d M y", 1248 RFC_1123: "D, d M yy", 1249 RFC_2822: "D, d M yy", 1250 RSS: "D, d M y", // RFC 822 1251 TICKS: "!", 1252 TIMESTAMP: "@", 1253 W3C: "yy-mm-dd", // ISO 8601 1254 1255 _ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) + 1256 Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000), 1257 1258 /* Format a date object into a string value. 1259 * The format can be combinations of the following: 1260 * d - day of month (no leading zero) 1261 * dd - day of month (two digit) 1262 * o - day of year (no leading zeros) 1263 * oo - day of year (three digit) 1264 * D - day name short 1265 * DD - day name long 1266 * m - month of year (no leading zero) 1267 * mm - month of year (two digit) 1268 * M - month name short 1269 * MM - month name long 1270 * y - year (two digit) 1271 * yy - year (four digit) 1272 * @ - Unix timestamp (ms since 01/01/1970) 1273 * ! - Windows ticks (100ns since 01/01/0001) 1274 * "..." - literal text 1275 * '' - single quote 1276 * 1277 * @param format string - the desired format of the date 1278 * @param date Date - the date value to format 1279 * @param settings Object - attributes include: 1280 * dayNamesShort string[7] - abbreviated names of the days from Sunday (optional) 1281 * dayNames string[7] - names of the days from Sunday (optional) 1282 * monthNamesShort string[12] - abbreviated names of the months (optional) 1283 * monthNames string[12] - names of the months (optional) 1284 * @return string - the date in the above format 1285 */ 1286 formatDate: function (format, date, settings) { 1287 if (!date) { 1288 return ""; 1289 } 1290 1291 var iFormat, 1292 dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort, 1293 dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames, 1294 monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort, 1295 monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames, 1296 // Check whether a format character is doubled 1297 lookAhead = function(match) { 1298 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match); 1299 if (matches) { 1300 iFormat++; 1301 } 1302 return matches; 1303 }, 1304 // Format a number, with leading zero if necessary 1305 formatNumber = function(match, value, len) { 1306 var num = "" + value; 1307 if (lookAhead(match)) { 1308 while (num.length < len) { 1309 num = "0" + num; 1310 } 1311 } 1312 return num; 1313 }, 1314 // Format a name, short or long as requested 1315 formatName = function(match, value, shortNames, longNames) { 1316 return (lookAhead(match) ? longNames[value] : shortNames[value]); 1317 }, 1318 output = "", 1319 literal = false; 1320 1321 if (date) { 1322 for (iFormat = 0; iFormat < format.length; iFormat++) { 1323 if (literal) { 1324 if (format.charAt(iFormat) === "'" && !lookAhead("'")) { 1325 literal = false; 1326 } else { 1327 output += format.charAt(iFormat); 1328 } 1329 } else { 1330 switch (format.charAt(iFormat)) { 1331 case "d": 1332 output += formatNumber("d", date.getDate(), 2); 1333 break; 1334 case "D": 1335 output += formatName("D", date.getDay(), dayNamesShort, dayNames); 1336 break; 1337 case "o": 1338 output += formatNumber("o", 1339 Math.round((new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000), 3); 1340 break; 1341 case "m": 1342 output += formatNumber("m", date.getMonth() + 1, 2); 1343 break; 1344 case "M": 1345 output += formatName("M", date.getMonth(), monthNamesShort, monthNames); 1346 break; 1347 case "y": 1348 output += (lookAhead("y") ? date.getFullYear() : 1349 (date.getYear() % 100 < 10 ? "0" : "") + date.getYear() % 100); 1350 break; 1351 case "@": 1352 output += date.getTime(); 1353 break; 1354 case "!": 1355 output += date.getTime() * 10000 + this._ticksTo1970; 1356 break; 1357 case "'": 1358 if (lookAhead("'")) { 1359 output += "'"; 1360 } else { 1361 literal = true; 1362 } 1363 break; 1364 default: 1365 output += format.charAt(iFormat); 1366 } 1367 } 1368 } 1369 } 1370 return output; 1371 }, 1372 1373 /* Extract all possible characters from the date format. */ 1374 _possibleChars: function (format) { 1375 var iFormat, 1376 chars = "", 1377 literal = false, 1378 // Check whether a format character is doubled 1379 lookAhead = function(match) { 1380 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match); 1381 if (matches) { 1382 iFormat++; 1383 } 1384 return matches; 1385 }; 1386 1387 for (iFormat = 0; iFormat < format.length; iFormat++) { 1388 if (literal) { 1389 if (format.charAt(iFormat) === "'" && !lookAhead("'")) { 1390 literal = false; 1391 } else { 1392 chars += format.charAt(iFormat); 1393 } 1394 } else { 1395 switch (format.charAt(iFormat)) { 1396 case "d": case "m": case "y": case "@": 1397 chars += "0123456789"; 1398 break; 1399 case "D": case "M": 1400 return null; // Accept anything 1401 case "'": 1402 if (lookAhead("'")) { 1403 chars += "'"; 1404 } else { 1405 literal = true; 1406 } 1407 break; 1408 default: 1409 chars += format.charAt(iFormat); 1410 } 1411 } 1412 } 1413 return chars; 1414 }, 1415 1416 /* Get a setting value, defaulting if necessary. */ 1417 _get: function(inst, name) { 1418 return inst.settings[name] !== undefined ? 1419 inst.settings[name] : this._defaults[name]; 1420 }, 1421 1422 /* Parse existing date and initialise date picker. */ 1423 _setDateFromField: function(inst, noDefault) { 1424 if (inst.input.val() === inst.lastVal) { 1425 return; 1426 } 1427 1428 var dateFormat = this._get(inst, "dateFormat"), 1429 dates = inst.lastVal = inst.input ? inst.input.val() : null, 1430 defaultDate = this._getDefaultDate(inst), 1431 date = defaultDate, 1432 settings = this._getFormatConfig(inst); 1433 1434 try { 1435 date = this.parseDate(dateFormat, dates, settings) || defaultDate; 1436 } catch (event) { 1437 dates = (noDefault ? "" : dates); 1438 } 1439 inst.selectedDay = date.getDate(); 1440 inst.drawMonth = inst.selectedMonth = date.getMonth(); 1441 inst.drawYear = inst.selectedYear = date.getFullYear(); 1442 inst.currentDay = (dates ? date.getDate() : 0); 1443 inst.currentMonth = (dates ? date.getMonth() : 0); 1444 inst.currentYear = (dates ? date.getFullYear() : 0); 1445 this._adjustInstDate(inst); 1446 }, 1447 1448 /* Retrieve the default date shown on opening. */ 1449 _getDefaultDate: function(inst) { 1450 return this._restrictMinMax(inst, 1451 this._determineDate(inst, this._get(inst, "defaultDate"), new Date())); 1452 }, 1453 1454 /* A date may be specified as an exact value or a relative one. */ 1455 _determineDate: function(inst, date, defaultDate) { 1456 var offsetNumeric = function(offset) { 1457 var date = new Date(); 1458 date.setDate(date.getDate() + offset); 1459 return date; 1460 }, 1461 offsetString = function(offset) { 1462 try { 1463 return $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"), 1464 offset, $.datepicker._getFormatConfig(inst)); 1465 } 1466 catch (e) { 1467 // Ignore 1468 } 1469 1470 var date = (offset.toLowerCase().match(/^c/) ? 1471 $.datepicker._getDate(inst) : null) || new Date(), 1472 year = date.getFullYear(), 1473 month = date.getMonth(), 1474 day = date.getDate(), 1475 pattern = /([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g, 1476 matches = pattern.exec(offset); 1477 1478 while (matches) { 1479 switch (matches[2] || "d") { 1480 case "d" : case "D" : 1481 day += parseInt(matches[1],10); break; 1482 case "w" : case "W" : 1483 day += parseInt(matches[1],10) * 7; break; 1484 case "m" : case "M" : 1485 month += parseInt(matches[1],10); 1486 day = Math.min(day, $.datepicker._getDaysInMonth(year, month)); 1487 break; 1488 case "y": case "Y" : 1489 year += parseInt(matches[1],10); 1490 day = Math.min(day, $.datepicker._getDaysInMonth(year, month)); 1491 break; 1492 } 1493 matches = pattern.exec(offset); 1494 } 1495 return new Date(year, month, day); 1496 }, 1497 newDate = (date == null || date === "" ? defaultDate : (typeof date === "string" ? offsetString(date) : 1498 (typeof date === "number" ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : new Date(date.getTime())))); 1499 1500 newDate = (newDate && newDate.toString() === "Invalid Date" ? defaultDate : newDate); 1501 if (newDate) { 1502 newDate.setHours(0); 1503 newDate.setMinutes(0); 1504 newDate.setSeconds(0); 1505 newDate.setMilliseconds(0); 1506 } 1507 return this._daylightSavingAdjust(newDate); 1508 }, 1509 1510 /* Handle switch to/from daylight saving. 1511 * Hours may be non-zero on daylight saving cut-over: 1512 * > 12 when midnight changeover, but then cannot generate 1513 * midnight datetime, so jump to 1AM, otherwise reset. 1514 * @param date (Date) the date to check 1515 * @return (Date) the corrected date 1516 */ 1517 _daylightSavingAdjust: function(date) { 1518 if (!date) { 1519 return null; 1520 } 1521 date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0); 1522 return date; 1523 }, 1524 1525 /* Set the date(s) directly. */ 1526 _setDate: function(inst, date, noChange) { 1527 var clear = !date, 1528 origMonth = inst.selectedMonth, 1529 origYear = inst.selectedYear, 1530 newDate = this._restrictMinMax(inst, this._determineDate(inst, date, new Date())); 1531 1532 inst.selectedDay = inst.currentDay = newDate.getDate(); 1533 inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth(); 1534 inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear(); 1535 if ((origMonth !== inst.selectedMonth || origYear !== inst.selectedYear) && !noChange) { 1536 this._notifyChange(inst); 1537 } 1538 this._adjustInstDate(inst); 1539 if (inst.input) { 1540 inst.input.val(clear ? "" : this._formatDate(inst)); 1541 } 1542 }, 1543 1544 /* Retrieve the date(s) directly. */ 1545 _getDate: function(inst) { 1546 var startDate = (!inst.currentYear || (inst.input && inst.input.val() === "") ? null : 1547 this._daylightSavingAdjust(new Date( 1548 inst.currentYear, inst.currentMonth, inst.currentDay))); 1549 return startDate; 1550 }, 1551 1552 /* Attach the onxxx handlers. These are declared statically so 1553 * they work with static code transformers like Caja. 1554 */ 1555 _attachHandlers: function(inst) { 1556 var stepMonths = this._get(inst, "stepMonths"), 1557 id = "#" + inst.id.replace( /\\\\/g, "\\" ); 1558 inst.dpDiv.find("[data-handler]").map(function () { 1559 var handler = { 1560 prev: function () { 1561
1561window["DP_jQuery_" + dpuuid].datepicker._adjustDate(id, -stepMonths, "M"); 1562 }, 1563 next: function () { 1564 window["DP_jQuery_" + dpuuid].datepicker._adjustDate(id, +stepMonths, "M"); 1565 }, 1566 hide: function () { 1567 window["DP_jQuery_" + dpuuid].datepicker._hideDatepicker(); 1568 }, 1569 today: function () { 1570 window["DP_jQuery_" + dpuuid].datepicker._gotoToday(id); 1571 }, 1572 selectDay: function () { 1573 window["DP_jQuery_" + dpuuid].datepicker._selectDay(id, +this.getAttribute("data-month"), +this.getAttribute("data-year"), this); 1574 return false; 1575 }, 1576 selectMonth: function () { 1577 window["DP_jQuery_" + dpuuid].datepicker._selectMonthYear(id, this, "M"); 1578 return false; 1579 }, 1580 selectYear: function () { 1581 window["DP_jQuery_" + dpuuid]
vendor: 20,874 bytes, lines 1581-2044
1581.datepicker._selectMonthYear(id, this, "Y"); 1582 return false; 1583 } 1584 }; 1585 $(this).bind(this.getAttribute("data-event"), handler[this.getAttribute("data-handler")]); 1586 }); 1587 }, 1588 1589 /* Generate the HTML for the current state of the date picker. */ 1590 _generateHTML: function(inst) { 1591 var maxDraw, prevText, prev, nextText, next, currentText, gotoDate, 1592 controls, buttonPanel, firstDay, showWeek, dayNames, dayNamesMin, 1593 monthNames, monthNamesShort, beforeShowDay, showOtherMonths, 1594 selectOtherMonths, defaultDate, html, dow, row, group, col, selectedDate, 1595 cornerClass, calender, thead, day, daysInMonth, leadDays, curRows, numRows, 1596 printDate, dRow, tbody, daySettings, otherMonth, unselectable, 1597 tempDate = new Date(), 1598 today = this._daylightSavingAdjust( 1599 new Date(tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate())), // clear time 1600 isRTL = this._get(inst, "isRTL"), 1601 showButtonPanel = this._get(inst, "showButtonPanel"), 1602 hideIfNoPrevNext = this._get(inst, "hideIfNoPrevNext"), 1603 navigationAsDateFormat = this._get(inst, "navigationAsDateFormat"), 1604 numMonths = this._getNumberOfMonths(inst), 1605 showCurrentAtPos = this._get(inst, "showCurrentAtPos"), 1606 stepMonths = this._get(inst, "stepMonths"), 1607 isMultiMonth = (numMonths[0] !== 1 || numMonths[1] !== 1), 1608 currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) : 1609 new Date(inst.currentYear, inst.currentMonth, inst.currentDay))), 1610 minDate = this._getMinMaxDate(inst, "min"), 1611 maxDate = this._getMinMaxDate(inst, "max"), 1612 drawMonth = inst.drawMonth - showCurrentAtPos, 1613 drawYear = inst.drawYear; 1614 1615 if (drawMonth < 0) { 1616 drawMonth += 12; 1617 drawYear--; 1618 } 1619 if (maxDate) { 1620 maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(), 1621 maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate())); 1622 maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw); 1623 while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) { 1624 drawMonth--; 1625 if (drawMonth < 0) { 1626 drawMonth = 11; 1627 drawYear--; 1628 } 1629 } 1630 } 1631 inst.drawMonth = drawMonth; 1632 inst.drawYear = drawYear; 1633 1634 prevText = this._get(inst, "prevText"); 1635 prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText, 1636 this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)), 1637 this._getFormatConfig(inst))); 1638 1639 prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ? 1640 "<a class='ui-datepicker-prev ui-corner-all' data-handler='prev' data-event='click'" + 1641 " title='" + prevText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "e" : "w") + "'>" + prevText + "</span></a>" : 1642 (hideIfNoPrevNext ? "" : "<a class='ui-datepicker-prev ui-corner-all ui-state-disabled' title='"+ prevText +"'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "e" : "w") + "'>" + prevText + "</span></a>")); 1643 1644 nextText = this._get(inst, "nextText"); 1645 nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText, 1646 this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)), 1647 this._getFormatConfig(inst))); 1648 1649 next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ? 1650 "<a class='ui-datepicker-next ui-corner-all' data-handler='next' data-event='click'" + 1651 " title='" + nextText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "w" : "e") + "'>" + nextText + "</span></a>" : 1652 (hideIfNoPrevNext ? "" : "<a class='ui-datepicker-next ui-corner-all ui-state-disabled' title='"+ nextText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "w" : "e") + "'>" + nextText + "</span></a>")); 1653 1654 currentText = this._get(inst, "currentText"); 1655 gotoDate = (this._get(inst, "gotoCurrent") && inst.currentDay ? currentDate : today); 1656 currentText = (!navigationAsDateFormat ? currentText : 1657 this.formatDate(currentText, gotoDate, this._getFormatConfig(inst))); 1658 1659 controls = (!inst.inline ? "<button type='button' class='ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all' data-handler='hide' data-event='click'>" + 1660 this._get(inst, "closeText") + "</button>" : ""); 1661 1662 buttonPanel = (showButtonPanel) ? "<div class='ui-datepicker-buttonpane ui-widget-content'>" + (isRTL ? controls : "") + 1663 (this._isInRange(inst, gotoDate) ? "<button type='button' class='ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all' data-handler='today' data-event='click'" + 1664 ">" + currentText + "</button>" : "") + (isRTL ? "" : controls) + "</div>" : ""; 1665 1666 firstDay = parseInt(this._get(inst, "firstDay"),10); 1667 firstDay = (isNaN(firstDay) ? 0 : firstDay); 1668 1669 showWeek = this._get(inst, "showWeek"); 1670 dayNames = this._get(inst, "dayNames"); 1671 dayNamesMin = this._get(inst, "dayNamesMin"); 1672 monthNames = this._get(inst, "monthNames"); 1673 monthNamesShort = this._get(inst, "monthNamesShort"); 1674 beforeShowDay = this._get(inst, "beforeShowDay"); 1675 showOtherMonths = this._get(inst, "showOtherMonths"); 1676 selectOtherMonths = this._get(inst, "selectOtherMonths"); 1677 defaultDate = this._getDefaultDate(inst); 1678 html = ""; 1679 dow; 1680 for (row = 0; row < numMonths[0]; row++) { 1681 group = ""; 1682 this.maxRows = 4; 1683 for (col = 0; col < numMonths[1]; col++) { 1684 selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay)); 1685 cornerClass = " ui-corner-all"; 1686 calender = ""; 1687 if (isMultiMonth) { 1688 calender += "<div class='ui-datepicker-group"; 1689 if (numMonths[1] > 1) { 1690 switch (col) { 1691 case 0: calender += " ui-datepicker-group-first"; 1692 cornerClass = " ui-corner-" + (isRTL ? "right" : "left"); break; 1693 case numMonths[1]-1: calender += " ui-datepicker-group-last"; 1694 cornerClass = " ui-corner-" + (isRTL ? "left" : "right"); break; 1695 default: calender += " ui-datepicker-group-middle"; cornerClass = ""; break; 1696 } 1697 } 1698 calender += "'>"; 1699 } 1700 calender += "<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix" + cornerClass + "'>" + 1701 (/all|left/.test(cornerClass) && row === 0 ? (isRTL ? next : prev) : "") + 1702 (/all|right/.test(cornerClass) && row === 0 ? (isRTL ? prev : next) : "") + 1703 this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate, 1704 row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers 1705 "</div><table class='ui-datepicker-calendar'><thead>" + 1706 "<tr>"; 1707 thead = (showWeek ? "<th class='ui-datepicker-week-col'>" + this._get(inst, "weekHeader") + "</th>" : ""); 1708 for (dow = 0; dow < 7; dow++) { // days of the week 1709 day = (dow + firstDay) % 7; 1710 thead += "<th" + ((dow + firstDay + 6) % 7 >= 5 ? " class='ui-datepicker-week-end'" : "") + ">" + 1711 "<span title='" + dayNames[day] + "'>" + dayNamesMin[day] + "</span></th>"; 1712 } 1713 calender += thead + "</tr></thead><tbody>"; 1714 daysInMonth = this._getDaysInMonth(drawYear, drawMonth); 1715 if (drawYear === inst.selectedYear && drawMonth === inst.selectedMonth) { 1716 inst.selectedDay = Math.min(inst.selectedDay, daysInMonth); 1717 } 1718 leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7; 1719 curRows = Math.ceil((leadDays + daysInMonth) / 7); // calculate the number of rows to generate 1720 numRows = (isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows); //If multiple months, use the higher number of rows (see #7043) 1721 this.maxRows = numRows; 1722 printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays)); 1723 for (dRow = 0; dRow < numRows; dRow++) { // create date picker rows 1724 calender += "<tr>"; 1725 tbody = (!showWeek ? "" : "<td class='ui-datepicker-week-col'>" + 1726 this._get(inst, "calculateWeek")(printDate) + "</td>"); 1727 for (dow = 0; dow < 7; dow++) { // create date picker days 1728 daySettings = (beforeShowDay ? 1729 beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, ""]); 1730 otherMonth = (printDate.getMonth() !== drawMonth); 1731 unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] || 1732 (minDate && printDate < minDate) || (maxDate && printDate > maxDate); 1733 tbody += "<td class='" + 1734 ((dow + firstDay + 6) % 7 >= 5 ? " ui-datepicker-week-end" : "") + // highlight weekends 1735 (otherMonth ? " ui-datepicker-other-month" : "") + // highlight days from other months 1736 ((printDate.getTime() === selectedDate.getTime() && drawMonth === inst.selectedMonth && inst._keyEvent) || // user pressed key 1737 (defaultDate.getTime() === printDate.getTime() && defaultDate.getTime() === selectedDate.getTime()) ? 1738 // or defaultDate is current printedDate and defaultDate is selectedDate 1739 " " + this._dayOverClass : "") + // highlight selected day 1740 (unselectable ? " " + this._unselectableClass + " ui-state-disabled": "") + // highlight unselectable days 1741 (otherMonth && !showOtherMonths ? "" : " " + daySettings[1] + // highlight custom dates 1742 (printDate.getTime() === currentDate.getTime() ? " " + this._currentClass : "") + // highlight selected day 1743 (printDate.getTime() === today.getTime() ? " ui-datepicker-today" : "")) + "'" + // highlight today (if different) 1744 ((!otherMonth || showOtherMonths) && daySettings[2] ? " title='" + daySettings[2].replace(/'/g, "'") + "'" : "") + // cell title 1745 (unselectable ? "" : " data-handler='selectDay' data-event='click' data-month='" + printDate.getMonth() + "' data-year='" + printDate.getFullYear() + "'") + ">" + // actions 1746 (otherMonth && !showOtherMonths ? " " : // display for other months 1747 (unselectable ? "<span class='ui-state-default'>" + printDate.getDate() + "</span>" : "<a class='ui-state-default" + 1748 (printDate.getTime() === today.getTime() ? " ui-state-highlight" : "") + 1749 (printDate.getTime() === currentDate.getTime() ? " ui-state-active" : "") + // highlight selected day 1750 (otherMonth ? " ui-priority-secondary" : "") + // distinguish dates from other months 1751 "' href='#'>" + printDate.getDate() + "</a>")) + "</td>"; // display selectable date 1752 printDate.setDate(printDate.getDate() + 1); 1753 printDate = this._daylightSavingAdjust(printDate); 1754 } 1755 calender += tbody + "</tr>"; 1756 } 1757 drawMonth++; 1758 if (drawMonth > 11) { 1759 drawMonth = 0; 1760 drawYear++; 1761 } 1762 calender += "</tbody></table>" + (isMultiMonth ? "</div>" + 1763 ((numMonths[0] > 0 && col === numMonths[1]-1) ? "<div class='ui-datepicker-row-break'></div>" : "") : ""); 1764 group += calender; 1765 } 1766 html += group; 1767 } 1768 html += buttonPanel; 1769 inst._keyEvent = false; 1770 return html; 1771 }, 1772 1773 /* Generate the month and year header. */ 1774 _generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate, 1775 secondary, monthNames, monthNamesShort) { 1776 1777 var inMinYear, inMaxYear, month, years, thisYear, determineYear, year, endYear, 1778 changeMonth = this._get(inst, "changeMonth"), 1779 changeYear = this._get(inst, "changeYear"), 1780 showMonthAfterYear = this._get(inst, "showMonthAfterYear"), 1781 html = "<div class='ui-datepicker-title'>", 1782 monthHtml = ""; 1783 1784 // month selection 1785 if (secondary || !changeMonth) { 1786 monthHtml += "<span class='ui-datepicker-month'>" + monthNames[drawMonth] + "</span>"; 1787 } else { 1788 inMinYear = (minDate && minDate.getFullYear() === drawYear); 1789 inMaxYear = (maxDate && maxDate.getFullYear() === drawYear); 1790 monthHtml += "<select class='ui-datepicker-month' data-handler='selectMonth' data-event='change'>"; 1791 for ( month = 0; month < 12; month++) { 1792 if ((!inMinYear || month >= minDate.getMonth()) && (!inMaxYear || month <= maxDate.getMonth())) { 1793 monthHtml += "<option value='" + month + "'" + 1794 (month === drawMonth ? " selected='selected'" : "") + 1795 ">" + monthNamesShort[month] + "</option>"; 1796 } 1797 } 1798 monthHtml += "</select>"; 1799 } 1800 1801 if (!showMonthAfterYear) { 1802 html += monthHtml + (secondary || !(changeMonth && changeYear) ? " " : ""); 1803 } 1804 1805 // year selection 1806 if ( !inst.yearshtml ) { 1807 inst.yearshtml = ""; 1808 if (secondary || !changeYear) { 1809 html += "<span class='ui-datepicker-year'>" + drawYear + "</span>"; 1810 } else { 1811 // determine range of years to display 1812 years = this._get(inst, "yearRange").split(":"); 1813 thisYear = new Date().getFullYear(); 1814 determineYear = function(value) { 1815 var year = (value.match(/c[+\-].*/) ? drawYear + parseInt(value.substring(1), 10) : 1816 (value.match(/[+\-].*/) ? thisYear + parseInt(value, 10) : 1817 parseInt(value, 10))); 1818 return (isNaN(year) ? thisYear : year); 1819 }; 1820 year = determineYear(years[0]); 1821 endYear = Math.max(year, determineYear(years[1] || "")); 1822 year = (minDate ? Math.max(year, minDate.getFullYear()) : year); 1823 endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear); 1824 inst.yearshtml += "<select class='ui-datepicker-year' data-handler='selectYear' data-event='change'>"; 1825 for (; year <= endYear; year++) { 1826 inst.yearshtml += "<option value='" + year + "'" + 1827 (year === drawYear ? " selected='selected'" : "") + 1828 ">" + year + "</option>"; 1829 } 1830 inst.yearshtml += "</select>"; 1831 1832 html += inst.yearshtml; 1833 inst.yearshtml = null; 1834 } 1835 } 1836 1837 html += this._get(inst, "yearSuffix"); 1838 if (showMonthAfterYear) { 1839 html += (secondary || !(changeMonth && changeYear) ? " " : "") + monthHtml; 1840 } 1841 html += "</div>"; // Close datepicker_header 1842 return html; 1843 }, 1844 1845 /* Adjust one of the date sub-fields. */ 1846 _adjustInstDate: function(inst, offset, period) { 1847 var year = inst.drawYear + (period === "Y" ? offset : 0), 1848 month = inst.drawMonth + (period === "M" ? offset : 0), 1849 day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) + (period === "D" ? offset : 0), 1850 date = this._restrictMinMax(inst, this._daylightSavingAdjust(new Date(year, month, day))); 1851 1852 inst.selectedDay = date.getDate(); 1853 inst.drawMonth = inst.selectedMonth = date.getMonth(); 1854 inst.drawYear = inst.selectedYear = date.getFullYear(); 1855 if (period === "M" || period === "Y") { 1856 this._notifyChange(inst); 1857 } 1858 }, 1859 1860 /* Ensure a date is within any min/max bounds. */ 1861 _restrictMinMax: function(inst, date) { 1862 var minDate = this._getMinMaxDate(inst, "min"), 1863 maxDate = this._getMinMaxDate(inst, "max"), 1864 newDate = (minDate && date < minDate ? minDate : date); 1865 return (maxDate && newDate > maxDate ? maxDate : newDate); 1866 }, 1867 1868 /* Notify change of month/year. */ 1869 _notifyChange: function(inst) { 1870 var onChange = this._get(inst, "onChangeMonthYear"); 1871 if (onChange) { 1872 onChange.apply((inst.input ? inst.input[0] : null), 1873 [inst.selectedYear, inst.selectedMonth + 1, inst]); 1874 } 1875 }, 1876 1877 /* Determine the number of months to show. */ 1878 _getNumberOfMonths: function(inst) { 1879 var numMonths = this._get(inst, "numberOfMonths"); 1880 return (numMonths == null ? [1, 1] : (typeof numMonths === "number" ? [1, numMonths] : numMonths)); 1881 }, 1882 1883 /* Determine the current maximum date - ensure no time components are set. */ 1884 _getMinMaxDate: function(inst, minMax) { 1885 return this._determineDate(inst, this._get(inst, minMax + "Date"), null); 1886 }, 1887 1888 /* Find the number of days in a given month. */ 1889 _getDaysInMonth: function(year, month) { 1890 return 32 - this._daylightSavingAdjust(new Date(year, month, 32)).getDate(); 1891 }, 1892 1893 /* Find the day of the week of the first of a month. */ 1894 _getFirstDayOfMonth: function(year, month) { 1895 return new Date(year, month, 1).getDay(); 1896 }, 1897 1898 /* Determines if we should allow a "next/prev" month display change. */ 1899 _canAdjustMonth: function(inst, offset, curYear, curMonth) { 1900 var numMonths = this._getNumberOfMonths(inst), 1901 date = this._daylightSavingAdjust(new Date(curYear, 1902 curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1)); 1903 1904 if (offset < 0) { 1905 date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth())); 1906 } 1907 return this._isInRange(inst, date); 1908 }, 1909 1910 /* Is the given date in the accepted range? */ 1911 _isInRange: function(inst, date) { 1912 var yearSplit, currentYear, 1913 minDate = this._getMinMaxDate(inst, "min"), 1914 maxDate = this._getMinMaxDate(inst, "max"), 1915 minYear = null, 1916 maxYear = null, 1917 years = this._get(inst, "yearRange"); 1918 if (years){ 1919 yearSplit = years.split(":"); 1920 currentYear = new Date().getFullYear(); 1921 minYear = parseInt(yearSplit[0], 10); 1922 maxYear = parseInt(yearSplit[1], 10); 1923 if ( yearSplit[0].match(/[+\-].*/) ) { 1924 minYear += currentYear; 1925 } 1926 if ( yearSplit[1].match(/[+\-].*/) ) { 1927 maxYear += currentYear; 1928 } 1929 } 1930 1931 return ((!minDate || date.getTime() >= minDate.getTime()) && 1932 (!maxDate || date.getTime() <= maxDate.getTime()) && 1933 (!minYear || date.getFullYear() >= minYear) && 1934 (!maxYear || date.getFullYear() <= maxYear)); 1935 }, 1936 1937 /* Provide the configuration settings for formatting/parsing. */ 1938 _getFormatConfig: function(inst) { 1939 var shortYearCutoff = this._get(inst, "shortYearCutoff"); 1940 shortYearCutoff = (typeof shortYearCutoff !== "string" ? shortYearCutoff : 1941 new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10)); 1942 return {shortYearCutoff: shortYearCutoff, 1943 dayNamesShort: this._get(inst, "dayNamesShort"), dayNames: this._get(inst, "dayNames"), 1944 monthNamesShort: this._get(inst, "monthNamesShort"), monthNames: this._get(inst, "monthNames")}; 1945 }, 1946 1947 /* Format the given date for display. */ 1948 _formatDate: function(inst, day, month, year) { 1949 if (!day) { 1950 inst.currentDay = inst.selectedDay; 1951 inst.currentMonth = inst.selectedMonth; 1952 inst.currentYear = inst.selectedYear; 1953 } 1954 var date = (day ? (typeof day === "object" ? day : 1955 this._daylightSavingAdjust(new Date(year, month, day))) : 1956 this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay))); 1957 return this.formatDate(this._get(inst, "dateFormat"), date, this._getFormatConfig(inst)); 1958 } 1959}); 1960 1961/* 1962 * Bind hover events for datepicker elements. 1963 * Done via delegate so the binding only occurs once in the lifetime of the parent div. 1964 * Global instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker. 1965 */ 1966function bindHover(dpDiv) { 1967 var selector = "button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a"; 1968 return dpDiv.delegate(selector, "mouseout", function() { 1969 $(this).removeClass("ui-state-hover"); 1970 if (this.className.indexOf("ui-datepicker-prev") !== -1) { 1971 $(this).removeClass("ui-datepicker-prev-hover"); 1972 } 1973 if (this.className.indexOf("ui-datepicker-next") !== -1) { 1974 $(this).removeClass("ui-datepicker-next-hover"); 1975 } 1976 }) 1977 .delegate(selector, "mouseover", function(){ 1978 if (!$.datepicker._isDisabledDatepicker( instActive.inline ? dpDiv.parent()[0] : instActive.input[0])) { 1979 $(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover"); 1980 $(this).addClass("ui-state-hover"); 1981 if (this.className.indexOf("ui-datepicker-prev") !== -1) { 1982 $(this).addClass("ui-datepicker-prev-hover"); 1983 } 1984 if (this.className.indexOf("ui-datepicker-next") !== -1) { 1985 $(this).addClass("ui-datepicker-next-hover"); 1986 } 1987 } 1988 }); 1989} 1990 1991/* jQuery extend now ignores nulls! */ 1992function extendRemove(target, props) { 1993 $.extend(target, props); 1994 for (var name in props) { 1995 if (props[name] == null) { 1996 target[name] = props[name]; 1997 } 1998 } 1999 return target; 2000} 2001 2002/* Invoke the datepicker functionality. 2003 @param options string - a command, optionally followed by additional parameters or 2004 Object - settings for attaching new datepicker functionality 2005 @return jQuery object */ 2006$.fn.datepicker = function(options){ 2007 2008 /* Verify an empty collection wasn't passed - Fixes #6976 */ 2009 if ( !this.length ) { 2010 return this; 2011 } 2012 2013 /* Initialise the date picker. */ 2014 if (!$.datepicker.initialized) { 2015 $(document).mousedown($.datepicker._checkExternalClick); 2016 $.datepicker.initialized = true; 2017 } 2018 2019 /* Append datepicker main container to body if not exist. */ 2020 if ($("#"+$.datepicker._mainDivId).length === 0) { 2021 $("body").append($.datepicker.dpDiv); 2022 } 2023 2024 var otherArgs = Array.prototype.slice.call(arguments, 1); 2025 if (typeof options === "string" && (options === "isDisabled" || options === "getDate" || options === "widget")) { 2026 return $.datepicker["_" + options + "Datepicker"]. 2027 apply($.datepicker, [this[0]].concat(otherArgs)); 2028 } 2029 if (options === "option" && arguments.length === 2 && typeof arguments[1] === "string") { 2030 return $.datepicker["_" + options + "Datepicker"]. 2031 apply($.datepicker, [this[0]].concat(otherArgs)); 2032 } 2033 return this.each(function() { 2034 typeof options === "string" ? 2035 $.datepicker["_" + options + "Datepicker"]. 2036 apply($.datepicker, [this].concat(otherArgs)) : 2037 $.datepicker._attachDatepicker(this, options); 2038 }); 2039}; 2040 2041$.datepicker = new Datepicker(); // singleton instance 2042$.datepicker.initialized = false; 2043$.datepicker.uuid = new Date().getTime(); 2044$.datepicker.version = "1.10.
20442"; 2045 2046// Workaround for #4055 2047// Add another global to avoid noConflict issues with inline event handlers 2048window["DP_jQuery_" + dpuuid] = $; 2049 2050})(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.