html truncation by character count

by bgmort

HTML

<section id="container" >
    I got a whole bunch of text in here.
    <div>first > second > third
        <br/><i>Some of it's nested:</i>
        <div>second > third > fourth > fifth > sixth</div>
    </div>
    
    <div><b>fifth > sixth > seventh > eighth</b> > ninth > tenth</div>
    <div>one > <a href="#test" style="color: red"><b>two</b> > three > <b>four</b> > five</a> > <b>six</b> > <span style="color: blue">seven > <b>eight</b></span></div>
</div>

<div id="trimmed"></div>

CSS

section {
    width: 300px;
    border: 1px solid blue;
}

JavaScript

function trim(el, chars, appendStr){
    appendStr = appendStr || '...';
    
    var trimContents = function(node){
//        for (var child = node.firstChild; child; child = child.nextSibling) {
        for (var child = node.firstChild, next; child;) {
            //do this before we remove the child
            next = child.nextSibling;
            
            if (chars <= 0) {
                node.removeChild(child);
            }
            else if (child.nodeType == document.TEXT_NODE){
                trimText(node, child);
            }
            else {
                trimContents(child);
            }
            child = next;
        }
    }
    var trimText = function(node, textNode){
        if (chars > 0) {
            var text = textNode.nodeValue.replace(/\s+/g, ' ');
            var len = text.length;

            if (len > chars) {
                //position of the last whitespace character, or -1
                var cutoff = text.substr(0, chars).search(/\s+\S*$/);
                textNode.nodeValue = text.substr(0, cutoff) + appendStr;
                chars = 0;
            }
            else {
                chars -= len;
            }
        }
    }

    trimContents(el);
}

function doTrim(html, len){
    var h3 = document.createElement('h3');
    h3.innerHTML = 'trimmed to ' + len;
    document.body.appendChild(h3);

    var trimmed = document.createElement('section');
    document.body.appendChild(trimmed);
    trimmed.innerHTML = html;

    trim(trimmed, len);
}

var html = document.getElementById('container').innerHTML;
for (var lengths = [0, 25, 50, 75, 100, 120, 150, 200, 250], i = 0, len; len = lengths[i], i < lengths.length; i++){
    doTrim(html, len);
}