开发者

Javascript detects zero anchors

I'm using this code

var anchors = document.getElementsByTagName("a"); to detect anchors in HTML document. There are a lot of such tags. But alert(anchors.length) reports 0. It seems strange. Do you know what 开发者_高级运维could be the problem?

I'm using this code in firefox extension

var Highlighter = {

 ...
highlightLinks: function() {
 var anchors = document.getElementsByTagName("a");
 ...
}


window.addEventListener("DOMContentLoaded", function(e) { Highlighter.highlightLinks(); }, false);

thank you


Try to wait for the dom like so:

window.onload = function () {
   var anchor = document.getElementsByTagName('a');
   alert(anchor.length);
}


In a Firefox extension, if you add code to the browser via an overlay, then document is the browser document (browser.xul) not the web page's document. You can get the web page via content.document.


When you use functions like getElementsByTagName, they search through the DOM tree as it is at that moment and (in that case) return a NodeList. If you immediately check the length property, it'll tell you how many anchors there are right then. If this code is in the head section of your document, the odds are that that number will probably be zero.

If you put the code at the end of the document instead, when all the anchors are there, you should see a different result.

(Side note: NodeList instances are live, so even if you grab it at the top, if you check it later once all the anchors have been created, they should be in there. But best to avoid keeping references to NodeList instances for too long, as the fact they're live means the browser has to keep them up-to-date, which can become a performance issue.)

Here's an example of checking too early:

<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>Too early</title>
<style>
  body {
    font-family: sans-serif;
  }
  p {
    margin: 0px;
  }
</style>
<script>
  alert("Too early: " + document.getElementsByTagName('a').length);
</script>
</head>
<body>
  <a href="http://google.com">Google</a>
  <a href="http://jsbin.com">JSBin</a>
  <a href="http://stackoverflow.com">StackOverflow</a>
</body>
</html>

Live copy

And of checking when the document's fully loaded (the only change is where the script tag is):

<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>Too early</title>
<style>
  body {
    font-family: sans-serif;
  }
  p {
    margin: 0px;
  }
</style>
</head>
<body>
  <a href="http://google.com">Google</a>
  <a href="http://jsbin.com">JSBin</a>
  <a href="http://stackoverflow.com">StackOverflow</a>
<script>
  alert("Fully loaded: " + document.getElementsByTagName('a').length);
</script>
</body>
</html>

Live copy

You can put your script up higher and then wait to run it. One common way is to use window.onload, but be aware that that event happens very, very late in the page load sequence, after all images and other resources have completely downloaded. Sometimes that's what you want, but more frequently you want to do things a bit earlier. Most libraries provide a "ready" or "DOM loaded" event that happens earlier, but whether you want to use them will depend on what you're doing. Google's Closure library doesn't even provide one (and they don't think it should, they think it's better to put the script at the end; see the link below).

You asked in the comments about whether putting scripts in the head tag is best practice. That's a common myth. In fact, having your scripts in the head section slows down the apparent load-time of your page by making the browser deal with (download, interpret) your script before it's shown anything to the user. Even using window.onload, the browser still has to download and interpret your script, it just then waits until the load event fires to run it. See the links I added, best practice barring a good reason to have the script loaded early (and there are some) is to load it at the end of the body tag.

More:

  • YUI Best Practices for Speeding Up your Website (putting scripts at the bottom is on the list)
  • Google on when the DOM is ready

There are sometimes reasons you need at least some script up-top, the most critical being if you need to hook up some default handling of things that the user might click on after the page has been shown to them but before the browser has finished retrieving your script, interpreting it, and hooking up your event handlers! This is the "user clicked too early" problem. How you deal with that problem varies depending on your page and your inclination. Top ways to deal with it are:

  1. Make sure everything works okay without JavaScript, and then provide a nicer interface when/if your JavaScript loads. This is called "progressive enhancement" and the main reason for it isn't the user-clicked-too-early problem, it's to support users who don't have JavaScript enabled at all for various reasons. But the nice thing is that it also helps with this problem.
  2. Hook up a document-wide click handler using a tiny bit of inline script at the top of your document (rather than a separate file) that queues up (or just rejects) the clicks. My preference by far is to queue them up (including some kind of indicator for the user that you've done that), and then process them when the JavaScript has loaded. Users don't like it when a click just does nothing. Note that this can go nicely hand-in-hand with progressive enhancement, in case the user has JavaScript disabled.
  3. Have nothing significant the user can interact with until your JavaScript runs. Not friendly to people with JavaScript disabled, but there can be justifications. The line between this and progressive enhancment is blurry, basically it's progressive enhancement if the page still fundamentally works without JavaScript, and it's this nameless lesser option if it doesn't.
  4. Make sure the page loads so fast, and your script loads so fast, that it doesn't matter. But beware of slow connections and fast users. ;-)


Odds are you need to have your <script> tags as the last thing in your <body>, or you could have them run after everything has loaded: <body onload="runStuff()">, window.onload = function() { ... }, $(document).ready(function() { ... });, etc.


Odds are that you have the code in a <script> element that appears in the <head> and don't do anything to delay execution (such as putting it in a function that you call onload).

This means the script runs immediately, at which point the DOM is half-built, and nothing in the body exists until after the script has finished executing.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜