jQuery। पहले से ही एक गतिशील रूप से सम्मिलित iframe में


184

जब कोई किसी चित्र पर क्लिक करता है तो हम गतिशील रूप से एक iframe प्रदर्शित करने के लिए jQuery के थिकबॉक्स का उपयोग कर रहे हैं । इस iframe में, हम कई चित्रों को प्रदर्शित करने के लिए गैलेरिया की एक लाइब्रेरी का उपयोग कर रहे हैं ।

समस्या यह है कि $(document).readyiframe में बहुत जल्द निकाल दिया जा रहा है और iframe सामग्री अभी भी भरी हुई नहीं है, ऐसा लगता है कि गैलरिया कोड DOM तत्वों पर ठीक से लागू नहीं किया गया है। $(document).readyअगर iframe तैयार है, तो यह तय करने के लिए iframe माता-पिता तैयार अवस्था का उपयोग करने लगता है।

यदि हम एक अलग फ़ंक्शन में तैयार दस्तावेज़ द्वारा बुलाए गए फ़ंक्शन को निकालते हैं और इसे 100 एमएस के टाइमआउट के बाद कहते हैं। यह काम करता है, लेकिन हम एक धीमी गति से कंप्यूटर के साथ उत्पादन में मौका नहीं ले सकते।

$(document).ready(function() { setTimeout(ApplyGalleria, 100); });

मेरा प्रश्न: हमें कौन सा jQuery इवेंट चाहिए जो हमारे कोड को निष्पादित करने में सक्षम होने के लिए बाध्य होना चाहिए जब गतिशील आइफ्रेम तैयार है और न केवल यह एक अभिभावक है?


1
और आप इस बात की पुष्टि करते हैं कि गैलरिया तब काम करता है जब आप इसे आईफ्रेम के माध्यम से सीधे लोड करते हैं, सही?
जेसन केली

हां, पित्ताशय पूरी तरह से काम करता है जब हम इसे एक सामान्य पृष्ठ में सीधे उपयोग करते हैं।
EtienneT

जवाबों:


291

मैंने इसी तरह के प्रश्न का उत्तर दिया ( जब IFRAME लोडिंग समाप्त हो गया है तो जावास्क्रिप्ट कॉलबैक देखें ? )। आप निम्नलिखित कोड के साथ iframe लोड घटना पर नियंत्रण प्राप्त कर सकते हैं:

function callIframe(url, callback) {
    $(document.body).append('<IFRAME id="myId" ...>');
    $('iframe#myId').attr('src', url);

    $('iframe#myId').load(function() {
        callback(this);
    });
}

आईफ्रेम से निपटने में मुझे दस्तावेज़ तैयार घटना के बजाय लोड इवेंट का उपयोग करने के लिए पर्याप्त अच्छा लगा।


17
क्या आपको attr ('src') को कॉल करने से पहले लोड ईवेंट सेट नहीं करना चाहिए?
शाय एर्लिचमेन 19

15
नहीं, इससे कोई फर्क नहीं पड़ता। कम से कम अगले ईवेंट लूप तक लोड इवेंट फायर नहीं करेगा।
बारुम रो

29
लोड घटना iframes है कि डाउनलोड के लिए उपयोग किया जाता है के लिए काम नहीं करेगा। जैसे <iframe src = "my.pdf" />
माइक

5
लोड के साथ समस्या यह है कि यह आग लग जाती है जब सभी छवियों और सबफ्रेम ने लोड किया है। तैयार घटना की तरह एक jQuery अधिक उपयोगी होगा।
टॉम


30

JQuery 1.3.2 का उपयोग करते हुए निम्नलिखित मेरे लिए काम किया:

$('iframe').ready(function() {
  $('body', $('iframe').contents()).html('Hello World!');
});

संशोधन :! वास्तव में उपरोक्त कोड कभी-कभी ऐसा लगता है कि यह फ़ायरफ़ॉक्स में काम करता है, कभी ऐसा नहीं दिखता कि यह ओपेरा में काम करता है।

इसके बजाय मैंने अपने उद्देश्यों के लिए एक मतदान समाधान लागू किया। नीचे सरलीकृत यह इस तरह दिखता है:

$(function() {
  function manipIframe() {
    el = $('body', $('iframe').contents());
    if (el.length != 1) {
      setTimeout(manipIframe, 100);
      return;
    }
    el.html('Hello World!');
  }
  manipIframe();
});

इसके लिए तथाकथित iframe पृष्ठों में कोड की आवश्यकता नहीं है। सभी कोड मूल फ्रेम / विंडो से रहते हैं और निष्पादित होते हैं।


क्या है setPreview fucntion setTimeout () में कहा गया है?
कैम 8001 3

@ cam8001: यह एक टाइपो था - अब ठीक कर दिया गया है।
मेर gsrlygsson

मैंने एक मतदान समाधान का भी उपयोग किया। अन्य समाधान आंशिक सफलता के साथ ही काम करने लगे। हालांकि, मेरे लिए, मुझे सफलता मिलने से पहले, केवल आइफ्रेम की सामग्री के बजाय एक जावास्क्रिप्ट फ़ंक्शन के अस्तित्व की जांच करने की आवश्यकता थी। जैसे। (टाइपऑफ iframe.contentWindow.myfunc == 'function')
जूलियन

2
यह समाधान पुनरावर्ती है जो प्रत्येक कॉल के लिए मेमोरी लेता है। अगर iframe कभी लोड नहीं होता है, तो यह तब तक गहरा और गहरा कॉल करेगा जब तक कि स्मृति बाहर नहीं निकल जाती। मैं setIntervalइसके बदले मतदान करने की सलाह दूंगा।
eremzeit

15

IFrames में मैं आमतौर पर ब्लॉक के बहुत अंत में एक छोटी स्क्रिप्ट डालकर इस समस्या को हल करता हूं:

<body>
The content of your IFrame
<script type="text/javascript">
//<![CDATA[
   fireOnReadyEvent();
   parent.IFrameLoaded();
//]]>
</script>
</body>

यह मेरे लिए ज्यादातर समय काम करता है। कभी-कभी सबसे सरल और सबसे भोला समाधान सबसे उपयुक्त होता है।


4
+1 यह समाधान मेरे लिए बहुत अच्छा काम करता है! एक बढ़िया जोड़ यह है कि आप parentjQuery की एक प्रति हड़पने और parent.$(document).ready(function(){ parent.IFrameLoaded( ); });iframe को इनिशियलाइज़ करने के लिए उपयोग कर सकते हैं।
डेविड मर्डोक

9

DrJokepu के और डेविड मर्डोक के विचार के बाद मैंने अधिक पूर्ण संस्करण लागू किया। यह माता-पिता और iframe और iframe दोनों को आपके नियंत्रण में रखने के लिए jQuery की आवश्यकता है

iframe कोड:

var iframe = window.frameElement;

if (iframe){
    iframe.contentDocument = document;//normalization: some browsers don't set the contentDocument, only the contentWindow

    var parent = window.parent;
    $(parent.document).ready(function(){//wait for parent to make sure it has jQuery ready
        var parent$ = parent.jQuery;

        parent$(iframe).trigger("iframeloading");

        $(function(){
            parent$(iframe).trigger("iframeready");
        });

        $(window).load(function(){//kind of unnecessary, but here for completion
            parent$(iframe).trigger("iframeloaded");
        });

        $(window).unload(function(e){//not possible to prevent default
            parent$(iframe).trigger("iframeunloaded");
        });

        $(window).on("beforeunload",function(){
            parent$(iframe).trigger("iframebeforeunload");
        });
    });
}

मूल परीक्षा कोड:

$(function(){
    $("iframe").on("iframeloading iframeready iframeloaded iframebeforeunload iframeunloaded", function(e){
        console.log(e.type);
    });
});

जो भी कारण $ (iframe) का उपयोग कर रहे हैं। माता-पिता में पहले से ही (फ़ंक्शन ...) मेरे लिए काम नहीं करेगा। ऐसा लग रहा था कि कॉलबैक फ़ंक्शन को इफ्रेम डोम तैयार होने से पहले निष्पादित किया जा रहा है। इस विधि का उपयोग महान काम किया!
w--

4

समस्या का समाधान पाया।

जब आप एक मोटी बॉक्स लिंक पर क्लिक करते हैं जो एक आइफ्रेम खोलते हैं, तो यह टीबी_इफ्रेम असेंबली की आईडी के साथ एक आइफ्रेम डाल देता है।

$(document).readyIframe कोड में ईवेंट पर निर्भर होने के बजाय , मुझे सिर्फ पेरेंट डॉक्यूमेंट में iframe के लोड ईवेंट के लिए बाध्य करना है:

$('#TB_iframeContent', top.document).load(ApplyGalleria);

यह कोड iframe में है, लेकिन मूल दस्तावेज़ में नियंत्रण की एक घटना के लिए बाध्य करता है। यह FireFox और IE में काम करता है।


9
समाधान मिल गया? लगता है कि पियर ने पहले ही इसे पोस्ट कर दिया था। चाहे आप इसे अपने दम पर पाए या नहीं, शिष्टाचार उसके उत्तर को स्वीकार करने के लिए होगा, इस प्रकार वह उस समय को पुरस्कृत करता है जो उसने आपको उत्तर देने में बिताया था।
स्काई सैंडर्स

पियर के समाधान और इस (और मैं अपने कोड में क्या याद कर रहा था) के बीच का अंतर वह संदर्भ top.documentहै जो मुझे iframe के अंदर कोड रखने की अनुमति देता है , जब iframe लोड किया गया है तो यह बताने में सक्षम होगा। (हालांकि loadइस उत्तर के बाद से पदावनत कर दिया गया है, और इसे बदल दिया जाना चाहिए on("load")।)
टेपेमम

2

मूल रूप से दूसरों ने पहले से ही क्या पोस्ट किया है, लेकिन IMHO थोड़ा साफ है:

$('<iframe/>', {
    src: 'https://example.com/',
    load: function() {
        alert("loaded")
    }
}).appendTo('body');

1

इसे इस्तेमाल करे,

<iframe id="testframe" src="about:blank" onload="if (testframe.location.href != 'about:blank') testframe_loaded()"></iframe>

फिर आपको केवल जावास्क्रिप्ट फ़ंक्शन testframe_loaded () बनाना होगा।


1
लोड के साथ समस्या यह है कि यह आग लग जाती है जब सभी छवियों और सबफ्रेम ने लोड किया है। तैयार घटना की तरह एक jQuery अधिक उपयोगी होगा।
टॉम

1

मैं ब्राउज़र कैश में jQuery के AJAX के साथ पीडीएफ लोड कर रहा हूं। फिर मैं पहले से ही ब्राउज़र कैश में डेटा के साथ एम्बेडेड तत्व बनाता हूं। मुझे लगता है कि यह iframe के साथ भी काम करेगा।


var url = "http://example.com/my.pdf";
// show spinner
$.mobile.showPageLoadingMsg('b', note, false);
$.ajax({
    url: url,
    cache: true,
    mimeType: 'application/pdf',
    success: function () {
        // display cached data
        $(scroller).append('<embed type="application/pdf" src="' + url + '" />');
        // hide spinner
        $.mobile.hidePageLoadingMsg();
    }
});

आपको अपने http हेडर को सही ढंग से सेट करना होगा।


HttpContext.Response.Expires = 1;
HttpContext.Response.Cache.SetNoServerCaching();
HttpContext.Response.Cache.SetAllowResponseInBrowserHistory(false);
HttpContext.Response.CacheControl = "Private";

1
ध्यान दें, यह उन मोबाइल ब्राउज़रों पर अच्छा काम नहीं करता है जहाँ कैश पीडीएफ के आकार से छोटा हो सकता है।
पावेल सवारा

1

यह सटीक मुद्दा था जिसे मैंने अपने ग्राहक के साथ चलाया था। मैंने थोड़ा jquery प्लगइन बनाया जो iframe तत्परता के लिए काम करता है। यह iframe दस्तावेज़ के साथ संयुक्त iframe दस्तावेज़ तैयार करने के लिए मतदान का उपयोग करता है, यह सुनिश्चित करने के लिए iframe स्रोत के साथ संयुक्त आंतरिक दस्तावेज़ url कि वास्तव में iframe "तैयार" है।

"Onload" के साथ समस्या यह है कि आपको DOM में जोड़े जा रहे वास्तविक iframe तक पहुंच की आवश्यकता है, यदि आपको नहीं है तो आपको iframe लोडिंग को पकड़ने की कोशिश करने की आवश्यकता है जो यदि यह कैश किया गया है तो आप नहीं कर सकते। मुझे जिस चीज की आवश्यकता थी वह एक ऐसी स्क्रिप्ट थी जिसे कभी भी बुलाया जा सकता है, और यह निर्धारित किया जा सकता है कि आइफ्रेम "तैयार" था या नहीं।

यहाँ सवाल है:

स्थानीय आइफ्रेम ने लोड किया है या नहीं, यह निर्धारित करने के लिए पवित्र ग्रिल

और यहाँ jsfiddle मैं अंततः के साथ आया था।

https://jsfiddle.net/q0smjkh5/10/

ऊपर के jsfiddle में, मैं डोम पर एक iframe संलग्न करने के लिए onload का इंतजार कर रहा हूं, फिर iframe के आंतरिक दस्तावेज़ की तैयार स्थिति की जांच कर रहा हूं - जिसे क्रॉस डोमेन होना चाहिए क्योंकि यह विकिपीडिया को इंगित किया गया है - लेकिन Chrome को "पूर्ण" रिपोर्ट करना प्रतीत होता है। प्लग-इन की विडंबना विधि तब कहलाती है जब आईफ्रेम वास्तव में तैयार होता है। कॉलबैक आंतरिक दस्तावेज़ की तैयार स्थिति को फिर से जांचने की कोशिश करता है - इस बार एक क्रॉस डोमेन अनुरोध (जो सही है) की रिपोर्ट कर रहा है - वैसे भी यह मेरी ज़रूरत के लिए काम करता है और आशा करता है कि यह दूसरों की मदद करता है।

<script>
  (function($, document, undefined) {
    $.fn["iready"] = function(callback) {
      var ifr = this.filter("iframe"),
          arg = arguments,
          src = this,
          clc = null, // collection
          lng = 50,   // length of time to wait between intervals
          ivl = -1,   // interval id
          chk = function(ifr) {
            try {
              var cnt = ifr.contents(),
                  doc = cnt[0],
                  src = ifr.attr("src"),
                  url = doc.URL;
              switch (doc.readyState) {
                case "complete":
                  if (!src || src === "about:blank") {
                    // we don't care about empty iframes
                    ifr.data("ready", "true");
                  } else if (!url || url === "about:blank") {
                    // empty document still needs loaded
                    ifr.data("ready", undefined);
                  } else {
                    // not an empty iframe and not an empty src
                    // should be loaded
                    ifr.data("ready", true);
                  }

                  break;
                case "interactive":
                  ifr.data("ready", "true");
                  break;
                case "loading":
                default:
                  // still loading
                  break;   
              }
            } catch (ignore) {
              // as far as we're concerned the iframe is ready
              // since we won't be able to access it cross domain
              ifr.data("ready", "true");
            }

            return ifr.data("ready") === "true";
          };

      if (ifr.length) {
        ifr.each(function() {
          if (!$(this).data("ready")) {
            // add to collection
            clc = (clc) ? clc.add($(this)) : $(this);
          }
        });
        if (clc) {
          ivl = setInterval(function() {
            var rd = true;
            clc.each(function() {
              if (!$(this).data("ready")) {
                if (!chk($(this))) {
                  rd = false;
                }
              }
            });

            if (rd) {
              clearInterval(ivl);
              clc = null;
              callback.apply(src, arg);
            }
          }, lng);
        } else {
          clc = null;
          callback.apply(src, arg);
        }
      } else {
        clc = null;
        callback.apply(this, arguments);
      }
      return this;
    };
  }(jQuery, document));
</script>

मेरे लिए अच्छा काम किया
हसन तारेक

0

इस उत्तर से यह फ़ंक्शन इसे संभालने का सबसे अच्छा तरीका है $.readyक्योंकि आईफ्रेम के लिए स्पष्ट रूप से विफल रहता है। यहां इसका समर्थन नहीं करने का निर्णय लिया गया है।

loadघटना भी आग नहीं करता है तो आइफ्रेम पहले से ही भरी हुई है। बहुत निराशा होती है कि यह 2020 में एक समस्या बनी हुई है!

function onIframeReady($i, successFn, errorFn) {
    try {
        const iCon = $i.first()[0].contentWindow,
        bl = "about:blank",
        compl = "complete";
        const callCallback = () => {
            try {
                const $con = $i.contents();
             if($con.length === 0) { // https://git.io/vV8yU
                throw new Error("iframe inaccessible");
             }


   successFn($con);
     } catch(e) { // accessing contents failed
        errorFn();
     }
  };
  const observeOnload = () => {
    $i.on("load.jqueryMark", () => {
        try {
            const src = $i.attr("src").trim(),
            href = iCon.location.href;
            if(href !== bl || src === bl || src === "") {
                $i.off("load.jqueryMark");
                callCallback();
            }
        } catch(e) {
            errorFn();
        }
    });
  };
  if(iCon.document.readyState === compl) {
    const src = $i.attr("src").trim(),
    href = iCon.location.href;
    if(href === bl && src !== bl && src !== "") {
        observeOnload();
    } else {
        callCallback();
    }
  } else {
    observeOnload();
  }
} catch(e) {
    errorFn();
}

}

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.