I need to hide or show an column with my extension. This one I want to hide/show
I have this code:
manifest.json
{
"manifest_version": 2,
"name": "Chat GPT Column Hider",
"description": "This extension allows you to hide the left column in Chat GPT.",
"version": "1.0",
"background": {
"scripts": ["background.js"]
},
"browser_action": {
"default_popup": "popup.html"
},
"permissions": [
"https://chat.openai.com/"
]
}
background.js
function hideColumn() {
// Get the left column element and hide it
var column = document.querySelector('div.dark.hidden.bg-gray-900.md\\:fixed.md\\:inset-y-0.md\\:flex.md\\:w-[260px].md\\:flex-col');
column.style.display = 'none';
}
function showColumn() {
// Get the left column element and show it
var column = document.querySelector('div.dark.hidden.bg-gray-900.md\\:fixed.md\\:inset-y-0.md\\:flex.md\\:w-[260px].md\\:flex-col');
column.style.display = 'block';
}
popup.html
<button id="hide-button">Hide Column</button>
<button id="show-button">Show Column</button>
<script src="popup.js"></script>
popup.js
// Get the hide and show button elements
var hideButton = document.querySelector('#hide-button');
var showButton = document.querySelector('#show-button');
// Add event listeners to the buttons
hideButton.addEventListener('click', function() {
// When the hide button is clicked, call the hideColumn function
chrome.tabs.executeScript({
code: 'hideColumn();'
});
});
showButton.addEventListener('click', function() {
// When the show button is clicked, call the showColumn function
chrome.tabs.executeScript({
code: 'showColumn();'
});
});
And we get this UI:
But if I press buttons I'm getting an error: Uncaught ReferenceError: hideColumn is not defined
I rewrote your extension.
manifest.json
{
"name": "Chat GPT Column Hider",
"version": "1.0",
"manifest_version": 3,
"permissions": [
"scripting"
],
"host_permissions": [
"https://chat.openai.com/"
],
"action": {
"default_popup": "popup.html"
}
}
popup.html
<html>
<body>
<button id="hide-button">Hide Column</button>
<button id="show-button">Show Column</button>
<script src="popup.js"></script>
</body>
</html>
popup.js
// Get the hide and show button elements
var hideButton = document.querySelector('#hide-button');
var showButton = document.querySelector('#show-button');
function hideColumn() {
// Get the left column element and hide it
var column = document.getElementsByClassName('dark hidden bg-gray-900 md:fixed md:inset-y-0 md:flex md:w-[260px] md:flex-col');
column[0].style.display = 'none';
}
function showColumn() {
// Get the left column element and show it
var column = document.getElementsByClassName('dark hidden bg-gray-900 md:fixed md:inset-y-0 md:flex md:w-[260px] md:flex-col');
column[0].style.display = 'block';
}
// Add event listeners to the buttons
hideButton.addEventListener('click', function () {
// When the hide button is clicked, call the hideColumn function
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
chrome.scripting.executeScript({
target: { tabId: tabs[0].id },
func: hideColumn
});
});
});
showButton.addEventListener('click', function () {
// When the show button is clicked, call the showColumn function
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
chrome.scripting.executeScript({
target: { tabId: tabs[0].id },
func: showColumn
});
});
});
Related
The Manifest V3 JavaScript Chrome extension only has one button. When the button is clicked the browser should go to multiple pages and perform an action on each page before going to the next one.
What's currently happening, is the browser jumping to the last page and not performing any action.
How to fix my code, so that the extension visits each page one by one (in the same tab), then waits on the page until a button is detected, clicks the button, checks if the button is clicked, and then goes to the next page?
Manifest.json:
{
"name": "Twitch Follower",
"version": "0.1",
"manifest_version": 3,
"description": "Automatically follows Twitch users.",
"action": {
"default_popup": "popup.html"
},
"permissions": [
"activeTab",
"tabs",
"scripting"
],
"background": {
"service_worker": "background.js"
},
"host_permissions": [
"https://www.twitch.tv/*"
]
}
popup.html:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/water.css#2/out/water.css">
</head>
<body>
<button id="start">Start</button>
<script src="popup.js"></script>
</body>
</html>
popup.js:
start.addEventListener("click", async () => {
chrome.runtime.sendMessage({ start: true });
});
background.js:
const list = ["https://www.twitch.tv/hello1", "https://www.twitch.tv/hello2"];
function clickFollow() {
document.querySelector("button[data-a-target='follow-button']").click();
}
function handleFollowButton(followButton) {
setTimeout(clickFollow, 1000);
}
// Check for a button
async function checkButton() {
const findButton = new Promise((resolve, reject) => {
const observerConfig = { attributes: true, attributeOldValue: true };
const observer = new MutationObserver((mutations) => {
const followButton = document.querySelector("button[data-a-target='follow-button']");
const unfollowButton = document.querySelector("button[data-a-target='unfollow-button']");
// If follow button is found, click it
if (followButton) {
handleFollowButton(followButton);
}
// If unfollow button is found, end observing and continue
if (unfollowButton) {
unfollowButtonFound = True;
observer.disconnect();
resolve;
}
});
window.setTimeout(() => {
if (!unfollowButtonFound) {
reject;
}
}, 5000);
observer.observe(document, {
childList: true,
subtree: true,
});
});
await findButton;
return true;
}
// When the start button is clicked
chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
if (request.start === true) {
// Loop through every link
for (const link of list) {
console.log(link);
// Open the link and inject the script
chrome.tabs.update({ url: link }, (tab) => {
chrome.scripting.executeScript(
{
target: { tabId: tab.id },
func: checkButton,
},
(result) => {
console.log(results);
}
);
});
}
}
});
I am facing two errors on Chrome extension that I am building:
Error 1:
Uncaught TypeError: Cannot set properties of null (setting 'onclick')
Context
_generated_background_page.html
Stack Trace
popup.js:3 (anonymous function)
Error 2:
Unchecked runtime.lastError: Could not establish connection. Receiving end does not exist.
Context
_generated_background_page.html
Stack Trace
_generated_background_page.html:0 (anonymous function)
I have already checked the questions on this site that address these two errors and I tried the solutions provided in them, but I am still facing the two errors.
My original code:-
popup.js (tried changing from onclick to onClicked for error 1, tried putting this code in window.onload for error 2)
let populateBtn = document.getElementById('populateBtn');
let textArea = document.getElementById('productList');
populateBtn.onclick = function(element) {
let color = element.target.value;
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
if(!textArea.value)
{
chrome.tabs.executeScript(
tabs[0].id,
{code: 'alert("Please, populate the order list!");'});
return;
}
chrome.tabs.sendMessage(tabs[0].id, {data: textArea.value.replace(/\t/g,'').split("\n")}, function(response) {
});
});
};
background.html (tried putting <script> after </body> tag for error 1)
<body>
<p>Gina's Bakery Bulk Order</p>
<textarea id="productList"></textarea>
<button id="populateBtn">Create Order</button>
<script src="popup.js"></script>
</body>
app.js (tried chrome.runtime.connect for error 2)
chrome.runtime.onInstalled.addListener(function() {
});
inject.js (tried chrome.runtime.onConnect.addListener for error 2)
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
let failed = [];
request.data.forEach(element => { // itterate over all products
if(element.includes('-')){
let data = element.split('-');
let quantity = data[0].toLowerCase().replace("gb", "").trim();
let ID = data[1].trim();
let elementName = 'pid_' + ID.replace(".", "_");
if(document.getElementsByName(elementName).length > 0)
document.getElementsByName(elementName)[0].value = quantity;
else
failed.push("<td>GB-"+ ID +"</td><td>" + quantity + "</td>");
}
});
if(failed.length > 0){
//alert("Order unsuccessful! One or more products are not ordered: " + failed.join(", "));
let modal = document.createElement("div");
modal.setAttribute("id", "failedOrderModal");
modal.setAttribute("style", "position:fixed;width:250px;left:50%;top:100px;background-color:#fff;border-radius:10px;padding:10px;z-index:10000;color:#000;border: 1px solid red;text-align:center;");
let head = document.createElement("h2");
head.innerText = "Order unsuccessful! One or more products were not found!";
modal.appendChild(head);
let table = document.createElement("table");
let tbody = document.createElement("tbody");
table.appendChild(tbody);
let tr = document.createElement("tr");
tr.innerHTML = "<td>ITEM</td><td>QTY</td>";
tbody.appendChild(tr);
failed.forEach(failedItem => {
tr = document.createElement("tr");
tr.innerHTML = failedItem;
tbody.appendChild(tr);
});
modal.appendChild(table);
let closeBtn = document.createElement("button");
closeBtn.setAttribute("type", "button");
closeBtn.innerText = "Close";
closeBtn.onclick = function(){
document.getElementById("failedOrderModal").remove();
}
modal.appendChild(closeBtn);
document.body.appendChild(modal);
}
else
{
alert("All products were successfuly populated!");
}
sendResponse({result: "ok"})
return true;
});
manifest.json
{
"name": "Gina's Bakery Order",
"version": "1.0",
"description": "Helps automate orders from ginas-bakery.com.au",
"permissions": ["activeTab", "declarativeContent", "storage"],
"background": {
"scripts": ["app.js", "popup.js"],
"persistent": false
},
"icons": {
"16": "images/ginas-bakery_16.png",
"32": "images/ginas-bakery_32.png",
"48": "images/ginas-bakery_48.png",
"128": "images/ginas-bakery_128.png"
},
"browser_action": {
"default_popup": "background.html"
},
"content_scripts": [
{
"matches": ["*://www.ginas-bakery.com.au/order/"],
"js": ["inject.js"]
}
],
"manifest_version": 2
}
None of the above mentioned solutions worked.
The background script page is an invisible hidden page, so running visible scripts like app.js or popup.js there is meaningless. Remove background section from manifest.json and rename your background.html to popup.html both on the disk and in manifest.json.
manifest.json:
{
"name": "Gina's Bakery Order",
"version": "1.0",
"permissions": ["activeTab", "declarativeContent", "storage"],
"browser_action": {"default_popup": "popup.html"},
"manifest_version": 2
}
Content scripts run only when the page loads, so if you just reloaded or installed/updated the extension without reloading the tab, the content scripts won't run there.
Although you can inject them explicitly, it's much better to switch to programmatic injection on demand (use executeScript instead of content_scripts) because you can do it without requiring any host permissions when installing the extension.
popup.js:
const textArea = document.getElementById('productList');
const btn = document.getElementById('populateBtn');
btn.onclick = () => {
const data = textArea.value.replace(/\t/g, '').split('\n');
chrome.tabs.query({active: true, currentWindow: true}, ([tab]) => {
chrome.tabs.sendMessage(tab.id, {data}, () => {
if (chrome.runtime.lastError) {
chrome.tabs.executeScript({file: 'inject.js'}, () => {
chrome.tabs.sendMessage(tab.id, {data});
});
}
});
});
};
Since you're not using the response in sendMessage, don't send it in the first place, i.e. remove sendResponse({result: "ok"}); return true; from inject.js.
Sorry, I messed that up. I did not update the manifest from the last post and I forgot the content.js, that is how the Change button was sending the value and the page was getting the new style attribute value from the one entered in the text field and then to the content.js, existing content.js file added below.
I have a styles.css that changes the web page and is loaded from the popup but want to change a variable in the styles.css from the data entered at the popup.
I've added a content.js file and I can now pass a value from the Popup and it adds a new style attribute to the page but it's not updating the --ptwidth in the styles.css file. I think I need to have it in the styles.css to give the correct location and add the !important option.
I tried to ask this question before an it was closed\linked to one about webpage DOMs and don't have the reputation to post a comment and not sure I should ask my questions there if I could:
How to access the webpage DOM rather than the extension page DOM?
The styles.css injection works using the Wider button and the --ptwidth var is passed the value given (310) in the styles.CSS, at the very least I'd like to be able to enter a new value in the textbox and then use the existing Wider button to load the updated styles.css but it would be nice to have it auto update and maybe even use the slider.
The change button moves the new value entered in the text field to the content.js file and it then adds the new style attribute but it's not working. The insertCSS on the Wider button works but the info it adds is different.
Content.js adds the Style attribute section and the insertCSS adds the :root section that works.
Added by Content.js No Work:
Added by insertCSS Works and adds these two:
Columns before:
Columns after:
Rule before using the working Wider button with insertCSS:
Rules after the insertCSS injections of styles.css:
Popup:
manifest:
{
"manifest_version": 3,
"name": "Hellper",
"description": "Extension",
"version": "0.1",
"icons": { "16": "logo_16_T.png",
"48": "logo_48_T.png",
"128": "logo_128_T.png"
},
"action": {
"default_icon": "logo_16_T.png",
"default_popup":"popup.html"
},
"permissions": ["scripting", "tabs", "activeTab", "content.js"],
"host_permissions": ["<all_urls>"],
"content_scripts": [{
"js": ["jquery-2.2.0.min.js", "popup.js"],
"matches": ["https://www.google.com/*",
"https://en.wikipedia.org/*",
"https://stackoverflow.com/*"]
}]
}
popup.html:
<!doctype html>
<html>
<head>
<title>Popup</title>
</head>
<body>
<input id="button1" type=button value=clickme>
<button class="format">Wider</button>
<button class="reset">Reset</button>
<script src="jquery-2.2.0.min.js"></script>
<script src="popup.js"></script>
<!--
<h2>Background Color</h2>
<input type="color" id="color-changer" />
<h2>Rotate Page</h2>
<input type="range" min="0" max="360" step="1" value="0" id="rotate" />
-->
<h1>New Width</h1>
<p>
<input type="text" id="newWidth" value="120"/>
<input type="submit" id="btnChange" value="Change"/>
</p>
<div class="form-group">
<lable for="slider">Project/Task Width</lable>
<input type="range" min="0" max="999" step="1" value="160" id="slider" />
</div>
</body>
</html>
styles.css:
:root {
--ptwidth: 310px
}
.quixote .qx-grid .editor_grid tbody tr td input, .quixote .qx-grid .editor_grid tbody tr td .input-group {
/*max-width: 450px !important;
min-width: 450px !important;*/
max-width: var(--ptwidth) !important;
min-width: var(--ptwidth) !important;
popup.js:
$(document).ready(function() {
$('.reset').click(function() {
chrome.tabs.query({currentWindow: true, active: true}, function (tabs){
var activeTab = tabs[0];
chrome.scripting.removeCSS({
target: { tabId: activeTab.id },
files: ["styles.css"]
});
});
})
$('.format').click(function() {
chrome.tabs.query({currentWindow: true, active: true}, function (tabs){
var activeTab = tabs[0];
chrome.scripting.insertCSS({
target: { tabId: activeTab.id, allFrames: true },
files: ["styles.css"]
});
/*chrome.tabs.sendMessage(activeTab.id, {"buttonclicked": "wider"});*/
});
})
})
$(function(){
var width = $('#newWidth').val();
$('#newWidth').on("change paste keyup", function(){
width = $(this).val();
});
$('#btnChange').click(function(){
chrome.tabs.query({currentWindow: true, active: true}, function (tabs){
chrome.tabs.sendMessage(tabs[0].id, {todo: "changeWidth", sliderWidth: width})
});
});
});
content.js
let root = document.documentElement;
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
if( request.todo == "changeWidth"){
var updateWidth = request.sliderWidth;
root.style.setProperty('--ptwidth', updateWidth + "px");
// start();
}
});
It seems like there is still some work to do on this extension. I will try to provide only a solution to what was asked an leave the rest for you to work on.
Issues I will try to address
You shouldn't be reusing popup.js as a content script. You should create a separate file instead of having one script be both injected into the webpage and also being used in the popup window.
You are also sending messages from the popup window without anything listening for the messages. This also would be solved by creating a separate content script that listens for these messages.
Partial solution
I edited the manifest.json and popup.js as well as created a new file content.js.
New manifest.json
changed "popup.js" to "content.js"
{
"manifest_version": 3,
"name": "Hellper",
"description": "Extension",
"version": "0.1",
"icons": { "16": "logo_16_T.png",
"48": "logo_48_T.png",
"128": "logo_128_T.png"
},
"action": {
"default_icon": "logo_16_T.png",
"default_popup":"popup.html"
},
"permissions": ["scripting", "tabs", "activeTab"],
"host_permissions": ["<all_urls>"],
"content_scripts": [{
"js": ["jquery-2.2.0.min.js", "content.js"],
"matches": ["https://www.google.com/*",
"https://en.wikipedia.org/*",
"https://stackoverflow.com/*"]
}]
}
New popup.js
only edited the last function block
added a listener for the slider changes
coupled the values in the text box and slider, so when one changes, the other changes as well
changed the message parameter from "sliderWidth" to "newWidth" to make it more general
moved retrieval of the width value into the listeners so the new changed value can be sent along
I also suggest removing the change button entirely because the other listeners make it unnecessary
// Unchanged
$(document).ready(function () {
$(".reset").click(function () {
chrome.tabs.query({ currentWindow: true, active: true }, function (tabs) {
var activeTab = tabs[0];
chrome.scripting.removeCSS({
target: { tabId: activeTab.id },
files: ["styles.css"],
});
});
});
$(".format").click(function () {
chrome.tabs.query({ currentWindow: true, active: true }, function (tabs) {
var activeTab = tabs[0];
chrome.scripting.insertCSS({
target: { tabId: activeTab.id, allFrames: true },
files: ["styles.css"],
});
/*chrome.tabs.sendMessage(activeTab.id, {"buttonclicked": "wider"});*/
});
});
});
// Changed
$(function () {
// text input listener
$("#newWidth").on("change paste keyup", function () {
const width = $(this).val();
// update slider
$("#slider").val(width);
chrome.tabs.query({ currentWindow: true, active: true }, function (tabs) {
chrome.tabs.sendMessage(tabs[0].id, { todo: "changeWidth", newWidth: width });
});
});
// listener for change button press
// button might not be needed anymore because of the text input listener above
$("#btnChange").click(function () {
const width = $("#newWidth").val();
// update slider
$("#slider").val(width);
chrome.tabs.query({ currentWindow: true, active: true }, function (tabs) {
chrome.tabs.sendMessage(tabs[0].id, { todo: "changeWidth", newWidth: width });
});
});
// listener for slider changes
$("#slider").on("input", function () {
const width = $("#slider").val();
// update text box
$("#newWidth").val(width);
chrome.tabs.query({ currentWindow: true, active: true }, function (tabs) {
chrome.tabs.sendMessage(tabs[0].id, { todo: "changeWidth", newWidth: width });
});
});
});
New content.js
created this script to listen for messages sent from the popup and make the changes to the CSS based on the message
$(document).ready(function () {
// listen for messages sent to the tab the content script is running in
chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
// check to see if the message received is something that needs to be acted on
if (request.todo === "changeWidth") {
// pull the width data from the message
const newWidth = request.newWidth;
// set the style attribute of :root to override the styles.css value for --ptwidth
document.documentElement.style.setProperty("--ptwidth", newWidth + "px");
}
// send a response to avoid errors in popup.js
sendResponse("Width updated");
});
});
Hopefully that get you on the right track for finishing your extension!
Don't forget to check out the developer documentation for Chrome extensions. There are several useful posts for teaching how to accomplish the various parts of an extension.
[1] Message Passing: https://developer.chrome.com/docs/extensions/mv3/messaging/
[2] Content Scripts: https://developer.chrome.com/docs/extensions/mv3/content_scripts/
I got this working by using the chrome.scripting.insertCSS to replace the --ptwidth value after the styles.css has been injected. So far everything works with just the popup.js and no need for the content.js file.
I use this to load the styles.css with it's default value.
chrome.tabs.query({currentWindow: true, active: true}, function (tabs){
var activeTab = tabs[0];
chrome.scripting.insertCSS({
target: { tabId: activeTab.id, allFrames: true },
files: ["styles.css"]
});
});
Then this when I get a new value from the textbox or slider.
chrome.tabs.query({currentWindow: true, active: true}, function (tabs){
var activeTab = tabs[0];
//alert(readsavewidth);
$("#slider").val(readsavewidth);
$("#newWidth").val(readsavewidth);
chrome.scripting.insertCSS({
target: { tabId: activeTab.id, allFrames: true },
css: `:root { --ptwidth: ${readsavewidth + "px"} }`
});
});
});
I also used the chrome.storage.local to set and get the last value used.
$(function () {
// text input listener
$("#newWidth").on("change paste keyup", function () {
width = $(this).val();
//Save it to the localStorage variable which will always remember what you store in it
chrome.storage.local.set({'savewidth': width});
// update slider
$("#slider").val(width);
chrome.tabs.query({currentWindow: true, active: true}, function (tabs){
var activeTab = tabs[0];
chrome.scripting.insertCSS({
target: { tabId: activeTab.id, allFrames: true },
css: `:root { --ptwidth: ${width + "px"} }`
});
});
});
// listener for slider changes
$("#slider").on("input", function () {
width = $("#slider").val();
// update text box
$("#newWidth").val(width);
chrome.tabs.query({currentWindow: true, active: true}, function (tabs){
var activeTab = tabs[0];
chrome.scripting.insertCSS({
target: { tabId: activeTab.id, allFrames: true },
css: `:root { --ptwidth: ${width + "px"} }`
});
});
//Pull text from user inputbox
var data = width;
//Save it to the localStorage variable which will always remember what you store in it
chrome.storage.local.set({'savewidth': data});
});
});
Then I get the value when the popup opens and it then overights the --ptwidth value using the chrome.scripting.insertCSS funtion.
chrome.storage.local.get('savewidth', function (result) {
readsavewidth = result.savewidth;
chrome.tabs.query({currentWindow: true, active: true}, function (tabs){
var activeTab = tabs[0];
//alert(readsavewidth);
$("#slider").val(readsavewidth);
$("#newWidth").val(readsavewidth);
chrome.scripting.insertCSS({
target: { tabId: activeTab.id, allFrames: true },
css: `:root { --ptwidth: ${readsavewidth + "px"} }`
});
});
});
I would like to implement a hotkey that triggers a function in my content script.
The content script (main.js) is executed on page laod from my popup.js file.
i have added the command into my manifest.json and when I add the onCommand listener to my popup.js I can console log that it gets triggered when I press my hotkey (Ctrl+Shift+K)
However I can not get it passed to my content script.
manifest.json
{
"manifest_version": 2,
"name": "Ccghjj",
"description": "hdjdjdjsjs",
"version": "1.0",
"browser_action": {
"default_icon": "icon.png",
"default_popup": "popup.html"
},
"permissions": ["tabs", "*storage", "activeTab"],
"content_scripts": [
{
"matches": ["*://"],
"css": ["style.css"],
"js": ["jquery.js", "main.js"]
}
],
"content_security_policy": "script-src 'self' https://ajax.googleapis.com; object-src 'self'",
"web_accessible_resources": ["toolbar.html", "style.css"],
"commands": {
"show_deals": {
"suggested_key": {
"default": "Ctrl+Shift+K"
},
"description": "Highlight Deals"
}
}
}
popup.js
function registerButtonAction(tabId, button, action) {
// clicking button will send a message to
// content script in the same tab as the popup
button.addEventListener('click', () => chrome.tabs.sendMessage(tabId, { [action]: true }));
}
function setupButtons(tabId) {
// add click actions to each 3 buttons
registerButtonAction(tabId, document.getElementById('start-btn'), 'startSearch');
registerButtonAction(tabId, document.getElementById('deals-btn'), 'startDeals');
registerButtonAction(tabId, document.getElementById('stop-btn'), 'stopSearch');
}
function injectStartSearchScript() {
chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
// Injects JavaScript code into a page
// chrome.tabs.executeScript(tabs[0].id, { file: 'main.js' });
// add click handlers for buttons
setupButtons(tabs[0].id);
});
}
injectStartSearchScript();
// hotkey command listener
chrome.commands.onCommand.addListener((show_deals) => {
console.log(`Command "${show_deals}" triggered`);
// how can I get to main.js to call deals()
});
main.js (content script)
async function deals() {
// should be fired when I press my hotkey Ctrl+Shift+K
Use messages like below
popup.js
chrome.commands.onCommand.addListener((show_deals) => {
console.log(`Command "${show_deals}" triggered`);
chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
chrome.tabs.sendMessage(tab.id, { msg: "deals"})
})
});
and in your content script
if (!window.firstTimeExecuted) {
window.firstTimeExecuted = true;
chrome.runtime.onMessage.addListener((data, sender, sendResponse) => {
if (data.msg == 'deals') {
deals()
}
});
}
I try to get the input value in my main.js (content script) but I struggle to finialize it somehow. I managed to save the value with the windows.onload approach as you can see below in my popup.js. But I can't get it over to the content script.
I want to use the value as a variable "userInput" in my content script.
popup.js:
function registerButtonAction(tabId, button, action) {
// clicking button will send a message to
// content script in the same tab as the popup
button.addEventListener('click', () => chrome.tabs.sendMessage(tabId, { [action]: true }));
}
function setupButtons(tabId) {
// add click actions to each 3 buttons
registerButtonAction(tabId, document.getElementById('start-btn'), 'startSearch');
registerButtonAction(tabId, document.getElementById('deals-btn'), 'startDeals');
registerButtonAction(tabId, document.getElementById('stop-btn'), 'stopSearch');
}
function injectStartSearchScript() {
chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
// Injects JavaScript code into a page
// chrome.tabs.executeScript(tabs[0].id, { file: 'main.js' });
// add click handlers for buttons
setupButtons(tabs[0].id);
});
}
injectStartSearchScript();
window.onload = function () {
document.getElementById('save-btn').onclick = function () {
let valueInput = document.getElementById('deal-ipt').value;
chrome.storage.sync.set({ 'maxBidDeal': valueInput }, function () {
alert('Saved!');
});
};
};
manifest.json:
{
"manifest_version": 2,
"name": "test app",
"description": "test desc",
"version": "1.0",
"browser_action": {
"default_icon": "icon.png",
"default_popup": "popup.html"
},
"permissions": ["tabs", "<all_urls>", "storage"],
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["main.js"]
}
],
"content_security_policy": "script-src 'self' https://ajax.googleapis.com; object-src 'self'"
}
main.js:
// highlight deals
async function deals() {
// let userInputBidPrice = prompt('Set max Bid Price to show deals:');
chrome.storage.sync.get('MaxBidDeal', function (data) {
let userinput = data.MaxBigDeal;
deals(userinput);
});
let cardCurrentBidValuesString = document.querySelectorAll('.auction > .auctionValue:nth-child(2) > .currency-coins.value');
let cardStartBidValueString = document.querySelectorAll('.auction > .auctionStartPrice.auctionValue > .currency-coins.value');
let cardBg = document.querySelectorAll('.rowContent.has-tap-callback');
for (let i = 0; i < cardCurrentBidValuesString.length; i++) {
cardsCurrentBidPrice = cardCurrentBidValuesString[i].textContent.toString().split(',').join('');
cardsStartBidPrice = cardStartBidValueString[i].textContent.toString().split(',').join('');
if (cardsCurrentBidPrice === '---') {
cardsCurrentBidPrice = 0;
}
if (cardsStartBidPrice === '---') {
cardsStartBidPrice = 0;
}
parsedCardsCurrentBidPrice = parseInt(cardsCurrentBidPrice);
parsedCardsStartBidPrice = parseInt(cardsStartBidPrice);
if (parsedCardsCurrentBidPrice < parseInt(userinput) && parsedCardsStartBidPrice < parseInt(userinput)) {
cardBg[i].style['background-color'] = '#0311c3';
}
}
}
chrome.runtime.onMessage.addListener((message) => {
// choose action based on received message:
if (message.startSearch) {
startSearch();
} else if (message.startDeals) {
deals();
}
});
// sanity check: content has loaded in the tab
console.log('content loaded');
So I am sure that I have to use chrome.storage.get somehow but I cant figure it out exactly.
Your code is calling deals recursively forever without actually passing the value because you didn't declare a parameter and then you're trying to use userinput beyond the variable's scope.
You can promisify chrome.storage and use await like this:
async function deals() {
// Note that chrome.storage is already promisified in ManifestV3 since Chrome 95
let { MaxBidDeal } = await new Promise(resolve =>
chrome.storage.sync.get('MaxBidDeal', resolve));
// use MaxBidDeal right here
console.log('MaxBidDeal', MaxBidDeal);
}