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.
However, not all the elements overflow.
Is there anyway I can use javascript to detect which elements are overflowing?
Thanks.
Added: example HTML structure I am working with.
<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.
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.
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:
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/
You could even create your own custom pseudo-selector for 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/
Hopefully this helps, hacky as it is.
Try this JS function, passing the span element as argument:
function isEllipsisActive(e) {
return (e.offsetWidth < e.scrollWidth);
}
Adding to italo's answer, you can also do this using 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().
function isEllipsisActive($jQueryObject) {
return ($jQueryObject.outerWidth() < $jQueryObject[0].scrollWidth);
}
For those using (or planning to use) the accepted answer from Christian Varga, please be aware of the performance issues.
Cloning/manipulating the DOM in such a way causes DOM Reflow (see an explanation on DOM reflow here) which is extremely resource intensive.
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.
Italo Borssatto's answer should be the accepted one, it was approximately 10 times quicker during my profiling.
elem.offsetWdith VS ele.scrollWidth This work for me! https://jsfiddle.net/gustavojuan/210to9p1/
$(function() {
$('.endtext').each(function(index, elem) {
debugger;
if(elem.offsetWidth !== elem.scrollWidth){
$(this).css({color: '#FF0000'})
}
});
});
The simplest (and cross-browser) solution is actually comparing scrollWidth with clientWidth
Working code here : https://stackoverflow.com/a/19156627/1213445
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/
It works on all version of jQuery
Answer from italo is very good! However let me refine it a little:
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.
So, depending on the font size you use, allow a certain tolerance!
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
work like 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
work like this
you can detect like this
All the solutions did not really work for me, what did work was compare the elements scrollWidth
to the scrollWidth
of its parent (or child, depending on which element has the trigger).
When the child's scrollWidth
is higher than its parents, it means .text-ellipsis
is active.
When event
is the parent element
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
function isEllipsisActive(event) {
let el = event.currentTarget;
let width = el.offsetWidth;
let widthParent = el.parentElement.scrollWidth;
return (width >= widthParent);
}
The e.offsetWidth < e.scrollWidth
solution is not always working.
And if you want to use pure JavaScript, I recommend to use this:
(typescript)
public isEllipsisActive(element: HTMLElement): boolean {
element.style.overflow = 'initial';
const noEllipsisWidth = element.offsetWidth;
element.style.overflow = 'hidden';
const ellipsisWidth = element.offsetWidth;
if (ellipsisWidth < noEllipsisWidth) {
return true;
} else {
return false;
}
}
来源:https://stackoverflow.com/questions/7738117/html-text-overflow-ellipsis-detection