JavaScript, Fractions, and DOM Manipulations: A Proof of Concept

As part of a Django App I’m building, I wanted to be able to scale a list of numeric values that also happened to be fractions.  Furthermore, I wanted to do this completely in browser without incurring a call to the server each time I needed to recalculate.  To accomplish this, I found a library on github that nicely handles doing math with fractions (Ratio.js), then manually modified the HTML table’s DOM where the values to be scaled were stored/displayed.  The following was a proof of concept, and I make no claims that this is the best way to do this.

My HTML table:

<h1>Table of values to scale</h1>
<form method="post">
<table id="myTable">
<tbody>
<tr><th>base value</th><th>scaled value</th></tr>
<tr><td>1/3</td><td>1/3</td></tr>
<tr><td>3/2</td><td>3/2</td></tr>
<tr><td>2 1/4</td><td>2 1/4</td></tr>
<tr><td>5/7</td><td>5/7</td></tr>
</tbody>
</table>
Scale:
<select id="scale" onchange="compute()">
<option value="3">3</option>
<option value="2">2</option>
<option selected="selected" value="1">1</option>
<option value="1/2">1/2</option>
<option value="1/3">1/3</option>
</select>
</form>

For what I’m doing, I want to keep the original values visible.  The Select element contains the different factors by which to scale my set of base values.

This is the Javascript that accomplishes the conversion:

function convert(input, factor){
  var ans = Ratio.parse(input);    // create Ratio object
  ans = ans.multiply(factor);      // scale the number
  ans = ans.reduce();              // simplify fraction
  return ans.toLocaleString();     // convert back to string
}

parse() offers a range of flexibility when attempting to turn a string into a ratio/fraction object.  multiply() accepts either a ratio object or can parse it’s input on the fly into a ratio object.  reduce() converts my fraction into a mixed number.

function getScaleFactor(){
  var scale=document.getElementById('scale').options;
  var factorIndex=document.getElementById('scale').selectedIndex;
  return scale[factorIndex].text;
}

function compute(){
  var myTable=document.getElementById('myTable').rows;
  var baseValue;
  var scaledValue;
  var factor = getScaleFactor();
  for (var row=1; row < myTable.length; row++) {
    baseValue=myTable[row].cells[0].innerHTML;
    scaledValue=convert(baseValue,factor);
    myTable[row].cells[1].innerHTML=scaledValue;
 }
}

compute() loops over the table, extracts the number from the first column, scales it using Ratio, then inserts it into the second column. The trickiest part was getting the right DOM syntax.

Sure, I could have used something like jQuery for updating the table, but since my application is light on DOM manipulation right now, I wanted to try doing it by hand first. Plus, I like to do things directly first, so I can understand things at their fundamental levels before relying on something like jQuery to do the heavy lifting for me.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s