I have a webpage with an elastic layout that changes its width if the browser window is resized.
In this layout there are headlines (h2) that will have
Here's another JavaScript solution. Works very good and very fast.
https://github.com/dobiatowski/jQuery.FastEllipsis
Tested on Chrome, FF, IE on Windows and Mac.
This is similar to Alex's but does it in log time instead of linear, and takes a maxHeight parameter.
jQuery.fn.ellipsis = function(text, maxHeight) {
var element = $(this);
var characters = text.length;
var step = text.length / 2;
var newText = text;
while (step > 0) {
element.html(newText);
if (element.outerHeight() <= maxHeight) {
if (text.length == newText.length) {
step = 0;
} else {
characters += step;
newText = text.substring(0, characters);
}
} else {
characters -= step;
newText = newText.substring(0, characters);
}
step = parseInt(step / 2);
}
if (text.length > newText.length) {
element.html(newText + "...");
while (element.outerHeight() > maxHeight && newText.length >= 1) {
newText = newText.substring(0, newText.length - 1);
element.html(newText + "...");
}
}
};
I couldn't find a script that worked exactly as I wanted it so did my own for jQuery - quite a few options to set with more on their way :)
https://github.com/rmorse/AutoEllipsis
Here is a nice widget/plugin library which has ellipsis built in: http://www.codeitbetter.co.uk/widgets/ellipsis/ All you need to do it reference the library and call the following:
<script type="text/javascript">
$(document).ready(function () {
$(".ellipsis_10").Ellipsis({
numberOfCharacters: 10,
showLessText: "less",
showMoreText: "more"
});
});
</script>
<div class="ellipsis_10">
Some text here that's longer than 10 characters.
</div>
<html>
<head>
<!-- By Warren E. Downs, copyright 2016. Based loosely on a single/multiline JQuery using example by Alex,
but optimized to avoid JQuery, to use binary search, to use CSS text-overflow: ellipsis for end,
and adding marquee option as well.
Credit: Marquee: http://jsfiddle.net/jonathansampson/xxuxd/
JQuery version: http://stackoverflow.com/questions/536814/insert-ellipsis-into-html-tag-if-content-too-wide
(by Alex, http://stackoverflow.com/users/71953/alex)
(Improved with Binary Search as suggested by StanleyH, http://stackoverflow.com/users/475848/stanleyh)
-->
<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
<meta content="utf-8" http-equiv="encoding">
<style>
.single {
overflow:hidden;
white-space: nowrap;
width: 10em;
padding: 10px;
margin: 0 auto;
border: solid 1px blue;
}
.multiline {
overflow: hidden;
white-space: wrap;
width: 10em;
height: 4.5em;
padding: 10px;
margin: 0 auto;
border: solid 1px blue;
}
.marquee {
overflow: hidden;
width: 40em;
padding: 10px;
margin: 0 auto;
border: solid 1px blue;
}
</style>
<script>
var _marqueeNumber=0;
// mode=start,end,middle
function clipText(text, len, mode) {
if(!mode) { mode="end"; }
else { mode=mode.toLowerCase(); }
if(mode == "start") { return "…"+clipText(text,len,"_start"); }
if(mode == "_start") { return text.substr(text.length - len); }
if(mode == "middle") {
return clipText(text, len/2, "end") + clipText(text, len/2, "_start");
}
return text.substr(0, len) + "…";
}
function generateKeyframes(clsName, start, end) {
var sec=5;
var totalLen=parseFloat(start)-parseFloat(end);
if(start.indexOf('em') > -1) { sec=Math.round(totalLen/3); }
else if(start.indexOf('px') > -1) { sec=Math.round(totalLen/42); }
var style = document.createElement('style');
style.type = 'text/css';
style.innerHTML = 'body {}';
document.getElementsByTagName('head')[0].appendChild(style);
this.stylesheet = document.styleSheets[document.styleSheets.length-1];
try {
this.stylesheet.insertRule('.'+clsName+' {\n'+
' animation: '+clsName+' '+sec+'s linear infinite;\n'+
'}\n', this.stylesheet.rules.length);
this.stylesheet.insertRule('.'+clsName+':hover {\n'+
' animation-play-state: paused\n'+
'}\n', this.stylesheet.rules.length);
this.stylesheet.insertRule('@keyframes '+clsName+' {\n'+
' 0% { text-indent: '+start+' }\n'+
' 100% { text-indent: '+end+' }\n'+
'}', this.stylesheet.rules.length);
} catch (e) {
console.log(e.message);
}
}
function addClone(el, multiline, estyle) {
if(!estyle) {
try { estyle=window.getComputedStyle(el); }
catch(e) { return null; }
}
var t = el.cloneNode(true);
var s=t.style;
//s.display='none';
s.visibility='hidden'; // WARNING: Infinite loop if this is not hidden (e.g. while testing)
s.display='inline-block';
s.background='black';
s.color='white';
s.position='absolute';
s.left=0;
s.top=0;
s.overflow='visible';
s.width=(multiline ? parseFloat(estyle.width) : 'auto');
s.height=(multiline ? 'auto' : parseFloat(estyle.height));
el.parentNode.insertBefore(t, el.nextSibling);
return t;
}
function getTextWidth(el, multiline) {
var t=addClone(el, multiline);
if(!t) { return null; }
var ts=window.getComputedStyle(t);
var w=ts.width;
if(multiline) {
var es=window.getComputedStyle(el);
var lines=Math.round(parseInt(ts.height)/parseInt(es.height))*2+0.5;
w=w+'';
var unit=''; // Extract unit
for(var xa=0; xa<w.length; xa++) {
var c=w[xa];
if(c <= '0' || c >= '9') { unit=w.substr(xa-1); }
}
w=parseFloat(w);
w*=lines; // Multiply by lines
w+=unit; // Append unit again
}
t.parentNode.removeChild(t);
return w;
}
// cls=class of element to ellipsize
// mode=start,end,middle,marq (scrolling marquee instead of clip)
function ellipsis(cls, mode) {
mode=mode.toLowerCase();
var elems=document.getElementsByClassName(cls);
for(xa in elems) {
var el=elems[xa];
var multiline = el.className ? el.className.indexOf('multiline') > -1 : true;
if(mode == "marq") {
var w=getTextWidth(el, multiline);
if(!w) { continue; }
var mCls="dsmarquee"+(_marqueeNumber++);
var es=window.getComputedStyle(el);
generateKeyframes(mCls,es.width, '-'+w);
el.className+=" "+mCls;
continue;
}
if(mode == "end" && !multiline) { el.style.textOverflow="ellipsis"; continue; }
var estyle=null;
try { estyle=window.getComputedStyle(el); }
catch(e) { continue; }
if(estyle.overflow == "hidden") {
var text = el.innerHTML;
var t=addClone(el, multiline, estyle);
function height() {
var ts=window.getComputedStyle(t);
var es=window.getComputedStyle(el);
return parseFloat(ts.height) - parseFloat(es.height);
}
function width() {
var ts=window.getComputedStyle(t);
var es=window.getComputedStyle(el);
return parseFloat(ts.width) - parseFloat(es.width);
}
var tooLong = multiline ? height : width;
var len=text.length;
var diff=1;
var olen=0;
var jump=len/2;
while (len > 0) {
var diff=tooLong();
if(diff > 0) { len-=jump; jump/=2; }
else if(diff < 0) { len+=jump; }
len=Math.round(len);
//alert('len='+len+';olen='+olen+';diff='+diff+';jump='+jump+';t='+JSON.stringify(t.innerHTML));
t.innerHTML=clipText(text, len, mode);
if(olen == len) { break; }
olen=len;
}
el.innerHTML=t.innerHTML;
t.parentNode.removeChild(t);
}
//break;
t.style.visibility='hidden';
}
}
function testHarness() {
ellipsis('ellipsis1', 'start');
ellipsis('ellipsis2', 'end');
ellipsis('ellipsis3', 'middle');
ellipsis('marquee', 'marq')
}
</script>
</head>
<body onload="testHarness()">
<div class="single ellipsis1" style="float:left">some long text that should be clipped left</div>
<div class="single ellipsis2" style="float:right">right clip long text that should be clipped</div>
<div class="single ellipsis3" style="float:center">some long text that should be clipped in the middle</div>
<br />
<p class="single marquee">Windows 8 and Windows RT are focused on your life—your friends and family, your apps, and your stuff. With new things like the <a href="http://windows.microsoft.com/en-US/windows-8/start-screen">Start screen</a>, <a href="http://windows.microsoft.com/en-US/windows-8/charms">charms</a>, and a <a href="http://windows.microsoft.com/en-US/windows-8/microsoft-account">Microsoft account</a>, you can spend less time searching and more time doing.</p>
<br />
<div class="multiline ellipsis1" style="float:left">Test test test test test test, some more long text, such as asdasdasdasdasd, that should be multiline clipped left(*)</div>
<div class="multiline ellipsis2" style="float:right">right clip multiline long text, such as Test test test test test test, and some more long text that should be multiline clipped right.</div>
<div class="multiline ellipsis3" style="float:center">Test test test test test test, some more long text, such as asdasdasdasdasd, that should be multiline clipped in the middle(*)</div>
<br />
<p class="multiline marquee">Multiline Marquee: Windows 8 and Windows RT are focused on your life—your friends and family, your apps, and your stuff. With new things like the <a href="http://windows.microsoft.com/en-US/windows-8/start-screen">Start screen</a>, <a href="http://windows.microsoft.com/en-US/windows-8/charms">charms</a>, and a <a href="http://windows.microsoft.com/en-US/windows-8/microsoft-account">Microsoft account</a>, you can spend less time searching and more time doing.</p>
</body>
</html>
Just like @acSlater I couldn't find something for what I needed so I rolled my own. Sharing in case anyone else can use:
Method:ellipsisIfNecessary(mystring,maxlength);
Usage:
trimmedString = ellipsisIfNecessary(mystring,50);
Code and Demo Link: https://gist.github.com/cemerson/10368014