drag and drop improvements (copy effect) (#6019)

* drag and drop fixes (copy effect)

* fix tests

* update tests

* test fixes
This commit is contained in:
Denys Vuika 2020-08-18 10:57:09 +01:00 committed by GitHub
parent 16d9d9e356
commit d355f76499
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 36 additions and 26 deletions

View File

@ -40,40 +40,52 @@ export class DropZoneDirective implements OnInit, OnDestroy {
ngOnInit() { ngOnInit() {
this.ngZone.runOutsideAngular(() => { this.ngZone.runOutsideAngular(() => {
this.element.addEventListener('dragenter', this.onDragEnter.bind(this));
this.element.addEventListener('dragover', this.onDragOver.bind(this)); this.element.addEventListener('dragover', this.onDragOver.bind(this));
this.element.addEventListener('drop', this.onDrop.bind(this)); this.element.addEventListener('drop', this.onDrop.bind(this));
}); });
} }
ngOnDestroy() { ngOnDestroy() {
this.element.removeEventListener('dragenter', this.onDragEnter);
this.element.removeEventListener('dragover', this.onDragOver); this.element.removeEventListener('dragover', this.onDragOver);
this.element.removeEventListener('drop', this.onDrop); this.element.removeEventListener('drop', this.onDrop);
} }
onDragOver(event: Event) { onDragEnter(event: DragEvent) {
const domEvent = new CustomEvent(`${this.dropTarget}-dragover`, { const domEvent = this.dispatchDomEvent(event, 'dragenter');
detail: {
target: this.dropTarget,
event,
column: this.dropColumn,
row: this.dropRow
},
bubbles: true
});
this.element.dispatchEvent(domEvent);
if (domEvent.defaultPrevented) { if (domEvent.defaultPrevented) {
event.dataTransfer.dropEffect = 'copy';
event.preventDefault();
event.stopPropagation();
}
}
onDragOver(event: DragEvent) {
const domEvent = this.dispatchDomEvent(event, 'dragover');
if (domEvent.defaultPrevented) {
event.dataTransfer.dropEffect = 'copy';
event.preventDefault(); event.preventDefault();
event.stopPropagation(); event.stopPropagation();
} }
} }
onDrop(event: Event) { onDrop(event: Event) {
const domEvent = new CustomEvent(`${this.dropTarget}-drop`, { const domEvent = this.dispatchDomEvent(event, 'drop');
if (domEvent.defaultPrevented) {
event.preventDefault();
event.stopPropagation();
}
}
private dispatchDomEvent(originalEvent: Event, eventName: string): CustomEvent {
const domEvent = new CustomEvent(`${this.dropTarget}-${eventName}`, {
detail: { detail: {
target: this.dropTarget, target: this.dropTarget,
event, event: originalEvent,
column: this.dropColumn, column: this.dropColumn,
row: this.dropRow row: this.dropRow
}, },
@ -81,10 +93,6 @@ export class DropZoneDirective implements OnInit, OnDestroy {
}); });
this.element.dispatchEvent(domEvent); this.element.dispatchEvent(domEvent);
return domEvent;
if (domEvent.defaultPrevented) {
event.preventDefault();
event.stopPropagation();
}
} }
} }

View File

@ -39,26 +39,26 @@ describe('UploadDirective', () => {
it('should update drag status on dragenter', () => { it('should update drag status on dragenter', () => {
expect(directive.isDragging).toBeFalsy(); expect(directive.isDragging).toBeFalsy();
directive.enabled = true; directive.enabled = true;
directive.onDragEnter(); directive.onDragEnter(new DragEvent('dragenter', { dataTransfer: new DataTransfer() }));
expect(directive.isDragging).toBeTruthy(); expect(directive.isDragging).toBeTruthy();
}); });
it('should not update drag status on dragenter when disabled', () => { it('should not update drag status on dragenter when disabled', () => {
expect(directive.isDragging).toBeFalsy(); expect(directive.isDragging).toBeFalsy();
directive.enabled = false; directive.enabled = false;
directive.onDragEnter(); directive.onDragEnter(new DragEvent('dragenter'));
expect(directive.isDragging).toBeFalsy(); expect(directive.isDragging).toBeFalsy();
}); });
it('should update drag status on dragover', () => { it('should update drag status on dragover', () => {
expect(directive.isDragging).toBeFalsy(); expect(directive.isDragging).toBeFalsy();
directive.enabled = true; directive.enabled = true;
directive.onDragOver(new CustomEvent('dragover')); directive.onDragOver(new DragEvent('dragover', { dataTransfer: new DataTransfer() }));
expect(directive.isDragging).toBeTruthy(); expect(directive.isDragging).toBeTruthy();
}); });
it('should prevent default event on dragover', () => { it('should prevent default event on dragover', () => {
const event = new Event('dom-event'); const event = new DragEvent('dragover', { dataTransfer: new DataTransfer() });
spyOn(event, 'preventDefault').and.stub(); spyOn(event, 'preventDefault').and.stub();
directive.enabled = true; directive.enabled = true;
directive.onDragOver(event); directive.onDragOver(event);
@ -69,7 +69,7 @@ describe('UploadDirective', () => {
it('should not update drag status on dragover when disabled', () => { it('should not update drag status on dragover when disabled', () => {
expect(directive.isDragging).toBeFalsy(); expect(directive.isDragging).toBeFalsy();
directive.enabled = false; directive.enabled = false;
directive.onDragOver(new CustomEvent('dragover')); directive.onDragOver(new DragEvent('dragover'));
}); });
it('should update drag status on dragleave', () => { it('should update drag status on dragleave', () => {

View File

@ -108,16 +108,18 @@ export class UploadDirective implements OnInit, OnDestroy {
} }
} }
onDragEnter() { onDragEnter(event: DragEvent) {
if (this.isDropMode()) { if (this.isDropMode()) {
event.dataTransfer.dropEffect = 'copy';
this.element.classList.add(this.cssClassName); this.element.classList.add(this.cssClassName);
this.isDragging = true; this.isDragging = true;
} }
} }
onDragOver(event: Event) { onDragOver(event: DragEvent) {
event.preventDefault(); event.preventDefault();
if (this.isDropMode()) { if (this.isDropMode()) {
event.dataTransfer.dropEffect = 'copy';
this.element.classList.add(this.cssClassName); this.element.classList.add(this.cssClassName);
this.isDragging = true; this.isDragging = true;
} }