Display rating scores and add filtering capabilities on Amazon search results.
// ==UserScript==
// @name Amazon Enhancements: Ratings Display and Filtering
// @namespace http://tampermonkey.net/
// @version 2.3
// @description Display rating scores and add filtering capabilities on Amazon search results.
// @author Dave w/ Claudi.ai & ChatGPT
// @match https://*.amazon.com/s?*
// @grant none
// @license MIT
// ==/UserScript==
(function() {
'use strict';
let currentFilter = 0;
// Function to enhance rating display
const enhanceRatingDisplay = (result) => {
const ratingElement = result.querySelector('i.a-icon-star-small span.a-icon-alt');
if (ratingElement && !result.classList.contains('enhanced-rating')) {
const ratingText = ratingElement.textContent.trim();
const ratingValue = parseFloat(ratingText.split(' ')[0]);
const newRatingElement = document.createElement('span');
newRatingElement.textContent = ratingValue + ' ';
newRatingElement.style.fontWeight = 'bold';
newRatingElement.style.color = '#007600'; // Change color if needed
newRatingElement.style.marginRight = '5px'; // Add some spacing between the ratings
ratingElement.parentElement.parentElement.insertBefore(newRatingElement, ratingElement.parentElement);
result.dataset.ratingValue = ratingValue;
result.classList.add('enhanced-rating');
}
};
// Function to add filter dropdown and refresh icon
const addFilterDropdown = () => {
const filterBar = document.createElement('div');
filterBar.id = 'rating-filter-bar';
const filterLabel = document.createElement('span');
filterLabel.textContent = 'Filter by star rating: ';
filterLabel.style.marginRight = '5px';
filterBar.appendChild(filterLabel);
const filterDropdown = document.createElement('select');
filterDropdown.style.marginRight = '10px';
// Define dropdown options and their actions
const filters = [
{ text: 'All', score: 0 },
{ text: '4.9+', score: 4.9 },
{ text: '4.8+', score: 4.8 },
{ text: '4.7+', score: 4.7 },
{ text: '4.6+', score: 4.6 },
{ text: '4.5+', score: 4.5 },
{ text: '4.4+', score: 4.4 },
{ text: '4.3+', score: 4.3 },
{ text: '4.2+', score: 4.2 },
{ text: '4.1+', score: 4.1 }
];
filters.forEach(filter => {
const option = document.createElement('option');
option.value = filter.score;
option.textContent = filter.text;
filterDropdown.appendChild(option);
});
filterDropdown.addEventListener('change', (event) => {
currentFilter = parseFloat(event.target.value);
filterResults(currentFilter);
});
filterBar.appendChild(filterDropdown);
const refreshIcon = document.createElement('span');
refreshIcon.innerHTML = '↻'; // HTML entity for refresh icon
refreshIcon.style.cursor = 'pointer';
refreshIcon.style.marginLeft = '5px';
refreshIcon.addEventListener('click', () => {
filterResults(currentFilter);
});
filterBar.appendChild(refreshIcon);
// Insert the filter bar at the top of the search results
const searchResults = document.querySelector('div.s-main-slot.s-result-list.s-search-results.sg-row');
if (searchResults) {
searchResults.insertBefore(filterBar, searchResults.firstChild);
}
};
// Function to filter results based on rating score
const filterResults = (minScore) => {
const results = document.querySelectorAll('div[data-asin]:not(.s-pagination-container)');
results.forEach(result => {
if (!result.querySelector('.s-pagination-container')) {
const ratingValue = parseFloat(result.dataset.ratingValue);
result.style.display = ratingValue >= minScore ? '' : 'none';
}
});
};
// Function to process search results
const processSearchResults = () => {
const searchResults = document.querySelectorAll('div[data-asin]:not(.s-pagination-container)');
searchResults.forEach(result => {
enhanceRatingDisplay(result);
});
filterResults(currentFilter);
};
// Throttle function to limit the rate of execution
const throttle = (func, delay) => {
let timeoutId = null;
return (...args) => {
if (timeoutId === null) {
func(...args);
timeoutId = setTimeout(() => {
timeoutId = null;
}, delay);
}
};
};
// Throttled version of processSearchResults
const throttledProcessSearchResults = throttle(processSearchResults, 500);
// Observe changes in the search results
const observeSearchResults = () => {
const searchResultsContainer = document.querySelector('div.s-main-slot.s-result-list.s-search-results.sg-row');
if (searchResultsContainer) {
const observer = new MutationObserver(throttledProcessSearchResults);
observer.observe(searchResultsContainer, {
childList: true,
subtree: true
});
}
};
// Initialize the script
const init = () => {
addFilterDropdown();
processSearchResults();
observeSearchResults();
};
// Run the script when the page has loaded
window.addEventListener('load', init);
})();