Ask a Jedi: Best way to trim text

Sal asks:

just curious what's the best way (or how you handle) to truncate a paragraph to only show say perhaps 500 chars.? I have a newsletter that I'm emailing out, and I only wanna show 500 chars. of each article in the email.

Ah, I love it when folks ask me the “best” way to do things since no matter what I say, I’m not wrong (grin). Seriously though - here are multiple ways to trim text. Let’s first start off with a block of text that we will use for our tests:


<cfsavecontent variable="quote">
The Constitution is not an instrument for the government to restrain the people, it is an instrument for the people to restrain the government -- lest it come to dominate our lives and interests. Patrick Henry.
</cfsavecontent>

So the quickest way to trim text is with left:


<cfoutput>#left(quote,100)#</cfoutput>

However if you use this on the text, you get:

The Constitution is not an instrument for the government to restrain the people, it is an instrumen

As you can see, the last word in the trimmed text, instrument, was cut off before the final t. This isn’t a horrible thing of course, but it could be done better. ColdFusion does ship with a Wrap function, but that won’t crop the text, it will simply break the text into lines of a certain length. It will break the text nicely though, so why not use list functions?


<cfoutput>#listFirst(wrap(quote,100),chr(10))#</cfoutput>

This returns a nicer trim:

The Constitution is not an instrument for the government to restrain the people, it is an

This works nicely, but I kinda feel ‘dirty’ doing it like this, so why not see if a UDF exists for this? Turns out one does: FullLeft. This UDF lets me do this instead:


<cfoutput>#fullleft(quote,100)#</cfoutput>

In theory it’s doing a lot less work than wrap so it should be quicker.

Ok, so we’re done, right? Well, what if we modify the quote a bit:


<cfsavecontent variable="quote">
The <a href="http://www.raymondcamden.com">Constitution</a> is <b>not</b> an instrument for the government to restrain the people, it is an instrument for the people to restrain the government -- lest it come to dominate our lives and interests. Patrick Henry.
</cfsavecontent>

As you can see I’ve added some HTML to the text. This HTML messes up my count. If I wanted to show 100 characters, I don’t think I’d want HTML to count at all. In fact, I probably don’t want to show HTML at all. I can fix that easily enough:


<cfset quote = rereplace(quote, "<.*?>", "", "all")>

Another issue is space. Now this is a contrived example, but it could happen in a live system:


<cfsavecontent variable="quote">
The <a href="http://www.coldfusionjedi.com">Constitution</a> is <b>not</b> 










an 
instrument for the government to restrain the people, it is an instrument for 
the people to restrain the government -- lest it come to dominate our lives and interests. 

Patrick Henry.
</cfsavecontent>

You can use another regex to handle this:


<cfset quote = rereplace(quote, "[[:space:]]+", " ", "all")>

Or conversely, if you use the wrap() function, it takes a 3rd argument to strip out existing line breaks and carriage returns.

Lastly - it sometimes helps to visually flag text that has been trimmed. Normally this is done with a “…”. You can mimic this affect like so:


<cfif len(quote) gt 100>
	<cfset trimmedQuote = fullLeft(quote, 100)>
	<cfset trimmedQuote &= "...">
<cfelse>
	<cfset trimmedQuote = quote>
</cfif>
<cfoutput>#trimmedQuote#</cfoutput>

I just check the length of the original quote and conditionally perform a trim and add the “…”.

Raymond Camden's Picture

About Raymond Camden

Raymond is a developer advocate. He focuses on JavaScript, serverless and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support.

Lafayette, LA https://www.raymondcamden.com

Comments