This commit is contained in:
gohabereg 2019-06-04 19:49:24 +03:00 committed by georgyb
parent 384cd1ad75
commit d0f6f81964
7 changed files with 25125 additions and 16 deletions

24931
dist/editor.js vendored

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,166 @@
import Module from '../__module';
import Block from '../block';
import SelectionUtils from '../selection';
export default class CBS extends Module {
public _shouldClearSelectionOnClick: boolean = true;
private isDownward: boolean = true;
private mousePressed: boolean = false;
private firstTarget: Block = null;
private lastTarget: Block = null;
public startSelection(event: MouseEvent) {
if (event.button !== 0) {
return;
}
this.firstTarget = this.Editor.BlockManager.getBlockByChildNode(event.target as HTMLElement);
this.lastTarget = null;
this.mousePressed = true;
this.Editor.Listeners.on(window, 'mousemove', this.onMouseMove);
this.Editor.Listeners.on(window, 'mouseup', this.finishSelection);
}
public onMouseMove = (e: MouseEvent): void => {
if (!this.mousePressed) {
return;
}
const {BlockManager} = this.Editor;
const target = e.target as HTMLElement;
const block = BlockManager.getBlockByChildNode(target);
if (!this.lastTarget) {
this.lastTarget = block;
}
if (block === this.lastTarget) {
return;
}
const lastTargetIndex = BlockManager.blocks.indexOf(this.lastTarget);
const blockIndex = BlockManager.blocks.indexOf(block);
if (this.lastTarget === this.firstTarget) {
const selection = SelectionUtils.get();
this.isDownward = lastTargetIndex - blockIndex < 0;
selection.removeAllRanges();
}
const currentDirection = lastTargetIndex - blockIndex < 0;
if (this.isDownward === currentDirection) {
this.lastTarget.selected = true;
this.lastTarget = block;
this.lastTarget.selected = !this.lastTarget.selected;
} else {
this.lastTarget.selected = !this.lastTarget.selected;
this.lastTarget = block;
}
console.log('Moved');
}
public finishSelection = (e: MouseEvent): void => {
const {BlockManager} = this.Editor;
console.log(e);
this.mousePressed = false;
this.shouldClearSelectionOnClick = false;
this.Editor.Listeners.off(window, 'mousemove', this.onMouseMove);
this.Editor.Listeners.off(window, 'mouseup', this.finishSelection);
if (e.metaKey) {
const block = BlockManager.getBlockByChildNode(e.target as HTMLElement);
block.selected = !block.selected;
}
}
public get shouldClearSelectionOnClick() {
return this._shouldClearSelectionOnClick;
}
public set shouldClearSelectionOnClick(value) {
// if (value === true) {
// this.lastTarget = null;
// this.firstTarget = null;
// }
this._shouldClearSelectionOnClick = value;
}
public selectNextBlock(): void {
console.log(this.Editor.Caret.isAtEnd);
if (!this.Editor.BlockSelection.anyBlockSelected && !this.Editor.Caret.isAtEnd && !this.lastTarget) {
return;
}
const {BlockManager} = this.Editor;
const {currentBlock} = BlockManager;
if (!this.lastTarget) {
this.lastTarget = currentBlock;
this.isDownward = true;
const selection = SelectionUtils.get();
selection.removeAllRanges();
}
const lastTargetIndex = BlockManager.blocks.indexOf(this.lastTarget);
const nextTarget = BlockManager.blocks[lastTargetIndex + 1];
if (!nextTarget) {
return;
}
if (this.isDownward) {
this.lastTarget.selected = true;
this.lastTarget = nextTarget;
this.lastTarget.selected = !this.lastTarget.selected;
} else {
this.lastTarget.selected = !this.lastTarget.selected;
this.lastTarget = nextTarget;
}
}
public selectPrevioiusBlock(): void {
if (!this.Editor.BlockSelection.anyBlockSelected && !this.Editor.Caret.isAtStart && !this.lastTarget) {
return;
}
const {BlockManager} = this.Editor;
if (!this.lastTarget) {
const {currentBlock} = BlockManager;
this.lastTarget = currentBlock;
this.isDownward = false;
const selection = SelectionUtils.get();
selection.removeAllRanges();
}
const lastTargetIndex = BlockManager.blocks.indexOf(this.lastTarget);
const nextTarget = BlockManager.blocks[lastTargetIndex - 1];
if (!nextTarget) {
return;
}
if (!this.isDownward) {
this.lastTarget.selected = true;
this.lastTarget = nextTarget;
this.lastTarget.selected = !this.lastTarget.selected;
} else {
this.lastTarget.selected = !this.lastTarget.selected;
this.lastTarget = nextTarget;
}
}
}

View file

@ -4,6 +4,7 @@
import Module from '../__module';
import _ from '../utils';
import SelectionUtils from '../selection';
import $ from '../dom';
export default class BlockEvents extends Module {
@ -109,6 +110,12 @@ export default class BlockEvents extends Module {
this.Editor.InlineToolbar.handleShowingEvent(event);
}
public mouseDown(event): void {
if (event.target.closest('[contenteditable="true"]') || $.isNativeInput(event.target)) {
this.Editor.CBS.startSelection(event);
}
}
/**
* Open Toolbox to leaf Tools
* @param {KeyboardEvent} event
@ -467,6 +474,12 @@ export default class BlockEvents extends Module {
* Handle right and down keyboard keys
*/
private arrowRightAndDown(event: KeyboardEvent): void {
if (event.shiftKey && event.keyCode === _.keyCodes.DOWN) {
this.Editor.CBS.selectNextBlock();
return;
}
if (this.Editor.Caret.navigateNext()) {
/**
* Default behaviour moves cursor by 1 character, we need to prevent it
@ -486,6 +499,12 @@ export default class BlockEvents extends Module {
* Handle left and up keyboard keys
*/
private arrowLeftAndUp(event: KeyboardEvent): void {
if (event.shiftKey && event.keyCode === _.keyCodes.UP) {
this.Editor.CBS.selectPrevioiusBlock();
return;
}
if (this.Editor.Caret.navigatePrevious()) {
/**
* Default behaviour moves cursor by 1 character, we need to prevent it

View file

@ -586,6 +586,7 @@ export default class BlockManager extends Module {
Listeners.on(block.holder, 'keydown', (event) => BlockEvents.keydown(event as KeyboardEvent), true);
Listeners.on(block.holder, 'mouseup', (event) => BlockEvents.mouseUp(event));
Listeners.on(block.holder, 'mousedown', (event) => BlockEvents.mouseDown(event));
Listeners.on(block.holder, 'keyup', (event) => BlockEvents.keyup(event));
Listeners.on(block.holder, 'dragover', (event) => BlockEvents.dragOver(event as DragEvent));
Listeners.on(block.holder, 'dragleave', (event) => BlockEvents.dragLeave(event as DragEvent));

View file

@ -163,6 +163,12 @@ export default class BlockSelection extends Module {
return;
}
console.trace();
if (!this.Editor.CBS.shouldClearSelectionOnClick) {
this.Editor.CBS.shouldClearSelectionOnClick = true;
return;
}
/**
* Restore selection when Block is already selected
* but someone tries to write something.

View file

@ -55,10 +55,18 @@ export default class Caret extends Module {
return false;
}
if (!this.Editor.BlockManager.currentBlock) {
return false;
}
const selection = Selection.get();
const firstNode = $.getDeepestNode(this.Editor.BlockManager.currentBlock.currentInput);
let anchorNode = selection.anchorNode;
if (!anchorNode) {
return false;
}
/** In case lastNode is native input */
if ($.isNativeInput(firstNode)) {
return (firstNode as HTMLInputElement).selectionEnd === 0;
@ -130,9 +138,17 @@ export default class Caret extends Module {
return false;
}
if (!this.Editor.BlockManager.currentBlock) {
return false;
}
const selection = Selection.get();
let anchorNode = selection.anchorNode;
if (!anchorNode) {
return false;
}
const lastNode = $.getDeepestNode(this.Editor.BlockManager.currentBlock.currentInput, true);
/** In case lastNode is native input */

View file

@ -31,6 +31,7 @@ import Saver from '../components/modules/saver';
import BlockSelection from '../components/modules/blockSelection';
import RectangleSelection from '../components/modules/RectangleSelection';
import InlineToolbarAPI from '../components/modules/api/inlineToolbar';
import CBS from "../components/modules/CBS";
export interface EditorModules {
UI: UI;
@ -66,4 +67,5 @@ export interface EditorModules {
ToolbarAPI: ToolbarAPI;
InlineToolbarAPI: InlineToolbarAPI;
NotifierAPI: NotifierAPI;
CBS: CBS;
}