Просмотр исходного кода

get datespans/selections/hits sorted out;

Adam Shaw 7 лет назад
Родитель
Сommit
04486227a7

+ 10 - 10
src/Calendar.ts

@@ -18,7 +18,7 @@ import { DateMarker, startOfDay } from './datelib/marker'
 import { createFormatter } from './datelib/formatting'
 import { Duration, createDuration } from './datelib/duration'
 import { CalendarState, reduce } from './reducers/main'
-import { parseSelection, SelectionInput, Selection } from './reducers/selection'
+import { parseDateSpan, DateSpanInput, DateSpan } from './reducers/date-span'
 import reselector from './util/reselector'
 import { assignTo } from './util/object'
 import { RenderForceFlags } from './component/Component'
@@ -896,25 +896,25 @@ export default class Calendar {
   }
 
 
-  // Selection / DayClick
+  // DateSpan / DayClick
   // -----------------------------------------------------------------------------------------------------------------
 
 
   // this public method receives start/end dates in any format, with any timezone
   // NOTE: args were changed from v3
   select(dateOrObj: DateInput | object, endDate?: DateInput) {
-    let selectionInput: SelectionInput
+    let selectionInput: DateSpanInput
 
     if (endDate == null) {
-      selectionInput = dateOrObj as SelectionInput
+      selectionInput = dateOrObj as DateSpanInput
     } else {
       selectionInput = {
         start: dateOrObj,
         end: endDate
-      } as SelectionInput
+      } as DateSpanInput
     }
 
-    let selection = parseSelection(selectionInput, this.dateEnv)
+    let selection = parseDateSpan(selectionInput, this.dateEnv)
     if (selection) {
       this.dispatch({
         type: 'SELECT',
@@ -935,7 +935,7 @@ export default class Calendar {
 
 
   // Triggers handlers to 'select'
-  triggerSelect(selection: Selection, view: View, ev?: UIEvent) {
+  triggerSelect(selection: DateSpan, view: View, ev?: UIEvent) {
     this.publiclyTrigger('select', [
       {
         start: this.dateEnv.toDate(selection.range.start),
@@ -958,11 +958,11 @@ export default class Calendar {
   }
 
 
-  triggerDayClick(selection: Selection, dayEl: HTMLElement, view: View, ev: UIEvent) {
+  triggerDayClick(dateSpan: DateSpan, dayEl: HTMLElement, view: View, ev: UIEvent) {
     this.publiclyTrigger('dayClick', [
       {
-        date: this.dateEnv.toDate(selection.range.start),
-        isAllDay: selection.isAllDay,
+        date: this.dateEnv.toDate(dateSpan.range.start),
+        isAllDay: dateSpan.isAllDay,
         dayEl,
         jsEvent: ev,
         view

+ 10 - 6
src/agenda/TimeGrid.ts

@@ -10,8 +10,9 @@ import { Duration, createDuration, addDurations, multiplyDuration, wholeDivideDu
 import { startOfDay, DateMarker, addMs } from '../datelib/marker'
 import { DateFormatter, createFormatter, formatIsoTimeString } from '../datelib/formatting'
 import DateComponent, { Seg } from '../component/DateComponent'
-import { Selection } from '../reducers/selection'
+import { DateSpan } from '../reducers/date-span'
 import { EventStore } from '../reducers/event-store'
+import { Hit } from '../interactions/HitDragging'
 
 /* A component that renders one or more columns of vertical time slots
 ----------------------------------------------------------------------------------------------------------------------*/
@@ -561,7 +562,7 @@ export default class TimeGrid extends DateComponent {
   ------------------------------------------------------------------------------------------------------------------*/
 
 
-  queryHit(leftOffset, topOffset): Selection {
+  queryHit(leftOffset, topOffset): Hit {
     let snapsPerSlot = this.snapsPerSlot
     let colCoordCache = this.colCoordCache
     let slatCoordCache = this.slatCoordCache
@@ -588,9 +589,12 @@ export default class TimeGrid extends DateComponent {
         let end = dateEnv.add(start, this.snapDuration)
 
         return {
-          range: new UnzonedRange(start, end),
-          isAllDay: false,
-          el: this.colEls[colIndex],
+          component: this,
+          dateSpan: {
+            range: new UnzonedRange(start, end),
+            isAllDay: false
+          },
+          dayEl: this.colEls[colIndex],
           rect: {
             left: colCoordCache.getLeftOffset(colIndex),
             right: colCoordCache.getRightOffset(colIndex),
@@ -660,7 +664,7 @@ export default class TimeGrid extends DateComponent {
 
 
   // Renders a visual indication of a selection. Overrides the default, which was to simply render a highlight.
-  renderSelection(selection: Selection) {
+  renderSelection(selection: DateSpan) {
     let segs = this.selectionToSegs(selection)
 
     if (this.opt('selectHelper')) { // this setting signals that a mock helper event should be rendered

+ 8 - 5
src/basic/DayGrid.ts

@@ -19,8 +19,8 @@ import { addDays } from '../datelib/marker'
 import { createFormatter } from '../datelib/formatting'
 import DateComponent, { Seg } from '../component/DateComponent'
 import { EventStore } from '../reducers/event-store'
-import { Selection } from '../reducers/selection'
 import DayTile from './DayTile'
+import { Hit } from '../interactions/HitDragging'
 
 const DAY_NUM_FORMAT = createFormatter({ day: 'numeric' })
 const WEEK_NUM_FORMAT = createFormatter({ week: 'numeric' })
@@ -291,7 +291,7 @@ export default class DayGrid extends DateComponent {
   ------------------------------------------------------------------------------------------------------------------*/
 
 
-  queryHit(leftOffset, topOffset): Selection { // why is this a Selection?
+  queryHit(leftOffset, topOffset): Hit {
     let { colCoordCache, rowCoordCache } = this
 
     if (colCoordCache.isLeftInBounds(leftOffset) && rowCoordCache.isTopInBounds(topOffset)) {
@@ -300,9 +300,12 @@ export default class DayGrid extends DateComponent {
 
       if (row != null && col != null) {
         return {
-          range: this.getCellRange(row, col),
-          isAllDay: true,
-          el: this.getCellEl(row, col),
+          component: this,
+          dateSpan: {
+            range: this.getCellRange(row, col),
+            isAllDay: true
+          },
+          dayEl: this.getCellEl(row, col),
           rect: {
             left: colCoordCache.getLeftOffset(col),
             right: colCoordCache.getRightOffset(col),

+ 8 - 7
src/component/DateComponent.ts

@@ -6,7 +6,7 @@ import View from '../View'
 import { DateProfile } from '../DateProfileGenerator'
 import { DateMarker, DAY_IDS, addDays, startOfDay, diffDays, diffWholeDays } from '../datelib/marker'
 import { Duration, createDuration, asRoughMs } from '../datelib/duration'
-import { Selection } from '../reducers/selection'
+import { DateSpan } from '../reducers/date-span'
 import UnzonedRange from '../models/UnzonedRange'
 import { EventRenderRange, sliceEventStore } from '../reducers/event-rendering'
 import { EventStore } from '../reducers/event-store'
@@ -16,12 +16,13 @@ import Theme from '../theme/Theme'
 import { EventInteractionState } from '../reducers/event-interaction'
 import { assignTo } from '../util/object'
 import GlobalContext from '../common/GlobalContext'
+import { Hit } from '../interactions/HitDragging'
 
 
 export interface DateComponentRenderState {
   dateProfile: DateProfile
   eventStore: EventStore
-  selection: Selection | null
+  selection: DateSpan | null
   dragState: EventInteractionState | null
   eventResizeState: EventInteractionState | null
   businessHoursDef: BusinessHourDef // BusinessHourDef's `false` is the empty state
@@ -76,7 +77,7 @@ export default abstract class DateComponent extends Component {
 
   dateProfile: DateProfile = null
   businessHoursDef: BusinessHourDef = false
-  selection: Selection = null
+  selection: DateSpan = null
   eventStore: EventStore = null
   dragState: EventInteractionState = null
   eventResizeState: EventInteractionState = null
@@ -191,7 +192,7 @@ export default abstract class DateComponent extends Component {
   }
 
 
-  queryHit(leftOffset, topOffset): Selection {
+  queryHit(leftOffset, topOffset): Hit {
     return null // this should be abstract
   }
 
@@ -724,12 +725,12 @@ export default abstract class DateComponent extends Component {
   }
 
 
-  // Selection
+  // DateSpan
   // ---------------------------------------------------------------------------------------------------------------
 
 
   // Renders a visual indication of the selection
-  renderSelection(selection: Selection) {
+  renderSelection(selection: DateSpan) {
     this.renderHighlightSegs(this.selectionToSegs(selection))
   }
 
@@ -818,7 +819,7 @@ export default abstract class DateComponent extends Component {
   }
 
 
-  selectionToSegs(selection: Selection): Seg[] {
+  selectionToSegs(selection: DateSpan): Seg[] {
     return this.rangeToSegs(selection.range, selection.isAllDay)
   }
 

+ 1 - 1
src/dnd/ElementMirror.ts

@@ -103,7 +103,7 @@ export default class ElementMirror {
   }
 
   updateElPosition() {
-    if (this.isVisible) {
+    if (this.sourceEl && this.isVisible) {
       if (!this.sourceElRect) {
         this.sourceElRect = computeRect(this.sourceEl)
       }

+ 15 - 10
src/interactions-external/ExternalElementDragging.ts

@@ -7,6 +7,8 @@ import UnzonedRange from '../models/UnzonedRange'
 import * as externalHooks from '../exports'
 import { createDuration } from '../datelib/duration'
 import { assignTo } from '../util/object'
+import { DateSpan } from '../reducers/date-span'
+import Calendar from '../Calendar'
 
 export default class ExternalElementDragging {
 
@@ -45,10 +47,14 @@ export default class ExternalElementDragging {
     this.eventCreationData = this.explicitEventCreationData || getDraggedElMeta(ev.subjectEl)
   }
 
-  onHitOver = (hit) => {
+  onHitOver = (hit: Hit) => {
     let calendar = hit.component.getCalendar()
 
-    this.addableEventStore = computeEventStoreForHit(hit, this.eventCreationData)
+    this.addableEventStore = computeEventStoreForDateSpan(
+      hit.dateSpan,
+      hit.component.getCalendar(),
+      this.eventCreationData
+    )
 
     calendar.dispatch({
       type: 'SET_DRAG',
@@ -104,8 +110,8 @@ export default class ExternalElementDragging {
       finalCalendar.publiclyTrigger('drop', [
         {
           draggedEl: pev.subjectEl,
-          date: finalCalendar.dateEnv.toDate(finalHit.range.start),
-          isAllDay: finalHit.isAllDay,
+          date: finalCalendar.dateEnv.toDate(finalHit.dateSpan.range.start),
+          isAllDay: finalHit.dateSpan.isAllDay,
           jsEvent: pev.origEvent,
           view: finalView
         }
@@ -135,27 +141,26 @@ export default class ExternalElementDragging {
 }
 
 
-function computeEventStoreForHit(hit: Hit, eventCreationData): EventStore {
-  let calendar = hit.component.getCalendar()
+function computeEventStoreForDateSpan(dateSpan: DateSpan, calendar: Calendar, eventCreationData): EventStore {
 
   let def = parseDef(
     eventCreationData.standardProps || {},
     null,
-    hit.isAllDay,
+    dateSpan.isAllDay,
     Boolean(eventCreationData.duration) // hasEnd
   )
 
-  let start = hit.range.start
+  let start = dateSpan.range.start
 
   // only rely on time info if drop zone is all-day,
   // otherwise, we already know the time
-  if (hit.isAllDay && eventCreationData.time) {
+  if (dateSpan.isAllDay && eventCreationData.time) {
     start = calendar.dateEnv.add(start, eventCreationData.time)
   }
 
   let end = eventCreationData.duration ?
     calendar.dateEnv.add(start, eventCreationData.duration) :
-    calendar.getDefaultEventEnd(hit.isAllDay, start)
+    calendar.getDefaultEventEnd(dateSpan.isAllDay, start)
 
   let instance = createInstance(def.defId, new UnzonedRange(start, end))
 

+ 6 - 1
src/interactions/DateClicking.ts

@@ -41,7 +41,12 @@ export default class DateClicking {
       let { initialHit, finalHit } = this.hitDragging
 
       if (initialHit && finalHit && isHitsEqual(initialHit, finalHit)) {
-        component.getCalendar().triggerDayClick(initialHit, initialHit.el, component.view, ev.origEvent)
+        component.getCalendar().triggerDayClick(
+          initialHit.dateSpan,
+          initialHit.dayEl,
+          component.view,
+          ev.origEvent
+        )
       }
     }
   }

+ 13 - 10
src/interactions/DateSelecting.ts

@@ -2,7 +2,7 @@ import { compareNumbers } from '../util/misc'
 import { elementClosest } from '../util/dom-manip'
 import DateComponent from '../component/DateComponent'
 import HitDragging, { Hit } from './HitDragging'
-import { Selection } from '../reducers/selection'
+import { DateSpan } from '../reducers/date-span'
 import UnzonedRange from '../models/UnzonedRange'
 import { PointerDragEvent } from '../dnd/PointerDragging'
 import FeaturefulElementDragging from '../dnd/FeaturefulElementDragging'
@@ -14,7 +14,7 @@ export default class DateSelecting {
   globalContext: GlobalContext
   dragging: FeaturefulElementDragging
   hitDragging: HitDragging
-  dragSelection: Selection
+  dragSelection: DateSpan
 
   constructor(component: DateComponent, globalContext: GlobalContext) {
     this.component = component
@@ -59,7 +59,10 @@ export default class DateSelecting {
   onHitOver = (overHit: Hit) => { // TODO: do a onHitChange instead?
     let { globalContext } = this
     let calendar = this.component.getCalendar()
-    let dragSelection = computeSelection(this.hitDragging.initialHit, overHit)
+    let dragSelection = computeSelection(
+      this.hitDragging.initialHit.dateSpan,
+      overHit.dateSpan
+    )
 
     if (dragSelection) {
       globalContext.selectedCalendar = calendar
@@ -72,7 +75,7 @@ export default class DateSelecting {
     }
   }
 
-  onHitOut = (hit: Selection, ev) => {
+  onHitOut = (hit: DateSpan, ev) => {
     let { globalContext } = this
     let calendar = this.component.getCalendar()
 
@@ -122,19 +125,19 @@ function getComponentDelay(component): number {
   return delay
 }
 
-function computeSelection(hit0: Hit, hit1: Hit): Selection {
+function computeSelection(dateSpan0: DateSpan, dateSpan1: DateSpan): DateSpan {
   let ms = [
-    hit0.range.start,
-    hit0.range.end,
-    hit1.range.start,
-    hit1.range.end
+    dateSpan0.range.start,
+    dateSpan0.range.end,
+    dateSpan1.range.start,
+    dateSpan1.range.end
   ]
 
   ms.sort(compareNumbers)
 
   return {
     range: new UnzonedRange(ms[0], ms[3]),
-    isAllDay: hit0.isAllDay
+    isAllDay: dateSpan0.isAllDay
   }
 }
 

+ 7 - 5
src/interactions/EventDragging.ts

@@ -185,17 +185,19 @@ export default class EventDragging {
 }
 
 function computeEventMutation(hit0: Hit, hit1: Hit): EventMutation {
-  let date0 = hit0.range.start
-  let date1 = hit1.range.start
+  let dateSpan0 = hit0.dateSpan
+  let dateSpan1 = hit1.dateSpan
+  let date0 = dateSpan0.range.start
+  let date1 = dateSpan1.range.start
   let standardProps = null
 
-  if (hit0.isAllDay !== hit1.isAllDay) {
+  if (dateSpan0.isAllDay !== dateSpan1.isAllDay) {
     standardProps = {
       hasEnd: false, // TODO: make this a setting
-      isAllDay: hit1.isAllDay
+      isAllDay: dateSpan1.isAllDay
     }
 
-    if (hit1.isAllDay) {
+    if (dateSpan1.isAllDay) {
       // means date1 is already start-of-day,
       // but date0 needs to be converted
       date0 = startOfDay(date0)

+ 3 - 3
src/interactions/EventResizing.ts

@@ -83,7 +83,7 @@ export default class EventDragging {
     }
   }
 
-  onHitOut = (hit, ev) => {
+  onHitOut = (hit: Hit, ev) => {
     let calendar = this.component.getCalendar()
 
     calendar.dispatch({
@@ -120,8 +120,8 @@ export default class EventDragging {
 
 function computeMutation(hit0: Hit, hit1: Hit, isFromStart: boolean, instanceRange: UnzonedRange): EventMutation {
   let dateEnv = hit0.component.getDateEnv()
-  let date0 = hit0.range.start
-  let date1 = hit1.range.start
+  let date0 = hit0.dateSpan.range.start
+  let date1 = hit1.dateSpan.range.start
 
   let delta = diffDates(
     date0, date1,

+ 9 - 25
src/interactions/HitDragging.ts

@@ -2,12 +2,15 @@ import EmitterMixin from '../common/EmitterMixin'
 import { PointerDragEvent } from '../dnd/PointerDragging'
 import ElementDragging from '../dnd/ElementDragging'
 import DateComponent, { DateComponentHash } from '../component/DateComponent'
-import { Selection } from '../reducers/selection'
+import { DateSpan, isDateSpansEqual } from '../reducers/date-span'
 import { computeRect } from '../util/dom-geom'
-import { constrainPoint, intersectRects, getRectCenter, diffPoints } from '../util/geom'
+import { constrainPoint, intersectRects, getRectCenter, diffPoints, Rect } from '../util/geom'
 
-export interface Hit extends Selection { // TODO: rename! put somewhere else
+export interface Hit {
   component: DateComponent
+  dateSpan: DateSpan
+  dayEl: HTMLElement
+  rect: Rect
 }
 
 /*
@@ -161,10 +164,9 @@ export default class HitDragging {
   queryHit(x, y): Hit {
     for (let id in this.droppableHash) {
       let component = this.droppableHash[id]
-      let hit = component.queryHit(x, y) as Hit
+      let hit = component.queryHit(x, y)
 
       if (hit) {
-        hit.component = component
         return hit
       }
     }
@@ -172,7 +174,7 @@ export default class HitDragging {
 
 }
 
-export function isHitsEqual(hit0: Selection, hit1: Selection) {
+export function isHitsEqual(hit0: Hit, hit1: Hit) {
   if (!hit0 && !hit1) {
     return true
   }
@@ -181,23 +183,5 @@ export function isHitsEqual(hit0: Selection, hit1: Selection) {
     return false
   }
 
-  if (!hit0.range.equals(hit1.range)) {
-    return false
-  }
-
-  for (let propName in hit1) {
-    if (propName !== 'range' && propName !== 'component' && propName !== 'rect') {
-      if (hit0[propName] !== hit1[propName]) {
-        return false
-      }
-    }
-  }
-
-  for (let propName in hit0) {
-    if (!(propName in hit1)) {
-      return false
-    }
-  }
-
-  return true
+  return isDateSpansEqual(hit0.dateSpan, hit1.dateSpan)
 }

+ 26 - 3
src/reducers/selection.ts → src/reducers/date-span.ts

@@ -2,14 +2,14 @@ import UnzonedRange from '../models/UnzonedRange'
 import { DateInput, DateEnv } from '../datelib/env'
 import { refineProps } from '../reducers/utils'
 
-export interface SelectionInput {
+export interface DateSpanInput {
   start: DateInput
   end: DateInput
   isAllDay?: boolean
   [otherProp: string]: any
 }
 
-export interface Selection {
+export interface DateSpan {
   range: UnzonedRange
   isAllDay: boolean
   [otherProp: string]: any
@@ -21,7 +21,7 @@ const STANDARD_PROPS = {
   isAllDay: Boolean
 }
 
-export function parseSelection(raw: SelectionInput, dateEnv: DateEnv): Selection {
+export function parseDateSpan(raw: DateSpanInput, dateEnv: DateEnv): DateSpan {
   let otherProps = {} as any
   let standardProps = refineProps(raw, STANDARD_PROPS, otherProps)
   let startMeta = standardProps.start ? dateEnv.createMarkerMeta(standardProps.start) : null
@@ -41,3 +41,26 @@ export function parseSelection(raw: SelectionInput, dateEnv: DateEnv): Selection
     return otherProps
   }
 }
+
+export function isDateSpansEqual(span0: DateSpan, span1: DateSpan): boolean {
+
+  if (!span0.range.equals(span1.range)) {
+    return false
+  }
+
+  for (let propName in span1) {
+    if (propName !== 'range') {
+      if (span0[propName] !== span1[propName]) {
+        return false
+      }
+    }
+  }
+
+  for (let propName in span0) {
+    if (!(propName in span1)) {
+      return false
+    }
+  }
+
+  return true
+}