Shortening a string by removing text in the middle

This post is more than 2 years old.

That as to be most exciting blog title ever. If you are still reading this, I congratulate you. While checking my email on my phone yesterday, I took note of how GMail will shorted labels in the top level display. Instead of using the full label, which wouldn't fit, they include part of the left side of the string and part of the right side of the string. So for example, a label, "Important Stuff / From People Who Think They Are Important" would be shorted to something like, "Important Stuff...They Are Important." Most of the time the shortening is very understandable.

Being bored, I thought I'd write up a quick ColdFusion version of this logic. Here's the UDF I came up with:

function shrink(str) { var maxstr = 25; if(arrayLen(arguments) >= 2) maxstr = arguments[2]; str = trim(str);

if(len(str) <= maxstr) return str;

var side = int((maxstr-3)/2);

return trim(left(str, side)) & "..." & trim(right(str, side));

}

The logic is simple. The UDF assumes a max size of 25 for the output, but you can override that by passing in a second argument. The input is trimmed for any extraneous white space and if it is smaller than our max size, we return it as is.

My result string should be a slice from the left and right side of the strings with ... in the middle. So I simply did a bit of math. I take my max size, minus 3, and divide by 2. The int function simply rounds down the values.

The final part then is to simply use left, right, and strict concatenation. Here's my test template:

<cfscript> function shrink(str) { var maxstr = 25; if(arrayLen(arguments) >= 2) maxstr = arguments[2]; str = trim(str);

if(len(str) &lt;= maxstr) return str;

var side = int((maxstr-3)/2);

return trim(left(str, side)) & "..." & trim(right(str, side));

} </cfscript>

<cfset tests = [ "This is my first input string and it has some words.", "This is a short string.", "This one has some more words in it." ]>

<cfloop index="s" array="#tests#"> <cfoutput> <p> input=#s#<br/> output=#shrink(s)#<br/> output(20)=#shrink(s,20)#<br/> output(40)=#shrink(s,40)#<br/> </p> </cfoutput> </cfloop>

And the results...

input=This is my first input string and it has some words. output=This is my...some words. output(20)=This is...e words. output(40)=This is my first i...it has some words.

input=This is a short string. output=This is a short string. output(20)=This is...string. output(40)=This is a short string.

input=This one has some more words in it. output=This one ha...ords in it. output(20)=This one...s in it. output(40)=This one has some more words in it.

Raymond Camden's Picture

About Raymond Camden

Raymond is a senior developer evangelist for Adobe. He focuses on document services, JavaScript, and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support. You can even buy me a coffee!

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

Archived Comments

Comment 1 by Duncan Nisbett posted on 2/15/2012 at 12:59 AM

Ray, this blog inspired me to create a JavaScript version of your function. It was a fun little exercise. Thanks for the post!

function shrinkText(iStr, iLen){
if(!iLen){
var vMaxStr = 50;
} else {
var vMaxStr = iLen;
}
var vStr = iStr.trim();

if(vStr.length <= vMaxStr){
return vStr;
}

var side = Math.round((vMaxStr-3)/2)-1;

return vStr.substr(0,side)+'...'+vStr.substr(vStr.length-side,vStr.length);
};

Comment 2 by Raymond Camden posted on 2/15/2012 at 1:09 AM

Is trim part of JavaScript? I didn't think it was standard yet?

Comment 3 by Duncan Nisbett posted on 2/15/2012 at 1:18 AM

A quick bit of research that there will most likely be problems in IE. When I tested it out, I ran it in Firefox 10.0.1. Looks like I'll still be using $.trim() in my applications for a while yet.

Comment 4 by Lana posted on 4/29/2013 at 3:36 PM

Hi Ray :) While writing my new script, been looking for such snippet in Perl. So I converted this one to Perl. Here is it in case somebody need it.

sub trim {
my $string = shift;
$string =~ s/^\s+//g;
$string =~ s/\s+$//g;
return $string;
} ## end sub trim

sub shrink_anchor {
my $string = shift;
my $maxlength = shift;
my $separator = shift;

if ( length($string) <= $maxlength ) {
return $string;
} else {
my $side = int( ( $maxlength - length($separator) ) / 2 );
$string = trim( substr( $string, 0, $side ) ) . $separator . trim( substr( $string, length($string) - $side, length($string) ) );
}

return $string;
} ## end sub shrink_anchor

#usage:
$str = "While checking my email on my phone yesterday, I took note of how GMail will shorted labels in the top level display.";
print shrink_anchor($str, 50, '...');
While checking my email...the top level display.

Comment 5 by Raymond Camden posted on 4/29/2013 at 6:08 PM

Nice. I began my 'web app' career doing Perl CGI scripts.