开发者

JS/jQuery: Trying to fit an arbitrary text string within a certain width through substr

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"


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


// 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;
}


I modified the OP code to make it work for me.

This uses jQuery and requires you to add this function (endsWith) to the String prototype. See https://stackoverflow.com/a/2548133/80353.

    function fitWidth(str, selector, widthLimit, heightLimit, suffix, original) {
        if (typeof heightLimit == 'undefined') {
            heightLimit = 10000000000;
        }
        if (typeof suffix == 'undefined') {
            suffix = '';
        }
        if (typeof original == 'undefined') {
            original = str;
        }
        if (suffix.length > 0 && str.endsWith(suffix)) {
            str = str.substr(0, str.length - suffix.length);
        }
        var width = $(selector).html(str).width();
        var height = $(selector).html(str).height();
        if (suffix.length > 0 && original != str) {
            var width = $(selector).html(str + suffix).width();
            var height = $(selector).html(str + suffix).height();
        }

        // console.info($(selector));
        // console.info(width);
        if (width > widthLimit || height > heightLimit) {
          strlength = str.length-1;
          str = str.substr(0,strlength);
          $(selector).html(str + suffix);
          fitWidth(str + suffix, selector, widthLimit, heightLimit, suffix, original);
        } else {
          return true;
        }
      }

// if you want to consider suffix for shortened content like "I want to ..."
fixWidth("I want to break free", "#selector", 180, 60, " ...");

Hope this will help others.


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜