English 中文(简体)
d3.js and document.onReady
原标题:

I m just getting started with d3.js and there is one detail which is completely eluding me: how do I have my code execute only after the DOM is ready to receive input?

I could, of course, use something like jQuery but that seems excessive.

In every d3.js example I ve encountered there seems to be no special document.onReady() type of routine, yet all the examples work flawlessly. When testing code on my end, however, the code totally fails if executed before the DOM is ready (throwing my code into a window.onload confirms this).

What gives?

最佳回答

You ll notice in their examples that their javascript is below any of the html elements that is utilized so that part of the dom is loaded before it starts executing the javascript.

Simply putting your javascript at the bottom of the body is usually good enough.

问题回答

Sometimes you can t rely on the DIV / HTML element placing, for instance when you need to insert the element manipulated with D3 dynamically into the document. In such situations one solution is to monitor the document for DOMNodeInserted events and insert the D3 code in a callback (I believe this rules out IE versions prior to 9 though). Here s an example with jQuery:

$(document).bind( DOMNodeInserted , function(event)
{
    if (event.target.id == "viz")
    {
        var sampleSVG = d3.select("#viz")
                 .append("svg:svg")
                 .attr("width", 100)
                 .attr("height", 100);    

        sampleSVG.append("svg:circle")
                 .style("stroke", "gray")
                 .style("fill", "white")
                 .attr("r", 40)
                 .attr("cx", 50)
                 .attr("cy", 50)
                 .on("mouseover", function() {
                      d3.select(this).style("fill", "aliceblue");
                 })
                 .on("mouseout", function() {
                      d3.select(this).style("fill", "white");}
                 );
    }
});

The answer marked as correct didn t work for me, and is actually wrong. It s some kind of a hack and should not be considered as a correct answer. Same way you could just execute your code inside setTimeout(function() { .. }, 1000). It is even more reliable as you can set the delay :-/

In my case I needed to wait for all elements to be processed in order to know their actual dimensions. When they are not built, processed and done, the numbers were not correct.

UPDATED. Here is the correct answer:

Most probably you get your data for building DOM using some async call like d3.json() and that s why it takes some time. As async call is non-blocking, then your subsequent code gets invoked even before the async call finishes, causing problems, and this is the reason why you posted this question.

So you are trying to solve this by looking for something in D3 or anywhere else, that would tell you that D3 async call is finished and now you can do your next thing. Some people suggest making sync ajax call. This is awfully WRONG. Async calls are created to be async.

What you actually need to do is to change your paradigm. Just pass a callback to that async call and that s it! Something like that:

function thingsToDoWhenDOMisBuilt() {
    ...
}

function buildDOM(rootNode, error, thingsToDoWhenDOMisBuilt) {
    ...
    // everything is built, so we can do our post-build thing against DOM
    if (thingsToDoWhenDOMisBuilt)
        thingsToDoWhenDOMisBuilt()
}

d3.json(urlToData, buildDOM) {
    if (error)
        console.log("oops")
    buildDOM(rootNode, thingsToDoWhenDOMisBuilt)
}

Also, take a look at async.js

Binding events as suggested above is also a horrible idea. You should use .enter() .exit() instead. D3 is Data driven, if you need event-driven flow, then just use jQuery or vanilla JS!

You can put an onload event at body and put all d3js code in a function. For example:

<body onload="yourFunctionName()">

And in your javascript, insert this:

function yourFunctionName() {
    //Your d3js code goes here
}

Just paste the full d3 example code inside this function. The onload event will happen after the DOM is ready.





相关问题
selected text in iframe

How to get a selected text inside a iframe. I my page i m having a iframe which is editable true. So how can i get the selected text in that iframe.

How to fire event handlers on the link using javascript

I would like to click a link in my page using javascript. I would like to Fire event handlers on the link without navigating. How can this be done? This has to work both in firefox and Internet ...

How to Add script codes before the </body> tag ASP.NET

Heres the problem, In Masterpage, the google analytics code were pasted before the end of body tag. In ASPX page, I need to generate a script (google addItem tracker) using codebehind ClientScript ...

Clipboard access using Javascript - sans Flash?

Is there a reliable way to access the client machine s clipboard using Javascript? I continue to run into permissions issues when attempting to do this. How does Google Docs do this? Do they use ...

javascript debugging question

I have a large javascript which I didn t write but I need to use it and I m slowely going trough it trying to figure out what does it do and how, I m using alert to print out what it does but now I ...

Parsing date like twitter

I ve made a little forum and I want parse the date on newest posts like twitter, you know "posted 40 minutes ago ","posted 1 hour ago"... What s the best way ? Thanx.

热门标签