Chrome extension "$ is not defined" error

This happens when the script that calls for jQuery loads prior to jQuery.js loading. In the example given by the question submitter, the background loads prior to the content script, and the content script loads jQuery itself after the background script calls for jQuery. This example can be fixed by having the background script load jQuery itself, like so:

 "background": {
    "scripts": ["jquery-2.0.2.js", "jquery.Jcrop.js", "background.js"],
    "persistent": false
  },  

Keep in mind also that js files listed in the manifest are loaded in the order they appear. For example, let's say that you have a file, "script.js", that contains:

console.log($('#elementID'));

If you write your manifest like this (WRONG), you'll get the error "$ is not defined":

"content_scripts": [
    {
        "js": [ 
            "script.js",
            "jquery.js" ]
    } 
]

Changing the manifest to this (RIGHT) will fix the error:

"content_scripts": [
    {
        "js": [ 
            "jquery.js",
            "script.js" ]
    } 
]

Note that "jquery.js" now precedes "script.js" and is therefore loaded first.

The problem can be seem intermittent because both scripts are loaded almost at the same time. If you change the script so that the call to jQuery is below some other javascript commands, the time it takes for those other commands to execute may be just enough time for jQuery.js to finish loading. So for example, if you wrote the manifest the wrong way above, you could also technically fix the error by changing the script.js file like so:

var t = setTimeout(function(){
     console.log($('#elementID'));
}, 1000);

The 1 second delay gives jQuery.js enough time to load, however, this is obviously not the ideal solution!


This is happening because you are calling your script before the jQuery file.
The right one is this:

{
  "name": "X",
  "description": "Snip this page",
  "version": "2.0",
  "permissions": [
    "activeTab"
  ],
  "background": {
    "scripts": ["background.js"],
    "persistent": false
  },
  "content_scripts":[{
    "matches" : ["<all_urls>"],
    "js": ["jquery-2.0.2.js","yourscript.js"],
    "css": ["jquery.Jcrop.min.css"]
  }],
  "browser_action": {
    "default_title": "Snip this page"
  },
  "manifest_version": 2
}