editor.js/src/components/modules/dragNDrop.ts
Peter Savchenko 73ac3e3f5f
Release 2.19.2 (#1597)
Save 2.19.2 changes
2021-03-15 22:05:53 +03:00

123 lines
2.9 KiB
TypeScript

import SelectionUtils from '../selection';
import Module from '../__module';
/**
*
*/
export default class DragNDrop extends Module {
/**
* If drag has been started at editor, we save it
*
* @type {boolean}
* @private
*/
private isStartedAtEditor = false;
/**
* Toggle read-only state
*
* if state is true:
* - disable all drag-n-drop event handlers
*
* if state is false:
* - restore drag-n-drop event handlers
*
* @param {boolean} readOnlyEnabled - "read only" state
*/
public toggleReadOnly(readOnlyEnabled: boolean): void {
if (readOnlyEnabled) {
this.disableModuleBindings();
} else {
this.enableModuleBindings();
}
}
/**
* Add drag events listeners to editor zone
*/
private enableModuleBindings(): void {
const { UI } = this.Editor;
this.readOnlyMutableListeners.on(UI.nodes.holder, 'drop', async (dropEvent: DragEvent) => {
await this.processDrop(dropEvent);
}, true);
this.readOnlyMutableListeners.on(UI.nodes.holder, 'dragstart', () => {
this.processDragStart();
});
/**
* Prevent default browser behavior to allow drop on non-contenteditable elements
*/
this.readOnlyMutableListeners.on(UI.nodes.holder, 'dragover', (dragEvent: DragEvent) => {
this.processDragOver(dragEvent);
}, true);
}
/**
* Unbind drag-n-drop event handlers
*/
private disableModuleBindings(): void {
this.readOnlyMutableListeners.clearAll();
}
/**
* Handle drop event
*
* @param {DragEvent} dropEvent - drop event
*/
private async processDrop(dropEvent: DragEvent): Promise<void> {
const {
BlockManager,
Caret,
Paste,
} = this.Editor;
dropEvent.preventDefault();
BlockManager.blocks.forEach((block) => {
block.dropTarget = false;
});
if (SelectionUtils.isAtEditor && !SelectionUtils.isCollapsed && this.isStartedAtEditor) {
document.execCommand('delete');
}
this.isStartedAtEditor = false;
/**
* Try to set current block by drop target.
* If drop target is not part of the Block, set last Block as current.
*/
const targetBlock = BlockManager.setCurrentBlockByChildNode(dropEvent.target as Node);
if (targetBlock) {
this.Editor.Caret.setToBlock(targetBlock, Caret.positions.END);
} else {
const lastBlock = BlockManager.setCurrentBlockByChildNode(BlockManager.lastBlock.holder);
this.Editor.Caret.setToBlock(lastBlock, Caret.positions.END);
}
await Paste.processDataTransfer(dropEvent.dataTransfer, true);
}
/**
* Handle drag start event
*/
private processDragStart(): void {
if (SelectionUtils.isAtEditor && !SelectionUtils.isCollapsed) {
this.isStartedAtEditor = true;
}
this.Editor.InlineToolbar.close();
}
/**
* @param {DragEvent} dragEvent - drag event
*/
private processDragOver(dragEvent: DragEvent): void {
dragEvent.preventDefault();
}
}