Creating something similar to this requires consideration of multiple factors. For example, your "text" may consist of a combination of text and various other elements like <b>
, <i>
, or <img>
. If we assume it's solely plain text, the approach outlined below involves iteratively splitting the string into smaller sections in order to determine the text that matches the height of your original element while keeping any overflow hidden.
function getVisibleText(source)
{
let yardstick = document.createElement(source.nodeName);
let sourceRectangle = source.getBoundingClientRect();
let text = source.textContent;
yardstick.style.width = sourceRectangle.width + "px";
yardstick.style.position = "absolute";
yardstick.style.top = "-999px";
yardstick.style.left = "-999px";
yardstick.textContent = text;
source.parentNode.appendChild(yardstick);
let size = text.length;
let difference = size;
let yardstickRectangle = yardstick.getBoundingClientRect();
let result = text;
while((difference > 1 || yardstickRectangle.height > sourceRectangle.height) && size > 0)
{
difference = Math.round(difference / 2);
if(yardstickRectangle.height > sourceRectangle.height)
size -= difference;
else
size += difference;
result = text.substring(0, size);
yardstick.textContent = result;
yardstickRectangle = yardstick.getBoundingClientRect();
}
yardstick.parentNode.removeChild(yardstick);
// Trim to the last whole word
let match = (new RegExp("\\s+\\S*?$", "g")).exec(result)[0];
if(match)
result = result.substring(0, result.length - match.length);
return(result);
}