Перенос Текста На JavaScript

Я новичок в JavaScript и jQuery.

у меня есть переменная с именем как str в JavaScript и содержит очень длинный текст, что-то вроде

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

Я хочу обернуть его и назначить его той же переменной str вставить правильный n или br/ теги в правильных местах.

Я не хочу использовать CSS и т. д. Не могли бы вы рассказать мне, как это сделать с помощью правильной функции в JavaScript, которая принимает str и возвращает правильный форматированный текст к нему?

что-то типа:

str = somefunction(str, maxchar);

Я много пробовал, но, к сожалению, ничего не получилось так, как я хотел! :(

любая помощь будет высоко ценится...

9 ответов


Это должно вставить разрыв строки в ближайшем пробеле 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));
};

вот немного более короткое решение:

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

эта функция использует рекурсию для решения проблемы.


мой вариант. Он сохраняет слова нетронутыми, поэтому он не всегда может соответствовать критерию 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");
    }

многие поведения, подобные этому, могут быть достигнуты как однострочные с использованием регулярных выражений (с использованием не-жадных кванторов с минимальным количеством совпадающих символов или жадных кванторов с максимальным количеством символов, в зависимости от того, какое поведение вам нужно).

ниже показана не-жадная глобальная замена, работающая в узле V8 REPL, поэтому вы можете увидеть команду и результат. Однако то же самое должно работать в браузере.

этот шаблон ищет at не менее 10 символов, соответствующих определенной группе (\w означает символы слова, \S означает пробелы), и привязывает шаблон к границе слова \b. Затем он использует backreference для замены исходного соответствия с добавлением новой строки (в этом случае необязательно заменяя пробел, который не захватывается в скобках backreference).

> 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, "\n")
'This is a \nparagraph \nwith several\nwords in it\n.'

в запрошенном формате оригинального плаката это может выглядеть так...

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,"\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.'

хотя этот вопрос довольно старый, многие решения, предоставленные до сих пор, более сложны и дороги, чем необходимо, как указал user2257198 - это полностью разрешимо с помощью короткого однострочного регулярного выражения.

однако я нашел некоторые проблемы с его решением, включая: wrapping после максимальная ширина, а не раньше, нарушение символов, явно не включенных в класс символов и не учитывая существующие символы новой строки, вызывающие запуск абзацы должны быть обрезаны в середине строки.

что привело меня к написанию моего собственного решения:

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

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

Бонусы

  • ручки любой char это не новая строка (e.G код).
  • правильно обрабатывает существующие новые строки (e.g пункты).
  • предотвращает нажатие пробелов на начало новых строк.
  • предотвращает добавление ненужной новой строки в конец строка.

объяснение

основная концепция просто найти непрерывные последовательности символов, которые не содержать новые строки [^\n], до нужной длины, e.g 32 {1,32}. Используя отрицание ^ в классе персонажа это гораздо более терпимым, избегая отсутствуют такие вещи, как знаки препинания, которые в противном случае должны быть добавлены:

str.replace(/([^\n]{1,32})/g, '[]\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.]
"

пока это только разрезает строку ровно на 32 символа. Это работает потому что это собственные вставки новой строки отмечают начало каждой последовательности после первой.

чтобы разбить на слова, квалификатор необходим после жадного квантора {1,32} чтобы предотвратить его от выбора последовательностей, заканчивающихся в середине слова. Слово-перерыв char \b может вызывать пробелы в начале новых строк, поэтому символ пробела \s должны использоваться вместо этого. Его также необходимо поместить вне группы поэтому он ел, для предотвращения увеличения максимальной ширины 1 char:

str.replace(/([^\n]{1,32})\s/g, '[]\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."

теперь он разбивается на слова перед пределом, но последнее слово и период не были сопоставлены в последней последовательности, потому что нет конечного пространства.

опция" или конец строки"(\s|$) может быть добавлен в Пробел, чтобы продлить матч, но было бы еще лучше, чтобы предотвратить соответствие последней строке на всех потому что это заставляет ненужную новую строку вставляться в конце. Добиться этого негативным взглядом-впереди ровно такая же последовательность может быть добавлена до, но используя символ конца строки вместо символа пробела:

str.replace(/(?![^\n]{1,32}$)([^\n]{1,32})\s/g, '[]\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."

моя версия. Он возвращает массив строк вместо строки, поскольку он более гибок в том, какие разделители строк вы хотите использовать (например, newline или 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;
};

чтобы преобразовать массив строк в строку в строку:

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

обратите внимание, что он только переносит слова и не ломает длинные слова, и это, вероятно, не самый быстрый.


вот расширенный ответ на основе решения javabeangrinder, который также обертывает текст для ввода нескольких абзацев:

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

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

после ищу идеальное решение, используя regex и другие реализации. Я решил исправить свою ошибку. Он не идеален, однако работал хорошо для моего случая, возможно, он не работает должным образом, когда у вас есть весь текст в верхнем регистре.

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