Pergunta

Eu preciso implementar reticências ("...") no meio de um texto dentro de um elemento redimensionável. Aqui é o que pode parecer. Então,

"Lorem ipsum dolor sit amet. Ut ornare dignissim ligula sed commodo."

se torna

"Lorem ipsum dolor sit amet ... commodo."

Quando o elemento é estendido à largura do texto, eu quero o reticências a desaparecer. Como isso pode ser feito?

Foi útil?

Solução

No HTML, coloque o valor total em um costume data- atributo * como

<span data-original="your string here"></span>

Em seguida, atribua load e eventos resize ouvintes para uma função JavaScript que irá ler o atributo de dados original e colocá-lo no innerHTML de sua tag span. Aqui está um exemplo da função reticências:

function start_and_end(str) {
  if (str.length > 35) {
    return str.substr(0, 20) + '...' + str.substr(str.length-10, str.length);
  }
  return str;
}

Ajustar os valores, ou se possível, fazê-los dinâmico, se necessário, para objetos diferentes. Se você tiver usuários de diferentes navegadores, você pode roubar uma largura de referência a partir de um texto pelo mesmo tipo de letra e em outros lugares tamanho em seu dom. Então interpolate para uma quantidade adequada de caracteres para uso.

Uma dica é também ter uma abbr-tag na ... ou que mensagem para tornar o usuário será capaz de obter uma dica com a cadeia completa.

<abbr title="simple tool tip">something</abbr>

Outras dicas

Eu gostaria de propor o meu exemplo de resolver este problema.

A idéia principal é texto dividido em duas partes mesmo (ou primeira é maior, se o comprimento é ímpar) um dos quais tem reticências no final e outro alinhado à direita com text-overflow: clip.

Então tudo que você precisa fazer com js, se você quiser torná-lo automático / universal - é a seqüência de divisão e atributos definidos

.

Ele tem algumas desvantagens, no entanto.

  1. No bom embrulho por palavras, ou mesmo letras (text-overflow: '' só funciona no FF no momento)
  2. Se a divisão acontece entre palavras - espaço deve estar na primeira parte. Caso contrário, ele será recolhido.
  3. Fim da corda não deve ter quaisquer pontos de exclamação, devido à direction: rtl - eles serão movidos para a esquerda da string. Eu acho, é possível corrigir isso com a colocação de parte direita da palavra na marca tag e de exclamação no ::after pseudo-elemento. Mas eu ainda não fez isso funcionando corretamente.

Mas, com tudo isso, ele parece muito legal para mim, especialmente quando você arrastar a borda do navegador, o que você pode fazer na página jsFiddle facilmente: https://jsfiddle.net/extempl/93ymy3oL/ . Ou simplesmente executar o trecho com max de largura fixa abaixo.

Gif sob o spoiler:

GIF

body {
  max-width: 400px;
}

span::before, span::after {
  display: inline-block;
  max-width: 50%;
  overflow: hidden;
  white-space: pre;
}

span::before {
  content: attr(data-content-start);
  text-overflow: ellipsis;
}

span::after {
  content: attr(data-content-end);
  text-overflow: '';
  direction: rtl;
}
<span data-content-start="Look deep into nature, and then you " 
      data-content-end=  "will understand everything better"></span>

<br>
<span data-content-start="https://www.google.com.ua/images/branding/g" 
      data-content-end=  "ooglelogo/2x/googlelogo_color_272x92dp.png"></span>

Então, o meu colega veio com uma solução que usa há elementos DOM extra. Nós verificamos para ver se o div transborda e adicionar um atributo de dados dos últimos n caracteres. O resto é feito em css.

Aqui está um pouco de HTML:

<div class="box">
    <div class="ellipsis" data-tail="some">This is my text it is awesome</div>
</div>
<div class="box">
    <div class="ellipsis">This is my text</div>
</div>

E o css:

.box {
    width: 200px;
}

.ellipsis:before {
    float: right;
    content: attr(data-tail);
}

.ellipsis {
    white-space: nowrap;
    text-overflow: ellipsis;
    overflow: hidden;
}

Aqui está a jsFiddle obrigatória para isso: http://jsfiddle.net/r96vB/1/

A seguinte função Javascript vai fazer um truncamento meio, como OS X:

function smartTrim(string, maxLength) {
    if (!string) return string;
    if (maxLength < 1) return string;
    if (string.length <= maxLength) return string;
    if (maxLength == 1) return string.substring(0,1) + '...';

    var midpoint = Math.ceil(string.length / 2);
    var toremove = string.length - maxLength;
    var lstrip = Math.ceil(toremove/2);
    var rstrip = toremove - lstrip;
    return string.substring(0, midpoint-lstrip) + '...' 
    + string.substring(midpoint+rstrip);
}       

Ele irá substituir caracteres no meio com reticências. Meus testes unitários mostrar:

var s = '1234567890';
assertEquals(smartTrim(s, -1), '1234567890');
assertEquals(smartTrim(s, 0), '1234567890');
assertEquals(smartTrim(s, 1), '1...');
assertEquals(smartTrim(s, 2), '1...0');
assertEquals(smartTrim(s, 3), '1...90');
assertEquals(smartTrim(s, 4), '12...90');
assertEquals(smartTrim(s, 5), '12...890');
assertEquals(smartTrim(s, 6), '123...890');
assertEquals(smartTrim(s, 7), '123...7890');
assertEquals(smartTrim(s, 8), '1234...7890');
assertEquals(smartTrim(s, 9), '1234...67890');
assertEquals(smartTrim(s, 10), '1234567890');
assertEquals(smartTrim(s, 11), '1234567890');

Você não pode fazer isso com CSS. O problema é que HTML e CSS são supostamente para trabalhar em uma variedade de navegadores e fontes e é quase impossível de calcular a largura de um fio de uma forma consistente. Este é um ideia que pode ajudá-lo. No entanto, você precisa fazer isso várias vezes, até encontrar a corda com a largura apropriada.

Este pode ser um pouco tarde no jogo, mas eu estava olhando para encontrar uma solução para isso, e um colega sugeriu uma forma muito elegante, que eu vou compartilhar. Ele requer algum JS, mas não muito.

Imagine que você tem um div de um tamanho que você precisa colocar o seu rótulo em:

<div style="width: 200px; overflow: hidden"></div>

Agora, você tem uma função que terá dois parâmetros: uma string com o rótulo, e um elemento DOM (este div) para se encaixar em:

function setEllipsisLabel(div, label) 

A primeira coisa que você faz é criar um span com esta etiqueta, e colocá-lo na div:

var span = document.createElement('span');
span.appendChild(document.createTextNode(label));
span.style.textOverflow = 'ellipsis';
span.style.display = 'inline-block';
div.appendChild(span);

Nós definir a propriedade text-overflow para "reticências", de modo que, como o texto é cortada, um bom "..." é adicionada no final para ilustrar isso. Nós também definir display ser "inline-block" para que estes elementos têm dimensões de pixel reais que podem manipular mais tarde. Até agora, nada que não poderia ter feito com CSS puro.

Mas queremos que as reticências no meio. Primeiro, devemos descobrir se precisamos dele em tudo ... Isto pode ser feito através da comparação div.clientWidth para span.clientWidth -. Reticências só é necessário se o span é mais largo que o div

Se nós precisamos de uma elipse, vamos começar por dizer que queremos um número fixo de caracteres que aparecem no final da palavra - digamos 10. Então vamos criar uma extensão contendo apenas os últimos 10 caracteres da etiqueta, e vara -lo para o div:

var endSpan = document.createElement('span');
endSpan.style.display = 'inline-block';
endspan.appendChild(document.createTextNode(label.substring(label.length - 10)));
div.appendChild(endSpan);

Agora, vamos substituir a largura da span original para acomodar o novo:

span.style.width = (div.clientWidth - endSpan.clientWidth) + 'px';

Como um resultado disso, agora temos uma estrutura DOM que é algo como isto:

<div style="width: 200px; overflow: hidden">
   <span style="display: inline-block; text-overflow: ellipsis; width: 100px">
      A really long label is shown in this span
   </span>
   <span style="display: inline-block"> this span</span>
</div>

Porque o primeiro span tem conjunto text-overflow para "reticências", ele irá mostrar "..." no final, seguido pelos 10 caracteres do segundo período, resultando na reticências mostrando aproximadamente no meio do div.

Você não precisa codificar o comprimento de 10 caracteres para o endspan quer: isso pode ser aproximada por cálculo proporção da largura inicial do span ao do div, subtraindo a proporção adequada do comprimento da etiqueta e dividindo por dois.

Depois de alguma pesquisa em caixas de flex Eu encontrei esta solução CSS puro que eu acredito que é muito legal.

<div style="width:100%;border:1px solid green;display:inline-flex;flex-wrap:nowrap;">
   <div style="flex: 0 1 content;text-overflow: ellipsis;overflow:hidden;white-space:nowrap;"> Her comes very very very very very very very very very very very very very very very very very very very long </div>
   <div style="flex: 1 0 content;white-space:nowrap;"> &nbsp;but flexible line</div>
</div>

Aqui está a pouco mais curto que eu poderia encontrar que substitui 3 caracteres no meio com ....

function shorten(s, max) {
  return s.length > max ? s.substring(0, (max / 2) - 1) + '...' + s.substring(s.length - (max / 2) + 2, s.length) : s
}

Esta solução é uma mistura das soluções e coloca a última palavra inteira acima no final do texto encurtado. No entanto, caso a última palavra é mais longo, em seguida, um terço do espaço disponível é também shortend da esquerda. Se um hífen ( "-") é encontrado, cortá-la de lá, se não, cortá-la de qualquer maneira.

function truncate(text, textLimit) {
    if (!text) return text;
    if (textLimit < 1) return string;
    if (text.length < textLimit) return text;
    if (textLimit === 1) return text.substring(0,1) + '...';
    /* extract the last word */
    var lastPart = text.slice( string.lastIndexOf(' ')+1 );
    /* if last word is longer then a third of the max available space
       cut it from the left */
    var lastPartLimit = Math.ceil(textLimit / 3);
    if(lastPart.length > lastPartLimit) {
        var truncatedLastPart = lastPart;
        /* Try to find a dash and cut the last word there */
        var lastDashPart = text.slice( text.lastIndexOf('-')+1 );
        if(lastDashPart.length < lastPartLimit){
            truncatedLastPart = lastDashPart;
        }
        /* If the last part is still to long or not available cut it anyway */
        if(truncatedLastPart.length > lastPartLimit) {
            var lastIndex = lastPart.length - lastPartLimit;
            truncatedLastPart = lastPart.substring( lastIndex );
        }
        lastPart = truncatedLastPart;
    }
    var dots = '... ';
    var firsPartLength = textLimit - lastPart.length - dots.length;
    return text.substring(0, firstPartLength) + dots + lastPart;
}

console.log( truncate("New York City", 10) ); // Ne... City (max of 10 characters)
console.log( truncate("New York Kindergarden", 14) ); // Ne...ergarden (max of 14 characters, last word gets cut from the left by a third)
console.log( truncate("New York Kinder-garden", 14) ); // Ne...garden (max of 14 characters, last word gets cut by the dash from the left)

Acabei de criar uma função que pode cortar no meio, nearEnd e End, mas não reembolsaram sido testado ainda, porque eu finalmente estava precisando-lo no lado do servidor

//position acceptable values : middle, end, closeEnd
function AddElipsis(input, maxChars, position) {
    if (typeof input === 'undefined') {
        return "";
    }
    else if (input.length <= maxChars) {
        return input;
    }
    else {
        if (position == 'middle') {
            var midPos = Math.floor(maxChars / 2) - 2;
            return input.substr(0, midPos) + '...' + input.substr(input.length - midPos, input.length);
        }
        else if (position == 'closeEnd') {
            var firstPart = Math.floor(maxChars * 0.80) - 2;
            var endPart = Math.floor(maxChars * 0.20) - 2;
            return input.substr(0, firstPart) + '...' + input.substr(input.length - endPart, input.length);
        }
        else {
            return input.substr(0, maxChars - 3) + '...';
        }
    }
}

Outra facada:

function truncate( str, max, sep ) {
    max = max || 10;
    var len = str.length;
    if(len > max){
        sep = sep || "...";
        var seplen = sep.length;
        if(seplen > max) { return str.substr(len - max) }

        var n = -0.5 * (max - len - seplen);
        var center = len/2;
        return str.substr(0, center - n) + sep + str.substr(len - center + n);
    }
    return str;
}

console.log( truncate("123456789abcde") ); // 123...bcde (using built-in defaults) 
console.log( truncate("123456789abcde", 8) ); // 12...cde (max of 8 characters) 
console.log( truncate("123456789abcde", 12, "_") ); // 12345_9abcde (customize the separator) 

Isto lhe dará um pouco mais de controle sobre a posição da elipse e o texto do espaço reservado:

function ellipsis(str, maxLength, ellipsisLocationPercentage,placeholder) {
    /*
    ARGUMENTS:
    str - the string you want to maninpulate
    maxLength -  max number of characters allowed in return string
    ellipsisLocationPercentage (optional) - How far (percentage wise) into the return string you want the ellipses to be placed
        Examples:
        .85 : This is a very long string. This is a very long string. This is a very long string. This is a ver[...]very long string.
        .25 : This is a very long string. [...]g. This is a very long string. This is a very long string. This is a very long string.
    placeholder (optional) - this will be used to replace the removed substring. Suggestions : '...', '[..]', '[ ... ]', etc....
    */
    if(ellipsisLocationPercentage == null || isNaN(ellipsisLocationPercentage) || ellipsisLocationPercentage >= 1 || ellipsisLocationPercentage <= 0){
        //we've got null or bad data.. default to something fun, like 85% (that's fun, right??)
        ellipsisLocationPercentage = .85;
    }
    if(placeholder == null || placeholder ==""){
        placeholder = "[...]";
    }

    if (str.length > (maxLength-placeholder.length)) {
        //get the end of the string
        var beginning = str.substr(0, (maxLength - placeholder.length)*ellipsisLocationPercentage );
        var end = str.substr(str.length-(maxLength - placeholder.length) * (1-ellipsisLocationPercentage));
        return beginning + placeholder + end;
    }
    return str;
}

Você pode chamar esta função chamando:

ellipsis("This is a very long string. Be Scared!!!!", 8);//uses default values
ellipsis("This is a very long string. Be Scared!!!!", 8,.5);//puts ellipsis at half way point
ellipsis("This is a very long string. Be Scared!!!!", 8,.75,'<..>');//puts ellipsis at 75% of the way into the string and uses '<..>' as the placeholder

Para fazer um corte limpo e ter uma palavra inteira no final do texto encurtado, eu usei o abaixo função.

function prepareText(text){
  var returnString = text;
  var textLimit = 35;
  if(text.length > textLimit){
    var lastWord = text.slice( text.lastIndexOf(' ')+1 );
    var indexFromEnd = lastWord.length;
    var ellipsis = '... ';

    returnString = text.slice(0, textLimit - indexFromEnd - ellipsis.length);
    returnString = returnString + ellipsis + lastWord;
  }
  return returnString;
}

$('#ex1Modified').html( prepareText( $('#ex1').html() ) );

$('#ex2Modified').html( prepareText( $('#ex2').html() ) );

$('#ex3Modified').html( prepareText( $('#ex3').html() ) );
body{color:#777; font-family: sans-serif;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<h2>Shortened Quotes from Albert Einstein</h2>

<div id="ex1">"The true sign of intelligence is not knowledge but imagination."</div>
<div id="ex1Modified"></div>
<br>
<div id="ex2">"Look deep into nature, and then you will understand everything better."</div>
<div id="ex2Modified"></div>
<br>
<div id="ex3">"You can't blame gravity for falling in love."</div>
<div id="ex3Modified"></div>

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top