mirror of
https://github.com/codex-team/editor.js
synced 2026-03-18 08:29:52 +01:00
dom improvements and merging blocks
This commit is contained in:
parent
eded07b984
commit
d29b3ae772
6 changed files with 151 additions and 47 deletions
|
|
@ -532,7 +532,7 @@ var Dom = function () {
|
|||
*
|
||||
* @description Method recursively goes throw the all Node until it finds the Leaf
|
||||
*
|
||||
* @param {Element} node - root Node. From this vertex we start Deep-first search {@link https://en.wikipedia.org/wiki/Depth-first_search}
|
||||
* @param {Node} node - root Node. From this vertex we start Deep-first search {@link https://en.wikipedia.org/wiki/Depth-first_search}
|
||||
* @param {Boolean} atLast - find last text node
|
||||
* @return {Node} - it can be text Node or Element Node, so that caret will able to work with it
|
||||
*/
|
||||
|
|
@ -543,32 +543,18 @@ var Dom = function () {
|
|||
var atLast = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
|
||||
|
||||
|
||||
if (node.childNodes.length === 0) {
|
||||
if (node && node.nodeType === Node.ELEMENT_NODE && node.firstChild) {
|
||||
|
||||
/**
|
||||
* We need to return an empty text node
|
||||
* But caret will not be placed in empty textNode, so we need textNode with zero-width char
|
||||
*/
|
||||
if (this.isElement(node) && !this.isNativeInput(node)) {
|
||||
if (atLast) {
|
||||
|
||||
var emptyTextNode = this.text('\u200B');
|
||||
return this.getDeepestNode(node.lastChild, atLast);
|
||||
} else {
|
||||
|
||||
node.appendChild(emptyTextNode);
|
||||
return this.getDeepestNode(node.firstChild, false);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
var childsLength = node.childNodes.length,
|
||||
last = childsLength - 1;
|
||||
|
||||
if (atLast) {
|
||||
|
||||
return this.getDeepestNode(node.childNodes[last], atLast);
|
||||
} else {
|
||||
|
||||
return this.getDeepestNode(node.childNodes[0], false);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1549,6 +1535,38 @@ var BlockManager = function (_Module) {
|
|||
this.Editor.Caret.setToBlock(block);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param targetBlock
|
||||
* @param mergingBlock
|
||||
*/
|
||||
|
||||
}, {
|
||||
key: 'mergeBlocks',
|
||||
value: function mergeBlocks(targetBlock, mergingBlock) {
|
||||
|
||||
if (!targetBlock) {
|
||||
|
||||
targetBlock = this._blocks[this.currentBlockIndex - 1];
|
||||
}
|
||||
|
||||
if (!mergingBlock) {
|
||||
|
||||
mergingBlock = this._blocks[this.currentBlockIndex];
|
||||
}
|
||||
|
||||
var range = document.createRange();
|
||||
|
||||
range.selectNodeContents(mergingBlock.pluginsContent);
|
||||
|
||||
var extracted = range.extractContents();
|
||||
|
||||
targetBlock.pluginsContent.appendChild(extracted);
|
||||
targetBlock.pluginsContent.normalize();
|
||||
|
||||
this.removeBlock(this.currentBlockIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove block with passed index or remove last
|
||||
* @param {Number|null} index
|
||||
|
|
@ -2497,6 +2515,38 @@ var Caret = function (_Module) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get's deepest first node and checks if offset is zero
|
||||
* @return {boolean}
|
||||
*/
|
||||
|
||||
}, {
|
||||
key: 'isAtStart',
|
||||
get: function get() {
|
||||
|
||||
var selection = _Selection2.default.get(),
|
||||
anchorNode = selection.anchorNode,
|
||||
firstNode = $.getDeepestNode(this.Editor.BlockManager.currentBlock.pluginsContent);
|
||||
|
||||
return anchorNode === firstNode && selection.anchorOffset === 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get's deepest last node and checks if offset is last node text length
|
||||
* @return {boolean}
|
||||
*/
|
||||
|
||||
}, {
|
||||
key: 'isAtEnd',
|
||||
get: function get() {
|
||||
|
||||
var selection = _Selection2.default.get(),
|
||||
anchorNode = selection.anchorNode,
|
||||
lastNode = $.getDeepest;
|
||||
|
||||
return anchorNode === lastNode && selection.anchorOffset === lastNode.textContent.length;
|
||||
}
|
||||
}]);
|
||||
|
||||
return Caret;
|
||||
|
|
@ -2751,7 +2801,11 @@ var Keyboard = function (_Module) {
|
|||
key: 'backSpacePressed',
|
||||
value: function backSpacePressed(event) {
|
||||
|
||||
this.Editor.BlockManager.removeBlock();
|
||||
if (this.Editor.Caret.isAtStart) {
|
||||
|
||||
this.Editor.BlockManager.mergeBlocks();
|
||||
event.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -103,42 +103,27 @@ export default class Dom {
|
|||
*
|
||||
* @description Method recursively goes throw the all Node until it finds the Leaf
|
||||
*
|
||||
* @param {Element} node - root Node. From this vertex we start Deep-first search {@link https://en.wikipedia.org/wiki/Depth-first_search}
|
||||
* @param {Node} node - root Node. From this vertex we start Deep-first search {@link https://en.wikipedia.org/wiki/Depth-first_search}
|
||||
* @param {Boolean} atLast - find last text node
|
||||
* @return {Node} - it can be text Node or Element Node, so that caret will able to work with it
|
||||
*/
|
||||
static getDeepestNode(node, atLast = false) {
|
||||
|
||||
if (node.childNodes.length === 0) {
|
||||
if (node && node.nodeType === Node.ELEMENT_NODE && node.firstChild) {
|
||||
|
||||
/**
|
||||
* We need to return an empty text node
|
||||
* But caret will not be placed in empty textNode, so we need textNode with zero-width char
|
||||
*/
|
||||
if (this.isElement(node) && !this.isNativeInput(node)) {
|
||||
if (atLast) {
|
||||
|
||||
let emptyTextNode = this.text('\u200B');
|
||||
return this.getDeepestNode(node.lastChild, atLast);
|
||||
|
||||
node.appendChild(emptyTextNode);
|
||||
} else {
|
||||
|
||||
return this.getDeepestNode(node.firstChild, false);
|
||||
|
||||
}
|
||||
|
||||
return node;
|
||||
|
||||
}
|
||||
|
||||
let childsLength = node.childNodes.length,
|
||||
last = childsLength - 1;
|
||||
|
||||
if (atLast) {
|
||||
|
||||
return this.getDeepestNode(node.childNodes[last], atLast);
|
||||
|
||||
} else {
|
||||
|
||||
return this.getDeepestNode(node.childNodes[0], false);
|
||||
|
||||
}
|
||||
return node;
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -185,6 +185,38 @@ export default class BlockManager extends Module {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param targetBlock
|
||||
* @param mergingBlock
|
||||
*/
|
||||
mergeBlocks(targetBlock, mergingBlock) {
|
||||
|
||||
if (!targetBlock) {
|
||||
|
||||
targetBlock = this._blocks[this.currentBlockIndex - 1];
|
||||
|
||||
}
|
||||
|
||||
if (!mergingBlock) {
|
||||
|
||||
mergingBlock = this._blocks[this.currentBlockIndex];
|
||||
|
||||
}
|
||||
|
||||
let range = document.createRange();
|
||||
|
||||
range.selectNodeContents(mergingBlock.pluginsContent);
|
||||
|
||||
let extracted = range.extractContents();
|
||||
|
||||
targetBlock.pluginsContent.appendChild(extracted);
|
||||
targetBlock.pluginsContent.normalize();
|
||||
|
||||
this.removeBlock(this.currentBlockIndex);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove block with passed index or remove last
|
||||
* @param {Number|null} index
|
||||
|
|
|
|||
|
|
@ -144,4 +144,32 @@ export default class Caret extends Module {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get's deepest first node and checks if offset is zero
|
||||
* @return {boolean}
|
||||
*/
|
||||
get isAtStart() {
|
||||
|
||||
let selection = Selection.get(),
|
||||
anchorNode = selection.anchorNode,
|
||||
firstNode = $.getDeepestNode(this.Editor.BlockManager.currentBlock.pluginsContent);
|
||||
|
||||
return anchorNode === firstNode && selection.anchorOffset === 0;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get's deepest last node and checks if offset is last node text length
|
||||
* @return {boolean}
|
||||
*/
|
||||
get isAtEnd() {
|
||||
|
||||
let selection = Selection.get(),
|
||||
anchorNode = selection.anchorNode,
|
||||
lastNode = $.getDeepest;
|
||||
|
||||
return anchorNode === lastNode && selection.anchorOffset === lastNode.textContent.length;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -108,7 +108,12 @@ export default class Keyboard extends Module {
|
|||
*/
|
||||
backSpacePressed(event) {
|
||||
|
||||
this.Editor.BlockManager.removeBlock();
|
||||
if (this.Editor.Caret.isAtStart) {
|
||||
|
||||
this.Editor.BlockManager.mergeBlocks();
|
||||
event.preventDefault();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue