4

I'm trying to use the following code on my server to estimate the length of some text fields and potentially trim them before sending them by email...

String.prototype.visualLength = function()
{
    var element = document.createElement("span");
    element.css({
        "visibility": "hidden",
        "white-space": "nowrap",
        "font-weight": "normal",
        "font-size": "18px",
        "line-height": "40px",
        "font-family": "Helvetica, Arial, sans-serif",
        "text-decoration": "none"
    });
    document.body.appendChild(element);
    element.innerHTML = this;
    return element.offsetWidth;
};

String.prototype.trimToPx = function(length)
{
    var tmp = this;
    var trimmed = this;
    if (tmp.visualLength() > length)
    {
        trimmed += "...";
        while (trimmed.visualLength() > length)
        {
            tmp = tmp.substring(0, tmp.length-1);
            trimmed = tmp + "...";
        }
    };
    return trimmed;
};

Obviously I'm getting an error because "document" is not defined server-side. I added the Meteor packages htmljs and domutils hoping they might solve this, but in vain. And I can't add the Node.js package jsdom because apparently it won't work in deployed Meteor apps.

Any idea how to achieve what I'm trying to do?

dimfisch
  • 437
  • 1
  • 4
  • 9
  • What's the goal you are trying to achieve by limiting the text? (Trying to understand why pixel length vs character length) – alanning Mar 20 '13 at 20:48
  • @Rahul no I haven't tried phantomjs. Didn't know about it. Just had a look... not sure how to go about solving this with phantom. Also, is it available as a Meteor package? – dimfisch Mar 20 '13 at 21:07
  • @alanning the goal is not to exceed the maximum width of an HTML email template I'm using. Right now I'm implementing it with a limit on character length instead, but that's way suboptimal ("M" is much wider than "i", unless I use a monospaced font...) – dimfisch Mar 20 '13 at 21:10

2 Answers2

1

I don't think this is possible. Server-side code running in node.js does not run in the context of a web browser's rendering environment and so can't access the browser's DOM and available fonts and display configuration. Even if you were to successfully run your code and compute a number, that computation has no relationship to my device when I receive your email. The fonts, the display size and resolution (could be a desktop, could be a mobile device), my own configuration (for example I set a minimum font size in Firefox on my desktop), etc. Instead try defining your size in em units instead of pixels.

Community
  • 1
  • 1
dsh
  • 12,037
  • 3
  • 33
  • 51
1

You cannot truly rely what will happen on client-side. Even Ubuntu and Windows shows the fonts different because of different hinting, antialiasing and they may have an effect on the displayed sizes.

If you modify your span's css as following, when it has a text larger than the desired space, no matter what, the remaining will be displayed as ...

max-width: 10%;
border: 1px #000 solid; // JUST TO SEE the effect clearly
width: 10%;
overflow: hidden;
height: 20px;
text-overflow: ellipsis;
display: block;
white-space: nowrap;

** Please note that you need a proper height value, other wise the text will go to bottom and what you want will not be achieved.

Try on http://jsfiddle.net/sG6H2/

mquandalle
  • 2,600
  • 20
  • 24
Mustafa
  • 10,013
  • 10
  • 70
  • 116