簡體   English   中英

在 JavaScript 中換行

[英]Wrap Text In JavaScript

我是 JavaScript 和 jQuery 的新手。

我在 JavaScript 中有一個名為str的變量,它包含很長的文本,比如

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

我想通過在正確的位置插入正確的\nbr/標簽來包裝它並將其分配給相同的變量str

我不想使用 CSS 等。你能告訴我如何在str中使用正確的 function 來執行此操作嗎?

就像是:

str = somefunction(str, maxchar);

我嘗試了很多,但不幸的是沒有出現我想要的方式::(

任何幫助都感激不盡...

盡管這個問題已經很老了,但到目前為止提供的許多解決方案都比必要的復雜和昂貴,正如 user2257198 指出的那樣 - 這完全可以用一個簡短的單行正則表達式解決。

但是,我發現他的解決方案存在一些問題,包括:最大寬度之后而不是在最大寬度之前換行,中斷未明確包含在字符類中的字符,並且不考慮現有的換行符導致段落開頭被截斷中線。

這導致我編寫了自己的解決方案:

// Static Width (Plain Regex)
const wrap = (s) => 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'
);

獎勵功能

  • 處理任何不是換行符的字符(例如代碼)。
  • 正確處理現有的換行符(例如段落)。
  • 防止將空格推到換行符的開頭。
  • 防止在字符串末尾添加不必要的換行符。

解釋

主要概念只是找到包含換行符[^\\n]連續字符序列,直到所需的長度,例如 32 {1,32} 通過在字符類中使用否定^ ,它更加寬容,避免丟失標點符號之類的東西,否則必須明確添加:

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.]
"

到目前為止,這只會將字符串切成 32 個字符。 它起作用是因為它自己的換行插入標記了第一個序列之后的每個序列的開始。

為了中斷單詞,在貪婪量詞{1,32}之后需要一個限定符,以防止它選擇以單詞中間結尾的序列。 換行符\\b可能會在新行的開頭產生空格,因此必須改用空白字符\\s 它還必須放置在組外以便被吃掉,以防止將最大寬度增加 1 個字符:

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

現在它在限制之前的單詞上中斷,但最后一個單詞和句點在最后一個序列中不匹配,因為沒有終止空格。

“或字符串結尾”選項(\\s|$)可以添加到空格以擴展匹配,但最好完全阻止匹配最后一行因為它會導致不必要的新 -要在最后插入的行。 為了實現這一點,可以在之前添加完全相同序列的否定前瞻,但使用字符串結尾字符而不是空白字符:

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

這應該在最近的 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 = '';
    while (str.length > maxWidth) {                 
        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);
        }

    }

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

該函數使用遞歸來解決問題。

我的版本。 它返回一個行數組而不是一個字符串,因為它更靈活地使用您想要使用的行分隔符(如換行符或 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/>');

請注意,它只進行自動換行,不會斷掉長單詞,而且它可能不是最快的。

可以使用正則表達式(使用具有最少匹配字符數的非貪婪量詞或具有最大字符數的貪婪量詞,具體取決於您需要的行為)作為單行實現這樣的許多行為。

下面,顯示了在 Node V8 REPL 中工作的非貪婪全局替換,因此您可以看到命令和結果。 然而,同樣的應該在瀏覽器中工作。

此模式搜索至少 10 個與定義的組匹配的字符(\\w 表示單詞字符,\\s 表示空白字符),並將該模式​​錨定在 \\b 單詞邊界上。 然后它使用反向引用將原始匹配替換為附加了換行符的匹配(在這種情況下,可以選擇替換未在括號反向引用中捕獲的空格字符)。

> 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.'

在原始海報要求的格式中,這可能看起來像......

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.'

我的變種。 它保持單詞完整,因此它可能並不總是滿足 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");
    }

這是基於 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 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) );

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

厭倦了正則表達式和難以閱讀的函數? 您可以使用內置的Array方法對文本進行換行。 這是一種方法(只需將100限制替換為您想要的長度:

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

也許你還想在每一行縮進這個文本? 沒問題,您可以在最后一次join后簡單地添加:

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

我正在使用一個簡單的 ajax 和 javascript 練習來做到這一點

 var protest = "France is actually the worlds most bad country consisting of people and president full of mentaly gone persons and the people there are causing the disturbance and very much problem in the whole of the world.France be aware that one day there will be no france but you will be highly abused of your bad acts.France go to hell."; protest = protest.replace(/(.{100})/g, "$1<br>"); document.write(protest);

const newString = string.split(' ').reduce((acc, curr) => {
  if(acc[acc.length - 1].length > 100) {
    acc[acc.length - 1] = acc[acc.length - 1].concat(" ").concat(curr);
    acc.push(""); // new line
  } else {
    acc[acc.length - 1] = acc[acc.length - 1].concat(" ").concat(curr);
  }
  return acc;
}, [""]).join("\n");

console.log(newString)

我知道我來晚了,但只是想分享代碼以獲取任何評論/改進。 學習和即興編寫代碼總是很有趣的。

var text = "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).";
    
    function WordWrap(text, maxLength){
        if(!text) return 'Please provide text';
    
        const strWords = text.split(' ');
        let tempWord = ''; 
        let lineLength = 0;
    
        return strWords.reduce((acc, word) => {
            lineLength += word.length;
            
            if(lineLength > maxLength){
                lineLength = 0;
                tempWord = word;
                return `${acc} <br />`
            } else {
                const withTempWord = `${acc} ${tempWord} ${word}`;
                tempWord = '';
                return withTempWord;
            }
        }, '');
    };
    
    document.write(WordWrap(text, 14));

除了@Ross Rogers 和@ieeehh 你的回答。 代碼中的變量“done”按照找到的方式使用。 只是想不要這樣,以免別人混淆。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM