50

I'm injecting my content script from the background page when the user clicks the browser action button, like so:

chrome.browserAction.onClicked.addListener(function (tab) {
    chrome.tabs.executeScript(null, { file: "content.js" });
});

So how can I access jQuery from inside my content.js? I don't see a way to inject that simultaneously.

Cœur
  • 37,241
  • 25
  • 195
  • 267
mpen
  • 272,448
  • 266
  • 850
  • 1,236

7 Answers7

92

What about:

chrome.tabs.executeScript(null, { file: "jquery.js" }, function() {
    chrome.tabs.executeScript(null, { file: "content.js" });
});

You can download "jquery.js" from here: http://jquery.com/download/

Daniel Möller
  • 84,878
  • 18
  • 192
  • 214
serg
  • 109,619
  • 77
  • 317
  • 330
16

How about adding this to your manifest file

"content_scripts": [
    {
        "js": [
                "jquery.js", 
                "contentscript.js"
            ]
    }
],
Apoorv Saini
  • 169
  • 1
  • 3
  • 7
    Wouldn't this make Chrome to parse jQuery in every tab even when it's not needed? – Manuel Faux Jun 27 '13 at 12:05
  • @ManuelFaux yes. You would need to add a "matches" property that controls the domains that it would execute jQuery on. – frosty Nov 18 '13 at 06:11
  • Where do I find this "jquery.js"? – Daniel Möller Jun 25 '15 at 02:47
  • 1
    @Daniel you have to download it (https://code.jquery.com/), name it "jquery.js" and leave it in the same directory if you want to use his exact code – neaumusic Jun 25 '15 at 03:00
  • This answer is not the solution to the question. The asker needs a programmatic injection (https://developer.chrome.com/extensions/content_scripts#pi), which is triggered by a click on the browser action button, not on every single page that matches the pattern in the manifest file. – Ethan Yang Jun 24 '16 at 11:32
  • I needed to use jq on all pattern matched pages so i fixed it like this http://prntscr.com/evhfj2 – Mr Megamind Apr 12 '17 at 10:25
4

UPDATE:

Execute second script after the first one would be more accurate in terms of script order, result is an array of results of execution of the script in list of tabs.

chrome.tabs.executeScript(null, {file:'js/jquery-2.1.1.min.js'}, function(result){
    chrome.tabs.executeScript(null, {file:'js/myscript.js'});
});

OLD:

Injecting Jquery followed by your script will gives ability to access Jquery within your script.

chrome.tabs.executeScript(null, {file:'js/jquery-2.1.1.min.js'});
chrome.tabs.executeScript(null, {file:'js/myscript.js'});

You have more control over how the script should be injected as described in here. Specially allFrames property is important if you wish to inject script to all the frames within the document. Ignoring it will only injected into the top frame. Since it is not mentioned in other answers guess it helps you. Scripts can be injected always by adding it to manifest as described here.

Ruwanka De Silva
  • 3,555
  • 6
  • 35
  • 51
  • 1
    Yes, but you should use the callback of the first one to inject the second one. Otherwise, they could finish executing in the wrong order, which would be difficult to debug. – Teepeemm Feb 21 '17 at 16:35
  • @Teepeemm yeah, that would be the correct solution. I'll update the answer. – Ruwanka De Silva Feb 22 '17 at 05:52
3

Since I've much scripts with many dependencies , I use a function concatenateInjection that takes three parameters:

//id: the tab id to pass to executeScript
//ar: an array containing scripts to load ( index order corresponds to execution order)
//scrpt (opzional): the last script to execute (if not provided, than the last script is the last insert in previous array)

function concatenateInjections(id, ar, scrpt){
  var i = ar.length;
  var idx = 0;

  function inject(idx){
    idx++;
    if(idx <= i){
      var f = ar[idx-1];
      chrome.tabs.executeScript(id, { file: f }, function() {
          inject(idx);
      });
    }else{
      if(typeof scrpt === 'undefined') return;
      chrome.tabs.executeScript(id, { file: scrpt });
    }
  }
  inject(idx);
}

and usage example:

// id is tab id

// sources: first execute jquery, than default.js and anime.js in the end
var def = [
  "lib/jquery-1.11.3.min.js", 
  "lib/default.js", 
  "injection/anime.js"
];

// run concatenate injections
concatenateInjections(id, def);

Think that's could be useful.

UPDATE

Version with concat and closure (more aesthetic):

function concatenateInjections(id, ar, scrpt){

  if( typeof scrpt !== 'undefined' ) ar = ar.concat([scrpt]);

  var i = ar.length;
  var idx = 0 ;

  (function (){
    var that = arguments.callee;
    idx++;
    if(idx <= i){
      var f = ar[idx-1];
      chrome.tabs.executeScript(id, { file: f }, function(){ that(idx);} );
    }
  })();

}
Sim Sca
  • 413
  • 7
  • 18
  • 1
    Because if there's several scripts with same dependencies then i can define a single array "ar" for this depencied and change only the scrpt parameter for each call of "concatenateInject". I'm very lazy ;-) – Sim Sca Sep 18 '15 at 23:25
  • https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/concat – Xan Sep 18 '15 at 23:26
  • I've updated using a `ar.concat(...)` as suggested by @Xan. Anyway I prefer to maintain `scrpt` parameter, so I dont' have to write `myarray.concat('str')` in `concatenateInjections()`. Remember: I'm very lazy :-) – Sim Sca Sep 19 '15 at 10:13
  • It's fine; it's usable code. What I meant is to use it like `concatenateInjections(id, ar.concat(script))` for the use case you present and keep it as 2 arguments. – Xan Sep 19 '15 at 10:21
1

anytime you want to dynamically insert jQuery, i recommend this script

i personally have a Chrome Custom Search "$" which replaces $ with

javascript:
var jq = document.createElement('script');
jq.onload = function(){};
jq.src = "https://code.jquery.com/jquery-2.1.1.min.js";
document.querySelector('head').appendChild(jq);

javascript: is just the way to run javascript from the url bar

i use this on my about:blank page when i'm trying to mock up some css situation quickly

neaumusic
  • 10,027
  • 9
  • 55
  • 83
1

Update for manifest v3

chrome.scripting.executeScript({
target: { tabId: tab.id },
files : [ "jquery.js" ]
}).then(() => chrome.scripting.executeScript({
    target: { tabId: tab.id },
    function: your_function,
}));
Vladyslav Panchenko
  • 1,517
  • 1
  • 19
  • 23
1

Official documented method of loading external scripts for manifest v3:

chrome.scripting.executeScript({
  target: {tabId: tab.id},
  files: ['jquery-min.js', 'content-script.js']
});
Nelson
  • 2,040
  • 17
  • 23