Explorar el Código

improve fillrenderer api

Adam Shaw hace 7 años
padre
commit
66b7e72815

+ 15 - 6
src/agenda/TimeGridFillRenderer.ts

@@ -1,11 +1,20 @@
 import FillRenderer from '../component/renderers/FillRenderer'
 import { Seg } from '../component/DateComponent'
+import TimeGrid from './TimeGrid'
 
 
 export default class TimeGridFillRenderer extends FillRenderer {
 
-  attachSegEls(type, segs: Seg[]) {
-    let timeGrid = this.component
+  timeGrid: TimeGrid
+
+  constructor(timeGrid: TimeGrid) {
+    super(timeGrid.context)
+
+    this.timeGrid = timeGrid
+  }
+
+  attachSegs(type, segs: Seg[]) {
+    let { timeGrid } = this
     let containerEls
 
     // TODO: more efficient lookup
@@ -24,12 +33,12 @@ export default class TimeGridFillRenderer extends FillRenderer {
     })
   }
 
-  computeSize(type) {
-    this.component.computeSegVerticals(this.renderedSegsByType[type] || [])
+  computeSizes(type) {
+    this.timeGrid.computeSegVerticals(this.getSegsByType(type))
   }
 
-  assignSize(type) {
-    this.component.assignSegVerticals(this.renderedSegsByType[type] || [])
+  assignSizes(type) {
+    this.timeGrid.assignSegVerticals(this.getSegsByType(type))
   }
 
 }

+ 11 - 6
src/basic/DayGridFillRenderer.ts

@@ -6,11 +6,16 @@ import { Seg } from '../component/DateComponent'
 
 export default class DayGridFillRenderer extends FillRenderer {
 
-  component: DayGrid
   fillSegTag: string = 'td' // override the default tag name
+  dayGrid: DayGrid
 
+  constructor(dayGrid: DayGrid) {
+    super(dayGrid.context)
 
-  attachSegEls(type, segs: Seg[]) {
+    this.dayGrid = dayGrid
+  }
+
+  attachSegs(type, segs: Seg[]) {
     let els = []
     let i
     let seg
@@ -19,17 +24,17 @@ export default class DayGridFillRenderer extends FillRenderer {
     for (i = 0; i < segs.length; i++) {
       seg = segs[i]
       skeletonEl = this.renderFillRow(type, seg)
-      this.component.rowEls[seg.row].appendChild(skeletonEl)
+      this.dayGrid.rowEls[seg.row].appendChild(skeletonEl)
       els.push(skeletonEl)
     }
 
     return els
   }
 
-
   // Generates the HTML needed for one row of a fill. Requires the seg's el to be rendered.
   renderFillRow(type, seg: Seg): HTMLElement {
-    let colCnt = this.component.colCnt
+    let { dayGrid } = this
+    let colCnt = dayGrid.colCnt
     let startCol = seg.leftCol
     let endCol = seg.rightCol + 1
     let className
@@ -60,7 +65,7 @@ export default class DayGridFillRenderer extends FillRenderer {
       trEl.appendChild(createElement('td', { colSpan: colCnt - endCol }))
     }
 
-    this.component.bookendCells(trEl)
+    dayGrid.bookendCells(trEl)
 
     return skeletonEl
   }

+ 10 - 36
src/component/DateComponent.ts

@@ -1,7 +1,7 @@
 import Component, { ComponentContext } from './Component'
 import { DateProfile } from '../DateProfileGenerator'
 import { EventStore, expandRecurring } from '../structs/event-store'
-import { EventUiHash, EventRenderRange, computeEventDefUis, sliceEventStore, computeEventDefUi, hasBgRendering, filterSegsViaEls } from './event-rendering'
+import { EventUiHash, EventRenderRange, computeEventDefUis, sliceEventStore, computeEventDefUi, hasBgRendering } from './event-rendering'
 import { DateSpan } from '../structs/date-span'
 import { EventInteractionUiState } from '../interactions/event-interaction-state'
 import { createDuration, Duration } from '../datelib/duration'
@@ -214,15 +214,7 @@ export default class DateComponent extends Component<DateComponentProps> {
 
   renderBusinessHourRanges(eventRanges: EventRenderRange[]) {
     if (this.fillRenderer) {
-      this.fillRenderer.renderSegs(
-        'businessHours',
-        this.eventRangesToSegs(eventRanges),
-        {
-          getClasses(seg) {
-            return [ 'fc-bgevent' ].concat(seg.eventRange.def.classNames)
-          }
-        }
-      )
+      this.fillRenderer.renderSegs('businessHours', this.eventRangesToSegs(eventRanges))
     }
   }
 
@@ -235,13 +227,13 @@ export default class DateComponent extends Component<DateComponentProps> {
 
   computeBusinessHoursSize() {
     if (this.fillRenderer) {
-      this.fillRenderer.computeSize('businessHours')
+      this.fillRenderer.computeSizes('businessHours')
     }
   }
 
   assignBusinessHoursSize() {
     if (this.fillRenderer) {
-      this.fillRenderer.assignSize('businessHours')
+      this.fillRenderer.assignSizes('businessHours')
     }
   }
 
@@ -303,20 +295,7 @@ export default class DateComponent extends Component<DateComponentProps> {
 
       if (this.fillRenderer) {
         bgRanges = this.filterBgEventRanges(bgRanges)
-
-        this.fillRenderer.renderSegs('bgEvent', this.eventRangesToSegs(bgRanges), {
-          getClasses: (seg) => {
-            return seg.eventRange.ui.classNames.concat([ 'fc-bgevent' ])
-          },
-          getCss: (seg) => {
-            return {
-              'background-color': seg.eventRange.ui.backgroundColor
-            }
-          },
-          filterSegs: (segs) => {
-            return filterSegsViaEls(this.view, segs, false)
-          }
-        })
+        this.fillRenderer.renderSegs('bgEvent', this.eventRangesToSegs(bgRanges))
       }
 
       let calendar = this.calendar
@@ -336,14 +315,13 @@ export default class DateComponent extends Component<DateComponentProps> {
     }
 
     if (this.fillRenderer) {
-      this.triggerWillRemoveSegs(this.fillRenderer.renderedSegsByType['bgEvent'] || [])
       this.fillRenderer.unrender('bgEvent')
     }
   }
 
   computeEventsSize() {
     if (this.fillRenderer) {
-      this.fillRenderer.computeSize('bgEvent')
+      this.fillRenderer.computeSizes('bgEvent')
     }
 
     if (this.eventRenderer) {
@@ -353,7 +331,7 @@ export default class DateComponent extends Component<DateComponentProps> {
 
   assignEventsSize() {
     if (this.fillRenderer) {
-      this.fillRenderer.assignSize('bgEvent')
+      this.fillRenderer.assignSizes('bgEvent')
     }
     if (this.eventRenderer) {
       this.eventRenderer.assignSizes()
@@ -487,11 +465,7 @@ export default class DateComponent extends Component<DateComponentProps> {
   // Renders an emphasis on the given date range. Given a span (unzoned start/end and other misc data)
   renderHighlightSegs(segs) {
     if (this.fillRenderer) {
-      this.fillRenderer.renderSegs('highlight', segs, {
-        getClasses() {
-          return [ 'fc-highlight' ]
-        }
-      })
+      this.fillRenderer.renderSegs('highlight', segs)
     }
   }
 
@@ -504,13 +478,13 @@ export default class DateComponent extends Component<DateComponentProps> {
 
   computeHighlightSize() {
     if (this.fillRenderer) {
-      this.fillRenderer.computeSize('highlight')
+      this.fillRenderer.computeSizes('highlight')
     }
   }
 
   assignHighlightSize() {
     if (this.fillRenderer) {
-      this.fillRenderer.assignSize('highlight')
+      this.fillRenderer.assignSizes('highlight')
     }
   }
 

+ 69 - 33
src/component/renderers/FillRenderer.ts

@@ -1,53 +1,65 @@
 import { cssToStr } from '../../util/html'
 import { htmlToElements, removeElement, elementMatches } from '../../util/dom-manip'
 import { Seg } from '../DateComponent'
+import { filterSegsViaEls } from '../event-rendering'
+import { ComponentContext } from '../Component'
 
 
-export default class FillRenderer { // use for highlight, background events, business hours
+export default abstract class FillRenderer { // use for highlight, background events, business hours
 
+  context: ComponentContext
   fillSegTag: string = 'div'
-  component: any
   containerElsByType: any // a hash of element sets used for rendering each fill. Keyed by fill name.
-  renderedSegsByType: any
+  segsByType: any
 
 
-  constructor(component) {
-    this.component = component
+  constructor(context: ComponentContext) {
+    this.context = context
     this.containerElsByType = {}
-    this.renderedSegsByType = {}
+    this.segsByType = {}
   }
 
 
-  // TODO: try to make props smallers
-  renderSegs(type, segs: Seg[], props) {
-    let renderedSegs = this.buildSegEls(type, segs, props) // assignes `.el` to each seg. returns successfully rendered segs
-    let containerEls = this.attachSegEls(type, renderedSegs)
+  getSegsByType(type: string) {
+    return this.segsByType[type] || []
+  }
+
+
+  renderSegs(type, segs: Seg[]) {
+    let renderedSegs = this.renderSegEls(type, segs) // assignes `.el` to each seg. returns successfully rendered segs
+    let containerEls = this.attachSegs(type, renderedSegs)
 
     if (containerEls) {
       (this.containerElsByType[type] || (this.containerElsByType[type] = []))
         .push(...containerEls)
     }
 
-    this.renderedSegsByType[type] = renderedSegs
+    this.segsByType[type] = renderedSegs
+
+    if (type === 'bgEvent') {
+      this.context.view.triggerRenderedSegs(renderedSegs, false) // isMirror=false
+    }
   }
 
 
   // Unrenders a specific type of fill that is currently rendered on the grid
   unrender(type) {
-    let containerEls = this.containerElsByType[type]
+    let segs = this.segsByType[type]
 
-    if (containerEls) {
-      containerEls.forEach(removeElement)
-      delete this.containerElsByType[type]
-    }
+    if (segs) {
 
-    delete this.renderedSegsByType[type]
+      if (type === 'bgEvent') {
+        this.context.view.triggerWillRemoveSegs(segs)
+      }
+
+      this.detachSegs(type, segs)
+    }
   }
 
 
   // Renders and assigns an `el` property for each fill segment. Generic enough to work with different types.
   // Only returns segments that successfully rendered.
-  buildSegEls(type, segs: Seg[], props) {
+  renderSegEls(type, segs: Seg[]) {
     let html = ''
     let i
 
@@ -55,7 +67,7 @@ export default class FillRenderer { // use for highlight, background events, bus
 
       // build a large concatenation of segment HTML
       for (i = 0; i < segs.length; i++) {
-        html += this.buildSegHtml(type, segs[i], props)
+        html += this.renderSegHtml(type, segs[i])
       }
 
       // Grab individual elements from the combined HTML string. Use each as the default rendering.
@@ -68,8 +80,12 @@ export default class FillRenderer { // use for highlight, background events, bus
         }
       })
 
-      if (props.filterSegs) {
-        segs = props.filterSegs(segs)
+      if (type === 'bgEvent') {
+        segs = filterSegsViaEls(
+          this.context.view,
+          segs,
+          false // isMirror. background events can never be mirror elements
+        )
       }
 
       // correct element type? (would be bad if a non-TD were inserted into a table for example)
@@ -83,29 +99,49 @@ export default class FillRenderer { // use for highlight, background events, bus
 
 
   // Builds the HTML needed for one fill segment. Generic enough to work with different types.
-  buildSegHtml(type, seg: Seg, props) {
-    // custom hooks per-type
-    let classes = props.getClasses ? props.getClasses(seg) : []
-    let css = cssToStr(props.getCss ? props.getCss(seg) : {})
+  renderSegHtml(type, seg: Seg) {
+    let css = null
+    let classNames = []
+
+    if (seg.eventRange) {
+      css = {
+        'background-color': seg.eventRange.ui.backgroundColor
+      }
+
+      classNames = classNames.concat(seg.eventRange.ui.classNames)
+    }
+
+    if (type === 'businessHours') {
+      classNames.push('fc-bgevent')
+    } else {
+      classNames.push('fc-' + type.toLowerCase())
+    }
 
     return '<' + this.fillSegTag +
-      (classes.length ? ' class="' + classes.join(' ') + '"' : '') +
-      (css ? ' style="' + css + '"' : '') +
+      (classNames.length ? ' class="' + classNames.join(' ') + '"' : '') +
+      (css ? ' style="' + cssToStr(css) + '"' : '') +
       '></' + this.fillSegTag + '>'
   }
 
 
-  // Should return wrapping DOM structure
-  attachSegEls(type, segs: Seg[]): HTMLElement[] {
-    // subclasses must implement
-    return null
+  abstract attachSegs(type, segs: Seg[]): HTMLElement[] | void
+
+
+  detachSegs(type, segs: Seg[]) {
+    let containerEls = this.containerElsByType[type]
+
+    if (containerEls) {
+      containerEls.forEach(removeElement)
+      delete this.containerElsByType[type]
+    }
   }
 
 
-  computeSize(type: string) {
+  computeSizes(type: string) {
   }
 
-  assignSize(type: string) {
+
+  assignSizes(type: string) {
   }
 
 }