2

UPDATE:

The problem is caused by including an old version of jQuery(1.4.2). After I use 1.8.2 instead, the problem is just gone. But I still don't know why.

I recently made a Chrome extension. Thanks to the post chrome extension insert content script on browser action I realized that I have to include a js file like:

<script src="popup.js"></script>

But later I figure out it seems you cannot include more than one file:

<html>
  <head>
    <script src="jquery.js"></script> <!-- NOT LOADED -->
    <script src="popup.js"></script> <!-- LOADED -->
  </head>
  <body>
  </body>
</html>

What's worse for me is that I cannot access the DOM of the popup HTML in the JS file. Like:

popup.html

<html>
  <head>
    <script src="popup.js"></script>
  </head>
  <body>
    <a id="intro" href="#"  target="_blank">Intro</a>
  </body>
</html>

popup.js

/*
  ... jQuery Codes here ... 
  jquery.js cannot be included via src="jquery.js" 
  but by copy and paste its source code here it works
*/
$("#intro").click(function(){
  alert("clicked"); // Not fireing at all
});

I am wondering what I can do to fix this. Thanks very much!

Community
  • 1
  • 1
AGamePlayer
  • 7,404
  • 19
  • 62
  • 119

2 Answers2

1

Here is a basic example of what you could use to get it working. My best guess is that it only appeared that jQuery wasn't loading because of how your popup.js is set up (it is trying to attach the click functionality before the element has loaded). I'm no JS expert, so I'm sure others will have better ideas of how to wait for the DOM to load, but this works as a basic test (NOTE: this uses a local version of the latest version of jQuery (1.8.2 currently), as the new content policies in manifest 2 do not allow in-line scripts):

Manifest.json

{
  "name": "Test Extension",
  "version": "1.0",
  "manifest_version": 2,
  "description": "Testing",

  "browser_action": {
    "default_icon":   "my_icon.png",
    "default_title":  "My Text Extension",
    "default_popup":  "popup.html"
  },

  "permissions": [
    "tabs", "http://*/", "https://*/"
  ]
}

Popup.html

<html>
  <head>
    <script type="text/javascript" src="jquery.min.js"></script>
    <script type="text/javascript" src="popup.js"></script>
  </head>
  <body>
    <a id="intro" href="#"  target="_blank">Intro</a>
  </body>
</html>

Popup.js

/*
   Here we wait for the body of the popup to load before
   attaching our functionality
*/
window.onload = function() {
  $("#intro").click(function(){
    alert("clicked"); // Should fire now
  });
};
RocketDonkey
  • 36,383
  • 7
  • 80
  • 84
  • Thanks for the answer but I am using Manifest 2. Manifest 1 is going to be dead in a few months according to Google's official doc. In Manifest 1 it seems everything's working fine. – AGamePlayer Oct 22 '12 at 03:25
  • @AwQiruiGuo Ah, my bad (living in the past :) ). Updating now - the only change I made was specifying `manifest_version: 2` and changing the keyword for the `popup` to `default_popup`. Does it work for you in that case? – RocketDonkey Oct 22 '12 at 03:39
  • Thanks. But jQuery is not loaded and it prompts a "Refused to execute inline script because it violates the following Content Security Policy directive: "script-src 'self' chrome-extension-resource:"." – AGamePlayer Oct 22 '12 at 03:43
  • It seems the problem is caused by including the jquery.js - This is a js file downloaded from jquery official site without any modification. – AGamePlayer Oct 22 '12 at 03:47
  • @AwQiruiGuo Are you loading a local copy of jQuery? – RocketDonkey Oct 22 '12 at 03:47
  • Yes, I am. And when I removed all the content in jquery.js it works. It seems the content blocks me! But I don't know why. – AGamePlayer Oct 22 '12 at 03:54
  • Oh, I updated to the latest jquery and it works! My previous version was 1.42 and the latest version is 1.8.2! That's really weird – AGamePlayer Oct 22 '12 at 03:56
  • @AwQiruiGuo Hmm, that is definitely weird, and now I really want to figure it out :) Which version are you using? I was using this one http://code.jquery.com/jquery-1.8.2.min.js – RocketDonkey Oct 22 '12 at 03:56
  • @AwQiruiGuo Awesome! I'll update the answer to reflect that (I was about to drive myself crazy thinking what it could be if that weren't the answer :) ). – RocketDonkey Oct 22 '12 at 03:57
  • Thanks very much for your kind effort on helping me! I think it must be some stuff in jQuery 1.4.2 source code blocking the load process from popup.html – AGamePlayer Oct 22 '12 at 05:44
0

The reason this is happening, is because the page is being loaded in order, and the scripts are firing before the DOM is loaded. This means that the scripts are called before the DOM even exists, so it cannot see the DOM at all; it's loading after the script.

Using events to wait for the DOM is one method to get around this, but you can also add the scripts at the end or after the body tag to be loaded last, so that the DOM is loaded first. There are of course many people who will argue this is bad practice, as well as vice versa. The reason being that you may have scripts load while the DOM loads, or because there are many large scripts that cause a lag in the loading, and these are all valid points when discussing jQuery manipulated websites.

The opposing practice can be beneficial when working with Chrome Extensions. One reason is to always give some representational responsiveness, even with the most intensive extensions, as well as not having to worry about waiting for the DOM in the code. Really it depends on what you need, but it's always beneficial to know all of your options. You can see both practices used in the Sample Chrome Extensions.

With jQuery you may want to use the Ready method instead, as onload waits until everything on the page is loaded (images, video, links, scripts, etc). Unlike onload, the ready method is called when the DOM itself is done loading, regardless of the page actually being done loading. You can do this with:

$(document).ready(function() { 
  // jQuery code to execute after
});

You can also wait for the DOM in JavaScript using the DOMContentLoaded event:

document.addEventListener('DOMContentLoaded', function() {
  // JavaScript code here
});
DBrown
  • 5,111
  • 2
  • 23
  • 24