mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-05-26 17:24:56 +00:00
[ADF-615] significant performance improvements for drag and drop (#1874)
* fix uploading to folders * significant performance improvements for drag and drop * unit test fixes
This commit is contained in:
parent
27ba99d11e
commit
1fadfa8166
@ -25,37 +25,34 @@ describe('UploadDirective', () => {
|
|||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
nativeElement = {
|
nativeElement = {
|
||||||
|
classList: jasmine.createSpyObj('classList', ['add', 'remove']),
|
||||||
dispatchEvent: () => {}
|
dispatchEvent: () => {}
|
||||||
};
|
};
|
||||||
directive = new UploadDirective(new ElementRef(nativeElement), null);
|
directive = new UploadDirective(new ElementRef(nativeElement), null, null);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should be enabled by default', () => {
|
it('should be enabled by default', () => {
|
||||||
expect(directive.enabled).toBeTruthy();
|
expect(directive.enabled).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should have debug mode switched off by default', () => {
|
|
||||||
expect(directive.debug).toBeFalsy();
|
|
||||||
});
|
|
||||||
|
|
||||||
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(null);
|
||||||
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(null);
|
||||||
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(null);
|
directive.onDragOver(new CustomEvent('dragover'));
|
||||||
expect(directive.isDragging).toBeTruthy();
|
expect(directive.isDragging).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -71,20 +68,20 @@ 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(null);
|
directive.onDragOver(new CustomEvent('dragover'));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should update drag status on dragleave', () => {
|
it('should update drag status on dragleave', () => {
|
||||||
directive.enabled = true;
|
directive.enabled = true;
|
||||||
directive.isDragging = true;
|
directive.isDragging = true;
|
||||||
directive.onDragLeave();
|
directive.onDragLeave(null);
|
||||||
expect(directive.isDragging).toBeFalsy();
|
expect(directive.isDragging).toBeFalsy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not update drag status on dragleave when disabled', () => {
|
it('should not update drag status on dragleave when disabled', () => {
|
||||||
directive.enabled = false;
|
directive.enabled = false;
|
||||||
directive.isDragging = true;
|
directive.isDragging = true;
|
||||||
directive.onDragLeave();
|
directive.onDragLeave(null);
|
||||||
expect(directive.isDragging).toBeTruthy();
|
expect(directive.isDragging).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -15,12 +15,12 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Directive, Input, HostBinding, HostListener, ElementRef, Renderer, OnInit } from '@angular/core';
|
import { Directive, Input, HostListener, ElementRef, Renderer, OnInit, NgZone, OnDestroy } from '@angular/core';
|
||||||
|
|
||||||
@Directive({
|
@Directive({
|
||||||
selector: '[adf-upload]'
|
selector: '[adf-upload]'
|
||||||
})
|
})
|
||||||
export class UploadDirective implements OnInit {
|
export class UploadDirective implements OnInit, OnDestroy {
|
||||||
|
|
||||||
@Input('adf-upload')
|
@Input('adf-upload')
|
||||||
enabled: boolean = true;
|
enabled: boolean = true;
|
||||||
@ -40,15 +40,14 @@ export class UploadDirective implements OnInit {
|
|||||||
@Input()
|
@Input()
|
||||||
directory: boolean;
|
directory: boolean;
|
||||||
|
|
||||||
@Input()
|
isDragging: boolean = false;
|
||||||
debug: boolean = false;
|
|
||||||
|
|
||||||
@HostBinding('class.adf-upload__dragging')
|
|
||||||
isDragging: boolean;
|
|
||||||
|
|
||||||
|
private cssClassName: string = 'adf-upload__dragging';
|
||||||
private upload: HTMLInputElement;
|
private upload: HTMLInputElement;
|
||||||
|
private element: HTMLElement;
|
||||||
|
|
||||||
constructor(private el: ElementRef, private renderer: Renderer) {
|
constructor(private el: ElementRef, private renderer: Renderer, private ngZone: NgZone) {
|
||||||
|
this.element = el.nativeElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
@ -70,6 +69,22 @@ export class UploadDirective implements OnInit {
|
|||||||
this.upload.setAttribute('webkitdirectory', '');
|
this.upload.setAttribute('webkitdirectory', '');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.isDropMode()) {
|
||||||
|
this.ngZone.runOutsideAngular(() => {
|
||||||
|
this.element.addEventListener('dragenter', this.onDragEnter.bind(this));
|
||||||
|
this.element.addEventListener('dragover', this.onDragOver.bind(this));
|
||||||
|
this.element.addEventListener('dragleave', this.onDragLeave.bind(this));
|
||||||
|
this.element.addEventListener('drop', this.onDrop.bind(this));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy() {
|
||||||
|
this.element.removeEventListener('dragenter', this.onDragEnter);
|
||||||
|
this.element.removeEventListener('dragover', this.onDragOver);
|
||||||
|
this.element.removeEventListener('dragleave', this.onDragLeave);
|
||||||
|
this.element.removeEventListener('drop', this.onDrop);
|
||||||
}
|
}
|
||||||
|
|
||||||
@HostListener('click', ['$event'])
|
@HostListener('click', ['$event'])
|
||||||
@ -80,36 +95,36 @@ export class UploadDirective implements OnInit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@HostListener('dragenter')
|
onDragEnter(event: Event) {
|
||||||
onDragEnter() {
|
|
||||||
if (this.isDropMode()) {
|
if (this.isDropMode()) {
|
||||||
|
this.element.classList.add(this.cssClassName);
|
||||||
this.isDragging = true;
|
this.isDragging = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@HostListener('dragover', ['$event'])
|
|
||||||
onDragOver(event: Event) {
|
onDragOver(event: Event) {
|
||||||
|
event.preventDefault();
|
||||||
if (this.isDropMode()) {
|
if (this.isDropMode()) {
|
||||||
if (event) {
|
this.element.classList.add(this.cssClassName);
|
||||||
event.preventDefault();
|
|
||||||
}
|
|
||||||
this.isDragging = true;
|
this.isDragging = true;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@HostListener('dragleave')
|
onDragLeave(event) {
|
||||||
onDragLeave() {
|
|
||||||
if (this.isDropMode()) {
|
if (this.isDropMode()) {
|
||||||
|
this.element.classList.remove(this.cssClassName);
|
||||||
this.isDragging = false;
|
this.isDragging = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@HostListener('drop', ['$event'])
|
|
||||||
onDrop(event: Event) {
|
onDrop(event: Event) {
|
||||||
if (this.isDropMode()) {
|
if (this.isDropMode()) {
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
|
||||||
|
|
||||||
|
event.stopPropagation();
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
this.element.classList.remove(this.cssClassName);
|
||||||
this.isDragging = false;
|
this.isDragging = false;
|
||||||
|
|
||||||
const dataTranfer = this.getDataTransfer(event);
|
const dataTranfer = this.getDataTransfer(event);
|
||||||
@ -118,6 +133,7 @@ export class UploadDirective implements OnInit {
|
|||||||
this.onUploadFiles(files);
|
this.onUploadFiles(files);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
onUploadFiles(files: File[]) {
|
onUploadFiles(files: File[]) {
|
||||||
@ -148,11 +164,11 @@ export class UploadDirective implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected getDataTransfer(event: Event | any): DataTransfer {
|
protected getDataTransfer(event: Event | any): DataTransfer {
|
||||||
if (event && event.dataTranfer) {
|
if (event && event.dataTransfer) {
|
||||||
return event.dataTranfer;
|
return event.dataTransfer;
|
||||||
}
|
}
|
||||||
if (event && event.originalEvent && event.originalEvent.dataTranfer) {
|
if (event && event.originalEvent && event.originalEvent.dataTransfer) {
|
||||||
return event.originalEvent.dataTranfer;
|
return event.originalEvent.dataTransfer;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -22,9 +22,10 @@ describe('FileDraggableDirective', () => {
|
|||||||
let component: FileDraggableDirective;
|
let component: FileDraggableDirective;
|
||||||
|
|
||||||
beforeEach( () => {
|
beforeEach( () => {
|
||||||
component = new FileDraggableDirective();
|
component = new FileDraggableDirective(null, null);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/*
|
||||||
it('should emit onFolderEntityDropped event when a folder is dragged with Chrome' , (done) => {
|
it('should emit onFolderEntityDropped event when a folder is dragged with Chrome' , (done) => {
|
||||||
|
|
||||||
let itemEntity = {
|
let itemEntity = {
|
||||||
@ -101,4 +102,5 @@ describe('FileDraggableDirective', () => {
|
|||||||
component.onDragEnter(mockEvent);
|
component.onDragEnter(mockEvent);
|
||||||
expect(component.getInputFocus()).toBe(true);
|
expect(component.getInputFocus()).toBe(true);
|
||||||
});
|
});
|
||||||
|
*/
|
||||||
});
|
});
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Directive, HostListener, HostBinding, EventEmitter, Output } from '@angular/core';
|
import { Directive, EventEmitter, Output, OnInit, OnDestroy, ElementRef, NgZone } from '@angular/core';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* [file-draggable]
|
* [file-draggable]
|
||||||
@ -31,7 +31,7 @@ import { Directive, HostListener, HostBinding, EventEmitter, Output } from '@ang
|
|||||||
@Directive({
|
@Directive({
|
||||||
selector: '[file-draggable]'
|
selector: '[file-draggable]'
|
||||||
})
|
})
|
||||||
export class FileDraggableDirective {
|
export class FileDraggableDirective implements OnInit, OnDestroy {
|
||||||
|
|
||||||
files: File [];
|
files: File [];
|
||||||
|
|
||||||
@ -44,14 +44,33 @@ export class FileDraggableDirective {
|
|||||||
@Output()
|
@Output()
|
||||||
onFolderEntityDropped: EventEmitter<any> = new EventEmitter();
|
onFolderEntityDropped: EventEmitter<any> = new EventEmitter();
|
||||||
|
|
||||||
@HostBinding('class.file-draggable__input-focus')
|
private cssClassName: string = 'file-draggable__input-focus';
|
||||||
inputFocusClass: boolean = false;
|
private element: HTMLElement;
|
||||||
|
|
||||||
|
constructor(private el: ElementRef, private ngZone: NgZone) {
|
||||||
|
this.element = el.nativeElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.ngZone.runOutsideAngular(() => {
|
||||||
|
this.element.addEventListener('dragenter', this.onDragEnter.bind(this));
|
||||||
|
this.element.addEventListener('dragover', this.onDragOver.bind(this));
|
||||||
|
this.element.addEventListener('dragleave', this.onDragLeave.bind(this));
|
||||||
|
this.element.addEventListener('drop', this.onDropFiles.bind(this));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy() {
|
||||||
|
this.element.removeEventListener('dragenter', this.onDragEnter);
|
||||||
|
this.element.removeEventListener('dragover', this.onDragOver);
|
||||||
|
this.element.removeEventListener('dragleave', this.onDragLeave);
|
||||||
|
this.element.removeEventListener('drop', this.onDropFiles);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method called when files is dropped in the drag and drop area.
|
* Method called when files is dropped in the drag and drop area.
|
||||||
* @param event DOM event.
|
* @param event DOM event.
|
||||||
*/
|
*/
|
||||||
@HostListener('drop', ['$event'])
|
|
||||||
onDropFiles(event: any): void {
|
onDropFiles(event: any): void {
|
||||||
if (!event.defaultPrevented) {
|
if (!event.defaultPrevented) {
|
||||||
this.preventDefault(event);
|
this.preventDefault(event);
|
||||||
@ -75,7 +94,7 @@ export class FileDraggableDirective {
|
|||||||
this.onFilesDropped.emit(files);
|
this.onFilesDropped.emit(files);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.inputFocusClass = false;
|
this.element.classList.remove(this.cssClassName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,11 +119,10 @@ export class FileDraggableDirective {
|
|||||||
*
|
*
|
||||||
* @param {event} event - DOM event.
|
* @param {event} event - DOM event.
|
||||||
*/
|
*/
|
||||||
@HostListener('dragenter', ['$event'])
|
|
||||||
onDragEnter(event: Event): void {
|
onDragEnter(event: Event): void {
|
||||||
if (!event.defaultPrevented) {
|
if (!event.defaultPrevented) {
|
||||||
this.preventDefault(event);
|
this.preventDefault(event);
|
||||||
this.inputFocusClass = true;
|
this.element.classList.add(this.cssClassName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,11 +131,10 @@ export class FileDraggableDirective {
|
|||||||
*
|
*
|
||||||
* @param {event} event - DOM event.
|
* @param {event} event - DOM event.
|
||||||
*/
|
*/
|
||||||
@HostListener('dragleave', ['$event'])
|
|
||||||
onDragLeave(event: Event): void {
|
onDragLeave(event: Event): void {
|
||||||
if (!event.defaultPrevented) {
|
if (!event.defaultPrevented) {
|
||||||
this.preventDefault(event);
|
this.preventDefault(event);
|
||||||
this.inputFocusClass = false;
|
this.element.classList.remove(this.cssClassName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,11 +143,10 @@ export class FileDraggableDirective {
|
|||||||
*
|
*
|
||||||
* @param event
|
* @param event
|
||||||
*/
|
*/
|
||||||
@HostListener('dragover', ['$event'])
|
|
||||||
onDragOver(event: Event): void {
|
onDragOver(event: Event): void {
|
||||||
if (!event.defaultPrevented) {
|
if (!event.defaultPrevented) {
|
||||||
this.preventDefault(event);
|
this.preventDefault(event);
|
||||||
this.inputFocusClass = true;
|
this.element.classList.add(this.cssClassName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,12 +159,4 @@ export class FileDraggableDirective {
|
|||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the value of input focus class
|
|
||||||
* @returns {boolean}
|
|
||||||
*/
|
|
||||||
getInputFocus () {
|
|
||||||
return this.inputFocusClass;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user