This code really helped me, thanks !
But I noticed a few enhancements to do :
1/ To solves the problem of insufficient width in some cases
Replace :
<td class="preview">Hey bob, got any plans for new years yet?</td>
With :
<td><div class="preview">Hey bob, got any plans for new years yet?</div></td>
2/ The script doens't works well with specific fonts (size, weight, family...)
You need to apply the fonts to your "invisible" span used to compute the text size. For example (to complete if necessary with all needed font properties) :
(...)
// build a bench-mark to gauge it from
var roomWidth = $(this).innerWidth();
// now, get the width and play with it until it fits (if it doesn't)
var fontSize=$(this).css("font-size");
spanTest.css("font-size", fontSize);
var fontStyle=$(this).css("font-style");
spanTest.css("font-style", fontStyle);
var fontWeight=$(this).css("font-weight");
spanTest.css("font-weight", fontWeight);
var fontFamily=$(this).css("font-family");
spanTest.css("font-family", fontFamily);
(...)
3/ Performances
I made a test with 1000 elements, each with 25 extra characters to remove (on Firefox 7)
You script needs near 40s to finish the job.
It seems that the problem is the "display:none" span.
Putting the span outside the window with "position:absolute;top:-100px" leads to better performances : about 11s to process the 1000 elements !
So replace :
var spanTest = $('<span>').css('display','none').attr('id','span-test-tester');
With :
var spanTest = $('<span>').attr('id','span-test-tester').css('position','absolute').css('top','-100px');
To conclude :
Thank you again for this script... It's very usefull !
Here my complete code adaptation, if it can help someone... :
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title> - jsFiddle demo</title>
<script type='text/javascript' src='http://code.jquery.com/jquery-1.4.4.min.js'></script>
<link rel="stylesheet" type="text/css" href="/css/normalize.css">
<link rel="stylesheet" type="text/css" href="/css/result-light.css">
<style type='text/css'>
.preview {
}
.backg{
background:red;
margin: 20px 0;
border:1px solid blue;
width:200px;
padding:10px;
font-size:14px; // change it to test with other fonts
font-weight:bold;
}
</style>
<script type='text/javascript'>
//<![CDATA[
$(window).load(function(){
truncate();
});
function truncate(){
// Create a span we can use just to test the widths of strings
var spanTest = $('<span>').attr('id','span-test-tester').css('position','absolute').css('top','-100px');
$('body').append(spanTest);
// function to get the length of a string
function getLength(txt){
return spanTest.text(txt).width();
}
var nb =0;
// now make all the previews fit
$('.preview').each(function(){
nb++;
// Get the current font and apply it to hidden span tester
var fontSize=$(this).css("font-size");
spanTest.css("font-size", fontSize);
var fontStyle=$(this).css("font-style");
spanTest.css("font-style", fontStyle);
var fontWeight=$(this).css("font-weight");
spanTest.css("font-weight", fontWeight);
var fontFamily=$(this).css("font-family");
spanTest.css("font-family", fontFamily);
// build a bench-mark to gauge it from
var roomWidth = $(this).innerWidth();
// now, get the width and play with it until it fits (if it doesn't)
var txt = $(this).text();
var contentsWidth = getLength(txt);
if (contentsWidth > roomWidth){ // bigger than we have to work with
roomWidth -= getLength('...'); // work within confines of room + the ellipsis
while (contentsWidth > roomWidth){
txt = txt.substring(0,txt.length-1);
contentsWidth = getLength(txt);
}
// set the text to this
$(this).text(txt).append($('<span>').text('...'));
}
});
}
//]]>
</script>
</head>
<body>
<div class="backg"><div class="preview">abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ</div></div>
(... repeat 1000 times ...)
<div class="backg"><div class="preview">abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ</div></div>
</body>
</html>
Bye !
DIVwouldn't be a good solution as it inherits the parent's width by default, not allowing it to "grow" with the content. You'd be better of with aSPAN. case in pointvar d = $('<div>');/*$('body').append(d);*/d.text('Hello,World!');var w1 = d.width();d.text('Longer string goes here');var w2 = d.width();alert('Short: '+w1+'\nLong: '+w2);(comment and un-comment the append statement [uses jQuery for simplicity])