I am trying to build a function that reduces an HTML
text until it does not overflow its container (I don't want the last line broken for the middle). I've taken a look at this question, but the solution is just to manage special characters as <>&
. I've also taken a look at this other question but the solution does not work if the HTML
is very complex. Some solutions are for Webkit only or do not work efficiently with any kind of text (My HTML
could have different styles with different line-heights
).
Here is the code that I have until now (it is as inefficient as the others), with long and complex texts it could iterate thousands of times and as in my application the container should change its size continuously, this code is useless for my needs.
Is there a good and efficient method to achieve this?
NOTE: My
HTML
text only containsTEXT_NODEs
andELEMENT_NODEs
(excludingscripts
andstyles
), I don't need to manage other kind of nodes.
function reduceHTMLText (container) {
var longer = false;
var reg = /^([\s\S]+?)\s*\.+$/;
var regpunt = /^(.*?)[,;\:\.]$/;
var isOverflow = function () {
return container.scrollHeight > container.clientHeight;
};
var reduce = function (element) {
var nodes = element.childNodes;
if (nodes.length === 0) {
longer = isOverflow();
if (longer) { reduce(container); }
return;
}
var last = nodes[nodes.length - 1];
//---Depend of the node type
switch (last.nodeType) {
//---If the node is a text
case 3:
var str = last.data.replace(reg, "$1");
var words = str.split(" ");
//---If the words array has more than five words
if (words.length > 5) {
words = words.slice(0, -5);
words[words.length - 1] = words[words.length - 1].replace(regpunt, "$1");
last.data = words.join(" ") + "...";
} else {
last.parentNode.removeChild(last);
}
longer = isOverflow();
if (longer) { reduce(element); }
break;
//---If the node is an element node
case 1:
if (last.childNodes.length) {
reduce(last);
} else {
last.parentNode.removeChild(last);
longer = isOverflow();
if (longer) { reduce(element); }
}
break;
}
};
longer = isOverflow();
if (longer) { reduce(container); }
}
var container = document.querySelector(".container");
reduceHTMLText(container);
.container {
background-color: #EEE;
height: 170px;
overflow: hidden;
width: 500px;
}
<div class="container">
<p style="text-align: left;">
Vestibulum imperdiet ipsum nec urna ornare, quis malesuada odio viverra. Etiam mollis dolor lacus, ac cursus leo aliquam ut. Etiam eu elit in <strong>massa egestas <em>interdum ut</em> vel magna</strong>. Suspendisse nisl velit, bibendum id hendrerit at, maximus vitae neque. Integer varius sed ante quis porta. Aenean venenatis pellentesque semper. Etiam a quam ut mauris imperdiet vehicula tristique id lacus. <a href='#'>Aliquam lacus metus, mattis a viverra a, <strong>convallis sit amet diam</strong>. In dignissim lorem</a> sit amet, consectetur adipiscing elit. Cras non sem laoreet, tristique felis id, fringilla mi. Fusce sit amet iaculis enim. In malesuada risus eu urna interdum gravida. <strong>Praesent malesuada felis et mi gravida</strong>, at <em>interdum nunc sollicitudin. Quisque <strong>ultrices nibh</strong> in malesuada tempus</em>. Donec tempus efficitur maximus. Praesent ac lacinia odio. Maecenas vel nunc condimentum, luctus diam ac, molestie purus. Cras non tempor magna. Nulla et eros in nunc iaculis eleifend vel at nisi. <strong>Castro pero normal</strong> Aenean quis ultricies arcu, non volutpat neque. Aliquam at justo sed nisi malesuada lobortis eu ut risus. Fusce at enim quis dolor dignissim gravida vel a felis <span class="soleil-label">text paloma samona</span> is cube rubick <a href="http://google.com">because is impossible to</a> mantain the text in a long way.
</p>
<p style="text-align: center;">
<div class='special'>
<span class="soleil-cta-button-pink">
<a href="http://google.com" class="soleil-cta-button-pink">NO REGRETS</a>
</span>
</div>
</p>
</div>