Manière intelligente de tronquer de longues chaînes

198

Quelqu'un a-t-il une solution / bibliothèque plus sophistiquée pour tronquer les chaînes avec JavaScript et mettre des points de suspension à la fin, que celle qui est évidente:

if (string.length > 25) {
  string = string.substring(0, 24) + "...";
}
naltatis
la source
5
Qu'entendez-vous par «plus sophistiqué»? Des fonctions qui prennent en compte les limites des mots?
Residuum
2
Et ne pas tronquer au milieu des balises HTML.
Sz.

Réponses:

388

Essentiellement, vous vérifiez la longueur de la chaîne donnée. S'il est plus long qu'une longueur donnée n, coupez-le à la longueur n( substrou slice) et ajoutez l'entité html …(…) à la chaîne coupée.

Une telle méthode ressemble à

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

Si par «plus sophistiqué» vous entendez tronquer à la limite du dernier mot d'une chaîne, vous avez besoin d'une vérification supplémentaire. Vous coupez d'abord la chaîne à la longueur désirée, ensuite vous coupez le résultat de cela à sa limite du dernier mot

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;";
};

Vous pouvez étendre le Stringprototype natif avec votre fonction. Dans ce cas, le strparamètre doit être supprimé et strdans la fonction doit être remplacé par 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;";
};

Des développeurs plus dogmatiques peuvent vous capituler fortement sur ce point (" Ne modifiez pas les objets que vous ne possédez pas ". Cela ne me dérangerait pas).

Une approche sans étendre le Stringprototype consiste à créer votre propre objet d'assistance, contenant la (longue) chaîne que vous fournissez et la méthode susmentionnée pour le tronquer. C'est ce que fait l'extrait ci-dessous.

Enfin, vous pouvez utiliser css uniquement pour tronquer les longues chaînes dans les nœuds HTML. Cela vous donne moins de contrôle, mais pourrait bien être une solution viable.

KooiInc
la source
5
Devrait également envisager d'avoir des limites «strictes» et «souples», comme, par exemple, si la chaîne est plus longue que 500 caractères, tronquez-la à 400. Cela peut être utile lorsque l'utilisateur veut voir tout le texte et clique sur un lien pour ça. Si, par conséquent, vous ne chargez que 1 ou 2 caractères de plus, cela aura l'air vraiment moche.
Maxim Sloyko
2
Le deuxième paramètre à substrest une longueur, il devrait donc être substr(0,n)plutôt limité aux premiers ncaractères.
JohnnyHK
10
Ne modifiez pas les objets que vous ne possédez pas. nczonline.net/blog/2010/03/02/…
Katie Kilian
5
Une chose que vous pourriez envisager est de remplacer le &hellip;par des points de suspension ( ...) dans votre exemple de code. Si vous essayez d'utiliser ceci pour interagir avec les API, vous voudrez que l'entité non HTML s'y trouve.
AlbertEngelB
1
@RuneJeppesen vous avez raison. Ajustement des méthodes. À ma défense: la réponse remonte à 7 ans;)
KooiInc
64

Notez que cela ne doit être fait que pour Firefox.

Tous les autres navigateurs prennent en charge une solution CSS (voir le tableau de support ):

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'ironie est que j'ai obtenu cet extrait de code de Mozilla MDC.

mwilcox
la source
1
mattsnider.com/css/css-string-truncation-with-ellipsis pour qu'il fonctionne également avec FF.
Neal
Wow, c'est une solution parfaite pour Safari mobile. Merci!
samvermette
10
Très bonne approche CSS. Il pourrait y avoir une note, que cela ne fonctionne qu'avec une seule ligne de texte (comme prévu par white-space: nowrap;). Quand il s'agit de plus d'une ligne, vous êtes coincé avec JavaScript.
insérer
Cela ne fonctionne également que pour l'élément entier. Si vous souhaitez tronquer une partie d'une chaîne, sans envelopper le bit que vous souhaitez tronquer dans un span ou un autre élément html, cela ne fonctionnera pas par exemple:Your picture ('some very long picture filename truncated...') has been uploaded.
Chris
1
OP a spécifiquement demandé une solution javascript
vsync
28

Il y a des raisons valables que les gens souhaitent faire cela en JavaScript au lieu de CSS.

Pour tronquer à 8 caractères (y compris les points de suspension) en JavaScript:

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

ou

short = long.replace(/(.{7})..+/, "$1…");
Adam Leggett
la source
1
Si vous comptez les points de suspension, ce sera 9 caractères. Si vous en avez besoin pour être 8 après la troncature, utilisez à la .replace(/^(.{7}).{2,}/, "$1…");place
Okku
1
longet shortsont réservés comme futurs mots-clés par des spécifications ECMAScript plus anciennes (ECMAScript 1 à 3). Voir MDN: Futurs mots-clés réservés dans les anciennes normes
Ricardo
@Ricardo Je suis sûr que quelqu'un, quelque part, écrit encore sur ES3, mais je pense que cela fonctionnera quand même à des fins d'illustration.
Adam Leggett
9
('long text to be truncated').replace(/(.{250})..+/, "$1…");

D'une manière ou d'une autre, le code ci-dessus ne fonctionnait pas pour une sorte de texte copié ou écrit dans l'application vuejs. J'ai donc utilisé lodash truncate et cela fonctionne maintenant très bien.

_.truncate('long text to be truncated', { 'length': 250, 'separator': ' '});
Afraz Ahmad
la source
belle réponse moderne!
ykonda
Je serais curieux de savoir quel était le texte. Utilisait-il des caractères non latins?
Adam Leggett
C'était juste un lorem ipsum
Afraz Ahmad
7

Voici ma solution, qui a quelques améliorations par rapport à d'autres suggestions:

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;"

Il:

  • Tronque sur le premier espace après 25 caractères
  • Étend l'objet JavaScript String, afin qu'il puisse être utilisé sur (et enchaîné à) n'importe quelle chaîne.
  • Coupera la chaîne si la troncature entraîne un espace de fin;
  • Ajoutera l'entité hellip unicode (points de suspension) si la chaîne tronquée contient plus de 25 caractères

la source
7

Meilleure fonction que j'ai trouvée. Crédit à text-ellipsis .

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;
}

Exemples :

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"
Jeff Hernandez
la source
6

Tous les navigateurs modernes prennent désormais en charge une solution CSS simple pour ajouter automatiquement des points de suspension si une ligne de texte dépasse la largeur disponible:

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

(Notez que cela nécessite que la largeur de l'élément soit limitée d'une manière ou d'une autre pour avoir un effet.)

Basé sur https://css-tricks.com/snippets/css/truncate-string-with-ellipsis/ .

Il convient de noter que cette approche ne limite pas en fonction du nombre de caractères. Cela ne fonctionne pas non plus si vous devez autoriser plusieurs lignes de texte.

Sean le haricot
la source
2
Ceci n'est utile que pour les phrases à une seule ligne, il n'y a aucun moyen (à ce que je sache) de faire un exemple sur plusieurs lignes via CSS.
Hooman Askari
Existe-t-il par hasard un moyen de faire en sorte que les points de suspension soient à gauche au lieu de droite?
GreenAsJade
1
@GreenAsJade Je crois que vous pouvez y parvenir en utilisant text-direction: rtlet text-align: left. Voir davidwalsh.name/css-ellipsis-left
Sean the Bean
4

La plupart des frameworks Javascript modernes ( JQuery , Prototype , etc ...) ont une fonction utilitaire attachée à String qui gère cela.

Voici un exemple dans Prototype:

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

Cela semble être l'une de ces fonctions dont vous voulez que quelqu'un d'autre s'occupe / maintienne. Je laisserais le framework le gérer, plutôt que d'écrire plus de code.

Jim Fiorato
la source
8
Je ne pense pas que jQuery ait quoi que ce soit pour cela.
alex
2
Underscore.js fait - _ ('Hello world'). Truncate (5) => 'Hello ...' _ ('Hello'). Truncate (10) => 'Hello'
JayCrossler
3
Pure Underscore ne semble pas en avoir truncate()non plus - vous pourriez avoir besoin d'une extension telle que underscore.string .
martin
2
C'est totalement la bonne réponse. Je ne sais pas pour le soulignement, mais lodash a _.truncqui fait exactement cela.
leftclickben
2
Je pense que la bonne réponse est d'utiliser lodash.trunc ou underscore.string.truncate.
ooolala
3

Text-overflow: les points de suspension sont la propriété dont vous avez besoin. Avec ceci et un débordement: caché avec une largeur spécifique, tout ce qui dépasse qui obtiendra l'effet trois périodes à la fin ... N'oubliez pas d'ajouter des espaces: nowrap ou le texte sera mis sur plusieurs lignes.

.wrap{
  text-overflow: ellipsis
  white-space: nowrap;
  overflow: hidden;
  width:"your desired width";
}
<p class="wrap">The string to be cut</p>
vijay kanaujia
la source
1
La brièveté est acceptable, mais des explications plus complètes sont meilleures.
Armali
mwilcox et Sean the Bean ont déjà publié cette solution.
Andrew Myers
1
Peut être utilisé pour le texte sur une seule ligne
Vally Pepyako
Le débordement de texte: les points de suspension sont parfaits !!
zardilior le
2

Peut-être ai-je manqué un exemple où quelqu'un gère les valeurs nulles, mais 3 réponses TOP ne fonctionnaient pas pour moi lorsque j'avais des valeurs nulles (bien sûr, je me rends compte que la gestion des erreurs est et que des millions d'autres choses ne sont PAS de la responsabilité de la personne qui répond à la question, mais depuis J'avais utilisé une fonction existante avec l'une des excellentes réponses d'ellipse de troncature, je pensais que je la fournirais pour d'autres.

par exemple

javascript:

news.comments

utilisation de la fonction de troncature

news.comments.trunc(20, true);

Cependant, sur news.comments étant nul, cela "casserait"

Final

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

fonction trunc avec l'aimable autorisation de 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_;
 };

Mon simple vérificateur de null (vérifie également la chose littérale "null" (cela attrape undefined, "", null, "null", etc.)

  function checkNull(val) {
      if (val) {
          if (val === "null") {
              return "";
          } else {
              return val;
          }
      } else {
          return "";
      }
  }
Tom Stickel
la source
Voici une version modifiée - évite l'utilisation du prototype, incorpore la vérification de null dans la fonction et a une utilisation de test / démo. codepen.io/mahemoff/pen/LGEdzy
mahemoff
Trouvez-vous le prototype problématique? Just curious
Tom Stickel
La raison de ma fonction de vérification de null distincte est qu'elle vérifiera réellement les valeurs nulles, indéfinies, NaN, chaîne vide (""), 0, false et "null" Mais dans l'ensemble, j'aime votre fx
Tom Stickel
1
Oui, c'est une question d'opinion et de contexte d'utilisation, mais le prototype devient moche lorsque vous travaillez avec d'autres bibliothèques car elles peuvent également remplacer la même chose. (Ou dans de rares cas, une fonction du même nom pourrait plus tard être introduite en tant que fonctionnalité de langue standard.)
mahemoff
Oui, je suis d'accord avec vous
Tom Stickel
2

Parfois, les noms de fichiers sont numérotés, où l'index peut être au début ou à la fin. J'ai donc voulu raccourcir à partir du centre de la corde:

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);
}

Sachez que j'ai utilisé ici un caractère de remplissage avec plus d'un octet en UTF-8.

Hauke
la source
1

J'ai voté pour la solution de Kooilnc. Solution compacte vraiment sympa. Il y a un petit cas critique que je voudrais aborder. Si quelqu'un entre une très longue séquence de caractères pour une raison quelconque, elle ne sera pas tronquée:

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;
}
backdesk
la source
1

Avec un rapide googler, j'ai trouvé ceci ... Est-ce que cela fonctionne pour vous?

/**
 * 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
Manrico Corazzi
la source
Qu'est-ce que STR? Où est-ce défini ??
Scott Fleming
0

La réponse de c_harm est à mon avis la meilleure. Veuillez noter que si vous souhaitez utiliser

"My string".truncate(n)

vous devrez utiliser un constructeur d'objet regexp plutôt qu'un littéral. Vous devrez également échapper au \Slors de la conversion.

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;';
    };
Matt Fletcher
la source
Avez-vous entendu parler de commentaires et de dénomination appropriée des variables?
vélo
@bicycle le code est copié et modifié à partir d'une autre réponse ci-dessus, pas besoin d'être si grossier et sournois.
Matt Fletcher
0

Utilisez le code suivant

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

Correction de la solution de Kooilnc:

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

Cela renvoie la valeur de chaîne au lieu de l'objet String s'il n'a pas besoin d'être tronqué.

qwales1
la source
Cela ne répond pas à la question. Pour critiquer ou demander des éclaircissements à un auteur, laissez un commentaire sous son message - vous pouvez toujours commenter vos propres articles, et une fois que vous avez une réputation suffisante, vous pourrez commenter n'importe quel article .
Spencer Wieczorek
Ah je vois la distinction maintenant. Merci pour les références. Je voulais laisser un commentaire dans l'espoir que @Kooilnc le verrait, et éventuellement modifierait la réponse acceptée s'il était d'accord, mais n'avait pas la réputation.
qwales1
0

J'ai récemment dû le faire et j'ai fini avec:

/**
 * 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, '...');
}

Je me sens bien et propre :)

John Doherty
la source
1
Cela pourrait rendre la chaîne résultante de 3 caractères plus longue que la limite.
Hauke
0

J'aime utiliser .slice () Le premier argument est l'index de départ et le second est l'index de fin. Tout ce qui se trouve entre les deux est ce que vous récupérez.

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

var short  = long.slice(0, 5)
// hello
Eric Wallen
la source
0

Quelque part intelligent: 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))

Satyam Pathak
la source
0

J'utilise toujours la bibliothèque cuttr.js pour tronquer les chaînes et ajouter des points de suspension personnalisés:

new Cuttr('.container', {
  //options here
  truncate: 'words',
  length: 8,
  ending: '... ►'
});
<script src="https://unpkg.com/[email protected]/dist/cuttr.min.js"></script>
<p class="container">Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. </p>

C'est de loin la méthode la plus simple (et n'a pas de dépendances) que je connaisse pour couper des chaînes avec JS et elle est également disponible en tant que plugin jQuery.

Basbee
la source
-1

Cette fonction fait également les parties de l'espace tronqué et des mots (ex: Mother into Moth ...)

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

usage:

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

production:

c'est lo ...

12345 ...

Elshan
la source