web-dev-qa-db-fra.com

Envelopper le texte en JavaScript

Je suis nouveau sur JavaScript et jQuery. 

J'ai une variable nommée str en JavaScript et elle contient un texte très long, disant quelque chose comme

"A quick brown fox jumps over a lazy dog". 

Je veux l'envelopper et l'assigner à la même variable str en insérant les balises \n ou br/ appropriées aux endroits appropriés. 

Je ne veux pas utiliser de CSS, etc. Pourriez-vous s'il vous plaît me dire comment le faire avec une fonction appropriée en JavaScript qui prend la str et lui renvoie le texte correctement formaté?

Quelque chose comme:

str = somefunction(str, maxchar);

J'ai essayé beaucoup mais malheureusement rien ne s'est passé comme je le voulais! :(

Toute aide sera très appréciée...

9
user2004685

Cela devrait insérer un saut de ligne dans l'espace blanc le plus proche de maxChar:

str = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It w as popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.";

str = wordWrap(str, 40);

function wordWrap(str, maxWidth) {
    var newLineStr = "\n"; done = false; res = '';
    do {                    
        found = false;
        // Inserts new line at first whitespace of the line
        for (i = maxWidth - 1; i >= 0; i--) {
            if (testWhite(str.charAt(i))) {
                res = res + [str.slice(0, i), newLineStr].join('');
                str = str.slice(i + 1);
                found = true;
                break;
            }
        }
        // Inserts new line at maxWidth position, the Word is too long to wrap
        if (!found) {
            res += [str.slice(0, maxWidth), newLineStr].join('');
            str = str.slice(maxWidth);
        }

        if (str.length < maxWidth)
            done = true;
    } while (!done);

    return res + str;
}

function testWhite(x) {
    var white = new RegExp(/^\s$/);
    return white.test(x.charAt(0));
};
14
ieeehh

Voici une solution un peu plus courte:

var str = "This is a very long line of text that we are going to use in this example to divide it into rows of maximum 40 chars."

var result = stringDivider(str, 40, "<br/>\n");
console.log(result);

function stringDivider(str, width, spaceReplacer) {
    if (str.length>width) {
        var p=width
        for (;p>0 && str[p]!=' ';p--) {
        }
        if (p>0) {
            var left = str.substring(0, p);
            var right = str.substring(p+1);
            return left + spaceReplacer + stringDivider(right, width, spaceReplacer);
        }
    }
    return str;
}

Cette fonction utilise la récursivité pour résoudre le problème.

11
javabeangrinder

Bien que cette question soit relativement ancienne, de nombreuses solutions proposées jusqu’à présent sont plus compliquées et plus coûteuses que nécessaire, comme le fait remarquer l’utilisateur2257198 - C’est une solution complète avec une expression régulière courte sur une ligne.

Cependant, j'ai trouvé quelques problèmes avec sa solution, notamment: wrapping after la largeur maximale plutôt qu'avant, rupture des caractères non explicitement inclus dans la classe de caractère et absence de considération des caractères de nouvelle ligne existants, ce qui entraîne la suppression du début des paragraphes au milieu -ligne.

Ce qui m'a amené à écrire ma propre solution:

// Static Width (Plain Regex)
const wrap = (s, w) => s.replace(
    /(?![^\n]{1,32}$)([^\n]{1,32})\s/g, '$1\n'
);

// Dynamic Width (Build Regex)
const wrap = (s, w) => s.replace(
    new RegExp(`(?![^\\n]{1,${w}}$)([^\\n]{1,${w}})\\s`, 'g'), '$1\n'
);

Caractéristiques bonus

  • Handles any char qui n'est pas une nouvelle ligne (par exemple, un code).
  • Traite correctement les nouvelles lignes existantes (par exemple, les paragraphes).
  • Empêche de placer des espaces au début des nouvelles lignes.
  • Empêche l'ajout de nouvelles lignes inutiles à la fin de la chaîne.

Explication

Le concept principal consiste simplement à rechercher des séquences contiguës de caractères qui font not contiennent des nouvelles lignes [^\n], jusqu’à la longueur souhaitée, par exemple 32 {1,32}. En utilisant negation ^ dans la classe de caractères, il est beaucoup plus permissif, en évitant les éléments manquants tels que la ponctuation qui, autrement, devraient être explicitement ajoutés:

str.replace(/([^\n]{1,32})/g, '[$1]\n');
// Matches wrapped in [] to help visualise

"[Lorem ipsum dolor sit amet, cons]
[ectetur adipiscing elit, sed do ]
[eiusmod tempor incididunt ut lab]
[ore et dolore magna aliqua.]
"

Jusqu'ici, cela ne fait que couper la chaîne à exactement 32 caractères. Cela fonctionne car ses propres insertions de nouvelle ligne marquent le début de chaque séquence après la première.

Pour rompre les mots, un qualificatif est nécessaire après le quantificateur glouton {1,32} pour l'empêcher de choisir des séquences se terminant au milieu d'un mot. Un caractère Word-break \b peut créer des espaces au début de nouvelles lignes, donc un caractère espace-blanc \s doit être utilisé à la place. Il doit également être placé à l'extérieur du groupe pour qu'il soit mangé afin d'éviter d'augmenter la largeur maximale d'un caractère:

str.replace(/([^\n]{1,32})\s/g, '[$1]\n');
// Matches wrapped in [] to help visualise

"[Lorem ipsum dolor sit amet,]
[consectetur adipiscing elit, sed]
[do eiusmod tempor incididunt ut]
[labore et dolore magna]
aliqua."

À présent, il se brise sur les mots avant la limite, mais le dernier mot et le dernier point n'ont pas été mis en correspondance dans la dernière séquence car il n'y a pas d'espace de fin.

Une option "ou fin de chaîne" (\s|$) pourrait être ajoutée à l'espace blanc pour étendre la correspondance, mais il serait même préférable d'éviter de faire correspondre la dernière ligne du tout car cela provoque une nouvelle -ligne à insérer à la fin. Pour ce faire, il est possible d’ajouter une veille négative sur exactement la même séquence before , mais en utilisant un caractère de fin de chaîne au lieu d’un caractère d’espace:

str.replace(/(?![^\n]{1,32}$)([^\n]{1,32})\s/g, '[$1]\n');
// Matches wrapped in [] to help visualise

"[Lorem ipsum dolor sit amet,]
[consectetur adipiscing elit, sed]
[do eiusmod tempor incididunt ut]
labore et dolore magna aliqua."
10
Thomas Brierley

Ma variante. Il garde les mots intacts, de sorte qu'il ne répond pas toujours au critère maxChars. 

function wrapText(text, maxChars) {
        var ret = [];
        var words = text.split(/\b/);

        var currentLine = '';
        var lastWhite = '';
        words.forEach(function(d) {
            var prev = currentLine;
            currentLine += lastWhite + d;

            var l = currentLine.length;

            if (l > maxChars) {
                ret.Push(prev.trim());
                currentLine = d;
                lastWhite = '';
            } else {
                var m = currentLine.match(/(.*)(\s+)$/);
                lastWhite = (m && m.length === 3 && m[2]) || '';
                currentLine = (m && m.length === 3 && m[1]) || currentLine;
            }
        });

        if (currentLine) {
            ret.Push(currentLine.trim());
        }

        return ret.join("\n");
    }
3
Stephan

De nombreux comportements de ce type peuvent être obtenus de manière linéaire avec des expressions régulières (en utilisant des quantificateurs non gloutons avec un nombre minimal de caractères correspondants ou des quantificateurs gloutons avec un nombre maximal de caractères, en fonction du comportement souhaité). 

Ci-dessous, un remplacement global non-glouton est montré, fonctionnant dans le NPL V8 REPL, vous pouvez ainsi voir la commande et le résultat. Cependant, la même chose devrait fonctionner dans un navigateur. 

Ce modèle recherche au moins 10 caractères correspondant à un groupe défini (\ w signifie caractères Word,\s signifie espaces blancs), et ancre le modèle contre une limite de mot\b. Il utilise ensuite une référence arrière pour remplacer la correspondance d'origine par une correspondance comportant une nouvelle ligne (dans ce cas, remplace éventuellement un caractère d'espacement qui n'est pas capturé dans la référence arrière entre crochets).

> s = "This is a paragraph with several words in it."
'This is a paragraph with several words in it.'
> s.replace(/([\w\s]{10,}?)\s?\b/g, "$1\n")
'This is a \nparagraph \nwith several\nwords in it\n.'

Dans le format demandé par l'affiche originale, cela pourrait ressembler à ...

var str = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It w as popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.";

function wordWrap(text,width){
    var re = new RegExp("([\\w\\s]{" + (width - 2) + ",}?\\w)\\s?\\b", "g")
    return text.replace(re,"$1\n")
}

> wordWrap(str,40)
'Lorem Ipsum is simply dummy text of the\nprinting and typesetting industry. Lorem Ipsum has been the industry\'s standard dummy text ever since the 1500s\n, when an unknown printer took a galley of\ntype and scrambled it to make a type specimen\nbook. It has survived not only five centuries\n, but also the leap into electronic typesetting\n, remaining essentially unchanged. It w as popularised in the 1960s with the\nrelease of Letraset sheets containing Lorem\nIpsum passages, and more recently with desktop publishing\nsoftware like Aldus PageMaker including\nversions of Lorem Ipsum.'
3
cefn

Ma version. Il retourne un tableau de lignes au lieu d'une chaîne, car il est plus flexible quant aux séparateurs de lignes que vous souhaitez utiliser (comme newline ou html BR). 

function wordWrapToStringList (text, maxLength) {
    var result = [], line = [];
    var length = 0;
    text.split(" ").forEach(function(Word) {
        if ((length + Word.length) >= maxLength) {
            result.Push(line.join(" "));
            line = []; length = 0;
        }
        length += Word.length + 1;
        line.Push(Word);
    });
    if (line.length > 0) {
        result.Push(line.join(" "));
    }
    return result;
};

Pour convertir le tableau de lignes en chaîne en chaîne:

wordWrapToStringList(textToWrap, 80).join('<br/>');

S'il vous plaît noter que cela ne fait que Word Wrap et ne cassera pas les mots longs, et ce n'est probablement pas le plus rapide.

3

Voici une réponse étendue basée sur la solution de javabeangrinder qui englobe également le texte pour une saisie multi-paragraphes: 

  function wordWrap(str, width, delimiter) {
    // use this on single lines of text only

    if (str.length>width) {
      var p=width
      for (; p > 0 && str[p] != ' '; p--) {
      }
      if (p > 0) {
        var left = str.substring(0, p);
        var right = str.substring(p + 1);
        return left + delimiter + wordWrap(right, width, delimiter);
      }
    }
    return str;
  }

  function multiParagraphWordWrap(str, width, delimiter) {
    // use this on multi-paragraph lines of text

    var arr = str.split(delimiter);

    for (var i = 0; i < arr.length; i++) {
        if (arr[i].length > width)
          arr[i] = wordWrap(arr[i], width, delimiter);
    }

    return arr.join(delimiter);
  }
1
Joshua Olson

Après avoir recherché la solution parfaite en utilisant regex et d’autres implémentations. J'ai décidé de redresser la mienne. Ce n’est pas parfait mais cela a fonctionné Bien pour mon cas, peut-être que cela ne fonctionnera pas correctement si vous avez tout votre texte en majuscule.

function breakTextNicely(text, limit, breakpoints) {

      var parts = text.split(' ');
      var lines = [];
      text = parts[0];
      parts.shift();

      while (parts.length > 0) {
        var newText = `${text} ${parts[0]}`;

        if (newText.length > limit) {
          lines.Push(`${text}\n`);
          breakpoints--;

          if (breakpoints === 0) {
            lines.Push(parts.join(' '));
            break;
          } else {
          	text = parts[0];
    	  }
        } else {
          text = newText;
        }
    	  parts.shift();
      }

      if (lines.length === 0) {
        return text;
      } else {
        return lines.join('');
      }
    }

    var mytext = 'this is my long text that you can break into multiple line sizes';
    console.log( breakTextNicely(mytext, 20, 3) );

0
fpauer
function GetWrapedText(text, maxlength) {    
    var resultText = [""];
    var len = text.length;    
    if (maxlength >= len) {
        return text;
    }
    else {
        var totalStrCount = parseInt(len / maxlength);
        if (len % maxlength != 0) {
            totalStrCount++
        }

        for (var i = 0; i < totalStrCount; i++) {
            if (i == totalStrCount - 1) {
                resultText.Push(text);
            }
            else {
                var strPiece = text.substring(0, maxlength - 1);
                resultText.Push(strPiece);
                resultText.Push("<br>");
                text = text.substring(maxlength - 1, text.length);
            }
        }
    }
    return resultText.join("");
}
0
Ashutosh Pathak

Fatigué des expressions régulières et des fonctions difficiles à lire? Vous pouvez envelopper des textes en utilisant les méthodes Array intégrées. Voici une façon de faire (remplacez simplement la limite 100 par la longueur souhaitée):

let string = 'Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry\'s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.';

string.split(' ').map((value, index, array) => {
    if (!array.currentLineLength) {array.currentLineLength = 0}
    array.currentLineLength += value.length+1;
    if (array.currentLineLength > 100) {
        array.currentLineLength = value.length;
        return "\n" + value;
    }
    return value;
}).join(' ');

Peut-être aimeriez-vous également mettre ce texte en retrait sur chaque ligne? Aucun problème, vous pouvez simplement ajouter ceci après la dernière join:

.split("\n").map(value => ''.padEnd(20) + value).join("\n");
0
Nicolas Bouvrette