How to find the last visible word position in a text container?
JSFiddle here: http://jsfiddle.net/SmokeyPHP/NQLcc/1/
HTML:
<div id="txt">
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor
invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et
accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata
sanctus est Lorem ipsum dolor sit amet.
</div>
CSS:
#txt {
width: 75px;
height: 75px;
border: 1px solid #F00;
overflow: hidden;
}
JS:
var cntnr = $("#txt");
cntnr.html('<span>'+cntnr.html().replace(/ /g,'</span> <span>')+'</span>')
var words = Array.prototype.slice.call(cntnr.find("span"),0).reverse();
var lastw = null;
for(var i=0,c=words.length;i<c;i++)
{
var w = $(words[i]);
var wbot = w.height() + w.offset().top;
var wleft = w.offset().left;
var wright = wleft+w.width();
if(wbot <= cntnr.height() && wleft <= cntnr.width() && wright <= cntnr.width())
{
lastw = w.text();
break;
}
}
cntnr.html(cntnr.text());
alert(lastw);
The JS could probably be shortened, but I've left it as I was writing & thinking at the same time... In essence, you wrap all words in a span, then loop backwards through the spans, see if their bounds fall within the container, and as soon as we find a span that does sit inside the container's boundaries, break out of the loop and return that word, after returning the text back to plain text (removing the temporary spans).
In addition to @SmokeyPhp answer:
First of all, that was a great answer that helped me a lot, but there were some mistakes in the condition there.
Second of all, I'm working with jqlite library instead of jQuery, so that answer was also very helpful in that area (all the methods he used were part of the jqlite library).
In addition to detecting the last visible word in a span or a div, my function is also replacing the rest of the text with "...".
I'm posting the code I'm using, basically the code @SmokeyPhp posted, but fixed where needed, and I hope others will benefit from it:
function dotdotdot(containersToDotdotdot) {
function dotdotdotContainers(containers) {
for (var i = 0; i < containers.length; i++) {
var cntnr = $jq(containers[i]);
cntnr.html('<span>' + cntnr.html().replace(/ /g,'</span> <span>') + '</span>');
var words = Array.prototype.slice.call(cntnr.find("span"), 0).reverse();
var lastw = null;
for (var j = 0; j < words.length; j++) {
var w = $jq(words[j]);
var wbot = w.height() + w.offset().top;
var wleft = w.offset().left;
var wright = wleft + w.width();
if (wbot <= (cntnr.offset().top + cntnr.height()) && wleft >= (cntnr.offset().left) && wright <= (cntnr.offset().left + cntnr.width())) {
lastw = words.length - j - 1;
break;
}
}
cntnr.html(lastw === null || lastw === (words.length - 1) ? cntnr.text() : (cntnr.text().split(' ').slice(0, lastw).join(' ') + '...'));
}
}
if (containersToDotdotdot instanceof Array) {
for (var i = 0; i < containersToDotdotdot.length; i++) {
dotdotdotContainers($jq(containersToDotdotdot[i]));
}
} else {
dotdotdotContainers($jq(containersToDotdotdot));
}
}
As you can see, my dotdotdot function can get an array of classes/ids to dotdotdot, or a single class/id.
The $jq is the jqlite replacement for jQuery's $.
Thanks @SmokeyPhp, I looked for a long time for a method that does not require jQuery to dotdotdot text, and your method is fantastic.