1

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: enter image description here

Added by insertCSS Works and adds these two: enter image description hereenter image description here

Columns before: enter image description here

Columns after: enter image description here

Rule before using the working Wider button with insertCSS: enter image description here

Rules after the insertCSS injections of styles.css: insertCSS

Popup: enter image description here

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();
      }
    });
Tanquen
  • 33
  • 8

2 Answers2

1

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

  1. 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.

  2. 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/

cactus12
  • 56
  • 1
  • 1
  • 9
  • Sorry I messed up and the question was unclear. I'd copied the closed post and did not update the manifest or add the contect.js I was using. Post updated. The bigger issue or the issue was that the styles.CSS worked using the insertCSS function but the content script did not. It's adds the new style attribute to the page but it does nothing. I'm thinking this is because the setProperty in the content.js is missing the extra info in the injected styles.css. Sorry again for messing that up. :( – Tanquen Jan 31 '22 at 16:51
  • I just finished adding the change you suggested and the coupled values was something I wanted and the "moved retrieval of the width value into the listeners" I'm guessing gets me the auto update and then the Changed button is no longer needed but I may keep if I think the auto update is too much. Thanks so much for that and I don't even have the rep to upvote it. Hopefully you have an idea for getting the content.js setProperty to work the same as the styles.css insertCSS injection. – Tanquen Jan 31 '22 at 17:27
  • @Tanquen it might help if you can describe what this extension is meant to accomplish. Do you want to have to click a button to have the CSS inserted into the page or do you want the CSS applied every time? – cactus12 Jan 31 '22 at 22:56
  • Not sure why the `setProperty` method wouldn't work. If you could create and share a link to a GitHub repository with all the code and a description of the extension in the `README`, it would be a lot easier to test. One solution might be to use [`removeCSS()`](https://developer.chrome.com/docs/extensions/reference/scripting/#method-removeCSS) in the popup to remove the stylesheet and then send a new updated one. But this depends on your answer to my previous comment. There might be better ways to do this. – cactus12 Jan 31 '22 at 23:05
  • The columns are on a secure page & hide the description so you can't see what data you are changing. I found the location in the page and the values that can widen the columns. They are in the OP styles.css section above and there is a pic at the top of the OP showing what the two rules look like. The `insertCSS` did not work until the `!important` option was added in the styles.css and the popup.js `insertCSS` function had the `allFrames: true` option added to the target. I got it working with the button & `insertCSS`, I just wanted to change the width in the styles.css from the popup. – Tanquen Feb 01 '22 at 01:11
  • At first I thought the `setProperty` in the content.js was going to change the var in the styles.css and then I could use the same Wider button to inject the working styles.css but it looks to just be adding the property into the live page. So it seems I need to trigger the insertCSS function after changing the `--ptwidth` value in the styles.css or figure out how to include the same `!important` and `allFrames: true` option using the `setProperty` method. And maybe the location `.quixote .qx-grid .editor_grid tbody tr td input, .quixote .qx-grid .editor_grid tbody tr td .input-group`? – Tanquen Feb 01 '22 at 01:17
  • I checked around in various pages of Google, Wikipedia, and StackOverflow with devTools and couldn't find anything with the class name `.quixote`, so I am still no closer to understanding what this extension is meant to do. Unfortunately, I can't help if I am unable to test the functions for myself. – cactus12 Feb 01 '22 at 01:45
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/241596/discussion-between-cactus12-and-tanquen). – cactus12 Feb 01 '22 at 01:45
0

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"} }`
  });
  });
});
Tanquen
  • 33
  • 8