1

NOTE: Originally had this listed as a memory leak. After looking into this deeper, I discovered that it's not a memory issue. It's just a very slow script. Any suggestions to speed this up would be greatly appreciated.

ANOTHER NOTE: After looking into this even further, I see that FF does not support any type of CSS that formats text in overflow. There is a hack and a workaround for that hack...but that will not be a suitable solution.

I have voted for and joined the e-mail list on this particular bug at mozilla. It's almost six years old so I resolve that users will just have to deal with it for now. At least it's not a common scenario for our product.

Original post:

The script truncates the value of an element and appends '...' while its scrollWidth is greater than it's offsetWidth. (e.g. A value of "LastName, VeryLongFirstName"will change to something like "LastName, Ver...", depending on the width of the column)

var eTable = document.getElementById(this._eDiv.id + "_tbl");

//...lots of code here...

//function called that gets all cells in a table, loops through them and clips the text
addEventListenerEx(window, "load", function() {     
        var aCells = eTable.getElementsByTagName("DIV");
        window.alert(aCells.length);   
            //When aCells is length of 100, we're ok...but when it's big (like 3,000) I have problems         
        for (var i = 0; i < aCells.length; i++){
            Grid.clipText(aCells[i]);
        }
}, false);

//...lots of code here...

//This is the function doing the actual clipping
Grid.clipText = function (oDiv) {   

    //for tooltip       
    var oCurDiv;
    var oTagA;
    var sToolTip;       
    if (oDiv.firstChild) {
            if (oDiv.firstChild.firstChild){            
                oCurDiv = oDiv.firstChild;
                while (oCurDiv) {
                    if (is.ie) {
                        oTagA = oCurDiv;                        
                    } else {
                        // there are some different between IE & FireFox.
                        oTagA = oCurDiv.firstChild.parentNode;                      
                    }
                    if (oTagA.tagName == "A") {
                        sToolTip = oTagA.innerHTML;     
                        if (sToolTip.indexOf('<b>') > 0) {
                            sToolTip = sToolTip.replace('<b>',"");
                            sToolTip = sToolTip.replace('</b>',"");
                        }
                        if (sToolTip.indexOf('<B>') > 0) {
                            sToolTip = sToolTip.replace('<B>',"");
                            sToolTip = sToolTip.replace('</B>',"");
                        }                       
                        oTagA.parentNode.title = convertHTMLToText(sToolTip);
                    }
                    oCurDiv = oCurDiv.nextSibling;                                      
                }
            } else {
                oDiv.title = convertHTMLToText(oDiv.innerHTML);
            }
        }

        //NOTE:  Additional steps to take for non-IE browsers
        if (!is.ie) {
                    var oText = oDiv;           
                    while (oText.nodeType != 3) {
                        oText = oText.firstChild;
                    }

                    var sDisplayText = oText.nodeValue;
                    if (sDisplayText.length < 3) return; 

                    var lastThree;
                    sDisplayText = sDisplayText.slice(0, parseInt(oDiv.offsetWidth / 5));
                    oText.nodeValue = sDisplayText + "...";

                    //NOTE:  Bad things happen here because of this loop
                    while (oDiv.scrollWidth > oDiv.offsetWidth && sDisplayText != "") {
                        lastThree = sDisplayText.slice(-3);
                        sDisplayText = sDisplayText.slice(0, sDisplayText.length - 3);
                        oText.nodeValue = sDisplayText + "...";
                    }
                    oText.nodeValue = sDisplayText + lastThree.slice(0, 1) + "...";
                    while (oDiv.scrollWidth > oDiv.offsetWidth && sDisplayText != "") {
                        oText.nodeValue = sDisplayText + "...";
                    }
                }

The code works. However, the problem is that it's called over and over again after a table is loaded on the page. When the table is huge (>1,500 cells), that's when the issue starts.

So, I'm really looking for a way to make this sample (particularly the WHILE loop) more efficient.

ray
  • 8,521
  • 7
  • 44
  • 58

2 Answers2

0

Nothing in that is going to leak by itself. You're probably leaking oText in the closure, can you show the surrounding code?

Btw, here is a vastly more efficient way of doing this:

http://jsfiddle.net/cwolves/hZqyj/

If you really want to keep doing it the way you are, you can estimate the cutoff point by taking the length of the string and multiplying it by the proportional width it needs to be...

e.g. if the string is 100 characters and it's 2x as long as it should be, cut it to 50 chars and re-check. Or you could implement a binary 'search' algorithm to get the correct length.

  • oh...I would love to do this in jQuery! :) Alas, I cannot. The pages that load and ultimately call this code may or may not have a reference to jQuery. – ray Mar 24 '11 at 01:05
  • 1
    you can do that without jQuery. jQuery is only doing the same check you are. The 'magic' there is in the CSS and simply showing the ellipsis when the child is longer than the parent. –  Mar 24 '11 at 01:06
  • @cwolves...thanks. you are right. I can. Sorry...when I see that "$" I'm quick to dismiss jQuery. I should've paid closer attention. Ok, so to give a better picture, I've add more code. hopefully to the point where it makes more sense why I have this problem. – ray Mar 24 '11 at 01:47
  • nothing in that should leak either... you sure there's a leak and it's not just that the code is slow? You're replacing the contents of who-knows-how-many cells who-knows-how-many times... –  Mar 24 '11 at 01:52
  • The code is definitely slow. However, there seems to be something with the memory as well. If I watch FF in the task manager as the page loads, the memory will go up to half a gig before the script times out. However, if I add an alert to popup after every 500 records are processed in the aCells loop, the memory goes up to 120mb and then drops down to 80mb after every alert. – ray Mar 24 '11 at 02:42
0

The work-around, and best answer to my problem came from basic arithmetic: cross multiplication

I posted my answer in a more popular stackoverflow thread discussing the topic in better detail.

Community
  • 1
  • 1
ray
  • 8,521
  • 7
  • 44
  • 58