developer tip

왼쪽의 텍스트 오버플로 줄임표

copycodes 2020. 12. 24. 23:52
반응형

왼쪽의 텍스트 오버플로 줄임표


경로 목록이 있습니다 (더 나은 단어가 없기 때문에 빵 부스러기 흔적이 더 잘 설명 할 수 있습니다). 일부 값이 너무 길어서 부모에 표시 할 수 없으므로 text-overflow: ellipsis. 문제는 중요한 정보가 오른쪽에 있으므로 줄임표를 왼쪽에 표시하고 싶습니다. 이 ascii 예술과 같은 것 :

----------------------------
|first > second > third    |
|...second > third > fourth|
|...fifth > sixth > seventh|
----------------------------

첫 번째 행은 충분히 짧아서 왼쪽 정렬 상태를 유지하지만 다른 두 행은 너무 길어 줄임표가 왼쪽에 나타납니다.

CSS 전용 솔루션을 선호하지만 피할 수 없다면 JS는 괜찮습니다. 솔루션이 Firefox 및 Chrome에서만 작동하면 괜찮습니다.

편집 : 이 시점에서 문서가 RTL과 LTR이 혼합되어있을 때 제대로 렌더링되지 않는 Chrome의 버그에 대한 해결 방법을 찾고 있습니다. 그것이 내가 처음부터 정말로 필요한 전부 였고, 나는 그것을 깨닫지 못했습니다.


jsFiddle 과 같은 것은 어떻습니까? 방향, 텍스트 정렬 및 텍스트 오버플로를 사용하여 왼쪽에 줄임표를 표시합니다. MDN 에 따르면 향후 left-overflow-type값으로 왼쪽에 줄임표를 지정할 가능성이 있지만 아직 실험적인 것으로 간주됩니다.

p {
  white-space: nowrap;
  overflow: hidden;
  /* "overflow" value must be different from "visible" */
  text-overflow: ellipsis;
  width: 170px;
  border: 1px solid #999;
  direction: rtl;
  text-align: left;
}
<p>first > second > third<br /> second > third > fourth > fifth > sixth<br /> fifth > sixth > seventh > eighth > ninth</p>​


드디어 자바 스크립트로 뭔가를해야했습니다. 나는 누군가가 우박 메리 CSS 솔루션을 가지고 올 것이다 그러나 사람들은 대답 투표까지-것으로 보인다 것으로 기대했다 한다 는 크롬 버그 아니었다면 정확합니다. j08691은 그의 작업에 대한 현상금을 가질 수 있습니다 .

<html>
    <head>
        <style>
            #container {
                width: 200px;
                border: 1px solid blue;
            }

            #container div {
                width: 100%;
                overflow: hidden;
                white-space: nowrap;
            }
        </style>
        <script>
            function trimRows() {

                var rows = document.getElementById('container').childNodes;
                for (var i=0, row; row = rows[i]; i++) {
                    if (row.scrollWidth > row.offsetWidth) {
                        var textNode = row.firstChild;
                        var value = '...' + textNode.nodeValue;
                        do {
                            value = '...' + value.substr(4);
                            textNode.nodeValue = value;

                        } while (row.scrollWidth > row.offsetWidth);
                    }
                }
            }
        </script>
    </head>
    <body onload='trimRows();'>
    <div id="container" >
        <div>first > second > third</div>
        <div>second > third > fourth > fifth > sixth</div>
        <div>fifth > sixth > seventh > eighth > ninth</div>​
    </div>
    </body>

</html>

깡깡이


약간 버그가 있지만 올바른 방향을 가리키는 것일 수 있습니다.

http://jsfiddle.net/HerrSerker/ZfbaD/50/

$('.container')
    .animate({'width': 450}, 4000)
    .animate({'width': 100}, 4000)
    .animate({'width': 170}, 4000)
.container {  
  white-space: nowrap;                   
  overflow: hidden;              /* "overflow" value must be different from "visible" */   
  text-overflow: ellipsis;  
    width:170px;
    border:1px solid #999;
    direction:rtl;
}  
.container .part {
  direction:ltr;

}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
    <span class="part">second</span> 
    <span class="part">&gt;</span> 
    <span class="part">third</span> 
    <span class="part">&gt;</span> 
    <span class="part">fourth</span> 
    <span class="part">&gt;</span> 
    <span class="part">fifth</span> 
    <span class="part">&gt;</span> 
    <span class="part">sixth</span>
</div>


그냥 사용하지 않는 이유 direction:rtl;


@Hemlocks, @Brian Mortenson 및 @Jimbo의 솔루션을 사용하여이 문제를 해결하기 위해 jQuery 플러그인을 구축했습니다.

또한 현재 innerHTML을 반환하는 대신 .html ()을 사용하여 초기 값을 반환하는 지원을 추가했습니다. 누군가에게 유용하기를 바랍니다.

(function($) {

$.trimLeft = function(element, options) {

    var trim = this;

    var $element = $(element), // reference to the jQuery version of DOM element
         element = element;    // reference to the actual DOM element

    var initialText = element.innerHTML;

    trim.init = function() {
        overrideNodeMethod("html", function(){ return initialText; });
        trimContents(element, element);
        return trim;
    };

    trim.reset = function(){
        element.innerHTML = initialText;
        return trim;
    };

    //Overide .html() to return initialText.
    var overrideNodeMethod = function(methodName, action) {
        var originalVal = $.fn[methodName];
        var thisNode = $element;
        $.fn[methodName] = function() {
            if (this[0]==thisNode[0]) {
                return action.apply(this, arguments);
            } else {
                return originalVal.apply(this, arguments);
            }
        };
    };

    var trimContents = function(row, node){
        while (row.scrollWidth > row.offsetWidth) {
            var childNode = node.firstChild;
            if (!childNode)
                return true;            
            if (childNode.nodeType == document.TEXT_NODE){
                trimText(row, node, childNode);
            }
            else {
                var empty = trimContents(row, childNode);
                if (empty){
                    node.removeChild(childNode);
                }
            }
        };
    };

    var trimText = function(row, node, textNode){
        var value = '\u2026' + textNode.nodeValue;
        do {
            value = '\u2026' + value.substr(4);
            textNode.nodeValue = value;
            if (value == '\u2026'){
                node.removeChild(textNode);
                return;
            }
        }
        while (row.scrollWidth > row.offsetWidth);
    };

    trim.init();

};

$.fn.trimLeft = (function(options){
  var othat = this;

  var single = function(that){
      if (undefined == $(that).data('trim')) {
          var trim = new $.trimLeft(that, options);
          $(that).data('trim', trim);
          $(window).resize(function(){
              $(that).each(function(){
                    trim.reset().init();
              });
          });
       }   
   };

   var multiple = function(){
        $(othat).each(function() {
            single(this);
        });
    };

    if($(othat).length>1)
        multiple(othat);            
    else
        single(othat);

    //-----------        
    return this;
});


})(jQuery);

다음을 사용하여 시작 :

//Call on elements with overflow: hidden and white-space: nowrap 
$('#container>div').trimLeft();
//Returns the original innerHTML
console.log($('#test').html());

깡깡이


Using a slightly more complex markup (using the bdi-tag and an extra span for the ellipsis), we can solve the problem fully in CSS, no JS required at all -- cross browser (IE, FF, Chrome) and including keeping punctuation marks to the right:

http://jsbin.com/dodijuwebe/1/edit?html,css,output

Granted, this is something of a hack, involving pseudo-element goodness. However, our team has been using this code in production and we haven't had any issues whatsoever.

The only caveats are: The height of the line needs to be fixed and the background color needs to be known explicitly (inherit won't work).


If you don't care the indexing of those texts, you could use this method (it reverses the text lines):

If you have in your texts other HTML elements besides <br> you need to make some arrangements to use this method.

HTML code:

<p>first > second > third<br/>
second > third > fourth <br>
fifth > sixth > seventh</p>

CSS code:

p{
  overflow: hidden;
  text-overflow: ellipsis;
  unicode-bidi: bidi-override;
  direction: rtl;
  text-align: left;
  white-space: nowrap;
  width: 140px;
}

JavaScript code

[].forEach.call(document.getElementsByTagName("p"), function(item) {

  var str = item.innerText;

  //Change the operators
  str = str.replace(/[<>]/g, function(char){ return ({"<" : ">", ">" : "<"})[char] });

  //Get lines
  var lines = str.split(/\n/);

  //Reverse the lines
  lines = lines.map(function(l){ return l.split("").reverse().join("") }); 

  //Join the lines
  str = lines.join("<br>");

  item.innerHTML = str;

});

jsfiddle


Based on your edit:

At this point I'm looking for a work around for the bugs in Chrome that prevent it from rendering properly when a document is mixed RTL and LTR. That was all I really needed from the outset, I just didn't realize it.

Have you looked into the unicode-bidi css property (see Sitepoint or W3C)? I actually just learned about this myself on another recent post. My guess is you would want to use the embed value for those pieces going the opposite direction to the main site. So in j08691's answer where it is direction: rtl add unicode-bidi: embed to the CSS. This should solve "mixed RTL and LTR" issues you are having.


I put some JavaScript together to regex out three items and add the ellipsis in where necessary. This does not explicitly look at how much text will fit in the box but if the box is fixed this may not be an issue.

<style>
p {  
    white-space: nowrap;                     
    overflow: hidden;
    text-overflow: ellipsis; 
    width:170px;
    border:1px solid #999;
    direction:rtl;
    text-align:left;
} 
</style>

<p>first &gt; second &gt; third<br />
second &gt; third &gt; fourth &gt; fifth &gt; sixth<br />
fifth &lt; sixth &lt; seventh &lt; eighth &lt; ninth</p>

<script>
    var text = $( 'p' ).text(),
        split = text.split( '\n' ),
        finalStr = '';
    for( i in split ){
        finalStr = finalStr.length > 0 ? finalStr + '<br />' : finalStr;
        var match = /(\w+\s?(<|>)?\s?){3}$/.exec( split[i] );
        finalStr = finalStr + ( split[i].length > match[0].length ? '...' : '' ) + match[0];
    }
    $( 'p' ).empty().html( finalStr );
</script>

ReferenceURL : https://stackoverflow.com/questions/9793473/text-overflow-ellipsis-on-left-side

반응형