Amazon - Show absolute review numbers

Adds the number of reviews to each rating separately

< Feedback on Amazon - Show absolute review numbers

Question/comment

§
Posted: 02. 10. 2019

confusion

Percentage and review numbers coincide

GraphenAuthor
§
Posted: 02. 10. 2019
Edited: 02. 10. 2019

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);

Post reply

Sign in to post a reply.