2

I have multiple images on a page with the owner's name below it. This is printed by PHP. Some of the names happen to be quite long (which is messing up the page layout). I could very well truncate them inside PHP, but I decided to go with JS instead.

Here is what I'm doing:

$(document).ready(function() {
    truncateNames(".users .a", 50); 
}

function truncateNames(usernameID, maxChars){
     $(usernameID).each(function() {
         var longName = $(this).text();
         if(longName.length > maxChars){ 
             $(this).html(longName.trunc(maxChars));  
         }
     });
}   

// Taken from another question at http://goo.gl/fY4s4. Thanks KooiInc!
String.prototype.trunc =
    function(n,useWordBoundary){
       var toLong = this.length>n,
           s_ = toLong ? this.substr(0,n-1) : this;
       s_ = useWordBoundary && toLong ? s_.substr(0,s_.lastIndexOf(' ')) : s_;
    return  toLong ? s_ + '…' : s_;
};

This works alright. But the problem is that I can see the long names for a few seconds before they are truncated. This also makes the messed up layout visible because of the long names, which auto fixes once names are truncated.

How can this be fixed?

Yeti
  • 5,628
  • 9
  • 45
  • 71
  • 10
    Why not use css - [`text-overflow: ellipsis`](https://developer.mozilla.org/en-US/docs/Web/CSS/text-overflow)? – James Thorpe Sep 08 '15 at 15:05
  • This is a display-layer issue, use CSS – JKirchartz Sep 08 '15 at 15:07
  • I didn't know this can be done using CSS. Now that embarrassing! Ok, but why does it happen? – Yeti Sep 08 '15 at 15:08
  • 1
    Why is it happening - because this bit `$(document).ready...` tells the JS not to run until the entire page has loaded. If you have a lot of records, this can take a few seconds while the browser renders them off the bottom of the page. If you have a lot of JS (outside this) then parsing all that can take time before it runs your script. You could put the jquery.js and this in the `` section, but then your page will take slightly longer before it starts rendering. This is commonly referred to as the FOUC (flash of unstyled content) which you get when using jquery visual plugins. – freedomn-m Sep 08 '15 at 15:17
  • If you truncate the text server-side then you'll also be sending less text down the line (which might be a consideration, depending on by how much you are truncating) – freedomn-m Sep 08 '15 at 15:20
  • 1
    @freedomn-m While true, it starts to become a problem when you truncate by number of characters. eg "WWWWW" is a lot wider than "IIIII". CSS is definitely the preferred way to go here, and gives users the chance to zoom in/out and still have the page render/overflow correctly. – James Thorpe Sep 08 '15 at 15:21
  • @JamesThorpe Indeed, *if* it matches your requirement (which it appears to in this specific case). The js in the question could be used (though appears not to be) to break on word rather than character, [which you can't do in css](http://stackoverflow.com/questions/13012777/text-overflow-ellipsis-avoid-word-break). If the requirement is to fill up a pre-defined space with text (which it appears to be in this case), then css does provide a nice solution. – freedomn-m Sep 08 '15 at 15:33

2 Answers2

4

CSS:

overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;

SASS:

@mixin text-truncate {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
Lowkase
  • 5,631
  • 2
  • 30
  • 48
  • Is this compatible with all major browsers? Had no clue this could be done in CSS. – Yeti Sep 08 '15 at 15:10
  • @Yeti There's a [browser compatibility table](https://developer.mozilla.org/en-US/docs/Web/CSS/text-overflow#Browser_compatibility) on the page I linked to - it should be fine. See also [caniuse.com](http://caniuse.com/#search=text-overflow). – James Thorpe Sep 08 '15 at 15:14
1

JavaScript probably isn't the way to go here, since you'll have to wait for the document to load before manually truncating all the text. I suggest the following CSS solution:

div.ellipsize { 
  width: 200px; 
  border: 1px solid #000; 
  overflow: hidden; 
  text-overflow: ellipsis; 
  white-space: nowrap; 
}
<div class="ellipsize">Long text that's gonna get cut off</div>