diff --git a/apps/editor/src/js/wwTableManager.js b/apps/editor/src/js/wwTableManager.js
index 27c9934d73..75cdfb9131 100644
--- a/apps/editor/src/js/wwTableManager.js
+++ b/apps/editor/src/js/wwTableManager.js
@@ -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
@@ -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);
@@ -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))
@@ -307,6 +311,7 @@ class WwTableManager {
if (domUtils.getNodeName(tdOrTh.lastChild) !== 'BR'
&& domUtils.getNodeName(tdOrTh.lastChild) !== 'DIV'
+ && !isIE10And11
) {
$(tdOrTh).append($('
')[0]);
}
@@ -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();
}
@@ -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
@@ -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();
}
});
@@ -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('
');
+ }
+ }
}
/**
diff --git a/apps/editor/src/js/wwTableSelectionManager.js b/apps/editor/src/js/wwTableSelectionManager.js
index c44f079fb6..46c214b7fd 100644
--- a/apps/editor/src/js/wwTableSelectionManager.js
+++ b/apps/editor/src/js/wwTableSelectionManager.js
@@ -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;
@@ -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(() => {
@@ -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
@@ -134,8 +155,6 @@ class WwTableSelectionManager {
if (isTableSelecting) {
this._tableSelectionTimer = setTimeout(() => {
this._isSelectionStarted = true;
- this._isCellsSelected = true;
- this._isSecondMouseDown = false;
}, 100);
}
}
@@ -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;
diff --git a/apps/editor/src/js/wysiwygCommands/bold.js b/apps/editor/src/js/wysiwygCommands/bold.js
index c3a66a245a..9c0588e54a 100644
--- a/apps/editor/src/js/wysiwygCommands/bold.js
+++ b/apps/editor/src/js/wysiwygCommands/bold.js
@@ -5,7 +5,8 @@
*/
-const CommandManager = require('../commandManager');
+import CommandManager from '../commandManager';
+import domUtils from '../domUtils';
/**
* Bold
@@ -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')) {
@@ -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);
+ }
}
});
diff --git a/apps/editor/src/js/wysiwygCommands/code.js b/apps/editor/src/js/wysiwygCommands/code.js
index 06e4038722..effa6688fe 100644
--- a/apps/editor/src/js/wysiwygCommands/code.js
+++ b/apps/editor/src/js/wysiwygCommands/code.js
@@ -5,8 +5,8 @@
*/
-const CommandManager = require('../commandManager'),
- domUtils = require('../domUtils');
+import CommandManager from '../commandManager';
+import domUtils from '../domUtils';
/**
* Code
@@ -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());
@@ -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);
+ }
}
});
diff --git a/apps/editor/src/js/wysiwygCommands/codeBlock.js b/apps/editor/src/js/wysiwygCommands/codeBlock.js
index 06453a3e43..dbcd6ae36b 100644
--- a/apps/editor/src/js/wysiwygCommands/codeBlock.js
+++ b/apps/editor/src/js/wysiwygCommands/codeBlock.js
@@ -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) {
diff --git a/apps/editor/src/js/wysiwygCommands/heading.js b/apps/editor/src/js/wysiwygCommands/heading.js
index 9cba3af295..4b416be640 100644
--- a/apps/editor/src/js/wysiwygCommands/heading.js
+++ b/apps/editor/src/js/wysiwygCommands/heading.js
@@ -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);
@@ -33,7 +36,6 @@ const Heading = CommandManager.command('wysiwyg', /** @lends Heading */{
}
}
- sq.focus();
}
});
diff --git a/apps/editor/src/js/wysiwygCommands/italic.js b/apps/editor/src/js/wysiwygCommands/italic.js
index 1dc9d281c8..dc2643b84a 100644
--- a/apps/editor/src/js/wysiwygCommands/italic.js
+++ b/apps/editor/src/js/wysiwygCommands/italic.js
@@ -6,6 +6,7 @@
import CommandManager from '../commandManager';
+import domUtils from '../domUtils';
/**
* Italic
@@ -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'});
@@ -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);
+ }
}
});
diff --git a/apps/editor/src/js/wysiwygCommands/strike.js b/apps/editor/src/js/wysiwygCommands/strike.js
index 0d79f102c1..686b950005 100644
--- a/apps/editor/src/js/wysiwygCommands/strike.js
+++ b/apps/editor/src/js/wysiwygCommands/strike.js
@@ -5,6 +5,7 @@
import CommandManager from '../commandManager';
+import domUtils from '../domUtils';
/**
* Strike
@@ -22,6 +23,14 @@ const Strike = CommandManager.command('wysiwyg', /** @lends Strike */{
*/
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('S')) {
sq.changeFormat(null, {tag: 'S'});
@@ -32,7 +41,10 @@ const Strike = CommandManager.command('wysiwyg', /** @lends Strike */{
sq.strikethrough();
}
- sq.focus();
+ if (sq.hasFormat('table') && !domUtils.isTextNode(range.commonAncestorContainer)) {
+ range.collapse(true);
+ sq.setSelection(range);
+ }
}
});
diff --git a/apps/editor/test/wwTableManager.spec.js b/apps/editor/test/wwTableManager.spec.js
index 20e9b4883d..a49c93b5a9 100644
--- a/apps/editor/test/wwTableManager.spec.js
+++ b/apps/editor/test/wwTableManager.spec.js
@@ -1052,57 +1052,7 @@ describe('WwTableManager', () => {
expect(target).toBeUndefined();
});
});
- describe('_createRangeBySelectedCells', () => {
- it('should create selection by selected cells and current selection is in table', () => {
- const html = '
1 | 2 |
---|---|
3 2 1 | 4 |
5 | 6 |
1 | 2 |
---|---|
3 2 1 | 4 |
5 | 6 |
1 | 2 |
---|---|
3 2 1 | 4 |
5 | 6 |
1 | 2 |
---|---|
3 2 1 | 4 |
5 | 6 |