Flickering due to fileover flag when child element is used #1190
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Hi,
When drag area contains child element, then flickering happens as fileover value changes from true to false continuously.
I can't disable pointer event in child, as child element has click events.
How we will be able to resolve the issue?
Thanks a lot,
I will try to use in my existing code.
On Sat, Dec 4, 2021, 23:35 Friederich Christophe @.***>
wrote:
Hi,
Sorry, I removed the comment because the dragleave didn’t work.
I can propose another following code. I add isDescendant function in dragleave to check if mouse pointer is in dropzone yet.
import { Directive, ElementRef, EventEmitter, HostListener, Input, Output } from @.***/core';
import { FileUploaderOptions, FileUploader } from 'ng2-file-upload';
function isDescendant(parent: Element, child: Element | null): boolean {
if (child == null) return false;
if (child === parent) return false;
let node = child.parentNode;
while (node != null) {
if (node === parent) {
return true;
}
node = node.parentNode;
}
return false;
}
/**
Modification of ng2FileDrop directive to fix the Flickering
Issue: https://github.com/valor-software/ng2-file-upload/issues/1190
*/
@Directive({ selector: ‘[ng2FileDrop]' })
export class FileDropDirective {
@Input() uploader?: FileUploader;
@Output() fileOver: EventEmitter = new EventEmitter();
// eslint-disable-next-line @angular-eslint/no-output-on-prefix
@Output() onFileDrop: EventEmitter = new EventEmitter();
public isDraggingOverDropZone = false;
constructor(private _elementRef: ElementRef) {}
public getOptions(): FileUploaderOptions | undefined {
return this.uploader?.options;
}
public getFilters(): string {
return '';
}
@HostListener('drop', ['$event'])
protected onDrop(event: DragEvent): void {
this.isDraggingOverDropZone = false;
if (event.dataTransfer) {
const dataTransfer = event.dataTransfer;
const options = this.getOptions();
const filters = this.getFilters();
this.preventAndStop(event);
if (options) {
const files: File[] = [];
if (dataTransfer.items) {
for (let index = 0; index < dataTransfer.items.length; index++) {
if (dataTransfer.items[index].kind === 'file') {
const element = dataTransfer.items[index].getAsFile();
if (element) files.push(element);
}
}
} else {
for (let index = 0; index < dataTransfer.files.length; index++) {
const element = dataTransfer.files[index];
if (element) files.push(element);
}
}
this.uploader?.addToQueue(files, options, filters);
this.fileOver.emit(this.isDraggingOverDropZone);
this.onFileDrop.emit(dataTransfer.files);
}
}
}
@HostListener('dragover', ['$event'])
protected onDragOver(event: DragEvent): void {
if (event.dataTransfer) {
const dataTransfer = event.dataTransfer;
if (!this.haveFiles(dataTransfer.types)) {
dataTransfer.dropEffect = 'none';
return;
} else if (!this.isDraggingOverDropZone) {
this.isDraggingOverDropZone = true;
this.fileOver.emit(this.isDraggingOverDropZone);
dataTransfer.dropEffect = 'copy';
}
}
this.preventAndStop(event);
}
@HostListener('dragleave', ['$event'])
protected onDragLeave(event: MouseEvent): void {
const el = this._elementRef.nativeElement as Element;
if (isDescendant(el, event.target as Element)) {
return;
}
if (this.isDraggingOverDropZone) {
this.isDraggingOverDropZone = false;
this.fileOver.emit(this.isDraggingOverDropZone);
}
this.preventAndStop(event);
}
protected preventAndStop(event: MouseEvent): void {
event.preventDefault();
event.stopPropagation();
}
protected haveFiles(types: readonly string[]): boolean {
return types.indexOf('Files') !== -1;
}
}
Regards,
Christophe Friederich
For me, I use
.drag-over *{ pointer-events: none }to disable descendent elements mouse events. And it works.Willing to send a PR if this solution is acceptable.