Переглянути джерело

move bg event rendering out of EventRenderer

Adam Shaw 7 роки тому
батько
коміт
44e7e00ef2

+ 2 - 2
src/agenda/TimeGridEventRenderer.ts

@@ -16,8 +16,8 @@ export default class TimeGridEventRenderer extends EventRenderer {
   fullTimeFormat: DateFormatter
   fullTimeFormat: DateFormatter
 
 
 
 
-  constructor(timeGrid, fillRenderer) {
-    super(timeGrid, fillRenderer)
+  constructor(timeGrid) {
+    super(timeGrid)
     this.timeGrid = timeGrid
     this.timeGrid = timeGrid
 
 
     this.fullTimeFormat = createFormatter({
     this.fullTimeFormat = createFormatter({

+ 8 - 0
src/basic/DayGrid.ts

@@ -366,6 +366,14 @@ export default class DayGrid extends DateComponent {
   ------------------------------------------------------------------------------------------------------------------*/
   ------------------------------------------------------------------------------------------------------------------*/
 
 
 
 
+  filterBgEventRanges(bgEventRanges) {
+    // don't render timed background events
+    return bgEventRanges.filter(function(eventRange) {
+      return eventRange.def.allDay
+    })
+  }
+
+
   // Unrenders all events currently rendered on the grid
   // Unrenders all events currently rendered on the grid
   unrenderEvents() {
   unrenderEvents() {
     this.removeSegPopover() // removes the "more.." events popover
     this.removeSegPopover() // removes the "more.." events popover

+ 2 - 12
src/basic/DayGridEventRenderer.ts

@@ -14,22 +14,12 @@ export default class DayGridEventRenderer extends EventRenderer {
   rowStructs: any // an array of objects, each holding information about a row's foreground event-rendering
   rowStructs: any // an array of objects, each holding information about a row's foreground event-rendering
 
 
 
 
-  constructor(dayGrid, fillRenderer) {
-    super(dayGrid, fillRenderer)
+  constructor(dayGrid) {
+    super(dayGrid)
     this.dayGrid = dayGrid
     this.dayGrid = dayGrid
   }
   }
 
 
 
 
-  renderBgSegs(segs: Seg[]) {
-    // don't render timed background events
-    segs = segs.filter(function(seg) {
-      return seg.eventRange.def.allDay
-    })
-
-    return super.renderBgSegs(segs)
-  }
-
-
   // Renders the given foreground event segments onto the grid
   // Renders the given foreground event segments onto the grid
   renderFgSegs(segs: Seg[]) {
   renderFgSegs(segs: Seg[]) {
     let rowStructs = this.rowStructs = this.renderSegRows(segs)
     let rowStructs = this.rowStructs = this.renderSegRows(segs)

+ 55 - 14
src/component/DateComponent.ts

@@ -1,7 +1,7 @@
 import Component, { ComponentContext } from './Component'
 import Component, { ComponentContext } from './Component'
 import { DateProfile } from '../DateProfileGenerator'
 import { DateProfile } from '../DateProfileGenerator'
 import { EventStore, expandRecurring } from '../structs/event-store'
 import { EventStore, expandRecurring } from '../structs/event-store'
-import { EventUiHash, EventRenderRange, computeEventDefUis, sliceEventStore, computeEventDefUi } from './event-rendering'
+import { EventUiHash, EventRenderRange, computeEventDefUis, sliceEventStore, computeEventDefUi, hasBgRendering, filterSegsViaEls } from './event-rendering'
 import { DateSpan } from '../structs/date-span'
 import { DateSpan } from '../structs/date-span'
 import { EventInteractionUiState } from '../interactions/event-interaction-state'
 import { EventInteractionUiState } from '../interactions/event-interaction-state'
 import { createDuration, Duration } from '../datelib/duration'
 import { createDuration, Duration } from '../datelib/duration'
@@ -80,8 +80,8 @@ export default class DateComponent extends Component<DateComponentProps> {
       this.fillRenderer = new this.fillRendererClass(this)
       this.fillRenderer = new this.fillRendererClass(this)
     }
     }
 
 
-    if (this.eventRendererClass) { // fillRenderer is optional -----v
-      this.eventRenderer = new this.eventRendererClass(this, this.fillRenderer)
+    if (this.eventRendererClass) {
+      this.eventRenderer = new this.eventRendererClass(this)
     }
     }
 
 
     if (this.mirrorRendererClass && this.eventRenderer) {
     if (this.mirrorRendererClass && this.eventRenderer) {
@@ -284,11 +284,43 @@ export default class DateComponent extends Component<DateComponentProps> {
   }
   }
 
 
   renderEventRanges(eventRanges: EventRenderRange[]) {
   renderEventRanges(eventRanges: EventRenderRange[]) {
-    if (this.eventRenderer) {
-      this.eventRenderer.rangeUpdated() // poorly named now
-      this.eventRenderer.renderSegs(
-        this.eventRangesToSegs(eventRanges)
-      )
+    if (this.eventRenderer || this.fillRenderer) {
+
+      let bgRanges = []
+      let fgRanges = []
+
+      for (let eventRange of eventRanges) {
+        if (hasBgRendering(eventRange.ui)) {
+          bgRanges.push(eventRange)
+        } else {
+          fgRanges.push(eventRange)
+        }
+      }
+
+      if (this.eventRenderer) {
+        this.eventRenderer.rangeUpdated() // poorly named now
+        this.eventRenderer.renderSegs(
+          this.eventRangesToSegs(fgRanges)
+        )
+      }
+
+      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)
+          }
+        })
+      }
 
 
       let calendar = this.calendar
       let calendar = this.calendar
       if (!calendar.state.loadingLevel) { // avoid initial empty state while pending
       if (!calendar.state.loadingLevel) { // avoid initial empty state while pending
@@ -297,17 +329,27 @@ export default class DateComponent extends Component<DateComponentProps> {
     }
     }
   }
   }
 
 
+  filterBgEventRanges(bgEventRanges) {
+    return bgEventRanges
+  }
+
   unrenderEvents() {
   unrenderEvents() {
     if (this.eventRenderer) {
     if (this.eventRenderer) {
-      this.triggerWillRemoveSegs(this.eventRenderer.getSegs())
+      this.triggerWillRemoveSegs(this.eventRenderer.fgSegs || [])
       this.eventRenderer.unrender()
       this.eventRenderer.unrender()
     }
     }
+
+    if (this.fillRenderer) {
+      this.triggerWillRemoveSegs(this.fillRenderer.renderedSegsByType['bgEvent'] || [])
+      this.fillRenderer.unrender('bgEvent')
+    }
   }
   }
 
 
   computeEventsSize() {
   computeEventsSize() {
     if (this.fillRenderer) {
     if (this.fillRenderer) {
       this.fillRenderer.computeSize('bgEvent')
       this.fillRenderer.computeSize('bgEvent')
     }
     }
+
     if (this.eventRenderer) {
     if (this.eventRenderer) {
       this.eventRenderer.computeFgSizes()
       this.eventRenderer.computeFgSizes()
     }
     }
@@ -576,11 +618,10 @@ export default class DateComponent extends Component<DateComponentProps> {
   }
   }
 
 
   getAllEventSegs(): Seg[] {
   getAllEventSegs(): Seg[] {
-    if (this.eventRenderer) {
-      return this.eventRenderer.getSegs()
-    } else {
-      return []
-    }
+    return [].concat(
+      this.eventRenderer ? (this.eventRenderer.fgSegs || []) : [],
+      this.fillRenderer ? (this.fillRenderer.renderedSegsByType['bgEvent'] || []) : []
+    )
   }
   }
 
 
 
 

+ 48 - 0
src/component/event-rendering.ts

@@ -6,6 +6,9 @@ import { mapHash } from '../util/object'
 import { parseClassName } from '../util/html'
 import { parseClassName } from '../util/html'
 import { Duration } from '../datelib/duration'
 import { Duration } from '../datelib/duration'
 import { computeVisibleDayRange } from '../util/misc'
 import { computeVisibleDayRange } from '../util/misc'
+import { Seg } from './DateComponent'
+import View from '../View'
+import EventApi from '../api/EventApi'
 
 
 export interface EventUi {
 export interface EventUi {
   startEditable: boolean
   startEditable: boolean
@@ -128,6 +131,51 @@ export function hasBgRendering(ui: EventUi) {
   return ui.rendering === 'background' || ui.rendering === 'inverse-background'
   return ui.rendering === 'background' || ui.rendering === 'inverse-background'
 }
 }
 
 
+export function filterSegsViaEls(view: View, segs: Seg[], isMirror) {
+
+  if (view.hasPublicHandlers('eventRender')) {
+    segs = segs.filter(function(seg) {
+      let custom = view.publiclyTrigger('eventRender', [
+        {
+          event: new EventApi(
+            view.calendar,
+            seg.eventRange.def,
+            seg.eventRange.instance
+          ),
+          isMirror,
+          isStart: seg.isStart,
+          isEnd: seg.isEnd,
+          // TODO: include seg.range once all components consistently generate it
+          el: seg.el,
+          view
+        }
+      ])
+
+      if (custom === false) { // means don't render at all
+        return false
+      } else if (custom && custom !== true) {
+        seg.el = custom
+      }
+
+      return true
+    })
+  }
+
+  for (let seg of segs) {
+    setElSeg(seg.el, seg)
+  }
+
+  return segs
+}
+
+function setElSeg(el: HTMLElement, seg: Seg) {
+  (el as any).fcSeg = seg
+}
+
+export function getElSeg(el: HTMLElement): Seg | null {
+  return (el as any).fcSeg || null
+}
+
 
 
 // UI Props
 // UI Props
 // ----------------------------------------------------------------------------------------------------
 // ----------------------------------------------------------------------------------------------------

+ 9 - 113
src/component/renderers/EventRenderer.ts

@@ -3,9 +3,8 @@ import { DateMarker } from '../../datelib/marker'
 import { createFormatter, DateFormatter } from '../../datelib/formatting'
 import { createFormatter, DateFormatter } from '../../datelib/formatting'
 import { htmlToElements } from '../../util/dom-manip'
 import { htmlToElements } from '../../util/dom-manip'
 import { compareByFieldSpecs } from '../../util/misc'
 import { compareByFieldSpecs } from '../../util/misc'
-import { EventRenderRange, EventUi, hasBgRendering } from '../event-rendering'
+import { EventRenderRange, EventUi, filterSegsViaEls } from '../event-rendering'
 import { Seg } from '../DateComponent'
 import { Seg } from '../DateComponent'
-import EventApi from '../../api/EventApi'
 import { assignTo } from '../../util/object'
 import { assignTo } from '../../util/object'
 
 
 
 
@@ -13,10 +12,8 @@ export default class EventRenderer {
 
 
   view: View
   view: View
   component: any
   component: any
-  fillRenderer: any // might remain null
 
 
   fgSegs: Seg[]
   fgSegs: Seg[]
-  bgSegs: Seg[]
 
 
   // derived from options
   // derived from options
   eventTimeFormat: DateFormatter
   eventTimeFormat: DateFormatter
@@ -24,10 +21,9 @@ export default class EventRenderer {
   displayEventEnd: boolean
   displayEventEnd: boolean
 
 
 
 
-  constructor(component, fillRenderer) { // fillRenderer is optional
+  constructor(component) {
     this.view = component.view || component
     this.view = component.view || component
     this.component = component
     this.component = component
-    this.fillRenderer = fillRenderer
   }
   }
 
 
 
 
@@ -61,46 +57,26 @@ export default class EventRenderer {
   }
   }
 
 
 
 
-  renderSegs(allSegs: Seg[]) {
-    let bgSegs: Seg[] = []
-    let fgSegs: Seg[] = []
-
-    for (let seg of allSegs) {
-      if (hasBgRendering(seg.eventRange.ui)) {
-        bgSegs.push(seg)
-      } else {
-        fgSegs.push(seg)
-      }
-    }
-
-    this.bgSegs = this.renderBgSegs(bgSegs)
+  renderSegs(fgSegs: Seg[]) {
 
 
     // render an `.el` on each seg
     // render an `.el` on each seg
     // returns a subset of the segs. segs that were actually rendered
     // returns a subset of the segs. segs that were actually rendered
-    fgSegs = this.renderFgSegEls(fgSegs)
+    fgSegs = this.renderFgSegEls(fgSegs, false)
 
 
     if (this.renderFgSegs(fgSegs) !== false) { // no failure?
     if (this.renderFgSegs(fgSegs) !== false) { // no failure?
       this.fgSegs = fgSegs
       this.fgSegs = fgSegs
     }
     }
 
 
-    this.view.triggerRenderedSegs(this.getSegs())
+    this.view.triggerRenderedSegs(this.fgSegs || [])
   }
   }
 
 
 
 
   unrender() {
   unrender() {
-    this.unrenderBgSegs()
-    this.bgSegs = null
-
     this.unrenderFgSegs(this.fgSegs || [])
     this.unrenderFgSegs(this.fgSegs || [])
     this.fgSegs = null
     this.fgSegs = null
   }
   }
 
 
 
 
-  getSegs() {
-    return (this.bgSegs || []).concat(this.fgSegs || [])
-  }
-
-
   // Renders foreground event segments onto the grid
   // Renders foreground event segments onto the grid
   renderFgSegs(segs: Seg[]): (boolean | void) {
   renderFgSegs(segs: Seg[]): (boolean | void) {
     // subclasses must implement
     // subclasses must implement
@@ -116,47 +92,10 @@ export default class EventRenderer {
   }
   }
 
 
 
 
-  renderBgSegs(segs: Seg[]): Seg[] {
-    if (this.fillRenderer) {
-      return this.fillRenderer.renderSegs('bgEvent', segs, {
-        getClasses: (seg) => {
-          return seg.eventRange.ui.classNames.concat([ 'fc-bgevent' ])
-        },
-        getCss: (seg) => {
-          return {
-            'background-color': seg.eventRange.ui.backgroundColor
-          }
-        },
-        filterEl: (seg, el) => {
-          el = this.filterEventRenderEl(seg, el)
-
-          if (el) {
-            setElSeg(el, seg)
-            seg.el = el
-          }
-
-          return el
-        }
-      })
-    }
-
-    return []
-  }
-
-
-  unrenderBgSegs() {
-    if (this.fillRenderer) {
-      this.fillRenderer.unrender('bgEvent')
-    }
-  }
-
-
   // Renders and assigns an `el` property for each foreground event segment.
   // Renders and assigns an `el` property for each foreground event segment.
   // Only returns segments that successfully rendered.
   // Only returns segments that successfully rendered.
-  renderFgSegEls(segs: Seg[], isMirrors?: boolean) {
-    let hasEventRenderHandlers = this.view.hasPublicHandlers('eventRender')
+  renderFgSegEls(segs: Seg[], isMirrors: boolean) {
     let html = ''
     let html = ''
-    let renderedSegs = []
     let i
     let i
 
 
     if (segs.length) { // don't build an empty html string
     if (segs.length) { // don't build an empty html string
@@ -171,19 +110,15 @@ export default class EventRenderer {
       htmlToElements(html).forEach((el, i) => {
       htmlToElements(html).forEach((el, i) => {
         let seg = segs[i]
         let seg = segs[i]
 
 
-        if (hasEventRenderHandlers) { // optimization
-          el = this.filterEventRenderEl(seg, el, isMirrors)
-        }
-
         if (el) {
         if (el) {
-          setElSeg(el, seg)
           seg.el = el
           seg.el = el
-          renderedSegs.push(seg)
         }
         }
       })
       })
+
+      segs = filterSegsViaEls(this.view, segs, isMirrors)
     }
     }
 
 
-    return renderedSegs
+    return segs
   }
   }
 
 
 
 
@@ -213,36 +148,6 @@ export default class EventRenderer {
   }
   }
 
 
 
 
-  // Given an event and the default element used for rendering, returns the element that should actually be used.
-  // Basically runs events and elements through the eventRender hook.
-  filterEventRenderEl(seg: Seg, el: HTMLElement, isMirror: boolean = false) {
-
-    let custom = this.view.publiclyTrigger('eventRender', [
-      {
-        event: new EventApi(
-          this.view.calendar,
-          seg.eventRange.def,
-          seg.eventRange.instance
-        ),
-        isMirror,
-        isStart: seg.isStart,
-        isEnd: seg.isEnd,
-        // TODO: include seg.range once all components consistently generate it
-        el,
-        view: this.view
-      }
-    ])
-
-    if (custom === false) { // means don't render at all
-      el = null
-    } else if (custom && custom !== true) {
-      el = custom
-    }
-
-    return el
-  }
-
-
   // Compute the text that should be displayed on an event's element.
   // Compute the text that should be displayed on an event's element.
   // `range` can be the Event object itself, or something range-like, with at least a `start`.
   // `range` can be the Event object itself, or something range-like, with at least a `start`.
   // If event times are disabled, or the event has no time, will return a blank string.
   // If event times are disabled, or the event has no time, will return a blank string.
@@ -352,15 +257,6 @@ export default class EventRenderer {
 }
 }
 
 
 
 
-function setElSeg(el: HTMLElement, seg: Seg) {
-  (el as any).fcSeg = seg
-}
-
-export function getElSeg(el: HTMLElement): Seg | null {
-  return (el as any).fcSeg || null
-}
-
-
 // returns a object with all primitive props that can be compared
 // returns a object with all primitive props that can be compared
 export function buildSegCompareObj(seg: Seg) {
 export function buildSegCompareObj(seg: Seg) {
   let eventDef = seg.eventRange.def
   let eventDef = seg.eventRange.def

+ 11 - 12
src/component/renderers/FillRenderer.ts

@@ -28,8 +28,6 @@ export default class FillRenderer { // use for highlight, background events, bus
     }
     }
 
 
     this.renderedSegsByType[type] = renderedSegs
     this.renderedSegsByType[type] = renderedSegs
-
-    return renderedSegs
   }
   }
 
 
 
 
@@ -50,7 +48,6 @@ export default class FillRenderer { // use for highlight, background events, bus
   // Only returns segments that successfully rendered.
   // Only returns segments that successfully rendered.
   buildSegEls(type, segs: Seg[], props) {
   buildSegEls(type, segs: Seg[], props) {
     let html = ''
     let html = ''
-    let renderedSegs = []
     let i
     let i
 
 
     if (segs.length) {
     if (segs.length) {
@@ -65,20 +62,22 @@ export default class FillRenderer { // use for highlight, background events, bus
       htmlToElements(html).forEach((el, i) => {
       htmlToElements(html).forEach((el, i) => {
         let seg = segs[i]
         let seg = segs[i]
 
 
-        // allow custom filter methods per-type
-        if (props.filterEl) {
-          el = props.filterEl(seg, el) // might return null/undefined
-        }
-
-        // correct element type? (would be bad if a non-TD were inserted into a table for example)
-        if (el && elementMatches(el, this.fillSegTag)) {
+        if (el) {
           seg.el = el
           seg.el = el
-          renderedSegs.push(seg)
         }
         }
       })
       })
+
+      if (props.filterSegs) {
+        segs = props.filterSegs(segs)
+      }
+
+      // correct element type? (would be bad if a non-TD were inserted into a table for example)
+      segs = segs.filter((seg) => {
+        return elementMatches(seg.el, this.fillSegTag)
+      })
     }
     }
 
 
-    return renderedSegs
+    return segs
   }
   }
 
 
 
 

+ 1 - 1
src/interactions/EventClicking.ts

@@ -1,8 +1,8 @@
 import DateComponent from '../component/DateComponent'
 import DateComponent from '../component/DateComponent'
 import { listenBySelector } from '../util/dom-event'
 import { listenBySelector } from '../util/dom-event'
-import { getElSeg } from '../component/renderers/EventRenderer'
 import EventApi from '../api/EventApi'
 import EventApi from '../api/EventApi'
 import { elementClosest } from '../util/dom-manip'
 import { elementClosest } from '../util/dom-manip'
+import { getElSeg } from '../component/event-rendering'
 
 
 /*
 /*
 Detects when the user clicks on an event within a DateComponent
 Detects when the user clicks on an event within a DateComponent

+ 1 - 2
src/interactions/EventDragging.ts

@@ -1,5 +1,4 @@
 import { default as DateComponent, Seg } from '../component/DateComponent'
 import { default as DateComponent, Seg } from '../component/DateComponent'
-import { getElSeg } from '../component/renderers/EventRenderer'
 import { PointerDragEvent } from '../dnd/PointerDragging'
 import { PointerDragEvent } from '../dnd/PointerDragging'
 import HitDragging, { isHitsEqual, Hit } from './HitDragging'
 import HitDragging, { isHitsEqual, Hit } from './HitDragging'
 import { EventMutation, applyMutationToEventStore } from '../structs/event-mutation'
 import { EventMutation, applyMutationToEventStore } from '../structs/event-mutation'
@@ -11,7 +10,7 @@ import { EventStore, getRelevantEvents, createEmptyEventStore } from '../structs
 import Calendar from '../Calendar'
 import Calendar from '../Calendar'
 import { EventInteractionState } from '../interactions/event-interaction-state'
 import { EventInteractionState } from '../interactions/event-interaction-state'
 import { diffDates, enableCursor, disableCursor } from '../util/misc'
 import { diffDates, enableCursor, disableCursor } from '../util/misc'
-import { EventRenderRange } from '../component/event-rendering'
+import { EventRenderRange, getElSeg } from '../component/event-rendering'
 import EventApi from '../api/EventApi'
 import EventApi from '../api/EventApi'
 
 
 export default class EventDragging { // TODO: rename to EventSelectingAndDragging
 export default class EventDragging { // TODO: rename to EventSelectingAndDragging

+ 1 - 1
src/interactions/EventHovering.ts

@@ -1,7 +1,7 @@
 import DateComponent from '../component/DateComponent'
 import DateComponent from '../component/DateComponent'
 import { listenToHoverBySelector } from '../util/dom-event'
 import { listenToHoverBySelector } from '../util/dom-event'
-import { getElSeg } from '../component/renderers/EventRenderer'
 import EventApi from '../api/EventApi'
 import EventApi from '../api/EventApi'
+import { getElSeg } from '../component/event-rendering'
 
 
 /*
 /*
 Triggers events and adds/removes core classNames when the user's pointer
 Triggers events and adds/removes core classNames when the user's pointer

+ 1 - 2
src/interactions/EventResizing.ts

@@ -4,12 +4,11 @@ import { EventMutation, applyMutationToEventStore } from '../structs/event-mutat
 import { elementClosest } from '../util/dom-manip'
 import { elementClosest } from '../util/dom-manip'
 import FeaturefulElementDragging from '../dnd/FeaturefulElementDragging'
 import FeaturefulElementDragging from '../dnd/FeaturefulElementDragging'
 import { PointerDragEvent } from '../dnd/PointerDragging'
 import { PointerDragEvent } from '../dnd/PointerDragging'
-import { getElSeg } from '../component/renderers/EventRenderer'
 import { EventStore, getRelevantEvents } from '../structs/event-store'
 import { EventStore, getRelevantEvents } from '../structs/event-store'
 import { diffDates, enableCursor, disableCursor } from '../util/misc'
 import { diffDates, enableCursor, disableCursor } from '../util/misc'
 import { DateRange } from '../datelib/date-range'
 import { DateRange } from '../datelib/date-range'
 import EventApi from '../api/EventApi'
 import EventApi from '../api/EventApi'
-import { EventRenderRange } from '../component/event-rendering'
+import { EventRenderRange, getElSeg } from '../component/event-rendering'
 import { createDuration } from '../datelib/duration'
 import { createDuration } from '../datelib/duration'
 
 
 export default class EventDragging {
 export default class EventDragging {