Обнаружение многоточия текстового переполнения 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);
}