Aligning Decimal Points in HTML

Aligning decimal points in HTML

See this article by Krijn Hoetmer for your options and how to achieve this. The essence of this solution is to use CSS and JS to achieve this:

(function() {  var currencies = /(\$|€|€)/;  var leftWidth = 0, rightWidth = 0;  for(var tableCounter = 0, tables = document.getElementsByTagName("table");      tableCounter < tables.length; tableCounter++) {    if(tables[tableCounter].className.indexOf("fix-align-char") != -1) {      var fCols = [], leftPart, rightPart, parts;      for(var i = 0, cols = tables[tableCounter].getElementsByTagName("col"); i < cols.length; i++) {        if(cols[i].getAttribute("char")) {          fCols[i] = cols[i].getAttribute("char");        }      }      for(var i = 0, trs = tables[tableCounter].rows; i < trs.length; i++) {        for(var j = 0, tds = trs[i].getElementsByTagName("td"); j < tds.length; j++) {          if(fCols[j]) {            if(tds[j].innerHTML.indexOf(fCols[j]) != -1) {              parts = tds[j].innerHTML.split(fCols[j]);              leftPart = parts.slice(0, parts.length -1).join(fCols[j]);              leftPart = leftPart.replace(currencies, "<span class='currency'>$1</span>");              rightPart = fCols[j] + parts.pop();              tds[j].innerHTML = "<span class='left'>" + leftPart + "</span><span class='right'>" + rightPart + "</span>";            } else {              tds[j].innerHTML = tds[j].innerHTML.replace(currencies, "<span class='currency'>$1</span>");              tds[j].innerHTML = "<span class='left'>" + tds[j].innerHTML + "</span>";            }            tds[j].className = "char-align";            var txt = document.createTextNode(tds[j].firstChild.offsetWidth);            if(leftWidth < tds[j].firstChild.offsetWidth) {              leftWidth = tds[j].firstChild.offsetWidth;            }            if(tds[j].childNodes[1]) {              txt = document.createTextNode(tds[j].childNodes[1].offsetWidth);              if(rightWidth < tds[j].childNodes[1].offsetWidth) {                rightWidth = tds[j].childNodes[1].offsetWidth;              }            }          }        }      }    }  }  // This is ugly and should be improved (amongst other parts of the code ;)  var styleText = "\n" +      "<style type='text/css'>\n" +      "  .fix-align-char td.char-align { width: " + (leftWidth + rightWidth) + "px; }\n" +      "  .fix-align-char span.left { float: left; text-align: right; width: " + leftWidth + "px; }\n" +      "  .fix-align-char span.currency { text-align: left; float: left; }\n" +      "  .fix-align-char span.right { float: right; text-align: left; width: " + rightWidth + "px; }\n" +      "</style>\n";  document.body.innerHTML += styleText;})();
table {  border-collapse: collapse;  width: 600px;}th {  padding: .5em;  background: #eee;  text-align: left;}td {  padding: .5em;}#only-css td.char-align {  width: 7em;}#only-css span.left {  float: left;  width: 4em;  text-align: right;}#only-css span.currency {  float: left;  width: 2em;  text-align: left;}#only-css span.right {  float: right;  width: 3em;  text-align: left;}
<table id="only-css">  <thead>    <tr>      <th>Number</th>      <th>Description</th>      <th>Costs</th>    </tr>  </thead>  <tbody>    <tr>      <td>1</td>      <td>Lorem ipsum dolor sit amet</td>      <td class="char-align">        <span class="left">          <span class="currency">$</span>3        </span>        <span class="right">,99</span>      </td>    </tr>    <tr>      <td>2</td>      <td>Consectetuer adipiscing elit</td>      <td class="char-align">        <span class="left">          <span class="currency">$</span>13        </span>        <span class="right">,95</span>      </td>    </tr>    <tr>      <td>3</td>      <td>Pellentesque fringilla nisl ac mi</td>      <td class="char-align">        <span class="left">          <span class="currency">$</span>4        </span>        <span class="right"></span>      </td>    </tr>    <tr>      <td>4</td>      <td>Aenean egestas gravida magna</td>      <td class="char-align">        <span class="left">          <span class="currency">$</span>123        </span>        <span class="right">,999</span>      </td>    </tr>  </tbody></table>

Aligning numbers at decimal point angular ui grid

I think that the best way is to select all the numbers with Javascript, then break them and encapsulate them in 2 span elements like this:

<div>
<span class="int">11.</span><span class="float">293</span>
</div>
<div>
<span class="int">233424.</span><span class="float">89</span>
</div>

Then you can assign a with to the elements and align the .int to right and .float to the left with css:

.int, .float{
display: inline-block;
width: 100px;
}
.int{
text-align: right;
}
.float{
text-align: left;
}

This way the selection is ok and div and span doesn't disturb the meaning of your html5 code. Also, you do not deppend on a fixed width font.

Hope this works, if not, please let me know.

how can I always have two decimals in my label and align the price list

You can use DecimalPipe, like this:

{{ price2 | number : '1.2-2'}}

You can check more in the doc:
https://angular.io/api/common/DecimalPipe

And also in Angular Wiki:
https://www.angularjswiki.com/angular/angular-decimal-pipe/

Cheers!

Formatting numbers so they align on the decimal point

I don't think there's a straight-forward way to do it, since you need to know the position of the decimal point in all the numbers before you start printing them. (I just had a look at Caramiriel's link, and some of the links from that page, but I couldn't find anything particularly applicable to this case).

So it looks like you have to do some string-based inspection & manipulation of the numbers in the list. Eg,

def dot_aligned(seq):
snums = [str(n) for n in seq]
dots = [s.find('.') for s in snums]
m = max(dots)
return [' '*(m - d) + s for s, d in zip(snums, dots)]

nums = [4.8, 49.723, 456.781, -72.18]

for s in dot_aligned(nums):
print(s)

output

  4.8
49.723
456.781
-72.18

If you want to handle a list of floats with some plain ints mixed in, then this approach gets a bit messier.

def dot_aligned(seq):
snums = [str(n) for n in seq]
dots = []
for s in snums:
p = s.find('.')
if p == -1:
p = len(s)
dots.append(p)
m = max(dots)
return [' '*(m - d) + s for s, d in zip(snums, dots)]

nums = [4.8, 49.723, 456.781, -72.18, 5, 13]

for s in dot_aligned(nums):
print(s)

output

  4.8
49.723
456.781
-72.18
5
13

As Mark Ransom notes in the comments, we can simplify handling ints by using .split:

def dot_aligned(seq):
snums = [str(n) for n in seq]
dots = [len(s.split('.', 1)[0]) for s in snums]
m = max(dots)
return [' '*(m - d) + s for s, d in zip(snums, dots)]

Masher mentions in a comment that it can be useful to add padding on the right so that the numbers can be printed in aligned columns. However, we don't need to compute the size of that padding for each string, we can use the str.ljust method.

def dot_aligned(seq):
snums = [str(n) for n in seq]
dots = [len(s.split('.', 1)[0]) for s in snums]
m = max(dots)
left_pad = [' '*(m - d) + s for s, d in zip(snums, dots)]
ms = max(map(len, left_pad))
return [s.ljust(ms) for s in left_pad]

nums = [4.8, 49.723, 456.781, -72.18, 5, 13, 1.2345] * 3
cols = 4
# Get number of cells in the output grid, using ceiling division
size = len(nums) // -cols * -cols

padded = dot_aligned(nums)
for i in range(0, size, cols):
print(*padded[i:i+cols])

output

  4.8     49.723  456.781  -72.18  
5 13 1.2345 4.8
49.723 456.781 -72.18 5
13 1.2345 4.8 49.723
456.781 -72.18 5 13
1.2345


Related Topics



Leave a reply



Submit