Умный способ обрезать длинные строки


188

Есть ли у кого-нибудь более изощренное решение / библиотека для усечения строк с помощью JavaScript и добавления многоточия к концу, чем очевидное:

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

5
Что вы подразумеваете под "более изощренным"? Функции, которые принимают во внимание границы слов?
Residuum

2
И не обрезать в середине HTML-теги.
СЗ

Ответы:


367

По сути, вы проверяете длину данной строки. Если он длиннее заданной длины n, обрежьте его по длине n( substrили slice) и добавьте 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 символа, это будет выглядеть ужасно.
Максим Слойко

2
Второй параметр substr- это длина, поэтому следует substr(0,n)ограничить его до первых nсимволов.
JohnnyHK

10
Не изменяйте объекты, которые вам не принадлежат. nczonline.net/blog/2010/03/02/…
Чарли Килиан

5
Одна вещь, которую вы могли бы рассмотреть, это заменить на &hellip;фактический многоточие ( ...) в вашем примере кода. Если вы пытаетесь использовать это для взаимодействия с API, вам понадобится не-HTML-сущность.
AlbertEngelB

1
@RuneJeppesen ты прав. Скорректированы методы. В мою защиту: ответ датируется 7 лет назад;)
KooiInc

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.


1
mattsnider.com/css/css-string-truncation-with-ellipsis, чтобы он работал и с FF.
Нил

Ух ты, это идеальное решение для мобильного Safari. Спасибо!
Самверметт

9
Очень хороший CSS-подход. Там может быть примечание, что это работает только с одной строкой текста (как задумано white-space: nowrap;). Когда дело касается нескольких строк, вы застряли в JavaScript.
insertusername здесь

Это также работает только для всего элемента. Если вы хотите обрезать часть строки без обрезания бита, который вы хотите обрезать, в span или другом HTML-элементе, это не сработает, например:Your picture ('some very long picture filename truncated...') has been uploaded.
Крис

1
ОП специально спросил о решении javascript
vsync

25

Есть веские причины, по которым люди могут захотеть сделать это на JavaScript вместо CSS.

Чтобы усечь до 8 символов (включая многоточие) в JavaScript:

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

или

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

1
Если вы посчитаете многоточие, это будет 9 символов. Если вам нужно 8 после усечения, используйте .replace(/^(.{7}).{2,}/, "$1…");вместо этого
Okku

longи shortзарезервированы как будущие ключевые слова в соответствии со старыми спецификациями ECMAScript (ECMAScript 1–3). См. MDN: будущие зарезервированные ключевые слова в старых стандартах
Рикардо,


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

Каким-то образом приведенный выше код не работал для некоторого текста, вставленного или написанного в приложении vuejs. Поэтому я использовал lodash truncate, и теперь он работает нормально.

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

хороший современный ответ!
ykonda

Мне было бы интересно узнать, что это за текст. Это было использование нелатинских символов?
Адам Леггетт

Это был просто Lorem Ipsum
Афраз Ахмад

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, поэтому его можно использовать с любой строкой (и связывать ее).
  • Обрезает строку, если усечение приводит к завершающему пробелу;
  • Добавит юникодную сущность hellip (многоточие), если длина усеченной строки превышает 25 символов

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"

5

Все современные браузеры теперь поддерживают простое решение CSS для автоматического добавления многоточия, если строка текста превышает доступную ширину:

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

(Обратите внимание, что для этого требуется, чтобы ширина элемента была каким-то образом ограничена.)

Основано на https://css-tricks.com/snippets/css/truncate-string-with-ellipsis/ .

Следует отметить, что этот подход не ограничивает количество символов. Это также не работает, если вам нужно разрешить несколько строк текста.


2
Это полезно только для однострочных предложений, пока нет способа (насколько я знаю) сделать многострочный пример с помощью CSS.
Хуман Аскари

Есть ли какой-нибудь способ заставить это сделать многоточие слева, а не справа?
GreenAsJade

1
@GreenAsJade Я считаю, что вы можете сделать это с помощью text-direction: rtlи text-align: left. См. Davidwalsh.name/css-ellipsis-left
Шон Боб

4

Большинство современных Javascript-фреймворков ( JQuery , Prototype и т. Д. ) Имеют встроенную функцию String, которая обрабатывает это.

Вот пример в Prototype:

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

Это похоже на одну из тех функций, которые вы хотите, чтобы кто-то еще имел дело с / поддерживал. Я бы позволил фреймворку справиться с этим, а не писать больше кода.


8
Я не думаю, что у jQuery есть что-то для этого.
Алекс

2
Underscore.js делает - _ ('Hello world'). Truncate (5) => 'Hello ...' _ ('Hello'). Truncate (10) => 'Hello'
JayCrossler

3
Pure Underscore, похоже, truncate()тоже не имеет - вам может понадобиться расширение, такое как underscore.string .
мартин

2
Это абсолютно правильный ответ. Я не знаю о подчеркивании, но у lodash есть _.truncименно это.
leftclickben

2
Я думаю, что правильный ответ - использовать lodash.trunc или underscore.string.truncate.
ооолала

2

Возможно, я пропустил пример, когда кто-то обрабатывает нули, но 3 ТОП-ответа не сработали для меня, когда у меня были нули (Конечно, я понимаю, что обработка ошибок и миллионы других вещей НЕ являются обязанностью человека, отвечающего на вопрос, но так как Я использовал существующую функцию вместе с одним из превосходных ответов об усеченном многоточии, которые, как я думал, я предоставлю для других.

например

JavaScript:

news.comments

используя функцию усечения

news.comments.trunc(20, true);

Тем не менее, на news.comments, являющихся нулевыми, это "сломается"

окончательный

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

Моя простая проверка нуля (тоже проверяет наличие буквального «нуля» (это ловит неопределенные, «», нуля, «нуля» и т. Д.)

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

Вот модифицированная версия - избегает использования прототипа, включает в себя нулевую проверку в функции и имеет некоторое тестовое / демонстрационное использование. codepen.io/mahemoff/pen/LGEdzy
mahemoff

Считаете ли вы прототип проблемным? Просто любопытно
Том Стиккель

Причина, по которой моя отдельная функция проверки нуля состоит в том, что она на самом деле будет проверять наличие нулевых, неопределенных, NaN, пустых строк (""), 0, ложных и "нулевых", но в целом мне нравится ваш fx
Том Стиккель

1
Да, это вопрос мнения и контекста использования, но прототип становится уродливым, когда вы работаете с другими библиотеками, поскольку они могут также переопределять то же самое. (Или в редких случаях функция с таким же именем может быть позже введена как стандартная языковая функция.)
mahemoff

Да, я согласен с вами
Том Стиккель

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

Имейте в виду, что я использовал здесь символ заполнения с более чем 1 байтом в UTF-8.


2

Переполнение текста: многоточие - это свойство, которое вам нужно. С этим и переполнением: скрыто с определенной шириной, все, что превосходит, что получит эффект трех периодов в конце ... Не забудьте добавить пробел: nowrap или текст будет помещен в несколько строк.

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

1
Краткость приемлема, но полные объяснения лучше.
Армали

Mwilcox и Шон Бин уже опубликовали это решение.
Эндрю Майерс

1
Может использоваться только для однострочного текста
Vally Pepyako

Текст переполнен: многоточие идеально!
Зардилиор


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

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, если его не нужно усекать.


Это не дает ответа на вопрос. Чтобы критиковать или запрашивать разъяснения у автора, оставьте комментарий под его постом - вы всегда можете комментировать свои собственные посты, и, когда у вас будет достаточно репутации, вы сможете комментировать любой пост .
Спенсер Вечорек

Ах, я вижу различие сейчас. Спасибо за ссылки. Я действительно хотел оставить комментарий с надеждой, что @Kooilnc его увидит, и, возможно, отредактирует принятый ответ, если он или она согласились, но не имели репутации.
qwales1

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 символа длиннее предела.
Хауке

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

Эта функция также усекает пространство и слова. (Например: Мать в Мотылек ...)

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.