The project I am working on is an extension that displays the 5 most popular colors on a specific webpage.
The issue that I am having is that when I click the "Get Palette" button, I want it to regrab all of the colors of the current page we're on. However, it just remains as what it was previously. For example, if I "Get Palette" on an initial page, it works but when I switch tabs or open a new page and press the button again, it only displays the colors from the previous output.
popup.html
<!DOCTYPE html>
<html>
<head>
<title>Color Palette</title>
</head>
<body>
<h1>Color Palette</h1>
<button id="get-palette">Get Palette</button>
<main id="output"></main>
<script src="popup.js"></script>
</body>
</html>
popup.js
document.addEventListener("DOMContentLoaded", function () {
const btn = document.getElementById('get-palette')
btn.addEventListener('click', () => {
populateColors();
})
});
function populateColors() {
chrome.runtime.sendMessage({ method: "getColors" }, function (response) {
// From response, get top colors and display
const colorCounts = {};
response.forEach((color) => {
colorCounts[color] = (colorCounts[color] || 0) + 1;
});
const sortedColors = Object.keys(colorCounts).sort(
(a, b) => colorCounts[b] - colorCounts[a]
);
// Create blocks of the most frequent colors
const colorsContainer = document.getElementById("output");
for (let i = 0; i < 5 && i < sortedColors.length; i++) {
const colorBlock = document.createElement("div");
colorBlock.style.backgroundColor = sortedColors[i];
colorBlock.style.width = "50px";
colorBlock.style.height = "50px";
colorBlock.style.margin = "5px";
colorBlock.style.border = "1px solid black";
colorsContainer.appendChild(colorBlock);
}
});
}
background.js
let colors = [];
chrome.runtime.onMessage.addListener(function (message, sender, sendResponse) {
// When we get a message from the content script
if (message.method == 'setColors') {
colors = message.colors;
console.log('Colors set:', colors);
}
// When we get a message from the popup
else if (message.method == 'getColors') {
sendResponse(colors);
console.log('Colors sent:', colors);
}
});
content_script.js
// Function to convert RGB color to HEX format
function rgbToHex(rgb) {
const rgbValues = rgb.match(/\d+/g);
const r = parseInt(rgbValues[0]);
const g = parseInt(rgbValues[1]);
const b = parseInt(rgbValues[2]);
return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
}
function renderColors() {
// Regular expression to match colors in CSS
const colorRegex = /#([0-9a-f]{3}){1,2}\b|\b((rgb|hsl)a?\([\d\s%,.]+\))/gi;
// Array to store the color values
const colors = [];
// Get all the link elements on the page
const links = document.getElementsByTagName('link');
// Loop through the links and process the CSS files
for (let i = 0; i < links.length; i++) {
const link = links[i];
// Only process link elements with rel="stylesheet"
if (link.rel === 'stylesheet') {
// Use the Fetch API to fetch the CSS file
fetch(link.href)
.then(response => response.text())
.then(cssText => {
// Parse the CSS file and process it
const colorValues = cssText.match(colorRegex);
if (colorValues) {
colorValues.forEach(colorValue => {
// Check if the color is in RGB format
if (colorValue.startsWith("rgb")) {
const hexValue = rgbToHex(colorValue);
colors.push(hexValue);
} else {
colors.push(colorValue);
}
});
}
//console.log(`FROM CONTENT SCRIPT: ${colors}`)
chrome.runtime.sendMessage({ 'method': 'setColors', 'colors': colors });
})
.catch(error => {
console.error('Error fetching CSS file:', error);
});
}
}
}
renderColors();