No, I don't know if there are js libraries dealing with this. I have pretty much no knowledge at all of those.
But, doing a rudimentary version in js is easy. This one deals with the basics and works decently in FF/Safari. For IE8 you'd need to add code to deal with enlarging cells (since that may very well shrink them presently). Using a framework that give you consistent event objects would alleviate this problem automatically though.
General downsides:
It's annoying that text get's selected as you resize the table.
There is no vertical line indicating how large the cell will become.
But I can't be bothered with trying to improve it beyond this. Feel free to do so yourself if you like though.
<script type="text/javascript">
var resizingTable;
var resizingCol;
function selectTable(event) {
if (event.target)
var et = event.target;
// ie
else {
var et = event.srcElement;
}
resizingTable = null;
resizingCol = null;
if (onBorderOf(event, et)) {
var row = et.parentNode;
for (var i = 0; i < row.childNodes.length && resizingCol == null; ++i){
if (row.childNodes[i] == et) {
resizingCol = i;
resizingTable = et.offsetParent;
}
}
}
}
function onBorderOf(event, o) {
// offset in event target's layer
if (event.layerX) {
var oX = event.layerX;
var oY = event.layerY;
// offset within the cell
var cellOffsetX = oX - o.offsetLeft;
var cellOffsety = oY - o.offsetTop;
}
// ie
else {
var cellOffsetX = event.offsetX;
var cellOffsetY = event.offsetY;
}
var st = getPortableComputedStyle(o, null);
var borderWidth = parseInt(st.borderRightWidth) + parseInt(st.borderLeftWidth);
if (o.clientWidth <= cellOffsetX && cellOffsetX <= (o.clientWidth + borderWidth)) {
return true;
}
}
function resizeTable(event) {
if (resizingTable == null || resizingCol == null)
return;
var d = document;
var rows = resizingTable.getElementsByTagName('tr');
var cell = rows[0].childNodes[resizingCol];
var st = getPortableComputedStyle(cell, null);
var borderWidth = parseInt(st.borderRightWidth) + parseInt(st.borderLeftWidth);
if (event.layerX) {
var oX = event.layerX;
var cellOffsetX = oX - cell.offsetLeft - borderWidth - 5; // why is 5 needed? padding, margin, left, not using border-collapse?
}
else {
var cellOffsetX = event.offsetX - 10; // once again, I've no idea why this would be needed.
}
/* For the strange -5 and -10 above, if you remove them and just mousedown and mouseup without moving the mouse,
the element will grow. In IE it will now shrink if you click the left side of the border and grow if
you click the right side. */
var minWidth = '50';
if (cellOffsetX < minWidth) {
cell.style.width = minWidth + 'px';
width = minWidth;
}
else {
cell.style.width = cellOffsetX + 'px';
width = cellOffsetX;
}
var span = d.createElement('span');
span.style.fontSize = st.fontSize;
span.style.fontFamily = st.fontFamily;
span.style.visibility = 'hidden';
span.style.margin = '0px';
span.style.padding = '0px';
span.style.border = 'none';
var body = d.getElementsByTagName('body');
body[0].appendChild(span);
for (var i = 0; i < rows.length; ++i) {
var cell = rows[i].childNodes[resizingCol];
if (cell.textContent)
var t = cell.textContent;
// ie
else
var t = cell.firstChild.nodeValue;
while(span.childNodes.length > 0)
span.removeChild(span.lastChild);
span.appendChild(d.createTextNode(t));
var len = t.length;
var halfLen = Math.ceil(len/2);
var left = t.substr(0, halfLen);
var right = t.substr(halfLen);
// Remove preexisting ellipsis in the middle
if (left.charAt(left.length - 1) == '\u2026')
left = left.substr(0, left.length - 1);
if (right.charAt(0) == '\u2026')
right = right.substr(1);
while (span.offsetWidth > width) {
if (left.length > right.length) {
var newLen = left.length - 2;
if (newLen < 0)
newLen = 0;
left = left.substr(0, newLen);
}
else {
var newLen = right.length - 2;
if (newLen < 0)
newLen = 0;
right = right.substr(2);
}
span.removeChild(span.lastChild);
span.appendChild(d.createTextNode(left + '\u2026' + right));
}
while(cell.childNodes.length > 0)
cell.removeChild(cell.firstChild);
cell.appendChild(span.firstChild); // this _should_ remove the span from the body element at the same time.
}
/* for certain browsers you may need to cleanup the span element which shouldn't be here (it's been appended in
the cell above. */
// body[0].removeChild[body[0].lastChild];
}
function getPortableComputedStyle(oElm, pseudo){
var strValue = "";
// standard
if (oElm.getPortableComputedStyle)
return oElm.getComputedStyle(pseudo);
// others
if(document.defaultView && document.defaultView.getComputedStyle){
return document.defaultView.getComputedStyle(oElm, pseudo);
}
// ie
else if(oElm.currentStyle){
return oElm.currentStyle;
}
}
</script>
<style type="text/css">
td {
border: 6pt solid;
border-collapse: collapse;
margin: 0px;
padding: 0px;
}
table {
border: 1pt solid red;
margin: 0px;
padding: 0px;
font-family: Helvetica;
font-size: 16px;
}
td {
padding: 3px;
margin: 0px;
}
</style>
</head>
<body>
<div style="position: relative; left: 20px; margin-left: 20px;">
<table onmousedown="selectTable(event);" onmouseup="resizeTable(event);">
<tbody>
<tr>
<td>Lorem</td>
<td>Lorem ipsum</td>
</tr>
<tr>
<td>Lorem ipsum dolor</td>
<td>Lorem ipsum dolor sit</td>
</tr>
<tr>
<td>Lorem ipsum dolor sit amet,</td>
<td>Lorem ipsum dolor sit amet, consectetur </td>
</tr>
</tbody>
</table>
</div>
</body>
</html>