chacham / Amazon Star percent to number

// ==UserScript==
// @name Amazon Star percent to number
// @namespace http://www.example.com/chacham/
// @description Replace percent with rounded number (and percent)
// @include http://*.amazon.com/dp/*
// @include https://*.amazon.com/dp/*
// @include http://*.amazon.com/*/dp/*
// @include https://*.amazon.com/*/dp/*
// @include http://*.amazon.com/review/*
// @include https://*.amazon.com/review/*
// @include http://*.amazon.com/*/product/*
// @include https://*.amazon.com/*/product/*
// @include http://*.amazon.com/product-reviews/*
// @include https://*.amazon.com/product-reviews/*
// @include http://*.amazon.com/*/product-reviews/*
// @include https://*.amazon.com/*/product-reviews/*
// @include http://*.amazon.com/*/customer-reviews/*
// @include https://*.amazon.com/*/customer-reviews/*
// @grant none
// @version 1.7
// ==/UserScript==

// product page and product-reviews page are implemented the same way, 
// though the product-reviews page has an actual number which could be used instead

// Stars are in different locations depending on the page:
//
// 1) Main product page
// 2) Star-level reviews page, for example, when looking at all 2 star reviews.
// 3) Single review page, when seeing a single review, such as after clicking a review's title, there is a review box on the right side
//
// We'll check for cases 2 and 3, and default to case 1 without a specific check.
// The checks are done on the url, which starts by the forwardslash after "amazon.com".

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// declarations
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
var total;
var percent;
var i;

var star_line;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// functions
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ts = thousands separator
// Only works when comma is the separator.
// Todo: internationalize
function ts_remove(number)
{
 return number.replace(',', '');
}

function ts_add(number)
{
 return number.replace(/(\d)(?=(\d{3})+(?!\d))/g, "$1,");
}

// the total line can have completely different names and html setup
// also, the same name may be used elsewhere for something else
// put them together for clarity and reuse
function get_total(section)
{
  var total;

  switch(section)
  {
   case 'crAvgStars':
     total = document.getElementsByClassName('crAvgStars')[0].childNodes[2].textContent.split(" ", 1)[0];
     break;
   case 'totalReviewCount':
     total = document.getElementsByClassName('a-size-medium totalReviewCount')[0].textContent;
     break;
   case 'summaryStars':
     total = document.getElementById('summaryStars').childNodes[1].childNodes[2].textContent.trim();
     break;
  }

  // remove any thousands separators
  return ts_remove(total);
}

// the star lines can also be completely different
function replace_star_line(section, percent_child_node)
{
 if(section == 'histoCount')
 {
  var star_line = document.getElementsByClassName('histoCount');

  for (i = 0; i < star_line.length; i++)
  {
   percent = star_line[i];
   percent.textContent = ts_add(Math.round(total * percent.textContent.slice(0, -1) * .01).toString()) + ' (' + percent.textContent + ')';
  }
 }
 else
 {
  var star_table;

  star_table = document.getElementById('histogramTable');
  for (i = 0; i < star_table.rows.length; i++)
  {
   percent = star_table.rows[i].cells[2].childNodes[percent_child_node];
   percent.textContent = ts_add(Math.round(total * percent.textContent.slice(0, -1) * .01).toString()) + ' (' + percent.textContent + ')';
  }
 }
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////


///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// case 3 Single review page
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// review doesn't use an html table. With no commonality with the other two cases, we'll modify it first and exit.
if(
      (window.location.pathname.indexOf("/review/") === 0)
   || (window.location.pathname.indexOf("/customer-reviews/") > 0)
  )
{
 // Get the total and remove comma as thousands separator
 total = get_total('crAvgStars');
 replace_star_line('histoCount');
 return;
}

// Cases 1 and 2
// product and reviews use the same mechanism, with some variation. Define what we need, then do the common work.
if(window.location.pathname.indexOf("/product-reviews/") >= 0)
{
 total = get_total('totalReviewCount');
 replace_star_line('histogramTable', 0);
}
else // (product, and the default)
{
 // summaryStars does not seem to be used anymore, instead using totalReviewCount.
 // So, we'll just add it at the end. Not so sure about adding structure to something
 // that changes all the time.
 if(document.getElementById('summaryStars'))
 {
  total = get_total('summaryStars');
  replace_star_line('histogramTable', 2);
 }
 else
 {
  if(document.getElementById('crAvgStars'))
  {
   total = get_total('crAvgStars');
   replace_star_line('histoCount');
  }
  else
  {
   total = get_total('totalReviewCount');
   replace_star_line('histogramTable', 0);
  }
 }
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////