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
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';
|
|
}
|
|
}
|