Skip to content

Commit

Permalink
better fg renderer api
Browse files Browse the repository at this point in the history
  • Loading branch information
arshaw committed Oct 30, 2018
1 parent 44e7e00 commit 640263c
Show file tree
Hide file tree
Showing 12 changed files with 201 additions and 189 deletions.
36 changes: 18 additions & 18 deletions src/agenda/TimeGridEventRenderer.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,36 @@
import { htmlEscape, cssToStr } from '../util/html'
import { removeElement, applyStyle } from '../util/dom-manip'
import { createFormatter, DateFormatter } from '../datelib/formatting'
import EventRenderer, { buildSegCompareObj } from '../component/renderers/EventRenderer'
import FgEventRenderer, { buildSegCompareObj } from '../component/renderers/FgEventRenderer'
import { Seg } from '../component/DateComponent'
import { isMultiDayRange, compareByFieldSpecs } from '../util/misc'
import TimeGrid from './TimeGrid'

/*
Only handles foreground segs.
Does not own rendering. Use for low-level util methods by TimeGrid.
*/
export default class TimeGridEventRenderer extends EventRenderer {
export default class TimeGridEventRenderer extends FgEventRenderer {

timeGrid: any
timeGrid: TimeGrid
segsByCol: any
fullTimeFormat: DateFormatter


constructor(timeGrid) {
super(timeGrid)
constructor(timeGrid: TimeGrid) {
super(timeGrid.context)

this.timeGrid = timeGrid

this.fullTimeFormat = createFormatter({
hour: 'numeric',
minute: '2-digit',
separator: this.opt('defaultRangeSeparator')
separator: this.context.options.defaultRangeSeparator
})
}


renderFgSegs(segs: Seg[]) {
attachSegs(segs: Seg[]) {
this.renderFgSegsIntoContainers(segs, this.timeGrid.fgContainerEls)
}

Expand All @@ -41,12 +43,10 @@ export default class TimeGridEventRenderer extends EventRenderer {
}


unrenderFgSegs() {
if (this.fgSegs) { // hack
this.fgSegs.forEach(function(seg) {
removeElement(seg.el)
})
}
detachSegs(segs: Seg[]) {
segs.forEach(function(seg) {
removeElement(seg.el)
})

this.segsByCol = null
}
Expand Down Expand Up @@ -93,13 +93,13 @@ export default class TimeGridEventRenderer extends EventRenderer {


// Renders the HTML for a single event segment's default rendering
fgSegHtml(seg: Seg) {
renderSegHtml(seg: Seg) {
let eventRange = seg.eventRange
let eventDef = eventRange.def
let eventUi = eventRange.ui
let allDay = eventDef.allDay
let isDraggable = eventUi.startEditable
let isResizableFromStart = seg.isStart && eventUi.durationEditable && this.opt('eventResizableFromStart')
let isResizableFromStart = seg.isStart && eventUi.durationEditable && this.context.options.eventResizableFromStart
let isResizableFromEnd = seg.isEnd && eventUi.durationEditable
let classes = this.getSegClasses(seg, isDraggable, isResizableFromStart || isResizableFromEnd)
let skinCss = cssToStr(this.getSkinCss(eventUi))
Expand Down Expand Up @@ -246,7 +246,7 @@ export default class TimeGridEventRenderer extends EventRenderer {
// put segments that are closer to initial edge first (and favor ones with no coords yet)
{ field: 'backwardCoord', order: 1 }
].concat(
this.view.eventOrderSpecs
this.context.view.eventOrderSpecs
)

objs.sort(function(obj0, obj1) {
Expand Down Expand Up @@ -280,10 +280,10 @@ export default class TimeGridEventRenderer extends EventRenderer {
// Generates an object with CSS properties/values that should be applied to an event segment element.
// Contains important positioning-related properties that should be applied to any event element, customized or not.
generateFgSegHorizontalCss(seg: Seg) {
let shouldOverlap = this.opt('slotEventOverlap')
let shouldOverlap = this.context.options.slotEventOverlap
let backwardCoord = seg.backwardCoord // the left side if LTR. the right side if RTL. floating-point
let forwardCoord = seg.forwardCoord // the right side if LTR. the left side if RTL. floating-point
let props = this.timeGrid.generateSegVerticalCss(seg) // get top/bottom first
let props = this.timeGrid.generateSegVerticalCss(seg) as any // get top/bottom first
let isRtl = this.timeGrid.isRtl
let left // amount of space from left edge, a fraction of the total width
let right // amount of space from right edge, a fraction of the total width
Expand Down
83 changes: 7 additions & 76 deletions src/basic/DayGridEventRenderer.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
import { htmlEscape, cssToStr } from '../util/html'
import { createElement, removeElement } from '../util/dom-manip'
import EventRenderer from '../component/renderers/EventRenderer'
import DayGrid from './DayGrid'
import { Seg } from '../component/DateComponent'
import SimpleDayGridEventRenderer from './SimpleDayGridEventRenderer'


/* Event-rendering methods for the DayGrid class
----------------------------------------------------------------------------------------------------------------------*/

export default class DayGridEventRenderer extends EventRenderer {
export default class DayGridEventRenderer extends SimpleDayGridEventRenderer {

dayGrid: DayGrid
rowStructs: any // an array of objects, each holding information about a row's foreground event-rendering


constructor(dayGrid) {
super(dayGrid)
constructor(dayGrid: DayGrid) {
super(dayGrid.context)

this.dayGrid = dayGrid
}


// Renders the given foreground event segments onto the grid
renderFgSegs(segs: Seg[]) {
attachSegs(segs: Seg[]) {
let rowStructs = this.rowStructs = this.renderSegRows(segs)

// append to each row's content skeleton
Expand All @@ -34,7 +34,7 @@ export default class DayGridEventRenderer extends EventRenderer {


// Unrenders all currently rendered foreground event segments
unrenderFgSegs() {
detachSegs() {
let rowStructs = this.rowStructs || []
let rowStruct

Expand Down Expand Up @@ -208,80 +208,11 @@ export default class DayGridEventRenderer extends EventRenderer {
}


// Computes a default event time formatting string if `eventTimeFormat` is not explicitly defined
computeEventTimeFormat() {
return {
hour: 'numeric',
minute: '2-digit',
omitZeroMinute: true,
meridiem: 'narrow'
}
}


// Computes a default `displayEventEnd` value if one is not expliclty defined
computeDisplayEventEnd() {
return this.dayGrid.colCnt === 1 // we'll likely have space if there's only one day
}


// Builds the HTML to be used for the default element for an individual segment
fgSegHtml(seg: Seg) {
let eventRange = seg.eventRange
let eventDef = eventRange.def
let eventUi = eventRange.ui
let allDay = eventDef.allDay
let isDraggable = eventUi.startEditable
let isResizableFromStart = allDay && seg.isStart && eventUi.durationEditable && this.opt('eventResizableFromStart')
let isResizableFromEnd = allDay && seg.isEnd && eventUi.durationEditable
let classes = this.getSegClasses(seg, isDraggable, isResizableFromStart || isResizableFromEnd)
let skinCss = cssToStr(this.getSkinCss(eventUi))
let timeHtml = ''
let timeText
let titleHtml

classes.unshift('fc-day-grid-event', 'fc-h-event')

// Only display a timed events time if it is the starting segment
if (seg.isStart) {
timeText = this.getTimeText(eventRange)
if (timeText) {
timeHtml = '<span class="fc-time">' + htmlEscape(timeText) + '</span>'
}
}

titleHtml =
'<span class="fc-title">' +
(htmlEscape(eventDef.title || '') || '&nbsp;') + // we always want one line of height
'</span>'

return '<a class="' + classes.join(' ') + '"' +
(eventDef.url ?
' href="' + htmlEscape(eventDef.url) + '"' :
''
) +
(skinCss ?
' style="' + skinCss + '"' :
''
) +
'>' +
'<div class="fc-content">' +
(this.component.isRtl ?
titleHtml + ' ' + timeHtml : // put a natural space in between
timeHtml + ' ' + titleHtml //
) +
'</div>' +
(isResizableFromStart ?
'<div class="fc-resizer fc-start-resizer"></div>' :
''
) +
(isResizableFromEnd ?
'<div class="fc-resizer fc-end-resizer"></div>' :
''
) +
'</a>'
}

}


Expand Down
28 changes: 19 additions & 9 deletions src/basic/DayTile.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import DateComponent, { Seg } from '../component/DateComponent'
import DayGridEventRenderer from './DayGridEventRenderer'
import SimpleDayGridEventRenderer from './SimpleDayGridEventRenderer'
import { htmlEscape } from '../util/html'
import { createFormatter } from '../datelib/formatting'
import { Hit } from '../interactions/HitDragging'
Expand All @@ -8,6 +8,7 @@ import { computeRect } from '../util/dom-geom'
import { Rect, pointInsideRect } from '../util/geom'
import { addDays, DateMarker } from '../datelib/marker'
import { ComponentContext } from '../component/Component'
import { removeElement } from '../util/dom-manip'

export default class DayTile extends DateComponent {

Expand Down Expand Up @@ -50,8 +51,6 @@ export default class DayTile extends DateComponent {

this.segContainerEl = this.el.querySelector('.fc-event-container')

// HACK
this.eventRenderer.rangeUpdated()
this.eventRenderer.renderSegs(props.segs)
}

Expand Down Expand Up @@ -100,19 +99,30 @@ export default class DayTile extends DateComponent {

}

// hack
export class DayTileEventRenderer extends DayGridEventRenderer {
export class DayTileEventRenderer extends SimpleDayGridEventRenderer {

// simply append the els the container element
renderFgSegs(segs: Seg[]) {
dayTile: DayTile

constructor(dayTile) {
super(dayTile.context)

this.dayTile = dayTile
}

attachSegs(segs: Seg[]) {
for (let seg of segs) {
this.component.segContainerEl.appendChild(seg.el)
this.dayTile.segContainerEl.appendChild(seg.el)
}
}

detachSegs(segs: Seg[]) {
for (let seg of segs) {
removeElement(seg.el)
}
}

}

DayTile.prototype.isInteractable = true
DayTile.prototype.useEventCenter = false

DayTile.prototype.eventRendererClass = DayTileEventRenderer
86 changes: 86 additions & 0 deletions src/basic/SimpleDayGridEventRenderer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import { htmlEscape, cssToStr } from '../util/html'
import FgEventRenderer from '../component/renderers/FgEventRenderer'
import { Seg } from '../component/DateComponent'


/* Event-rendering methods for the DayGrid class
----------------------------------------------------------------------------------------------------------------------*/

export default abstract class SimpleDayGridEventRenderer extends FgEventRenderer {


// Builds the HTML to be used for the default element for an individual segment
renderSegHtml(seg: Seg) {
let { options } = this.context
let eventRange = seg.eventRange
let eventDef = eventRange.def
let eventUi = eventRange.ui
let allDay = eventDef.allDay
let isDraggable = eventUi.startEditable
let isResizableFromStart = allDay && seg.isStart && eventUi.durationEditable && options.eventResizableFromStart
let isResizableFromEnd = allDay && seg.isEnd && eventUi.durationEditable
let classes = this.getSegClasses(seg, isDraggable, isResizableFromStart || isResizableFromEnd)
let skinCss = cssToStr(this.getSkinCss(eventUi))
let timeHtml = ''
let timeText
let titleHtml

classes.unshift('fc-day-grid-event', 'fc-h-event')

// Only display a timed events time if it is the starting segment
if (seg.isStart) {
timeText = this.getTimeText(eventRange)
if (timeText) {
timeHtml = '<span class="fc-time">' + htmlEscape(timeText) + '</span>'
}
}

titleHtml =
'<span class="fc-title">' +
(htmlEscape(eventDef.title || '') || '&nbsp;') + // we always want one line of height
'</span>'

return '<a class="' + classes.join(' ') + '"' +
(eventDef.url ?
' href="' + htmlEscape(eventDef.url) + '"' :
''
) +
(skinCss ?
' style="' + skinCss + '"' :
''
) +
'>' +
'<div class="fc-content">' +
(options.dir === 'rtl' ?
titleHtml + ' ' + timeHtml : // put a natural space in between
timeHtml + ' ' + titleHtml //
) +
'</div>' +
(isResizableFromStart ?
'<div class="fc-resizer fc-start-resizer"></div>' :
''
) +
(isResizableFromEnd ?
'<div class="fc-resizer fc-end-resizer"></div>' :
''
) +
'</a>'
}


// Computes a default event time formatting string if `eventTimeFormat` is not explicitly defined
computeEventTimeFormat() {
return {
hour: 'numeric',
minute: '2-digit',
omitZeroMinute: true,
meridiem: 'narrow'
}
}


computeDisplayEventEnd() {
return false // TODO: somehow consider the originating DayGrid's column count
}

}

0 comments on commit 640263c

Please sign in to comment.