@@ -53,23 +53,28 @@ namespace dnd {
53
53
export class Simulation {
54
54
private store : DragDataStore ;
55
55
private dataTransfer : DataTransfer ;
56
+ private marker : HTMLElement ;
56
57
57
- constructor ( private draggable : Element , private droppable : Element ) {
58
+ constructor ( private draggable : HTMLElement , private droppable : HTMLElement ) {
58
59
this . store = new DragDataStore ( ) ;
59
60
this . store . mode = "readwrite" ;
60
61
this . dataTransfer = new DataTransfer ( this . store ) ;
62
+ droppable . style . outline = "thin double #ffa1ce" ;
63
+ this . marker = Simulation . createAndAttachMarker ( droppable ) ;
61
64
}
62
65
63
66
dragStart ( ) {
64
67
dragStart ( this . draggable , this . dataTransfer ) ;
65
68
}
66
69
67
- dragOver ( ) {
68
- dragOver ( this . store , this . droppable , this . dataTransfer ) ;
70
+ dragOver ( x : number , y : number ) {
71
+ const event = dragOver ( this . store , this . droppable , this . dataTransfer , x , y ) ;
72
+ this . moveMarkerToEventPageCoordinates ( event ) ;
69
73
}
70
74
71
75
dragOverElement ( x : number , y : number ) {
72
- dragOverElement ( this . droppable , { x, y } , this . dataTransfer ) ;
76
+ const event = dragOverElement ( this . droppable , x , y , this . dataTransfer ) ;
77
+ this . moveMarkerToEventPageCoordinates ( event ) ;
73
78
}
74
79
75
80
drop ( element ?: Element ) {
@@ -79,31 +84,65 @@ namespace dnd {
79
84
endDrag ( ) {
80
85
endDrag ( this . store , this . draggable , this . dataTransfer ) ;
81
86
}
87
+
88
+ private moveMarkerToEventPageCoordinates ( event : MouseEvent ) {
89
+ this . marker . style . left = `${ event . pageX } px` ;
90
+ this . marker . style . top = `${ event . pageY } px` ;
91
+ }
92
+
93
+ private static createAndAttachMarker ( droppable : HTMLElement ) : HTMLElement {
94
+ const style = document . createElement ( "style" ) ;
95
+ style . textContent = `
96
+ #content_main {
97
+ outline: thin double #ffa1ce;
98
+ }
99
+ #dnd-debug-marker {
100
+ position: absolute;
101
+ width: 20px;
102
+ height: 20px;
103
+ box-sizing: border-box;
104
+ top: -9999px;
105
+ left: -9999px;
106
+ transform: translate(-50%, -50%);
107
+ background: rgba(255, 0, 0, 0.2);
108
+ border: thin solid rgba(255, 255, 255, 0.75);
109
+ border-radius: 50%;
110
+ z-index: 9999;
111
+ }
112
+ ` ;
113
+ const body = ( droppable as any ) . closest ( "body" ) ;
114
+ const marker = document . createElement ( "div" ) ;
115
+ marker . id = "dnd-debug-marker" ;
116
+ body . appendChild ( style ) ;
117
+ body . appendChild ( marker ) ;
118
+ return marker ;
119
+ }
82
120
}
83
121
84
122
function dragStart ( draggable : Element , dataTransfer : DataTransfer ) : void {
85
123
const dragstartEvent = createEventWithDataTransfer ( "dragstart" , dataTransfer ) ;
86
124
draggable . dispatchEvent ( dragstartEvent ) ;
87
125
}
88
126
89
- function dragOver ( store : DragDataStore , droppable : Element , dataTransfer : DataTransfer ) : void {
127
+ function dragOver ( store : DragDataStore , droppable : Element , dataTransfer : DataTransfer , xOffset : number = 0 , yOffset : number = 0 ) : DragEvent {
90
128
// For the drop event. The list of items representing dragged data can be
91
129
// read, including the data. No new data can be added.
92
130
store . mode = "readonly" ;
93
131
const dragEnterEvent = createEventWithDataTransfer ( "dragenter" , dataTransfer ) ;
94
132
droppable . dispatchEvent ( dragEnterEvent ) ;
95
133
96
- dragOverElement ( droppable , { x : 0 , y : 0 } , dataTransfer ) ;
134
+ return dragOverElement ( droppable , xOffset , yOffset , dataTransfer ) ;
97
135
}
98
136
99
- function dragOverElement ( droppable : Element , offset : { x : number , y : number } , dataTransfer : DataTransfer ) {
137
+ function dragOverElement ( droppable : Element , xOffset : number , yOffset : number , dataTransfer : DataTransfer ) : DragEvent {
100
138
const dragOverEvent = createEventWithDataTransfer ( "dragover" , dataTransfer ) ;
101
- const { pageX, pageY} = elementCenterInPage ( droppable ) ;
139
+ const { pageX, pageY } = coordinatesOfElementWithOffset ( droppable , xOffset , yOffset ) ;
102
140
// We are assigning read-only properties here.
103
141
// That only works because this is not a browser-created native event!
104
- dragOverEvent . pageX = pageX + offset . x ;
105
- dragOverEvent . pageY = pageY + offset . y ;
142
+ dragOverEvent . pageX = pageX ;
143
+ dragOverEvent . pageY = pageY ;
106
144
droppable . dispatchEvent ( dragOverEvent ) ;
145
+ return dragOverEvent ;
107
146
}
108
147
109
148
function drop ( droppable : Element , dataTransfer : DataTransfer ) : void {
@@ -129,6 +168,15 @@ namespace dnd {
129
168
}
130
169
131
170
171
+ function coordinatesOfElementWithOffset ( droppable : Element , xOffset : number , yOffset : number ) : { pageX : number , pageY : number } {
172
+ const rect = droppable . getBoundingClientRect ( ) ;
173
+ const body = ( droppable as any ) . closest ( "body" ) ;
174
+ const bodyRect = body . getBoundingClientRect ( ) ;
175
+ const pageX = rect . left - bodyRect . left + xOffset ;
176
+ const pageY = rect . top - bodyRect . top + yOffset ;
177
+ return { pageX, pageY} ;
178
+ }
179
+
132
180
/**
133
181
* Creates an event instance with a DataTransfer.
134
182
*/
@@ -139,15 +187,6 @@ namespace dnd {
139
187
return event ;
140
188
}
141
189
142
- function elementCenterInPage ( droppable : Element ) {
143
- let rect = droppable . getBoundingClientRect ( ) ;
144
- return {
145
- pageX : window . scrollX + rect . left + rect . width / 2 ,
146
- pageY : window . scrollY + rect . top + rect . height / 2 ,
147
- } ;
148
- }
149
-
150
-
151
190
type EventType = 'dragstart'
152
191
| 'drag'
153
192
| 'dragenter'
@@ -175,7 +214,7 @@ namespace dnd {
175
214
176
215
/**
177
216
* Returns the kind of operation that is currently selected. If the kind of
178
- * operation isn' t one of those that is allowed by the effectAllowed
217
+ * operation isn" t one of those that is allowed by the effectAllowed
179
218
* attribute, then the operation will fail.
180
219
*
181
220
* Can be set, to change the selected operation.
@@ -228,7 +267,7 @@ namespace dnd {
228
267
// If the DataTransfer object is no longer associated with a drag data
229
268
// store, return the empty string and abort these steps.
230
269
231
- // If the drag data store' s mode is in the protected mode, return the empty
270
+ // If the drag data store" s mode is in the protected mode, return the empty
232
271
// string and abort these steps.
233
272
if ( this . store . mode === "protected" ) {
234
273
return "" ;
@@ -283,7 +322,7 @@ namespace dnd {
283
322
return ;
284
323
}
285
324
286
- // If the drag data store' s mode is not the read/write mode, abort these
325
+ // If the drag data store" s mode is not the read/write mode, abort these
287
326
// steps. Nothing happens.
288
327
if ( this . store . mode !== "readwrite" ) {
289
328
return ;
@@ -304,7 +343,7 @@ namespace dnd {
304
343
// Unicode string and whose type string is equal to format, if there is
305
344
// one. Add an item to the drag data store item list whose kind is Plain
306
345
// Unicode string, whose type string is equal to format, and whose data
307
- // is the string given by the method' s second argument.
346
+ // is the string given by the method" s second argument.
308
347
this . typeTable [ format ] = data ;
309
348
this . types = Object . keys ( this . typeTable ) ;
310
349
}
@@ -321,7 +360,7 @@ namespace dnd {
321
360
return ;
322
361
}
323
362
324
- // If the drag data store' s mode is not the read/write mode, abort these
363
+ // If the drag data store" s mode is not the read/write mode, abort these
325
364
// steps. Nothing happens.
326
365
if ( this . store . mode !== "readwrite" ) {
327
366
return ;
@@ -332,7 +371,7 @@ namespace dnd {
332
371
// these steps.
333
372
if ( typeof format === "undefined" ) {
334
373
// Note: The clearData() method does not affect whether any files were
335
- // included in the drag, so the types attribute' s list might still not
374
+ // included in the drag, so the types attribute" s list might still not
336
375
// be empty after calling clearData() (it would still contain the
337
376
// "Files" string if any files were included in the drag).
338
377
this . types . filter ( ( type ) => type !== "Files" )
@@ -511,7 +550,7 @@ namespace dnd {
511
550
if ( typeof data === "string" ) {
512
551
// If there is already an item in the drag data store item list whose
513
552
// kind is Plain Unicode string and whose type string is equal to the
514
- // value of the method' s second argument, converted to ASCII lowercase,
553
+ // value of the method" s second argument, converted to ASCII lowercase,
515
554
// then throw a NotSupportedError exception and abort these steps.
516
555
const typeLowerCase = type . toLowerCase ( ) ;
517
556
if ( this . typeTable [ typeLowerCase ] ) {
@@ -520,8 +559,8 @@ namespace dnd {
520
559
521
560
// Otherwise, add an item to the drag data store item list whose kind is
522
561
// Plain Unicode string, whose type string is equal to the value of the
523
- // method' s second argument, converted to ASCII lowercase, and whose
524
- // data is the string given by the method' s first argument.
562
+ // method" s second argument, converted to ASCII lowercase, and whose
563
+ // data is the string given by the method" s first argument.
525
564
const stringItem = DataTransferItem . createForString (
526
565
data , typeLowerCase , this . store ) ;
527
566
this . items . push ( stringItem ) ;
@@ -530,7 +569,7 @@ namespace dnd {
530
569
else {
531
570
// Add an item to the drag data store item list whose kind is File,
532
571
// whose type string is the type of the File, converted to ASCII
533
- // lowercase, and whose data is the same as the File' s data.
572
+ // lowercase, and whose data is the same as the File" s data.
534
573
const fileItem = DataTransferItem . createForFile (
535
574
data , this . store ) ;
536
575
this . items . push ( fileItem ) ;
@@ -556,17 +595,17 @@ namespace dnd {
556
595
557
596
558
597
/**
559
- * While the DataTransferItem object' s DataTransfer object is associated with
560
- * a drag data store and that drag data store' s drag data store item list
598
+ * While the DataTransferItem object" s DataTransfer object is associated with
599
+ * a drag data store and that drag data store" s drag data store item list
561
600
* still contains the item that the DataTransferItem object represents, the
562
- * DataTransferItem object' s mode is the same as the drag data store mode.
563
- * When the DataTransferItem object' s DataTransfer object is not associated
601
+ * DataTransferItem object" s mode is the same as the drag data store mode.
602
+ * When the DataTransferItem object" s DataTransfer object is not associated
564
603
* with a drag data store, or if the item that the DataTransferItem object
565
604
* represents has been removed from the relevant drag data store item list,
566
- * the DataTransferItem object' s mode is the disabled mode. The drag data
605
+ * the DataTransferItem object" s mode is the disabled mode. The drag data
567
606
* store referenced in this section (which is used only when the
568
607
* DataTransferItem object is not in the disabled mode) is the drag data store
569
- * with which the DataTransferItem object' s DataTransfer object is associated.
608
+ * with which the DataTransferItem object" s DataTransfer object is associated.
570
609
*
571
610
* @see https://html.spec.whatwg.org/multipage/interaction.html#datatransferitem
572
611
*/
@@ -711,7 +750,7 @@ namespace dnd {
711
750
}
712
751
713
752
return textUriList . split ( / \r \n / ) . filter ( ( line ) => {
714
- // Any lines beginning with the '#' character are comment lines
753
+ // Any lines beginning with the "#" character are comment lines
715
754
// and are ignored during processing.
716
755
// The remaining non-comment lines shall be URIs (URNs or URLs),
717
756
// encoded according to the URL or URN specifications (RFC2141,
0 commit comments