# Rewriting file names according to the available screen space

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">
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: After: 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. - ## 2 Answers 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.

-
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.

-
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. – zb' Dec 25 '12 at 3:21
fyi in xfs max filename size is 255 bytes, not sure if it big or not, depend how often you plan call such function – zb' Dec 25 '12 at 3:25