2

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 HTMLis 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 contains TEXT_NODEs and ELEMENT_NODEs (excluding scripts and styles), 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>
Community
  • 1
  • 1
ElChiniNet
  • 2,778
  • 2
  • 19
  • 27
  • 1
    Have you looked at doing this with css? You can clip overflow text or use ellipsis. https://developer.mozilla.org/en-US/docs/Web/CSS/text-overflow – noveyak Feb 23 '17 at 21:23
  • The `text-overflow` is useful for inline texts, not for a block of texts. Take a look at the comment: _This property only affects content that is overflowing a block container element in its inline progression direction (not text overflowing at the bottom of a box, for example) Text can overflow when it is prevented from wrapping (e.g., due to ‘white-space: nowrap’) or a single word being too long to fit_ – ElChiniNet Feb 23 '17 at 21:27
  • you can try css's `overflow:scroll/hide` and that can achieve the same effect – xxfast Feb 23 '17 at 23:29
  • 1
    @IsuruKusumal, my text already has `overflow: hidden` property. But the size of the container is dynamic and the content could have different `fonts`, `sizes` and `line-heights`. I don't want the last line broken for the middle. – ElChiniNet Feb 23 '17 at 23:35

0 Answers0