javascript اكواد - استدعاء شفرة جافا سكريبت في iframe من الصفحة الرئيسية




شرح تحميل (15)

في الأساس ، لدي iframe مضمن في صفحة ، ويحتوي iframe على بعض إجراءات JavaScript أحتاجها للاحتفاظ بها من الصفحة الرئيسية.

أما الآن فالعكس بسيط للغاية حيث أنك تحتاج فقط إلى استدعاء parent.functionName() ، ولكن للأسف ، أحتاج إلى عكس ذلك تمامًا.

يرجى ملاحظة أن مشكلتي لا تغير URL المصدر iframe ، بل تستدعي وظيفة محددة في iframe .


Answers

       $("#myframe").load(function() {
            alert("loaded");
        });

مع استمرار جواب :

لمزيد من المتانة ، استخدم كالتالي:

var el = document.getElementById('targetFrame');

if(el.contentWindow)
{
   el.contentWindow.targetFunction();
}
else if(el.contentDocument)
{
   el.contentDocument.targetFunction();
}

workd مثل سحر :)


إذا كان iFrame والمستند المحتوي على نطاق مختلف ، فقد لا تعمل الطرق التي تم نشرها مسبقًا ، ولكن يوجد حل:

على سبيل المثال ، إذا كان المستند A يحتوي على عنصر iframe يحتوي على المستند B ، والنص البرمجي في المستند A يستدعي postMessage () على كائن النافذة من المستند B ، فسيتم تشغيل حدث رسالة على هذا الكائن ، يتم وضع علامة على أنها ناشئة من نافذة المستند A. قد يبدو النص البرمجي في المستند A:

var o = document.getElementsByTagName('iframe')[0];
o.contentWindow.postMessage('Hello world', 'http://b.example.org/');

لتسجيل معالج أحداث للأحداث الواردة ، قد يستخدم البرنامج النصي addEventListener () (أو آليات مشابهة). على سبيل المثال ، قد يبدو النص البرمجي في المستند B كما يلي:

window.addEventListener('message', receiver, false);
function receiver(e) {
  if (e.origin == 'http://example.com') {
    if (e.data == 'Hello world') {
      e.source.postMessage('Hello', e.origin);
    } else {
      alert(e.data);
    }
  }
}

يقوم هذا البرنامج النصي أولاً بالتحقق من أن المجال هو المجال المتوقع ، ثم ينظر إلى الرسالة التي يعرضها إما للمستخدم ، أو يستجيب لها عن طريق إرسال رسالة إلى المستند الذي أرسل الرسالة في المقام الأول.

عبر http://dev.w3.org/html5/postmsg/#web-messaging


نفس الأشياء ولكن طريقة أسهل قليلاً هي كيفية تحديث الصفحة الرئيسية من الصفحة داخل iframe . ما عليك سوى استدعاء وظيفة الصفحة الرئيسية لاستدعاء وظيفة جافا سكريبت لإعادة تحميل الصفحة:

window.location.reload();

أو افعل ذلك مباشرة من الصفحة في iframe:

window.parent.location.reload();

كلاهما يعمل.


يمكن استدعاء وظيفة JS من iframe ، ولكن فقط عندما يكون كل من الأصل والصفحة التي تم تحميلها في iframe من نفس المجال مثل abc.com ، وكلاهما يستخدمان نفس البروتوكول أي أن كلاهما إما على http:// أو https:// .

ستفشل المكالمة في الحالات المذكورة أدناه:

  1. الصفحة الرئيسية وصفحة iframe من نطاق مختلف.
  2. انهم يستخدمون بروتوكولات مختلفة ، واحد على http: // وآخر على https: //.

أي حل بديل لهذا التقييد سيكون غير آمن للغاية.

على سبيل المثال ، تخيل أنني سجلت النطاق superwinningcontest.com وأرسلت روابط إلى رسائل البريد الإلكتروني للأشخاص. عندما حمّلوا الصفحة الرئيسية ، كان بإمكاني إخفاء بعض iframe على Facebook ، والتحقق من معاملات Amazon أو PayPal الأخيرة ، أو - إذا استخدموا خدمة لم تنفذ الأمان الكافي - قم بتحويل الأموال من حساباتهم. لهذا السبب تقتصر JavaScript على نفس المجال ونفس البروتوكول.


هناك بعض المراوغات لتكون على بينة من هنا.

  1. ربما يكون HTMLIFrameElement.contentWindow الطريقة الأسهل ، ولكنها ليست خاصية قياسية تمامًا ولا تدعمها بعض المتصفحات ، ومعظمها أقدم منها. هذا لأن معيار DOM المستوى 1 HTML ليس لديه ما يقوله عن كائن window .

  2. يمكنك أيضًا تجربة HTMLIFrameElement.contentDocument.defaultView ، والذي يسمح به بعض المتصفحات القديمة ولكن لا يعمل المتصفح IE. ومع ذلك ، فإن المعيار لا ينص صراحة على استرجاع كائن window ، لنفس السبب (1) ، ولكن يمكنك اختيار بعض إصدارات المتصفح الإضافية هنا إذا كنت تهتم.

  3. window.frames['name'] إعادة النافذة هي أقدم واجهة وبالتالي فهي أكثر موثوقية. ولكن يجب عليك بعد ذلك استخدام خاصية name="..." لتكون قادرة على الحصول على إطار بالاسم ، وهو قبيح / موقوف / انتقالي. ( id="..." سيكون أفضل ولكن IE لا تحب ذلك.)

  4. window.frames[number] موثوق بها للغاية ، ولكن معرفة المؤشر الصحيح هو الخدعة. يمكنك الابتعاد مع هذا على سبيل المثال. إذا كنت تعرف أنك تملك إطار iframe واحد فقط على الصفحة.

  5. من المحتمل تمامًا أن يكون iframe الطفل لم يتم تحميله بعد ، أو حدث خطأ آخر لجعله غير ممكن الوصول إليه. قد تجد أنه من الأسهل عكس تدفق الاتصالات: أي أن يكون iframe التابع للأطفال قد قام بإخطار البرنامج النصي window.parent الخاص به عند الانتهاء من التحميل وهو جاهز لاستدعائه مرة أخرى. بتمرير أحد الأشياء الخاصة به (على سبيل المثال ، وظيفة رد الاتصال) إلى البرنامج النصي الأصل ، يمكن لذلك الوالد الاتصال مباشرة مع البرنامج النصي في iframe دون الحاجة إلى القلق بشأن HTMLIFrameElement المرتبط به.


نفترض أن معرّف iFrame هو "targetFrame" وأن الوظيفة التي تريد الاتصال بها هي targetFunction() :

document.getElementById('targetFrame').contentWindow.targetFunction();

يمكنك أيضًا الوصول إلى الإطار باستخدام window.frames بدلاً من document.getElementById .

// this option does not work in most of latest versions of chrome and Firefox
window.frames[0].frameElement.contentWindow.targetFunction(); 

فقط للتسجيل ، واجهت نفس المشكلة اليوم ولكن هذه المرة تم تضمين الصفحة في كائن ، وليس iframe (حيث كان مستند XHTML 1.1). فيما يلي كيفية عملها مع الكائنات:

document
  .getElementById('targetFrame')
  .contentDocument
  .defaultView
  .targetFunction();

(نعتذر عن فواصل الأسطر القبيحة ، لم تتناسب مع خط واحد)


افرج نيتين بانسال الجواب

ولمزيد من المتانة:

function getIframeWindow(iframe_object) {
  var doc;

  if (iframe_object.contentWindow) {
    return iframe_object.contentWindow;
  }

  if (iframe_object.window) {
    return iframe_object.window;
  } 

  if (!doc && iframe_object.contentDocument) {
    doc = iframe_object.contentDocument;
  } 

  if (!doc && iframe_object.document) {
    doc = iframe_object.document;
  }

  if (doc && doc.defaultView) {
   return doc.defaultView;
  }

  if (doc && doc.parentWindow) {
    return doc.parentWindow;
  }

  return undefined;
}

و

...
var el = document.getElementById('targetFrame');

getIframeWindow(el).targetFunction();
...

لقد وجدت حلًا رائعًا.

كما قلت ، من السهل جدًا تنفيذ التعليمة البرمجية الموجودة في المستند الأصلي. وهذه هي قاعدة الكود ، افعل العكس تماماً.

عندما يتم تحميل iframe ، أقوم باستدعاء دالة موجودة في المستند الأصل ، وتمريرها كوسيطة كمرجع لوظيفة محلية ، موجودة في مستند iframe. يحتوي المستند الأصل الآن على وصول مباشر إلى وظيفة iframe من خلال هذا المرجع.

مثال:

على الوالد:

function tunnel(fn) {
    fn();
}

على iframe:

var myFunction = function() {
    alert("This work!");
}

parent.tunnel(myFunction);

عند تحميل iframe ، سيتم استدعاء parent.tunnel (YourFunctionReference) ، والذي سيقوم بتنفيذ الوظيفة المستلمة في المعلمة.

هذا بسيط ، دون الحاجة إلى التعامل مع جميع الأساليب غير القياسية من المتصفحات المختلفة.


في IFRAME ، اجعل وظيفتك عامة لكائن النافذة:

window.myFunction = function(args) {
   doStuff();
}

للوصول من الصفحة الرئيسية ، استخدم هذا:

var iframe = document.getElementById("iframeId");
iframe.contentWindow.myFunction(args);

يجب أن يكون IFRAME في مجموعة frames[] . استخدام شيء من هذا القبيل

frames['iframeid'].method();

حاول فقط parent.myfunction()


لا تتناول بعض هذه الإجابات مشكلة CORS أو لا توضح مكان وضع مقتطفات الشفرة في جعل الاتصال ممكنًا.

هنا مثال ملموس. قل أرغب في النقر فوق زر في الصفحة الرئيسية ، وقم بإجراء ذلك في إطار iframe. هنا كيف سأفعلها.

parent_frame.html

<button id='parent_page_button' onclick='call_button_inside_frame()'></button>

function call_button_inside_frame() {
   document.getElementById('my_iframe').contentWindow.postMessage('foo','*');
}

iframe_page.html

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

function receiveMessage(event)
    {
      if(event) {
        click_button_inside_frame();
    }
}

function click_button_inside_frame() {
   document.getElementById('frame_button').click();
}

للانتقال إلى الاتجاه الآخر (انقر على زر iframe لاستدعاء طريقة خارجية iframe) ما عليك سوى التبديل إلى مكان مقتطف الشفرة ، وتغيير هذا:

document.getElementById('my_iframe').contentWindow.postMessage('foo','*');

الى هذا:

window.parent.postMessage('foo','*')

إذا كنت تستخدم iFrame لملاءمة عرض وارتفاع الشاشة بأكملها ، والتي أفترض أنك لا تعتمد على حجم 300 × 300 ، يجب عليك أيضًا ضبط هوامش النص على "0" كما يلي:

<body style="margin:0px;">




javascript html iframe