Modo intelligente per troncare stringhe lunghe


187

Qualcuno ha una soluzione / libreria più sofisticata per troncare le stringhe con JavaScript e mettere un'ellissi all'estremità, rispetto a quella ovvia:

if (string.length > 25) {
  string = string.substring(0, 24) + "...";
}

5
Cosa intendi con "più sofisticato"? Funzioni che tengono conto dei confini delle parole?
Residuum,

2
E non troncare nel mezzo di tag HTML.
Sz.

Risposte:


367

In sostanza, controlli la lunghezza della stringa data. Se è più lungo di una determinata lunghezza n, taglialo alla lunghezza n( substro slice) e aggiungi un'entità html …(...) alla stringa ritagliata.

Sembra un tale metodo

function truncate(str, n){
  return (str.length > n) ? str.substr(0, n-1) + '…' : str;
};

Se per "più sofisticato" intendi troncare all'ultimo limite di una stringa, allora hai bisogno di un controllo extra. Per prima cosa ritagli la stringa alla lunghezza desiderata, poi ritagli il risultato fino al limite dell'ultima parola

function truncate( str, n, useWordBoundary ){
  if (str.length <= n) { return str; }
  const subString = str.substr(0, n-1); // the original check
  return (useWordBoundary 
    ? subString.substr(0, subString.lastIndexOf(" ")) 
    : subString) + "&hellip;";
};

Puoi estendere il Stringprototipo nativo con la tua funzione. In tal caso, il strparametro deve essere rimosso e strall'interno della funzione deve essere sostituito con this:

String.prototype.truncate = String.prototype.truncate || 
function ( n, useWordBoundary ){
  if (this.length <= n) { return this; }
  const subString = this.substr(0, n-1); // the original check
  return (useWordBoundary 
    ? subString.substr(0, subString.lastIndexOf(" ")) 
    : subString) + "&hellip;";
};

Altri sviluppatori dogmatici potrebbero farti capitolare fortemente su questo (" Non modificare oggetti che non possiedi ". Non mi dispiacerebbe però).

Un approccio senza estendere il Stringprototipo è quello di creare il proprio oggetto helper, contenente la stringa (lunga) fornita e il metodo summenzionato per troncarlo. Questo è ciò che fa lo snippet di seguito.

Infine, puoi usare css solo per troncare stringhe lunghe nei nodi HTML. Ti dà meno controllo, ma potrebbe essere una soluzione praticabile.


5
Dovresti anche considerare di avere limiti "difficili" e "soft", come, ad esempio, se la stringa è più lunga di 500 caratteri, troncala a 400. Ciò può essere utile quando l'utente vuole vedere l'intero testo e fa clic su un link per questo. Se, di conseguenza, carichi solo 1 o 2 caratteri in più, sembrerà davvero brutto.
Maxim Sloyko,

2
Il secondo parametro substrè una lunghezza, quindi dovrebbe essere substr(0,n)invece di limitarlo ai primi ncaratteri.
JohnnyHK,

10
Non modificare oggetti che non possiedi. nczonline.net/blog/2010/03/02/…
Charlie Kilian,

5
Una cosa che potresti considerare è la sostituzione &hellip;con i puntini di sospensione ( ...) nell'esempio di codice. Se stai provando a usarlo per interagire con le API, vorrai lì l'entità non HTML.
AlbertEngel,

1
@RuneJeppesen hai ragione. Modificati i metodi. A mia difesa: la risposta risale a 7 anni fa;)
KooiInc,

62

Nota che questo deve essere fatto solo per Firefox.

Tutti gli altri browser supportano una soluzione CSS (vedi tabella di supporto ):

p {
    white-space: nowrap;
    width: 100%;                   /* IE6 needs any width */
    overflow: hidden;              /* "overflow" value must be different from  visible"*/ 
    -o-text-overflow: ellipsis;    /* Opera < 11*/
    text-overflow:    ellipsis;    /* IE, Safari (WebKit), Opera >= 11, FF > 6 */
}

L'ironia è che ho preso quel frammento di codice da Mozilla MDC.



Wow, questa è una soluzione perfetta per Safari mobile. Grazie!
Samvermette,

9
Ottimo approccio CSS. Potrebbe esserci una nota, che funziona solo con una singola riga di testo (come previsto da white-space: nowrap;). Quando si tratta di più di una riga, sei bloccato con JavaScript.
insertusernamehere

Funziona anche solo per l'intero elemento. Se si desidera troncare parte di una stringa, senza racchiudere il bit che si desidera troncare in una span o in un altro elemento html, questo non funzionerà ad esempio:Your picture ('some very long picture filename truncated...') has been uploaded.
Chris

1
OP ha chiesto espressamente una soluzione JavaScript
vsync,

25

Ci sono validi motivi per cui le persone potrebbero voler fare questo in JavaScript anziché CSS.

Per troncare a 8 caratteri (inclusi i puntini di sospensione) in JavaScript:

short = long.replace(/(.{7})..+/, "$1&hellip;");

o

short = long.replace(/(.{7})..+/, "$1…");

1
Se conti i puntini di sospensione, questo sarà di 9 caratteri. Se è necessario che siano 8 dopo il troncamento, utilizzare .replace(/^(.{7}).{2,}/, "$1…");invece
Okku,

longe shortsono riservati come parole chiave future dalle specifiche ECMAScript precedenti (ECMAScript da 1 a 3). Vedi MDN: future parole chiave riservate negli standard più vecchi
Ricardo,


9
('long text to be truncated').replace(/(.{250})..+/, "$1…");

In qualche modo sopra il codice non funzionava per qualche tipo di copia o incolla del testo scritto nell'app vuejs. Quindi ho usato lodash truncate e ora funziona benissimo.

_.truncate('long text to be truncated', { 'length': 250, 'separator': ' '});

bella risposta moderna!
ykonda,

Sarei curioso di sapere quale fosse il testo. Stava usando caratteri non latini?
Adam Leggett l'

Era solo un lorem ipsum
Afraz Ahmad il

7

Ecco la mia soluzione, che presenta alcuni miglioramenti rispetto ad altri suggerimenti:

String.prototype.truncate = function(){
    var re = this.match(/^.{0,25}[\S]*/);
    var l = re[0].length;
    var re = re[0].replace(/\s$/,'');
    if(l < this.length)
        re = re + "&hellip;";
    return re;
}

// "This is a short string".truncate();
"This is a short string"

// "Thisstringismuchlongerthan25characters".truncate();
"Thisstringismuchlongerthan25characters"

// "This string is much longer than 25 characters and has spaces".truncate();
"This string is much longer&hellip;"

It:

  • Tronca sul primo spazio dopo 25 caratteri
  • Estende l'oggetto String JavaScript, in modo che possa essere utilizzato su (e incatenato a) qualsiasi stringa.
  • Taglia la stringa se il troncamento si traduce in uno spazio finale;
  • Aggiungerà l'entità unipode hellip (puntini di sospensione) se la stringa troncata è più lunga di 25 caratteri

7

La migliore funzione che ho trovato. Ringraziamo i puntini di sospensione .

function textEllipsis(str, maxLength, { side = "end", ellipsis = "..." } = {}) {
  if (str.length > maxLength) {
    switch (side) {
      case "start":
        return ellipsis + str.slice(-(maxLength - ellipsis.length));
      case "end":
      default:
        return str.slice(0, maxLength - ellipsis.length) + ellipsis;
    }
  }
  return str;
}

Esempi :

var short = textEllipsis('a very long text', 10);
console.log(short);
// "a very ..."

var short = textEllipsis('a very long text', 10, { side: 'start' });
console.log(short);
// "...ng text"

var short = textEllipsis('a very long text', 10, { textEllipsis: ' END' });
console.log(short);
// "a very END"

5

Tutti i browser moderni ora supportano una semplice soluzione CSS per aggiungere automaticamente i puntini di sospensione se una riga di testo supera la larghezza disponibile:

p {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

(Nota che questo richiede che la larghezza dell'elemento sia limitata in qualche modo per avere qualche effetto.)

Basato su https://css-tricks.com/snippets/css/truncate-string-with-ellipsis/ .

Va notato che questo approccio non si limita in base al numero di caratteri. Inoltre non funziona se è necessario consentire più righe di testo.


2
Questo è utile solo per frasi a riga singola, non c'è modo (finora lo so) di fare un esempio a più righe tramite CSS.
Hooman Askari,

C'è forse un modo per farlo fare i puntini di sospensione a sinistra anziché a destra?
GreenAsJade,

1
@GreenAsJade Credo che tu possa realizzarlo usando text-direction: rtle text-align: left. Vedi davidwalsh.name/css-ellipsis-left
Sean the Bean

4

I più moderni framework Javascript ( JQuery , Prototype , ecc ...) hanno una funzione di utilità applicata a String che gestisce questo.

Ecco un esempio in prototipo:

'Some random text'.truncate(10);
// -> 'Some ra...'

Sembra una di quelle funzioni che vuoi che qualcun altro gestisca / mantenga. Lascerei che il framework lo gestisca, piuttosto che scrivere più codice.


8
Non penso che jQuery abbia qualcosa per questo.
alex,

2
Underscore.js fa - _ ('Hello world'). Truncate (5) => 'Hello ...' _ ('Hello'). Truncate (10) => 'Hello'
JayCrossler

3
Pure Underscore non sembra avere truncate()neanche - potresti aver bisogno di un'estensione come underscore.string .
martin,

2
Questa è totalmente la risposta giusta. Non so di sottolineatura, ma lodash ha _.truncesattamente questo.
leftclickben,

2
Penso che la risposta giusta sia usare lodash.trunc o underscore.string.truncate.
ooolala,

2

Forse ho perso un esempio di dove qualcuno sta gestendo i null, ma 3 risposte TOP non hanno funzionato per me quando avevo i null (Certo, mi rendo conto che la gestione degli errori è e milioni di altre cose NON sono responsabilità della persona che risponde alla domanda, ma poiché Avevo usato una funzione esistente insieme a una delle eccellenti risposte di ellissi di troncamento che pensavo che avrei fornito ad altri.

per esempio

javascript:

news.comments

utilizzando la funzione di troncamento

news.comments.trunc(20, true);

Tuttavia, su news.comments essere nulli, questo si "spezzerebbe"

Finale

checkNull(news.comments).trunc(20, true) 

funzione trunc per gentile concessione di KooiInc

String.prototype.trunc =
 function (n, useWordBoundary) {
     console.log(this);
     var isTooLong = this.length > n,
         s_ = isTooLong ? this.substr(0, n - 1) : this;
     s_ = (useWordBoundary && isTooLong) ? s_.substr(0, s_.lastIndexOf(' ')) : s_;
     return isTooLong ? s_ + '&hellip;' : s_;
 };

Il mio semplice controllo null (controlla anche la cosa letterale "null" (questo cattura indefinito, "", null, "null", ecc.)

  function checkNull(val) {
      if (val) {
          if (val === "null") {
              return "";
          } else {
              return val;
          }
      } else {
          return "";
      }
  }

Ecco una versione modificata: evita l'uso del prototipo, incorpora il controllo null nella funzione e ha un uso di test / demo. codepen.io/mahemoff/pen/LGEdzy
mahemoff

Trovi che il prototipo sia problematico? Solo curioso
Tom Stickel l'

Il motivo della mia funzione di controllo null separato è che controllerà effettivamente null, non definito, NaN, stringa vuota (""), 0, false e "null" Ma nel complesso mi piace il tuo fx
Tom Stickel

1
Sì, è una questione di opinione e contesto di utilizzo, ma il prototipo diventa brutto quando si lavora con altre librerie poiché potrebbero anche sostituire la stessa cosa. (O in rari casi, una funzione con lo stesso nome potrebbe in seguito essere introdotta come funzionalità del linguaggio standard.)
mahemoff

Sì, sono d'accordo con te
Tom Stickel,

2

A volte i nomi dei file sono numerati, dove l'indice può essere all'inizio o alla fine. Quindi volevo accorciare dal centro della stringa:

function stringTruncateFromCenter(str, maxLength) {
    const midChar = "…";      // character to insert into the center of the result
    var left, right;

    if (str.length <= maxLength) return str;

    // length of beginning part      
    left = Math.ceil(maxLength / 2);

    // start index of ending part   
    right = str.length - Math.floor(maxLength / 2) + 1;   

    return str.substr(0, left) + midChar + str.substring(right);
}

Ricorda che qui ho usato un carattere di riempimento con più di 1 byte in UTF-8.


2

Overflow del testo: i puntini di sospensione sono la proprietà di cui hai bisogno. Con questo e un overflow: nascosto con una larghezza specifica, tutto ciò che sorpassa alla fine otterrà l'effetto tre periodi ... Non dimenticare di aggiungere spazi bianchi: nowrap o il testo verrà inserito in più righe.

.wrap{
  text-overflow: ellipsis
  white-space: nowrap;
  overflow: hidden;
  width:"your desired width";
}
<p class="wrap">The string to be cut</p>

1
La brevità è accettabile, ma spiegazioni più complete sono migliori.
Armali,

mwilcox e Sean the Bean hanno già pubblicato questa soluzione.
Andrew Myers,

1
Può essere utilizzato solo per il testo di una riga
Vally Pepyako,

L'overflow del testo: i puntini di sospensione sono perfetti !!
zardilior


1

Ho votato a favore della soluzione di Kooilnc. Soluzione compatta davvero piacevole. C'è un piccolo caso limite che vorrei affrontare. Se qualcuno inserisce una sequenza di caratteri molto lunga per qualsiasi motivo, non verrà troncato:

function truncate(str, n, useWordBoundary) {
    var singular, tooLong = str.length > n;
    useWordBoundary = useWordBoundary || true;

    // Edge case where someone enters a ridiculously long string.
    str = tooLong ? str.substr(0, n-1) : str;

    singular = (str.search(/\s/) === -1) ? true : false;
    if(!singular) {
      str = useWordBoundary && tooLong ? str.substr(0, str.lastIndexOf(' ')) : str;
    }

    return  tooLong ? str + '&hellip;' : str;
}

1

Con una rapida ricerca su Google ho trovato questo ... Funziona per te?

/**
 * Truncate a string to the given length, breaking at word boundaries and adding an elipsis
 * @param string str String to be truncated
 * @param integer limit Max length of the string
 * @return string
 */
var truncate = function (str, limit) {
    var bits, i;
    if (STR !== typeof str) {
        return '';
    }
    bits = str.split('');
    if (bits.length > limit) {
        for (i = bits.length - 1; i > -1; --i) {
            if (i > limit) {
                bits.length = i;
            }
            else if (' ' === bits[i]) {
                bits.length = i;
                break;
            }
        }
        bits.push('...');
    }
    return bits.join('');
};
// END: truncate

0

La risposta di c_harm è secondo me la migliore. Si prega di notare che se si desidera utilizzare

"My string".truncate(n)

dovrai usare un costruttore di oggetti regexp piuttosto che un valore letterale. Inoltre dovrai sfuggire a \Squando lo converti.

String.prototype.truncate =
    function(n){
        var p  = new RegExp("^.{0," + n + "}[\\S]*", 'g');
        var re = this.match(p);
        var l  = re[0].length;
        var re = re[0].replace(/\s$/,'');

        if (l < this.length) return re + '&hellip;';
    };

Hai mai sentito parlare di commenti e denominazione delle variabili appropriate?
bicicletta,

@bicycle il codice viene copiato e modificato da un'altra risposta sopra, non c'è bisogno di essere così scortese e snarky.
Matt Fletcher,

0

Usa il seguente codice

 function trancateTitle (title) {
    var length = 10;
    if (title.length > length) {
       title = title.substring(0, length)+'...';
    }
    return title;
}

0

Correzione della soluzione di Kooilnc:

String.prototype.trunc = String.prototype.trunc ||
  function(n){
      return this.length>n ? this.substr(0,n-1)+'&hellip;' : this.toString();
  };

In questo modo viene restituito il valore stringa anziché l'oggetto String se non è necessario troncarlo.


Questo non fornisce una risposta alla domanda. Per criticare o richiedere chiarimenti a un autore, lascia un commento sotto il suo post: puoi sempre commentare i tuoi post e una volta che avrai una reputazione sufficiente sarai in grado di commentare qualsiasi post .
Spencer Wieczorek,

Ah vedo la distinzione ora. Grazie per i riferimenti. Volevo lasciare un commento con la speranza che @Kooilnc lo vedesse, ed eventualmente modificare la risposta accettata se lui o lei fosse d'accordo, ma non aveva la reputazione.
qwales1

0

Di recente ho dovuto farlo e ho finito con:

/**
 * Truncate a string over a given length and add ellipsis if necessary
 * @param {string} str - string to be truncated
 * @param {integer} limit - max length of the string before truncating
 * @return {string} truncated string
 */
function truncate(str, limit) {
    return (str.length < limit) ? str : str.substring(0, limit).replace(/\w{3}$/gi, '...');
}

Mi sento bene e pulito per me :)


1
Ciò potrebbe rendere la stringa risultante 3 caratteri più lunga del limite.
Hauke,

0

Mi piace usare .slice () Il primo argomento è l'indice iniziale e il secondo è l'indice finale. Tutto nel mezzo è ciò che ottieni.

var long = "hello there! Good day to ya."
// hello there! Good day to ya.

var short  = long.slice(0, 5)
// hello

0

Somewhere Smart: D

//My Huge Huge String
    let tooHugeToHandle = `It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using 'Content here, content here', making it look like readable English. Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, and a search for 'lorem ipsum' will uncover many web sites still in their infancy. Various versions have evolved over the years, sometimes by accident, sometimes on purpose (injected humour and the like).`
    
//Trim Max Length
 const maxValue = 50
// The barber.
 const TrimMyString = (string, maxLength, start = 0) => {
//Note - `start` is if I want to start after some point of the string
    	if (string.length > maxLength) {
    	let trimmedString = string.substr(start, maxLength)
    	 return (
    	   trimmedString.substr(
    	   start,
    	   Math.min(trimmedString.length,   trimmedString.lastIndexOf(' '))
           ) + ' ...'
         )
       }
    return string
}

console.log(TrimMyString(tooHugeToHandle, maxValue))


-1

Questa funzione fa anche troncare lo spazio e le parti delle parole (ad esempio: Mother into Moth ...)

String.prototype.truc= function (length) {
        return this.length>length ? this.substring(0, length) + '&hellip;' : this;
};

utilizzo:

"this is long length text".trunc(10);
"1234567890".trunc(5);

produzione:

questo è lo ...

12345 ...

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.