UNPKG

ionic2-calendar

Version:
762 lines (758 loc) 185 kB
import * as i0 from '@angular/core'; import { Injectable, EventEmitter, Component, ViewChild, Input, Output, ViewEncapsulation, HostBinding, LOCALE_ID, Inject, NgModule } from '@angular/core'; import * as i2 from '@angular/common'; import { DatePipe, CommonModule } from '@angular/common'; import * as i2$1 from '@ionic/angular'; import { IonicSlides, IonicModule } from '@ionic/angular'; import SwiperCore, { Swiper } from 'swiper'; import { Subject } from 'rxjs'; class CalendarService { constructor() { this._currentDate = new Date(); this.currentDateChangedFromParent = new Subject(); this.currentDateChangedFromChildren = new Subject(); this.eventSourceChanged = new Subject(); this.slideChanged = new Subject(); this.slideUpdated = new Subject(); this.currentDateChangedFromParent$ = this.currentDateChangedFromParent.asObservable(); this.currentDateChangedFromChildren$ = this.currentDateChangedFromChildren.asObservable(); this.eventSourceChanged$ = this.eventSourceChanged.asObservable(); this.slideChanged$ = this.slideChanged.asObservable(); this.slideUpdated$ = this.slideUpdated.asObservable(); } setCurrentDate(val, fromParent = false) { this._currentDate = new Date(val); if (fromParent) { this.currentDateChangedFromParent.next(val); } else { this.currentDateChangedFromChildren.next(val); } } get currentDate() { return this._currentDate; } rangeChanged(component) { if (this.queryMode === 'local') { if (component.eventSource && component.onDataLoaded) { component.onDataLoaded(); } } else if (this.queryMode === 'remote') { let rangeStart = new Date(component.range.startTime.getTime()), rangeEnd = new Date(component.range.endTime.getTime()); rangeStart.setHours(0); if (rangeStart.getHours() === 23) { rangeStart.setTime(rangeStart.getTime() + 3600000); } rangeEnd.setHours(0); if (rangeEnd.getHours() === 23) { rangeEnd.setTime(rangeEnd.getTime() + 3600000); } component.onRangeChanged.emit({ startTime: rangeStart, endTime: rangeEnd }); } } getStep(mode) { switch (mode) { case 'month': return { years: 0, months: 1, days: 0 }; case 'week': return { years: 0, months: 0, days: 7 }; case 'day': return { years: 0, months: 0, days: 1 }; } } getAdjacentCalendarDate(mode, direction) { let calculateCalendarDate = this.currentDate; const step = this.getStep(mode), year = calculateCalendarDate.getFullYear() + direction * step.years, month = calculateCalendarDate.getMonth() + direction * step.months, date = calculateCalendarDate.getDate() + direction * step.days; calculateCalendarDate = new Date(year, month, date, 12, 0, 0); if (mode === 'month') { const firstDayInNextMonth = new Date(year, month + 1, 1, 12, 0, 0); if (firstDayInNextMonth.getTime() <= calculateCalendarDate.getTime()) { calculateCalendarDate = new Date(firstDayInNextMonth.getTime() - 24 * 60 * 60 * 1000); } } return calculateCalendarDate; } getAdjacentViewStartTime(component, direction) { let adjacentCalendarDate = this.getAdjacentCalendarDate(component.mode, direction); return component.getRange(adjacentCalendarDate).startTime; } populateAdjacentViews(component) { let currentViewStartDate, currentViewData, toUpdateViewIndex, currentViewIndex = component.currentViewIndex; if (component.direction === 1) { currentViewStartDate = this.getAdjacentViewStartTime(component, 1); toUpdateViewIndex = (currentViewIndex + 1) % 3; component.views[toUpdateViewIndex] = component.getViewData(currentViewStartDate); } else if (component.direction === -1) { currentViewStartDate = this.getAdjacentViewStartTime(component, -1); toUpdateViewIndex = (currentViewIndex + 2) % 3; component.views[toUpdateViewIndex] = component.getViewData(currentViewStartDate); } else { if (!component.views) { currentViewData = []; currentViewStartDate = component.range.startTime; currentViewData.push(component.getViewData(currentViewStartDate)); currentViewStartDate = this.getAdjacentViewStartTime(component, 1); currentViewData.push(component.getViewData(currentViewStartDate)); currentViewStartDate = this.getAdjacentViewStartTime(component, -1); currentViewData.push(component.getViewData(currentViewStartDate)); component.views = currentViewData; } else { currentViewStartDate = component.range.startTime; component.views[currentViewIndex] = component.getViewData(currentViewStartDate); currentViewStartDate = this.getAdjacentViewStartTime(component, -1); toUpdateViewIndex = (currentViewIndex + 2) % 3; component.views[toUpdateViewIndex] = component.getViewData(currentViewStartDate); currentViewStartDate = this.getAdjacentViewStartTime(component, 1); toUpdateViewIndex = (currentViewIndex + 1) % 3; component.views[toUpdateViewIndex] = component.getViewData(currentViewStartDate); } } } loadEvents() { this.eventSourceChanged.next(); } slide(direction) { this.slideChanged.next(direction); } update() { this.slideUpdated.next(); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: CalendarService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: CalendarService }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: CalendarService, decorators: [{ type: Injectable }], ctorParameters: () => [] }); class MonthViewComponent { constructor(calendarService, zone) { this.calendarService = calendarService; this.zone = zone; this.autoSelect = true; this.dir = ''; this.lockSwipeToPrev = false; this.lockSwipeToNext = false; this.lockSwipes = false; this.onRangeChanged = new EventEmitter(); this.onEventSelected = new EventEmitter(); this.onTimeSelected = new EventEmitter(); this.onTitleChanged = new EventEmitter(); this.views = []; this.currentViewIndex = 0; this.mode = 'month'; this.direction = 0; this.moveOnSelected = false; this.inited = false; } static getDates(startDate, n) { const dates = new Array(n), current = new Date(startDate.getTime()); let i = 0; while (i < n) { dates[i++] = new Date(current.getTime()); current.setDate(current.getDate() + 1); } return dates; } ngOnInit() { if (!this.sliderOptions) { this.sliderOptions = {}; } this.sliderOptions.loop = true; this.sliderOptions.allowSlidePrev = !this.lockSwipeToPrev; this.sliderOptions.allowSlideNext = !this.lockSwipeToNext; this.sliderOptions.allowTouchMove = !this.lockSwipes; if (this.dateFormatter && this.dateFormatter.formatMonthViewDay) { this.formatDayLabel = this.dateFormatter.formatMonthViewDay; } else { const dayLabelDatePipe = new DatePipe('en-US'); this.formatDayLabel = function (date) { return dayLabelDatePipe.transform(date, this.formatDay) || ''; }; } if (this.dateFormatter && this.dateFormatter.formatMonthViewDayHeader) { this.formatDayHeaderLabel = this.dateFormatter.formatMonthViewDayHeader; } else { const datePipe = new DatePipe(this.locale); this.formatDayHeaderLabel = function (date) { return datePipe.transform(date, this.formatDayHeader) || ''; }; } if (this.dateFormatter && this.dateFormatter.formatMonthViewTitle) { this.formatTitle = this.dateFormatter.formatMonthViewTitle; } else { const datePipe = new DatePipe(this.locale); this.formatTitle = function (date) { return datePipe.transform(date, this.formatMonthTitle) || ''; }; } this.refreshView(); this.inited = true; this.currentDateChangedFromParentSubscription = this.calendarService.currentDateChangedFromParent$.subscribe(currentDate => { this.refreshView(); }); this.eventSourceChangedSubscription = this.calendarService.eventSourceChanged$.subscribe(() => { this.onDataLoaded(); }); this.slideChangedSubscription = this.calendarService.slideChanged$.subscribe(direction => { if (direction === 1) { this.slider.slideNext(); } else if (direction === -1) { this.slider.slidePrev(); } }); this.slideUpdatedSubscription = this.calendarService.slideUpdated$.subscribe(() => { this.slider.update(); }); } ngOnDestroy() { if (this.currentDateChangedFromParentSubscription) { this.currentDateChangedFromParentSubscription.unsubscribe(); this.currentDateChangedFromParentSubscription = undefined; } if (this.eventSourceChangedSubscription) { this.eventSourceChangedSubscription.unsubscribe(); this.eventSourceChangedSubscription = undefined; } if (this.slideChangedSubscription) { this.slideChangedSubscription.unsubscribe(); this.slideChangedSubscription = undefined; } if (this.slideUpdatedSubscription) { this.slideUpdatedSubscription.unsubscribe(); this.slideUpdatedSubscription = undefined; } } ngOnChanges(changes) { if (!this.inited) { return; } const eventSourceChange = changes['eventSource']; if (eventSourceChange && eventSourceChange.currentValue) { this.onDataLoaded(); } const lockSwipeToPrev = changes['lockSwipeToPrev']; if (lockSwipeToPrev) { this.slider.allowSlidePrev = !lockSwipeToPrev.currentValue; } const lockSwipeToNext = changes['lockSwipeToNext']; if (lockSwipeToNext) { this.slider.allowSlideNext = !lockSwipeToNext.currentValue; } const lockSwipes = changes['lockSwipes']; if (lockSwipes) { this.slider.allowTouchMove = !lockSwipes.currentValue; } } ngAfterViewInit() { this.slider = new Swiper(this.swiperElement?.nativeElement, this.sliderOptions); let me = this; this.slider.on('slideNextTransitionEnd', function () { me.onSlideChanged(1); }); this.slider.on('slidePrevTransitionEnd', function () { me.onSlideChanged(-1); }); if (this.dir == 'rtl') { this.slider.changeLanguageDirection('rtl'); } const title = this.getTitle(); this.onTitleChanged.emit(title); } setSwiperInstance(swiper) { this.slider = swiper; } onSlideChanged(direction) { this.currentViewIndex = (this.currentViewIndex + direction + 3) % 3; this.move(direction); } move(direction) { if (direction === 0) { return; } this.direction = direction; if (!this.moveOnSelected) { const adjacentDate = this.calendarService.getAdjacentCalendarDate(this.mode, direction); this.calendarService.setCurrentDate(adjacentDate); } this.refreshView(); this.direction = 0; this.moveOnSelected = false; } createDateObject(date) { let disabled = false; if (this.markDisabled) { disabled = this.markDisabled(date); } return { date, events: [], label: this.formatDayLabel(date), secondary: false, disabled }; } getViewData(startTime) { const startDate = startTime, date = startDate.getDate(), month = (startDate.getMonth() + (date !== 1 ? 1 : 0)) % 12; const dates = MonthViewComponent.getDates(startDate, 42); const days = []; for (let i = 0; i < 42; i++) { const dateObject = this.createDateObject(dates[i]); dateObject.secondary = dates[i].getMonth() !== month; days[i] = dateObject; } const dayHeaders = []; for (let i = 0; i < 7; i++) { dayHeaders.push(this.formatDayHeaderLabel(days[i].date)); } return { dates: days, dayHeaders }; } getHighlightClass(date) { let className = ''; if (date.hasEvent) { if (date.secondary) { className = 'monthview-secondary-with-event'; } else { className = 'monthview-primary-with-event'; } } if (date.selected) { if (className) { className += ' '; } className += 'monthview-selected'; } if (date.current) { if (className) { className += ' '; } className += 'monthview-current'; } if (date.secondary) { if (className) { className += ' '; } className += 'text-muted'; } if (date.disabled) { if (className) { className += ' '; } className += 'monthview-disabled'; } return className; } getRange(currentDate) { const year = currentDate.getFullYear(), month = currentDate.getMonth(), firstDayOfMonth = new Date(year, month, 1, 12, 0, 0), // set hour to 12 to avoid DST problem difference = this.startingDayMonth - firstDayOfMonth.getDay(), numDisplayedFromPreviousMonth = (difference > 0) ? 7 - difference : -difference, startDate = new Date(firstDayOfMonth.getTime()); if (numDisplayedFromPreviousMonth > 0) { startDate.setDate(-numDisplayedFromPreviousMonth + 1); } const endDate = new Date(startDate.getTime()); endDate.setDate(endDate.getDate() + 42); return { startTime: startDate, endTime: endDate }; } onDataLoaded() { const range = this.range, eventSource = this.eventSource, len = eventSource ? eventSource.length : 0, startTime = range.startTime, endTime = range.endTime, utcStartTime = Date.UTC(startTime.getFullYear(), startTime.getMonth(), startTime.getDate()), utcEndTime = Date.UTC(endTime.getFullYear(), endTime.getMonth(), endTime.getDate()), currentViewIndex = this.currentViewIndex, dates = this.views[currentViewIndex].dates, oneDay = 86400000, eps = 0.0006; for (let r = 0; r < 42; r += 1) { if (dates[r].hasEvent) { dates[r].hasEvent = false; dates[r].events = []; } } for (let i = 0; i < len; i += 1) { const event = eventSource[i], eventStartTime = event.startTime, eventEndTime = event.endTime; let eventUTCStartTime, eventUTCEndTime; if (event.allDay) { eventUTCStartTime = eventStartTime.getTime(); eventUTCEndTime = eventEndTime.getTime(); } else { eventUTCStartTime = Date.UTC(eventStartTime.getFullYear(), eventStartTime.getMonth(), eventStartTime.getDate()); eventUTCEndTime = Date.UTC(eventEndTime.getFullYear(), eventEndTime.getMonth(), eventEndTime.getDate() + 1); } if (eventUTCEndTime <= utcStartTime || eventUTCStartTime >= utcEndTime) { continue; } let timeDifferenceStart, timeDifferenceEnd; if (eventUTCStartTime < utcStartTime) { timeDifferenceStart = 0; } else { timeDifferenceStart = (eventUTCStartTime - utcStartTime) / oneDay; } if (eventUTCEndTime > utcEndTime) { timeDifferenceEnd = (utcEndTime - utcStartTime) / oneDay; } else { timeDifferenceEnd = (eventUTCEndTime - utcStartTime) / oneDay; } let index = Math.floor(timeDifferenceStart); const endIndex = Math.ceil(timeDifferenceEnd - eps); while (index < endIndex) { dates[index].hasEvent = true; let eventSet = dates[index].events; if (eventSet) { eventSet.push(event); } else { eventSet = []; eventSet.push(event); dates[index].events = eventSet; } index += 1; } } for (let r = 0; r < 42; r += 1) { if (dates[r].hasEvent) { dates[r].events.sort(this.compareEvent); } } if (this.autoSelect) { let findSelected = false; for (let r = 0; r < 42; r += 1) { if (dates[r].selected) { this.selectedDate = dates[r]; findSelected = true; break; } } if (findSelected && this.selectedDate) { this.onTimeSelected.emit({ selectedTime: this.selectedDate.date, events: this.selectedDate.events, disabled: this.selectedDate.disabled }); } } } refreshView() { this.range = this.getRange(this.calendarService.currentDate); if (this.inited) { const title = this.getTitle(); this.onTitleChanged.emit(title); } this.calendarService.populateAdjacentViews(this); this.updateCurrentView(this.range.startTime, this.views[this.currentViewIndex]); this.calendarService.rangeChanged(this); } getTitle() { const currentViewStartDate = this.range.startTime, date = currentViewStartDate.getDate(), month = (currentViewStartDate.getMonth() + (date !== 1 ? 1 : 0)) % 12, year = currentViewStartDate.getFullYear() + (date !== 1 && month === 0 ? 1 : 0), headerDate = new Date(year, month, 1, 12, 0, 0, 0); return this.formatTitle(headerDate); } compareEvent(event1, event2) { if (event1.allDay) { return 1; } else if (event2.allDay) { return -1; } else { return (event1.startTime.getTime() - event2.startTime.getTime()); } } select(viewDate) { if (!this.views) { return; } const selectedDate = viewDate.date, events = viewDate.events; if (!viewDate.disabled) { const dates = this.views[this.currentViewIndex].dates, currentCalendarDate = this.calendarService.currentDate, currentMonth = currentCalendarDate.getMonth(), currentYear = currentCalendarDate.getFullYear(), selectedMonth = selectedDate.getMonth(), selectedYear = selectedDate.getFullYear(); let direction = 0; if (currentYear === selectedYear) { if (currentMonth !== selectedMonth) { direction = currentMonth < selectedMonth ? 1 : -1; } } else { direction = currentYear < selectedYear ? 1 : -1; } this.calendarService.setCurrentDate(selectedDate); if (direction === 0) { const currentViewStartDate = this.range.startTime, oneDay = 86400000, selectedDayDifference = Math.round((Date.UTC(selectedDate.getFullYear(), selectedDate.getMonth(), selectedDate.getDate()) - Date.UTC(currentViewStartDate.getFullYear(), currentViewStartDate.getMonth(), currentViewStartDate.getDate())) / oneDay); for (let r = 0; r < 42; r += 1) { dates[r].selected = false; } if (selectedDayDifference >= 0 && selectedDayDifference < 42) { dates[selectedDayDifference].selected = true; this.selectedDate = dates[selectedDayDifference]; } } else { this.moveOnSelected = true; this.slideView(direction); } } this.onTimeSelected.emit({ selectedTime: selectedDate, events, disabled: viewDate.disabled }); } slideView(direction) { if (direction === 1) { this.slider.slideNext(); } else if (direction === -1) { this.slider.slidePrev(); } } updateCurrentView(currentViewStartDate, view) { const currentCalendarDate = this.calendarService.currentDate, today = new Date(), oneDay = 86400000, selectedDayDifference = Math.round((Date.UTC(currentCalendarDate.getFullYear(), currentCalendarDate.getMonth(), currentCalendarDate.getDate()) - Date.UTC(currentViewStartDate.getFullYear(), currentViewStartDate.getMonth(), currentViewStartDate.getDate())) / oneDay), currentDayDifference = Math.round((Date.UTC(today.getFullYear(), today.getMonth(), today.getDate()) - Date.UTC(currentViewStartDate.getFullYear(), currentViewStartDate.getMonth(), currentViewStartDate.getDate())) / oneDay); for (let r = 0; r < 42; r += 1) { view.dates[r].selected = false; } if (selectedDayDifference >= 0 && selectedDayDifference < 42 && !view.dates[selectedDayDifference].disabled && (this.autoSelect || this.moveOnSelected)) { view.dates[selectedDayDifference].selected = true; this.selectedDate = view.dates[selectedDayDifference]; } else { this.selectedDate = undefined; } if (currentDayDifference >= 0 && currentDayDifference < 42) { view.dates[currentDayDifference].current = true; } } eventSelected(event) { this.onEventSelected.emit(event); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: MonthViewComponent, deps: [{ token: CalendarService }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.0.5", type: MonthViewComponent, isStandalone: false, selector: "monthview", inputs: { monthviewDisplayEventTemplate: "monthviewDisplayEventTemplate", monthviewInactiveDisplayEventTemplate: "monthviewInactiveDisplayEventTemplate", monthviewEventDetailTemplate: "monthviewEventDetailTemplate", formatDay: "formatDay", formatDayHeader: "formatDayHeader", formatMonthTitle: "formatMonthTitle", eventSource: "eventSource", startingDayMonth: "startingDayMonth", showEventDetail: "showEventDetail", noEventsLabel: "noEventsLabel", autoSelect: "autoSelect", markDisabled: "markDisabled", locale: "locale", dateFormatter: "dateFormatter", dir: "dir", lockSwipeToPrev: "lockSwipeToPrev", lockSwipeToNext: "lockSwipeToNext", lockSwipes: "lockSwipes", sliderOptions: "sliderOptions" }, outputs: { onRangeChanged: "onRangeChanged", onEventSelected: "onEventSelected", onTimeSelected: "onTimeSelected", onTitleChanged: "onTitleChanged" }, viewQueries: [{ propertyName: "swiperElement", first: true, predicate: ["monthViewSwiper"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"swiper monthview-swiper\" #monthViewSwiper>\r\n <div class=\"swiper-wrapper\">\r\n <div class=\"swiper-slide\">\r\n <table *ngIf=\"0===currentViewIndex\" class=\"table table-bordered table-fixed monthview-datetable\">\r\n <thead>\r\n <tr>\r\n <th *ngFor=\"let dayHeader of views[0].dayHeaders\">\r\n <small>{{dayHeader}}</small>\r\n </th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n <tr *ngFor=\"let row of [0,1,2,3,4,5]\">\r\n <td *ngFor=\"let col of [0,1,2,3,4,5,6]\" tappable (click)=\"select(views[0].dates[row*7+col])\"\r\n [ngClass]=\"getHighlightClass(views[0].dates[row*7+col])\">\r\n <ng-template [ngTemplateOutlet]=\"monthviewDisplayEventTemplate\"\r\n [ngTemplateOutletContext]=\"{view: views[0], row: row, col: col}\">\r\n </ng-template>\r\n </td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n <table *ngIf=\"0!==currentViewIndex\" class=\"table table-bordered table-fixed monthview-datetable\">\r\n <thead>\r\n <tr class=\"text-center\">\r\n <th *ngFor=\"let dayHeader of views[0].dayHeaders\">\r\n <small>{{dayHeader}}</small>\r\n </th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n <tr *ngFor=\"let row of [0,1,2,3,4,5]\">\r\n <td *ngFor=\"let col of [0,1,2,3,4,5,6]\">\r\n <ng-template [ngTemplateOutlet]=\"monthviewInactiveDisplayEventTemplate\"\r\n [ngTemplateOutletContext]=\"{view: views[0], row: row, col: col}\">\r\n </ng-template>\r\n </td>\r\n <tr>\r\n </tbody>\r\n </table>\r\n </div>\r\n <div class=\"swiper-slide\">\r\n <table *ngIf=\"1===currentViewIndex\" class=\"table table-bordered table-fixed monthview-datetable\">\r\n <thead>\r\n <tr>\r\n <th *ngFor=\"let dayHeader of views[1].dayHeaders\">\r\n <small>{{dayHeader}}</small>\r\n </th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n <tr *ngFor=\"let row of [0,1,2,3,4,5]\">\r\n <td *ngFor=\"let col of [0,1,2,3,4,5,6]\" tappable (click)=\"select(views[1].dates[row*7+col])\"\r\n [ngClass]=\"getHighlightClass(views[1].dates[row*7+col])\">\r\n <ng-template [ngTemplateOutlet]=\"monthviewDisplayEventTemplate\"\r\n [ngTemplateOutletContext]=\"{view: views[1], row: row, col: col}\">\r\n </ng-template>\r\n </td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n <table *ngIf=\"1!==currentViewIndex\" class=\"table table-bordered table-fixed monthview-datetable\">\r\n <thead>\r\n <tr class=\"text-center\">\r\n <th *ngFor=\"let dayHeader of views[1].dayHeaders\">\r\n <small>{{dayHeader}}</small>\r\n </th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n <tr *ngFor=\"let row of [0,1,2,3,4,5]\">\r\n <td *ngFor=\"let col of [0,1,2,3,4,5,6]\">\r\n <ng-template [ngTemplateOutlet]=\"monthviewInactiveDisplayEventTemplate\"\r\n [ngTemplateOutletContext]=\"{view: views[1], row: row, col: col}\">\r\n </ng-template>\r\n </td>\r\n <tr>\r\n </tbody>\r\n </table>\r\n </div>\r\n <div class=\"swiper-slide\">\r\n <table *ngIf=\"2===currentViewIndex\" class=\"table table-bordered table-fixed monthview-datetable\">\r\n <thead>\r\n <tr>\r\n <th *ngFor=\"let dayHeader of views[2].dayHeaders\">\r\n <small>{{dayHeader}}</small>\r\n </th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n <tr *ngFor=\"let row of [0,1,2,3,4,5]\">\r\n <td *ngFor=\"let col of [0,1,2,3,4,5,6]\" tappable (click)=\"select(views[2].dates[row*7+col])\"\r\n [ngClass]=\"getHighlightClass(views[2].dates[row*7+col])\">\r\n <ng-template [ngTemplateOutlet]=\"monthviewDisplayEventTemplate\"\r\n [ngTemplateOutletContext]=\"{view: views[2], row: row, col: col}\">\r\n </ng-template>\r\n </td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n <table *ngIf=\"2!==currentViewIndex\" class=\"table table-bordered table-fixed monthview-datetable\">\r\n <thead>\r\n <tr class=\"text-center\">\r\n <th *ngFor=\"let dayHeader of views[2].dayHeaders\">\r\n <small>{{dayHeader}}</small>\r\n </th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n <tr *ngFor=\"let row of [0,1,2,3,4,5]\">\r\n <td *ngFor=\"let col of [0,1,2,3,4,5,6]\">\r\n <ng-template [ngTemplateOutlet]=\"monthviewInactiveDisplayEventTemplate\"\r\n [ngTemplateOutletContext]=\"{view: views[2], row: row, col: col}\">\r\n </ng-template>\r\n </td>\r\n <tr>\r\n </tbody>\r\n </table>\r\n </div>\r\n </div>\r\n <ng-template [ngTemplateOutlet]=\"monthviewEventDetailTemplate\"\r\n [ngTemplateOutletContext]=\"{showEventDetail:showEventDetail, selectedDate: selectedDate, noEventsLabel: noEventsLabel}\">\r\n </ng-template>\r\n</div>", styles: [".text-muted{color:#999}.table-fixed{table-layout:fixed}.table{width:100%;max-width:100%;background-color:transparent}.table>thead>tr>th,.table>tbody>tr>th,.table>tfoot>tr>th,.table>thead>tr>td,.table>tbody>tr>td,.table>tfoot>tr>td{padding:8px;line-height:20px;vertical-align:top}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>thead:first-child>tr:first-child>th,.table>thead:first-child>tr:first-child>td{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table-bordered{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>tbody>tr>td,.table-bordered>tfoot>tr>td{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>thead>tr>td{border-bottom-width:2px}.table-striped>tbody>tr:nth-child(odd)>td,.table-striped>tbody>tr:nth-child(odd)>th{background-color:#f9f9f9}.monthview-primary-with-event{background-color:#3a87ad;color:#fff}.monthview-current{background-color:#f0f0f0}.monthview-selected{background-color:#090;color:#fff}.monthview-datetable td.monthview-disabled{color:#d3d3d3;cursor:default}.monthview-datetable th{text-align:center}.monthview-datetable td{cursor:pointer;text-align:center}.monthview-secondary-with-event{background-color:#d9edf7}::-webkit-scrollbar,*::-webkit-scrollbar{display:none}\n"], dependencies: [{ kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: MonthViewComponent, decorators: [{ type: Component, args: [{ selector: 'monthview', standalone: false, template: "<div class=\"swiper monthview-swiper\" #monthViewSwiper>\r\n <div class=\"swiper-wrapper\">\r\n <div class=\"swiper-slide\">\r\n <table *ngIf=\"0===currentViewIndex\" class=\"table table-bordered table-fixed monthview-datetable\">\r\n <thead>\r\n <tr>\r\n <th *ngFor=\"let dayHeader of views[0].dayHeaders\">\r\n <small>{{dayHeader}}</small>\r\n </th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n <tr *ngFor=\"let row of [0,1,2,3,4,5]\">\r\n <td *ngFor=\"let col of [0,1,2,3,4,5,6]\" tappable (click)=\"select(views[0].dates[row*7+col])\"\r\n [ngClass]=\"getHighlightClass(views[0].dates[row*7+col])\">\r\n <ng-template [ngTemplateOutlet]=\"monthviewDisplayEventTemplate\"\r\n [ngTemplateOutletContext]=\"{view: views[0], row: row, col: col}\">\r\n </ng-template>\r\n </td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n <table *ngIf=\"0!==currentViewIndex\" class=\"table table-bordered table-fixed monthview-datetable\">\r\n <thead>\r\n <tr class=\"text-center\">\r\n <th *ngFor=\"let dayHeader of views[0].dayHeaders\">\r\n <small>{{dayHeader}}</small>\r\n </th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n <tr *ngFor=\"let row of [0,1,2,3,4,5]\">\r\n <td *ngFor=\"let col of [0,1,2,3,4,5,6]\">\r\n <ng-template [ngTemplateOutlet]=\"monthviewInactiveDisplayEventTemplate\"\r\n [ngTemplateOutletContext]=\"{view: views[0], row: row, col: col}\">\r\n </ng-template>\r\n </td>\r\n <tr>\r\n </tbody>\r\n </table>\r\n </div>\r\n <div class=\"swiper-slide\">\r\n <table *ngIf=\"1===currentViewIndex\" class=\"table table-bordered table-fixed monthview-datetable\">\r\n <thead>\r\n <tr>\r\n <th *ngFor=\"let dayHeader of views[1].dayHeaders\">\r\n <small>{{dayHeader}}</small>\r\n </th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n <tr *ngFor=\"let row of [0,1,2,3,4,5]\">\r\n <td *ngFor=\"let col of [0,1,2,3,4,5,6]\" tappable (click)=\"select(views[1].dates[row*7+col])\"\r\n [ngClass]=\"getHighlightClass(views[1].dates[row*7+col])\">\r\n <ng-template [ngTemplateOutlet]=\"monthviewDisplayEventTemplate\"\r\n [ngTemplateOutletContext]=\"{view: views[1], row: row, col: col}\">\r\n </ng-template>\r\n </td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n <table *ngIf=\"1!==currentViewIndex\" class=\"table table-bordered table-fixed monthview-datetable\">\r\n <thead>\r\n <tr class=\"text-center\">\r\n <th *ngFor=\"let dayHeader of views[1].dayHeaders\">\r\n <small>{{dayHeader}}</small>\r\n </th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n <tr *ngFor=\"let row of [0,1,2,3,4,5]\">\r\n <td *ngFor=\"let col of [0,1,2,3,4,5,6]\">\r\n <ng-template [ngTemplateOutlet]=\"monthviewInactiveDisplayEventTemplate\"\r\n [ngTemplateOutletContext]=\"{view: views[1], row: row, col: col}\">\r\n </ng-template>\r\n </td>\r\n <tr>\r\n </tbody>\r\n </table>\r\n </div>\r\n <div class=\"swiper-slide\">\r\n <table *ngIf=\"2===currentViewIndex\" class=\"table table-bordered table-fixed monthview-datetable\">\r\n <thead>\r\n <tr>\r\n <th *ngFor=\"let dayHeader of views[2].dayHeaders\">\r\n <small>{{dayHeader}}</small>\r\n </th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n <tr *ngFor=\"let row of [0,1,2,3,4,5]\">\r\n <td *ngFor=\"let col of [0,1,2,3,4,5,6]\" tappable (click)=\"select(views[2].dates[row*7+col])\"\r\n [ngClass]=\"getHighlightClass(views[2].dates[row*7+col])\">\r\n <ng-template [ngTemplateOutlet]=\"monthviewDisplayEventTemplate\"\r\n [ngTemplateOutletContext]=\"{view: views[2], row: row, col: col}\">\r\n </ng-template>\r\n </td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n <table *ngIf=\"2!==currentViewIndex\" class=\"table table-bordered table-fixed monthview-datetable\">\r\n <thead>\r\n <tr class=\"text-center\">\r\n <th *ngFor=\"let dayHeader of views[2].dayHeaders\">\r\n <small>{{dayHeader}}</small>\r\n </th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n <tr *ngFor=\"let row of [0,1,2,3,4,5]\">\r\n <td *ngFor=\"let col of [0,1,2,3,4,5,6]\">\r\n <ng-template [ngTemplateOutlet]=\"monthviewInactiveDisplayEventTemplate\"\r\n [ngTemplateOutletContext]=\"{view: views[2], row: row, col: col}\">\r\n </ng-template>\r\n </td>\r\n <tr>\r\n </tbody>\r\n </table>\r\n </div>\r\n </div>\r\n <ng-template [ngTemplateOutlet]=\"monthviewEventDetailTemplate\"\r\n [ngTemplateOutletContext]=\"{showEventDetail:showEventDetail, selectedDate: selectedDate, noEventsLabel: noEventsLabel}\">\r\n </ng-template>\r\n</div>", styles: [".text-muted{color:#999}.table-fixed{table-layout:fixed}.table{width:100%;max-width:100%;background-color:transparent}.table>thead>tr>th,.table>tbody>tr>th,.table>tfoot>tr>th,.table>thead>tr>td,.table>tbody>tr>td,.table>tfoot>tr>td{padding:8px;line-height:20px;vertical-align:top}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>thead:first-child>tr:first-child>th,.table>thead:first-child>tr:first-child>td{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table-bordered{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>tbody>tr>td,.table-bordered>tfoot>tr>td{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>thead>tr>td{border-bottom-width:2px}.table-striped>tbody>tr:nth-child(odd)>td,.table-striped>tbody>tr:nth-child(odd)>th{background-color:#f9f9f9}.monthview-primary-with-event{background-color:#3a87ad;color:#fff}.monthview-current{background-color:#f0f0f0}.monthview-selected{background-color:#090;color:#fff}.monthview-datetable td.monthview-disabled{color:#d3d3d3;cursor:default}.monthview-datetable th{text-align:center}.monthview-datetable td{cursor:pointer;text-align:center}.monthview-secondary-with-event{background-color:#d9edf7}::-webkit-scrollbar,*::-webkit-scrollbar{display:none}\n"] }] }], ctorParameters: () => [{ type: CalendarService }, { type: i0.NgZone }], propDecorators: { swiperElement: [{ type: ViewChild, args: ['monthViewSwiper'] }], monthviewDisplayEventTemplate: [{ type: Input }], monthviewInactiveDisplayEventTemplate: [{ type: Input }], monthviewEventDetailTemplate: [{ type: Input }], formatDay: [{ type: Input }], formatDayHeader: [{ type: Input }], formatMonthTitle: [{ type: Input }], eventSource: [{ type: Input }], startingDayMonth: [{ type: Input }], showEventDetail: [{ type: Input }], noEventsLabel: [{ type: Input }], autoSelect: [{ type: Input }], markDisabled: [{ type: Input }], locale: [{ type: Input }], dateFormatter: [{ type: Input }], dir: [{ type: Input }], lockSwipeToPrev: [{ type: Input }], lockSwipeToNext: [{ type: Input }], lockSwipes: [{ type: Input }], sliderOptions: [{ type: Input }], onRangeChanged: [{ type: Output }], onEventSelected: [{ type: Output }], onTimeSelected: [{ type: Output }], onTitleChanged: [{ type: Output }] } }); class initPositionScrollComponent { constructor(el, ngZone) { this.ngZone = ngZone; this.onScroll = new EventEmitter(); this.listenerAttached = false; this.element = el; } ngOnChanges(changes) { let initPosition = changes['initPosition']; if (initPosition && initPosition.currentValue !== undefined && this.scrollContent && initPosition.currentValue != this.scrollContent.scrollTop) { const me = this; this.ngZone.run(() => { me.scrollContent.scrollTop = initPosition.currentValue; }); } } ngAfterViewInit() { const scrollContent = this.scrollContent = this.element.nativeElement.querySelector('.scroll-content'); if (this.initPosition !== undefined) { scrollContent.scrollTop = this.initPosition; } if (this.emitEvent && !this.listenerAttached) { let onScroll = this.onScroll; let me = this; this.handler = function () { if (me.initPosition != scrollContent.scrollTop) { onScroll.emit(scrollContent.scrollTop); } }; this.listenerAttached = true; scrollContent.addEventListener('scroll', this.handler); } } ngOnDestroy() { if (this.listenerAttached) { this.scrollContent.removeEventListener('scroll', this.handler); this.listenerAttached = false; } } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: initPositionScrollComponent, deps: [{ token: i0.ElementRef }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.0.5", type: initPositionScrollComponent, isStandalone: false, selector: "init-position-scroll", inputs: { initPosition: "initPosition", emitEvent: "emitEvent" }, outputs: { onScroll: "onScroll" }, usesOnChanges: true, ngImport: i0, template: ` <div class="scroll-content" style="height:100%"> <ng-content></ng-content> </div> `, isInline: true, styles: [".scroll-content{overflow-y:auto;overflow-x:hidden}\n"], encapsulation: i0.ViewEncapsulation.None }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: initPositionScrollComponent, decorators: [{ type: Component, args: [{ selector: 'init-position-scroll', template: ` <div class="scroll-content" style="height:100%"> <ng-content></ng-content> </div> `, encapsulation: ViewEncapsulation.None, standalone: false, styles: [".scroll-content{overflow-y:auto;overflow-x:hidden}\n"] }] }], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.NgZone }], propDecorators: { initPosition: [{ type: Input }], emitEvent: [{ type: Input }], onScroll: [{ type: Output }] } }); class WeekViewComponent { constructor(calendarService, elm, zone) { this.calendarService = calendarService; this.elm = elm; this.zone = zone; this.class = true; this.autoSelect = true; this.dir = ''; this.scrollToHour = 0; this.onRangeChanged = new EventEmitter(); this.onEventSelected = new EventEmitter(); this.onTimeSelected = new EventEmitter(); this.onDayHeaderSelected = new EventEmitter(); this.onTitleChanged = new EventEmitter(); this.sliderIndexList = [0, 1, 2]; this.views = []; this.currentViewIndex = 0; this.direction = 0; this.mode = 'week'; this.inited = false; } static createDateObjects(startTime, startHour, endHour, timeInterval) { const times = [], currentHour = 0, currentDate = startTime.getDate(); let hourStep, minStep; if (timeInterval < 1) { hourStep = Math.floor(1 / timeInterval); minStep = 60; } else { hourStep = 1; minStep = Math.floor(60 / timeInterval); } for (let hour = startHour; hour < endHour; hour += hourStep) { for (let interval = 0; interval < 60; interval += minStep) { const row = []; for (let day = 0; day < 7; day += 1) { const time = new Date(startTime.getTime()); time.setHours(currentHour + hour, interval); time.setDate(currentDate + day); row.push({ events: [], time }); } times.push(row); } } return times; } static getDates(startTime, n) { const dates = new Array(n), current = new Date(startTime.getTime()); let i = 0; while (i < n) { dates[i++] = { date: new Date(current.getTime()), events: [], dayHeader: '' }; current.setDate(current.getDate() + 1); } return dates; } static compareEventByStartOffset(eventA, eventB) { return eventA.startOffset - eventB.startOffset; } static calculateWidth(orderedEvents, size, hourParts) { const totalSize = size * hourParts, cells = new Array(totalSize); // sort by position in descending order, the right most columns should be calculated first orderedEvents.sort((eventA, eventB) => { return eventB.position - eventA.position; }); for (let i = 0; i < totalSize; i += 1) { cells[i] = { calculated: false, events: [] }; } const len = orderedEvents.length; for (let i = 0; i < len; i += 1) { const event = orderedEvents[i]; let index = event.startIndex * hourParts + event.startOffset; while (index < event.endIndex * hourParts - event.endOffset) { cells[index].events.push(event); index += 1; } } let i = 0; while (i < len) { let event = orderedEvents[i]; if (!event.overlapNumber) { const overlapNumber = event.position + 1; event.overlapNumber = overlapNumber; const eventQueue = [event]; while (event = eventQueue.shift()) { let index = event.startIndex * hourParts + event.startOffset; while (index < event.endIndex * hourParts - event.endOffset) { if (!cells[index].calculated) { cells[index].calculated = true; if (cells[index].events) { const eventCountInCell = cells[index].events.le