Flickering due to fileover flag when child element is used #1190

Open
opened 2021-11-16 14:48:30 +00:00 by avi150890 · 4 comments
avi150890 commented 2021-11-16 14:48:30 +00:00 (Migrated from github.com)

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?

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?
avi150890 commented 2021-12-05 07:09:22 +00:00 (Migrated from github.com)

Thanks a lot,
I will try to use in my existing code.

On Sat, Dec 4, 2021, 23:35 Friederich Christophe @.***>
wrote:

import { Directive, ElementRef, EventEmitter, HostListener, Input, Output } from @.***/core';import { FileUploaderOptions, FileUploader } from 'ng2-file-upload';

@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) {}

getOptions(): FileUploaderOptions | void {
    return this.uploader?.options;
}

getFilters(): string {
    return '';
}

@HostListener('drop', ['$event'])
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[] = [];
            for (let index = 0; index < dataTransfer.files.length; index++) {
                const element = dataTransfer.files.item(index);
                if (element) files.push(element);
            }
            this.uploader?.addToQueue(files, options, filters);
        }
        this.fileOver.emit(false);
        this.onFileDrop.emit(dataTransfer.files);
    }
}

@HostListener('dragover', ['$event'])
onDragOver(event: DragEvent): void {
    if (event.dataTransfer) {
        const dataTransfer = event.dataTransfer;
        if (!this.haveFiles(dataTransfer.types)) {
            return;
        }
        if (!this.isDraggingOverDropZone) {
            this.isDraggingOverDropZone = true;
            this.fileOver.emit(true);
        }
        this._preventAndStop(event);
        dataTransfer.dropEffect = 'copy';
    }
}

@HostListener('dragleave', ['$event'])
onDragLeave(event: MouseEvent): void {
    if (this._elementRef) {
        if (event.currentTarget === this._elementRef.nativeElement) {
            return;
        }
    }
    if (this.isDraggingOverDropZone) {
        this.isDraggingOverDropZone = false;
        this.fileOver.emit(false);
    }
}

protected _preventAndStop(event: MouseEvent): void {
    event.preventDefault();
    event.stopPropagation();
}

protected haveFiles(types: readonly string[]): boolean {
    if (!types) {
        return false;
    }
    return types.indexOf('Files') !== -1;
}}

Hi,
I don't try to find the problem, but after fix all types, the above code
works.

// maybe this change
if (event.currentTarget === (this as any).element[ 0 ]) {// to
if (event.currentTarget === this._elementRef.nativeElement) {


You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
https://github.com/valor-software/ng2-file-upload/issues/1190#issuecomment-986068510,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/AKPAVZBFOQ6SXLRQH2ZZKE3UPJJ4ZANCNFSM5IEOQRCQ
.

Thanks a lot, I will try to use in my existing code. On Sat, Dec 4, 2021, 23:35 Friederich Christophe ***@***.***> wrote: > import { Directive, ElementRef, EventEmitter, HostListener, Input, Output } from ***@***.***/core';import { FileUploaderOptions, FileUploader } from 'ng2-file-upload'; > > @Directive({ selector: '[ng2FileDrop]' })export class FileDropDirective { > @Input() uploader?: FileUploader; > @Output() fileOver: EventEmitter<boolean> = new EventEmitter(); > // eslint-disable-next-line @angular-eslint/no-output-on-prefix > @Output() onFileDrop: EventEmitter<FileList> = new EventEmitter<FileList>(); > > public isDraggingOverDropZone = false; > > constructor(private _elementRef: ElementRef) {} > > getOptions(): FileUploaderOptions | void { > return this.uploader?.options; > } > > getFilters(): string { > return ''; > } > > @HostListener('drop', ['$event']) > 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[] = []; > for (let index = 0; index < dataTransfer.files.length; index++) { > const element = dataTransfer.files.item(index); > if (element) files.push(element); > } > this.uploader?.addToQueue(files, options, filters); > } > this.fileOver.emit(false); > this.onFileDrop.emit(dataTransfer.files); > } > } > > @HostListener('dragover', ['$event']) > onDragOver(event: DragEvent): void { > if (event.dataTransfer) { > const dataTransfer = event.dataTransfer; > if (!this.haveFiles(dataTransfer.types)) { > return; > } > if (!this.isDraggingOverDropZone) { > this.isDraggingOverDropZone = true; > this.fileOver.emit(true); > } > this._preventAndStop(event); > dataTransfer.dropEffect = 'copy'; > } > } > > @HostListener('dragleave', ['$event']) > onDragLeave(event: MouseEvent): void { > if (this._elementRef) { > if (event.currentTarget === this._elementRef.nativeElement) { > return; > } > } > if (this.isDraggingOverDropZone) { > this.isDraggingOverDropZone = false; > this.fileOver.emit(false); > } > } > > protected _preventAndStop(event: MouseEvent): void { > event.preventDefault(); > event.stopPropagation(); > } > > protected haveFiles(types: readonly string[]): boolean { > if (!types) { > return false; > } > return types.indexOf('Files') !== -1; > }} > > Hi, > I don't try to find the problem, but after fix all types, the above code > works. > > // maybe this change > if (event.currentTarget === (this as any).element[ 0 ]) {// to > if (event.currentTarget === this._elementRef.nativeElement) { > > — > You are receiving this because you authored the thread. > Reply to this email directly, view it on GitHub > <https://github.com/valor-software/ng2-file-upload/issues/1190#issuecomment-986068510>, > or unsubscribe > <https://github.com/notifications/unsubscribe-auth/AKPAVZBFOQ6SXLRQH2ZZKE3UPJJ4ZANCNFSM5IEOQRCQ> > . >
devacfr commented 2021-12-05 07:58:16 +00:00 (Migrated from github.com)

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

Le 5 déc. 2021 à 08:09, AVINASH SHARMA @.***> a écrit :

Thanks a lot,
I will try to use in my existing code.

On Sat, Dec 4, 2021, 23:35 Friederich Christophe @.***>
wrote:

import { Directive, ElementRef, EventEmitter, HostListener, Input, Output } from @.***/core';import { FileUploaderOptions, FileUploader } from 'ng2-file-upload';

@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) {}

getOptions(): FileUploaderOptions | void {
return this.uploader?.options;
}

getFilters(): string {
return '';
}

@HostListener('drop', ['$event'])
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[] = [];
for (let index = 0; index < dataTransfer.files.length; index++) {
const element = dataTransfer.files.item(index);
if (element) files.push(element);
}
this.uploader?.addToQueue(files, options, filters);
}
this.fileOver.emit(false);
this.onFileDrop.emit(dataTransfer.files);
}
}

@HostListener('dragover', ['$event'])
onDragOver(event: DragEvent): void {
if (event.dataTransfer) {
const dataTransfer = event.dataTransfer;
if (!this.haveFiles(dataTransfer.types)) {
return;
}
if (!this.isDraggingOverDropZone) {
this.isDraggingOverDropZone = true;
this.fileOver.emit(true);
}
this._preventAndStop(event);
dataTransfer.dropEffect = 'copy';
}
}

@HostListener('dragleave', ['$event'])
onDragLeave(event: MouseEvent): void {
if (this._elementRef) {
if (event.currentTarget === this._elementRef.nativeElement) {
return;
}
}
if (this.isDraggingOverDropZone) {
this.isDraggingOverDropZone = false;
this.fileOver.emit(false);
}
}

protected _preventAndStop(event: MouseEvent): void {
event.preventDefault();
event.stopPropagation();
}

protected haveFiles(types: readonly string[]): boolean {
if (!types) {
return false;
}
return types.indexOf('Files') !== -1;
}}

Hi,
I don't try to find the problem, but after fix all types, the above code
works.

// maybe this change
if (event.currentTarget === (this as any).element[ 0 ]) {// to
if (event.currentTarget === this._elementRef.nativeElement) {


You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
https://github.com/valor-software/ng2-file-upload/issues/1190#issuecomment-986068510,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/AKPAVZBFOQ6SXLRQH2ZZKE3UPJJ4ZANCNFSM5IEOQRCQ
.


You are receiving this because you commented.
Reply to this email directly, view it on GitHub https://github.com/valor-software/ng2-file-upload/issues/1190#issuecomment-986178846, or unsubscribe https://github.com/notifications/unsubscribe-auth/AARRQZCYPQ72PH3LMXYQMSLUPMF23ANCNFSM5IEOQRCQ.

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<boolean> = new EventEmitter(); // eslint-disable-next-line @angular-eslint/no-output-on-prefix @Output() onFileDrop: EventEmitter<FileList> = new EventEmitter<FileList>(); 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 > Le 5 déc. 2021 à 08:09, AVINASH SHARMA ***@***.***> a écrit : > > > Thanks a lot, > I will try to use in my existing code. > > > On Sat, Dec 4, 2021, 23:35 Friederich Christophe ***@***.***> > wrote: > > > import { Directive, ElementRef, EventEmitter, HostListener, Input, Output } from ***@***.***/core';import { FileUploaderOptions, FileUploader } from 'ng2-file-upload'; > > > > @Directive({ selector: '[ng2FileDrop]' })export class FileDropDirective { > > @Input() uploader?: FileUploader; > > @Output() fileOver: EventEmitter<boolean> = new EventEmitter(); > > // eslint-disable-next-line @angular-eslint/no-output-on-prefix > > @Output() onFileDrop: EventEmitter<FileList> = new EventEmitter<FileList>(); > > > > public isDraggingOverDropZone = false; > > > > constructor(private _elementRef: ElementRef) {} > > > > getOptions(): FileUploaderOptions | void { > > return this.uploader?.options; > > } > > > > getFilters(): string { > > return ''; > > } > > > > @HostListener('drop', ['$event']) > > 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[] = []; > > for (let index = 0; index < dataTransfer.files.length; index++) { > > const element = dataTransfer.files.item(index); > > if (element) files.push(element); > > } > > this.uploader?.addToQueue(files, options, filters); > > } > > this.fileOver.emit(false); > > this.onFileDrop.emit(dataTransfer.files); > > } > > } > > > > @HostListener('dragover', ['$event']) > > onDragOver(event: DragEvent): void { > > if (event.dataTransfer) { > > const dataTransfer = event.dataTransfer; > > if (!this.haveFiles(dataTransfer.types)) { > > return; > > } > > if (!this.isDraggingOverDropZone) { > > this.isDraggingOverDropZone = true; > > this.fileOver.emit(true); > > } > > this._preventAndStop(event); > > dataTransfer.dropEffect = 'copy'; > > } > > } > > > > @HostListener('dragleave', ['$event']) > > onDragLeave(event: MouseEvent): void { > > if (this._elementRef) { > > if (event.currentTarget === this._elementRef.nativeElement) { > > return; > > } > > } > > if (this.isDraggingOverDropZone) { > > this.isDraggingOverDropZone = false; > > this.fileOver.emit(false); > > } > > } > > > > protected _preventAndStop(event: MouseEvent): void { > > event.preventDefault(); > > event.stopPropagation(); > > } > > > > protected haveFiles(types: readonly string[]): boolean { > > if (!types) { > > return false; > > } > > return types.indexOf('Files') !== -1; > > }} > > > > Hi, > > I don't try to find the problem, but after fix all types, the above code > > works. > > > > // maybe this change > > if (event.currentTarget === (this as any).element[ 0 ]) {// to > > if (event.currentTarget === this._elementRef.nativeElement) { > > > > — > > You are receiving this because you authored the thread. > > Reply to this email directly, view it on GitHub > > <https://github.com/valor-software/ng2-file-upload/issues/1190#issuecomment-986068510>, > > or unsubscribe > > <https://github.com/notifications/unsubscribe-auth/AKPAVZBFOQ6SXLRQH2ZZKE3UPJJ4ZANCNFSM5IEOQRCQ> > > . > > > — > You are receiving this because you commented. > Reply to this email directly, view it on GitHub <https://github.com/valor-software/ng2-file-upload/issues/1190#issuecomment-986178846>, or unsubscribe <https://github.com/notifications/unsubscribe-auth/AARRQZCYPQ72PH3LMXYQMSLUPMF23ANCNFSM5IEOQRCQ>. >
xianshenglu commented 2022-01-25 02:11:11 +00:00 (Migrated from github.com)

For me, I use .drag-over *{ pointer-events: none } to disable descendent elements mouse events. And it works.

For me, I use `.drag-over *{ pointer-events: none }` to disable descendent elements mouse events. And it works.
xianshenglu commented 2022-01-25 02:12:42 +00:00 (Migrated from github.com)

Willing to send a PR if this solution is acceptable.

Willing to send a PR if this solution is acceptable.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: dc/ng2-file-upload#1190