declare var require: any; declare var window: any; import { Component, ElementRef, Input, Output, EventEmitter, HostBinding, HostListener, OnInit } from "@angular/core"; import { Options } from "./daterangepicker-options"; import { Defaults } from "./daterangepicker-default-ranges"; import * as moment from "moment"; @Component({ selector: "date-range-picker", template: `
` }) export class DaterangepickerComponent implements OnInit { //inputs @Input() options: Options; @Input() class: string; //outputs @Output() rangeSelected = new EventEmitter(); //variables showCalendars: boolean; range: string = ""; enableApplyButton: boolean = false; areOldDatesStored: boolean = false; fromDate: any; toDate: any; tempFromDate: any; tempToDate: any; oldFromDate: any; oldToDate: any; fromMonth: number; toMonth: number; fromYear: number; toYear: number; format: string; defaultRanges: {}; //handle outside/inside click to show rangepicker @HostListener("document:mousedown", ["$event"]) @HostListener("document:mouseup", ["$event"]) handleOutsideClick(event) { if (!this.options.disabled) { let current: any = event.target; let host: any = this.elem.nativeElement; if (host.compareDocumentPosition) { if ( host.compareDocumentPosition(current) & window.Node.DOCUMENT_POSITION_CONTAINED_BY ) { this.storeOldDates(); return this.toggleCalendars(true); } } else if (host.contains) { if (host.contains(current)) { this.storeOldDates(); return this.toggleCalendars(true); } } else { do { if (current === host) { this.storeOldDates(); return this.toggleCalendars(true); } current = current.parentNode; } while (current); } if (this.showCalendars) { if (!this.isAutoApply()) { this.restoreOldDates(); } this.toggleCalendars(false); } } } constructor(private elem: ElementRef) { } toggleCalendars(value) { this.showCalendars = value; if (!value) { this.areOldDatesStored = false; this.updateCalendar(); } } updateCalendar() { //get month and year to show calendar var fromDate = this.fromDate || this.tempFromDate; var toDate = this.toDate || this.tempToDate; let tDate = moment(fromDate, this.format); this.fromMonth = tDate.get("month"); this.fromYear = tDate.get("year"); tDate = moment(toDate, this.format); this.toMonth = tDate.get("month"); this.toYear = tDate.get("year"); this.setRange(); } ngOnInit(): void { //get default options provided by user this.setFormat(); this.validateMinMaxDates(); this.setFromDate(this.options.startDate); this.setToDate(this.options.endDate); this.defaultRanges = this.validatePredefinedRanges( this.options.preDefinedRanges || Defaults.ranges ); //update calendar grid this.updateCalendar(); } getPositionClass(): string { let positionClass = "open-left"; if (this.options.position === "right") { positionClass = "open-right"; } if (this.options.position === "center" && !this.options.singleCalendar) { positionClass = "open-center"; } return positionClass; } setFormat() { if (this.options) { this.format = this.options.format || "YYYY-MM-DD"; } else { this.format = "YYYY-MM-DD"; } } validateMinMaxDates() { if (this.options) { //only mindate is suppplied if (this.options.minDate && !this.options.maxDate) { this.options.minDate = this.getMoment(this.options.minDate); } //only maxdate is supplied if (!this.options.minDate && this.options.maxDate) { this.options.maxDate = this.getMoment(this.options.maxDate); } //both min and max dates are supplied if (this.options.minDate && this.options.maxDate) { this.options.minDate = this.getMoment(this.options.minDate); this.options.maxDate = this.getMoment(this.options.maxDate); if (this.options.maxDate.isBefore(this.options.minDate, "date")) { this.options.minDate = ""; this.options.maxDate = ""; console.warn( "supplied minDate is after maxDate. Discarding options for minDate and maxDate" ); } } if ( this.options.minDate && this.options.minDate.format("HH:mm") === "00:00" ) { this.options.minDate.set({ hour: 0, minutes: 0, seconds: 0 }); } if ( this.options.maxDate && this.options.maxDate.format("HH:mm") === "00:00" ) { this.options.maxDate.set({ hour: 23, minutes: 59, seconds: 59 }); } } } setFromDate(value) { if (this.options.noDefaultRangeSelected && !value) { this.fromDate = ""; this.tempFromDate = this.getActualFromDate(value); } else { this.fromDate = this.getActualFromDate(value); } } getActualFromDate(value) { let temp; if ((temp = this.getValidateMoment(value))) { return this.getValidateFromDate(temp); } else { return this.getValidateFromDate(moment()); } } getValidateFromDate(value) { if (!this.options.timePicker) { if ( this.options.minDate && this.options.maxDate && value.isSameOrAfter(this.options.minDate, "date") && value.isSameOrBefore(this.options.maxDate, "date") ) { return value; } else if ( this.options.minDate && !this.options.maxDate && value.isAfter(this.options.minDate, "date") ) { return value; } else if (this.options.minDate) { return this.options.minDate.clone(); } else { return moment(); } } else { if ( this.options.minDate && this.options.maxDate && value.isSameOrAfter(this.options.minDate, this.options.format) && value.isSameOrBefore(this.options.maxDate, this.options.format) ) { return value; } else if ( this.options.minDate && !this.options.maxDate && value.isAfter(this.options.minDate, this.options.format) ) { return value; } else if (this.options.minDate) { return this.options.minDate.clone(); } else { return moment(); } } } setToDate(value) { if (this.options.noDefaultRangeSelected && !value) { this.toDate = ""; this.tempToDate = this.getActualToDate(value); } else { this.toDate = this.getActualToDate(value); } } getActualToDate(value) { let temp; if ((temp = this.getValidateMoment(value))) { return this.getValidateToDate(temp); } else { return this.getValidateToDate(moment()); } } getValidateToDate(value) { if (!this.options.timePicker) { if ( (this.options.maxDate && value.isSameOrAfter(this.fromDate, "date"), value.isSameOrBefore(this.options.maxDate, "date")) ) { return value; } else if (this.options.maxDate) { return this.options.maxDate.clone(); } else { return moment(); } } else { if ( (this.options.maxDate && value.isSameOrAfter(this.fromDate, this.options.format), value.isSameOrBefore(this.options.maxDate, this.options.format)) ) { return value; } else if (this.options.maxDate) { return this.options.maxDate.clone(); } else { return moment(); } } } //detects which date to set from or to and validates dateChanged(data) { let value = data.day; let isLeft = data.isLeft; if (isLeft) { if (!this.options.timePicker) { value.set({ hour: 0, minute: 0, second: 0 }); } this.fromDate = value; if (!this.options.timePicker) { if (value.isAfter(this.toDate, "date")) { this.toDate = this.fromDate.clone(); } } else { if (value.isAfter(this.toDate, this.options.format)) { this.toDate = this.fromDate.clone(); } } } else { if (!this.options.timePicker) { value.set({ hour: 23, minute: 59, second: 59 }); } //this.setToDate(value.format(this.format)); this.toDate = value; if (!this.options.timePicker) { if (value.isBefore(this.fromDate, "date")) { this.fromDate = this.toDate.clone(); } } else { if (value.isBefore(this.fromDate, this.options.format)) { this.fromDate = this.toDate.clone(); } } } if (this.isAutoApply()) { if (this.options.singleCalendar || !isLeft) { this.toggleCalendars(false); this.setRange(); this.emitRangeSelected(); } } else if (!this.options.singleCalendar && !isLeft) { this.enableApplyButton = true; } else if (this.options.singleCalendar) { this.enableApplyButton = true; } this.fromMonth = this.fromDate ? this.fromDate.get("month") : this.fromMonth; this.toMonth = this.toDate ? this.toDate.get("month") : this.toMonth; } emitRangeSelected() { let data = {}; if (this.options.singleCalendar) { data = { start: this.getMoment(this.fromDate) }; } else { data = { start: this.getMoment(this.fromDate), end: this.getMoment(this.toDate) }; } this.rangeSelected.emit(data); } getMoment(value) { return moment(value, this.format); } getValidateMoment(value) { let momentValue = null; if (moment(value, this.format, true).isValid()) { momentValue = moment(value, this.format, true); } return momentValue; } setRange() { const displayFormat = this.options.displayFormat !== undefined ? this.options.displayFormat : this.format; if (this.options.singleCalendar && this.fromDate) { this.range = this.fromDate.format(displayFormat); } else if (this.fromDate && this.toDate) { this.range = this.fromDate.format(displayFormat) + " - " + this.toDate.format(displayFormat); } else { this.range = ""; } } formatFromDate(event) { if (event.target.value !== this.fromDate.format(this.format)) { this.dateChanged({ day: event.target.value ? this.getMoment(event.target.value) : moment(), isLeft: true }); } } formatToDate(event) { if (event.target.value !== this.toDate.format(this.format)) { this.dateChanged({ day: event.target.value ? this.getMoment(event.target.value) : moment(), isLeft: false }); } } monthChanged(data) { let temp; if (data.isLeft) { temp = moment([this.fromYear, this.fromMonth]).add(data.value, "months"); this.fromMonth = temp.get("month"); this.fromYear = temp.get("year"); } else { temp = moment([this.toYear, this.toMonth]).add(data.value, "months"); this.toMonth = temp.get("month"); this.toYear = temp.get("year"); } } yearChanged(data) { let temp; if (data.isLeft) { temp = moment([this.fromYear, this.fromMonth]).add(data.value, "year"); this.fromMonth = temp.get("month"); this.fromYear = temp.get("year"); } else { temp = moment([this.toYear, this.toMonth]).add(data.value, "year"); this.toMonth = temp.get("month"); this.toYear = temp.get("year"); } } storeOldDates() { if (!this.areOldDatesStored) { this.oldFromDate = this.fromDate; this.oldToDate = this.toDate; this.areOldDatesStored = true; } } restoreOldDates() { this.fromDate = this.oldFromDate; this.toDate = this.oldToDate; } apply() { this.toggleCalendars(false); this.setRange(); this.emitRangeSelected(); } cancel() { this.restoreOldDates(); this.toggleCalendars(false); } clear() { this.fromDate = this.toDate = ""; this.apply(); this.enableApplyButton = false; this.emitRangeSelected(); } applyPredefinedRange(data) { this.setFromDate(data.value.start); this.setToDate(data.value.end); this.toggleCalendars(false); this.emitRangeSelected(); } validatePredefinedRanges(ranges) { return ranges.filter(range => { if (range.value.start.isAfter(range.value.end, "date")) { return false; } if ( this.options.minDate && range.value.start.isBefore(this.options.minDate, this.options.format) ) { return false; } if ( this.options.maxDate && range.value.end.isAfter(this.options.maxDate, this.options.format) ) { return false; } return true; }); } isAutoApply() { if (this.options.timePicker) { return false; } else if (this.options.singleCalendar) { return true; } else { return this.options.autoApply; } } }