Chop text to width

by Paulpro

HTML

<div>This text is too long for this 120px wide div</div>

CSS

div{
    width: 120px;
    overflow: hidden;
    border: 1px solid #226;
}

JavaScript

chop(document.getElementsByTagName('div')[0], 120);


function chop(els, max){
    if(els instanceof NodeList || els instanceof Array || els instanceof HTMLCollection)
        for(var i = els.length; i;)
            _chop(els[--i], max);
    else
        _chop(els, max);

    function _chop(el, max){
        
        el.style.overflow = 'visible';
        el.style.width = max+'px';
        
        var tmp = document.createElement('div');
        if(getComputedStyle)
            tmp.style.cssText = getComputedStyle(el, null).cssText;
        else if(el.currentStyle)
            tmp.style.cssText = el.currentStyle.cssText;
        
        tmp.style.position = 'absolute';
        tmp.style.width = 'auto';
        
        var padding = tmp.style.padding;
        tmp.style.padding = '0';
        tmp.innerHTML = 'M';
        el.parentNode.appendChild(tmp);
        var em = tmp.clientWidth;
        tmp.style.padding = padding;
        
        var text = el.textContent || el.innerText;
        el.setAttribute('title', text);
            
        // Estimate number of characters that can fit.
        var numc = Math.floor(max/em);
        
        var width = 0;
        while(width < max && numc <= text.length){
            numc++;
            tmp.innerHTML = text.substring(0, numc).replace(/&/g, "&amp;")
                                   .replace(/</g, "&lt;")
                                   .replace(/>/g, "&gt;")
                                   .replace(/"/g, "&quot;")
                                   .replace(/'/g, "&#039;");
            width = tmp.clientWidth;
        }
        
        if(numc > text.length){
            tmp.parentNode.removeChild(tmp);
            return;
        }
        numc--;
        
        do{
            text = text.substring(0, numc)+'...';
            tmp.innerHTML = text.replace(/&/g, "&amp;")
                                   .replace(/</g, "&lt;")
                                   .replace(/>/g, "&gt;")
                ...