programing

HTML 텍스트 오버플로 줄임표 검출

firstcheck 2022. 10. 29. 14:23
반응형

HTML 텍스트 오버플로 줄임표 검출

페이지에 블록 요소의 컬렉션이 있습니다.모두 CSS 규칙이 공백, 오버플로, 텍스트 오버플로우 세트로 설정되어 있기 때문에 오버플로우 텍스트가 트리밍되고 생략 부호가 사용됩니다.

그러나 모든 요소가 오버플로하는 것은 아닙니다.

javascript를 사용하여 어떤 요소가 넘치고 있는지 알 수 있는 방법이 있습니까?

감사해요.

추가: 현재 사용하고 있는 HTML 구조의 예.

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

SPAN 요소는 항상 셀에 들어가 생략 부호 규칙이 적용됩니다.SPAN의 텍스트 내용에 줄임표가 적용되었을 때를 검출하고 싶다.

span 요소를 인수로 전달하여 다음 JS 함수를 시도합니다.

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

옛날에는 이 작업을 해야 했는데, 유일하게 신뢰할 수 있는 크로스 브라우저 솔루션이 해킹 작업이었습니다.저는 이런 솔루션의 광팬은 아니지만 정확한 결과를 계속해서 얻을 수 있습니다.

이 방법은 요소를 복제하고 경계 너비를 제거한 후 복제된 요소가 원래 요소보다 넓은지 테스트하는 것입니다.이 경우 잘릴 수 있습니다.

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

이게 도움이 됐으면 좋겠군, 해킹이긴 하지만.

이탤로의 답변에 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가 승인한 답변을 사용하는(또는 사용하려는) 사용자는 성능 문제에 유의하십시오.

이러한 방법으로 DOM을 복제/조작하면 DOM Reflow(DOM Reflow에 대한 설명 참조)가 발생하며, 이는 매우 많은 자원을 필요로 합니다.

페이지의 100개 이상의 요소에 Christian Varga의 솔루션을 사용하면 JS 스레드가 잠기는 동안 4초의 리플로 지연이 발생했습니다.JS가 싱글 스레드임을 고려하면 최종 사용자에게 상당한 UX 지연을 의미합니다.

Italo Borsato의 답변은 받아들여진 답변이어야 합니다.프로파일링에서는 약 10배 빠릅니다.

이탤로 답장이 아주 좋아요!하지만 조금 더 다듬어 보겠습니다.

function isEllipsisActive(e) {
   var tolerance = 2; // In px. Depends on the font you are using
   return e.offsetWidth + tolerance < e.scrollWidth;
}

브라우저 간 호환성

, 「」를 사용하고 있는 console.loge.offsetWidth ★★★★★★★★★★★★★★★★★」e.scrollWidth에서는, 절단이 없는 에서도, IE 의 값의 것을 수 있습니다.1px ★★★★★★★★★★★★★★★★★」2px험이이많많많많

따라서 사용하는 글꼴 크기에 따라 일정한 허용 오차를 허용하십시오!

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

다음 예제에서는 텍스트가 잘린 셀테이블의 툴팁을 보여 줍니다.테이블 폭에 따라 동적:

$.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에서 작동합니다.

모든 솔루션이 실제로 효과가 있었던 것은 아닙니다.요소를 비교하는 것이 효과가 있었습니다.scrollWidthscrollWidth부모(또는 자식, 트리거가 있는 요소에 따라 다름)를 지정합니다.

아이가 임신했을 때scrollWidth보다 높다, 부모보다 높다, 부모보다 높다..text-ellipsis활성화 되어 있습니다.


el입니다.

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

el입니다.

function isEllipsisActive(event) {
    let width       = el.offsetWidth;
    let widthParent = el.parentElement.scrollWidth;
    return (width >= widthParent);
}

구현)

const items = Array.from(document.querySelectorAll('.item'));
items.forEach(item =>{
    item.style.color = checkEllipsis(item) ? 'red': 'black'
})

function checkEllipsis(el){
  const styles = getComputedStyle(el);
  const widthEl = parseFloat(styles.width);
  const ctx = document.createElement('canvas').getContext('2d');
  ctx.font = `${styles.fontSize} ${styles.fontFamily}`;
  const text = ctx.measureText(el.innerText);
  return text.width > widthEl;
}
.item{
  width: 60px;
  overflow: hidden;
  text-overflow: ellipsis;
}
      <div class="item">Short</div>
      <div class="item">Loooooooooooong</div>

하는 더 은 걸걸 i i를 사용하는 것이라고 생각합니다.getClientRects() 것 는 서로 다른 와 함께 할 수 topdiscloss.discloss 。

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이렇게 일하다

이렇게 검출할 수 있습니다.

어느 솔루션도 효과가 없었기 때문에, 전혀 다른 어프로치를 선택했습니다.줄임표와 함께 CSS 솔루션을 사용하는 대신 특정 문자열 길이에서 텍스트를 잘라냅니다.

  if (!this.isFullTextShown && this.text.length > 350) {
    return this.text.substring(0, 350) + '...'
  }
  return this.text

길이가 초과되면 "more/less" 버튼을 표시합니다.

  <span
    v-if="text.length > 350"
    @click="isFullTextShown = !isFullTextShown"
  >
    {{ isFullTextShown ? 'show less' : 'show more' }}
  </span>

e.offsetWidth < e.scrollWidth솔루션이 항상 효과가 있는 것은 아닙니다.

순수 JavaScript를 사용하려면 다음을 사용하는 것이 좋습니다.

(타이프 스크립트)

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/users/241142/iconoclast에서 언급한 데모 http://jsfiddle.net/brandonzylstra/hjk9mvcy/에는 몇 가지 실수가 있습니다.

데모에서 다음 코드를 추가합니다.

setTimeout(() => {      
  console.log(EntryElm[0].offsetWidth)
}, 0)

리액션을 하고 있다면, 내가 한 방법은 이렇다.

<div 
  ref={ref => {
    if (!ref) return
    const isOverflowing = ref.scrollWidth > ref.clientWidth
    if (isOverflowing) {
      // handle what to do next here
    }
  }}
/>

Adding to @Дмытрык answer, missing deduction of borders and paddings to be fully functional!!

const items = Array.from(document.querySelectorAll('.item'));
items.forEach(item =>{
    item.style.color = checkEllipsis(item) ? 'red': 'black'
})

function checkEllipsis(el){
  const styles = getComputedStyle(el);
  const widthEl = parseFloat(styles.width);
  const ctx = document.createElement('canvas').getContext('2d');
  ctx.font = `${styles.fontSize} ${styles.fontFamily}`;
  const text = ctx.measureText(el.innerText);

  let extra = 0;
  extra += parseFloat(styles.getPropertyValue('border-left-width'));
  extra += parseFloat(styles.getPropertyValue('border-right-width'));
  extra += parseFloat(styles.getPropertyValue('padding-left'));
  extra += parseFloat(styles.getPropertyValue('padding-right'));
  return text.width > (widthEl - extra);
}
.item{
  width: 60px;
  overflow: hidden;
  text-overflow: ellipsis;
}
      <div class="item">Short</div>
      <div class="item">Loooooooooooong</div>

e.offsetWidth < e.scrollWidth전체 텍스트는 표시할 수 있지만 줄임표는 남아 있는 버그가 발생했습니다.

그유 it it it it it it 。offsetWidth ★★★★★★★★★★★★★★★★★」scrollWidth항상 값을 반올림합니다.를 들면, '먹다'와 같이요.offsetWidth161 실제 은 제제 is이다.161.25해결책은 사용입니다.getBoundingClientRect

const clonedEl = e.cloneNode(true)
clonedElement.style.overflow = "visible"
clonedElement.style.visibility = "hidden"
clonedElement.style.width = "fit-content"

e.parentElement.appendChild(clonedEl)
const fullWidth = clonedElement.getBoundingClientRect().width
const currentWidth = e.getBoundingClientRect().width

return currentWidth < fullWidth

하고 는 ★★★★★★★★★★★★★★★★★★★★★★★★★★★★」line-clamp>= 두 줄 이상의 줄에 줄임표를 추가하는 경우 다음 조건을 사용할 수 있습니다.

if (
      descriptionElement &&
      descriptionElement.offsetHeight < descriptionElement.scrollHeight
    ) {
      // has text-overflow
    }

솔루션 @ItaloBorsato는 완벽합니다.하지만 SO를 보기 전에 나는 결정을 내렸다.여기 있습니다:)

const elems = document.querySelectorAll('span');
elems.forEach(elem => {
  checkEllipsis(elem);
});

function checkEllipsis(elem){
  const canvas = document.createElement('canvas');
  const ctx = canvas.getContext('2d');
  const styles = getComputedStyle(elem);
  ctx.font = `${styles.fontWeight} ${styles.fontSize} ${styles.fontFamily}`;
  const widthTxt = ctx.measureText(elem.innerText).width;
  if (widthTxt > parseFloat(styles.width)){
    elem.style.color = 'red'
  }
}
span.cat {
    display: block;
    border: 1px solid black;
    white-space: nowrap;
    width: 100px;
    overflow: hidden;
    text-overflow: ellipsis;
}
 <span class="cat">Small Cat</span>
      <span class="cat">Looooooooooooooong Cat</span>

언급URL : https://stackoverflow.com/questions/7738117/html-text-overflow-ellipsis-detection

반응형