You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

84 lines
2.5 KiB

import { Node } from 'prosemirror-model';
import { NodeView } from 'prosemirror-view';
/**
* @public
*/
export class TableView implements NodeView {
public dom: HTMLDivElement;
public table: HTMLTableElement;
public colgroup: HTMLTableColElement;
public contentDOM: HTMLTableSectionElement;
constructor(public node: Node, public cellMinWidth: number) {
this.dom = document.createElement('div');
this.dom.className = 'tableWrapper';
this.table = this.dom.appendChild(document.createElement('table'));
this.colgroup = this.table.appendChild(document.createElement('colgroup'));
updateColumnsOnResize(node, this.colgroup, this.table, cellMinWidth);
this.contentDOM = this.table.appendChild(document.createElement('tbody'));
}
update(node: Node): boolean {
if (node.type != this.node.type) return false;
this.node = node;
updateColumnsOnResize(node, this.colgroup, this.table, this.cellMinWidth);
return true;
}
ignoreMutation(record: MutationRecord): boolean {
return (
record.type == 'attributes' &&
(record.target == this.table || this.colgroup.contains(record.target))
);
}
}
/**
* @public
*/
export function updateColumnsOnResize(
node: Node,
colgroup: HTMLTableColElement,
table: HTMLTableElement,
cellMinWidth: number,
overrideCol?: number,
overrideValue?: number,
): void {
let totalWidth = 0,
fixedWidth = true;
let nextDOM = colgroup.firstChild as HTMLElement;
const row = node.firstChild;
for (let i = 0, col = 0; i < row.childCount; i++) {
const { colspan, colwidth } = row.child(i).attrs;
for (let j = 0; j < colspan; j++, col++) {
const hasWidth =
overrideCol == col ? overrideValue : colwidth && colwidth[j];
const cssWidth = hasWidth ? hasWidth + 'px' : '';
totalWidth += hasWidth || cellMinWidth;
if (!hasWidth) fixedWidth = false;
if (!nextDOM) {
colgroup.appendChild(document.createElement('col')).style.width =
cssWidth;
} else {
if (nextDOM.style.width != cssWidth) nextDOM.style.width = cssWidth;
nextDOM = nextDOM.nextSibling as HTMLElement;
}
}
}
while (nextDOM) {
const after = nextDOM.nextSibling;
nextDOM.parentNode.removeChild(nextDOM);
nextDOM = after as HTMLElement;
}
if (fixedWidth) {
table.style.width = totalWidth + 'px';
table.style.minWidth = '';
} else {
table.style.width = '';
table.style.minWidth = totalWidth + 'px';
}
}