views:

202

answers:

3

Hi,

I'm trying to take a text string, (e.g. the word "testing") and calculating if the string, when displayed on screen, will exceed a certain width. I do this by putting it in a element and using width().

Now, the thing is I want to reduce the text string by a character at a time, and then determining the width. If the width is within say "130px", then i'll return that truncated string. I have the following recursive function, but I'm quite new to Js/jQuery and am unsure what I did wrong. If the string is determined to require truncating, the function returns undefined.

Any help is greatly appreciated. Thanks a lot!

  function fitWidth(str) {
    var width = $('span.width').html(str).width();
    if (width > '130') {
      strlength = str.length-1;
      str = str.substr(0,strlength);
      fitWidth(str);
    } else {
      return str; // something wrong here?
    }
  }

var testStr = 'Lorem Ipsum';
alert(fitWidth(testStr)); // returns undefined if it was truncated

if str requires truncating, fitWidth() will return "undefined"

+1  A: 

You need to say return fitWidth(str); in the recursive case.

Russell Leggett
damn. thanks for your help :S haha :)
Lyon
A: 

New Answer: I don't know if this would be faster but it does work.

function fitWidth(str) {
  var width = $('span.width').css('display', 'inline').html(str).width();
  var charWidth = Math.round(width / str.length);
  var maxLength = 130 / charWidth;
  $('span.width').html(str.substr(0, maxLength));
}

Old Answer:

instead of doing this recursively why don't you just use substr() to make the width 130.

like so:

function fitWidth(str) {
  var width = $('span.width').html(str).width();
  if(width > 130) {
    return str.substr(0, 130);
  } else {
    return str; 
  }
}

EDIT: oh, i see now that you are talking about width vs the length of the characters in the string. Still, if you take the width of a font being used i think you could still avoid doing multiple steps.

Samuel
because width is in pixels, and substr is character-based.
DDaviesBrackett
A: 

// Here is one other method,

// but you'll need to translate it to jquery-

function truncate(str, w, pa){
    if(!pa) pa= document.body;
    w= w || pa.offsetWidth;
    var wid, t, L= str.length, c= document.createElement('div');
    c.style.cssText= 
    'position:absolute; visibility:hidden; font:inherit; white-space:pre';
    t= document.createTextNode(str);
    c.appendChild(t);
    pa.appendChild(c);
    wid= c.offsetWidth;

    if(w< wid){
        L= Math.floor(L*(w/wid))-1;
        t.data= str= str.substring(0, L);
        while(t.data && c.offsetWidth> w){
            t.data= str= str.slice(0, -1);
        }
    }
    pa.removeChild(c);
    return str;
}
var testStr= 'The style is white-space:pre to keep it on one line';
alert(truncate(testStr, 130));


//comments
function truncate(str, w, pa){
    // create a hidden element to measure the text-
    // pass a parent element (pa) if the target's font family,
    // weight or size is not the same as body text
    // or if you use the parent's width to size the text

    if(!pa) pa= document.body;
    w= w || pa.offsetWidth;
    var wid, t, L= str.length, c= document.createElement('div');
    c.style.cssText= 
    'position:absolute;visibility:hidden;font:inherit;white-space:pre';
    t= document.createTextNode(str);
    c.appendChild(t);
    pa.appendChild(c);
    wid= c.offsetWidth;

    // measure the width of the whole string
    // if it fits your width, skip the calculations,
    // otherwise multiply the length of the string by
    // the width you want divided by the actual width

    if(w< wid){
        L= Math.floor(L*(w/wid))-1;
        //I'd subtract 1 to grow on and call it str.substring(0, L);

        //but if the exact to the pixel width is critical,
        //measure the new string and chop it if it still needs it:

        t.data= str= str.substring(0, L);
        while(t.data && c.offsetWidth> w){
            t.data= str= str.slice(0, -1);
        }
    }
    // clean up, and return the (possibly) shortened string

    pa.removeChild(c);
    return str;
}
kennebec