Truncating Text with JavaScript
Since Alex posted an article on truncating text with Prototype, I thought I would write an article on truncating text without the help of a JavaScript framework.
I won't define a class like in his example, but I will try to provide the same functionality, and perhaps add some functionality as well. This code will search for all HTML elements with the class 'truncate', or with another className if one is specified, and will truncate to the nearest word less than the character-count you specify. It also defaults to appending '...' (the ellipsis) but you can override this with an empty string as the third optional parameter, if you prefer not to have anything appended.
Note: I wrote in the comments on Alex's article that you may want to add ellipsis to his code. I realized after reading the Prototype API docs that in fact, this is exactly what it does by default. Unless you specify an override with an optional parameter, the Prototype truncate() method will automatically add an ellipsis at the end of the string it returns.
Here is my implementation of the truncate() function, without the use of JavaScript libraries:
// Input parameters:
// String text, [Number length, String ellipsis]
//
// Returns:
// String text
function truncate(text, length, ellipsis) {
// Set length and ellipsis to defaults if not defined
if (typeof length == 'undefined') var length = 100;
if (typeof ellipsis == 'undefined') var ellipsis = '...';
// Return if the text is already lower than the cutoff
if (text.length < length) return text;
// Otherwise, check if the last character is a space.
// If not, keep counting down from the last character
// until we find a character that is a space
for (var i = length-1; text.charAt(i) != ' '; i--) {
length--;
}
// The for() loop ends when it finds a space, and the length var
// has been updated so it doesn't cut in the middle of a word.
return text.substr(0, length) + ellipsis;
}
Truncating Text by Class Name
In Alex's example, he wrote a class in Prototype that you initialize with an array of HTML elements. For this example, we'll register an event handler to the window onload that will look for all elements with the class 'truncate' and truncate them to our specifications.
window.onload = function() {
var elements = document.getElementsByClassName('truncate');
for (var i = 0; i < elements.length; i++) {
elements[i].innerHTML = truncate(elements[i].innerHTML, 100);
}
}
It's basically doing the same thing as in Alex's example, except that I'm using the window.onload event instead of the custom 'domready' event (called dom:loaded in Prototype) which triggers much quicker. If you are using a framework, then use one of the custom 'domready' events because they trigger as soon as the DOM is accessible for manipulation, whereas the traditional window.onload event waits to fire until each and every image is finished downloading. Good grief!
Note that this example will only work in Firefox 3 or Safari 3, as other browsers do not natively support document.getElementsByClassName. You could just implement your own getElementsByClassName function like so:
function getElementsByClassName(className) {
// RegExp from http://www.robertnyman.com
// /2005/11/07/the-ultimate-getelementsbyclassname/
var match = new RegExp('(^|\\\\s)' + className + '(\\\\s|$)');
// All elements which match are added to the array
var matchingTags = new Array();
var allTags = document.getElementsByTagName('*');
for (var i = 0; i < allTags.length; i++) {
if (match.test(allTags[i].className)) {
matchingTags.push(allTags[i]);
}
}
return matchingTags;
}
window.onload = function() {
var elements = getElementsByClassName('truncate');
for (var i = 0; i < elements.length; i++) {
elements[i].innerHTML = truncate(elements[i].innerHTML, 100);
}
}
Make sure that you only give the 'truncate' class to elements whose only child is a text node. If the element has other HTML children then this won't work correctly. It's possible to code around this but for the sake of this example, let's just keep it simple. Here are two examples that show proper and improper use:
This is OK:
<span class="truncate">some text </span>
This is not OK:
<span class="truncate"><span>some text </span></span>
As always, feel free to post in the comments with any questions or alternative suggestions for the code. This is a fairly simplistic implementation and truth be told, if you're using a JavaScript library (which it seems most people are these days) then this may not be too relevant for you. But, hopefully it has been informative to explore this library-free, albeit simple, implementation.
Since Alex posted an article on truncating text with Prototype, I thought I would write an article on truncating text without the help of a JavaScript framework.
I won't define a class like in his example, but I will try to provide the same functionality, and perhaps add some functionality as well. This code will search for all HTML elements with the class 'truncate', or with another className if one is specified, and will truncate to the nearest word less than the character-count you specify. It also defaults to appending '...' (the ellipsis) but you can override this with an empty string as the third optional parameter, if you prefer not to have anything appended.
Note: I wrote in the comments on Alex's article that you may want to add ellipsis to his code. I realized after reading the Prototype API docs that in fact, this is exactly what it does by default. Unless you specify an override with an optional parameter, the Prototype truncate() method will automatically add an ellipsis at the end of the string it returns.
Here is my implementation of the truncate() function, without the use of JavaScript libraries:
// Input parameters: // String text, [Number length, String ellipsis] // // Returns: // String text function truncate(text, length, ellipsis) { // Set length and ellipsis to defaults if not defined if (typeof length == 'undefined') var length = 100; if (typeof ellipsis == 'undefined') var ellipsis = '...'; // Return if the text is already lower than the cutoff if (text.length < length) return text; // Otherwise, check if the last character is a space. // If not, keep counting down from the last character // until we find a character that is a space for (var i = length-1; text.charAt(i) != ' '; i--) { length--; } // The for() loop ends when it finds a space, and the length var // has been updated so it doesn't cut in the middle of a word. return text.substr(0, length) + ellipsis; }
Truncating Text by Class Name
In Alex's example, he wrote a class in Prototype that you initialize with an array of HTML elements. For this example, we'll register an event handler to the window onload that will look for all elements with the class 'truncate' and truncate them to our specifications.
window.onload = function() { var elements = document.getElementsByClassName('truncate'); for (var i = 0; i < elements.length; i++) { elements[i].innerHTML = truncate(elements[i].innerHTML, 100); } }
It's basically doing the same thing as in Alex's example, except that I'm using the window.onload event instead of the custom 'domready' event (called dom:loaded in Prototype) which triggers much quicker. If you are using a framework, then use one of the custom 'domready' events because they trigger as soon as the DOM is accessible for manipulation, whereas the traditional window.onload event waits to fire until each and every image is finished downloading. Good grief!
Note that this example will only work in Firefox 3 or Safari 3, as other browsers do not natively support document.getElementsByClassName. You could just implement your own getElementsByClassName function like so:
function getElementsByClassName(className) { // RegExp from http://www.robertnyman.com // /2005/11/07/the-ultimate-getelementsbyclassname/ var match = new RegExp('(^|\\\\s)' + className + '(\\\\s|$)'); // All elements which match are added to the array var matchingTags = new Array(); var allTags = document.getElementsByTagName('*'); for (var i = 0; i < allTags.length; i++) { if (match.test(allTags[i].className)) { matchingTags.push(allTags[i]); } } return matchingTags; } window.onload = function() { var elements = getElementsByClassName('truncate'); for (var i = 0; i < elements.length; i++) { elements[i].innerHTML = truncate(elements[i].innerHTML, 100); } }
Make sure that you only give the 'truncate' class to elements whose only child is a text node. If the element has other HTML children then this won't work correctly. It's possible to code around this but for the sake of this example, let's just keep it simple. Here are two examples that show proper and improper use:
This is OK:
<span class="truncate">some text </span>
This is not OK:
<span class="truncate"><span>some text </span></span>
As always, feel free to post in the comments with any questions or alternative suggestions for the code. This is a fairly simplistic implementation and truth be told, if you're using a JavaScript library (which it seems most people are these days) then this may not be too relevant for you. But, hopefully it has been informative to explore this library-free, albeit simple, implementation.
1 Comments:
Great article. Thanks. What would be sweet to have is an option to customize where the truncation occurs. For example, when you are showing filenames, you want center truncation and not necessarily tail truncation, which would make it quite useless actually.
Post a Comment
Subscribe to Post Comments [Atom]
<< Home