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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 03:23:35  来源:igfitidea点击:

HTML text-overflow ellipsis detection

javascripthtmlcssellipsis

提问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.

Italo Borssatto 的答案应该是公认的答案,在我的分析过程中,它的速度大约快了 10 倍。

回答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.logto print out the values of e.offsetWidthand e.scrollWidth, you will notice, on IE, that, even when you have no text truncation, a value difference of 1pxor 2pxis experienced.

事实上,如果你尝试上面的代码并使用console.log打印出e.offsetWidthand的值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

这里的工作代码: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 scrollWidthto the scrollWidthof its parent (or child, depending on which element has the trigger).

所有的解决方案并没有真正为我工作,怎么工作的要素比较scrollWidthscrollWidth其父(或子女,这取决于哪个元素具有触发)。

When the child's scrollWidthis higher than its parents, it means .text-ellipsisis active.

当孩子的scrollWidth比父母高时,就意味着.text-ellipsis活跃。



When eventis the parent element

什么时候event是父元素

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


When eventis 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 topvalue.

我认为检测它的更好方法是使用getClientRects(),似乎每个矩形都具有相同的高度,因此我们可以使用不同top值的数量计算行数。

getClientRectswork 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;
}

getRowRectswork like this

getRowRects这样工作

you can detect like this

你可以发现像这样