fix: table paste will be nested

This commit is contained in:
yanmao 2022-01-07 01:32:35 +08:00
parent 9453ea48b7
commit a53e5db82e
8 changed files with 100 additions and 35 deletions

View File

@ -119,17 +119,20 @@ class CardToolbar implements CardToolbarInterface {
content:
item.content ||
`<span class="data-icon data-icon-copy"></span>`,
title:
item.title || language.get('copy', 'title').toString(),
onClick: () => {
title: item.title || language.get<string>('copy', 'title'),
onClick: (e, node) => {
if (item.onClick) {
item.onClick(e, node);
return;
}
const result = clipboard.copy(this.card.root[0], true);
if (result)
editor.messageSuccess(
language.get('copy', 'success').toString(),
language.get<string>('copy', 'success'),
);
else
editor.messageError(
language.get('copy', 'error').toString(),
language.get<string>('copy', 'error'),
);
},
};
@ -142,7 +145,11 @@ class CardToolbar implements CardToolbarInterface {
title:
item.title ||
language.get('delete', 'title').toString(),
onClick: () => {
onClick: (e, node) => {
if (item.onClick) {
item.onClick(e, node);
return;
}
card.remove(this.card.root);
},
};
@ -155,7 +162,11 @@ class CardToolbar implements CardToolbarInterface {
title:
item.title ||
language.get('maximize', 'title').toString(),
onClick: () => {
onClick: (e, node) => {
if (item.onClick) {
item.onClick(e, node);
return;
}
this.card.maximize();
},
};

View File

@ -75,6 +75,7 @@ export type CardToolbarItemOptions =
disabled?: boolean;
content?: string;
title?: string;
onClick?: (event: MouseEvent, node: NodeInterface) => void;
}
| {
type: 'more';

View File

@ -457,9 +457,9 @@ class TableCommand extends EventEmitter2 implements TableCommandInterface {
this.editor.card.remove(this.table.id);
}
copy() {
copy(all: boolean = false) {
const { selection, helper } = this.table;
const areaHtml = selection.getSelectionHtml();
const areaHtml = selection.getSelectionHtml(all);
if (!areaHtml) return;
this.editor.clipboard.copy($(areaHtml)[0]);
helper.copyHTML(areaHtml);

View File

@ -32,7 +32,7 @@ class Helper implements HelperInterface {
isEmptyModelCol(
model: TableModelCol | TableModelEmptyCol,
): model is TableModelEmptyCol {
return (model as TableModelEmptyCol).isEmpty;
return model && (model as TableModelEmptyCol).isEmpty;
}
/**

View File

@ -413,6 +413,12 @@ class TableComponent<V extends TableValue = TableValue>
},
{
type: 'copy',
onClick: () => {
this.command.copy(true);
this.editor.messageSuccess(
this.editor.language.get<string>('copy', 'success'),
);
},
},
{
type: 'delete',

View File

@ -369,6 +369,7 @@ class TableSelection extends EventEmitter2 implements TableSelectionInterface {
for (let row = fBeginRow; row > -1 && row <= fEndRow; row++) {
for (let col = fBeginCol; col > -1 && col <= fEndCol; col++) {
const cell = this.tableModel.table[row][col];
if (!cell) continue;
if (this.table.helper.isEmptyModelCol(cell)) {
if (beginRow > cell.parent.row) beginRow = cell.parent.row;
if (beginCol >= cell.parent.col) beginCol = cell.parent.col;
@ -409,7 +410,7 @@ class TableSelection extends EventEmitter2 implements TableSelectionInterface {
for (let r = beginRow; r <= endRow; r++) {
for (let c = beginCol; c <= endCol; c++) {
const col = this.tableModel.table[r][c];
if (!this.table.helper.isEmptyModelCol(col)) {
if (col && !this.table.helper.isEmptyModelCol(col)) {
if (!isSame && col.element) {
$(col.element).attributes(
'table-cell-selection',
@ -424,6 +425,7 @@ class TableSelection extends EventEmitter2 implements TableSelectionInterface {
if (isSame && begin.row > -1 && begin.col > -1) {
const cell = this.tableModel.table[begin.row][begin.col];
if (
cell &&
!this.table.helper.isEmptyModelCol(cell) &&
cell.element &&
!this.prevMouseDownTd?.equal(cell.element)
@ -871,11 +873,18 @@ class TableSelection extends EventEmitter2 implements TableSelectionInterface {
} else this.select(begin, { ...end, row: triggerRow });
}
getSelectionHtml() {
getSelectionHtml(all: boolean = false) {
const { tableModel } = this;
const { helper } = this.table;
if (!tableModel || !this.tableRoot) return null;
const { begin, end } = this.getSelectArea();
let begin = { row: 0, col: 0 };
let end = { row: tableModel.rows - 1, col: tableModel.cols - 1 };
if (!all) {
const area = this.getSelectArea();
begin = area.begin;
end = area.end;
}
const colsEl = this.tableRoot.find('col');
let cols = [];
let tableWidth = 0;

View File

@ -60,7 +60,10 @@ class Table<T extends TableOptions = TableOptions> extends Plugin<T> {
if (!isEngine(this.editor)) return true;
const { change, card } = this.editor;
const range = change.range.get();
const component = card.find(range.commonAncestorNode, true);
const component = card.find<TableValue, TableComponent>(
range.commonAncestorNode,
true,
);
if (
component &&
component.getSelectionNodes &&
@ -69,8 +72,10 @@ class Table<T extends TableOptions = TableOptions> extends Plugin<T> {
const nodes = component.getSelectionNodes();
if (nodes.length > 1) {
event.preventDefault();
const tableComponent = component as TableInterface;
tableComponent.command.copy();
component.command.copy();
this.editor.messageSuccess(
this.editor.language.get<string>('copy', 'success'),
);
return false;
}
}
@ -81,7 +86,10 @@ class Table<T extends TableOptions = TableOptions> extends Plugin<T> {
if (!isEngine(this.editor)) return true;
const { change, card } = this.editor;
const range = change.range.get();
const component = card.find(range.commonAncestorNode, true);
const component = card.find<TableValue, TableComponent>(
range.commonAncestorNode,
true,
);
if (
component &&
component.getSelectionNodes &&
@ -90,8 +98,7 @@ class Table<T extends TableOptions = TableOptions> extends Plugin<T> {
const nodes = component.getSelectionNodes();
if (nodes.length > 1) {
event.preventDefault();
const tableComponent = component as TableInterface;
tableComponent.command.cut();
component.command.cut();
return false;
}
}
@ -102,19 +109,19 @@ class Table<T extends TableOptions = TableOptions> extends Plugin<T> {
if (!isEngine(this.editor)) return true;
const { change, card } = this.editor;
const range = change.range.get();
const component = card.find(range.commonAncestorNode, true);
const component = card.find<TableValue, TableComponent>(
range.commonAncestorNode,
true,
);
if (
component &&
component.getSelectionNodes &&
component.name === TableComponent.cardName
component.name === TableComponent.cardName &&
component.command.hasCopyData()
) {
const nodes = component.getSelectionNodes();
if (nodes.length > 0) {
event.preventDefault();
const tableComponent = component as TableInterface;
tableComponent.command.mockPaste();
return false;
}
event.preventDefault();
component.command.mockPaste();
return false;
}
return true;
}
@ -284,22 +291,53 @@ class Table<T extends TableOptions = TableOptions> extends Plugin<T> {
if (width.endsWith('pt')) node.css(type, this.convertToPX(width));
};
const tables = root.find('table');
if (tables.length === 0) return;
const helper = new Helper(this.editor);
// 判断当前是在可编辑卡片内,在可编辑卡片内不嵌套表格
const { change } = this.editor;
const range = change.range.get();
const clearTable = (table: NodeInterface) => {
const thead = table.find('thead');
const headTds = thead.find('th,td').toArray();
headTds.forEach((td) => {
table.before(td.children());
});
const trs = table.find('tr').toArray();
trs.forEach((tr) => {
const tds = tr.find('td').toArray();
tds.forEach((td) => {
if (!this.editor.node.isEmpty(td))
table.before(td.children());
});
});
const tfoot = table.find('tfoot');
const footTds = tfoot.find('th,td').toArray();
footTds.forEach((td) => {
table.before(td.children());
});
table.remove();
};
const isClear = range.startNode.closest(EDITABLE_SELECTOR).length > 0;
tables.each((_, index) => {
let node = tables.eq(index);
if (!node) return;
if (isClear || node.parent()?.name === 'td') {
clearTable(node);
return;
}
node = helper.normalizeTable(node);
clearWH(node);
clearWH(node, 'height');
const tbody = node.find('tbody');
// 表头放在tbody最前面
const thead = node.find('thead');
if (thead && thead.length > 0)
node.find('tbody').prepend(thead.children());
if (thead && thead.length > 0) tbody.prepend(thead.children());
thead.remove();
// 表头放在tbody最前面
const tfoot = node.find('thead');
if (tfoot && tfoot.length > 0)
node.find('tbody').append(tfoot.children());
const tfoot = node.find('tfoot');
if (tfoot && tfoot.length > 0) tbody.append(tfoot.children());
tfoot.remove();
const ths = node.find('th');
ths.each((_, index) => {

View File

@ -293,7 +293,7 @@ export interface TableCommandInterface extends EventEmitter2 {
removeTable(): void;
copy(): void;
copy(all?: boolean): void;
mockCopy(): void;
@ -373,7 +373,7 @@ export interface TableSelectionInterface extends EventEmitter2 {
clearSelect(): void;
getSelectionHtml(): string | null;
getSelectionHtml(all?: boolean): string | null;
hasMergeCell(): boolean;