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