mirror of
https://github.com/codex-team/editor.js
synced 2024-06-18 13:45:20 +02:00
[Shortcuts]: CMD+X (#592)
* [Shortcuts]: CMD+X * shortcuts must be in BlockManager * small code improvements * compact bundle * insert new block in case of cmd+x * prevent default * suggested changes
This commit is contained in:
parent
bc3341bfa1
commit
d00412e1df
6
dist/codex-editor.js
vendored
6
dist/codex-editor.js
vendored
File diff suppressed because one or more lines are too long
1
dist/codex-editor.js.map
vendored
Normal file
1
dist/codex-editor.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
|
@ -1,5 +1,9 @@
|
|||
# Changelog
|
||||
|
||||
### 2.2.23 changelog
|
||||
|
||||
- `New` *Shortcuts — copy and cut Blocks selected by CMD+A
|
||||
|
||||
### 2.2—2.7 changelog
|
||||
|
||||
- `New` *Sanitize API* — [Sanitize Config](https://github.com/codex-team/codex.editor/blob/master/docs/tools.md#automatic-sanitize) of `Block Tools` now automatically extends by tags of `Inline Tools` that is enabled by current Tool by `inlineToolbar` option. You don't need more to specify `a, b, mark, code` manually. This feature will be added to fields that supports inline markup.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "codex.editor",
|
||||
"version": "2.7.22",
|
||||
"version": "2.7.23",
|
||||
"description": "CodeX Editor. Native JS, based on API and Open Source",
|
||||
"main": "dist/codex-editor.js",
|
||||
"types": "./types/index.d.ts",
|
||||
|
|
|
@ -168,6 +168,63 @@ export default class BlockEvents extends Module {
|
|||
block.dropTarget = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copying selected blocks
|
||||
* Before putting to the clipboard we sanitize all blocks and then copy to the clipboard
|
||||
*
|
||||
* @param event
|
||||
*/
|
||||
public handleCommandC(event): void {
|
||||
const { BlockSelection } = this.Editor;
|
||||
|
||||
if (!BlockSelection.anyBlockSelected) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent default copy
|
||||
* Remove "decline sound" on macOS
|
||||
*/
|
||||
event.preventDefault();
|
||||
|
||||
// Copy Selected Blocks
|
||||
BlockSelection.copySelectedBlocks();
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy and Delete selected Blocks
|
||||
* @param event
|
||||
*/
|
||||
public handleCommandX(event): void {
|
||||
const { BlockSelection, BlockManager, Caret } = this.Editor;
|
||||
const currentBlock = BlockManager.currentBlock;
|
||||
|
||||
if (!currentBlock) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent default copy
|
||||
* Remove "decline sound" on macOS
|
||||
*/
|
||||
event.preventDefault();
|
||||
|
||||
/** Copy Blocks before removing */
|
||||
if (currentBlock.selected || BlockManager.currentBlock.isEmpty) {
|
||||
BlockSelection.copySelectedBlocks();
|
||||
|
||||
if (BlockSelection.allBlocksSelected) {
|
||||
BlockManager.removeAllBlocks();
|
||||
} else {
|
||||
BlockManager.removeBlock();
|
||||
Caret.setToBlock(BlockManager.insert(), CaretClass.positions.START);
|
||||
}
|
||||
|
||||
/** Clear selection */
|
||||
BlockSelection.clearSelection();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ENTER pressed on block
|
||||
* @param {KeyboardEvent} event - keydown
|
||||
|
@ -257,11 +314,29 @@ export default class BlockEvents extends Module {
|
|||
*/
|
||||
if (currentBlock.selected || BlockManager.currentBlock.isEmpty) {
|
||||
if (BlockSelection.allBlocksSelected) {
|
||||
this.removeAllBlocks();
|
||||
BlockManager.removeAllBlocks();
|
||||
} else {
|
||||
this.removeCurrentBlock();
|
||||
BlockManager.removeBlock();
|
||||
|
||||
/**
|
||||
* In case of deletion first block we need to set caret to the current Block
|
||||
* After BlockManager removes the Block (which is current now),
|
||||
* pointer that references to the current Block, now points to the Next
|
||||
*/
|
||||
if (BlockManager.currentBlockIndex === 0) {
|
||||
Caret.setToBlock(BlockManager.currentBlock);
|
||||
} else if (BlockManager.currentBlock.inputs.length === 0) {
|
||||
/** If previous (now current) block doesn't contain inputs, remove it */
|
||||
BlockManager.removeBlock();
|
||||
BlockManager.insert();
|
||||
}
|
||||
|
||||
Caret.setToBlock(BlockManager.currentBlock, CaretClass.positions.END);
|
||||
}
|
||||
|
||||
/** Close Toolbar */
|
||||
this.Editor.Toolbar.close();
|
||||
|
||||
/** Clear selection */
|
||||
BlockSelection.clearSelection();
|
||||
return;
|
||||
|
@ -291,44 +366,6 @@ export default class BlockEvents extends Module {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* remove all selected Blocks
|
||||
*/
|
||||
private removeAllBlocks(): boolean {
|
||||
const { BlockManager } = this.Editor;
|
||||
|
||||
BlockManager.removeAllBlocks();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* remove current Block and sets Caret to the correct position
|
||||
*/
|
||||
private removeCurrentBlock(): boolean {
|
||||
const { BlockManager, Caret } = this.Editor;
|
||||
|
||||
/** If current Block is empty just remove this Block */
|
||||
BlockManager.removeBlock();
|
||||
|
||||
/**
|
||||
* In case of deletion first block we need to set caret to the current Block
|
||||
* After BlockManager removes the Block (which is current now),
|
||||
* pointer that references to the current Block, now points to the Next
|
||||
*/
|
||||
if (BlockManager.currentBlockIndex === 0) {
|
||||
Caret.setToBlock(BlockManager.currentBlock);
|
||||
} else if (BlockManager.currentBlock.inputs.length === 0) {
|
||||
/** If previous (now current) block doesn't contain inputs, remove it */
|
||||
BlockManager.removeBlock();
|
||||
BlockManager.insert();
|
||||
}
|
||||
|
||||
Caret.setToBlock(BlockManager.currentBlock, CaretClass.positions.END);
|
||||
|
||||
this.Editor.Toolbar.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge current and previous Blocks if they have the same type
|
||||
*/
|
||||
|
@ -409,5 +446,4 @@ export default class BlockEvents extends Module {
|
|||
|
||||
return !(event.shiftKey || flippingToolboxItems || toolboxItemSelected);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -120,6 +120,7 @@ export default class BlockManager extends Module {
|
|||
*/
|
||||
public async prepare() {
|
||||
const blocks = new Blocks(this.Editor.UI.nodes.redactor);
|
||||
const { BlockEvents, Shortcuts } = this.Editor;
|
||||
|
||||
/**
|
||||
* We need to use Proxy to overload set/get [] operator.
|
||||
|
@ -139,6 +140,22 @@ export default class BlockManager extends Module {
|
|||
set: Blocks.set,
|
||||
get: Blocks.get,
|
||||
});
|
||||
|
||||
/** Copy shortcut */
|
||||
Shortcuts.add({
|
||||
name: 'CMD+C',
|
||||
handler: (event) => {
|
||||
BlockEvents.handleCommandC(event);
|
||||
},
|
||||
});
|
||||
|
||||
/** Copy and cut */
|
||||
Shortcuts.add({
|
||||
name: 'CMD+X',
|
||||
handler: (event) => {
|
||||
BlockEvents.handleCommandX(event);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -110,14 +110,6 @@ export default class BlockSelection extends Module {
|
|||
},
|
||||
});
|
||||
|
||||
/** Shortcut to copy selected blocks */
|
||||
Shortcuts.add({
|
||||
name: 'CMD+C',
|
||||
handler: (event) => {
|
||||
this.handleCommandC(event);
|
||||
},
|
||||
});
|
||||
|
||||
this.selection = new SelectionUtils();
|
||||
}
|
||||
|
||||
|
@ -144,6 +136,28 @@ export default class BlockSelection extends Module {
|
|||
this.allBlocksSelected = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reduce each Block and copy its content
|
||||
*/
|
||||
public copySelectedBlocks(): void {
|
||||
const { BlockManager, Sanitizer } = this.Editor;
|
||||
const fakeClipboard = $.make('div');
|
||||
|
||||
BlockManager.blocks.filter( (block) => block.selected )
|
||||
.forEach( (block) => {
|
||||
/**
|
||||
* Make <p> tag that holds clean HTML
|
||||
*/
|
||||
const cleanHTML = Sanitizer.clean(block.holder.innerHTML, this.sanitizerConfig);
|
||||
const fragment = $.make('p');
|
||||
|
||||
fragment.innerHTML = cleanHTML;
|
||||
fakeClipboard.appendChild(fragment);
|
||||
});
|
||||
|
||||
_.copyTextToClipboard(fakeClipboard.innerHTML);
|
||||
}
|
||||
|
||||
/**
|
||||
* First CMD+A Selects current focused blocks,
|
||||
* and consequent second CMD+A keypress selects all blocks
|
||||
|
@ -169,49 +183,11 @@ export default class BlockSelection extends Module {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copying selected blocks
|
||||
* Before putting to the clipboard we sanitize all blocks and then copy to the clipboard
|
||||
*
|
||||
* @param event
|
||||
*/
|
||||
private handleCommandC(event): void {
|
||||
const { BlockManager, Sanitizer } = this.Editor;
|
||||
|
||||
if (!this.anyBlockSelected) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent default copy
|
||||
* Remove "decline sound" on macOS
|
||||
*/
|
||||
event.preventDefault();
|
||||
|
||||
const fakeClipboard = $.make('div');
|
||||
|
||||
BlockManager.blocks.filter( (block) => block.selected )
|
||||
.forEach( (block) => {
|
||||
/**
|
||||
* Make <p> tag that holds clean HTML
|
||||
*/
|
||||
const cleanHTML = Sanitizer.clean(block.holder.innerHTML, this.sanitizerConfig);
|
||||
const fragment = $.make('p');
|
||||
|
||||
fragment.innerHTML = cleanHTML;
|
||||
fakeClipboard.appendChild(fragment);
|
||||
});
|
||||
|
||||
_.copyTextToClipboard(fakeClipboard.innerHTML);
|
||||
}
|
||||
|
||||
/**
|
||||
* Select All Blocks
|
||||
* Each Block has selected setter that makes Block copyable
|
||||
*/
|
||||
private selectAllBlocks() {
|
||||
const { BlockManager } = this.Editor;
|
||||
|
||||
this.allBlocksSelected = true;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue