瀏覽代碼

type tricks

Adam Shaw 7 年之前
父節點
當前提交
8191546448
共有 6 個文件被更改,包括 86 次插入66 次删除
  1. 34 9
      src/agenda/AgendaView.ts
  2. 1 18
      src/agenda/TimeGrid.ts
  3. 43 14
      src/basic/BasicView.ts
  4. 3 20
      src/basic/DayGrid.ts
  5. 3 3
      src/util/reselector.ts
  6. 2 2
      tests/automated/view-render/columnHeader.js

+ 34 - 9
src/agenda/AgendaView.ts

@@ -24,6 +24,7 @@ import DayTable from '../component/DayTable';
 import { ComponentContext } from '../component/Component';
 import { ViewSpec } from '../structs/view-spec';
 import DateProfileGenerator, { DateProfile } from '../DateProfileGenerator';
+import DayTableHeader from '../basic/DayTableHeader'
 
 const AGENDA_ALL_DAY_EVENT_LIMIT = 5
 const WEEK_HEADER_FORMAT = createFormatter({ week: 'short' })
@@ -36,11 +37,14 @@ const WEEK_HEADER_FORMAT = createFormatter({ week: 'short' })
 
 export default class AgendaView extends View {
 
+  header: DayTableHeader
   timeGrid: TimeGrid // the main time-grid subcomponent of this view
   dayGrid: DayGrid // the "all-day" subcomponent. if all-day is turned off, this will be null
 
   scroller: ScrollComponent
 
+  dayTable: DayTable
+
   // reselectors
   filterEventsForTimeGrid: any
   filterEventsForDayGrid: any
@@ -68,6 +72,13 @@ export default class AgendaView extends View {
       'auto' // overflow y
     )
 
+    if (this.opt('columnHeader')) {
+      this.header = new DayTableHeader(
+        this.context,
+        this.el.querySelector('.fc-head-container')
+      )
+    }
+
     let timeGridWrapEl = this.scroller.el
     this.el.querySelector('.fc-body > tr > td').appendChild(timeGridWrapEl)
     timeGridWrapEl.classList.add('fc-time-grid-container')
@@ -76,10 +87,8 @@ export default class AgendaView extends View {
 
     this.timeGrid = new TimeGrid(
       this.context,
-      this.el.querySelector('.fc-head-container'),
       timeGridEl,
       {
-        renderHeadIntroHtml: this.renderTimeGridHeadIntroHtml,
         renderBgIntroHtml: this.renderTimeGridBgIntroHtml,
         renderIntroHtml: this.renderTimeGridIntroHtml
       }
@@ -89,10 +98,8 @@ export default class AgendaView extends View {
 
       this.dayGrid = new DayGrid( // the all-day subcomponent of this view
         this.context,
-        null, // headContainerEl
         this.el.querySelector('.fc-day-grid'),
         {
-          renderHeadIntroHtml: this.renderDayGridIntroHtml, // not used, because head not used
           renderNumberIntroHtml: this.renderDayGridIntroHtml, // don't want numbers
           renderBgIntroHtml: this.renderDayGridBgIntroHtml,
           renderIntroHtml: this.renderDayGridIntroHtml,
@@ -110,6 +117,10 @@ export default class AgendaView extends View {
   destroy() {
     super.destroy()
 
+    if (this.header) {
+      this.header.destroy()
+    }
+
     this.timeGrid.destroy()
 
     if (this.dayGrid) {
@@ -172,7 +183,17 @@ export default class AgendaView extends View {
       }
     }
 
-    let dayTable = this.buildDayTable(props.dateProfile)
+    let dayTable = this.dayTable =
+      this.buildDayTable(props.dateProfile)
+
+    if (this.header) {
+      this.header.receiveProps({
+        dateProfile: props.dateProfile,
+        dates: dayTable.dayDates,
+        datesRepDistinctDays: true,
+        renderIntroHtml: this.renderHeadIntroHtml
+      })
+    }
 
     this.timeGrid.receiveProps(
       assignTo({}, props, {
@@ -205,7 +226,7 @@ export default class AgendaView extends View {
       this.isRtl,
       false
     )
-  }) as any
+  })
 
 
   /* Now Indicator
@@ -354,12 +375,12 @@ export default class AgendaView extends View {
   }
 
 
-  /* Time Grid Render Methods
+  /* Header Render Methods
   ------------------------------------------------------------------------------------------------------------------*/
 
 
   // Generates the HTML that will go before the day-of week header cells
-  renderTimeGridHeadIntroHtml = (dayTable: DayTable) => {
+  renderHeadIntroHtml = () => {
     let { theme, dateEnv } = this
     let weekStart = this.props.dateProfile.renderRange.start
     let weekText
@@ -371,7 +392,7 @@ export default class AgendaView extends View {
         '<th class="fc-axis fc-week-number ' + theme.getClass('widgetHeader') + '">' +
           buildGotoAnchorHtml( // aside from link, important for matchCellWidths
             this,
-            { date: weekStart, type: 'week', forceOff: dayTable.colCnt > 1 },
+            { date: weekStart, type: 'week', forceOff: this.dayTable.colCnt > 1 },
             htmlEscape(weekText) // inner HTML
           ) +
         '</th>'
@@ -381,6 +402,10 @@ export default class AgendaView extends View {
   }
 
 
+  /* Time Grid Render Methods
+  ------------------------------------------------------------------------------------------------------------------*/
+
+
   // Generates the HTML that goes before the bg of the TimeGrid slot area. Long vertical column.
   renderTimeGridBgIntroHtml = () => {
     let { theme } = this

+ 1 - 18
src/agenda/TimeGrid.ts

@@ -1,6 +1,5 @@
 import { htmlEscape } from '../util/html'
 import { htmlToElement, findElements, createElement, removeElement, applyStyle } from '../util/dom-manip'
-import DayTable from '../component/DayTable'
 import PositionCache from '../common/PositionCache'
 import { DateRange, intersectRanges } from '../datelib/date-range'
 import TimeGridEventRenderer from './TimeGridEventRenderer'
@@ -14,7 +13,6 @@ import { Seg } from '../component/DateComponent'
 import StandardDateComponent from '../component/StandardDateComponent'
 import OffsetTracker from '../common/OffsetTracker'
 import { Hit } from '../interactions/HitDragging'
-import DayTableHeader from '../basic/DayTableHeader'
 import DayBgRow from '../basic/DayBgRow'
 
 /* A component that renders one or more columns of vertical time slots
@@ -32,7 +30,6 @@ const AGENDA_STOCK_SUB_DURATIONS = [
 ]
 
 export interface RenderProps {
-  renderHeadIntroHtml: (dayTable: DayTable) => string
   renderBgIntroHtml: () => string
   renderIntroHtml: () => string
 }
@@ -49,7 +46,6 @@ export default class TimeGrid extends StandardDateComponent {
   labelFormat: DateFormatter // formatting string for times running along vertical axis
   labelInterval: Duration // duration of how often a label should be displayed for a slot
 
-  headContainerEl: HTMLElement // div that hold's the date header
   colEls: HTMLElement[] // cells elements in the day-row background
   slatContainerEl: HTMLElement // div that wraps all the slat rows
   slatEls: HTMLElement[] // elements running horizontally across all columns
@@ -72,7 +68,7 @@ export default class TimeGrid extends StandardDateComponent {
   businessContainerEls: HTMLElement[]
 
 
-  constructor(context: ComponentContext, headContainerEl: HTMLElement, el: HTMLElement, renderProps: RenderProps) {
+  constructor(context: ComponentContext, el: HTMLElement, renderProps: RenderProps) {
     super(context, el)
 
     this.eventRenderer = new TimeGridEventRenderer(this)
@@ -82,8 +78,6 @@ export default class TimeGrid extends StandardDateComponent {
 
     this.processOptions()
 
-    this.headContainerEl = headContainerEl // already created by called! where content is inserted directly!
-
     el.innerHTML =
       '<div class="fc-bg"></div>' +
       '<div class="fc-slats"></div>' +
@@ -311,17 +305,6 @@ export default class TimeGrid extends StandardDateComponent {
       }
     })
 
-    if (this.headContainerEl) {
-      // TODO: destroy?
-      let header = new DayTableHeader(this.context, this.headContainerEl)
-      header.receiveProps({
-        dateProfile,
-        dates: dayDates,
-        datesRepDistinctDays: true,
-        renderIntroHtml: this.renderProps.renderHeadIntroHtml.bind(null, dayTable)
-      })
-    }
-
     let bgRow = new DayBgRow(this.context)
     this.rootBgContainerEl.innerHTML =
       '<table class="' + theme.getClass('tableGrid') + '">' +

+ 43 - 14
src/basic/BasicView.ts

@@ -20,7 +20,8 @@ import DayTable from '../component/DayTable';
 import { ComponentContext } from '../component/Component'
 import { ViewSpec } from '../structs/view-spec'
 import DateProfileGenerator, { DateProfile } from '../DateProfileGenerator'
-import reselector from '../util/reselector';
+import reselector from '../util/reselector'
+import DayTableHeader from './DayTableHeader'
 
 const WEEK_NUM_FORMAT = createFormatter({ week: 'numeric' })
 
@@ -33,7 +34,10 @@ const WEEK_NUM_FORMAT = createFormatter({ week: 'numeric' })
 export default class BasicView extends View {
 
   scroller: ScrollComponent
+  header: DayTableHeader
   dayGrid: DayGrid // the main subcomponent that does most of the heavy lifting
+
+  dayTable: DayTable
   colWeekNumbersVisible: boolean
 
 
@@ -69,12 +73,17 @@ export default class BasicView extends View {
       cellWeekNumbersVisible = false
     }
 
+    if (this.opt('columnHeader')) {
+      this.header = new DayTableHeader(
+        this.context,
+        this.el.querySelector('.fc-head-container')
+      )
+    }
+
     this.dayGrid = new DayGrid(
       this.context,
-      this.el.querySelector('.fc-head-container'),
       dayGridEl,
       {
-        renderHeadIntroHtml: this.renderDayGridHeadIntroHtml,
         renderNumberIntroHtml: this.renderDayGridNumberIntroHtml,
         renderBgIntroHtml: this.renderDayGridBgIntroHtml,
         renderIntroHtml: this.renderDayGridIntroHtml,
@@ -89,6 +98,10 @@ export default class BasicView extends View {
   destroy() {
     super.destroy()
 
+    if (this.header) {
+      this.header.destroy()
+    }
+
     this.dayGrid.destroy()
     this.scroller.destroy()
   }
@@ -97,7 +110,17 @@ export default class BasicView extends View {
   render(props: StandardDateComponentProps) {
     super.render(props)
 
-    let dayTable = this.buildDayTable(props.dateProfile)
+    let dayTable = this.dayTable =
+      this.buildDayTable(props.dateProfile)
+
+    if (this.header) {
+      this.header.receiveProps({
+        dateProfile: props.dateProfile,
+        dates: this.sliceDayDates(dayTable), // get just the first row
+        datesRepDistinctDays: dayTable.rowCnt === 1,
+        renderIntroHtml: this.renderHeadIntroHtml
+      })
+    }
 
     this.dayGrid.receiveProps(
       assignTo({}, props, {
@@ -114,7 +137,12 @@ export default class BasicView extends View {
       this.isRtl,
       /year|month|week/.test(dateProfile.currentRangeUnit)
     )
-  }) as any
+  })
+
+
+  sliceDayDates = reselector(function(dayTable: DayTable) {
+    return dayTable.dayDates.slice(0, dayTable.colCnt)
+  })
 
 
   // Builds the HTML skeleton for the view.
@@ -162,12 +190,9 @@ export default class BasicView extends View {
 
   // Refreshes the horizontal dimensions of the view
   updateBaseSize(viewHeight: number, isAuto: boolean, isResize: boolean) {
-    let { dayGrid } = this
+    let { header, dayGrid } = this
     let eventLimit = this.opt('eventLimit')
-    let headRowEl =
-      dayGrid.headerContainerEl ?
-        dayGrid.headerContainerEl.querySelector('.fc-row') as HTMLElement :
-        null
+    let headRowEl = header ? header.el : null
     let scrollerHeight
     let scrollbarWidths
 
@@ -269,12 +294,12 @@ export default class BasicView extends View {
   }
 
 
-  /* Day Grid Rendering
+  /* Header Rendering
   ------------------------------------------------------------------------------------------------------------------*/
 
 
   // Generates the HTML that will go before the day-of week header cells
-  renderDayGridHeadIntroHtml = () => {
+  renderHeadIntroHtml = () => {
     let { theme } = this
 
     if (this.colWeekNumbersVisible) {
@@ -290,9 +315,13 @@ export default class BasicView extends View {
   }
 
 
+  /* Day Grid Rendering
+  ------------------------------------------------------------------------------------------------------------------*/
+
+
   // Generates the HTML that will go before content-skeleton cells that display the day/week numbers
-  renderDayGridNumberIntroHtml = (row, dayTable: DayTable) => {
-    let { dateEnv } = this
+  renderDayGridNumberIntroHtml = (row) => {
+    let { dateEnv, dayTable } = this
     let weekStart = dayTable.getCellDate(row, 0)
 
     if (this.colWeekNumbersVisible) {

+ 3 - 20
src/basic/DayGrid.ts

@@ -9,7 +9,6 @@ import {
 import { computeRect } from '../util/dom-geom'
 import PositionCache from '../common/PositionCache'
 import Popover from '../common/Popover'
-import DayTable from '../component/DayTable'
 import DayGridEventRenderer from './DayGridEventRenderer'
 import DayGridMirrorRenderer from './DayGridMirrorRenderer'
 import DayGridFillRenderer from './DayGridFillRenderer'
@@ -24,7 +23,6 @@ import { DateRange, rangeContainsMarker, intersectRanges } from '../datelib/date
 import OffsetTracker from '../common/OffsetTracker'
 import { EventRenderRange } from '../component/event-rendering'
 import { buildGotoAnchorHtml, getDayClasses } from '../component/date-rendering'
-import DayTableHeader from './DayTableHeader'
 import DayBgRow from './DayBgRow'
 
 const DAY_NUM_FORMAT = createFormatter({ day: 'numeric' })
@@ -39,8 +37,7 @@ export interface DayGridProps extends StandardDateComponent {
 }
 
 export interface RenderProps {
-  renderHeadIntroHtml: (dayTable: DayTable) => string
-  renderNumberIntroHtml: (row: number, dayTable: DayTable) => string
+  renderNumberIntroHtml: (row: number) => string
   renderBgIntroHtml: () => string
   renderIntroHtml: () => string
   colWeekNumbersVisible: boolean // week numbers render in own column? (caller does HTML via intro)
@@ -54,7 +51,6 @@ export default class DayGrid extends StandardDateComponent {
 
   bottomCoordPadding: number = 0 // hack for extending the hit area for the last row of the coordinate grid
 
-  headerContainerEl: HTMLElement // div that hold's the date header
   rowEls: HTMLElement[] // set of fake row elements
   cellEls: HTMLElement[] // set of whole-day elements comprising the row's background
 
@@ -70,7 +66,7 @@ export default class DayGrid extends StandardDateComponent {
   segPopoverTile: DayTile
 
 
-  constructor(context, headerContainerEl, el, renderProps: RenderProps) {
+  constructor(context, el, renderProps: RenderProps) {
     super(context, el)
 
     this.eventRenderer = new DayGridEventRenderer(this)
@@ -78,7 +74,6 @@ export default class DayGrid extends StandardDateComponent {
     this.fillRenderer = new DayGridFillRenderer(this)
     this.slicingType = 'all-day'
 
-    this.headerContainerEl = headerContainerEl
     this.renderProps = renderProps
   }
 
@@ -145,17 +140,6 @@ export default class DayGrid extends StandardDateComponent {
     let row
     let col
 
-    if (this.headerContainerEl) {
-      // TODO: destroy?
-      let header = new DayTableHeader(this.context, this.headerContainerEl)
-      header.receiveProps({
-        dateProfile,
-        dates: dayTable.dayDates.slice(0, dayTable.colCnt), // because might be mult rows
-        datesRepDistinctDays: dayTable.rowCnt === 1,
-        renderIntroHtml: this.renderProps.renderHeadIntroHtml.bind(null, dayTable)
-      })
-    }
-
     for (row = 0; row < rowCnt; row++) {
       html += this.renderDayRowHtml(row, this.isRigid)
     }
@@ -261,8 +245,7 @@ export default class DayGrid extends StandardDateComponent {
 
 
   renderNumberTrHtml(row: number) {
-    let dayTable = (this.props as any).dayTable
-    let intro = this.renderProps.renderNumberIntroHtml(row, dayTable)
+    let intro = this.renderProps.renderNumberIntroHtml(row)
 
     return '' +
       '<tr>' +

+ 3 - 3
src/util/reselector.ts

@@ -1,16 +1,16 @@
 import { isArraysEqual } from './array'
 
 
-export default function(workerFunc) {
+export default function<T>(workerFunc: T): T {
   let prevArgs
   let prevResult
 
   return function() {
     if (!prevArgs || !isArraysEqual(prevArgs, arguments)) {
       prevArgs = arguments
-      prevResult = workerFunc.apply(this, arguments)
+      prevResult = (workerFunc as any).apply(this, arguments)
     }
 
     return prevResult
-  }
+  } as any
 }

+ 2 - 2
tests/automated/view-render/columnHeader.js

@@ -11,7 +11,7 @@ describe('columnHeader', function() {
     'when basic view': 'basicDay'
   }, function() {
 
-    describe('when off', function() {
+    describe('when on', function() {
       pushOptions({
         columnHeader: true
       })
@@ -22,7 +22,7 @@ describe('columnHeader', function() {
       })
     })
 
-    describe('when on', function() {
+    describe('when off', function() {
       pushOptions({
         columnHeader: false
       })