Ellissi nel mezzo di un testo (stile Mac)

Devo implementare i puntini di sospensione ( "..." ) nel mezzo di un testo all’interno di un elemento ridimensionabile. Ecco come potrebbe essere. Così,

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

diventa

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

Quando l’elemento è allungato alla larghezza del testo, voglio che i puntini di sospensione scompaiano. Come si può fare?

Nel codice HTML, inserisci il valore completo in un attributo personalizzato data- * come

  

Quindi assegna il load e resize listener di eventi a una funzione JavaScript che leggerà l’attributo di dati originale e lo inserirà nel innerHTML del tag span. Ecco un esempio della funzione ellissi:

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

Regola i valori o, se ansible, rendili dinamici, se necessario per oggetti diversi. Se hai utenti da diversi browser, puoi rubare una larghezza di riferimento da un testo con lo stesso carattere e le stesse dimensioni in altre parti della tua dom. Quindi interpolare su una quantità appropriata di caratteri da utilizzare.

Un consiglio è anche quello di avere un tag abbr-in sul … o quale messaggio per rendere l’utente in grado di ottenere un suggerimento con la stringa completa.

 something 

Vorrei proporre il mio esempio per risolvere questo problema.

L’idea principale è quella di dividere il testo in due parti pari (o il primo è più grande, se la lunghezza è dispari), una delle quali ha un’ellissi alla fine e un’altra allineata a destra con l’ text-overflow: clip .

Quindi tutto ciò che devi fare con js, se vuoi renderlo automatico / universale – è dividere la stringa e impostare gli attributi.

Ha alcuni svantaggi, però.

  1. Nessun piacevole involucro di parole o persino di lettere ( text-overflow: '' non funziona, almeno, in chrome)
  2. Se la divisione avviene tra le parole, lo spazio dovrebbe essere nella prima parte. Altrimenti, sarà collassato.
  3. La fine della stringa non dovrebbe avere punti esclamativi, a causa della direction: rtl – saranno spostati a sinistra della stringa. Penso che sia ansible risolvere questo problema inserendo la parte destra della parola nel tag e nel punto esclamativo nello pseudo-elemento ::after . Ma non l’ho ancora fatto funzionare correttamente.

Ma, con tutti questi, mi sembra davvero interessante, specialmente quando si trascina il bordo del browser, cosa che si può fare facilmente nella pagina jsfiddle: https://jsfiddle.net/extempl/93ymy3oL/ . Oppure esegui lo snippet con larghezza massima fissa di seguito.

Gif sotto lo 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: clip; direction: rtl; } 
  

Quindi il mio collega ha trovato una soluzione che non utilizza elementi dom aggiuntivi. Controlliamo se il div è in overflow e aggiungiamo un attributo di dati degli ultimi n caratteri. Il resto è fatto in css.

Ecco alcuni HTML:

 
This is my text it is awesome
This is my text

E il css:

 .box { width: 200px; } .ellipsis:before { float: right; content: attr(data-tail); } .ellipsis { white-space: nowrap; text-overflow: ellipsis; overflow: hidden; } 

Ecco il jsfiddle obbligatorio per questo: http://jsfiddle.net/r96vB/1/

La seguente funzione Javascript eseguirà un troncamento intermedio, come 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); } 

Sostituirà i caratteri nel mezzo con ellissi. I miei test unitari mostrano:

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

Non puoi farlo con i CSS. Il problema è che HTML e CSS dovrebbero funzionare in una varietà di browser e font ed è quasi imansible calcolare la larghezza di una stringa in modo coerente. Questa è un’idea che potrebbe aiutarti. Tuttavia, è necessario farlo un certo numero di volte, fino a trovare la stringa con la larghezza appropriata.

Questo potrebbe essere un po ‘in ritardo nel gioco, ma stavo cercando di trovare una soluzione a questo, e un collega ha suggerito uno molto elegante, che condividerò. Richiede un po ‘di JS, ma non molto.

Immagina di avere un div di una dimensione di cui hai bisogno per mettere la tua etichetta in:

 

Ora, hai una funzione che richiede due parametri: una stringa con l’etichetta e un elemento DOM (questo div ) per adattarlo a:

 function setEllipsisLabel(div, label) 

La prima cosa che fai è creare una span con questa etichetta e inserirla nel div :

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

text-overflow proprietà di text-overflow del text-overflow “ellissi” in modo che, man mano che il testo viene troncato, venga aggiunto un bel “…” alla fine per illustrare questo. Impostiamo anche la display come “blocco in linea” in modo che questi elementi abbiano dimensioni reali dei pixel che possiamo manipolare in seguito. Finora, nulla che non avremmo potuto fare con puro CSS.

Ma vogliamo l’ellissi nel mezzo. Innanzitutto, dovremmo scoprire se ne abbiamo div.clientWidth bisogno … Questo può essere fatto confrontando div.clientWidth a span.clientWidth – i puntini di sospensione sono necessari solo se lo span è più largo del div .

Se abbiamo bisogno di puntini di sospensione, iniziamo dicendo che vogliamo un numero fisso di caratteri mostrati alla fine della parola, diciamo 10. Quindi creiamo uno span contenente solo gli ultimi 10 caratteri dell’etichetta e incollalo nel div:

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

Ora, sovrascriviamo la larghezza dello span originale per adattarlo a quello nuovo:

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

Di conseguenza, ora abbiamo una struttura DOM simile a questa:

 
A really long label is shown in this span this span

Poiché la prima span ha l’ text-overflow impostato su “ellissi”, alla fine verrà visualizzato “…”, seguito dai 10 caratteri della seconda span, con la conseguenza che i puntini di sospensione mostrano approssimativamente nel mezzo del div .

Non è necessario codificare con hardkey la lunghezza di 10 caratteri per endSpan: questo può essere approssimato calcolando il rapporto tra la larghezza iniziale dello span e quella del div , sottraendo la proporzione appropriata dalla lunghezza dell’etichetta e dividendo per due .

Dopo alcune ricerche su scatole flessibili ho trovato questa soluzione CSS pura che ritengo sia piuttosto interessante.

 
Her comes very very very very very very very very very very very very very very very very very very very long
 but flexible line

Ho appena creato una funzione che può tagliare al centro, vicino a End and End ma non è stata ancora testata perché alla fine ne avevo bisogno sul lato server

 //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) + '...'; } } } 

Un’altra pugnalata:

 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) 

Questo ti darà un po ‘più di controllo sulla posizione dei puntini di sospensione e sul testo segnaposto:

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

Puoi chiamare questa funzione chiamando:

 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 

Per fare un taglio netto e avere una parola intera alla fine del testo abbreviato, ho usato la funzione qui sotto.

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

Shortened Quotes from Albert Einstein

"The true sign of intelligence is not knowledge but imagination."

"Look deep into nature, and then you will understand everything better."

"You can't blame gravity for falling in love."

Ecco la parte più breve che ho trovato che sostituisce 3 caratteri nel mezzo con ….

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