Răsfoiți Sursa

global context

Adam Shaw 7 ani în urmă
părinte
comite
33fb723099

+ 3 - 3
src/Calendar.ts

@@ -3,7 +3,7 @@ import { computeHeightAndMargins } from './util/dom-geom'
 import { listenBySelector } from './util/dom-event'
 import { capitaliseFirstLetter, debounce } from './util/misc'
 import { globalDefaults, rtlDefaults } from './options'
-import GlobalEmitter from './common/GlobalEmitter'
+import GlobalContext from './common/GlobalContext'
 import { default as EmitterMixin, EmitterInterface } from './common/EmitterMixin'
 import Toolbar from './Toolbar'
 import OptionsManager from './OptionsManager'
@@ -274,7 +274,7 @@ export default class Calendar {
 
 
   bindGlobalHandlers() {
-    GlobalEmitter.needed()
+    GlobalContext.registerCalendar(this)
 
     if (this.opt('handleWindowResize')) {
       window.addEventListener('resize',
@@ -287,7 +287,7 @@ export default class Calendar {
   }
 
   unbindGlobalHandlers() {
-    GlobalEmitter.unneeded()
+    GlobalContext.unregisterCalendar(this)
 
     if (this.windowResizeProxy) {
       window.removeEventListener('resize', this.windowResizeProxy)

+ 0 - 4
src/basic/DayGrid.ts

@@ -624,10 +624,6 @@ export default class DayGrid extends InteractiveDateComponent {
     this.segPopover = new Popover(options)
     this.segPopover.show()
 
-    // the popover doesn't live within the grid's container element, and thus won't get the event
-    // delegated-handlers for free. attach event-related handlers to the popover.
-    this.bindAllSegHandlersToEl(this.segPopover.el)
-
     this.triggerRenderedSegs(segs)
   }
 

+ 31 - 0
src/common/GlobalContext.ts

@@ -0,0 +1,31 @@
+import { removeExact } from '../util/array'
+import Calendar from '../Calendar'
+
+let activeCalendars = []
+
+export default {
+
+  registerCalendar(calendar: Calendar) {
+    activeCalendars.push(calendar)
+
+    if (activeCalendars.length === 1) {
+      this.bind()
+    }
+  },
+
+  unregisterCalendar(calendar: Calendar) {
+    if (
+      removeExact(activeCalendars, calendar) && // any removed?
+      !activeCalendars.length // no more left
+    ) {
+      this.unbind()
+    }
+  },
+
+  bind() {
+  },
+
+  unbind() {
+  }
+
+}

+ 0 - 218
src/common/GlobalEmitter.ts

@@ -1,218 +0,0 @@
-import * as exportHooks from '../exports'
-import { default as EmitterMixin, EmitterInterface } from './EmitterMixin'
-
-(exportHooks as any).touchMouseIgnoreWait = 500
-
-let globalEmitter = null
-let neededCount = 0
-
-/*
-Listens to document and window-level user-interaction events, like touch events and mouse events,
-and fires these events as-is to whoever is observing a GlobalEmitter.
-Best when used as a singleton via GlobalEmitter.get()
-
-Normalizes mouse/touch events. For examples:
-- ignores the the simulated mouse events that happen after a quick tap: mousemove+mousedown+mouseup+click
-- compensates for various buggy scenarios where a touchend does not fire
-*/
-export default class GlobalEmitter {
-
-  on: EmitterInterface['on']
-  one: EmitterInterface['one']
-  off: EmitterInterface['off']
-  trigger: EmitterInterface['trigger']
-  triggerWith: EmitterInterface['triggerWith']
-  hasHandlers: EmitterInterface['hasHandlers']
-
-  isTouching: boolean = false
-  mouseIgnoreDepth: number = 0
-
-
-  // gets the singleton
-  static get() {
-    if (!globalEmitter) {
-      globalEmitter = new GlobalEmitter()
-      globalEmitter.bind()
-    }
-
-    return globalEmitter
-  }
-
-
-  // called when an object knows it will need a GlobalEmitter in the near future.
-  static needed() {
-    GlobalEmitter.get() // ensures globalEmitter
-    neededCount++
-  }
-
-
-  // called when the object that originally called needed() doesn't need a GlobalEmitter anymore.
-  static unneeded() {
-    if (neededCount > 0) {
-      neededCount--
-      if (!neededCount) { // nobody else needs it
-        globalEmitter.unbind()
-        globalEmitter = null
-      }
-    }
-  }
-
-
-  bind() {
-    // this.listenTo(document, {
-    //   touchstart: this.handleTouchStart,
-    //   touchcancel: this.handleTouchCancel,
-    //   touchend: this.handleTouchEnd,
-    //   mousedown: this.handleMouseDown,
-    //   mousemove: this.handleMouseMove,
-    //   mouseup: this.handleMouseUp,
-    //   click: this.handleClick,
-    //   selectstart: this.handleSelectStart,
-    //   contextmenu: this.handleContextMenu
-    // })
-
-    // because we need to call preventDefault
-    // because https://www.chromestatus.com/features/5093566007214080
-    // TODO: investigate performance because this is a global handler
-    window.addEventListener(
-      'touchmove',
-      this.handleTouchMove, // always bound to `this`
-      { passive: false } as any // allows preventDefault()
-    )
-
-    // attach a handler to get called when ANY scroll action happens on the page.
-    // this was impossible to do with normal on/off because 'scroll' doesn't bubble.
-    // http://stackoverflow.com/a/32954565/96342
-    window.addEventListener(
-      'scroll',
-      this.handleScroll, // always bound to `this`
-      true // useCapture
-    )
-  }
-
-  unbind() {
-    // this.stopListeningTo(document)
-
-    window.removeEventListener(
-      'touchmove',
-      this.handleTouchMove
-    )
-
-    window.removeEventListener(
-      'scroll',
-      this.handleScroll,
-      true // useCapture
-    )
-  }
-
-
-  // Touch Handlers
-  // -----------------------------------------------------------------------------------------------------------------
-
-  handleTouchStart(ev) {
-
-    // if a previous touch interaction never ended with a touchend, then implicitly end it,
-    // but since a new touch interaction is about to begin, don't start the mouse ignore period.
-    this.stopTouch(ev, true) // skipMouseIgnore=true
-
-    this.isTouching = true
-    this.trigger('touchstart', ev)
-  }
-
-  handleTouchMove = (ev) => {
-    if (this.isTouching) {
-      this.trigger('touchmove', ev)
-    }
-  }
-
-  handleTouchCancel(ev) {
-    if (this.isTouching) {
-      this.trigger('touchcancel', ev)
-
-      // Have touchcancel fire an artificial touchend. That way, handlers won't need to listen to both.
-      // If touchend fires later, it won't have any effect b/c isTouching will be false.
-      this.stopTouch(ev)
-    }
-  }
-
-  handleTouchEnd(ev) {
-    this.stopTouch(ev)
-  }
-
-
-  // Mouse Handlers
-  // -----------------------------------------------------------------------------------------------------------------
-
-  handleMouseDown(ev) {
-    if (!this.shouldIgnoreMouse()) {
-      this.trigger('mousedown', ev)
-    }
-  }
-
-  handleMouseMove(ev) {
-    if (!this.shouldIgnoreMouse()) {
-      this.trigger('mousemove', ev)
-    }
-  }
-
-  handleMouseUp(ev) {
-    if (!this.shouldIgnoreMouse()) {
-      this.trigger('mouseup', ev)
-    }
-  }
-
-  handleClick(ev) {
-    if (!this.shouldIgnoreMouse()) {
-      this.trigger('click', ev)
-    }
-  }
-
-
-  // Misc Handlers
-  // -----------------------------------------------------------------------------------------------------------------
-
-  handleSelectStart(ev) {
-    this.trigger('selectstart', ev)
-  }
-
-  handleContextMenu(ev) {
-    this.trigger('contextmenu', ev)
-  }
-
-  handleScroll = (ev) => {
-    this.trigger('scroll', ev)
-  }
-
-
-  // Utils
-  // -----------------------------------------------------------------------------------------------------------------
-
-  stopTouch(ev, skipMouseIgnore= false) {
-    if (this.isTouching) {
-      this.isTouching = false
-      this.trigger('touchend', ev)
-
-      if (!skipMouseIgnore) {
-        this.startTouchMouseIgnore()
-      }
-    }
-  }
-
-  startTouchMouseIgnore() {
-    let wait = (exportHooks as any).touchMouseIgnoreWait
-
-    if (wait) {
-      this.mouseIgnoreDepth++
-      setTimeout(() => {
-        this.mouseIgnoreDepth--
-      }, wait)
-    }
-  }
-
-  shouldIgnoreMouse() {
-    return this.isTouching || Boolean(this.mouseIgnoreDepth)
-  }
-
-}
-
-EmitterMixin.mixInto(GlobalEmitter)

+ 1 - 140
src/component/InteractiveDateComponent.ts

@@ -1,7 +1,4 @@
-import { elementClosest } from '../util/dom-manip'
-import { getEvIsTouch, listenBySelector, listenToHoverBySelector } from '../util/dom-event'
 import DateComponent from './DateComponent'
-import GlobalEmitter from '../common/GlobalEmitter'
 
 
 /*
@@ -9,146 +6,10 @@ NOTE: still needed for event element clicking and drag initiation
 */
 export default abstract class InteractiveDateComponent extends DateComponent {
 
-  // self-config, overridable by subclasses
-  segSelector: string = '.fc-event-container > *' // what constitutes an event element?
-
   // if defined, holds the unit identified (ex: "year" or "month") that determines the level of granularity
   // of the date areas. if not defined, assumes to be day and time granularity.
   // TODO: port isTimeScale into same system?
-  largeUnit: any
-
-
-  // Sets the container element that the view should render inside of, does global DOM-related initializations,
-  // and renders all the non-date-related content inside.
-  setElement(el) {
-    super.setElement(el)
-
-    this.bindAllSegHandlersToEl(el)
-  }
-
-
-  removeElement() {
-    this.endInteractions()
-
-    super.removeElement()
-  }
-
-
-  unrenderEvents() {
-    this.endInteractions()
-
-    super.unrenderEvents()
-  }
-
-
-  bindDateHandlerToEl(el, name, handler) {
-    el.addEventListener(name, (ev) => {
-      if (
-        !elementClosest(
-          ev.target,
-          this.segSelector + ':not(.fc-helper),' + // on or within an event segment
-          '.fc-more,' + // a "more.." link
-          'a[data-goto]' // a clickable nav link
-        )
-      ) {
-        return handler.call(this, ev)
-      }
-    })
-  }
-
-
-  bindAllSegHandlersToEl(el) {
-    // TODO
-  }
-
-
-  bindSegHandlerToEl(el, name, handler) {
-    listenBySelector(
-      el,
-      name,
-      this.segSelector,
-      this.makeSegMouseHandler(handler)
-    )
-  }
-
-
-  bindSegHoverHandlersToEl(el, onMouseEnter, onMouseLeave) {
-    listenToHoverBySelector(
-      el,
-      this.segSelector,
-      this.makeSegMouseHandler(onMouseEnter),
-      this.makeSegMouseHandler(onMouseLeave)
-    )
-  }
-
-
-  makeSegMouseHandler(handler) {
-    return (ev, segEl) => {
-      if (!segEl.classList.contains('fc-helper')) {
-        let seg = (segEl as any).fcSeg // grab segment data. put there by View::renderEventsPayload
-        if (seg && !this.shouldIgnoreEventPointing()) {
-          return handler.call(this, seg, ev) // context will be the Grid
-        }
-      }
-    }
-  }
-
-
-  shouldIgnoreMouse() {
-    // HACK
-    // This will still work even though bindDateHandlerToEl doesn't use GlobalEmitter.
-    return GlobalEmitter.get().shouldIgnoreMouse()
-  }
-
-
-  shouldIgnoreTouch() {
-    let view = this.view
-
-    // On iOS (and Android?) when a new selection is initiated overtop another selection,
-    // the touchend never fires because the elements gets removed mid-touch-interaction (my theory).
-    // HACK: simply don't allow this to happen.
-    // ALSO: prevent selection when an *event* is already raised.
-    return view.isSelected || Boolean(view.selectedEventInstance)
-  }
-
-
-  shouldIgnoreEventPointing() {
-    // only call the handlers if there is not a drag/resize in progress
-
-    return false
-    // return (this.eventDragging && this.eventDragging.isDragging) ||
-    //   (this.eventResizing && this.eventResizing.isResizing)
-  }
-
-
-  canStartSelection(seg, ev) {
-    return getEvIsTouch(ev) &&
-      !this.canStartResize(seg, ev) &&
-      (this.isEventDefDraggable(seg.eventRange.eventDef) ||
-        this.isEventDefResizable(seg.eventRange.eventDef))
-  }
-
-
-  canStartDrag(seg, ev) {
-    return !this.canStartResize(seg, ev) &&
-      this.isEventDefDraggable(seg.eventRange.eventDef)
-  }
-
-
-  canStartResize(seg, ev) {
-    let { eventDef, eventInstance } = seg.eventRange
-
-    return (!getEvIsTouch(ev) || this.selectedEventInstanceId === eventInstance.instanceId) &&
-      this.isEventDefResizable(eventDef) &&
-      ev.target.classList.contains('fc-resizer')
-  }
-
-
-  // Kills all in-progress dragging.
-  // Useful for when public API methods that result in re-rendering are invoked during a drag.
-  // Also useful for when touch devices misbehave and don't fire their touchend.
-  endInteractions() {
-  }
+  largeUnit: any // used still ?
 
 
   // Event Drag-n-Drop

+ 0 - 2
src/list/ListView.ts

@@ -17,8 +17,6 @@ export default class ListView extends View {
   eventRendererClass: any
   eventPointingClass: any
 
-  segSelector: any = '.fc-list-item' // which elements accept event actions
-
   scroller: Scroller
   contentEl: HTMLElement