Подтвердить что ты не робот

Эллипсис переполнения текста с левой стороны

У меня есть список путей (из-за отсутствия лучшего слова, возможно, дорожки из крошки хлеба лучше описывают их). Некоторые из значений слишком длинны для отображения в их родительском объекте, поэтому я использую text-overflow: ellipsis. Проблема в том, что важная информация находится справа, поэтому мне хотелось бы, чтобы эллипсис появился слева. Что-то вроде этого искусства ascii:

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

Обратите внимание, что первая строка достаточно короткая, поэтому она остается левой, а две другие слишком длинны, поэтому эллипсис появляется с левой стороны.

Я бы предпочел только решение CSS, но JS в порядке, если его не избежать. Это нормально, если решение работает только в Firefox и Chrome.

EDIT: На этом этапе я ищу работу для ошибок в Chrome, которые не позволяют корректно отображать документ в смешанном RTL и LTR. Это все, что мне действительно нужно с самого начала, я просто этого не осознавал.

4b9b3361

Ответ 1

Наконец-то мне пришлось взломать и сделать что-то в JavaScript. Я надеялся, что кто-то придумает решение для града Мэри, но люди, похоже, просто голосуют за ответ, который должен быть правильным, если бы не ошибки Chrome. 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>

Fiddle

Ответ 2

Как насчет чего-то вроде этого 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>​

Ответ 3

Это немного багги, но, может быть, точка в правильном направлении

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

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

​.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;

}

Ответ 4

Почему бы просто не использовать direction:rtl;

Ответ 5

Используя @Hemlocks, @Brian Mortenson и @Jimbo решения, я создал плагин jQuery для решения этой проблемы.

Я также добавил поддержку, чтобы вернуть начальное значение с помощью .html() вместо того, чтобы вернуть текущий innerHTML. Надеюсь, это будет полезно кому-то...

(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());

fiddle

Ответ 6

Используя немного более сложную разметку (используя bdi-тег и дополнительный диапазон для многоточия), мы можем полностью решить проблему в CSS, никакой JS не требуется - перекрестный браузер (IE, FF, Chrome) и включая сохранение знаков препинания вправо:

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

Конечно, это что-то вроде взлома, связанного с доброжелательностью псевдоэлемента. Однако наша команда использует этот код в производстве, и у нас не было никаких проблем.

Единственные предостережения: Высота линии должна быть исправлена, а цвет фона должен быть явно известен (наследование не будет работать).

Ответ 7

Если вам не нужна индексация этих текстов, вы можете использовать этот метод (он меняет текстовые строки):

Если в ваших текстах есть другие элементы HTML помимо <br>, вам нужно сделать некоторые шаги для использования этого метода.

HTML-код:

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

Код CSS:

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

Код JavaScript

[].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

Ответ 8

На основе вашего редактирования:

На этом этапе я ищу работу для ошибок в Chrome которые препятствуют правильному отображению документа при смешанном RTL RTL и LTR. Это было все, что мне действительно нужно с самого начала, я просто не осознайте это.

Вы просмотрели свойство unicode-bidi css (см. Sitepoint или W3C)? На самом деле я просто узнал об этом на еще одном недавнем сообщении. Я предполагаю, что вы хотели бы использовать значение embed для тех частей, которые идут в противоположном направлении к основному сайту. Поэтому в j08691 ответьте, где это direction: rtl добавьте unicode-bidi: embed в CSS. Это должно решить проблемы смешанного RTL и LTR, которые у вас есть.

Ответ 9

Я добавил некоторый JavaScript для повторного выражения из трех элементов и добавил эллипсис там, где это необходимо. Это явно не рассматривает, сколько текста будет вписываться в поле, но если поле исправлено, это может не быть проблемой.

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