views:

2705

answers:

5

I'm trying to set a column width of a table, which works fine until it gets to the point where child elements would be visually truncated ... then it won't size any smaller. ("visually truncated"-what doesn't fit appears to be hidden behind the next column)

Here is some sample code to demonstrate my problem:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
<html>
<head>
<script language="javascript" type="text/javascript">
    var intervalID = null;

    function btn_onClick()
    {
     // keep it simple, only click once
     var btn = document.getElementById("btn");
     btn.disabled = true;     
     // start shrinking
     intervalID = window.setInterval( "shrinkLeftCell();", 100);
    }

    function shrinkLeftCell()
    {
     // get elements
     var td1 = document.getElementById("td1");
     var td2 = document.getElementById("td2");

     // initialize for first pass
     if( "undefined" == typeof( td1.originalWidth))
     {
      td1.originalWidth = td1.offsetWidth;
      td1.currentShrinkCount = td1.offsetWidth;
     }

     // shrink and set width size
     td1.currentShrinkCount--;
     td1.width = td1.currentShrinkCount;  // does nothing if truncating!

     // set reporting values in right cell
     td2.innerHTML = "Desired Width : [" 
        + td1.currentShrinkCount 
        + "], Actual : [" 
        + td1.offsetWidth + "]";

     // Stop shrinking
     if( 1 >= td1.currentShrinkCount)
      window.clearInterval(intervalID);
    }
</script>
</head>
<body>
    <table width="100%" border="1">
     <tr>
      <td id="td1">
       Extra_long_filler_text
      </td>
      <td id="td2">
       Desired Width : [----], Actual : [----]
      </td>
     </tr>
    </table>

    <button id="btn" onclick="btn_onClick();">Start</button>
</body>
</html>

I've tried setting the width in different ways including

td1.offsetWidth = td1.currentShrinkCount;

and

td1.width = td1.currentShrinkCount + "px";

and

td1.style.width = td1.currentShrinkCount + "px";

and

td1.style.posWidth = td1.currentShrinkCount;

and

td1.scrollWidth = td1.currentShrinkCount;

and

td1.style.overflow = "hidden";
td1.width = td1.currentShrinkCount;

and

td1.style.overflow = "scroll";
td1.width = td1.currentShrinkCount;

and

td1.style.overflow = "auto";
td1.width = td1.currentShrinkCount;

I realize, I could probably use DIV's, but I'd prefer not to since the table is being generated from a bound control, and I don't really want to get into rewriting asp.net controls.

Having said that, I thought as a last ditch effort, I could at least wrap each 'td1's contents with a DIV, and the overflow would take care of things, but even replacing

<td id="td1">
    Extra_long_filler_text
</td>

with

<td id="td1" style="overflow:hidden;">
    <div style="margin=0;padding:0;overflow:hidden;">
     Extra_long_filler_text
    </div>
</td>

didn't work.

Does anybody know how I can set a width to visually truncate its contents?

BTW-My target browser is IE7. Other browsers are not important right now, since this is an internal app.

+1  A: 
<td id="td1" style="overflow-x:hidden;">

Should be

<td id="td1" style="overflow:hidden;">

overflow-x is a Microsoft CSS attribute, which is now part of CSS3. I would stick with the older overflow attribute.

EDIT:

As Paolo mentions you also need to add table-layout:fixed; and specify the width of the table. A full example follows.

<html>
<head>
<style>
    table
    {

        table-layout:fixed;
        width:100px;
        }
td
{
    overflow:hidden;
    width:50px;
    border-bottom: solid thin;
    border-top:solid thin;
    border-right:solid thin;
    border-left:solid thin;

}
</style>
</head>
<body>
<table>
<tr><td>Some_long_content</td><td>Short</td></tr>
</table>
</body>
</html>
Darryl Braaten
It should be noted that this won't "truncate" the contents. It will merely hide the overflow.
Jonathan Sampson
Thanks Darryl, but this didn't work.
John MacIntyre
It probably didn't work because it's CSS3, which isn't supported by most browsers yet.
Kibbee
+1  A: 

CSS Solution

"Truncate" may not be the word you are looking for. You may just want to hide the overflowing characters. If that is the case, look into the css-property "overflow," which will hide any content extending past the declared limits of its container.

td div.masker {
  height:25px;
  width:100px;
  overflow:hidden;
}

    <td>
      <div class="masker">
        This is a string of sample text that
        should be hidden when it reaches out of the bounds of the parent controller.
      </div>
    </td>

Javascript Solution

If you are indeed wanting to truncate the text within the container, you will have to remove one character from the right, test the width of the parent, and continue to remove characters and testing the parent width until the parent width matches the declared width.

while (parent.width > desiredWidth) {
  remove one char from right-side of child-text
}
Jonathan Sampson
Thanks Jonathan, You're right, the wording was wrong. It won't always be text ... I want to be able to do this with whatever is in the cell. it could be actual input controls. ... But then again, I suppose, I don't necessarilly want to do this with input controls do I? ... Let me ponder this. +1
John MacIntyre
Oh yeah ... the overflow style isn't working for me at all.
John MacIntyre
+1  A: 

As far as I know, a table cell will always stretch to accommodate its contents.

Have you thought about using Javascript to dynamically truncate the data in table cells that have more than a certain amount of content? Alternatively, you could do this more easily server side.

Robert Venables
Well, this is part of a table column sizing routine, so it can't be done server side. And I won't always know what is in the cell, so it's not as simple as removing text when it stops shrinking. thx though.
John MacIntyre
A: 

You could use jQuery or plain javascript to surround the content of your cell(s) with div tags and set a fixed width and overflow:hidden on those instead. Not beautiful, but it'd work.

ETA:

<td><div style="width:30px;overflow:hidden">Text goes here</div></td>

Since the DIV is the bounding element, that's where the width should be set.

Hank
+6  A: 

I just tried adding table-layout: fixed; to the <table> and it worked for me on IE7.

In a fixed table layout, the horizontal layout only depends on the table's width, the width of the columns, and not the content of the cells

Check out the documentation.

Paolo Bergantino
YOU DA MAN Paolo!!! That worked great. Thanks a lot.
John MacIntyre