Elipsis de desbordamiento de texto en el lado izquierdo


Tengo una lista de caminos (a falta de una palabra mejor, tal vez bread crumb trails los describe mejor). Algunos de los valores son demasiado largos para mostrarse en su padre, así que estoy usando text-overflow: ellipsis. El problema es que la información importante está a la derecha, así que me gustaría que los puntos suspensivos aparezcan a la izquierda. Algo como esto este arte ascii:

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

Observe que la primera fila es lo suficientemente corta para que permanezca alineada a la izquierda, pero las otras dos son demasiado largas para que aparezcan los puntos suspensivos en la mano izquierda lado.

Preferiría una solución solo CSS, pero JS está bien si no se puede evitar. Está bien si la solución solo funciona en Firefox y Chrome.

EDITAR: En este punto estoy buscando una solución para los errores en Chrome que impiden que se renderice correctamente cuando un documento se mezcla RTL y LTR. Eso era todo lo que realmente necesitaba desde el principio, simplemente no me di cuenta.

Author: Jesper Rønn-Jensen, 2012-03-20

9 answers

¿algo como esto jsFiddle? Utiliza la dirección, alineación de texto y desbordamiento de texto para obtener los puntos suspensivos a la izquierda. De acuerdo con MDN , puede haber la posibilidad de especificar los puntos suspensivos a la izquierda en el futuro con el valor left-overflow-type sin embargo, se considera que todavía es experimental.

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>​
 64
Author: j08691,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-20 14:19:01

Finalmente tuve que crackear y hacer algo en JavaScript. Tenía la esperanza de que alguien se le ocurriría una solución CSS ave maría, pero la gente parece que acaba de ser up-votar la respuesta que debería ser correcta si no fuera por los errores de Chrome. j08691 puede tener la recompensa por su trabajo.

<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

 14
Author: Hemlock,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-03-30 18:53:42

Es un poco buggy, pero tal vez un punto en la dirección correcta

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;

}
 3
Author: HerrSerker,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-03-27 16:50:12

¿Por qué no usar simplemente direction:rtl;

 2
Author: YGT,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-06-03 17:35:23

Usando las soluciones de @Hemlocks, @Brian Mortenson y @Jimbo, he construido un plugin de jQuery para resolver este problema.

También he añadido soporte para devolver el valor inicial usando .html() en lugar de hacer que devuelva el innerHTML actual. Espero que sea útil para alguien...

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

Iniciar usando:

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

Fiddle

 1
Author: Graham Dixon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-01-03 20:00:43

Usando un marcado un poco más complejo (usando la bdi-tag y un span extra para los puntos suspensivos), podemos resolver el problema completamente en CSS, no se requiere JS en absoluto cross cross browser (IE, FF, Chrome) e incluyendo mantener los signos de puntuación a la derecha:

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

Concedido, esto es algo así como un truco, que implica la bondad pseudo-elemento. Sin embargo, nuestro equipo ha estado usando este código en producción y no hemos tenido ningún problema lo que sea.

Las únicas advertencias son: La altura de la línea debe fijarse y el color de fondo debe conocerse explícitamente (inherit no funcionará).

 1
Author: mbaer3000,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-12-03 04:30:37

Si no le importa la indexación de esos textos, podría usar este método (invierte las líneas de texto):

Si tienes en tus textos otros elementos HTML además de <br> necesitas hacer algunos arreglos para usar este método.

Código HTML:

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

Código CSS:

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

Código 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

 1
Author: ElChiniNet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-01-01 11:30:36

Basado en su edición:

En este punto estoy buscando un trabajo alrededor de los errores en Chrome que impiden la representación correctamente cuando un documento se mezcla RTL y LTR. Eso era todo lo que realmente necesitaba desde el principio, simplemente no lo hice date cuenta.

¿Has mirado en la propiedad css unicode-bidi (ver Sitepoint o W3C)? De hecho, acabo de enterarme de esto en otro post reciente. Mi conjetura es que usted querría utilizar el embed valor para aquellas piezas que van en dirección opuesta al sitio principal. Así que en la respuesta de j08691 donde está direction: rtl agregue unicode-bidi: embed al CSS. Esto debería resolver los problemas de "RTL y LTR mixtos" que tenga.

 0
Author: ScottS,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:34:28

Pongo un poco de JavaScript juntos para regex tres elementos y añadir los puntos suspensivos en donde sea necesario. Esto no analiza explícitamente cuánto texto cabrá en el cuadro, pero si el cuadro se corrige, esto puede no ser un problema.

<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>
 0
Author: MasterNone,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-03-29 16:41:15