Reputation: 19831
anyone have a handy method to truncate a string in the middle? Something like:
truncate ('abcdefghi', 8);
would result in
'abc...hi'
UPDATE:
to be a bit more complete
Upvotes: 21
Views: 19190
Reputation: 93203
function truncateString(str, maxLength) {
if (str.length <= maxLength) {
return str;
}
var ellipsis = '...';
var truncatedLength = maxLength - ellipsis.length;
var leftLength = Math.ceil(truncatedLength / 2);
var rightLength = Math.floor(truncatedLength / 2);
var leftSubstring = str.substring(0, leftLength);
var rightSubstring = str.substring(str.length - rightLength);
return leftSubstring + ellipsis + rightSubstring;
}
EXPLAINED:
The truncateString function takes two parameters: str, which is the original string to be truncated, and maxLength, which is the maximum length of the truncated string (including the ellipsis). If the length of the original string is less than or equal to the maxLength, the function simply returns the original string.
If the length of the original string is greater than the maxLength, the function calculates the lengths of the left and right substrings to be included in the truncated string. The lengths are calculated to be roughly equal, with the left substring potentially having one extra character if the truncatedLength is an odd number.
The function then uses the substring method to extract the appropriate substrings from the original string, and concatenates them with the ellipsis in the middle.
Finally, the truncated string is returned.
Upvotes: 1
Reputation: 662
I personally found this approach to be nice and easy to use.
export function truncate(str: string, maxLength: number, location = 'middle') {
if (str.length <= maxLength) {
return str;
}
let partLength = Math.ceil((maxLength - 3) / 2);
let startStr, endStr;
switch (location) {
case 'start':
endStr = str.substring(str.length - maxLength + 3);
return '...' + endStr;
case 'end':
startStr = str.substring(0, maxLength - 3);
return startStr + '...';
case 'middle':
default:
startStr = str.substring(0, partLength);
endStr = str.substring(str.length - partLength);
return startStr + '...' + endStr;
}
}
console.log(truncate('abcdefghi', 8, 'start')); // Output: '...defghi'
console.log(truncate('abcdefghi', 8, 'end')); // Output: 'abcdef...'
console.log(truncate('abcdefghi', 8)); // Output: 'abc...hi'
Upvotes: 1
Reputation: 1125
Here is how I did it:
function truncate(
fullStr,
strLen = 8,
separator = "...",
frontChars = 3,
backChars = 4
) {
if (fullStr.length <= strLen) return fullStr;
return (
fullStr.substr(0, frontChars) +
separator +
fullStr.substr(fullStr.length - backChars)
);
}
Upvotes: 2
Reputation: 180
By relying on the @mvChr solution, I propose to use a @pipe with Typescript.
First, You need to create a @pipe helper where you will described the function of truncate.
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'truncateString',
})
export class TreeHelperPipe implements PipeTransform {
transform(fullStr: string, strLen: number, separator: string): any {
if (fullStr.length < strLen) {
return fullStr;
}
separator = separator || '...';
const sepLen = separator.length,
charsToShow = strLen - sepLen,
frontChars = Math.ceil(charsToShow / 2),
backChars = Math.floor(charsToShow / 2);
return (
fullStr.substr(0, frontChars) +
separator +
fullStr.substr(fullStr.length - backChars)
);
}
}
After that, you will be able to use your @pipe helper on your template like that :
<span
class="item-name"
[text]="item.name | truncateString: 60"
[title]="item.name"
></span>
I only apply the @pipe to the text and not the title attribute (which displays the text in a flyover window).
Upvotes: 0
Reputation: 3
If you are playing in PHP you can call this, works fine and could be adjusted to JS well I assume.
function middle_dots($crumb, $max=30){
if(strlen($crumb) > $max)
$crumb = substr_replace($crumb, '...', $max/2, round(-$max/2));
return $crumb;
}
echo middle_dots('Some long text here would if longer than 30 chars get some ...');
Enjoy
Steve
Upvotes: -5
Reputation: 33300
CoffeeScript version based on mVChr's answer:
truncate = (str, length, separator = '...') ->
return '' if str is null
return str if str.length <= length
pad = Math.round (length - separator.length) / 2
start = str.substr(0, pad)
end = str.substr(str.length - pad)
[start, separator, end].join('')
Upvotes: -1
Reputation: 38503
Something like this...
function truncate(text, startChars, endChars, maxLength) {
if (text.length > maxLength) {
var start = text.substring(0, startChars);
var end = text.substring(text.length - endChars, text.length);
while ((start.length + end.length) < maxLength)
{
start = start + '.';
}
return start + end;
}
return text;
}
alert(truncate('abcdefghi',2,2,8));
Or to limit to true ellipsis:
function truncate(text, startChars, endChars, maxLength) {
if (text.length > maxLength) {
var start = text.substring(0, startChars);
var end = text.substring(text.length - endChars, text.length);
return start + '...' + end;
}
return text;
}
alert(truncate('abcdefghi',2,2,8));
Upvotes: 1
Reputation: 39219
This may be a bit 'heavy' for what you're looking for but there's a jQuery plugin that does this sort of thing.
Upvotes: 0
Reputation: 50185
Here's one way to do it chopping up the string with substr
:
var truncate = function (fullStr, strLen, separator) {
if (fullStr.length <= strLen) return fullStr;
separator = separator || '...';
var sepLen = separator.length,
charsToShow = strLen - sepLen,
frontChars = Math.ceil(charsToShow/2),
backChars = Math.floor(charsToShow/2);
return fullStr.substr(0, frontChars) +
separator +
fullStr.substr(fullStr.length - backChars);
};
Upvotes: 40