getElementById not working in Google Chrome extens

2020-08-04 10:47发布

问题:

In my Google Chrome extension content script I have the following:

jQuery(document).ready(function() {
    var player = document.getElementById('player');
    console.log(player);
    console.log(document);
});

I'm running it on any Hulu video, which has the following embed with id='player'

<embed id="player" type="application/x-shockwave-flash" src="/site-player/playerwrapper.swf?cb=e80c477cL" width="100%" height="428" style="z-index:10;" name="player" quality="high" allowscriptaccess="always" allowfullscreen="true" bgcolor="#000000" flashvars="bitrate=700000&amp;user_id=-1&amp;startLoadWrapperTime=1299572732904&amp;overrideBrand=&amp;referrer=http://www.hulu.com/watch/20338/saturday-night-live-steve-carell-monologue#continuous_play=on&amp;continuous_play_on=true&amp;sortBy=&amp;initMode=4&amp;modes=4&amp;content_id=7751491&amp;cb=2011-3-8-8&amp;v=3">

For example, the following link http://www.hulu.com/watch/20337/saturday-night-live-snl-digital-short-the-japanese-office

But when the script is run, console.log(player) returns null. However, console.log(document) returns the proper document object. Even if I try var player = Document.prototype.getElementById.apply(document, ['player']); I still get null.

The funny thing is, if I try it from the Chrome JavaScript Console, it works fine, I get the proper <embed> printed to console.

Any ideas why this isn't working in my content script?

UPDATE: As requested, here are the complete contents of my chrome extension folder:

manifest.json:

{
    "name": "gebidtest",
    "version": "1",
    "permissions": [
      "http://*/*",
      "https://*/*"
    ],
    "content_scripts": [{
      "matches": ["http://*/*"],
      "js": ["jquery-1.5.1.min.js","app.js"]
    }]
}

app.js:

jQuery(document).ready( function() {
    var player = document.getElementById('player');
    console.log(player);
    console.log(document);
});

jquery-1.5.1.min.js: I just downloaded it

I'm using Chrome version 10.0.648.127 on a Mac, but I also tried it on a PC with the same results

回答1:

Direct executing DOM related operation in JS is not correct. For example:

default.html

<!DOCTYPE HTML>
<html>
    <head>
    <script type="text/javascript" src="default.js"></script>
    </head>
    <body>
         <a id="Bar" href="#"></a>
    </body>
</html>

default.js

const bar = document.getElementById("Bar");
alert(bar.id);

At this time the DOM content may not be completely loaded yet, and that is why the "bar" may be "NULL".

The correct way to do this is:

default.js

document.addEventListener('DOMContentLoaded', function() {
  const bar = document.getElementById("Bar");
  alert(bar.id);
  });

That is: executing the DOM related operation when the DOMContentLoaded event happens.

"setTimeout" is not the right way because you cannot make sure the DOM content is completely loaded by setting some time delay!



回答2:

Turns out the problem was with timing. Even though it was inside a jQuery(document).ready(), the getElementById failed because the embed wasn't loaded yet. When I do a setTimeout of a few seconds, the getElementById works.



回答3:

Works fine for me in chrome 9.

Try this fiddle: http://jsfiddle.net/Ee7mq/

If the console doesn't show the player tag something is wrong with your browser. If it does, something is wrong with your code. To figure out what i'd need to see more of it.



回答4:

Use defer.

<script defer>...</script>