Procházet zdrojové kódy

move external dragging higher up the chain

Adam Shaw před 7 roky
rodič
revize
aa90f11d93

+ 44 - 0
src/Calendar.ts

@@ -61,6 +61,7 @@ export default class Calendar {
   defaultTimedEventDuration: moment.Duration
   localeData: object
 
+  $document: any // jQuery
   el: HTMLElement
   contentEl: HTMLElement
   suggestedViewHeight: number
@@ -405,10 +406,53 @@ export default class Calendar {
         )
       )
     }
+
+    if (!this.$document && window['jQuery']) {
+      this.$document = window['jQuery'](document)
+    }
+    if (this.$document) { // we can only attach jQueryUI drag handlers to a jQuery element reference
+      this.$document.on('dragstart sortstart', this.handleJqUiDragStart)
+    }
+  }
+
+
+  handleJqUiDragStart = (ev, ui) => {
+
+    const handleJqUiDragMove = (ev, ui) => {
+      if (this.view) {
+        this.view.handleExternalDragMove(ev)
+      }
+    }
+    const handleJqUiDragStop = (ev, ui) => {
+      if (this.view) {
+        this.view.handleExternalDragStop(ev)
+      }
+      this.$document
+        .off('drag', handleJqUiDragMove)
+        .off('dragstop', handleJqUiDragStop)
+    }
+
+    this.$document
+      .on('drag', handleJqUiDragMove)
+      .on('dragstop', handleJqUiDragStop)
+
+    if (this.view) {
+      const el = ((ui && ui.item) ? ui.item[0] : null) || ev.target
+      this.view.handlExternalDragStart(
+        ev.originalEvent,
+        el,
+        ev.name === 'dragstart' // don't watch mouse/touch movements if doing jqui drag (not sort)
+      )
+    }
   }
 
 
   destroy() {
+
+    if (this.$document) {
+      this.$document.off('dragstart sortstart', this.handleJqUiDragStart)
+    }
+
     if (this.view) {
       this.clearView()
     }

+ 3 - 4
src/View.ts

@@ -608,18 +608,18 @@ export default abstract class View extends InteractiveDateComponent {
   // Must be called when an external element, via jQuery UI, has been dropped onto the calendar.
   // `meta` is the parsed data that has been embedded into the dragging event.
   // `dropLocation` is an object that contains the new zoned start/end/allDay values for the event.
-  reportExternalDrop(singleEventDef, isEvent, isSticky, el, ev, ui) {
+  reportExternalDrop(singleEventDef, isEvent, isSticky, el, ev) {
 
     if (isEvent) {
       this.calendar.eventManager.addEventDef(singleEventDef, isSticky)
     }
 
-    this.triggerExternalDrop(singleEventDef, isEvent, el, ev, ui)
+    this.triggerExternalDrop(singleEventDef, isEvent, el, ev)
   }
 
 
   // Triggers external-drop handlers that have subscribed via the API
-  triggerExternalDrop(singleEventDef, isEvent, el, ev, ui) {
+  triggerExternalDrop(singleEventDef, isEvent, el, ev) {
 
     // trigger 'drop' regardless of whether element represents an event
     this.publiclyTrigger('drop', {
@@ -627,7 +627,6 @@ export default abstract class View extends InteractiveDateComponent {
       args: [
         singleEventDef.dateProfile.start.clone(),
         ev,
-        ui,
         this
       ]
     })

+ 4 - 17
src/common/DragListener.ts

@@ -33,7 +33,6 @@ export default class DragListener {
   listenTo: ListenerInterface['listenTo']
   stopListeningTo: ListenerInterface['stopListeningTo']
 
-  $document: any // jQuery object
   options: DragListenerOptions
   subjectEl: HTMLElement
 
@@ -50,7 +49,7 @@ export default class DragListener {
   isDelayEnded: boolean = false
   isDragging: boolean = false
   isTouch: boolean = false
-  isGeneric: boolean = false // initiated by 'dragstart' (jqui)
+  skipBinding: boolean = false // if true, don't watch mouse/touch events
 
   delay: any
   delayTimeoutId: any
@@ -81,7 +80,7 @@ export default class DragListener {
   // -----------------------------------------------------------------------------------------------------------------
 
 
-  startInteraction(ev, extraOptions: any= {}) {
+  startInteraction(ev, extraOptions: any = {}) {
 
     if (ev.type === 'mousedown') {
       if (GlobalEmitter.get().shouldIgnoreMouse()) {
@@ -104,7 +103,6 @@ export default class DragListener {
 
       this.isInteracting = true
       this.isTouch = getEvIsTouch(ev)
-      this.isGeneric = ev.type === 'dragstart'
       this.isDelayEnded = false
       this.isDistanceSurpassed = false
 
@@ -163,16 +161,8 @@ export default class DragListener {
     // so listen to the GlobalEmitter singleton, which is always bound, instead of the document directly.
     let globalEmitter = GlobalEmitter.get()
 
-    if (this.isGeneric) {
-      if (!this.$document && window['jQuery']) {
-        this.$document = window['jQuery'](document)
-      }
-      if (this.$document) { // we can only attach jQueryUI drag handlers to a jQuery element reference
-        this.listenTo(this.$document, { // might only work on iOS because of GlobalEmitter's bind :(
-          drag: this.handleMove,
-          dragstop: this.endInteraction
-        })
-      }
+    if (this.skipBinding) {
+      ;
     } else if (this.isTouch) {
       this.listenTo(globalEmitter, {
         touchmove: this.handleTouchMove,
@@ -195,9 +185,6 @@ export default class DragListener {
 
   unbindHandlers() {
     this.stopListeningTo(GlobalEmitter.get())
-    if (this.$document) {
-      this.stopListeningTo(this.$document) // for isGeneric
-    }
   }
 
 

+ 31 - 18
src/component/InteractiveDateComponent.ts

@@ -91,24 +91,6 @@ export default abstract class InteractiveDateComponent extends DateComponent {
   }
 
 
-  bindGlobalHandlers() {
-    super.bindGlobalHandlers()
-
-    if (this.externalDropping) {
-      this.externalDropping.bindToDocument()
-    }
-  }
-
-
-  unbindGlobalHandlers() {
-    super.unbindGlobalHandlers()
-
-    if (this.externalDropping) {
-      this.externalDropping.unbindFromDocument()
-    }
-  }
-
-
   bindDateHandlerToEl(el, name, handler) {
     el.addEventListener(name, (ev) => {
       if (
@@ -273,6 +255,37 @@ export default abstract class InteractiveDateComponent extends DateComponent {
   }
 
 
+  // EXTERNAL Drag-n-Drop
+  // ---------------------------------------------------------------------------------------------------------------
+
+
+  handlExternalDragStart(ev, el, skipBinding) {
+    if (this.externalDropping) {
+      this.externalDropping.handleDragStart(ev, el, skipBinding)
+    }
+
+    this.callChildren('handlExternalDragStart', arguments)
+  }
+
+
+  handleExternalDragMove(ev) {
+    if (this.externalDropping) {
+      this.externalDropping.handleDragMove(ev)
+    }
+
+    this.callChildren('handleExternalDragMove', arguments)
+  }
+
+
+  handleExternalDragStop(ev) {
+    if (this.externalDropping) {
+      this.externalDropping.handleDragStop(ev)
+    }
+
+    this.callChildren('handleExternalDragStop', arguments)
+  }
+
+
   // Event Resizing
   // ---------------------------------------------------------------------------------------------------------------
 

+ 20 - 34
src/component/interactions/ExternalDropping.ts

@@ -4,7 +4,6 @@ import { assignTo } from '../../util/object'
 import { elementMatches } from '../../util/dom-manip'
 import { disableCursor, enableCursor } from '../../util/misc'
 import momentExt from '../../moment-ext'
-import { default as ListenerMixin, ListenerInterface } from '../../common/ListenerMixin'
 import HitDragListener from '../../common/HitDragListener'
 import SingleEventDef from '../../models/event/SingleEventDef'
 import EventInstanceGroup from '../../models/event/EventInstanceGroup'
@@ -14,10 +13,6 @@ import Interaction from './Interaction'
 
 export default class ExternalDropping extends Interaction {
 
-  listenTo: ListenerInterface['listenTo']
-  stopListeningTo: ListenerInterface['stopListeningTo']
-
-  $document: any
   dragListener: any
   isDragging: boolean = false // jqui-dragging an external element? boolean
 
@@ -39,48 +34,40 @@ export default class ExternalDropping extends Interaction {
   }
 
 
-  bindToDocument() {
-    if (!this.$document && window['jQuery']) {
-      this.$document = window['jQuery'](document)
-    }
-    if (this.$document) { // need jquery for attaching jqui handlers
-      this.listenTo(this.$document, {
-        dragstart: this.handleDragStart, // jqui
-        sortstart: this.handleDragStart // jqui
-      })
-    }
-  }
-
-
-  unbindFromDocument() {
-    if (this.$document) {
-      this.stopListeningTo(this.$document)
-    }
-  }
-
-
   // Called when a jQuery UI drag is initiated anywhere in the DOM
-  handleDragStart(ev, ui) {
-    let el
+  handleDragStart(ev, el, skipBinding) {
     let accept
 
     if (this.opt('droppable')) { // only listen if this setting is on
-      el = ((ui && ui.item) ? ui.item[0] : null) || ev.target
 
       // Test that the dragged element passes the dropAccept selector or filter function.
       // FYI, the default is "*" (matches all)
       accept = this.opt('dropAccept')
       if (typeof accept === 'function' ? accept.call(el, el) : elementMatches(el, accept)) {
         if (!this.isDragging) { // prevent double-listening if fired twice
-          this.listenToExternalDrag(el, ev, ui)
+          this.listenToExternalDrag(ev, el, skipBinding)
         }
       }
     }
   }
 
 
-  // Called when a jQuery UI drag starts and it needs to be monitored for dropping
-  listenToExternalDrag(el, ev, ui) {
+  handleDragMove(ev) {
+    if (this.dragListener) {
+      this.dragListener.handleMove(ev)
+    }
+  }
+
+
+  handleDragStop(ev) {
+    if (this.dragListener) {
+      this.dragListener.endInteraction(ev)
+    }
+  }
+
+
+  // Called when a 3rd-party draggable starts and it needs to be monitored for dropping
+  listenToExternalDrag(ev, el, skipBinding) {
     let component = this.component
     let view = this.view
     let meta = getDraggedElMeta(el) // extra data about event drop, including possible event to create
@@ -140,7 +127,7 @@ export default class ExternalDropping extends Interaction {
             singleEventDef,
             Boolean(meta.eventProps), // isEvent
             Boolean(meta.stick), // isSticky
-            el, ev, ui
+            el, ev
           )
         }
 
@@ -149,6 +136,7 @@ export default class ExternalDropping extends Interaction {
       }
     })
 
+    dragListener.skipBinding = skipBinding
     dragListener.startDrag(ev) // start listening immediately
   }
 
@@ -196,8 +184,6 @@ export default class ExternalDropping extends Interaction {
 
 }
 
-ListenerMixin.mixInto(ExternalDropping);
-
 
 /* External-Dragging-Element Data
 ----------------------------------------------------------------------------------------------------------------------*/