2012-05-08 4 views
9

में एक विंडो से दूसरे में फ़ंक्शन पास नहीं कर सकता है मेरे पास दो विंडो हैं, एक दूसरे से खोला गया है, इसलिए, मेरे पास "बच्चे" विंडो में opener संपत्ति है।आईई

अभिभावक विंडो में वैश्विक क्षेत्र में कुछ फ़ंक्शन है, जिसे फ़ंक्शन के साथ पहली तर्क के रूप में जाना जाना चाहिए (इसे कॉलबैक के रूप में उपयोग किया जाएगा)।

दोनों पेज एक ही डोमेन से खोल रहे हैं, इसलिए, मैं किसी भी एक ही मूल नीति प्रतिबंध (मैं बहुत उम्मीद है) नहीं है ...

एक बच्चे विंडो में मैं इस

if(window.opener) { 
    window.opener.myFunction(function() { ... }); 
} 
की तरह कोड है

सबकुछ ठीक काम करता है, जब तक कि मैं इसे आईई में चलाने की कोशिश नहीं करता। इस ब्राउज़र में myFunction द्वारा प्राप्त एक तर्क, हमेशा Object टाइप करें (typeof के साथ चेक किया गया)।

window.myFunction = function(cb) { 
    alert('Callback type is ' + (typeof cb)); 
    if(typeof cb == 'function') 
     cb(); 
    else 
     alert('Not a function!'); 
} 

लाइव डेमो: http://elifantiev.ru/ie-opener-issue/first.html

सवाल

है:

  1. यह एक standarts अनुरूप व्यवहार है myFunction संहिता कुछ इस तरह है?
  2. इस मुद्दे के लिए कुछ कामकाज है?
+0

कृपया आईई के संस्करण (नों) निर्दिष्ट करें जिसमें आपको यह समस्या आती है। –

+0

आईई 7 + (आईई 7,8,9) – Olegas

उत्तर

6

भले ही टाइपऑफ रिटर्न "ऑब्जेक्ट" फ़ंक्शन अभी भी अपेक्षित कार्य करता है। कॉलिंग cb() फ़ंक्शन निष्पादित करेगा।

typeof का उपयोग कर यदि पैरामीटर कोई समारोह कॉल संपत्ति जो सभी कार्यों की अपेक्षा की जाती के लिए परीक्षण कर रहा है यह निर्धारित करने के लिए एक वैकल्पिक:

if (cb && cb.call) { cb(); } 

आप कुछ के साथ से गुजर रहे हैं यह एक समारोह को उम्मीद है कि अगर इस तरह लपेटा जा सकता है:

function newCb() { 
    return cb.apply(object, arguments); 
} 

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

+0

'if (cb && cb.call) 'के लिए +1 ...' टाइपोफ़ ' –

+0

से दूर रहने के लिए सबसे अच्छा है, लेकिन लपेटना अच्छा नहीं है, क्योंकि' मैं ' फ्रेमवर्क के किसी भी फ़ंक्शन में रैपिंग जोड़ने की आवश्यकता है, जो एक फ़ंक्शन के रूप में फ़ंक्शन प्राप्त कर सकता है ... – Olegas

+0

मुझे उन्हें पसंद नहीं है लेकिन आप फ़ंक्शन को प्रोटोटाइप कर सकते हैं ताकि आपको अपने पूरे ढांचे को फिर से लिखने की चिंता न हो, केवल आपके क्लाइंट साइड कॉल मैं एक मिनट में अपना जवाब अपडेट करूंगा। – Jeff

2

ऐसा लगता है कि यह डिज़ाइन द्वारा है।

http://www.kilometer0.com/blog/code/internet-explorer-ie-cross-window-javascript-object-typeof-bug/

https://bugzilla.mozilla.org/show_bug.cgi?id=475038

प्रत्येक विंडो अलग प्रोटोटाइप चेन होती है, इसलिए कार्यों की उम्मीद के रूप में पारित नहीं किया जा सकता।पुष्टि करने के लिए कुछ इस तरह कर रही प्रयास करें:

var popup = window.open('second.html'); 

    window.myFunction = function(cb) { 
      alert(cb instanceof Function);  //false 
      alert(cb instanceof popup.Function); //true 
    } 

तो यहाँ कैसे मैं उचित समारोह सत्यापन करना होगा अगर वहाँ माता-पिता की ओर (मैं प्रोटोटाइप नफरत लेकिन इस बार मैं तुम्हें अटक कर रहे हैं लगता है) पर के बारे में चिंता करने के लिए बहुत से आयोजन कर रहे थे है :

जनक विंडो:

<html> 
<script type="text/javascript"> 
    /* give all our functions the validation check at once */ 
    Function.prototype.remote = function(cb) { 
     if(cb instanceof popup.Function) { 
      this(cb); 
     } else { 
      alert('Not a function!'); 
     } 
    }; 

    var popup, 
    myFunction = function(cb) { 
     cb(); 
    }, 
    test = function(cb) { 
     cb(); 
    } 

</script> 
<body> 
    <a href="#" onclick="popup = window.open('second.html'); return false;">Open window</a> 
</body> 
</html> 

बाल विंडो:

<html> 
<body> 
    <script type="text/javascript"> 
     var Parent = window.opener; 
     if(Parent) { 
      Parent.myFunction.remote(function(){ 
       alert('callback!'); 
      }); 

      Parent.test.remote(function() { 
       alert('callback again'); 
      }); 
     } 
    </script> 
    This is a second page! 
</body> 
</html> 

और यहाँ एक काम उदाहरण है: http://dl.dropbox.com/u/169857/first.html

-1

चाइल्ड विंडो खोलने के बाद, आप अपने window संदर्भ में माता-पिता के द्वारा बनाई गई एक समारोह रजिस्टर कर सकते हैं। आप नीचे दिए गए कोड jsFiddle में चल देख सकते हैं:

<html> 
<head> 
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script> 
<script> 

// will be called by the child window 
function MyExportedCallback(x) { 
    $("#my-callback-result").text("this callback was run with '" + x + "'."); 
} 

// will open a child window and create content for testing 
function MyLinkHandler() { 
    var wnd = window.open("about:blank"); 

    // IMPORTANT: this is where the parent defined function is "registered" 
    // into child window scope 
    wnd["myExternal"] = MyExportedCallback; 

    // auxiliary code to generate some HTML to test the external function 
    var put = function(x) { wnd.document.write(x); }; 
    put("<html><body>"); 
    put("<a href='#' onclick='window.myExternal(123);'>"); 
    put("click me to run external function"); 
    put("</a>"); 
    put("</body></html>"); 
} 

// attach events 
$.ready(function() { 
    $("#my-link").click(MyLinkHandler); 
}); 

</script> 
<body> 
<p><a id="my-link" href="#">Open window</a></p> 
<p id="my-callback-result">waitting callback...</p> 
</body> 
</html> 
+0

मुख्य समस्या यह है कि पैरेंट विंडो में बनाए गए फ़ंक्शन को कैसे पास किया जाए, माता-पिता के विंडो फ़ंक्शन के लिए तर्क के रूप में। – Olegas

+0

@ ओलेगस, आपकी मूल पोस्ट कहती है: "अभिभावक विंडो में वैश्विक क्षेत्र में कुछ फ़ंक्शन है, जिसे पहले तर्क के रूप में फ़ंक्शन के साथ बुलाया जाना चाहिए (इसे कॉलबैक के रूप में उपयोग किया जाएगा)।" तो मुझे उम्मीद थी कि समस्या बच्चे की खिड़की से पैरेंट विंडो में परिभाषित एक समारोह को बुलाएगी। व्यावहारिक मामलों के लिए, जावास्क्रिप्ट में एक फ़ंक्शन पास करना किसी अन्य तर्क को पार करने जैसा है, और इसलिए मैंने इसका पता नहीं लगाया। लेकिन कभी नहीं, ऐसा लगता है कि आप पहले से ही अपनी समस्या हल कर चुके हैं, आपको कोई और मदद नहीं है। –

+0

कॉल करने के लिए - कोई समस्या नहीं है। एक समारोह पारित करने के लिए - समस्या है। आईई में यह विंडो सीमा के माध्यम से पारित होने पर 'ऑब्जेक्ट' को 'टाइपोफ़' में बदल रहा है। – Olegas

2

भले ही आपने यह अब के लिए काम करने के लिए प्राप्त कर सकते हैं, मैं दो ब्राउज़र विंडो के लिए क्षमता सीधे एक दूसरे पर कार्यों को लागू करने के आसपास होने के लिए पर भरोसा नहीं होता बहुत लंबे समय तक। परिदृश्य से क्रॉस-डोमेन समस्याओं को हटाने के बावजूद, बहुत सारी सुरक्षा चिंताएं हैं।

ऐसा करने का एकमात्र भविष्य-सबूत तरीका है, और यह सुनिश्चित करता है कि यह सभी ब्राउज़रों में काम करता है, cross-document messaging APIs का उपयोग करना है जो IE8 और ऊपर सहित सभी आधुनिक ब्राउज़रों में समर्थित है।

इस समस्या को हल करने के लिए मुझे सबसे अधिक विस्तृत उदाहरण मिल सकता था, यह window.postMessage article on MDN था।

otherWindow.postMessage(message, targetOrigin); 

और फिर एक ईवेंट हैंडलर दूसरी तरफ:

क्या यह करने पर निर्भर करता एक तरफ एक कॉल संदेश, जैसे पोस्ट करने के लिए है

window.addEventListener("message", receiveMessage, false); 

function receiveMessage(event) 
{ 
    alert("I got it!\n" + event.data); 
} 

IE6 और IE7 हो सकता है यदि आप एक ही डोमेन से हैं, तो विंडोज़ के लिए उन क्रॉस-विंडो कॉल करने की अनुमति दें, लेकिन आईई 8 और इससे ऊपर की संभावना है कि आप इस एपीआई का उपयोग करें, और मैं अनुमान लगा रहा हूं कि अन्य ब्राउज़र अंततः इस सुरक्षित संचार पर वापस आ जाएंगे तंत्र।

स्थिति को देखते हुए, मैं आपके कोड को साझा करने के लिए साझा लाइब्रेरी का उपयोग करने की दृढ़ता से अनुशंसा करता हूं, (LAB.js या require.js या यहां तक ​​कि केवल Jquery's getScript() फ़ंक्शन) का उपयोग करके, और फिर क्रॉस-दस्तावेज़ मैसेजिंग का उपयोग करें सिस्टम कॉलबैक फ़ंक्शन की बजाय ईवेंट भेजने के लिए, जिसे आप आज उपयोग करने का प्रयास कर रहे हैं।

अद्यतन


पुराने ब्राउज़र के लिए postMessage समर्थन जोड़ने के लिए उपलब्ध polyfills रहे हैं। चूंकि आप क्रॉस-डोमेन कॉल नहीं कर रहे हैं, इसलिए मैं बेन आलमैन के Jquery postMessage plugin से शुरू करूंगा। मैंने इसका इस्तेमाल नहीं किया है, लेकिन मैंने बेन के उत्कृष्ट jQuery बीबीक्यू प्लगइन्स का उपयोग किया है। यदि समर्थित हो तो इसे अंतर्निहित विधियों पर वापस आना चाहिए, और केवल पुराने ब्राउज़र में वैकल्पिक तरीकों में तैरना चाहिए। यह आईई 7 में काम करने का दावा करता है ...

यदि बेन की प्लगइन चाल नहीं करती है, तो आप easyXDM को आजमा सकते हैं, लेकिन यह सेट अप करने के लिए थोड़ा अधिक दृढ़ दिखता है।

+0

मुझे लगता है कि यह एक बेहतरीन, स्टैंडअर्ट अनुरूप कामकाज है। लेकिन यह मेरे लिए एक समस्या है जो आईई 7 में समर्थित नहीं है। वैसे भी, मुझे लगता है कि आप विजेता हैं। – Olegas

+0

मुझे पहले देखना नहीं था (मैं समय सीमा के खिलाफ था), लेकिन आईई 7 में इस विधि को प्रदान करने के लिए कुछ पॉलीफिल हैं। मैंने उन्हें शामिल करने के उत्तर को अद्यतन किया। –

+0

अच्छा lib, लेकिन यह संदेशों को पास करने के लिए location.hash का उपयोग करता है ... मेरे पर्यावरण में हैश का आंतरिक उपयोग (जैसे नेविगेशन, आदि ...) के लिए अत्यधिक उपयोग किया जाता है। लेकिन इसे मेरी जरूरतों को पूरा करने के लिए संशोधित किया जा सकता है और जो कुछ भी पहले से काम कर रहा है उसे तोड़ने के लिए नहीं किया जा सकता है। धन्यवाद। – Olegas