text-overflow: reticências no Firefox 4? (e FF5)

104

A text-overflow:ellipsis;propriedade CSS deve ser uma das poucas coisas que a Microsoft fez certo para a web.

Todos os outros navegadores agora o suportam ... exceto o Firefox.

Os desenvolvedores do Firefox têm discutido sobre isso desde 2005, mas apesar da óbvia demanda por ele, eles não conseguem realmente implementá-lo (mesmo uma -moz-implementação experimental seria suficiente).

Alguns anos atrás, alguém descobriu uma maneira de hackear o Firefox 3 para torná-lo compatível com reticências . O hack usa o -moz-bindingrecurso para implementá-lo usando XUL. Vários sites já estão usando esse hack.

As más notícias? O Firefox 4 está removendo o -moz-bindingrecurso , o que significa que esse hack não funcionará mais.

Portanto, assim que o Firefox 4 for lançado (no final deste mês, ouvi dizer), voltaremos ao problema de não ter suporte para esse recurso.

Portanto, minha pergunta é: existe alguma outra maneira de contornar isso? (Estou tentando evitar cair em uma solução Javascript, se possível)

[EDIT]
Muitos votos a favor, então obviamente não sou o único que quer saber, mas tenho uma resposta até agora que basicamente diz 'use javascript'. Ainda estou esperando por uma solução que não precise do JS ou, na pior das hipóteses, apenas o use como um fallback onde o recurso CSS não funciona. Então, vou postar uma recompensa pela pergunta, na chance de que alguém, em algum lugar, tenha encontrado uma resposta.

[EDIT]
Uma atualização: o Firefox entrou em modo de desenvolvimento rápido, mas apesar do FF5 agora ser lançado, esse recurso ainda não é suportado. E agora que a maioria dos usuários atualizou do FF3.6, o hack não é mais uma solução. A boa notícia é que ele pode ser adicionado ao Firefox 6, que com a nova programação de lançamentos deve ser lançado em apenas alguns meses. Se for esse o caso, então acho que posso esperar, mas é uma pena que eles não pudessem ter resolvido isso antes.

[EDIÇÃO FINAL]
Vejo que o recurso de reticências foi finalmente adicionado ao "Canal Aurora" do Firefox (ou seja, versão de desenvolvimento). Isso significa que agora ele deve ser lançado como parte do Firefox 7, que deve ser lançado no final de 2011. Que alívio.

Notas de versão disponíveis aqui: https://developer.mozilla.org/en-US/Firefox/Releases/7

Spudley
fonte
19
fwiw, outras coisas incríveis que a Microsoft fez para a web: AJAX, innerHTML, copiar JavaScript com fidelidade suficiente para que fosse a mesma linguagem em navegadores diferentes, mesmo que as APIs não fossem exatamente as mesmas, IE6
sdleihssirhc
8
@sdleihssirhc: a transição IE5.5 -> IE6 foi realmente uma revolução. Você é uma das poucas pessoas que vi que reconhecia isso publicamente;).
mingos
3
@mingos Sim, tenho a mente muito aberta, profética, perspicaz e inteligente assim.
sdleihssirhc
6
@mingos & @sdleihssirhc: Ponto bem colocado, e eu concordo - o IE6 era bom em sua época. Meus problemas com o IE6 não são como ele era bom na época, mas como ele causou 10 anos de estagnação na web. Mas este não é o lugar para entrar em um debate sobre o bem ou o mal do IE. :-) Há muitos outros lugares para ir para isso. Enquanto isso, ainda estou frustrado com os desenvolvedores do Firefox por serem teimosos nas reticências.
Spudley de
4
Infelizmente, por enquanto, não há solução CSS. A solução alternativa que uso, modernizr, também não tem o teste para essa propriedade. Você pode verificar se o UserAgent é Firefox e carregar o javascript em vez do CSS
nunopolonia

Respostas:

27

Spudley, você poderia conseguir a mesma coisa escrevendo um pequeno JavaScript usando jQuery:

var limit = 50;
var ellipsis = "...";
if( $('#limitedWidthTextBox').val().length > limit) {
   // -4 to include the ellipsis size and also since it is an index
   var trimmedText = $('#limitedWidthTextBox').val().substring(0, limit - 4); 
   trimmedText += ellipsis;
   $('#limitedWidthTextBox').val(trimmedText);
}

Eu entendo que deve haver alguma maneira de todos os navegadores suportarem isso nativamente (sem JavaScript), mas é isso que temos neste momento.

EDIT Além disso, você pode torná-lo mais organizado anexando uma cssclasse a todos os campos de largura fixa, digamos, fixWidth e fazer algo como o seguinte:

$(document).ready(function() {
   $('.fixWidth').each(function() {
      var limit = 50;
      var ellipsis = "...";
      var text = $(this).val();
      if (text.length > limit) {
         // -4 to include the ellipsis size and also since it is an index
         var trimmedText = text.substring(0, limit - 4); 
         trimmedText += ellipsis;
         $(this).val(trimmedText);
      }
   });
});//EOF
picoit
fonte
2
Eu lhe dei +1, mas estou hesitante em aceitar uma solução Javascript a menos que não haja mais nada possível. Vou esperar um pouco mais para ver se obtenho alguma outra resposta. Se JS for a única opção, seria bom ter um que funcionasse bem, text-overflow:ellipsis;para que eu ainda pudesse usar a opção CSS em outros navegadores.
Spudley de
Na ausência de qualquer outra solução de trabalho, terei de aceitar esta com relutância. Vou modificá-lo para que funcione apenas no Firefox, para que possa usar o recurso CSS em outros navegadores. Esperamos que o pessoal da Mozilla consiga implementar reticências para o FF5. Obrigado pela ajuda.
Spudley de
Não deveria length()ser length? É uma propriedade.
alex
É difícil escolher um comprimento de caractere que funcione o tempo todo, especialmente se você estiver usando fontes de largura variável ou tiver aumentado ou diminuído o tamanho do texto no navegador.
spb
21

EDITAR 30/09/2011

FF7 foi lançado, esse bug foi resolvido e funciona!


EDITAR 29/08/2011

Este problema está marcado como resolvido e estará disponível no FF 7; atualmente definido para lançamento em 27/09/2011.

Marque seus calendários e prepare-se para remover todos os hacks que você implementou.

VELHO

Eu tenho outra resposta: espere .

A equipe de desenvolvimento do FF está empenhada em resolver esse problema.

Eles têm uma correção provisória definida para o Firefox 6.

Firefox 6 !! Quando isso vai sair?!?

Calma aí, pessoa imaginária e super reativa. O Firefox está no caminho do desenvolvimento rápido. O FF6 está programado para lançamento seis semanas após o Firefox 5. O Firefox 5 está programado para lançamento em 21 de junho de 2011.

Então isso coloca a correção em algum momento no início de agosto de 2011 ... espero.

Você pode se inscrever na lista de discussão seguindo o bug do link na pergunta do postador original.

Ou você pode clicar aqui ; o que for mais fácil.

raio
fonte
Este hacks.mozilla.org/2011/07/aurora7 implica que será no Firefox 7, não 6. Mas seu ponto principal ( espere ) é válido de qualquer maneira.
MatrixFrog
"Esperar" parece ser a única resposta realista, mas é uma resposta difícil de aceitar quando seu chefe está exigindo. :( Felizmente, a espera parece estar finalmente chegando ao fim (embora o problema
perdure
5
Não, está programado para Firefox 7 : developer.mozilla.org/en/CSS/…
Christian
6

Devo dizer que estou um pouco desapontado com o fato de que o único hack específico do navegador em meu aplicativo será o suporte a FF4. A solução javascript acima não leva em conta fontes de largura variável. Aqui está um script mais detalhado que explica isso. O grande problema com essa solução é que, se o elemento que contém o texto estiver oculto quando o código for executado, a largura da caixa não será conhecida. Este foi um problema para mim, então parei de trabalhar / testá-lo ... mas pensei em postá-lo aqui, caso seja útil para alguém. Certifique-se de testá-lo bem, pois meu teste não foi exaustivo. Eu pretendia adicionar uma verificação de navegador para executar apenas o código para FF4 e permitir que todos os outros navegadores usassem sua solução existente.

Deve estar disponível para manipulação aqui: http://jsfiddle.net/kn9Qg/130/

HTML:

<div id="test">hello World</div>

CSS:

#test {
    margin-top: 20px;
    width: 68px;
    overflow: hidden;
    white-space: nowrap;
    border: 1px solid green;
}

Javascript (usa jQuery)

function ellipsify($c){
    // <div $c>                 content container (passed)
    //    <div $b>              bounds
    //       <div $o>           outer
    //          <span $i>       inner
    //       </div>
    //       <span $d></span>   dots
    //    </div>
    // </div>

    var $i = $('<span>' + $c.html() + '</span>');
    var $d = $('<span>...</span>');
    var $o = $('<div></div>');
    var $b = $('<div></div>');

    $b.css( {
        'white-space' : "nowrap",
        'display' : "block",
        'overflow': "hidden"
    }).attr('title', $c.html());

    $o.css({
        'overflow' : "hidden",
        'width' : "100%",
        'float' : "left"
    });

    $c.html('').append($b.append( $o.append($i)).append($d));

    function getWidth($w){
        return parseInt( $w.css('width').replace('px', '') );
    }

    if (getWidth($o) < getWidth($i))
    {
        while (getWidth($i) > (getWidth($b) - getWidth($d)) )
        {
             var content = $i.html();
             $i.html(content.substr(0, content.length - 1));
        }

        $o.css('width', (getWidth($b) - getWidth($d)) + 'px');
    }
    else
    {
        var content = $i.html();
        $c.empty().html(content);
    }
}

Seria chamado assim:

$(function(){
    ellipsify($('#test'));
});
wwwhack
fonte
6

Também encontrei este gremlin na semana passada.

Uma vez que a solução aceita não leva em conta fontes de largura variável e a solução do wwwhack tem um loop while, eu colocarei meu $ 0,02.

Consegui reduzir drasticamente o tempo de processamento do meu problema usando a multiplicação cruzada. Basicamente, temos uma fórmula semelhante a esta:

insira a descrição da imagem aqui

A variável x neste caso é o que precisamos resolver. Quando retornado como um inteiro, ele fornecerá o novo comprimento que o texto transbordado deve ter. Multipliquei MaxLength por 80% para dar às elipses espaço suficiente para serem exibidas.

Aqui está um exemplo completo de html:

<html>
    <head>
        <!-- CSS setting the width of the DIV elements for the table columns.  Assume that these widths could change.  -->
        <style type="text/css">
            .div1 { overflow: hidden; white-space: nowrap; width: 80px; }
            .div2 { overflow: hidden; white-space: nowrap; width: 150px; }
            .div3 { overflow: hidden; white-space: nowrap; width: 70px; }
        </style>
        <!-- Make a call to Google jQuery to run the javascript below.  
             NOTE:  jQuery is NOT necessary for the ellipses javascript to work; including jQuery to make this example work -->
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js"></script>
        <script type="text/javascript">
            $(document).ready(function() {  
                //Loop through each DIV element
                $('div').each(function(index) {
                    var myDiv = this;  //The original Div element which will have a nodeType of 1 (e.g. ELEMENT_NODE)
                    var divText = myDiv; //Variable used to obtain the text from the DIV element above  

                    //Get the nodeType of 3 (e.g. TEXT_NODE) from the DIV element.  For this example, it will always be the firstChild  
                    divText = divText.firstChild;  

                    //Create another variable to hold the display text  
                    var sDisplayText = divText.nodeValue;  

                    //Determine if the DIV element is longer than it's supposed to be.
                    if (myDiv.scrollWidth > myDiv.offsetWidth) {  
                        //Percentage Factor is just a way of determining how much text should be removed to append the ellipses  
                        //With variable width fonts, there's no magic number, but 80%, should give you enough room
                        var percentageFactor = .8;  

                        //This is where the magic happens.
                        var sliceFactor = ((myDiv.offsetWidth * percentageFactor) * sDisplayText.length) / myDiv.scrollWidth;
                        sliceFactor = parseInt(sliceFactor);  //Get the value as an Integer
                        sDisplayText = sDisplayText.slice(0, sliceFactor) + "..."; //Append the ellipses
                        divText.nodeValue = sDisplayText; //Set the nodeValue of the Display Text
                    }
                });
            });
        </script>
    </head>
    <body>
        <table border="0">
            <tr>    
                <td><div class="div1">Short Value</div></td>    
                <td><div class="div2">The quick brown fox jumps over the lazy dog; lots and lots of times</div></td>    
                <td><div class="div3">Prince</div></td> 
            </tr>
            <tr>    
                <td><div class="div1">Longer Value</div></td>   
                <td><div class="div2">For score and seven year ago</div></td>   
                <td><div class="div3">Brown, James</div></td>   
            </tr>
            <tr>    
                <td><div class="div1">Even Long Td and Div Value</div></td> 
                <td><div class="div2">Once upon a time</div></td>   
                <td><div class="div3">Schwarzenegger, Arnold</div></td> 
            </tr>
        </table>
    </body>
</html>

Eu entendo que essa é uma correção apenas de JS, mas até que o Mozilla corrija o bug, eu simplesmente não sou inteligente o suficiente para apresentar uma solução CSS.

Este exemplo funciona melhor para mim porque o JS é chamado sempre que uma grade é carregada em nosso aplicativo. A largura da coluna para cada grade varia e não temos controle sobre o tipo de computador que nossos usuários do Firefox visualizam nosso aplicativo (o que, é claro, não deveríamos ter esse controle :)).

raio
fonte
Obrigado pela resposta; Vou tentar e tenho certeza de que será útil para outras pessoas que procuram resolver o mesmo problema. +1
Spudley
Hmm, parece que você configurou incorretamente seu editor de texto ;-P - parece que você está usando guias com menos de 8 caracteres de largura!
SamB
3

Essa solução CSS pura é muito próxima, exceto pelo fato de que faz com que apareçam reticências após cada linha.

Jhuebsch
fonte
obrigado pela resposta. Por mais que eu queira aceitar uma solução CSS pura, esta não é realmente viável para mim, pois requer marcação extra e, como você disse, deixa as reticências aparecendo quando você não quer. obrigado embora. Eu te dei +1, no entanto.
Spudley de