
This tutorial will demonstrate how to add ellipsis (...) to text when it exceeds a desired length using Javascript.
Microsoft was nice enough to invent the CSS tag, textOverflow:ellipsis, for Internet Explorer, but unfortunately this doesn't exist on other browsers. What I'm going to do is create a Javascript function that will automatically add ellipsis to a string when its length exceeds a certain width in pixels. This function should work on most current browsers.
Let's start by defining the signature for this function.
function autoEllipseText(element, text, width)
This function takes three arguments: the element the text will be added
to, the text to truncate, and the desired width in pixels. The reason
there needs to be an element is because Javascript has no way to tell us
the text's width in pixels. We have to modify the DOM and have the
browser tell us what the width is. Using the browser also takes care of
any font size changes your users may have made to their browser. This
function will return a truncated string with a set of ellipsis. If the
string's width is already less than width, the function will return
the original text.
The first thing we're going to do is add a span to the element passed in. We're going to use the span to tell us how wide the text is.
function autoEllipseText(element, text, width)
{
element.innerHTML = '<span id="ellipsisSpan";
style="white-space:nowrap;">' + text + '</span>';
}
We added a span with the id "ellipsisSpan" to the element passed in to the function. You'll want to make sure there isn't anything in the element before it's passed to this function, because this call will remove it. We added a white-space:nowrap style to the span to make sure the text doesn't wrap to a new line.
Now we can start removing characters from the text to make it fits in the desired width.
function autoEllipseText(element, text, width)
{
element.innerHTML = '<span id="ellipsisSpan"
style="white-space:nowrap;">' + text + '</span>';
inSpan = document.getElementById('ellipsisSpan');
if(inSpan.offsetWidth > width)
{
var i = 1;
inSpan.innerHTML = '';
while(inSpan.offsetWidth < (width) && i < text.length)
{
inSpan.innerHTML = text.substr(0,i) + '...';
i++;
}
returnText = inSpan.innerHTML;
element.innerHTML = '';
return returnText;
}
return text;
}
The first thing this section of code does it to get the span element we
just created by calling document.getElementById(). It then compares the
span's offsetWidth to the desired width to see if the text needs to be
truncated. The while loop builds the text up character by character
until it exceeds the desired width. Once this happens, the function
removes the added span element and returns the new text. For the sake of
simplicity, I've done a simple loop adding characters one at a time.
This isn't very efficient for long input strings. For a more efficient
implementation, replace that loop with a O(log(n)) algorithm such as a
binary search. That will greatly reduce the number of comparisons needed
to build the output string.
If you wanted, you could remove the line that resets the element's innerHTML and the new text would already be added to passed in element. I clear the element because someone might want to do something else with the text.
Below is an example using the code above. This is a table with one cell which is 90 pixels wide. When the button is pressed, the cell's text will be set to whatever was typed in the text box. Whenever something is typed that is longer than 80 pixels, the function will add ellipsis to guarantee that it fits. I made it 80 pixels to make room for the borders and any default padding. This example only works for text with no html markup. For a more robust implementation, you may want to escape any special characters that are passed into the autoEllipseText() function.
Here's all the finished code to produce the above controls.
function setCellText()
{
cellElement = document.getElementById('textCell');
textBoxElement = document.getElementById('cellText');
cellElement.innerHTML =
autoEllipseText(cellElement, textBoxElement.value, 80);
}
<table border="1">
<tr>
<td id="textCell" width="90px">Text</td>
</tr>
</table>
<input type="text" id="cellText"></input>
<input type="button" onclick="setCellText();" value="Update Text" ></input>
I added a helper function, setCellText(), which is called when the button is clicked. This function sets the cell's innerHTML to the output of a call to autoEllipseText().
That's all that's required to automatically add ellipsis to text using Javascript. If you'd like to see this code in action, our site Gaming Textures uses auto ellipsis to limit the amount of text displayed on the search tabs.
Source Files:
so if i am not mistaken,
we are losing that "longer than expected" part of the text.
is there any way that the user can reach the full text, in case it is needed?
A common solution is to provide the full text in a tooltip. To put text in a tooltip use the following syntax:
The title attribute of the span element is what holds the tooltip's text. So in the function
autoEllipseText(), change the linereturn returnText;to:Now when a user mouses over the truncated text, the full text will appear in a tooltip. Thanks for the question!
This is assuming your website targets en-us only. In other languages/cultures, if you start trimming off random chars then you might change the meaning of the word and the way it gets rendered. This is why the platform normally provides API to do the ellipsis work...
This code is great!! I've been looking for something like this off and on for months!
very interesting but if it's not too much trouble then I want some help with this case I have which is that I have a textbox that I set it's width to 200px and in firefox it scrolls left when the lines exceeds it's limit so my question is how can I stop the textbox from scrolling left and force the text to wrap?
Best Regards.
How can I call the function "setCellText" without using a button?
http://www.godheval.net/5.0/
And if I'm using IDs, does that mean I can only do it once, and not on all of my module content - see right side of page.
funny stuff. i’ve been looking at a few other proposed methods and your function seems to deal with all the major concerns quite well… but now you get new questions like “what about other languages?”
nice job.
this is pretty awesome. The only issue is i would like the limited text to run across 2 lines. This is awesome for 1 line of text. wish i could wrap it then truncate :\
if there is no ID or Class in HTML file,or we can't modify it,but there is have a "li" element.how can i edit the code?
I am not a programmer, so there is a problem need your help. Here, how this can be achieved it? thanks in advance!!
[language]
[/language]
great! thanks a lot for that
Awesome!
Hi, thanks for this it is perfect!
I've customised this so that it is a now a jQuery plugin - let me know if that will be of any use to anyone!?! :D
Neat! I don't want to belittle your efforts, but was there something that the actual jQuery tabs didn't offer that made you convert this into a plugin?
Edit: whoops, I thought this was our tabs tutorial. Never mind. Great effort!
Haha no worries! Yeah, yours was the best auto ellipse script I found and just need converting for jQuery so I could easily add it to all H3 tags for example (as well as the fact I was already using the jQuery library all over the place).
\$("h3").autoEllipse(vars);
Like I said, if you want the code just let me know where to send it to :)
Cheers Ross
If you don't mind, I'd really like to publish your source in a new post. Zip it up and email it to support@switchonthecode.com. If you've got a website or something, put that in there so we can attribute you correctly!
hi The Reddest,
Your implementation works for a separate textbox or input field. It is not applicable when applied on the same textbox.The same textbox returns "htmlfile: Unknown runtime error" when you try to assign an html that includes the span.
So Ross' update using jQuery should probably work.
See above :)
Great works like a charm......
Great !!! There's something wrong in the code though.
When you exit the "while" with "inSpan.offsetWidth > width", you're already one character too far.