Javascript HTML 文本溢出省略号检测
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7738117/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
HTML text-overflow ellipsis detection
提问by deanoj
I have a collection of block elements on a page. They all have the CSS rules white-space, overflow, text-overflow set so that overflowing text is trimmed and an ellipsis is used.
我在页面上有一组块元素。它们都设置了 CSS 规则 white-space、overflow、text-overflow,以便修剪溢出的文本并使用省略号。
However, not all the elements overflow.
但是,并非所有元素都会溢出。
Is there anyway I can use javascript to detect which elements are overflowing?
无论如何我可以使用javascript来检测哪些元素溢出?
Thanks.
谢谢。
Added: example HTML structure I am working with.
添加:我正在使用的示例 HTML 结构。
<td><span>Normal text</span></td>
<td><span>Long text that will be trimmed text</span></td>
The SPAN elements always fit in the cells, they have the ellipsis rule applied. I want to detect when the ellipsis is applied to the text content of the SPAN.
SPAN 元素总是适合单元格,它们应用了省略号规则。我想检测省略号何时应用于 SPAN 的文本内容。
采纳答案by Christian
Once upon a time I needed to do this, and the only cross-browser reliable solution I came across was hack job. I'm not the biggest fan of solutions like this, but it certainly produces the correct result time and time again.
曾几何时,我需要这样做,而我遇到的唯一跨浏览器可靠解决方案是 hack 工作。我不是这样的解决方案的最大粉丝,但它肯定会一次又一次地产生正确的结果。
The idea is that you clone the element, remove any bounding width, and test if the cloned element is wider than the original. If so, you know it's going to have been truncated.
这个想法是你克隆元素,删除任何边界宽度,并测试克隆的元素是否比原始元素宽。如果是这样,您知道它将被截断。
For example, using jQuery:
例如,使用 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();
I made a jsFiddle to demonstrate this, http://jsfiddle.net/cgzW8/2/
我做了一个 jsFiddle 来演示这一点,http://jsfiddle.net/cgzW8/2/
You could even create your own custom pseudo-selector for jQuery:
您甚至可以为 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;
};
Then use it to find elements
然后用它来查找元素
$truncated_elements = $('.my-selector:truncated');
Demo: http://jsfiddle.net/cgzW8/293/
演示:http: //jsfiddle.net/cgzW8/293/
Hopefully this helps, hacky as it is.
希望这会有所帮助,尽管如此。
回答by Italo Borssatto
Try this JS function, passing the span element as argument:
试试这个 JS 函数,将 span 元素作为参数传递:
function isEllipsisActive(e) {
return (e.offsetWidth < e.scrollWidth);
}
回答by Alex K
Adding to italo's answer, you can also do this using jQuery.
添加到 italo 的答案中,您也可以使用 jQuery 来做到这一点。
function isEllipsisActive($jQueryObject) {
return ($jQueryObject.width() < $jQueryObject[0].scrollWidth);
}
Also, as Smoky pointed out, you may want to use jQuery outerWidth() instead of width().
此外,正如 Smoky 所指出的,您可能希望使用 jQuery 外层宽度()而不是宽度()。
function isEllipsisActive($jQueryObject) {
return ($jQueryObject.outerWidth() < $jQueryObject[0].scrollWidth);
}
回答by RyanGled
For those using (or planning to use) the accepted answer from Christian Varga, please be aware of the performance issues.
对于那些使用(或计划使用)Christian Varga 接受的答案的人,请注意性能问题。
Cloning/manipulating the DOM in such a way causes DOM Reflow(see an explanation on DOM reflowhere) which is extremely resource intensive.
以这种方式克隆/操作 DOM 会导致DOM 重排(请参阅此处对 DOM 重排的解释),这是非常耗费资源的。
Using Christian Varga's solution on 100+ elements on a page caused a 4 second reflow delay during which the JS thread is locked. Considering JS is single-threaded this means a significant UX delay to the end user.
在页面上的 100 多个元素上使用 Christian Varga 的解决方案会导致 4 秒的回流延迟,在此期间 JS 线程被锁定。考虑到 JS 是单线程的,这对最终用户来说意味着显着的 UX 延迟。
Italo Borssatto's answershould be the accepted one, it was approximately 10 times quicker during my profiling.
回答by Andry
Answer from italois very good! However let me refine it a little:
来自italo 的回答非常好!不过让我稍微细化一下:
function isEllipsisActive(e) {
var tolerance = 2; // In px. Depends on the font you are using
return e.offsetWidth + tolerance < e.scrollWidth;
}
Cross browser compatibility
跨浏览器兼容性
If, in fact, you try the above code and use console.log
to print out the values of e.offsetWidth
and e.scrollWidth
, you will notice, on IE, that, even when you have no text truncation, a value difference of 1px
or 2px
is experienced.
事实上,如果你尝试上面的代码并使用console.log
打印出e.offsetWidth
and的值e.scrollWidth
,你会注意到,在 IE 上,即使你没有文本截断,也经历了1px
或的值差异2px
。
So, depending on the font size you use, allow a certain tolerance!
因此,根据您使用的字体大小,允许有一定的公差!
回答by Gustavo Juan
elem.offsetWdith VS ele.scrollWidth This work for me! https://jsfiddle.net/gustavojuan/210to9p1/
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'})
}
});
});
回答by NicolasBernier
The simplest (and cross-browser) solution is actually comparing scrollWidth with clientWidth
最简单(和跨浏览器)的解决方案实际上是将 scrollWidth 与 clientWidth 进行比较
Working code here : https://stackoverflow.com/a/19156627/1213445
回答by Red
This sample show tooltip on cell table with text truncated. Is dynamic based on table width:
此示例在文本被截断的单元格表上显示工具提示。基于表格宽度是动态的:
$.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);
});
});
Demo: https://jsfiddle.net/t4qs3tqs/
演示:https: //jsfiddle.net/t4qs3tqs/
It works on all version of jQuery
它适用于所有版本的 jQuery
回答by Jeffrey Roosendaal
All the solutions did not really work for me, what didwork was compare the elements scrollWidth
to the scrollWidth
of its parent (or child, depending on which element has the trigger).
所有的解决方案并没有真正为我工作,怎么做工作的要素比较scrollWidth
给scrollWidth
其父(或子女,这取决于哪个元素具有触发)。
When the child's scrollWidth
is higher than its parents, it means .text-ellipsis
is active.
当孩子的scrollWidth
比父母高时,就意味着.text-ellipsis
活跃。
When event
is the parent element
什么时候event
是父元素
function isEllipsisActive(event) {
let el = event.currentTarget;
let width = el.offsetWidth;
let widthChild = el.firstChild.offsetWidth;
return (widthChild >= width);
}
When event
is the child element
什么时候event
是子元素
function isEllipsisActive(event) {
let el = event.currentTarget;
let width = el.offsetWidth;
let widthParent = el.parentElement.scrollWidth;
return (width >= widthParent);
}
回答by Defims
I think the better way to detect it is use getClientRects()
, it seems each rect has the same height, so we can caculate lines number with the number of different top
value.
我认为检测它的更好方法是使用getClientRects()
,似乎每个矩形都具有相同的高度,因此我们可以使用不同top
值的数量计算行数。
getClientRects
work like this
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
work like this
getRowRects
像这样工作
you can detect like this
你可以发现像这样