Skip to content

Commit

Permalink
Table cell selection failure fixed #757 (#762)
Browse files Browse the repository at this point in the history
* Apply text inline text command on table selection fixes #758
* Prevent codeblock insertion in table related #758
  • Loading branch information
junghwan-park authored and seonim-ryu committed Jan 6, 2020
1 parent 60012cf commit 20ee2bd
Show file tree
Hide file tree
Showing 14 changed files with 228 additions and 92 deletions.
75 changes: 55 additions & 20 deletions apps/editor/src/js/wwTableManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ const isIE10 = tui.util.browser.msie && tui.util.browser.version === 10;
const TABLE_COMPLETION_DELAY = 10;
const SET_SELECTION_DELAY = 50;
const TABLE_CLASS_PREFIX = 'te-content-table-';
const isIE10And11 = tui.util.browser.msie
&& (tui.util.browser.version === 10 || tui.util.browser.version === 11);

/**
* WwTableManager
Expand Down Expand Up @@ -98,6 +100,7 @@ class WwTableManager {

if (isRangeInTable && !this._isSingleModifierKey(keymap)) {
this._recordUndoStateIfNeed(range);
this._removeBRIfNeed(range);
this._removeContentsAndChangeSelectionIfNeed(range, keymap, ev);
} else if (!isRangeInTable && this._lastCellNode) {
this._recordUndoStateAndResetCellNode(range);
Expand Down Expand Up @@ -211,6 +214,7 @@ class WwTableManager {
this._tableHandlerOnDelete(range, ev);
}

this._insertBRIfNeed(range);
this._removeContentsAndChangeSelectionIfNeed(range, keymap, ev);
isNeedNext = false;
} else if ((isBackspace && this._isBeforeTable(range))
Expand Down Expand Up @@ -307,6 +311,7 @@ class WwTableManager {

if (domUtils.getNodeName(tdOrTh.lastChild) !== 'BR'
&& domUtils.getNodeName(tdOrTh.lastChild) !== 'DIV'
&& !isIE10And11
) {
$(tdOrTh).append($('<br />')[0]);
}
Expand All @@ -320,9 +325,16 @@ class WwTableManager {
* @private
*/
_unwrapBlockInTable() {
this.wwe.get$Body().find('td div,th div,tr>br').each((index, node) => {
if (node.nodeName === 'BR') {
$(node).remove();
this.wwe.get$Body().find('td div,th div,tr>br,td>br,th>br').each((index, node) => {
if (domUtils.getNodeName(node) === 'BR') {
const parentNodeName = domUtils.getNodeName(node.parentNode);
const isInTableCell = /TD|TH/.test(parentNodeName);
const isEmptyTableCell = node.parentNode.textContent.length === 0;
const isLastBR = node.parentNode.lastChild === node;

if (parentNodeName === 'TR' || (isInTableCell && !isEmptyTableCell && isLastBR)) {
$(node).remove();
}
} else {
$(node).children().unwrap();
}
Expand Down Expand Up @@ -992,22 +1004,6 @@ class WwTableManager {
}
}

/**
* Create selection by selected cells and collapse that selection to end
* @private
*/
_createRangeBySelectedCells() {
const sq = this.wwe.getEditor();
const range = sq.getSelection().cloneRange();
const selectedCells = this.wwe.getManager('tableSelection').getSelectedCells();

if (selectedCells.length && this.isInTable(range)) {
range.setStart(selectedCells.first()[0], 0);
range.setEnd(selectedCells.last()[0], 1);
sq.setSelection(range);
}
}

/**
* Create selection by selected cells and collapse that selection to end
* @private
Expand Down Expand Up @@ -1062,10 +1058,11 @@ class WwTableManager {
_bindKeyEventForTableCopyAndCut() {
const isMac = /Mac OS X/.test(navigator.userAgent);
const commandKey = isMac ? 'metaKey' : 'ctrlKey';
const selectionManager = this.wwe.getManager('tableSelection');

this.wwe.getEditor().addEventListener('keydown', event => {
if (event[commandKey]) {
this._createRangeBySelectedCells();
selectionManager.createRangeBySelectedCells();
}
});

Expand Down Expand Up @@ -1113,6 +1110,44 @@ class WwTableManager {

return tableClassName;
}

/**
* Remove br when text inputted
* @param {Range} range Range object
* @private
*/
_removeBRIfNeed(range) {
const startContainer = domUtils.isTextNode(range.startContainer)
? range.startContainer.parentNode : range.startContainer;
const nodeName = domUtils.getNodeName(startContainer);

if (/td|th/i.test(nodeName) && range.collapsed && startContainer.textContent.length === 1) {
$(startContainer).find('br').remove();
}
}


/**
* Insert br when text deleted
* @param {Range} range Range object
* @private
*/
_insertBRIfNeed(range) {
const currentCell = range.startContainer.nodeType === 3
? range.startContainer.parentNode : range.startContainer;
const nodeName = domUtils.getNodeName(currentCell);
const $currentCell = $(currentCell);

if (/td|th/i.test(nodeName)
&& range.collapsed
&& !currentCell.textContent.length
&& !$currentCell.children().length
&& !isIE10And11
) {
currentCell.normalize();
$currentCell.append('<br>');
}
}
}

/**
Expand Down
64 changes: 50 additions & 14 deletions apps/editor/src/js/wwTableSelectionManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ class WwTableSelectionManager {

this.eventManager.listen('mousedown', ev => {
const MOUSE_RIGHT_BUTTON = 2;
selectionStart = ev.data.target;
selectionStart = $(ev.data.target).closest('td,th')[0];
const isSelectedCell = $(selectionStart).hasClass(TABLE_CELL_SELECTED_CLASS_NAME);
selectionEnd = null;

Expand All @@ -91,12 +91,14 @@ class WwTableSelectionManager {
});

this.eventManager.listen('mouseover', ev => {
const isTextSelect = this.wwe.getEditor().getSelection().commonAncestorContainer.nodeType === 3;
selectionEnd = $(ev.data.target).closest('td,th')[0];

selectionEnd = ev.data.target;
const isTableCell = $(selectionEnd).parents('table')[0];
const range = this.wwe.getEditor().getSelection();
const isEndsInTable = $(selectionEnd).parents('table')[0];
const isSameCell = selectionStart === selectionEnd;
const isTextSelect = this._isTextSelect(range, isSameCell);

if (this._isSelectionStarted && !isTextSelect && isTableCell) {
if (this._isSelectionStarted && isEndsInTable && (!isTextSelect || isSameCell && !isTextSelect)) {
// For disable firefox's native table cell selection
if (tui.util.browser.firefox && !this._removeSelectionTimer) {
this._removeSelectionTimer = setInterval(() => {
Expand All @@ -106,23 +108,42 @@ class WwTableSelectionManager {
this._highlightTableCellsBy(selectionStart, selectionEnd);
}
});
this.eventManager.listen('mouseup', () => {
const isTextSelect = this.wwe.getEditor().getSelection().commonAncestorContainer.nodeType === 3;
this.eventManager.listen('mouseup', ev => {
selectionEnd = $(ev.data.target).closest('td,th')[0];

let range = this.wwe.getEditor().getSelection();
const isSameCell = selectionStart === selectionEnd;
const isTextSelect = this._isTextSelect(range, isSameCell);

this._clearTableSelectionTimerIfNeed();

if (this._isSelectionStarted && !isTextSelect) {
this.wwe.getManager('table').resetLastCellNode();
if (this._isSelectionStarted) {
if (isTextSelect) {
this.removeClassAttrbuteFromAllCellsIfNeed();
} else {
this.wwe.getManager('table').resetLastCellNode();

const range = this.wwe.getEditor().getSelection();
range.collapse(true);
this.wwe.getEditor().setSelection(range);
range = this.wwe.getEditor().getSelection();
range.collapse(true);
this.wwe.getEditor().setSelection(range);
}
}

this._isSelectionStarted = false;
});
}

/**
* Return whether single cell text selection or not
* @param {Range} range Range object
* @param {boolean} isSameCell Boolean value for same cell selection
* @returns {boolean}
* @private
*/
_isTextSelect(range, isSameCell) {
return /TD|TH|TEXT/i.test(range.commonAncestorContainer.nodeName) && isSameCell;
}

/**
* Set setTimeout and setInterval timer execution if table selecting situation
* @param {HTMLElement} selectionStart Start element
Expand All @@ -134,8 +155,6 @@ class WwTableSelectionManager {
if (isTableSelecting) {
this._tableSelectionTimer = setTimeout(() => {
this._isSelectionStarted = true;
this._isCellsSelected = true;
this._isSecondMouseDown = false;
}, 100);
}
}
Expand Down Expand Up @@ -335,5 +354,22 @@ class WwTableSelectionManager {
getSelectedCells() {
return this.wwe.get$Body().find(`.${TABLE_CELL_SELECTED_CLASS_NAME}`);
}

/**
* Create selection by selected cells and collapse that selection to end
* @private
*/
createRangeBySelectedCells() {
const sq = this.wwe.getEditor();
const range = sq.getSelection().cloneRange();
const selectedCells = this.getSelectedCells();
const tableManager = this.wwe.getManager('table');

if (selectedCells.length && tableManager.isInTable(range)) {
range.setStart(selectedCells.first()[0], 0);
range.setEnd(selectedCells.last()[0], 1);
sq.setSelection(range);
}
}
}
module.exports = WwTableSelectionManager;
14 changes: 13 additions & 1 deletion apps/editor/src/js/wysiwygCommands/bold.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
*/


const CommandManager = require('../commandManager');
import CommandManager from '../commandManager';
import domUtils from '../domUtils';

/**
* Bold
Expand All @@ -23,9 +24,14 @@ const Bold = CommandManager.command('wysiwyg', /** @lends Bold */{
*/
exec(wwe) {
const sq = wwe.getEditor();
const tableSelectionManager = wwe.getManager('tableSelection');

sq.focus();

if (sq.hasFormat('table') && tableSelectionManager.getSelectedCells().length) {
tableSelectionManager.createRangeBySelectedCells();
}

if (sq.hasFormat('b') || sq.hasFormat('strong')) {
sq.changeFormat(null, {tag: 'b'});
} else if (!sq.hasFormat('a') && !sq.hasFormat('PRE')) {
Expand All @@ -34,6 +40,12 @@ const Bold = CommandManager.command('wysiwyg', /** @lends Bold */{
}
sq.bold();
}

const range = sq.getSelection();
if (sq.hasFormat('table') && !domUtils.isTextNode(range.commonAncestorContainer)) {
range.collapse(true);
sq.setSelection(range);
}
}
});

Expand Down
17 changes: 14 additions & 3 deletions apps/editor/src/js/wysiwygCommands/code.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
*/


const CommandManager = require('../commandManager'),
domUtils = require('../domUtils');
import CommandManager from '../commandManager';
import domUtils from '../domUtils';

/**
* Code
Expand All @@ -24,9 +24,15 @@ const Code = CommandManager.command('wysiwyg', /** @lends Code */{
*/
exec(wwe) {
const sq = wwe.getEditor();
let range = sq.getSelection();
const tableSelectionManager = wwe.getManager('tableSelection');

sq.focus();

if (sq.hasFormat('table') && tableSelectionManager.getSelectedCells().length) {
tableSelectionManager.createRangeBySelectedCells();
}

if (!sq.hasFormat('PRE') && sq.hasFormat('code')) {
sq.changeFormat(null, {tag: 'code'});
removeUnnecessaryCodeInNextToRange(wwe.getEditor().getSelection().cloneRange());
Expand All @@ -39,12 +45,17 @@ const Code = CommandManager.command('wysiwyg', /** @lends Code */{

sq.changeFormat({tag: 'code'});

const range = sq.getSelection().cloneRange();
range = sq.getSelection().cloneRange();
range.setStart(range.endContainer, range.endOffset);
range.collapse(true);

sq.setSelection(range);
}

if (sq.hasFormat('table') && !domUtils.isTextNode(range.commonAncestorContainer)) {
range.collapse(true);
sq.setSelection(range);
}
}
});

Expand Down
2 changes: 1 addition & 1 deletion apps/editor/src/js/wysiwygCommands/codeBlock.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const CodeBlock = CommandManager.command('wysiwyg', /** @lends CodeBlock */{
exec(wwe, type) {
const sq = wwe.getEditor();
const range = sq.getSelection().cloneRange();
if (!sq.hasFormat('PRE')) {
if (!sq.hasFormat('PRE') && !sq.hasFormat('TABLE')) {
let attr = `${CODEBLOCK_ATTR_NAME} class = "${CODEBLOCK_CLASS_PREFIX}${codeBlockID}"`;

if (type) {
Expand Down
4 changes: 3 additions & 1 deletion apps/editor/src/js/wysiwygCommands/heading.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ const Heading = CommandManager.command('wysiwyg', /** @lends Heading */{
*/
exec(wwe, size) {
const sq = wwe.getEditor();

sq.focus();

const range = sq.getSelection().cloneRange();
const nodeName = domUtils.getNodeName(range.commonAncestorContainer);

Expand All @@ -33,7 +36,6 @@ const Heading = CommandManager.command('wysiwyg', /** @lends Heading */{
}
}

sq.focus();
}
});

Expand Down
14 changes: 13 additions & 1 deletion apps/editor/src/js/wysiwygCommands/italic.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@


import CommandManager from '../commandManager';
import domUtils from '../domUtils';

/**
* Italic
Expand All @@ -23,6 +24,14 @@ const Italic = CommandManager.command('wysiwyg', /** @lends Italic */{
*/
exec(wwe) {
const sq = wwe.getEditor();
const range = sq.getSelection();
const tableSelectionManager = wwe.getManager('tableSelection');

sq.focus();

if (sq.hasFormat('table') && tableSelectionManager.getSelectedCells().length) {
tableSelectionManager.createRangeBySelectedCells();
}

if (sq.hasFormat('i') || sq.hasFormat('em')) {
sq.changeFormat(null, {tag: 'i'});
Expand All @@ -33,7 +42,10 @@ const Italic = CommandManager.command('wysiwyg', /** @lends Italic */{
sq.italic();
}

sq.focus();
if (sq.hasFormat('table') && !domUtils.isTextNode(range.commonAncestorContainer)) {
range.collapse(true);
sq.setSelection(range);
}
}
});

Expand Down
Loading

0 comments on commit 20ee2bd

Please sign in to comment.