Обнаружение многоточия переполнения текста HTML - PullRequest
147 голосов
/ 12 октября 2011

У меня есть коллекция блочных элементов на странице.У всех них есть правила CSS: пробел, переполнение, переполнение текста, так что переполняемый текст обрезается и используется многоточие.

Однако не все элементы переполняются.

Есть лиВ любом случае, я могу использовать javascript для определения, какие элементы переполнены?

Спасибо.

Добавлено: пример структуры HTML, с которой я работаю.

<td><span>Normal text</span></td>
<td><span>Long text that will be trimmed text</span></td>

Элементы SPAN всегда подходятв ячейках применяется правило эллипса.Я хочу определить, когда многоточие применяется к текстовому содержимому SPAN.

Ответы [ 10 ]

228 голосов
/ 04 апреля 2012

Попробуйте эту функцию JS, передав элемент span в качестве аргумента:

function isEllipsisActive(e) {
     return (e.offsetWidth < e.scrollWidth);
}
105 голосов
/ 12 октября 2011

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

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

Например, используя jQuery:

var $element = $('#element-to-test');
var $c = $element
           .clone()
           .css({display: 'inline', width: 'auto', visibility: 'hidden'})
           .appendTo('body');

if( $c.width() > $element.width() ) {
    // text was truncated. 
    // do what you need to do
}

$c.remove();

Я сделал jsFiddle, чтобы продемонстрировать это, http://jsfiddle.net/cgzW8/2/

Вы даже можете создать свой собственный псевдоселектор для jQuery:

$.expr[':'].truncated = function(obj) {
  var $this = $(obj);
  var $c = $this
             .clone()
             .css({display: 'inline', width: 'auto', visibility: 'hidden'})
             .appendTo('body');

  var c_width = $c.width();
  $c.remove();

  if ( c_width > $this.width() )
    return true;
  else
    return false;
};

Затем использовать его для поиска элементов

$truncated_elements = $('.my-selector:truncated');

Демонстрация: http://jsfiddle.net/cgzW8/293/

Надеюсь, этопомогает, хакер как есть.

13 голосов
/ 10 октября 2013

Добавляя к ответу italo, вы также можете сделать это с помощью jQuery.

function isEllipsisActive($jQueryObject) {
    return ($jQueryObject.width() < $jQueryObject[0].scrollWidth);
}

Кроме того, как отметил Смоки, вы можете использовать jQuery outerWidth () вместо width ().

function isEllipsisActive($jQueryObject) {
    return ($jQueryObject.outerWidth() < $jQueryObject[0].scrollWidth);
}
7 голосов
/ 08 июня 2017

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

Клонирование / манипулирование DOM таким способом вызывает Переработка DOM (см. объяснение перекомпоновки DOM * здесь 1006 *), что чрезвычайно ресурсоемко.

Использование решения Кристиана Варги для 100+ элементов на странице вызвало 4-секундную задержку перекомпоновки, во время которой поток JSзаблокированУчитывая, что JS является однопоточным, это означает значительную задержку UX для конечного пользователя.

Ответ Итало Борссатто должен быть принят, он был примерно в 10 раз быстрее во время моего профилирования.

5 голосов
/ 27 апреля 2017

Самым простым (и кросс-браузерным) решением является сравнение scrollWidth с clientWidth

Рабочий код: https://stackoverflow.com/a/19156627/1213445

5 голосов
/ 08 февраля 2016

elem.offsetWdith VS ele.scrollWidth Это работа для меня! https://jsfiddle.net/gustavojuan/210to9p1/

$(function() {
  $('.endtext').each(function(index, elem) {
    debugger;
    if(elem.offsetWidth !== elem.scrollWidth){
      $(this).css({color: '#FF0000'})
    }
  });
});
4 голосов
/ 07 августа 2015

В этом примере показывается всплывающая подсказка для таблицы ячеек с усеченным текстом. Является динамическим в зависимости от ширины таблицы:

$.expr[':'].truncated = function (obj) {
    var element = $(obj);

    return (element[0].scrollHeight > (element.innerHeight() + 1)) || (element[0].scrollWidth > (element.innerWidth() + 1));
};

$(document).ready(function () {
    $("td").mouseenter(function () {
        var cella = $(this);
        var isTruncated = cella.filter(":truncated").length > 0;
        if (isTruncated) 
            cella.attr("title", cella.text());
        else 
            cella.attr("title", null);
    });
});

Демо: https://jsfiddle.net/t4qs3tqs/

Работает на всех версиях jQuery

3 голосов
/ 02 февраля 2016

Ответ от итало очень хорошо!Однако позвольте мне немного его уточнить:

function isEllipsisActive(e) {
   var tolerance = 2; // In px. Depends on the font you are using
   return e.offsetWidth + tolerance < e.scrollWidth;
}

Кросс-браузерная совместимость

Если вы на самом деле пытаетесь использовать приведенный выше код и используете console.log, чтобы распечатать значения e.offsetWidthи e.scrollWidth, вы заметите, что в IE, даже если у вас нет усечения текста, возникает разница значений 1px или 2px.

Таким образом, в зависимости от размера шрифта, который выиспользуйте, допускайте определенный допуск!

1 голос
/ 20 октября 2017

Все решения на самом деле не работали для меня, то, что сделал , работало, сравнивало элементы scrollWidth с scrollWidth его родителя (или потомка, в зависимости от того, какой элемент имеет триггер).

Когда scrollWidth у ребенка выше, чем у его родителей, это означает, что .text-ellipsis активен.


Когда event является родительским элементом

function isEllipsisActive(event) {
    let el          = event.currentTarget;
    let width       = el.offsetWidth;
    let widthChild  = el.firstChild.offsetWidth;
    return (widthChild >= width);
}

Когда event является дочерним элементом

function isEllipsisActive(event) {
    let el          = event.currentTarget;
    let width       = el.offsetWidth;
    let widthParent = el.parentElement.scrollWidth;
    return (width >= widthParent);
}
1 голос
/ 07 марта 2016

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

getClientRects работает как это

function getRowRects(element) {
    var rects = [],
        clientRects = element.getClientRects(),
        len = clientRects.length,
        clientRect, top, rectsLen, rect, i;

    for(i=0; i<len; i++) {
        has = false;
        rectsLen = rects.length;
        clientRect = clientRects[i];
        top = clientRect.top;
        while(rectsLen--) {
            rect = rects[rectsLen];
            if (rect.top == top) {
                has = true;
                break;
            }
        }
        if(has) {
            rect.right = rect.right > clientRect.right ? rect.right : clientRect.right;
            rect.width = rect.right - rect.left;
        }
        else {
            rects.push({
                top: clientRect.top,
                right: clientRect.right,
                bottom: clientRect.bottom,
                left: clientRect.left,
                width: clientRect.width,
                height: clientRect.height
            });
        }
    }
    return rects;
}

getRowRects работает как это

вы можете обнаружить, как это

...