Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

send message from background to contentscript/web page? #54

Open
jryebread opened this issue Aug 22, 2022 · 3 comments
Open

send message from background to contentscript/web page? #54

jryebread opened this issue Aug 22, 2022 · 3 comments

Comments

@jryebread
Copy link

Hi there, I was wondering:
why this starter doesn't have a content script to be able to read the DOM of the web page

I am trying to create a context menu (which works fine) in backgroundPage.ts:

browser.runtime.onInstalled.addListener(function() {
    chrome.contextMenus.create({
        title: "Mage - Explain Code",
        contexts: ["selection"],
        id: "Mage - Explain Code"
    });
});
browser.contextMenus.onClicked.addListener(function (info, tab) {
    if (info.menuItemId === "Mage - Explain Code") {
        let code = info.selectionText
        console.log(code)
        browser.runtime.sendMessage({type: "mageQuery"}); //send msg to tab
    }
})

tf2BPOG

when the context menu button is pressed it should send a message to the current tab and open a tool tip on the highlighted text in the web page.

Which file should I handle this message in? Can this be done inside the popup folder component.tsx, or do I need to create a content script file somehow?

I have spent all day struggling with how to do this so I would very much appreciate help! thank you!

@bershanskiy
Copy link

This template has scripting permission, so the easiest way to do this is:

in src/backgroundPage.ts add

browser.runtime.onInstalled.addListener(function() {
    chrome.contextMenus.create({
        title: "Mage - Explain Code",
        contexts: ["selection"],
        id: "Mage - Explain Code"
    });
});

// This function is serialized, sent to content context, deserialized, and then executed,
// so all external variables will be lost. Use arguments instead.
function handler(code) {
    console.log('Hello world!');
    console.log(code);
}

browser.contextMenus.onClicked.addListener(function (info, tab) {
    if (info.menuItemId === "Mage - Explain Code") {
        let code = info.selectionText;
        // Use args to pass arguments to handler
        browser.scripting.executeScript({target: {tabId: tab.id}, func: handler, args: [code]});
    }
})

@jryebread
Copy link
Author

jryebread commented Aug 29, 2022

@bershanskiy thanks I am trying to import tippy.js to insert this javascript into the page (on the highlighted text) however I'm running into issues with using the installed module in the injected script.
in backgroundPage.ts

import tippy from 'tippy.js'

function executeTippy() {
    const selection = window.getSelection();
    if (selection === null) {
        throw new Error("No selection of text available")
        return;
    }
         // get the selection then
    const range = selection.getRangeAt(0);        // the range at first selection group
    const rect = range.getBoundingClientRect(); // and convert this to useful data
    // const scrollPos = window.scrollY;
    // const containerTop = scrollPos + rect.top - 50 + "px";
    // const containerLeft = rect.left + rect.width / 2 - 50 + "px";

    const divTextSelect = document.createElement('div');   // make box

    divTextSelect.setAttribute("id",
        "textSelectionTooltipContainer"
    );

    // divTextSelect.style.transform =
    // "translate3d(" + containerLeft + "," + containerTop + "," + "0px)";

    
     // With the above scripts loaded, you can call `tippy()` with a CSS
      // selector and a `content` prop:
      tippy('#textSelectionTooltipContainer', {
        content: 'My tooltip!',
        showOnCreate: true,
      });
    divTextSelect.style.border = '2px solid black';      // with outline
    divTextSelect.style.position = 'absolute';              // fixed positioning = easy mode
    divTextSelect.style.top = rect.top + 'px';       // set coordinates
    divTextSelect.style.left = rect.left + 'px';
    divTextSelect.style.height = rect.height + 'px'; // and size
    divTextSelect.style.width = rect.width + 'px';
    document.body.appendChild(divTextSelect);
    console.log("added textSelect")
}

The error I get is that tippy is undefined:
image

@bershanskiy
Copy link

bershanskiy commented Aug 29, 2022

@jryebread This error is expected, since executeTippy() is stringified by

browser.scripting.executeScript({target: {tabId: tab.id}, func: executeTippy});

It is almost like calling .toString() on any other function, so all external variables are lost (including external imports). I recommend one of these methods:

  • use browser.scripting.executeScript with a files parameter instead of func. Just copy executeTippy() into a separate file and pass its path in files
  • use dynamic import within executeTippy(). I do not recommend this method, unless you do not need to support old browsers are able to test extension in all relevant browser versions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants