vendor: 45,962 bytes, lines 1-1543
1/** 2 * @author: Rinat G. http://coding.kz 3 * @copyright: Copyright (c) 2019 Rinat G. 4 * @license: Licensed under the MIT license. See http://www.opensource.org/licenses/mit-license.php 5 */ 6 7// Following the UMD template https://github.com/umdjs/umd/blob/master/templates/returnExportsGlobal.js 8(function(root, factory) { 9 if (typeof define === 'function' && define.amd) { 10 // AMD. Make globaly available as well 11 define(['moment'], function(moment) { 12 return factory(moment); 13 }); 14 } else if (typeof module === 'object' && module.exports) { 15 // Node / Browserify 16 var moment = 17 typeof window != 'undefined' && typeof window.moment != 'undefined' 18 ? window.moment 19 : require('moment'); 20 module.exports = factory(moment); 21 } else { 22 // Browser globals 23 root.Lightpick = factory(root.moment); 24 } 25})(this, function(moment) { 26 'use strict'; 27 28 var document = window.document, 29 defaults = { 30 field: null, 31 secondField: null, 32 firstDay: 1, 33 parentEl: 'body', 34 lang: 'auto', 35 format: 'DD/MM/YYYY', 36 separator: ' - ', 37 numberOfMonths: 1, 38 numberOfColumns: 2, 39 singleDate: true, 40 autoclose: true, 41 repick: false, 42 startDate: null, 43 endDate: null, 44 minDate: null, 45 maxDate: null, 46 disableDates: null, 47 selectForward: false, 48 selectBackward: false, 49 minDays: null, 50 maxDays: null, 51 hoveringTooltip: true, 52 hideOnBodyClick: true, 53 footer: false, 54 disabledDatesInRange: true, 55 tooltipNights: false, 56 orientation: 'auto', 57 disableWeekends: false, 58 inline: false, 59 weekdayStyle: 'short', 60 dropdowns: { 61 years: { 62 min: 1900, 63 max: null 64 }, 65 months: true 66 }, 67 locale: { 68 buttons: { 69 prev: '←', 70 next: '→', 71 close: '×', 72 reset: 'Reset', 73 apply: 'Apply' 74 }, 75 tooltip: { 76 one: 'day', 77 other: 'days' 78 }, 79 tooltipOnDisabled: null, 80 pluralize: function(i, locale) { 81 if (typeof i === 'string') i = parseInt(i, 10); 82 83 if (i === 1 && 'one' in locale) return locale.one; 84 if ('other' in locale) return locale.other; 85 86 return ''; 87 } 88 }, 89 90 onSelect: null, 91 onSelectStart: null, 92 onSelectEnd: null, 93 onOpen: null, 94 onClose: null, 95 onError: null, 96 onMonthsChange: null, 97 onYearsChange: null 98 }, 99 renderTopButtons = function(opts) { 100 return ( 101 '<div class="lightpick__toolbar">' + 102 '' + 103 '<button type="button" class="lightpick__previous-action">' + 104 opts.locale.buttons.prev + 105 '</button>' + 106 '<button type="button" class="lightpick__next-action">' + 107 opts.locale.buttons.next + 108 '</button>' + 109 (!opts.autoclose && !opts.inline 110 ? '<button type="button" class="lightpick__close-action">' + 111 opts.locale.buttons.close + 112 '</button>' 113 : '') + 114 '</div>' 115 ); 116 }, 117 weekdayName = function(opts, day, weekdayStyle) { 118 return new Date(1970, 0, day, 12, 0, 0, 0).toLocaleString(opts.lang, { 119 weekday: weekdayStyle || opts.weekdayStyle 120 }); 121 }, 122 renderDay = function(opts, date, dummy, extraClass) { 123 if (dummy) return '<div></div>'; 124 125 var date = moment(date), 126 prevMonth = moment(date).subtract(1, 'month'), 127 nextMonth = moment(date).add(1, 'month'); 128 129 var day = { 130 time: moment(date).valueOf(), 131 className: ['lightpick__day', 'is-available'] 132 }; 133 134 if ( 135 extraClass instanceof Array || 136 Object.prototype.toString.call(extraClass) === '[object Array]' 137 ) { 138 extraClass = extraClass.filter(function(el) { 139 return ( 140 [ 141 'lightpick__day', 142 'is-available', 143 'is-previous-month', 144 'is-next-month' 145 ].indexOf(el) >= 0 146 ); 147 }); 148 day.className = day.className.concat(extraClass); 149 } else { 150 day.className.push(extraClass); 151 } 152 153 if (opts.disableDates) { 154 for (var i = 0; i < opts.disableDates.length; i++) { 155 if ( 156 opts.disableDates[i] instanceof Array || 157 Object.prototype.toString.call(opts.disableDates[i]) === 158 '[object Array]' 159 ) { 160 var _from = moment(opts.disableDates[i][0], opts.format), 161 _to = moment(opts.disableDates[i][1], opts.format); 162 163 if ( 164 _from.isValid() && 165 _to.isValid() && 166 date.isBetween(_from, _to, 'day', '[]') 167 ) { 168 day.className.push('is-disabled'); 169 } 170 } else if ( 171 moment(opts.disableDates[i], opts.format).isValid() && 172 moment(opts.disableDates[i], opts.format).isSame(date, 'day') 173 ) { 174 day.className.push('is-disabled'); 175 } 176 177 if (day.className.indexOf('is-disabled') >= 0) { 178 if ( 179 opts.locale.tooltipOnDisabled && 180 (!opts.startDate || 181 date.isAfter(opts.startDate) || 182 (opts.startDate && opts.endDate)) 183 ) { 184 day.className.push('disabled-tooltip'); 185 } 186 187 if (day.className.indexOf('is-start-date') >= 0) { 188 this.setStartDate(null); 189 this.setEndDate(null); 190 } else if (day.className.indexOf('is-end-date') >= 0) { 191 this.setEndDate(null); 192 } 193 } 194 } 195 } 196 197 if (opts.minDays && opts.startDate && !opts.endDate) { 198 if ( 199 date.isBetween( 200 moment(opts.startDate).subtract(opts.minDays - 1, 'day'), 201 moment(opts.startDate).add(opts.minDays - 1, 'day'), 202 'day' 203 ) 204 ) { 205 day.className.push('is-disabled'); 206 207 if (opts.selectForward && date.isSameOrAfter(opts.startDate)) { 208 day.className.push('is-forward-selected'); 209 day.className.push('is-in-range'); 210 } 211 } 212 } 213 214 if (opts.maxDays && opts.startDate && !opts.endDate) { 215 if ( 216 date.isSameOrBefore( 217 moment(opts.startDate).subtract(opts.maxDays, 'day'), 218 'day' 219 ) 220 ) { 221 day.className.push('is-disabled'); 222 } else if ( 223 date.isSameOrAfter( 224 moment(opts.startDate).add(opts.maxDays, 'day'), 225 'day' 226 ) 227 ) { 228 day.className.push('is-disabled'); 229 } 230 } 231 232 if ( 233 opts.repick && 234 (opts.minDays || opts.maxDays) && 235 opts.startDate && 236 opts.endDate 237 ) { 238 var tempStartDate = moment( 239 opts.repickTrigger == opts.field ? opts.endDate : opts.startDate 240 ); 241 242 if (opts.minDays) { 243 if ( 244 date.isBetween( 245 moment(tempStartDate).subtract(opts.minDays - 1, 'day'), 246 moment(tempStartDate).add(opts.minDays - 1, 'day'), 247 'day' 248 ) 249 ) { 250 day.className.push('is-disabled'); 251 } 252 } 253 254 if (opts.maxDays) { 255 if ( 256 date.isSameOrBefore( 257 moment(tempStartDate).subtract(opts.maxDays, 'day'), 258 'day' 259 ) 260 ) { 261 day.className.push('is-disabled'); 262 } else if ( 263 date.isSameOrAfter( 264 moment(tempStartDate).add(opts.maxDays, 'day'), 265 'day' 266 ) 267 ) { 268 day.className.push('is-disabled'); 269 } 270 } 271 } 272 273 if (date.isSame(new Date(), 'day')) { 274 day.className.push('is-today'); 275 } 276 277 if (date.isSame(opts.startDate, 'day')) { 278 day.className.push('is-start-date'); 279 } 280 281 if (date.isSame(opts.endDate, 'day')) { 282 day.className.push('is-end-date'); 283 } 284 285 if ( 286 opts.startDate && 287 opts.endDate && 288 date.isBetween(opts.startDate, opts.endDate, 'day', '[]') 289 ) { 290 day.className.push('is-in-range'); 291 } 292 293 if (moment().isSame(date, 'month')) { 294 } else if (prevMonth.isSame(date, 'month')) { 295 day.className.push('is-previous-month'); 296 } else if (nextMonth.isSame(date, 'month')) { 297 day.className.push('is-next-month'); 298 } 299 300 if (opts.minDate && date.isBefore(opts.minDate, 'day')) { 301 day.className.push('is-disabled'); 302 } 303 304 if (opts.maxDate && date.isAfter(opts.maxDate, 'day')) { 305 day.className.push('is-disabled'); 306 } 307 308 if ( 309 opts.selectForward && 310 !opts.singleDate && 311 opts.startDate && 312 !opts.endDate && 313 date.isBefore(opts.startDate, 'day') 314 ) { 315 day.className.push('is-disabled'); 316 } 317 318 if ( 319 opts.selectBackward && 320 !opts.singleDate && 321 opts.startDate && 322 !opts.endDate && 323 date.isAfter(opts.startDate, 'day') 324 ) { 325 day.className.push('is-disabled'); 326 } 327 328 if ( 329 opts.disableWeekends && 330 (date.isoWeekday() == 6 || date.isoWeekday() == 7) 331 ) { 332 day.className.push('is-disabled'); 333 } 334 335 day.className = day.className.filter(function(value, index, self) { 336 return self.indexOf(value) === index; 337 }); 338 339 if ( 340 day.className.indexOf('is-disabled') >= 0 && 341 day.className.indexOf('is-available') >= 0 342 ) { 343 day.className.splice(day.className.indexOf('is-available'), 1); 344 } 345 346 var div = document.createElement('div'); 347 div.className = day.className.join(' '); 348 div.innerHTML = date.get('date'); 349 div.setAttribute('data-time', day.time); 350 351 return div.outerHTML; 352 }, 353 renderMonthsList = function(date, opts) { 354 var d = moment(date), 355 select = document.createElement('select'); 356 357 for (var idx = 0; idx < 12; idx++) { 358 d.set('month', idx); 359 360 var option = document.createElement('option'); 361 option.value = d.toDate().getMonth(); 362 option.text = d.toDate().toLocaleString(opts.lang, { month: 'long' }); 363 364 if (idx === date.toDate().getMonth()) { 365 option.setAttribute('selected', 'selected'); 366 } 367 368 select.appendChild(option); 369 } 370 371 select.className = 'lightpick__select lightpick__select-months'; 372 373 // for text align to right 374 select.dir = 'rtl'; 375 376 if (!opts.dropdowns || !opts.dropdowns.months) { 377 select.disabled = true; 378 } 379 380 return select.outerHTML; 381 }, 382 renderYearsList = function(date, opts) { 383 var d = moment(date), 384 select = document.createElement('select'), 385 years = 386 opts.dropdowns && opts.dropdowns.years ? opts.dropdowns.years : null, 387 minYear = years && years.min ? years.min : 1900, 388 maxYear = 389 years && years.max 390 ? years.max 391 : Number.parseInt(moment().format('YYYY')); 392 393 if (Number.parseInt(date.format('YYYY')) < minYear) { 394 minYear = Number.parseInt(date.format('YYYY')); 395 } 396 397 if (Number.parseInt(date.format('YYYY')) > maxYear) { 398 maxYear = Number.parseInt(date.format('YYYY')); 399 } 400 401 for (var idx = minYear; idx <= maxYear; idx++) { 402 d.set('year', idx); 403 404 var option = document.createElement('option'); 405 option.value = d.toDate().getFullYear(); 406 option.text = d.toDate().getFullYear(); 407 408 if (idx === date.toDate().getFullYear()) { 409 option.setAttribute('selected', 'selected'); 410 } 411 412 select.appendChild(option); 413 } 414 415 select.className = 'lightpick__select lightpick__select-years'; 416 417 if (!opts.dropdowns || !opts.dropdowns.years) { 418 select.disabled = true; 419 } 420 421 return select.outerHTML; 422 }, 423 renderCalendar = function(el, opts) { 424 var html = '', 425 monthDate = moment(opts.calendar[0]); 426 427 for (var i = 0; i < opts.numberOfMonths; i++) { 428 var day = moment(monthDate); 429 430 html += '<section class="lightpick__month">'; 431 html += '<div class="lightpick__month-title-bar">'; 432 html += 433 '<div class="lightpick__month-title">' + 434 renderMonthsList(day, opts) + 435 renderYearsList(day, opts) + 436 '</div>'; 437 438 if (opts.numberOfMonths === 1) { 439 html += renderTopButtons(opts, 'days'); 440 } 441 442 html += '</div>'; // lightpick__month-title-bar 443 444 html += '<div class="lightpick__days-of-the-week">'; 445 for (var w = opts.firstDay + 4; w < 7 + opts.firstDay + 4; ++w) { 446 html += 447 '<div class="lightpick__day-of-the-week" title="' + 448 weekdayName(opts, w, 'long') + 449 '">' + 450 weekdayName(opts, w) + 451 '</div>'; 452 } 453 html += '</div>'; // lightpick__days-of-the-week 454 455 html += '<div class="lightpick__days">'; 456 457 if (day.isoWeekday() !== opts.firstDay) { 458 var prevDays = 459 day.isoWeekday() - opts.firstDay > 0 460 ? day.isoWeekday() - opts.firstDay 461 : day.isoWeekday(), 462 prevMonth = moment(day).subtract(prevDays, 'day'), 463 daysInMonth = prevMonth.daysInMonth(); 464 465 for (var d = prevMonth.get('date'); d <= daysInMonth; d++) { 466 html += renderDay(opts, prevMonth, i > 0, 'is-previous-month'); 467 468 prevMonth.add(1, 'day'); 469 } 470 } 471 472 var daysInMonth = day.daysInMonth(), 473 today = new Date(); 474 475 for (var d = 0; d < daysInMonth; d++) { 476 html += renderDay(opts, day); 477 478 day.add(1, 'day'); 479 } 480 481 var nextMonth = moment(day), 482 nextDays = 7 - nextMonth.isoWeekday() + opts.firstDay; 483 484 if (nextDays < 7) { 485 for (var d = nextMonth.get('date'); d <= nextDays; d++) { 486 html += renderDay( 487 opts, 488 nextMonth, 489 i < opts.numberOfMonths - 1, 490 'is-next-month' 491 ); 492 493 nextMonth.add(1, 'day'); 494 } 495 } 496 497 html += '</div>'; // lightpick__days 498 499 html += '</section>'; // lightpick__month 500 501 monthDate.add(1, 'month'); 502 } 503 504 opts.calendar[1] = moment(monthDate); 505 506 el.querySelector('.lightpick__months').innerHTML = html; 507 }, 508 updateDates = function(el, opts) { 509 var days = el.querySelectorAll('.lightpick__day'); 510 [].forEach.call(days, function(day) { 511 day.outerHTML = renderDay( 512 opts, 513 parseInt(day.getAttribute('data-time')), 514 false, 515 day.className.split(' ') 516 ); 517 }); 518 519 checkDisabledDatesInRange(el, opts); 520 }, 521 checkDisabledDatesInRange = function(el, opts) { 522 if ( 523 opts.disabledDatesInRange || 524 !opts.startDate || 525 opts.endDate || 526 !opts.disableDates 527 ) 528 return; 529 530 var days = el.querySelectorAll('.lightpick__day'), 531 disabledArray = opts.disableDates.map(function(entry) { 532 return entry instanceof Array || 533 Object.prototype.toString.call(entry) === '[object Array]' 534 ? entry[0] 535 : entry; 536 }), 537 closestPrev = moment( 538 disabledArray 539 .filter(function(d) { 540 return moment(d).isBefore(opts.startDate); 541 }) 542 .sort(function(a, b) { 543 return moment(b).isAfter(moment(a)); 544 })[0] 545 ), 546 closestNext = moment( 547 disabledArray 548 .filter(function(d) { 549 return moment(d).isAfter(opts.startDate); 550 }) 551 .sort(function(a, b) { 552 return moment(a).isAfter(moment(b)); 553 })[0] 554 ); 555 556 [].forEach.call(days, function(dayCell) { 557 var day = moment(parseInt(dayCell.getAttribute('data-time'))); 558 if ( 559 (closestPrev && 560 day.isBefore(closestPrev) && 561 opts.startDate.isAfter(closestPrev)) || 562 (closestNext && 563 day.isAfter(closestNext) && 564 closestNext.isAfter(opts.startDate)) 565 ) { 566 dayCell.classList.remove('is-available'); 567 dayCell.classList.add('is-disabled'); 568 } 569 }); 570 }, 571 Lightpick = function(options) { 572 var self = this, 573 opts = self.config(options); 574 575 self.el = document.createElement('section'); 576 577 self.el.className = 578 'lightpick lightpick--' + opts.numberOfColumns + '-columns is-hidden'; 579 580 if (opts.inline) { 581 self.el.className += ' lightpick--inlined'; 582 } 583 584 var html = 585 '<div class="lightpick__inner">' + 586 (opts.numberOfMonths > 1 ? renderTopButtons(opts, 'days') : '') + 587 '<div class="lightpick__months"></div>' + 588 '<div class="lightpick__tooltip" style="visibility: hidden"></div>'; 589 590 if (opts.footer) { 591 html += '<div class="lightpick__footer">'; 592 if (opts.footer === true) { 593 html += 594 '<button type="button" class="lightpick__reset-action">' + 595 opts.locale.buttons.reset + 596 '</button>'; 597 html += '<div class="lightpick__footer-message"></div>'; 598 html += 599 '<button type="button" class="lightpick__apply-action">' + 600 opts.locale.buttons.apply + 601 '</button>'; 602 } else { 603 html += opts.footer; 604 } 605 html += '</div>'; 606 } 607 608 html += '</div>'; 609 610 self.el.innerHTML = html; 611 612 if (opts.parentEl instanceof Node) { 613 opts.parentEl.appendChild(self.el); 614 } else if (opts.parentEl === 'body' && opts.inline) { 615 opts.field.parentNode.appendChild(self.el); 616 } else { 617 document.querySelector(opts.parentEl).appendChild(self.el); 618 } 619 620 self._onMouseDown = function(e) { 621 if (!self.isShowing) { 622 return; 623 } 624 625 e = e || window.event; 626 var target = e.target || e.srcElement; 627 if (!target) { 628 return; 629 } 630 631 e.stopPropagation(); 632 633 if (!target.classList.contains('lightpick__select')) { 634 e.preventDefault(); 635 } 636 637 var opts = self._opts; 638 639 if ( 640 target.classList.contains('lightpick__day') && 641 target.classList.contains('is-available') 642 ) { 643 var day = moment(parseInt(target.getAttribute('data-time'))); 644 645 if ( 646 !opts.disabledDatesInRange && 647 opts.disableDates && 648 opts.startDate 649 ) { 650 var start = day.isAfter(opts.startDate) 651 ? moment(opts.startDate) 652 : moment(day), 653 end = day.isAfter(opts.startDate) 654 ? moment(day) 655 : moment(opts.startDate), 656 isInvalidRange = opts.disableDates.filter(function(d) { 657 if ( 658 d instanceof Array || 659 Object.prototype.toString.call(d) === '[object Array]' 660 ) { 661 var _from = moment(d[0]), 662 _to = moment(d[1]); 663 664 return ( 665 _from.isValid() && 666 _to.isValid() && 667 (_from.isBetween(start, end, 'day', '[]') || 668 _to.isBetween(start, end, 'day', '[]')) 669 ); 670 } 671 672 return moment(d).isBetween(start, end, 'day', '[]'); 673 }); 674 675 if (isInvalidRange.length) { 676 self.setStartDate(null); 677 self.setEndDate(null); 678 679 target.dispatchEvent(new Event('mousedown')); 680 self.el.querySelector('.lightpick__tooltip').style.visibility = 681 'hidden'; 682 683 updateDates(self.el, opts); 684 return; 685 } 686 } 687 688 if ( 689 opts.singleDate || 690 (!opts.startDate && !opts.endDate) || 691 (opts.startDate && opts.endDate) 692 ) { 693 if (opts.repick && opts.startDate && opts.endDate) { 694 if (opts.repickTrigger === opts.field) { 695 self.setStartDate(day); 696 target.classList.add('is-start-date'); 697 } else { 698 self.setEndDate(day); 699 target.classList.add('is-end-date'); 700 } 701 702 if (opts.startDate.isAfter(opts.endDate)) { 703 self.swapDate(); 704 } 705 706 if (opts.autoclose) { 707 setTimeout(function() { 708 self.hide(); 709 }, 100); 710 } 711 } else { 712 self.setStartDate(day); 713 self.setEndDate(null); 714 715 target.classList.add('is-start-date'); 716 717 if (opts.singleDate && opts.autoclose) { 718 setTimeout(function() { 719 self.hide(); 720 }, 100); 721 } else if (!opts.singleDate || opts.inline || !opts.autoclose) { 722 updateDates(self.el, opts); 723 } 724 } 725 } else if (opts.startDate && !opts.endDate) { 726 self.setEndDate(day); 727 728 if (opts.startDate.isAfter(opts.endDate)) { 729 self.swapDate(); 730 } 731 732 target.classList.add('is-end-date'); 733 734 if (opts.autoclose) { 735 setTimeout(function() { 736 self.hide(); 737 }, 100); 738 } else { 739 updateDates(self.el, opts); 740 } 741 } 742 743 if (!opts.disabledDatesInRange) { 744 if ( 745 self.el.querySelectorAll('.lightpick__day.is-available') 746 .length === 0 747 ) { 748 self.setStartDate(null); 749 updateDates(self.el, opts); 750 751 if (opts.footer) { 752 if (typeof self._opts.onError === 'function') { 753 self._opts.onError.call(self, 'Invalid range'); 754 } else { 755 var footerMessage = self.el.querySelector( 756 '.lightpick__footer-message' 757 ); 758 759 if (footerMessage) { 760 footerMessage.innerHTML = opts.locale.not_allowed_range; 761 762 setTimeout(function() { 763 footerMessage.innerHTML = ''; 764 }, 3000); 765 } 766 } 767 } 768 } 769 } 770 } else if (target.classList.contains('lightpick__previous-action')) { 771 self.prevMonth(); 772 } else if (target.classList.contains('lightpick__next-action')) { 773 self.nextMonth(); 774 } else if ( 775 target.classList.contains('lightpick__close-action') || 776 target.classList.contains('lightpick__apply-action') 777 ) { 778 self.hide(); 779 } else if (target.classList.contains('lightpick__reset-action')) { 780 self.reset(); 781 } 782 }; 783 self._onMouseEnter = function(e) { 784 if (!self.isShowing) { 785 return; 786 } 787 788 e = e || window.event; 789 var target = e.target || e.srcElement; 790 if (!target) { 791 return; 792 } 793 794 var opts = self._opts; 795 796 if ( 797 target.classList.contains('lightpick__day') && 798 target.classList.contains('disabled-tooltip') && 799 opts.locale.tooltipOnDisabled 800 ) { 801 self.showTooltip(target, opts.locale.tooltipOnDisabled); 802 return; 803 } else { 804 self.hideTooltip(); 805 } 806 807 if (opts.singleDate || (!opts.startDate && !opts.endDate)) { 808 return; 809 } 810 811 if ( 812 !target.classList.contains('lightpick__day') && 813 !target.classList.contains('is-available') 814 ) { 815 return; 816 } 817 818 if ((opts.startDate && !opts.endDate) || opts.repick) { 819 var hoverDate = moment(parseInt(target.getAttribute('data-time'))); 820 821 if (!hoverDate.isValid()) { 822 return; 823 } 824 825 var startDate = 826 (opts.startDate && !opts.endDate) || 827 (opts.repick && opts.repickTrigger === opts.secondField) 828 ? opts.startDate 829 : opts.endDate; 830 831 var days = self.el.querySelectorAll('.lightpick__day'); 832 [].forEach.call(days, function(day) { 833 var dt = moment(parseInt(day.getAttribute('data-time'))); 834 835 day.classList.remove('is-flipped'); 836 837 if ( 838 dt.isValid() && 839 dt.isSameOrAfter(startDate, 'day') && 840 dt.isSameOrBefore(hoverDate, 'day') 841 ) { 842 day.classList.add('is-in-range'); 843 844 if ( 845 opts.repickTrigger === opts.field && 846 dt.isSameOrAfter(opts.endDate) 847 ) { 848 day.classList.add('is-flipped'); 849 } 850 } else if ( 851 dt.isValid() && 852 dt.isSameOrAfter(hoverDate, 'day') && 853 dt.isSameOrBefore(startDate, 'day') 854 ) { 855 day.classList.add('is-in-range'); 856 857 if ( 858 ((opts.startDate && !opts.endDate) || 859 opts.repickTrigger === opts.secondField) && 860 dt.isSameOrBefore(opts.startDate) 861 ) { 862 day.classList.add('is-flipped'); 863 } 864 } else { 865 day.classList.remove('is-in-range'); 866 } 867 868 if ( 869 opts.startDate && 870 opts.endDate && 871 opts.repick && 872 opts.repickTrigger === opts.field 873 ) { 874 day.classList.remove('is-start-date'); 875 } else { 876 day.classList.remove('is-end-date'); 877 } 878 }); 879 880 if (opts.hoveringTooltip) { 881 days = Math.abs( 882 hoverDate.isAfter(startDate) 883 ? hoverDate.diff(startDate, 'day') 884 : startDate.diff(hoverDate, 'day') 885 ); 886 887 if (!opts.tooltipNights) { 888 days += 1; 889 } 890 891 var tooltip = self.el.querySelector('.lightpick__tooltip'); 892 893 if (days > 0 && !target.classList.contains('is-disabled')) { 894 var pluralText = ''; 895 if (typeof opts.locale.pluralize === 'function') { 896 pluralText = opts.locale.pluralize.call( 897 self, 898 days, 899 opts.locale.tooltip 900 ); 901 } 902 903 self.showTooltip(target, days + ' ' + pluralText); 904 } else { 905 self.hideTooltip(); 906 } 907 } 908 909 if ( 910 opts.startDate && 911 opts.endDate && 912 opts.repick && 913 opts.repickTrigger === opts.field 914 ) { 915 target.classList.add('is-start-date'); 916 } else { 917 target.classList.add('is-end-date'); 918 } 919 } 920 }; 921 self._onChange = function(e) { 922 e = e || window.event; 923 var target = e.target || e.srcElement; 924 if (!target) { 925 return; 926 } 927 928 if (target.classList.contains('lightpick__select-months')) { 929 if (typeof self._opts.onMonthsChange === 'function') { 930 self._opts.onMonthsChange.call(this, target.value); 931 } 932 933 self.gotoMonth(target.value); 934 } else if (target.classList.contains('lightpick__select-years')) { 935 if (typeof self._opts.onYearsChange === 'function') { 936 self._opts.onYearsChange.call(this, target.value); 937 } 938 939 self.gotoYear(target.value); 940 } 941 }; 942 943 self._onInputChange = function(e) { 944 var target = e.target || e.srcElement; 945 946 if (self._opts.singleDate) { 947 if (!self._opts.autoclose) { 948 self.gotoDate(opts.field.value); 949 } 950 } 951 952 self.syncFields(); 953 954 if (!self.isShowing) { 955 self.show(); 956 } 957 }; 958 959 self._onInputFocus = function(e) { 960 var target = e.target || e.srcElement; 961 962 self.show(target); 963 }; 964 965 self._onInputClick = function(e) { 966 var target = e.target || e.srcElement; 967 968 self.show(target); 969 }; 970 971 self._onClick = function(e) { 972 e = e || window.event; 973 var target = e.target || e.srcElement, 974 parentEl = target; 975 976 if (!target) { 977 return; 978 } 979 980 do { 981 if ( 982 (parentEl.classList && parentEl.classList.contains('lightpick')) || 983 parentEl === opts.field || 984 (opts.secondField && parentEl === opts.secondField) 985 ) { 986 return; 987 } 988 } while ((parentEl = parentEl.parentNode)); 989 990 if ( 991 self.isShowing && 992 opts.hideOnBodyClick && 993 target !== opts.field && 994 parentEl !== opts.field 995 ) { 996 self.hide(); 997 } 998 }; 999 1000 self.showTooltip = function(target, text) { 1001 var tooltip = self.el.querySelector('.lightpick__tooltip'); 1002 1003 var hasParentEl = self.el.classList.contains('lightpick--inlined'), 1004 dayBounding = target.getBoundingClientRect(), 1005 pickerBouding = hasParentEl 1006 ? self.el.parentNode.getBoundingClientRect() 1007 : self.el.getBoundingClientRect(), 1008 _left = dayBounding.left - pickerBouding.left + dayBounding.width / 2, 1009 _top = dayBounding.top - pickerBouding.top; 1010 1011 tooltip.style.visibility = 'visible'; 1012 tooltip.textContent = text; 1013 1014 var tooltipBounding = tooltip.getBoundingClientRect(); 1015 1016 _top -= tooltipBounding.height; 1017 _left -= tooltipBounding.width / 2; 1018 1019 setTimeout(function() { 1020 tooltip.style.top = _top + 'px'; 1021 tooltip.style.left = _left + 'px'; 1022 }, 10); 1023 }; 1024 1025 self.hideTooltip = function() { 1026 var tooltip = self.el.querySelector('.lightpick__tooltip'); 1027 tooltip.style.visibility = 'hidden'; 1028 }; 1029 1030 self.el.addEventListener('mousedown', self._onMouseDown, true); 1031 self.el.addEventListener('mouseenter', self._onMouseEnter, true); 1032 self.el.addEventListener('touchend', self._onMouseDown, true); 1033 self.el.addEventListener('change', self._onChange, true); 1034 1035 if (opts.inline) { 1036 self.show(); 1037 } else { 1038 self.hide(); 1039 } 1040 1041 opts.field.addEventListener('change', self._onInputChange); 1042 opts.field.addEventListener('click', self._onInputClick); 1043 opts.field.addEventListener('focus', self._onInputFocus); 1044 1045 if (opts.secondField) { 1046 opts.secondField.addEventListener('change', self._onInputChange); 1047 opts.secondField.addEventListener('click', self._onInputClick); 1048 opts.secondField.addEventListener('focus', self._onInputFocus); 1049 } 1050 }; 1051 1052 Lightpick.prototype = { 1053 config: function(options) { 1054 var opts = Object.assign({}, defaults, options); 1055 1056 opts.field = opts.field && opts.field.nodeName ? opts.field : null; 1057 1058 opts.calendar = [moment().set('date', 1)]; 1059 1060 if (opts.numberOfMonths === 1 && opts.numberOfColumns > 1) { 1061 opts.numberOfColumns = 1; 1062 } 1063 1064 opts.minDate = 1065 opts.minDate && moment(opts.minDate, opts.format).isValid() 1066 ? moment(opts.minDate, opts.format) 1067 : null; 1068 1069 opts.maxDate = 1070 opts.maxDate && moment(opts.maxDate, opts.format).isValid() 1071 ? moment(opts.maxDate, opts.format) 1072 : null; 1073 1074 if (opts.lang === 'auto') { 1075 var browserLang = navigator.language || navigator.userLanguage; 1076 if (browserLang) { 1077 opts.lang = browserLang; 1078 } else { 1079 opts.lang = 'en-US'; 1080 } 1081 } 1082 1083 if (opts.secondField && opts.singleDate) { 1084 opts.singleDate = false; 1085 } 1086 1087 if (opts.hoveringTooltip && opts.singleDate) { 1088 opts.hoveringTooltip = false; 1089 } 1090 1091 if ( 1092 Object.prototype.toString.call(options.locale) === '[object Object]' 1093 ) { 1094 opts.locale = Object.assign({}, defaults.locale, options.locale); 1095 } 1096 1097 if (window.innerWidth < 480 && opts.numberOfMonths > 1) { 1098 opts.numberOfMonths = 1; 1099 opts.numberOfColumns = 1; 1100 } 1101 1102 if (opts.repick && !opts.secondField) { 1103 opts.repick = false; 1104 } 1105 1106 if (opts.inline) { 1107 opts.autoclose = false; 1108 opts.hideOnBodyClick = false; 1109 } 1110 1111 this._opts = Object.assign({}, opts); 1112 1113 this.syncFields(); 1114 1115 this.setStartDate(this._opts.startDate, true); 1116 this.setEndDate(this._opts.endDate, true); 1117 1118 return this._opts; 1119 }, 1120 1121 syncFields: function() { 1122 if (this._opts.singleDate || this._opts.secondField) { 1123 if (moment(this._opts.field.value, this._opts.format).isValid()) { 1124 this._opts.startDate = moment( 1125 this._opts.field.value, 1126 this._opts.format 1127 ); 1128 } 1129 1130 if ( 1131 this._opts.secondField && 1132 moment(this._opts.secondField.value, this._opts.format).isValid() 1133 ) { 1134 this._opts.endDate = moment( 1135 this._opts.secondField.value, 1136 this._opts.format 1137 ); 1138 } 1139 } else { 1140 var dates = this._opts.field.value.split(this._opts.separator); 1141 1142 if (dates.length === 2) { 1143 if (moment(dates[0], this._opts.format).isValid()) { 1144 this._opts.startDate = moment(dates[0], this._opts.format); 1145 } 1146 1147 if (moment(dates[1], this._opts.format).isValid()) { 1148 this._opts.endDate = moment(dates[1], this._opts.format); 1149 } 1150 } 1151 } 1152 }, 1153 1154 swapDate: function() { 1155 var tmp = moment(this._opts.startDate); 1156 this.setDateRange(this._opts.endDate, tmp); 1157 }, 1158 1159 gotoToday: function() { 1160 this.gotoDate(new Date()); 1161 }, 1162 1163 gotoDate: function(date) { 1164 var date = moment(date, this._opts.format); 1165 1166 if (!date.isValid()) { 1167 date = moment(); 1168 } 1169 1170 date.set('date', 1); 1171 1172 this._opts.calendar = [moment(date)]; 1173 1174 renderCalendar(this.el, this._opts); 1175 }, 1176 1177 gotoMonth: function(month) { 1178 if (isNaN(month)) { 1179 return; 1180 } 1181 1182 this._opts.calendar[0].set('month', month); 1183 1184 renderCalendar(this.el, this._opts); 1185 }, 1186 1187 gotoYear: function(year) { 1188 if (isNaN(year)) { 1189 return; 1190 } 1191 1192 this._opts.calendar[0].set('year', year); 1193 1194 renderCalendar(this.el, this._opts); 1195 }, 1196 1197 prevMonth: function() { 1198 this._opts.calendar[0] = moment(this._opts.calendar[0]).subtract( 1199 this._opts.numberOfMonths, 1200 'month' 1201 ); 1202 1203 renderCalendar(this.el, this._opts); 1204 1205 checkDisabledDatesInRange(this.el, this._opts); 1206 }, 1207 1208 nextMonth: function() { 1209 this._opts.calendar[0] = moment(this._opts.calendar[1]); 1210 1211 renderCalendar(this.el, this._opts); 1212 1213 checkDisabledDatesInRange(this.el, this._opts); 1214 }, 1215 1216 updatePosition: function() { 1217 if (this.el.classList.contains('lightpick--inlined')) return; 1218 1219 // remove `is-hidden` class for getBoundingClientRect 1220 this.el.classList.remove('is-hidden'); 1221 1222 var rect = this._opts.field.getBoundingClientRect(), 1223 calRect = this.el.getBoundingClientRect(), 1224 orientation = this._opts.orientation.split(' '), 1225 top = 0, 1226 left = 0; 1227 1228 if (orientation[0] == 'auto' || !/top|bottom/.test(orientation[0])) { 1229 if ( 1230 rect.bottom + calRect.height > window.innerHeight && 1231 window.pageYOffset > calRect.height 1232 ) { 1233 top = rect.top + window.pageYOffset - calRect.height; 1234 } else { 1235 top = rect.bottom + window.pageYOffset; 1236 } 1237 } else { 1238 top = rect[orientation[0]] + window.pageYOffset; 1239 1240 if (orientation[0] == 'top') { 1241 top -= calRect.height; 1242 } 1243 } 1244 1245 if ( 1246 !/left|right/.test(orientation[0]) && 1247 (!orientation[1] || 1248 orientation[1] == 'auto' || 1249 !/left|right/.test(orientation[1])) 1250 ) { 1251 if (rect.left + calRect.width > window.innerWidth) { 1252 left = rect.right + window.pageXOffset - calRect.width; 1253 } else { 1254 left = rect.left + window.pageXOffset; 1255 } 1256 } else { 1257 if (/left|right/.test(orientation[0])) { 1258 left = rect[orientation[0]] + window.pageXOffset; 1259 } else { 1260 left = rect[orientation[1]] + window.pageXOffset; 1261 } 1262 1263 if (orientation[0] == 'right' || orientation[1] == 'right') { 1264 left -= calRect.width; 1265 } 1266 } 1267 1268 this.el.classList.add('is-hidden'); 1269 1270 this.el.style.top = top + 'px'; 1271 this.el.style.left = left + 'px'; 1272 }, 1273 1274 setStartDate: function(date, preventOnSelect) { 1275 var dateISO = moment(date, moment.ISO_8601), 1276 dateOptFormat = moment(date, this._opts.format); 1277 1278 if (!dateISO.isValid() && !dateOptFormat.isValid()) { 1279 this._opts.startDate = null; 1280 this._opts.field.value = ''; 1281 return; 1282 } 1283 1284 this._opts.startDate = moment( 1285 dateISO.isValid() ? dateISO : dateOptFormat 1286 ); 1287 1288 if (this._opts.singleDate || this._opts.secondField) { 1289 this._opts.field.value = this._opts.startDate.format(this._opts.format); 1290 } else { 1291 this._opts.field.value = 1292 this._opts.startDate.format(this._opts.format) + 1293 this._opts.separator + 1294 '...'; 1295 } 1296 1297 if (!preventOnSelect && typeof this._opts.onSelect === 'function') { 1298 this._opts.onSelect.call(this, this.getStartDate(), this.getEndDate()); 1299 } 1300 1301 if ( 1302 !preventOnSelect && 1303 !this._opts.singleDate && 1304 typeof this._opts.onSelectStart === 'function' 1305 ) { 1306 this._opts.onSelectStart.call(this, this.getStartDate()); 1307 } 1308 }, 1309 1310 setEndDate: function(date, preventOnSelect) { 1311 var dateISO = moment(date, moment.ISO_8601), 1312 dateOptFormat = moment(date, this._opts.format); 1313 1314 if (!dateISO.isValid() && !dateOptFormat.isValid()) { 1315 this._opts.endDate = null; 1316 1317 if (this._opts.secondField) { 1318 this._opts.secondField.value = ''; 1319 } else if (!this._opts.singleDate && this._opts.startDate) { 1320 this._opts.field.value = 1321 this._opts.startDate.format(this._opts.format) + 1322 this._opts.separator + 1323 '...'; 1324 } 1325 return; 1326 } 1327 1328 this._opts.endDate = moment(dateISO.isValid() ? dateISO : dateOptFormat); 1329 1330 if (this._opts.secondField) { 1331 this._opts.field.value = this._opts.startDate.format(this._opts.format); 1332 this._opts.secondField.value = this._opts.endDate.format( 1333 this._opts.format 1334 ); 1335 } else { 1336 this._opts.field.value = 1337 this._opts.startDate.format(this._opts.format) + 1338 this._opts.separator + 1339 this._opts.endDate.format(this._opts.format); 1340 } 1341 1342 if (!preventOnSelect && typeof this._opts.onSelect === 'function') { 1343 this._opts.onSelect.call(this, this.getStartDate(), this.getEndDate()); 1344 } 1345 1346 if ( 1347 !preventOnSelect && 1348 !this._opts.singleDate && 1349 typeof this._opts.onSelectEnd === 'function' 1350 ) { 1351 this._opts.onSelectEnd.call(this, this.getEndDate()); 1352 } 1353 }, 1354 1355 setDate: function(date, preventOnSelect) { 1356 if (!this._opts.singleDate) { 1357 return; 1358 } 1359 this.setStartDate(date, preventOnSelect); 1360 1361 if (this.isShowing) { 1362 updateDates(this.el, this._opts); 1363 } 1364 }, 1365 1366 setDateRange: function(start, end, preventOnSelect) { 1367 if (this._opts.singleDate) { 1368 return; 1369 } 1370 this.setStartDate(start, true); 1371 this.setEndDate(end, true); 1372 1373 if (this.isShowing) { 1374 updateDates(this.el, this._opts); 1375 } 1376 1377 if (!preventOnSelect && typeof this._opts.onSelect === 'function') { 1378 this._opts.onSelect.call(this, this.getStartDate(), this.getEndDate()); 1379 } 1380 }, 1381 1382 setDisableDates: function(dates) { 1383 this._opts.disableDates = dates; 1384 1385 if (this.isShowing) { 1386 updateDates(this.el, this._opts); 1387 } 1388 }, 1389 1390 getStartDate: function() { 1391 return moment(this._opts.startDate).isValid() 1392 ? this._opts.startDate.clone() 1393 : null; 1394 }, 1395 1396 getEndDate: function() { 1397 return moment(this._opts.endDate).isValid() 1398 ? this._opts.endDate.clone() 1399 : null; 1400 }, 1401 1402 getDate: function() { 1403 return moment(this._opts.startDate).isValid() 1404 ? this._opts.startDate.clone() 1405 : null; 1406 }, 1407 1408 toString: function(format) { 1409 if (this._opts.singleDate) { 1410 return moment(this._opts.startDate).isValid() 1411 ? this._opts.startDate.format(format) 1412 : ''; 1413 } 1414 1415 if ( 1416 moment(this._opts.startDate).isValid() && 1417 moment(this._opts.endDate).isValid() 1418 ) { 1419 return ( 1420 this._opts.startDate.format(format) + 1421 this._opts.separator + 1422 this._opts.endDate.format(format) 1423 ); 1424 } 1425 1426 if ( 1427 moment(this._opts.startDate).isValid() && 1428 !moment(this._opts.endDate).isValid() 1429 ) { 1430 return ( 1431 this._opts.startDate.format(format) + this._opts.separator + '...' 1432 ); 1433 } 1434 1435 if ( 1436 !moment(this._opts.startDate).isValid() && 1437 moment(this._opts.endDate).isValid() 1438 ) { 1439 return '...' + this._opts.separator + this._opts.endDate.format(format); 1440 } 1441 1442 return ''; 1443 }, 1444 1445 show: function(target) { 1446 if (!this.isShowing) { 1447 this.isShowing = true; 1448 1449 if (this._opts.repick) { 1450 this._opts.repickTrigger = target; 1451 } 1452 1453 this.syncFields(); 1454 1455 if ( 1456 this._opts.secondField && 1457 this._opts.secondField === target && 1458 this._opts.endDate 1459 ) { 1460 this.gotoDate(this._opts.endDate); 1461 } else { 1462 this.gotoDate(this._opts.startDate || this._opts.minDate); 1463 } 1464 1465 document.addEventListener('mousedown', this._onClick); 1466 1467 this.updatePosition(); 1468 1469 this.el.classList.remove('is-hidden'); 1470 1471 if (typeof this._opts.onOpen === 'function') { 1472 this._opts.onOpen.call(this); 1473 } 1474 } 1475 }, 1476 1477 hide: function() { 1478 if (this.isShowing) { 1479 this.isShowing = false; 1480 1481 document.removeEventListener('mousedown', this._onClick); 1482 1483 this.el.classList.add('is-hidden'); 1484 1485 this.el.querySelector('.lightpick__tooltip').style.visibility = 1486 'hidden'; 1487 1488 if (typeof this._opts.onClose === 'function') { 1489 this._opts.onClose.call(this); 1490 } 1491 } 1492 }, 1493 1494 destroy: function() { 1495 var opts = this._opts; 1496 1497 this.hide(); 1498 1499 this.el.removeEventListener('mousedown', self._onMouseDown, true); 1500 this.el.removeEventListener('mouseenter', self._onMouseEnter, true); 1501 this.el.removeEventListener('touchend', self._onMouseDown, true); 1502 this.el.removeEventListener('change', self._onChange, true); 1503 1504 opts.field.removeEventListener('change', this._onInputChange); 1505 opts.field.removeEventListener('click', this._onInputClick); 1506 opts.field.removeEventListener('focus', this._onInputFocus); 1507 1508 if (opts.secondField) { 1509 opts.secondField.removeEventListener('change', this._onInputChange); 1510 opts.secondField.removeEventListener('click', this._onInputClick); 1511 opts.secondField.removeEventListener('focus', this._onInputFocus); 1512 } 1513 1514 if (this.el.parentNode) { 1515 this.el.parentNode.removeChild(this.el); 1516 } 1517 }, 1518 1519 reset: function() { 1520 this.setStartDate(null, true); 1521 this.setEndDate(null, true); 1522 1523 updateDates(this.el, this._opts); 1524 1525 if (typeof this._opts.onSelect === 'function') { 1526 this._opts.onSelect.call(this, this.getStartDate(), this.getEndDate()); 1527 } 1528 1529 this.el.querySelector('.lightpick__tooltip').style.visibility = 'hidden'; 1530 }, 1531 1532 reloadOptions: function(options) { 1533 var dropdowns = this._opts.dropdowns; 1534 var locale = this._opts.locale; 1535 1536 Object.assign(this._opts, this._opts, options); 1537 Object.assign(this._opts.dropdowns, dropdowns, options.dropdowns); 1538 Object.assign(this._opts.locale, locale, options.locale); 1539 } 1540 }; 1541 1542 return Lightpick; 1543});
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.