JSFiddle - React, Tailwind, and code Playground
by Malleys
HTML
<button onclick="document.querySelector('table').merge();">Merge</button>
<!-- <button onclick="document.querySelector('table').split();">Split</button> -->
<div id="tableEditor"></div>
CSS
table {
height: 500px;
width: 500px;
border-collapse: collapse;
position: relative;
user-select: none;
cursor: default;
table-layout: fixed;
font: 1em Helvetica Neue, Segoe UI, Roboto, Ubuntu, sans-serif;
}
td {
border: 1px gray solid;
}
td:focus {
box-shadow: inset 0 0 0 2px rgba(111, 168, 220, 0.66);
outline: 0;
}
JavaScript
class Box {
constructor(x = 0, y = 0, width = 0, height = 0) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
contains({ x, y, width, height }) {
return (
x > this.x &&
y > this.y &&
(x + width) < (this.x + this.width) &&
(y + height) < (this.y + this.height)
);
}
overlaps({ x, y, width, height }) {
return (
1.0001 * Math.max(x, this.x) < 0.9998 * Math.min(x + width, this.x + this.width) &&
1.0001 * Math.max(y, this.y) < 0.9998 * Math.min(y + height, this.y + this.height)
);
}
equals({ x, y, width, height }) {
return (
x === this.x &&
y === this.y &&
width === this.width &&
height === this.height
);
}
add({ x, y, width, height }) {
return new Box(
Math.min(x, this.x),
Math.min(y, this.y),
Math.max(x + width, this.x + this.width) - Math.min(x, this.x),
Math.max(y + height, this.y + this.height) - Math.min(y, this.y)
);
}
intersection({ x, y, width, height }) {
return new Box(
Math.max(x, this.x),
Math.max(y, this.y),
Math.min(x + width, this.x + this.width) - Math.max(x, this.x),
Math.min(y + height, this.y + this.height) - Math.max(y, this.y)
);
}
relativeTo({ x, y }) {
return new Box(
this.x - x,
this.y - y,
this.width,
this.height
);
}
relativeToElement(element) {
return this.relativeTo(element.getBoundingClientRect());
}
static from({ x = 0, y = 0, width = 0, height = 0 } = {}) {
return new Box(x, y, width, height);
}
}
class EditableTable extends HTMLTableElement {
constructor() {
super();
const document = this.ownerDocument;
this.selectionElement = document.createElement("div");
this.selectionElement2 = document.createElement("div");
this.selectionElement.style.cssText = `
position: absolute;
background: rgba(111, 168, 220, 0.66);
pointer-events: none;
`;
this.selectionElement2.style.cssText = `
position: absolute;
outline: 1px dashed rgba(0, 0, 0, 0.5);
pointer-events:...