user2057449
user2057449

Reputation: 161

Return value from chrome.scripting.executeScript or chrome.tabs.executeScript

In popup.js i'm using the following code to display all the text within a certain div id of the current tab - and display in alert. I'm wondering how would it be possible to save the div text to a variable within popup.js?

Nothing is returned:

var getText = chrome.tabs.executeScript({
  code: "document.getElementById('DIVid').innerText"
});

Upvotes: 16

Views: 17904

Answers (3)

Sudarshan
Sudarshan

Reputation: 18534

ManifestV2:

var getText = Array();
chrome.tabs.executeScript(tabs[tab].id, {
    "code": "document.getElementById(\"_Your_ID_Here_\").innerText.split(' ')"
}, function (result) {
    for (i = 0; i < result[0].length; i++)
    getText [i] = result[0][i];
    console.log(getText);
});

You have update variable inside callback, because of async nature of chrome.api

ManifestV3:

async function example(tabId) {
  if (tabId == null)
    [{id: tabId}] = await chrome.tabs.query({active: true, currentWindow: true});
  const [{result}] = await chrome.scripting.executeScript({
    target: {tabId},
    args: ['foo', 'bar'],
    func: (arg1, arg2) => [
      document.querySelector(arg1)?.textContent,
      document.querySelector(arg2)?.textContent,
    ],
  });
  console.log(result);
  return result;
}

Upvotes: 17

Fdebijl
Fdebijl

Reputation: 1021

If you're using chrome.scripting.executeScript, I've noticed that func can't return an object directly. I had to serialize the response with JSON.parse, otherwise the script would never return the value.

Broken:

chrome.scripting.executeScript({
    target: { tabId: request.tabId },
    world: 'MAIN',
    func: () => {
      const sessionService = window.namespace.__container__.lookup('service:session');
      const user = sessionService.get('user');
      const course = sessionService.get('course');
      const activity = sessionService.get('activity');
      return { user, course, activity };
    }
  }, (bundleInfo) => {
    console.log(bundleInfo) // This never gets logged
  });

Working:

chrome.scripting.executeScript({
    target: { tabId: request.tabId },
    world: 'MAIN',
    func: () => {
      const sessionService = window.namespace.__container__.lookup('service:session');
      const user = sessionService.get('user');
      const course = sessionService.get('course');
      const activity = sessionService.get('activity');
      return JSON.stringify({ user, course, activity }); // Serialize the object before returning
    }
  }, (bundleInfo) => {
    console.log(bundleInfo);
  });

Upvotes: 2

vdegenne
vdegenne

Reputation: 13270

Here's a modern and concise way to achieve that :

Defining a reusable promise-like wrapper function

const executeScript = (tabId, func) => new Promise(resolve => {
  chrome.scripting.executeScript({ target: { tabId }, func }, resolve)
}

Usage :

const [{result: selection}] = await executeScript(tabId,
  () => document.getSelection().toString()
)
console.log(selection) // log page selection

Upvotes: 2

Related Questions