programing tip

HTML 텍스트 오버플로 줄임표 감지

itbloger 2020. 6. 6. 08:45
반응형

HTML 텍스트 오버플로 줄임표 감지


페이지에 블록 요소 모음이 있습니다. 모두 CSS 규칙 공백, 오버플로, 텍스트 오버플로가 설정되어 넘쳐 나오는 텍스트가 잘리고 줄임표가 사용됩니다.

그러나 모든 요소가 오버플로되지는 않습니다.

어쨌든 자바 스크립트를 사용하여 어떤 요소가 오버플로하는지 감지 할 수 있습니까?

감사.

추가 된 예제 HTML 구조.

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

SPAN 요소는 항상 셀에 맞으며 줄임표 규칙이 적용됩니다. 줄임표가 SPAN의 텍스트 내용에 적용되는시기를 감지하고 싶습니다.


옛날 옛적에 나는 이것을해야했고, 내가 찾은 유일한 크로스 브라우저 신뢰할 수있는 솔루션은 해킹 작업이었습니다. 나는 이와 같은 솔루션의 가장 큰 팬은 아니지만 확실히 정확한 결과를 계속해서 산출합니다.

아이디어는 요소를 복제하고 경계 너비를 제거하고 복제 된 요소가 원본보다 넓은 지 테스트하는 것입니다. 그렇다면 잘릴 것입니다.

예를 들어, 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/

잘만되면 이것이 도움이 될 것입니다.


span 요소를 인수로 전달하여이 JS 함수를 시도하십시오.

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

italo의 답변에 추가하여 jQuery를 사용 하여이 작업을 수행 할 수도 있습니다.

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

또한 Smoky가 지적했듯이 width () 대신 jQuery outerWidth ()를 사용할 수 있습니다.

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

Christian Varga의 대답을 사용하거나 사용하려는 경우 성능 문제를 알고 있어야합니다.

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

참고URL : https://stackoverflow.com/questions/7738117/html-text-overflow-ellipsis-detection

반응형