2017-11-21 12 views
0

私はOOPを初めて使っています。私はcalendarと3 viewsを持っています(今のところ)。私は単にtableオブジェクトを作成しabstractクラス、セッターとゲッターとabstract方法と子クラスの基本クラスのメソッドをオーバーライドするカレンダー一部を保持しているabstractCalendarTableクラスを持っています。問題は、すべてのメソッドがに基づいてメソッドview'sを呼び出すswitchです。すべてのビューがの予定表コンストラクタのinstantiatedです。プロパティに基づいて `switch`を置き換えて子メソッドを呼び出す

カレンダー

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です。すべてのviewクラスをカレンダーに拡張し、そのメソッドをオーバーライドし、適切なビューオーバーライドメソッドを呼び出すためにハンドラの1つが起動したときに、現在のビューが何であるかを判断せずにインスタンス化されたクラスメソッドを呼び出すようにするにはどうすればよいですか?

viewクラスのいずれかを添付すると、すべてのビュークラスには基本的な考えがあります。他の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 */ 

答えて

1

あなたはすべてのビューのための共通のインタフェースを持っていると、クラスのメンバーで、現在のビューのインスタンスを保持する必要があります。

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(); 
    } 
} 
+0

申し訳ありません私のカレンダーの設定を表すオブジェクトに 'currentView'を保持しています。更新すると' currentView:IView'を 'set 'して正確なビューロジックを呼び出すべきですか? – Denisx

+0

これはあなた次第ですが、個人的にはまずconfigに基づいてコンストラクタで設定します。設定の変更は 'currentView'フィールドに反映されませんが、カレンダークラス' setCurrentView(view: "day" | "year" | "month"):voidを更新するメソッドも追加します'currentView'フィールドとおそらくconfig内の' string'フィールド(天気に応じて、いくつかのカレンダーの中でconfigが再利用できない場合)\ –

+0

ですが、このメソッドでは 'setCurrentView'は' switch'に依存しますがatlestは1になりますコード全体で私は推測する。 – Denisx

関連する問題