Truncate text on full words only - a simple version of "full left"
Common scenario: you want to show the first part of a long chunk of text, and then have the full text available via a link like " (more...) " , which would either show the text with javascript (more on that later) or take you to another page to see the full article.
For a long time now I have used the "fullLeft()" udf, which works just fine and does exactly what it should. But the other day, I got a wild hair and, rather than calling in the fullLeft function to my page, decided to script something right in place... just 'because'.
And whaddyaknow, it works... works great, really.
But it is so simple - what am I missing?
Like most things, my 'aha' is haunted by a 'what if', as in 'what if it breaks on certain characters or other stuff in the text'? What if I don't really know what the heck I am doing? But ...hey... it works!
//// Here is the logic:
take a chunk of text and a number, passed in as variables.
replace all line breaks in the text with <br> tags (easy to remove if not needed)
if the length of the text is more than the given number, cut it off at that
number of characters
find the number of characters at the end of the remaining string that come after the last space ( ' '), and remove them
if the text was trimmed, output the text in a p tag with a (more...) link - this can all be modified to give the link a url, or in my case to use javascript to show the full text in place of the truncated content.
/// Here is the code:
<cfscript>
/**
* Another version of "full left"
*
* @param trimlength Length, in characters, to trim text to (Required)
* @param rawtext Text to trim (Required)
* @return Returns a string with an ellipsis (...)
* @author Michael Evangelista (mredesign.com)
* @created June 6, 2008
Usage:
<cfinclude template="func/trimtext.cfm">
<cfoutput>#trimtext(recordbody, 160)#</cfoutput>
*/
function trimtext(rawtext, trimlength)
{
// this line replaced line returns in the text block with html breaks
rawtext = replace(rawtext, chr(13), '<br />', 'all');
if (len(rawtext) gt trimlength)
{
cuttext = left(rawtext, trimlength);
trimlen = len(cuttext) - len(listLast(cutText, ' '));
texttouse = left(rawtext, trimlen) & '... <em>(<a class="morelink" href="##">more</a>)</em>';
}
else
{
texttouse = rawtext;
}
textoutput = '<p>' & texttouse & '</p>';
return textoutput;
}
</cfscript>
Feedback and/or testing appreciated.
thanks


Why the need for the <br> replacement tags - save space?
(example uses 'recordbody' as variable name, and the file is in a folder called 'func')
<cfinclude template="func/trimtext.cfm">
<cfoutput>#trimtext(recordbody, 160)#</cfoutput>
as for the <br> tags, that was just my own need at the time, since the line returns in a text area, saved to a database, don't usually return as visual line breaks in the browser. So I am replacing the stored character for a line return with an html line break.
Can I make a suggestion though? Remove all of the HTML specific stuff, but make your function HTML aware (in terms of not breaking markup by cutting in the middle of links, etc). Then create a separate ConvertTextToHtml() function if you need it.
The above is just for re-usability, because it would hardcode fewer assumptions into your usage of the function. Will you remember a month down the track that the function replaces the new lines with BR tags? What if a later requirement Requires you to wrap paragraphs more progressively with P tags? What if you continue to come up with further text to html replacements that you need (for example > and special symbols).
Keeping 2 separate functions focussed on their specific jobs means you would always have the option. Depending on the requirement you then call trimText(convertTextToHtml(myString)) OR convertTextToHtml(trimText(myString)) OR either on their own.
Similarly, the format and needs of your specific 'more' link will change from project to project (as you mention), so you may as well pass that into the function like: trimText(myText,1000, myMoreHtml). You function could then determine the length of the 'more' html and adjust to compensate.
Of course if you didn't mind about re-use and maintenance, none of this applies. If so the only obviously oversight is protecting HTML markup (but check out Ray's blog posts).