Обнаружение многоточия текстового переполнения HTML

У меня есть набор элементов блока на странице. Все они имеют правила CSS white-space, overflow, text-overflow, так что переполненный текст обрезается и используется многоточие.

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

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

Спасибо.

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

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

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

Ответ 1

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

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

Например, используя 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/

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

Ответ 2

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

function isEllipsisActive(e) {
     return (e.offsetWidth < e.scrollWidth);
}

Ответ 3

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

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

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

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

Ответ 4

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

Ответ 5

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

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

Ответ 6

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

Рабочий код здесь: fooobar.com/questions/15488/...

Ответ 7

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

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

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

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

Ответ 8

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

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.

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

Ответ 9

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

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

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 работает как this

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

Ответ 10

Все решения на самом деле не работали для меня, что работа сравнивала элементы 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);
}