Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Typescript 替换“switch”并基于属性调用子方法_Typescript - Fatal编程技术网

Typescript 替换“switch”并基于属性调用子方法

Typescript 替换“switch”并基于属性调用子方法,typescript,Typescript,我是新手。我有日历,有3个视图(目前)。我有一个abstract类,它只创建table对象,一个abstractCalendarTable类,它包含一些setter和getter以及abstract方法,还有一个子类Calendar,它覆盖了基类方法。问题是每个方法都有一个开关,它根据我的属性currentView调用视图的方法,其中每个视图都是在日历构造函数中实例化的 日历 export class Calendar extends my.core.calendar.CalendarTable

我是新手。我有
日历
,有3个
视图
(目前)。我有一个
abstract
类,它只创建
table
对象,一个
abstract
CalendarTable类,它包含一些setter和getter以及
abstract
方法,还有一个子类Calendar,它覆盖了基类方法。问题是每个方法都有一个
开关
,它根据我的属性
currentView
调用
视图的
方法,其中每个视图都是
日历构造函数中实例化的

日历

export class Calendar extends my.core.calendar.CalendarTable {
        weeklyView: my.calendar.WeeklyView;
        monthlyView: my.calendar.MontlyView;
        dayView: my.calendar.DayView;

        constructor(cfg: my.core.calendar.iCalendarConfiguration) {
            super(cfg);

            this.weeklyView = new my.calendar.WeeklyView(this);
            this.monthlyView = new my.calendar.MontlyView(this);
            this.dayView = new my.calendar.DayView(this);
        }


        onResize(): void {
            /**
             *  Repaint all appointments on window resize
             *  For many reasons
             */
            this.bindAppointments();
        }

        createCalendar(): void {

            /** Clear everything on change */
            if (this.tBody.rows.length > 0) {
                this.tBody.clear();
                this.tHead.clear();
            }

            switch (this.config.currentView) {
                case "month":
                    this.monthlyView.createMontlyView();
                    break;
                case "day":
                    this.dayView.createDayView();
                    break;
                case "week":
                    this.weeklyView.createWeeklyView();
                    break;
            }

            this.bindAppointments();
        }

        bindAppointments(): void {
            this.clearAll();

            switch (this.config.currentView) {
                case "month":
                    this.monthlyView.bindMonthAppointments();
                    break;
                case "day":
                    this.dayView.bindDayAppointments();
                    break;
                case "week":
                    this.weeklyView.bindWeekAppointments();
                    break;
            }
        }

        Next(sender, e, data): void {
            switch (this.config.currentView) {
                case "month":
                    this.monthlyView.monthNavigationChange(true);
                    break;
                case "day":
                    this.dayView.dayNavigationChange(true);
                    break;
                case "week":
                    this.weeklyView.weekNavigationChange(true);
                    break;
            }
            this.createCalendar();
            this.updateLabels();
        }

        Previous(sender, e, data): void {
            switch (this.config.currentView) {
                case "month":
                    this.monthlyView.monthNavigationChange(false);
                    break;
                case "day":
                    this.dayView.dayNavigationChange(false);
                    break;
                case "week":
                    this.weeklyView.weekNavigationChange(false);
                    break;
            }
            this.createCalendar();
            this.updateLabels();
        }

        TabClick(sender: any, event: any, data: any): void {

            switch (sender.id.toLowerCase()) {
                case "day":
                    this.setActiveTab('day', event);
                    // update currentdate
                    break;
                case "month":
                    this.setActiveTab('month', event);
                    // update currentdate
                    break;
                case "week":
                    this.setActiveTab('week', event);
                    // update currentdate
                    break;
            }
            this.createCalendar();
            this.updateLabels();
        }


        updateLabels(): void {
            let date = new Date(this.config.currentDate);
            switch (this.config.currentView) {
                case "month":
                    this.currentDateMonth.value = String(this.calendar_months_label[date.getMonth()]) + ' ' + String(date.getFullYear());
                    break;
                case "day":
                    this.currentDateMonth.value = String(this.config.currentDate.getDate()) + ' ' + String(this.calendar_months_label[this.config.currentDate.getMonth()]) + ' ' + String(this.config.currentDate.getFullYear());
                    break;
                case "week":
                    this.currentDateMonth.value = String(this.getPreviousWeekStr(this.weekStart, this.weekEnd, this.calendar_months_label[this.config.currentDate.getMonth()], this.config.currentDate.getFullYear()));
                    break;
            }
        }
我认为这个设计很糟糕。我的基本用户处理程序是
TabClick、Next、Previous
。如何使每个
视图
类扩展日历并重写其方法,以及当一个处理程序触发以调用适当的视图重写方法而不必切换以确定我当前的视图是什么并调用实例化的类方法时

附加一个
视图
类以了解每个视图类的基本内容。其他2个有类似的方法,只是渲染逻辑、计算等不同

export class MontlyView {
        table: my.core.calendar.CalendarTable;

        EVENTS_DIV: string = 'cal-monthview-events-div';
        EVENTS_WRAPPER: string = 'cal-monthview-events-wrapper';

        TBODY_TD_DIV: string = 'cal-monthview-tbody-td-div';
        TBODY_TD_PREVIOUSORNEXTMONTH: string = 'cal-monthview-tbody-td-prevAndNextMonth';
        TBODY_TD_ISTODAY: string = 'cal-monthview-tbody-td-istoday';
        TBODY_TD_DISABLED: string = 'cal-monthview-tbody-td-disabled';
        TBODY_TD: string = 'cal-monthview-tbody-td';

        THEAD_TR: string = 'cal-monthview-thead-th';
        THEAD_TH: string = 'cal-monthview-thead-row';

        constructor(tbl: my.core.calendar.CalendarTable) {
            this.table = tbl;
        }

        private createMonthCellArray(day: number, nextMonth: boolean = undefined): Array<object> {
            let date = this.table.config.currentDate;

            if (nextMonth) {
                return [
                    {
                        startDate: new Date(new Date(date).getFullYear(), new Date(date).getMonth() + 1, day, 0, 0, 0, 0),
                        endDate: new Date(new Date(date).getFullYear(), new Date(date).getMonth() + 1, day, 23, 59, 59, 999)
                    }
                ]
            } else if (nextMonth == false) {
                return [
                    {
                        startDate: new Date(new Date(date).getFullYear(), new Date(date).getMonth() - 1, day, 0, 0, 0, 0),
                        endDate: new Date(new Date(date).getFullYear(), new Date(date).getMonth() - 1, day, 23, 59, 59, 999)
                    }
                ]
            } else {
                return [
                    {
                        startDate: new Date(new Date(date).getFullYear(), new Date(date).getMonth(), day, 0, 0, 0, 0),
                        endDate: new Date(new Date(date).getFullYear(), new Date(date).getMonth(), day, 23, 59, 59, 999),
                        isToday: new Date(new Date(date).getFullYear(), new Date(date).getMonth(), day).getTime() == new Date(new Date().setHours(0, 0, 0, 0)).getTime() ? 1 : 0
                    }
                ]
            }
        }

        private attachSmallAppointment() {

        }

        private attachDisabledDays(j: number, el: HTMLElement, day: number): void {
            /**
             *  We have to check for startDate and endDate aswell because they may be all provided and we will apply
             *  the same class 2 times or more
             */
            for (let i = 0; i < this.table.config.disabledDays.length; i++) {
                if (this.table.config.startDate == null && this.table.config.endDate == null) {
                    if (j == this.table.config.disabledDays[i]) {
                        el.classList.add(this.TBODY_TD_DISABLED);
                    }
                } else if (this.table.config.startDate && this.table.config.endDate) {
                    if (day < this.table.config.startDate.getDate() || day > this.table.config.endDate.getDate()) {
                        el.classList.add(this.TBODY_TD_DISABLED);
                    }
                    if (j == this.table.config.disabledDays[i]) {
                        if (!this.table.checkClassContaining(el.classList, this.TBODY_TD_DISABLED)) {
                            el.classList.add(this.TBODY_TD_DISABLED);
                        }
                    }
                } else if (this.table.config.startDate && this.table.config.endDate == null) {
                    if (day < this.table.config.startDate.getDate()) {
                        el.classList.add(this.TBODY_TD_DISABLED);
                    }
                    if (j == this.table.config.disabledDays[i]) {
                        if (!this.table.checkClassContaining(el.classList, this.TBODY_TD_DISABLED)) {
                            el.classList.add(this.TBODY_TD_DISABLED);
                        }
                    }
                } else if (this.table.config.endDate && this.table.config.startDate == null) {
                    if (day > this.table.config.endDate.getDate()) {
                        el.classList.add(this.TBODY_TD_DISABLED);
                    }
                    if (j == this.table.config.disabledDays[i]) {
                        if (!this.table.checkClassContaining(el.classList, this.TBODY_TD_DISABLED)) {
                            el.classList.add(this.TBODY_TD_DISABLED);
                        }
                    }
                }
            }
        }

        private attachStartEndDateDisableClass(j: number, el: HTMLElement, day: number): void {
            /** Construct date based on the day so we can compare year month and date, not only date. */
            let currentIterationDate = new Date(this.table.config.currentDate.getFullYear(), this.table.config.currentDate.getMonth(), day);

            if (this.table.config.startDate && this.table.config.endDate) {
                if (currentIterationDate.getTime() < this.table.config.startDate.getTime() || currentIterationDate.getTime() > this.table.config.endDate.getTime()) {
                    el.classList.add(this.TBODY_TD_DISABLED);
                }
            } else if (this.table.config.startDate && this.table.config.endDate == null) {
                if (currentIterationDate.getTime() < this.table.config.startDate.getTime()) {
                    el.classList.add(this.TBODY_TD_DISABLED);
                }
            } else if (this.table.config.endDate && this.table.config.startDate == null) {
                if (currentIterationDate.getTime() > this.table.config.endDate.getTime()) {
                    el.classList.add(this.TBODY_TD_DISABLED);
                }
            }
        }

        public createMontlyView(): void {
            let self = this.table,
                 row: my.core.table.Row = new my.core.table.Row(this.table),
                 th: my.core.table.iCell,
                 td: my.core.table.tdCell,
                 finished = false,
                 day = 1,
                 nextMonthDay = 1,
                 previousMonthDayToStart;

            /** Reapply classes */
            this.table.element.className = "table table-bordered table-responsive col-sm-12 col-md-12 cal-monthview-table";

            /** Month view header */
            this.table.calendar_days_label.forEach((label, idx) => {
                th = new my.core.table.thCell();
                th.element.innerText = label;
                th.element.classList.add(this.THEAD_TH);
                row.addCell(th);
            });
            row.element.classList.add(this.THEAD_TR);
            this.table.tHead.addRow(row);

            /** Month view body */
            for (let i = 0; i < 9; i++) {
                row = new my.core.table.Row(this.table);
                for (let j = 0; j <= 6; j++) {
                    td = new my.core.table.tdCell();
                    /** add extra class for disabled days */
                    if (this.table.config.disabledDays.length > 0) {
                        this.attachDisabledDays(j, td.element, day);
                    } else if (this.table.config.startDate || this.table.config.endDate) {
                        this.attachStartEndDateDisableClass(j, td.element, day);
                    }

                    if (!this.table.checkClassContaining(td.element.classList, this.TBODY_TD_DISABLED)) {
                        /**
                             *  Bind cell click to the table config `cellClick` function
                             *  so it could be overrided if needed.
                             *  And only if it doesn contain class '*-disabled'
                             */
                        td.events.on.click(function (sender, e, data) {
                            self.config.cellClick(sender, e, data);
                        })
                    }

                    if (day <= this.table.monthLength && (i > 0 || j >= this.table.startingDay)) {
                        /**
                         *  Create empty div with the date related
                         *  and css class
                         */
                        td.element.appendChild(this.table.createDiv(day, this.TBODY_TD_DIV));
                        td.element.classList.add(this.TBODY_TD);
                        td.data = this.createMonthCellArray(day, undefined);

                        /** Append new css class if the flag isToday == 1 */
                        if (td.data[0]['isToday'] === 1) {
                            td.element.classList.add(this.TBODY_TD_ISTODAY);
                        }
                        row.addCell(td);

                        day++;
                    } else {
                        if (!finished) {
                            /** If it's January get the December previous year days */
                            if (new Date(this.table.config.currentDate).getMonth() === 0 && previousMonthDayToStart == null) {
                                previousMonthDayToStart = this.table.calendar_days_in_month[this.table.calendar_days_in_month.length - 1] - this.table.startingDay;
                            } else if (previousMonthDayToStart == null) {
                                previousMonthDayToStart = this.table.calendar_days_in_month[new Date(this.table.config.currentDate).getMonth() - 1] - (this.table.startingDay - 1);
                            }
                            td.element.classList.add(this.TBODY_TD_PREVIOUSORNEXTMONTH);

                            /**
                             *  If day is greater than month length and the flag `finished` is false
                             *  Then we have to get the next month length and render it.
                             */
                            if (day > this.table.monthLength) {
                                td.element.appendChild(this.table.createDiv(nextMonthDay, this.TBODY_TD_DIV));
                                td.data = this.createMonthCellArray(nextMonthDay, true);
                                nextMonthDay++;
                            } else {

                                td.element.appendChild(this.table.createDiv(previousMonthDayToStart, this.TBODY_TD_DIV));
                                td.data = this.createMonthCellArray(previousMonthDayToStart, false);
                                previousMonthDayToStart++;
                            }
                            row.addCell(td);
                        }
                    }
                    /** Stop creating rows */
                    if (day > this.table.monthLength && j == 6) {
                        finished = true;
                    }
                }
                this.table.tBody.addRow(row);
            }
        }

        public monthNavigationChange(next: boolean): void {
            let month = new Date(this.table.config.currentDate).getMonth(),
                 year = new Date(this.table.config.currentDate).getFullYear();

            if (next) {
                if (month == 11) {
                    month = 0;
                    this.table.config.currentDate = new Date(year + 1, month);
                    this.table.MonthLength = month;
                } else {
                    month += 1;
                    this.table.config.currentDate = new Date(year, month);
                    this.table.MonthLength = month;
                }
            } else if (!next) {
                if (month == 0) {
                    month = 11;
                    this.table.config.currentDate = new Date(year - 1, month);
                    this.table.MonthLength = month;
                } else {
                    month -= 1;
                    this.table.config.currentDate = new Date(year, month);
                    this.table.MonthLength = month;
                }

            }
        }

        public bindMonthAppointments(): void {
            let eventsContainer = this.table.createDiv('', this.EVENTS_WRAPPER, 'events'),
                self = this.table,
                _datesOffset: Array<object> = [],
                toPrint = false;

            if (this.table.appointments) {

                for (let i = 0; i < this.table.appointments.length; i++) {
                    this.table.tBody.rows.forEach((rowObj, rowIdx) => {
                        rowObj.cells.forEach((cellObj, cellIdx) => {
                            /* Set time to 0 so we can compare date and month only */
                            let appDate = new Date(new Date(this.table.appointments[i]['startDate']).setHours(0, 0, 0, 0)),
                                cellDate = new Date(new Date(cellObj['data'][0]['startDate']).setHours(0, 0, 0, 0));

                            if (appDate.getTime() == cellDate.getTime()) {
                                let cell = rowObj.cells[cellIdx].element,
                                    eventApp,
                                    appCounter;

                                /* we have to keep track of the previous element's offsetleft for the same time */
                                if (!this.table.isDateInArray(this.table.appointments[i]['startDate'], _datesOffset)) {
                                    /* Start render at about 35% of the cell height (or almost center) */
                                    _datesOffset.push(
                                        {
                                            startDate: new Date(new Date(this.table.appointments[i]['startDate']).setHours(0, 0, 0, 0)),
                                            offsetTop: cell.offsetTop + (cell.offsetHeight * 0.33),
                                            eventCounter: 0
                                        }
                                    )
                                }
                                /* We found the f app, now render it */
                                let eventDimension = {
                                    transformX: cell.offsetLeft,
                                    transformY: '', // overrided 
                                    w: cell.offsetWidth,
                                    h: cell.offsetHeight / 3,
                                    bColor: this.table.appointments[i]['Color'],
                                }
                                /* Override offsetTop */
                                if (_datesOffset.length > 0) {
                                    _datesOffset.forEach((obj, idx) => {
                                        if (new Date(obj['startDate']).getTime() == new Date(new Date(this.table.appointments[i]['startDate']).setHours(0, 0, 0, 0)).getTime()) {
                                            eventDimension['transformY'] = obj['offsetTop'];
                                            obj['offsetTop'] += cell.offsetHeight * 0.33;
                                            obj['eventCounter'] += 1;

                                            appCounter = obj['eventCounter'];
                                        }
                                    })
                                }
                                if (appCounter <= 2) {
                                    eventApp = new my.controls.cAppointment(this.EVENTS_DIV, eventDimension);
                                    /* InnerHTML like that , because someone may want to override it outside */
                                    eventApp.element.insertAdjacentHTML('afterbegin', this.table.config.appointmentTemplate(this.table.appointments[i]));
                                    eventApp.element.addEventListener('click', function (ev) {
                                        self.config.appointmentClick(self.appointments[i], ev)
                                    });
                                    eventsContainer.appendChild(eventApp.element);
                                } else {
                                    /* create small block which shows all other appointments on button popup */
                                    this.attachSmallAppointment();
                                }
                            }
                        })
                    })
                }
            }
            this.table.element.parentElement.appendChild(eventsContainer);
        }
    } /** end monthly view */
导出类MontlyView{
表:my.core.calendar.CalendarTable;
EVENTS_DIV:string='cal monthview EVENTS DIV';
EVENTS_WRAPPER:string='cal monthview EVENTS WRAPPER';
TBODY_TD_DIV:string='cal monthview TBODY TD DIV';
TBODY_TD_上一个月或下一个月:字符串='cal monthview TBODY TD Previous and NextMonth';
TBODY_TD_ISTODAY:string='cal monthview TBODY TD ISTODAY';
TBODY_TD_DISABLED:string='cal monthview TBODY TD DISABLED';
TBODY_TD:string='cal monthview TBODY TD';
THEAD_TR:string='cal monthview THEAD th';
THEAD_TH:string='cal monthview THEAD row';
构造函数(tbl:my.core.calendar.CalendarTable){
本表=tbl;
}
私有createMonthCellArray(天:数字,下个月:布尔值=未定义):数组{
让日期=this.table.config.currentDate;
如果(下个月){
返回[
{
startDate:新日期(新日期.getFullYear(),新日期.getMonth()+1,天,0,0,0),
endDate:新日期(新日期(Date).getFullYear(),新日期(Date).getMonth()+1,day,23,59,59999)
}
]
}else if(nextMonth==false){
返回[
{
startDate:新日期(新日期.getFullYear(),新日期.getMonth()-1,天,0,0,0),
endDate:新日期(新日期(Date).getFullYear(),新日期(Date).getMonth()-1,day,23,59,59999)
}
]
}否则{
返回[
{
startDate:新日期(新日期.getFullYear(),新日期.getMonth(),天,0,0,0),
endDate:新日期(新日期.getFullYear(),新日期.getMonth(),日期,23,59,59999),
isToday:新日期(新日期(Date).getFullYear(),新日期(Date).getMonth(),day).getTime()==新日期(新日期().setHours(0,0,0,0)).getTime()?1:0
}
]
}
}
私人助理{
}
private attachDisabledDays(j:number,el:HTMLElement,day:number):无效{
/**
*我们必须检查startDate和endDate,因为它们可能都已提供,我们将申请
*同一班级2次或2次以上
*/
for(设i=0;ithis.table.config.endDate.getDate()){
el.classList.add(此.TBODY\u TD\u已禁用);
}
如果(j==this.table.config.disabledDays[i]){
if(!this.table.checkClassContaining(el.classList,this.TBODY\u TD\u禁用)){
el.classList.add(此.TBODY\u TD\u已禁用);
}
}
}else if(this.table.config.startDate&&this.table.config.endDate==null){
如果(日期this.table.config.endDate.getDate()){
el.classList.add(此.TBODY\u TD\u已禁用);
}
如果(j==this.table.config.disabledDays[i]){
if(!this.table.checkClassContaining(el.classList,this.TBODY\u TD\u禁用)){
el.classList.add(此.TBODY\u TD\u已禁用);
}
}
}
}
}
private attachStartEndDateDisableClass(j:number,el:HTMLElement,day:number):无效{
/**基于日期构造日期,以便我们可以比较y
interface IView {
    create();
    bindAppointments();
    navigationChange(next: boolean);
}
export class Calendar extends my.core.calendar.CalendarTable {
    currentView: IView; // Set this when the current view changes,

    bindAppointments(): void {
       this.clearAll();
       this.currentView.bindAppointments();
    }   
}