2011-08-24 8 views
30

मैं बस d3.js के साथ शुरू कर रहा हूं और एक विवरण है जो पूरी तरह से मुझे छेड़छाड़ कर रहा है: डीओएम इनपुट प्राप्त करने के लिए तैयार होने के बाद ही मेरा कोड निष्पादित कैसे हो सकता है?d3.js और document.onReady

मैं निश्चित रूप से jQuery की तरह कुछ उपयोग कर सकता हूं लेकिन यह अत्यधिक लगता है।

every d3.js example में मुझे लगता है कि कोई विशेष document.onReady() दिनचर्या का प्रकार नहीं लगता है, फिर भी सभी उदाहरण निर्दोष रूप से काम करते हैं। मेरे अंत में कोड का परीक्षण करते समय, हालांकि, डीओएम तैयार होने से पहले निष्पादित होने पर कोड पूरी तरह विफल हो जाता है (window.onload में मेरा कोड फेंकना) इसकी पुष्टि करता है।

क्या देता है?

उत्तर

46

आप उनके उदाहरणों में नोटिस करेंगे कि उनका जावास्क्रिप्ट किसी भी HTML तत्व से नीचे है जिसका उपयोग किया जाता है ताकि जावा के भाग को जावास्क्रिप्ट को निष्पादित करने से पहले लोड किया जा सके।

बस शरीर के निचले हिस्से में अपना जावास्क्रिप्ट डालना आम तौर पर पर्याप्त है।

+7

शानदार, धन्यवाद। जाहिर है, मैं बहुत दूर तक jQuery भूमि में रहा हूँ। – Roshambo

+2

यह बुरा अभ्यास है, और क्यों jQuery और उसके प्रतिस्पर्धियों में इतने सारे पहले से ही भिन्न हैं। – ijw

+0

ilw सही है। कुछ मोबाइल वेब दृश्यों पर, यह कभी-कभी ऐप खोलते समय गलत स्क्रीन चौड़ाई आकार की रिपोर्ट करेगा। तैयार होने पर दस्तावेज़ की प्रतीक्षा करना इससे बचा जाता है। – phreakhead

5

कभी-कभी आप डीआईवी/एचटीएमएल तत्व प्लेसमेंट पर भरोसा नहीं कर सकते हैं, उदाहरण के लिए जब आपको दस्तावेज़ में डायनामिक रूप से डी 3 के साथ छेड़छाड़ करने वाले तत्व को सम्मिलित करने की आवश्यकता होती है। ऐसी परिस्थितियों में एक समाधान DOMNodeInserted ईवेंट के लिए दस्तावेज़ की निगरानी करना है और कॉलबैक में डी 3 कोड डालना है (मुझे विश्वास है कि यह 9 से पहले आईई संस्करणों को बाहर करता है)। यहां 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");} 
       ); 
    } 
}); 
+1

अच्छा जवाब। जब डीओएम में गतिशील रूप से एसवीजी लोड हो रहा है, तो क्या एसवीजी नोड सम्मिलन कार्यक्रम को ट्रिगर करने का कोई तरीका है? यदि ऐसा है, तो यह एसवीजी वस्तुओं की पुन: प्रतिपादन को कम करेगा जब असंबद्ध डीओएम तत्व जैसे divs, p's, आदि बनाए जाते हैं। –

+0

ग्रेट तकनीक, थोड़ा ज्ञात! – VividD

+1

दुर्भाग्य से 'DOMNodeInserted' जैसे उत्परिवर्तन कार्यक्रम अब बहिष्कृत किए गए हैं - https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Mutation_events। काश मैं आपको बता सकता हूं कि सबसे अच्छा विकल्प क्या है लेकिन मैं नहीं कर सकता (यही वह है जो मुझे यह प्रश्न मिलने पर खोजने की कोशिश कर रहा था!) ​​ – Willl

2

आप शरीर पर एक अधिभार ईवेंट डाल सकते हैं और सभी d3js कोड को फ़ंक्शन में डाल सकते हैं। उदाहरण के लिए:

<body onload="yourFunctionName()"> 

और अपने जावास्क्रिप्ट में, इस सम्मिलित करें:

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

बस इस समारोह के अंदर पूर्ण d3 उदाहरण कोड पेस्ट करें। डीओएम तैयार होने के बाद अधिभार कार्यक्रम होगा।

+0

परीक्षण उद्देश्यों के लिए यह ठीक है लेकिन ध्यान दें कि 'body.onload' को सेट करना आम तौर पर माना जाता है खराब स्क्रिप्ट के रूप में खराब रूप इसे ओवरराइड कर सकते हैं। 'addEventListener' बेहतर है, लेकिन' document.onReady' की तुलना में अभी भी थोड़ा धीमा है। – Roshambo

3

सही के रूप में चिह्नित उत्तर मेरे लिए काम नहीं करता है, और वास्तव में गलत है। यह किसी प्रकार का हैक है और इसे सही उत्तर के रूप में नहीं माना जाना चाहिए। वैसे ही आप सेटटाइमआउट (फ़ंक्शन() {..}, 1000 के अंदर अपना कोड निष्पादित कर सकते हैं)। यह और भी भरोसेमंद है क्योंकि आप देरी निर्धारित कर सकते हैं: -/

मेरे मामले में मुझे अपने वास्तविक आयामों को जानने के लिए सभी तत्वों को संसाधित करने की प्रतीक्षा करनी होगी। जब वे निर्मित, संसाधित और नहीं किए जाते हैं, तो संख्याएं सही नहीं होतीं।

अद्यतन। यहां सही उत्तर दिया गया है:

शायद आपको कुछ एसिंक कॉल जैसे d3.json() का उपयोग करके डोम बनाने के लिए अपना डेटा मिलता है और यही कारण है कि इसमें कुछ समय लगता है। चूंकि एसिंक कॉल गैर-अवरुद्ध है, तो आपका अगला कोड एसिंक कॉल समाप्त होने से पहले भी लागू हो जाता है, जिससे समस्याएं आती हैं, और यही कारण है कि आपने यह प्रश्न पोस्ट किया है।

तो आप डी 3 या कहीं और किसी चीज़ की तलाश करके इसे हल करने का प्रयास कर रहे हैं, जो आपको बताएगा कि डी 3 एसिंक कॉल समाप्त हो गया है और अब आप अपनी अगली चीज़ कर सकते हैं। कुछ लोग सिंक AJAX कॉल बनाने का सुझाव देते हैं। यह बहुत गलत है। Async कॉल async होने के लिए बनाए जाते हैं।

आपको वास्तव में क्या करने की आवश्यकता है अपने प्रतिमान को बदलने के लिए है। बस उस async कॉल पर कॉलबैक पास करें और यही वह है!ऐसा ही कुछ:

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) 
} 

इसके अलावा, जैसा कि ऊपर का सुझाव दिया async.js

बाध्यकारी घटनाओं पर एक नज़र डालें भी एक भयानक विचार है। आपको इसके बजाय .enter() .exit() का उपयोग करना चाहिए। डी 3 डेटा संचालित है, अगर आपको ईवेंट संचालित प्रवाह की आवश्यकता है, तो बस jQuery या वेनिला जेएस का उपयोग करें!