I need to implement ellipsis (\"...\"
) in the middle of a text within a resizable element. Here is what it might look like. So,
\"Lorem ipsum do
To make a clean cut and have a whole word at the end of the shortened text, I used the below function.
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>
Another stab:
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)
So my colleague came up with a solution that uses no extra dom elements. We check to see if the div overflows and add a data attribute of the last n characters. The rest is done in css.
Here is some 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>
And the css:
.box {
width: 200px;
}
.ellipsis:before {
float: right;
content: attr(data-tail);
}
.ellipsis {
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
Here is the obligatory jsfiddle for this: http://jsfiddle.net/r96vB/1/
I just created a function that can trim at the middle, nearEnd and End but havent been tested yet because I finally was needing it at the server side
//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) + '...';
}
}
}
I'd like to propose mine example of solving this problem.
The main idea is to split text in two even parts (or first is bigger, if the length is odd) one of which has ellipsis in the end and another aligned right with text-overflow: clip
.
So all you need to do with js, if you want to make it automatic/universal - is to split string and set attributes.
It has some disadvantages, though.
text-overflow: ''
works only in FF at the moment)direction: rtl
- they will be moved to the left of the string. I think, it is possible to fix this with putting right part of the word in the tag and exclamation mark in the ::after
pseudo-element. But I haven't yet made it properly working.But, with all of these, it looks really cool to me, especially when you dragging the border of the browser, which you can do on the jsfiddle page easily: https://jsfiddle.net/extempl/93ymy3oL/. Or just run the snippet with fixed max-width below.
Gif under the spoiler:
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>
The following Javascript function will do a middle truncation, like 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);
}
It will replace characters in the middle with ellipsis. My unit tests show:
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');