Handle paste on images and blocks w\o inputs (#583)

This commit is contained in:
George Berezhnoy 2019-01-12 03:34:44 +03:00 committed by GitHub
parent d00412e1df
commit e8d43c8fc7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 49 additions and 47 deletions

12
dist/codex-editor.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1,5 +1,9 @@
# Changelog # Changelog
### 2.2.24 changelog
- `Improvements` *Paste handling — minor paste handling improvements
### 2.2.23 changelog ### 2.2.23 changelog
- `New` *Shortcuts — copy and cut Blocks selected by CMD+A - `New` *Shortcuts — copy and cut Blocks selected by CMD+A

View file

@ -1,6 +1,6 @@
{ {
"name": "codex.editor", "name": "codex.editor",
"version": "2.7.23", "version": "2.7.24",
"description": "CodeX Editor. Native JS, based on API and Open Source", "description": "CodeX Editor. Native JS, based on API and Open Source",
"main": "dist/codex-editor.js", "main": "dist/codex-editor.js",
"types": "./types/index.d.ts", "types": "./types/index.d.ts",

View file

@ -90,11 +90,7 @@ export default class Block {
* @param {HTMLElement} element * @param {HTMLElement} element
*/ */
set currentInput(element: HTMLElement) { set currentInput(element: HTMLElement) {
const index = this.inputs.findIndex((input) => input === element || input.contains(element)); this.inputIndex = this.inputs.findIndex((input) => input === element || input.contains(element));
if (index !== -1) {
this.inputIndex = index;
}
} }
/** /**

View file

@ -468,12 +468,13 @@ export default class Dom {
* @return {boolean} * @return {boolean}
*/ */
public static containsOnlyInlineElements(data: string | HTMLElement): boolean { public static containsOnlyInlineElements(data: string | HTMLElement): boolean {
const wrapper = document.createElement('template'); let wrapper: HTMLElement;
if (typeof data === 'string') { if (typeof data === 'string') {
wrapper = document.createElement('div');
wrapper.innerHTML = data; wrapper.innerHTML = data;
} else { } else {
wrapper.appendChild(data); wrapper = data;
} }
const check = (element: HTMLElement) => { const check = (element: HTMLElement) => {
@ -481,6 +482,6 @@ export default class Dom {
&& Array.from(element.children).every(check); && Array.from(element.children).every(check);
}; };
return check(wrapper); return Array.from(wrapper.children).every(check);
} }
} }

View file

@ -180,7 +180,7 @@ export default class Paste extends Module {
private setCallback(): void { private setCallback(): void {
const {Listeners, UI} = this.Editor; const {Listeners, UI} = this.Editor;
Listeners.on(UI.nodes.redactor, 'paste', this.handlePasteEvent); Listeners.on(document, 'paste', this.handlePasteEvent);
} }
/** /**
@ -328,15 +328,7 @@ export default class Paste extends Module {
* @returns {boolean} * @returns {boolean}
*/ */
private isNativeBehaviour(element: EventTarget): boolean { private isNativeBehaviour(element: EventTarget): boolean {
const {Editor: {BlockManager}} = this; return $.isNativeInput(element);
if ( $.isNativeInput(element) ) {
return true;
}
const block = BlockManager.getBlock(element as HTMLElement);
return !block;
} }
/** /**
@ -345,15 +337,20 @@ export default class Paste extends Module {
* @param {ClipboardEvent} event * @param {ClipboardEvent} event
*/ */
private handlePasteEvent = async (event: ClipboardEvent): Promise<void> => { private handlePasteEvent = async (event: ClipboardEvent): Promise<void> => {
const {BlockManager, Toolbar} = this.Editor;
/** If target is native input or is not Block, use browser behaviour */ /** If target is native input or is not Block, use browser behaviour */
if ( if (
this.isNativeBehaviour(event.target) && !event.clipboardData.types.includes('Files') !BlockManager.currentBlock || this.isNativeBehaviour(event.target) && !event.clipboardData.types.includes('Files')
) { ) {
return; return;
} }
event.preventDefault(); event.preventDefault();
this.processDataTransfer(event.clipboardData); this.processDataTransfer(event.clipboardData);
BlockManager.clearFocused();
Toolbar.close();
} }
/** /**
@ -362,7 +359,7 @@ export default class Paste extends Module {
* @param {FileList} items - pasted or dropped items * @param {FileList} items - pasted or dropped items
*/ */
private async processFiles(items: FileList) { private async processFiles(items: FileList) {
const {BlockManager} = this.Editor; const {BlockManager, Tools} = this.Editor;
let dataToInsert: Array<{type: string, event: PasteEvent}>; let dataToInsert: Array<{type: string, event: PasteEvent}>;
@ -373,14 +370,12 @@ export default class Paste extends Module {
); );
dataToInsert = dataToInsert.filter((data) => !!data); dataToInsert = dataToInsert.filter((data) => !!data);
const isCurrentBlockInitial = Tools.isInitial(BlockManager.currentBlock.tool);
const needToReplaceCurrentBlock = isCurrentBlockInitial && BlockManager.currentBlock.isEmpty;
dataToInsert.forEach( dataToInsert.forEach(
(data, i) => { (data, i) => {
if (i === 0 && BlockManager.currentBlock && BlockManager.currentBlock.isEmpty) { BlockManager.paste(data.type, data.event, i === 0 && needToReplaceCurrentBlock);
BlockManager.paste(data.type, data.event, true);
return;
}
BlockManager.paste(data.type, data.event);
}, },
); );
} }
@ -598,7 +593,11 @@ export default class Paste extends Module {
const currentToolSanitizeConfig = Sanitizer.getInlineToolsConfig(BlockManager.currentBlock.name); const currentToolSanitizeConfig = Sanitizer.getInlineToolsConfig(BlockManager.currentBlock.name);
/** If there is no pattern substitute - insert string as it is */ /** If there is no pattern substitute - insert string as it is */
document.execCommand('insertHTML', false, Sanitizer.clean(content.innerHTML, currentToolSanitizeConfig)); if (BlockManager.currentBlock.currentInput) {
document.execCommand('insertHTML', false, Sanitizer.clean(content.innerHTML, currentToolSanitizeConfig));
} else {
this.insertBlock(dataToInsert);
}
} }
/** /**

View file

@ -196,22 +196,25 @@ export default class UI extends Module {
*/ */
private defaultBehaviour(event: KeyboardEvent): void { private defaultBehaviour(event: KeyboardEvent): void {
const keyDownOnEditor = (event.target as HTMLElement).closest(`.${this.CSS.editorWrapper}`); const keyDownOnEditor = (event.target as HTMLElement).closest(`.${this.CSS.editorWrapper}`);
const {currentBlock} = this.Editor.BlockManager;
const isMetaKey = event.altKey || event.ctrlKey || event.metaKey || event.shiftKey;
/** /**
* Ignore keydowns on document * Ignore keydowns on editor and meta keys
* clear pointer and close toolbar
*/ */
if (!keyDownOnEditor) { if (keyDownOnEditor || currentBlock && isMetaKey) {
/** return;
* Remove all highlights and remove caret
*/
this.Editor.BlockManager.dropPointer();
/**
* Close Toolbar
*/
this.Editor.Toolbar.close();
} }
/**
* Remove all highlights and remove caret
*/
this.Editor.BlockManager.dropPointer();
/**
* Close Toolbar
*/
this.Editor.Toolbar.close();
} }
/** /**