views:

622

answers:

11

I have a page with lots of big number values. Millions and billions of dollars going everywhere. And it is hard to read these numbers, so my client asks me to break them into more readable chunks of three symbols, "$100000000" => "$100 000 000".

This is completely reasonable request, but the problem is that I do not want to do this on server-side, and I do not want to do this with javascript. You see, I have a really big heap of javascript already running on this page, doing complex computations on these long numbers, and it will be really difficult to insert a parseReadableStringToInteger() in every place that reads data from page and a writeIntegerAsReadableString() in every place that writes results back to page.

So, I am thinking of using CSS to make long string display as a set of short chunks. My first thought was of -moz-column and -webkit-column, but unfortunately, they work only with words that are already separated by space.

Maybe there is another way? Any suggestions are welcome.

p.s. Cross-browser compatibility is not required. I'm ok with Gecko and/or Webkit.

+1  A: 

You're going to have to find a JavaScript way to do this, I'm pretty certain. Any CSS technique, even if it were possible, wouldn't be cross-browser.

Skilldrick
Cross-browser compatibility is not an issue for the moment. I'm ok with Gecko and/or Webkit.
n1313
After two days of experiments I decided to drop it and go with JS. So, this answer is technically correct :)
n1313
@n1313 Sorry about that!
Skilldrick
+2  A: 

If you aren't willing to use JavaScript to change the formatting, you should change their format from the server...ie, before rendering the page.

Andreas Grech
A: 

I found this piece of javascript which might help you out if you are going to do it client-side: http://homepage.mac.com/ruske/ruske/C2127905073/E844527267/Media/FormatInteger.js

James B
A: 

No CSS manipulates strings. Sry you'll have to do it with JS

fmsf
really? IMHO, "word-wrap" property manipulates strings pretty nicely.
n1313
@n1313: not to mention `text-transform`.
RegDwight
@n1313: Word-wrap doesn't manipulate strings - it actually just 'controls' it's behavior in box/div/p/whatever.
Adam Kiss
@Adam Kiss: well, isn't that exactly what I want?
n1313
i should clarify that it does change/control behavior when it comes to wrapping text. also `text-transform` only changes case of text. AFAIK, you can't split, change or otherwise modify text in HTML with css
Adam Kiss
+1  A: 

Here is a suggestion that would work, although even I will admit it isn't very nice...

Using the jQuery framework, $("#myElement").text() returns just the text (not any nested html). So you could do this:

<p>$<span id="myElement"><span class="triad">1</span><span class="triad">000</span><span class="triad">000</span></p>

And apply some padding or margin to make it more readable.

When you then call:

$("#myElement").text();

You would get the plain 1000000 back.

CSS:

.triad { padding-left: 5px; }
Sohnee
No, I don't use jQuery here and I don't plan to. Sorry, I must stick with ol' good innerHTML :(
n1313
This is the best solution so far.
Skilldrick
Just use a regex to strip the <span>s then.
Skilldrick
+1 for "simpleness" of solution :]
Adam Kiss
he can not write all of that manually for a number of monetary text, he needed a way to select and manipulate that text.
Sarfraz
I already mentioned this approach in the question text, note the "parseReadableStringToInteger()" and "writeIntegerAsReadableString()" functions. I will go this way if there is no another way, because there is, like, 230kb of javascript to patch, and I am lazy. :)
n1313
You should still be able to use `document.getElementById("myElement").textContent` to get the text back. `innerHTML` is unnecessary here.
Samir Talwar
Wow - I wasn't expecting such a big response for this. My motivation for this suggestion was that you didn't need any JavaScript to render this text and it's quite easy to get it back out without parsing. I admit it isn't the best solution - if you were green-field, would you do things this way? Not a chance. But given the situation in the question, you might consider it.
Sohnee
A: 

I wish this was possible with CSS :( you can not get text value and use that in later operations using CSS.

Sarfraz
Well, that's a nice trick, but how it can help me? :)
n1313
@n1313: sry, misunderstood little bit :)
Sarfraz
+13  A: 

Noway do it via CSS, but you can extend Number type like this:

    Number.prototype.formatMoney = function(c, d, t){
    var n = this, c = isNaN(c = Math.abs(c)) ? 2 : c, d = d == undefined ? "," : d, t = t == undefined ? "." : t, s = n < 0 ? "-" : "", i = parseInt(n = Math.abs(+n || 0).toFixed(c)) + "", j = (j = i.length) > 3 ? j % 3 : 0;
       return s + (j ? i.substr(0, j) + t : "") + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + t) + (c ? d + Math.abs(n - i).toFixed(c).slice(2) : "");
    };

then use it like this:

var count = 10000000;
count.formatMoney(2, '.', ' ')
Skay
Hey, that's pretty clever.
n1313
Nice way of thinking. Maybe you could even override the `toString()` function for a new 'Currency' class having the `Number` as prototype.
xtofl
Yeah, but it's limited for i18n. Better make it on the server side.
e-satis
A: 

How about having the number twice: Once for displaying and once for manipulation like this:

<span class="money" data-value="1000000">$ 1 000 000</span>

Then you can easly use getAttribute('data-value') to get to the value from your JS and format the number any way you want.

data-* attributes are a new feature in HTML 5, but pretty much all current browsers already support it (modulu the .dataset property in the DOM, so you'll have to use getAttribute() in current/older browsers).

Joachim Sauer
Does the `data-value` attribute exist for the `span` element, or can you freely add attributes to your liking?
xtofl
So I still need to write a function that translates data-value into innerHTML?
n1313
@n1313: I missed the part where you asked about changing the value. In that case: yes, you'd still have to do that.
Joachim Sauer
+6  A: 

Damn it, I'm almost there!!

span {
    display: block;
    -moz-column-gap:5px;
    -moz-column-width:24px;
    word-wrap:break-word;
}

<span>100000</span>
<span>1000000</span>
<span>10000000</span>
<span>100000000</span>

gives me

100 000
100 000 0
100 000 00
100 000 000

The only thing that is left is somehow start the splitting from the right. Now experimenting with direction: rtl and such :)

n1313
in my firefox 3.5.9 (mac os x) it doesnt work ^^ i can see - "10 00 00 00 0" =)
Skay
You'll need to be absolutely sure of the pixel width of your typeface, surely? Try using numbers that don't end with all zeroes (so the column gaps would be at varying pixel offsets from the right of the strings).
Andrew Duffy
Well, yeah, sure, it will need some fine tuning on a later stage :)
n1313
Can you use some transformation to turn the text to right-to-left and then back to left-to-right (i.e., through nesting)
Michael Stum
i give you A for Effort
Ian Boyd
Just thought I'd mention that it might be worth looking at CSS3 pseudo-selector `nth-child(n)`. Problem is, it won't select "nth-letters", but it would work if you wrapped all your digits in spans. (ugly, though) Then you could do: `p :nth-child(3n){margin-left:3px}` which is in the same area as the column-properties you're messing around with.
peirix
+1  A: 

n1313, http://wiki.csswg.org/ideas/content-formatting ;) it's not a solution, just idea

Skay
O bright future, where art thou?!
n1313
A: 

The first thing that comes to mind is using :after and :before with content:" "
Then you just need something that dynamically add a tag around the right numbers and style it.

Knu