1 2(function ($, undefined) { 3 4 function UTCDate() { 5 return new Date(Date.UTC.apply(Date, arguments)); 6 } 7 function UTCToday() { 8 var today = new Date(); 9 return UTCDate(today.getFullYear(), today.getMonth(), today.getDate()); 10 } 11 function isUTCEquals(date1, date2) { 12 return ( 13 date1.getUTCFullYear() === date2.getUTCFullYear() && 14 date1.getUTCMonth() === date2.getUTCMonth() && 15 date1.getUTCDate() === date2.getUTCDate() 16 ); 17 } 18 function alias(method) { 19 return function () { 20 return this[method].apply(this, arguments); 21 }; 22 } 23 24 var DateArray = (function () { 25 var extras = { 26 get: function (i) { 27 return this.slice(i)[0]; 28 }, 29 contains: function (d) { 30 // Array.indexOf is not cross-browser; 31 // $.inArray doesn't work with Dates 32 var val = d && d.valueOf(); 33 for (var i = 0, l = this.length; i < l; i++) 34 if (this[i].valueOf() === val) 35 return i; 36 return -1; 37 }, 38 remove: function (i) { 39 this.splice(i, 1); 40 }, 41 replace: function (new_array) { 42 if (!new_array) 43 return; 44 if (!$.isArray(new_array)) 45 new_array = [new_array]; 46 this.clear(); 47 this.push.apply(this, new_array); 48 }, 49 clear: function () { 50 this.length = 0; 51 }, 52 copy: function () { 53 var a = new DateArray(); 54 a.replace(this); 55 return a; 56 } 57 }; 58 59 return function () { 60 var a = []; 61 a.push.apply(a, arguments); 62 $.extend(a, extras); 63 return a; 64 }; 65 })(); 66 67 68 // Picker object 69 70 var Datepicker = function (element, options) { 71 this._process_options(options); 72 73 this.dates = new DateArray(); 74 this.viewDate = this.o.defaultViewDate; 75 this.focusDate = null; 76 77 this.element = $(element); 78 this.isInline = false; 79 this.isInput = this.element.is('input'); 80 this.component = this.element.hasClass('date') ? this.element.find('.add-on, .input-group-addon, .btn') : false; 81 this.hasInput = this.component && this.element.find('input').length; 82 if (this.component && this.component.length === 0) 83 this.component = false; 84 85 this.picker = $(DPGlobal.template); 86 this._buildEvents(); 87 this._attachEvents(); 88 89 if (this.isInline) { 90 this.picker.addClass('datepicker-inline').appendTo(this.element); 91 } 92 else { 93 this.picker.addClass('datepicker-dropdown dropdown-menu'); 94 } 95 96 if (this.o.rtl) { 97 this.picker.addClass('datepicker-rtl'); 98 } 99 100 this.viewMode = this.o.startView; 101 102 if (this.o.calendarWeeks) 103 this.picker.find('tfoot .today, tfoot .clear') 104 .attr('colspan', function (i, val) { 105 return parseInt(val) + 1; 106 }); 107 108 this._allow_update = false; 109 110 this.setStartDate(this._o.startDate); 111 this.setEndDate(this._o.endDate); 112 this.setDaysOfWeekDisabled(this.o.daysOfWeekDisabled); 113 this.setDatesDisabled(this.o.datesDisabled); 114 115 this.fillDow(); 116 this.fillMonths(); 117 118 this._allow_update = true; 119 120 this.update(); 121 this.showMode(); 122 123 if (this.isInline) { 124 this.show(); 125 } 126 }; 127 128 Datepicker.prototype = { 129 constructor: Datepicker, 130 131 _process_options: function (opts) { 132 // Store raw options for reference 133 this._o = $.extend({}, this._o, opts); 134 // Processed options 135 var o = this.o = $.extend({}, this._o); 136 137 // Check if "de-DE" style date is available, if not language should 138 // fallback to 2 letter code eg "de" 139 var lang = o.language; 140 if (!dates[lang]) { 141 lang = lang.split('-')[0]; 142 if (!dates[lang]) 143 lang = defaults.language; 144 } 145 o.language = lang; 146 147 switch (o.startView) { 148 case 2: 149 case 'decade': 150 o.startView = 2; 151 break; 152 case 1: 153 case 'year': 154 o.startView = 1; 155 break; 156 default: 157 o.startView = 0; 158 } 159 160 switch (o.minViewMode) { 161 case 1: 162 case 'months': 163 o.minViewMode = 1; 164 break; 165 case 2: 166 case 'years': 167 o.minViewMode = 2; 168 break; 169 default: 170 o.minViewMode = 0; 171 } 172 173 o.startView = Math.max(o.startView, o.minViewMode); 174 175 // true, false, or Number > 0 176 if (o.multidate !== true) { 177 o.multidate = Number(o.multidate) || false; 178 if (o.multidate !== false) 179 o.multidate = Math.max(0, o.multidate); 180 } 181 o.multidateSeparator = String(o.multidateSeparator); 182 183 o.weekStart %= 7; 184 o.weekEnd = ((o.weekStart + 6) % 7); 185 186 var format = DPGlobal.parseFormat(o.format); 187 if (o.startDate !== -Infinity) { 188 if (!!o.startDate) { 189 if (o.startDate instanceof Date) 190 o.startDate = this._local_to_utc(this._zero_time(o.startDate)); 191 else 192 o.startDate = DPGlobal.parseDate(o.startDate, format, o.language); 193 } 194 else { 195 o.startDate = -Infinity; 196 } 197 } 198 if (o.endDate !== Infinity) { 199 if (!!o.endDate) { 200 if (o.endDate instanceof Date) 201 o.endDate = this._local_to_utc(this._zero_time(o.endDate)); 202 else 203 o.endDate = DPGlobal.parseDate(o.endDate, format, o.language); 204 } 205 else { 206 o.endDate = Infinity; 207 } 208 } 209 210 o.daysOfWeekDisabled = o.daysOfWeekDisabled || []; 211 if (!$.isArray(o.daysOfWeekDisabled)) 212 o.daysOfWeekDisabled = o.daysOfWeekDisabled.split(/[,\s]*/); 213 o.daysOfWeekDisabled = $.map(o.daysOfWeekDisabled, function (d) { 214 return parseInt(d, 10); 215 }); 216 217 o.datesDisabled = o.datesDisabled || []; 218 if (!$.isArray(o.datesDisabled)) { 219 var datesDisabled = []; 220 datesDisabled.push(DPGlobal.parseDate(o.datesDisabled, format, o.language)); 221 o.datesDisabled = datesDisabled; 222 } 223 o.datesDisabled = $.map(o.datesDisabled, function (d) { 224 return DPGlobal.parseDate(d, format, o.language); 225 }); 226 227 var plc = String(o.orientation).toLowerCase().split(/\s+/g), 228 _plc = o.orientation.toLowerCase(); 229 plc = $.grep(plc, function (word) { 230 return /^auto|left|right|top|bottom$/.test(word); 231 }); 232 o.orientation = { x: 'auto', y: 'auto' }; 233 if (!_plc || _plc === 'auto') 234 ; // no action 235 else if (plc.length === 1) { 236 switch (plc[0]) { 237 case 'top': 238 case 'bottom': 239 o.orientation.y = plc[0]; 240 break; 241 case 'left': 242 case 'right': 243 o.orientation.x = plc[0]; 244 break; 245 } 246 } 247 else { 248 _plc = $.grep(plc, function (word) { 249 return /^left|right$/.test(word); 250 }); 251 o.orientation.x = _plc[0] || 'auto'; 252 253 _plc = $.grep(plc, function (word) { 254 return /^top|bottom$/.test(word); 255 }); 256 o.orientation.y = _plc[0] || 'auto'; 257 } 258 if (o.defaultViewDate) { 259 var year = o.defaultViewDate.year || new Date().getFullYear();
260 var month = o.defaultViewDate.month || 0; 261 var day = o.defaultViewDate.day || 1; 262 o.defaultViewDate = UTCDate(year, month, day); 263 } else { 264 o.defaultViewDate = UTCToday(); 265 } 266 o.showOnFocus = o.showOnFocus !== undefined ? o.showOnFocus : true; 267 }, 268 _events: [], 269 _secondaryEvents: [], 270 _applyEvents: function (evs) { 271 for (var i = 0, el, ch, ev; i < evs.length; i++) { 272 el = evs[i][0]; 273 if (evs[i].length === 2) { 274 ch = undefined; 275 ev = evs[i][1]; 276 } 277 else if (evs[i].length === 3) { 278 ch = evs[i][1]; 279 ev = evs[i][2]; 280 } 281 el.on(ev, ch); 282 } 283 }, 284 _unapplyEvents: function (evs) { 285 for (var i = 0, el, ev, ch; i < evs.length; i++) { 286 el = evs[i][0]; 287 if (evs[i].length === 2) { 288 ch = undefined; 289 ev = evs[i][1]; 290 } 291 else if (evs[i].length === 3) { 292 ch = evs[i][1]; 293 ev = evs[i][2]; 294 } 295 el.off(ev, ch); 296 } 297 }, 298 _buildEvents: function () { 299 var events = { 300 keyup: $.proxy(function (e) { 301 if ($.inArray(e.keyCode, [27, 37, 39, 38, 40, 32, 13, 9]) === -1) 302 this.update(); 303 }, this), 304 keydown: $.proxy(this.keydown, this), 305 paste: $.proxy(this.paste, this) 306 }; 307 308 if (this.o.showOnFocus === true) { 309 events.focus = $.proxy(this.show, this); 310 } 311 312 if (this.isInput) { // single input 313 this._events = [ 314 [this.element, events] 315 ]; 316 } 317 else if (this.component && this.hasInput) { // component: input + button 318 this._events = [ 319 // For components that are not readonly, allow keyboard nav 320 [this.element.find('input'), events], 321 [this.component, { 322 click: $.proxy(this.show, this) 323 }] 324 ]; 325 } 326 else if (this.element.is('div')) { // inline datepicker 327 this.isInline = true; 328 } 329 else { 330 this._events = [ 331 [this.element, { 332 click: $.proxy(this.show, this) 333 }] 334 ]; 335 } 336 this._events.push( 337 // Component: listen for blur on element descendants 338 [this.element, '*', { 339 blur: $.proxy(function (e) { 340 this._focused_from = e.target; 341 }, this) 342 }], 343 // Input: listen for blur on element 344 [this.element, { 345 blur: $.proxy(function (e) { 346 this._focused_from = e.target; 347 }, this) 348 }] 349 ); 350 351 this._secondaryEvents = [ 352 [this.picker, { 353 click: $.proxy(this.click, this) 354 }], 355 [$(window), { 356 resize: $.proxy(this.place, this) 357 }], 358 [$(document), { 359 mousedown: $.proxy(function (e) { 360 // Clicked outside the datepicker, hide it 361 if (!( 362 this.element.is(e.target) || 363 this.element.find(e.target).length || 364 this.picker.is(e.target) || 365 this.picker.find(e.target).length 366 )) { 367 $(this.picker).hide(); 368 } 369 }, this) 370 }] 371 ]; 372 }, 373 _attachEvents: function () { 374 this._detachEvents(); 375 this._applyEvents(this._events); 376 }, 377 _detachEvents: function () { 378 this._unapplyEvents(this._events); 379 }, 380 _attachSecondaryEvents: function () { 381 this._detachSecondaryEvents(); 382 this._applyEvents(this._secondaryEvents); 383 }, 384 _detachSecondaryEvents: function () { 385 this._unapplyEvents(this._secondaryEvents); 386 }, 387 _trigger: function (event, altdate) { 388 var date = altdate || this.dates.get(-1), 389 local_date = this._utc_to_local(date); 390 391 this.element.trigger({ 392 type: event, 393 date: local_date, 394 dates: $.map(this.dates, this._utc_to_local), 395 format: $.proxy(function (ix, format) { 396 if (arguments.length === 0) { 397 ix = this.dates.length - 1; 398 format = this.o.format; 399 } 400 else if (typeof ix === 'string') { 401 format = ix; 402 ix = this.dates.length - 1; 403 } 404 format = format || this.o.format; 405 var date = this.dates.get(ix); 406 return DPGlobal.formatDate(date, format, this.o.language); 407 }, this) 408 }); 409 }, 410 411 show: function () { 412 if (this.element.attr('readonly') && this.o.enableOnReadonly === false) 413 return; 414 if (!this.isInline) 415 this.picker.appendTo(this.o.container); 416 this.place(); 417 this.picker.show(); 418 this._attachSecondaryEvents(); 419 this._trigger('show'); 420 if ((window.navigator.msMaxTouchPoints || 'ontouchstart' in document) && this.o.disableTouchKeyboard) { 421 $(this.element).blur(); 422 } 423 return this; 424 }, 425 426 hide: function () { 427 if (this.isInline) 428 return this; 429 if (!this.picker.is(':visible')) 430 return this; 431 this.focusDate = null; 432 this.picker.hide().detach(); 433 this._detachSecondaryEvents(); 434 this.viewMode = this.o.startView; 435 this.showMode(); 436 437 if ( 438 this.o.forceParse && 439 ( 440 this.isInput && this.element.val() || 441 this.hasInput && this.element.find('input').val() 442 ) 443 ) 444 this.setValue(); 445 this._trigger('hide'); 446 return this; 447 }, 448 449 remove: function () { 450 this.hide(); 451 this._detachEvents(); 452 this._detachSecondaryEvents(); 453 this.picker.remove(); 454 delete this.element.data().datepicker; 455 if (!this.isInput) { 456 delete this.element.data().date; 457 } 458 return this; 459 }, 460 461 paste: function (evt) { 462 var dateString; 463 if (evt.originalEvent.clipboardData && evt.originalEvent.clipboardData.types 464 && $.inArray('text/plain', evt.originalEvent.clipboardData.types) !== -1) { 465 dateString = evt.originalEvent.clipboardData.getData('text/plain'); 466 } 467 else if (window.clipboardData) { 468 dateString = window.clipboardData.getData('Text'); 469 } 470 else { 471 return; 472 } 473 this.setDate(dateString); 474 this.update(); 475 evt.preventDefault(); 476 }, 477 478 _utc_to_local: function (utc) { 479 return utc && new Date(utc.getTime() + (utc.getTimezoneOffset() * 60000)); 480 }, 481 _local_to_utc: function (local) { 482 return local && new Date(local.getTime() - (local.getTimezoneOffset() * 60000)); 483 }, 484 _zero_time: function (local) { 485 return local && new Date(local.getFullYear(), local.getMonth(), local.getDate()); 486 }, 487 _zero_utc_time: function (utc) { 488 return utc && new Date(Date.UTC(utc.getUTCFullYear(), utc.getUTCMonth(), utc.getUTCDate())); 489 }, 490 491 getDates: function () { 492 return $.map(this.dates, this._utc_to_local); 493 }, 494 495 getUTCDates: function () { 496 return $.map(this.dates, function (d) { 497 return new Date(d); 498 }); 499 }, 500 501 getDate: function () { 502 return this._utc_to_local(this.getUTCDate()); 503 }, 504 505 getUTCDate: function () { 506 var selected_date = this.dates.get(-1); 507 if (typeof selected_date !== 'undefined') { 508 return new Date(selected_date); 509 } else { 510 return null; 511 } 512 }, 513 514 clearDates: function () { 515 var element; 516 if (this.isInput) { 517 element = this.element; 518 } else if (this.component) { 519 element = this.element.find('input'); 520 } 521 522 if (element) { 523 element.val('').change(); 524 } 525 526 this.update(); 527 this._trigger('changeDate'); 528 529 if (this.o.autoclose) { 530 this.hide(); 531 } 532 }, 533 setDates: function () { 534 var args = $.isArray(arguments[0]) ? arguments[0] : arguments; 535 this.update.apply(this, args); 536 this._trigger('changeDate'); 537 this.setValue(); 538 return this; 539 }, 540 541 setUTCDates: function () { 542 var args = $.isArray(arguments[0]) ? arguments[0] : arguments; 543 this.update.apply(this, $.map(args, this._utc_to_local)); 544 this._trigger('changeDate'); 545 this.setValue(); 546 return this; 547 }, 548 549 setDate: alias('setDates'), 550 setUTCDate: alias('setUTCDates'), 551 552 setValue: function () { 553 var formatted = this.getFormattedDate(); 554 if (!this.isInput) { 555 if (this.component) { 556 this.element.find('input').val(formatted).change(); 557 } 558 } 559 else { 560 this.element.val(formatted).change(); 561 var AttributeId = this.element[0].id; 562 var dateObject = $('input#' + AttributeId).val(); 563 if (dateObject != null) { 564 $("input#" + AttributeId).removeClass("input-validation-error"); 565 $("#errorSpam" + AttributeId).find("span").remove(); 566 } 567 } 568 return this; 569 }, 570 571 getFormattedDate: function (format) { 572 if (format === undefined) 573 format = this.o.format; 574 575 var lang = this.o.language; 576 return $.map(this.dates, function (d) { 577 return DPGlobal.formatDate(d, format, lang); 578 }).join(this.o.multidateSeparator); 579 }, 580 581 setStartDate: function (startDate) { 582 this._process_options({ startDate: startDate });
583 this.update(); 584 this.updateNavArrows(); 585 return this; 586 }, 587 588 setEndDate: function (endDate) { 589 this._process_options({ endDate: endDate }); 590 this.update(); 591 this.updateNavArrows(); 592 return this; 593 }, 594 595 setDaysOfWeekDisabled: function (daysOfWeekDisabled) { 596 this._process_options({ daysOfWeekDisabled: daysOfWeekDisabled }); 597 this.update(); 598 this.updateNavArrows(); 599 return this; 600 }, 601 602 setDatesDisabled: function (datesDisabled) { 603 this._process_options({ datesDisabled: datesDisabled }); 604 this.update(); 605 this.updateNavArrows(); 606 }, 607 608 place: function () { 609 if (this.isInline) 610 return this; 611 var calendarWidth = this.picker.outerWidth(), 612 calendarHeight = this.picker.outerHeight(), 613 visualPadding = 10, 614 windowWidth = $(this.o.container).width(), 615 windowHeight = $(this.o.container).height(), 616 scrollTop = $(this.o.container).scrollTop(), 617 appendOffset = $(this.o.container).offset(); 618 619 var parentsZindex = []; 620 this.element.parents().each(function () { 621 var itemZIndex = $(this).css('z-index'); 622 if (itemZIndex !== 'auto' && itemZIndex !== 0) parentsZindex.push(parseInt(itemZIndex)); 623 }); 624 var zIndex = Math.max.apply(Math, parentsZindex) + 10; 625 var offset = this.component ? this.component.parent().offset() : this.element.offset(); 626 var height = this.component ? this.component.outerHeight(true) : this.element.outerHeight(false); 627 var width = this.component ? this.component.outerWidth(true) : this.element.outerWidth(false); 628 var left = offset.left - appendOffset.left, 629 top = offset.top - appendOffset.top; 630 631 this.picker.removeClass( 632 'datepicker-orient-top datepicker-orient-bottom ' + 633 'datepicker-orient-right datepicker-orient-left' 634 ); 635 636 if (this.o.orientation.x !== 'auto') { 637 this.picker.addClass('datepicker-orient-' + this.o.orientation.x); 638 if (this.o.orientation.x === 'right') 639 left -= calendarWidth - width; 640 } 641 // auto x orientation is best-placement: if it crosses a window 642 // edge, fudge it sideways 643 else { 644 if (offset.left < 0) { 645 // component is outside the window on the left side. Move it into visible range 646 this.picker.addClass('datepicker-orient-left'); 647 left -= offset.left - visualPadding; 648 } else if (left + calendarWidth > windowWidth) { 649 // the calendar passes the widow right edge. Align it to component right side 650 this.picker.addClass('datepicker-orient-right'); 651 left = offset.left + width - calendarWidth; 652 } else { 653 // Default to left 654 this.picker.addClass('datepicker-orient-left'); 655 } 656 } 657 658 // auto y orientation is best-situation: top or bottom, no fudging, 659 // decision based on which shows more of the calendar 660 var yorient = this.o.orientation.y, 661 top_overflow, bottom_overflow; 662 if (yorient === 'auto') { 663 top_overflow = -scrollTop + top - calendarHeight; 664 bottom_overflow = scrollTop + windowHeight - (top + height + calendarHeight); 665 if (Math.max(top_overflow, bottom_overflow) === bottom_overflow) 666 yorient = 'top'; 667 else 668 yorient = 'bottom'; 669 } 670 this.picker.addClass('datepicker-orient-' + yorient); 671 if (yorient === 'top') 672 top += height; 673 else 674 top -= calendarHeight + parseInt(this.picker.css('padding-top')); 675 676 if (this.o.rtl) { 677 var right = windowWidth - (left + width); 678 this.picker.css({ 679 top: top, 680 right: right, 681 zIndex: zIndex 682 }); 683 } else { 684 this.picker.css({ 685 top: top, 686 left: left, 687 zIndex: zIndex 688 }); 689 } 690 return this; 691 }, 692 693 _allow_update: true, 694 update: function () { 695 if (!this._allow_update) 696 return this; 697 698 var oldDates = this.dates.copy(), 699 dates = [], 700 fromArgs = false; 701 if (arguments.length) { 702 $.each(arguments, $.proxy(function (i, date) { 703 if (date instanceof Date) 704 date = this._local_to_utc(date); 705 dates.push(date); 706 }, this)); 707 fromArgs = true; 708 } 709 else { 710 dates = this.isInput 711 ? this.element.val() 712 : this.element.data('date') || this.element.find('input').val(); 713 if (dates && this.o.multidate) 714 dates = dates.split(this.o.multidateSeparator); 715 else 716 dates = [dates]; 717 delete this.element.data().date; 718 } 719 720 dates = $.map(dates, $.proxy(function (date) { 721 return DPGlobal.parseDate(date, this.o.format, this.o.language); 722 }, this)); 723 dates = $.grep(dates, $.proxy(function (date) { 724 return ( 725 date < this.o.startDate || 726 date > this.o.endDate || 727 !date 728 ); 729 }, this), true); 730 this.dates.replace(dates); 731 732 if (this.dates.length) 733 this.viewDate = new Date(this.dates.get(-1)); 734 else if (this.viewDate < this.o.startDate) 735 this.viewDate = new Date(this.o.startDate); 736 else if (this.viewDate > this.o.endDate) 737 this.viewDate = new Date(this.o.endDate); 738 739 if (fromArgs) { 740 // setting date by clicking 741 this.setValue(); 742 } 743 else if (dates.length) { 744 // setting date by typing 745 if (String(oldDates) !== String(this.dates)) 746 this._trigger('changeDate'); 747 } 748 if (!this.dates.length && oldDates.length) 749 this._trigger('clearDate'); 750 751 this.fill(); 752 return this; 753 }, 754 755 fillDow: function () { 756 var dowCnt = this.o.weekStart, 757 html = '<tr>'; 758 if (this.o.calendarWeeks) { 759 this.picker.find('.datepicker-days thead tr:first-child .datepicker-switch') 760 .attr('colspan', function (i, val) { 761 return parseInt(val) + 1; 762 }); 763 var cell = '<th class="cw"> </th>'; 764 html += cell; 765 } 766 while (dowCnt < this.o.weekStart + 7) { 767 html += '<th class="dow">' + dates[this.o.language].daysShort[(dowCnt++) % 7] + '</th>'; 768 } 769 html += '</tr>'; 770 this.picker.find('.datepicker-days thead').append(html); 771 }, 772 773 fillMonths: function () { 774 var html = '', 775 i = 0; 776 while (i < 12) { 777 html += '<span class="month">' + dates[this.o.language].monthsShort[i++] + '</span>'; 778 } 779 this.picker.find('.datepicker-months td').html(html); 780 }, 781 782 setRange: function (range) { 783 if (!range || !range.length) 784 delete this.range; 785 else 786 this.range = $.map(range, function (d) { 787 return d.valueOf(); 788 }); 789 this.fill(); 790 }, 791 792 getClassNames: function (date) { 793 var cls = [], 794 year = this.viewDate.getUTCFullYear(),
795 month = this.viewDate.getUTCMonth(), 796 today = new Date(); 797 if (date.getUTCFullYear() < year || (date.getUTCFullYear() === year && date.getUTCMonth() < month)) { 798 cls.push('old'); 799 } 800 else if (date.getUTCFullYear() > year || (date.getUTCFullYear() === year && date.getUTCMonth() > month)) { 801 cls.push('new'); 802 } 803 if (this.focusDate && date.valueOf() === this.focusDate.valueOf()) 804 cls.push('focused'); 805 // Compare internal UTC date with local today, not UTC today 806 if (this.o.todayHighlight && 807 date.getUTCFullYear() === today.getFullYear() && 808 date.getUTCMonth() === today.getMonth() && 809 date.getUTCDate() === today.getDate()) { 810 cls.push('today'); 811 } 812 if (this.dates.contains(date) !== -1) 813 cls.push('active'); 814 if (date.valueOf() < this.o.startDate || date.valueOf() > this.o.endDate || 815 $.inArray(date.getUTCDay(), this.o.daysOfWeekDisabled) !== -1) { 816 cls.push('disabled'); 817 } 818 if (this.o.datesDisabled.length > 0 && 819 $.grep(this.o.datesDisabled, function (d) { 820 return isUTCEquals(date, d); 821 }).length > 0) { 822 cls.push('disabled', 'disabled-date'); 823 } 824 825 if (this.range) { 826 if (date > this.range[0] && date < this.range[this.range.length - 1]) { 827 cls.push('range'); 828 } 829 if ($.inArray(date.valueOf(), this.range) !== -1) { 830 cls.push('selected'); 831 } 832 } 833 return cls; 834 }, 835 836 fill: function () { 837 var d = new Date(this.viewDate), 838 year = d.getUTCFullYear(), 839 month = d.getUTCMonth(), 840 startYear = this.o.startDate !== -Infinity ? this.o.startDate.getUTCFullYear() : -Infinity, 841 startMonth = this.o.startDate !== -Infinity ? this.o.startDate.getUTCMonth() : -Infinity, 842 endYear = this.o.endDate !== Infinity ? this.o.endDate.getUTCFullYear() : Infinity, 843 endMonth = this.o.endDate !== Infinity ? this.o.endDate.getUTCMonth() : Infinity, 844 todaytxt = dates[this.o.language].today || dates['en'].today || '', 845 cleartxt = dates[this.o.language].clear || dates['en'].clear || '', 846 tooltip; 847 if (isNaN(year) || isNaN(month)) 848 return; 849 this.picker.find('.datepicker-days thead .datepicker-switch') 850 .text(dates[this.o.language].months[month] + ' ' + year); 851 this.picker.find('tfoot .today') 852 .text(todaytxt) 853 .toggle(this.o.todayBtn !== false); 854 this.picker.find('tfoot .clear') 855 .text(cleartxt) 856 .toggle(this.o.clearBtn !== false); 857 this.updateNavArrows(); 858 this.fillMonths(); 859 var prevMonth = UTCDate(year, month - 1, 28), 860 day = DPGlobal.getDaysInMonth(prevMonth.getUTCFullYear(), prevMonth.getUTCMonth()); 861 prevMonth.setUTCDate(day); 862 prevMonth.setUTCDate(day - (prevMonth.getUTCDay() - this.o.weekStart + 7) % 7); 863 var nextMonth = new Date(prevMonth); 864 nextMonth.setUTCDate(nextMonth.getUTCDate() + 42); 865 nextMonth = nextMonth.valueOf(); 866 var html = []; 867 var clsName; 868 while (prevMonth.valueOf() < nextMonth) { 869 if (prevMonth.getUTCDay() === this.o.weekStart) { 870 html.push('<tr>'); 871 if (this.o.calendarWeeks) { 872 // ISO 8601: First week contains first thursday. 873 // ISO also states week starts on Monday, but we can be more abstract here. 874 var 875 // Start of current week: based on weekstart/current date 876 ws = new Date(+prevMonth + (this.o.weekStart - prevMonth.getUTCDay() - 7) % 7 * 864e5), 877 // Thursday of this week 878 th = new Date(Number(ws) + (7 + 4 - ws.getUTCDay()) % 7 * 864e5), 879 // First Thursday of year, year from thursday 880 yth = new Date(Number(yth = UTCDate(th.getUTCFullYear(), 0, 1)) + (7 + 4 - yth.getUTCDay()) % 7 * 864e5), 881 // Calendar week: ms between thursdays, div ms per day, div 7 days 882 calWeek = (th - yth) / 864e5 / 7 + 1; 883 html.push('<td class="cw">' + calWeek + '</td>'); 884 885 } 886 } 887 clsName = this.getClassNames(prevMonth); 888 clsName.push('day'); 889 890 if (this.o.beforeShowDay !== $.noop) { 891 var before = this.o.beforeShowDay(this._utc_to_local(prevMonth)); 892 if (before === undefined) 893 before = {}; 894 else if (typeof (before) === 'boolean') 895 before = { enabled: before }; 896 else if (typeof (before) === 'string') 897 before = { classes: before }; 898 if (before.enabled === false) 899 clsName.push('disabled'); 900 if (before.classes) 901 clsName = clsName.concat(before.classes.split(/\s+/)); 902 if (before.tooltip) 903 tooltip = before.tooltip; 904 } 905 906 clsName = $.unique(clsName); 907 html.push('<td class="' + clsName.join(' ') + '"' + (tooltip ? ' title="' + tooltip + '"' : '') + '>
907' + prevMonth.getUTCDate() + '</td>'); 908 tooltip = null; 909 if (prevMonth.getUTCDay() === this.o.weekEnd) { 910 html.push('</tr>'); 911 } 912 prevMonth.setUTCDate(prevMonth.getUTCDate() + 1); 913 } 914 this.picker.find('.datepicker-days tbody').empty().append(html.join('')); 915 916 var months = this.picker.find('.datepicker-months') 917 .find('th:eq(1)') 918 .text(year) 919 .end() 920 .find('span').removeClass('active'); 921 922 $.each(this.dates, function (i, d) { 923 if (d.getUTCFullYear() === year) 924 months.eq(d.getUTCMonth()).addClass('active'); 925 }); 926 927 if (year < startYear || year > endYear) { 928 months.addClass('disabled'); 929 } 930 if (year === startYear) { 931 months.slice(0, startMonth).addClass('disabled'); 932 } 933 if (year === endYear) { 934 months.slice(endMonth + 1).addClass('disabled'); 935 } 936 937 if (this.o.beforeShowMonth !== $.noop) { 938 var that = this; 939 $.each(months, function (i, month) { 940 if (!$(month).hasClass('disabled')) { 941 var moDate = new Date(year, i, 1); 942 var before = that.o.beforeShowMonth(moDate); 943 if (before === false) 944 $(month).addClass('disabled'); 945 } 946 }); 947 } 948 949 html = ''; 950 year = parseInt(year / 10, 10) * 10; 951 var yearCont = this.picker.find('.datepicker-years') 952 .find('th:eq(1)') 953 .text(year + '-' + (year + 9)) 954 .end() 955 .find('td'); 956 year -= 1; 957 var years = $.map(this.dates, function (d) { 958 return d.getUTCFullYear(); 959 }), 960 classes; 961 for (var i = -1; i < 11; i++) { 962 classes = ['year']; 963 if (i === -1) 964 classes.push('old'); 965 else if (i === 10) 966 classes.push('new'); 967 if ($.inArray(year, years) !== -1) 968 classes.push('active'); 969 if (year < startYear || year > endYear) 970 classes.push('disabled'); 971 html += '<span class="' + classes.join(' ') + '">' + year + '</span>'; 972 year += 1; 973 } 974 yearCont.html(html); 975 }, 976 977 updateNavArrows: function () { 978 if (!this._allow_update) 979 return; 980 981 var d = new Date(this.viewDate), 982 year = d.getUTCFullYear(), 983 month = d.getUTCMonth(); 984 switch (this.viewMode) { 985 case 0: 986 if (this.o.startDate !== -Infinity && year <= this.o.startDate.getUTCFullYear() && month <= this.o.startDate.getUTCMonth()) { 987 this.picker.find('.prev').css({ visibility: 'hidden' }); 988 } 989 else { 990 this.picker.find('.prev').css({ visibility: 'visible' }); 991 } 992 if (this.o.endDate !== Infinity && year >= this.o.endDate.getUTCFullYear() && month >= this.o.endDate.getUTCMonth()) { 993 this.picker.find('.next').css({ visibility: 'hidden' }); 994 } 995 else { 996 this.picker.find('.next').css({ visibility: 'visible' }); 997 } 998 break; 999 case 1: 1000 case 2: 1001 if (this.o.startDate !== -Infinity && year <= this.o.startDate.getUTCFullYear()) { 1002 this.picker.find('.prev').css({ visibility: 'hidden' }); 1003 } 1004 else { 1005 this.picker.find('.prev').css({ visibility: 'visible' }); 1006 } 1007 if (this.o.endDate !== Infinity && year >= this.o.endDate.getUTCFullYear()) { 1008 this.picker.find('.next').css({ visibility: 'hidden' }); 1009 } 1010 else { 1011 this.picker.find('.next').css({ visibility: 'visible' }); 1012 } 1013 break; 1014 } 1015 }, 1016 1017 click: function (e) { 1018 e.preventDefault(); 1019 var target = $(e.target).closest('span, td, th'), 1020 year, month, day; 1021 if (target.length === 1) { 1022 switch (target[0].nodeName.toLowerCase()) { 1023 case 'th': 1024 switch (target[0].className) { 1025 case 'datepicker-switch': 1026 this.showMode(1); 1027 break; 1028 case 'prev': 1029 case 'next': 1030 var dir = DPGlobal.modes[this.viewMode].navStep * (target[0].className === 'prev' ? -1 : 1); 1031 switch (this.viewMode) { 1032 case 0: 1033 this.viewDate = this.moveMonth(this.viewDate, dir); 1034 this._trigger('changeMonth', this.viewDate); 1035 break; 1036 case 1: 1037 case 2: 1038 this.viewDate = this.moveYear(this.viewDate, dir); 1039 if (this.viewMode === 1) 1040 this._trigger('changeYear', this.viewDate); 1041 break; 1042 } 1043 this.fill(); 1044 break; 1045 case 'today': 1046 var date = new Date(); 1047 date = UTCDate(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0); 1048 1049 this.showMode(-2); 1050 var which = this.o.todayBtn === 'linked' ? null : 'view'; 1051 this._setDate(date, which); 1052 break; 1053 case 'clear': 1054 this.clearDates();
1055 break; 1056 } 1057 break; 1058 case 'span': 1059 if (!target.hasClass('disabled')) { 1060 this.viewDate.setUTCDate(1); 1061 if (target.hasClass('month')) { 1062 day = 1; 1063 month = target.parent().find('span').index(target); 1064 year = this.viewDate.getUTCFullYear(); 1065 this.viewDate.setUTCMonth(month); 1066 this._trigger('changeMonth', this.viewDate); 1067 if (this.o.minViewMode === 1) { 1068 this._setDate(UTCDate(year, month, day)); 1069 } 1070 } 1071 else { 1072 day = 1; 1073 month = 0; 1074 year = parseInt(target.text(), 10) || 0; 1075 this.viewDate.setUTCFullYear(year); 1076 this._trigger('changeYear', this.viewDate); 1077 if (this.o.minViewMode === 2) { 1078 this._setDate(UTCDate(year, month, day)); 1079 } 1080 } 1081 this.showMode(-1); 1082 this.fill(); 1083 } 1084 break; 1085 case 'td': 1086 if (target.hasClass('day') && !target.hasClass('disabled')) { 1087 day = parseInt(target.text(), 10) || 1; 1088 year = this.viewDate.getUTCFullYear(); 1089 month = this.viewDate.getUTCMonth(); 1090 if (target.hasClass('old')) { 1091 if (month === 0) { 1092 month = 11; 1093 year -= 1; 1094 } 1095 else { 1096 month -= 1; 1097 } 1098 } 1099 else if (target.hasClass('new')) { 1100 if (month === 11) { 1101 month = 0; 1102 year += 1; 1103 } 1104 else { 1105 month += 1; 1106 } 1107 } 1108 this._setDate(UTCDate(year, month, day)); 1109 } 1110 break; 1111 } 1112 } 1113 if (this.picker.is(':visible') && this._focused_from) { 1114 $(this._focused_from).focus(); 1115 } 1116 delete this._focused_from; 1117 }, 1118 1119 _toggle_multidate: function (date) { 1120 var ix = this.dates.contains(date); 1121 if (!date) { 1122 this.dates.clear(); 1123 } 1124 1125 if (ix !== -1) { 1126 if (this.o.multidate === true || this.o.multidate > 1 || this.o.toggleActive) { 1127 this.dates.remove(ix); 1128 } 1129 } else if (this.o.multidate === false) { 1130 this.dates.clear(); 1131 this.dates.push(date); 1132 } 1133 else { 1134 this.dates.push(date); 1135 } 1136 1137 if (typeof this.o.multidate === 'number') 1138 while (this.dates.length > this.o.multidate) 1139 this.dates.remove(0); 1140 }, 1141 1142 _setDate: function (date, which) { 1143 if (!which || which === 'date') 1144 this._toggle_multidate(date && new Date(date)); 1145 if (!which || which === 'view') 1146 this.viewDate = date && new Date(date); 1147 1148 this.fill(); 1149 this.setValue(); 1150 if (!which || which !== 'view') { 1151 this._trigger('changeDate'); 1152 } 1153 var element; 1154 if (this.isInput) { 1155 element = this.element; 1156 } 1157 else if (this.component) { 1158 element = this.element.find('input'); 1159 } 1160 if (element) { 1161 element.change(); 1162 } 1163 if (this.o.autoclose && (!which || which === 'date')) { 1164 this.hide(); 1165 } 1166 }, 1167 1168 moveMonth: function (date, dir) { 1169 if (!date) 1170 return undefined; 1171 if (!dir) 1172 return date; 1173 var new_date = new Date(date.valueOf()), 1174 day = new_date.getUTCDate(),
1175 month = new_date.getUTCMonth(), 1176 mag = Math.abs(dir), 1177 new_month, test; 1178 dir = dir > 0 ? 1 : -1; 1179 if (mag === 1) { 1180 test = dir === -1 1181 // If going back one month, make sure month is not current month 1182 // (eg, Mar 31 -> Feb 31 == Feb 28, not Mar 02) 1183 ? function () { 1184 return new_date.getUTCMonth() === month; 1185 } 1186 // If going forward one month, make sure month is as expected 1187 // (eg, Jan 31 -> Feb 31 == Feb 28, not Mar 02) 1188 : function () { 1189 return new_date.getUTCMonth() !== new_month; 1190 }; 1191 new_month = month + dir; 1192 new_date.setUTCMonth(new_month); 1193 // Dec -> Jan (12) or Jan -> Dec (-1) -- limit expected date to 0-11 1194 if (new_month < 0 || new_month > 11) 1195 new_month = (new_month + 12) % 12; 1196 } 1197 else { 1198 // For magnitudes >1, move one month at a time... 1199 for (var i = 0; i < mag; i++) 1200 // ...which might decrease the day (eg, Jan 31 to Feb 28, etc)... 1201 new_date = this.moveMonth(new_date, dir); 1202 // ...then reset the day, keeping it in the new month 1203 new_month = new_date.getUTCMonth(); 1204 new_date.setUTCDate(day); 1205 test = function () { 1206 return new_month !== new_date.getUTCMonth(); 1207 }; 1208 } 1209 // Common date-resetting loop -- if date is beyond end of month, make it 1210 // end of month 1211 while (test()) { 1212 new_date.setUTCDate(--day); 1213 new_date.setUTCMonth(new_month); 1214 } 1215 return new_date; 1216 }, 1217 1218 moveYear: function (date, dir) { 1219 return this.moveMonth(date, dir * 12); 1220 }, 1221 1222 dateWithinRange: function (date) { 1223 return date >= this.o.startDate && date <= this.o.endDate; 1224 }, 1225 1226 keydown: function (e) { 1227 if (!this.picker.is(':visible')) { 1228 if (e.keyCode === 40 || e.keyCode === 27) // allow down to re-show picker 1229 this.show(); 1230 return; 1231 } 1232 var dateChanged = false, 1233 dir, newDate, newViewDate, 1234 focusDate = this.focusDate || this.viewDate; 1235 switch (e.keyCode) { 1236 case 27: // escape 1237 if (this.focusDate) { 1238 this.focusDate = null; 1239 this.viewDate = this.dates.get(-1) || this.viewDate; 1240 this.fill(); 1241 } 1242 else { 1243 this.hide(); 1244 } 1245 $('.table-condensed').closest('.popover').hide(); 1246 e.preventDefault(); 1247 break; 1248 case 37: // left 1249 case 39: // right 1250 if (!this.o.keyboardNavigation) 1251 break; 1252 dir = e.keyCode === 37 ? -1 : 1; 1253 if (e.ctrlKey) { 1254 newDate = this.moveYear(this.dates.get(-1) || UTCToday(), dir); 1255 newViewDate = this.moveYear(focusDate, dir); 1256 this._trigger('changeYear', this.viewDate); 1257 } 1258 else if (e.shiftKey) { 1259 newDate = this.moveMonth(this.dates.get(-1) || UTCToday(), dir); 1260 newViewDate = this.moveMonth(focusDate, dir); 1261 this._trigger('changeMonth', this.viewDate); 1262 } 1263 else { 1264 newDate = new Date(this.dates.get(-1) || UTCToday()); 1265 newDate.setUTCDate(newDate.getUTCDate() + dir); 1266 newViewDate = new Date(focusDate); 1267 newViewDate.setUTCDate(focusDate.getUTCDate() + dir); 1268 } 1269 if (this.dateWithinRange(newViewDate)) { 1270 this.focusDate = this.viewDate = newViewDate; 1271 this.setValue(); 1272 this.fill(); 1273 this.announceDate(newViewDate); 1274 e.preventDefault(); 1275 } 1276 break; 1277 case 38: // up 1278 case 40: // down 1279 if (!this.o.keyboardNavigation) 1280 break; 1281 dir = e.keyCode === 38 ? -1 : 1; 1282 if (e.ctrlKey) { 1283 newDate = this.moveYear(this.dates.get(-1) || UTCToday(), dir); 1284 newViewDate = this.moveYear(focusDate, dir); 1285 this._trigger('changeYear', this.viewDate); 1286 } 1287 else if (e.shiftKey) { 1288 newDate = this.moveMonth(this.dates.get(-1) || UTCToday(), dir); 1289 newViewDate = this.moveMonth(focusDate, dir); 1290 this._trigger('changeMonth', this.viewDate); 1291 } 1292 else { 1293 newDate = new Date(this.dates.get(-1) || UTCToday()); 1294 newDate.setUTCDate(newDate.getUTCDate() + dir * 7); 1295 newViewDate = new Date(focusDate); 1296 newViewDate.setUTCDate(focusDate.getUTCDate() + dir * 7); 1297 } 1298 if (this.dateWithinRange(newViewDate)) { 1299 this.focusDate = this.viewDate = newViewDate; 1300 this.setValue(); 1301 this.fill(); 1302 this.announceDate(newViewDate); 1303 e.preventDefault(); 1304 } 1305 break; 1306 case 32: // spacebar 1307 // Spacebar is used in manually typing dates in some formats. 1308 // As such, its behavior should not be hijacked. 1309 break; 1310 case 13: // enter 1311 focusDate = this.focusDate || this.dates.get(-1) || this.viewDate; 1312 if (this.o.keyboardNavigation) { 1313 this._toggle_multidate(focusDate); 1314 dateChanged = true; 1315 } 1316 this.focusDate = null; 1317 this.viewDate = this.dates.get(-1) || this.viewDate; 1318 this.setValue(); 1319 this.fill(); 1320 this.announceDate(this.viewDate); 1321 if (this.picker.is(':visible')) { 1322 e.preventDefault(); 1323 if (typeof e.stopPropagation === 'function') { 1324 e.stopPropagation(); // All modern browsers, IE9+ 1325 } else { 1326 e.cancelBubble = true; // IE6,7,8 ignore "stopPropagation" 1327 } 1328 if (this.o.autoclose) 1329 this.hide(); 1330 } 1331 break; 1332 case 9: // tab 1333 this.focusDate = null; 1334 this.viewDate = this.dates.get(-1) || this.viewDate; 1335 this.fill(); 1336 this.hide(); 1337 break; 1338 } 1339 if (dateChanged) { 1340 if (this.dates.length) 1341 this._trigger('changeDate'); 1342 else 1343 this._trigger('clearDate'); 1344 var element; 1345 if (this.isInput) { 1346 element = this.element; 1347 } 1348 else if (this.component) { 1349 element = this.element.find('input'); 1350 } 1351 if (element) { 1352 element.change(); 1353 } 1354 } 1355 }, 1356 1357 // Function to announce the selected date for screen readers 1358 announceDate: function (date) { 1359 var liveRegion = document.getElementById('datepicker-live-region'); 1360 if (!liveRegion) { 1361 liveRegion = document.createElement('div'); 1362 liveRegion.id = 'datepicker-live-region'; 1363 liveRegion.setAttribute('role', 'alert'); 1364 liveRegion.setAttribute('aria-live', 'assertive'); 1365 document.body.appendChild(liveRegion); 1366 } 1367 liveRegion.textContent = "Selected date: " + date.toLocaleDateString("en-US", { 1368 weekday: "long", 1369 year: "numeric", 1370 month: "long", 1371 day: "numeric" 1372 }); 1373 }, 1374 1375 showMode: function (dir) { 1376 if (dir) { 1377 this.viewMode = Math.max(this.o.minViewMode, Math.min(2, this.viewMode + dir)); 1378 } 1379 this.picker 1380 .children('div') 1381 .hide() 1382 .filter('.datepicker-' + DPGlobal.modes[this.viewMode].clsName) 1383 .css('display', 'block'); 1384 this.updateNavArrows(); 1385 } 1386 }; 1387 1388 var DateRangePicker = function (element, options) { 1389 this.element = $(element); 1390 this.inputs = $.map(options.inputs, function (i) { 1391 return i.jquery ? i[0] : i; 1392 }); 1393 delete options.inputs; 1394 1395 datepickerPlugin.call($(this.inputs), options) 1396 .on('changeDate', $.proxy(this.dateUpdated, this)); 1397 1398 this.pickers = $.map(this.inputs, function (i) { 1399 return $(i).data('datepicker'); 1400 }); 1401 this.updateDates();
1402 }; 1403 DateRangePicker.prototype = { 1404 updateDates: function () { 1405 this.dates = $.map(this.pickers, function (i) { 1406 return i.getUTCDate(); 1407 }); 1408 this.updateRanges(); 1409 }, 1410 updateRanges: function () { 1411 var range = $.map(this.dates, function (d) { 1412 return d.valueOf(); 1413 }); 1414 $.each(this.pickers, function (i, p) { 1415 p.setRange(range); 1416 }); 1417 }, 1418 dateUpdated: function (e) { 1419 // `this.updating` is a workaround for preventing infinite recursion 1420 // between `changeDate` triggering and `setUTCDate` calling. Until 1421 // there is a better mechanism. 1422 if (this.updating) 1423 return; 1424 this.updating = true; 1425 1426 var dp = $(e.target).data('datepicker'), 1427 new_date = dp.getUTCDate(), 1428 i = $.inArray(e.target, this.inputs), 1429 j = i - 1, 1430 k = i + 1, 1431 l = this.inputs.length; 1432 if (i === -1) 1433 return; 1434 1435 $.each(this.pickers, function (i, p) { 1436 if (!p.getUTCDate()) 1437 p.setUTCDate(new_date); 1438 }); 1439 1440 if (new_date < this.dates[j]) { 1441 // Date being moved earlier/left 1442 while (j >= 0 && new_date < this.dates[j]) { 1443 this.pickers[j--].setUTCDate(new_date); 1444 } 1445 } 1446 else if (new_date > this.dates[k]) { 1447 // Date being moved later/right 1448 while (k < l && new_date > this.dates[k]) { 1449 this.pickers[k++].setUTCDate(new_date); 1450 } 1451 } 1452 this.updateDates(); 1453 1454 delete this.updating; 1455 }, 1456 remove: function () { 1457 $.map(this.pickers, function (p) { p.remove(); }); 1458 delete this.element.data().datepicker; 1459 } 1460 }; 1461 1462 function opts_from_el(el, prefix) { 1463 // Derive options from element data-attrs 1464 var data = $(el).data(), 1465 out = {}, inkey, 1466 replace = new RegExp('^' + prefix.toLowerCase() + '([A-Z])'); 1467 prefix = new RegExp('^' + prefix.toLowerCase()); 1468 function re_lower(_, a) { 1469 return a.toLowerCase(); 1470 } 1471 for (var key in data) 1472 if (prefix.test(key)) { 1473 inkey = key.replace(replace, re_lower); 1474 out[inkey] = data[key]; 1475 } 1476 return out; 1477 } 1478 1479 function opts_from_locale(lang) { 1480 // Derive options from locale plugins 1481 var out = {}; 1482 // Check if "de-DE" style date is available, if not language should 1483 // fallback to 2 letter code eg "de" 1484 if (!dates[lang]) { 1485 lang = lang.split('-')[0]; 1486 if (!dates[lang]) 1487 return; 1488 } 1489 var d = dates[lang]; 1490 $.each(locale_opts, function (i, k) { 1491 if (k in d) 1492 out[k] = d[k]; 1493 }); 1494 return out; 1495 } 1496 1497 var old = $.fn.datepicker; 1498 var datepickerPlugin = function (option) { 1499 var args = Array.apply(null, arguments); 1500 args.shift(); 1501 var internal_return; 1502 this.each(function () { 1503 var $this = $(this), 1504 data = $this.data('datepicker'), 1505 options = typeof option === 'object' && option; 1506 if (!data) { 1507 var elopts = opts_from_el(this, 'date'), 1508 // Preliminary otions 1509 xopts = $.extend({}, defaults, elopts, options), 1510 locopts = opts_from_locale(xopts.language), 1511 // Options priority: js args, data-attrs, locales, defaults 1512 opts = $.extend({}, defaults, locopts, elopts, options); 1513 if ($this.hasClass('input-daterange') || opts.inputs) { 1514 var ropts = { 1515 inputs: opts.inputs || $this.find('input').toArray() 1516 }; 1517 $this.data('datepicker', (data = new DateRangePicker(this, $.extend(opts, ropts)))); 1518 } 1519 else { 1520 $this.data('datepicker', (data = new Datepicker(this, opts))); 1521 } 1522 } 1523 if (typeof option === 'string' && typeof data[option] === 'function') { 1524 internal_return = data[option].apply(data, args); 1525 if (internal_return !== undefined) 1526 return false; 1527 } 1528 }); 1529 if (internal_return !== undefined) 1530 return internal_return; 1531 else 1532 return this; 1533 }; 1534 $.fn.datepicker = datepickerPlugin; 1535 1536 var defaults = $.fn.datepicker.defaults = { 1537 autoclose: true, 1538 beforeShowDay: $.noop, 1539 beforeShowMonth: $.noop, 1540 calendarWeeks: false, 1541 clearBtn: true, 1542 toggleActive: false, 1543 daysOfWeekDisabled: [], 1544 datesDisabled: [], 1545 endDate: Infinity, 1546 forceParse: true, 1547 format: 'mm/dd/yyyy', 1548 keyboardNavigation: true, 1549 language: 'en', 1550 minViewMode: 0, 1551 multidate: false, 1552 multidateSeparator: ',', 1553 orientation: "auto", 1554 rtl: false, 1555 startDate: -Infinity, 1556 startView: 0, 1557 todayBtn: false, 1558 todayHighlight: false, 1559 weekStart: 0, 1560 disableTouchKeyboard: false, 1561 enableOnReadonly: true, 1562 container: 'body' 1563 }; 1564 var locale_opts = $.fn.datepicker.locale_opts = [ 1565 'format', 1566 'rtl', 1567 'weekStart' 1568 ]; 1569 $.fn.datepicker.Constructor = Datepicker; 1570 var dates = $.fn.datepicker.dates = { 1571 en: { 1572 days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], 1573 daysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], 1574 daysMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"], 1575 months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "
1575November", "December"], 1576 monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], 1577 today: "Today", 1578 clear: "Clear" 1579 } 1580 }; 1581 1582 var DPGlobal = { 1583 modes: [ 1584 { 1585 clsName: 'days', 1586 navFnc: 'Month', 1587 navStep: 1 1588 }, 1589 { 1590 clsName: 'months', 1591 navFnc: 'FullYear', 1592 navStep: 1 1593 }, 1594 { 1595 clsName: 'years', 1596 navFnc: 'FullYear', 1597 navStep: 10 1598 }], 1599 isLeapYear: function (year) { 1600 return (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0)); 1601 }, 1602 getDaysInMonth: function (year, month) { 1603 return [31, (DPGlobal.isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month]; 1604 }, 1605 validParts: /dd?|DD?|mm?|MM?|yy(?:yy)?/g, 1606 nonpunctuation: /[^ -\/:-@\[\u3400-\u9fff-`{-~\t\n\r]+/g, 1607 parseFormat: function (format) { 1608 // IE treats \0 as a string end in inputs (truncating the value), 1609 // so it's a bad format delimiter, anyway 1610 var separators = format.replace(this.validParts, '\0').split('\0'), 1611 parts = format.match(this.validParts); 1612 if (!separators || !separators.length || !parts || parts.length === 0) { 1613 throw new Error("Invalid date format."); 1614 } 1615 return { separators: separators, parts: parts }; 1616 }, 1617 parseDate: function (date, format, language) { 1618 if (!date) 1619 return undefined; 1620 if (date instanceof Date) 1621 return date; 1622 if (typeof format === 'string') 1623 format = DPGlobal.parseFormat(format); 1624 var part_re = /([\-+]\d+)([dmwy])/, 1625 parts = date.match(/([\-+]\d+)([dmwy])/g), 1626 part, dir, i; 1627 if (/^[\-+]\d+[dmwy]([\s,]+[\-+]\d+[dmwy])*$/.test(date)) { 1628 date = new Date(); 1629 for (i = 0; i < parts.length; i++) { 1630 part = part_re.exec(parts[i]); 1631 dir = parseInt(part[1]); 1632 switch (part[2]) { 1633 case 'd': 1634 date.setUTCDate(date.getUTCDate() + dir); 1635 break; 1636 case 'm': 1637 date = Datepicker.prototype.moveMonth.call(Datepicker.prototype, date, dir); 1638 break; 1639 case 'w': 1640 date.setUTCDate(date.getUTCDate() + dir * 7); 1641 break; 1642 case 'y': 1643 date = Datepicker.prototype.moveYear.call(Datepicker.prototype, date, dir); 1644 break; 1645 } 1646 } 1647 return UTCDate(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), 0, 0, 0); 1648 } 1649 parts = date && date.match(this.nonpunctuation) || []; 1650 date = new Date(); 1651 var parsed = {}, 1652 setters_order = ['yyyy', 'yy', 'M', 'MM', 'm', 'mm', 'd', 'dd'], 1653 setters_map = { 1654 yyyy: function (d, v) { 1655 return d.setUTCFullYear(v); 1656 }, 1657 yy: function (d, v) { 1658 return d.setUTCFullYear(2000 + v); 1659 }, 1660 m: function (d, v) { 1661 if (isNaN(d)) 1662 return d; 1663 v -= 1; 1664 while (v < 0) v += 12; 1665 v %= 12; 1666 d.setUTCMonth(v); 1667 while (d.getUTCMonth() !== v) 1668 d.setUTCDate(d.getUTCDate() - 1); 1669 return d; 1670 }, 1671 d: function (d, v) { 1672 return d.setUTCDate(v); 1673 } 1674 }, 1675 val, filtered; 1676 setters_map['M'] = setters_map['MM'] = setters_map['mm'] = setters_map['m']; 1677 setters_map['dd'] = setters_map['d']; 1678 date = UTCDate(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0); 1679 var fparts = format.parts.slice(); 1680 // Remove noop parts 1681 if (parts.length !== fparts.length) { 1682 fparts = $(fparts).filter(function (i, p) { 1683 return $.inArray(p, setters_order) !== -1; 1684 }).toArray(); 1685 } 1686 // Process remainder 1687 function match_part() { 1688 var m = this.slice(0, parts[i].length), 1689 p = parts[i].slice(0, m.length); 1690 return m.toLowerCase() === p.toLowerCase(); 1691 } 1692 if (parts.length === fparts.length) { 1693 var cnt; 1694 for (i = 0, cnt = fparts.length; i < cnt; i++) { 1695 val = parseInt(parts[i], 10); 1696 part = fparts[i];
vendor: 4,131 bytes, lines 1697-1809
1697 if (isNaN(val)) { 1698 switch (part) { 1699 case 'MM': 1700 filtered = $(dates[language].months).filter(match_part); 1701 val = $.inArray(filtered[0], dates[language].months) + 1; 1702 break; 1703 case 'M': 1704 filtered = $(dates[language].monthsShort).filter(match_part); 1705 val = $.inArray(filtered[0], dates[language].monthsShort) + 1; 1706 break; 1707 } 1708 } 1709 parsed[part] = val; 1710 } 1711 var _date, s; 1712 for (i = 0; i < setters_order.length; i++) { 1713 s = setters_order[i]; 1714 if (s in parsed && !isNaN(parsed[s])) { 1715 _date = new Date(date); 1716 setters_map[s](_date, parsed[s]); 1717 if (!isNaN(_date)) 1718 date = _date; 1719 } 1720 } 1721 } 1722 return date; 1723 }, 1724 formatDate: function (date, format, language) { 1725 if (!date) 1726 return ''; 1727 if (typeof format === 'string') 1728 format = DPGlobal.parseFormat(format); 1729 var val = { 1730 d: date.getUTCDate(), 1731 D: dates[language].daysShort[date.getUTCDay()], 1732 DD: dates[language].days[date.getUTCDay()], 1733 m: date.getUTCMonth() + 1, 1734 M: dates[language].monthsShort[date.getUTCMonth()], 1735 MM: dates[language].months[date.getUTCMonth()], 1736 yy: date.getUTCFullYear().toString().substring(2), 1737 yyyy: date.getUTCFullYear() 1738 }; 1739 val.dd = (val.d < 10 ? '0' : '') + val.d; 1740 val.mm = (val.m < 10 ? '0' : '') + val.m; 1741 date = []; 1742 var seps = $.extend([], format.separators); 1743 for (var i = 0, cnt = format.parts.length; i <= cnt; i++) { 1744 if (seps.length) 1745 date.push(seps.shift()); 1746 date.push(val[format.parts[i]]); 1747 } 1748 return date.join(''); 1749 }, 1750 headTemplate: '<thead>' + 1751 '<tr>' + 1752 '<th class="prev">«</th>' + 1753 '<th colspan="5" class="datepicker-switch"></th>' + 1754 '<th class="next">»</th>' + 1755 '</tr>' + 1756 '</thead>', 1757 contTemplate: '<tbody><tr><td colspan="7"></td></tr></tbody>', 1758 footTemplate: '<tfoot>' + 1759 '<tr>' + 1760 '<th colspan="7" class="today"></th>' + 1761 '</tr>' + 1762 '<tr>' + 1763 '<th colspan="7" class="clear"></th>' + 1764 '</tr>' + 1765 '</tfoot>' 1766 }; 1767 DPGlobal.template = '<div class="datepicker">' + 1768 '<div class="datepicker-days">' + 1769 '<table class=" table-condensed">' + 1770 DPGlobal.headTemplate + 1771 '<tbody></tbody>' + 1772 DPGlobal.footTemplate + 1773 '</table>' + 1774 '</div>' + 1775 '<div class="datepicker-months">' + 1776 '<table class="table-condensed">' + 1777 DPGlobal.headTemplate + 1778 DPGlobal.contTemplate + 1779 DPGlobal.footTemplate + 1780 '</table>' + 1781 '</div>' + 1782 '<div class="datepicker-years">' + 1783 '<table class="table-condensed">' + 1784 DPGlobal.headTemplate + 1785 DPGlobal.contTemplate + 1786 DPGlobal.footTemplate + 1787 '</table>' + 1788 '</div>' + 1789 '</div>'; 1790 1791 $.fn.datepicker.DPGlobal = DPGlobal; 1792 1793 1794 /* DATEPICKER NO CONFLICT 1795 * =================== */ 1796 1797 $.fn.datepicker.noConflict = function () { 1798 $.fn.datepicker = old; 1799 return this; 1800 }; 1801 1802 /* DATEPICKER VERSION 1803 * =================== */ 1804 $.fn.datepicker.version = "1.5.0"; 1805 1806 /* DATEPICKER DATA-API 1807 * ================== */ 1808 1809 $(document).on(
1810 'focus.datepicker.data-api click.datepicker.data-api', 1811 '[data-provide="datepicker"]', 1812 function (e) { 1813 var $this = $(this); 1814 if ($this.data('datepicker')) 1815 return; 1816 e.preventDefault(); 1817 // component click requires us to explicitly show it 1818 datepickerPlugin.call($this, 'show'); 1819 } 1820 ); 1821 $(function () { 1822 datepickerPlugin.call($('[data-provide="datepicker-inline"]')); 1823 }); 1824 1825}(window.jQuery)); 1826 1827var startDate = new Date('01/01/2016'); 1828var FromEndDate = new Date(); 1829var groupName; 1830var srcDate; 1831if (jQuery('.datepicker').length > 0) { 1832 if (jQuery('.datepicker').filter('input[mindate]').length === 0) { 1833 1834 jQuery('.datepicker').datepicker().on('changeMonth', 1835 function (event) { 1836 isSelectCalender = true; 1837 }).on('changeDate', function () { 1838 isSelectCalender = true; 1839 }).on('changeYear', function () { 1840 isSelectCalender = true; 1841 }).on('changeDecade', function () { 1842 isSelectCalender = true; 1843 }).on('changeCentury', function () { 1844 isSelectCalender = true; 1845 }).on('show', function () { 1846 isSelectCalender = true; 1847 }).on('clearDate', function () { 1848 isSelectCalender = true; 1849 }); 1850 } 1851 else { 1852 jQuery('.datepicker').filter('input[mindate]').datepicker({ 1853 weekStart: 1, 1854 autoclose: true 1855 }).on('changeDate', function (selected) { 1856 startDate = new Date(selected.date.valueOf()); 1857 startDate.setDate(startDate.getDate(new Date(selected.date.valueOf()))); 1858 groupName = $(this).attr('group'); 1859 $('.datepicker').filter('input[group=' + groupName + ']').filter('input[maxdate]').datepicker('setStartDate', startDate); 1860 }).on('show', function (ev) { 1861 if ($(this).attr('mindate') !== undefined && $(this).attr('mindate') !== "") { 1862 srcDate = $(this).attr('mindate').replace(/-/g, ' '); 1863 var mindate = new Date(srcDate); 1864 $(this).datepicker('setStartDate', mindate); 1865 } 1866 groupName = $(this).attr('group'); 1867 if (this.s == null) return ''; 1868 if (groupName !== undefined && groupName !== "") 1869 srcDate = $('.datepicker').filter('input[group=' + groupName + ']').filter('input[maxdate]').val().replace(/-/g, ' '); 1870 1871 if (srcDate !== "" && srcDate !== undefined) { 1872 startDate = new Date(srcDate); 1873 startDate.setDate(startDate.getDate(new Date(srcDate))); 1874 $(this).datepicker('setEndDate', startDate); 1875 } 1876 1877 if ($(this).attr('maxdate') !== undefined && $(this).attr('maxdate') !== "") { 1878 srcDate = $(this).attr('maxdate').replace(/-/g, ' '); 1879 var maxdate = new Date(srcDate); 1880 $(this).datepicker('setEndDate', maxdate); 1881 } 1882 }); 1883 1884 jQuery('.datepicker').filter('input[maxdate]').datepicker({ 1885 weekStart: 1, 1886 autoclose: true 1887 }).on('changeDate', function (selected) { 1888 //srcDate = selected.date.valueOf().replace(/-/g, ' '); 1889 FromEndDate = new Date(selected.date.valueOf()); 1890 FromEndDate.setDate(FromEndDate.getDate(new Date(selected.date.valueOf()))); 1891 groupName = $(this).attr('group'); 1892 $('.datepicker').filter('input[group=' + groupName + ']').filter('input[mindate]').datepicker('setEndDate', FromEndDate); 1893 }).on('show', function (ev) { 1894 groupName = $(this).attr('group'); 1895 srcDate = $('.datepicker').filter('input[group=' + groupName + ']').filter('input[mindate]').val().replace(/-/g, ' '); 1896 startDate = new Date(srcDate); 1897 startDate.setDate(startDate.getDate(new Date(srcDate))); 1898 1899 $('.datepicker').filter('input[group=' + groupName + ']').filter('input[maxdate]').datepicker('setStartDate', startDate); 1900 1901 if ($(this).attr('mindate') !== undefined && $(this).attr('mindate') !== "") { 1902 srcDate = $(this).attr('mindate').replace(/-/g, ' '); 1903 var mindate = new Date($(this).attr('mindate')); 1904 $(this).datepicker('setStartDate', mindate); 1905 } 1906 1907 if ($(this).attr('maxdate') !== undefined && $(this).attr('maxdate') !== "") { 1908 srcDate = $(this).attr('maxdate').replace(/-/g, ' '); 1909 var maxdate = new Date($(this).attr('maxdate')); 1910 $(this).datepicker('setEndDate', maxdate); 1911 } 1912 }); 1913 } 1914} 1915 1916//To show time format popup on click of start and expire time input box. 1917$("#StartTime, #ExpireTime").on("click", function () { 1918 $(".bootstrap-datetimepicker-widget").css("display", "block"); 1919}); 1920jQuery('.datepicker').attr("readonly", "readonly");
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.