Adds the number of reviews to each rating separately
< Feedback on Amazon - Show absolute review numbers
Thanks for the report, see if the updated version 1.1.1 works for you.
I also got a rewrite of this which I unfortunately never finished... it will include the reviewbars in popups and better handle everything by mutation observers. As I'm a noob on all this async stuff (... and all JS in general) it never really worked.
// ==UserScript==
// @name Amazon show absolute review numbers
// @namespace graphen
// @version 2.1.1
// @description Adds the number of reviews to each rating separately
// @author Graphen
// @include /^https?:\/\/www\.amazon\.(cn|in|co\.jp|sg|fr|de|it|nl|es|co\.uk|ca|com(\.(mx|au|br))?)\/.*(dp|gp\/(product|video)|exec\/obidos\/ASIN|o\/ASIN|product-reviews)\/.*$/
// @include /^https?:\/\/www\.amazon\.(cn|in|co\.jp|sg|fr|de|it|nl|es|co\.uk|ca|com(\.(mx|au|br))?)\/s\?.*$/
// @icon https://www.amazon.com/favicon.ico
// @grant none
// @noframes
// ==/UserScript==
/* jshint esversion: 8 */
(function(doc) {
'use strict';
// checkElement helper
const checkElement = async selector => {
while ( document.querySelector(selector) === null) {
await new Promise( resolve => requestAnimationFrame(resolve) );
}
return document.querySelector(selector);
};
// Sanitize totalReviewCount
function saniTRC(TRC) {
//console.log("saniTRC: untreated --- " + TRC);
TRC = TRC.replace(/\D/g, ''); // Remove all non-digits
TRC = parseInt(TRC, 10); // Convert string to integer
if (TRC < 250000) { // Check for nonsense (Most reviewed product has ~100000 at the moment)
return TRC;
}
else {
//console.log("saniTRC: Failed! TRC > 250000 --- " + TRC);
}
}
function appendCount(totalReviews, targetArr) {
for (let e of targetArr) {
let v = e.innerText; // Take respective percentage value
v = parseInt(v, 10); // Get rid of percentage sign and convert string to integer
v = Math.round(v * totalReviews / 100); // Calculate absolute review count
if (v > totalReviews || v < 0) { // Cancel if nonsense
break;
}
e.textContent += " (" + v + ")"; // Append calculated value to visible node
}
}
function reviewCountOnPopups(nodeElement) {
checkElement('.a-link-emphasis') //use whatever selector you want
.then((element) => {
console.info(element);
//Do whatever you want now the element is there
});
totalReviewCount = nodeElement.querySelector(".a-link-emphasis");
if (totalReviewCount) {
if (totalReviewCount.innerText) { // TypeError if totalReviewCount doesn't exist; But need to check for empty innerText
totalReviewCount = saniTRC(totalReviewCount.innerText);
console.log("Sanitized TRC: " + totalReviewCount);
arrPercentages = Array.from(nodeElement.querySelectorAll("#histogramTable td:last-of-type > span:last-of-type"));
if (arrPercentages) {
appendCount(totalReviewCount, arrPercentages);
}
}
}
}
function checkHistogramTable(nodeElement) {
let MOht = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
mutation.addedNodes.forEach(function(nodeElement) {
if (nodeElement.id) { // Not having an ID would produce error in next line
if (nodeElement.id.match(/^a-popover-\d+/)) { // Filter popup nodes from addedNodes MutationRecord NodeList
hasHistogramTable = checkHistogramTable(nodeElement);
console.log("Popup detected.");
if (hasHistogramTable) {
reviewCountOnPopups(nodeElement);
// add MO for [aria-hidden=false] - popup is not removed when unhovered, but hidden by [aria-hidden=true]
}
}
}
});
});
});
MOht.observe(resultList, { childList: true, subtree: false });
return hasHistogramTable;
}
// Insert own stylesheet
let reviewStyle = doc.createElement("style");
reviewStyle.innerHTML = "#histogramTable td:last-of-type { text-align: right !important; }";
doc.head.appendChild(reviewStyle);
// Initialize variables
var totalReviewCount, arrPercentages, intervalCounter, hasHistogramTable;
// Append absolute review numbers to product and review pages, not search pages
if (window.location.href.match(/^https?:\/\/www\.amazon\.(cn|in|co\.jp|sg|fr|de|it|nl|es|co\.uk|ca|com(\.(mx|au|br))?)\/.*(dp|gp\/(product|video)|exec\/obidos\/ASIN|o\/ASIN|product-reviews)\/.*$/)) {
try { // try-catch to suppress errors
totalReviewCount = document.querySelector('[data-hook="total-review-count"]').innerText;
arrPercentages = Array.from(document.querySelectorAll("#histogramTable .a-text-right > span > .a-link-normal"));
}
catch(error) {
console.log("Amazon absolute review numbers: Target element not found.");
}
if (totalReviewCount && arrPercentages) {
totalReviewCount = saniTRC(totalReviewCount);
appendCount(totalReviewCount, arrPercentages);
}
}
// MutationObserver: Search for hover popups in Amazon search results and append
let resultList = doc.querySelector('body');
if (resultList) {
let MO = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
mutation.addedNodes.forEach(function(nodeElement) {
if (nodeElement.id) { // Not having an ID would produce error in next line
if (nodeElement.id.match(/^a-popover-\d+/)) { // Filter popup nodes from addedNodes MutationRecord NodeList
hasHistogramTable = checkHistogramTable(nodeElement);
console.log("Popup detected.");
if (hasHistogramTable) {
reviewCountOnPopups(nodeElement);
// add MO for [aria-hidden=false] - popup is not removed when unhovered, but hidden by [aria-hidden=true]
}
}
}
});
});
});
MO.observe(resultList, { childList: true, subtree: false });
}
/**/
})(document);
confusion
Percentage and review numbers coincide