147

I'm not very good with string manipulation in JavaScript, and I was wondering how you would go about shortening a string without cutting any word off. I know how to use substring, but not indexOf or anything really well.

Say I had the following string:

text = "this is a long string I cant display"

I want to trim it down to 10 characters, but if it doesn't end with a space, finish the word. I don't want the string variable to look like this:

"this is a long string I cant dis"

I want it to finish the word until a space occurs.

Tot Zam
  • 8,406
  • 10
  • 51
  • 76
Josh Bedo
  • 3,410
  • 3
  • 21
  • 33
  • you mean trim a string? try `" too many spaces ".trim()` – Anurag Mar 28 '11 at 03:06
  • 2
    Some example input and expected output would help a lot in answering this question. – deceze Mar 28 '11 at 03:09
  • alright sorry say i had the string text = "this is a long string i cant display" i want to trim it down to 10 characters but if it doesnt end with a space finish the word i don't want the string variable to look like this "this is a long string i cant dis" – Josh Bedo Mar 28 '11 at 03:14

27 Answers27

227

If I understand correctly, you want to shorten a string to a certain length (e.g. shorten "The quick brown fox jumps over the lazy dog" to, say, 6 characters without cutting off any word).

If this is the case, you can try something like the following:

var yourString = "The quick brown fox jumps over the lazy dog"; //replace with your string.
var maxLength = 6 // maximum number of characters to extract

//trim the string to the maximum length
var trimmedString = yourString.substr(0, maxLength);

//re-trim if we are in the middle of a word
trimmedString = trimmedString.substr(0, Math.min(trimmedString.length, trimmedString.lastIndexOf(" ")))
Pavel Chuchuva
  • 22,633
  • 10
  • 99
  • 115
NT3RP
  • 15,262
  • 9
  • 61
  • 97
  • nice one - also easier to make the length variable that my regex solution. – Hamish Mar 28 '11 at 03:22
  • seems to be printing out everything still. – Josh Bedo Mar 28 '11 at 03:26
  • will have to try the edited version i just found out .replace doesn't work in jquery functions ex:.each so i have to figure out a way around that. – Josh Bedo Mar 28 '11 at 06:54
  • 10
    @josh it's absolutely not true that ".replace" does not work in "jQuery functions". There's not even any such thing as a "jQuery function". – Pointy Mar 28 '11 at 20:25
  • 7
    isn't that should be "maxLength + 1". And if maxLength is greater or equal than the complete sentence length, than the last word is not included. but thanks for the solution. – Beytan Kurt Jan 27 '14 at 12:20
  • based on your answer, I've made a proper function to handle this: http://stackoverflow.com/a/24168721/82609 – Sebastien Lorber Jun 11 '14 at 17:28
  • 6
    If using this on a string that's shorter than the maxLength, the last word gets cut off. Maybe @AndrewJuniorHoward already stated the fix for this (`maxLength + 1`), but I fixed it by simply adding this line up top: `var yourString += " ";` – tylerl Aug 14 '14 at 19:24
  • 3
    Unfortunately, if you take away `fox jumps over the lazy dog` part, the result will be `The quick brown `, when it should be `The quick brown fox`. – Andrey Gordeev Jul 28 '16 at 14:26
  • 4
    This always cuts the last word. – Chris Cinelli Nov 02 '16 at 14:23
  • 1
    This is a good solution, however if the purpose was to make text fit in a wide section, and there was 2 or 3 words in the string, if there was plenty of space and no overflow out of the section, this code would delete a whole word unnecessarily. So for the small string "Hello my name is Yusef", if it was in a wide div section: ["Hello my name is Yusef" ______] it will unsuccessfully change it to ["Hello my name is"______]. In my case, I wanted to keep whole words to fill a section. – naz786 Feb 24 '17 at 12:02
  • @NT3RP - According to your provided solution, the strings with the lesser length will not be truncated as desired.. Just for example please try the string - "Clever fox jumps over lazy dog", after giving any number to `maxLength`, the output according to your solution will be: `Clever fox jumps over lazy` only, the last word `dog` will be missed every time... – Saumya Rastogi Jul 12 '17 at 05:59
  • So just wrap it in a test for the length of the string `if (yourString.length > maxLength)` .... – Jeremy Daalder Aug 02 '17 at 06:30
  • @JeremyDaalder even then what if trimmedString ends with a space like "Clever fox jumps ".. better to trim() before returning – Shishir Arora May 25 '19 at 22:41
  • without the modification of @BeytanKurt this solution is not applicable. – Wajid Mar 09 '22 at 08:52
152

There are lots of ways to do it, but a regular expression is a useful one line method:

"this is a longish string of text".replace(/^(.{11}[^\s]*).*/, "$1"); 
//"this is a longish"

This expressions returns the first 11 (any) characters plus any subsequent non-space characters.

Example script:

<pre>
<script>
var t = "this is a longish string of text";

document.write("1:   " + t.replace(/^(.{1}[^\s]*).*/, "$1") + "\n");
document.write("2:   " + t.replace(/^(.{2}[^\s]*).*/, "$1") + "\n");
document.write("5:   " + t.replace(/^(.{5}[^\s]*).*/, "$1") + "\n");
document.write("11:  " + t.replace(/^(.{11}[^\s]*).*/, "$1") + "\n");
document.write("20:  " + t.replace(/^(.{20}[^\s]*).*/, "$1") + "\n");
document.write("100: " + t.replace(/^(.{100}[^\s]*).*/, "$1") + "\n");
</script>

Output:

1:   this
2:   this
5:   this is
11:  this is a longish
20:  this is a longish string
100: this is a longish string of text
Ghoul Fool
  • 6,249
  • 10
  • 67
  • 125
Hamish
  • 22,860
  • 8
  • 53
  • 67
  • 1
    Awesome, i literally googled this question a million ways and could only find a working version for php nothing close to this and involving loops. – Josh Bedo Mar 28 '11 at 03:20
  • 1
    It's referring to the first (and only, in this case) sub expression match - the stuff in the brackets. $0 would refer to the whole match, which in this case is the whole string. – Hamish Mar 28 '11 at 03:25
  • alright thanks a lot, i'm guessing a max value variable isn't possible? – Josh Bedo Mar 28 '11 at 03:28
  • 4
    @josh You should be able to make max length a variable by using a regexp object: `t.replace(new RegExp("^(.{"+length+"}[^\s]*).*"), "$1")` – rjmackay Aug 08 '13 at 22:04
  • Also worth noting that this breaks with a multi-line input.. since the regex matches the first line longer than max-length, rather than matching from the start. – rjmackay Aug 08 '13 at 22:13
  • 1
    @Hamish your option works well, but it is including the last word also if the length exceeds. I tried altering the regex expression to exclude the last word if the max word limit is exceeding but didn't get it working. How can we achieve that? – Shashank Agrawal Aug 11 '15 at 12:50
  • @Hamish look at this: supposed to have a var maxLength=140,text.length>=maxLength I have: `text.replace(/^(.{140}[^\s]*).*/, "$1").length` ok but `text.replace( new RegExp("/^(.{"+maxLength+"}[^\s]*).*/"), "$1").length` not, why? – loretoparisi Feb 10 '16 at 13:34
  • This doesn't seem to work if there are non-English characters towards the end of the string. – Ethan Chen Jul 12 '16 at 00:09
  • 1
    Well, this is not really working correctly, sometimes I pass the maximum value as for example if the last word was 30 character already it will be with length more than 60 already! even if it set length to `{30}` – Al-Mothafar Jul 02 '17 at 09:26
  • @Al-Mothafar right well the question does ask "without cutting words" and I do say "plus any subsequent non-space characters" so it's working exactly as described. If you've got different needs you'll need to modify accordingly. – Hamish Jul 11 '17 at 03:14
  • Well, in my opinion, the question does not specify, but make more sense with limitation to not exceed it anyway, so if he wants "this is a long string i cant display" or "this is a long string i can't", in your answer the result will show the last word "display" but in my case if limitation should be the second case. – Al-Mothafar Jul 11 '17 at 09:27
  • One of the better and smarter solutions out there for a simple problem like this :) Good job – hlozancic Oct 01 '17 at 12:07
  • Btw if you want to cut string like this which is multiline use this regex: ^([\s\S]{50}[^\s]*)[\s\S]* – hlozancic Oct 01 '17 at 12:40
  • The trailing `.*` in the regex isn't necessary and could negatively impact performance. – Bananaapple Oct 09 '20 at 14:53
  • Thank you @hlozanic, This is what I was looking for and this should be appended to this top answer. – Conor Reid Feb 09 '22 at 19:02
109

I am kind of surprised that for a simple problem like this there are so many answers that are difficult to read and some, including the chosen one, do not work .

I usually want the result string to be at most maxLen characters. I also use this same function to shorten the slugs in URLs.

str.lastIndexOf(searchValue[, fromIndex]) takes a second parameter that is the index at which to start searching backwards in the string making things efficient and simple.

// Shorten a string to less than maxLen characters without truncating words.
function shorten(str, maxLen, separator = ' ') {
  if (str.length <= maxLen) return str;
  return str.substr(0, str.lastIndexOf(separator, maxLen));
}

This is a sample output:

for (var i = 0; i < 50; i += 3) 
  console.log(i, shorten("The quick brown fox jumps over the lazy dog", i));

 0 ""
 3 "The"
 6 "The"
 9 "The quick"
12 "The quick"
15 "The quick brown"
18 "The quick brown"
21 "The quick brown fox"
24 "The quick brown fox"
27 "The quick brown fox jumps"
30 "The quick brown fox jumps over"
33 "The quick brown fox jumps over"
36 "The quick brown fox jumps over the"
39 "The quick brown fox jumps over the lazy"
42 "The quick brown fox jumps over the lazy"
45 "The quick brown fox jumps over the lazy dog"
48 "The quick brown fox jumps over the lazy dog"

And for the slug:

for (var i = 0; i < 50; i += 10) 
  console.log(i, shorten("the-quick-brown-fox-jumps-over-the-lazy-dog", i, '-'));

 0 ""
10 "the-quick"
20 "the-quick-brown-fox"
30 "the-quick-brown-fox-jumps-over"
40 "the-quick-brown-fox-jumps-over-the-lazy"
Chris Cinelli
  • 4,679
  • 4
  • 28
  • 40
  • 1
    I completely forgot about the lastIndexOf(). Good catch! – Tici Dec 02 '16 at 16:19
  • 2
    This crashes if for some reason `str` is `undefined`. I added `if (!str || str.length <= maxLen) return str;` – Silvain Aug 23 '17 at 07:32
  • 1
    this doesn't handle the edge case where the separator doesn't occur in the string – shrewquest Feb 16 '18 at 20:45
  • 2
    @shrewquest It works. If the separator is not in the string, it returns the string itself if `str.length <= maxLen`. Otherwise it returns an empty string. – Chris Cinelli Feb 19 '18 at 02:54
  • This returns empty string if str>maxLen. Solved it by adding if(str.split(separator)[0].length>maxLen) return str.split(separator)[0].substr(0,maxLen-2)+"..."; – Niclas Sep 24 '21 at 07:35
31

Everyone seems to forget that indexOf takes two arguments- the string to match, and the character index to start looking from. You can break the string at the first space after 10 characters.

function cutString(s, n){
    var cut= s.indexOf(' ', n);
    if(cut== -1) return s;
    return s.substring(0, cut)
}
var s= "this is a long string i cant display";
cutString(s, 10)

/*  returned value: (String)
this is a long
*/
kennebec
  • 102,654
  • 32
  • 106
  • 127
18

Lodash has a function specifically written for this: _.truncate

const truncate = _.truncate
const str = 'The quick brown fox jumps over the lazy dog'

truncate(str, {
  length: 30, // maximum 30 characters
  separator: /,?\.* +/ // separate by spaces, including preceding commas and periods
})

// 'The quick brown fox jumps...'
Leon Li
  • 337
  • 3
  • 4
14

Here is a solution in one line.

text = "this is a long string I cant display"

function shorten(text,max) {
    return text && text.length > max ? text.slice(0,max).split(' ').slice(0, -1).join(' ') : text
}


console.log(shorten(text,10));
Joakim Poromaa Helger
  • 1,261
  • 10
  • 17
8

Based on NT3RP answer which does not handle some corner cases, I've made this code. It guarantees to not return a text with a size > maxLength event an ellipsis ... was added at the end.

This also handle some corner cases like a text which have a single word being > maxLength

shorten: function(text,maxLength,options) {
    if ( text.length <= maxLength ) {
        return text;
    }
    if ( !options ) options = {};
    var defaultOptions = {
        // By default we add an ellipsis at the end
        suffix: true,
        suffixString: " ...",
        // By default we preserve word boundaries
        preserveWordBoundaries: true,
        wordSeparator: " "
    };
    $.extend(options, defaultOptions);
    // Compute suffix to use (eventually add an ellipsis)
    var suffix = "";
    if ( text.length > maxLength && options.suffix) {
        suffix = options.suffixString;
    }

    // Compute the index at which we have to cut the text
    var maxTextLength = maxLength - suffix.length;
    var cutIndex;
    if ( options.preserveWordBoundaries ) {
        // We use +1 because the extra char is either a space or will be cut anyway
        // This permits to avoid removing an extra word when there's a space at the maxTextLength index
        var lastWordSeparatorIndex = text.lastIndexOf(options.wordSeparator, maxTextLength+1);
        // We include 0 because if have a "very long first word" (size > maxLength), we still don't want to cut it
        // But just display "...". But in this case the user should probably use preserveWordBoundaries:false...
        cutIndex = lastWordSeparatorIndex > 0 ? lastWordSeparatorIndex : maxTextLength;
    } else {
        cutIndex = maxTextLength;
    }

    var newText = text.substr(0,cutIndex);
    return newText + suffix;
}

I guess you can easily remove the jquery dependency if this bothers you.

Sebastien Lorber
  • 89,644
  • 67
  • 288
  • 419
6

I'm late to the party, but here's a small and easy solution I came up with to return an amount of words.

It's not directly related to your requirement of characters, but it serves the same outcome that I believe you were after.

function truncateWords(sentence, amount, tail) {
  const words = sentence.split(' ');

  if (amount >= words.length) {
    return sentence;
  }

  const truncated = words.slice(0, amount);
  return `${truncated.join(' ')}${tail}`;
}

const sentence = 'Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.';

console.log(truncateWords(sentence, 10, '...'));

See the working example here: https://jsfiddle.net/bx7rojgL/

Michael Giovanni Pumo
  • 14,338
  • 18
  • 91
  • 140
4
function shorten(str,n) {
  return (str.match(RegExp(".{"+n+"}\\S*"))||[str])[0];
}

shorten("Hello World", 3); // "Hello"

// SHORTEN STRING TO WHOLE WORDS
function shorten(s,l) {
  return (s.match(new RegExp(".{"+l+"}\\S*"))||[s])[0];
}

console.log( shorten("The quick brown fox jumps over the lazy dog", 6) ); // "The quick"
Roko C. Buljan
  • 196,159
  • 39
  • 305
  • 313
3

I took a different approach. While I needed a similar result I wanted to keep my return value less than the specified length.

function wordTrim(value, length, overflowSuffix) {
    value = value.trim();
    if (value.length <= length) return value;
    var strAry = value.split(' ');
    var retString = strAry[0];
    for (var i = 1; i < strAry.length; i++) {
        if (retString.length >= length || retString.length + strAry[i].length + 1 > length) break;
        retString += " " + strAry[i];
    }
    return retString + (overflowSuffix || '');
}

Edit I refactored it a bit here: JSFiddle Example. It rejoins the original array instead of concatenating.

function wordTrim(value, length, overflowSuffix) {
    if (value.length <= length) return value;
    var strAry = value.split(' ');
    var retLen = strAry[0].length;
    for (var i = 1; i < strAry.length; i++) {
        if(retLen == length || retLen + strAry[i].length + 1 > length) break;
        retLen+= strAry[i].length + 1
    }
    return strAry.slice(0,i).join(' ') + (overflowSuffix || '');
}
Pete
  • 2,393
  • 2
  • 24
  • 31
3
const title = "Hello world is not the way to go"    
const trimmedTitle = title.split(" ").slice(0, 4).join(" ");

// outputs: "Hello world is not"

fahad saleem
  • 616
  • 6
  • 8
2

This excludes the final word instead of including it.

function smartTrim(str, length, delim, appendix) {
    if (str.length <= length) return str;

    var trimmedStr = str.substr(0, length+delim.length);

    var lastDelimIndex = trimmedStr.lastIndexOf(delim);
    if (lastDelimIndex >= 0) trimmedStr = trimmedStr.substr(0, lastDelimIndex);

    if (trimmedStr) trimmedStr += appendix;
    return trimmedStr;
}

Usage:

smartTrim(yourString, 11, ' ', ' ...')
"The quick ..."
clime
  • 8,695
  • 10
  • 61
  • 82
2

You can use truncate one-liner below:

const text = "The string that I want to truncate!";

const truncate = (str, len) => str.substring(0, (str + ' ').lastIndexOf(' ', len));

console.log(truncate(text, 14));
Viktor Vlasenko
  • 2,332
  • 14
  • 16
2

Typescript, and with ellipses :)

export const sliceByWord = (phrase: string, length: number, skipEllipses?: boolean): string => {
  if (phrase.length < length) return phrase
  else {
    let trimmed = phrase.slice(0, length)
    trimmed = trimmed.slice(0, Math.min(trimmed.length, trimmed.lastIndexOf(' ')))
    return skipEllipses ? trimmed : trimmed + '…'
  }
}
Alexander Kim
  • 17,304
  • 23
  • 100
  • 157
doublejosh
  • 5,548
  • 4
  • 39
  • 45
2

Here's a one-line version with a few useful properties:

  1. Handles any form of space matched by the \s regex
  2. Performs independent of input length (anything past the max length is not scanned)
  3. Performs independent of output length (scans backward from max length and doesn't split/join the string)
s.length > maxLen ? s.substring(0, s.substring(0, maxLen + 1).search(/\s+\S*$/)) : s
Trevor Robinson
  • 15,694
  • 5
  • 73
  • 72
2

If you (already) using a lodash library, there is a function called truncate which can be used for trimming the string.

Based on the example on the docs page

_.truncate('hi-diddly-ho there, neighborino', {
  'length': 24,
  'separator': ' '
});
// => 'hi-diddly-ho there,...'
Aditya Kresna Permana
  • 11,869
  • 8
  • 42
  • 48
1

For what it's worth I wrote this to truncate to word boundary without leaving punctuation or whitespace at the end of the string:

function truncateStringToWord(str, length, addEllipsis)
{
    if(str.length <= length)
    {
        // provided string already short enough
        return(str);
    }

    // cut string down but keep 1 extra character so we can check if a non-word character exists beyond the boundary
    str = str.substr(0, length+1);

    // cut any non-whitespace characters off the end of the string
    if (/[^\s]+$/.test(str))
    {
        str = str.replace(/[^\s]+$/, "");
    }

    // cut any remaining non-word characters
    str = str.replace(/[^\w]+$/, "");

    var ellipsis = addEllipsis && str.length > 0 ? '&hellip;' : '';

    return(str + ellipsis);
}

var testString = "hi stack overflow, how are you? Spare";
var i = testString.length;

document.write('<strong>Without ellipsis:</strong><br>');

while(i > 0)
{
  document.write(i+': "'+ truncateStringToWord(testString, i) +'"<br>');
  i--;
}

document.write('<strong>With ellipsis:</strong><br>');

i = testString.length;
while(i > 0)
{
  document.write(i+': "'+ truncateStringToWord(testString, i, true) +'"<br>');
  i--;
}
bbeckford
  • 4,467
  • 6
  • 34
  • 48
1
shorten(str, maxLen, appendix, separator = ' ') {
if (str.length <= maxLen) return str;
let strNope = str.substr(0, str.lastIndexOf(separator, maxLen));
return (strNope += appendix);

}

var s= "this is a long string and I cant explain all"; shorten(s, 10, '...')

/* "this is .." */

1

Here's yet another piece of code that truncates along punctuation marks (was looking for this and Google found this question here). Had to come up with a solution on my own, so this is what I hacked in 15 minutes. Finds all occurrences of . ! ? and truncates at any position of these that's < than len

function pos(str, char) {
    let pos = 0
    const ret = []
    while ( (pos = str.indexOf(char, pos + 1)) != -1) {
        ret.push(pos)
    }
    return ret
}

function truncate(str, len) {
    if (str.length < len)
        return str

    const allPos = [  ...pos(str, '!'), ...pos(str, '.'), ...pos(str, '?')].sort( (a,b) => a-b )
    if (allPos.length === 0) {
        return str.substr(0, len)
    }

    for(let i = 0; i < allPos.length; i++) {
        if (allPos[i] > len) {
            return str.substr(0, allPos[i-1] + 1)
        }
    }
}

module.exports = truncate
Stefan
  • 3,382
  • 4
  • 23
  • 27
1

'Pasta with tomato and spinach'

if you do not want to cut the word in half

first iteration:

acc:0 / acc +cur.length = 5 / newTitle = ['Pasta'];

second iteration:

acc:5 / acc + cur.length = 9 / newTitle = ['Pasta', 'with'];

third iteration:

acc:9 / acc + cur.length = 15 / newTitle = ['Pasta', 'with', 'tomato'];

fourth iteration:

acc:15 / acc + cur.length = 18(limit bound) / newTitle = ['Pasta', 'with', 'tomato'];

const limitRecipeTitle = (title, limit=17)=>{
    const newTitle = [];
    if(title.length>limit){
        title.split(' ').reduce((acc, cur)=>{
            if(acc+cur.length <= limit){
                newTitle.push(cur);
            }
            return acc+cur.length;
        },0);
    }

    return `${newTitle.join(' ')} ...`
}

output: Pasta with tomato ...

Rafiq
  • 8,987
  • 4
  • 35
  • 35
  • This doesn't account for the 'join(' ') characters, which can make the string longer than limit. If you change reduce()'s function to (acc, cur, idx) and the if to (acc + cur.length <= limit - idx) then it will account for the extra spaces when the words are joined back together. If being strictly within limit is required. – PSaul Aug 25 '20 at 21:55
0

Didn't find the voted solutions satisfactory. So I wrote something thats is kind of generic and works both first and last part of your text (something like substr but for words). Also you can set if you'd like the spaces to be left out in the char-count.

    function chopTxtMinMax(txt, firstChar, lastChar=0){
        var wordsArr = txt.split(" ");
        var newWordsArr = [];

        var totalIteratedChars = 0;
        var inclSpacesCount = true;

        for(var wordIndx in wordsArr){
            totalIteratedChars += wordsArr[wordIndx].length + (inclSpacesCount ? 1 : 0);
            if(totalIteratedChars >= firstChar && (totalIteratedChars <= lastChar || lastChar==0)){
                newWordsArr.push(wordsArr[wordIndx]);
            }
        }

        txt = newWordsArr.join(" ");
        return txt;
    }
0

I came late for this but I think this function makes exactly what OP requests. You can easily change the SENTENCE and the LIMIT values for different results.

function breakSentence(word, limit) {
  const queue = word.split(' ');
  const list = [];

  while (queue.length) {
    const word = queue.shift();

    if (word.length >= limit) {
      list.push(word)
    }
    else {
      let words = word;

      while (true) {
        if (!queue.length ||
            words.length > limit ||
            words.length + queue[0].length + 1 > limit) {
          break;
        }

        words += ' ' + queue.shift();
      }

      list.push(words);
    }
  }

  return list;
}

const SENTENCE = 'the quick brown fox jumped over the lazy dog';
const LIMIT = 11;

// get result
const words = breakSentence(SENTENCE, LIMIT);

// transform the string so the result is easier to understand
const wordsWithLengths = words.map((item) => {
  return `[${item}] has a length of - ${item.length}`;
});

console.log(wordsWithLengths);

The output of this snippet is where the LIMIT is 11 is:

[ '[the quick] has a length of - 9',
  '[brown fox] has a length of - 9',
  '[jumped over] has a length of - 11',
  '[the lazy] has a length of - 8',
  '[dog] has a length of - 3' ]
0

With boundary conditions like empty sentence and very long first word. Also, it uses no language specific string api/library.

function solution(message, k) {
    if(!message){
        return ""; //when message is empty
    }
    const messageWords = message.split(" ");
    let result = messageWords[0];
    if(result.length>k){
        return ""; //when length of first word itself is greater that k
    }
    for(let i = 1; i<messageWords.length; i++){
        let next = result + " " + messageWords[i];

        if(next.length<=k){
            result = next;
        }else{
            break;
        }
    }
    return result;
}

console.log(solution("this is a long string i cant display", 10));
Shishir Arora
  • 5,521
  • 4
  • 30
  • 35
0

we can do this easily by using truncate function of lodash

_.truncate('hi-diddly-ho there, neighborino');
// => 'hi-diddly-ho there, neighbo...'

_.truncate('hi-diddly-ho there, neighborino', {
  'length': 24,
  'separator': ' '
 });
// => 'hi-diddly-ho there,...'

go on Lodash Documentation for more clearence.

0

KISS answer

'this is a string'.split(' ').reduce((a, b) => (a+b).length < 10 ? a+' '+b : a);
Oded Breiner
  • 28,523
  • 10
  • 105
  • 71
  • this will actually put a random word that fits at the end if there is still space rather than finishing the last longest word... just try this on a FF console: `'not very good with string manipulation in JavaScript, and I was wondering how you would go about shortening a string without cutting any word off. I know how to use substring, but not indexOf or anything really well.'.split(' ').reduce((a, b) => (a+b).length < 10 ? a+' '+b : a)` - results in: _"not very I"_ – Zathrus Writer Aug 04 '23 at 11:00
-1

Updated from @NT3RP I found that if the string happens to hit a space first time around it will end up deleting that word making your string one word shorter than it can be. So I just threw in an if else statement to check that the maxLength doesn't fall on a space.

codepen.io

var yourString = "The quick brown fox jumps over the lazy dog"; //replace with your string.
var maxLength = 15 // maximum number of characters to extract

if (yourString[maxLength] !== " ") {

//trim the string to the maximum length
var trimmedString = yourString.substr(0, maxLength);

alert(trimmedString)

//re-trim if we are in the middle of a word
trimmedString = trimmedString.substr(0, Math.min(trimmedString.length, trimmedString.lastIndexOf(" ")))
}

else {
  var trimmedString = yourString.substr(0, maxLength);
}

alert(trimmedString)
Parzi
  • 694
  • 2
  • 10
  • 33
-3

You can use the JavaScript method called substring:

var content = "ABCD";
content.substring(0, 2);
console.log(content);

The expected output is "D"
"ABC" is trimmed so the available content is "D"

GooDeeJAY
  • 1,681
  • 2
  • 20
  • 27