views:

240

answers:

2

I am trying to create a jQuery function that will take a string and a fixed width as an input, then through a binary search method (for efficiency) "shrink" that piece of text so it's no longer than the fixed width.

This is what I have so far:

function constrain(text, ideal_width){
    var temp = $('.temp_item');
    temp.html(text);
    var item_width = temp.width();
    var ideal = parseInt(ideal_width);

    var text_len_lower = 0;
    var smaller_text = text;
    var text_len_higher = text.length;

    while (true) {
        if (item_width > ideal) {

            // make smaller to the mean of "lower" and this
            text_len_higher = smaller_text.length;
            smaller_text = text.substr(0, ((text_len_higher + text_len_lower)/2));

        } else {

            if (smaller_text.length >= text_len_higher) break;

            // make larger to the mean of "higher" and this
            text_len_lower = smaller_text.length;
            smaller_text = text.substr(0, ((smaller_text.length + text_len_higher)/2));

        }

        temp.html(smaller_text);
        item_width = temp.width();
    }

    var new_text = smaller_text + '…'
    return new_text;
}

Unfortunately this causes a "slow script" that never completes in my browser. Firebug points to line 1131 of jquery.js (version 1.3.2), which is the "unique" jQuery utility, as the culprit. I'm not using "unique" anywhere however.

What am I doing wrong here?

+2  A: 

Can you hook up a javascript debugger and check where it crashes? Use Firebug with Firefox or MSVS with IE. If it blows up so hard the debugger dies, step through the function and see how far it gets.

Update based on last comments: I think you need to step through your code and see how far it gets. I would be suspicious of a few things:

  1. Maybe the width of the object hasn't been recalculated yet (or has become invalid) after setting the new inner text. It could be that the updated width is not available until later, when the UI does a readjustment.

  2. This loop in theory should always terminate, but its possible (especially if the browser is not recalculating the width correctly) the loop could go on forever.

  3. You could be splitting an HTML tag when you split the inner text, causing your code to insert malformed HTML perhaps causing the page layout to break.

Frank Schwieterman
Firebug is telling there's an error in jquery.min.js, which I'm sure isn't the culprit here.
Simon
Try debugging with the un-minified jquery. You should be able to get more info about where the error is that way.
Matthew Crumley
Thanks Matthew. I just tried this and it seems to stall on line 1131 of jquery.js (version 1.3.2), which is the return array of the "unique" jQuery utility as far as I can tell. I'm not using "unique" anywhere though. Confused I am.
Simon
Did you check what else is on the callstack?
Frank Schwieterman
@Frank, this is what I have in the callstack:(?)()pushStack()add()add()empty()each()each()(?)()html()constrain(?)()each()each()(?)()(?)()each()ready()(?)()What's further bizarre (to my unexperienced self, at least), is that after running the script again, Firebug now points to line 26 of jquery.js as the problem.
Simon
Debug step by step rather than just at the moment of error.
Dmitri Farkov
+1  A: 

You are trying to implement something that is already there:

the text-overflow:ellipsis property of CSS. Unfortunately, it is only supported by IE yet, but a jQuery plugin brings the functionality to Firefox. Google for "text-overflow:ellipsis firefox" as I'm not yet allowed to post links.

Franz
here's a link I found via Franz's suggestion http://devongovett.wordpress.com/2009/04/06/text-overflow-ellipsis-for-firefox-via-jquery/
Frank Schwieterman
Wow - this is great! The CSS solution is (of course) much faster, and it works in Safari 4 too (I did not try with Safari 3). Thanks much!
Simon