截断长字符串的智能方法


184

有没有人比显而易见的解决方案/库更复杂的解决方案/库,用于使用JavaScript截断字符串并在末尾添加省略号:

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

5
“更复杂”是什么意思?考虑单词边界的功能?
Residuum

1
而且不要在HTML标记中间截断。
Sz。

Answers:


363

本质上,您检查给定字符串的长度。如果长度超过给定的长度n,请将其裁剪为length nsubstrslice),然后将html实体…(…)添加到裁剪的字符串中。

这样的方法看起来像

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

如果“更复杂”是指在字符串的最后一个单词边界处截断,则需要进行额外的检查。首先,将字符串裁剪为所需的长度,然后将其结果裁剪为其最后一个单词的边界

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

您可以String使用函数扩展本机原型。在这种情况下,str应删除参数,并str在函数内将其替换为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;";
};

更具教条主义的开发人员可能会对此深表歉意(“ 不要修改您不拥有的对象 ”。不过我不介意)。

不扩展String原型的一种方法是创建自己的帮助器对象,其中包含您提供的(长)字符串以及前面提到的截断它的方法。这就是下面的代码片段。

最后,您只能使用css截断HTML节点中的长字符串。它给您的控制较少,但可能是可行的解决方案。


5
还应该考虑具有“硬”和“软”限制,例如,如果字符串长于500个字符,则将其截断为400。当用户希望查看整个文本并单击某些链接时,这可能很有用。为了它。结果,如果只加载1或2个字符,则看起来会很丑陋。
Maxim Sloyko,2009年

2
第二个参数to substr是一个长度,因此应该将substr(0,n)其限制为第一个n字符。
JohnnyHK

10
不要修改您不拥有的对象。nczonline.net/blog/2010/03/02/…–
查理·基利安

5
您可能要考虑的一件事是在代码示例中将替换为&hellip;实际的省略号(...)。如果您尝试使用它与API进行交互,则需要非HTML实体。
AlbertEngelB 2014年

1
@RuneJeppesen你是对的。调整方法。为我辩护:答案可以追溯到7年
以前

62

请注意,这只需要针对Firefox完成。

所有其他浏览器都支持CSS解决方案(请参阅支持表):

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 */
}

具有讽刺意味的是,我从Mozilla MDC获得了该代码段。



哇,这是移动Safari的完美解决方案。谢谢!
samvermette

9
很好的CSS方法。可能需要注意的是,这仅适用于一行文本(如所预期white-space: nowrap;)。当涉及到多行内容时,您将不得不使用JavaScript。
2012年

它也仅适用于整个元素。如果您想截断字符串的一部分,而没有将要截断的位包装在span或其他html元素中,则将无法正常工作,例如:Your picture ('some very long picture filename truncated...') has been uploaded.
Chris

1
OP特别要求使用JavaScript解决方案
vsync

24

人们可能有理由希望使用JavaScript而不是CSS进行此操作。

在JavaScript中将其截断为8个字符(包括省略号):

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

要么

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

如果计算省略号,则为9个字符。如果您需要截断后将其设为8,请.replace(/^(.{7}).{2,}/, "$1…");改用
Okku,

long并且short由较旧的ECMAScript规范(ECMAScript 1至3)保留作为将来的关键字。见MDN:未来预留老年标准关键字
里卡多


7

这是我的解决方案,与其他建议相比有一些改进:

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

它:

  • 在25个字符后的第一个空格处截断
  • 扩展JavaScript String对象,因此可以在任何字符串上使用(并链接到它)。
  • 如果截断导致尾随空格,将修剪字符串;
  • 如果截断的字符串超过25个字符,将添加unicode hellip实体(省略号)

7

我发现的最佳功能。归功于文字省略号

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

例子

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"

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

以上代码某种程度上不适用于vuejs应用程序中的某种复制粘贴或书面文本。所以我用lodash截断了,现在可以正常工作了。

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

不错的现代答案!
ykonda

我很想知道案文是什么。是否使用非拉丁字符?
亚当·莱格特

这只是lorem ipsum
Afraz Ahmad

5

现在,所有现代浏览器都支持简单的CSS解决方案,如果一行文本超出了可用宽度,则会自动添加省略号:

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

(请注意,这需要以某种方式限制元素的宽度,才能产生效果。)

基于https://css-tricks.com/snippets/css/truncate-string-with-ellipsis/

应当指出的是,这种方法并没有基于字符数限制。它也没有,如果你需要允许多行文本工作。


2
这仅对单行句子有用,到目前为止(据我所知)没有办法通过CSS进行多行示例。
Hooman Askari

有没有机会使它做到左边而不是右边的省略号?
GreenAsJade

1
@GreenAsJade我相信您可以使用text-direction: rtl和来实现text-align: left。参见davidwalsh.name/css-ellipsis-left
肖恩·比恩

4

大多数现代JavaScript框架(JQuery的原型 ...)都上涨到字符串处理这一实用功能。

这是原型中的一个示例:

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

这似乎是您希望其他人处理/维护的功能之一。我会让框架处理它,而不是编写更多代码。


8
我认为jQuery对此没有任何帮助。
Alex

2
。Underscore.js确实- _( '你好世界')截断(5)=> '喂...' _( '你好')截断(10)=> '你好'。
JayCrossler

3
Pure Underscore似乎也truncate()没有-您可能需要扩展名,例如underscore.string
马丁

2
这是完全正确的答案。我不知道下划线,但是lodash _.trunc确实做到了这一点。
leftclickben 2015年

2
我认为正确的答案是使用lodash.trunc或underscore.string.truncate。
ooolala 2016年

2

也许我错过了一个示例,其中有人在处理空值,但是当我有空值时,有3个TOP答案对我不起作用(当然,我知道错误处理是一百万个其他事情也不是回答问题的人的责任,但是我使用了现有功能以及出色的截断省略号答案之一,我认为我会为其他人提供它。

例如

javascript:

news.comments

使用截断功能

news.comments.trunc(20, true);

但是,如果news.comments为null, 则将“中断”

最后

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

截断功能由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_;
 };

我简单的null检查器(也检查文字“ null”东西(它捕获未定义,“”,null,“ null”等)。

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

这是一个修改后的版本-避免使用原型,在函数中合并了null检查,并具有一些测试/演示用法。codepen.io/mahemoff/pen/LGEdzy
mahemoff 2015年

您是否发现原型有问题?只是好奇
Tom Stickel 2015年

我使用单独的null检查函数的原因是它实际上将检查null,undefined,NaN,空字符串(“”),0,false和“ null”,但是总体而言,我喜欢您的fx
Tom Stickel

1
是的,这是一个观点和使用上下文的问题,但是当您与其他库一起使用时,原型会变得很丑陋,因为它们也可能会覆盖同一件事。(或者在极少数情况下,稍后可能会引入相同名称的功能作为标准语言功能。)
mahemoff 2015年

是的,我同意你的说法
汤姆Stickel

2

有时,文件名会被编号,其中索引可能位于开头或结尾。所以我想从字符串的中心开始缩短:

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

请注意,我在UTF-8中使用的填充字符超过1个字节。



1

我赞成Kooilnc的解决方案。非常好的紧凑型解决方案。我想解决一个小问题。如果有人出于任何原因输入了一个很长的字符序列,它将不会被截断:

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

快速浏览Google,我发现了这一点 ……对您有用吗?

/**
 * 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

1

文本溢出:省略号是您需要的属性。有了这个和溢出:隐藏一个特定的宽度,所有超出的内容都会在最后得到三个周期的效果。...别忘了添加空白:nowrap,否则文本将被放置在多行中。

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

1
简短是可以接受的,但是更充分的解释会更好。
Armali

mwilcoxSean Bean已经发布了此解决方案。
安德鲁·迈尔斯,

1
只能用于单行文本
Vally Pepyako '19

文本溢出:省略号是完美的!
zardilior

0

我认为c_harm的答案是最好的。请注意,如果您想使用

"My string".truncate(n)

您将必须使用regexp对象构造函数而不是文字。另外\S,转换时必须转义。

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

大家都听说过评论和适当的变量命名吗?
骑自行车

@bicycle是从上面的另一个答案复制和修改的代码,无需如此粗鲁和狡猾。
马特·弗莱彻

0

使用以下代码

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

0

纠正Kooilnc的解决方案:

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

如果不需要将其截断,则返回字符串值而不是String对象。


这不能为问题提供答案。要批评或要求作者澄清,请在其帖子下方发表评论-您可以随时对自己的帖子发表评论,一旦您拥有足够的声誉,就可以在任何帖子中发表评论
Spencer Wieczorek

啊,我现在看到了区别。感谢您的参考。我确实想发表评论,希望@Kooilnc能够看到它,如果他或她同意但可能没有声誉,可以编辑接受的答案。
qwales1 2014年

0

我最近不得不这样做,最终导致:

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

给我感觉很干净:)


1
这可能会使结果字符串比限制长3个字符。
Hauke '18

0

我喜欢使用.slice()第一个参数是起始索引,第二个参数是结束索引。介于两者之间的一切就是您得到的回报。

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

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

0

聪明的地方: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

此功能还可以截断空格和单词部分。(例如:Mother into Moth ...)

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

用法:

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

输出:

这是...

12345 ...

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.