Take the 2-minute tour ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

I created a function that rewrites file names according to the available space on screen:

@{
  var index = 0;
  foreach (var item in Model)
  {
  <div class="gallery-item">
    <a href="@item.Uri" title="Click to open file" target="_blank" style="display:block; width: 100%;">          
        var id = "filename_" + ++index;
        @Html.SpanFor(i => item.FileName, new { id = id, title = item.FileName, style = "white-space: nowrap;" })          
    </a>
  </div>
  }
}

@section Scripts
{
  <script type="text/javascript">
    function adaptWidth(span) {
      var span = $(span);
      var origfilename = span.text();
      var ext = origfilename.split('.').pop();
      var filename = origfilename.substr(0, origfilename.length - ext.length - 1);
      var text = origfilename;

      while (span.outerWidth() > span.parent().innerWidth()) {
        span.text(text = (filename = filename.substr(0, filename.length - 4) + '...') + ext);
      }
    }

    $(document).ready(function () {
      $('span[id^=filename_]').each(function (i) { adaptWidth(this) });
    });
  </script>
}

Here are the results before and after running script:

Before:

enter image description here

After:

enter image description here

The function runs quite fast for now, but should I be worried from future impact? Any other suggestion or alternatives? Optimization?

I thought about splitting it to 3 spans, 1 for filename, second for ..., and 3rd for the extension, but I don't really know how to make the overflow of the first be hidden under the other two. Besides, if a truncation isn't required, it's gonna look weird.

share|improve this question

2 Answers 2

up vote 2 down vote accepted

Here are a couple tweeks for your code. I integrated @eicto's suggestion, which is the first step in applying an interpolated search.

var $spans = $('span'),
    parentWidth = $spans.first().parent().innerWidth();

$spans.each(function () { 
    adaptWidth(this, parentWidth);
});

function adaptWidth(elm, maxW) {

    // make a var `$elm` so know it's a jQuery object
   var $elm = $(elm),
        // use `lastIndexOf()` to split the filename and
        // extension halves instead of splitting into an array
        fullname = $elm.text(),
        idx = $elm.text().lastIndexOf('.'),
        name = fullname.substr(0, idx),
        ext = fullname.substr(idx),
        // factor is the ratio of the space available for
        // the text vs the space it currently takes up
        factor = maxW / $elm.outerWidth(),
        // idx is a first guess at where the cutoff will be
        idx = (fullname.length+4) * factor;

    idx = Math.round(idx);

    while ($elm.outerWidth() > maxW) {
        name = name.substr(0, --idx);
        $elm.text(name + '...' + ext);
    }
}

The jsFiddle i was testing with.

Edit:

A few edits in the text and, per a comment from the OP, updated the code to determine the max-width only once.

As a side-note, apparently this type of search is called an interpolation-sequential search.

share|improve this answer
    
Since the tiles are shared width, I will check its size only once. Answer updated. –  Shimmy Dec 27 '12 at 12:05
    
@Shimmy Good to know. I don't see your edit so I added the change. –  tiffon Dec 28 '12 at 7:39

In general case I would to get text_width and container_width, then calculate new_string_length=container_width/text_width*length, than setup increase or decrease text, depending on result_text_width > container_width and do the loop like yours.

This is really needed only if strings have a very big size.

share|improve this answer
    
1) It's for filenames, how long can a filename be? I guess not too long. 2) I'm affraid you missed out the whole point, the reason I needed this function is because the font is not a fixed-width one, the width varies between the various characters in it. –  Shimmy Dec 25 '12 at 3:20
    
2) not i not missed, I just think that change length before loop will decrease interations. –  eicto Dec 25 '12 at 3:21
    
I see your point, thanks then. –  Shimmy Dec 25 '12 at 3:23
1  
fyi in xfs max filename size is 255 bytes, not sure if it big or not, depend how often you plan call such function –  eicto Dec 25 '12 at 3:25

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.